created sicxe emulator project
This commit is contained in:
parent
cb38efe586
commit
3332b2971b
18 changed files with 1051 additions and 0 deletions
95
simulator_SIC_XE/.gitignore
vendored
Normal file
95
simulator_SIC_XE/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
# Build directories
|
||||||
|
build/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# CMake generated files
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
CMakeScripts/
|
||||||
|
cmake_install.cmake
|
||||||
|
Makefile
|
||||||
|
*.cmake
|
||||||
|
!CMakeLists.txt
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
# CLion
|
||||||
|
.idea/
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
*.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
*.xcuserstate
|
||||||
|
project.xcworkspace/
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
# Qt Creator
|
||||||
|
*.pro.user
|
||||||
|
*.pro.user.*
|
||||||
|
*.qbs.user
|
||||||
|
*.qbs.user.*
|
||||||
|
*.moc
|
||||||
|
*.moc.cpp
|
||||||
|
*.qm
|
||||||
|
*.prl
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Core dumps
|
||||||
|
core
|
||||||
45
simulator_SIC_XE/CMakeLists.txt
Normal file
45
simulator_SIC_XE/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(simulator_SIC_XE VERSION 1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Put all build outputs under target/bin as requested
|
||||||
|
set(OUTPUT_DIR ${CMAKE_SOURCE_DIR}/target/bin)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||||
|
|
||||||
|
# Collect all .cpp sources under src/
|
||||||
|
file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")
|
||||||
|
|
||||||
|
if(NOT SOURCES)
|
||||||
|
message(WARNING "No source files found in ${PROJECT_SOURCE_DIR}/src — the build will create an empty library")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build a static library from all sources
|
||||||
|
add_library(simulator_lib STATIC ${SOURCES})
|
||||||
|
target_include_directories(simulator_lib PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
set_target_properties(simulator_lib PROPERTIES OUTPUT_NAME "simulator")
|
||||||
|
|
||||||
|
# If a main.cpp exists, create an executable that links the library.
|
||||||
|
if(EXISTS "${PROJECT_SOURCE_DIR}/src/main.cpp")
|
||||||
|
add_executable(simulator_exec "${PROJECT_SOURCE_DIR}/src/main.cpp")
|
||||||
|
target_link_libraries(simulator_exec PRIVATE simulator_lib)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Convenience target: `cmake --build build --target run`
|
||||||
|
# This target will build `simulator_exec` (if present) and then execute it.
|
||||||
|
if(TARGET simulator_exec)
|
||||||
|
add_custom_target(run
|
||||||
|
DEPENDS simulator_exec
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "Running simulator_exec..."
|
||||||
|
COMMAND $<TARGET_FILE:simulator_exec>
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
COMMENT "Builds and runs simulator_exec"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Project: ${PROJECT_NAME}")
|
||||||
|
message(STATUS "Sources found: ${SOURCES}")
|
||||||
|
message(STATUS "Output directory: ${OUTPUT_DIR}")
|
||||||
52
simulator_SIC_XE/README.md
Normal file
52
simulator_SIC_XE/README.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# SIC/XE Simulator
|
||||||
|
|
||||||
|
A complete SIC/XE architecture simulator with instruction execution, device I/O, and memory management.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
The easiest way to build and run the simulator:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make run
|
||||||
|
```
|
||||||
|
|
||||||
|
This single command will:
|
||||||
|
- Configure the build system (if needed)
|
||||||
|
- Compile all source files
|
||||||
|
- Link the executable
|
||||||
|
- Run the simulator
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `make` | Build the project |
|
||||||
|
| `make run` | Build and run the simulator |
|
||||||
|
| `make clean` | Clean build artifacts |
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
simulator_SIC_XE/
|
||||||
|
├── include/ # Header files (.h)
|
||||||
|
├── src/ # Source files (.cpp)
|
||||||
|
├── target/bin/ # Build output (executables, libraries)
|
||||||
|
└── build/ # CMake build directory
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **SIC/XE Architecture**: Complete register set (A, X, L, B, S, T, F, PC, SW)
|
||||||
|
- **Instruction Execution**: Format 1, 2, and 3/4 instruction support
|
||||||
|
- **Device I/O**: Input, output, and file device management
|
||||||
|
- **Memory Management**: 24-bit address space with proper bounds checking
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
The project uses CMake with a convenient Makefile wrapper. All build artifacts are placed in `target/bin/` for easy access.
|
||||||
|
|
||||||
|
For manual CMake usage:
|
||||||
|
```bash
|
||||||
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build -j
|
||||||
|
```
|
||||||
16
simulator_SIC_XE/include/device.h
Normal file
16
simulator_SIC_XE/include/device.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef DEVICE_H
|
||||||
|
#define DEVICE_H
|
||||||
|
|
||||||
|
|
||||||
|
class Device {
|
||||||
|
public:
|
||||||
|
Device();
|
||||||
|
|
||||||
|
bool test();
|
||||||
|
virtual unsigned char read();
|
||||||
|
virtual void write(unsigned char value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DEVICE_H
|
||||||
19
simulator_SIC_XE/include/file_device.h
Normal file
19
simulator_SIC_XE/include/file_device.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef FILE_DEVICE_H
|
||||||
|
#define FILE_DEVICE_H
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class FileDevice : public Device {
|
||||||
|
public:
|
||||||
|
explicit FileDevice(const std::string &filename);
|
||||||
|
~FileDevice();
|
||||||
|
unsigned char read() override;
|
||||||
|
void write(unsigned char value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::fstream fileStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILE_DEVICE_H
|
||||||
18
simulator_SIC_XE/include/input_device.h
Normal file
18
simulator_SIC_XE/include/input_device.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef INPUT_DEVICE_H
|
||||||
|
#define INPUT_DEVICE_H
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
class InputDevice : public Device {
|
||||||
|
public:
|
||||||
|
explicit InputDevice(std::istream &in);
|
||||||
|
~InputDevice();
|
||||||
|
|
||||||
|
unsigned char read();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::istream &inStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INPUT_DEVICE_H
|
||||||
20
simulator_SIC_XE/include/instructions.h
Normal file
20
simulator_SIC_XE/include/instructions.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef INSTRUCTIONS_H
|
||||||
|
#define INSTRUCTIONS_H
|
||||||
|
|
||||||
|
#include "opcode.h"
|
||||||
|
|
||||||
|
// Type 2 instruction handlers
|
||||||
|
void addr_handler(Machine& m, int r1, int r2);
|
||||||
|
void clear_handler(Machine& m, int r, int unused);
|
||||||
|
void divr_handler(Machine& m, int r1, int r2);
|
||||||
|
void mulr_handler(Machine& m, int r1, int r2);
|
||||||
|
void rmo_handler(Machine& m, int r1, int r2);
|
||||||
|
void shiftl_handler(Machine& m, int r1, int n);
|
||||||
|
void shiftr_handler(Machine& m, int r1, int n);
|
||||||
|
void subr_handler(Machine& m, int r1, int r2);
|
||||||
|
void svc_handler(Machine& m, int n, int unused);
|
||||||
|
void tixr_handler(Machine& m, int r1, int unused);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // INSTRUCTIONS_H
|
||||||
145
simulator_SIC_XE/include/machine.h
Normal file
145
simulator_SIC_XE/include/machine.h
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
#ifndef MACHINE_H
|
||||||
|
#define MACHINE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "input_device.h"
|
||||||
|
#include "output_device.h"
|
||||||
|
#include "file_device.h"
|
||||||
|
#include "opcode.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#define MEMORY_SIZE 65536
|
||||||
|
#define NUM_DEVICES 256
|
||||||
|
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::cout;
|
||||||
|
|
||||||
|
|
||||||
|
class Machine {
|
||||||
|
public:
|
||||||
|
Machine();
|
||||||
|
~Machine();
|
||||||
|
|
||||||
|
// Accessor methods for registers
|
||||||
|
int getA() const { return A; }
|
||||||
|
void setA(int value) { A = value; }
|
||||||
|
|
||||||
|
int getB() const { return B; }
|
||||||
|
void setB(int value) { B = value; }
|
||||||
|
|
||||||
|
int getX() const { return X; }
|
||||||
|
void setX(int value) { X = value; }
|
||||||
|
|
||||||
|
int getL() const { return L; }
|
||||||
|
void setL(int value) { L = value; }
|
||||||
|
|
||||||
|
int getS() const { return S; }
|
||||||
|
void setS(int value) { S = value; }
|
||||||
|
|
||||||
|
int getT() const { return T; }
|
||||||
|
void setT(int value) { T = value; }
|
||||||
|
|
||||||
|
int getPC() const { return PC; }
|
||||||
|
void setPC(int value) { PC = value; }
|
||||||
|
|
||||||
|
int getSW() const { return SW; }
|
||||||
|
void setSW(int value) { SW = value; }
|
||||||
|
|
||||||
|
double getF() const { return F; }
|
||||||
|
void setF(double value) { F = value; }
|
||||||
|
|
||||||
|
int getReg(int regNum) const;
|
||||||
|
void setReg(int regNum, int value);
|
||||||
|
|
||||||
|
// Memory access methods
|
||||||
|
int getByte(int address);
|
||||||
|
void setByte(int address, int value);
|
||||||
|
|
||||||
|
int getWord(int address);
|
||||||
|
void setWord(int address, int value);
|
||||||
|
|
||||||
|
double getFloat(int address);
|
||||||
|
void setFloat(int address, double value);
|
||||||
|
|
||||||
|
|
||||||
|
// Device access methods
|
||||||
|
Device& getDevice(int num);
|
||||||
|
void setDevice(int num, std::shared_ptr<Device> device);
|
||||||
|
// Set a file device at index `num` using the provided filename.
|
||||||
|
void setFileDevice(int num, const std::string &filename);
|
||||||
|
|
||||||
|
|
||||||
|
// Fetch and execute instructions
|
||||||
|
int fetch();
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
bool execF1(int opcode);
|
||||||
|
bool execF2(int opcode, int operand);
|
||||||
|
bool execSICF3F4(int opcode, int ni, int operand);
|
||||||
|
|
||||||
|
// error handling methods
|
||||||
|
void notImplemented(string mnemonic);
|
||||||
|
void invalidOpcode(int opcode);
|
||||||
|
void invalidAddressing();
|
||||||
|
void divisionByZero(int opcode);
|
||||||
|
void undefinedHandler(int opcode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// registers
|
||||||
|
int A, B, X, L, S, T, PC, SW;
|
||||||
|
double F;
|
||||||
|
|
||||||
|
// memory
|
||||||
|
unsigned char memory[MEMORY_SIZE];
|
||||||
|
|
||||||
|
// devices
|
||||||
|
std::vector<std::shared_ptr<Device>> devices;
|
||||||
|
// fallback device returned when device slot is empty/invalid
|
||||||
|
Device fallbackDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert integer to 24-bit signed SIC representation
|
||||||
|
inline int toSIC24(int value) {
|
||||||
|
value &= 0xFFFFFF;
|
||||||
|
if (value & 0x800000) {
|
||||||
|
value -= 0x1000000;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int setCC(int sw, int cc) {
|
||||||
|
sw &= ~CC_MASK;
|
||||||
|
sw |= (cc & CC_MASK);
|
||||||
|
return sw;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int sic_comp(int a, int b, int sw) {
|
||||||
|
int sa = toSIC24(a);
|
||||||
|
int sb = toSIC24(b);
|
||||||
|
|
||||||
|
int cc;
|
||||||
|
if (sa < sb) {
|
||||||
|
cc = CC_LT;
|
||||||
|
} else if (sa == sb) {
|
||||||
|
cc = CC_EQ;
|
||||||
|
} else {
|
||||||
|
cc = CC_GT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setCC(sw, cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getCC(int sw) {
|
||||||
|
return sw & CC_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MACHINE_H
|
||||||
100
simulator_SIC_XE/include/opcode.h
Normal file
100
simulator_SIC_XE/include/opcode.h
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#ifndef OPCODE_H
|
||||||
|
#define OPCODE_H
|
||||||
|
|
||||||
|
// ==============================
|
||||||
|
// Opcode definitions (SIC/XE)
|
||||||
|
// ==============================
|
||||||
|
#define ADD 0x18
|
||||||
|
#define ADDF 0x58
|
||||||
|
#define ADDR 0x90
|
||||||
|
#define AND 0x40
|
||||||
|
#define CLEAR 0xB4
|
||||||
|
#define COMP 0x28
|
||||||
|
#define COMPF 0x88
|
||||||
|
#define COMPR 0xA0
|
||||||
|
#define DIV 0x24
|
||||||
|
#define DIVF 0x64
|
||||||
|
#define DIVR 0x9C
|
||||||
|
#define FIX 0xC4
|
||||||
|
#define FLOAT 0xC0
|
||||||
|
#define HIO 0xF4
|
||||||
|
#define J 0x3C
|
||||||
|
#define JEQ 0x30
|
||||||
|
#define JGT 0x34
|
||||||
|
#define JLT 0x38
|
||||||
|
#define JSUB 0x48
|
||||||
|
#define LDA 0x00
|
||||||
|
#define LDB 0x68
|
||||||
|
#define LDCH 0x50
|
||||||
|
#define LDF 0x70
|
||||||
|
#define LDL 0x08
|
||||||
|
#define LDS 0x6C
|
||||||
|
#define LDT 0x74
|
||||||
|
#define LDX 0x04
|
||||||
|
#define LPS 0xD0
|
||||||
|
#define MUL 0x20
|
||||||
|
#define MULF 0x60
|
||||||
|
#define MULR 0x98
|
||||||
|
#define NORM 0xC8
|
||||||
|
#define OR 0x44
|
||||||
|
#define RD 0xD8
|
||||||
|
#define RMO 0xAC
|
||||||
|
#define RSUB 0x4C
|
||||||
|
#define SHIFTL 0xA4
|
||||||
|
#define SHIFTR 0xA8
|
||||||
|
#define SIO 0xF0
|
||||||
|
#define SSK 0xEC
|
||||||
|
#define STA 0x0C
|
||||||
|
#define STB 0x78
|
||||||
|
#define STCH 0x54
|
||||||
|
#define STF 0x80
|
||||||
|
#define STI 0xD4
|
||||||
|
#define STL 0x14
|
||||||
|
#define STS 0x7C
|
||||||
|
#define STSW 0xE8
|
||||||
|
#define STT 0x84
|
||||||
|
#define STX 0x10
|
||||||
|
#define SUB 0x1C
|
||||||
|
#define SUBF 0x5C
|
||||||
|
#define SUBR 0x94
|
||||||
|
#define SVC 0xB0
|
||||||
|
#define TD 0xE0
|
||||||
|
#define TIO 0xF8
|
||||||
|
#define TIX 0x2C
|
||||||
|
#define TIXR 0xB8
|
||||||
|
#define WD 0xDC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// SW register condition codes
|
||||||
|
constexpr int CC_LT = 0x0; // 00
|
||||||
|
constexpr int CC_EQ = 0x1; // 01
|
||||||
|
constexpr int CC_GT = 0x2; // 10
|
||||||
|
constexpr int CC_MASK = 0x3; // mask for 2 bits
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum class InstructionType {
|
||||||
|
TYPE1,
|
||||||
|
TYPE2,
|
||||||
|
TYPE3_4,
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
class Machine; // forward
|
||||||
|
|
||||||
|
// Store raw function pointer (void*) to allow different handler signatures
|
||||||
|
using RawHandler = void*;
|
||||||
|
|
||||||
|
struct InstructionInfo {
|
||||||
|
const char* name;
|
||||||
|
InstructionType type;
|
||||||
|
RawHandler handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern InstructionInfo instructions[];
|
||||||
|
|
||||||
|
// Initialize the instruction table
|
||||||
|
void loadInstructionSet();
|
||||||
|
|
||||||
|
#endif // OPCODE_H
|
||||||
18
simulator_SIC_XE/include/output_device.h
Normal file
18
simulator_SIC_XE/include/output_device.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef OUTPUT_DEVICE_H
|
||||||
|
#define OUTPUT_DEVICE_H
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
class OutputDevice : public Device {
|
||||||
|
public:
|
||||||
|
explicit OutputDevice(std::ostream &out);
|
||||||
|
~OutputDevice();
|
||||||
|
|
||||||
|
void write(unsigned char value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostream &outStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OUTPUT_DEVICE_H
|
||||||
19
simulator_SIC_XE/src/device.cpp
Normal file
19
simulator_SIC_XE/src/device.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
Device::Device()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::test()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char Device::read()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::write(unsigned char value)
|
||||||
|
{
|
||||||
|
}
|
||||||
45
simulator_SIC_XE/src/file_device.cpp
Normal file
45
simulator_SIC_XE/src/file_device.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "file_device.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
FileDevice::FileDevice(const std::string &filename)
|
||||||
|
{
|
||||||
|
fileStream.open(filename, std::ios::in | std::ios::out | std::ios::binary);
|
||||||
|
if (!fileStream.is_open()) {
|
||||||
|
std::ofstream create(filename, std::ios::binary);
|
||||||
|
if (!create) {
|
||||||
|
throw std::runtime_error("Failed to create file: " + filename);
|
||||||
|
}
|
||||||
|
create.close();
|
||||||
|
|
||||||
|
fileStream.clear();
|
||||||
|
fileStream.open(filename, std::ios::in | std::ios::out | std::ios::binary);
|
||||||
|
if (!fileStream.is_open()) {
|
||||||
|
throw std::runtime_error("Failed to open file after creating: " + filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileDevice::~FileDevice()
|
||||||
|
{
|
||||||
|
if (fileStream.is_open()) {
|
||||||
|
fileStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char FileDevice::read()
|
||||||
|
{
|
||||||
|
unsigned char value = 0;
|
||||||
|
if (fileStream.is_open()) {
|
||||||
|
fileStream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDevice::write(unsigned char value)
|
||||||
|
{
|
||||||
|
if (fileStream.is_open()) {
|
||||||
|
fileStream.write(reinterpret_cast<const char*>(&value), sizeof(value));
|
||||||
|
fileStream.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
20
simulator_SIC_XE/src/input_device.cpp
Normal file
20
simulator_SIC_XE/src/input_device.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "input_device.h"
|
||||||
|
|
||||||
|
InputDevice::InputDevice(std::istream &in)
|
||||||
|
: inStream(in)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
InputDevice::~InputDevice()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char InputDevice::read()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
if (!inStream.get(c)) {
|
||||||
|
// If stream is at EOF or error, return 0
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<unsigned char>(c);
|
||||||
|
}
|
||||||
60
simulator_SIC_XE/src/instructions.cpp
Normal file
60
simulator_SIC_XE/src/instructions.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include "instructions.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
|
||||||
|
void addr_handler(Machine& m, int r1, int r2) {
|
||||||
|
m.setReg(r2, m.getReg(r1) + m.getReg(r2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLEAR instruction: clears register r (first nibble), second nibble unused
|
||||||
|
void clear_handler(Machine& m, int r, int unused) {
|
||||||
|
m.setReg(r, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void divr_handler(Machine& m, int r1, int r2) {
|
||||||
|
|
||||||
|
if (m.getReg(r2) == 0) {
|
||||||
|
m.invalidOpcode(DIVR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m.setReg(r2, m.getReg(r2) / m.getReg(r1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mulr_handler(Machine &m, int r1, int r2)
|
||||||
|
{
|
||||||
|
m.setReg(r2, m.getReg(r1) * m.getReg(r2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rmo_handler(Machine &m, int r1, int r2)
|
||||||
|
{
|
||||||
|
m.setReg(r2, m.getReg(r1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftl_handler(Machine &m, int r1, int n)
|
||||||
|
{
|
||||||
|
m.setReg(r1, m.getReg(r1) << n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftr_handler(Machine &m, int r1, int n)
|
||||||
|
{
|
||||||
|
m.setReg(r1, m.getReg(r1) >> n);
|
||||||
|
}
|
||||||
|
void subr_handler(Machine &m, int r1, int r2)
|
||||||
|
{
|
||||||
|
m.setReg(r2, m.getReg(r2) - m.getReg(r1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement SVC functionality
|
||||||
|
void svc_handler(Machine &m, int n, int unused)
|
||||||
|
{
|
||||||
|
m.notImplemented("SVC");
|
||||||
|
}
|
||||||
|
|
||||||
|
void tixr_handler(Machine &m, int r1, int unused)
|
||||||
|
{
|
||||||
|
m.setX(m.getX() + 1);
|
||||||
|
int valX = m.getX();
|
||||||
|
int valR1 = m.getReg(r1);
|
||||||
|
m.setSW(sic_comp(valX, valR1, m.getSW()));
|
||||||
|
}
|
||||||
261
simulator_SIC_XE/src/machine.cpp
Normal file
261
simulator_SIC_XE/src/machine.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "opcode.h"
|
||||||
|
#include "instructions.h"
|
||||||
|
|
||||||
|
using std::make_shared;
|
||||||
|
|
||||||
|
string prefix = "Machine error: ";
|
||||||
|
|
||||||
|
|
||||||
|
Machine::Machine()
|
||||||
|
{
|
||||||
|
devices.resize(NUM_DEVICES);
|
||||||
|
// device 0: standard input
|
||||||
|
devices[0] = make_shared<InputDevice>(std::cin);
|
||||||
|
// device 1: standard output
|
||||||
|
devices[1] = make_shared<OutputDevice>(std::cout);
|
||||||
|
// device 2: standard error
|
||||||
|
devices[2] = make_shared<OutputDevice>(std::cerr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Machine::~Machine()
|
||||||
|
{
|
||||||
|
for (auto& device : devices) {
|
||||||
|
device.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::notImplemented(string mnemonic)
|
||||||
|
{
|
||||||
|
cout << prefix << "Not implemented: " << mnemonic << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::invalidOpcode(int opcode)
|
||||||
|
{
|
||||||
|
cout << prefix << "Invalid opcode: " << opcode << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::invalidAddressing()
|
||||||
|
{
|
||||||
|
cout << prefix << "Invalid addressing mode" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::divisionByZero(int opcode)
|
||||||
|
{
|
||||||
|
cout << prefix << "Division by zero error in opcode: " << opcode << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::undefinedHandler(int opcode)
|
||||||
|
{
|
||||||
|
cout << prefix << "Undefined handler for opcode: " << opcode << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Machine::getReg(int regNum) const
|
||||||
|
{
|
||||||
|
switch (regNum) {
|
||||||
|
case 0: return A;
|
||||||
|
case 1: return X;
|
||||||
|
case 2: return L;
|
||||||
|
case 3: return B;
|
||||||
|
case 4: return S;
|
||||||
|
case 5: return T;
|
||||||
|
case 6: return F;
|
||||||
|
case 8: return PC;
|
||||||
|
case 9: return SW;
|
||||||
|
default:
|
||||||
|
cerr << prefix << "Invalid register number: " << regNum << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle double for F register
|
||||||
|
void Machine::setReg(int regNum, int value)
|
||||||
|
{
|
||||||
|
value = toSIC24(value);
|
||||||
|
switch (regNum) {
|
||||||
|
case 0: A = value; break;
|
||||||
|
case 1: X = value; break;
|
||||||
|
case 2: L = value; break;
|
||||||
|
case 3: B = value; break;
|
||||||
|
case 4: S = value; break;
|
||||||
|
case 5: T = value; break;
|
||||||
|
case 6: F = value; break;
|
||||||
|
case 8: PC = value; break;
|
||||||
|
case 9: SW = value; break;
|
||||||
|
default:
|
||||||
|
cerr << prefix << "Invalid register number: " << regNum << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Machine::getByte(int address)
|
||||||
|
{
|
||||||
|
if (address < 0 || address >= MEMORY_SIZE) {
|
||||||
|
cerr << prefix << "Invalid memory address: " << address << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return static_cast<int>(memory[address]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::setByte(int address, int value)
|
||||||
|
{
|
||||||
|
if(address < 0 || address >= MEMORY_SIZE) {
|
||||||
|
cerr << prefix << "Invalid memory address: " << address << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory[address] = static_cast<unsigned char>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming word is 3 bytes
|
||||||
|
|
||||||
|
int Machine::getWord(int address)
|
||||||
|
{
|
||||||
|
if (address < 0 || address + 2 >= MEMORY_SIZE) {
|
||||||
|
cerr << prefix << "Invalid memory address: " << address << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return static_cast<int>(memory[address]) | (static_cast<int>(memory[address + 1]) << 8) | (static_cast<int>(memory[address + 2]) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming word is 3 bytes
|
||||||
|
void Machine::setWord(int address, int value)
|
||||||
|
{
|
||||||
|
if(address < 0 || address + 2 >= MEMORY_SIZE) {
|
||||||
|
cerr << prefix << "Invalid memory address: " << address << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory[address] = static_cast<unsigned char>(value & 0xFF);
|
||||||
|
memory[address + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
|
||||||
|
memory[address + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement proper float storage and retrieval
|
||||||
|
double Machine::getFloat(int address)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::setFloat(int address, double value)
|
||||||
|
{
|
||||||
|
// TODO: implement proper float storage
|
||||||
|
}
|
||||||
|
|
||||||
|
Device &Machine::getDevice(int num)
|
||||||
|
{
|
||||||
|
if(num < 0 || num >= static_cast<int>(devices.size()) || !devices[num]) {
|
||||||
|
cerr << prefix << "Invalid device number: " << num << endl;
|
||||||
|
return fallbackDevice;
|
||||||
|
}
|
||||||
|
return *devices[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::setDevice(int num, std::shared_ptr<Device> device)
|
||||||
|
{
|
||||||
|
if(num < 0 || num >= NUM_DEVICES) {
|
||||||
|
cerr << prefix << "Invalid device number: " << num << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(static_cast<int>(devices.size()) != NUM_DEVICES) {
|
||||||
|
devices.resize(NUM_DEVICES);
|
||||||
|
}
|
||||||
|
// Enforce: devices with index >= 2 must be FileDevice instances
|
||||||
|
if (num >= 2) {
|
||||||
|
// try dynamic cast
|
||||||
|
if (std::dynamic_pointer_cast<FileDevice>(device) == nullptr) {
|
||||||
|
cerr << prefix << "Device at index " << num << " must be a FileDevice." << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
devices[num] = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::setFileDevice(int num, const std::string &filename)
|
||||||
|
{
|
||||||
|
if(num < 0 || num >= NUM_DEVICES) {
|
||||||
|
cerr << prefix << "Invalid device number: " << num << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(static_cast<int>(devices.size()) != NUM_DEVICES) {
|
||||||
|
devices.resize(NUM_DEVICES);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
devices[num] = std::make_shared<FileDevice>(filename);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
cerr << prefix << "Failed to create FileDevice for index " << num << ": " << e.what() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Machine::fetch()
|
||||||
|
{
|
||||||
|
return getByte(PC++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::execute()
|
||||||
|
{
|
||||||
|
int opcode = fetch();
|
||||||
|
InstructionType type = instructions[opcode].type;
|
||||||
|
switch (type) {
|
||||||
|
case InstructionType::TYPE1: execF1(opcode);break;
|
||||||
|
case InstructionType::TYPE2: execF2(opcode, fetch());break;
|
||||||
|
case InstructionType::TYPE3_4: // extract n and i bits
|
||||||
|
{
|
||||||
|
int ni = opcode & 0x3;
|
||||||
|
int operand = fetch();
|
||||||
|
execSICF3F4(opcode, ni, operand);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: invalidOpcode(opcode); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Machine::execF1(int opcode)
|
||||||
|
{
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case FIX:
|
||||||
|
setA(static_cast<int>(getF()));
|
||||||
|
return true;
|
||||||
|
case FLOAT:
|
||||||
|
setF(static_cast<double>(getA()));
|
||||||
|
return true;
|
||||||
|
case HIO:
|
||||||
|
notImplemented("HIO");
|
||||||
|
return true;
|
||||||
|
case NORM:
|
||||||
|
notImplemented("NORM");
|
||||||
|
return true;
|
||||||
|
case SIO:
|
||||||
|
notImplemented("SIO");
|
||||||
|
return true;
|
||||||
|
case TIO:
|
||||||
|
notImplemented("TIO");
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Machine::execF2(int opcode, int operand)
|
||||||
|
{
|
||||||
|
int r1 = (operand >> 4) & 0xF;
|
||||||
|
int r2 = operand & 0xF;
|
||||||
|
|
||||||
|
if (instructions[opcode].handler) {
|
||||||
|
auto handler = reinterpret_cast<void(*)(Machine&, int, int)>(instructions[opcode].handler);
|
||||||
|
handler(*this, r1, r2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
undefinedHandler(opcode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Machine::execSICF3F4(int opcode, int ni, int operand)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
27
simulator_SIC_XE/src/main.cpp
Normal file
27
simulator_SIC_XE/src/main.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "machine.h"
|
||||||
|
#include "file_device.h"
|
||||||
|
#include "opcode.h"
|
||||||
|
#include "instructions.h"
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
loadInstructionSet();
|
||||||
|
Machine machine;
|
||||||
|
|
||||||
|
cout << "Machine initialized successfully." << endl;
|
||||||
|
|
||||||
|
// COMPUTE A + B and store result in B
|
||||||
|
machine.setA(10);
|
||||||
|
machine.setB(20);
|
||||||
|
machine.setByte(0, ADDR);
|
||||||
|
machine.setByte(1, 0x03); // r1 = 0 (A), r2 = 3 (B)
|
||||||
|
cout << "Before ADDR: A = " << machine.getA() << ", B = " << machine.getB() << endl;
|
||||||
|
machine.execute();
|
||||||
|
cout << "After ADDR: A = " << machine.getA() << ", B = " << machine.getB() << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
75
simulator_SIC_XE/src/opcode.cpp
Normal file
75
simulator_SIC_XE/src/opcode.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include "opcode.h"
|
||||||
|
#include "instructions.h"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
InstructionInfo instructions[0xff];
|
||||||
|
|
||||||
|
void loadInstructionSet()
|
||||||
|
{
|
||||||
|
instructions[ADD] = {"ADD", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[ADDF] = {"ADDF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[ADDR] = {"ADDR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(addr_handler)};
|
||||||
|
instructions[AND] = {"AND", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[CLEAR] = {"CLEAR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(clear_handler)};
|
||||||
|
instructions[COMP] = {"COMP", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[COMPF] = {"COMPF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[COMPR] = {"COMPR", InstructionType::TYPE2, nullptr};
|
||||||
|
instructions[DIV] = {"DIV", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[DIVF] = {"DIVF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[DIVR] = {"DIVR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(divr_handler)};
|
||||||
|
instructions[FIX] = {"FIX", InstructionType::TYPE1, nullptr};
|
||||||
|
instructions[FLOAT] = {"FLOAT", InstructionType::TYPE1, nullptr};
|
||||||
|
instructions[HIO] = {"HIO", InstructionType::TYPE1, nullptr};
|
||||||
|
instructions[J] = {"J", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[JEQ] = {"JEQ", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[JGT] = {"JGT", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[JLT] = {"JLT", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[JSUB] = {"JSUB", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDA] = {"LDA", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDB] = {"LDB", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDCH] = {"LDCH", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDF] = {"LDF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDL] = {"LDL", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDS] = {"LDS", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDT] = {"LDT", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LDX] = {"LDX", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[LPS] = {"LPS", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[MUL] = {"MUL", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[MULF] = {"MULF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[MULR] = {"MULR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(mulr_handler)};
|
||||||
|
instructions[NORM] = {"NORM", InstructionType::TYPE1, nullptr};
|
||||||
|
instructions[OR] = {"OR", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[RD] = {"RD", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[RMO] = {"RMO", InstructionType::TYPE2, reinterpret_cast<RawHandler>(rmo_handler)};
|
||||||
|
instructions[RSUB] = {"RSUB", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[SHIFTL] = {"SHIFTL", InstructionType::TYPE2, reinterpret_cast<RawHandler>(shiftl_handler)};
|
||||||
|
instructions[SHIFTR] = {"SHIFTR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(shiftr_handler)};
|
||||||
|
instructions[SIO] = {"SIO", InstructionType::TYPE1, nullptr};
|
||||||
|
instructions[SSK] = {"SSK", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STA] = {"STA", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STB] = {"STB", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STCH] = {"STCH", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STF] = {"STF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STI] = {"STI", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STL] = {"STL", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STS] = {"STS", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STSW] = {"STSW", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STT] = {"STT", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[STX] = {"STX", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[SUB] = {"SUB", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[SUBF] = {"SUBF", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[SUBR] = {"SUBR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(subr_handler)};
|
||||||
|
instructions[SVC] = {"SVC", InstructionType::TYPE2, reinterpret_cast<RawHandler>(svc_handler)};
|
||||||
|
instructions[TIXR] = {"TIXR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(tixr_handler)};
|
||||||
|
instructions[TD] = {"TD", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[TIX] = {"TIX", InstructionType::TYPE3_4, nullptr};
|
||||||
|
instructions[TIO] = {"TIO", InstructionType::TYPE1, nullptr};
|
||||||
|
instructions[WD] = {"WD", InstructionType::TYPE3_4, nullptr};
|
||||||
|
|
||||||
|
// Mark uninitialized opcodes as INVALID
|
||||||
|
for (int i = 0; i < 0xff; ++i) {
|
||||||
|
if (instructions[i].name == nullptr) {
|
||||||
|
instructions[i] = {"INVALID", InstructionType::INVALID, nullptr};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
simulator_SIC_XE/src/output_device.cpp
Normal file
16
simulator_SIC_XE/src/output_device.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "output_device.h"
|
||||||
|
|
||||||
|
OutputDevice::OutputDevice(std::ostream &out)
|
||||||
|
: outStream(out)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputDevice::~OutputDevice()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputDevice::write(unsigned char value)
|
||||||
|
{
|
||||||
|
outStream.put(static_cast<char>(value));
|
||||||
|
outStream.flush();
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue