Uploaded_3_22_2020

This commit is contained in:
MicroCoreLabs 2020-03-22 22:35:52 -07:00
parent a3ad7214a4
commit 9460ef4da9
3 changed files with 234 additions and 6 deletions

View File

@ -0,0 +1,226 @@
//
//
// File Name : MCL65.c
// Used on :
// Author : Ted Fried, MicroCore Labs
// Creation : 3/22/2020
// Code Type : C code
//
// Description:
// ============
//
// C Code emulating the MCL65 Microsequencer of the MOS 6502 microprocessor
// This is a C version of the MCL65 which is written in Verilog. It runs the
// exact same microcode. NMI and Interrupts are suppored.
// Each loop of the code below is equivalent to one microsequencer clock
// and will execute a new micro-instruction each time.
// The user code and data RAM are held in a 64KB array.
//
//------------------------------------------------------------------------
//
// Modification History:
// =====================
//
// Revision 1 3/22/2020
// Initial revision
//
//
//------------------------------------------------------------------------
//
// Copyright (c) 2020 Ted Fried
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//------------------------------------------------------------------------
#include <stdio.h>
#include "mcl65.h"
#define rdwr_n ( system_output & 0x1 ) >> 0 // system_output[0]
#define flag_i ( register_flags & 0x04 ) >> 2 // register_flags[2]
#define opcode_type ( rom_data & 0xF0000000 ) >> 28 // rom_data[30:28];
#define opcode_dst_sel ( rom_data & 0x0F000000 ) >> 24 // rom_data[27:24];
#define opcode_op0_sel ( rom_data & 0x00F00000 ) >> 20 // rom_data[23:20];
#define opcode_op1_sel ( rom_data & 0x000F0000 ) >> 16 // rom_data[19:16];
#define opcode_immediate ( rom_data & 0x0000FFFF ) >> 00 // rom_data[15:0];
#define opcode_jump_call ( rom_data & 0x01000000 ) >> 24 // rom_data[24];
#define opcode_jump_src ( rom_data & 0x00700000 ) >> 20 // rom_data[22:20];
#define opcode_jump_cond ( rom_data & 0x000F0000 ) >> 16 // rom_data[16:19];
unsigned char attached_memory[65536]={ };
unsigned char register_flags=0;
unsigned char add_carry7=0;
unsigned char add_carry8=0;
unsigned char nmi_asserted=0;
unsigned char irq_gated=0;
unsigned char add_overflow8=0;
unsigned char nmi_debounce=0;
unsigned char system_status=0;
unsigned char register_a=0;
unsigned char register_x=0;
unsigned char register_y=0;
unsigned short int register_r0=0;
unsigned short int register_r1=0;
unsigned short int register_r2=0;
unsigned short int register_r3=0;
unsigned short int register_pc=0x400;
unsigned short int register_sp=0;
unsigned short int address_out=0;
unsigned short int data_in=0;
unsigned short int data_out=0;
unsigned short int system_output=0;
unsigned short int alu_last_result=0;
unsigned short int alu_out=0;
unsigned short int rom_address=0x07D0; // Address for Microcode Reset procedure
unsigned short int operand0=0;
unsigned short int operand1=0;
unsigned long rom_data;
unsigned long calling_address;
// Main loop
//
int main()
{
while (1)
{
// Optional INT and NMI Signals
// irq_gated = P6502_IRQ_n & ~flag_i;
// 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;
data_in = attached_memory[address_out]; // Read data from the Attached Memory RAM
rom_data = microcode_rom[rom_address]; // Fetch the next microcode instruction
system_status = ( add_carry8 << 0 | // system_status[0]
nmi_asserted << 3 | // system_status[3]
irq_gated << 5 | // system_status[5]
add_overflow8 << 6 ); // system_status[6]
switch (opcode_op0_sel)
{
case 0x0: operand0 = register_r0; break;
case 0x1: operand0 = register_r1; break;
case 0x2: operand0 = register_r2; break;
case 0x3: operand0 = register_r3; break;
case 0x4: operand0 = register_a & 0x00FF; break;
case 0x5: operand0 = register_x & 0x00FF; break;
case 0x6: operand0 = register_y & 0x00FF; break;
case 0x7: operand0 = register_pc; break;
case 0x8: operand0 = ((register_sp & 0x00FF) | 0x0100); break;
case 0x9: operand0 = register_flags & 0x00FF; break;
case 0xA: operand0 = address_out; break;
case 0xB: operand0 = ((data_in&0xFF) << 8) | (data_in&0xFF); break;
case 0xC: operand0 = system_status; break;
case 0xD: operand0 = system_output; break;
case 0xE: operand0 = 0; break;
case 0xF: operand0 = 0; break;
}
switch (opcode_op1_sel)
{
case 0x0: operand1 = register_r0; break;
case 0x1: operand1 = register_r1; break;
case 0x2: operand1 = register_r2; break;
case 0x3: operand1 = register_r3; break;
case 0x4: operand1 = register_a & 0x00FF; break;
case 0x5: operand1 = register_x & 0x00FF; break;
case 0x6: operand1 = register_y & 0x00FF; break;
case 0x7: operand1 = ( (register_pc<<8) | (register_pc>>8) ) ; break;
case 0x8: operand1 = ((register_sp & 0x00FF) | 0x0100); break;
case 0x9: operand1 = register_flags & 0x00FF; break;
case 0xA: operand1 = address_out; break;
case 0xB: operand1 =( ( data_in << 8) | data_in); break;
case 0xC: operand1 = system_status; break;
case 0xD: operand1 = system_output; break;
case 0xE: operand1 = 0; break;
case 0xF: operand1 = opcode_immediate; break;
}
switch (opcode_type)
{
case 0x2: // ADD
alu_out = operand0 + operand1;
add_carry7 = (( ((operand0&0x007F) + (operand1&0x007F)) & 0x0080) >> 7);
add_carry8 = (( ((operand0&0x00FF) + (operand1&0x00FF)) & 0x0100) >> 8);
add_overflow8 = (add_carry7 ^ add_carry8) & 0x1;
break;
case 0x3: alu_out = operand0 & operand1; break; // AND
case 0x4: alu_out = operand0 | operand1; break; // OR
case 0x5: alu_out = operand0 ^ operand1; break; // XOR
case 0x6: alu_out = operand0 >> 1; break; // SHR
default: alu_out = 0xEEEE; break;
}
// Register write-back
if (opcode_type > 1)
{
alu_last_result = alu_out;
switch (opcode_dst_sel)
{
case 0x0: register_r0 = alu_out; break;
case 0x1: register_r1 = alu_out; break;
case 0x2: register_r2 = alu_out; break;
case 0x3: register_r3 = alu_out; break;
case 0x4: register_a = alu_out & 0x00FF; break;
case 0x5: register_x = alu_out & 0x00FF; break;
case 0x6: register_y = alu_out & 0x00FF; break;
case 0x7: register_pc = alu_out; break;
case 0x8: register_sp = alu_out & 0x00FF; break;
case 0x9: register_flags = alu_out | 0x30; break;
case 0xA: address_out = alu_out; break;
case 0xB: data_out = alu_out & 0x00FF; break;
case 0xD: system_output = alu_out & 0x001F; break;
default: break;
}
}
// JUMP Opcode
if ( ( opcode_type==0x1 && opcode_jump_cond==0x0 ) || // Unconditional jump
( opcode_type==0x1 && opcode_jump_cond==0x1 && alu_last_result!=0 ) || // Jump Not Zero
( opcode_type==0x1 && opcode_jump_cond==0x2 && alu_last_result==0 ) ) // Jump Zero
{
// For subroutine CALLs, store next opcode address
if (opcode_jump_call==1)
calling_address = (calling_address<<11) | (rom_address&0x07FF) ;
switch (opcode_jump_src)
{
case 0x0: rom_address = opcode_immediate & 0x07FF; break;
case 0x1: rom_address = data_in & 0x00FF; break; // Opcode Jump Table
case 0x2: rom_address = (calling_address & 0x07FF) + 1;
calling_address = calling_address>>11;
break;
}
}
else
rom_address = rom_address + 1;
// Writes to the 6502 Data RAM occur on the simulated rising edge of the clock
if (opcode_type==0x1 && opcode_jump_cond==0x3 && rdwr_n==0) attached_memory[address_out] = data_out;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
# Ted Fried's MicroCore Labs Projects
My blog which has some details on these projects: MicroCoreLabs.Wordpress.com
My blog which has some details on these projects: www.MicroCoreLabs.Wordpress.com
My YouTube Channel with some videos of the stuff in action: www.youtube.com/channel/UC9B3TaEUon-araO2j7tp9jg/videos
@ -9,20 +9,21 @@ My YouTube Channel with some videos of the stuff in action: www.youtube.com/chan
Microsequencer-based processors:
MCL65 - MOS 6502
- C Version as well
MCL51 - Intel 8051
MCL86 - Intel 8086/8088
Other processors:
MCLR5 - Quad-Issue Superscalar RISCV
Lockstep Quad Modular Redundant System
Lockstep Quad Modular Redundant System
Misc:
Wheelwriter - FPGA based Printer Option for the IBM Wheelwriter 5
Wheelwriter2 - Arduino Leonardo based Printer Option for the IBM Wheelwriter 5
For questions email me at www.MicroCoreLabs.com