1 /* CPU emulation loop and memory access
3 * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #define IOMASK 0xfffff000
30 #define IOBASE 0x00dff000
32 static uint8_t *memory = NULL;
33 static uint32_t memory_size = 0;
34 static uint16_t *chipreg = NULL;
36 static uint16_t read_io(unsigned int address)
39 printf("Chip read from 0x%08x\n", address);
41 return emulate_io_read(address);
44 static void write_io(unsigned int address, uint16_t value)
47 printf("Chip write to 0x%08x\n", address);
49 if ((address & IOMASK) == IOBASE)
50 chipreg[address & ~IOMASK] = value;
51 emulate_io_write(address, value);
54 unsigned int m68k_read_memory_8(unsigned int address)
56 if (address > memory_size - 1) {
58 /* read lower (right) byte */
59 return read_io(address & ~1);
61 /* read upper (left) byte */
62 return read_io(address) >> 8;
65 return *((uint8_t *)(memory + address));
68 unsigned int m68k_read_memory_16(unsigned int address)
70 if (address > memory_size - 2) {
71 return read_io(address);
73 return (memory[address] << 8) |
77 unsigned int m68k_read_memory_32(unsigned int address)
79 if (address > memory_size - 4) {
81 value = read_io(address) << 16;
82 value |= read_io(address + 2);
85 return (memory[address] << 24)|
86 (memory[address + 1] << 16) |
87 (memory[address + 2] << 8) |
91 void m68k_write_memory_8(unsigned int address, unsigned int value)
93 if (address > memory_size - 1) {
95 /* write lower (right) byte */
96 write_io(address & ~1, 0xff00 | value);
98 /* write upper (left) byte */
99 write_io(address, 0x00ff | (value << 8));
103 *((uint8_t *)(memory + address)) = value;
106 void m68k_write_memory_16(unsigned int address, unsigned int value)
108 if (address > memory_size - 2) {
109 write_io(address, value);
112 memory[address] = value >> 8;
113 memory[address + 1] = value;
116 void m68k_write_memory_32(unsigned int address, unsigned int value)
118 if (address > memory_size - 4) {
119 write_io(address, value >> 16);
120 write_io(address + 2, value);
123 memory[address] = value >> 24;
124 memory[address + 1] = value >> 16;
125 memory[address + 2] = value >> 8;
126 memory[address + 3] = value;
129 void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg)
131 memory_size = _memory_size;
137 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
145 int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event)
148 int instruction_count = 0;
155 /* loop until we returned from interrupt */
157 /* execute one opcode */
158 cycle_count += m68k_execute(0);
160 } while (REG_PC != save_pc);
162 printf("interrupt %d took %d opcodes\n", irq, instruction_count);
166 /* execute one opcode */
167 cycle_count += m68k_execute(0);
170 /* checking if game does not hit any 'stop_at' break point, give error output */
171 if (instruction_count >= 10000000) {
172 if (instruction_count == 10000000)
173 fprintf(stderr, "!!! games seems to got stuck in an endless loop, please fix !!!\n");
174 fprintf(stderr, "program counter at: %06x\n", REG_PC);
175 if (instruction_count == 10000020)
179 for (i = 0; stop_at[i].event; i++) {
180 if (REG_PC == stop_at[i].pc) {
182 printf("execution to address 0x%06x took %d opcodes\n", REG_PC, instruction_count);
184 *event = stop_at[i].event;