Skip to content

Commit 9460ef4

Browse files
committed
Uploaded_3_22_2020
1 parent a3ad721 commit 9460ef4

File tree

3 files changed

+234
-6
lines changed

3 files changed

+234
-6
lines changed

MCL65/MCL65_C_Version/mcl65.c

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
//
2+
//
3+
// File Name : MCL65.c
4+
// Used on :
5+
// Author : Ted Fried, MicroCore Labs
6+
// Creation : 3/22/2020
7+
// Code Type : C code
8+
//
9+
// Description:
10+
// ============
11+
//
12+
// C Code emulating the MCL65 Microsequencer of the MOS 6502 microprocessor
13+
// This is a C version of the MCL65 which is written in Verilog. It runs the
14+
// exact same microcode. NMI and Interrupts are suppored.
15+
// Each loop of the code below is equivalent to one microsequencer clock
16+
// and will execute a new micro-instruction each time.
17+
// The user code and data RAM are held in a 64KB array.
18+
//
19+
//------------------------------------------------------------------------
20+
//
21+
// Modification History:
22+
// =====================
23+
//
24+
// Revision 1 3/22/2020
25+
// Initial revision
26+
//
27+
//
28+
//------------------------------------------------------------------------
29+
//
30+
// Copyright (c) 2020 Ted Fried
31+
//
32+
// Permission is hereby granted, free of charge, to any person obtaining a copy
33+
// of this software and associated documentation files (the "Software"), to deal
34+
// in the Software without restriction, including without limitation the rights
35+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36+
// copies of the Software, and to permit persons to whom the Software is
37+
// furnished to do so, subject to the following conditions:
38+
//
39+
// The above copyright notice and this permission notice shall be included in all
40+
// copies or substantial portions of the Software.
41+
//
42+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
48+
// SOFTWARE.
49+
//
50+
//------------------------------------------------------------------------
51+
52+
#include <stdio.h>
53+
#include "mcl65.h"
54+
55+
#define rdwr_n ( system_output & 0x1 ) >> 0 // system_output[0]
56+
#define flag_i ( register_flags & 0x04 ) >> 2 // register_flags[2]
57+
#define opcode_type ( rom_data & 0xF0000000 ) >> 28 // rom_data[30:28];
58+
#define opcode_dst_sel ( rom_data & 0x0F000000 ) >> 24 // rom_data[27:24];
59+
#define opcode_op0_sel ( rom_data & 0x00F00000 ) >> 20 // rom_data[23:20];
60+
#define opcode_op1_sel ( rom_data & 0x000F0000 ) >> 16 // rom_data[19:16];
61+
#define opcode_immediate ( rom_data & 0x0000FFFF ) >> 00 // rom_data[15:0];
62+
#define opcode_jump_call ( rom_data & 0x01000000 ) >> 24 // rom_data[24];
63+
#define opcode_jump_src ( rom_data & 0x00700000 ) >> 20 // rom_data[22:20];
64+
#define opcode_jump_cond ( rom_data & 0x000F0000 ) >> 16 // rom_data[16:19];
65+
66+
67+
unsigned char attached_memory[65536]={ };
68+
unsigned char register_flags=0;
69+
unsigned char add_carry7=0;
70+
unsigned char add_carry8=0;
71+
unsigned char nmi_asserted=0;
72+
unsigned char irq_gated=0;
73+
unsigned char add_overflow8=0;
74+
unsigned char nmi_debounce=0;
75+
unsigned char system_status=0;
76+
unsigned char register_a=0;
77+
unsigned char register_x=0;
78+
unsigned char register_y=0;
79+
unsigned short int register_r0=0;
80+
unsigned short int register_r1=0;
81+
unsigned short int register_r2=0;
82+
unsigned short int register_r3=0;
83+
unsigned short int register_pc=0x400;
84+
unsigned short int register_sp=0;
85+
unsigned short int address_out=0;
86+
unsigned short int data_in=0;
87+
unsigned short int data_out=0;
88+
unsigned short int system_output=0;
89+
unsigned short int alu_last_result=0;
90+
unsigned short int alu_out=0;
91+
unsigned short int rom_address=0x07D0; // Address for Microcode Reset procedure
92+
unsigned short int operand0=0;
93+
unsigned short int operand1=0;
94+
unsigned long rom_data;
95+
unsigned long calling_address;
96+
97+
98+
// Main loop
99+
//
100+
int main()
101+
{
102+
while (1)
103+
{
104+
// Optional INT and NMI Signals
105+
// irq_gated = P6502_IRQ_n & ~flag_i;
106+
// if (nmi_debounce==1) nmi_asserted=0; else if (P6502_NMI_n_old==1 && P6502_NMI_n==0) nmi_asserted=1; P6502_NMI_n_old = P6502_NMI_n;
107+
108+
data_in = attached_memory[address_out]; // Read data from the Attached Memory RAM
109+
110+
rom_data = microcode_rom[rom_address]; // Fetch the next microcode instruction
111+
112+
system_status = ( add_carry8 << 0 | // system_status[0]
113+
nmi_asserted << 3 | // system_status[3]
114+
irq_gated << 5 | // system_status[5]
115+
add_overflow8 << 6 ); // system_status[6]
116+
117+
118+
switch (opcode_op0_sel)
119+
{
120+
case 0x0: operand0 = register_r0; break;
121+
case 0x1: operand0 = register_r1; break;
122+
case 0x2: operand0 = register_r2; break;
123+
case 0x3: operand0 = register_r3; break;
124+
case 0x4: operand0 = register_a & 0x00FF; break;
125+
case 0x5: operand0 = register_x & 0x00FF; break;
126+
case 0x6: operand0 = register_y & 0x00FF; break;
127+
case 0x7: operand0 = register_pc; break;
128+
case 0x8: operand0 = ((register_sp & 0x00FF) | 0x0100); break;
129+
case 0x9: operand0 = register_flags & 0x00FF; break;
130+
case 0xA: operand0 = address_out; break;
131+
case 0xB: operand0 = ((data_in&0xFF) << 8) | (data_in&0xFF); break;
132+
case 0xC: operand0 = system_status; break;
133+
case 0xD: operand0 = system_output; break;
134+
case 0xE: operand0 = 0; break;
135+
case 0xF: operand0 = 0; break;
136+
}
137+
138+
139+
switch (opcode_op1_sel)
140+
{
141+
case 0x0: operand1 = register_r0; break;
142+
case 0x1: operand1 = register_r1; break;
143+
case 0x2: operand1 = register_r2; break;
144+
case 0x3: operand1 = register_r3; break;
145+
case 0x4: operand1 = register_a & 0x00FF; break;
146+
case 0x5: operand1 = register_x & 0x00FF; break;
147+
case 0x6: operand1 = register_y & 0x00FF; break;
148+
case 0x7: operand1 = ( (register_pc<<8) | (register_pc>>8) ) ; break;
149+
case 0x8: operand1 = ((register_sp & 0x00FF) | 0x0100); break;
150+
case 0x9: operand1 = register_flags & 0x00FF; break;
151+
case 0xA: operand1 = address_out; break;
152+
case 0xB: operand1 =( ( data_in << 8) | data_in); break;
153+
case 0xC: operand1 = system_status; break;
154+
case 0xD: operand1 = system_output; break;
155+
case 0xE: operand1 = 0; break;
156+
case 0xF: operand1 = opcode_immediate; break;
157+
}
158+
159+
160+
switch (opcode_type)
161+
{
162+
case 0x2: // ADD
163+
alu_out = operand0 + operand1;
164+
add_carry7 = (( ((operand0&0x007F) + (operand1&0x007F)) & 0x0080) >> 7);
165+
add_carry8 = (( ((operand0&0x00FF) + (operand1&0x00FF)) & 0x0100) >> 8);
166+
add_overflow8 = (add_carry7 ^ add_carry8) & 0x1;
167+
break;
168+
case 0x3: alu_out = operand0 & operand1; break; // AND
169+
case 0x4: alu_out = operand0 | operand1; break; // OR
170+
case 0x5: alu_out = operand0 ^ operand1; break; // XOR
171+
case 0x6: alu_out = operand0 >> 1; break; // SHR
172+
default: alu_out = 0xEEEE; break;
173+
}
174+
175+
176+
// Register write-back
177+
if (opcode_type > 1)
178+
{
179+
alu_last_result = alu_out;
180+
switch (opcode_dst_sel)
181+
{
182+
case 0x0: register_r0 = alu_out; break;
183+
case 0x1: register_r1 = alu_out; break;
184+
case 0x2: register_r2 = alu_out; break;
185+
case 0x3: register_r3 = alu_out; break;
186+
case 0x4: register_a = alu_out & 0x00FF; break;
187+
case 0x5: register_x = alu_out & 0x00FF; break;
188+
case 0x6: register_y = alu_out & 0x00FF; break;
189+
case 0x7: register_pc = alu_out; break;
190+
case 0x8: register_sp = alu_out & 0x00FF; break;
191+
case 0x9: register_flags = alu_out | 0x30; break;
192+
case 0xA: address_out = alu_out; break;
193+
case 0xB: data_out = alu_out & 0x00FF; break;
194+
case 0xD: system_output = alu_out & 0x001F; break;
195+
default: break;
196+
}
197+
}
198+
199+
200+
// JUMP Opcode
201+
if ( ( opcode_type==0x1 && opcode_jump_cond==0x0 ) || // Unconditional jump
202+
( opcode_type==0x1 && opcode_jump_cond==0x1 && alu_last_result!=0 ) || // Jump Not Zero
203+
( opcode_type==0x1 && opcode_jump_cond==0x2 && alu_last_result==0 ) ) // Jump Zero
204+
{
205+
// For subroutine CALLs, store next opcode address
206+
if (opcode_jump_call==1)
207+
calling_address = (calling_address<<11) | (rom_address&0x07FF) ;
208+
209+
switch (opcode_jump_src)
210+
{
211+
case 0x0: rom_address = opcode_immediate & 0x07FF; break;
212+
case 0x1: rom_address = data_in & 0x00FF; break; // Opcode Jump Table
213+
case 0x2: rom_address = (calling_address & 0x07FF) + 1;
214+
calling_address = calling_address>>11;
215+
break;
216+
}
217+
}
218+
else
219+
rom_address = rom_address + 1;
220+
221+
222+
// Writes to the 6502 Data RAM occur on the simulated rising edge of the clock
223+
if (opcode_type==0x1 && opcode_jump_cond==0x3 && rdwr_n==0) attached_memory[address_out] = data_out;
224+
}
225+
}
226+

0 commit comments

Comments
 (0)