summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2019-12-14 23:58:01 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2019-12-14 23:58:01 -0500
commit0b81224b6ab8cd6da45039525962c6490ed2df56 (patch)
treea76bfa10ee6ae726efb212442a68c17b253b49ba
parentc6d71bcf0e545a490fdeb0dfcafea2d5a02157c6 (diff)
We now have keyboard support!!!
I also added the WAI instruction, which puts the thread that executed it, into a catatonic stat, where it can't do anything, until an interrupt occurs. I will be starting work on GFsuX next. I also might start work on SuBAsm, the Sux Bootstrapping Assembler.
-rw-r--r--Makefile2
-rw-r--r--asmmon.c25
-rw-r--r--opcode.h4
-rw-r--r--sux.c207
-rw-r--r--test/hello-world.s5
-rw-r--r--test/input.s127
6 files changed, 335 insertions, 35 deletions
diff --git a/Makefile b/Makefile
index d2764cd..7266284 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ CFLAGS = $(PCC_CFLAGS) $(CFLAGS_EXTRA)
OBJS = asmmon.o sux.o
OBJ_NAME = cisc-0.2
all : $(OBJS)
- $(CC) $(OBJS) $(CFLAGS) -lpthread -o $(OBJ_NAME)
+ $(CC) $(OBJS) $(CFLAGS) -lpthread -lcurses -o $(OBJ_NAME)
sux.o :
$(CC) sux.c -c $(CFLAGS) -o sux.o
asmmon.o :
diff --git a/asmmon.c b/asmmon.c
index 7467985..422d8ce 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -4,7 +4,7 @@
#define debug 1
-#define OPNUM 88
+#define OPNUM 89
#define SETOP(num, _mne, _IMM, _ZM, _ZMX, _ZMY, _ABS, _IMPL) \
{opcodes[num].mnemonic[3] = '\0'; strncpy(opcodes[num].mnemonic, _mne, 3); \
opcodes[num].imm = _IMM; \
@@ -123,7 +123,7 @@ void viewmem(uint64_t address) {
printf("\n");
}
}
-int asmmon() {
+int asmmon(const char *fn) {
opent opcodes[OPNUM];
/* mne IMM ZM ZMX ZMY ABS IMPL*/
SETOP(0, "CPS", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
@@ -210,10 +210,17 @@ int asmmon() {
SETOP(81, "DAY", 0x00, 0xF3, 0x00, 0x00, 0xF1, 0xD3);
SETOP(82, "DEX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4);
SETOP(83, "DAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5);
- SETOP(84, "JSL", 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00);
- SETOP(85, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8);
- SETOP(86, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0);
- SETOP(87, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8);
+ SETOP(84, "WAI", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8);
+ SETOP(85, "JSL", 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00);
+ SETOP(86, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8);
+ SETOP(87, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0);
+ SETOP(88, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8);
+ FILE *fp;
+ if (strcasecmp(fn, "stdin") != 0) {
+ fp = fopen(fn, "r");
+ if (fp == NULL)
+ return 2;
+ }
uint8_t done = 0;
uint64_t address = 0x0000;
while (!(done & 1)) {
@@ -231,7 +238,11 @@ int asmmon() {
char *tmp = malloc(sizeof(char *)*128);
size_t size;
done &= ~0x1F;
- getline(&buf, &size, stdin);
+ if (!strcasecmp(fn, "stdin")) {
+ getline(&buf, &size, stdin);
+ } else {
+ getline(&buf, &size, fp);
+ }
cmd = strtok_r(buf, "\n", &tmp);
if (cmd != NULL) {
if (strcasecmp(cmd, "done") == 0) {
diff --git a/opcode.h b/opcode.h
index 92d504c..a759ff8 100644
--- a/opcode.h
+++ b/opcode.h
@@ -77,7 +77,7 @@
#define CPX 0xB4 /* ComPare X register. */
#define CAX 0xB5 /* Compare Accumulator, and X register. */
#define ENT 0xB8 /* ENd Threads. */
-#define RTI 0xC0 /* ReTurn from Interupt. */
+#define RTI 0xC0 /* ReTurn from Interrupt. */
#define INC 0xC1 /* INCrement accumulator. */
#define INY 0xC2 /* INcrement Y register. */
#define IAY 0xC3 /* Increment Accumulator, and Y register. */
@@ -88,6 +88,7 @@
#define DAY 0xD3 /* Decrement Accumulator, and Y register. */
#define DEX 0xD4 /* DEcrement X register. */
#define DAX 0xD5 /* Decrement Accumulator, and X register. */
+#define WAI 0xD8 /* WAit for Interrupt. */
#define JSL 0xE0 /* Jump to Subroutine Long. */
#define NOP 0xE8 /* No OPeration. */
#define RTL 0xF0 /* ReTurn from subroutine Long. */
@@ -265,6 +266,7 @@ static const char *opname[0x100] = {
OPNAME(DAY),
OPNAME(DEX),
OPNAME(DAX),
+ OPNAME(WAI),
OPNAME(JSL),
[0xE1] = "INC a",
[0xE2] = "CPY a",
diff --git a/sux.c b/sux.c
index 452c8fa..21ac0ca 100644
--- a/sux.c
+++ b/sux.c
@@ -1,24 +1,38 @@
#include "opcode.h"
#include <assert.h>
+#include <curses.h>
#include <string.h>
#include <pthread.h>
#define bench 0
#define debug 0
#define IO 1
+#define en_nc 1
#if bench
#include <sys/time.h>
#endif
#define THREADS 1
#define BENCH_INST 100000000*THREADS
-#define DATA_ADDR 0xC001
+#define CTRL_ADDR 0xC000
+#define TX_ADDR 0xC001
+#define RX_ADDR 0xC002
+#define CURSES_BACKSPACE 0x7F
+
uint64_t clk[THREADS]; /* Per Thread Clock cycles. */
uint64_t tclk; /* Total Clock cycles. */
uint64_t inst[THREADS];
uint64_t inss;
uint8_t threads_done = 0;
+uint8_t kbd_rdy = 0;
+uint8_t wai = 0;
+uint8_t irq = 0;
+#if en_nc
+WINDOW *scr;
+#endif
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t main_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+pthread_cond_t main_cond = PTHREAD_COND_INITIALIZER;
struct suxthr {
struct sux sx;
uint8_t th;
@@ -44,10 +58,36 @@ void *run(void *args) {
char *s = malloc(2048);
uint8_t lines = (6*thread)+2;
uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */
+ int x = 0, y = 0;
#if bench
gettimeofday(&str[thread], 0);
#endif
while (!end) {
+ #if en_nc
+ if (wai) {
+ for (int8_t i = 56; i >= 0; i-=8) {
+ if (i)
+ addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread]-1 >> i;
+ else
+ addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread]-1 & 0xFF;
+ cpu->sp[thread]--;
+ }
+ addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->ps >> 8*thread;
+ cpu->sp[thread]--;
+ cpu->i[thread] = 1;
+ (cpu->i[thread]) ? (cpu->ps |= (I << 8*thread)) : (cpu->ps &= ~(I << 8*thread));
+ cpu->pc[thread] = (uint64_t)addr[0xFFA0]
+ | (uint64_t)addr[0xFFA1] << 8
+ | (uint64_t)addr[0xFFA2] << 16
+ | (uint64_t)addr[0xFFA3] << 24
+ | (uint64_t)addr[0xFFA4] << 32
+ | (uint64_t)addr[0xFFA5] << 40
+ | (uint64_t)addr[0xFFA6] << 48
+ | (uint64_t)addr[0xFFA7] << 56;
+ wai = 0;
+ kbd_rdy &= (uint8_t)~(1 << thread);
+ }
+ #endif
prefix = addr[cpu->pc[thread]];
if ((prefix & 0x07) == 0x07)
cpu->pc[thread]++;
@@ -56,16 +96,21 @@ void *run(void *args) {
opcode = addr[cpu->pc[thread]];
#if debug && !bench
- sprintf(s, "\033[%uH"
+ /*sprintf(s, "\033[%uH"
"pc: 0x%08llx, a: 0x%016llx, x: 0x%016llx, y: 0x%016llx"
", sp: 0x%04lx, ps: 0x%016llx, prefix: 0x%02x, opcode: 0x%02x, thread: %u, inst: %s \r"
, lines
, cpu->pc[thread], cpu->a[thread], cpu->x[thread], cpu->y[thread]
, cpu->sp[thread], cpu->ps, prefix, opcode, thread, opname[opcode]);
- fwrite(s, sizeof(char), strlen(s), stdout);
+ fwrite(s, sizeof(char), strlen(s), stdout);*/
+ mvwprintw(scr, lines, 0, "pc: 0x%08llx, a: 0x%016llx, x: 0x%016llx, y: 0x%016llx"
+ ", sp: 0x%04lx, ps: 0x%016llx, prefix: 0x%02x, opcode: 0x%02x, thread: %u, inst: %s \r"
+ , cpu->pc[thread], cpu->a[thread], cpu->x[thread], cpu->y[thread]
+ , cpu->sp[thread], cpu->ps, prefix, opcode, thread, opname[opcode]);
+ wrefresh(scr);
lines++;
- if (lines > 6*(thread+1))
- lines = (6*thread)+2;
+ if (lines > 24*(thread+1))
+ lines = (24*thread)+2;
#endif
uint8_t rs = (prefix & 0x30) >> 4;
@@ -716,14 +761,38 @@ void *run(void *args) {
value = cpu->y[thread];
if (opcode == STX || opcode == 0x7E || opcode == 0x9E)
value = cpu->x[thread];
-
addr[address] = value & 0xFF;
#if IO
- if (address == DATA_ADDR) {
+ if (address == TX_ADDR) {
+ /*if (addr[address] == '\r') {
+ waddch(context->screen, '\n');
+ }*/
+ #if en_nc
+ if (addr[address] == CURSES_BACKSPACE || addr[address] == '\b') {
+ if (x > 0) {
+ x--;
+ wmove(scr, y, x);
+ }
+ wdelch(scr);
+ wrefresh(scr);
+ } else {
+ wmove(scr, y, x);
+ waddch(scr, addr[address]);
+ wrefresh(scr);
+ if (addr[address] == '\n') {
+ x = 0;
+ y+=1;
+ } else {
+ x+=1;
+ }
+ /*putchar(addr[address]);*/
+ }
+ #else
if (addr[address] == '\b')
putchar('\b');
else
putchar(addr[address]);
+ #endif
}
#endif
if (regsize >= 2)
@@ -1207,7 +1276,7 @@ void *run(void *args) {
if ((value >> i) & 1)
cpu->pc[i+1] = cpu->pc[0]+(i+1);
break;
- case RTI: /* ReTurn from Interupt routine. */
+ case RTI: /* ReTurn from Interrupt routine. */
cpu->sp[thread]++;
cpu->ps = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 8*thread;
for (uint8_t i = 0; i < 64; i+=8) {
@@ -1365,12 +1434,7 @@ void *run(void *args) {
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->ps >> 8*thread;
cpu->sp[thread]--;
cpu->i[thread] = 1;
- (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread));
- (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread));
(cpu->i[thread]) ? (cpu->ps |= (I << 8*thread)) : (cpu->ps &= ~(I << 8*thread));
- (cpu->s[thread]) ? (cpu->ps |= (S << 8*thread)) : (cpu->ps &= ~(S << 8*thread));
- (cpu->v[thread]) ? (cpu->ps |= (V << 8*thread)) : (cpu->ps &= ~(V << 8*thread));
- (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread));
cpu->pc[thread] = (uint64_t)addr[0xFFE0]
| (uint64_t)addr[0xFFE1] << 8
| (uint64_t)addr[0xFFE2] << 16
@@ -1380,6 +1444,15 @@ void *run(void *args) {
| (uint64_t)addr[0xFFE6] << 48
| (uint64_t)addr[0xFFE7] << 56;
break;
+ case WAI: /* WAit for Interrupt. */
+ wai = 1;
+ pthread_mutex_lock(&main_mutex);
+ pthread_cond_signal(&main_cond);
+ pthread_mutex_unlock(&main_mutex);
+ pthread_mutex_lock(&mutex);
+ pthread_cond_wait(&cond, &mutex);
+ pthread_mutex_unlock(&mutex);
+ break;
default:
if(opcode != BRK) {
/*printf("Cool, you inputed a non existent opcode, which means\n"
@@ -1390,9 +1463,11 @@ void *run(void *args) {
}
ins++;
#if debug && !bench
- sprintf(s, "\033[%uHInstructions executed: %llu, Clock cycles: %llu\n", (6*thread)+1, ins, iclk);
+ /*sprintf(s, "\033[%uHInstructions executed: %llu, Clock cycles: %llu\n", (6*thread)+1, ins, iclk);
fwrite(s, sizeof(char), strlen(s), stdout);
- fflush(stdout);
+ fflush(stdout);*/
+ mvwprintw(scr, (24*thread)+1, 0, "Instructions executed: %llu, Clock cycles: %llu\r", ins, iclk);
+ wrefresh(scr);
#endif
#if bench
if (ins >= BENCH_INST) {
@@ -1401,7 +1476,7 @@ void *run(void *args) {
threads_done++;
inst[thread] = ins;
clk[thread] = iclk;
- pthread_cond_signal(&cond);
+ pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&mutex);
gettimeofday(&en[thread], 0);
}
@@ -1418,8 +1493,33 @@ int main(int argc, char **argv) {
inss = 0;
int v = 0;
- if (asmmon() == 2)
- return 0;
+ if (argc != 2) {
+ if (asmmon("stdin") == 2)
+ return 0;
+ } else {
+ if (asmmon(argv[1]) == 2)
+ return 0;
+ }
+ sprintf(tmp, "\033[2J\033[H");
+ fwrite(tmp, sizeof(char), strlen(tmp), stdout);
+ fflush(stdout);
+ #if en_nc
+ if(!scr)
+ scr = initscr();
+ nodelay(stdscr, 0);
+ crmode();
+ noecho();
+ nl();
+ curs_set(0);
+ werase(scr);
+ scrollok(scr, 1);
+ wrefresh(scr);
+ start_color();
+ use_default_colors();
+ init_pair(1, COLOR_WHITE, -1);
+ attron(COLOR_PAIR(1) | A_BOLD);
+ wmove(scr, 0, 0);
+ #endif
for (int i = 0; i < THREADS; i++) {
thr[i].sx.sp[i] = 0xFFFF;
thr[i].sx.stk_st[i] = i+1;
@@ -1450,25 +1550,80 @@ int main(int argc, char **argv) {
}
thr[i].th = i;
}
+ pthread_t therads[THREADS];
+ int result;
for (int i = 0; i < THREADS; i++) {
inst[i] = 0;
}
- pthread_t therads[THREADS];
- int result;
- sprintf(tmp, "\033[2J\033[H");
- fwrite(tmp, sizeof(char), strlen(tmp), stdout);
- fflush(stdout);
for (int i = 0; i < THREADS; i++) {
result = pthread_create(&therads[i], NULL, run, &thr[i]);
assert(!result);
}
- pthread_mutex_lock(&mutex);
+ int c = 0;
while (threads_done < THREADS) {
- pthread_cond_wait(&cond, &mutex);
+ int x, y, i = 0;
+ #if !bench
+ if ((c != EOF && c !=-1)) {
+ pthread_mutex_lock(&main_mutex);
+ pthread_cond_wait(&main_cond, &main_mutex);
+ pthread_mutex_unlock(&main_mutex);
+ c = 0;
+ }
+ #if en_nc
+ getyx(scr, y, x);
+ attroff(A_REVERSE);
+ attron(A_BLINK);
+ wprintw(scr, "_");
+ attroff(A_BLINK);
+ wmove(scr, y, x);
+ wrefresh(scr);
+
+ c = wgetch(scr);
+
+ /*wmove(scr, 0, getmaxx(scr) - 1);
+ attron(A_REVERSE);
+ wprintw(scr, "!");
+ attroff(A_REVERSE);
+ wmove(scr, y, x);
+ wrefresh(scr);*/
+ switch (c) {
+ case ERR:
+ kbd_rdy = 0;
+ wmove(scr, getmaxy(scr)-1, 0);
+ wprintw(scr, "c: %i, x: %i, y: %i, i: %i.", c, x, y, i++);
+ wmove(scr, y, x);
+ wrefresh(scr);
+ break;
+ default:
+ addr[RX_ADDR] = (uint8_t)c;
+ kbd_rdy = 1 << 0;
+ pthread_mutex_lock(&mutex);
+ pthread_cond_broadcast(&cond);
+ pthread_mutex_unlock(&mutex);
+ break;
+ }
+ #else
+ c = getchar();
+ if (c != EOF) {
+ sprintf(tmp, "\033[24Hc: %i\r", c);
+ fwrite(tmp, sizeof(char), strlen(tmp), stdout);
+ fflush(stdout);
+ kbd_rdy = 1 << 0;
+ pthread_mutex_lock(&mutex);
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&mutex);
+ }
+ #endif
+ #else
+
+ #endif
}
- pthread_mutex_unlock(&mutex);
#if bench
if (threads_done == THREADS) {
+ #if en_nc
+ scr = NULL;
+ endwin();
+ #endif
double tm_sec, tm_usec, tm[THREADS], ttm;
double clkspd;
double mhz;
diff --git a/test/hello-world.s b/test/hello-world.s
index 465583c..9138bc7 100644
--- a/test/hello-world.s
+++ b/test/hello-world.s
@@ -6,6 +6,11 @@
string:
.byte "Hello, world!\n"
+; Text buffer.
+.org $2000
+buffer:
+
+
; Get CPU into a known state.
.org $0
reset:
diff --git a/test/input.s b/test/input.s
new file mode 100644
index 0000000..9e5ef69
--- /dev/null
+++ b/test/input.s
@@ -0,0 +1,127 @@
+; Testing input.
+;
+; Writen in Sux assembly by
+; mr b0nk 500 <b0nk@b0nk.xyz>
+
+
+; Initalize some variables.
+.org $1000
+string:
+ .byte "Please, type something.\n"
+string2:
+ .byte "You typed, "
+end:
+ .byte $0
+
+; Input buffer.
+.org $2000
+buffer:
+
+; Main program
+.org $0
+reset:
+ cps
+ ldx.w #$FFFF
+ txs
+ ldy #$0
+clr_buf:
+ lda #$0
+ cpy.w #$1000
+ beq start
+ sta buffer, y
+ iny
+ jmp clr_buf
+
+start:
+ ldx.w #$0 ; Reset x.
+ ldy #$0 ; Reset y.
+ jmp print
+
+sleep:
+ wai ; Sleep until we get a character.
+ lda end
+ bne spin ; Are we done with getting input?
+ jmp sleep ; Loop until we get a newline.
+
+print:
+ lda string, x ; Get character at offset x.
+ beq sleep ; Did we find a null terminator?
+ sta $C001 ; Print character.
+ inx ; Increment offset.
+ jmp print ; Keep printing more characters.
+
+irq_routine:
+ lda $C002 ; Get typed character.
+ cmp #$A
+ beq nl ; Did the user type a newline?
+ cmp #$8
+ beq bs ; Did the user type a backspace?
+echo:
+ sta $C001 ; Echo typed character.
+ sta buffer, y ; Store typed character into the input buffer.
+ iny ; Increment buffer offset.
+return:
+ rti ; End of interrupt routine.
+
+nl:
+ sta $C001
+ lda #$0 ; Replace newline with a null terminator.
+ sta buffer, y ; Store said terminator into the input buffer.
+ ldy.w #$0 ; Reset y, to print the result.
+ jmp result
+
+bs:
+ cpy #$0
+ beq return ; Are we at the start of the buffer?
+ jmp echo ; We are not, so add the backspace to the buffer.
+
+result:
+ lda string2, y
+ beq rset_y ; Reset y, if we hit the null terminator.
+ sta $C001 ; Print 'You have typed, '
+ iny ; Increment offset.
+ jmp result ; Keep printing.
+
+rset_y:
+ ldy.w #$0
+ jmp print_buf ; Print the input buffer.
+
+print_buf:
+ lda buffer, y ; Get a character from the input buffer.
+ beq fin ; Are we done with printing the buffer?
+ sta $C001 ; Print said character.
+ iny
+ jmp print_buf ; Keep printing the buffer.
+
+fin:
+ lda #$A ; Load a newline.
+ sta $C001 ; Print the newline.
+ lda #$1 ; Tell the program that we are done.
+ sta end ; We are done.
+
+
+spin:
+ nop
+ nop
+ nop
+ jmp spin
+
+.org $FFC0
+.qword reset
+
+.org $FF50
+.qword spin
+.qword spin
+.qword spin
+.qword spin
+.qword spin
+.qword spin
+.qword spin
+
+.org $FFA0
+.qword irq_routine
+;.org $0
+;viewmem
+;q
+done
+