summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/cpu/m6502/m6502.h
blob: c16757581f3dac7e2275501f5af1e16d5801f04b (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                     





                                                                            

                                                                            

                              
 

                                                          
 
                                       
                                                                                  
 


                                        
                                           
                                               
                                          
                                               

          
                                                                                                      
 
                                              
                                                       
 
                                                                                                                                   
 
                                
 
          

                                                                                                                        

                                
                                                  
                                                                             
 
                                              





                                                                  



                                                           
                                               



                                                                       



                                                        
                                           

                                                                 

          
              
                                    


              


                                     
                                                                                   









                                 

                                             

                                             


                                                              

                                                                         
                                                                               

                                            
                                                                         

                                           

                                                                            
                                                                                                           

                                            
                                                                                       
 
                                                             
 










                                                                                                  
                                                                      
 
                                                

                                      
                                                          
                                                                 
 






                                                                             

                              
                               
 

                                                               



                                       


                                                                                                               



                                                      



                                    


                         



                                                
                      




                                  

































































































                                                                                                       

  







                     

  


                                                
                                                 

  
                                        
 
                                
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************

    m6502.h

    Mostek 6502, original NMOS variant

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

#ifndef MAME_CPU_M6502_M6502_H
#define MAME_CPU_M6502_M6502_H

#define MCFG_M6502_DISABLE_CACHE() \
	downcast<m6502_device *>(device)->disable_cache();

#define MCFG_M6502_SYNC_CALLBACK(_cb) \
	devcb = &downcast<m6502_device &>(*device).set_sync_callback(DEVCB_##_cb);

class m6502_device : public cpu_device {
public:
	enum {
		IRQ_LINE = INPUT_LINE_IRQ0,
		APU_IRQ_LINE = INPUT_LINE_IRQ1,
		NMI_LINE = INPUT_LINE_NMI,
		V_LINE   = INPUT_LINE_IRQ0 + 16
	};

	m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	bool get_sync() const { return sync; }
	void disable_cache() { cache_disabled = true; }

	template<class Object> devcb_base &set_sync_callback(Object &&cb) { return sync_w.set_callback(std::forward<Object>(cb)); }

	devcb_write_line sync_w;

protected:
	m6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	class memory_interface {
	public:
		address_space *program, *sprogram;
		memory_access_cache<0, 0, ENDIANNESS_LITTLE> *cache, *scache;

		virtual ~memory_interface() {}
		virtual uint8_t read(uint16_t adr) = 0;
		virtual uint8_t read_9(uint16_t adr);
		virtual uint8_t read_sync(uint16_t adr) = 0;
		virtual uint8_t read_arg(uint16_t adr) = 0;
		virtual void write(uint16_t adr, uint8_t val) = 0;
		virtual void write_9(uint16_t adr, uint8_t val);
	};

	class mi_default_normal : public memory_interface {
	public:
		virtual ~mi_default_normal() {}
		virtual uint8_t read(uint16_t adr) override;
		virtual uint8_t read_sync(uint16_t adr) override;
		virtual uint8_t read_arg(uint16_t adr) override;
		virtual void write(uint16_t adr, uint8_t val) override;
	};

	class mi_default_nd : public mi_default_normal {
	public:
		virtual ~mi_default_nd() {}
		virtual uint8_t read_sync(uint16_t adr) override;
		virtual uint8_t read_arg(uint16_t adr) override;
	};

	enum {
		STATE_RESET = 0xff00
	};

	enum {
		F_N = 0x80,
		F_V = 0x40,
		F_E = 0x20, // 65ce02
		F_T = 0x20, // M740: replaces A with $00,X in some opcodes when set
		F_B = 0x10,
		F_D = 0x08,
		F_I = 0x04,
		F_Z = 0x02,
		F_C = 0x01
	};

	virtual void init();

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	// device_execute_interface overrides
	virtual uint32_t execute_min_cycles() const override;
	virtual uint32_t execute_max_cycles() const override;
	virtual uint32_t execute_input_lines() const override;
	virtual void execute_run() override;
	virtual void execute_set_input(int inputnum, int state) override;
	virtual bool execute_input_edge_triggered(int inputnum) const override;

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	// device_state_interface overrides
	virtual void state_import(const device_state_entry &entry) override;
	virtual void state_export(const device_state_entry &entry) override;
	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;

	// device_disasm_interface overrides
	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;

	address_space_config program_config, sprogram_config;

	uint16_t  PPC;                    /* previous program counter */
	uint16_t  NPC;                    /* next start-of-instruction program counter */
	uint16_t  PC;                     /* program counter */
	uint16_t  SP;                     /* stack pointer (always 100 - 1FF) */
	uint16_t  TMP;                    /* temporary internal values */
	uint8_t   TMP2;                   /* another temporary internal value, 8 bits this time */
	uint8_t   A;                      /* Accumulator */
	uint8_t   X;                      /* X index register */
	uint8_t   Y;                      /* Y index register */
	uint8_t   P;                      /* Processor status */
	uint8_t   IR;                     /* Prefetched instruction register */
	int     inst_state_base;        /* Current instruction bank */

	std::unique_ptr<memory_interface> mintf;
	int inst_state, inst_substate;
	int icount;
	bool nmi_state, irq_state, apu_irq_state, v_state;
	bool irq_taken, sync, cache_disabled, inhibit_interrupts;

	uint8_t read(uint16_t adr) { return mintf->read(adr); }
	uint8_t read_9(uint16_t adr) { return mintf->read_9(adr); }
	void write(uint16_t adr, uint8_t val) { mintf->write(adr, val); }
	void write_9(uint16_t adr, uint8_t val) { mintf->write_9(adr, val); }
	uint8_t read_arg(uint16_t adr) { return mintf->read_arg(adr); }
	uint8_t read_pc() { return mintf->read_arg(PC++); }
	uint8_t read_pc_noinc() { return mintf->read_arg(PC); }
	void prefetch();
	void prefetch_noirq();
	void set_nz(uint8_t v);

	u32 XPC;
	virtual offs_t pc_to_external(u16 pc); // For paged PCs
	virtual void do_exec_full();
	virtual void do_exec_partial();

	// inline helpers
	static inline bool page_changing(uint16_t base, int delta) { return ((base + delta) ^ base) & 0xff00; }
	static inline uint16_t set_l(uint16_t base, uint8_t val) { return (base & 0xff00) | val; }
	static inline uint16_t set_h(uint16_t base, uint8_t val) { return (base & 0x00ff) | (val << 8); }

	inline void dec_SP() { SP = set_l(SP, SP-1); }
	inline void inc_SP() { SP = set_l(SP, SP+1); }

	void do_adc_d(uint8_t val);
	void do_adc_nd(uint8_t val);
	void do_sbc_d(uint8_t val);
	void do_sbc_nd(uint8_t val);
	void do_arr_d();
	void do_arr_nd();

	void do_adc(uint8_t val);
	void do_cmp(uint8_t val1, uint8_t val2);
	void do_sbc(uint8_t val);
	void do_bit(uint8_t val);
	void do_arr();
	uint8_t do_asl(uint8_t v);
	uint8_t do_lsr(uint8_t v);
	uint8_t do_ror(uint8_t v);
	uint8_t do_rol(uint8_t v);
	uint8_t do_asr(uint8_t v);

#define O(o) void o ## _full(); void o ## _partial()

	// NMOS 6502 opcodes
	//   documented opcodes
	O(adc_aba); O(adc_abx); O(adc_aby); O(adc_idx); O(adc_idy); O(adc_imm); O(adc_zpg); O(adc_zpx);
	O(and_aba); O(and_abx); O(and_aby); O(and_imm); O(and_idx); O(and_idy); O(and_zpg); O(and_zpx);
	O(asl_aba); O(asl_abx); O(asl_acc); O(asl_zpg); O(asl_zpx);
	O(bcc_rel);
	O(bcs_rel);
	O(beq_rel);
	O(bit_aba); O(bit_zpg);
	O(bmi_rel);
	O(bne_rel);
	O(bpl_rel);
	O(brk_imp);
	O(bvc_rel);
	O(bvs_rel);
	O(clc_imp);
	O(cld_imp);
	O(cli_imp);
	O(clv_imp);
	O(cmp_aba); O(cmp_abx); O(cmp_aby); O(cmp_idx); O(cmp_idy); O(cmp_imm); O(cmp_zpg); O(cmp_zpx);
	O(cpx_aba); O(cpx_imm); O(cpx_zpg);
	O(cpy_aba); O(cpy_imm); O(cpy_zpg);
	O(dec_aba); O(dec_abx); O(dec_zpg); O(dec_zpx);
	O(dex_imp);
	O(dey_imp);
	O(eor_aba); O(eor_abx); O(eor_aby); O(eor_idx); O(eor_idy); O(eor_imm); O(eor_zpg); O(eor_zpx);
	O(inc_aba); O(inc_abx); O(inc_zpg); O(inc_zpx);
	O(inx_imp);
	O(iny_imp);
	O(jmp_adr); O(jmp_ind);
	O(jsr_adr);
	O(lda_aba); O(lda_abx); O(lda_aby); O(lda_idx); O(lda_idy); O(lda_imm); O(lda_zpg); O(lda_zpx);
	O(ldx_aba); O(ldx_aby); O(ldx_imm); O(ldx_zpg); O(ldx_zpy);
	O(ldy_aba); O(ldy_abx); O(ldy_imm); O(ldy_zpg); O(ldy_zpx);
	O(lsr_aba); O(lsr_abx); O(lsr_acc); O(lsr_zpg); O(lsr_zpx);
	O(nop_imp);
	O(ora_aba); O(ora_abx); O(ora_aby); O(ora_imm); O(ora_idx); O(ora_idy); O(ora_zpg); O(ora_zpx);
	O(pha_imp);
	O(php_imp);
	O(pla_imp);
	O(plp_imp);
	O(rol_aba); O(rol_abx); O(rol_acc); O(rol_zpg); O(rol_zpx);
	O(ror_aba); O(ror_abx); O(ror_acc); O(ror_zpg); O(ror_zpx);
	O(rti_imp);
	O(rts_imp);
	O(sbc_aba); O(sbc_abx); O(sbc_aby); O(sbc_idx); O(sbc_idy); O(sbc_imm); O(sbc_zpg); O(sbc_zpx);
	O(sec_imp);
	O(sed_imp);
	O(sei_imp);
	O(sta_aba); O(sta_abx); O(sta_aby); O(sta_idx); O(sta_idy); O(sta_zpg); O(sta_zpx);
	O(stx_aba); O(stx_zpg); O(stx_zpy);
	O(sty_aba); O(sty_zpg); O(sty_zpx);
	O(tax_imp);
	O(tay_imp);
	O(tsx_imp);
	O(txa_imp);
	O(txs_imp);
	O(tya_imp);

	//   exceptions
	O(reset);

	//   undocumented reliable instructions
	O(dcp_aba); O(dcp_abx); O(dcp_aby); O(dcp_idx); O(dcp_idy); O(dcp_zpg); O(dcp_zpx);
	O(isb_aba); O(isb_abx); O(isb_aby); O(isb_idx); O(isb_idy); O(isb_zpg); O(isb_zpx);
	O(lax_aba); O(lax_aby); O(lax_idx); O(lax_idy); O(lax_zpg); O(lax_zpy);
	O(rla_aba); O(rla_abx); O(rla_aby); O(rla_idx); O(rla_idy); O(rla_zpg); O(rla_zpx);
	O(rra_aba); O(rra_abx); O(rra_aby); O(rra_idx); O(rra_idy); O(rra_zpg); O(rra_zpx);
	O(sax_aba); O(sax_idx); O(sax_zpg); O(sax_zpy);
	O(sbx_imm);
	O(sha_aby); O(sha_idy);
	O(shs_aby);
	O(shx_aby);
	O(shy_abx);
	O(slo_aba); O(slo_abx); O(slo_aby); O(slo_idx); O(slo_idy); O(slo_zpg); O(slo_zpx);
	O(sre_aba); O(sre_abx); O(sre_aby); O(sre_idx); O(sre_idy); O(sre_zpg); O(sre_zpx);

	//   undocumented unreliable instructions
	//     behaviour differs between visual6502 and online docs, which
	//     is a clear sign reliability is not to be expected
	//     implemented version follows visual6502
	O(anc_imm);
	O(ane_imm);
	O(arr_imm);
	O(asr_imm);
	O(las_aby);
	O(lxa_imm);

	//   nop variants
	O(nop_imm); O(nop_aba); O(nop_abx); O(nop_zpg); O(nop_zpx);

	//   system killers
	O(kil_non);

#undef O
};

enum {
	M6502_PC = 1,
	M6502_A,
	M6502_X,
	M6502_Y,
	M6502_P,
	M6502_S,
	M6502_IR
};

enum {
	M6502_IRQ_LINE = m6502_device::IRQ_LINE,
	M6502_NMI_LINE = m6502_device::NMI_LINE,
	M6502_SET_OVERFLOW = m6502_device::V_LINE
};

DECLARE_DEVICE_TYPE(M6502, m6502_device)

#endif // MAME_CPU_M6502_M6502_H