summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2008-10-19 22:06:47 +0000
committer Couriersud <couriersud@users.noreply.github.com>2008-10-19 22:06:47 +0000
commita7da02e00ef357ca4cfa6f5ce26ccdc405034a5d (patch)
treec2fea696b40db5e7a49baff7c3dcf4c055e2fc34 /src
parent10e8a13d823452554d65846f465040056558e286 (diff)
MCS51/I8051 overhaul, micro3d improvements and full m72 protection emulation for lohtb2
* improved serial port timing (f15se (micro3d.c) sound board now works) * better infrastructure for adding more variants like DS5002 * Fixed port reading * Rewrote Macros for better readibility * Fixed and rewrote Interrupt handling * Now returns INTERNAL_DIVIDER, adjusted cycle counts * Remove unnecessary and duplicated code * Remove unnecessary functions * Rewrite to have sfr-registers stored in int_ram. * Debugger may now watch sfr-registers as well. * implemented interrupt callbacks (HOLD_LINE now supported) * Runtime switch for processor type - remove ifdefs * internal memory maps for internal rom versions (internal ram now displayed in debugger) * more timer cleanups from manual micro3d: * serial port communication between main cpu and sound board works * sound board now works m72 - lohtb2: * full emulation of protection device * Samples are now piped through the mcu
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/i8051/i8051.c3885
-rw-r--r--src/emu/cpu/i8051/i8051.h122
-rw-r--r--src/emu/cpu/i8051/i8051ops.c389
-rw-r--r--src/mame/drivers/cardline.c9
-rw-r--r--src/mame/drivers/limenko.c6
-rw-r--r--src/mame/drivers/m72.c351
-rw-r--r--src/mame/drivers/micro3d.c93
-rw-r--r--src/mame/drivers/peplus.c32
-rw-r--r--src/mame/drivers/sliver.c9
-rw-r--r--src/mame/drivers/sslam.c11
-rw-r--r--src/mame/drivers/videopkr.c15
11 files changed, 2273 insertions, 2649 deletions
diff --git a/src/emu/cpu/i8051/i8051.c b/src/emu/cpu/i8051/i8051.c
index ef78f3af124..d073a76c6be 100644
--- a/src/emu/cpu/i8051/i8051.c
+++ b/src/emu/cpu/i8051/i8051.c
@@ -53,353 +53,430 @@
* July 28,2004: Fixed MOVX command and added External Ram Paging Support
* July 31,2004: Added Serial Mode 0 Support & Fixed Interrupt Flags for Serial Port
*
- * Todo: Full Timer support (all modes)
- *
* NOW Implemented: RAM paging using hardware configured addressing...
* (July 28,2004) the "MOVX a,@R0/R1" and "MOVX @R0/R1,a" commands can use any of the other ports
* to output a page offset into external ram, but it is totally based on the hardware setup.
*
* Timing needs to be implemented via MAME timers perhaps?
+ *
+ * October, 2008, Couriersud - Major rewrite
*
*****************************************************************************/
+/* TODO: Varios
+ * - EA pin - defined by architecture, must implement:
+ * 1 means external access, bypassing internal ROM
+ * - T0 output clock ?
+ *
+ * - Full Timer support (all modes)
+ * - Fix serial communication - This is a big hack (but working) right now.
+ * - Handle internal ram better (debugger visible)
+ * - Fix limenko.c videopkr.c : Issue with core allocation of ram (duplicate savestate)
+ * - Fix sslam.c and cardline.c
+ * most likely due to different behaviour of I/O pins. The boards
+ * actually use 80CXX, i.e. CMOS versions.
+ * "Normal" 805X will return a 0 if reading from a output port which has
+ * a 0 written to it's latch. At least cardline expects a 1 here.
+ *
+ * Done:
+ * - Fixed port reading
+ * - Rewrote Macros for better readibility
+ * - Fixed and rewrote Interrupt handling
+ * - Now returns INTERNAL_DIVIDER, adjusted cycle counts
+ * - Remove unnecessary and duplicated code
+ * - Remove unnecessary functions
+ * - Rewrite to have sfr-registers stored in int_ram.
+ * - Debugger may now watch sfr-registers as well.
+ * - implemented interrupt callbacks (HOLD_LINE now supported)
+ * - Runtime switch for processor type - remove ifdefs
+ * - internal memory maps for internal rom versions (internal ram now displayed in debugger)
+ * - more timer cleanups from manual
+ */
+
#include "debugger.h"
#include "deprecat.h"
#include "i8051.h"
-#define VERBOSE 0
+#define VERBOSE 1
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
-//Prototypes
-INLINE void push_pc(void);
-INLINE void pop_pc(void);
-INLINE void set_parity(void);
-INLINE void do_add_flags(UINT8 a, UINT8 data, UINT8 c);
-INLINE void do_sub_flags(UINT8 a, UINT8 data, UINT8 c);
-INLINE UINT8 check_interrupts(void);
-INLINE void update_timer(int cyc);
-INLINE void update_serial(int cyc);
-INLINE void serial_transmit(UINT8 data);
-static READ8_HANDLER(internal_ram_read);
-static WRITE8_HANDLER(internal_ram_write);
-static READ8_HANDLER(internal_ram_iread);
-static READ32_HANDLER(external_ram_iaddr);
-static WRITE8_HANDLER(internal_ram_iwrite);
-static READ8_HANDLER(sfr_read);
-static WRITE8_HANDLER(sfr_write);
-static WRITE8_HANDLER( bit_address_w );
-static READ8_HANDLER( bit_address_r );
+enum
+{
+ FEATURE_NONE = 0,
+ FEATURE_I8052_UART = 1,
+};
-#if (HAS_I8052 || HAS_I8752)
-static READ8_HANDLER(i8052_internal_ram_iread);
-static WRITE8_HANDLER(i8052_internal_ram_iwrite);
-#endif
-//
+/* Internal address in SFR of registers */
+enum
+{
+ ADDR_PSW = 0xd0,
+ ADDR_ACC = 0xe0,
+ ADDR_B = 0xf0,
+
+ ADDR_P0 = 0x80,
+ ADDR_SP = 0x81,
+ ADDR_DPL = 0x82,
+ ADDR_DPH = 0x83,
+ ADDR_PCON = 0x87,
+ ADDR_TCON = 0x88,
+ ADDR_TMOD = 0x89,
+ ADDR_TL0 = 0x8a,
+ ADDR_TL1 = 0x8b,
+ ADDR_TH0 = 0x8c,
+ ADDR_TH1 = 0x8d,
+ ADDR_P1 = 0x90,
+ ADDR_SCON = 0x98,
+ ADDR_SBUF = 0x99,
+ ADDR_P2 = 0xa0,
+ ADDR_IE = 0xa8,
+ ADDR_P3 = 0xb0,
+ ADDR_IP = 0xb8,
+
+ /* 8052 Only registers */
+ ADDR_T2CON = 0xc8,
+ ADDR_RCAP2L = 0xca,
+ ADDR_RCAP2H = 0xcb,
+ ADDR_TL2 = 0xcc,
+ ADDR_TH2 = 0xcd,
+};
+
+/* PC vectors */
+
+enum
+{
+ V_RESET = 0x000, /* power on address */
+ V_IE0 = 0x003, /* External Interrupt 0 */
+ V_TF0 = 0x00b, /* Timer 0 Overflow */
+ V_IE1 = 0x013, /* External Interrupt 1 */
+ V_TF1 = 0x01b, /* Timer 1 Overflow */
+ V_RITI = 0x023, /* Serial Receive/Transmit */
+
+ /* 8052 Only Vectors */
+ V_TF2 = 0x02b, /* Timer 2 Overflow */
+};
-typedef struct {
- UINT8 timerbaud; //Flag set if timer overflow is controlling baud
- UINT8 sending; //Flag set when uart is sending
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _mcs51_uart mcs51_uart;
+struct _mcs51_uart
+{
UINT8 data_out; //Data to send out
UINT8 bits_to_send; //How many bits left to send when transmitting out the serial port
- UINT8 bitcycles; //# of bitcycles passed since last bit was sent
-} I8051_UART;
-
-typedef struct {
+
+ int smod_div; /* signal divided by 2^SMOD */
+ int rx_clk; /* rx clock */
+ int tx_clk; /* tx clock */
+ UINT8 delay_cycles; //Gross Hack;
+};
+typedef struct _mcs51_regs mcs51_regs;
+struct _mcs51_regs
+{
//Internal stuff
UINT16 ppc; //previous pc
UINT16 pc; //current pc
- UINT16 subtype; //specific version of the cpu, ie 8031, or 8051 for example
+ UINT16 features; //features of this cpu
UINT8 cur_irq; //Holds value of any current IRQ being serviced
UINT8 irq_priority; //Holds value of the current IRQ Priority Level
UINT8 rwm; //Signals that the current instruction is a read/write/modify instruction
- UINT8 prev_used_cycles; //Track previous # of used cycles
- UINT8 last_int0; //Store state of int0
- UINT8 last_int1; //Store state of int1
- UINT8 int_vec; //Pending Interrupt Vector
- UINT8 priority_request; //Priority level of incoming new irq
- //SFR Registers (Note: Appear in order as they do in memory)
- UINT8 po; //Port 0
- UINT8 sp; //Stack Pointer
- UINT8 dpl; //Data Pointer (DPTR) (Hi bit)
- UINT8 dph; //Data Pointer (DPTR) (Lo bit)
- UINT8 pcon; //Power Mode Control
- UINT8 tcon; //Timer/Counter Control
- UINT8 tmod; //Timer/Counter Mode Control
- UINT8 tl0; //Timer 0 Lo
- UINT8 tl1; //Timer 1 Lo
- UINT8 th0; //Timer 0 Hi
- UINT8 th1; //Timer 1 Hi
- UINT8 p1; //Port 1
- UINT8 scon; //Serial Control
- UINT8 sbuf; //Serial Data Buffer
- UINT8 p2; //Port 2
- UINT8 ie; //Interrupt Enable
- UINT8 p3; //Port 3
- UINT8 ip; //Interrupt Priority
- //8052 Only registers
- #if (HAS_I8052 || HAS_I8752)
- UINT8 t2con; //Timer/Counter 2 Control
- UINT8 rcap2l; //Timer/Counter 2 Capture Register Lo
- UINT8 rcap2h; //Timer/Counter 2 Capture Register Hi
- UINT8 tl2; //Timer 2 Lo
- UINT8 th2; //Timer 2 Hi
- #endif
- UINT8 psw; //Program Status Word
- UINT8 acc; //Accumulator
- UINT8 b; //Register B
-
- //Internal Ram
- UINT8 IntRam[0xff+1]; //Max 256 Bytes of Internal RAM (8031/51 have 128, 8032/52 have 256)
+ int inst_cycles; /* cycles for the current instruction */
+ int ram_mask; /* second ram bank for indirect access available ? */
+ int num_interrupts; /* number of interrupts supported */
+ int recalc_parity; /* recalculate parity before next instruction */
+ int last_line_state; /* last state of input lines line */
+ int t0_cnt; /* number of 0->1 transistions on T0 line */
+ int t1_cnt; /* number of 0->1 transistions on T1 line */
+ int t2_cnt; /* number of 0->1 transistions on T2 line */
+ int t2ex_cnt; /* number of 0->1 transistions on T2EX line */
+
+ mcs51_uart uart; /* internal uart */
+
+ /* Internal Ram */
+ UINT8 *internal_ram; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */
+ UINT8 *sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */
+
+ // SFR Callbacks
+ void (*sfr_write)(size_t offset, UINT8 data);
+ UINT8 (*sfr_read)(size_t offset);
+
//Interrupt Callback
int (*irq_callback)(int irqline);
- //Serial Port TX/RX Call backs
+ //Serial Port TX/RX Callbacks
+ // TODO: Move to special port r/w
void (*serial_tx_callback)(int data); //Call back funciton when sending data out of serial port
int (*serial_rx_callback)(void); //Call back function to retrieve data when receiving serial port data
- //Internal Indirect Read/Write Handlers
- READ8_HANDLER((*iram_iread));
- WRITE8_HANDLER((*iram_iwrite));
+};
- //External Ram Address Callback for generating the hardware specific access to external ram
- READ32_HANDLER((*eram_iaddr_callback));
+/***************************************************************************
+ MACROS
+***************************************************************************/
-} I8051;
+#undef change_pc
+#define change_pc(x)
-static int i8051_icount;
+/* Read Opcode/Opcode Arguments from Program Code */
+#define ROP(pc) cpu_readop(pc)
+#define ROP_ARG(pc) cpu_readop_arg(pc)
-static I8051 i8051;
-static I8051_UART uart;
+/* Read a byte from External Code Memory (Usually Program Rom(s) Space) */
+#define CODEMEM_R(a) (UINT8)program_read_byte_8le(a)
-//Hold callback functions so they can be set by caller (before the cpu reset)
-static void (*hold_serial_tx_callback)(int data);
-static int (*hold_serial_rx_callback)(void);
-static READ32_HANDLER((*hold_eram_iaddr_callback));
+/* Read/Write a byte from/to External Data Memory (Usually RAM or other I/O) */
+#define DATAMEM_R(a) (UINT8)io_read_byte_8le(a)
+#define DATAMEM_W(a,v) io_write_byte_8le(a,v)
+//#define DATAMEM_R(a) (UINT8)data_read_byte_8le(a)
+//#define DATAMEM_W(a,v) data_write_byte_8le(a,v)
-/*Short cuts*/
+/* Read/Write a byte from/to the Internal RAM */
-/***************************************************************
- * Read Opcode/Opcode Arguments from Program Code
- ***************************************************************/
-#define ROP(pc) cpu_readop(pc)
-#define ROP_ARG(pc) cpu_readop_arg(pc)
-/*****************************************************************************
- * Read a byte from External Code Memory (Usually Program Rom(s) Space)
- *****************************************************************************
- This area is mapped from 0-FFFF internally (64K) */
-#define CODEMEM_R(a) (UINT8)program_read_byte_8le(a)
-/*****************************************************************************
- * Read/Write a byte from/to External Data Memory (Usually RAM or other I/O)
- *****************************************************************************
- This area is *ALSO* mapped from 0-FFFF internally (64K)
- ** HOWEVER **
- We *FORCE* the address space into the range 10000-1FFFF to allow both
- Code Memory and Data Memory to be pyshically separate while mapped @ the same
- addresses, w/o any contention.
- As far as the 8051 program code which is executing knows data memory still lives
- in the 0-FFFF range.*/
-#define DATAMEM_R(a) (UINT8)data_read_byte_8le(a)
-#define DATAMEM_W(a,v) data_write_byte_8le(a,v)
-
-/***************************************************************
- * Read/Write a byte from/to the Internal RAM
- ***************************************************************/
-#define IRAM_R(a) internal_ram_read(Machine,a)
-#define IRAM_W(a,v) internal_ram_write(Machine,a,v)
-/***************************************************************
- * Read/Write a byte from/to the Internal RAM indirectly (called from indirect addressing)
- ***************************************************************/
-#define IRAM_IR(a) internal_ram_iread(Machine,a)
-#define IRAM_IW(a,v) internal_ram_iwrite(Machine,a,v)
-/***************************************************************
- * Form an Address to Read/Write to External RAM indirectly (called from indirect addressing)
- ***************************************************************/
-#define ERAM_ADDR(a,m) external_ram_iaddr(Machine,a,m)
-/***************************************************************
- * Read/Write a byte from/to the SFR Registers
- ***************************************************************/
-#define SFR_R(a) sfr_read(Machine,a)
-#define SFR_W(a,v) sfr_write(Machine,a,v)
-/***************************************************************
- * Read/Write a bit from Bit Addressable Memory
- ***************************************************************/
-#define BIT_R(a) bit_address_r(Machine,a)
-#define BIT_W(a,v) bit_address_w(Machine,a,v)
-/***************************************************************
- * Input/Output a byte from given I/O port
- ***************************************************************/
-#define IN(port) ((UINT8)io_read_byte(port))
-#define OUT(port,value) io_write_byte(port,value)
-/***************************************************************
- * Access the 4 banks of R registers (R0...R7)
- ***************************************************************/
-#define R_R(n) i8051.IntRam[(GET_RS*8)+(n)]
-/***************************************************************
- * Easy macro for working with 16 bit DPTR
- ***************************************************************/
-#define R_DPTR ((R_DPH<<8) | R_DPL)
-#define DPTR_W(n) SFR_W(DPH, ((n)>>8)&0xff);\
- SFR_W(DPL, ((n)&0xff));
-/***************************************************************
- * Easy macros for Setting Flags
- ***************************************************************/
-/*PSW Flags*/
-#define SET_CY(n) R_PSW = (R_PSW & 0x7f) | (n<<7); //Carry Flag
-#define SET_AC(n) R_PSW = (R_PSW & 0xbf) | (n<<6); //Aux.Carry Flag
-#define SET_FO(n) R_PSW = (R_PSW & 0xdf) | (n<<5); //User Flag
-#define SET_RS(n) R_PSW = (R_PSW & 0xe7) | (n<<3); //R Bank Select
-#define SET_OV(n) R_PSW = (R_PSW & 0xfb) | (n<<2); //Overflow Flag
-#define SET_P(n) R_PSW = (R_PSW & 0xfe) | (n<<0); //Parity Flag
-/*IE Flags*/
-#define SET_EA(n) R_IE = (R_IE & 0x7f) | (n<<7); //Global Interrupt Enable/Disable
-#if (HAS_I8052 || HAS_I8752)
- #define SET_ET2(n) R_IE = (R_IE & 0xdf) | (n<<5); //Timer 2 Interrupt Enable/Disable
-#endif
-#define SET_ES(n) R_IE = (R_IE & 0xef) | (n<<4); //Serial Interrupt Enable/Disable
-#define SET_ET1(n) R_IE = (R_IE & 0xf7) | (n<<3); //Timer 1 Interrupt Enable/Disable
-#define SET_EX1(n) R_IE = (R_IE & 0xfb) | (n<<2); //External Int 1 Interrupt Enable/Disable
-#define SET_ET0(n) R_IE = (R_IE & 0xfd) | (n<<1); //Timer 0 Interrupt Enable/Disable
-#define SET_EX0(n) R_IE = (R_IE & 0xfe) | (n<<0); //External Int 0 Interrupt Enable/Disable
-/*IP Flags*/
-#if (HAS_I8052 || HAS_I8752)
- #define SET_PT2(n) R_IP = (R_IP & 0xdf) | (n<<5); //Set Timer 2 Priority Level
-#endif
-#define SET_PS0(n) R_IP = (R_IP & 0xef) | (n<<4); //Set Serial Priority Level
-#define SET_PT1(n) R_IP = (R_IP & 0xf7) | (n<<3); //Set Timer 1 Priority Level
-#define SET_PX1(n) R_IP = (R_IP & 0xfb) | (n<<2); //Set External Int 1 Priority Level
-#define SET_PT0(n) R_IP = (R_IP & 0xfd) | (n<<1); //Set Timer 0 Priority Level
-#define SET_PX0(n) R_IP = (R_IP & 0xfe) | (n<<0); //Set External Int 0 Priority Level
-/*TCON Flags*/
-#define SET_TF1(n) R_TCON = (R_TCON & 0x7f) | (n<<7); //Indicated Timer 1 Overflow Int Triggered
-#define SET_TR1(n) R_TCON = (R_TCON & 0xbf) | (n<<6); //IndicateS Timer 1 is running
-#define SET_TF0(n) R_TCON = (R_TCON & 0xdf) | (n<<5); //Indicated Timer 0 Overflow Int Triggered
-#define SET_TR0(n) R_TCON = (R_TCON & 0xef) | (n<<4); //IndicateS Timer 0 is running
-#define SET_IE1(n) R_TCON = (R_TCON & 0xf7) | (n<<3); //Indicated External Int 1 Triggered
-#define SET_IT1(n) R_TCON = (R_TCON & 0xfb) | (n<<2); //Indicates how External Int 1 is Triggered
-#define SET_IE0(n) R_TCON = (R_TCON & 0xfd) | (n<<1); //Indicated External Int 0 Triggered
-#define SET_IT0(n) R_TCON = (R_TCON & 0xfe) | (n<<0); //Indicates how External Int 0 is Triggered
-/*SCON Flags*/
-#define SET_SM0(n) R_SCON = (R_SCON & 0x7f) | (n<<7); //Sets Serial Port Mode
-#define SET_SM1(n) R_SCON = (R_SCON & 0xbf) | (n<<6); //Sets Serial Port Mode
-#define SET_SM2(n) R_SCON = (R_SCON & 0xdf) | (n<<5); //Sets Serial Port Mode (Multiprocesser mode)
-#define SET_REN(n) R_SCON = (R_SCON & 0xef) | (n<<4); //Sets Serial Port Receive Enable
-#define SET_TB8(n) R_SCON = (R_SCON & 0xf7) | (n<<3); //Transmit 8th Bit
-#define SET_RB8(n) R_SCON = (R_SCON & 0xfb) | (n<<2); //Receive 8th Bit
-#define SET_TI(n) R_SCON = (R_SCON & 0xfd) | (n<<1); //Indicates Transmit Interrupt Occurred
-#define SET_RI(n) R_SCON = (R_SCON & 0xfe) | (n<<0); //Indicates Receive Interrupt Occurred
-/*TMOD Flags*/
-#define SET_GATE1(n) R_TMOD = (R_TMOD & 0x7f) | (n<<7); //Timer 1 Gate Mode
-#define SET_CT1(n) R_TMOD = (R_TMOD & 0xbf) | (n<<6); //Timer 1 Counter Mode
-#define SET_M1_1(n) R_TMOD = (R_TMOD & 0xdf) | (n<<5); //Timer 1 Timer Mode Bit 1
-#define SET_M1_0(n) R_TMOD = (R_TMOD & 0xef) | (n<<4); //Timer 1 Timer Mode Bit 0
-#define SET_GATE0(n) R_TMOD = (R_TMOD & 0xf7) | (n<<3); //Timer 0 Gate Mode
-#define SET_CT0(n) R_TMOD = (R_TMOD & 0xfb) | (n<<2); //Timer 0 Counter Mode
-#define SET_M0_1(n) R_TMOD = (R_TMOD & 0xfd) | (n<<1); //Timer 0 Timer Mode Bit 1
-#define SET_M0_0(n) R_TMOD = (R_TMOD & 0xfe) | (n<<0); //Timer 0 Timer Mode Bit 0
+#define IRAM_R(a) iram_read(a)
+#define IRAM_W(a, d) iram_write(a, d)
-#if (HAS_I8052 || HAS_I8752)
- /*T2CON Flags*/
- #define SET_TF2(n) R_T2CON = (R_T2CON & 0x7f) | (n<<7); //Indicated Timer 2 Overflow Int Triggered
- #define SET_EXF2(n) R_T2CON = (R_T2CON & 0xbf) | (n<<6); //Indicates Timer 2 External Flag
- #define SET_RCLK(n) R_T2CON = (R_T2CON & 0xdf) | (n<<5); //Receive Clock
- #define SET_TCLK(n) R_T2CON = (R_T2CON & 0xef) | (n<<4); //Transmit Clock
- #define SET_EXEN2(n) R_T2CON = (R_T2CON & 0xf7) | (n<<3); //Timer 2 External Interrupt Enable
- #define SET_TR2(n) R_T2CON = (R_T2CON & 0xfb) | (n<<2); //Indicates Timer 2 is running
- #define SET_CT2(n) R_T2CON = (R_T2CON & 0xfd) | (n<<1); //Sets Timer 2 Counter/Timer Mode
- #define SET_CP(n) R_T2CON = (R_T2CON & 0xfe) | (n<<0); //Sets Timer 2 Capture/Reload Mode
-#endif
+/* Read/Write a byte from/to the Internal RAM indirectly */
+/* (called from indirect addressing) */
+#define IRAM_IR(a) data_read_byte_8le((a) & mcs51.ram_mask)
+#define IRAM_IW(a, d) data_write_byte_8le((a) & mcs51.ram_mask, d)
-/***************************************************************
- * Easy macros for Getting Flags
- ***************************************************************/
-/*PSW Flags*/
-#define GET_CY ((R_PSW & 0x80)>>7)
-#define GET_AC ((R_PSW & 0x40)>>6)
-#define GET_FO ((R_PSW & 0x20)>>5)
-#define GET_RS ((R_PSW & 0x18)>>3)
-#define GET_OV ((R_PSW & 0x04)>>2)
-#define GET_P ((R_PSW & 0x01)>>0)
-/*IE Flags*/
-#define GET_EA ((R_IE & 0x80)>>7)
-#define GET_ET2 ((R_IE & 0x20)>>5)
-#define GET_ES ((R_IE & 0x10)>>4)
-#define GET_ET1 ((R_IE & 0x08)>>3)
-#define GET_EX1 ((R_IE & 0x04)>>2)
-#define GET_ET0 ((R_IE & 0x02)>>1)
-#define GET_EX0 ((R_IE & 0x01)>>0)
-/*IP Flags*/
-#if (HAS_I8052 || HAS_I8752)
- #define GET_PT2 ((R_IP & 0x20)>>5)
-#endif
-#define GET_PS ((R_IP & 0x10)>>4)
-#define GET_PT1 ((R_IP & 0x08)>>3)
-#define GET_PX1 ((R_IP & 0x04)>>2)
-#define GET_PT0 ((R_IP & 0x02)>>1)
-#define GET_PX0 ((R_IP & 0x01)>>0)
-/*TCON Flags*/
-#define GET_TF1 ((R_TCON & 0x80)>>7)
-#define GET_TR1 ((R_TCON & 0x40)>>6)
-#define GET_TF0 ((R_TCON & 0x20)>>5)
-#define GET_TR0 ((R_TCON & 0x10)>>4)
-#define GET_IE1 ((R_TCON & 0x08)>>3)
-#define GET_IT1 ((R_TCON & 0x04)>>2)
-#define GET_IE0 ((R_TCON & 0x02)>>1)
-#define GET_IT0 ((R_TCON & 0x01)>>0)
-/*SCON Flags*/
-#define GET_SM0 ((R_SCON & 0x80)>>7)
-#define GET_SM1 ((R_SCON & 0x40)>>6)
-#define GET_SM2 ((R_SCON & 0x20)>>5)
-#define GET_REN ((R_SCON & 0x10)>>4)
-#define GET_TB8 ((R_SCON & 0x08)>>3)
-#define GET_RB8 ((R_SCON & 0x04)>>2)
-#define GET_TI ((R_SCON & 0x02)>>1)
-#define GET_RI ((R_SCON & 0x01)>>0)
-/*TMOD Flags*/
-#define GET_GATE1 ((R_TMOD & 0x80)>>7)
-#define GET_CT1 ((R_TMOD & 0x40)>>6)
-#define GET_M1_1 ((R_TMOD & 0x20)>>5)
-#define GET_M1_0 ((R_TMOD & 0x10)>>4)
-#define GET_GATE0 ((R_TMOD & 0x08)>>3)
-#define GET_CT0 ((R_TMOD & 0x04)>>2)
-#define GET_M0_1 ((R_TMOD & 0x02)>>1)
-#define GET_M0_0 ((R_TMOD & 0x01)>>0)
+/* Form an Address to Read/Write to External RAM indirectly */
+/* (called from indirect addressing) */
+#define ERAM_ADDR(a,m) external_ram_iaddr(a,m)
-#if (HAS_I8052 || HAS_I8752)
- /*T2CON Flags*/
- #define GET_TF2 ((R_T2CON & 0x80)>>7)
- #define GET_EXF2 ((R_T2CON & 0x40)>>6)
- #define GET_RCLK ((R_T2CON & 0x20)>>5)
- #define GET_TCLK ((R_T2CON & 0x10)>>4)
- #define GET_EXEN2 ((R_T2CON & 0x08)>>3)
- #define GET_TR2 ((R_T2CON & 0x04)>>2)
- #define GET_CT2 ((R_T2CON & 0x02)>>1)
- #define GET_CP ((R_T2CON & 0x01)>>0)
-#endif
+/* Read/Write a bit from Bit Addressable Memory */
+#define BIT_R(a) bit_address_r(a)
+#define BIT_W(a,v) bit_address_w(a,v)
-/*Add and Subtract Flag settings*/
-#define DO_ADD_FLAGS(a,d,c) do_add_flags(a,d,c);
-#define DO_SUB_FLAGS(a,d,c) do_sub_flags(a,d,c);
+/* Input/Output a byte from given I/O port */
+#define IN(port) ((UINT8)io_read_byte(port))
+#define OUT(port,value) io_write_byte(port,value)
-#define SET_PARITY set_parity();
-#define PUSH_PC push_pc();
-#define POP_PC pop_pc();
-/* PC vectors */
-#define V_RESET 0x000 /* power on address */
-#define V_IE0 0x003 /* External Interrupt 0 */
-#define V_TF0 0x00b /* Timer 0 Overflow */
-#define V_IE1 0x013 /* External Interrupt 1 */
-#define V_TF1 0x01b /* Timer 1 Overflow */
-#define V_RITI 0x023 /* Serial Receive/Transmit */
+/***************************************************************************
+ SHORTCUTS
+***************************************************************************/
+
+#define PPC mcs51.ppc
+#define PC mcs51.pc
+#define RWM mcs51.rwm
+
+/* SFR Registers - These are accessed directly for speed on read */
+/* Read accessors */
+
+#define SFR_A(a) mcs51.sfr_ram[(a)]
+#define SET_SFR_A(a,v) do { SFR_A(a) = (v); } while (0)
+
+#define ACC ((const UINT8) SFR_A(ADDR_ACC))
+#define PSW ((const UINT8) SFR_A(ADDR_PSW))
+
+#define P0 ((const UINT8) SFR_A(ADDR_P0))
+#define P1 ((const UINT8) SFR_A(ADDR_P1))
+#define P2 ((const UINT8) SFR_A(ADDR_P2))
+#define P3 ((const UINT8) SFR_A(ADDR_P3))
+
+#define SP SFR_A(ADDR_SP)
+#define DPL SFR_A(ADDR_DPL)
+#define DPH SFR_A(ADDR_DPH)
+#define PCON SFR_A(ADDR_PCON)
+#define TCON SFR_A(ADDR_TCON)
+#define TMOD SFR_A(ADDR_TMOD)
+#define TL0 SFR_A(ADDR_TL0)
+#define TL1 SFR_A(ADDR_TL1)
+#define TH0 SFR_A(ADDR_TH0)
+#define TH1 SFR_A(ADDR_TH1)
+#define SCON SFR_A(ADDR_SCON)
+#define IE SFR_A(ADDR_IE)
+#define IP SFR_A(ADDR_IP)
+#define B SFR_A(ADDR_B)
+#define SBUF SFR_A(ADDR_SBUF)
+
+#define R_REG(r) mcs51.internal_ram[(r) | (PSW & 0x18)]
+#define DPTR ((DPH<<8) | DPL)
+
+/* 8052 Only registers */
+#define T2CON SFR_A(ADDR_T2CON)
+#define RCAP2L SFR_A(ADDR_RCAP2L)
+#define RCAP2H SFR_A(ADDR_RCAP2H)
+#define TL2 SFR_A(ADDR_TL2)
+#define TH2 SFR_A(ADDR_TH2)
+
+/* WRITE accessors */
+
+/* Shortcuts */
+
+#define SET_PSW(v) do { SFR_A(ADDR_PSW) = (v); SET_PARITY(); } while (0)
+#define SET_ACC(v) do { SFR_A(ADDR_ACC) = (v); SET_PARITY(); } while (0)
+
+/* These trigger actions on modification and have to be written through SFR_W */
+#define SET_P0(v) IRAM_W(ADDR_P0, v)
+#define SET_P1(v) IRAM_W(ADDR_P1, v)
+#define SET_P2(v) IRAM_W(ADDR_P2, v)
+#define SET_P3(v) IRAM_W(ADDR_P3, v)
+
+/* Within the cpu core, do not trigger a send */
+#define SET_SBUF(v) SET_SFR_A(ADDR_SBUF, v)
+
+/* No actions triggered on write */
+#define SET_REG(r, v) do { mcs51.internal_ram[(r) | (PSW & 0x18)] = (v); } while (0)
+
+#define SET_DPTR(n) do { DPH = ((n) >> 8) & 0xff; DPL = (n) & 0xff; } while (0)
+
+/* Macros for Setting Flags */
+#define SET_X(R, v) do { R = (v);} while (0)
+
+#define SET_CY(n) SET_PSW((PSW & 0x7f) | (n<<7)) //Carry Flag
+#define SET_AC(n) SET_PSW((PSW & 0xbf) | (n<<6)) //Aux.Carry Flag
+#define SET_FO(n) SET_PSW((PSW & 0xdf) | (n<<5)) //User Flag
+#define SET_RS(n) SET_PSW((PSW & 0xe7) | (n<<3)) //R Bank Select
+#define SET_OV(n) SET_PSW((PSW & 0xfb) | (n<<2)) //Overflow Flag
+#define SET_P(n) SET_PSW((PSW & 0xfe) | (n<<0)) //Parity Flag
+
+#define SET_BIT(R, n, v) do { R = (R & ~(1<<(n))) | ((v) << (n));} while (0)
+#define GET_BIT(R, n) (((R)>>(n)) & 0x01)
+
+#define SET_EA(n) SET_BIT(IE, 7, n) //Global Interrupt Enable/Disable
+#define SET_ES(n) SET_BIT(IE, 4, v) //Serial Interrupt Enable/Disable
+#define SET_ET1(n) SET_BIT(IE, 3, n) //Timer 1 Interrupt Enable/Disable
+#define SET_EX1(n) SET_BIT(IE, 2, n) //External Int 1 Interrupt Enable/Disable
+#define SET_ET0(n) SET_BIT(IE, 1, n) //Timer 0 Interrupt Enable/Disable
+#define SET_EX0(n) SET_BIT(IE, 0, n) //External Int 0 Interrupt Enable/Disable
+/* 8052 Only flags */
+#define SET_ET2(n) SET_BIT(IE, 5, n) //Timer 2 Interrupt Enable/Disable
+
+/* 8052 Only flags */
+#define SET_PT2(n) SET_BIT(IP, 5, n); //Set Timer 2 Priority Level
+
+#define SET_PS0(n) SET_BIT(IP, 4, n) //Set Serial Priority Level
+#define SET_PT1(n) SET_BIT(IP, 3, n) //Set Timer 1 Priority Level
+#define SET_PX1(n) SET_BIT(IP, 2, n) //Set External Int 1 Priority Level
+#define SET_PT0(n) SET_BIT(IP, 1, n) //Set Timer 0 Priority Level
+#define SET_PX0(n) SET_BIT(IP, 0, n) //Set External Int 0 Priority Level
+
+#define SET_TF1(n) SET_BIT(TCON, 7, n) //Indicated Timer 1 Overflow Int Triggered
+#define SET_TR1(n) SET_BIT(TCON, 6, n) //IndicateS Timer 1 is running
+#define SET_TF0(n) SET_BIT(TCON, 5, n) //Indicated Timer 0 Overflow Int Triggered
+#define SET_TR0(n) SET_BIT(TCON, 4, n) //IndicateS Timer 0 is running
+#define SET_IE1(n) SET_BIT(TCON, 3, n) //Indicated External Int 1 Triggered
+#define SET_IT1(n) SET_BIT(TCON, 2, n) //Indicates how External Int 1 is Triggered
+#define SET_IE0(n) SET_BIT(TCON, 1, n) //Indicated External Int 0 Triggered
+#define SET_IT0(n) SET_BIT(TCON, 0, n) //Indicates how External Int 0 is Triggered
+
+#define SET_SM0(n) SET_BIT(SCON, 7, n) //Sets Serial Port Mode
+#define SET_SM1(n) SET_BIT(SCON, 6, n) //Sets Serial Port Mode
+#define SET_SM2(n) SET_BIT(SCON, 5, n) //Sets Serial Port Mode (Multiprocesser mode)
+#define SET_REN(n) SET_BIT(SCON, 4, n) //Sets Serial Port Receive Enable
+#define SET_TB8(n) SET_BIT(SCON, 3, n) //Transmit 8th Bit
+#define SET_RB8(n) SET_BIT(SCON, 2, n) //Receive 8th Bit
+#define SET_TI(n) SET_BIT(SCON, 1, n) //Indicates Transmit Interrupt Occurred
+#define SET_RI(n) SET_BIT(SCON, 0, n) //Indicates Receive Interrupt Occurred
+
+#define SET_GATE1(n) SET_BIT(TMOD, 7, n) //Timer 1 Gate Mode
+#define SET_CT1(n) SET_BIT(TMOD, 6, n) //Timer 1 Counter Mode
+#define SET_M1_1(n) SET_BIT(TMOD, 5, n) //Timer 1 Timer Mode Bit 1
+#define SET_M1_0(n) SET_BIT(TMOD, 4, n) //Timer 1 Timer Mode Bit 0
+#define SET_GATE0(n) SET_BIT(TMOD, 3, n) //Timer 0 Gate Mode
+#define SET_CT0(n) SET_BIT(TMOD, 2, n) //Timer 0 Counter Mode
+#define SET_M0_1(n) SET_BIT(TMOD, 1, n) //Timer 0 Timer Mode Bit 1
+#define SET_M0_0(n) SET_BIT(TMOD, 0, n) //Timer 0 Timer Mode Bit 0
+
+
+
+/* 8052 Only flags - T2CON Flags */
+#define SET_TF2(n) SET_BIT(T2CON, 7, n) //Indicated Timer 2 Overflow Int Triggered
+#define SET_EXF2(n) SET_BIT(T2CON, 6, n) //Indicates Timer 2 External Flag
+#define SET_RCLK(n) SET_BIT(T2CON, 5, n) //Receive Clock
+#define SET_TCLK(n) SET_BIT(T2CON, 4, n) //Transmit Clock
+#define SET_EXEN2(n) SET_BIT(T2CON, 3, n) //Timer 2 External Interrupt Enable
+#define SET_TR2(n) SET_BIT(T2CON, 2, n) //Indicates Timer 2 is running
+#define SET_CT2(n) SET_BIT(T2CON, 1, n) //Sets Timer 2 Counter/Timer Mode
+#define SET_CP(n) SET_BIT(T2CON, 0, n) //Sets Timer 2 Capture/Reload Mode
+
+/* Macros for accessing flags */
+
+#define GET_CY GET_BIT(PSW, 7)
+#define GET_AC GET_BIT(PSW, 6)
+#define GET_FO GET_BIT(PSW, 5)
+#define GET_RS GET_BIT(PSW, 3)
+#define GET_OV GET_BIT(PSW, 2)
+#define GET_P GET_BIT(PSW, 0)
+
+#define GET_EA GET_BIT(IE, 7)
+#define GET_ET2 GET_BIT(IE, 5)
+#define GET_ES GET_BIT(IE, 4)
+#define GET_ET1 GET_BIT(IE, 3)
+#define GET_EX1 GET_BIT(IE, 2)
+#define GET_ET0 GET_BIT(IE, 1)
+#define GET_EX0 GET_BIT(IE, 0)
+
+/* 8052 Only flags */
+#define GET_PT2 GET_BIT(R_IP, 5)
+
+#define GET_PS GET_BIT(IP, 4)
+#define GET_PT1 GET_BIT(IP, 3)
+#define GET_PX1 GET_BIT(IP, 2)
+#define GET_PT0 GET_BIT(IP, 1)
+#define GET_PX0 GET_BIT(IP, 0)
+
+#define GET_TF1 GET_BIT(TCON, 7)
+#define GET_TR1 GET_BIT(TCON, 6)
+#define GET_TF0 GET_BIT(TCON, 5)
+#define GET_TR0 GET_BIT(TCON, 4)
+#define GET_IE1 GET_BIT(TCON, 3)
+#define GET_IT1 GET_BIT(TCON, 2)
+#define GET_IE0 GET_BIT(TCON, 1)
+#define GET_IT0 GET_BIT(TCON, 0)
+
+#define GET_SM0 GET_BIT(SCON, 7)
+#define GET_SM1 GET_BIT(SCON, 6)
+#define GET_SM2 GET_BIT(SCON, 5)
+#define GET_REN GET_BIT(SCON, 4)
+#define GET_TB8 GET_BIT(SCON, 3)
+#define GET_RB8 GET_BIT(SCON, 2)
+#define GET_TI GET_BIT(SCON, 1)
+#define GET_RI GET_BIT(SCON, 0)
+
+#define GET_GATE1 GET_BIT(TMOD, 7)
+#define GET_CT1 GET_BIT(TMOD, 6)
+#define GET_M1_1 GET_BIT(TMOD, 5)
+#define GET_M1_0 GET_BIT(TMOD, 4)
+#define GET_GATE0 GET_BIT(TMOD, 3)
+#define GET_CT0 GET_BIT(TMOD, 2)
+#define GET_M0_1 GET_BIT(TMOD, 1)
+#define GET_M0_0 GET_BIT(TMOD, 0)
+
+#define GET_SMOD GET_BIT(PCON, 7)
+#define GET_GF1 GET_BIT(TMOD, 3)
+#define GET_GF0 GET_BIT(TMOD, 2)
+#define GET_PD GET_BIT(TMOD, 1) /* Only in 80C51BH */
+#define GET_IDL GET_BIT(TMOD, 0) /* Only in 80C51BH */
+
+/* 8052 Only flags */
+#define GET_TF2 GET_BIT(T2CON, 7)
+#define GET_EXF2 GET_BIT(T2CON, 6)
+#define GET_RCLK GET_BIT(T2CON, 5)
+#define GET_TCLK GET_BIT(T2CON, 4)
+#define GET_EXEN2 GET_BIT(T2CON, 3)
+#define GET_TR2 GET_BIT(T2CON, 2)
+#define GET_CT2 GET_BIT(T2CON, 1)
+#define GET_CP GET_BIT(T2CON, 0)
-#if (HAS_I8052 || HAS_I8752)
-#define V_TF2 0x02b /* Timer 2 Overflow */
-#endif
+/*Add and Subtract Flag settings*/
+#define DO_ADD_FLAGS(a,d,c) do_add_flags(a,d,c)
+#define DO_SUB_FLAGS(a,d,c) do_sub_flags(a,d,c)
+#define SET_PARITY() do {mcs51.recalc_parity |= 1;} while (0)
+#define PUSH_PC() push_pc()
+#define POP_PC() pop_pc()
+
+#if 0
/* Any pending IRQ */
#define SERIALPORT_IRQ ((R_SCON & 0x03) && GET_ES)
#define TIMERS_IRQ ((GET_TF0 && GET_ET0) || (GET_TF1 && GET_ET1))
@@ -410,1051 +487,908 @@ static READ32_HANDLER((*hold_eram_iaddr_callback));
#else
#define NO_PENDING_IRQ !(TIMERS_IRQ) && !(EXTERNAL_IRQ) && !(SERIALPORT_IRQ)
#endif
+#endif
/* Clear Current IRQ */
-#define CLEAR_CURRENT_IRQ i8051.cur_irq = 0xff;\
- i8051.irq_priority = 0;
-
-/* shorter names for the I8051 structure elements */
-
-//Internal stuff
-#define PPC i8051.ppc
-#define PC i8051.pc
-#define TYPE i8051.subtype
-#define RWM i8051.rwm
-
-//SFR Registers
-#define R_P0 i8051.po
-#define R_SP i8051.sp
-#define R_DPL i8051.dpl
-#define R_DPH i8051.dph
-#define R_PCON i8051.pcon
-#define R_TCON i8051.tcon
-#define R_TMOD i8051.tmod
-#define R_TL0 i8051.tl0
-#define R_TL1 i8051.tl1
-#define R_TH0 i8051.th0
-#define R_TH1 i8051.th1
-#define R_P1 i8051.p1
-#define R_SCON i8051.scon
-#define R_SBUF i8051.sbuf
-#define R_P2 i8051.p2
-#define R_IE i8051.ie
-#define R_P3 i8051.p3
-#define R_IP i8051.ip
-//8052 Only registers
-#if (HAS_I8052 || HAS_I8752)
- #define R_T2CON i8051.t2con
- #define R_RCAP2L i8051.rcap2l
- #define R_RCAP2H i8051.rcap2h
- #define R_TL2 i8051.tl2
- #define R_TH2 i8051.th2
-#endif
-#define R_PSW i8051.psw
-#define R_ACC i8051.acc
-#define R_B i8051.b
+#define CLEAR_CURRENT_IRQ() do { mcs51.cur_irq = 0xff; mcs51.irq_priority = 0; } while (0)
-/* # of oscilations each opcode requires*/
-static const UINT8 i8051_cycles[] = {
- 12,24,24,12,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,24,12,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,24,12,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,24,12,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,12,24,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,12,24,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,12,24,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,24,24,12,24,12,12,12,12,12,12,12,12,12,12,
- 24,24,24,24,48,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,12,24,48,12,24,24,24,24,24,24,24,24,24,24,
- 24,24,12,12,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,12,12,12,24,12,12,24,24,24,24,24,24,24,24,
- 24,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12,
- 24,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
-};
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
-/* Include Opcode functions */
-#include "i8051ops.c"
+static int mcs51_icount;
-void i8051_init(int index, int clock, const void *config, int (*irqcallback)(int))
-{
- i8051_set_irq_callback(irqcallback);
+static mcs51_regs mcs51;
- //Internal stuff
- state_save_register_item("i8051", index, i8051.ppc);
- state_save_register_item("i8051", index, i8051.pc);
- state_save_register_item("i8051", index, i8051.subtype);
- state_save_register_item("i8051", index, i8051.rwm );
- state_save_register_item("i8051", index, i8051.cur_irq );
- state_save_register_item("i8051", index, i8051.irq_priority );
- state_save_register_item("i8051", index, i8051.prev_used_cycles );
- state_save_register_item("i8051", index, i8051.last_int0 );
- state_save_register_item("i8051", index, i8051.last_int1 );
- state_save_register_item("i8051", index, i8051.int_vec );
- state_save_register_item("i8051", index, i8051.priority_request );
- //SFR Registers
- state_save_register_item("i8051", index, i8051.po);
- state_save_register_item("i8051", index, i8051.sp);
- state_save_register_item("i8051", index, i8051.dpl);
- state_save_register_item("i8051", index, i8051.dph);
- state_save_register_item("i8051", index, i8051.pcon);
- state_save_register_item("i8051", index, i8051.tcon);
- state_save_register_item("i8051", index, i8051.tmod);
- state_save_register_item("i8051", index, i8051.tl0);
- state_save_register_item("i8051", index, i8051.tl1);
- state_save_register_item("i8051", index, i8051.th0);
- state_save_register_item("i8051", index, i8051.th1);
- state_save_register_item("i8051", index, i8051.p1);
- state_save_register_item("i8051", index, i8051.scon);
- state_save_register_item("i8051", index, i8051.sbuf);
- state_save_register_item("i8051", index, i8051.p2);
- state_save_register_item("i8051", index, i8051.ie);
- state_save_register_item("i8051", index, i8051.p3);
- state_save_register_item("i8051", index, i8051.ip);
- //8052 Only registers
- #if (HAS_I8052 || HAS_I8752)
- state_save_register_item("i8051", index, i8051.t2con);
- state_save_register_item("i8051", index, i8051.rcap2l);
- state_save_register_item("i8051", index, i8051.rcap2h);
- state_save_register_item("i8051", index, i8051.tl2);
- state_save_register_item("i8051", index, i8051.th2);
- #endif
- state_save_register_item("i8051", index, i8051.psw);
- state_save_register_item("i8051", index, i8051.acc);
- state_save_register_item("i8051", index, i8051.b);
- state_save_register_item_array("i8051", index, i8051.IntRam);
-}
-/* Reset registers to the initial values */
-void i8051_reset(void)
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void check_irqs(void);
+INLINE void serial_transmit(UINT8 data);
+
+/* Hold callback functions so they can be set by caller (before the cpu reset) */
+
+static void (*hold_serial_tx_callback)(int data);
+static int (*hold_serial_rx_callback)(void);
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE UINT8 r_acc(void) { return SFR_A(ADDR_ACC); }
+
+INLINE UINT8 r_psw(void) { return SFR_A(ADDR_PSW); }
+
+INLINE void update_ptrs(void)
{
- int (*save_irqcallback)(int);
+ mcs51.internal_ram = memory_get_write_ptr(cpu_getactivecpu(), ADDRESS_SPACE_DATA, 0x00);
+ mcs51.sfr_ram = memory_get_write_ptr(cpu_getactivecpu(), ADDRESS_SPACE_DATA, 0x100);
+}
- save_irqcallback = i8051.irq_callback;
- memset(&i8051, 0, sizeof(I8051));
- i8051.irq_callback = save_irqcallback;
- memset(&uart, 0, sizeof(I8051_UART));
- i8051.subtype = 8051;
+/* Generate an external ram address for read/writing using indirect addressing mode */
+/*The lowest 8 bits of the address are passed in (from the R0/R1 register), however
+ the hardware can be configured to set the rest of the address lines to any available output port pins, which
+ means the only way we can implement this is to allow the driver to setup a callback to generate the
+ address as defined by the specific hardware setup. We'll assume the address won't be bigger than 32 bits
- //Set up 8051 specific internal read/write (indirect) handlers..
- i8051.iram_iread = internal_ram_read; //Indirect ram read/write handled the same as direct for 8051!
- i8051.iram_iwrite = internal_ram_write; //Indirect ram read/write handled the same as direct for 8051!
+ Couriersud, October 2008:
+ There is no way external hardware can distinguish between 8bit access and 16 bit access.
+ During 16bit access the high order byte of the address is output on port 2. We therefore
+ assume that most hardware will use port 2 for 8bit access as well.
+
+ On configurations where 8 bit access in conjunction with other ports is used,
+ it is up to the driver to use AM_MIRROR to mask out the high level address and
+ provide it's own mapping.
+*/
- //Set up serial call back handlers
- i8051.serial_tx_callback = hold_serial_tx_callback;
- hold_serial_tx_callback = NULL;
- i8051.serial_rx_callback = hold_serial_rx_callback;
- hold_serial_rx_callback = NULL;
+INLINE offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask)
+{
+ if (mem_mask == 0x00ff)
+ return (offset & mem_mask) | (P2 << 8);
+#if 0
+ if(mcs51.eram_iaddr_callback)
+ return mcs51.eram_iaddr_callback(machine,offset,mem_mask);
+ else
+ if (mem_mask <= 0x100) LOG(("mcs51 #%d: external ram address requested (8 bit offset=%02x), but no callback available! at PC:%04x\n", cpu_getactivecpu(), offset, PC));
+#endif
+ return offset;
+}
- //Setup External ram callback handlers
- i8051.eram_iaddr_callback = hold_eram_iaddr_callback;
- hold_eram_iaddr_callback = NULL;
+/* Internal ram read/write */
- //Clear Ram (w/0xff)
- memset(&i8051.IntRam,0xff,sizeof(i8051.IntRam));
+INLINE UINT8 iram_read(size_t offset)
+{
+ return (((offset) < 0x80) ? data_read_byte_8le(offset) : mcs51.sfr_read(offset));
+}
- /* these are all defined reset states */
- PC = 0;
- SFR_W(SP, 0x7);
- SFR_W(PSW, 0);
- SFR_W(DPH, 0);
- SFR_W(DPL, 0);
- SFR_W(ACC, 0);
- SFR_W(B, 0);
- SFR_W(IP, 0);
- SFR_W(IE, 0);
- SFR_W(SCON, 0);
- SFR_W(TCON, 0);
- SFR_W(TMOD, 0);
- SFR_W(TH1, 0);
- SFR_W(TH0, 0);
- SFR_W(TL1, 0);
- SFR_W(TL0, 0);
- /* set the port configurations to all 1's */
- SFR_W(P3, 0xff);
- SFR_W(P2, 0xff);
- SFR_W(P1, 0xff);
- SFR_W(P0, 0xff);
+INLINE void iram_write(size_t offset, UINT8 data)
+{
+ if ((offset) < 0x80)
+ data_write_byte_8le(offset, data);
+ else
+ mcs51.sfr_write(offset, data);
+}
- /* Flag as NO IRQ in Progress */
- CLEAR_CURRENT_IRQ
+/*Push the current PC to the stack*/
+INLINE void push_pc(void)
+{
+ UINT8 tmpSP = SP+1; //Grab and Increment Stack Pointer
+ IRAM_IW(tmpSP, (PC & 0xff)); //Store low byte of PC to Internal Ram (Use IRAM_IW to store stack above 128 bytes)
+ tmpSP++; // ""
+ SP = tmpSP; // ""
+ IRAM_IW(tmpSP, ( (PC & 0xff00) >> 8)); //Store hi byte of PC to next address in Internal Ram (Use IRAM_IW to store stack above 128 bytes)
}
-/* Shut down CPU core */
-void i8051_exit(void)
+/*Pop the current PC off the stack and into the pc*/
+INLINE void pop_pc(void)
{
- /* nothing to do */
+ UINT8 tmpSP = SP; //Grab Stack Pointer
+ PC = (IRAM_IR(tmpSP--) & 0xff) << 8; //Store hi byte to PC (must use IRAM_IR to access stack pointing above 128 bytes)
+ PC = PC | IRAM_IR(tmpSP--); //Store lo byte to PC (must use IRAM_IR to access stack pointing above 128 bytes)
+ SP = tmpSP; //Decrement Stack Pointer
+ change_pc(PC);
}
-/* Execute cycles - returns number of cycles actually run */
-int i8051_execute(int cycles)
+//Set the PSW Parity Flag
+INLINE void set_parity(void)
{
- i8051_icount = cycles;
+ //This flag will be set when the accumulator contains an odd # of bits set..
+ UINT8 p = 0;
+ int i;
+ UINT8 a = ACC;
+
+ for (i=0; i<8; i++) { //Test for each of the 8 bits in the ACC!
+ p ^= (a & 1);
+ a = (a >> 1);
+ }
- do
- {
- //Read next opcode
- UINT8 op = cpu_readop(PC);
+ SET_P(p & 1);
+}
- //Store previous PC
- PPC = PC;
+INLINE UINT8 bit_address_r(UINT8 offset)
+{
+ int word;
+ UINT8 mask;
+ int bit_pos;
+ int distance; /* distance between bit addressable words */
+ /* 1 for normal bits, 8 for sfr bit addresses */
- //Call Debugger
- debugger_instruction_hook(Machine, PC);
+ //User defined bit addresses 0x20-0x2f (values are 0x0-0x7f)
+ if (offset < 0x80) {
+ distance = 1;
+ word = ( (offset & 0x78) >> 3) * distance + 0x20;
+ bit_pos = offset & 0x7;
+ mask = 0x1 << bit_pos;
+ return((IRAM_R(word) & mask) >> bit_pos);
+ }
+ //SFR bit addressable registers
+ else {
+ distance = 8;
+ word = ( (offset & 0x78) >> 3) * distance + 0x80;
+ bit_pos = offset & 0x7;
+ mask = 0x1 << bit_pos;
+ return ((IRAM_R(word) & mask) >> bit_pos);
+ }
+}
+
+
+INLINE void bit_address_w(UINT8 offset, UINT8 bit)
+{
+ int word;
+ UINT8 mask;
+ int bit_pos;
+ UINT8 result;
+ int distance;
+
+ /* User defined bit addresses 0x20-0x2f (values are 0x0-0x7f) */
+ if (offset < 0x80) {
+ distance = 1;
+ word = ((offset & 0x78) >> 3) * distance + 0x20;
+ bit_pos = offset & 0x7;
+ bit = (bit & 0x1) << bit_pos;
+ mask = ~(1 << bit_pos) & 0xff;
+ result = IRAM_R(word) & mask;
+ result = result | bit;
+ IRAM_W(word, result);
+ }
+ /* SFR bit addressable registers */
+ else {
+ distance = 8;
+ word = ((offset & 0x78) >> 3) * distance + 0x80;
+ bit_pos = offset & 0x7;
+ bit = (bit & 0x1) << bit_pos;
+ mask = ~(1 << bit_pos) & 0xff;
+ result = IRAM_R(word) & mask;
+ result = result | bit;
+ IRAM_W(word, result);
+ }
+}
- //remove after testing
- if(PC != PPC) op = cpu_readop(PC);
+INLINE void do_add_flags(UINT8 a, UINT8 data, UINT8 c)
+{
+ UINT16 result = a+data+c;
+ INT16 result1 = (INT8)a+(INT8)data+c;
+
+ SET_CY((result & 0x100) >> 8);
+ result = (a&0x0f)+(data&0x0f)+c;
+ SET_AC((result & 0x10) >> 4);
+ SET_OV(result1 < -128 || result1 > 127);
+}
- //Update Timer (if any timers are running)
- if(GET_TR0 || GET_TR1)
- update_timer(i8051.prev_used_cycles);
+INLINE void do_sub_flags(UINT8 a, UINT8 data, UINT8 c)
+{
+ UINT16 result = a-(data+c);
+ INT16 result1 = (INT8)a-(INT8)(data+c);
- //Update Serial (if serial port sending data)
- if(uart.sending)
- update_serial(i8051.prev_used_cycles);
+ SET_CY((result & 0x100) >> 8);
+ result = (a&0x0f)-((data&0x0f)+c);
+ SET_AC((result & 0x10) >> 4);
+ SET_OV((result1 < -128 || result1 > 127));
+}
- //Update PC
- PC += 1;
- //Decrement total count by # of cycles used for this opcode
- i8051_icount -= (i8051_cycles[op]);
+INLINE void transmit_receive(int source)
+{
+ int mode = (GET_SM0<<1) | GET_SM1;
+
+ if (source == 1) /* timer1 */
+ mcs51.uart.smod_div = (mcs51.uart.smod_div + 1) & (2-GET_SMOD);
- switch( op )
+ switch(mode) {
+ //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
+ case 0:
+ mcs51.uart.rx_clk += (source == 0) ? 16 : 0; /* clock / 12 */
+ mcs51.uart.tx_clk += (source == 0) ? 16 : 0; /* clock / 12 */
+ break;
+ //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
+ case 1:
+ if (source == 1)
+ {
+ mcs51.uart.tx_clk += (GET_TCLK ? 0 : !mcs51.uart.smod_div);
+ mcs51.uart.rx_clk += (GET_RCLK ? 0 : !mcs51.uart.smod_div);
+ }
+ if (source == 2)
+ {
+ mcs51.uart.tx_clk += (GET_TCLK ? 1 : 0);
+ mcs51.uart.rx_clk += (GET_RCLK ? 1 : 0);
+ }
+ break;
+ //9 bit uart
+ case 2:
+ case 3:
+ LOG(("Serial mode 2 & 3 not supported in mcs51!\n"));
+ break;
+ }
+ /* transmit ? */
+ if (mcs51.uart.tx_clk >= 16)
+ {
+ mcs51.uart.tx_clk &= 0x0f;
+ if(mcs51.uart.bits_to_send)
{
- //NOP
- case 0x00: /* 1: 0000 0000 */
- nop();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0x01:
- ajmp();
+ mcs51.uart.bits_to_send--;
+ if(mcs51.uart.bits_to_send == 0) {
+ //printf("Here1 %d\n", mcs51.uart.bits_to_send);
+ //Call the callback function
+ if(mcs51.serial_tx_callback)
+ mcs51.serial_tx_callback(mcs51.uart.data_out);
+ //Set Interrupt Flag
+ SET_TI(1);
+ //Note: we'll let the main loop catch the interrupt
+ }
+ }
+
+ }
+ /* receive */
+ if (mcs51.uart.rx_clk >= 16)
+ {
+ mcs51.uart.rx_clk &= 0x0f;
+ if (mcs51.uart.delay_cycles>0)
+ {
+ mcs51.uart.delay_cycles--;
+ if (mcs51.uart.delay_cycles == 0)
+ {
+ int data = 0;
+ //Call our callball function to retrieve the data
+ if(mcs51.serial_rx_callback)
+ data = mcs51.serial_rx_callback();
+ //printf("RX Deliver %d\n", data);
+ SET_SBUF(data);
+ //Flag the IRQ
+ SET_RI(1);
+ }
+ }
+ }
+}
+
+
+INLINE void update_timer_t0(int cycles)
+{
+ int mode = (GET_M0_1<<1) | GET_M0_0;
+ UINT32 count = 0;
+
+ if (GET_TR0)
+ {
+ UINT32 delta;
+
+ /* counter / external input */
+ delta = GET_CT0 ? mcs51.t0_cnt : cycles;
+ /* taken, reset */
+ mcs51.t0_cnt = 0;
+ /* TODO: Not sure about IE0. The manual specifies INT0=high,
+ * which in turn means CLEAR_LINE.
+ * IE0 may be edge triggered depending on IT0 */
+ if (GET_GATE0 && !GET_IE0)
+ delta = 0;
+
+ switch(mode) {
+ case 0: /* 13 Bit Timer Mode */
+ count = ((TH0<<5) | ( TL0 & 0x1f ) );
+ count += delta;
+ if ( count & 0xffffe000 ) /* Check for overflow */
+ SET_TF0(1);
+ TH0 = (count>>5) & 0xff;
+ TL0 = count & 0x1f ;
break;
- //LJMP code addr
- case 0x02: /* 1: 0000 0010 */
- ljmp();
+ case 1: /* 16 Bit Timer Mode */
+ count = ((TH0<<8) | TL0);
+ count += delta;
+ if ( count & 0xffff0000 ) /* Check for overflow */
+ SET_TF0(1);
+ TH0 = (count>>8) & 0xff;
+ TL0 = count & 0xff;
break;
- //RR A
- case 0x03: /* 1: 0000 0011 */
- rr_a();
+ case 2: /* 8 Bit Autoreload */
+ count = (UINT32) TL0 + delta;
+ if ( count & 0xffffff00 ) /* Check for overflow */
+ {
+ SET_TF0(1);
+ count += TH0; /* Reload timer */
+ }
+ /* Update new values of the counter */
+ TL0 = count & 0xff;
break;
- //INC A
- case 0x04: /* 1: 0000 0100 */
- inc_a();
+ case 3:
+ /* Split Timer 1 */
+ count = (UINT16) TL0 + delta;
+ if ( count & 0xffffff00 ) /* Check for overflow */
+ SET_TF0(1);
+ TL0 = count & 0xff; /* Update new values of the counter */
break;
- //INC data addr
- case 0x05: /* 1: 0000 0101 */
- RWM=1;
- inc_mem();
- RWM=0;
+ }
+ }
+ if (GET_TR1)
+ {
+ switch(mode)
+ {
+ case 3:
+ /* Split Timer 2 */
+ count = (UINT16) TH0 + cycles; /* No gate control or counting !*/
+ if ( count & 0xffffff00 ) /* Check for overflow */
+ SET_TF1(1);
+ TH0 = count & 0xff; /* Update new values of the counter */
break;
- //INC @R0/@R1 /* 1: 0000 011i */
- case 0x06:
- case 0x07:
- inc_ir(op&1);
- break;
- //INC R0 to R7 /* 1: 0000 1rrr */
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
- inc_r(op&7);
- break;
- //JBC bit addr, code addr
- case 0x10: /* 1: 0001 0000 */
- RWM=1;
- jbc();
- RWM=0;
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0x11:
- acall();
- break;
- //LCALL code addr
- case 0x12: /* 1: 0001 0010 */
- lcall();
- break;
- //RRC A
- case 0x13: /* 1: 0001 0011 */
- rrc_a();
- break;
- //DEC A
- case 0x14: /* 1: 0001 0100 */
- dec_a();
- break;
- //DEC data addr
- case 0x15: /* 1: 0001 0101 */
- RWM=1;
- dec_mem();
- RWM=0;
- break;
- //DEC @R0/@R1 /* 1: 0001 011i */
- case 0x16:
- case 0x17:
- dec_ir(op&1);
- break;
- //DEC R0 to R7 /* 1: 0001 1rrr */
- case 0x18:
- case 0x19:
- case 0x1a:
- case 0x1b:
- case 0x1c:
- case 0x1d:
- case 0x1e:
- case 0x1f:
- dec_r(op&7);
- break;
- //JB bit addr, code addr
- case 0x20: /* 1: 0010 0000 */
- jb();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0x21:
- ajmp();
- break;
- //RET
- case 0x22: /* 1: 0010 0010 */
- ret();
- break;
- //RL A
- case 0x23: /* 1: 0010 0011 */
- rl_a();
- break;
- //ADD A, #data
- case 0x24: /* 1: 0010 0100 */
- add_a_byte();
- break;
- //ADD A, data addr
- case 0x25: /* 1: 0010 0101 */
- add_a_mem();
- break;
- //ADD A, @R0/@R1 /* 1: 0010 011i */
- case 0x26:
- case 0x27:
- add_a_ir(op&1);
- break;
- //ADD A, R0 to R7 /* 1: 0010 1rrr */
- case 0x28:
- case 0x29:
- case 0x2a:
- case 0x2b:
- case 0x2c:
- case 0x2d:
- case 0x2e:
- case 0x2f:
- add_a_r(op&7);
- break;
- //JNB bit addr, code addr
- case 0x30: /* 1: 0011 0000 */
- jnb();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0x31:
- acall();
- break;
- //RETI
- case 0x32: /* 1: 0011 0010 */
- reti();
- break;
- //RLC A
- case 0x33: /* 1: 0011 0011 */
- rlc_a();
- break;
- //ADDC A, #data
- case 0x34: /* 1: 0011 0100 */
- addc_a_byte();
- break;
- //ADDC A, data addr
- case 0x35: /* 1: 0011 0101 */
- addc_a_mem();
- break;
- //ADDC A, @R0/@R1 /* 1: 0011 011i */
- case 0x36:
- case 0x37:
- addc_a_ir(op&1);
- break;
- //ADDC A, R0 to R7 /* 1: 0011 1rrr */
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- case 0x3c:
- case 0x3d:
- case 0x3e:
- case 0x3f:
- addc_a_r(op&7);
- break;
- //JC code addr
- case 0x40: /* 1: 0100 0000 */
- jc();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0x41:
- ajmp();
- break;
- //ORL data addr, A
- case 0x42: /* 1: 0100 0010 */
- RWM=1;
- orl_mem_a();
- RWM=0;
- break;
- //ORL data addr, #data
- case 0x43: /* 1: 0100 0011 */
- RWM=1;
- orl_mem_byte();
- RWM=0;
- break;
- //ORL A, #data
- case 0x44: /* 1: 0100 0100 */
- orl_a_byte();
- break;
- //ORL A, data addr
- case 0x45: /* 1: 0100 0101 */
- orl_a_mem();
- break;
- //ORL A, @RO/@R1 /* 1: 0100 011i */
- case 0x46:
- case 0x47:
- orl_a_ir(op&1);
- break;
- //ORL A, RO to R7 /* 1: 0100 1rrr */
- case 0x48:
- case 0x49:
- case 0x4a:
- case 0x4b:
- case 0x4c:
- case 0x4d:
- case 0x4e:
- case 0x4f:
- orl_a_r(op&7);
- break;
- //JNC code addr
- case 0x50: /* 1: 0101 0000 */
- jnc();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0x51:
- acall();
- break;
- //ANL data addr, A
- case 0x52: /* 1: 0101 0010 */
- RWM=1;
- anl_mem_a();
- RWM=0;
- break;
- //ANL data addr, #data
- case 0x53: /* 1: 0101 0011 */
- RWM=1;
- anl_mem_byte();
- RWM=0;
- break;
- //ANL A, #data
- case 0x54: /* 1: 0101 0100 */
- anl_a_byte();
- break;
- //ANL A, data addr
- case 0x55: /* 1: 0101 0101 */
- anl_a_mem();
- break;
- //ANL A, @RO/@R1 /* 1: 0101 011i */
- case 0x56:
- case 0x57:
- anl_a_ir(op&1);
- break;
- //ANL A, RO to R7 /* 1: 0101 1rrr */
- case 0x58:
- case 0x59:
- case 0x5a:
- case 0x5b:
- case 0x5c:
- case 0x5d:
- case 0x5e:
- case 0x5f:
- anl_a_r(op&7);
- break;
- //JZ code addr
- case 0x60: /* 1: 0110 0000 */
- jz();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0x61:
- ajmp();
- break;
- //XRL data addr, A
- case 0x62: /* 1: 0110 0010 */
- RWM=1;
- xrl_mem_a();
- RWM=0;
- break;
- //XRL data addr, #data
- case 0x63: /* 1: 0110 0011 */
- RWM=1;
- xrl_mem_byte();
- RWM=0;
- break;
- //XRL A, #data
- case 0x64: /* 1: 0110 0100 */
- xrl_a_byte();
- break;
- //XRL A, data addr
- case 0x65: /* 1: 0110 0101 */
- xrl_a_mem();
- break;
- //XRL A, @R0/@R1 /* 1: 0110 011i */
- case 0x66:
- case 0x67:
- xrl_a_ir(op&1);
- break;
- //XRL A, R0 to R7 /* 1: 0110 1rrr */
- case 0x68:
- case 0x69:
- case 0x6a:
- case 0x6b:
- case 0x6c:
- case 0x6d:
- case 0x6e:
- case 0x6f:
- xrl_a_r(op&7);
- break;
- //JNZ code addr
- case 0x70: /* 1: 0111 0000 */
- jnz();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0x71:
- acall();
- break;
- //ORL C, bit addr
- case 0x72: /* 1: 0111 0010 */
- orl_c_bitaddr();
- break;
- //JMP @A+DPTR
- case 0x73: /* 1: 0111 0011 */
- jmp_iadptr();
- break;
- //MOV A, #data
- case 0x74: /* 1: 0111 0100 */
- mov_a_byte();
- break;
- //MOV data addr, #data
- case 0x75: /* 1: 0111 0101 */
- mov_mem_byte();
- break;
- //MOV @R0/@R1, #data /* 1: 0111 011i */
- case 0x76:
- case 0x77:
- mov_ir_byte(op&1);
- break;
- //MOV R0 to R7, #data /* 1: 0111 1rrr */
- case 0x78:
- case 0x79:
- case 0x7a:
- case 0x7b:
- case 0x7c:
- case 0x7d:
- case 0x7e:
- case 0x7f:
- mov_r_byte(op&7);
- break;
- //SJMP code addr
- case 0x80: /* 1: 1000 0000 */
- sjmp();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0x81:
- ajmp();
- break;
- //ANL C, bit addr
- case 0x82: /* 1: 1000 0010 */
- anl_c_bitaddr();
- break;
- //MOVC A, @A + PC
- case 0x83: /* 1: 1000 0011 */
- movc_a_iapc();
- break;
- //DIV AB
- case 0x84: /* 1: 1000 0100 */
- div_ab();
- break;
- //MOV data addr, data addr
- case 0x85: /* 1: 1000 0101 */
- mov_mem_mem();
- break;
- //MOV data addr, @R0/@R1 /* 1: 1000 011i */
- case 0x86:
- case 0x87:
- mov_mem_ir(op&1);
- break;
- //MOV data addr,R0 to R7 /* 1: 1000 1rrr */
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- case 0x8c:
- case 0x8d:
- case 0x8e:
- case 0x8f:
- mov_mem_r(op&7);
- break;
- //MOV DPTR, #data
- case 0x90: /* 1: 1001 0000 */
- mov_dptr_byte();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0x91:
- acall();
- break;
- //MOV bit addr, C
- case 0x92: /* 1: 1001 0010 */
- RWM = 1;
- mov_bitaddr_c();
- RWM = 0;
- break;
- //MOVC A, @A + DPTR
- case 0x93: /* 1: 1001 0011 */
- movc_a_iadptr();
- break;
- //SUBB A, #data
- case 0x94: /* 1: 1001 0100 */
- subb_a_byte();
- break;
- //SUBB A, data addr
- case 0x95: /* 1: 1001 0101 */
- subb_a_mem();
- break;
- //SUBB A, @R0/@R1 /* 1: 1001 011i */
- case 0x96:
- case 0x97:
- subb_a_ir(op&1);
- break;
- //SUBB A, R0 to R7 /* 1: 1001 1rrr */
- case 0x98:
- case 0x99:
- case 0x9a:
- case 0x9b:
- case 0x9c:
- case 0x9d:
- case 0x9e:
- case 0x9f:
- subb_a_r(op&7);
- break;
- //ORL C, /bit addr
- case 0xa0: /* 1: 1010 0000 */
- orl_c_nbitaddr();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0xa1:
- ajmp();
- break;
- //MOV C, bit addr
- case 0xa2: /* 1: 1010 0010 */
- mov_c_bitaddr();
- break;
- //INC DPTR
- case 0xa3: /* 1: 1010 0011 */
- inc_dptr();
- break;
- //MUL AB
- case 0xa4: /* 1: 1010 0100 */
- mul_ab();
- break;
- //reserved
- case 0xa5: /* 1: 1010 0101 */
- illegal();
- break;
- //MOV @R0/@R1, data addr /* 1: 1010 011i */
- case 0xa6:
- case 0xa7:
- mov_ir_mem(op&1);
- break;
- //MOV R0 to R7, data addr /* 1: 1010 1rrr */
- case 0xa8:
- case 0xa9:
- case 0xaa:
- case 0xab:
- case 0xac:
- case 0xad:
- case 0xae:
- case 0xaf:
- mov_r_mem(op&7);
- break;
- //ANL C,/bit addr
- case 0xb0: /* 1: 1011 0000 */
- anl_c_nbitaddr();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0xb1:
- acall();
- break;
- //CPL bit addr
- case 0xb2: /* 1: 1011 0010 */
- RWM=1;
- cpl_bitaddr();
- RWM=0;
- break;
- //CPL C
- case 0xb3: /* 1: 1011 0011 */
- cpl_c();
- break;
- //CJNE A, #data, code addr
- case 0xb4: /* 1: 1011 0100 */
- cjne_a_byte();
- break;
- //CJNE A, data addr, code addr
- case 0xb5: /* 1: 1011 0101 */
- cjne_a_mem();
- break;
- //CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */
- case 0xb6:
- case 0xb7:
- cjne_ir_byte(op&1);
- break;
- //CJNE R0 to R7, #data, code addr/* 1: 1011 1rrr */
- case 0xb8:
- case 0xb9:
- case 0xba:
- case 0xbb:
- case 0xbc:
- case 0xbd:
- case 0xbe:
- case 0xbf:
- cjne_r_byte(op&7);
- break;
- //PUSH data addr
- case 0xc0: /* 1: 1100 0000 */
- push();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0xc1:
- ajmp();
- break;
- //CLR bit addr
- case 0xc2: /* 1: 1100 0010 */
- RWM=1;
- clr_bitaddr();
- RWM=0;
- break;
- //CLR C
- case 0xc3: /* 1: 1100 0011 */
- clr_c();
- break;
- //SWAP A
- case 0xc4: /* 1: 1100 0100 */
- swap_a();
- break;
- //XCH A, data addr
- case 0xc5: /* 1: 1100 0101 */
- xch_a_mem();
- break;
- //XCH A, @RO/@R1 /* 1: 1100 011i */
- case 0xc6:
- case 0xc7:
- xch_a_ir(op&1);
- break;
- //XCH A, RO to R7 /* 1: 1100 1rrr */
- case 0xc8:
- case 0xc9:
- case 0xca:
- case 0xcb:
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xcf:
- xch_a_r(op&7);
- break;
- //POP data addr
- case 0xd0: /* 1: 1101 0000 */
- pop();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0xd1:
- acall();
- break;
- //SETB bit addr
- case 0xd2: /* 1: 1101 0010 */
- RWM=1;
- setb_bitaddr();
- RWM=0;
- break;
- //SETB C
- case 0xd3: /* 1: 1101 0011 */
- setb_c();
- break;
- //DA A
- case 0xd4: /* 1: 1101 0100 */
- da_a();
- break;
- //DJNZ data addr, code addr
- case 0xd5: /* 1: 1101 0101 */
- RWM=1;
- djnz_mem();
- RWM=0;
- break;
- //XCHD A, @R0/@R1 /* 1: 1101 011i */
- case 0xd6:
- case 0xd7:
- xchd_a_ir(op&1);
- break;
- //DJNZ R0 to R7,code addr /* 1: 1101 1rrr */
- case 0xd8:
- case 0xd9:
- case 0xda:
- case 0xdb:
- case 0xdc:
- case 0xdd:
- case 0xde:
- case 0xdf:
- djnz_r(op&7);
- break;
- //MOVX A,@DPTR
- case 0xe0: /* 1: 1110 0000 */
- movx_a_idptr();
- break;
- //AJMP code addr /* 1: aaa0 0001 */
- case 0xe1:
- ajmp();
- break;
- //MOVX A, @R0/@R1 /* 1: 1110 001i */
- case 0xe2:
- case 0xe3:
- movx_a_ir(op&1);
- break;
- //CLR A
- case 0xe4: /* 1: 1110 0100 */
- clr_a();
- break;
- //MOV A, data addr
- case 0xe5: /* 1: 1110 0101 */
- mov_a_mem();
- break;
- //MOV A,@RO/@R1 /* 1: 1110 011i */
- case 0xe6:
- case 0xe7:
- mov_a_ir(op&1);
- break;
- //MOV A,R0 to R7 /* 1: 1110 1rrr */
- case 0xe8:
- case 0xe9:
- case 0xea:
- case 0xeb:
- case 0xec:
- case 0xed:
- case 0xee:
- case 0xef:
- mov_a_r(op&7);
- break;
- //MOVX @DPTR,A
- case 0xf0: /* 1: 1111 0000 */
- movx_idptr_a();
- break;
- //ACALL code addr /* 1: aaa1 0001 */
- case 0xf1:
- acall();
- break;
- //MOVX @R0/@R1,A /* 1: 1111 001i */
- case 0xf2:
- case 0xf3:
- movx_ir_a(op&1);
- break;
- //CPL A
- case 0xf4: /* 1: 1111 0100 */
- cpl_a();
+ }
+ }
+}
+
+INLINE void update_timer_t1(int cycles)
+{
+ int mode = (GET_M1_1<<1) | GET_M1_0;
+ UINT32 count = 0;
+
+ if (GET_TR1)
+ {
+ UINT32 delta;
+ int overflow = 0;
+
+ /* counter / external input */
+ delta = GET_CT1 ? mcs51.t1_cnt : cycles;
+ /* taken, reset */
+ mcs51.t1_cnt = 0;
+ /* TODO: Not sure about IE0. The manual specifies INT0=high,
+ * which in turn means CLEAR_LINE. Change to access last_state?
+ * IE0 may be edge triggered depending on IT0 */
+ if (GET_GATE1 && !GET_IE1)
+ delta = 0;
+
+ //printf("mode: %d\n", mode);
+ switch(mode) {
+ case 0: /* 13 Bit Timer Mode */
+ count = ((TH1<<5) | ( TL1 & 0x1f ) );
+ count += delta;
+ overflow = count & 0xffffe000; /* Check for overflow */
+ if ( overflow )
+ SET_TF1(1);
+ TH1 = (count>>5) & 0xff;
+ TL1 = count & 0x1f ;
break;
- //MOV data addr, A
- case 0xf5: /* 1: 1111 0101 */
- mov_mem_a();
+ case 1: /* 16 Bit Timer Mode */
+ count = ((TH1<<8) | TL1);
+ count += delta;
+ overflow = count & 0xffff0000; /* Check for overflow */
+ if ( overflow )
+ {
+ SET_TF1(1);
+ }
+ TH1 = (count>>8) & 0xff;
+ TL1 = count & 0xff;
break;
- //MOV @R0/@R1, A /* 1: 1111 011i */
- case 0xf6:
- case 0xf7:
- mov_ir_a(op&1);
+ case 2: /* 8 Bit Autoreload */
+ count = (UINT32) TL1 + delta;
+ overflow = count & 0xffffff00; /* Check for overflow */
+ if ( overflow )
+ {
+ SET_TF1(1);
+ count += TH1; /* Reload timer */
+ }
+ /* Update new values of the counter */
+ TL1 = count & 0xff;
break;
- //MOV R0 to R7, A /* 1: 1111 1rrr */
- case 0xf8:
- case 0xf9:
- case 0xfa:
- case 0xfb:
- case 0xfc:
- case 0xfd:
- case 0xfe:
- case 0xff:
- mov_r_a(op&7);
+ case 3:
+ /* do nothing */
break;
- default:
- illegal();
}
+ if (overflow)
+ transmit_receive(1);
+ }
+}
- //Store # of used cycles for this opcode (for timer & serial check at top of code)
- i8051.prev_used_cycles = i8051_cycles[op];
-
- //Check for pending interrupts & handle - remove cycles used
- i8051_icount-=check_interrupts();
+INLINE void update_timer_t2(int cycles)
+{
+ /* Update Timer 2 */
+ if(GET_TR2) {
+ int mode = ((GET_TCLK | GET_RCLK) << 1) | GET_CP;
+ int delta = GET_CT2 ? mcs51.t2_cnt : (mode & 2) ? cycles * (12/2) : cycles;
- } while( i8051_icount > 0 );
+ UINT32 count = ((TH2<<8) | TL2) + delta;
+ mcs51.t2_cnt = 0;
- return cycles - i8051_icount;
+ switch (mode)
+ {
+ case 0: /* 16 Bit Auto Reload */
+ if ( count & 0xffff0000 )
+ {
+ SET_TF2(1);
+ count += ((RCAP2H<<8) | RCAP2L);
+ }
+ else if (GET_EXEN2 && mcs51.t2ex_cnt>0)
+ {
+ count += ((RCAP2H<<8) | RCAP2L);
+ mcs51.t2ex_cnt = 0;
+ }
+ TH2 = (count>>8) & 0xff;
+ TL2 = count & 0xff;
+ break;
+ case 1: /* 16 Bit Capture */
+ if ( count & 0xffff0000 )
+ SET_TF2(1);
+ TH2 = (count>>8) & 0xff;
+ TL2 = count & 0xff;
+
+ if (GET_EXEN2 && mcs51.t2ex_cnt>0)
+ {
+ RCAP2H = TH2;
+ RCAP2L = TL2;
+ mcs51.t2ex_cnt = 0;
+ }
+ break;
+ case 2:
+ case 3: /* Baud rate */
+ if ( count & 0xffff0000 )
+ {
+ count += ((RCAP2H<<8) | RCAP2L);
+ transmit_receive(2);
+ }
+ TH2 = (count>>8) & 0xff;
+ TL2 = count & 0xff;
+ break;
+ }
+ }
}
-/* Get registers, return context size */
-void i8051_get_context(void *dst)
+INLINE void update_timers(int cycles)
{
- if( dst )
- memcpy(dst, &i8051, sizeof(I8051));
-}
+ if (cycles == 0)
+ return; /* nothing to do */
+ /* Update Timer 0 */
+ update_timer_t0(cycles);
+ update_timer_t1(cycles);
-/* Set registers */
-void i8051_set_context(void *src)
-{
- if( src )
- memcpy(&i8051, src, sizeof(I8051));
+ if (mcs51.features & FEATURE_I8052_UART)
+ {
+ update_timer_t2(cycles);
+ }
}
-/* Get Internal RAM value */
-unsigned i8051_get_intram(int offset)
+//Set up to transmit data out of serial port
+//NOTE: Enable Serial Port Interrupt bit is NOT required to send/receive data!
+
+INLINE void serial_transmit(UINT8 data)
{
- UINT8 ram_ret = 0;
- RWM = 1;
- ram_ret = IRAM_R(offset);
- RWM = 0;
- return ram_ret;
+ int mode = (GET_SM0<<1) | GET_SM1;
+
+ //Flag that we're sending data
+ mcs51.uart.data_out = data;
+ //printf("serial_tansmit: %x %x\n", mode, data);
+ switch(mode) {
+ //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
+ case 0:
+ mcs51.uart.bits_to_send = 8+2;
+ break;
+ //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
+ case 1:
+ mcs51.uart.bits_to_send = 8+2;
+ break;
+ //9 bit uart
+ case 2:
+ case 3:
+ LOG(("Serial mode 2 & 3 not supported in mcs51!\n"));
+ break;
+ }
}
-/*NOTE: These are not used by the opcode functions, they are here only for MAME requirements*/
-unsigned i8051_get_reg(int regnum)
+INLINE void serial_receive(void)
{
- switch( regnum )
- {
- case REG_PREVIOUSPC: return PPC;
- case REG_PC:
- case I8051_PC: return PC;
- case REG_SP:
- case I8051_SP: return R_SP;
- case I8051_ACC: return R_ACC;
- case I8051_PSW: return R_PSW;
- case I8051_B: return R_B;
- case I8051_DPH: return R_DPH;
- case I8051_DPL: return R_DPL;
- case I8051_IE: return R_IE;
- //Not real registers
- case I8051_R0: return R_R(0);
- case I8051_R1: return R_R(1);
- case I8051_R2: return R_R(2);
- case I8051_R3: return R_R(3);
- case I8051_R4: return R_R(4);
- case I8051_R5: return R_R(5);
- case I8051_R6: return R_R(6);
- case I8051_R7: return R_R(7);
- case I8051_RB: return GET_RS;
- default:
- return 0;
+ int mode = (GET_SM0<<1) | GET_SM1;
+
+ if(GET_ES && GET_REN) {
+ switch(mode) {
+ //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
+ case 0:
+ mcs51.uart.delay_cycles = 8+2;
+ break;
+ //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
+ case 1:
+ mcs51.uart.delay_cycles = 8+2;
+ break;
+ //9 bit uart
+ case 2:
+ case 3:
+ LOG(("Serial mode 2 & 3 not supported in mcs51!\n"));
+ break;
+ }
}
}
-/*NOTE: These are not used by the opcode functions, they are here only for MAME requirements*/
-void i8051_set_reg (int regnum, unsigned val)
+//Check and update status of serial port
+INLINE void update_serial(int cycles)
{
- switch( regnum )
- {
- case REG_PC:
- case I8051_PC: PC = val & 0xffff; break;
- case REG_SP:
- case I8051_SP: SFR_W(SP,val); break; //Use SFR to handle error checking
- case I8051_ACC: SFR_W(ACC,val); break;
- case I8051_PSW: SFR_W(PSW,val); break;
- case I8051_B: SFR_W(B,val); break;
- case I8051_DPH: SFR_W(DPH,val); break;
- case I8051_DPL: SFR_W(DPL,val); break;
- case I8051_IE: SFR_W(IE,val); break;
- //Not real registers
- case I8051_R0: R_R(0) = val; break;
- case I8051_R1: R_R(1) = val; break;
- case I8051_R2: R_R(2) = val; break;
- case I8051_R3: R_R(3) = val; break;
- case I8051_R4: R_R(4) = val; break;
- case I8051_R5: R_R(5) = val; break;
- case I8051_R6: R_R(6) = val; break;
- case I8051_R7: R_R(7) = val; break;
- case I8051_RB: SET_RS( (val&3) ); break;
-
- default:
- return;
- }
+ while (--cycles>=0)
+ transmit_receive(0);
}
-void i8051_set_irq_line(int irqline, int state)
+/***************************************************************************
+ CALLBACKS - TODO: Remove
+***************************************************************************/
+
+
+void i8051_set_serial_tx_callback(void (*callback)(int data))
{
- switch( irqline )
- {
- //External Interrupt 0
- case I8051_INT0_LINE:
- //Line Asserted?
- if (state != CLEAR_LINE) {
- //Is the enable flag for this interrupt set?
- if(GET_EX0) {
- //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT0 active lo!
- if(GET_IT0){
- if(i8051.last_int0 == CLEAR_LINE)
- SET_IE0(1);
- }
- else
- SET_IE0(1); //Nope, just set it..
- }
- }
- else
- SET_IE0(0); //Clear Int occurred flag
- i8051.last_int0 = state;
+ //Hold in static variable since this function can get called before reset has run, which wipes i8051 memory clean
+ hold_serial_tx_callback = callback;
+}
- //Do the interrupt & handle - remove machine cycles used
- if(GET_IE0)
- i8051_icount-=check_interrupts();
- break;
+void i8051_set_serial_rx_callback(int (*callback)(void))
+{
+ //Hold in static variable since this function can get called before reset has run, which wipes i8051 memory clean
+ hold_serial_rx_callback = callback;
+}
- //External Interrupt 1
- case I8051_INT1_LINE:
+/***************************************************************************
+ OPCODES
+***************************************************************************/
- //Line Asserted?
- if (state != CLEAR_LINE) {
- if(GET_EX1) {
- //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT1 active lo!
- if(GET_IT1){
- if(i8051.last_int1 == CLEAR_LINE)
- SET_IE1(1);
- }
- else
- SET_IE1(1); //Nope, just set it..
- }
- }
- else
- SET_IE1(0); //Clear Int occurred flag
- i8051.last_int1 = state;
+#include "i8051ops.c"
- //Do the interrupt & handle - remove machine cycles used
- if(GET_IE1)
- i8051_icount-=check_interrupts();
- break;
- //Serial Port Receive
- case I8051_RX_LINE:
- //Is the enable flags for this interrupt set?
- if(GET_ES && GET_REN) {
- int data = 0;
- //Call our callball function to retrieve the data
- if(i8051.serial_rx_callback)
- data = i8051.serial_rx_callback();
- //Update the register directly, since SFR_W() will trigger a serial transmit instead!
- R_SBUF=data;
- //Flag the IRQ
- SET_RI(1);
- }
- break;
- //Note: we won't call check interrupts, we'll let the main loop catch it
+static void execute_op(UINT8 op)
+{
+ if (mcs51.recalc_parity)
+ {
+ set_parity();
+ mcs51.recalc_parity = 0;
+ }
+
+ switch( op )
+ {
+
+ case 0x00: nop(); break; //NOP
+ case 0x01: ajmp(op); break; //AJMP code addr
+ case 0x02: ljmp(); break; //LJMP code addr
+ case 0x03: rr_a(); break; //RR A
+ case 0x04: inc_a(); break; //INC A
+ case 0x05: RWM=1; inc_mem(); RWM=0; break; //INC data addr
+
+ case 0x06:
+ case 0x07: inc_ir(op&1); break; //INC @R0/@R1
+
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f: inc_r(op&7); break; //INC R0 to R7
+
+ case 0x10: RWM=1; jbc(); RWM=0; break; //JBC bit addr, code addr
+ case 0x11: acall(op); break; //ACALL code addr
+ case 0x12: lcall(); break; //LCALL code addr
+ case 0x13: rrc_a(); break; //RRC A
+ case 0x14: dec_a(); break; //DEC A
+ case 0x15: RWM=1; dec_mem(); RWM=0; break; //DEC data addr
+
+ case 0x16:
+ case 0x17: dec_ir(op&1); break; //DEC @R0/@R1
+
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: dec_r(op&7); break; //DEC R0 to R7
+
+ case 0x20: jb(); break; //JB bit addr, code addr
+ case 0x21: ajmp(op); break; //AJMP code addr
+ case 0x22: ret(); break; //RET
+ case 0x23: rl_a(); break; //RL A
+ case 0x24: add_a_byte(); break; //ADD A, #data
+ case 0x25: add_a_mem(); break; //ADD A, data addr
+
+ case 0x26:
+ case 0x27: add_a_ir(op&1); break; //ADD A, @R0/@R1
+
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f: add_a_r(op&7); break; //ADD A, R0 to R7
+
+ case 0x30: jnb(); break; //JNB bit addr, code addr
+ case 0x31: acall(op); break; //ACALL code addr
+ case 0x32: reti(); break; //RETI
+ case 0x33: rlc_a(); break; //RLC A
+ case 0x34: addc_a_byte(); break; //ADDC A, #data
+ case 0x35: addc_a_mem(); break; //ADDC A, data addr
+
+ case 0x36:
+ case 0x37: addc_a_ir(op&1); break; //ADDC A, @R0/@R1
+
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: addc_a_r(op&7); break; //ADDC A, R0 to R7
+
+ case 0x40: jc(); break; //JC code addr
+ case 0x41: ajmp(op); break; //AJMP code addr
+ case 0x42: RWM=1; orl_mem_a(); RWM=0; break; //ORL data addr, A
+ case 0x43: RWM=1; orl_mem_byte(); RWM=0; break; //ORL data addr, #data
+ case 0x44: orl_a_byte(); break;
+ case 0x45: orl_a_mem(); break; //ORL A, data addr
+
+ case 0x46:
+ case 0x47: orl_a_ir(op&1); break; //ORL A, @RO/@R1
+
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f: orl_a_r(op&7); break; //ORL A, RO to R7
+
+ case 0x50: jnc(); break; //JNC code addr
+ case 0x51: acall(op); break; //ACALL code addr
+ case 0x52: RWM=1; anl_mem_a(); RWM=0; break; //ANL data addr, A
+ case 0x53: RWM=1; anl_mem_byte(); RWM=0; break; //ANL data addr, #data
+ case 0x54: anl_a_byte(); break; //ANL A, #data
+ case 0x55: anl_a_mem(); break; //ANL A, data addr
+
+ case 0x56:
+ case 0x57: anl_a_ir(op&1); break; //ANL A, @RO/@R1
+
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x5f: anl_a_r(op&7); break; //ANL A, RO to R7
+
+ case 0x60: jz(); break; //JZ code addr
+ case 0x61: ajmp(op); break; //AJMP code addr
+ case 0x62: RWM=1; xrl_mem_a(); RWM=0; break; //XRL data addr, A
+ case 0x63: RWM=1; xrl_mem_byte(); RWM=0; break; //XRL data addr, #data
+ case 0x64: xrl_a_byte(); break; //XRL A, #data
+ case 0x65: xrl_a_mem(); break; //XRL A, data addr
+
+ case 0x66:
+ case 0x67: xrl_a_ir(op&1); break; //XRL A, @R0/@R1
+
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f: xrl_a_r(op&7); break; //XRL A, R0 to R7
+
+ case 0x70: jnz(); break; //JNZ code addr
+ case 0x71: acall(op); break; //ACALL code addr
+ case 0x72: orl_c_bitaddr(); break; //ORL C, bit addr
+ case 0x73: jmp_iadptr(); break; //JMP @A+DPTR
+ case 0x74: mov_a_byte(); break; //MOV A, #data
+ case 0x75: mov_mem_byte(); break; //MOV data addr, #data
+
+ case 0x76:
+ case 0x77: mov_ir_byte(op&1); break; //MOV @R0/@R1, #data
+
+ case 0x78:
+ case 0x79:
+ case 0x7a:
+ case 0x7b:
+ case 0x7c:
+ case 0x7d:
+ case 0x7e:
+ case 0x7f: mov_r_byte(op&7); break; //MOV R0 to R7, #data
+
+ case 0x80: sjmp(); break; //SJMP code addr
+ case 0x81: ajmp(op); break; //AJMP code addr
+ case 0x82: anl_c_bitaddr(); break; //ANL C, bit addr
+ case 0x83: movc_a_iapc(); break; //MOVC A, @A + PC
+ case 0x84: div_ab(); break; //DIV AB
+ case 0x85: mov_mem_mem(); break; //MOV data addr, data addr
+
+ case 0x86:
+ case 0x87: mov_mem_ir(op&1); break; //MOV data addr, @R0/@R1
+
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f: mov_mem_r(op&7); break; //MOV data addr,R0 to R7
+
+ case 0x90: mov_dptr_byte(); break; //MOV DPTR, #data
+ case 0x91: acall(op); break; //ACALL code addr
+ case 0x92: RWM = 1; mov_bitaddr_c(); RWM = 0; break; //MOV bit addr, C
+ case 0x93: movc_a_iadptr(); break; //MOVC A, @A + DPTR
+ case 0x94: subb_a_byte(); break; //SUBB A, #data
+ case 0x95: subb_a_mem(); break; //SUBB A, data addr
+
+ case 0x96:
+ case 0x97: subb_a_ir(op&1); break; //SUBB A, @R0/@R1
+
+ case 0x98:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0x9f: subb_a_r(op&7); break; //SUBB A, R0 to R7
+
+ case 0xa0: orl_c_nbitaddr(); break; //ORL C, /bit addr
+ case 0xa1: ajmp(op); break; //AJMP code addr
+ case 0xa2: mov_c_bitaddr(); break; //MOV C, bit addr
+ case 0xa3: inc_dptr(); break; //INC DPTR
+ case 0xa4: mul_ab(); break; //MUL AB
+ case 0xa5: illegal(op); break; //reserved
+
+ case 0xa6:
+ case 0xa7: mov_ir_mem(op&1); break; //MOV @R0/@R1, data addr
+
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf: mov_r_mem(op&7); break; //MOV R0 to R7, data addr
+
+ case 0xb0: anl_c_nbitaddr(); break; //ANL C,/bit addr
+ case 0xb1: acall(op); break; //ACALL code addr
+ case 0xb2: RWM=1; cpl_bitaddr(); RWM=0; break; //CPL bit addr
+ case 0xb3: cpl_c(); break; //CPL C
+ case 0xb4: cjne_a_byte(); break; //CJNE A, #data, code addr
+ case 0xb5: cjne_a_mem(); break; //CJNE A, data addr, code addr
+
+ case 0xb6:
+ case 0xb7: cjne_ir_byte(op&1); break; //CJNE @R0/@R1, #data, code addr
+
+ case 0xb8:
+ case 0xb9:
+ case 0xba:
+ case 0xbb:
+ case 0xbc:
+ case 0xbd:
+ case 0xbe:
+ case 0xbf: cjne_r_byte(op&7); break; //CJNE R0 to R7, #data, code addr
+
+ case 0xc0: push(); break; //PUSH data addr
+ case 0xc1: ajmp(op); break; //AJMP code addr
+ case 0xc2: RWM=1; clr_bitaddr(); RWM=0; break; //CLR bit addr
+ case 0xc3: clr_c(); break; //CLR C
+ case 0xc4: swap_a(); break; //SWAP A
+ case 0xc5: xch_a_mem(); break; //XCH A, data addr
+
+ case 0xc6:
+ case 0xc7: xch_a_ir(op&1); break; //XCH A, @RO/@R1
+
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf: xch_a_r(op&7); break; //XCH A, RO to R7
+
+ case 0xd0: pop(); break; //POP data addr
+ case 0xd1: acall(op); break; //ACALL code addr
+ case 0xd2: RWM=1; setb_bitaddr(); RWM=0; break; //SETB bit addr
+ case 0xd3: setb_c(); break; //SETB C
+ case 0xd4: da_a(); break; //DA A
+ case 0xd5: RWM=1; djnz_mem(); RWM=0; break; //DJNZ data addr, code addr
+
+ case 0xd6:
+ case 0xd7: xchd_a_ir(op&1); break; //XCHD A, @R0/@R1
+
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf: djnz_r(op&7); break; //DJNZ R0 to R7,code addr
+
+ case 0xe0: movx_a_idptr(); break; //MOVX A,@DPTR
+ case 0xe1: ajmp(op); break; //AJMP code addr
+
+ case 0xe2:
+ case 0xe3: movx_a_ir(op&1); break; //MOVX A, @R0/@R1
+
+ case 0xe4: clr_a(); break; //CLR A
+ case 0xe5: mov_a_mem(); break; //MOV A, data addr
+ case 0xe6:
+ case 0xe7: mov_a_ir(op&1); break; //MOV A,@RO/@R1
+
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef: mov_a_r(op&7); break; //MOV A,R0 to R7
+
+ case 0xf0: movx_idptr_a(); break; //MOVX @DPTR,A
+ case 0xf1: acall(op); break; //ACALL code addr
+
+ case 0xf2:
+ case 0xf3: movx_ir_a(op&1); break; //MOVX @R0/@R1,A
+
+ case 0xf4: cpl_a(); break; //CPL A
+ case 0xf5: mov_mem_a(); break; //MOV data addr, A
+
+ case 0xf6:
+ case 0xf7: mov_ir_a(op&1); break; //MOV @R0/@R1, A
+
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ case 0xff: mov_r_a(op&7); break; //MOV R0 to R7, A
+ default:
+ illegal(op);
}
}
+/***************************************************************************
+ OPCODE CYCLES
+***************************************************************************/
+
+/* # of oscilations each opcode requires*/
+static const UINT8 mcs51_cycles[] = {
+ 1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,1,2,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,4,1,2,2,2,2,2,2,2,2,2,2,
+ 2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,1,1,2,1,1,2,2,2,2,2,2,2,2,
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
/***********************************************************************************
Check for pending Interrupts and process - returns # of cycles used for the int
@@ -1472,79 +1406,70 @@ void i8051_set_irq_line(int irqline, int state)
e) RI+TI
f) TF2+EXF2
**********************************************************************************/
-INLINE UINT8 check_interrupts(void)
+static void check_irqs(void)
{
- //If All Inerrupts Disabled or no pending abort..
- if(!GET_EA) return 0;
+ UINT8 ints = IE & (GET_IE0 | (GET_TF0<<1) | (GET_IE1<<2) | (GET_TF1<<3)
+ | ((GET_RI|GET_TI)<<4));
+ UINT8 ip = IP;
+ UINT8 int_vec = 0;
+ UINT8 priority_request = 0;
+ int i;
- //Any Interrupts Pending?
- if(NO_PENDING_IRQ) return 0;
+ //If All Inerrupts Disabled or no pending abort..
+ if(!GET_EA) return;
- //Skip if current irq in progress is high priority!
- if(i8051.irq_priority) { /* LOG(("high priority irq in progress, skipping irq request\n")); */ return 0; }
+ if (mcs51.features & FEATURE_I8052_UART)
+ ints |= ((GET_TF2|GET_EXF2)<<5);
- //Check which interrupt(s) requests have occurred..
- //NOTE: The order of checking is based on the internal/default priority levels when levels are the same
+ if (!ints) return;
- //External Int 0
- if(GET_IE0) {
- //Set vector & priority level request
- i8051.int_vec = V_IE0;
- i8051.priority_request = GET_PX0;
- }
- //Timer 0 overflow
- if(!i8051.priority_request && GET_TF0 && (!i8051.int_vec || (i8051.int_vec && GET_PT0))) {
- //Set vector & priority level request
- i8051.int_vec = V_TF0;
- i8051.priority_request = GET_PT0;
- }
- //External Int 1
- if(!i8051.priority_request && GET_IE1 && (!i8051.int_vec || (i8051.int_vec && GET_PX1))) {
- //Set vector & priority level request
- i8051.int_vec = V_IE1;
- i8051.priority_request = GET_PX1;
- }
- //Timer 1 overflow
- if(!i8051.priority_request && GET_TF1 && (!i8051.int_vec || (i8051.int_vec && GET_PT1))) {
- //Set vector & priority level request
- i8051.int_vec = V_TF1;
- i8051.priority_request = GET_PT1;
- }
- //Serial Interrupt Transmit/Receive Interrupts (Note: ES Bit - Serial Interrupts must be enabled)
- if(!i8051.priority_request && GET_ES && (GET_TI || GET_RI) && (!i8051.int_vec || (i8051.int_vec && GET_PS))) {
- //Set vector & priority level request
- i8051.int_vec = V_RITI;
- i8051.priority_request = GET_PS;
+ if(mcs51.irq_priority)
+ {
+ LOG(("high priority irq in progress, skipping irq request\n"));
+ return;
}
-#if (HAS_I8052 || HAS_I8752)
- //Timer 2 overflow (Either Timer Overflow OR External Interrupt)
- if(!i8051.priority_request && GET_ET2 && (GET_TF2 || GET_EXF2) && (!i8051.int_vec || (i8051.int_vec && GET_PT2))) {
- //Set vector & priority level request
- i8051.int_vec = V_TF2;
- i8051.priority_request = GET_PT2;
+
+ for (i=0; i<mcs51.num_interrupts; i++)
+ {
+ if (ints & (1<<i))
+ {
+ int_vec = (i<<3) | 3;
+ priority_request = (ip & (1<<i));
+ if (priority_request)
+ break;
+ }
}
-#endif
//Skip the interrupt request if currently processing is lo priority, and the new request IS NOT HI PRIORITY!
- if(i8051.cur_irq < 0xff && !i8051.priority_request)
- { LOG(("low priority irq in progress already, skipping low irq request\n")); return 0; }
-
- /*** --- Perform the interrupt --- ***/
+ if(mcs51.cur_irq < 0xff && !priority_request)
+ {
+ LOG(("low priority irq in progress already, skipping low irq request\n"));
+ return;
+ }
- //Save current pc to stack, set pc to new interrupt vector
+ //Save current pc to stack, set pc to new interrupt vector
push_pc();
- PC = i8051.int_vec;
+ PC = int_vec;
+ change_pc(PC);
+
+ /* interrupts take 24 cycles */
+ mcs51.inst_cycles += 2;
//Set current Irq & Priority being serviced
- i8051.cur_irq = i8051.int_vec;
- i8051.irq_priority = i8051.priority_request;
+ mcs51.cur_irq = int_vec;
+ mcs51.irq_priority = priority_request;
//Clear any interrupt flags that should be cleared since we're servicing the irq!
- switch(i8051.cur_irq) {
+ switch(mcs51.cur_irq) {
case V_IE0:
//External Int Flag only cleared when configured as Edge Triggered..
- //if(GET_IT0) - for some reason having this, breaks alving dmd games
+ if(GET_IT0) /* for some reason having this, breaks alving dmd games */
SET_IE0(0);
+
+ /* indicate we took the external IRQ */
+ if (mcs51.irq_callback != NULL)
+ (*mcs51.irq_callback)(0);
+
break;
case V_TF0:
//Timer 0 - Always clear Flag
@@ -1552,8 +1477,12 @@ INLINE UINT8 check_interrupts(void)
break;
case V_IE1:
//External Int Flag only cleared when configured as Edge Triggered..
- //if(GET_IT1) - for some reason having this, breaks alving dmd games
+ if(GET_IT1) /* for some reason having this, breaks alving dmd games */
SET_IE1(0);
+ /* indicate we took the external IRQ */
+ if (mcs51.irq_callback != NULL)
+ (*mcs51.irq_callback)(1);
+
break;
case V_TF1:
//Timer 0 - Always clear Flag
@@ -1562,884 +1491,486 @@ INLINE UINT8 check_interrupts(void)
case V_RITI:
// no flags are cleared, TI and RI remain set until reset by software
break;
-#if (HAS_I8052 || HAS_I8752)
+ /* I8052 specific */
case V_TF2:
// no flags are cleared according to manual
break;
-#endif
}
-
- //Clear vars.. (these are part of the 8051 structure for speed, so we don't have to dynamically allocate space each time)
- i8051.int_vec = 0;
- i8051.priority_request = 0;
-
- //All interrupts use 2 machine cycles
- return 24;
-}
-
-
-void i8051_set_irq_callback(int (*callback)(int irqline))
-{
- i8051.irq_callback = callback;
-}
-
-void i8051_set_serial_tx_callback(void (*callback)(int data))
-{
- //Hold in static variable since this function can get called before reset has run, which wipes i8051 memory clean
- hold_serial_tx_callback = callback;
-}
-void i8051_set_serial_rx_callback(int (*callback)(void))
-{
- //Hold in static variable since this function can get called before reset has run, which wipes i8051 memory clean
- hold_serial_rx_callback = callback;
-}
-
-void i8051_set_eram_iaddr_callback(READ32_HANDLER((*callback)))
-{
- //Hold in static variable since this function can get called before reset has run, which wipes i8051 memory clean
- hold_eram_iaddr_callback = callback;
}
-
-void i8051_state_save(void *file)
+INLINE void burn_cycles(int cycles)
{
+ /* Update Timer (if any timers are running) */
+ update_timers(cycles);
+
+ /* Update Serial (only for mode 0) */
+ update_serial(cycles);
+
+ /* check_irqs */
+ check_irqs();
}
-void i8051_state_load(void *file)
+static void mcs51_set_irq_line(int irqline, int state)
{
-}
-
-/* HELPER FUNCTIONS */
-
-/*All writes to SFR are handled here*/
-static WRITE8_HANDLER(sfr_write)
-{
- data &= 0xff; //Ensure only 8 bits
- switch (offset)
+ /* From the manual:
+ *
+ * <cite>In operatiom all the interrupt tlags are latched into the
+ * interrupt control system during State 5 of every ma-
+ * chine cycle. The samples are polled during the follow-
+ * ing machine cycle.</cite>
+ *
+ * ==> Since we do not emulate substates, this assumes that the signal is present
+ * for at least one cycle (12 states)
+ *
+ */
+ int new_state = (mcs51.last_line_state & ~(1 << irqline)) | ((state != CLEAR_LINE) << irqline);
+ /* detect 0->1 transistions */
+ int tr_state = (~mcs51.last_line_state) & new_state;
+
+ switch( irqline )
{
- case P0:
- R_P0 = data;
- OUT(0,data);
- break;
-
- case SP:
- if(offset > 0xff)
- LOG(("i8051 #%d: attemping to write value to SP past 256 bytes at 0x%04x\n", cpu_getactivecpu(), PC));
- R_SP = data&0xff; //keep sp w/in 256 bytes
+ //External Interrupt 0
+ case I8051_INT0_LINE:
+ //Line Asserted?
+ if (state != CLEAR_LINE) {
+ //Is the enable flag for this interrupt set?
+ if (GET_EX0) {
+ //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT0 active lo!
+ if (GET_IT0) {
+ if (GET_BIT(tr_state, I8051_INT0_LINE))
+ SET_IE0(1);
+ }
+ else
+ SET_IE0(1); //Nope, just set it..
+ }
+ }
+ else
+ {
+ if (!GET_IT0) /* clear if level triggered */
+ SET_IE0(0);
+ }
+
break;
- case DPL: R_DPL = data; break;
- case DPH: R_DPH = data; break;
- case PCON: R_PCON= data; break;
- case TCON: R_TCON= data; break;
- case TMOD: R_TMOD= data; break;
- case TL0: R_TL0 = data; break;
- case TL1: R_TL1 = data; break;
- case TH0: R_TH0 = data; break;
- case TH1: R_TH1 = data; break;
-
- case P1:
- R_P1 = data;
- OUT(1,data);
- break;
+ //External Interrupt 1
+ case I8051_INT1_LINE:
- case SCON: {
- //Update register
- R_SCON = data;
+ //Line Asserted?
+ if (state != CLEAR_LINE) {
+ if(GET_EX1) {
+ //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT1 active lo!
+ if(GET_IT1){
+ if (GET_BIT(tr_state, I8051_INT1_LINE))
+ SET_IE1(1);
+ }
+ else
+ SET_IE1(1); //Nope, just set it..
+ }
+ }
+ else
+ {
+ if (!GET_IT1) /* clear if level triggered */
+ SET_IE1(0);
+ }
break;
- }
- case SBUF:
- //R_SBUF = data; //This register is used only for "Receiving data coming in!"
- serial_transmit(data); //Set up to transmit the data
+ case MCS51_T0_LINE:
+ if (GET_BIT(tr_state, MCS51_T0_LINE))
+ mcs51.t0_cnt++;
break;
-
- case P2:
- R_P2 = data;
- OUT(2,data);
+
+ case MCS51_T1_LINE:
+ if (GET_BIT(tr_state, MCS51_T1_LINE))
+ mcs51.t1_cnt++;
break;
- case IE: R_IE = data; break;
-
- case P3:
- R_P3 = data;
- OUT(3,data);
+ case MCS51_T2_LINE:
+ if (mcs51.features & FEATURE_I8052_UART)
+ {
+ if (GET_BIT(tr_state, MCS51_T2_LINE))
+ mcs51.t2_cnt++;
+ }
+ else
+ fatalerror("mcs51: Trying to set T2_LINE on a non I8052 type cpu.\n");
break;
- case IP: R_IP = data; break;
-
- //8052 Only registers
- #if (HAS_I8052 || HAS_I8752)
- case T2CON: R_T2CON = data; break;
- case RCAP2L: R_RCAP2L = data; break;
- case RCAP2H: R_RCAP2H = data; break;
- case TL2: R_TL2 = data; break;
- case TH2: R_TH2 = data; break;
- #endif
-
- case PSW:
- R_PSW = data;
- SET_PARITY;
+ case MCS51_T2EX_LINE:
+ if (mcs51.features & FEATURE_I8052_UART)
+ {
+ if (GET_TR2 && GET_EXEN2)
+ if (GET_BIT(tr_state, MCS51_T2EX_LINE))
+ {
+ SET_EXF2(1);
+ mcs51.t2ex_cnt++;
+ }
+ }
+ else
+ fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
break;
-
- case ACC:
- R_ACC = data;
- SET_PARITY;
+ //Serial Port Receive
+ case I8051_RX_LINE:
+ //Is the enable flags for this interrupt set?
+ if (state != CLEAR_LINE)
+ {
+ serial_receive();
+ }
break;
-
- case B: R_B = data; break;
-
- /* Illegal or non-implemented sfr */
- default:
- LOG(("i8051 #%d: attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", cpu_getactivecpu(), offset,PC,data));
- }
-}
-
-/*All reads to SFR are handled here*/
-static READ8_HANDLER(sfr_read)
-{
- switch (offset)
- {
- case P0:
- if(RWM)
- return R_P0; //Read directly from port latch
- else
- return IN(0); //Read from actual port
- case SP: return R_SP;
- case DPL: return R_DPL;
- case DPH: return R_DPH;
- case PCON: return R_PCON;
- case TCON: return R_TCON;
- case TMOD: return R_TMOD;
- case TL0: return R_TL0;
- case TL1: return R_TL1;
- case TH0: return R_TH0;
- case TH1: return R_TH1;
- case P1:
- if(RWM)
- return R_P1; //Read directly from port latch
- else
- return IN(1); //Read from actual port
- case SCON: return R_SCON;
- case SBUF: return R_SBUF;
- case P2:
- if(RWM)
- return R_P2; //Read directly from port latch
- else
- return IN(2); //Read from actual port
- case IE: return R_IE;
- case P3:
- if(RWM)
- return R_P3; //Read directly from port latch
- else
- return IN(3); //Read from actual port
- case IP: return R_IP;
- //8052 Only registers
- #if (HAS_I8052 || HAS_I8752)
- case T2CON: return R_T2CON;
- case RCAP2L: return R_RCAP2L;
- case RCAP2H: return R_RCAP2H;
- case TL2: return R_TL2;
- case TH2: return R_TH2;
- #endif
- case PSW: return R_PSW;
- case ACC: return R_ACC;
- case B: return R_B;
-
- /* Illegal or non-implemented sfr */
- default:
- LOG(("i8051 #%d: attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", cpu_getactivecpu(), offset,PC));
- }
- return 0xff;
-}
-
-/* Reads the contents of the Internal RAM memory */
-/* Anything above 0x7f is a sfr/register */
-static READ8_HANDLER(internal_ram_read)
-{
- if (offset < 0x80)
- return i8051.IntRam[offset];
- else {
- if (offset < 0x100)
- return SFR_R(offset);
- else
- LOG(("i8051 #%d: attemping to read from an invalid Internal Ram address: %x at 0x%04x\n", cpu_getactivecpu(), offset,PC));
}
- return 0xff;
+ mcs51.last_line_state = new_state;
}
-/* Writes the contents of the Internal RAM memory */
-/* Anything above 0x7f is a sfr/register */
-static WRITE8_HANDLER(internal_ram_write)
+/* Execute cycles - returns number of cycles actually run */
+static int mcs51_execute(int cycles)
{
- data &= 0xff; //Ensure it's only 8 bits
- if (offset < 0x80)
- i8051.IntRam[offset] = data;
- else {
- if (offset < 0x100)
- SFR_W(offset,data);
- else
- LOG(("i8051 #%d: attemping to write to invalid Internal Ram address: %x at 0x%04x\n", cpu_getactivecpu(), offset,PC));
- }
-}
+ UINT8 op;
+
+ mcs51_icount = cycles;
-/* Reads the contents of the Internal RAM memory (BUT CALLED FROM AN INDIRECT ADDRESSING MODE) */
-/* Different chip types handle differently, for speed, simply call the chip's handler */
-static READ8_HANDLER(internal_ram_iread)
-{
- return i8051.iram_iread(machine,offset);
-}
+ /* external interrupts may have been set since we last checked */
+ mcs51.inst_cycles = 0;
+ check_irqs();
+ mcs51_icount -= mcs51.inst_cycles;
+ burn_cycles(mcs51.inst_cycles);
-/* Writes the contents of the Internal RAM memory (BUT CALLED FROM AN INDIRECT ADDRESSING MODE) */
-/* Different chip types handle differently, for speed, simply call the chip's handler */
-static WRITE8_HANDLER(internal_ram_iwrite)
-{
- i8051.iram_iwrite(machine,offset,data);
-}
-
-/*Generate an external ram address for read/writing using indirect addressing mode */
-/*The lowest 8 bits of the address are passed in (from the R0/R1 register), however
- the hardware can be configured to set the rest of the address lines to any available output port pins, which
- means the only way we can implement this is to allow the driver to setup a callback to generate the
- address as defined by the specific hardware setup. We'll assume the address won't be bigger than 32 bits
-*/
-static READ32_HANDLER(external_ram_iaddr)
-{
- if(i8051.eram_iaddr_callback)
- return i8051.eram_iaddr_callback(machine,offset,mem_mask);
- else
- LOG(("i8051 #%d: external ram address requested (8 bit offset=%02x), but no callback available! at PC:%04x\n", cpu_getactivecpu(), offset, PC));
+ do
+ {
+ /* Read next opcode */
+ PPC = PC;
+ debugger_instruction_hook(Machine, PC);
+ op = cpu_readop(PC++);
- return offset;
-}
+ /* process opcode and count cycles */
+ mcs51.inst_cycles = mcs51_cycles[op];
+ execute_op(op);
-/*Push the current PC to the stack*/
-INLINE void push_pc()
-{
- UINT8 tmpSP = R_SP; //Grab and Increment Stack Pointer
- tmpSP++; // ""
- SFR_W(SP,tmpSP); // ""
- if (tmpSP == R_SP) //Ensure it was able to write to new stack location
- IRAM_IW(tmpSP, (PC & 0xff)); //Store low byte of PC to Internal Ram (Use IRAM_IW to store stack above 128 bytes)
- tmpSP = R_SP; //Increment Stack Pointer
- tmpSP++; // ""
- SFR_W(SP,tmpSP); // ""
- if (tmpSP == R_SP) //Ensure it was able to write to new stack location
- IRAM_IW(tmpSP, ( (PC & 0xff00) >> 8)); //Store hi byte of PC to next address in Internal Ram (Use IRAM_IW to store stack above 128 bytes)
-}
+ /* burn the cycles */
+ mcs51_icount -= mcs51.inst_cycles;
+ burn_cycles(mcs51.inst_cycles);
+
+ } while( mcs51_icount > 0 );
-/*Pop the current PC off the stack and into the pc*/
-INLINE void pop_pc()
-{
- UINT8 tmpSP = R_SP; //Grab Stack Pointer
- PC = (IRAM_IR(tmpSP) & 0xff) << 8; //Store hi byte to PC (must use IRAM_IR to access stack pointing above 128 bytes)
- tmpSP = R_SP-1; //Decrement Stack Pointer
- SFR_W(SP,tmpSP); // ""
- if (tmpSP == R_SP) //Ensure it was able to write to new stack location
- PC = PC | IRAM_IR(tmpSP); //Store lo byte to PC (must use IRAM_IR to access stack pointing above 128 bytes)
- SFR_W(SP,tmpSP-1); //Decrement Stack Pointer
+ return cycles - mcs51_icount;
}
-//Set the PSW Parity Flag
-INLINE void set_parity()
-{
- //This flag will be set when the accumulator contains an odd # of bits set..
- int i,
- p = 0;
- for (i=1; i<=128; i=i*2) { //Test for each of the 8 bits in the ACC!
- if ((R_ACC & i) != 0)
- p++; //Keep track of how many bits are set
- }
- //Update the PSW Pairty bit
- SET_P(p & 1);
-}
+/****************************************************************************
+ * MCS51/8051 Section
+ ****************************************************************************/
-static READ8_HANDLER(bit_address_r)
+static void mcs51_sfr_write(size_t offset, UINT8 data)
{
- int word;
- int mask;
- int bit_pos;
- int base; /* base of bit space or sfr */
- int distance; /* distance between bit addressable words */
- /* 1 for normal bits, 8 for sfr bit addresses */
-
- offset &= 0xff;
-
- //User defined bit addresses 0x20-0x2f (values are 0x0-0x7f)
- if (offset < 0x80) {
- base = 0x20;
- distance = 1;
- }
- //SFR bit addressable registers
- else {
- base = 0x80;
- distance = 8;
+ /* update register */
+ assert(offset >= 0x80 && offset <= 0xff);
+
+ /* TODO: Move to memory map */
+ switch (offset)
+ {
+ case ADDR_P0: OUT(MCS51_PORT_P0,data); break;
+ case ADDR_P1: OUT(MCS51_PORT_P1,data); break;
+ case ADDR_P2: OUT(MCS51_PORT_P2,data); break;
+ case ADDR_P3: OUT(MCS51_PORT_P3,data); break;
+ case ADDR_SBUF: serial_transmit(data); break;
+ case ADDR_PSW: SET_PARITY(); break;
+ case ADDR_ACC: SET_PARITY(); break;
+ /* R_SBUF = data; //This register is used only for "Receiving data coming in!" */
+
+ case ADDR_B:
+ case ADDR_IP:
+ case ADDR_SP:
+ case ADDR_DPL:
+ case ADDR_DPH:
+ case ADDR_PCON:
+ case ADDR_TCON:
+ case ADDR_TMOD:
+ case ADDR_IE:
+ case ADDR_TL0:
+ case ADDR_TL1:
+ case ADDR_TH0:
+ case ADDR_TH1:
+ case ADDR_SCON:
+ break;
+ default:
+ LOG(("mcs51 #%d: attemping to write to an invalid/non-implemented SFR address: %zx at 0x%04x, data=%x\n", cpu_getactivecpu(), offset,PC,data));
+ /* no write in this case according to manual */
+ return;
}
- word = ( (offset & 0x78) >> 3) * distance + base;
- bit_pos = offset & 0x7;
- mask = 0x1 << bit_pos;
- return((IRAM_R(word) & mask) >> bit_pos); //Do not use IRAM_IR
+ data_write_byte_8le((size_t)offset | 0x100, data);
}
-
-static WRITE8_HANDLER(bit_address_w)
+static UINT8 mcs51_sfr_read(size_t offset)
{
- int word;
- int mask;
- int bit_pos;
- int result;
- int base;
- int distance;
+ assert(offset >= 0x80 && offset <= 0xff);
- offset &= 0xff;
-
- //User defined bit addresses 0x20-0x2f (values are 0x0-0x7f)
- if (offset < 0x80) {
- base = 0x20;
- distance = 1;
- }
- //SFR bit addressable registers
- else {
- base = 0x80;
- distance = 8;
+ switch (offset)
+ {
+ /* Read/Write/Modify operations read the port latch ! */
+ /* Move to memory map */
+ case ADDR_P0: return RWM ? P0 : P0 & IN(MCS51_PORT_P0);
+ case ADDR_P1: return RWM ? P1 : P1 & IN(MCS51_PORT_P1);
+ case ADDR_P2: return RWM ? P2 : P2 & IN(MCS51_PORT_P2);
+ case ADDR_P3: return RWM ? P3 : P3 & IN(MCS51_PORT_P3);
+
+ case ADDR_PSW:
+ case ADDR_ACC:
+ case ADDR_B:
+ case ADDR_SP:
+ case ADDR_DPL:
+ case ADDR_DPH:
+ case ADDR_PCON:
+ case ADDR_TCON:
+ case ADDR_TMOD:
+ case ADDR_TL0:
+ case ADDR_TL1:
+ case ADDR_TH0:
+ case ADDR_TH1:
+ case ADDR_SCON:
+ case ADDR_SBUF:
+ case ADDR_IE:
+ case ADDR_IP:
+ return data_read_byte_8le((size_t) offset | 0x100);
+ /* Illegal or non-implemented sfr */
+ default:
+ LOG(("mcs51 #%d: attemping to read an invalid/non-implemented SFR address: %zx at 0x%04x\n", cpu_getactivecpu(), offset,PC));
+ /* according to the manual, the read may return random bits */
+ return 0xff;
}
- word = ((offset & 0x78) >> 3) * distance + base;
- bit_pos = offset & 0x7;
- data = (data & 0x1) << bit_pos;
- mask = ~(1 << bit_pos) & 0xff;
- result = IRAM_R(word) & mask; //Do not use IRAM_IR
- result = result | data;
- IRAM_W(word, result); //Do not use IRAM_IW
}
-/* The following two handlers are used by the MAME Debugger Memory Window...
- By keeping these functions separate from the internally used IRAM_W/IRAM_R functions,
- we can manipulate and display internal memory in the debugger memory window in a layout
- that is not necessarily how the real memory is.. this will be especially useful for
- the 8052 chip where both the SFR and the upper 128 bytes of ram are mapped to the same
- address, so we can handle that here by mapping the sfr to a different address */
-READ8_HANDLER(i8051_internal_r)
-{
- //Restrict internal ram to 256 Bytes max
- if(offset < 0x100)
- return IRAM_R(offset);
- else
- return 0;
-}
-WRITE8_HANDLER(i8051_internal_w)
+static void mcs51_init(int index, int clock, const void *config, int (*irqcallback)(int))
{
- //Restrict internal ram to 256 Bytes max
- if(offset < 0x100)
- IRAM_W(offset,data);
+ mcs51.irq_callback = irqcallback;
+
+ mcs51.features = FEATURE_NONE;
+ mcs51.ram_mask = 0x7F; /* 128 bytes of ram */
+ mcs51.num_interrupts = 5; /* 5 interrupts */
+ mcs51.sfr_read = mcs51_sfr_read;
+ mcs51.sfr_write = mcs51_sfr_write;
+
+ /* Save states */
+ state_save_register_item("mcs51", index, mcs51.ppc);
+ state_save_register_item("mcs51", index, mcs51.pc);
+ state_save_register_item("mcs51", index, mcs51.rwm );
+ state_save_register_item("mcs51", index, mcs51.cur_irq );
+ state_save_register_item("mcs51", index, mcs51.irq_priority );
+ state_save_register_item("mcs51", index, mcs51.last_line_state );
+ state_save_register_item("mcs51", index, mcs51.t0_cnt );
+ state_save_register_item("mcs51", index, mcs51.t1_cnt );
+ state_save_register_item("mcs51", index, mcs51.t2_cnt );
+ state_save_register_item("mcs51", index, mcs51.t2ex_cnt );
+ state_save_register_item("mcs51", index, mcs51.recalc_parity );
}
-INLINE void do_add_flags(UINT8 a, UINT8 data, UINT8 c)
+/* Reset registers to the initial values */
+static void mcs51_reset(void)
{
- UINT16 result = a+data+c;
- INT16 result1 = (INT8)a+(INT8)data+c;
- int cy, ac, ov;
-
- cy = (result & 0x100) >> 8;
- result = (a&0x0f)+(data&0x0f)+c;
- ac = (result & 0x10) >> 4;
- ov = (result1 < -128 || result1 > 127);
-
- SET_CY(cy);
- SET_AC(ac);
- SET_OV(ov);
+ update_ptrs();
+ //Set up serial call back handlers
+ mcs51.serial_tx_callback = hold_serial_tx_callback;
+ hold_serial_tx_callback = NULL;
+ mcs51.serial_rx_callback = hold_serial_rx_callback;
+ hold_serial_rx_callback = NULL;
+
+ mcs51.last_line_state = 0;
+ mcs51.t0_cnt = 0;
+ mcs51.t1_cnt = 0;
+ mcs51.t2_cnt = 0;
+ mcs51.t2ex_cnt = 0;
+
+ /* these are all defined reset states */
+ PC = 0;
+ SP = 0x7;
+ SET_PSW(0);
+ SET_ACC(0);
+ DPH = 0;
+ DPL = 0;
+ B = 0;
+ IP = 0;
+ IE = 0;
+ SCON = 0;
+ TCON = 0;
+ TMOD = 0;
+ TH1 = 0;
+ TH0 = 0;
+ TL1 = 0;
+ TL0 = 0;
+ /* set the port configurations to all 1's */
+ SET_P3(0xff);
+ SET_P2(0xff);
+ SET_P1(0xff);
+ SET_P0(0xff);
-// mame_printf_debug("add: result=%x, c=%x, ac=%x, ov=%x\n",a+data+c,cy,ac,ov);
+ /* Flag as NO IRQ in Progress */
+ CLEAR_CURRENT_IRQ();
}
-INLINE void do_sub_flags(UINT8 a, UINT8 data, UINT8 c)
+/* Shut down CPU core */
+static void mcs51_exit(void)
{
- UINT16 result = a-(data+c);
- INT16 result1 = (INT8)a-(INT8)(data+c);
- int cy, ac, ov;
- cy = (result & 0x100) >> 8;
- result = (a&0x0f)-((data&0x0f)+c);
- ac = (result & 0x10) >> 4;
- ov = (result1 < -128 || result1 > 127);
- SET_CY(cy);
- SET_AC(ac);
- SET_OV(ov);
-
-// mame_printf_debug("sub: a=%x, d=%x, c=%x, result=%x, cy=%x, ac=%x, ov=%x\n",a,data,c,a-data-c,cy,ac,ov);
+ /* nothing to do */
}
-INLINE void update_timer(int cyc)
-{
- //This code sucks, needs to be rewritten SJE
-
- //Todo: Probably better to store the current mode of the timer on a write, so we don't waste time reading it.
-
- //Note: Counting modes increment on 1 machine cycle (12 oscilator periods) - except Timer 2 in certain modes
-
- /* Update Timer 0 */
- if(GET_TR0) {
- //Determine Mode
- int mode = (GET_M0_1<<1) | GET_M0_0;
- UINT32 count = 0;
- switch(mode) {
- case 0: /* 13 Bit Timer Mode */
- count = ((R_TH0<<5) | ( R_TL0 & 0x1F ) );
- /* Update the timer */
- /* Gate Bit Set? Timer only incremented if Int0 is set! */
- if(GET_GATE0 && GET_IE0)
- count += (cyc/12);
- /* Counter Mode? Only increment on 1-0 transition of the Port 3's T0 Line */
- if(GET_CT0)
- {
- /* Not supported */
- }
- /* Neither, regular timer mode */
- if(!GET_GATE0 && !GET_CT0)
- count += (cyc/12);
-
- /* Check for overflow */
- if ( count & 0xffffe000 )
- {
- SET_TF0(1);
- }
- /* Update new values of the counter */
- R_TH0 = (count>>5) & 0xff;
- R_TL0 = count & 0x1f;
- break;
- case 1: /* 16 Bit Timer Mode */
- count = ((R_TH0<<8) | R_TL0);
- /* Update the timer */
- /* Gate Bit Set? Timer only incremented if Int0 is set! */
- if(GET_GATE0 && GET_IE0)
- count += (cyc/12);
- /* Counter Mode? Only increment on 1-0 transition of the Port 3's T0 Line */
- if(GET_CT0)
- {
- /* Not supported */
- }
- /* Neither, regular timer mode */
- if(!GET_GATE0 && !GET_CT0)
- count += (cyc/12);
-
- /* Check for overflow */
- if ( count & 0xffff0000 )
- {
- SET_TF0(1);
- }
- /* Update new values of the counter */
- R_TH0 = (count>>8) & 0xff;
- R_TL0 = count & 0xff;
- break;
- case 2: /* 8 Bit Autoreload */
- count = R_TL0;
- count += (cyc/12);
- /* Check for overflow */
- if ( count & 0xffffff00 )
- {
- SET_TF0(1);
- /* Reload timer */
- count += R_TH0;
- }
- /* Update new values of the counter */
- R_TL0 = count & 0xff;
- break;
- case 3: /* Split Timer */
- /* Split Timer 1 */
- count = R_TL0;
- count += (cyc/12);
- /* Check for overflow */
- if ( count & 0xffffff00 )
- {
- SET_TF0(1);
- }
- /* Update new values of the counter */
- R_TL0 = count & 0xff;
-
- /* Split Timer 2 */
- count = R_TH0;
- count += (cyc/12);
- /* Check for overflow */
- if ( count & 0xffffff00 )
- {
- SET_TF1(1);
- }
- /* Update new values of the counter */
- R_TH0 = count & 0xff;
- break;
- }
- }
-
- /* Update Timer 1 */
- if(GET_TR1) {
- /* Determine Mode */
- int mode = (GET_M1_1<<1) | GET_M1_0;
- UINT32 count = 0;
- switch(mode) {
- case 0: /* 13 Bit Timer Mode */
- count = ((R_TH1<<5) | ( R_TL1 & 0x1F ) );
- /* Update the timer */
- /* Gate Bit Set? Timer only incremented if Int0 is set! */
- if(GET_GATE1 && GET_IE1)
- count += (cyc/12);
- /* Counter Mode? Only increment on 1-0 transition of the Port 3's T1 Line */
- if(GET_CT1)
- {
- /* Not supported */
- }
- /* Neither, regular timer mode */
- if(!GET_GATE1 && !GET_CT1)
- count += (cyc/12);
-
- /* Check for overflow */
- if ( count & 0xffffe000 )
- {
- SET_TF1(1);
- }
- /* Update new values of the counter */
- R_TH1 = (count>>5) & 0xff;
- R_TL1 = count & 0x1f;
- break;
- case 1: /* 16 Bit Timer Mode */
- count = ((R_TH1<<8) | R_TL1);
- /* Update the timer */
- /* Gate Bit Set? Timer only incremented if Int1 is set! */
- if(GET_GATE1 && GET_IE1)
- count += (cyc/12);
- /* Counter Mode? Only increment on 1-0 transition of the Port 3's T1 Line */
- if(GET_CT1)
- {
- /* Not supported */
- }
- /* Neither, regular timer mode */
- if(!GET_GATE1 && !GET_CT1)
- count += (cyc/12);
-
- /* Check for overflow */
- if ( count & 0xffff0000 )
- {
- //TODO: Timer 1 can be set as Serial Baud Rate in the 8051 only... process bits here..
- SET_TF1(1);
- }
- /* Update new values of the counter */
- R_TH1 = (count>>8) & 0xff;
- R_TL1 = count & 0xff;
- break;
- case 2: /* 8 Bit Autoreload */
- count = R_TL1;
- count += (cyc/12);
- /* Check for overflow */
- if ( count & 0xffffff00 )
- {
- SET_TF1(1);
- /* Reload timer */
- count += R_TH1;
- }
- /* Update new values of the counter */
- R_TL1 = count & 0xff;
- break;
- }
- }
-
-#if (HAS_I8052 || HAS_I8752)
- /* Update Timer 2 */
- if(GET_TR2) {
- UINT32 count = ((R_TH2<<8) | R_TL2);
+/****************************************************************************
+ * 8052 Section
+ ****************************************************************************/
- /* Are we in counter mode? */
- if(GET_CT2)
- {
- /* Not supported */
- }
- /* Are we in timer mode? */
- else
- {
- /* 16 Bit Timer Mode */
- /* Timer 2 Used as Baud Generator? (For now, only *same* send/receive rates supported) */
- if(GET_TCLK || GET_RCLK)
- count += cyc/2; /* Timer increments every cycles/2 in baud mode */
- else
- /* REGULAR TIMER - */
- count += cyc/12; /* Timer increments every cycles/12 in normal mode */
+static void i8052_sfr_write(size_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+ /* 8052 family specific */
+ case ADDR_T2CON:
+ case ADDR_RCAP2L:
+ case ADDR_RCAP2H:
+ case ADDR_TL2:
+ case ADDR_TH2:
+ data_write_byte_8le((size_t) offset | 0x100, data);
+ break;
- /* Check for overflow */
- if ( count & 0xffff0000 )
- {
- /* Set Interrupt flag *unless* used as baud generator */
- if(!GET_TCLK && !GET_RCLK)
- {
- SET_TF2(1);
- }
- else
- {
- /* Update bits sent if sending & bits left to send! */
- if(uart.sending && uart.bits_to_send && uart.timerbaud)
- uart.bits_to_send-=1;
- }
- /* Auto reload? */
- if(!GET_CP)
- count += ((R_RCAP2H<<8) | R_RCAP2L);
- }
- /* Update new values of the counter */
- R_TH2 = (count>>8) & 0xff;
- R_TL2 = count & 0xff;
- }
+ default:
+ mcs51_sfr_write(offset, data);
}
-#endif
}
-//Set up to transmit data out of serial port
-//NOTE: Enable Serial Port Interrupt bit is NOT required to send/receive data!
-INLINE void serial_transmit(UINT8 data)
+static UINT8 i8052_sfr_read(size_t offset)
{
- int mode = (GET_SM0<<1) | GET_SM1;
-
- //Flag that we're sending data
- uart.sending = 1;
- uart.data_out = data;
- switch(mode) {
- //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
- case 0:
- uart.timerbaud = 0;
- uart.bitcycles = 0;
- uart.bits_to_send = 8+2;
- break;
- //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
- case 1:
- uart.timerbaud = 1;
- uart.bits_to_send = 8+2;
- break;
- //9 bit uart
- case 2:
- case 3:
- LOG(("Serial mode 2 & 3 not supported in i8051!\n"));
- break;
+ switch (offset)
+ {
+ /* 8052 family specific */
+ case ADDR_T2CON:
+ case ADDR_RCAP2L:
+ case ADDR_RCAP2H:
+ case ADDR_TL2:
+ case ADDR_TH2:
+ return data_read_byte_8le((size_t) offset | 0x100);
+ default:
+ return mcs51_sfr_read(offset);
}
}
-//Check and update status of serial port
-INLINE void update_serial(int cyc)
+static void i8052_init (int index, int clock, const void *config, int (*irqcallback)(int))
{
- //Any bits left to send?
- if(uart.bits_to_send) {
- //Timer Generated baud?
- if(uart.timerbaud) {
- //Let Timer overflow handle removing bits
- }
- else {
- //Oscillator Based baud rate = Osc/12 baud rate, however it also means 1 bit = 12 cycles.
- uart.bitcycles+=cyc;
- if(uart.bitcycles > 11) {
- int bits_sent = uart.bitcycles / 12;
- int diff = uart.bitcycles % 12;
- //don't allow more bits sent than ready to send
- if(bits_sent > uart.bits_to_send) {
- bits_sent = uart.bits_to_send;
- diff = 0;
- }
- uart.bits_to_send-=bits_sent;
- uart.bitcycles = diff;
- }
- }
- }
- //If no bits left to send - flag the interrupt & call the callback
- if(!uart.bits_to_send) {
- //Clear sending flag
- uart.sending = 0;
- uart.bitcycles = 0;
- //Call the callback function
- if(i8051.serial_tx_callback)
- i8051.serial_tx_callback(uart.data_out);
- //Set Interrupt Flag
- SET_TI(1);
- //Note: we'll let the main loop catch the interrupt
- }
+ mcs51_init(index, clock, config, irqcallback);
+
+ mcs51.ram_mask = 0xFF; /* 256 bytes of ram */
+ mcs51.num_interrupts = 6; /* 6 interrupts */
+
+ mcs51.features |= FEATURE_I8052_UART;
+ mcs51.sfr_read = i8052_sfr_read;
+ mcs51.sfr_write = i8052_sfr_write;
}
-/****************************************************************************
- * 8752 Section
- ****************************************************************************/
-#if (HAS_I8052 || HAS_I8752)
-void i8752_init (int index, int clock, const void *config, int (*irqcallback)(int)) { i8051_init(index, clock, config, irqcallback); }
-void i8752_reset (void)
+static void i8052_reset(void)
{
- memset(&i8051, 0, sizeof(I8051));
- memset(&uart, 0, sizeof(I8051_UART));
- i8051.subtype = 8752;
+ mcs51_reset();
+
+ //8052 Only registers
+ T2CON = 0;
+ RCAP2L = 0;
+ RCAP2H = 0;
+ TL2 = 0;
+ TH2 = 0;
+}
- //Set up 8052 specific internal read/write (indirect) handlers..
- i8051.iram_iread = i8052_internal_ram_iread;
- i8051.iram_iwrite = i8052_internal_ram_iwrite;
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
- //Set up serial call back handlers
- i8051.serial_tx_callback = hold_serial_tx_callback;
- hold_serial_tx_callback = NULL;
- i8051.serial_rx_callback = hold_serial_rx_callback;
- hold_serial_rx_callback = NULL;
+/* FIXME: the memory maps should probably support rom banking for EA */
+static ADDRESS_MAP_START(program_12bit, ADDRESS_SPACE_PROGRAM, 8)
+ AM_RANGE(0x00, 0x0fff) AM_ROM
+ADDRESS_MAP_END
- //Setup External ram callback handlers
- i8051.eram_iaddr_callback = hold_eram_iaddr_callback;
- hold_eram_iaddr_callback = NULL;
+static ADDRESS_MAP_START(program_13bit, ADDRESS_SPACE_PROGRAM, 8)
+ AM_RANGE(0x00, 0x1fff) AM_ROM
+ADDRESS_MAP_END
- //Clear Ram (w/0xff)
- memset(&i8051.IntRam,0xff,sizeof(i8051.IntRam));
+static ADDRESS_MAP_START(data_7bit, ADDRESS_SPACE_DATA, 8)
+ AM_RANGE(0x0000, 0x007f) AM_RAM
+ AM_RANGE(0x0100, 0x01ff) AM_RAM /* SFR */
+ADDRESS_MAP_END
- /* these are all defined reset states */
- PC = 0;
- SFR_W(SP, 0x7);
- SFR_W(PSW, 0);
- SFR_W(DPH, 0);
- SFR_W(DPL, 0);
- SFR_W(ACC, 0);
- SFR_W(B, 0);
- SFR_W(IP, 0);
- SFR_W(IE, 0);
- SFR_W(SCON, 0);
- SFR_W(TCON, 0);
- SFR_W(TMOD, 0);
- SFR_W(TH1, 0);
- SFR_W(TH0, 0);
- SFR_W(TL1, 0);
- SFR_W(TL0, 0);
- //8052 Only registers
- SFR_W(T2CON, 0);
- SFR_W(RCAP2L, 0);
- SFR_W(RCAP2H, 0);
- SFR_W(TL2, 0);
- SFR_W(TH2, 0);
-
- /* set the port configurations to all 1's */
- SFR_W(P3, 0xff);
- SFR_W(P2, 0xff);
- SFR_W(P1, 0xff);
- SFR_W(P0, 0xff);
+static ADDRESS_MAP_START(data_8bit, ADDRESS_SPACE_DATA, 8)
+ AM_RANGE(0x0000, 0x00ff) AM_RAM
+ AM_RANGE(0x0100, 0x01ff) AM_RAM /* SFR */
+ADDRESS_MAP_END
- /* Flag as NO IRQ in Progress */
- CLEAR_CURRENT_IRQ
-}
-void i8752_exit (void) { i8051_exit(); }
-int i8752_execute(int cycles) { return i8051_execute(cycles); }
-void i8752_get_context (void *dst) { i8051_get_context(dst); }
-void i8752_set_context (void *src) { i8051_set_context(src); }
-unsigned i8752_get_reg (int regnum) { return i8051_get_reg(regnum); }
-void i8752_set_reg (int regnum, unsigned val) { i8051_set_reg(regnum,val); }
-void i8752_set_irq_line(int irqline, int state) { i8051_set_irq_line(irqline,state); }
-void i8752_set_irq_callback(int (*callback)(int irqline)) { i8051_set_irq_callback(callback); }
-void i8752_set_serial_tx_callback(void (*callback)(int data)) { i8051_set_serial_tx_callback(callback); }
-void i8752_set_serial_rx_callback(int (*callback)(void)) { i8051_set_serial_rx_callback(callback); }
-void i8752_state_save(void *file) { i8051_state_save(file); }
-void i8752_state_load(void *file) { i8051_state_load(file); }
-
-/* The following two handlers are used by the MAME Debugger Memory Window...
- By keeping these functions separate from the internally used IRAM_W/IRAM_R functions,
- we can manipulate and display internal memory in the debugger memory window in a layout
- that is not necessarily how the real memory is.. this will be especially useful for
- the 8052 chip where both the SFR and the upper 128 bytes of ram are mapped to the same
- address, so we can handle that here by mapping the sfr to a different address */
-
-READ8_HANDLER(i8752_internal_r)
-{
- //USE INDIRECT READ TO ALLOW FULL 256 Bytes of RAM to show in the debugger
- if(offset < 0x100)
- return IRAM_IR(offset);
- else
- //MAP SFR registers starting at 256 (they are only 128 bytes in size)
- if(offset < 0x100+0x80)
- return SFR_R(offset-0x80);
- else
- //Everything else is 0 (and invalid)
- return 0;
-}
-WRITE8_HANDLER(i8752_internal_w)
-{
- //USE INDIRECT WRITE TO ALLOW FULL 256 Bytes of RAM to show in the debugger
- if(offset < 0x100)
- IRAM_IW(offset,data);
- else
- if(offset < 0x100+0x80)
- SFR_W(offset-0x80,data);
-}
+/***************************************************************************
+ GENERAL CONTEXT ACCESS
+***************************************************************************/
-/* Reads the contents of the Internal RAM memory INDIRECTLY */
-/* Anything above 0x7f is NOT sfr/register, but rather UPPER 128K OF INTERNAL RAM */
-static READ8_HANDLER(i8052_internal_ram_iread)
+static void mcs51_get_context(void *dst)
{
- if (offset < 0x100)
- return i8051.IntRam[offset];
- else
- LOG(("i8051 #%d: attemping to read from an invalid Internal Ram address: %x at 0x%04x\n", cpu_getactivecpu(), offset,PC));
- return 0xff;
+ if( dst )
+ memcpy(dst, &mcs51, sizeof(mcs51_regs));
}
-/* Writes the contents of the Internal RAM memory INDIRECTLY */
-/* Anything above 0x7f is NOT sfr/register, but rather UPPER 128K OF INTERNAL RAM */
-static WRITE8_HANDLER(i8052_internal_ram_iwrite)
+static void mcs51_set_context(void *src)
{
- data &= 0xff; //Ensure it's only 8 bits
- if (offset < 0x100)
- i8051.IntRam[offset] = data;
- else
- LOG(("i8051 #%d: attemping to write to an invalid Internal Ram address: %x at 0x%04x\n", cpu_getactivecpu(), offset,PC));
+ if( src )
+ memcpy(&mcs51, src, sizeof(mcs51_regs));
+ change_pc(PC);
+ update_ptrs();
}
-#endif //(HAS_8752)
-
/**************************************************************************
* Generic set_info
**************************************************************************/
-static void i8051_set_info(UINT32 state, cpuinfo *info)
+static void mcs51_set_info(UINT32 state, cpuinfo *info)
{
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
case CPUINFO_INT_PC: PC = info->i; break;
- case CPUINFO_INT_SP: i8051.sp = info->i; break;
-
- case CPUINFO_INT_INPUT_STATE + I8051_INT0_LINE: i8051_set_irq_line(I8051_INT0_LINE, info->i); break;
- case CPUINFO_INT_INPUT_STATE + I8051_INT1_LINE: i8051_set_irq_line(I8051_INT1_LINE, info->i); break;
- case CPUINFO_INT_INPUT_STATE + I8051_T0_LINE: i8051_set_irq_line(I8051_T0_LINE, info->i); break;
- case CPUINFO_INT_INPUT_STATE + I8051_T1_LINE: i8051_set_irq_line(I8051_T1_LINE, info->i); break;
- case CPUINFO_INT_INPUT_STATE + I8051_RX_LINE: i8051_set_irq_line(I8051_RX_LINE, info->i); break;
-
- case CPUINFO_INT_REGISTER + I8051_PC: PC = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_SP: R_SP = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_PSW: i8051.psw = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_ACC: i8051.acc = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_B: i8051.b = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_DPH: i8051.dph = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_DPL: i8051.dpl = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_IE: i8051.ie = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R0: i8051.IntRam[0+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R1: i8051.IntRam[1+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R2: i8051.IntRam[2+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R3: i8051.IntRam[3+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R4: i8051.IntRam[4+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R5: i8051.IntRam[5+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R6: i8051.IntRam[6+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_R7: i8051.IntRam[7+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
- case CPUINFO_INT_REGISTER + I8051_RB: i8051.IntRam[8+(8*((i8051.psw & 0x18)>>3))] = info->i; break;
+ case CPUINFO_INT_SP: SP = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + I8051_INT0_LINE: mcs51_set_irq_line(I8051_INT0_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + I8051_INT1_LINE: mcs51_set_irq_line(I8051_INT1_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MCS51_T0_LINE: mcs51_set_irq_line(MCS51_T0_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MCS51_T1_LINE: mcs51_set_irq_line(MCS51_T1_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + I8051_RX_LINE: mcs51_set_irq_line(I8051_RX_LINE, info->i); break;
+
+ case CPUINFO_INT_REGISTER + I8051_PC: PC = info->i; break;
+ case CPUINFO_INT_REGISTER + I8051_SP: SP = info->i; break;
+ case CPUINFO_INT_REGISTER + I8051_PSW: SET_PSW(info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_ACC: SET_ACC(info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_B: B = info->i; break;
+ case CPUINFO_INT_REGISTER + I8051_DPH: DPH = info->i; break;
+ case CPUINFO_INT_REGISTER + I8051_DPL: DPL = info->i; break;
+ case CPUINFO_INT_REGISTER + I8051_IE: IE = info->i; break;
+ case CPUINFO_INT_REGISTER + I8051_R0: SET_REG(0, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R1: SET_REG(1, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R2: SET_REG(2, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R3: SET_REG(3, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R4: SET_REG(4, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R5: SET_REG(5, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R6: SET_REG(6, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_R7: SET_REG(7, info->i); break;
+ case CPUINFO_INT_REGISTER + I8051_RB: SET_RS(info->i); break;
}
}
+
+
/**************************************************************************
* Generic get_info
**************************************************************************/
-void i8051_get_info(UINT32 state, cpuinfo *info)
+static void mcs51_get_info(UINT32 state, cpuinfo *info)
{
- I8051 *r = &i8051;
+ mcs51_regs *r = &mcs51;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i8051); break;
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mcs51); break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
- case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 12; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
@@ -2450,51 +1981,50 @@ void i8051_get_info(UINT32 state, cpuinfo *info)
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 9; /* due to sfr mapping */ break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 17; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
case CPUINFO_INT_PC: info->i = PC; break;
- case CPUINFO_INT_SP: info->i = R_SP; break;
+ case CPUINFO_INT_SP: info->i = SP; break;
case CPUINFO_INT_REGISTER + I8051_PC: info->i = PC; break;
- case CPUINFO_INT_REGISTER + I8051_SP: info->i = R_SP; break;
- case CPUINFO_INT_REGISTER + I8051_PSW: info->i = i8051.psw; break;
- case CPUINFO_INT_REGISTER + I8051_ACC: info->i = i8051.acc; break;
- case CPUINFO_INT_REGISTER + I8051_B: info->i = i8051.b; break;
- case CPUINFO_INT_REGISTER + I8051_DPH: info->i = i8051.dph; break;
- case CPUINFO_INT_REGISTER + I8051_DPL: info->i = i8051.dpl; break;
- case CPUINFO_INT_REGISTER + I8051_IE: info->i = i8051.ie; break;
- case CPUINFO_INT_REGISTER + I8051_R0: info->i = i8051.IntRam[0+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R1: info->i = i8051.IntRam[1+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R2: info->i = i8051.IntRam[2+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R3: info->i = i8051.IntRam[3+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R4: info->i = i8051.IntRam[4+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R5: info->i = i8051.IntRam[5+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R6: info->i = i8051.IntRam[6+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_R7: info->i = i8051.IntRam[7+(8*((i8051.psw & 0x18)>>3))]; break;
- case CPUINFO_INT_REGISTER + I8051_RB: info->i = i8051.IntRam[8+(8*((i8051.psw & 0x18)>>3))]; break;
+ case CPUINFO_INT_REGISTER + I8051_SP: info->i = SP; break;
+ case CPUINFO_INT_REGISTER + I8051_PSW: info->i = PSW; break;
+ case CPUINFO_INT_REGISTER + I8051_ACC: info->i = ACC; break;
+ case CPUINFO_INT_REGISTER + I8051_B: info->i = B; break;
+ case CPUINFO_INT_REGISTER + I8051_DPH: info->i = DPH; break;
+ case CPUINFO_INT_REGISTER + I8051_DPL: info->i = DPL; break;
+ case CPUINFO_INT_REGISTER + I8051_IE: info->i = IE; break;
+ case CPUINFO_INT_REGISTER + I8051_R0: info->i = R_REG(0); break;
+ case CPUINFO_INT_REGISTER + I8051_R1: info->i = R_REG(1); break;
+ case CPUINFO_INT_REGISTER + I8051_R2: info->i = R_REG(2); break;
+ case CPUINFO_INT_REGISTER + I8051_R3: info->i = R_REG(3); break;
+ case CPUINFO_INT_REGISTER + I8051_R4: info->i = R_REG(4); break;
+ case CPUINFO_INT_REGISTER + I8051_R5: info->i = R_REG(5); break;
+ case CPUINFO_INT_REGISTER + I8051_R6: info->i = R_REG(6); break;
+ case CPUINFO_INT_REGISTER + I8051_R7: info->i = R_REG(7); break;
+ case CPUINFO_INT_REGISTER + I8051_RB: info->i = R_REG(8); break;
/* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = i8051_set_info; break;
- case CPUINFO_PTR_GET_CONTEXT: info->getcontext = i8051_get_context; break;
- case CPUINFO_PTR_SET_CONTEXT: info->setcontext = i8051_set_context; break;
- case CPUINFO_PTR_INIT: info->init = i8051_init; break;
- case CPUINFO_PTR_RESET: info->reset = i8051_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = i8051_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = i8051_execute; break;
+ case CPUINFO_PTR_SET_INFO: info->setinfo = mcs51_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = mcs51_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = mcs51_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = mcs51_init; break;
+ case CPUINFO_PTR_RESET: info->reset = mcs51_reset; break;
+ case CPUINFO_PTR_EXIT: info->exit = mcs51_exit; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = mcs51_execute; break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = i8051_dasm; break;
- case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i8051_icount; break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &mcs51_icount; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map8 = NULL; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map8 = NULL; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map8 = NULL; break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "I8051"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "MCS-51"); break;
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
@@ -2503,82 +2033,91 @@ void i8051_get_info(UINT32 state, cpuinfo *info)
case CPUINFO_STR_FLAGS:
sprintf(info->s, "%c%c%c%c%c%c%c%c",
- r->psw & 0x80 ? 'C':'.',
- r->psw & 0x40 ? 'A':'.',
- r->psw & 0x20 ? 'F':'.',
- r->psw & 0x10 ? '0':'.',
- r->psw & 0x08 ? '1':'.',
- r->psw & 0x04 ? 'V':'.',
- r->psw & 0x02 ? '?':'.',
- r->psw & 0x01 ? 'P':'.');
+ PSW & 0x80 ? 'C':'.',
+ PSW & 0x40 ? 'A':'.',
+ PSW & 0x20 ? 'F':'.',
+ PSW & 0x10 ? '0':'.',
+ PSW & 0x08 ? '1':'.',
+ PSW & 0x04 ? 'V':'.',
+ PSW & 0x02 ? '?':'.',
+ PSW & 0x01 ? 'P':'.');
break;
case CPUINFO_STR_REGISTER + I8051_PC: sprintf(info->s, "PC:%04X", r->pc); break;
- case CPUINFO_STR_REGISTER + I8051_SP: sprintf(info->s, "SP:%02X", r->sp); break;
- case CPUINFO_STR_REGISTER + I8051_PSW: sprintf(info->s, "PSW:%02X", r->psw); break;
- case CPUINFO_STR_REGISTER + I8051_ACC: sprintf(info->s, "A:%02X", r->acc); break;
- case CPUINFO_STR_REGISTER + I8051_B: sprintf(info->s, "B:%02X", r->b); break;
- case CPUINFO_STR_REGISTER + I8051_DPH: sprintf(info->s, "DPH:%02X", r->dph); break;
- case CPUINFO_STR_REGISTER + I8051_DPL: sprintf(info->s, "DPL:%02X", r->dpl); break;
- case CPUINFO_STR_REGISTER + I8051_IE: sprintf(info->s, "IE:%02X", r->ie); break;
- case CPUINFO_STR_REGISTER + I8051_R0: sprintf(info->s, "R0:%02X", r->IntRam[0+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R1: sprintf(info->s, "R1:%02X", r->IntRam[1+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R2: sprintf(info->s, "R2:%02X", r->IntRam[2+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R3: sprintf(info->s, "R3:%02X", r->IntRam[3+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R4: sprintf(info->s, "R4:%02X", r->IntRam[4+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R5: sprintf(info->s, "R5:%02X", r->IntRam[5+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R6: sprintf(info->s, "R6:%02X", r->IntRam[6+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_R7: sprintf(info->s, "R7:%02X", r->IntRam[7+(8*((r->psw & 0x18)>>3))]); break;
- case CPUINFO_STR_REGISTER + I8051_RB: sprintf(info->s, "RB:%02X", ((r->psw & 0x18)>>3)); break;
+ case CPUINFO_STR_REGISTER + I8051_SP: sprintf(info->s, "SP:%02X", SP); break;
+ case CPUINFO_STR_REGISTER + I8051_PSW: sprintf(info->s, "PSW:%02X", PSW); break;
+ case CPUINFO_STR_REGISTER + I8051_ACC: sprintf(info->s, "A:%02X", ACC); break;
+ case CPUINFO_STR_REGISTER + I8051_B: sprintf(info->s, "B:%02X", B); break;
+ case CPUINFO_STR_REGISTER + I8051_DPH: sprintf(info->s, "DPH:%02X", DPH); break;
+ case CPUINFO_STR_REGISTER + I8051_DPL: sprintf(info->s, "DPL:%02X", DPL); break;
+ case CPUINFO_STR_REGISTER + I8051_IE: sprintf(info->s, "IE:%02X", IE); break;
+ case CPUINFO_STR_REGISTER + I8051_R0: sprintf(info->s, "R0:%02X", R_REG(0)); break;
+ case CPUINFO_STR_REGISTER + I8051_R1: sprintf(info->s, "R1:%02X", R_REG(1)); break;
+ case CPUINFO_STR_REGISTER + I8051_R2: sprintf(info->s, "R2:%02X", R_REG(2)); break;
+ case CPUINFO_STR_REGISTER + I8051_R3: sprintf(info->s, "R3:%02X", R_REG(3)); break;
+ case CPUINFO_STR_REGISTER + I8051_R4: sprintf(info->s, "R4:%02X", R_REG(4)); break;
+ case CPUINFO_STR_REGISTER + I8051_R5: sprintf(info->s, "R5:%02X", R_REG(5)); break;
+ case CPUINFO_STR_REGISTER + I8051_R6: sprintf(info->s, "R6:%02X", R_REG(6)); break;
+ case CPUINFO_STR_REGISTER + I8051_R7: sprintf(info->s, "R7:%02X", R_REG(7)); break;
+ case CPUINFO_STR_REGISTER + I8051_RB: sprintf(info->s, "RB:%02X", ((PSW & 0x18)>>3)); break;
+ }
+}
+
+void i8051_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map8 = address_map_program_12bit; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map8 = address_map_data_7bit; break;
+
+ case CPUINFO_STR_NAME: strcpy(info->s, "I8051"); break;
+ default: mcs51_get_info(state, info); break;
}
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
}
-#if (HAS_I8052)
void i8052_get_info(UINT32 state, cpuinfo *info)
{
switch (state)
{
- case CPUINFO_PTR_GET_CONTEXT: info->getcontext = i8752_get_context; break;
- case CPUINFO_PTR_SET_CONTEXT: info->setcontext = i8752_set_context; break;
- case CPUINFO_PTR_INIT: info->init = i8752_init; break;
- case CPUINFO_PTR_RESET: info->reset = i8752_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = i8752_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = i8752_execute; break;
+ case CPUINFO_PTR_INIT: info->init = i8052_init; break;
+ case CPUINFO_PTR_RESET: info->reset = i8052_reset; break;
+
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map8 = address_map_program_13bit; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map8 = address_map_data_8bit; break;
case CPUINFO_STR_NAME: strcpy(info->s, "I8052"); break;
- default: i8051_get_info(state, info); break;
+ default: mcs51_get_info(state, info); break;
}
}
-#endif
-#if (HAS_I8751)
void i8751_get_info(UINT32 state, cpuinfo *info)
{
switch (state)
{
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map8 = address_map_program_12bit; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map8 = address_map_data_7bit; break;
+
case CPUINFO_STR_NAME: strcpy(info->s, "I8751"); break;
- default: i8051_get_info(state, info); break;
+ default: mcs51_get_info(state, info); break;
}
}
-#endif
-#if (HAS_I8752)
void i8752_get_info(UINT32 state, cpuinfo *info)
{
switch (state)
{
- case CPUINFO_PTR_GET_CONTEXT: info->getcontext = i8752_get_context; break;
- case CPUINFO_PTR_SET_CONTEXT: info->setcontext = i8752_set_context; break;
- case CPUINFO_PTR_INIT: info->init = i8752_init; break;
- case CPUINFO_PTR_RESET: info->reset = i8752_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = i8752_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = i8752_execute; break;
+ case CPUINFO_PTR_INIT: info->init = i8052_init; break;
+ case CPUINFO_PTR_RESET: info->reset = i8052_reset; break;
+
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map8 = address_map_program_13bit; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map8 = address_map_data_8bit; break;
case CPUINFO_STR_NAME: strcpy(info->s, "I8752"); break;
- default: i8051_get_info(state, info); break;
+ default: mcs51_get_info(state, info); break;
}
}
-#endif
+
diff --git a/src/emu/cpu/i8051/i8051.h b/src/emu/cpu/i8051/i8051.h
index d1f1563779c..9beafefffac 100644
--- a/src/emu/cpu/i8051/i8051.h
+++ b/src/emu/cpu/i8051/i8051.h
@@ -43,108 +43,48 @@ enum
I8051_R0, I8051_R1, I8051_R2, I8051_R3, I8051_R4, I8051_R5, I8051_R6, I8051_R7, I8051_RB
};
-#define I8051_INT0_LINE 0 /* External Interrupt 0 */
-#define I8051_INT1_LINE 1 /* External Interrupt 1 */
-#define I8051_T0_LINE 2 /* Timer 0 External Input */
-#define I8051_T1_LINE 3 /* Timer 1 External Input */
-#define I8051_RX_LINE 4 /* Serial Port Receive Line */
-
-/* definition of the special function registers. Note that the values are */
-/* the same as the internal memory address in the 8051 */
-#define P0 0x80
-#define SP 0x81
-#define DPL 0x82
-#define DPH 0x83
-#define PCON 0x87
-#define TCON 0x88
-#define TMOD 0x89
-#define TL0 0x8a
-#define TL1 0x8b
-#define TH0 0x8c
-#define TH1 0x8d
-#define P1 0x90
-#define SCON 0x98
-#define SBUF 0x99
-#define P2 0xa0
-#define IE 0xa8
-#define P3 0xb0
-#define IP 0xb8
-//8052 Only registers
-#if (HAS_I8052 || HAS_I8752)
- #define T2CON 0xc8
- #define RCAP2L 0xca
- #define RCAP2H 0xcb
- #define TL2 0xcc
- #define TH2 0xcd
-#endif
-#define PSW 0xd0
-#define ACC 0xe0
-#define B 0xf0
+enum
+{
+ I8051_INT0_LINE = 0, /* P3.2: External Interrupt 0 */
+ I8051_INT1_LINE, /* P3.3: External Interrupt 1 */
+ I8051_RX_LINE, /* P3.0: Serial Port Receive Line */
+ MCS51_T0_LINE, /* P3,4: Timer 0 External Input */
+ MCS51_T1_LINE, /* P3.5: Timer 1 External Input */
+ MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
+ MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */
+};
-/* commonly used bit address for the 8051 */
-#define C 0xd7
-#define P 0xd0
-#define AC 0xd6
-#define OV 0xd2
-#define TF0 0x8d
-#define TF1 0x8f
-#define IE0 0x89
-#define IE1 0x8b
-#define TI 0x99
-#define RI 0x98
+/* special I/O space ports */
-#define TI_FLAG 1
-#define RI_FLAG 2
+enum
+{
+ MCS51_PORT_P0 = 0x10000,
+ MCS51_PORT_P1 = 0x10001,
+ MCS51_PORT_P2 = 0x10002,
+ MCS51_PORT_P3 = 0x10003,
+ MCS51_PORT_TX = 0x10004, /* P3.1 */
+};
-extern void i8051_init (int index, int clock, const void *config, int (*irqcallback)(int)); /* Initialize save states */
-extern void i8051_reset (void); /* Reset registers to the initial values */
-extern void i8051_exit (void); /* Shut down CPU core */
-extern int i8051_execute(int cycles); /* Execute cycles - returns number of cycles actually run */
-extern void i8051_get_context (void *dst); /* Get registers, return context size */
-extern void i8051_set_context (void *src); /* Set registers */
-extern unsigned i8051_get_intram (int offset);
-extern unsigned i8051_get_reg (int regnum);
-extern void i8051_set_reg (int regnum, unsigned val);
-extern void i8051_set_irq_line(int irqline, int state);
-extern void i8051_set_irq_callback(int (*callback)(int irqline));
-extern void i8051_state_save(void *file);
-extern void i8051_state_load(void *file);
-WRITE8_HANDLER( i8051_internal_w );
-READ8_HANDLER( i8051_internal_r );
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
extern void i8051_set_serial_tx_callback(void (*callback)(int data));
extern void i8051_set_serial_rx_callback(int (*callback)(void));
-extern void i8051_set_eram_iaddr_callback(READ32_HANDLER((*callback)));
-extern offs_t i8051_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
+/* variants 4k internal rom and 128 byte internal memory */
+void i8051_get_info(UINT32 state, cpuinfo *info);
+void i8751_get_info(UINT32 state, cpuinfo *info);
+
+/* variants 8k internal rom and 256 byte internal memory and more registers */
+void i8052_get_info(UINT32 state, cpuinfo *info);
+void i8752_get_info(UINT32 state, cpuinfo *info);
/****************************************************************************
- * 8752 Section
+ * Disassembler
****************************************************************************/
-#if (HAS_I8752)
-extern void i8752_init (int index, int clock, const void *config, int (*irqcallback)(int)); /* Initialize save states */
-extern void i8752_reset (void); /* Reset registers to the initial values */
-extern void i8752_exit (void); /* Shut down CPU core */
-extern int i8752_execute(int cycles); /* Execute cycles - returns number of cycles actually run */
-extern void i8752_get_context (void *dst); /* Get registers, return context size */
-extern void i8752_set_context (void *src); /* Set registers */
-extern unsigned i8752_get_reg (int regnum);
-extern void i8752_set_reg (int regnum, unsigned val);
-extern void i8752_set_irq_line(int irqline, int state);
-extern void i8752_set_irq_callback(int (*callback)(int irqline));
-extern void i8752_state_save(void *file);
-extern void i8752_state_load(void *file);
-extern void i8752_set_serial_tx_callback(void (*callback)(int data));
-extern void i8752_set_serial_rx_callback(int (*callback)(void));
-WRITE8_HANDLER( i8752_internal_w );
-READ8_HANDLER( i8752_internal_r );
-#endif //(HAS_8752)
-
-void i8051_get_info(UINT32 state, cpuinfo *info);
-void i8052_get_info(UINT32 state, cpuinfo *info);
-void i8751_get_info(UINT32 state, cpuinfo *info);
-void i8752_get_info(UINT32 state, cpuinfo *info);
+offs_t i8051_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
#endif /* __I8051_H__ */
diff --git a/src/emu/cpu/i8051/i8051ops.c b/src/emu/cpu/i8051/i8051ops.c
index 250fec3096c..240b77c749a 100644
--- a/src/emu/cpu/i8051/i8051ops.c
+++ b/src/emu/cpu/i8051/i8051ops.c
@@ -1,26 +1,26 @@
/*******************************************************************************************
NOTE: All registers are accessed directly, instead of using the SFR_R() function for speed
- Direct register access is availabe from the R_(register name) macros.. ex: R_ACC for the ACC
+ Direct register access is availabe from the R_(register name) macros.. ex: ACC for the ACC
with the exception of the PC
********************************************************************************************/
//ACALL code addr /* 1: aaa1 0001 */
-INLINE void acall(void)
+INLINE void acall(UINT8 op)
{
- UINT8 op = ROP(PC-1); //Grab the opcode for ACALL
UINT8 addr = ROP_ARG(PC++); //Grab code address byte
- PUSH_PC //Save PC to the stack
+ PUSH_PC(); //Save PC to the stack
//Thanks Gerrit for help with this! :)
PC = (PC & 0xf800) | ((op & 0xe0) << 3) | addr;
+ change_pc(PC);
}
//ADD A, #data /* 1: 0010 0100 */
INLINE void add_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- UINT8 result = R_ACC + data; //Add data to accumulator
- DO_ADD_FLAGS(R_ACC,data,0) //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADD A, data addr /* 1: 0010 0101 */
@@ -28,36 +28,36 @@ INLINE void add_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- UINT8 result = R_ACC + data; //Add data to accumulator
- DO_ADD_FLAGS(R_ACC,data,0); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADD A, @R0/@R1 /* 1: 0010 011i */
INLINE void add_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data from memory pointed to by R0 or R1
- UINT8 result = R_ACC + data; //Add data to accumulator
- DO_ADD_FLAGS(R_ACC,data,0); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADD A, R0 to R7 /* 1: 0010 1rrr */
INLINE void add_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0 - R7
- UINT8 result = R_ACC + data; //Add data to accumulator
- DO_ADD_FLAGS(R_ACC,data,0); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADDC A, #data /* 1: 0011 0100 */
INLINE void addc_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- UINT8 result = R_ACC + data + GET_CY; //Add data + carry flag to accumulator
- DO_ADD_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADDC A, data addr /* 1: 0011 0101 */
@@ -65,36 +65,36 @@ INLINE void addc_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- UINT8 result = R_ACC + data + GET_CY; //Add data + carry flag to accumulator
- DO_ADD_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADDC A, @R0/@R1 /* 1: 0011 011i */
INLINE void addc_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data from memory pointed to by R0 or R1
- UINT8 result = R_ACC + data + GET_CY; //Add data + carry flag to accumulator
- DO_ADD_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//ADDC A, R0 to R7 /* 1: 0011 1rrr */
INLINE void addc_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0 - R7
- UINT8 result = R_ACC + data + GET_CY; //Add data + carry flag to accumulator
- DO_ADD_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//AJMP code addr /* 1: aaa0 0001 */
-INLINE void ajmp(void)
+INLINE void ajmp(UINT8 op)
{
- UINT8 op = ROP(PC-1); //Grab the opcode for AJMP
UINT8 addr = ROP_ARG(PC++); //Grab code address byte
//Thanks Gerrit for help with this! :)
PC = (PC & 0xf800) | ((op & 0xe0) << 3) | addr;
+ change_pc(PC);
}
//ANL data addr, A /* 1: 0101 0010 */
@@ -102,7 +102,7 @@ INLINE void anl_mem_a(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- IRAM_W(addr,data & R_ACC); //Set data address value to it's value Logical AND with ACC
+ IRAM_W(addr,data & ACC); //Set data address value to it's value Logical AND with ACC
}
//ANL data addr, #data /* 1: 0101 0011 */
@@ -118,7 +118,7 @@ INLINE void anl_mem_byte(void)
INLINE void anl_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- SFR_W(ACC,R_ACC & data); //Set ACC to value of ACC Logical AND with Data
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
}
//ANL A, data addr /* 1: 0101 0101 */
@@ -126,21 +126,21 @@ INLINE void anl_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- SFR_W(ACC,R_ACC & data); //Set ACC to value of ACC Logical AND with Data
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
}
//ANL A, @RO/@R1 /* 1: 0101 011i */
INLINE void anl_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data from address R0 or R1 points to
- SFR_W(ACC,R_ACC & data); //Set ACC to value of ACC Logical AND with Data
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
}
//ANL A, RO to R7 /* 1: 0101 1rrr */
INLINE void anl_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0 - R7
- SFR_W(ACC,R_ACC & data); //Set ACC to value of ACC Logical AND with Data
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
}
//ANL C, bit addr /* 1: 1000 0010 */
@@ -168,11 +168,14 @@ INLINE void cjne_a_byte(void)
UINT8 data = ROP_ARG(PC++); //Grab data
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
- if(R_ACC != data) //Jump if values are not equal
- PC = PC + rel_addr;
+ if(ACC != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ change_pc(PC);
+ }
//Set carry flag to 1 if 1st compare value is < 2nd compare value
- SET_CY( (R_ACC < data) );
+ SET_CY( (ACC < data) );
}
//CJNE A, data addr, code addr /* 1: 1011 0101 */
@@ -182,11 +185,14 @@ INLINE void cjne_a_mem(void)
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
UINT8 data = IRAM_R(addr); //Pull value from data address
- if(R_ACC != data) //Jump if values are not equal
+ if(ACC != data) //Jump if values are not equal
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
//Set carry flag to 1 if 1st compare value is < 2nd compare value
- SET_CY( (R_ACC < data) );
+ SET_CY( (ACC < data) );
}
//CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */
@@ -194,10 +200,13 @@ INLINE void cjne_ir_byte(int r)
{
UINT8 data = ROP_ARG(PC++); //Grab data
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
- UINT8 srcdata = IRAM_IR(R_R(r)); //Grab value pointed to by R0 or R1
+ UINT8 srcdata = IRAM_IR(R_REG(r)); //Grab value pointed to by R0 or R1
if(srcdata != data) //Jump if values are not equal
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
//Set carry flag to 1 if 1st compare value is < 2nd compare value
SET_CY( (srcdata < data) );
@@ -208,10 +217,13 @@ INLINE void cjne_r_byte(int r)
{
UINT8 data = ROP_ARG(PC++); //Grab data
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
- UINT8 srcdata = R_R(r); //Grab value of R0 - R7
+ UINT8 srcdata = R_REG(r); //Grab value of R0 - R7
if(srcdata != data) //Jump if values are not equal
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
//Set carry flag to 1 if 1st compare value is < 2nd compare value
SET_CY( (srcdata < data) );
@@ -233,7 +245,7 @@ INLINE void clr_c(void)
//CLR A /* 1: 1110 0100 */
INLINE void clr_a(void)
{
- SFR_W(ACC,0); //Clear Accumulator
+ SET_ACC(0); //Clear Accumulator
}
//CPL bit addr /* 1: 1011 0010 */
@@ -254,8 +266,8 @@ INLINE void cpl_c(void)
//CPL A /* 1: 1111 0100 */
INLINE void cpl_a(void)
{
- UINT8 data = ((~R_ACC)&0xff);
- SFR_W(ACC,data); //Complement Accumulator
+ UINT8 data = ((~ACC)&0xff);
+ SET_ACC(data); //Complement Accumulator
}
//DA A /* 1: 1101 0100 */
@@ -269,12 +281,12 @@ INLINE void da_a(void)
If the carry is set, OR the four high bits 4-7 exceed nine, six is added to the value of these bits.
The carry flag will be set if the result is > 0x99, but not cleared otherwise */
- UINT16 new_acc = R_ACC & 0xff;
+ UINT16 new_acc = ACC & 0xff;
if(GET_AC || (new_acc & 0x0f) > 0x09)
new_acc += 0x06;
if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff))
new_acc += 0x60;
- SFR_W(ACC,new_acc&0xff);
+ SET_ACC(new_acc&0xff);
if(new_acc & ~0xff)
SET_CY(1);
}
@@ -282,7 +294,7 @@ INLINE void da_a(void)
//DEC A /* 1: 0001 0100 */
INLINE void dec_a(void)
{
- SFR_W(ACC,R_ACC-1);
+ SET_ACC(ACC-1);
}
//DEC data addr /* 1: 0001 0101 */
@@ -296,32 +308,32 @@ INLINE void dec_mem(void)
//DEC @R0/@R1 /* 1: 0001 011i */
INLINE void dec_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r));
- IRAM_W(R_R(r),data-1);
+ UINT8 data = IRAM_IR(R_REG(r));
+ IRAM_W(R_REG(r),data-1);
}
//DEC R0 to R7 /* 1: 0001 1rrr */
INLINE void dec_r(int r)
{
- R_R(r) = R_R(r) - 1;
+ SET_REG(r, R_REG(r) - 1);
}
//DIV AB /* 1: 1000 0100 */
INLINE void div_ab(void)
{
- if( R_B == 0 ) {
+ if( B == 0 ) {
//Overflow flag is set!
SET_OV(1);
//Really the values are undefined according to the manual, but we'll just leave them as is..
- //SFR_W(ACC,0xff);
+ //SET_ACC(0xff);
//SFR_W(B,0xff);
}
else {
- int a = (int)R_ACC/R_B;
- int b = (int)R_ACC%R_B;
+ int a = (int)ACC / B;
+ int b = (int)ACC % B;
//A gets quotient byte, B gets remainder byte
- SFR_W(ACC,a);
- SFR_W(B, b);
+ SET_ACC(a);
+ B = b;
//Overflow flag is cleared
SET_OV(0);
}
@@ -336,22 +348,28 @@ INLINE void djnz_mem(void)
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
IRAM_W(addr,IRAM_R(addr) - 1); //Decrement value contained at data address
if(IRAM_R(addr) != 0) //Branch if contents of data address is not 0
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
}
//DJNZ R0 to R7,code addr /* 1: 1101 1rrr */
INLINE void djnz_r(int r)
{
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
- R_R(r) = R_R(r) - 1; //Decrement value
- if(R_R(r) != 0) //Branch if contents of R0 - R7 is not 0
+ SET_REG(r ,R_REG(r) - 1); //Decrement value
+ if(R_REG(r) != 0) //Branch if contents of R0 - R7 is not 0
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
}
//INC A /* 1: 0000 0100 */
INLINE void inc_a(void)
{
- SFR_W(ACC,R_ACC+1);
+ SET_ACC(ACC+1);
}
//INC data addr /* 1: 0000 0101 */
@@ -365,22 +383,22 @@ INLINE void inc_mem(void)
//INC @R0/@R1 /* 1: 0000 011i */
INLINE void inc_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r));
- IRAM_W(R_R(r),data+1);
+ UINT8 data = IRAM_IR(R_REG(r));
+ IRAM_W(R_REG(r),data+1);
}
//INC R0 to R7 /* 1: 0000 1rrr */
INLINE void inc_r(int r)
{
- UINT8 data = R_R(r);
- R_R(r) = data + 1;
+ UINT8 data = R_REG(r);
+ SET_REG(r, data + 1);
}
//INC DPTR /* 1: 1010 0011 */
INLINE void inc_dptr(void)
{
- UINT16 dptr = (R_DPTR)+1;
- DPTR_W(dptr);
+ UINT16 dptr = (DPTR)+1;
+ SET_DPTR(dptr);
}
//JB bit addr, code addr /* 1: 0010 0000 */
@@ -389,7 +407,10 @@ INLINE void jb(void)
UINT8 addr = ROP_ARG(PC++); //Grab bit address
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
if(BIT_R(addr)) //If bit set at specified bit address, jump
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
}
//JBC bit addr, code addr /* 1: 0001 0000 */
@@ -400,6 +421,7 @@ INLINE void jbc(void)
if(BIT_R(addr)) { //If bit set at specified bit address, jump
PC = PC + rel_addr;
BIT_W(addr,0); //Clear Bit also
+ change_pc(PC);
}
}
@@ -408,13 +430,17 @@ INLINE void jc(void)
{
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
if(GET_CY) //Jump if Carry Flag Set
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
}
//JMP @A+DPTR /* 1: 0111 0011 */
INLINE void jmp_iadptr(void)
{
- PC = R_ACC+R_DPTR;
+ PC = ACC + DPTR;
+ change_pc(PC);
}
//JNB bit addr, code addr /* 1: 0011 0000 */
@@ -423,7 +449,10 @@ INLINE void jnb(void)
UINT8 addr = ROP_ARG(PC++); //Grab bit address
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
if(!BIT_R(addr)) //If bit NOT set at specified bit address, jump
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
}
//JNC code addr /* 1: 0101 0000 */
@@ -431,23 +460,32 @@ INLINE void jnc(void)
{
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
if(!GET_CY) //Jump if Carry Flag not set
+ {
PC = PC + rel_addr;
+ change_pc(PC);
+ }
}
//JNZ code addr /* 1: 0111 0000 */
INLINE void jnz(void)
{
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
- if(R_ACC != 0) //Branch if ACC is not 0
+ if(ACC != 0) //Branch if ACC is not 0
+ {
PC = PC+rel_addr;
+ change_pc(PC);
+ }
}
//JZ code addr /* 1: 0110 0000 */
INLINE void jz(void)
{
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
- if(R_ACC == 0) //Branch if ACC is 0
+ if(ACC == 0) //Branch if ACC is 0
+ {
PC = PC+rel_addr;
+ change_pc(PC);
+ }
}
//LCALL code addr /* 1: 0001 0010 */
@@ -456,8 +494,9 @@ INLINE void lcall(void)
UINT8 addr_hi, addr_lo;
addr_hi = ROP_ARG(PC++);
addr_lo = ROP_ARG(PC++);
- PUSH_PC
+ PUSH_PC();
PC = (UINT16)((addr_hi<<8) | addr_lo);
+ change_pc(PC);
}
//LJMP code addr /* 1: 0000 0010 */
@@ -467,32 +506,33 @@ INLINE void ljmp(void)
addr_hi = ROP_ARG(PC++);
addr_lo = ROP_ARG(PC++);
PC = (UINT16)((addr_hi<<8) | addr_lo);
+ change_pc(PC);
}
//MOV A, #data /* 1: 0111 0100 */
INLINE void mov_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- SFR_W(ACC,data); //Store data to ACC
+ SET_ACC(data); //Store data to ACC
}
//MOV A, data addr /* 1: 1110 0101 */
INLINE void mov_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- SFR_W(ACC,IRAM_R(addr)); //Store contents of data address to ACC
+ SET_ACC(IRAM_R(addr)); //Store contents of data address to ACC
}
//MOV A,@RO/@R1 /* 1: 1110 011i */
INLINE void mov_a_ir(int r)
{
- SFR_W(ACC,IRAM_IR(R_R(r))); //Store contents of address pointed by R0 or R1 to ACC
+ SET_ACC(IRAM_IR(R_REG(r))); //Store contents of address pointed by R0 or R1 to ACC
}
//MOV A,R0 to R7 /* 1: 1110 1rrr */
INLINE void mov_a_r(int r)
{
- SFR_W(ACC,R_R(r)); //Store contents of R0 - R7 to ACC
+ SET_ACC(R_REG(r)); //Store contents of R0 - R7 to ACC
}
//MOV data addr, #data /* 1: 0111 0101 */
@@ -517,28 +557,28 @@ INLINE void mov_mem_mem(void)
INLINE void mov_ir_byte(int r)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- IRAM_IW(R_R(r),data); //Store data to address pointed by R0 or R1
+ IRAM_IW(R_REG(r),data); //Store data to address pointed by R0 or R1
}
//MOV R0 to R7, #data /* 1: 0111 1rrr */
INLINE void mov_r_byte(int r)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- R_R(r) = data; //Store to R0 - R7
+ SET_REG(r, data); //Store to R0 - R7
}
//MOV data addr, @R0/@R1 /* 1: 1000 011i */
INLINE void mov_mem_ir(int r)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- IRAM_W(addr,IRAM_IR(R_R(r))); //Store contents pointed to by R0 or R1 to data address
+ IRAM_W(addr,IRAM_IR(R_REG(r))); //Store contents pointed to by R0 or R1 to data address
}
//MOV data addr,R0 to R7 /* 1: 1000 1rrr */
INLINE void mov_mem_r(int r)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- IRAM_W(addr,R_R(r)); //Store contents of R0 - R7 to data address
+ IRAM_W(addr,R_REG(r)); //Store contents of R0 - R7 to data address
}
//MOV DPTR, #data16 /* 1: 1001 0000 */
@@ -547,7 +587,7 @@ INLINE void mov_dptr_byte(void)
UINT8 data_hi, data_lo;
data_hi = ROP_ARG(PC++); //Grab hi byte
data_lo = ROP_ARG(PC++); //Grab lo byte
- DPTR_W((UINT16)((data_hi<<8)|data_lo)); //Store to DPTR
+ SET_DPTR((UINT16)((data_hi<<8)|data_lo)); //Store to DPTR
}
//MOV bit addr, C /* 1: 1001 0010 */
@@ -561,41 +601,41 @@ INLINE void mov_bitaddr_c(void)
INLINE void mov_ir_mem(int r)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- IRAM_IW(R_R(r),IRAM_R(addr)); //Store data from data address to address pointed to by R0 or R1
+ IRAM_IW(R_REG(r),IRAM_R(addr)); //Store data from data address to address pointed to by R0 or R1
}
//MOV R0 to R7, data addr /* 1: 1010 1rrr */
INLINE void mov_r_mem(int r)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- R_R(r) = IRAM_R(addr); //Store to R0 - R7
+ SET_REG(r, IRAM_R(addr)); //Store to R0 - R7
}
//MOV data addr, A /* 1: 1111 0101 */
INLINE void mov_mem_a(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- IRAM_W(addr,R_ACC); //Store A to data address
+ IRAM_W(addr,ACC); //Store A to data address
}
//MOV @R0/@R1, A /* 1: 1111 011i */
INLINE void mov_ir_a(int r)
{
- IRAM_IW(R_R(r),R_ACC); //Store A to location pointed to by R0 or R1
+ IRAM_IW(R_REG(r),ACC); //Store A to location pointed to by R0 or R1
}
//MOV R0 to R7, A /* 1: 1111 1rrr */
INLINE void mov_r_a(int r)
{
- R_R(r) = R_ACC; //Store A to R0-R7
+ SET_REG(r, ACC); //Store A to R0-R7
}
//MOVC A, @A + PC /* 1: 1000 0011 */
INLINE void movc_a_iapc(void)
{
UINT8 data;
- data = CODEMEM_R(R_ACC+PC); //Move a byte from CODE(Program) Memory and store to ACC
- SFR_W(ACC,data);
+ data = CODEMEM_R(ACC+PC); //Move a byte from CODE(Program) Memory and store to ACC
+ SET_ACC(data);
}
//MOV C, bit addr /* 1: 1010 0010 */
@@ -609,8 +649,8 @@ INLINE void mov_c_bitaddr(void)
INLINE void movc_a_iadptr(void)
{
UINT8 data;
- data = CODEMEM_R(R_ACC+R_DPTR); //Move a byte from CODE(Program) Memory and store to ACC
- SFR_W(ACC,data);
+ data = CODEMEM_R(ACC + DPTR); //Move a byte from CODE(Program) Memory and store to ACC
+ SET_ACC(data);
}
//MOVX A,@DPTR /* 1: 1110 0000 */
@@ -618,44 +658,44 @@ INLINE void movc_a_iadptr(void)
INLINE void movx_a_idptr(void)
{
// UINT8 byte = DATAMEM_R(R_DPTR); //Grab 1 byte from External DATA memory pointed to by dptr
- UINT32 addr = ERAM_ADDR(R_DPTR,0xFFFF);
+ UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
UINT8 byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by dptr
- SFR_W(ACC,byte); //Store to ACC
+ SET_ACC(byte); //Store to ACC
}
//MOVX A, @R0/@R1 /* 1: 1110 001i */
//(Move External Ram 8 bit address to A)
INLINE void movx_a_ir(int r)
{
- UINT32 addr = ERAM_ADDR(R_R(r),0xFF); //Grab address by reading location pointed to by R0 or R1
+ UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); //Grab address by reading location pointed to by R0 or R1
UINT8 byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by address
- SFR_W(ACC,byte); //Store to ACC
+ SET_ACC(byte); //Store to ACC
}
//MOVX @DPTR,A /* 1: 1111 0000 */
//(Move A to External Ram 16 bit address)
INLINE void movx_idptr_a(void)
{
-// DATAMEM_W(R_DPTR, R_ACC); //Store ACC to External DATA memory address pointed to by DPTR
- UINT32 addr = ERAM_ADDR(R_DPTR,0xFFFF);
- DATAMEM_W(addr, R_ACC); //Store ACC to External DATA memory address pointed to by DPTR
+// DATAMEM_W(R_DPTR, ACC); //Store ACC to External DATA memory address pointed to by DPTR
+ UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
+ DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address pointed to by DPTR
}
//MOVX @R0/@R1,A /* 1: 1111 001i */
//(Move A to External Ram 8 bit address)
INLINE void movx_ir_a(int r)
{
- UINT32 addr = ERAM_ADDR(R_R(r),0xFF); //Grab address by reading location pointed to by R0 or R1
- DATAMEM_W(addr, R_ACC); //Store ACC to External DATA memory address
+ UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); //Grab address by reading location pointed to by R0 or R1
+ DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address
}
//MUL AB /* 1: 1010 0100 */
INLINE void mul_ab(void)
{
- UINT16 result = R_ACC * R_B;
+ UINT16 result = ACC * B;
//A gets lo bits, B gets hi bits of result
- SFR_W(B,(UINT8)((result & 0xFF00) >> 8));
- SFR_W(ACC,(UINT8)(result & 0x00FF));
+ B = (UINT8) ((result & 0xFF00) >> 8);
+ SET_ACC((UINT8)(result & 0x00FF));
//Set flags
SET_OV( ((result & 0x100) >> 8) ); //Set/Clear Overflow Flag if result > 255
SET_CY(0); //Carry Flag always cleared
@@ -671,7 +711,7 @@ INLINE void orl_mem_a(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- IRAM_W(addr,data | R_ACC); //Set data address value to it's value Logical OR with ACC
+ IRAM_W(addr,data | ACC); //Set data address value to it's value Logical OR with ACC
}
//ORL data addr, #data /* 1: 0100 0011 */
@@ -687,7 +727,7 @@ INLINE void orl_mem_byte(void)
INLINE void orl_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- SFR_W(ACC,R_ACC | data); //Set ACC to value of ACC Logical OR with Data
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
}
//ORL A, data addr /* 1: 0100 0101 */
@@ -695,21 +735,21 @@ INLINE void orl_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- SFR_W(ACC,R_ACC | data); //Set ACC to value of ACC Logical OR with Data
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
}
//ORL A, @RO/@R1 /* 1: 0100 011i */
INLINE void orl_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data from address R0 or R1 points to
- SFR_W(ACC,R_ACC | data); //Set ACC to value of ACC Logical OR with Data
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
}
//ORL A, RO to R7 /* 1: 0100 1rrr */
INLINE void orl_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0 - R7
- SFR_W(ACC,R_ACC | data); //Set ACC to value of ACC Logical OR with Data
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
}
//ORL C, bit addr /* 1: 0111 0010 */
@@ -735,51 +775,49 @@ INLINE void orl_c_nbitaddr(void)
INLINE void pop(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- IRAM_W(addr, IRAM_IR(R_SP)); //Store to contents of data addr, data pointed to by Stack - IRAM_IR needed to access upper 128 bytes of stack
+ IRAM_W(addr, IRAM_IR(SP)); //Store to contents of data addr, data pointed to by Stack - IRAM_IR needed to access upper 128 bytes of stack
//IRAM_IW(addr, IRAM_IR(R_SP)); //Store to contents of data addr, data pointed to by Stack - doesn't work, sfr's are not restored this way and it's not an indirect access anyway
- SFR_W(SP,R_SP-1); //Decrement SP
+ SP = SP-1; //Decrement SP
}
//PUSH data addr /* 1: 1100 0000 */
INLINE void push(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
- UINT8 tmpSP = R_SP; //Grab and Increment Stack Pointer
- tmpSP++; // ""
- SFR_W(SP,tmpSP); // ""
- if (tmpSP == R_SP) //Ensure it was able to write to new stack location
- IRAM_IW(tmpSP, IRAM_R(addr)); //Store to stack contents of data address - IRAM_IW needed to store to upper 128 bytes of stack, however, can't use IRAM_IR because that won't store the sfrs and it's not an indirect access anyway
+ UINT8 tmpSP = SP+1; //Grab and Increment Stack Pointer
+ SP = tmpSP; // ""
+ IRAM_IW(tmpSP, IRAM_R(addr)); //Store to stack contents of data address - IRAM_IW needed to store to upper 128 bytes of stack, however, can't use IRAM_IR because that won't store the sfrs and it's not an indirect access anyway
}
//RET /* 1: 0010 0010 */
INLINE void ret(void)
{
- POP_PC
+ POP_PC();
}
//RETI /* 1: 0011 0010 */
INLINE void reti(void)
{
- POP_PC
- CLEAR_CURRENT_IRQ
+ POP_PC();
+ CLEAR_CURRENT_IRQ();
}
//RL A /* 1: 0010 0011 */
INLINE void rl_a(void)
{
//Left Shift A, Bit 7 carries to Bit 0
- int carry = ((R_ACC & 0x80) >> 7);
- int data = (R_ACC<<1) & 0xfe;
- SFR_W(ACC, data | carry);
+ int carry = ((ACC & 0x80) >> 7);
+ int data = (ACC<<1) & 0xfe;
+ SET_ACC( data | carry);
}
//RLC A /* 1: 0011 0011 */
INLINE void rlc_a(void)
{
//Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC
- int carry = ((R_ACC & 0x80) >> 7);
- int data = ((R_ACC<<1) & 0xfe) | GET_CY;
- SFR_W(ACC, data);
+ int carry = ((ACC & 0x80) >> 7);
+ int data = ((ACC<<1) & 0xfe) | GET_CY;
+ SET_ACC( data);
SET_CY(carry);
}
@@ -787,18 +825,18 @@ INLINE void rlc_a(void)
INLINE void rr_a(void)
{
//Right Shift A, Bit 0 carries to Bit 7
- int carry = ((R_ACC & 1) << 7);
- int data = (R_ACC>>1) & 0x7f;
- SFR_W(ACC, data | carry);
+ int carry = ((ACC & 1) << 7);
+ int data = (ACC>>1) & 0x7f;
+ SET_ACC( data | carry);
}
//RRC A /* 1: 0001 0011 */
INLINE void rrc_a(void)
{
//Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag
- int carry = (R_ACC & 1);
- int data = ((R_ACC>>1) & 0x7f) | (GET_CY<<7);
- SFR_W(ACC, data);
+ int carry = (ACC & 1);
+ int data = ((ACC>>1) & 0x7f) | (GET_CY<<7);
+ SET_ACC( data);
SET_CY(carry);
}
@@ -820,15 +858,16 @@ INLINE void sjmp(void)
{
INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
PC = PC + rel_addr; //Update PC
+ change_pc(PC);
}
//SUBB A, #data /* 1: 1001 0100 */
INLINE void subb_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- UINT8 result = R_ACC - data - GET_CY; //Subtract data & carry flag from accumulator
- DO_SUB_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
@@ -837,36 +876,36 @@ INLINE void subb_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- UINT8 result = R_ACC - data - GET_CY; //Subtract data & carry flag from accumulator
- DO_SUB_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//SUBB A, @R0/@R1 /* 1: 1001 011i */
INLINE void subb_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data from memory pointed to by R0 or R1
- UINT8 result = R_ACC - data - GET_CY; //Subtract data & carry flag from accumulator
- DO_SUB_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//SUBB A, R0 to R7 /* 1: 1001 1rrr */
INLINE void subb_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0 - R7
- UINT8 result = R_ACC - data - GET_CY; //Subtract data & carry flag from accumulator
- DO_SUB_FLAGS(R_ACC,data,GET_CY); //Set Flags
- SFR_W(ACC,result); //Store 8 bit result of addtion in ACC
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
}
//SWAP A /* 1: 1100 0100 */
INLINE void swap_a(void)
{
UINT8 a_nib_lo, a_nib_hi;
- a_nib_hi = (R_ACC & 0x0f) << 4; //Grab lo byte of ACC and move to hi
- a_nib_lo = (R_ACC & 0xf0) >> 4; //Grab hi byte of ACC and move to lo
- SFR_W(ACC, a_nib_hi | a_nib_lo);
+ a_nib_hi = (ACC & 0x0f) << 4; //Grab lo byte of ACC and move to hi
+ a_nib_lo = (ACC & 0xf0) >> 4; //Grab hi byte of ACC and move to lo
+ SET_ACC( a_nib_hi | a_nib_lo);
}
//XCH A, data addr /* 1: 1100 0101 */
@@ -874,37 +913,37 @@ INLINE void xch_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data
- UINT8 oldACC = R_ACC; //Hold value of ACC
- SFR_W(ACC,data); //Sets ACC to data
+ UINT8 oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
IRAM_W(addr,oldACC); //Sets data address to old value of ACC
}
//XCH A, @RO/@R1 /* 1: 1100 011i */
INLINE void xch_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data pointed to by R0 or R1
- UINT8 oldACC = R_ACC; //Hold value of ACC
- SFR_W(ACC,data); //Sets ACC to data
- IRAM_W(R_R(r),oldACC); //Sets data address to old value of ACC
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1
+ UINT8 oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
+ IRAM_W(R_REG(r),oldACC); //Sets data address to old value of ACC
}
//XCH A, RO to R7 /* 1: 1100 1rrr */
INLINE void xch_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0-R7
- UINT8 oldACC = R_ACC; //Hold value of ACC
- SFR_W(ACC,data); //Sets ACC to data
- R_R(r) = oldACC; //Sets data address to old value of ACC
+ UINT8 data = R_REG(r); //Grab data from R0-R7
+ UINT8 oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
+ SET_REG(r, oldACC); //Sets data address to old value of ACC
}
//XCHD A, @R0/@R1 /* 1: 1101 011i */
INLINE void xchd_a_ir(int r)
{
UINT8 acc, ir_data;
- ir_data = IRAM_IR(R_R(r)); //Grab data pointed to by R0 or R1
- acc = R_ACC; //Grab ACC value
- SFR_W(ACC, (acc & 0xf0) | (ir_data & 0x0f) ); //Set ACC to lower nibble of data pointed to by R0 or R1
- IRAM_W(R_R(r), (ir_data & 0xf0) | (acc & 0x0f) ); //Set data pointed to by R0 or R1 to lower nibble of ACC
+ ir_data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1
+ acc = ACC; //Grab ACC value
+ SET_ACC( (acc & 0xf0) | (ir_data & 0x0f) ); //Set ACC to lower nibble of data pointed to by R0 or R1
+ IRAM_W(R_REG(r), (ir_data & 0xf0) | (acc & 0x0f) ); //Set data pointed to by R0 or R1 to lower nibble of ACC
}
//XRL data addr, A /* 1: 0110 0010 */
@@ -912,7 +951,7 @@ INLINE void xrl_mem_a(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- IRAM_W(addr,data ^ R_ACC); //Set data address value to it's value Logical XOR with ACC
+ IRAM_W(addr,data ^ ACC); //Set data address value to it's value Logical XOR with ACC
}
//XRL data addr, #data /* 1: 0110 0011 */
@@ -928,7 +967,7 @@ INLINE void xrl_mem_byte(void)
INLINE void xrl_a_byte(void)
{
UINT8 data = ROP_ARG(PC++); //Grab data
- SFR_W(ACC,R_ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
}
//XRL A, data addr /* 1: 0110 0101 */
@@ -936,25 +975,25 @@ INLINE void xrl_a_mem(void)
{
UINT8 addr = ROP_ARG(PC++); //Grab data address
UINT8 data = IRAM_R(addr); //Grab data from data address
- SFR_W(ACC,R_ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
}
//XRL A, @R0/@R1 /* 1: 0110 011i */
INLINE void xrl_a_ir(int r)
{
- UINT8 data = IRAM_IR(R_R(r)); //Grab data from address R0 or R1 points to
- SFR_W(ACC,R_ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
}
//XRL A, R0 to R7 /* 1: 0110 1rrr */
INLINE void xrl_a_r(int r)
{
- UINT8 data = R_R(r); //Grab data from R0 - R7
- SFR_W(ACC,R_ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
}
//illegal opcodes
-INLINE void illegal(void)
+INLINE void illegal(UINT8 op)
{
- LOG(("i8051 #%d: illegal opcode at 0x%03x: %02x\n", cpu_getactivecpu(), PC, ROP(PC)));
+ LOG(("i8051 #%d: illegal opcode at 0x%03x: %02x\n", cpu_getactivecpu(), PC-1, op));
}
diff --git a/src/mame/drivers/cardline.c b/src/mame/drivers/cardline.c
index 8e31c747e13..05b2a65a49b 100644
--- a/src/mame/drivers/cardline.c
+++ b/src/mame/drivers/cardline.c
@@ -78,6 +78,7 @@ static READ8_HANDLER(unk_r)
{
static int var=0;
var^=0x10;
+ printf("var %d\n",var);
return var;
}
@@ -98,7 +99,7 @@ static ADDRESS_MAP_START( mem_prg, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0xffff) AM_ROM
ADDRESS_MAP_END
-static ADDRESS_MAP_START( mem_data, ADDRESS_SPACE_DATA, 8 )
+static ADDRESS_MAP_START( mem_io, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0x0000, 0x1fff) AM_RAM
AM_RANGE(0x2003, 0x2003) AM_READ_PORT("IN0")
AM_RANGE(0x2005, 0x2005) AM_READ_PORT("IN1")
@@ -113,11 +114,10 @@ static ADDRESS_MAP_START( mem_data, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x3003, 0x3003) AM_NOP
AM_RANGE(0xc000, 0xdfff) AM_WRITE(vram_w) AM_BASE(&videoram)
AM_RANGE(0xe000, 0xffff) AM_WRITE(attr_w) AM_BASE(&colorram)
+ /* Ports */
+ AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_READWRITE(unk_r, video_w)
ADDRESS_MAP_END
-static ADDRESS_MAP_START( mem_io, ADDRESS_SPACE_IO, 8 )
- AM_RANGE(0x01, 0x01) AM_READWRITE(unk_r, video_w)
-ADDRESS_MAP_END
static INPUT_PORTS_START( cardline )
PORT_START("IN0")
@@ -196,7 +196,6 @@ static MACHINE_DRIVER_START( cardline )
/* basic machine hardware */
MDRV_CPU_ADD("main", I8051,12000000)
MDRV_CPU_PROGRAM_MAP(mem_prg,0)
- MDRV_CPU_DATA_MAP(mem_data,0)
MDRV_CPU_IO_MAP(mem_io,0)
/* video hardware */
diff --git a/src/mame/drivers/limenko.c b/src/mame/drivers/limenko.c
index 262886dc005..89b3ed0c79f 100644
--- a/src/mame/drivers/limenko.c
+++ b/src/mame/drivers/limenko.c
@@ -26,6 +26,7 @@
#include "driver.h"
#include "machine/eeprom.h"
#include "sound/okim6295.h"
+#include "cpu/i8051/i8051.h"
static tilemap *bg_tilemap, *md_tilemap, *fg_tilemap;
static UINT32 *bg_videoram, *md_videoram, *fg_videoram, *limenko_videoreg;
@@ -214,8 +215,8 @@ static READ8_HANDLER( spotty_sound_r )
}
static ADDRESS_MAP_START( spotty_sound_io_map, ADDRESS_SPACE_IO, 8 )
- AM_RANGE(0x0001, 0x0001) AM_READWRITE(spotty_sound_r, okim6295_data_0_w) //? sound latch and ?
- AM_RANGE(0x0003, 0x0003) AM_READWRITE(spotty_sound_cmd_r, spotty_sound_cmd_w) //not sure about anything...
+ AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_READWRITE(spotty_sound_r, okim6295_data_0_w) //? sound latch and ?
+ AM_RANGE(MCS51_PORT_P3, MCS51_PORT_P3) AM_READWRITE(spotty_sound_cmd_r, spotty_sound_cmd_w) //not sure about anything...
ADDRESS_MAP_END
/*****************************************************************************************************
@@ -675,7 +676,6 @@ static MACHINE_DRIVER_START( spotty )
MDRV_CPU_ADD("audio", I8051, 4000000) /* 4 MHz */
MDRV_CPU_PROGRAM_MAP(spotty_sound_prg_map, 0)
- MDRV_CPU_DATA_MAP(0, 0)
MDRV_CPU_IO_MAP(spotty_sound_io_map,0)
MDRV_NVRAM_HANDLER(93C46)
diff --git a/src/mame/drivers/m72.c b/src/mame/drivers/m72.c
index e08bd328c6c..373711e4191 100644
--- a/src/mame/drivers/m72.c
+++ b/src/mame/drivers/m72.c
@@ -89,6 +89,7 @@ other supported games as well.
#include "iremipt.h"
#include "m72.h"
#include "cpu/nec/nec.h"
+#include "cpu/i8051/i8051.h"
#define MASTER_CLOCK XTAL_32MHz
@@ -98,6 +99,9 @@ other supported games as well.
static UINT16 *protection_ram;
static emu_timer *scanline_timer;
static UINT8 m72_irq_base;
+static UINT8 mcu_snd_cmd_latch;
+static UINT8 mcu_sample_latch;
+static UINT32 mcu_sample_addr;
static TIMER_CALLBACK( m72_scanline_interrupt );
@@ -108,11 +112,25 @@ static MACHINE_START( m72 )
scanline_timer = timer_alloc(m72_scanline_interrupt, NULL);
}
+static TIMER_CALLBACK( synch_callback )
+{
+ //cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(8000000));
+ cpu_boost_interleave(ATTOTIME_IN_HZ(MASTER_CLOCK/4/12), ATTOTIME_IN_SEC(8));
+}
+
static MACHINE_RESET( m72 )
{
m72_irq_base = 0x20;
+ mcu_sample_addr = 0;
+ mcu_snd_cmd_latch = 0;
+
MACHINE_RESET_CALL(m72_sound);
+
+ state_save_register_global(mcu_sample_addr);
+ state_save_register_global(mcu_snd_cmd_latch);
+
timer_adjust_oneshot(scanline_timer, video_screen_get_time_until_pos(machine->primary_screen, 0, 0), 0);
+ timer_call_after_resynch( NULL, 0, synch_callback);
}
static MACHINE_RESET( xmultipl )
@@ -153,6 +171,170 @@ static TIMER_CALLBACK( m72_scanline_interrupt )
timer_adjust_oneshot(scanline_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline, 0), scanline);
}
+/***************************************************************************
+
+Protection emulation
+
+Currently only available for lohtb2, since this is the only game
+with a dumped 8751.
+
+The protection device does
+
+* provide startup code
+* provide checksums
+* feed samples to the sound cpu
+
+***************************************************************************/
+
+static TIMER_CALLBACK( delayed_ram16_w )
+{
+ UINT16 val = ((UINT32) param) & 0xffff;
+ UINT16 offset = (((UINT32) param) >> 16) & 0xffff;
+ UINT16 *ram = ptr;
+
+ ram[offset] = val;
+}
+
+static TIMER_CALLBACK( mcu_irq0_clear )
+{
+ cputag_set_input_line(machine, "mcu", 0, CLEAR_LINE);
+}
+
+
+static WRITE16_HANDLER( m72_main_mcu_sound_w )
+{
+ if (data & 0xfff0)
+ logerror("sound_w: %04x %04x\n", mem_mask, data);
+
+ if (ACCESSING_BITS_0_7)
+ {
+ mcu_snd_cmd_latch = data;
+ cputag_set_input_line(machine, "mcu", 1, ASSERT_LINE);
+ }
+}
+
+static WRITE16_HANDLER( m72_main_mcu_w)
+{
+ UINT16 val = protection_ram[offset];
+
+ COMBINE_DATA(&val);
+
+ /* 0x07fe is used for synchronization as well.
+ * This address however will not trigger an interrupt
+ */
+
+ if (offset == 0x0fff/2 && ACCESSING_BITS_8_15)
+ {
+ protection_ram[offset] = val;
+ cputag_set_input_line(machine, "mcu", 0, ASSERT_LINE);
+ /* Line driven, most likely by write line */
+ timer_set(ATTOTIME_IN_CYCLES(2, mame_find_cpu_index(machine, "mcu")), NULL, 0, mcu_irq0_clear);
+ }
+ else
+ timer_call_after_resynch( protection_ram, (offset<<16) | val, delayed_ram16_w);
+}
+
+static WRITE8_HANDLER( m72_mcu_data_w )
+{
+ UINT16 val;
+ if (offset&1) val = (protection_ram[offset/2] & 0x00ff) | (data << 8);
+ else val = (protection_ram[offset/2] & 0xff00) | (data&0xff);
+
+ timer_call_after_resynch( protection_ram, ((offset >>1 ) << 16) | val, delayed_ram16_w);
+}
+
+static READ8_HANDLER(m72_mcu_data_r )
+{
+ UINT8 ret;
+
+ if (offset&1) ret = (protection_ram[offset/2] & 0xff00)>>8;
+ else ret = (protection_ram[offset/2] & 0x00ff);
+
+ return ret;
+}
+
+static INTERRUPT_GEN( m72_mcu_int )
+{
+ mcu_snd_cmd_latch |= 0x11; /* 0x10 is special as well - FIXME */
+ cputag_set_input_line(machine, "mcu", 1, ASSERT_LINE);
+}
+
+static READ8_HANDLER(m72_mcu_sample_r )
+{
+ UINT8 sample;
+ sample = memory_region(machine, "samples")[mcu_sample_addr++];
+ return sample;
+}
+
+static WRITE8_HANDLER(m72_mcu_ack_w )
+{
+ cputag_set_input_line(machine, "mcu", 1, CLEAR_LINE);
+ mcu_snd_cmd_latch = 0;
+}
+
+static READ8_HANDLER(m72_mcu_snd_r )
+{
+ return mcu_snd_cmd_latch;
+}
+
+static READ8_HANDLER(m72_mcu_port_r )
+{
+ logerror("port read: %02x\n", offset);
+ return 0;
+}
+
+static WRITE8_HANDLER(m72_mcu_port_w )
+{
+ if (offset == 1)
+ {
+ mcu_sample_latch = data;
+ cputag_set_input_line(machine, "sound", INPUT_LINE_NMI, PULSE_LINE);
+ }
+ else
+ logerror("port: %02x %02x\n", offset, data);
+
+}
+
+static WRITE8_HANDLER( m72_mcu_low_w )
+{
+ mcu_sample_addr = (mcu_sample_addr & 0xffe000) | (data<<5);
+ logerror("low: %02x %02x %08x\n", offset, data, mcu_sample_addr);
+}
+
+static WRITE8_HANDLER( m72_mcu_high_w )
+{
+ mcu_sample_addr = (mcu_sample_addr & 0x1fff) | (data<<(8+5));
+ logerror("high: %02x %02x %08x\n", offset, data, mcu_sample_addr);
+}
+
+static WRITE8_HANDLER( m72_snd_cpu_sample_w )
+{
+ //dac_signed_data_w(0,data);
+ dac_data_w(0,data);
+}
+
+static READ8_HANDLER( m72_snd_cpu_sample_r )
+{
+ return mcu_sample_latch;
+}
+
+INLINE DRIVER_INIT( loht_mcu )
+{
+ int cpunum = mame_find_cpu_index(machine, "main");
+ int sndnum = mame_find_cpu_index(machine, "sound");
+
+ protection_ram = auto_malloc(0x10000);
+ memory_install_read16_handler(machine, cpunum, ADDRESS_SPACE_PROGRAM, 0xb0000, 0xbffff, 0, 0, SMH_BANK1);
+ memory_install_write16_handler(machine, cpunum, ADDRESS_SPACE_PROGRAM, 0xb0000, 0xb0fff, 0, 0, m72_main_mcu_w);
+ memory_set_bankptr(1, protection_ram);
+
+ //memory_install_write16_handler(machine, cpunum, ADDRESS_SPACE_IO, 0xc0, 0xc1, 0, 0, loht_sample_trigger_w);
+ memory_install_write16_handler(machine, cpunum, ADDRESS_SPACE_IO, 0xc0, 0xc1, 0, 0, m72_main_mcu_sound_w);
+
+ /* sound cpu */
+ memory_install_write8_handler(machine, sndnum, ADDRESS_SPACE_IO, 0x82, 0x82, 0xff, 0, m72_snd_cpu_sample_w);
+ memory_install_read8_handler (machine, sndnum, ADDRESS_SPACE_IO, 0x84, 0x84, 0xff, 0, m72_snd_cpu_sample_r);
+}
/***************************************************************************
@@ -541,70 +723,6 @@ static DRIVER_INIT( loht )
/* since we skip the startup tests, clear video RAM to prevent garbage on title screen */
memset(m72_videoram2,0,0x4000);
}
-#if 0
-int stepping = 0;
-
-static TIMER_CALLBACK( single_step )
-{
- if (param>0)
- timer_set( ATTOTIME_IN_NSEC(20), NULL, param-1, single_step);
- else
- stepping = 0;
-}
-static TIMER_CALLBACK( delayed_ram16_w )
-{
- UINT16 val = ((UINT32) param) & 0xffff;
- UINT16 offset = (((UINT32) param) >> 16) & 0xffff;
- UINT16 *ram = ptr;
-
- ram[offset] = val;
-
- if (!stepping)
- {
- stepping = 1;
- timer_call_after_resynch( NULL, 50, single_step);
- }
-}
-#else
-static TIMER_CALLBACK( delayed_ram16_w )
-{
- UINT16 val = ((UINT32) param) & 0xffff;
- UINT16 offset = (((UINT32) param) >> 16) & 0xffff;
- UINT16 *ram = ptr;
-
- ram[offset] = val;
-}
-
-#endif
-
-static WRITE16_HANDLER( m72_main_mcu_w)
-{
- UINT16 val = protection_ram[offset];
-
- COMBINE_DATA(&val);
-
- if (offset == 0x0fff/2 && ACCESSING_BITS_8_15)
- {
- protection_ram[offset] = val;
- cputag_set_input_line(machine, "mcu", 0, PULSE_LINE);
- }
- else
- timer_call_after_resynch( protection_ram, (offset<<16) | val, delayed_ram16_w);
-}
-
-static DRIVER_INIT( loht_mcu )
-{
- int cpunum = mame_find_cpu_index(machine, "main");
-
- protection_ram = auto_malloc(0x1000);
- memset(protection_ram, 0xff, 0x1000);
- memory_install_read16_handler(machine, cpunum, ADDRESS_SPACE_PROGRAM, 0xb0000, 0xb0fff, 0, 0, SMH_BANK1);
- memory_install_write16_handler(machine, cpunum, ADDRESS_SPACE_PROGRAM, 0xb0000, 0xb0fff, 0, 0, m72_main_mcu_w);
- memory_set_bankptr(1, protection_ram);
-
- memory_install_write16_handler(machine, cpunum, ADDRESS_SPACE_IO, 0xc0, 0xc1, 0, 0, loht_sample_trigger_w);
-
-}
static DRIVER_INIT( xmultipl )
{
@@ -800,7 +918,7 @@ static ADDRESS_MAP_START( m72_portmap, ADDRESS_SPACE_IO, 16 )
AM_RANGE(0x02, 0x03) AM_WRITE(m72_port02_w) /* coin counters, reset sound cpu, other stuff? */
AM_RANGE(0x04, 0x05) AM_WRITE(m72_dmaon_w)
AM_RANGE(0x06, 0x07) AM_WRITE(m72_irq_line_w)
- AM_RANGE(0x40, 0x43) AM_WRITE(SMH_NOP) /* Interrupt controller, only written to at bootup */
+ //AM_RANGE(0x40, 0x43) AM_WRITE(SMH_NOP) /* Interrupt controller, only written to at bootup */
AM_RANGE(0x80, 0x81) AM_WRITE(m72_scrolly1_w)
AM_RANGE(0x82, 0x83) AM_WRITE(m72_scrollx1_w)
AM_RANGE(0x84, 0x85) AM_WRITE(m72_scrolly2_w)
@@ -916,6 +1034,42 @@ static ADDRESS_MAP_START( poundfor_sound_portmap, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0x42, 0x42) AM_WRITE(m72_sound_irq_ack_w)
ADDRESS_MAP_END
+#if 0
+/* TODO: internal - should be removed */
+static ADDRESS_MAP_START( mcu_map, ADDRESS_SPACE_PROGRAM, 8 )
+ //ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0000, 0x0fff) AM_ROM
+ADDRESS_MAP_END
+#endif
+
+#if 0
+static ADDRESS_MAP_START( mcu_data_map, ADDRESS_SPACE_DATA, 8 )
+ //ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0000, 0x0000) AM_READWRITE(m72_mcu_sample_r, m72_mcu_low_w)
+ AM_RANGE(0x0001, 0x0001) AM_WRITE(m72_mcu_high_w)
+ AM_RANGE(0x0002, 0x0002) AM_READWRITE(m72_mcu_snd_r, m72_mcu_ack_w)
+ /* shared at b0000 - b0fff on the main cpu */
+ AM_RANGE(0xc000, 0xcfff) AM_RAM AM_READWRITE(m72_mcu_data_r,m72_mcu_data_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( mcu_io_map, ADDRESS_SPACE_IO, 8 )
+ //ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0000, 0x0003) AM_READWRITE(m72_mcu_port_r, m72_mcu_port_w)
+ADDRESS_MAP_END
+#else
+static ADDRESS_MAP_START( mcu_io_map, ADDRESS_SPACE_IO, 8 )
+ /* External access */
+ AM_RANGE(0x0000, 0x0000) AM_READWRITE(m72_mcu_sample_r, m72_mcu_low_w)
+ AM_RANGE(0x0001, 0x0001) AM_WRITE(m72_mcu_high_w)
+ AM_RANGE(0x0002, 0x0002) AM_READWRITE(m72_mcu_snd_r, m72_mcu_ack_w)
+ /* shared at b0000 - b0fff on the main cpu */
+ AM_RANGE(0xc000, 0xcfff) AM_RAM AM_READWRITE(m72_mcu_data_r,m72_mcu_data_w )
+
+ /* Ports */
+ AM_RANGE(MCS51_PORT_P0, MCS51_PORT_P3) AM_READWRITE(m72_mcu_port_r, m72_mcu_port_w)
+ADDRESS_MAP_END
+
+#endif
#define COIN_MODE_1 \
PORT_DIPNAME( 0x00f0, 0x00f0, DEF_STR( Coinage ) ) PORT_CONDITION("DSW", 0x0400, PORTCOND_NOTEQUALS, 0x0000) PORT_DIPLOCATION("SW1:5,6,7,8") \
@@ -1661,45 +1815,7 @@ static MACHINE_DRIVER_START( rtype )
MDRV_SOUND_ROUTE(1, "right", 1.0)
MACHINE_DRIVER_END
-
-static ADDRESS_MAP_START( mcu_map, ADDRESS_SPACE_PROGRAM, 8 )
- ADDRESS_MAP_UNMAP_HIGH
- AM_RANGE(0x0000, 0x0fff) AM_ROM
-ADDRESS_MAP_END
-
-static WRITE8_HANDLER( m72_mcu_data_w )
-{
- UINT16 val;
- if (offset&1) val = (protection_ram[offset/2] & 0x00ff) | (data << 8);
- else val = (protection_ram[offset/2] & 0xff00) | (data&0xff);
-
- if (offset == 6 && data == 0xfe)
- /* Hack - The v30 overshoots and will not see the unlock written to offset 6
- * We thus delay the lock, i.e. storing an unconditional branch to 6
- * here. This is highly time critical ... */
- timer_set(ATTOTIME_IN_USEC(10), protection_ram, ((offset >>1 ) << 16) | val, delayed_ram16_w);
- else
- timer_call_after_resynch( protection_ram, ((offset >>1 ) << 16) | val, delayed_ram16_w);
-}
-
-static READ8_HANDLER(m72_mcu_data_r )
-{
- UINT8 ret;
-
- if (offset&1) ret = (protection_ram[offset/2] & 0xff00)>>8;
- else ret = (protection_ram[offset/2] & 0x00ff);
-
- return ret;
-}
-
-static ADDRESS_MAP_START( mcu_data_map, ADDRESS_SPACE_DATA, 8 )
- ADDRESS_MAP_UNMAP_HIGH
- /* shared at b0000 - b0fff on the main cpu */
- AM_RANGE(0xc000, 0xcfff) AM_READWRITE(m72_mcu_data_r,m72_mcu_data_w )
-ADDRESS_MAP_END
-
-
-static MACHINE_DRIVER_START( m72 )
+static MACHINE_DRIVER_START( m72_base )
/* basic machine hardware */
MDRV_CPU_ADD("main",V30,MASTER_CLOCK/2/2) /* 16 MHz external freq (8MHz internal) */
@@ -1709,8 +1825,6 @@ static MACHINE_DRIVER_START( m72 )
MDRV_CPU_ADD("sound",Z80, SOUND_CLOCK)
MDRV_CPU_PROGRAM_MAP(sound_ram_map,0)
MDRV_CPU_IO_MAP(sound_portmap,0)
- MDRV_CPU_VBLANK_INT_HACK(fake_nmi,128) /* clocked by V1? (Vigilante) */
- /* IRQs are generated by main Z80 and YM2151 */
MDRV_MACHINE_START(m72)
MDRV_MACHINE_RESET(m72)
@@ -1739,15 +1853,25 @@ static MACHINE_DRIVER_START( m72 )
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 0.40)
MACHINE_DRIVER_END
-static MACHINE_DRIVER_START( m72_8751 )
+static MACHINE_DRIVER_START( m72 )
+
+ MDRV_IMPORT_FROM(m72_base)
+ MDRV_CPU_MODIFY("main")
+ MDRV_CPU_VBLANK_INT_HACK(fake_nmi,128) /* clocked by V1? (Vigilante) */
+ /* IRQs are generated by main Z80 and YM2151 */
+MACHINE_DRIVER_END
- MDRV_IMPORT_FROM(m72)
- MDRV_CPU_ADD("mcu",I8751, 16000000)
- MDRV_CPU_PROGRAM_MAP(mcu_map,0)
- MDRV_CPU_DATA_MAP(mcu_data_map,0)
- //MDRV_CPU_VBLANK_INT("main", irq0_line_pulse)
- MDRV_INTERLEAVE(1000)
+static MACHINE_DRIVER_START( m72_8751 )
+
+ MDRV_IMPORT_FROM(m72_base)
+
+ MDRV_CPU_ADD("mcu",I8751, MASTER_CLOCK/2)
+ /* internal - MDRV_CPU_PROGRAM_MAP(mcu_map,0) */
+ //MDRV_CPU_DATA_MAP(mcu_data_map,0)
+ MDRV_CPU_IO_MAP(mcu_io_map,0)
+ MDRV_CPU_VBLANK_INT("main", m72_mcu_int)
+ //MDRV_INTERLEAVE(1000)
MACHINE_DRIVER_END
@@ -2158,6 +2282,7 @@ static MACHINE_DRIVER_START( cosmccop )
MACHINE_DRIVER_END
static const nec_config kengo_config ={ gunforce_decryption_table, };
+
static MACHINE_DRIVER_START( kengo )
MDRV_IMPORT_FROM( cosmccop )
MDRV_CPU_MODIFY("main")
diff --git a/src/mame/drivers/micro3d.c b/src/mame/drivers/micro3d.c
index a20070a50e5..0e3c1e746ce 100644
--- a/src/mame/drivers/micro3d.c
+++ b/src/mame/drivers/micro3d.c
@@ -108,20 +108,26 @@ enum{ RX=0,TX,STATUS,SYN1,SYN2,DLE,MODE1,MODE2,COMMAND
/* Probably wrong and a bit crap */
static int data_to_i8031(void)
{
- mame_printf_debug("68k sent data: %x\n",M68681.TBB);
- return M68681.TBB;
+ mame_printf_debug("68k sent data: %x\n",M68681.TBB);
+ M68681.SRB |=0x0400; // Data has been sent - TX ready for more.
+ // Write to sound board
+ if(M68681.IMR & 0x1000)
+ {
+ cpunum_set_input_line_and_vector(Machine, 0,3, HOLD_LINE, M68681.IVR); // Generate an interrupt, if allowed.
+ }
+ return M68681.TBB;
}
static void data_from_i8031(int data)
{
- M68681.RBB = data<<8; // Put into receive buffer.
- M68681.SRB |= 0x0100; // Set Receiver B ready.
- if(M68681.IMR & 0x1000)
- {
- cpunum_set_input_line_and_vector(Machine, 0,3, HOLD_LINE, M68681.IVR); // Generate a receiver interrupt.
- mame_printf_debug("INTERRUPT!!!\n");
- }
- mame_printf_debug("8031 sent data: %x\n",data);
+ M68681.RBB = data<<8; // Put into receive buffer.
+ M68681.SRB |= 0x0100; // Set Receiver B ready.
+ if(M68681.IMR & 0x1000)
+ {
+ cpunum_set_input_line_and_vector(Machine, 0,3, HOLD_LINE, M68681.IVR); // Generate a receiver interrupt.
+ mame_printf_debug("INTERRUPT!!!\n");
+ }
+ mame_printf_debug("8031 sent data: %x\n",data);
}
@@ -205,14 +211,15 @@ static DRIVER_INIT( f15se )
static DRIVER_INIT( f15se21 )
{
+#if 1
UINT16 *rom = (UINT16 *)memory_region(machine, "main");
-
rom[0x2A8B3]=0x6006; //055166: 6606 bne 5516e -> bra
rom[0x2A8BF]=0x4E71; //05517E: 6704 beq 55184 -> nop
rom[0x28AD1]=0x4E71; //0515A2: 67F8 beq 5159c -> nop
rom[0x28A9E]=0x4E71;
rom[0x28ABD]=0x4E71;
rom[0x28C3B]=0x4E71;
+#endif
}
static INPUT_PORTS_START( stankatk )
@@ -492,8 +499,6 @@ switch(offset)
}
-
-
/* I should really re-write all this. */
static WRITE16_HANDLER( m68681_w )
@@ -537,6 +542,7 @@ switch(offset)
case 0x0a: break;
case 0x0b: M68681.TBB = value; // Fill transmit buffer
+#if 0
M68681.SRB |=0x0400; // Data has been sent - TX ready for more.
// Write to sound board
if(M68681.IMR & 0x1000)
@@ -545,6 +551,10 @@ switch(offset)
}
cpunum_set_input_line(machine, 2, I8051_RX_LINE, ASSERT_LINE); // Generate 8031 interrupt
mame_printf_debug("Sound board TX: %4X at PC=%4X\n",value,activecpu_get_pc());
+#endif
+ M68681.SRB &=~0x0400; // Data has been sent - TX ready for more.
+ cpunum_set_input_line(machine, 2, I8051_RX_LINE, ASSERT_LINE); // Generate 8031 interrupt
+ mame_printf_debug("Sound board TX: %4X at PC=%4X\n",value,activecpu_get_pc());
break;
case 0x0c: //mame_printf_debug("IVR: %d",value);
@@ -588,7 +598,8 @@ switch(offset)
case 0x09: return M68681.SRB; // Status Register B
case 0x0b: mame_printf_debug("\nHost received: %x\n",M68681.RBB);
- M68681.SRB^=0x0100; // No longer have data.
+ M68681.SRB^=0x0100; // No longer have data.
+ //M68681.SRB &= ~0x0100; // No longer have data.
return M68681.RBB;
// RX B - Monitor Port
}
@@ -786,36 +797,36 @@ ADDRESS_MAP_END
/* P1.7 = SELFTEST I P3.7 */
/*====================================================================*/
+static UINT8 port_latch[4];
static WRITE8_HANDLER(sound_io_w)
{
-
-switch(offset)
-{
- case 0x01: break;
- case 0x03: //if(data & 0x4) speech_bank=0;
-
- if(data & 0x10)
- {
- upd7759_0_reset_w(machine,0,0);
- }
- else
- {
- upd7759_0_reset_w(machine,0,1);
- }
- break;
-}
+ port_latch[offset] = data;
+ switch(offset)
+ {
+ case 0x01:
+ break;
+ case 0x03:
+ upd7759_set_bank_base(0, (data & 0x4) ? 0x20000 : 0);
+ upd7759_0_reset_w(machine,0,(data & 0x10) ? 0 : 1);
+ }
}
static READ8_HANDLER(sound_io_r)
{
+ switch(offset)
+ {
+ case 0x01: return (port_latch[offset] & 0x7f) | input_port_read_safe(machine, "SOUND", 0); /* Test push switch */
+ case 0x03: return (port_latch[offset] & 0xf7) | (upd7759_0_busy_r(machine,0) ? 0x08 : 0);
+ default: return 0;
+ }
-switch(offset)
-{
- case 0x01: return input_port_read_safe(machine, "SOUND", 0); /* Test push switch */
- case 0x03: return (int)(upd7759_0_busy_r(machine,0))<<3;
- default: return 0;
}
+static WRITE8_HANDLER( upd7759_port_start_w)
+{
+ upd7759_0_start_w(machine, offset, 0);
+ upd7759_0_port_w(machine, offset, data);
+ upd7759_0_start_w(machine, offset, 1);
}
static ADDRESS_MAP_START( soundmem_prg, ADDRESS_SPACE_PROGRAM, 8 )
@@ -825,20 +836,17 @@ ADDRESS_MAP_END
/* FFXX - 00XX */
-static ADDRESS_MAP_START( soundmem_data, ADDRESS_SPACE_DATA, 8 )
+static ADDRESS_MAP_START( soundmem_io, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0x0000, 0x07ff) AM_RAM /* 2Kb RAM */
AM_RANGE(0xfd00, 0xfd00) AM_WRITE(ym2151_register_port_0_w)
AM_RANGE(0xfd01, 0xfd01) AM_READWRITE(ym2151_status_port_0_r,ym2151_data_port_0_w)
- AM_RANGE(0xfe00, 0xfe00) AM_WRITE(upd7759_0_port_w)
+ AM_RANGE(0xfe00, 0xfe00) AM_WRITE(upd7759_port_start_w)
AM_RANGE(0xff00, 0xff00) AM_WRITE(dac_0_data_w) /* DAC A - used for S&H, special effects? */
AM_RANGE(0xff01, 0xff01) AM_WRITE(dac_1_data_w) /* DAC B - 'SPEECH' */
+ /* ports */
+ AM_RANGE(MCS51_PORT_P0, MCS51_PORT_P3) AM_READWRITE(sound_io_r,sound_io_w)
ADDRESS_MAP_END
-static ADDRESS_MAP_START( soundmem_io, ADDRESS_SPACE_IO, 8 )
- AM_RANGE(0x00, 0xff) AM_READWRITE(sound_io_r,sound_io_w)
-ADDRESS_MAP_END
-
-
static const tms34010_config vgb_config =
{
@@ -864,7 +872,6 @@ static MACHINE_DRIVER_START( micro3d )
MDRV_CPU_ADD("audio", I8051, 11059000)
MDRV_CPU_PROGRAM_MAP(soundmem_prg,0)
- MDRV_CPU_DATA_MAP(soundmem_data,0)
MDRV_CPU_IO_MAP(soundmem_io,0)
MDRV_MACHINE_RESET(micro3d)
diff --git a/src/mame/drivers/peplus.c b/src/mame/drivers/peplus.c
index 211996e1b7e..74fdf23bf5c 100644
--- a/src/mame/drivers/peplus.c
+++ b/src/mame/drivers/peplus.c
@@ -487,16 +487,6 @@ static READ8_HANDLER( peplus_sf000_r )
return sf000_ram[offset];
}
-/* External RAM Callback for I8052 */
-static READ32_HANDLER( peplus_external_ram_iaddr )
-{
- if (mem_mask == 0xff) {
- return (io_port[2] << 8) | offset;
- } else {
- return offset;
- }
-}
-
/* Last Color in Every Palette is bgcolor */
static READ8_HANDLER( peplus_bgcolor_r )
{
@@ -541,7 +531,7 @@ static READ8_HANDLER( peplus_input_bank_a_r )
last_cycles = activecpu_gettotalcycles();
} else {
/* Process Next Coin Optic State */
- if (curr_cycles - last_cycles > 600000 && coin_state != 0) {
+ if (curr_cycles - last_cycles > 600000/6 && coin_state != 0) {
coin_state++;
if (coin_state > 5)
coin_state = 0;
@@ -571,7 +561,7 @@ static READ8_HANDLER( peplus_input_bank_a_r )
break;
}
- if (curr_cycles - last_door > 6000) { // Guessing with 6000
+ if (curr_cycles - last_door > 6000/12) { // Guessing with 6000
if ((input_port_read_safe(machine, "DOOR",0xff) & 0x01) == 0x01) {
door_open = (!door_open & 0x01);
} else {
@@ -580,7 +570,7 @@ static READ8_HANDLER( peplus_input_bank_a_r )
last_door = activecpu_gettotalcycles();
}
- if (curr_cycles - last_coin_out > 600000 && coin_out_state != 0) { // Guessing with 600000
+ if (curr_cycles - last_coin_out > 600000/12 && coin_out_state != 0) { // Guessing with 600000
if (coin_out_state != 2) {
coin_out_state = 2; // Coin-Out Off
} else {
@@ -711,7 +701,7 @@ static ADDRESS_MAP_START( peplus_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0xffff) AM_ROM AM_BASE(&program_ram)
ADDRESS_MAP_END
-static ADDRESS_MAP_START( peplus_datamap, ADDRESS_SPACE_DATA, 8 )
+static ADDRESS_MAP_START( peplus_iomap, ADDRESS_SPACE_IO, 8 )
// Battery-backed RAM (0x1000-0x01fff Extended RAM for Superboards Only)
AM_RANGE(0x0000, 0x1fff) AM_READWRITE(peplus_cmos_r, peplus_cmos_w) AM_BASE(&cmos_ram)
@@ -763,16 +753,11 @@ static ADDRESS_MAP_START( peplus_datamap, ADDRESS_SPACE_DATA, 8 )
// Superboard Data
AM_RANGE(0xf000, 0xffff) AM_READWRITE(peplus_sf000_r, peplus_sf000_w) AM_BASE(&sf000_ram)
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( peplus_iomap, ADDRESS_SPACE_IO, 8 )
- ADDRESS_MAP_GLOBAL_MASK(0xff)
- // I/O Ports
- AM_RANGE(0x00, 0x03) AM_READ(peplus_io_r) AM_WRITE(peplus_io_w) AM_BASE(&io_port)
+ /* Ports start here */
+ AM_RANGE(MCS51_PORT_P0, MCS51_PORT_P3) AM_READ(peplus_io_r) AM_WRITE(peplus_io_w) AM_BASE(&io_port)
ADDRESS_MAP_END
-
/*************************
* Input ports *
*************************/
@@ -1010,7 +995,7 @@ static MACHINE_DRIVER_START( peplus )
// basic machine hardware
MDRV_CPU_ADD("main", I8052, 3686400*2)
MDRV_CPU_PROGRAM_MAP(peplus_map, 0)
- MDRV_CPU_DATA_MAP(peplus_datamap, 0)
+ //MDRV_CPU_DATA_MAP(peplus_datamap, 0)
MDRV_CPU_IO_MAP(peplus_iomap, 0)
MDRV_CPU_VBLANK_INT("main", irq0_line_hold)
@@ -1047,9 +1032,6 @@ MACHINE_DRIVER_END
/* Normal board */
static void peplus_init(void)
{
- /* External RAM callback */
- i8051_set_eram_iaddr_callback(peplus_external_ram_iaddr);
-
/* EEPROM is a X2404P 4K-bit Serial I2C Bus */
i2cmem_init(0, I2CMEM_SLAVE_ADDRESS, 8, eeprom_NVRAM_SIZE, NULL);
diff --git a/src/mame/drivers/sliver.c b/src/mame/drivers/sliver.c
index 58c29de18fb..32a13c1b73f 100644
--- a/src/mame/drivers/sliver.c
+++ b/src/mame/drivers/sliver.c
@@ -435,13 +435,11 @@ static ADDRESS_MAP_START( soundmem_prg, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0xffff) AM_ROM
ADDRESS_MAP_END
-static ADDRESS_MAP_START( soundmem_data, ADDRESS_SPACE_DATA, 8 )
+static ADDRESS_MAP_START( soundmem_io, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0x0100, 0x0100) AM_READWRITE( okim6295_status_0_r, okim6295_data_0_w )
AM_RANGE(0x0101, 0x0101) AM_READ(soundlatch_r)
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( soundmem_io, ADDRESS_SPACE_IO, 8 )
- AM_RANGE(0x0001, 0x0001) AM_WRITE( oki_setbank )
+ /* ports */
+ AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_WRITE( oki_setbank )
ADDRESS_MAP_END
static VIDEO_START(sliver)
@@ -540,7 +538,6 @@ static MACHINE_DRIVER_START( sliver )
MDRV_CPU_ADD("audio", I8051, 8000000)
MDRV_CPU_PROGRAM_MAP(soundmem_prg,0)
- MDRV_CPU_DATA_MAP(soundmem_data,0)
MDRV_CPU_IO_MAP(soundmem_io,0)
diff --git a/src/mame/drivers/sslam.c b/src/mame/drivers/sslam.c
index 7c8d610f459..6f4926d016e 100644
--- a/src/mame/drivers/sslam.c
+++ b/src/mame/drivers/sslam.c
@@ -494,8 +494,8 @@ static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 )
ADDRESS_MAP_END
static ADDRESS_MAP_START( sound_io_map, ADDRESS_SPACE_IO, 8 )
- AM_RANGE(0x0001, 0x0001) AM_WRITE(playmark_snd_control_w)
- AM_RANGE(0x0003, 0x0003) AM_READWRITE(playmark_snd_command_r, playmark_oki_w)
+ AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_WRITE(playmark_snd_control_w)
+ AM_RANGE(MCS51_PORT_P3, MCS51_PORT_P3) AM_READWRITE(playmark_snd_command_r, playmark_oki_w)
ADDRESS_MAP_END
/* Input Ports */
@@ -735,7 +735,6 @@ static MACHINE_DRIVER_START( sslam )
MDRV_CPU_ADD("audio", I8051, 12000000)
MDRV_CPU_FLAGS(CPU_DISABLE) /* Internal code is not dumped - 2 boards were protected */
MDRV_CPU_PROGRAM_MAP(sound_map,0)
- MDRV_CPU_IO_MAP(0,0)
/* video hardware */
MDRV_SCREEN_ADD("main", RASTER)
@@ -829,7 +828,7 @@ ROM_START( sslam )
ROM_RELOAD ( 0xe00001, 0x80000 )
ROM_RELOAD ( 0xf00001, 0x80000 )
- ROM_REGION( 0x0800, "audio", 0 )
+ ROM_REGION( 0x1000, "audio", 0 )
ROM_LOAD( "s87c751.bin", 0x0000, 0x0800, NO_DUMP )
ROM_REGION( 0x200000, "gfx1", ROMREGION_DISPOSE ) /* Bg */
@@ -889,7 +888,7 @@ ROM_START( sslama )
ROM_RELOAD ( 0xe00001, 0x80000 )
ROM_RELOAD ( 0xf00001, 0x80000 )
- ROM_REGION( 0x0800, "audio", 0 )
+ ROM_REGION( 0x1000, "audio", 0 )
ROM_LOAD( "s87c751.bin", 0x0000, 0x0800, NO_DUMP )
ROM_REGION( 0x200000, "gfx1", ROMREGION_DISPOSE ) /* Bg */
@@ -920,7 +919,7 @@ ROM_START( powerbls )
ROM_LOAD16_BYTE( "21.u67", 0x00000, 0x40000, CRC(4e302381) SHA1(5685d15fd3137866093ff13b95a7df2265a8bc64) )
ROM_LOAD16_BYTE( "22.u66", 0x00001, 0x40000, CRC(89b70599) SHA1(57a5d71e4d8ca62fffe2e81116c5236d2194ae11) )
- ROM_REGION( 0x0800, "audio", 0 )
+ ROM_REGION( 0x1000, "audio", 0 )
ROM_LOAD( "s87c751.bin", 0x0000, 0x0800, CRC(5b8b2d3a) SHA1(c3409243dfc0ca959a80f6890c87b4ce9eb0741d) )
ROM_REGION( 0x200000, "gfx1", ROMREGION_DISPOSE ) /* Bg */
diff --git a/src/mame/drivers/videopkr.c b/src/mame/drivers/videopkr.c
index 90b6eb6ac42..bea08e86358 100644
--- a/src/mame/drivers/videopkr.c
+++ b/src/mame/drivers/videopkr.c
@@ -899,15 +899,13 @@ static ADDRESS_MAP_START( i8051_sound_mem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x0fff) AM_ROM
ADDRESS_MAP_END
-static ADDRESS_MAP_START( i8051_sound_dat, ADDRESS_SPACE_DATA, 8 )
- AM_RANGE(0x0000, 0x1ff) AM_RAM
-ADDRESS_MAP_END
-
static ADDRESS_MAP_START( i8051_sound_port, ADDRESS_SPACE_IO, 8 )
- AM_RANGE(0x00, 0x00) AM_READWRITE(baby_sound_p0_r, baby_sound_p0_w)
- AM_RANGE(0x01, 0x01) AM_READWRITE(baby_sound_p1_r, baby_sound_p1_w)
- AM_RANGE(0x02, 0x02) AM_READWRITE(baby_sound_p2_r, baby_sound_p2_w)
- AM_RANGE(0x03, 0x03) AM_READWRITE(baby_sound_p3_r, baby_sound_p3_w)
+ AM_RANGE(0x0000, 0x1ff) AM_RAM
+ /* ports */
+ AM_RANGE(MCS51_PORT_P0, MCS51_PORT_P0) AM_READWRITE(baby_sound_p0_r, baby_sound_p0_w)
+ AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_READWRITE(baby_sound_p1_r, baby_sound_p1_w)
+ AM_RANGE(MCS51_PORT_P2, MCS51_PORT_P2) AM_READWRITE(baby_sound_p2_r, baby_sound_p2_w)
+ AM_RANGE(MCS51_PORT_P3, MCS51_PORT_P3) AM_READWRITE(baby_sound_p3_r, baby_sound_p3_w)
ADDRESS_MAP_END
@@ -1228,7 +1226,6 @@ static MACHINE_DRIVER_START( babypkr )
MDRV_CPU_REPLACE("main", I8039, CPU_CLOCK_ALT)
MDRV_CPU_REPLACE("sound", I8051, CPU_CLOCK )
MDRV_CPU_PROGRAM_MAP(i8051_sound_mem, 0)
- MDRV_CPU_DATA_MAP(i8051_sound_dat, 0)
MDRV_CPU_IO_MAP(i8051_sound_port, 0)
/* video hardware */