From 9526483f93b5950ecfa81a93f30b617bec22dfe1 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Wed, 11 Dec 2019 11:28:30 -0500 Subject: We can print to the Screen!!!! I also added the ASR instruction, for doing arithmetic shifts, and have added a hello world program. --- asmmon.c | 209 ++++++++++++++++++++++++++++++++++++++++++----------- opcode.h | 8 +- sux.c | 84 +++++++++++++-------- test/asr.s | 19 +++++ test/hello-world.s | 56 ++++++++++++++ 5 files changed, 299 insertions(+), 77 deletions(-) create mode 100644 test/asr.s create mode 100644 test/hello-world.s diff --git a/asmmon.c b/asmmon.c index 5b30fdc..43811f7 100644 --- a/asmmon.c +++ b/asmmon.c @@ -4,7 +4,7 @@ #define debug 1 -#define OPNUM 87 +#define OPNUM 88 #define SETOP(num, _mne, _IMM, _ZM, _ZMX, _ZMY, _ABS, _IMPL) \ {opcodes[num].mnemonic[3] = '\0'; strncpy(opcodes[num].mnemonic, _mne, 3); \ opcodes[num].imm = _IMM; \ @@ -24,6 +24,7 @@ struct label { uint8_t def; char name[1]; }; +static char tstr[2048]; struct label *labels = 0; struct fixup *fixups = 0; uint8_t defined = 0; @@ -190,28 +191,29 @@ int asmmon() { SETOP(62, "BVC", 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00); SETOP(63, "DIV", 0xA1, 0xA5, 0x00, 0x00, 0xA3, 0x00); SETOP(64, "CLV", 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8); - SETOP(65, "RTS", 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0); - SETOP(66, "CMP", 0xB1, 0xF5, 0x00, 0x00, 0xE5, 0x00); - SETOP(67, "CPY", 0xB2, 0xF2, 0x00, 0x00, 0xE2, 0x00); - SETOP(68, "CAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3); - SETOP(69, "CPX", 0xB4, 0xF4, 0x00, 0x00, 0xE4, 0x00); - SETOP(70, "CAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5); - SETOP(71, "ENT", 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00); - SETOP(72, "RTI", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0); - SETOP(73, "INC", 0x00, 0xE3, 0x00, 0x00, 0xE1, 0xC1); - SETOP(74, "INY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2); - SETOP(75, "IAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3); - SETOP(76, "INX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4); - SETOP(77, "IAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5); - SETOP(78, "DEC", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1); - SETOP(79, "DEY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2); - SETOP(80, "DAY", 0x00, 0xF3, 0x00, 0x00, 0xF1, 0xD3); - SETOP(81, "DEX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4); - SETOP(82, "DAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5); - SETOP(83, "JSL", 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00); - SETOP(84, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8); - SETOP(85, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0); - SETOP(86, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8); + SETOP(65, "ASR", 0xA9, 0xAD, 0x00, 0x00, 0xAB, 0x00); + SETOP(66, "RTS", 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0); + SETOP(67, "CMP", 0xB1, 0xF5, 0x00, 0x00, 0xE5, 0x00); + SETOP(68, "CPY", 0xB2, 0xF2, 0x00, 0x00, 0xE2, 0x00); + SETOP(69, "CAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3); + SETOP(70, "CPX", 0xB4, 0xF4, 0x00, 0x00, 0xE4, 0x00); + SETOP(71, "CAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5); + SETOP(72, "ENT", 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00); + SETOP(73, "RTI", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0); + SETOP(74, "INC", 0x00, 0xE3, 0x00, 0x00, 0xE1, 0xC1); + SETOP(75, "INY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2); + SETOP(76, "IAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3); + SETOP(77, "INX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4); + SETOP(78, "IAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5); + SETOP(79, "DEC", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1); + SETOP(80, "DEY", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2); + SETOP(81, "DAY", 0x00, 0xF3, 0x00, 0x00, 0xF1, 0xD3); + SETOP(82, "DEX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4); + SETOP(83, "DAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5); + SETOP(84, "JSL", 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00); + SETOP(85, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8); + SETOP(86, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0); + SETOP(87, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8); uint8_t done = 0; uint64_t address = 0x0000; while (!(done & 1)) { @@ -224,6 +226,8 @@ int asmmon() { uint64_t value = 0; char *oprand; char *cmd; + char ir[2] = ""; /* Index register. */ + int a = 0; char *tmp = malloc(sizeof(char *)*128); size_t size; done &= ~0x1F; @@ -235,8 +239,29 @@ int asmmon() { } else { ins = strtok(buf, "\t\n "); if (ins != NULL) { - oprand = strtok(NULL, "\t\n "); + oprand = strtok(NULL, "\t\n"); strtok_r(ins, ".", &postfix); + if (oprand != NULL) { + for (int i = 0; i < strlen(oprand); i++) { + if (oprand[i] == '"') + break; + if (oprand[i] == 'x' || oprand[i] == 'X') { + ir[0] = 'x'; + ir[1] = '\0'; + break; + } + if (oprand[i] == 'y' || oprand[i] == 'Y') { + ir[0] = 'y'; + ir[1] = '\0'; + break; + } + if (oprand[i] == ',' || oprand[i] == ';') { + a = i; + } + } + if (a) + oprand[a] = '\0'; + } } if (strcasecmp(cmd, "quit") == 0 || strcasecmp(cmd, "q") == 0) { return 2; @@ -277,23 +302,86 @@ int asmmon() { } if (strcasecmp(ins, ".byte") == 0 || strcasecmp(ins, ".word") == 0 || strcasecmp(ins, ".dword") == 0 || strcasecmp(ins, ".qword") == 0) { done |= 6; + uint8_t qstr = 0; + uint64_t staddr = address; + uint16_t slen = 0; + char *tmpstr = tstr; + char c; for (int i = 0; i < strlen(oprand); i++) { - if (oprand[i] == '$') { - oprand = strtok(oprand, "$"); - value = strtoull(oprand, NULL, 16); - break; - } - if (oprand[i] == ';') { - done |= 16; - break; - } - if (isalnum(oprand[i]) || oprand[i] == '_') { - use_label(oprand, address); - sprintf(oprand, "%llx", value); - break; + if (!qstr) { + if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') { + qstr = 0; + value = use_label(oprand, address); + sprintf(oprand, "%llx", value); + break; + } + if (oprand[i] == '"' && !strcasecmp(ins, ".byte")) { + qstr = 1; + continue; + } + if (oprand[i] == '$') { + qstr = 0; + oprand = strtok(oprand, "$"); + value = strtoull(oprand, NULL, 16); + break; + } + if (oprand[i] == ';') { + qstr = 0; + done |= 16; + break; + } + } else if (qstr == 1) { + switch (oprand[i]) { + case 0: + puts("oof, unterminated string."); + qstr = 2; + break; + case '"': + value = '\0'; + c = '\0'; + tmpstr[slen++] = '\0'; + qstr = 3; + break; + case '\\': + switch (oprand[i+1]) { + case 'n': + value = '\n'; + c = '\n'; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = 'n'; + break; + case 't': + value = '\t'; + c = '\t'; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = 't'; + break; + case 'r': + value = '\r'; + c = '\r'; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = 'r'; + break; + case '0': + break; + default: + value = oprand[i]; + tmpstr[slen++] = '\\'; + tmpstr[slen++] = oprand[i]; + break; + } + i++; + break; + default: + value = oprand[i]; + c = oprand[i]; + tmpstr[slen++] = c; + break; + } + addr[address++] = value & 0xFF; } } - if (strcasecmp(ins, ".byte") == 0) + if (strcasecmp(ins, ".byte") == 0 && !qstr) addr[address++] = value & 0xFF; if (strcasecmp(ins, ".word") == 0) { addr[address] = value & 0xFF; @@ -319,7 +407,19 @@ int asmmon() { address+=8; } #if debug - printf("The value $%llx was placed at address $%llx.\n", value, address); + if (!qstr) { + printf("The value $%llx was placed at address%s ", value, (staddr != address-1) ? "es" : ""); + if (staddr == address-1) + printf("$%llx.\n", staddr); + else + printf("$%llx-$%llx.\n", staddr, address-1); + } else { + printf("The string \"%s\", was placed at address%s ", tmpstr, (staddr != address-1) ? "es" : ""); + if (staddr == address-1) + printf("$%llx.\n", staddr); + else + printf("$%llx-$%llx.\n", staddr, address-1); + } #endif } } @@ -362,6 +462,16 @@ int asmmon() { } else if (value & 0xFFFFFFFF00000000) { addrmode = 5; } + if (addrmode == 2 && ir != NULL) { + switch (ir[0]) { + case 'x': + addrmode = 3; + break; + case 'y': + addrmode = 4; + break; + } + } } } else { for (int i = 0; i < strlen(oprand); i++) { @@ -369,7 +479,7 @@ int asmmon() { done |= 16; break; } - if (isalnum(oprand[i]) || oprand[i] == '_') { + if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') { value = use_label(oprand, address); if (value == 0) addrmode = 2; @@ -383,10 +493,19 @@ int asmmon() { addrmode = 2; } } - } else if (value & 0xFFFFFFFF00000000) { addrmode = 5; } + if (addrmode == 2 && ir != NULL) { + switch (ir[0]) { + case 'x': + addrmode = 3; + break; + case 'y': + addrmode = 4; + break; + } + } sprintf(oprand, "%llx", value); break; } @@ -415,6 +534,7 @@ int asmmon() { case LSR: case ROL: case ROR: + case ASR: case ENT: done |= 8; break; @@ -495,6 +615,7 @@ int asmmon() { case LSR: case ROL: case ROR: + case ASR: case ENT: addr[address++] = value & 0xFF; break; @@ -541,7 +662,7 @@ int asmmon() { break; case 3: if (op.zmx) { - addr[address++] = op.zmy; + addr[address++] = op.zmx; addr[address] = value & 0xFF; addr[address+1] = value >> 8; addr[address+2] = value >> 16; @@ -591,7 +712,9 @@ int asmmon() { #else printf("Postfix: %s, ", (postfix[0] != '\0') ? postfix : "none"); #endif - printf("Operand: %s, Address: $%llx\n", (oprand != NULL && !(done & 16)) ? oprand : "none", address); + printf("Operand: %s, ", (oprand != NULL && !(done & 16)) ? oprand : "none"); + printf("Index Register: %s, ", (ir != NULL) ? ir : "none"); + printf("Address: $%llx\n", address); } #endif } diff --git a/opcode.h b/opcode.h index 990df5a..92d504c 100644 --- a/opcode.h +++ b/opcode.h @@ -69,6 +69,7 @@ #define BVC 0xA0 /* Branch if oVerflow Clear. */ #define DIV 0xA1 /* DIVide with accumulator. */ #define CLV 0xA8 /* CLear oVerflow flag. */ +#define ASR 0xA9 /* Arithmetic Shift Right. */ #define RTS 0xB0 /* ReTurn from Subroutine. */ #define CMP 0xB1 /* CoMPare accumulator. */ #define CPY 0xB2 /* ComPare Y register. */ @@ -232,8 +233,8 @@ static const char *opname[0x100] = { [0x95] = "MUL zm", OPNAME(SEV), [0x99] = "LDA zm, y", - [0x9B] = "LDX zm, y", - [0x9C] = "STA zm, y", + [0x9B] = "STA zm, y", + [0x9C] = "LDX zm, y", [0x9E] = "STX zm, y", OPNAME(BVC), [DIV] = "DIV #", @@ -242,6 +243,9 @@ static const char *opname[0x100] = { [0xA4] = "XRX zm", [0xA5] = "DIV zm", OPNAME(CLV), + [ASR] = "ASR #", + [0xAB] = "ASR a", + [0xAD] = "ASR zm", OPNAME(RTS), [CMP] = "CMP #", [CPY] = "CPY #", diff --git a/sux.c b/sux.c index 97a695d..19263c3 100644 --- a/sux.c +++ b/sux.c @@ -3,12 +3,15 @@ #include #include #define bench 0 +#define debug 0 +#define IO 1 #if bench #include #endif #define THREADS 1 #define BENCH_INST 100000000*THREADS +#define DATA_ADDR 0xC001 uint64_t clk[THREADS]; /* Per Thread Clock cycles. */ uint64_t tclk; /* Total Clock cycles. */ uint64_t inst[THREADS]; @@ -37,6 +40,7 @@ void *run(void *args) { uint64_t value = 0; uint64_t iclk = 0; uint64_t ins = 0; + uint64_t sign = 0; char *s = malloc(2048); uint8_t lines = (6*thread)+2; uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */ @@ -51,10 +55,10 @@ void *run(void *args) { prefix = 0; opcode = addr[cpu->pc[thread]]; - #if !bench + #if debug && !bench sprintf(s, "\033[%uH" "pc: 0x%08llx, a: 0x%016llx, x: 0x%016llx, y: 0x%016llx" - ", sp: 0x%04lx, ps: 0x%016llx, prefix: 0x%02x, opcode: 0x%02x, thread: %u, inst: %s \r" + ", sp: 0x%04lx, ps: 0x%016llx, prefix: 0x%02x, opcode: 0x%02x, thread: %u, inst: %s \r" , lines , cpu->pc[thread], cpu->a[thread], cpu->x[thread], cpu->y[thread] , cpu->sp[thread], cpu->ps, prefix, opcode, thread, opname[opcode]); @@ -87,7 +91,7 @@ void *run(void *args) { case 0x05: /* ADC Zero Matrix. */ if (opcode == ADC) { address = cpu->pc[thread]; - cpu->pc[thread]++; + cpu->pc[thread]+=regsize; } if (opcode == 0x03) { address = (uint64_t)addr[cpu->pc[thread]] @@ -247,7 +251,7 @@ void *run(void *args) { case 0x15: /* SBC Zero Matrix. */ if (opcode == SBC) { address = cpu->pc[thread]; - cpu->pc[thread]++; + cpu->pc[thread]+=regsize; } if (opcode == 0x13) { address = (uint64_t)addr[cpu->pc[thread]] @@ -706,14 +710,22 @@ void *run(void *args) { cpu->pc[thread]+=4; iclk++; } - if (opcode == STA || opcode == 0x7B) + if (opcode == STA || opcode == 0x7B || opcode == 0x8B || opcode == 0x9B) value = cpu->a[thread]; - if (opcode == STY || opcode == 0x7D) + if (opcode == STY || opcode == 0x7D || opcode == 0x8D) value = cpu->y[thread]; - if (opcode == STX || opcode == 0x7E) + if (opcode == STX || opcode == 0x7E || opcode == 0x9E) value = cpu->x[thread]; addr[address] = value & 0xFF; + #if IO + if (address == DATA_ADDR) { + if (addr[address] == '\b') + putchar('\b'); + else + putchar(addr[address]); + } + #endif if (regsize >= 2) addr[address+1] = value >> 8; if (regsize >= 4) { @@ -744,11 +756,14 @@ void *run(void *args) { case LSR: /* LSR Immediate. */ case 0x63: /* LSR Absolute. */ case 0x65: /* LSR Zero Matrix. */ - if (opcode == LSR) { + case ASR: /* ASR Immediate. */ + case 0xAB: /* ASR Absolute. */ + case 0xAD: /* ASR Zero Matrix. */ + if (opcode == LSR || opcode == ASR) { address = cpu->pc[thread]; cpu->pc[thread]++; } - if (opcode == 0x63) { + if (opcode == 0x63 || opcode == 0xAB) { address = (uint64_t)addr[cpu->pc[thread]] | (uint64_t)addr[cpu->pc[thread]+1] << 8 | (uint64_t)addr[cpu->pc[thread]+2] << 16 @@ -760,7 +775,7 @@ void *run(void *args) { cpu->pc[thread]+=8; iclk++; } - if (opcode == 0x65) { + if (opcode == 0x65 || opcode == 0xAD) { address = addr[cpu->pc[thread]] | addr[cpu->pc[thread]+1] << 8 | addr[cpu->pc[thread]+2] << 16 @@ -769,7 +784,13 @@ void *run(void *args) { iclk++; } value = addr[address]; - sum = (value < 64) ? cpu->a[thread] >> value : 0; + if (opcode == ASR || opcode == 0xAB || opcode == 0xAD) { + sign = cpu->a[thread] & 0x8000000000000000; + sum = (value < 64) ? (cpu->a[thread] >> value) | sign : 0; + } + if (opcode == LSR || opcode == 0x63 || opcode == 0x65) { + sum = (value < 64) ? cpu->a[thread] >> value : 0; + } cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] & 1; @@ -836,11 +857,11 @@ void *run(void *args) { value += (uint64_t)addr[address+6] << 48; value += (uint64_t)addr[address+7] << 56; } - if (opcode == LDA || opcode == 0x59 || opcode == 0x79) + if (opcode == LDA || opcode == 0x59 || opcode == 0x79 || opcode == 0x89 || opcode == 0x99) cpu->a[thread] = value; - if (opcode == LDY || opcode == 0x5A || opcode == 0x7A) + if (opcode == LDY || opcode == 0x5A || opcode == 0x7A || opcode == 0x8A) cpu->y[thread] = value; - if (opcode == LDX || opcode == 0x5C || opcode == 0x7C) + if (opcode == LDX || opcode == 0x5C || opcode == 0x7C || opcode == 0x9C) cpu->x[thread] = value; cpu->z[thread] = (value == 0); cpu->n[thread] = (value >> 63); @@ -978,7 +999,7 @@ void *run(void *args) { case 0x95: /* MUL Zero Matrix. */ if (opcode == MUL) { address = cpu->pc[thread]; - cpu->pc[thread]++; + cpu->pc[thread]+=regsize; } if (opcode == 0x93) { address = (uint64_t)addr[cpu->pc[thread]] @@ -1048,7 +1069,7 @@ void *run(void *args) { case 0xA5: /* DIV Zero Matrix. */ if (opcode == DIV) { address = cpu->pc[thread]; - cpu->pc[thread]++; + cpu->pc[thread]+=regsize; } if (opcode == 0xA3) { address = (uint64_t)addr[cpu->pc[thread]] @@ -1117,7 +1138,7 @@ void *run(void *args) { case 0xF5: /* CMP Zero Matrix. */ if (opcode == CMP || opcode == CPY || opcode == CPX) { address = cpu->pc[thread]; - cpu->pc[thread]++; + cpu->pc[thread]+=regsize; } if (opcode == 0xE5 || opcode == 0xE2 || opcode == 0xE4) { address = (uint64_t)addr[cpu->pc[thread]] @@ -1360,18 +1381,19 @@ void *run(void *args) { break; default: if(opcode != BRK) { - printf("Cool, you inputed a non existent opcode, which means\n" + /*printf("Cool, you inputed a non existent opcode, which means\n" "that you have now wasted clock cycles.\n" - "Good job! *clap*\n"); + "Good job! *clap*\n");*/ } break; } ins++; - #if !bench + #if debug && !bench sprintf(s, "\033[%uHInstructions executed: %llu, Clock cycles: %llu\n", (6*thread)+1, ins, iclk); fwrite(s, sizeof(char), strlen(s), stdout); fflush(stdout); #endif + #if bench if (ins >= BENCH_INST) { end = 1; pthread_mutex_lock(&mutex); @@ -1380,10 +1402,9 @@ void *run(void *args) { clk[thread] = iclk; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); -#if bench - gettimeofday(&en[thread], 0); -#endif + gettimeofday(&en[thread], 0); } + #endif } free(s); } @@ -1405,14 +1426,14 @@ int main(int argc, char **argv) { thr[i].sx.a[i] = 0; thr[i].sx.x[i] = 0; thr[i].sx.y[i] = 0; - thr[i].sx.pc[i] = (uint64_t)addr[0xFF50+(8*i)] - | (uint64_t)addr[0xFF51+(8*i)] << 8 - | (uint64_t)addr[0xFF52+(8*i)] << 16 - | (uint64_t)addr[0xFF53+(8*i)] << 24 - | (uint64_t)addr[0xFF54+(8*i)] << 32 - | (uint64_t)addr[0xFF55+(8*i)] << 40 - | (uint64_t)addr[0xFF56+(8*i)] << 48 - | (uint64_t)addr[0xFF57+(8*i)] << 56; + thr[i].sx.pc[i] = (uint64_t)addr[0xFF50+(8*(i-1))] + | (uint64_t)addr[0xFF51+(8*(i-1))] << 8 + | (uint64_t)addr[0xFF52+(8*(i-1))] << 16 + | (uint64_t)addr[0xFF53+(8*(i-1))] << 24 + | (uint64_t)addr[0xFF54+(8*(i-1))] << 32 + | (uint64_t)addr[0xFF55+(8*(i-1))] << 40 + | (uint64_t)addr[0xFF56+(8*(i-1))] << 48 + | (uint64_t)addr[0xFF57+(8*(i-1))] << 56; } else { thr[i].sx.a[i] = 0; thr[i].sx.x[i] = 0; @@ -1472,7 +1493,6 @@ int main(int argc, char **argv) { mhz = 1000000.0/clkspd/1000000; sprintf(tmp, "Instructions executed for thread %i: %llu, Instructions per Second for thread %i in MIPS: %f, tm: %f\n", i, inst[i], i, ips[i], tm[i]/1000000); fwrite(tmp, sizeof(char), strlen(tmp), stdout); - fflush(stdout); } clkspd = (ttm/1000000)*1000000/tclk; mhz = 1000000.0/clkspd/1000000; diff --git a/test/asr.s b/test/asr.s new file mode 100644 index 0000000..6377875 --- /dev/null +++ b/test/asr.s @@ -0,0 +1,19 @@ +; Testing Signed shifts. +; +; Writen by mr b0nk 500 + +reset: + cps + +start: + lda.q #$-FFFF + +signshft: + asr #$1 + cmp.q #$-1 + beq start + jmp signshft + +.org $0 +done + diff --git a/test/hello-world.s b/test/hello-world.s new file mode 100644 index 0000000..fef5a46 --- /dev/null +++ b/test/hello-world.s @@ -0,0 +1,56 @@ +; Hello world. +; Writen in Sux assembly by mr b0nk 500 + +; Initialize, and declare variables. +.org $8000 +string: + .byte "Hello, world!\n" + +; Get CPU into a known state. +.org $0 +reset: + cps ; Reset the processor status. + ldx.w #$FFFF ; Set up the stack pointer. + txs ; Reset the stack pointer. + +; Start of main program. +start: + ldx.w #$0 ; Reset x. + jmp print + +line_count: + iny ; Increment the line count. + cpy #$32 + beq spin ; Have we printed 50 lines? + jmp start ; Keep looping until we have printed 50 lines. + +; Printing sub routine. +print: + lda string, x ; Get character at offset x. + beq line_count ; Did we find a null terminator? + sta $C001 ; Print character. + inx ; Increment offset. + jmp print ; Keep printing more characters. + +; The other threads would clash, if we're running the same code. +; So, have them spin instead, please? +.org $1000 +spin: + nop + nop + nop + jmp spin + +.org $FFC0 +.qword reset + +.org $FF50 +.qword spin +.qword spin +.qword spin +.qword spin +.qword spin +.qword spin +.qword spin +done + -- cgit v1.2.3-13-gbd6f