diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | asmmon.c | 554 | ||||
| -rw-r--r-- | asmmon.h | 79 | ||||
| -rw-r--r-- | assemble.c | 378 | ||||
| -rw-r--r-- | disasm.c | 53 | ||||
| -rw-r--r-- | lexer.c | 506 | ||||
| -rw-r--r-- | programs/subasm-2.s | 323 | ||||
| -rw-r--r-- | programs/subasm.s | 1019 | ||||
| -rw-r--r-- | programs/subeditor.s | 302 | ||||
| -rw-r--r-- | sux.c | 6 | ||||
| -rw-r--r-- | sux.h | 8 | 
11 files changed, 1343 insertions, 1887 deletions
@@ -36,7 +36,7 @@ IO_CFLAGS=-DIO=0  endif -OBJS = sux.o opcode.o io.o $(DBG_OBJ) asmmon.o lexer.o +OBJS = sux.o opcode.o io.o $(DBG_OBJ) asmmon.o assemble.o lexer.o  CFLAGS = $(PCC_CFLAGS) $(DBG_CFLAGS) $(IO_CFLAGS) $(BENCH_CFLAGS) $(CFLAGS_EXTRA)  OBJS2 = subasm.o subeditor.o @@ -13,7 +13,8 @@ char lexeme[MAX_TOK];  char *string[MAX_TOK];  char *comment[MAX_TOK];  uint16_t incl[MAX_TOK]; -struct line tokline[MAX_TOK]; +line *lines; +line *last_line;  struct line tln[MAX_TOK];  struct symbol *symbols[MAX_TOK];  struct fixup *fixups[MAX_TOK]; @@ -109,8 +110,9 @@ char *showbits(uint64_t value, uint8_t bitnum, uint8_t dbg) {  } -void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) { -	uint16_t i = start; +void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) { +	line *s = find_line(start, dbg); +	line *e = find_line(end, dbg);  	uint8_t j = 0;  	uint8_t flags = 0;  	uint8_t isstr; @@ -125,31 +127,24 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,  	char ch[6];  	if (all) { -		end = lineidx; +		s = lines; +		e = last_line;  	} -	for (; i < end; i++) { -		flags = 0; -		flags |= (l[i].dir    != 0x00FF) << 0; -		flags |= (l[i].mne    != 0x00FF) << 1; -		flags |= (l[i].rs     != 0x00FF) << 2; -		flags |= (l[i].am     != 0x00FF) << 3; -		flags |= (l[i].opbase != 0x00FF) << 4; -		flags |= (l[i].sym    != 0xFFFF) << 5; -		flags |= (l[i].rs     != 0x00FF) << 6; -		flags |= (l[i].am     != 0x00FF) << 7; -		iscm = l[i].cm != 0xFF; -		isstr = l[i].str != 0xFFFF; -		iscom = l[i].com != 0xFFFF; + +	do { +		token *t = s->tok; +		uint8_t am = 0xFF; +		uint8_t rs = 0xFF;  		if (dbg) {  			printf("list(): ");  		}  		if (ln) { -			printf("%u\t", l[i].linenum); +			printf("%u\t", s->linenum);  		} else if (addr) { -			printf("$%"PRIX64":\t", l[i].addr); +			printf("$%"PRIX64":\t", s->addr);  		} -		spaces = l[i].sspace; -		tabs = l[i].stab; +		spaces = s->sspace; +		tabs = s->stab;  		while (spaces || tabs) {  			if (spaces) {  				putchar(' '); @@ -160,136 +155,89 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,  				tabs--;  			}  		} -		if (flags & 0x01) { -			printf(".%s ", dir_t[l[i].dir]); -			if (isstr) { -				printf("\"%s\"", string[l[i].str]); -			} -		} -		if (flags & 0x02) { -			for (; j < 3; j++) { -				mne_lower[j] = tolower(mne[l[i].mne][j]); -			} -			mne_lower[j] = '\0'; -			j = 0; -			printf("%s", mne_lower); -		} -		if (flags & 0x04) { -			printf("%s ", rs_t[l[i].rs]); -		} else if (flags & 0x02) { -			printf(" "); -		} -		if (flags & 0x7F) { -			switch (l[i].am) { -				case IMM: -					putchar('#'); +		for (; t && t->id != TOK_COMMENT; t = t->next) { +			switch (t->id) { +				case TOK_DIR   : printf(".%s ", dir_t[t->type]); break; +				case TOK_STRING: printf("\"%s\"", t->str)      ; break; +				case TOK_OPCODE: +					for (; j < 3; j++) { +						mne_lower[j] = tolower(mne[t->byte][j]); +					} +					mne_lower[j] = '\0'; +					j = 0; +					printf("%s", mne_lower); +					am = t->type; +					t = t->next; +					if (t->id == TOK_RS) { +						rs = t->type; +						printf("%s", rs_t[t->type]); +					} +					switch (am) { +						case IMM : putchar('#'); break; +						case IND : +						case INDX: +						case INDY: putchar('('); break; +					}  					break; -				case INDX: -				case INDY: -				case IND: -					putchar('('); +				case TOK_SYM: +				case TOK_LABEL: +					printf("%s", symbols[t->word]->name); +					if (t->id == TOK_LABEL) { +						putchar(':'); +					} else if (t == s->tok && t->id == TOK_SYM) { +						printf(" = "); +					}  					break; -			} -		} -		if (flags & 0x20) { -			printf("%s", symbols[l[i].sym]->name); -			if (l[i].islabel) { -				printf(": "); -			} else if (l[i].issym) { -				printf(" = "); -			} -		} -		if (flags & 0x10) { -			if (flags & 0x04) { -				bitnum = (l[i].rs << 3); -			} else { -				opsize += (l[i].op <= 0x000000FF) + 0; -				opsize += (l[i].op >  0x000000FF) + 1; -				opsize += (l[i].op >  0x0000FFFF) + 2; -				opsize += (l[i].op >  0xFFFFFFFF) + 3; -				if (opsize) { -					bitnum = bitsize[opsize-1]; -				} -			} - -			j = 0; - -			if (l[i].opbase == BASE_CHAR) { -				switch (l[i].op) { -					default  : ch[j++] = l[i].op;              break; -					case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; -					case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; -					case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; -					case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; -					case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; -					case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; -				} -			} - -			ch[j] = '\0'; -			j = 0; - -			switch (l[i].opbase) { -				case BASE_HEX:  printf("$%"PRIX64, l[i].op); break; -				case BASE_DEC:  printf("%"PRIu64, l[i].op); break; -				case BASE_BIN:  printf("%%%s", showbits(l[i].op, bitnum, dbg)); break; -				case BASE_CHAR: printf("\'%s\'", ch); break; -			} -			bitnum = 0; -			opsize = 0; -		} -		if (iscm) { -			switch (l[i].cm) { -				case 0: -					putchar('+'); +				case TOK_HEX: printf("$%"PRIX64, t->qword); break; +				case TOK_DEC: printf( "%"PRIu64, t->qword); break; +				case TOK_BIN: +					if (rs != 0xFF) { +						bitnum = (rs << 3); +					} else { +						opsize += (t->qword <= 0x000000FF) + 0; +						opsize += (t->qword >  0x000000FF) + 1; +						opsize += (t->qword >  0x0000FFFF) + 2; +						opsize += (t->qword >  0xFFFFFFFF) + 3; +						if (opsize) { +							bitnum = bitsize[opsize-1]; +						} +					} +					printf("%%%s", showbits(t->qword, bitnum, dbg)); +					bitnum = 0; +					opsize = 0;  					break; -				case 1: -					putchar ('-'); +				case TOK_CHAR: +					j = 0; +					switch (t->byte) { +						default  : ch[j++] = t->byte;              break; +						case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; +						case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; +						case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; +						case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; +						case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; +						case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; +					} +					ch[j] = '\0'; +					j = 0; +					printf("\'%s\'", ch); +					break; +				case TOK_EXPR: +					switch (t->type) { +						case EXPR_PLUS : putchar('+'); break; +						case EXPR_MINUS: putchar('-'); break; +					}  					break;  			} -			opsize += (l[i].aop <= 0x000000FF) + 0; -			opsize += (l[i].aop >  0x000000FF) + 1; -			opsize += (l[i].aop >  0x0000FFFF) + 2; -			opsize += (l[i].aop >  0xFFFFFFFF) + 3; -			if (opsize) { -				bitnum = bitsize[opsize-1]; -			} - -			j = 0; - -			if (l[i].aopbase == BASE_CHAR) { -				switch (l[i].aop) { -					default  : ch[j++] = l[i].aop;             break; -					case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; -					case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; -					case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; -					case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; -					case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; -					case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; -				} -			} - -			ch[j] = '\0'; -			j = 0; - -			switch (l[i].aopbase) { -				case BASE_HEX : printf("$%"PRIX64, l[i].aop); break; -				case BASE_DEC : printf("%"PRIu64, l[i].aop); break; -				case BASE_BIN : printf("%%%s", showbits(l[i].aop, bitnum, dbg)); break; -				case BASE_CHAR: printf("\'%s\'", ch); break; -			} -			bitnum = 0; -			opsize = 0;  		} -		if (flags & 0x7F) { +		if (am != 0xFF) {  			if (fall) {  				fall = 0;  			} -			switch (l[i].am) { +			switch (am) {  				case INDX:  				case ZMX:  					printf(", x"); -					if (l[i].am == ZMX) { +					if (am == ZMX) {  						break;  					}  					fall = 1; @@ -308,8 +256,8 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,  					break;  			}  		} -		spaces = l[i].espace; -		tabs = l[i].etab; +		spaces = s->espace; +		tabs = s->etab;  		while (spaces || tabs) {  			if (spaces) {  				putchar(' '); @@ -320,302 +268,12 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,  				tabs--;  			}  		} -		if (iscom) { -			printf(";%s", comment[l[i].com]); +		if (t->id == TOK_COMMENT) { +			printf(";%s", t->str);  		}  		puts(""); -	} -} - -void assemble(struct line *line, bytecount *bc, uint8_t dbg) { -	bc->progsize = 0; -	bc->datasize = 0; -	uint64_t tmpaddr; -	uint64_t value; -	uint16_t flags = 0; -	uint16_t i = 0; -	uint16_t k = 0; -	uint16_t tmp; -	uint8_t c = 0; -	uint8_t prefix = 0; -	uint8_t opsize = 0; -	uint8_t skip = 0; - -	uint64_t address; -	uint64_t op; -	uint64_t aop; -	uint16_t symid; -	uint16_t str; -	uint16_t com; -	uint8_t islabel; -	uint8_t opbase; -	uint8_t aopbase; -	uint8_t dir; -	uint8_t am; -	uint8_t cm; -	uint8_t rs; -	uint8_t ins; - -	for (; i < lineidx; i++) { -		if (dbg) { -			printf("assemble(): i: $%X\n", i); -		} -		address = line[i].addr; -		tmpaddr = address; -		op = line[i].op; -		aop = line[i].aop; -		symid = line[i].sym; -		str = line[i].str; -		com = line[i].com; -		islabel = line[i].islabel; -		opbase = line[i].opbase; -		aopbase = line[i].aopbase; -		dir = line[i].dir; -		am = line[i].am; -		cm = line[i].cm; -		rs = line[i].rs; -		ins = line[i].mne; -		flags = 0; -		flags |= (dir     != 0x00FF) << 0x00; -		flags |= (ins     != 0x00FF) << 0x01; -		flags |= (rs      != 0x00FF) << 0x02; -		flags |= (am      != 0x00FF) << 0x03; -		flags |= (opbase  != 0x00FF) << 0x04; -		flags |= (aopbase != 0x00FF) << 0x05; -		flags |= (symid   != 0xFFFF) << 0x06; -		flags |= (islabel          ) << 0x07; -		flags |= (am      != 0x00FF) << 0x08; -		flags |= (cm      != 0x00FF) << 0x09; -		flags |= (str     != 0xFFFF) << 0x0A; -		if (dbg) { -			printf("assemble(): "); -			putchar('%'); -                	printf("%u", str     != 0xFFFF); -                	printf("%u", cm      != 0x00FF); -                	printf("%u", am      != 0x00FF); -                	printf("%u", islabel          ); -                	printf("%u", symid   != 0xFFFF); -                	printf("%u", aopbase != 0x00FF); -                	printf("%u", opbase  != 0x00FF); -                	printf("%u", am      != 0x00FF); -                	printf("%u", rs      != 0x00FF); -                	printf("%u", ins     != 0x00FF); -			printf("%u", dir     != 0x00FF); -			putchar('\n'); - -			printf("assemble(): "); -			printf("flags: $%04X\n", flags); -		} -		if (!flags) { -			if (dbg) { -				printf("assemble(): "); -				puts("This line only contains a comment, so skip it."); -			} -			continue; -		} -		opsize = 0; -		skip = 0; -		if ((flags & 0x53) == 0x42 || (flags & 0x51) == 0x41) { -			value = symbols[symid]->val; -		} else { -			value = op; -		} -		if (flags & 0x220) { -			switch (cm) { -				case 0: value += aop; break; -				case 1: value -= aop; break; -			} -		} -		if (dbg) { -			printf("assemble(): value: $%"PRIX64"\n", value); -		} -		switch (dir) { -			case DIR_ORG: -				tmpaddr = value; -				if (dbg) { -					printf("assemble(): "); -					printf("The Program Counter's origin is now at, $%"PRIX64".\n", value); -				} -				skip = 1; -				break; -			case DIR_BYTE: -				if (flags & 0x400) { -					for (k = 0; string[str][k] != '\0'; k++) { -						switch (string[str][k]) { -							case '\\': -								switch (string[str][k+1]) { -									case 'n': c = '\n'; break; -									case 'r': c = '\r'; break; -									case 't': c = '\t'; break; -									case '0': c = '\0'; break; -								} -								k++; -								break; -							default: -								c = string[str][k]; -								break; -						} -						bc->datasize++; -						addr[tmpaddr++] = c; -					} -					addr[tmpaddr] = '\0'; -					if (dbg) { -						printf("assemble(): "); -						printf("Placed string \"%s\"", string[str]); -						printf(", at address(es) $%"PRIX64"-$%"PRIX64".\n", address, tmpaddr); -					} -				} else { -					bc->datasize++; -					addr[tmpaddr++] = value & 0xFF; -				} -				break; -			case DIR_QWORD: -				addr[tmpaddr+7] = value >> 0x38; -				addr[tmpaddr+6] = value >> 0x30; -				addr[tmpaddr+5] = value >> 0x28; -				addr[tmpaddr+4] = value >> 0x20; -				tmp+=4; -				bc->datasize+=4; -			case DIR_DWORD: -				addr[tmpaddr+3] = value >> 0x18; -				addr[tmpaddr+2] = value >> 0x10; -				tmp+=2; -				bc->datasize+=2; -			case DIR_WORD: -				addr[tmpaddr+1] = value >> 0x08; -				addr[tmpaddr  ] = value  & 0xFF; -				tmp+=2; -				bc->datasize+=2; -				break; -		} -		tmpaddr += tmp; -		tmp = 0; -		if (skip | (flags & 0x80) | (flags == 0x108)) { -			if (dbg) { -				printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address); -				printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr); -			} -			continue; -		} -		if (flags & 0x04) { -			prefix = (rs << 4) | 3; -		} else { -			rs = 0; -		} -		if (flags & 0x102) { -			if (ins == 80) { -				if (flags & 0x10) { -					am =  IMM; -					prefix |= 0x13; -				} else { -					am = IMPL; -					addr[tmpaddr++] = opcodes[ins][IMM]; -					bc->progsize++; -					if (dbg) { -						printf("assemble(): The instruction that is being used is, %s.\n", mne[ins]); -						printf("assemble(): The addressing mode that this instruction is using is, %s.\n", adrmode[IMM]); -						printf("assemble(): The opcode for this instruction, and addressing mode is, $%02X.\n", opcodes[ins][IMM]); -					} -				} -			} -			opsize = 0; -			if (am != IMM && am != IMPL) { -				opsize = (value <= 0x00000000000000FF) ? 1 : opsize; -				opsize = (value >  0x00000000000000FF) ? 2 : opsize; -				opsize = (value >  0x000000000000FFFF) ? 3 : opsize; -				opsize = (value >  0x0000000000FFFFFF) ? 4 : opsize; -				opsize = (value >  0x00000000FFFFFFFF) ? 5 : opsize; -				opsize = (value >  0x000000FFFFFFFFFF) ? 6 : opsize; -				opsize = (value >  0x0000FFFFFFFFFFFF) ? 7 : opsize; -				opsize = (value >  0x00FFFFFFFFFFFFFF) ? 8 : opsize; -				if (opsize) { -					opsize--; -					prefix |= amp[opsize]; -				} -			} -			if (prefix) { -				if (dbg) { -					printf("assemble(): "); -					  puts("Prefix byte detected."); -				} -				addr[tmpaddr++] = prefix; -				bc->progsize++; -				if (dbg) { -					uint8_t addrsize = (prefix & 0x0C) >> 2; -					uint8_t regsize  = (prefix & 0x30) >> 4; - -					printf("assemble(): "); -					printf("The values of the prefix bits are"); -					printf(", AM: %u, RS: %u\n", addrsize, regsize); -				} -				prefix = 0; -			} -			if (opcodes[ins][am] != 0xFF) { -				addr[tmpaddr++] = opcodes[ins][am]; -				bc->progsize++; -				if (dbg) { -					printf("assemble(): The instruction that is being used is, %s.\n", mne[ins]); -					printf("assemble(): The addressing mode that this instruction is using is, %s.\n", adrmode[am]); -					printf("assemble(): The opcode for this instruction, and addressing mode is, $%02X.\n", opcodes[ins][am]); -				} -				switch (am) { -					case IMM: -						switch (rs) { -							case 3: -								addr[tmpaddr+7] = value >> 0x38; -								addr[tmpaddr+6] = value >> 0x30; -								addr[tmpaddr+5] = value >> 0x28; -								addr[tmpaddr+4] = value >> 0x20; -								tmp+=4; -							case 2: -								addr[tmpaddr+3] = value >> 0x18; -								addr[tmpaddr+2] = value >> 0x10; -								tmp+=2; -							case 1: -								addr[tmpaddr+1] = value >> 0x08; -								tmp+=1; -							case 0: -								addr[tmpaddr  ] = value  & 0xFF; -								tmp+=1; -						} -						break; -					case ABS: -					case ZM: -					case ZMX: -					case ZMY: -					case IND: -					case INDX: -					case INDY: -						switch (opsize) { -							case 7: addr[tmpaddr+7] = value >> 0x38; tmp++; -							case 6: addr[tmpaddr+6] = value >> 0x30; tmp++; -							case 5: addr[tmpaddr+5] = value >> 0x28; tmp++; -							case 4: addr[tmpaddr+4] = value >> 0x20; tmp++; -							case 3: addr[tmpaddr+3] = value >> 0x18; tmp++; -							case 2: addr[tmpaddr+2] = value >> 0x10; tmp++; -							case 1: addr[tmpaddr+1] = value >> 0x08; tmp++; -							case 0: addr[tmpaddr  ] = value  & 0xFF; tmp++; -						} -						break; -				} -				tmpaddr += tmp; -				bc->progsize += tmp; -				tmp = 0; -			} -		} -		if (dbg) { -			printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address); -			printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr); - -			printf("assemble(): The program size is now at"); -			printf(", %"PRIu64" bytes in decimal", bc->progsize); -			printf(", and $%"PRIX64" bytes in hex.\n", bc->progsize); - -			printf("assemble(): The data size is now at"); -			printf(", %"PRIu64" bytes in decimal", bc->datasize); -			printf(", and $%"PRIX64" bytes in hex.\n", bc->datasize); -		} -	} +		s = s->next; +	} while (s != e && s);  }  int asmmon(const char *fn) { @@ -700,6 +358,9 @@ int asmmon(const char *fn) {  					if (fp2 != NULL) {  						fclose(fp2);  					} +					if (lines) { +						free_lines(); +					}  					return 2;  				case 0x02:  					viewmem(address); @@ -727,12 +388,12 @@ int asmmon(const char *fn) {  								for (; isspace(tmp[i]); i++);  							}  							switch (tmp[i]) { -								case '$': base = BASE_HEX; i++; break; -								case '%': base = BASE_BIN; i++; break; +								case '$': base = 16; i++; break; +								case '%': base =  2; i++; break;  								default:  									j = i;  									for (; isdigit(tmp[j]); j++, isflag++); -									base = (isflag) ? BASE_DEC : 0xFF; +									base = (isflag) ? 10 : 0xFF;  									isflag = 0;  									j = 0;  									break; @@ -741,11 +402,7 @@ int asmmon(const char *fn) {  							arg[j] = '\0';  							j = 0;  							if (base != 0xFF) { -								switch (base) { -									case BASE_HEX: value = strtol(arg, NULL, 16); break; -									case BASE_BIN: value = strtol(arg, NULL,  2); break; -									case BASE_DEC: value = strtol(arg, NULL, 10); break; -								} +								value = strtol(arg, NULL, base);  								base = 0xFF;  								(isstart) ? (start = value) : (end = value);  								if (isstart) { @@ -765,15 +422,15 @@ int asmmon(const char *fn) {  							}  							i++;  						} -						list(tokline, start, end, isstart, islinenum, isaddr, isdebug); +						list(start, end, isstart, islinenum, isaddr, isdebug);  					} else { -						list(tokline, 0, 0, 1, 0, 0, 0); +						list(0, 0, 1, 0, 0, 0);  					}  					break;  				case 0x08:  					if (!inc_file) {  						printf("Assembling %s\n", (strcasecmp(fn, "stdin")) ? fn : "typed in program."); -						assemble(tokline, &bc, dbg); +						assemble(lines, &bc, dbg);  						progsize = bc.progsize;  						datasize = bc.datasize;  						printf("Finished assembling %s\n", (strcasecmp(fn, "stdin")) ? fn : "typed in program."); @@ -846,7 +503,7 @@ int asmmon(const char *fn) {  				case 0xFF:  					break;  				default: -					address = lex(lex_line, tokline, address, dbg); +					address = lex(lex_line, address, dbg);  					break;  			}  		} @@ -860,5 +517,8 @@ int asmmon(const char *fn) {  	if (fp2 != NULL) {  		fclose(fp2);  	} +	if (lines) { +		free_lines(); +	}  	return 0;  } @@ -28,9 +28,40 @@ struct line {  	uint64_t addr;  }; +struct tok { +	struct tok *next;	/* Pointer to the next token. */ +	uint8_t id;		/* Token ID.      */ +	uint8_t type;		/* Token type ID. */ + +	/* Token value(s). */ +	union { +		char *str; +		uint8_t  byte ; +		uint16_t word ; +		uint32_t dword; +		uint64_t qword; +	}; +}; + +struct ln { +	struct ln  *next;	/* Pointer to the next line.   */ +	struct tok *tok;	/* The token(s) for this line. */ +	uint16_t count;		/* Total tokens for this line. */ +	uint16_t linenum;	/* Line number.                */ +	uint64_t addr;		/* The address of this line.   */ +	uint8_t stab;		/* Number of starting tabs.    */ +	uint8_t sspace;		/* Number of starting spaces.  */ +	uint8_t etab;		/* Number of ending tabs.      */ +	uint8_t espace;		/* Number of ending spaces.    */ +}; + +typedef struct tok token; +typedef struct ln  line; + +  struct fixup {  	struct symbol *s; -	uint16_t ln; +	token *t;  	uint64_t adr;  }; @@ -45,6 +76,10 @@ extern char lexeme[];  extern char *string[];  extern char *comment[];  extern uint16_t incl[]; +extern line *lines; +extern line *last_line; +extern token *tokens; +extern token *last_tok;  extern struct line tokline[];  extern struct line tln[];  extern struct symbol *symbols[]; @@ -52,7 +87,7 @@ extern struct fixup *fixups[];  extern uint8_t lex_type; -enum { +enum dir {  	DIR_ORG,  	DIR_BYTE,  	DIR_WORD, @@ -61,12 +96,12 @@ enum {  	DIR_INCLUDE  }; -enum { +enum token {  	TOK_DIR,  	TOK_LABEL,  	TOK_SYM, -	TOK_PLUS, -	TOK_MINUS, +	TOK_EXPR, +	TOK_COMMA,  	TOK_STRING,  	TOK_CHAR,  	TOK_IMM, @@ -79,11 +114,12 @@ enum {  	TOK_INCLUDE  }; -enum { -	BASE_HEX, -	BASE_DEC, -	BASE_BIN, -	BASE_CHAR +enum expr { +	EXPR_PLUS, +	EXPR_MINUS, +	EXPR_LOW, +	EXPR_HIGH, +	EXPR_NONE  };  static const uint8_t opcodes[OPNUM][9] = { @@ -200,8 +236,8 @@ static const char *lex_tok[15] = {  	[0x0] = "TOK_DIR",  	[0x1] = "TOK_LABEL",  	[0x2] = "TOK_SYM", -	[0x3] = "TOK_PLUS", -	[0x4] = "TOK_MINUS", +	[0x3] = "TOK_EXPR", +	[0x4] = "TOK_COMMA",  	[0x5] = "TOK_STRING",  	[0x6] = "TOK_CHAR",  	[0x7] = "TOK_IMM", @@ -437,10 +473,12 @@ extern uint16_t stridx;  extern uint16_t comidx;  extern uint16_t inc_file; /* Number of included files. */ -typedef struct { +struct bc {  	uint64_t progsize;  	uint64_t datasize; -} bytecount; +}; + +typedef struct bc bytecount;  extern uint8_t defined;  extern uint8_t isfixup; @@ -450,7 +488,14 @@ extern uint16_t mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t us  extern uint64_t use_symbol(const char *name, uint16_t id, uint64_t val, uint8_t useid, uint8_t dbg);  extern uint8_t set_symval(const char *name, uint16_t id, uint64_t val, uint8_t useid, uint8_t dbg);  extern char *get_symname(uint16_t id, uint8_t dbg); -extern uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg); +extern uint16_t get_symid(const char *name, uint64_t val, token *t, uint8_t dbg);  extern uint16_t get_comment(const char *cmnt, uint8_t dbg); -extern uint16_t reslv_fixups(struct line *l, uint8_t dbg); -extern uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg); +extern uint16_t reslv_fixups(uint8_t dbg); +extern line *find_line(uint16_t ln, uint8_t dbg); +extern uint64_t lex(char *str, uint64_t address, uint8_t dbg); + +extern uint64_t parse_tokens(token *tm, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg); +extern token *make_token(uint8_t id, uint8_t type, uint64_t value, char *str); +extern void assemble(line *ln, bytecount *bc, uint8_t dbg); +extern void free_tokens(token *t, uint16_t count); +extern void free_lines(); diff --git a/assemble.c b/assemble.c new file mode 100644 index 0000000..869e6b8 --- /dev/null +++ b/assemble.c @@ -0,0 +1,378 @@ +#include "asmmon.h" + +token *tok_global; + +uint8_t isexpr(uint8_t type, uint8_t dbg) { +	switch (type) { +		case EXPR_PLUS: +		case EXPR_MINUS: +			return 1; +		default: +			return 0; +	} +} + +uint8_t get_rs(token *t, uint8_t inst, uint8_t dbg) { +	if (t->id == TOK_RS) { +		return t->type; +	} else { +		return 0xFF; +	} +} + +uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { +	uint64_t value = 0; +	uint64_t tmp_val = 0; +	uint16_t expr_count = 0; +	uint8_t type = EXPR_NONE; +	do { +		if (expr_count) { +			type = t->type; +			t = t->next; +		} +		switch (t->id) { +			case TOK_HEX: +			case TOK_DEC: +			case TOK_BIN: +			case TOK_CHAR: +				tmp_val = t->qword; +				t = t->next; +				break; +			case TOK_SYM: +			case TOK_LABEL: +				tmp_val = use_symbol("", t->word, addr, 1, dbg); +				t = t->next; +				break; +		} +		switch (type) { +			case EXPR_PLUS : value += tmp_val; break; +			case EXPR_MINUS: value -= tmp_val; break; +			case EXPR_LOW  : +				switch (size) { +					default: +					case 2 : value &= 0xFFFFFFFF; break; +					case 1 : value &= 0x0000FFFF; break; +					case 0 : value &= 0x000000FF; break; +				} +				break; +			case EXPR_HIGH : +				switch (size) { +					default: +					case 2 : value >>= 0x20; break; +					case 1 : value >>= 0x10; break; +					case 0 : value >>= 0x08; break; +				} +				break; +			case EXPR_NONE : value  = tmp_val; break; +		} +		expr_count++; +		if (!t) { +			break; +		} +	} while (t->id == TOK_EXPR && isexpr(t->type, dbg)); +	return value; +} + +uint8_t get_dirsize(uint8_t type, uint8_t dbg) { +	uint8_t size = 0; +	switch (type) { +		case DIR_QWORD: size = 3; break; +		case DIR_DWORD: size = 2; break; +		case DIR_WORD : size = 1; break; +		case DIR_BYTE : size = 0; break; +	} +	return size; +} + +uint64_t handle_dir(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) { +	union reg val; +	uint8_t c = 0; +	uint8_t tmp = 0; +	uint8_t type = t->type; +	uint64_t tmpaddr = address; +	t = t->next; +	for (; t; t = t->next) { +		tmp = 0; +		switch (t->id) { +			case TOK_HEX: +			case TOK_DEC: +			case TOK_BIN: +			case TOK_CHAR: +			case TOK_SYM: +			case TOK_LABEL: +				val.u64 = get_val(t, tmpaddr, get_dirsize(type, dbg), dbg); +				switch (type) { +					case DIR_QWORD: +						if (isasm) { +							addr[tmpaddr+7] = val.u8[7]; +							addr[tmpaddr+6] = val.u8[6]; +							addr[tmpaddr+5] = val.u8[5]; +							addr[tmpaddr+4] = val.u8[4]; +						} +						tmp += 4; +					case DIR_DWORD: +						if (isasm) { +							addr[tmpaddr+3] = val.u8[3]; +							addr[tmpaddr+2] = val.u8[2]; +						} +						tmp += 2; +					case DIR_WORD: +						if (isasm) { +							addr[tmpaddr+1] = val.u8[1]; +						} +						tmp++; +					case DIR_BYTE: +						if (isasm) { +							addr[tmpaddr  ] = val.u8[0]; +						} +						tmp++; +						tmpaddr += tmp; +						bc->datasize += tmp; +						break; +				} +				break; +			case TOK_STRING: +				if (type == DIR_BYTE) { +					for (uint16_t k = 0; t->str[k] != '\0'; k++) { +						switch (t->str[k]) { +							case '\\': +								switch (t->str[k+1]) { +									case 'n': c = '\n'; break; +									case 'r': c = '\r'; break; +									case 't': c = '\t'; break; +									case '0': c = '\0'; break; +								} +								k++; +								break; +							default: c = t->str[k]; break; +						} +						if (isasm) { +							addr[tmpaddr] = c; +						} +						tmpaddr++; +						bc->datasize++; +					} +					if (isasm) { +						addr[tmpaddr] = '\0'; +					} +					tmpaddr++; +					bc->datasize++; +				} +				break; +		} +	} +	return tmpaddr; +} + +uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) { +	union reg val; +	uint8_t opsize; +	uint8_t inst; +	uint8_t opcode; +	uint8_t type; +	uint8_t tmp = 0; +	uint8_t prefix = 0; +	uint8_t rs = 0; + +	for (; t; t = t->next) { +		if (t->id == TOK_OPCODE) { +			inst = t->byte; +			type = t->type; +		} else { +			break; +		} +		tmp = 0; +		opsize = 0; +		opcode = 0; +		if (t->next) { +			rs = get_rs(t->next, inst, dbg); +			t = (rs != 0xFF) ? t->next : t; +		} +		prefix = (rs != 0xFF) ? ((rs << 4) | 3) : 0; +		if (opcodes[inst][IMPL] != 0xFF && (!t->next || t->next->id == TOK_COMMENT)) { +			type = IMPL; +		} else { +			if (t->next) { +				t = t->next; +			} +			val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg); +		} +		opcode = opcodes[inst][type]; +		if (inst == 80) { +			if (type == IMM) { +				rs = 1; +			} else { +				type = IMPL; +				opcode = opcodes[inst][IMM]; +			} +		} +		switch (type) { +			case IMPL: +				if (isasm) { +					addr[address] = opcode; +				} +				address++; +				bc->progsize++; +				break; +			case IMM: +				if (prefix) { +					if (isasm) { +						addr[address] = prefix; +					} +					address++; +				} +				if (isasm) { +					addr[address] = opcode; +				} +				address++; +				bc->progsize++; +				switch (rs) { +					case 3: +						if (isasm) { +							addr[address+7] = val.u8[7]; +							addr[address+6] = val.u8[6]; +							addr[address+5] = val.u8[5]; +							addr[address+4] = val.u8[4]; +						} +						tmp += 4; +					case 2: +						if (isasm) { +							addr[address+3] = val.u8[3]; +							addr[address+2] = val.u8[2]; +						} +						tmp += 2; +					case 1 : +						if (isasm) { +							addr[address+1] = val.u8[1]; +						} +						tmp++; +					default: +						if (isasm) { +							addr[address  ] = val.u8[0]; +						} +						tmp++; +				} +				break; +			default: +				opsize = (val.u64 <= 0x00000000000000FF) ? 1 : opsize; +				opsize = (val.u64 >  0x00000000000000FF) ? 2 : opsize; +				opsize = (val.u64 >  0x000000000000FFFF) ? 3 : opsize; +				opsize = (val.u64 >  0x0000000000FFFFFF) ? 4 : opsize; +				opsize = (val.u64 >  0x00000000FFFFFFFF) ? 5 : opsize; +				opsize = (val.u64 >  0x000000FFFFFFFFFF) ? 6 : opsize; +				opsize = (val.u64 >  0x0000FFFFFFFFFFFF) ? 7 : opsize; +				opsize = (val.u64 >  0x00FFFFFFFFFFFFFF) ? 8 : opsize; +				if (type == 0xFF) { +					switch (opsize-1) { +						case 0: case 2: case 5: case 3: type = ZM ; break; +						case 1: case 4: case 6: case 7: type = ABS; break; +					} +				} +				if (opsize) { +					if (type != ABS) { +						switch (opsize) { +							case 2: opsize = 3; break; +							case 5: opsize = 6; break; +						} +					} +					prefix |= amp[opsize-1]; +				} +				if (prefix) { +					if (isasm) { +						addr[address] = prefix; +					} +					address++; +					bc->progsize++; +				} +				opcode = opcodes[inst][type]; +				if (isasm) { +					addr[address] = opcode; +				} +				address++; +				bc->progsize++; +				if (isasm) { +					switch (opsize-1) { +						case 7: addr[address+7] = val.u8[7]; +						case 6: addr[address+6] = val.u8[6]; +						case 5: addr[address+5] = val.u8[5]; +						case 4: addr[address+4] = val.u8[4]; +						case 3: addr[address+3] = val.u8[3]; +						case 2: addr[address+2] = val.u8[2]; +						case 1: addr[address+1] = val.u8[1]; +						case 0: addr[address  ] = val.u8[0]; +					} +				} +				tmp = opsize; +				break; +		} +		address += tmp; +		bc->progsize += tmp; +	} +	return address; +} + +uint64_t parse_tokens(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) { +	for (; t; t = t->next) { +		switch (t->id) { +			case TOK_DIR: +				switch (t->type) { +					case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break; +					case DIR_BYTE: +					case DIR_WORD: +					case DIR_DWORD: +					case DIR_QWORD: address = handle_dir(t, bc, isasm, address, dbg); break; +				} +				break; +			case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break; +			case TOK_COMMENT: break; +		} +	} +	return address; +} + +token *make_token(uint8_t id, uint8_t type, uint64_t value, char *str) { +	token *new_tok = malloc(sizeof(token)); +	(last_tok) ? (last_tok->next = new_tok) : (tokens = new_tok); +	new_tok->id = id; +	new_tok->type = type; +	if (!str[0]) { +		new_tok->qword = value; +	} else { +		new_tok->str = str; +	} +	new_tok->next = NULL; +	last_tok = new_tok; +	return new_tok; +} + +void assemble(line *ln, bytecount *bc, uint8_t dbg) { +	uint64_t address = 0; +	for (; ln; ln = ln->next) { +		address = parse_tokens(ln->tok, bc, 1, address, dbg); +	} +} + +void free_tokens(token *t, uint16_t count) { +	token *tok; +	while (t != NULL) { +		if (count--) { +			break; +		} +		tok = t; +		free(tok); +		t = t->next; +	} +} + +void free_lines() { +	line *l = lines; +	line *ln; +	for (; l != NULL; l = l->next) { +		if (l < ln) { +			break; +		} +		free_tokens(l->tok, l->count); +		ln = l; +		free(ln); +	} +} @@ -69,30 +69,45 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,  	if (subdbg) {  		uint8_t ln = 33;  		uint16_t line_idx = 0; -		uint16_t tmpad = 0x2000; +		uint32_t tmpad = 0x31000;  		int row, col;  		uint8_t iscursor = 0; -		uint64_t ptr; -		uint8_t adr; +		union reg ptr; +		uint32_t adr;  		wmove(scr, 30, 0); -		adr = 0x1F; -		ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | -		      (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; -		wprintw(scr, "ptr1: $%04"PRIX64, ptr); -		adr = 0x27; -		ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | -		      (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; -		wprintw(scr, ", ptr2: $%04"PRIX64, ptr); -		adr = 0x2F; -		ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | -		      (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; -		wprintw(scr, ", ptr3: $%04"PRIX64, ptr); +		wclrtoeol(scr); +		adr = 0x25; +		ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1]; +		ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3]; +		ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5]; +		ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7]; +		wprintw(scr, "ptr1: $%04"PRIX64, ptr.u64); +		adr = 0x2D; +		ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1]; +		ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3]; +		ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5]; +		ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7]; +		wprintw(scr, ", ptr2: $%04"PRIX64, ptr.u64); +		adr = 0x35; +		ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1]; +		ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3]; +		ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5]; +		ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7]; +		wprintw(scr, ", ptr3: $%04"PRIX64, ptr.u64); +		adr = 0x3349A; +		ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1]; +		ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3]; +		ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5]; +		ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7]; +		wprintw(scr, ", idx0: $%04"PRIX64, ptr.u64);  		if (address == CTRL_ADDR || addr[STEP_ADDR]) {  			mvwprintw(scr, 29, 0, "address: $%04"PRIX64", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u\r", address, addr[0], addr[1], addr[0x1C], addr[0x1D]); -			mvwprintw(scr, 32, 0, "bitabl: %02X%02X%02X%02X%02X%02X%02X%02X" -						"%02X%02X%02X%02X%02X%02X%02X%02X" -						, addr[0x1000], addr[0x1001], addr[0x1002], addr[0x1003], addr[0x1004], addr[0x1005], addr[0x1006], addr[0x1007] -						, addr[0x1008], addr[0x1009], addr[0x100A], addr[0x100B], addr[0x100C], addr[0x100D], addr[0x100E], addr[0x100F]); +			adr = 0x300000; +			wmove(scr, 32, 0); +			wprintw(scr, "bitabl: "); +			for (uint8_t i = 0; i < 16; i++) { +				wprintw(scr, "%02X", addr[adr+i]); +			}  			mvwprintw(scr, ln++, 0, "buffer:\r");  			wmove(scr, ln++, 0);  			for (uint8_t i = 0; i < 10; i++) { @@ -2,6 +2,8 @@  uint8_t lex_type;  uint16_t sym_count = 0; +token *tokens = NULL; +token *last_tok = NULL;  void init_symbol() {  	uint16_t i = 0; @@ -41,10 +43,8 @@ uint16_t mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t useid, ui  					printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s\n", def, val, name);  					printf("mksymbol(): i: $%X, id: $%04X\n", i, symbols[i]->id);  				} -				return symbols[i]->id; -			} else { -				return symbols[i]->id;  			} +			return symbols[i]->id;  		}  	}  	symbols[i] = malloc(sizeof(**symbols) + strlen(name)); @@ -123,8 +123,8 @@ char *get_symname(uint16_t id, uint8_t dbg) {  }  uint16_t fixup_cnt = 0; -uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg) { -	uint16_t i = mksymbol(name, 0, 0, 0, ln, dbg); +uint16_t get_symid(const char *name, uint64_t val, token *t, uint8_t dbg) { +	uint16_t i = mksymbol(name, 0, 0, 0, 0, dbg);  	if (dbg) {  		printf("get_symid(): Symbol ID: $%X, i: $%X.\n", symbols[i]->id, i);  	} @@ -136,7 +136,7 @@ uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg) {  		}  		fixups[fixup_cnt] = malloc(sizeof(**fixups));  		fixups[fixup_cnt]->adr = val; -		fixups[fixup_cnt]->ln = ln; +		fixups[fixup_cnt]->t = t;  		fixups[fixup_cnt]->s = symbols[i];  		fixup_cnt++;  		return 0xFFFF; @@ -196,14 +196,14 @@ uint16_t get_string(const char *str, uint8_t dbg) {  	return i;  } -uint16_t reslv_fixups(struct line *l, uint8_t dbg) { +uint16_t reslv_fixups(uint8_t dbg) {  	uint16_t i = 0, j = 0;  	for (; fixups[j]; j++) {  		if (fixups[j]->s->def) {  			if (dbg) { -				printf("reslv_fixups(): Symbol ID: $%X, Symbol Name: %s, Symbol Value: $%X.\n", fixups[j]->s->id, fixups[j]->s->name, fixups[j]->s->val); +				printf("reslv_fixups(): Symbol ID: $%X, Symbol Name: %s, Symbol Value: $%"PRIX64".\n", fixups[j]->s->id, fixups[j]->s->name, fixups[j]->s->val);  			} -			l[fixups[j]->ln].sym = fixups[j]->s->id; +			fixups[j]->t->word = fixups[j]->s->id;  		} else {  			if (dbg) {  				printf("reslv_fixups(): oof, undefined reference to '%s', at $%016"PRIX64".\n", fixups[j]->s->name, fixups[j]->adr); @@ -215,205 +215,40 @@ uint16_t reslv_fixups(struct line *l, uint8_t dbg) {  } -uint64_t update_addr(struct line *ln, uint64_t address, uint8_t fixup, uint16_t l, uint8_t dbg) { -	uint64_t value = 0; +line *find_line(uint16_t ln, uint8_t dbg) {  	uint16_t i = 0; -	uint16_t j = 0; -	uint16_t flags = 0; -	uint8_t opsize = 0; - -	uint16_t symid	= ln[l].sym; -	uint16_t str	= ln[l].str; -	uint16_t com	= ln[l].com; -	uint8_t islabel	= ln[l].islabel; -	uint8_t issym	= ln[l].issym; -	uint8_t opbase	= ln[l].opbase; -	uint8_t aopbase	= ln[l].aopbase; -	uint8_t dir	= ln[l].dir; -	uint8_t am	= ln[l].am; -	uint8_t cm	= ln[l].cm; -	uint8_t rs	= ln[l].rs; -	uint8_t mne	= ln[l].mne; - -	flags |= (dir     != 0x00FF) << 0x00; -	flags |= (mne     != 0x00FF) << 0x01; -	flags |= (rs      != 0x00FF) << 0x02; -	flags |= (am      != 0x00FF) << 0x03; -	flags |= (opbase  != 0x00FF) << 0x04; -	flags |= (aopbase != 0x00FF) << 0x05; -	flags |= (symid   != 0xFFFF) << 0x06; -	flags |= (fixup    > 0x0000) << 0x06; -	flags |= (islabel          ) << 0x07; -	flags |= (issym            ) << 0x07; -	flags |= (am      != 0x00FF) << 0x08; -	flags |= (cm      != 0x00FF) << 0x09; -	flags |= (str     != 0xFFFF) << 0x0A; - -	if (dbg) { -		printf("update_addr(): "); -		printf("flags: $%04X\n", flags); -	} -	if (!flags || flags == 0x40) { -		if (dbg) { -			printf("update_addr(): "); -			puts("This line only contains a comment, so don't update the address."); -		} -		return address; -	} -	if ((flags & 0x53) == 0x42 || (flags & 0x51) == 0x41) { -		if (fixup && symid == 0xFFFF && (opcodes[mne][IMPL] == 0xFF)) { -			value = address; -		} else if (opcodes[mne][IMPL] != 0xFF && symid == 0xFFFF) { -			value = 0; -		} else { -			value = use_symbol("", symid, address, 1, dbg); -		} -	} else { -		value = ln[l].op; -	} -	if (flags & 0x220) { -		switch (cm) { -			case 0: value += ln[l].aop; break; -			case 1: value -= ln[l].aop; break; +	line *l = lines; +	for (; l && l->linenum != ln; l = l->next); +	/*if (dbg) { +		if (l->linenum == ln) { +			printf("find_line(): Found line number %u, at line index %X.\n", ln, i);  		} -	} -	if (dbg) { -		printf("update_addr(): value: $%"PRIX64"\n", value); -	} -	switch (dir) { -		case DIR_ORG: -			address = value; +		printf("find_line(): linenum: %u, i: %X\n", l->linenum, i); +	}*/ +	if (l != NULL) { +		if (l->linenum == ln) {  			if (dbg) { -				printf("update_addr(): "); -				printf("Set the Program Counter's Origin to $%"PRIX64".\n", address); -			} -			break; -		case DIR_BYTE: -			if (flags & 0x400) { -				for (; string[str][i] != '\0'; i++, j++, address++) { -					i += string[str][i] == '\\'; -				} -				j++; -				address++; -				if (dbg) { -					printf("update_addr(): "); -					printf("Increment Program Counter by $%04X", j); -					  puts(", to make room for the string."); -				} -			} else { -				address += 1; +				printf("find_line(): Found line number %u.\n", ln);  			} -			break; -		case DIR_WORD:  address += 2; break; -		case DIR_DWORD: address += 4; break; -		case DIR_QWORD: address += 8; break; -	} -	if (flags & 0x01) { -		if (dbg) { -			printf("update_addr(): "); -			puts("This line contains a directive, so skip everything else."); -		} -		return address; -	} -	if ((flags & 0x15B) == 0x02 || (opcodes[mne][IMPL] != 0xFF && am == 0xFF && opbase == 0xFF && symid == 0xFFFF)) { -		ln[l].am = IMPL; -		am = IMPL; -		if (dbg) { -			printf("update_addr(): "); -			puts("Addressing Mode has been set to Implied."); -		} -	} -	if (am == IMPL) { -		opsize = 0; -	} else if (am == IMM) { -		switch (rs) { -			case 3:  address += 8; break; -			case 2:  address += 4; break; -			case 1:  address += 2; break; -			default: address += 1; break; +			return l;  		} +	} else {  		if (dbg) { -			if (!(flags & 0x04)) { -				rs = 0; -			} -			printf("update_addr(): "); -			printf("Increment Program Counter by $%02X", 1 << rs); -			  puts(", to make room for the operand."); -		} -	} else if ((flags & 0x158) && (!(flags & 0x80))) { -		opsize = 0; -		opsize = (value <= 0x00000000000000FF) ? 1 : opsize; -		opsize = (value >  0x00000000000000FF) ? 2 : opsize; -		opsize = (value >  0x000000000000FFFF) ? 3 : opsize; -		opsize = (value >  0x0000000000FFFFFF) ? 4 : opsize; -		opsize = (value >  0x00000000FFFFFFFF) ? 5 : opsize; -		opsize = (value >  0x000000FFFFFFFFFF) ? 6 : opsize; -		opsize = (value >  0x0000FFFFFFFFFFFF) ? 7 : opsize; -		opsize = (value >  0x00FFFFFFFFFFFFFF) ? 8 : opsize; -		if (opsize) { -			switch (opsize-1) { -				case 0: -				case 2: -				case 5: -				case 3: -					if (!(flags & 0x100)) { -						am = ZM; -						ln[l].am = am; -						if (dbg) { -							printf("update_addr(): "); -							puts("Addressing Mode has been set to Zero Matrix."); -						} -					} -					break; -				case 1: -				case 4: -				case 6: -				case 7: -					if (!(flags & 0x100)) { -						am = ABS; -						ln[l].am = am; -						if (dbg) { -							printf("update_addr(): "); -							puts("Addressing Mode has been set to Absolute."); -						} -					} -					break; -			} -			address += opsize; -			if (dbg) { -				printf("update_addr(): "); -				printf("Increment Program Counter by $%02X", opsize); -				  puts(", to make room for the address."); -			} -		} -	} -	if (dbg) { -		printf("update_addr(): "); -		printf("Address: $%"PRIX64"\n", address); -	} -	return address; -} - -uint16_t find_line(struct line *l, uint16_t ln, uint8_t dbg) { -	uint16_t i = 0; -	for (; i < lineidx && l[i].linenum != ln; i++); -	if (dbg) { -		if (l[i].linenum == ln) { -			printf("find_line(): Found line number %u, at line index %X.\n", ln, i); +			printf("find_line(): oof, could not find line number %u.\n", ln);  		} -		printf("find_line(): linenum: %u, i: %X\n", l[i].linenum, i); +		return NULL;  	} -	return i; +	return l;  } -uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { +uint64_t lex(char *str, uint64_t address, uint8_t dbg) {  	char sym[0x100];  	uint16_t i = 0;  	uint16_t j = 0;  	uint16_t comid = 0;  	uint16_t strid = 0;  	uint16_t symid = 0; -	uint16_t line = 0; +	uint64_t value = 0;  	lex_type = 0xFF;  	uint8_t k = 0; @@ -436,6 +271,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  	uint8_t isstart = 1;  	uint8_t fall = 0;  	uint8_t done = 0; +	line *l = NULL; +	token *st = NULL; +	token *t = NULL; +	token *lt = NULL;  	while (isdigit(str[i]) && !isspace(str[i])) {  		lnum[j++] = str[i++]; @@ -448,25 +287,18 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  	} else {  		ln = linenum;  	} -	line = find_line(l, ln, dbg); -	if (line != lineidx) { -		address = l[line].addr; +	l = find_line(ln, dbg); +	if (l) { +		address = l->addr; +	} else { +		l = malloc(sizeof(line)); +		(last_line) ? (last_line->next = l) : (lines = l); +		l->tok = NULL; +		l->next = NULL; +		l->count = 0; +		last_line = l; +  	} -	l[line].dir = 0xFF; -	l[line].mne = 0xFF; -	l[line].rs = 0xFF; -	l[line].am = 0xFF; -	l[line].cm = 0xFF; -	l[line].opbase = 0xFF; -	l[line].aopbase = 0xFF; -	l[line].islabel = 0; -	l[line].issym = 0; -	l[line].str = 0xFFFF; -	l[line].com = 0xFFFF; -	l[line].sym = 0xFFFF; -	l[line].op = 0; -	l[line].aop = 0; -	l[line].addr = address;  	while (str[i] != '\0' && str[i] != '\n') {  		base = 0;  		space = 0; @@ -481,10 +313,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  			printf("lex(): tab: %u, space: %u\n", tab, space);  		}  		if (isstart) { -			l[line].stab = tab; -			l[line].sspace = space; +			l->stab = tab; +			l->sspace = space;  			if (dbg) { -				printf("lex(): starting tabs: %u, starting spaces: %u\n", l[line].stab, l[line].sspace); +				printf("lex(): starting tabs: %u, starting spaces: %u\n", l->stab, l->sspace);  			}  		}  		if (isspace(str[i])) { @@ -506,7 +338,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  							break;  						}  					} -					l[line].dir = k; +					l->count++; +					t = make_token(lex_type, k, 0, "");  				} else {  					lex_type = TOK_RS;  					switch (tolower(lexeme[j-1])) { @@ -523,8 +356,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  							rs = 3;  							break;  					} -					address++; -					l[line].rs = rs; +					l->count++; +					t = make_token(lex_type, rs, 0, "");  					isop = 0;  				}  				break; @@ -535,59 +368,45 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  				}  				strid = get_string(lexeme, dbg);  				if (strid == 0xFFFF) { -					if (line != lineidx && l[line].str != 0xFFFF) { -						strid = l[line].str; -					} else { -						strid = stridx; -					} +					strid = stridx;  					string[strid] = malloc(j+1);  					memcpy(string[strid], lexeme, j+1); -					l[line].str = strid; -					stridx += (line == lineidx); +					stridx++;  				} else { -					l[line].str = strid;  				}  				if (dbg) {  					printf("lex(): str[0x%04X]: %s\n", strid, string[strid]);  				} -				if (l[line].dir == DIR_INCLUDE) { -					l[line].incl = strid; +				if (lt->id == TOK_DIR && lt->type == DIR_INCLUDE) {  					incl[inc_file++] = strid;  				}  				lex_type = TOK_STRING; +				l->count++; +				t = make_token(lex_type, 0, 0, string[strid]);  				break; -				if (str[i] == '$') { -			case '$':	base = 16; -				} else if (str[i] == '%') { -			case '%':	base = 2; -				} +			case '$': +			case '%': +				value = 0; +				base = (str[i] == '$') ? 16 : 2;  				i++; -				while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n')) { +				while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n' && str[i] != ',')) {  					lexeme[j++] = str[i++];  				}  				lexeme[j] = '\0'; -				switch (lex_type) { -					default: -						if (l[line].cm != 0xFF) { -					case TOK_PLUS : -					case TOK_MINUS:	l[line].aop = strtoull(lexeme, NULL, base); -							l[line].aopbase = (base & 16) ? BASE_HEX : BASE_BIN; -						} else { -					case TOK_SYM:	l[line].op = strtoull(lexeme, NULL, base); -							l[line].opbase = (base & 16) ? BASE_HEX : BASE_BIN; -						} -						if (lex_type == TOK_SYM) { -							mksymbol(sym, l[line].op, 1, 0, 0, dbg); -							l[line].sym = get_symid(sym, address, line, dbg); -							isfixup += (l[line].sym == 0xFFFF); -							if (dbg) { -								printf("lex(): isfixup: %u\n", isfixup); -							} -						} -						break; +				lex_type = (base == 16) ? TOK_HEX : TOK_BIN; +				value = strtoull(lexeme, NULL, base); +				if (lt->id == TOK_SYM) { +					mksymbol(sym, value, 1, 0, 0, dbg); +					if (lt) { +						lt->word = get_symid(sym, address, lt, dbg); +					} +					isfixup += (lt->word == 0xFFFF); +					if (dbg) { +						printf("lex(): isfixup: %u\n", isfixup); +					}  				} - -				lex_type = (base & 16) ? TOK_HEX : TOK_BIN; +				l->count++; +				t = make_token(lex_type, 0, value, "");  				break;  			case '\'':  				i++; @@ -611,37 +430,35 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  						break;  					default: ch = lexeme[k];  				} -				switch (lex_type) { -					case TOK_PLUS : -					case TOK_MINUS: -						l[line].aop	= ch; -						l[line].aopbase = BASE_CHAR; -						break; -					default: -						l[line].op	= ch; -						l[line].opbase	= BASE_CHAR; -						break; -				}  				lex_type = TOK_CHAR; +				l->count++; +				t = make_token(lex_type, 0, ch, "");  				break; -			case '(': -				if (str[i] == '#' || str[i] == '(') { -					if (str[i] == '#') { -			case '#':		lex_type   = TOK_IMM; -					} -					l[line].am = (str[i] == '#') ? IMM : IND; -				} else { +			case '(': l->tok->type = IND; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; +			case '#': l->tok->type = IMM; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break;  			case '+': -			case '-':	l[line].cm = (str[i] == '-'); -					lex_type   = (str[i] == '-') ? TOK_MINUS : TOK_PLUS; +			case '-': +			case '>': +			case '<': +				lex_type = TOK_EXPR; +				switch (str[i]) { +					case '+': value = EXPR_PLUS ; break; +					case '-': value = EXPR_MINUS; break; +					case '>': value = EXPR_LOW  ; break; +					case '<': value = EXPR_HIGH ; break;  				} +				l->count++; +				t = make_token(lex_type, value, 0, ""); +				memset(lexeme, 0, strlen(lexeme)+1); +				lexeme[j++] = str[i]; +				break; +			case '=': +				i++; +				lex_type = TOK_SYM; +				l->count++; +				t = make_token(lex_type, 0, 0, "");  				memset(lexeme, 0, strlen(lexeme)+1);  				lexeme[j] = str[i]; -				if (str[i] == '=') { -			case '=':	i++; -					l[line].issym = 1; -					lex_type = TOK_SYM; -				}  				break;  			case ')':  				i++; @@ -650,9 +467,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  					while (isspace(str[i])) {  						lexeme[j++] = str[i++];  					} -					if (l[line].am == IND && tolower(str[i]) == 'y') { +					if (l->tok->type == IND && tolower(str[i]) == 'y') {  						lexeme[j++] = 'y'; -						l[line].am = INDY; +						l->tok->type = INDY;  					}  					lexeme[j] = '\0';  				} else { @@ -666,20 +483,21 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  				while (isspace(str[i])) {  					lexeme[j++] = str[i++];  				} -				if (l[line].am == IND && tolower(str[i]) == 'x') { -					l[line].am = INDX; +				if (l->tok->type == IND && tolower(str[i]) == 'x') { +					l->tok->type = INDX;  					lexeme[j++] = 'x';  					i++;  				} else {  					switch (tolower(str[i])) {  						case 'x': -							l[line].am = ZMX; +							l->tok->type = ZMX;  							lexeme[j++] = 'x';  							break;  						case 'y': -							l[line].am = ZMY; +							l->tok->type = ZMY;  							lexeme[j++] = 'y';  							break; +						default: lex_type = TOK_COMMA; i--; break;  					}  				}  				lexeme[j] = '\0'; @@ -689,13 +507,14 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  				lexeme[j] = ':';  				lexeme[j+1] = '\0';  				lex_type = TOK_LABEL; -				l[line].islabel = 1; +				l->count++; +				t = make_token(lex_type, 0, 0, "");  				mksymbol(sym, address, 1, 0, 0, dbg);  				if (isfixup) { -					isfixup = reslv_fixups(l, dbg); +					isfixup = reslv_fixups(dbg);  				} -				l[line].sym = get_symid(sym, address, line, dbg); -				isfixup += (l[line].sym == 0xFFFF); +				t->word = get_symid(sym, address, t, dbg); +				isfixup += (t->word == 0xFFFF);  				if (dbg) {  					printf("lex(): isfixup: %u\n", isfixup);  				} @@ -708,22 +527,23 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  				lexeme[j] = '\0';  				comid = get_comment(lexeme, dbg);  				if (comid == 0xFFFF) { -					if (line != lineidx && l[line].com != 0xFFFF) { +					/*if (line != lineidx && l[line].com != 0xFFFF) {  						comid = l[line].com;  					} else {  						comid = comidx; -					} +					}*/ +					comid = comidx;  					comment[comid] = malloc(j+1);  					memcpy(comment[comid], lexeme, j+1); -					l[line].com = comid; -					comidx += (line == lineidx); +					comidx++;  				} else { -					l[line].com = comid;  				}  				if (dbg) {  					printf("lex(): com[0x%04X]: %s\n", comid, comment[comid]);  				}  				lex_type = TOK_COMMENT; +				l->count++; +				t = make_token(lex_type, 0, 0, comment[comid]);  				break;  			default:  				if (isalnum(str[i]) || str[i] == '_') { @@ -733,6 +553,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  							case ',':  							case '.':  							case '+': +							case '<': +							case '>':  							case '-':  							case ':':  							case '=': @@ -759,8 +581,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  								if (!strcasecmp(lexeme, mne[k])) {  									lex_type = TOK_OPCODE;  									isop = 1; -									l[line].mne = k; -									address++; +									l->count++; +									t = make_token(lex_type, 0xFF, k, "");  									break;  								}  							} @@ -774,6 +596,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  								case '.':  								case '+':  								case '-': +								case '<': +								case '>':  								case ':':  								case ';':  								case '=': @@ -800,29 +624,25 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  						}  						if (lexeme[k] == '\0') {  							if (num) { -								switch (lex_type) { -									default: -										if (l[line].cm != 0xFF) { -									case TOK_PLUS : -									case TOK_MINUS:	l[line].aop = strtoull(lexeme, NULL, 10); -											l[line].aopbase = BASE_DEC; -										} else { -									case TOK_SYM:	l[line].op = strtoull(lexeme, NULL, 10); -											l[line].opbase = BASE_DEC; -										} -										if (lex_type == TOK_SYM) { -											mksymbol(sym, l[line].op, 1, 0, 0, dbg); -											l[line].sym = get_symid(sym, address, line, dbg); -											isfixup += (l[line].sym == 0xFFFF); -											if (dbg) { -												printf("lex(): isfixup: %u\n", isfixup); -											} -										} -										break; +								value = 0; +								value = strtoull(lexeme, NULL, 10); +								if (lt->id == TOK_SYM) { +									mksymbol(sym, value, 1, 0, 0, dbg); +									if (lt) { +										lt->word = get_symid(sym, address, lt, dbg); +									} +									isfixup += (lt->word == 0xFFFF); +									if (dbg) { +										printf("lex(): isfixup: %u\n", isfixup); +									}  								}  								lex_type = TOK_DEC; +								l->count++; +								t = make_token(lex_type, 0, value, "");  							} else if (isch && lex_type != TOK_HEX && lex_type != TOK_BIN) {  								lex_type = TOK_SYM; +								l->count++; +								t = make_token(lex_type, 0, 0, "");  								memcpy(sym, lexeme, j+1);  								uint8_t spaces = 0;  								for (; isspace(str[i+spaces]); spaces++); @@ -830,8 +650,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  									printf("lex(): spaces: %u\n", spaces);  								}  								if (str[i+spaces] != ':' && str[i+spaces] != '=') { -									l[line].sym = get_symid(lexeme, address, line, dbg); -									isfixup += l[line].sym == 0xFFFF; +									t->word = get_symid(lexeme, address, t, dbg); +									isfixup += (t->word == 0xFFFF);  									if (dbg) {  										printf("lex(): isfixup: %u\n", isfixup);  									} @@ -842,6 +662,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  				}  				break;  		} +		if (!l->tok && t) { +			l->tok = tokens; +		}  		if (dbg) {  			printf("lex(): lexeme: %s, lex_type: %s\n", lexeme, (lex_type != 0xFF) ? lex_tok[lex_type] : "TOK_NONE");  		} @@ -850,7 +673,7 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  		if (lex_type == TOK_OPCODE && !isop) {  			j = 0;  		} else { -			if (lex_type == TOK_PLUS || lex_type == TOK_MINUS) { +			if (lex_type == TOK_EXPR) {  				i++;  			} else {  				switch (str[i]) { @@ -859,6 +682,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  					case '.':  					case '+':  					case '-': +					case '<': +					case '>':  					case ':':  					case ';':  					case '=': @@ -875,10 +700,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  		}  		if (lex_type == TOK_COMMENT) {  			if (!isstart) { -				l[line].etab = tab; -				l[line].espace = space; +				l->etab = tab; +				l->espace = space;  				if (dbg) { -					printf("lex(): ending tabs: %u, ending spaces: %u\n", l[line].etab, l[line].espace); +					printf("lex(): ending tabs: %u, ending spaces: %u\n", l->etab, l->espace);  				}  			}  		} @@ -886,48 +711,29 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {  			memset(lexeme, 0, strlen(lexeme)+1);  			lex_type = 0xFF;  		} +		if (t) { +			lt = t; +			t = t->next; +		}  	}  	if (i) { -		address = update_addr(l, address, isfixup, line, dbg); +		l->tok  = tokens; +		tokens = NULL; +		last_tok = NULL; +		bytecount dummy; +		address = parse_tokens(l->tok, &dummy, 0, address, dbg);  		if (dbg) {  			printf("lex(): Next address: $%"PRIX64"\n", address); -			printf( -				"lex(): " -				"address: $%"PRIX64 -				", dir: %u" -				", mne: $%02X" -				", rs: %u" -				", am: %u" -				", cm: %u" -				", opbase: %u" -				", com: $%04X" -				", sym: $%04X" -				", op: $%016"PRIX64 -				", aop: $%016"PRIX64 -				", ln: %u\n" -				, l[line].addr -				, l[line].dir -				, l[line].mne -				, l[line].rs -				, l[line].am -				, l[line].cm -				, l[line].opbase -				, l[line].com -				, l[line].sym -				, l[line].op -				, l[line].aop -				, line);  		}  		if (ln > linenum || islinenum) { -			l[line].linenum = ln; +			l->linenum = ln;  			if (ln > linenum) {  				linenum+=(10+(ln & 10));  			}  		} else if (!islinenum) { -			l[line].linenum = linenum; +			l->linenum = linenum;  			linenum += 10;  		} -		lineidx += (line == lineidx);  	}  	return address;  } diff --git a/programs/subasm-2.s b/programs/subasm-2.s deleted file mode 100644 index f10dac8..0000000 --- a/programs/subasm-2.s +++ /dev/null @@ -1,323 +0,0 @@ -; SuBAsm -; The Sux Bootstrapped Assembler. -; -; by mr b0nk 500 <b0nk@b0nk.xyz> - -.org incl -; String Constants. -prg_name: -	.byte "SuBAsm" -ver_txt: -	.byte ", version " -ver_num: -	.byte "0.1" - -; Directives. -dir: -	.byte "org" -	.byte "byte" -	.byte "word" -	.byte "dword" -	.byte "qword" -	.byte "include" - -; Short form Commands. -sh_cmds: -	.byte "vlahirs" - -; Commands. -cmds: -	.byte "viewmem" -	.byte "list" -	.byte "asm" -	.byte "help" -	.byte "inst" -	.byte "run" -	.byte "set" - -; Instruction Mnemonics. -mne: -	.byte "AAB" -	.byte "ABA" -	.byte "ADC" -	.byte "AND" -	.byte "ARB" -	.byte "ASR" -	.byte "BCC" -	.byte "BCS" -	.byte "BEQ" -	.byte "BNE" -	.byte "BNG" -	.byte "BPO" -	.byte "BRK" -	.byte "BVC" -	.byte "BVS" -	.byte "CAB" -	.byte "CLC" -	.byte "CLI" -	.byte "CLV" -	.byte "CMP" -	.byte "CPB" -	.byte "CPS" -	.byte "CPX" -	.byte "CPY" -	.byte "DAB" -	.byte "DEB" -	.byte "DEC" -	.byte "DEX" -	.byte "DEY" -	.byte "DIV" -	.byte "ENT" -	.byte "INB" -	.byte "INC" -	.byte "INX" -	.byte "INY" -	.byte "JMP" -	.byte "JSL" -	.byte "JSR" -	.byte "LDA" -	.byte "LDB" -	.byte "LDX" -	.byte "LDY" -	.byte "LLB" -	.byte "LRB" -	.byte "LSL" -	.byte "LSR" -	.byte "MAB" -	.byte "MUL" -	.byte "NOP" -	.byte "OAB" -	.byte "ORA" -	.byte "PHA" -	.byte "PHB" -	.byte "PHP" -	.byte "PHX" -	.byte "PHY" -	.byte "PLA" -	.byte "PLB" -	.byte "PLP" -	.byte "PLX" -	.byte "PLY" -	.byte "RLB" -	.byte "ROL" -	.byte "ROR" -	.byte "RRB" -	.byte "RTI" -	.byte "RTL" -	.byte "RTS" -	.byte "SAB" -	.byte "SBC" -	.byte "SEC" -	.byte "SEI" -	.byte "STA" -	.byte "STB" -	.byte "STT" -	.byte "STX" -	.byte "STY" -	.byte "TAB" -	.byte "TAX" -	.byte "TAY" -	.byte "TBA" -	.byte "TSX" -	.byte "TXA" -	.byte "TXS" -	.byte "TXY" -	.byte "TYA" -	.byte "TYX" -	.byte "WAI" -	.byte "XAB" -	.byte "XOR" - -; Command subroutine table. -cmd_srt: -	.word viewmem -	.word list -	.word asm -	.word help -	.word inst -	.word run -	.word set - -; Hex character table. -hex_char: -	.byte "0123456789ABCDEF" - - -.org $4400 -; Subroutine pointer. -sub_ptr: -	.word 0 - -; Indecies. -idx0: -	.word 0 -idx1: -	.word 0 -idx2: -	.word 0 - -; Program Counter. -prg_cnt: -	.qword 0 - -; Start of program code. -.org parser -subasm: -	ldb #0		; Set the first pointer -	lda.w #cmd_buf	; to the command buffer. -	jsl set_ptr	; -	tba		; Reset A. -	tax		; Reset X. -	jsl chk_shcmd	; Did we get a shortend command? -	bne parse_cmd	; Yes, so skip everything else. -	jsl chk_cmd	; No, but did we get a full command? -	bne parse_cmd	; Yes, so skip everything else. -	jsl lexer	; No, so start lexing this line. -subasm_end: -	rtl		; End of subasm. - -parse_cmd: -	inb		; Set the second pointer -	lda.w #cmd_srt	; to the command subroutine table. -	jsl set_ptr	; -	deb		; Reset B. -	tba		; Reset A. -	lda f		; Get the command ID. -	cmp #8		; Is the command ID greater than the command count? -	bcs subasm_end	; Yes, so we're done. -	lsl #1		; No, so multiply the command ID by two. -	phy #2		; Preserve the screen buffer position. -	tay		; Set the index to the offset that we just calculated. -	lda.w (ptr2), y	; Get the command subroutine, from the command subroutine table. -	ply #2		; Get back the screen buffer position. -	ldb #2		; Save it in the third pointer. -	jsl set_ptr	; -	ldb #0		; Reset B. -	jsr (ptr3)	; Run the command's subroutine. -	jmp subasm_end	; We are done. - -chk_shcmd: -	inb		; Set the second pointer -	lda.w #sh_cmds	; to the shortend command table. -	jsl set_ptr	; -	deb		; Reset B. -	tba		; Reset A. -	phy #2		; Preserve the screen buffer position. -	txy		; Set our index to zero. -	lda (ptr), y	; Is there nothing in the command buffer? -	beq shcmd_fail	; Yes, so return that we failed. -	cmp #' '	; No, but is this character, a space? -	beq shcmd_fail	; Yes, so return that we failed. -shcmd_loop: -	ldb (ptr2), y	; Are we at the end of the table? -	beq shcmd_fail	; Yes, so return that we failed. -	cab		; No, so did the character match? -	beq shcmd_fnd	; Yes, so check if there are any arguments. -	iny		; No, so check the next command. -	jmp shcmd_loop	; Keep looping. -shcmd_fnd: -	sty f		; Save the command ID. -	ldy #1		; Check the next character in the command buffer. -	lda (ptr), y	; Is this the end of the buffer? -	beq shcmd_true	; Yes, so return that we succeded. -	cmp #' '	; No, but is this a space? -	beq shcmd_true	; Yes, so return that we succeded. -	jmp shcmd_fail	; No, so return that we failed. -shcmd_true: -	lda #1		; Return true. -	jmp shcmd_end	; We are done. -shcmd_fail: -	tba		; Return false. -	tax		; Reset X. -shcmd_end: -	ldb #0		; Reset B. -	ply #2		; Get back the screen buffer position. -	rtl		; End of chk_shcmd. - -print_hex: -	pha #8		; Preserve the hex value. -	ldb #1		; Set the second pointer -	lda.w hex_char	; to the start of hex character table. -	jsl set_ptr	; -	ldb #0		; Reset B. -	pla #8		; Get the hex value back. -pnthex_lp: -	pha #8		; Preserve the hex value. -	and #$F		; Mask the lowest nibble. -	phx #2		; Preserve the digit count. -	phy #2		; Preserve the screen buffer position. -	tay		; Get the index for the hex digit. -	lda (ptr2), y	; Get the hex digit. -	ply #2		; Get back the screen buffer position. -	jsl print_char	; Print the hex digit. -	plx #2		; Get the digit count back. -	pla #8		; Get the hex value back. -pnthex_lp1: -	cpx #1		; Is the digit count less than one? -	bcc pnthex_lp2	; Yes, so don't decrement the digit count. -	dex		; No, but was the digit count zero, when decremented? -	beq pnthex_end	; Yes, so we're done. -	jmp pnthex_lp3	; No, so get the next nibble. -pnthex_lp2: -	ldb #1		; Enable auto digit count. -pnthex_lp3: -	lsr #4		; No, but is the next nibble, a zero? -	beq pnthex_lp4	; Yes, so check if auto digit count is enabled. -	jmp pnthex_lp	; No, so print the next digit. -pnthex_lp4: -	cpb #1		; Is auto digit count enabled? -	beq pnthex_end	; Yes, so we're done. -	jmp pnthex_lp	; No, so keep printing more digits. -pnthex_end: -	ldb #0		; Reset B. -	rtl		; End of print_hex. - -print_space: -	lda #' '	; Set the character to a space. -	phb #1		; Preserve the spacing count. -	ldb #1		; Enable replace mode. -	stb b		; -	jsl print_char	; Print the space. -	plb #1		; Get the spacing count back. -	deb		; Have we printed all of the spacing? -	beq pntsp_end	; Yes, so we're done. -	jmp print_space	; No, so keep printing spaces. -pntsp_end: -	rtl		; End of print_space. - -viewmem: -	pha #8		; Preserve the address. -	lda #'\n'	; Print a newline. -	jsl print_char	; -	ldb #19		; Print 19 spaces. -	jsl print_space	; -vmem_lp: -	pla #8		; Get the address back. -	nop		; -vmem_end: -	rts		; End of viewmem. - -list: -	nop		; -list_end: -	rts		; End of list. -asm: -	nop		; -asm_end: -	rts		; End of asm. -help: -	nop		; -help_end: -	rts		; End of help. -inst: -	nop		; -inst_end: -	rts		; End of inst. -run: -	nop		; -run_end: -	rts		; End of run. -set: -	nop		; -set_end: -	rts		; End of set. diff --git a/programs/subasm.s b/programs/subasm.s index 50f2e8d..350e105 100644 --- a/programs/subasm.s +++ b/programs/subasm.s @@ -3,576 +3,471 @@  ;  ; by mr b0nk 500 <b0nk@b0nk.xyz> -; Variables -.org $1000 -prg_name: +MAX_SYM = $800		; Max symbol size. + +.org incl +; String Constants. +asm_name:  	.byte "SuBAsm" -ver_txt: -	.byte ", version " -ver_num: +asm_ver:  	.byte "0.1"  ; Directives.  dir: -	.byte "org" +	.byte "org",  	.byte "byte"  	.byte "word"  	.byte "dword"  	.byte "qword" +	.byte "include" + +; Short form Commands. +sh_cmds: +	.byte "vlahirs" + +; Commands. +cmds: +	.byte "viewmem" +	.byte "list" +	.byte "asm" +	.byte "help" +	.byte "inst" +	.byte "run" +	.byte "set" + +; Instruction mnemonics, and opcodes. + +; Legend. +; mne = Mnemonic. +; imm = Immediate data. +; zm  = Zero Matrix. +; zmx = Zero Matrix, indexed with X. +; zmy = Zero Matrix, indexed with Y. +; ind = Indirect. +; idx = Indexed Indirect. +; idy = Indirect Indexed. +; abs = Absolute. +; imp = Implied. -; Instruction mnemonics.  mne: -	.byte "CPS" -	.byte "ADC" -	.byte "AAB" -	.byte "PHB" -	.byte "PHP" -	.byte "PHA" -	.byte "PHY" -	.byte "TAY" -	.byte "PHX" -	.byte "TAX" -	.byte "TYX" -	.byte "JMP" -	.byte "SBC" -	.byte "SAB" -	.byte "PLB" -	.byte "PLP" -	.byte "PLA" -	.byte "PLY" -	.byte "TYA" -	.byte "PLX" -	.byte "TXA" -	.byte "TXY" -	.byte "JSR" -	.byte "AND" -	.byte "ABA" -	.byte "STT" -	.byte "TAB" -	.byte "TSX" -	.byte "BPO" -	.byte "ORA" -	.byte "OAB" -	.byte "TBA" -	.byte "SEI" -	.byte "TXS" -	.byte "BNG" -	.byte "XOR" -	.byte "XAB" -	.byte "CLI" -	.byte "BCS" -	.byte "LSL" -	.byte "LLB" -	.byte "STB" -	.byte "SEC" -	.byte "STA" -	.byte "STY" -	.byte "STX" -	.byte "BCC" -	.byte "LSR" -	.byte "LRB" -	.byte "LDB" -	.byte "CLC" -	.byte "LDA" -	.byte "LDY" -	.byte "LDX" -	.byte "BEQ" -	.byte "ROL" -	.byte "RLB" -	.byte "SSP" -	.byte "BNE" -	.byte "ROR" -	.byte "RRB" -	.byte "CSP" -	.byte "BVS" -	.byte "MUL" -	.byte "MAB" -	.byte "SEV" -	.byte "BVC" -	.byte "DIV" -	.byte "DAB" -	.byte "CLV" -	.byte "RTS" -	.byte "CMP" -	.byte "CAB" -	.byte "CPY" -	.byte "CPX" -	.byte "CPB" -	.byte "ENT" -	.byte "RTI" -	.byte "INC" -	.byte "IAB" -	.byte "INY" -	.byte "INX" -	.byte "DEC" -	.byte "DBA" -	.byte "DEY" -	.byte "DEX" -	.byte "WAI" -	.byte "JSL" -	.byte "ASR" -	.byte "ARB" -	.byte "NOP" -	.byte "RTL" -	.byte "BRK" - - -scr_row: -	.byte $0 -scr_col: -	.byte $0 -a: -	.word $0 -b: -	.word $0 -c: -	.word $0 -d: -	.word $0 - -str_buf: - -; Input buffer. -.org $2000 -buf: - -.org $2400 -ptr1: -	.qword $2500 - -ptr2: -	.qword $2900 - -; Control Register. -.org $C000 -ctrl_reg: - -; Screen. -.org $C001 -scr: - -; Keyboard. -.org $C002 -kbd: - -; Main program. -.org $0 -reset: -	cps -	ldx.w #$FFFF -	txs -	ldy #0 -	jsr clr_buf -	ldx.w #0	; Reset x. -	ldy #0		; Reset y. -	jmp print_title - -read: -	lda ctrl_reg	; Is the keyboard ready? -	beq read	; Loop until the keyboard is ready. -	lda #0		; Start resetting the control register. -	sta ctrl_reg	; Reset the control register. -	jmp getchar	; We got a key. - -rset_x: - -	ldx #0		; Reset x. -	stx.w x -	rts - -print_title: -	lda prg_name, x -	beq print_ver	; Did we find a null terminator? -	sta		; Print character. -	inx		; Increment offset. -	inc x -	jmp print_title	; Keep printing more characters. - -print_ver -	jsr rset_x -	lda ver_txt, x -	beq print_num	; Did we find a null terminator? -	sta scr		; Print character. -	inx		; Increment offset. -	jmp print_ver	; Keep printing more characters. - -print_num: -	lda ver_num, x -	beq getline	; Did we find a null terminator? -	sta scr		; Print character. -	inx		; Increment offset. -	jmp print_num	; Keep printing more characters. -getline: -	lda #$A -	sta scr		; Print newline -	inc scr_row -	lda #0 -	sta scr_col -	inc y -	jsr rset_x -	jmp read - -getchar: -	lda kbd		; Get typed character. -	cmp #$1B	; Did the user type an escape? -	beq esc		; Yes, so start getting the escape code. -	cmp #$A		; Did the user type a newline? -	beq nl		; Yes, so start parsing the input. -	cmp #8		; Did the user type a backspace? -	beq bs		; Yes, so start checking the buffer. -	jsr echo	; Print character to screen. - -store_char: -	sta buf, y	; Store typed character into the input buffer. -	iny		; Increment buffer offset. -	jmp read	; Get another character. - -esc: -	lda ctrl_reg	; Skip the '['. -	lda ctrl_reg	; Get the next character. -	beq read	; We have an error, so discard it, and go back to getting user input. -	lda kbd		; Get the escape code. -	sta c		; Store the escape code, until we need it. -	jsr isup	; Check if the user pressed up. -	lda d -	cmp #0 -	bne esc_end -	jsr isdown	; Check if the user pressed down. -	lda d -	cmp #0 -	bne esc_end -	lda #0 -	jsr isleft	; Check if the user pressed left. -	lda d -	cmp #0 -	bne esc_end -	jsr isright	; Check if the user pressed right. -esc_end: -	lda #$0 -	sta d -	jmp rset_a	; Go back to getting user input. - -isup: -	lda scr_row	; Is the cursor at the top of the screen? -	beq isup_done	; Yes, so return. -	lda c		; No, so load the escape code back into the accumulator. -	cmp #$41	; Did the user press the up arrow key? -	beq up		; Yes, so move the cursor up. -isup_done: -	rts		; End of isup. - -isdown: -	lda scr_row	; Start checking the y coordinate of the cursor. -	cmp #$17	; Is the cursor at the bottom of the screen? -	beq isdown_done	; Yes, so return. -	lda c		; No, so load the escape code back into the accumulator. -	cmp #$42	; Did the user press the down arrow key? -	beq down	; Yes, so move the cursor down. -isdown_done: -	rts		; End of isdown. - -isright: -	lda scr_col	; Start checking the x coordinate of the cursor. -	cmp #$4F	; Is the cursor at the far right of the screen? -	beq isright_end	; Yes, so return. -	lda c		; No, so load the escape code back into the accumulator. -	cmp #$43	; Did the user press the right arrow key? -	beq right	; Yes, so move the cursor right. -isright_end: -	rts		; End of isright. - -isleft: -	lda scr_col	; Is the cursor at the far left of the screen? -	beq isleft_done	; Yes, so return. -	lda c		; No, so load the escape code back into the accumulator. -	cmp #$44	; Did the user press the left arrow key? -	beq left	; Yes, so move the cursor left. -isleft_done: -	rts		; End of isleft. - -up: -	dec scr_row -	jsr update_pos -	lda #1 -	sta d -	jmp isup_done -down: -	inc scr_row -	jsr update_pos -	lda #1 -	sta d -	jmp isdown_done -right: -	inc scr_col -	jsr update_pos -	jmp isright_end -left: -	dec scr_col -	jsr update_pos -	lda #1 -	sta d -	jmp isleft_done - -update_pos: -	lda #$1B	; Print an escape character -	sta scr		; to the screen. -	lda #$5B	; Print '[' -	sta scr		; to the screen, and start the escape sequence. -	jsr getrow	; Start printing the row number to the screen. -	jsr getcol	; Start printing the column number to the screen. -	lda #$48	; Print 'H' -	sta scr		; to the screen. -	rts		; End of update_pos. -getrow: -	lda scr_row	; Get the cursor's y coordinate. -	div #$A		; Divide A by 10. -	adc #$30	; Convert it to ascii, and -	sta scr		; print to the screen. -	tba		; Get the remainder. -	adc #$30	; Convert it to ascii, and -	sta scr		; print to the screen. -	rts		; End of getrow. -getcol: -	lda #$3B	; Print ';' -	sta scr		; to the screen. -	lda scr_col	; Get the cursor's x coordinate. -	div #$A		; Divide A by 10. -	adc #$30	; Convert it to ascii, and -	sta scr		; print to the screen. -	tba		; Get the remainder. -	adc #$30	; Convert it to ascii, and -	sta scr		; print to the screen. -	rts		; End of getrow. - - - -nl: -	sta scr		; Print newline. -	inc scr_row	; Move the cursor down one line. -	lda #0		; Put a null terminator, in place of the newline. -	sta scr_col	; Move the cursor back to column 0. -	sta buf, y	; Place it into the input buffer. -	ldy.w #0	; Reset y, to parse the input. -	jsr parse	; Start parsing input. - -back: -	sta scr		; Print backspace. -	lda #0		; Put a null terminator, in place of the backspace. -	sta buf, y	; Place it into the input buffer. -	dey		; Decrement buffer offset. -	dec scr_col -	jmp read	; Get next character. - -bs: -	cpy #0		; Are we at the start of the buffer? -	beq read	; We are, so do not store the backspace into the buffer. -	jmp back	; We are not, so add the backspace to the buffer. - -parse: -	jsr getdir -	jsr -	rts - -getdir: -	iny		; Increment offset. -	lda buf, y -	jsr iswhite -	bcs getdir	; Reset y, if we hit the null terminator. -	cmp #$2E	; Is this character a '.'? -	bne getdir_exit	; No, so return. -	jsr clr_ptr - -getdir_end: -	iny		; Increment offset. -	lda buf, y -	jsr iswhite -	bcs getdir_cmp -	ora #%00100000	; Make character lower case. -	sta (ptr1), y -	jmp getdir_end -gettok: -	ply #1 -	iny -gettok2: -	lda buf, y -	jsr istoken -	bcs gettok3 -	jmp gettok2 -gettok3: -	cmp #$ -	cmp #$24	; Is this character, a '$'? -	beq getaddr	; Yes, so start getting the address. - - - -getdir_cmp: -	phy #1 -	ldy.w #0 -	tyx -getdir_cpl: -	ldb dir, x	; Start checking if the directive we're using, is "org". -	stb (ptr2), y -	beq getdir_scmp -	inx -	iny -	jmp getdir_cpl -getdir_scmp: -	ldy #0 -	jsr strcmp -	cpx #0 -	beq getdir_tok -getdir_exit: -	rts		; End of getdir. - - -istoken: -	cmp #$20	; Is this character a space? -	beq istoken_f	; Yes, so return false. -	cmp #$09	; Is this character a tab? -	beq istoken_f	; Yes, so return false. -	cmp #$A		; Is this character a newline? -	beq istoken_f	; Yes, so return false. -	cmp #$3B	; Is this character a ';'? -	beq istoken_f	; Yes, so return false. -	cmp #0		; Is this character a null terminator? -	beq istoken_f	; Yes, so return false. -	sec		; Return true. -	rts		; End of istoken. -istoken_f -	clc		; Return false. -	rts		; End of istoken_f. - -iswhite: -	cmp #$20	; Is this character a space? -	beq iswhite_t	; Yes, so return true. -	cmp #9		; Is this character a tab? -	beq iswhite_t	; Yes, so return true. -	clc		; No, so return false. -	rts		; End of iswhite. -iswhite_t: -	sec		; Return true. -	rts		; End of iswhite_t. - -rset_y: -	ldy.w #0 -	jmp print_buf	; Print the input buffer. - -print_buf: -	lda buf, y	; Get a character from the input buffer. -	beq fin		; Are we done with printing the buffer? -	sta scr		; Print said character. -	iny -	jmp print_buf	; Keep printing the buffer. - -spin: -	nop -	nop -	nop -	jmp spin - -clr_buf: -	lda #0 -	cpy.w #$3FF -	beq clr_end -	sta buf, y -	iny -	jmp clr_buf -clr_sbuf: -	lda #0 -	cpy.w #$1FF -	beq clr_end -	sta str_buf, y -	iny -	jmp clr_sbuf - -clr_end: -	rts - -echo: -	tab -	ldx scr_col -	cpx #$4F -	bne echo_print -	cmp #$A -	beq linewrap -linewrap: -	inc scr_row -	ldx #0 -	stx scr_col -	jsr update_pos -echo_print: -	tba -	sta scr		; Echo typed character. -	inc scr_col	; Increment the cursor's x coordinate. -	sta buf, y	; Store typed character into the input buffer. -	iny		; Increment the buffer offset. -	rts		; Return. - -clr_ptr: -	lda #0 -	cpy.w #$3FF -	beq ptr_end -	sta (ptr1), y -	sta (ptr2), y -	iny -	jmp clr_ptr -ptr_end: -	rts - -strcmp: -	lda (ptr1), y -	cmp (ptr2), y -	bne strcmp_l1 -	tax -	beq strcmp_l3 -	iny -	bne strcmp -	jmp strcmp - - -strcmp_l1: -	bcs strcmp_l2 -	ldx #0 -	dex -	rts - -strcmp_l2: -	ldx #1 -strcmp_l3: -	rts - - -.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 -v -.org $100 -v -.org $200 -v -.org $300 -v -.org $1000 -v -.org $1100 -v -.org $1200 -v -.org $1300 -v -.org $1400 -v -q - +;	       mne   imm,  zm, zmx, zmy, ind, idx, idy, abs, imp +	.byte "CPS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00 +	.byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF +	.byte "AAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $02 +	.byte "PHP", $08, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "CPB", $09, $2D, $FF, $FF, $55, $AD, $AC, $2C, $FF +	.byte "PHB", $0A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "DEC", $FF, $0D, $FF, $FF, $FF, $FF, $FF, $0C, $E5 +	.byte "JMP", $FF, $0E, $FF, $FF, $CE, $FF, $FF, $10, $FF +	.byte "SBC", $11, $16, $FF, $FF, $FF, $FF, $FF, $14, $FF +	.byte "SAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $12 +	.byte "ENT", $18, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "CPY", $19, $3D, $FF, $FF, $85, $FF, $FF, $4C, $FF +	.byte "PLB", $1A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "INC", $FF, $1D, $FF, $FF, $FF, $FF, $FF, $1C, $F5 +	.byte "JSR", $FF, $1E, $FF, $FF, $BE, $FF, $FF, $FF, $FF +	.byte "JSL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $20, $FF +	.byte "AND", $21, $26, $FF, $FF, $FF, $FF, $FF, $24, $FF +	.byte "ABA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $22 +	.byte "PLP", $28, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "CPX", $29, $4D, $FF, $FF, $B5, $FF, $FF, $3C, $FF +	.byte "PHY", $2A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "BPO", $FF, $2E, $FF, $FF, $FF, $FF, $FF, $30, $FF +	.byte "ORA", $31, $36, $FF, $FF, $FF, $FF, $FF, $34, $FF +	.byte "OAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $32 +	.byte "STT", $38, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "PLY", $3A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "BNG", $FF, $3E, $FF, $FF, $FF, $FF, $FF, $40, $FF +	.byte "XOR", $41, $46, $FF, $FF, $FF, $FF, $FF, $44, $FF +	.byte "XAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $42 +	.byte "PHA", $48, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "PHX", $4A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "BCS", $FF, $4E, $FF, $FF, $FF, $FF, $FF, $50, $FF +	.byte "LSL", $51, $56, $FF, $FF, $FF, $FF, $FF, $54, $FF +	.byte "LLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $52 +	.byte "CLC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $58 +	.byte "PLX", $5A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "BCC", $FF, $5E, $FF, $FF, $FF, $FF, $FF, $60, $FF +	.byte "LSR", $61, $66, $FF, $FF, $FF, $FF, $FF, $64, $FF +	.byte "LRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $62 +	.byte "PLA", $68, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "TAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $6A +	.byte "BEQ", $FF, $6E, $FF, $FF, $FF, $FF, $FF, $70, $FF +	.byte "ROL", $71, $76, $FF, $FF, $FF, $FF, $FF, $74, $FF +	.byte "RLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $72 +	.byte "SEC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $78 +	.byte "TBA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $7A +	.byte "BNE", $FF, $7E, $FF, $FF, $FF, $FF, $FF, $80, $FF +	.byte "ROR", $81, $86, $FF, $FF, $FF, $FF, $FF, $84, $FF +	.byte "RRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $82 +	.byte "DEY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $88 +	.byte "TAY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $8A +	.byte "BVS", $FF, $8E, $FF, $FF, $FF, $FF, $FF, $90, $FF +	.byte "MUL", $91, $96, $FF, $FF, $FF, $FF, $FF, $94, $FF +	.byte "MAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $92 +	.byte "CLI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $98 +	.byte "TYA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $9A +	.byte "BVC", $FF, $9E, $FF, $FF, $FF, $FF, $FF, $A0, $FF +	.byte "DIV", $A1, $A6, $FF, $FF, $FF, $FF, $FF, $A4, $FF +	.byte "DAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A2 +	.byte "INY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A8 +	.byte "TAX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AA +	.byte "RTS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AE +	.byte "RTL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B0 +	.byte "CMP", $B1, $B6, $FF, $FF, $25, $7D, $7C, $B4, $FF +	.byte "CAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B2 +	.byte "SEI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B8 +	.byte "LDX", $B9, $BD, $FF, $C9, $95, $FF, $FF, $BC, $FF +	.byte "TXA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $BA +	.byte "RTI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C0 +	.byte "LDA", $C1, $C6, $79, $39, $05, $5D, $5C, $C4, $FF +	.byte "DEX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C5 +	.byte "CLV", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C8 +	.byte "TYX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $CA +	.byte "STA", $FF, $CD, $89, $49, $15, $6D, $6C, $CC, $FF +	.byte "TSX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D0 +	.byte "LDB", $D1, $D6, $99, $59, $35, $8D, $8C, $D4, $FF +	.byte "INX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D5 +	.byte "WAI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D8 +	.byte "TXY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $DA +	.byte "STB", $FF, $DD, $A9, $69, $45, $9D, $9C, $DC, $FF +	.byte "TXS", $E0, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF +	.byte "LDY", $E1, $E6, $E9, $FF, $65, $FF, $FF, $E4, $FF +	.byte "BRK", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E8 +	.byte "NOP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EA +	.byte "STY", $FF, $ED, $F9, $FF, $75, $FF, $FF, $EC, $FF +	.byte "DEB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EE +	.byte "ASR", $F1, $F6, $FF, $FF, $FF, $FF, $FF, $F4, $FF +	.byte "ARB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F2 +	.byte "STX", $FF, $FD, $FF, $D9, $A5, $FF, $FF, $FC, $FF +	.byte "INB"  $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FE + +; Command subroutine table. +cmd_srt: +	.word viewmem +	.word list +	.word asm +	.word help +	.word inst +	.word run +	.word set + +; Hex character table. +hex_char: +	.byte "0123456789ABCDEF" + + +; Token table. +.org $20000 +tokline: + +.org cmd_buf+$400 +; Program Counter. +prg_cnt: +	.qword 0 +; Hex digit string buffer. +hex_str: +	.qword 0, 0 +; String buffer. +strbuf: + +.org strbuf+$80 +; Subroutine pointer. +sub_ptr: +	.word 0 + +; Indecies. +idx0: +	.qword 0 +idx1: +	.qword 0 +idx2: +	.qword 0 +idx3: +	.qword 0 + +; Lexeme string. +lexeme: + +; Symbol tables. +.org lexeme+$100 +sym_val: +.org sym_val+$4000 +sym_id: +.org sym_id+$1000 +sym_def: +.org sym_def+$100 +sym_name: + +; Fixup table. +; Fixups are unresolved symbols. +.org sym_name+$1000 +fix_sym: +.org fix_sym+$1000 +fix_ln: +.org fix_ln+$1000 +fix_val: + + +; Start of program code. +.org parser +subasm: +	ldb #0		; Set the first pointer +	lda.d #cmd_buf	; to the command buffer. +	jsl set_ptr	; +	tba		; Reset A. +	tax		; Reset X. +	jsl chk_shcmd	; Did we get a shortend command? +	bne parse_cmd	; Yes, so skip everything else. +	jmp subasm_end	; +	jsl chk_cmd	; No, but did we get a full command? +	bne parse_cmd	; Yes, so skip everything else. +	jsl lexer	; No, so start lexing this line. +subasm_end: +	rtl		; End of subasm. + +parse_cmd: +	ldb #1		; Set the second pointer +	lda.d #cmd_srt	; to the command subroutine table. +	jsl set_ptr	; +	deb		; Reset B. +	tba		; Reset A. +	lda f		; Get the command ID. +	cmp #8		; Is the command ID greater than the command count? +	bcs subasm_end	; Yes, so we're done. +	lsl #1		; No, so multiply the command ID by two. +	phy #2		; Preserve the screen buffer position. +	tay		; Set the index to the offset that we just calculated. +	lda.w (ptr2), y	; Get the command subroutine, from the command subroutine table. +	ply #2		; Get back the screen buffer position. +	ldb #2		; Save it in the third pointer. +	jsl set_ptr	; +	ldb #0		; Reset B. +	jsr (ptr3)	; Run the command's subroutine. +	jmp subasm_end	; We are done. + +chk_shcmd: +	tba		; Reset A. +	inb		; Set the second pointer +	lda.w #sh_cmds	; to the shortend command table. +	jsl set_ptr	; +	deb		; Reset B. +	tba		; Reset A. +	phy #2		; Preserve the screen buffer position. +	txy		; Set our index to zero. +	lda (ptr), y	; Is there nothing in the command buffer? +	beq shcmd_fail	; Yes, so return that we failed. +	cmp #' '	; No, but is this character, a space? +	beq shcmd_fail	; Yes, so return that we failed. +shcmd_loop: +	ldb (ptr2), y	; Are we at the end of the table? +	beq shcmd_fail	; Yes, so return that we failed. +	cab		; No, so did the character match? +	beq shcmd_fnd	; Yes, so check if there are any arguments. +	iny		; No, so check the next command. +	jmp shcmd_loop	; Keep looping. +shcmd_fnd: +	sty f		; Save the command ID. +	ldy #1		; Check the next character in the command buffer. +	lda (ptr), y	; Is this the end of the buffer? +	beq shcmd_true	; Yes, so return that we succeded. +	cmp #' '	; No, but is this a space? +	beq shcmd_true	; Yes, so return that we succeded. +	jmp shcmd_fail	; No, so return that we failed. +shcmd_true: +	lda #1		; Return true. +	jmp shcmd_end	; We are done. +shcmd_fail: +	ldb #0		; Reset B. +	tba		; Return false. +	tax		; Reset X. +shcmd_end: +	ply #2		; Get back the screen buffer position. +	rtl		; End of chk_shcmd. + +print_hex: +	pha #8		; Preserve the hex value. +	and #0		; Reset A. +	ldb #1		; Set the second pointer +	lda.w #hex_char	; to the start of hex character table. +	jsl set_ptr	; +	inb		; Set the third pointer +	lda.d #hex_str	; to the end of hex string buffer. +	clc		; Do a non carrying add. +	adc #$10	; +	jsl set_ptr	; +	ldb #0		; Reset B. +	pla #8		; Get the hex value back. +pnthex_lp: +	pha #8		; Preserve the hex value. +	and #$F		; Mask the lowest nibble. +	phy #2		; Preserve the screen buffer position. +	tay		; Get the index for the hex digit. +	lda (ptr2), y	; Get the hex digit. +	dec ptr3	; Decrement the string pointer. +	sta (ptr3)	; Save the hex digit character in the string. +	ply #2		; Get back the screen buffer position. +	pla #8		; Get the hex value back. +pnthex_lp1: +	cpx #1		; Is the digit count less than one? +	bcc pnthex_lp2	; Yes, so don't decrement the digit count. +	dex		; No, but was the digit count zero, when decremented? +	beq pnthex_end	; Yes, so we're done. +	jmp pnthex_lp3	; No, so get the next nibble. +pnthex_lp2: +	ldb #1		; Enable auto digit count. +pnthex_lp3: +	lsr #4		; No, but is the next nibble, a zero? +	beq pnthex_lp4	; Yes, so check if auto digit count is enabled. +	jmp pnthex_lp	; No, so print the next digit. +pnthex_lp4: +	cpb #1		; Is auto digit count enabled? +	beq pnthex_end	; Yes, so we're done. +	jmp pnthex_lp	; No, so keep printing more digits. +pnthex_end: +	rtl		; End of print_hex. + +charcpy: +	ldx idx3	; Get the string index. +	sta strbuf, x	; Save it in the string buffer. +	inc idx3	; Increment the string index. +	rtl		; End of charcpy. + +print_hi: +	and #0		; Reset A. +	sta idx3	; Clear the string index. +	lda #'$'	; Print the hex delimiter. +	jsl charcpy	; +	lda.q idx0	; Get the masked address. +	ldx #$10	; Set digit count to 16. +	jsl print_hex	; Print the address. +	lda.q hex_str	; Get the lower half of the string. +	sta.q strbuf+1	; Save it in the string buffer. +	lda.q hex_str+8	; Get the upper half of the string. +	sta.q strbuf+9	; Save it in the string buffer. +	ldx #$11	; Add 16 to the index. +	stx idx3	; +	lda #':'	; Print a colon. +	jsl charcpy	; +	lda # ' '	; Print a space. +	jsl charcpy	; +	rtl		; End of print_hi. + +print_lo: +	lda #0		; Reset A. +	sta idx3	; Clear the string index. +pntlo_lp: +	ldx #2		; Set digit count to 2. +	pha #1		; Preserve the nibble offset. +	jsl print_hex	; Print the low nibble offset. +	lda.w (ptr3)	; Get the two digits. +	jsl charcpy	; Copy the first digit. +	lsr #8		; Copy the next digit. +	jsl charcpy	; +	pla #1		; Get the nibble offset back. +	inc		; Increment the offset. +	cmp #$10	; Are we at the last offset? +	bcs pntlo_end	; Yes, so we're done. +pntlo_lp1: +	pha #1		; No, so preserve the nibble offset. +	lda #' '	; Add a space to the string buffer. +	jsl charcpy	; +	pla #1		; Get the nibble offset back. +	jmp pntlo_lp	; Keep looping. +pntlo_end: +	inx		; Increment the index by one. +	lda #0		; Null terminate the string buffer. +	sta strbuf, x	; +	tax		; Reset X. +	lda.d #strbuf	; Print the string buffer. +	jsl print_str	; +	rtl		; End of print_lo. + +print_chunk: +	ldx #0		; Reset X. +	phy #2		; Preserve the screen buffer index. +	txy		; Copy the byte index to it. +pntchnk_lp: +	and #0		; Reset A. +	ldx #2		; Set the digit count to 2. +	lda (idx0), y	; Get the byte at that address. +	jsl print_hex	; Print the byte. +	lda.w (ptr3)	; Get the two digits. +	jsl charcpy	; Copy the first digit. +	lsr #8		; Copy the next digit. +	jsl charcpy	; +	iny		; Increment the byte index. +	cpy #$10	; Have we read 16 bytes? +	beq pntchnk_end	; Yes, so we're done. +	lda #' '	; No, so add a soace to the string buffer. +	jsl charcpy	; +	jmp pntchnk_lp	; Keep looping. +pntchnk_end: +	ply #2		; Get the screen buffer index back. +	inx		; Increment the index by one. +	and #0		; Null terminate the string. +	sta strbuf, x	; +	tax		; Reset X. +	sta idx3	; Clear the string index. +	rtl		; End of print_chunk. + +viewmem: +	lda.q prg_cnt	; Get the program counter. +	sta.q idx0	; Save the address in the first index. +	and #$F0	; Clear the first four bits of the address. +	sta idx0	; Overwrite the first byte, with the masked byte. +	lda #19		; Move the cursor to the right, by 19 columns. +	sta scr_col	; +	jsl update_pos	; +	jsl print_lo	; Print the low nibble offsets. +	ldx #0		; Reset X. +	ldb #0		; Reset B. +	stb idx1	; Reset the byte count. +vmem_lp0: +	lda #'\n'	; Print a newline. +	jsl print_char	; +	jsl print_hi	; Place the address in the string buffer. +	jsl print_chunk	; Place the next 16 bytes in the string buffer. +	lda.d #strbuf	; Print the string buffer. +	jsl print_str	; +	inc idx1	; Increment the chunk count. +	ldb idx1	; Get the chunk count. +	cpb #$10	; Did we print 16 chunks? +	beq vmem_end	; Yes, so we're done. +	lda.q idx0	; No, so get the address index. +	clc		; Prepare for a non carrying add. +	adc #$10	; Add 16 to the address. +	sta.q idx0	; Put it back into the address. +	and #0		; Reset A. +	jmp vmem_lp0	; Keep looping. +vmem_end: +	lda #'\n'	; Print a newline. +	jsl print_char	; +	and #0		; Reset A. +	rts		; End of viewmem. + + +list: +	nop		; +list_end: +	rts		; End of list. +asm: +	nop		; +asm_end: +	rts		; End of asm. +help: +	nop		; +help_end: +	rts		; End of help. +inst: +	nop		; +inst_end: +	rts		; End of inst. +run: +	nop		; +run_end: +	rts		; End of run. +set: +	nop		; +set_end: +	rts		; End of set. diff --git a/programs/subeditor.s b/programs/subeditor.s index bdd3a11..e344588 100644 --- a/programs/subeditor.s +++ b/programs/subeditor.s @@ -4,17 +4,17 @@  ; mr b0nk 500 <b0nk@b0nk.xyz>  ; I/O constants. -status	= $C000		; Keyboard status. -scr	= $C001		; Character that is to be printed. -kbd	= $C002		; Character from the Keyboard. -step	= $C010		; Enables clock stepping, when set. +status	= $100		; Keyboard status. +scr	= $101		; Character that is to be printed. +kbd	= $102		; Character from the Keyboard. +step	= $110		; Enables clock stepping, when set.  ; Screen constants.  maxrow	= 23		; Screen's row count.  maxcol	= 79		; Screen's column count.  ; Include SuBAsm. -.include "subasm-2.s" +.include "subasm.s"  .org $A000  ; String Literals/Constants. @@ -22,36 +22,49 @@ tok:  	.byte "dab"  msg:  	.byte "oof, you divided a, and b on me.\n" -string: -	.byte "Please, type something.\n" + +ed_name: +	.byte "SuBEditor" +ed_ver: +	.byte "1" +ed_sver: +	.byte ".0.0" + +ver_str: +	.byte ", version " +made: +	.byte "Created by, " + +author: +	.byte "mr b0nk 500" + +;sub_name: +;	.byte "SuB Suite" +;sub_ver: +;	.byte "0.9" +  string2:  	.byte "You typed, "  ; Linewrap bitmask table.  bits: -	.byte $80 -	.byte $40 -	.byte $20 -	.byte $10 -	.byte $08 -	.byte $04 -	.byte $02 -	.byte $01 +	.byte $80, $40, $20, $10, $08, $04, $02, $01  ; This label is for any included files.  incl:  ; Linewrap table. -.org $1000 +.org $30000  bitabl:  	.qword 0  	.qword 0 -; Input buffer. -.org $2000 +; SCreen buffer. +.org bitabl+$1000  buffer: -.org $4000 +; Command buffer. +.org buffer+$2000  cmd_buf: @@ -93,7 +106,7 @@ zero:  ; End of pseudo registers.  end: -	.word 0 +	.qword 0  bitmask:  	.byte 0  scr_str: @@ -129,8 +142,9 @@ reset:  	inc end		;  	lda.w #$1FFF	; Set the clear count to $1FFF.  	sta.w scr_ptr	; -	lda.w #buffer	; Set the array to be cleared to the screen buffer. +	lda.d #buffer	; Set the array to be cleared to the screen buffer.  	jsl clr_arr	; Clear the screen buffer. +	jsl pnt_strt	; Print the starting message.  	jmp start	; Goto the start of the main program.  clr_arr: @@ -163,6 +177,25 @@ clr_arr_end:  	plb #1		; Get whatever was in the B register, back.  	rtl		; End of clr_arr. +pnt_strt: +	lda.w #ed_name	; Print the name of the editor. +	jsl print_str	; +	lda.w #ver_str	; Print the version text. +	jsl print_str	; +	lda.w #ed_ver	; Print the version number. +	jsl print_str	; +	lda.w #ed_sver	; Print the sub version number. +	jsl print_str	; +	lda #'\n'	; Print a newline. +	jsl print_char	; +	lda.w #made	; Print the "Created by" text. +	jsl print_str	; +	lda.w #author	; Print the name of the author. +	jsl print_str	; +	lda #'\n'	; Print a newline. +	jsl print_char	; +	rtl		; End of pnt_strt. +  start:  	lda #0		; TODO: Update this for the Super VIA.  	sta status	; Clear the control register of the I/O adapter. @@ -171,12 +204,10 @@ start:  	tay		; Reset the cursor index.  	lda.w #$3FF	; Set the clear count to $3FF.  	sta.w scr_ptr	; -	lda.w #cmd_buf	; Set the array to be cleared to the command buffer. +	lda.d #cmd_buf	; Set the array to be cleared to the command buffer.  	jsl clr_arr	; Clear the command buffer.  	ply #2		; Get back the cursor index. -	lda.w #string	; Print the startup message. -	jsl print_str	; -	lsr #$10	; Reset the Accumulator. +	and #0		; Reset the Accumulator.  	sta end		;  	jmp read	; Start reading the keyboard. @@ -191,19 +222,20 @@ read:  	jmp read	; No, so keep looping.  print_str: -	sta.w end	; Save the parameter. +	ldx #0		; Reset X. +	sta.q end	; Save the parameter.  print_str2: -	lda.w end	; Get the parameter. +	lda.q end	; Get the parameter.  	ldb #0		; Clear the B register.  	jsl set_ptr	; Set the first pointer to the parameter.  	tba		; Clear the Accumulator. -	inb		; Enable replace mode. -	stb b		;  pntstr_lp: -	lda.w ptr	; Get the first pointer. -	cmp.w end	; Did the pointer change? +	ldb #1		; Enable replace mode. +	stb b		; +	lda.q ptr	; Get the first pointer. +	cmp.q end	; Did the pointer change?  	bne print_str2	; Yes, so set it back. -	lsr #$10	; No, reset the accumulator. +	and #0		; No, reset the accumulator.  	phy #2		; Save the cursor index.  	txy		; Copy the string index into Y.  	lda (ptr), y    ; Are we at the end of the string? @@ -230,7 +262,7 @@ getbt0:  getbt1:  	pha #1		; Save the parameter.  	ldb #1		; Make sure that set_ptr sets the second pointer. -	lda.w #bitabl	; Set the second pointer to the linewrap table. +	lda.d #bitabl	; Set the second pointer to the linewrap table.  	jsl set_ptr	;  	lsr #$10	; Clear the Accumulator.  	pla #1		; Get the return byte back. @@ -246,9 +278,9 @@ getbt1:  clrbit:  	pha #1		; Save the parameter.  	ldb #1		; Make sure that set_ptr sets the second pointer. -	lda.w #bitabl	; Set the second pointer to the linewrap table. +	lda.d #bitabl	; Set the second pointer to the linewrap table.  	jsl set_ptr	; -	lsr #$10	; Clear the Accumulator. +	and #0		; Clear the Accumulator.  	pla #1		; Get the return byte back.  	jsl bitpos	; Get the bit, and byte position.  	xor #$FF	; Invert the bitmask. @@ -266,9 +298,9 @@ bitout:  setbit:  	pha #1		; Save the parameter.  	ldb #1		; Make sure that set_ptr sets the second pointer. -	lda.w #bitabl	; Set the second pointer to the linewrap table. +	lda.d #bitabl	; Set the second pointer to the linewrap table.  	jsl set_ptr	; -	lsr #$10	; Clear the Accumulator. +	and #0		; Clear the Accumulator.  	pla #1		; Get the return byte back.  	jsl bitpos	; Get the bit, and byte position.  	phy #2		; Save the screen index. @@ -282,7 +314,7 @@ bitpos:  	ldb #0		; Make sure that set_ptr sets the first pointer.  	lda.w #bits	; Set the first pointer to the bitmask table.  	jsl set_ptr	; -	lsr #$10	; Clear the Accumulator. +	and #0		; Clear the Accumulator.  	pla #1		; Get the parameter back.  	stx bitmask	; Make the line number the bitmask.  	txa		; Copy it to the Accumulator. @@ -361,10 +393,10 @@ cmd_cpy3:  	tay		; Place it into the index.  	ldx.w #0	; Reset the X register.  	ldb #0		; Make sure that set_ptr sets the first pointer. -	lda.w #buffer	; Set the first pointer to the start of the screen buffer. +	lda.d #buffer	; Set the first pointer to the start of the screen buffer.  	jsl set_ptr	;  	inb		; Make sure that set_ptr sets the second pointer. -	lda.w #cmd_buf	; Set the second pointer to the start of the command buffer. +	lda.d #cmd_buf	; Set the second pointer to the start of the command buffer.  	jsl set_ptr	;  	deb		; Set B back to zero.  	tba		; Set the accumulator to zero. @@ -403,26 +435,26 @@ cmd_cpy_nd:  findst: -	lda #0		; +	lda #0		; Reset A.  findst_lp: -	pha #1		; -	jsl getbit	; -	pla #1		; -	bcc findst_done	; -	inc		; -	dec scr_row	; -	bpo findst_lp	; -	dec		; -	inc scr_row	; +	pha #1		; Save the current line number. +	jsl getbit	; Is this the start of the line? +	pla #1		; Get the current line number back. +	bcc findst_done	; Yes, so we're done. +	inc		; No, so check the next physical line. +	dec scr_row	; Are we at the top of the screen? +	bpo findst_lp	; No, so keep looping. +	dec		; Yes, so move back one line. +	inc scr_row	; Put the row postiion back to zero.  findst_done: -	cmp #0		; -	rtl		; +	cmp #0		; Update all the flags. +	rtl		; End of findst.  fndend:  	phb #1		; Save the contents of the B register.  	ldb #0		; Make sure that set_ptr sets the first pointer. -	lda.w #buffer	; Set the first pointer to the start of the screen buffer. +	lda.d #buffer	; Set the first pointer to the start of the screen buffer.  	jsl set_ptr	;  	tba		; Set the Accumulator to zero.  	plb #1		; Restore the contents of the B register. @@ -446,16 +478,13 @@ findend:  parse:  	lda #0		;  	tax		; -	jsl dabbed	; -	beq start	; -	lda #0		; -	tax		; -	jmp result	; +	jsl subasm	; +	jmp start	;  print_char:  	sta a		; Save the typed character for now.  	ldb #2		; Make sure that set_ptr sets the third pointer. -	lda.w #buffer	; Set the third pointer to the start of the screen buffer. +	lda.d #buffer	; Set the third pointer to the start of the screen buffer.  	jsl set_ptr	;  	ldb #0		; Set B to zero.  	tba		; Set the Accumulator to zero. @@ -482,25 +511,25 @@ printc:  	lda b		; No, but was the flag set?  	bne printc_save	; Yes, so don't shift the line.  	sty.w scr_ptr	; No, so save the cursor index for later. -	jsl fndend	; -	jmp prntc_movln	; +	jsl fndend	; Find the end of the line. +	jmp prntc_movln	; Start shifting the line right.  prntc_updt: -	lda scr_col	; +	lda scr_col	; Save the current column position for later.  	sta scr_tcol	;  prntc_updt2: -	jsl findend	; -	sta e		; -	sta scr_row	; -	jsl findst	; -	lda scr_row	; +	jsl findend	; Find the end of the line. +	sta e		; Use it for redrawing the line. +	sta scr_row	; Set the row position to to the end of the line. +	jsl findst	; Find the start of the line. +	lda scr_row	; Get the start of the line.  prntc_updt3: -	sta f		; -	jsl rdrw_ln	; -	lda scr_trow	; +	sta f		; Set the starting line, to the start of the line. +	jsl rdrw_ln	; Redraw the line. +	lda scr_trow	; Get the real row position back.  	sta scr_row	; -	lda scr_tcol	; +	lda scr_tcol	; Get the real column position back.  	sta scr_col	; -	jsl update_pos	; +	jsl update_pos	; Update the cursor's position.  	dec d		;  	jmp printc_sav1	;  prntc_movln: @@ -574,22 +603,22 @@ printc_end:  	rtl		;  nl: -	lda #0		; -	ldb (ptr3), y	; -	bne nl1		; -	sta (ptr3), y	; Store said terminator into the input buffer. +	lda #0		; Reset A. +	ldb (ptr3), y	; Is this character not a null terminator? +	bne nl1		; Yes, so don't overwrite it. +	sta (ptr3), y	; No, so overwrite it.  nl1: -	sta scr_col	; -	lda scr_row	; -	cmp #maxrow	; -	bcc nl_inc	; -	jsl scrl_down	; -	jmp nl_end	; +	sta scr_col	; Move the cursor to the start of the next line. +	lda scr_row	; Get the row position. +	cmp #maxrow	; Are we at the bottom of the screen? +	bcc nl_inc	; No, so move down one line. +	jsl scrl_down	; Yes, so scroll down one line. +	jmp nl_end	; We are done.  nl_inc: -	inc scr_row	; -	jsl update_pos	; +	inc scr_row	; Move the cursor down by one line. +	jsl update_pos	; Update the cursor's position.  nl_end: -	lda #'\n'	; +	lda #'\n'	; Print the newline.  	sta a		;  	jmp printc_end	; @@ -603,12 +632,12 @@ clr_scr:  	tay		;  	lda.w #$1FFF	; Set the clear count to $1FFF.  	sta.w scr_ptr	; -	lda.w #buffer	; Set the array to be cleared to the command buffer. +	lda.d #buffer	; Set the array to be cleared to the screen buffer.  	jsl clr_arr	; Clear the screen buffer.  	tay		;  	lda.w #$3FF	; Set the clear count to $3FF.  	sta.w scr_ptr	; -	lda.w #buffer	; Set the array to be cleared to the command buffer. +	lda.d #cmd_buf	; Set the array to be cleared to the command buffer.  	jsl clr_arr	; Clear the screen buffer.  	sta scr_col	;  	sta scr_row	; @@ -636,18 +665,18 @@ step_dis:  	jmp printc_end	;  back: -	ldb #0		; +	ldb #0		; Reset B, and some flags.  	stb e		;  	stb f		; -	lda scr_row	; +	lda scr_row	; Save the current row position for later.  	sta scr_trow	; -	jsl findend	; -	sta scr_row	; +	jsl findend	; Find the end of the line. +	sta scr_row	; Set our row position to the end of the line.  back0: -	jsl findst	; -	beq back1	; -	bcs back_updt	; -	lda scr_trow	; +	jsl findst	; Does this line take up more than one real line? +	beq back1	; No, so skip updating any other lines. +	bcs back_updt	; Yes, so update the other lines. +	lda scr_trow	; Get the real row position back.  	sta scr_row	;  back1:  	dey		; Decrement the buffer's offset. @@ -655,32 +684,32 @@ back1:  	sta (ptr3), y	; into the buffer.  	tyx		; Copy the current cursor index to X.  	iny		; Increment cursor index. -	ldb #0		; +	ldb #0		; Set shifting direction to left.  	stb d		;  	jsl shftln	; Shift line back by one character.  	lda #$7F	; Print a backspace to the screen.  	sta scr		; -	lda e		; -	beq back3	; +	lda e		; Are we updating more than one line? +	beq back3	; No, so skip to the next step.  back2: -	jsl findend	; -	sta e		; -	lda scr_col	; +	jsl findend	; Yes, so find the end of the line. +	sta e		; Set the end parameter to it. +	lda scr_col	; Save the current column position for now.  	sta scr_tcol	; -	jsl rdrw_ln	; -	lda scr_tcol	; +	jsl rdrw_ln	; Start redrawing the line. +	lda scr_tcol	; Get the real column position back.  	sta scr_col	;  back3: -	lda scr_trow	; +	lda scr_trow	; Get the real row position bac.  	sta scr_row	;  	dec scr_col	; Move the cursor back by one column,  	jsl update_pos	; and update it's position.  	jmp printc_end	; We are done.  back_updt: -	lda scr_row	; +	lda scr_row	; Set the line to start redrawing, to the start of the line.  	sta f		; -	inc e		; -	jmp back1	; +	inc e		; Set the redraw flag to true. +	jmp back1	; Start shifting the line back.  bs:  	lda scr_col	; Are we at the far left of the screen? @@ -1155,62 +1184,6 @@ rdrow_end:  rdrow_done:  	rtl		; -result: -	lda.w #string2	; -	ldx.w zero	; -	jsl print_str	; -rset_x: -	lda #0		; Reset a. -	tax		; Reset x. -	jmp print_buf	; Print the input buffer. - -dabbed: -	ldb #0		; Make sure that set_ptr is setting the first pointer. -	lda.w #cmd_buf	; Set the first pointer to the start of the command buffer. -	jsl set_ptr	; -	inb		; Make set_ptr set the second pointer. -	lda.w #tok	; Set the second pointer to the start of the token string. -	jsl set_ptr	; -	deb		; Set B back to zero. -	tba		; Also set the accumulator back to zero. -dab_st: -	phy #2		; -	txy		; -	lda (ptr), y	; Are we at the end of the string? -	beq dab_pend	; Yes, so return false. -	cmp (ptr2), y	; No, but is this character the same as the character in the token string? -	beq chk_str	; Yes, so increment the character count. -	jmp dab_pend	; No, so return false. -chk_str: -	ply #2		; -	inx		; -	cpx #3		; -	bne dab_st	; -	ldx #0		; -pnt_msg: -	lda.w #msg	; -	ldx #0		; -	jsl print_str	; -	jmp dab_peqnd	; -dab_pend: -	ply #2		; -	lda #1		; -	jmp dab_end	; -dab_peqnd: -	lda #0		; -	jmp dab_end	; -dab_end: -	rtl		; - -print_buf: -	lda.w #cmd_buf	; -	jsl print_str	; -	lsr #$10	; Clear the Accumulator. -cmd_clr: -	lda #'\n'	; -	jsl print_char	; -	jmp start	; -  rdrw_ln:  	lda scr_row	;  	pha #1		; @@ -1246,12 +1219,15 @@ set_ptr:  	cpb #2		; No, but are we setting the third pointer?  	beq set_ptr3	; Yes, so start setting it.  set_ptr1: +	stb.q ptr	; Reset the first pointer.  	sta.q ptr	; No, so set the first pointer.  	jmp setptr_end	; We are done.  set_ptr2: +	stb.q ptr2	; Reset the second pointer.  	sta.q ptr2	; Set the second pointer.  	jmp setptr_end	; We are done.  set_ptr3: +	stb.q ptr3	; Reset the third pointer.  	sta.q ptr3	; Set the third pointer.  setptr_end:  	rtl		; End of set_ptr. @@ -97,7 +97,11 @@ void *run(void *args) {  		#if keypoll  		pthread_mutex_lock(&mutex);  		#endif -		wmove(scr, lines, 0); +		for (uint8_t i = (24*thread)+2; i <= 24*(thread+1); i++) { +			wmove(scr, i, 0); +			waddch(scr, (i == lines) ? '>' : ' '); +		} +		wmove(scr, lines, 1);  		wclrtoeol(scr);  		wprintw(scr,  			"pc: $%04"PRIX64 @@ -8,10 +8,10 @@  #define THREADS	1  #define BENCH_INST 100000000 << (THREADS-1) -#define CTRL_ADDR 0xC000 -#define TX_ADDR 0xC001 -#define RX_ADDR 0xC002 -#define STEP_ADDR 0xC010 +#define CTRL_ADDR 0x100 +#define TX_ADDR 0x101 +#define RX_ADDR 0x102 +#define STEP_ADDR 0x110  #define CURSES_BACKSPACE 0x7F  extern uint8_t kbd_rdy;  | 
