Initial Commit`

This commit is contained in:
2018-10-16 21:46:37 +01:00
commit 0359d4e0b2
10 changed files with 421 additions and 0 deletions

84
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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