Initial commit
This commit is contained in:
commit
5a5bed307d
7 changed files with 1014 additions and 0 deletions
2
assembl/Makefile
Normal file
2
assembl/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[all]:
|
||||||
|
gcc src/main.c -lm
|
BIN
assembl/a.out
Executable file
BIN
assembl/a.out
Executable file
Binary file not shown.
254
assembl/src/main.c
Normal file
254
assembl/src/main.c
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
|
||||||
|
int id;
|
||||||
|
|
||||||
|
int ntyps;
|
||||||
|
|
||||||
|
//Bitfields representing possible arg combinations:
|
||||||
|
//(Using left to right big endian naming)
|
||||||
|
// upper 4 bits : left arg / arg1
|
||||||
|
// lower 4 bits : right arg / arg2
|
||||||
|
//0 : rm/rn
|
||||||
|
//1 : r0
|
||||||
|
//2 : *rm/*rn
|
||||||
|
//3 : #imm
|
||||||
|
//4 : *#imm
|
||||||
|
//5 : sr
|
||||||
|
//6 : *sr
|
||||||
|
//7 : sr0-1
|
||||||
|
//F : none
|
||||||
|
uint8_t argtyps[7];
|
||||||
|
|
||||||
|
//Opcodes for the different types, a 0xF
|
||||||
|
//nibble indicates replaceable
|
||||||
|
uint16_t opcodes[7];
|
||||||
|
|
||||||
|
} InstrDef;
|
||||||
|
|
||||||
|
#define INSTR_DICT_S 29
|
||||||
|
|
||||||
|
InstrDef instr_dict[INSTR_DICT_S] = {
|
||||||
|
{0 ,1, {0xFF,0,0,0,0,0,0},{0,0,0,0,0,0,0}},//nop
|
||||||
|
{1 ,7, {0x00,0x03,0x02,0x04,0x20,0x40,0x22},{0x20FF,0x8FFF,0xB0FF,0x9FFF,0xB1FF,0xAFFF,0xB2FF}},//mov
|
||||||
|
{2 ,2, {0x06,0x60,0,0,0,0,0},{0xB3FF,0xB4FF,0,0,0,0,0}},//mmv
|
||||||
|
{3 ,1, {0x0F,0,0,0,0,0,0},{0xB5F0,0,0,0,0,0,0}},//psh
|
||||||
|
{4 ,1, {0x0F,0,0,0,0,0,0},{0xB6F0,0,0,0,0,0,0}},//pop
|
||||||
|
{5 ,1, {0x70,0,0,0,0,0,0},{0xE0FF,0,0,0,0,0,0}},//lds
|
||||||
|
{6 ,1, {0x07,0,0,0,0,0,0},{0xE1FF,0,0,0,0,0,0}},//sts
|
||||||
|
{7 ,2, {0x00,0x13,0,0,0,0,0},{0x40FF,0x48FF,0,0,0,0,0}},//add
|
||||||
|
{8 ,1, {0x70,0,0,0,0,0,0},{0xE2FF,0,0,0,0,0,0}},//sad
|
||||||
|
{9 ,1, {0x00,0,0,0,0,0,0},{0x41FF,0,0,0,0,0,0}},//sub
|
||||||
|
{10,1, {0x0F,0,0,0,0,0,0},{0x42F0,0,0,0,0,0,0}},//shl
|
||||||
|
{11,1, {0x0F,0,0,0,0,0,0},{0x43F0,0,0,0,0,0,0}},//shr
|
||||||
|
{12,1, {0x00,0,0,0,0,0,0},{0x44FF,0,0,0,0,0,0}},//and
|
||||||
|
{13,1, {0x00,0,0,0,0,0,0},{0x45FF,0,0,0,0,0,0}},//or
|
||||||
|
{14,1, {0x00,0,0,0,0,0,0},{0x46FF,0,0,0,0,0,0}},//xor
|
||||||
|
{15,1, {0x0F,0,0,0,0,0,0},{0x47FF,0,0,0,0,0,0}},//not
|
||||||
|
{16,1, {0xFF,0,0,0,0,0,0},{0x6000,0,0,0,0,0,0}},//rtb
|
||||||
|
{17,1, {0x00,0,0,0,0,0,0},{0x61FF,0,0,0,0,0,0}},//gth
|
||||||
|
{18,1, {0x00,0,0,0,0,0,0},{0x64FF,0,0,0,0,0,0}},//gts
|
||||||
|
{19,1, {0x00,0,0,0,0,0,0},{0x62FF,0,0,0,0,0,0}},//eql
|
||||||
|
{20,1, {0x0F,0,0,0,0,0,0},{0x63F0,0,0,0,0,0,0}},//stb
|
||||||
|
{21,2, {0x2F,0x4F,0,0,0,0,0},{0x32F0,0x30FF,0,0,0,0,0}},//br
|
||||||
|
{22,2, {0x2F,0x4F,0,0,0,0,0},{0x35F0,0x31FF,0,0,0,0,0}},//bt
|
||||||
|
{23,1, {0x2F,0,0,0,0,0,0},{0x33F0,0,0,0,0,0,0}},//bf
|
||||||
|
{24,1, {0x6F,0,0,0,0,0,0},{0x34F0,0,0,0,0,0,0}},//jmp
|
||||||
|
{25,1, {0x0F,0,0,0,0,0,0},{0x71F0,0,0,0,0,0,0}},//itp
|
||||||
|
{26,1, {0xFF,0,0,0,0,0,0},{0x7200,0,0,0,0,0,0}},//dsi
|
||||||
|
{27,1, {0xFF,0,0,0,0,0,0},{0x7300,0,0,0,0,0,0}},//eni
|
||||||
|
{28,1, {0x0F,0,0,0,0,0,0},{0x70F0,0,0,0,0,0,0}}//rgi
|
||||||
|
};
|
||||||
|
|
||||||
|
char *instr_tok_dict[INSTR_DICT_S] = {
|
||||||
|
"nop",
|
||||||
|
"mov",
|
||||||
|
"mmv",
|
||||||
|
"psh",
|
||||||
|
"pop",
|
||||||
|
"lds",
|
||||||
|
"sts",
|
||||||
|
"add",
|
||||||
|
"sad",
|
||||||
|
"sub",
|
||||||
|
"shl",
|
||||||
|
"shr",
|
||||||
|
"and",
|
||||||
|
"or",
|
||||||
|
"xor",
|
||||||
|
"not",
|
||||||
|
"rtb",
|
||||||
|
"gth",
|
||||||
|
"gts",
|
||||||
|
"eql",
|
||||||
|
"stb",
|
||||||
|
"br",
|
||||||
|
"bt",
|
||||||
|
"bf",
|
||||||
|
"jmp",
|
||||||
|
"itp",
|
||||||
|
"dsi",
|
||||||
|
"eni",
|
||||||
|
"rgi"
|
||||||
|
};
|
||||||
|
|
||||||
|
int find_token(char *token, int dicts, char *dict[]){
|
||||||
|
int toklen = strlen(token);
|
||||||
|
|
||||||
|
if(toklen < 2) return -1;
|
||||||
|
|
||||||
|
for(int i=0; i < dicts; i++){
|
||||||
|
if(token[1] == dict[i][1]){
|
||||||
|
if(!strcmp(token, dict[i])){
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uint8_t_cmpfunc(const void *a, const void *b){
|
||||||
|
return *(uint8_t*)a - *(uint8_t*)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_corres_def(uint8_t argtyps, InstrDef *indef){
|
||||||
|
uint8_t *match = bsearch(&argtyps, &indef->argtyps, 7, 1, &uint8_t_cmpfunc);
|
||||||
|
|
||||||
|
if(!match) return -1;
|
||||||
|
|
||||||
|
return (int64_t)match - (int64_t)&indef->argtyps;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t pars_line(char *line){
|
||||||
|
char *tok;
|
||||||
|
|
||||||
|
tok = strtok(line, " ");
|
||||||
|
|
||||||
|
int tokid = find_token(tok, INSTR_DICT_S, instr_tok_dict);
|
||||||
|
|
||||||
|
if(tokid < 0) return -1;
|
||||||
|
|
||||||
|
InstrDef *indef = &instr_dict[tokid];
|
||||||
|
|
||||||
|
tok = strtok(NULL, " ");
|
||||||
|
char *ntok = strtok(NULL, " ");
|
||||||
|
|
||||||
|
tok = strtok(tok, ",");
|
||||||
|
|
||||||
|
int8_t argtyps = 0xFF;
|
||||||
|
int8_t argt[2] = {0xF,0xF};
|
||||||
|
int8_t fargs[2];
|
||||||
|
int8_t rn, imm;
|
||||||
|
|
||||||
|
for(int i = 0; i < 2; i++){
|
||||||
|
if(!strncmp(tok,"ac",2) + (!strncmp(tok,"pc",2))*2 && strlen(tok)>2){
|
||||||
|
if((tok[2]-48) > -1 && (tok[2]-48) < 10){
|
||||||
|
argt[i] = 0x7;
|
||||||
|
fargs[i] = !strncmp(tok,"ac",2) + (!strncmp(tok,"pc",2))*2 + tok[2]-48;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strncmp(tok,"*ac",2) + (!strncmp(tok,"*pc",2))*2){
|
||||||
|
argt[i] = 0x6;
|
||||||
|
fargs[i] = !strncmp(tok,"*ac",2) + (!strncmp(tok,"*pc",2))*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(tok)>1 && !strncmp(tok,"r",1)){
|
||||||
|
if(!sscanf(&tok[1], "%d", &rn)){
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
else if(rn > -1 && rn < 16){
|
||||||
|
argt[i] = 0x0;
|
||||||
|
fargs[i] = rn;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(tok)>1 && !strncmp(tok,"*r",1)){
|
||||||
|
if(!sscanf(&tok[2], "%d", &rn)){
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if(rn > -1 && rn < 16){
|
||||||
|
argt[i] = 0x2;
|
||||||
|
fargs[i] = rn;
|
||||||
|
}
|
||||||
|
else return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(tok)>1 && !strncmp(tok, "#",1)){
|
||||||
|
if(!sscanf(&tok[1], "%d", &imm)){
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if(imm < -128 || imm > 127){
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
argt[i] = 0x3;
|
||||||
|
fargs[i] = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(tok) > 1 && !strncmp(tok,"*#",2)){
|
||||||
|
if(!sscanf(&tok[2], "%d", &imm)){
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if(imm < -128 || imm > 127){
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
argt[i] = 0x4;
|
||||||
|
fargs[i] = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = ntok;
|
||||||
|
|
||||||
|
argtyps = (argtyps & (0xF0F>>(i*4)));
|
||||||
|
argtyps += (argt[i] << (4-i*4));
|
||||||
|
}
|
||||||
|
|
||||||
|
int instt = find_corres_def(argtyps, indef);
|
||||||
|
|
||||||
|
if(instt < 0) return -4;
|
||||||
|
|
||||||
|
uint16_t op = indef->opcodes[instt];
|
||||||
|
|
||||||
|
uint8_t *opb = &op;
|
||||||
|
|
||||||
|
if((argtyps & 0xF0) < 5 && (argtyps & 0xF0) > 2){
|
||||||
|
opb[1] = (opb[1] & 0x0F) + fargs[1];
|
||||||
|
opb[0] = fargs[0];
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
if((argtyps & 0x0F) < 5 && (argtyps & 0x0F) > 2){
|
||||||
|
opb[1] = (opb[1] & 0xF0) + fargs[0];
|
||||||
|
opb[0] = fargs[1];
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
if((argtyps & 0xF0) < 3 || (argtyps & 0xF0 > 4 && argtyps & 0xF0 < 8)){
|
||||||
|
opb[1] = opb[1] & 0x0F + fargs[0];
|
||||||
|
}
|
||||||
|
if(argtyps & 0x0F < 3 || (argtyps & 0x0F > 4 && argtyps & 0x0F < 8)){
|
||||||
|
opb[1] = opb[1] & 0xF0 + fargs[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, int *argv[]){
|
||||||
|
|
||||||
|
if(argc < 2) return -1;
|
||||||
|
|
||||||
|
char *line_ = argv[1];
|
||||||
|
|
||||||
|
char *line = malloc(strlen(line_));
|
||||||
|
|
||||||
|
memcpy(line, line_, 11);
|
||||||
|
|
||||||
|
printf("%x\n", pars_line(line));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
5
interpr/Makefile
Normal file
5
interpr/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
CFLAGS = -O2 -lm
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
[all]:
|
||||||
|
${CC} src/main.c ${CFLAGS}
|
BIN
interpr/a.out
Executable file
BIN
interpr/a.out
Executable file
Binary file not shown.
421
interpr/src/main.c
Normal file
421
interpr/src/main.c
Normal file
|
@ -0,0 +1,421 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MEM_ALLOC 0xFFFF //64KiB
|
||||||
|
|
||||||
|
#define TOTAL_ALLOC (MEM_ALLOC)
|
||||||
|
|
||||||
|
#define BOOTCODE_S 18
|
||||||
|
|
||||||
|
uint8_t bootcode[] = {
|
||||||
|
0x00,0xFF,
|
||||||
|
0xFF,0x00,
|
||||||
|
0x00,0x06,
|
||||||
|
0x72,0x00,
|
||||||
|
0xB6,0xE0,
|
||||||
|
0xE0,0x0E,
|
||||||
|
0xB6,0xE0,
|
||||||
|
0xE0,0x1E,
|
||||||
|
0x34,0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
|
||||||
|
uint8_t *mem;
|
||||||
|
|
||||||
|
uint8_t greg[16];
|
||||||
|
|
||||||
|
uint16_t sreg[2];
|
||||||
|
|
||||||
|
uint8_t interr[16];
|
||||||
|
uint8_t intern;
|
||||||
|
|
||||||
|
uint8_t interen;
|
||||||
|
|
||||||
|
uint8_t tbit;
|
||||||
|
|
||||||
|
int32_t cycles;
|
||||||
|
|
||||||
|
} ProcDat;
|
||||||
|
|
||||||
|
int init_proc(ProcDat *procdat){
|
||||||
|
procdat->mem = malloc(MEM_ALLOC);
|
||||||
|
|
||||||
|
if(!procdat->mem){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<BOOTCODE_S; i++){
|
||||||
|
procdat->mem[i] = bootcode[i-1];
|
||||||
|
}
|
||||||
|
for(int i=BOOTCODE_S; i<MEM_ALLOC; i++){
|
||||||
|
procdat->mem[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
procdat->sreg[1] = procdat->mem[0]<<8 + procdat->mem[1];
|
||||||
|
printf("%x\n", procdat->mem[1]);
|
||||||
|
procdat->interen = 1;
|
||||||
|
procdat->interr[0] = 0b01;
|
||||||
|
procdat->intern = 1;
|
||||||
|
procdat->cycles = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_proc(ProcDat *procdat){
|
||||||
|
free(procdat->mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void itp(uint8_t interrupt, uint8_t call_type, ProcDat *procdat){
|
||||||
|
if(!procdat->interen)return;
|
||||||
|
if(!(procdat->interr[interrupt] & 0x2) && call_type) return;
|
||||||
|
|
||||||
|
printf("Interrupt %x, PC : %x\n", interrupt, procdat->sreg[1]);
|
||||||
|
|
||||||
|
uint16_t st = procdat->mem[0x2]<<8 + procdat->mem[0x3];
|
||||||
|
|
||||||
|
procdat->mem[st+procdat->greg[12]] = procdat->sreg[1] >> 8;
|
||||||
|
procdat->greg[12]++;
|
||||||
|
procdat->mem[st+procdat->greg[12]] = procdat->sreg[1] & 0xFF;
|
||||||
|
procdat->greg[12]++;
|
||||||
|
|
||||||
|
procdat->sreg[1] = procdat->mem[3]<<8 + procdat->mem[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
int exec_instr(uint16_t instr, ProcDat *procdat){
|
||||||
|
int8_t in0 = instr & 0xFF;
|
||||||
|
uint8_t in1 = instr & 0xF;
|
||||||
|
uint8_t in2 = (instr>>4) & 0xF;
|
||||||
|
uint8_t in3 = (instr>>8) & 0xF;
|
||||||
|
uint8_t in4 = instr>>12;
|
||||||
|
|
||||||
|
uint8_t *greg = &procdat->greg;
|
||||||
|
uint16_t *sreg = &procdat->sreg;
|
||||||
|
uint8_t *mem = procdat->mem;
|
||||||
|
uint16_t st = mem[0x2]<<8 + mem[0x3];
|
||||||
|
int32_t cycles = 0;
|
||||||
|
|
||||||
|
switch(in4){
|
||||||
|
case 0x2 : {
|
||||||
|
greg[in2] = greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3 : {
|
||||||
|
switch(in3){
|
||||||
|
case 0x0 : {
|
||||||
|
sreg[1] += in0*2;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x1 : {
|
||||||
|
if(procdat->tbit){
|
||||||
|
sreg[1] += in0*2;
|
||||||
|
}
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2 : {
|
||||||
|
sreg[1] += ((int8_t)in2)*2;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3 : {
|
||||||
|
if(!procdat->tbit){
|
||||||
|
sreg[1] += ((int8_t)in2)*2;
|
||||||
|
}
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x4 : {
|
||||||
|
sreg[1] = sreg[0];
|
||||||
|
cycles+=2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x5 : {
|
||||||
|
if(procdat->tbit){
|
||||||
|
sreg[1] += ((int8_t)in2)*2;
|
||||||
|
}
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0x4 : {
|
||||||
|
switch(in3){
|
||||||
|
case 0x0 : {
|
||||||
|
greg[in2] += greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x1 : {
|
||||||
|
greg[in2] -= greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2 : {
|
||||||
|
greg[in2] <<= 1;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3 : {
|
||||||
|
greg[in2] >>= 2;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x4 : {
|
||||||
|
greg[in2] &= greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x5 : {
|
||||||
|
greg[in2] |= greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x6 : {
|
||||||
|
greg[in2] ^= greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x7 : {
|
||||||
|
greg[in2] = ~greg[in2];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x8 : {
|
||||||
|
greg[0] += in0;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x6 : {
|
||||||
|
switch(in3){
|
||||||
|
case 0x0 : {
|
||||||
|
procdat->tbit = 0;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x1 : {
|
||||||
|
procdat->tbit = greg[in2] > greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2 : {
|
||||||
|
procdat->tbit = greg[in2] == greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3 : {
|
||||||
|
greg[in2] = procdat->tbit;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x4 : {
|
||||||
|
procdat->tbit = (int8_t)greg[in2] > (int8_t)greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x7 : {
|
||||||
|
switch(in3){
|
||||||
|
case 0x0 : {
|
||||||
|
if(procdat->intern > 15){
|
||||||
|
greg[in2] = 0xFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
procdat->interr[procdat->intern] = greg[in2];
|
||||||
|
procdat->intern++;
|
||||||
|
cycles+=2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x1 : {
|
||||||
|
itp(in2, 1, procdat);
|
||||||
|
cycles+=6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2 : {
|
||||||
|
procdat->interen = 0;
|
||||||
|
printf("PC : %x - disabled interrupts\n", sreg[1]);
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3 : {
|
||||||
|
procdat->interen = 1;
|
||||||
|
printf("PC : %x - enabled interrupts\n", sreg[1]);
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0x8 : {
|
||||||
|
greg[in3] = in0;
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x9 : {
|
||||||
|
greg[in3] = mem[(sreg[1]+in0)&0xFFFF];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xA : {
|
||||||
|
mem[(sreg[1]+in0)&0xFFFF] = greg[in3];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xB : {
|
||||||
|
switch(in3){
|
||||||
|
case 0x0 : {
|
||||||
|
greg[in2] = mem[(sreg[1]+(int8_t)greg[in1])&0xFFFF];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x1 : {
|
||||||
|
mem[(sreg[1]+(int8_t)greg[in2])&0xFFFF] = greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2 : {
|
||||||
|
mem[(sreg[1]+(int8_t)greg[in2])&0xFFFF] = mem[(sreg[1]+(int8_t)greg[in1])&0xFFFF];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3 : {
|
||||||
|
greg[in2] = mem[sreg[0]];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x4 : {
|
||||||
|
mem[sreg[0]] = greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x5 : {
|
||||||
|
mem[st+greg[12]] = greg[in2];
|
||||||
|
greg[12]++;
|
||||||
|
cycles+=2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x6 : {
|
||||||
|
greg[12]--;
|
||||||
|
greg[in2] = mem[st+greg[12]];
|
||||||
|
cycles+=2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xE : {
|
||||||
|
switch(in3){
|
||||||
|
case 0x0 : {
|
||||||
|
if(in2 < 2){
|
||||||
|
sreg[1] = (sreg[1] & (0x00FF00>>(8*in2))) + greg[in1]<<(8*in2);
|
||||||
|
}
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x1 : {
|
||||||
|
greg[in2] = sreg[in1/2] >> (in1%2 ? 8:0);
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2 : {
|
||||||
|
sreg[in2] += greg[in1];
|
||||||
|
cycles++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
itp(0, 0, procdat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sreg[1]+=2;
|
||||||
|
procdat->cycles += cycles;
|
||||||
|
if(mem[sreg[1]] == 1){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(mem[sreg[1]])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
|
||||||
|
ProcDat procdat;
|
||||||
|
|
||||||
|
if(init_proc(&procdat)){
|
||||||
|
printf("Error during initialization !\n(Likely couldn't allocate %d KiB)\n", TOTAL_ALLOC/1024);
|
||||||
|
free_proc(&procdat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = malloc(100);
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
int inp = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
scanf("%X", &inp);
|
||||||
|
if(inp == 0x1){
|
||||||
|
scanf("%99s", buf);
|
||||||
|
if(!memcmp(buf, "-d", 2)){
|
||||||
|
printf("PC : %x AC : %x\n", procdat.sreg[1], procdat.sreg[0]);
|
||||||
|
for(i=0; i<16; i++){
|
||||||
|
printf("r%d : %x\n", i, procdat.greg[i]);
|
||||||
|
}
|
||||||
|
for(i=0; i<MEM_ALLOC;){
|
||||||
|
printf("%x : ", i);
|
||||||
|
i++;
|
||||||
|
printf("%x ",procdat.mem[i]);
|
||||||
|
i++;
|
||||||
|
printf("%x\n",procdat.mem[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!memcmp(buf, "-q", 2)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(exec_instr(inp & 0xFFFF, &procdat)){
|
||||||
|
while(exec_instr(procdat.mem[procdat.sreg[1]], &procdat)){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
|
||||||
|
free_proc(&procdat);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
332
spec.txt
Normal file
332
spec.txt
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
instruction format:
|
||||||
|
big endian
|
||||||
|
16bits
|
||||||
|
|
||||||
|
Bit order:
|
||||||
|
0 : Largest (leftmost), 7 : smallest (rightmost)
|
||||||
|
|
||||||
|
|
||||||
|
registers:
|
||||||
|
r0-r12 (mov 0x0-0xc):
|
||||||
|
general purpose
|
||||||
|
8 bits
|
||||||
|
r13-r15 (mov 0xd-0xf):
|
||||||
|
Interrupt reserved
|
||||||
|
8 bits
|
||||||
|
ac,pr (special 0x0,1):
|
||||||
|
accumulator, progam counter
|
||||||
|
16bits
|
||||||
|
ac0-1,pc0-1 (lds/sts 0x0-1,0x2-3):
|
||||||
|
accumulator, progam counter
|
||||||
|
8-8bits (lower-upper)
|
||||||
|
id (special 0x2):
|
||||||
|
interrupt data,
|
||||||
|
set by the interrupt
|
||||||
|
if raised by bus
|
||||||
|
8bits
|
||||||
|
in (Special 0x3):
|
||||||
|
interrupt register,
|
||||||
|
contains the type of
|
||||||
|
interrupt
|
||||||
|
4bits - bits 0-3 will always be 0
|
||||||
|
t bit:
|
||||||
|
is set by comp ops
|
||||||
|
1bit
|
||||||
|
calling conventions:
|
||||||
|
r0-r1 : return registers
|
||||||
|
r2-r11: call args
|
||||||
|
r12 : stack pos
|
||||||
|
r13-15:interrupt reserved (only adressable in interrupt mode)
|
||||||
|
caller pushes desired return addr
|
||||||
|
to stack, callee jumps to it
|
||||||
|
|
||||||
|
Interrupts:
|
||||||
|
Hardware interrupts:
|
||||||
|
0x0 : Invalid instruction
|
||||||
|
The 15 other interrupts are free to
|
||||||
|
define by the user
|
||||||
|
On interrupt (either called through
|
||||||
|
the bus or itp)
|
||||||
|
startup:
|
||||||
|
the cpu will look
|
||||||
|
at adress 0x0,and
|
||||||
|
expects to find :
|
||||||
|
-0x0-1: adress of
|
||||||
|
the starting
|
||||||
|
point,will be
|
||||||
|
jumped to
|
||||||
|
-0x2-3: adress of
|
||||||
|
the stack, the
|
||||||
|
adress will be
|
||||||
|
read here
|
||||||
|
everytime
|
||||||
|
-0x4-5:adress of
|
||||||
|
the interrupt
|
||||||
|
handler, the
|
||||||
|
adress will be
|
||||||
|
read here
|
||||||
|
everytime
|
||||||
|
When an interrupt is raised, the cpu will allow acces
|
||||||
|
to r12-15 and push the resume adress to stack (in
|
||||||
|
order pc0 then pc1)
|
||||||
|
|
||||||
|
instructions :
|
||||||
|
format:
|
||||||
|
rm,rn: general purpose registers
|
||||||
|
#imm:immediate signed 8bit value
|
||||||
|
*rm:memory at adress (pc+rm)
|
||||||
|
*#imm:memory at adress (pc+#imm)
|
||||||
|
sr: pr,ac
|
||||||
|
sr0-1: pr0-1/ac0-1, in/id
|
||||||
|
st: stack adress that is at 0x2,
|
||||||
|
abreviation for explanation only
|
||||||
|
nop :
|
||||||
|
0b0000000000000000
|
||||||
|
0x0000
|
||||||
|
No-OP:
|
||||||
|
Does nothing
|
||||||
|
1 clock
|
||||||
|
mov rm,rn:
|
||||||
|
0b00100000mmmmnnnn
|
||||||
|
0x20mn
|
||||||
|
MOVe :
|
||||||
|
rm <- rn
|
||||||
|
1 clock
|
||||||
|
mov rn,#imm:
|
||||||
|
0b1000nnnnmmmmmmmm
|
||||||
|
0x8nmm
|
||||||
|
rn <- #imm
|
||||||
|
1 clock
|
||||||
|
mov rm,*rn:
|
||||||
|
0b11000000mmmmnnnn
|
||||||
|
0xB0mn
|
||||||
|
rm <- *(pc+rn)
|
||||||
|
1 clock
|
||||||
|
mov rn,*#imm:
|
||||||
|
0b1001nnnnmmmmmmmm
|
||||||
|
0x9nmm
|
||||||
|
rn <- *(pc+#imm)
|
||||||
|
1 clock
|
||||||
|
mov *rm,rn:
|
||||||
|
0b11000001mmmmnnnn
|
||||||
|
0xB1mn
|
||||||
|
*(pc+rm) <- rn
|
||||||
|
1 clock
|
||||||
|
mov *#imm,rn:
|
||||||
|
0b1010nnnnmmmmmmmm
|
||||||
|
0xAnmm
|
||||||
|
*(pc+#imm) <- rn
|
||||||
|
1 clock
|
||||||
|
mov *rm,*rn:
|
||||||
|
0b11000010mmmmnnnn
|
||||||
|
0xB2mn
|
||||||
|
*(pc+rm) <- *(pc+rn)
|
||||||
|
1 clock
|
||||||
|
mmv rm, *sr:
|
||||||
|
0b11000011mmmmssss
|
||||||
|
0xB3ms
|
||||||
|
Memory MoVe
|
||||||
|
rm <- *sr
|
||||||
|
Meant to be used with the accumulator
|
||||||
|
1 clock
|
||||||
|
mmv *sr, rm:
|
||||||
|
0b11000100ssssmmmm
|
||||||
|
0xB4sm
|
||||||
|
*sr <- rm
|
||||||
|
Meant to be used with the accumulator
|
||||||
|
1 clock
|
||||||
|
psh rm:
|
||||||
|
0b11000101mmmm0000
|
||||||
|
0xB5m0
|
||||||
|
PuSH to stack:
|
||||||
|
*(st+r11) <- rm
|
||||||
|
r11 <- r11+1
|
||||||
|
2 clocks
|
||||||
|
pop rm:
|
||||||
|
0b11000110mmmm0000
|
||||||
|
0xB6m0
|
||||||
|
POP from stack
|
||||||
|
r11 <- r11-1
|
||||||
|
rm <- *(st+r11)
|
||||||
|
2 clocks
|
||||||
|
lds sr0-1,rm:
|
||||||
|
0b11100000ssssmmmm
|
||||||
|
0xE0sm
|
||||||
|
LoaD Special :
|
||||||
|
sr0-1 <- rm
|
||||||
|
nop on pc
|
||||||
|
1 clock
|
||||||
|
sts rm,sr0-1:
|
||||||
|
0b11100001mmmmssss
|
||||||
|
0xE1ms
|
||||||
|
STore Special :
|
||||||
|
rm <- sr0-1
|
||||||
|
1 clock
|
||||||
|
add rn,rm:
|
||||||
|
0b01000000nnnnmmmm
|
||||||
|
0x40nm
|
||||||
|
ADD :
|
||||||
|
rn <- rn+rm
|
||||||
|
1 clock
|
||||||
|
add r0,#imm:
|
||||||
|
0b01001000mmmmmmmm
|
||||||
|
0x48mm
|
||||||
|
r0 <- r0+#imm
|
||||||
|
1 clock
|
||||||
|
sad sr0-1,rm:
|
||||||
|
0b11100010ssssmmmm
|
||||||
|
0xE2sm
|
||||||
|
Special ADd
|
||||||
|
sr0-1 <- sr0-1+rm
|
||||||
|
(16bit add)
|
||||||
|
nop on pc
|
||||||
|
1 clock
|
||||||
|
sub rm,rn:
|
||||||
|
0b01000001mmmmnnnn
|
||||||
|
0x41mn
|
||||||
|
SUBstract :
|
||||||
|
rm <- rm-rn
|
||||||
|
1 clock
|
||||||
|
shl rm:
|
||||||
|
0b01000010mmmm0000
|
||||||
|
0x42m0
|
||||||
|
SHift Left
|
||||||
|
rm <- rm<<1
|
||||||
|
pure shift, no keep sign
|
||||||
|
1 clock
|
||||||
|
shr rm:
|
||||||
|
0b01000011mmmm0000
|
||||||
|
0x43m0
|
||||||
|
SHift Right
|
||||||
|
rm <- rm>>1
|
||||||
|
pure shift, no keep sign
|
||||||
|
1 clock
|
||||||
|
and rm,rn:
|
||||||
|
0b01000100mmmmnnnn
|
||||||
|
0x44mn
|
||||||
|
binary AND :
|
||||||
|
rm <- rm&rn
|
||||||
|
1 clock
|
||||||
|
or rm,rn:
|
||||||
|
0b01000101mmmmnnnn
|
||||||
|
0x45mn
|
||||||
|
binary OR :
|
||||||
|
rm <- rm|rn
|
||||||
|
1 clock
|
||||||
|
xor rm,rn:
|
||||||
|
0b01000110mmmmnnnn
|
||||||
|
0x46mn
|
||||||
|
binary eXclusive OR:
|
||||||
|
rm <- rm^rn
|
||||||
|
1 clock
|
||||||
|
not rm:
|
||||||
|
0b01000111mmmmnnnn
|
||||||
|
0x47mn
|
||||||
|
binary NOT :
|
||||||
|
rm <- !rm
|
||||||
|
binary not
|
||||||
|
1 clock
|
||||||
|
rtb :
|
||||||
|
0b0110000000000000
|
||||||
|
0x6000
|
||||||
|
Reset T Bit :
|
||||||
|
t <- 0
|
||||||
|
1 clock
|
||||||
|
gth rm,rn:
|
||||||
|
0b01100001mmmmnnnn
|
||||||
|
0x61mn
|
||||||
|
Greater THan :
|
||||||
|
t <- rm > rn ? 1:0
|
||||||
|
1 clock
|
||||||
|
gts rm,rn:
|
||||||
|
0b01100100mmmmnnn
|
||||||
|
0x64mn
|
||||||
|
Greater Than (Signed):
|
||||||
|
t <- rm > rn ? 1:0
|
||||||
|
(signed) (signed)
|
||||||
|
1 clock
|
||||||
|
eql rm,rn:
|
||||||
|
0b01100010mmmmnnnn
|
||||||
|
0x62mn
|
||||||
|
EQuaL :
|
||||||
|
t <- rm == rn ? 1:0
|
||||||
|
1 clock
|
||||||
|
stb rm:
|
||||||
|
0b01100011mmmm0000
|
||||||
|
0x63m0
|
||||||
|
Store T Bit:
|
||||||
|
rm <- t
|
||||||
|
1 clock
|
||||||
|
br *rm:
|
||||||
|
0b10110010mmmm0000
|
||||||
|
0x32m0
|
||||||
|
BRanch :
|
||||||
|
pc <- pc + rm *2
|
||||||
|
(signed)
|
||||||
|
1 clock
|
||||||
|
br *#imm:
|
||||||
|
0b10110000mmmmmmmm
|
||||||
|
0x30mm
|
||||||
|
pc <- pc + #imm*2
|
||||||
|
1 clock
|
||||||
|
bt *rm:
|
||||||
|
0b10110101mmmm0000
|
||||||
|
0x35m0
|
||||||
|
Branch if True:
|
||||||
|
If t == 1,
|
||||||
|
pc <- pc + rm *2
|
||||||
|
(signed)
|
||||||
|
else is nop
|
||||||
|
1 clock
|
||||||
|
bt *#imm:
|
||||||
|
0b10110001mmmmmmmm
|
||||||
|
0x31mm
|
||||||
|
If t == 1,
|
||||||
|
pc <- pc + #imm*2
|
||||||
|
else is nop
|
||||||
|
1 clock
|
||||||
|
bf *rm:
|
||||||
|
0b10110011mmmm0000
|
||||||
|
0x33m0
|
||||||
|
Branch if False:
|
||||||
|
If t == 0,
|
||||||
|
pc <- pc + rm *2
|
||||||
|
(signed)
|
||||||
|
else is nop
|
||||||
|
1 clock
|
||||||
|
jmp *sr:
|
||||||
|
0b10110100ssss0000
|
||||||
|
0x34s0
|
||||||
|
JuMP :
|
||||||
|
pc <- sr
|
||||||
|
nop on pc
|
||||||
|
2 clocks
|
||||||
|
itp rm:
|
||||||
|
0b01110001mmmm0000
|
||||||
|
0x71m0
|
||||||
|
InTerruPt :
|
||||||
|
Raises interrupt of id
|
||||||
|
rm
|
||||||
|
6 clocks
|
||||||
|
dsi :
|
||||||
|
0b0111001000000000
|
||||||
|
0x7200
|
||||||
|
DiSable Interrupts:
|
||||||
|
Disables interrupts
|
||||||
|
1 clock
|
||||||
|
eni :
|
||||||
|
0b0111001100000000
|
||||||
|
0x7300
|
||||||
|
ENable Interrupts:
|
||||||
|
Enables interrupts
|
||||||
|
1 clock
|
||||||
|
rgi rm:
|
||||||
|
0b01110000mmmm0000
|
||||||
|
0x70m0
|
||||||
|
ReGister Interrupt :
|
||||||
|
rm should be as follows:
|
||||||
|
bit 0 : raisable by itp
|
||||||
|
bit 1 : raisable by bus
|
||||||
|
Sets rm to id on succes,
|
||||||
|
and 0xFF on failure
|
||||||
|
2 clocks
|
Loading…
Reference in a new issue