Initial Commit`
This commit is contained in:
84
.gitignore
vendored
Normal file
84
.gitignore
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
# Created by https://www.gitignore.io/api/clion
|
||||
|
||||
### CLion ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### CLion Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
|
||||
# End of https://www.gitignore.io/api/clion
|
||||
29
.idea/codeStyles/Project.xml
generated
Normal file
29
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C-extensions>
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/uVM.iml" filepath="$PROJECT_DIR$/.idea/uVM.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/uVM.iml
generated
Normal file
2
.idea/uVM.iml
generated
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||
6
CMakeLists.txt
Normal file
6
CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(uVM C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
add_executable(uVM main.c vm.c vm.h)
|
||||
24
main.c
Normal file
24
main.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vm.h"
|
||||
#include "string.h"
|
||||
|
||||
int main() {
|
||||
VM* vm = new_vm();
|
||||
|
||||
uint8_t data[] = {
|
||||
0x31, 0x05,
|
||||
0x32, 0x02,
|
||||
0x73, 0x12
|
||||
};
|
||||
memcpy(&vm->M, data, 6);
|
||||
|
||||
printf("%i\n", (uint8_t)0x101);
|
||||
|
||||
while(!vm->halted) {
|
||||
vm_step(vm);
|
||||
}
|
||||
|
||||
free_vm(vm);
|
||||
return 0;
|
||||
}
|
||||
186
vm.c
Normal file
186
vm.c
Normal file
@@ -0,0 +1,186 @@
|
||||
//
|
||||
// Created by Sam on 27/08/2018.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "vm.h"
|
||||
|
||||
VM *new_vm() {
|
||||
VM *vm = calloc(1, sizeof(VM));
|
||||
return vm;
|
||||
}
|
||||
|
||||
void free_vm(VM *vm) {
|
||||
free(vm);
|
||||
}
|
||||
|
||||
void vm_reset(VM *vm) {
|
||||
memset(vm->R, 0, sizeof(uint8_t) * VM_REG_SIZE);
|
||||
vm->PC = 0;
|
||||
vm->carry = 0;
|
||||
vm->halted = false;
|
||||
}
|
||||
|
||||
void vm_clear(VM *vm) {
|
||||
vm_reset(vm);
|
||||
memset(&vm->M, 0, VM_MEM_SIZE);
|
||||
}
|
||||
|
||||
inline uint8_t vm_get_r(VM *vm, uint8_t r) {
|
||||
if (r == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (r < VM_REG_SIZE) {
|
||||
return vm->R[r];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void vm_put_r(VM *vm, uint8_t r, uint8_t v) {
|
||||
if (r < VM_REG_SIZE) {
|
||||
vm->R[r] = v;
|
||||
}
|
||||
}
|
||||
|
||||
inline void vm_decode_Q(VM_Instruction *inst, uint16_t raw) {
|
||||
inst->rd = (uint8_t) ((raw & 0x0F00) >> 8);
|
||||
inst->imm = (uint8_t) (raw & 0x00FF);
|
||||
}
|
||||
|
||||
inline void vm_decode_S(VM_Instruction *inst, uint16_t raw) {
|
||||
inst->rd = (uint8_t) ((raw & 0x0F00) >> 8);
|
||||
inst->rx = (uint8_t) ((raw & 0x00F0) >> 4);
|
||||
inst->ry = (uint8_t) ((raw & 0x000F) >> 0);
|
||||
}
|
||||
|
||||
inline void vm_decode_T(VM_Instruction *inst, uint16_t raw) {
|
||||
inst->rd = (uint8_t) ((raw & 0x0F00) >> 8);
|
||||
inst->rx = (uint8_t) ((raw & 0x00F0) >> 4);
|
||||
inst->imm = (uint8_t) ((raw & 0x000F) >> 0);
|
||||
}
|
||||
|
||||
inline uint8_t vm_subtract(uint8_t x, uint8_t y, uint8_t *ptr_borrow) {
|
||||
uint8_t borrow = *ptr_borrow,
|
||||
difference = 0,
|
||||
xb, yb;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
xb = (uint8_t) ((x >> i) & 1);
|
||||
yb = (uint8_t) ((y >> i) & 1);
|
||||
difference |= (uint8_t) (((xb ^ yb) ^ borrow) & 1) << i;
|
||||
borrow = (uint8_t) (((~xb & yb) | ~(xb ^ yb) * borrow) & 1);
|
||||
}
|
||||
|
||||
*ptr_borrow = borrow;
|
||||
return difference;
|
||||
}
|
||||
|
||||
void vm_step(VM *vm) {
|
||||
VM_Instruction inst;
|
||||
memset(&inst, 0, sizeof(VM_Instruction));
|
||||
|
||||
uint16_t PC = vm->PC;
|
||||
uint16_t raw = (vm->M[PC] << 8) + vm->M[PC + 1];
|
||||
vm->PC += 2;
|
||||
inst.op = (uint8_t) (raw >> 12);
|
||||
|
||||
if (vm->halted) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t temp = 0, x = 0, y = 0;
|
||||
uint16_t temp16 = 0;
|
||||
switch (inst.op) {
|
||||
case OP_LDA:
|
||||
vm_decode_Q(&inst, raw);
|
||||
vm_put_r(vm, inst.rd, vm->M[inst.imm]);
|
||||
break;
|
||||
case OP_STA:
|
||||
vm_decode_Q(&inst, raw);
|
||||
vm->M[inst.imm] = (uint8_t) vm_get_r(vm, inst.rd);
|
||||
break;
|
||||
case OP_LDI:
|
||||
vm_decode_Q(&inst, raw);
|
||||
vm_put_r(vm, inst.rd, inst.imm);
|
||||
break;
|
||||
case OP_ADD:
|
||||
vm_decode_S(&inst, raw);
|
||||
vm->carry = 0;
|
||||
temp = vm_get_r(vm, inst.rx) + vm_get_r(vm, inst.ry);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
break;
|
||||
case OP_ADC:
|
||||
vm_decode_S(&inst, raw);
|
||||
temp16 = vm_get_r(vm, inst.rx) + vm_get_r(vm, inst.ry) + vm->carry;
|
||||
vm->carry = (uint8_t) (temp16 >> 8);
|
||||
vm_put_r(vm, inst.rd, (uint8_t)temp16);
|
||||
break;
|
||||
case OP_SUB:
|
||||
vm_decode_S(&inst, raw);
|
||||
vm->carry = 0;
|
||||
temp = vm_get_r(vm, inst.rx) - vm_get_r(vm, inst.ry);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
break;
|
||||
case OP_SBC:
|
||||
vm_decode_S(&inst, raw);
|
||||
x = vm_get_r(vm, inst.rx);
|
||||
y = vm_get_r(vm, inst.ry);
|
||||
temp = vm_subtract(x, y, &vm->carry);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
break;
|
||||
case OP_NOT:
|
||||
vm_decode_T(&inst, raw);
|
||||
temp = vm_get_r(vm, inst.rx);
|
||||
vm_put_r(vm, inst.rd, ~temp);
|
||||
break;
|
||||
case OP_AND:
|
||||
vm_decode_S(&inst, raw);
|
||||
temp = vm_get_r(vm, inst.rx) & vm_get_r(vm, inst.ry);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
break;
|
||||
case OP_SHL:
|
||||
vm_decode_T(&inst, raw);
|
||||
temp = vm_get_r(vm, inst.rx) << vm_get_r(vm, (uint8_t) inst.imm);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
break;
|
||||
case OP_SHR:
|
||||
vm_decode_T(&inst, raw);
|
||||
temp = vm_get_r(vm, inst.rx) >> vm_get_r(vm, (uint8_t) inst.imm);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
break;
|
||||
case OP_SYS:
|
||||
vm_decode_Q(&inst, raw);
|
||||
if (vm->syscall != NULL) {
|
||||
temp = vm->syscall(vm, inst.imm);
|
||||
vm_put_r(vm, inst.rd, temp);
|
||||
} else {
|
||||
printf("SYSCALL #%d\n", inst.imm);
|
||||
}
|
||||
break;
|
||||
case OP_JMP:
|
||||
vm_decode_Q(&inst, raw);
|
||||
vm->PC = vm->M[inst.rd];
|
||||
break;
|
||||
case OP_JEQ:
|
||||
vm_decode_S(&inst, raw);
|
||||
if (vm_get_r(vm, inst.rx) == vm_get_r(vm, inst.ry)) {
|
||||
vm->PC = vm->M[inst.rd];
|
||||
}
|
||||
break;
|
||||
case OP_JLT:
|
||||
vm_decode_S(&inst, raw);
|
||||
if (vm_get_r(vm, inst.rx) < vm_get_r(vm, inst.ry)) {
|
||||
vm->PC = vm->M[inst.rd];
|
||||
}
|
||||
break;
|
||||
case OP_HLT:
|
||||
printf("Halted at 0x%04hX\n", PC);
|
||||
vm->halted = true;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown Instruction at 0x%04hX: 0x%hhX\n", PC, inst.op);
|
||||
vm->halted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
70
vm.h
Normal file
70
vm.h
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Created by Sam on 27/08/2018.
|
||||
//
|
||||
|
||||
#ifndef UVM_VM_H
|
||||
#define UVM_VM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define VM_MEM_SIZE (1<<8)-1
|
||||
#define VM_REG_SIZE 15
|
||||
|
||||
#define OP_HLT 0x0
|
||||
#define OP_LDA 0x1
|
||||
#define OP_STA 0x2
|
||||
#define OP_LDI 0x3
|
||||
#define OP_ADD 0x4
|
||||
#define OP_ADC 0x5
|
||||
#define OP_SUB 0x6
|
||||
#define OP_SBC 0x7
|
||||
#define OP_NOT 0x8
|
||||
#define OP_AND 0x9
|
||||
#define OP_SHL 0xa
|
||||
#define OP_SHR 0xb
|
||||
#define OP_SYS 0xc
|
||||
#define OP_JMP 0xd
|
||||
#define OP_JEQ 0xe
|
||||
#define OP_JLT 0xf
|
||||
|
||||
struct VM_Instruction_t {
|
||||
uint8_t op;
|
||||
uint8_t rd;
|
||||
uint8_t rx;
|
||||
uint8_t ry;
|
||||
uint8_t imm;
|
||||
};
|
||||
typedef struct VM_Instruction_t VM_Instruction;
|
||||
|
||||
struct VM_t {
|
||||
uint8_t R[VM_REG_SIZE];
|
||||
uint16_t PC;
|
||||
uint8_t M[VM_MEM_SIZE];
|
||||
uint8_t carry;
|
||||
bool halted;
|
||||
uint8_t (*syscall)(struct VM_t* vm, uint8_t callno);
|
||||
};
|
||||
typedef struct VM_t VM;
|
||||
|
||||
VM * new_vm();
|
||||
|
||||
void free_vm(VM *vm);
|
||||
|
||||
void vm_reset(VM *vm);
|
||||
|
||||
void vm_clear(VM *vm);
|
||||
|
||||
uint8_t vm_get_r(VM *vm, uint8_t r);
|
||||
|
||||
void vm_put_r(VM *vm, uint8_t r, uint8_t v);
|
||||
|
||||
void vm_decode_Q(VM_Instruction *inst, uint16_t raw);
|
||||
void vm_decode_S(VM_Instruction *inst, uint16_t raw);
|
||||
void vm_decode_T(VM_Instruction *inst, uint16_t raw);
|
||||
|
||||
uint8_t vm_subtract(uint8_t x, uint8_t y, uint8_t *ptr_borrow);
|
||||
|
||||
void vm_step(VM *vm);
|
||||
|
||||
#endif //UVM_VM_H
|
||||
Reference in New Issue
Block a user