Started on arduino version
This commit is contained in:
35
arduino/arduino.ino
Normal file
35
arduino/arduino.ino
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Sam Stevens
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vm.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
VM vm;
|
||||||
|
Console console(&vm);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
vm_reset(&vm);
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
console.loop(&Serial);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
166
arduino/console.cpp
Normal file
166
arduino/console.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Sam Stevens
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <HardwareSerial.h>
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
Console::Console(VM* _vm) {
|
||||||
|
this->state = CONSOLE_NONE;
|
||||||
|
this->vm = _vm;
|
||||||
|
this->inputBuffer = new String("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::loop(HardwareSerial * serial) {
|
||||||
|
int i;
|
||||||
|
char d;
|
||||||
|
|
||||||
|
switch(this->state) {
|
||||||
|
case CONSOLE_NONE:
|
||||||
|
serial->println("Press Enter to activate console.");
|
||||||
|
this->state = CONSOLE_OFF;
|
||||||
|
break;
|
||||||
|
case CONSOLE_OFF:
|
||||||
|
if(serial->available()) {
|
||||||
|
if (serial->read() == 10) {
|
||||||
|
serial->println("Console active. Type ? for help.");
|
||||||
|
this->state = CONSOLE_ACTIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_ACTIVATE:
|
||||||
|
serial->print("> ");
|
||||||
|
this->state = CONSOLE_ACTIVE;
|
||||||
|
break;
|
||||||
|
case CONSOLE_ACTIVE:
|
||||||
|
if(serial->available()) {
|
||||||
|
while((d = (char)serial->read()) != -1) {
|
||||||
|
if (d == 27) {
|
||||||
|
//escape, deactivate console
|
||||||
|
this->inputBuffer = new String("");
|
||||||
|
serial->println("Console deactivated.");
|
||||||
|
this->state = CONSOLE_NONE;
|
||||||
|
} else if (d == '\n') {
|
||||||
|
//Finished input
|
||||||
|
serial->print("\n");
|
||||||
|
if (this->inputBuffer->equals("?")) {
|
||||||
|
serial->print(F(
|
||||||
|
"Commands\n"
|
||||||
|
"? | this help\n"
|
||||||
|
"q | deactivate console\n"
|
||||||
|
"r | run until halted\n"
|
||||||
|
"s | step one instruction\n"
|
||||||
|
"e | examine and update memory\n"
|
||||||
|
"v | show vm status\n"
|
||||||
|
"rst | reset PC and registers\n"
|
||||||
|
"clr | reset and clear memory\n"
|
||||||
|
));
|
||||||
|
serial->print("> ");
|
||||||
|
} else if (this->inputBuffer->equals("q")) {
|
||||||
|
serial->println("Console deactivated.");
|
||||||
|
this->state = CONSOLE_NONE;
|
||||||
|
} else if (this->inputBuffer->equals("r")) {
|
||||||
|
this->state = CONSOLE_RUN;
|
||||||
|
} else if (this->inputBuffer->equals("s")) {
|
||||||
|
this->state = CONSOLE_STEP;
|
||||||
|
} else if (this->inputBuffer->equals("e")) {
|
||||||
|
this->state = CONSOLE_EXAMINE;
|
||||||
|
} else if (this->inputBuffer->equals("v")) {
|
||||||
|
this->state = CONSOLE_VIEW;
|
||||||
|
} else if (this->inputBuffer->equals("rst")) {
|
||||||
|
this->state = CONSOLE_RESET;
|
||||||
|
} else if (this->inputBuffer->equals("clr")) {
|
||||||
|
this->state = CONSOLE_CLEAR;
|
||||||
|
} else {
|
||||||
|
serial->println("Unknown command. Type ? for help.");
|
||||||
|
serial->print("> ");
|
||||||
|
}
|
||||||
|
this->inputBuffer = new String("");
|
||||||
|
} else if (isAlphaNumeric(d) || isPunct(d) || isSpace(d)) {
|
||||||
|
//Append input to buffer
|
||||||
|
this->inputBuffer->concat(d);
|
||||||
|
serial->print(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_RUN:
|
||||||
|
break;
|
||||||
|
case CONSOLE_STEP:
|
||||||
|
break;
|
||||||
|
case CONSOLE_EXAMINE:
|
||||||
|
break;
|
||||||
|
case CONSOLE_VIEW:
|
||||||
|
//PC
|
||||||
|
serial->print( "PC ");
|
||||||
|
serial->print(this->vm->PC, HEX);
|
||||||
|
serial->print("\n");
|
||||||
|
|
||||||
|
//Registers
|
||||||
|
serial->print( "R ");
|
||||||
|
for(i = 0; i < VM_REG_SIZE; i++) {
|
||||||
|
if (this->vm->R[i] < 0x10) {
|
||||||
|
serial->print("0");
|
||||||
|
}
|
||||||
|
serial->print(this->vm->R[i], HEX);
|
||||||
|
serial->print(" ");
|
||||||
|
}
|
||||||
|
serial->print("\n");
|
||||||
|
|
||||||
|
//Memory
|
||||||
|
serial->println(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
|
||||||
|
for(i = 0; i < VM_MEM_SIZE; i++) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
if (i > 0) {
|
||||||
|
serial->print("\n");
|
||||||
|
if (i % 128 == 0 ) {
|
||||||
|
serial->println(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serial->print("0x");
|
||||||
|
if (i < 0x10) {
|
||||||
|
serial->print("0");
|
||||||
|
}
|
||||||
|
serial->print(i, HEX);
|
||||||
|
serial->print(" ");
|
||||||
|
}
|
||||||
|
uint8_t m = this->vm->M[i];
|
||||||
|
if (m < 0x10) {
|
||||||
|
serial->print("0");
|
||||||
|
}
|
||||||
|
serial->print(m, HEX);
|
||||||
|
serial->print(" ");
|
||||||
|
}
|
||||||
|
serial->print("\n");
|
||||||
|
|
||||||
|
this->state = CONSOLE_ACTIVATE;
|
||||||
|
break;
|
||||||
|
case CONSOLE_RESET:
|
||||||
|
vm_reset(this->vm);
|
||||||
|
serial->println("VM Reset");
|
||||||
|
this->state = CONSOLE_ACTIVATE;
|
||||||
|
break;
|
||||||
|
case CONSOLE_CLEAR:
|
||||||
|
vm_reset(this->vm);
|
||||||
|
for(i = 0; i < VM_MEM_SIZE; i++) {
|
||||||
|
this->vm->M[i] = 0;
|
||||||
|
}
|
||||||
|
serial->println("VM Reset & Memory Cleared");
|
||||||
|
this->state = CONSOLE_ACTIVATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
46
arduino/console.h
Normal file
46
arduino/console.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Sam Stevens
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UVM_CONSOLE_H
|
||||||
|
#define UVM_CONSOLE_H
|
||||||
|
|
||||||
|
#include <HardwareSerial.h>
|
||||||
|
#include "vm.h"
|
||||||
|
|
||||||
|
enum ConsoleState_t {
|
||||||
|
CONSOLE_NONE,
|
||||||
|
CONSOLE_OFF,
|
||||||
|
CONSOLE_ACTIVATE,
|
||||||
|
CONSOLE_ACTIVE,
|
||||||
|
CONSOLE_RUN,
|
||||||
|
CONSOLE_STEP,
|
||||||
|
CONSOLE_EXAMINE,
|
||||||
|
CONSOLE_VIEW,
|
||||||
|
CONSOLE_RESET,
|
||||||
|
CONSOLE_CLEAR,
|
||||||
|
};
|
||||||
|
typedef enum ConsoleState_t ConsoleState;
|
||||||
|
|
||||||
|
class Console {
|
||||||
|
ConsoleState state;
|
||||||
|
VM *vm;
|
||||||
|
String *inputBuffer;
|
||||||
|
public:
|
||||||
|
Console (VM*);
|
||||||
|
void loop(HardwareSerial*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //UVM_CONSOLE_H
|
||||||
212
arduino/vm.c
Normal file
212
arduino/vm.c
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Sam Stevens
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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));
|
||||||
|
|
||||||
|
uint8_t PC = vm->PC;
|
||||||
|
if (PC % 2 != 0) {
|
||||||
|
fprintf(stderr, "Halted. PC not aligned.\n");
|
||||||
|
vm->halted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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 x = 0;
|
||||||
|
uint8_t y = 0;
|
||||||
|
uint8_t d = 0;
|
||||||
|
uint16_t temp16 = 0;
|
||||||
|
switch (inst.op) {
|
||||||
|
case OP_LDA:
|
||||||
|
vm_decode_Q(&inst, raw);
|
||||||
|
d = vm->M[inst.imm];
|
||||||
|
break;
|
||||||
|
case OP_STA:
|
||||||
|
vm_decode_Q(&inst, raw);
|
||||||
|
vm->M[inst.imm] = vm_get_r(vm, inst.rd);
|
||||||
|
break;
|
||||||
|
case OP_LDI:
|
||||||
|
vm_decode_Q(&inst, raw);
|
||||||
|
d = inst.imm;
|
||||||
|
break;
|
||||||
|
case OP_ADD:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
vm->carry = 0;
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
d = x + y;
|
||||||
|
break;
|
||||||
|
case OP_ADC:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
temp16 = x + y + vm->carry;
|
||||||
|
vm->carry = (uint8_t) (temp16 >> 8);
|
||||||
|
d = (uint8_t) temp16;
|
||||||
|
break;
|
||||||
|
case OP_SUB:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
vm->carry = 0;
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
d = x - y;
|
||||||
|
break;
|
||||||
|
case OP_SBC:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
d = vm_subtract(x, y, &vm->carry);
|
||||||
|
break;
|
||||||
|
case OP_NOT:
|
||||||
|
vm_decode_T(&inst, raw);
|
||||||
|
d = ~x;
|
||||||
|
break;
|
||||||
|
case OP_AND:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
d = x & y;
|
||||||
|
break;
|
||||||
|
case OP_SHL:
|
||||||
|
vm_decode_T(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
d = x << vm_get_r(vm, inst.imm);
|
||||||
|
break;
|
||||||
|
case OP_SHR:
|
||||||
|
vm_decode_T(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
d = x >> vm_get_r(vm, inst.imm);
|
||||||
|
break;
|
||||||
|
case OP_SYS:
|
||||||
|
vm_decode_Q(&inst, raw);
|
||||||
|
if (vm->syscall != NULL) {
|
||||||
|
d = vm->syscall(vm, inst.imm);
|
||||||
|
} else {
|
||||||
|
printf("SYSCALL #%d\n", inst.imm);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OP_JMP:
|
||||||
|
vm_decode_Q(&inst, raw);
|
||||||
|
vm->PC = vm_get_r(vm, inst.rd);
|
||||||
|
break;
|
||||||
|
case OP_JEQ:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
if (x == y) {
|
||||||
|
vm->PC = vm_get_r(vm, inst.rd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OP_JLT:
|
||||||
|
vm_decode_S(&inst, raw);
|
||||||
|
x = vm_get_r(vm, inst.rx);
|
||||||
|
y = vm_get_r(vm, inst.ry);
|
||||||
|
if (x < y) {
|
||||||
|
vm->PC = vm_get_r(vm, inst.rd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OP_HLT:
|
||||||
|
printf("Halted at 0x%04X\n", PC);
|
||||||
|
vm->halted = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown Instruction at 0x%04X: 0x%hhX\n", PC, inst.op);
|
||||||
|
vm->halted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vm_put_r(vm, inst.rd, d);
|
||||||
|
}
|
||||||
90
arduino/vm.h
Normal file
90
arduino/vm.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 Sam Stevens
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UVM_VM_H
|
||||||
|
#define UVM_VM_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define VM_MEM_SIZE 256
|
||||||
|
#define VM_REG_SIZE 16
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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];
|
||||||
|
uint8_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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //UVM_VM_H
|
||||||
4
vm.h
4
vm.h
@@ -20,8 +20,8 @@ limitations under the License.
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define VM_MEM_SIZE (1<<8)-1
|
#define VM_MEM_SIZE 256
|
||||||
#define VM_REG_SIZE 15
|
#define VM_REG_SIZE 16
|
||||||
|
|
||||||
#define OP_HLT 0x0
|
#define OP_HLT 0x0
|
||||||
#define OP_LDA 0x1
|
#define OP_LDA 0x1
|
||||||
|
|||||||
Reference in New Issue
Block a user