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