ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/cpu.cpp
Revision: 1.4
Committed: 2003-10-21T16:56:19Z (21 years, 1 month ago) by cebix
Branch: MAIN
Changes since 1.3: +2 -2 lines
Log Message:
- play_adr is updated from the IRQ vector every time before the replay routine
  is called if it was 0 in the PSID header (this makes some tunes play
  correctly now)
- f(void) -> f() (this is C++, dammit!)

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * cpu.cpp - 6510 CPU emulation
3     *
4 cebix 1.3 * SIDPlayer (C) Copyright 1996-2003 Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sys.h"
22    
23     #include "mem.h"
24     #include "sid.h"
25    
26     #define DEBUG 0
27     #include "debug.h"
28    
29    
30     // Memory access functions
31     typedef uint32 (*mem_read_func)(uint32, cycle_t);
32     typedef void (*mem_write_func)(uint32, uint32, cycle_t, bool);
33    
34     static mem_read_func mem_read_table[256]; // Table of read/write functions for 256 pages
35     static mem_write_func mem_write_table[256];
36    
37    
38     // Memory access function prototypes
39     static uint32 ram_read(uint32 adr, cycle_t now);
40     static void ram_write(uint32 adr, uint32 byte, cycle_t now, bool rmw);
41     static void cia_write(uint32 adr, uint32 byte, cycle_t now, bool rmw);
42    
43    
44     /*
45     * Init CPU emulation
46     */
47    
48     static void set_memory_funcs(uint16 from, uint16 to, mem_read_func r, mem_write_func w)
49     {
50     for (int page = (from >> 8); page <= (to >> 8); page++) {
51     mem_read_table[page] = r;
52     mem_write_table[page] = w;
53     }
54     }
55    
56 cebix 1.4 void CPUInit()
57 cebix 1.1 {
58     // Set up memory access tables
59     set_memory_funcs(0x0000, 0xffff, ram_read, ram_write);
60     set_memory_funcs(0xd400, 0xd7ff, sid_read, sid_write);
61     set_memory_funcs(0xdc00, 0xdcff, ram_read, cia_write);
62     }
63    
64    
65     /*
66     * Exit CPU emulation
67     */
68    
69 cebix 1.4 void CPUExit()
70 cebix 1.1 {
71     }
72    
73    
74     /*
75     * Memory access functions
76     */
77    
78     static uint32 ram_read(uint32 adr, cycle_t now)
79     {
80     return ram[adr];
81     }
82    
83     static void ram_write(uint32 adr, uint32 byte, cycle_t now, bool rmw)
84     {
85     ram[adr] = byte;
86     }
87    
88     static void cia_write(uint32 adr, uint32 byte, cycle_t now, bool rmw)
89     {
90     if (adr == 0xdc04)
91     cia_tl_write(byte);
92     else if (adr == 0xdc05)
93     cia_th_write(byte);
94     else
95     ram[adr] = byte;
96     }
97    
98    
99     /*
100     * CPU emulation loop
101     */
102    
103     void CPUExecute(uint16 startadr, uint8 init_ra, uint8 init_rx, uint8 init_ry, cycle_t max_cycles)
104     {
105     // 6510 registers
106     register uint8 a = init_ra, x = init_rx, y = init_ry;
107     register uint8 n_flag = 0, z_flag = 0;
108     uint8 sp = 0xff, pflags = 0;
109    
110     // Program counter
111     register uint8 *pc;
112    
113     // Temporary address storage
114     uint16 adr;
115    
116     // Phi 2 cycle counter
117     register cycle_t current_cycle = 0;
118    
119     // Flag: last branch instruction delays IRQ/NMI by 1 cycle (unused)
120     bool branch_delays_int = false;
121    
122     #define RA a
123     #define RX x
124     #define RY y
125     #define RSP sp
126     #define RPC (pc - ram)
127     #define N_FLAG n_flag
128     #define Z_FLAG z_flag
129     #define PFLAGS pflags
130     #define ADR adr
131    
132     #define read_byte(adr) \
133     mem_read_table[(adr) >> 8](adr, current_cycle)
134     #define read_zp(adr) \
135     ram[adr]
136    
137     #define write_byte(adr, byte) \
138     mem_write_table[(adr) >> 8](adr, byte, current_cycle, false)
139     #define write_byte_rmw(adr, byte) \
140     mem_write_table[(adr) >> 8](adr, byte, current_cycle, true)
141     #define write_zp(adr, byte) \
142     ram[adr] = (byte)
143    
144     #define read_idle(adr)
145     #define read_idle_zp(adr)
146     #define read_idle_stack(sp)
147    
148     #define read_opcode \
149     (*pc)
150     #define read_idle_opcode
151    
152     #define push_byte(byte) \
153     { \
154     if (sp == 0) \
155     quit = true; \
156     (ram + 0x100)[sp--] = (byte); \
157     }
158     #define pop_byte \
159     (sp == 0xff ? (quit = true, 0) : (ram + 0x100)[++sp])
160    
161     #define jump(adr) \
162     pc = ram + (adr)
163     #define inc_pc \
164     pc++
165    
166     #define next_cycle \
167     current_cycle++
168    
169     #include "cpu_macros.h"
170    
171     // Jump to specified start address
172     jump(startadr);
173    
174     // Main loop: execute opcodes until stack under-/overflow, RTI, illegal opcode, or max_cycles reached
175     bool quit = false;
176     while (current_cycle < max_cycles && !quit) {
177    
178     // Fetch opcode
179     uint8 opcode = read_opcode; inc_pc; next_cycle;
180    
181     // Execute opcode
182     switch (opcode) {
183     #include "cpu_opcodes.h"
184     case 0xf2:
185     default:
186     illegal_op: quit = true;
187     break;
188     }
189     }
190     }