diff options
| author | mrb0nk500 <b0nk@b0nk.xyz> | 2019-12-14 23:58:01 -0500 | 
|---|---|---|
| committer | mrb0nk500 <b0nk@b0nk.xyz> | 2019-12-14 23:58:01 -0500 | 
| commit | 0b81224b6ab8cd6da45039525962c6490ed2df56 (patch) | |
| tree | a76bfa10ee6ae726efb212442a68c17b253b49ba | |
| parent | c6d71bcf0e545a490fdeb0dfcafea2d5a02157c6 (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-- | Makefile | 2 | ||||
| -rw-r--r-- | asmmon.c | 25 | ||||
| -rw-r--r-- | opcode.h | 4 | ||||
| -rw-r--r-- | sux.c | 207 | ||||
| -rw-r--r-- | test/hello-world.s | 5 | ||||
| -rw-r--r-- | test/input.s | 127 | 
6 files changed, 335 insertions, 35 deletions
@@ -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 : @@ -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) { @@ -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", @@ -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 +  | 
