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, -typedef struct { - UINT8 timerbaud; //Flag set if timer overflow is controlling baud - UINT8 sending; //Flag set when uart is sending + 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 */ +}; + +/*************************************************************************** + 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; - -static I8051 i8051; -static I8051_UART uart; - -//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)); - -/*Short cuts*/ - -/*************************************************************** - * Read Opcode/Opcode Arguments from Program Code - ***************************************************************/ +/* 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 - ***************************************************************/ +/* Read a byte from External Code Memory (Usually Program Rom(s) Space) */ +#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) */ +#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) + +/* Read/Write a byte from/to the Internal RAM */ + +#define IRAM_R(a) iram_read(a) +#define IRAM_W(a, d) iram_write(a, d) + +/* 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) + +/* Form an Address to Read/Write to External RAM indirectly */ +/* (called from indirect addressing) */ +#define ERAM_ADDR(a,m) external_ram_iaddr(a,m) + +/* 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) + +/* 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 -#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 -/*************************************************************** - * 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) +/*************************************************************************** + SHORTCUTS +***************************************************************************/ -#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 +#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) /*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 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 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 */ - -#if (HAS_I8052 || HAS_I8752) -#define V_TF2 0x02b /* Timer 2 Overflow */ -#endif +#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,1050 +487,907 @@ 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; +#define CLEAR_CURRENT_IRQ() do { mcs51.cur_irq = 0xff; mcs51.irq_priority = 0; } while (0) -/* shorter names for the I8051 structure elements */ +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ -//Internal stuff -#define PPC i8051.ppc -#define PC i8051.pc -#define TYPE i8051.subtype -#define RWM i8051.rwm +static int mcs51_icount; -//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 +static mcs51_regs mcs51; + + +/*************************************************************************** + 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) +{ + 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); +} + + +/* 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 + + 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. +*/ + +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 -#define R_PSW i8051.psw -#define R_ACC i8051.acc -#define R_B i8051.b - -/* # 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 -}; - -/* Include Opcode functions */ -#include "i8051ops.c" - -void i8051_init(int index, int clock, const void *config, int (*irqcallback)(int)) -{ - i8051_set_irq_callback(irqcallback); - - //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); + return offset; } -/* Reset registers to the initial values */ -void i8051_reset(void) +/* Internal ram read/write */ + +INLINE UINT8 iram_read(size_t offset) { - int (*save_irqcallback)(int); - - save_irqcallback = i8051.irq_callback; - memset(&i8051, 0, sizeof(I8051)); - i8051.irq_callback = save_irqcallback; - - memset(&uart, 0, sizeof(I8051_UART)); - i8051.subtype = 8051; - - //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! - - //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; - - //Setup External ram callback handlers - i8051.eram_iaddr_callback = hold_eram_iaddr_callback; - hold_eram_iaddr_callback = NULL; - - //Clear Ram (w/0xff) - memset(&i8051.IntRam,0xff,sizeof(i8051.IntRam)); - - /* 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); - - /* Flag as NO IRQ in Progress */ - CLEAR_CURRENT_IRQ + return (((offset) < 0x80) ? data_read_byte_8le(offset) : mcs51.sfr_read(offset)); } -/* Shut down CPU core */ -void i8051_exit(void) +INLINE void iram_write(size_t offset, UINT8 data) { - /* nothing to do */ + if ((offset) < 0x80) + data_write_byte_8le(offset, data); + else + mcs51.sfr_write(offset, data); } -/* Execute cycles - returns number of cycles actually run */ -int i8051_execute(int cycles) +/*Push the current PC to the stack*/ +INLINE void push_pc(void) { - i8051_icount = cycles; + 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) +} - do +/*Pop the current PC off the stack and into the pc*/ +INLINE void pop_pc(void) +{ + 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); +} + +//Set the PSW Parity Flag +INLINE void set_parity(void) +{ + //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); + } + + SET_P(p & 1); +} + +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 */ + + //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); + } +} + +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); +} + +INLINE void do_sub_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)); +} + +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(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) { - //Read next opcode - UINT8 op = cpu_readop(PC); - - //Store previous PC - PPC = PC; - - //Call Debugger - debugger_instruction_hook(Machine, PC); - - //remove after testing - if(PC != PPC) op = cpu_readop(PC); - - //Update Timer (if any timers are running) - if(GET_TR0 || GET_TR1) - update_timer(i8051.prev_used_cycles); - - //Update Serial (if serial port sending data) - if(uart.sending) - update_serial(i8051.prev_used_cycles); - - //Update PC - PC += 1; - //Decrement total count by # of cycles used for this opcode - i8051_icount -= (i8051_cycles[op]); - - switch( op ) + 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(); - break; - //LJMP code addr - case 0x02: /* 1: 0000 0010 */ - ljmp(); - break; - //RR A - case 0x03: /* 1: 0000 0011 */ - rr_a(); - break; - //INC A - case 0x04: /* 1: 0000 0100 */ - inc_a(); - break; - //INC data addr - case 0x05: /* 1: 0000 0101 */ - RWM=1; - inc_mem(); - RWM=0; - 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(); - break; - //MOV data addr, A - case 0xf5: /* 1: 1111 0101 */ - mov_mem_a(); - break; - //MOV @R0/@R1, A /* 1: 1111 011i */ - case 0xf6: - case 0xf7: - mov_ir_a(op&1); - 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); - break; - default: - illegal(); + 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 + } } - - //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(); - - } while( i8051_icount > 0 ); - - return cycles - i8051_icount; -} - -/* Get registers, return context size */ -void i8051_get_context(void *dst) -{ - if( dst ) - memcpy(dst, &i8051, sizeof(I8051)); -} - -/* Set registers */ -void i8051_set_context(void *src) -{ - if( src ) - memcpy(&i8051, src, sizeof(I8051)); -} - -/* Get Internal RAM value */ -unsigned i8051_get_intram(int offset) -{ - UINT8 ram_ret = 0; - RWM = 1; - ram_ret = IRAM_R(offset); - RWM = 0; - return ram_ret; -} - -/*NOTE: These are not used by the opcode functions, they are here only for MAME requirements*/ -unsigned i8051_get_reg(int regnum) -{ - 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; + } -} - -/*NOTE: These are not used by the opcode functions, they are here only for MAME requirements*/ -void i8051_set_reg (int regnum, unsigned val) -{ - switch( regnum ) + /* receive */ + if (mcs51.uart.rx_clk >= 16) { - 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; - } -} - -void i8051_set_irq_line(int irqline, int state) -{ - 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; - - //Do the interrupt & handle - remove machine cycles used - if(GET_IE0) - i8051_icount-=check_interrupts(); - break; - - //External Interrupt 1 - case I8051_INT1_LINE: - - //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; - - //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) { + 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(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; + 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); } - break; - //Note: we won't call check interrupts, we'll let the main loop catch it + } } } + + +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; + 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; + 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; + 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; + } + } + 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; + } + } +} + +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; + 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; + 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; + case 3: + /* do nothing */ + break; + } + if (overflow) + transmit_receive(1); + } +} + +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; + + UINT32 count = ((TH2<<8) | TL2) + delta; + mcs51.t2_cnt = 0; + + 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; + } + } +} + +INLINE void update_timers(int cycles) +{ + if (cycles == 0) + return; /* nothing to do */ + /* Update Timer 0 */ + update_timer_t0(cycles); + update_timer_t1(cycles); + + if (mcs51.features & FEATURE_I8052_UART) + { + update_timer_t2(cycles); + } +} + +//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) +{ + 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; + } +} + +INLINE void serial_receive(void) +{ + 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; + } + } +} + +//Check and update status of serial port +INLINE void update_serial(int cycles) +{ + while (--cycles>=0) + transmit_receive(0); +} + +/*************************************************************************** + CALLBACKS - TODO: Remove +***************************************************************************/ + + +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; +} + +/*************************************************************************** + OPCODES +***************************************************************************/ + +#include "i8051ops.c" + + +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) { + 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; + //If All Inerrupts Disabled or no pending abort.. - if(!GET_EA) return 0; + if(!GET_EA) return; - //Any Interrupts Pending? - if(NO_PENDING_IRQ) return 0; + if (mcs51.features & FEATURE_I8052_UART) + ints |= ((GET_TF2|GET_EXF2)<<5); - //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 (!ints) return; - //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 - - //External Int 0 - if(GET_IE0) { - //Set vector & priority level request - i8051.int_vec = V_IE0; - i8051.priority_request = GET_PX0; + if(mcs51.irq_priority) + { + LOG(("high priority irq in progress, skipping irq request\n")); + return; } - //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; + + for (i=0; iIn 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. + * + * ==> 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 - 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; - - case SCON: { - //Update register - R_SCON = data; - 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 - break; - - case P2: - R_P2 = data; - OUT(2,data); - break; - - case IE: R_IE = data; break; - - case P3: - R_P3 = data; - OUT(3,data); - 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; - break; - - case ACC: - R_ACC = data; - SET_PARITY; - 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 + //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 - 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; -} - -/* Writes the contents of the Internal RAM memory */ -/* Anything above 0x7f is a sfr/register */ -static WRITE8_HANDLER(internal_ram_write) -{ - 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)); - } -} - -/* 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); -} - -/* 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)); - - return offset; -} - -/*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) -} - -/*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 -} - -//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); -} - -static READ8_HANDLER(bit_address_r) -{ - 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; - } - 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 -} - - -static WRITE8_HANDLER(bit_address_w) -{ - int word; - int mask; - int bit_pos; - int result; - int base; - int distance; - - 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; - } - 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) -{ - //Restrict internal ram to 256 Bytes max - if(offset < 0x100) - IRAM_W(offset,data); -} - -INLINE void do_add_flags(UINT8 a, UINT8 data, UINT8 c) -{ - 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("add: result=%x, c=%x, ac=%x, ov=%x\n",a+data+c,cy,ac,ov); -} - -INLINE void do_sub_flags(UINT8 a, UINT8 data, UINT8 c) -{ - 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); -} - -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); - - /* 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 */ - - /* 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); + if (!GET_IT0) /* clear if level triggered */ + SET_IE0(0); } - /* Update new values of the counter */ - R_TH2 = (count>>8) & 0xff; - R_TL2 = count & 0xff; - } + + break; + + //External Interrupt 1 + case I8051_INT1_LINE: + + //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 MCS51_T0_LINE: + if (GET_BIT(tr_state, MCS51_T0_LINE)) + mcs51.t0_cnt++; + break; + + case MCS51_T1_LINE: + if (GET_BIT(tr_state, MCS51_T1_LINE)) + mcs51.t1_cnt++; + break; + + 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 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; + //Serial Port Receive + case I8051_RX_LINE: + //Is the enable flags for this interrupt set? + if (state != CLEAR_LINE) + { + serial_receive(); + } + break; } -#endif + mcs51.last_line_state = new_state; } -//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) +/* Execute cycles - returns number of cycles actually run */ +static int mcs51_execute(int cycles) { - int mode = (GET_SM0<<1) | GET_SM1; + UINT8 op; + + mcs51_icount = cycles; - //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; - } -} + /* 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); -//Check and update status of serial port -INLINE void update_serial(int cyc) -{ - //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 - } + do + { + /* Read next opcode */ + PPC = PC; + debugger_instruction_hook(Machine, PC); + op = cpu_readop(PC++); + + /* process opcode and count cycles */ + mcs51.inst_cycles = mcs51_cycles[op]; + execute_op(op); + + /* burn the cycles */ + mcs51_icount -= mcs51.inst_cycles; + burn_cycles(mcs51.inst_cycles); + + } while( mcs51_icount > 0 ); + + return cycles - mcs51_icount; } /**************************************************************************** - * 8752 Section + * MCS51/8051 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 mcs51_sfr_write(size_t offset, UINT8 data) { - memset(&i8051, 0, sizeof(I8051)); - memset(&uart, 0, sizeof(I8051_UART)); - i8051.subtype = 8752; + /* 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!" */ - //Set up 8052 specific internal read/write (indirect) handlers.. - i8051.iram_iread = i8052_internal_ram_iread; - i8051.iram_iwrite = i8052_internal_ram_iwrite; + 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; + } + data_write_byte_8le((size_t)offset | 0x100, data); +} +static UINT8 mcs51_sfr_read(size_t offset) +{ + assert(offset >= 0x80 && offset <= 0xff); + + 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; + } +} + + +static void mcs51_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + 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 ); +} + +/* Reset registers to the initial values */ +static void mcs51_reset(void) +{ + update_ptrs(); //Set up serial call back handlers - i8051.serial_tx_callback = hold_serial_tx_callback; + mcs51.serial_tx_callback = hold_serial_tx_callback; hold_serial_tx_callback = NULL; - i8051.serial_rx_callback = hold_serial_rx_callback; + mcs51.serial_rx_callback = hold_serial_rx_callback; hold_serial_rx_callback = NULL; - - //Setup External ram callback handlers - i8051.eram_iaddr_callback = hold_eram_iaddr_callback; - hold_eram_iaddr_callback = NULL; - - //Clear Ram (w/0xff) - memset(&i8051.IntRam,0xff,sizeof(i8051.IntRam)); - + + 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; - 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); - + 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 */ - SFR_W(P3, 0xff); - SFR_W(P2, 0xff); - SFR_W(P1, 0xff); - SFR_W(P0, 0xff); + SET_P3(0xff); + SET_P2(0xff); + SET_P1(0xff); + SET_P0(0xff); /* Flag as NO IRQ in Progress */ - CLEAR_CURRENT_IRQ + 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) +/* Shut down CPU core */ +static void mcs51_exit(void) { - //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); + /* nothing to do */ } -/* 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) +/**************************************************************************** + * 8052 Section + ****************************************************************************/ + +static void i8052_sfr_write(size_t offset, UINT8 data) { - 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; + 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; + + default: + mcs51_sfr_write(offset, data); + } } -/* 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 UINT8 i8052_sfr_read(size_t offset) { - 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)); + 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); + } } -#endif //(HAS_8752) +static void i8052_init (int index, int clock, const void *config, int (*irqcallback)(int)) +{ + 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; +} + + +static void i8052_reset(void) +{ + mcs51_reset(); + + //8052 Only registers + T2CON = 0; + RCAP2L = 0; + RCAP2H = 0; + TL2 = 0; + TH2 = 0; +} + +/*************************************************************************** + ADDRESS MAPS +***************************************************************************/ + +/* 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 + +static ADDRESS_MAP_START(program_13bit, ADDRESS_SPACE_PROGRAM, 8) + AM_RANGE(0x00, 0x1fff) AM_ROM +ADDRESS_MAP_END + +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 + +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 + + +/*************************************************************************** + GENERAL CONTEXT ACCESS +***************************************************************************/ + +static void mcs51_get_context(void *dst) +{ + if( dst ) + memcpy(dst, &mcs51, sizeof(mcs51_regs)); +} + +static void mcs51_set_context(void *src) +{ + if( src ) + memcpy(&mcs51, src, sizeof(mcs51_regs)); + change_pc(PC); + update_ptrs(); +} /************************************************************************** * 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_SP: 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_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: 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_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; } } -#if (HAS_I8052) +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 --- */ +} + 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 */ +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 */ +}; -/* 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 +/* special I/O space ports */ -/* 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 +enum +{ + MCS51_PORT_P0 = 0x10000, + MCS51_PORT_P1 = 0x10001, + MCS51_PORT_P2 = 0x10002, + MCS51_PORT_P3 = 0x10003, + MCS51_PORT_TX = 0x10004, /* P3.1 */ +}; -#define TI_FLAG 1 -#define RI_FLAG 2 -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); - -/**************************************************************************** - * 8752 Section - ****************************************************************************/ -#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) - +/* variants 4k internal rom and 128 byte internal memory */ void i8051_get_info(UINT32 state, cpuinfo *info); -void i8052_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); +/**************************************************************************** + * Disassembler + ****************************************************************************/ + +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 ) + + 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 + + static MACHINE_DRIVER_START( m72_8751 ) - 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) + 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) + + /* 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 -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) -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 */