From 5ac280026e50ec85289d153ff4eaa04f0591c60b Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 7 Feb 2019 00:06:32 +0100 Subject: [PATCH 1/8] Experimentally use rst 1 to optimise frame variable loads. Reduces Star Trek from 43892 to 43205 bytes. --- mach/i80/libem/rst.s | 29 +++++++++++++++++++++++++++++ mach/i80/ncg/table | 28 +++++++++++++++++++++------- plat/cpm/boot.s | 6 ++++++ plat/cpm/build-pkg.lua | 5 ++++- plat/cpm/build-tools.lua | 3 +++ 5 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 mach/i80/libem/rst.s diff --git a/mach/i80/libem/rst.s b/mach/i80/libem/rst.s new file mode 100644 index 000000000..b4ad39bee --- /dev/null +++ b/mach/i80/libem/rst.s @@ -0,0 +1,29 @@ +# +.sect .text +.sect .rom +.sect .data +.sect .bss +.sect .text + +.define .rst_init +.rst_init: + mvi a, 0xc3 ! jmp + sta 0x08 + lxi h, rst1 + shld 0x09 + ret + + ! de = [bc+const2] (remember bc is the frame pointer) +rst1: + pop h + mov e, m + inx h + mov d, m + inx h + push h + xchg ! hl = offset + dad b + mov e, m + inx h + mov d, m + ret diff --git a/mach/i80/ncg/table b/mach/i80/ncg/table index 0368b31e3..4101d2772 100644 --- a/mach/i80/ncg/table +++ b/mach/i80/ncg/table @@ -82,6 +82,8 @@ INSTRUCTIONS /* cpo label:ro cost(3,14). */ /* cz label:ro cost(3,14). */ /* daa kills a:cc cost(1, 4). */ + data1 ".data1" const1:ro. + data2 ".data2" const2:ro. dad b_d_h_sp:ro kills hl:cc cost(1,10). dcr reg+lbreg:rw:cc cost(1, 5). dcr m:rw:cc cost(1, 7). @@ -129,7 +131,7 @@ INSTRUCTIONS /* rpe cost(1, 8). */ /* rpo cost(1, 8). */ rrc kills a:cc cost(1, 4). -/* rst const1:ro cost(1,11). */ + rst const1:ro kills a:cc cost(1,11). /* rz cost(1, 8). */ sbb reg1:ro kills a:cc cost(1, 4). /* sbi const1:ro kills a:cc cost(2, 7). */ @@ -241,12 +243,24 @@ pat loc yields {const2,$1} pat ldc yields {const2,highw($1)} {const2,loww($1)} -pat lol -uses hlreg={const2,$1}, dereg -gen dad lb - mov e,{m} - inx hl - mov d,{m} yields de +#ifdef USE_I80_RSTS + pat lol + kills hlreg + uses hlreg, dereg + gen + rst {const1, 1} + data2 {const2, $1} + yields de +#else + pat lol + uses hlreg={const2, $1}, dereg + gen + dad lb + mov e,{m} + inx hl + mov d,{m} + yields de +#endif pat loe uses hlreg diff --git a/plat/cpm/boot.s b/plat/cpm/boot.s index 960dc400d..40ab0d775 100644 --- a/plat/cpm/boot.s +++ b/plat/cpm/boot.s @@ -48,6 +48,12 @@ begtext: lxi sp, stack + STACKSIZE + ! Initialise the rsts (if desired). + + #ifdef USE_I80_RSTS + call .rst_init + #endif + ! C-ify the command line at 0x0080. lxi h, 0x0080 diff --git a/plat/cpm/build-pkg.lua b/plat/cpm/build-pkg.lua index 0a4da3be0..59c9f806a 100644 --- a/plat/cpm/build-pkg.lua +++ b/plat/cpm/build-pkg.lua @@ -4,7 +4,10 @@ include("lang/build.lua") ackfile { name = "boot", srcs = { "./boot.s" }, - vars = { plat = "cpm" } + vars = { + plat = "cpm", + ["+ackcflags"] = "-DUSE_I80_RSTS", + } } build_plat_libs { diff --git a/plat/cpm/build-tools.lua b/plat/cpm/build-tools.lua index 383cf8c17..25d1b1327 100644 --- a/plat/cpm/build-tools.lua +++ b/plat/cpm/build-tools.lua @@ -8,6 +8,9 @@ build_as { build_ncg { name = "ncg", arch = "i80", + vars = { + ["+cflags"] = "-DUSE_I80_RSTS" + } } build_top { From 9d8ea79c7fc763cdb809f35b77e65bdff6c9f469 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 7 Feb 2019 08:45:20 +0100 Subject: [PATCH 2/8] rst 1 now takes an eight-bit parameter, not a 16 bit one. Reduces Star Trek again from 43205 to 42339 bytes. --- mach/i80/libem/rst.s | 15 +++++++++------ mach/i80/ncg/table | 24 ++++++++++++------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/mach/i80/libem/rst.s b/mach/i80/libem/rst.s index b4ad39bee..37025ef17 100644 --- a/mach/i80/libem/rst.s +++ b/mach/i80/libem/rst.s @@ -13,16 +13,19 @@ shld 0x09 ret - ! de = [bc+const2] (remember bc is the frame pointer) + ! de = [bc+const1] (remember bc is the frame pointer) rst1: pop h - mov e, m - inx h - mov d, m + mov a, m inx h push h - xchg ! hl = offset - dad b + + mov l, a + ral + sbb a + mov h, a + + dad b mov e, m inx h mov d, m diff --git a/mach/i80/ncg/table b/mach/i80/ncg/table index 4101d2772..f24c4d39c 100644 --- a/mach/i80/ncg/table +++ b/mach/i80/ncg/table @@ -131,7 +131,7 @@ INSTRUCTIONS /* rpe cost(1, 8). */ /* rpo cost(1, 8). */ rrc kills a:cc cost(1, 4). - rst const1:ro kills a:cc cost(1,11). + rst const1:ro cost(1,11). /* rz cost(1, 8). */ sbb reg1:ro kills a:cc cost(1, 4). /* sbi const1:ro kills a:cc cost(2, 7). */ @@ -244,24 +244,24 @@ pat ldc yields {const2,highw($1)} {const2,loww($1)} #ifdef USE_I80_RSTS - pat lol + pat lol sfit($1, 8) kills hlreg uses hlreg, dereg gen rst {const1, 1} - data2 {const2, $1} - yields de -#else - pat lol - uses hlreg={const2, $1}, dereg - gen - dad lb - mov e,{m} - inx hl - mov d,{m} + data1 {const1, $1} yields de #endif +pat lol + uses hlreg={const2, $1}, dereg + gen + dad lb + mov e,{m} + inx hl + mov d,{m} + yields de + pat loe uses hlreg gen lhld {label,$1} yields hl From 67a9be26d12d74bae4bcc73cf2914c6525229a9e Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 7 Feb 2019 09:09:31 +0100 Subject: [PATCH 3/8] Fix warnings. --- mach/i80/ncg/mach.c | 7 +------ mach/proto/ncg/salloc.c | 2 +- mach/proto/ncg/types.h | 1 + 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/mach/i80/ncg/mach.c b/mach/i80/ncg/mach.c index a01c11eec..30682eb82 100644 --- a/mach/i80/ncg/mach.c +++ b/mach/i80/ncg/mach.c @@ -4,18 +4,13 @@ * */ -#ifndef NORCSID -static char rcsid[] = "$Id$"; -#endif - /* * machine dependent back end routines for the Intel 8080. */ #include /* atol */ -void con_part(sz, w) register sz; -word w; +void con_part(int sz, word w) { while (part_size % sz) diff --git a/mach/proto/ncg/salloc.c b/mach/proto/ncg/salloc.c index 71fe20c3d..0f9fa28f8 100644 --- a/mach/proto/ncg/salloc.c +++ b/mach/proto/ncg/salloc.c @@ -34,7 +34,7 @@ int nstab=0; static void chkstr(string, char *); -string myalloc(size) { +string myalloc(int size) { string p; p = (string) calloc((unsigned)size, 1); diff --git a/mach/proto/ncg/types.h b/mach/proto/ncg/types.h index 35b848e82..825d2e42d 100644 --- a/mach/proto/ncg/types.h +++ b/mach/proto/ncg/types.h @@ -44,6 +44,7 @@ void in_init(char *); void in_start(void); void fillemlines(void); void swtxt(void); +void dopseudo(void); /* gencode.c */ void out_init(char *); void out_finish(void); From a5bf2932c809345ecf063d9467b83980aa3d7690 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 7 Feb 2019 09:31:38 +0100 Subject: [PATCH 4/8] Add rst 1 to store frame variables. Reduces Star Trek from 42339 to 41821 bytes. --- mach/i80/ncg/table | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/mach/i80/ncg/table b/mach/i80/ncg/table index f24c4d39c..ab99b882e 100644 --- a/mach/i80/ncg/table +++ b/mach/i80/ncg/table @@ -460,13 +460,23 @@ uses hl_or_de={label,$1} yields %a pat stl lol $1==$2 with dereg yields de de leaving stl $1 +#ifdef USE_I80_RSTS + pat stl sfit($1, 8) + with dereg + kills hlreg, areg + gen + rst {const1, 2} + data1 {const1, $1} +#endif + pat stl -with dereg -uses hlreg={const2,$1} -gen dad lb - mov {m},e - inx hl - mov {m},d + with dereg + uses hlreg={const2, $1} + gen + dad lb + mov {m}, e + inx hl + mov {m}, d pat ste loe $1==$2 with hlreg yields hl hl leaving ste $1 From d319c7d679fbd71182530a15624076f952cd9b70 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 8 Feb 2019 08:09:55 +0100 Subject: [PATCH 5/8] Fix swapped bytes in probyte which was causing junk stack frames. --- mach/i80/libem/pro.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mach/i80/libem/pro.s b/mach/i80/libem/pro.s index 05976358e..0c5fa3f22 100644 --- a/mach/i80/libem/pro.s +++ b/mach/i80/libem/pro.s @@ -21,8 +21,8 @@ .probyte: pop h push b - mvi e, 0xff - mov d, m + mvi d, 0xff + mov e, m inx h jmp .pron From 22032575c5feffc182e6e0b46255bc07a2839bd7 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 8 Feb 2019 20:54:44 +0100 Subject: [PATCH 6/8] Add a 'disassemble' command to the CP/M emulator. --- plat/cpm/emu/dis8080.c | 22 +++++++++++++---- plat/cpm/emu/emulator.c | 52 ++++++++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/plat/cpm/emu/dis8080.c b/plat/cpm/emu/dis8080.c index 1adf2bc26..a667c6347 100644 --- a/plat/cpm/emu/dis8080.c +++ b/plat/cpm/emu/dis8080.c @@ -343,24 +343,36 @@ static struct insn insns[0x100] = uint16_t i8080_disassemble(char* buffer, size_t bufsiz, uint16_t pc) { - uint8_t opcode = i8080_read(pc++); + uint8_t opcode = i8080_read(pc); + uint8_t p1 = i8080_read(pc+1); + uint8_t p2 = i8080_read(pc+2); struct insn* insn = &insns[opcode]; uint16_t value = 0; + const char* left = ""; + + snprintf(buffer, bufsiz, "%04x : ", pc); + pc++; + switch (insn->operand) { case NOTHING: + left = "%02x : "; break; case CONST8: - value = i8080_read(pc++); + left = "%02x %02x : "; + value = p1; + pc++; break; case CONST16: - value = i8080_read(pc++); - value |= i8080_read(pc++) << 8; + left = "%02x %02x %02x : "; + value = p1 | (p2<<8); + pc += 2; break; } - snprintf(buffer, bufsiz, insn->name, value); + snprintf(buffer + 7, bufsiz - 7, left, opcode, p1, p2); + snprintf(buffer + 18, bufsiz - 18, insn->name, value); return pc; } diff --git a/plat/cpm/emu/emulator.c b/plat/cpm/emu/emulator.c index 5f8dd1c43..eb192dbf8 100644 --- a/plat/cpm/emu/emulator.c +++ b/plat/cpm/emu/emulator.c @@ -23,6 +23,8 @@ static bool tracing = false; static bool singlestepping = true; static bool bdosbreak = false; +static const char* delimiters = " \t\n\r"; + uint8_t i8080_read(uint16_t addr) { return ram[addr]; @@ -65,13 +67,13 @@ void showregs(void) int tstates; uint16_t pc = i8080_read_reg16(PC); i8080_disassemble(buffer, sizeof(buffer), pc); - printf("%04x : %s\n", pc, buffer); + puts(buffer); } static void cmd_register(void) { - char* w1 = strtok(NULL, " "); - char* w2 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); + char* w2 = strtok(NULL, delimiters); if (w1 && w2) { @@ -102,7 +104,7 @@ static void cmd_register(void) static void cmd_break(void) { - char* w1 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); if (w1) { uint16_t breakpc = strtoul(w1, NULL, 16); @@ -128,7 +130,7 @@ static void cmd_break(void) static void cmd_watch(void) { - char* w1 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); if (w1) { uint16_t watchaddr = strtoul(w1, NULL, 16); @@ -158,7 +160,7 @@ static void cmd_watch(void) static void cmd_delete_breakpoint(void) { - char* w1 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); if (w1) { uint16_t breakpc = strtoul(w1, NULL, 16); @@ -176,7 +178,7 @@ static void cmd_delete_breakpoint(void) static void cmd_delete_watchpoint(void) { - char* w1 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); if (w1) { uint16_t address = strtoul(w1, NULL, 16); @@ -195,8 +197,8 @@ static void cmd_delete_watchpoint(void) static void cmd_memory(void) { - char* w1 = strtok(NULL, " "); - char* w2 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); + char* w2 = strtok(NULL, delimiters); if (!w2) w2 = "100"; @@ -241,9 +243,30 @@ static void cmd_memory(void) } } +static void cmd_unassemble(void) +{ + char* w1 = strtok(NULL, delimiters); + char* w2 = strtok(NULL, delimiters); + uint16_t startaddr = i8080_read_reg16(PC); + uint16_t endaddr; + + if (w1) + startaddr = strtoul(w1, NULL, 16); + endaddr = startaddr + 0x20; + if (w2) + endaddr = startaddr + strtoul(w2, NULL, 16); + + while (startaddr < endaddr) + { + char buffer[80]; + startaddr = i8080_disassemble(buffer, sizeof(buffer), startaddr); + puts(buffer); + } +} + static void cmd_bdos(void) { - char* w1 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); if (w1) bdosbreak = !!strtoul(w1, NULL, 16); else @@ -252,7 +275,7 @@ static void cmd_bdos(void) static void cmd_tracing(void) { - char* w1 = strtok(NULL, " "); + char* w1 = strtok(NULL, delimiters); if (w1) tracing = !!strtoul(w1, NULL, 16); else @@ -270,10 +293,11 @@ static void cmd_help(void) " w set watchpoint\n" " dw delete watchpoint\n" " m show memory\n" + " u unassemble memory\n" " s single step\n" " g continue\n" " bdos 0|1 enable break on bdos entry\n" - " trace 0|1 enable tracing\n" + " tracing 0|1 enable tracing\n" ); } @@ -289,7 +313,7 @@ static void debug(void) if (!fgets(cmdline, sizeof(cmdline), stdin)) exit(0); - char* token = strtok(cmdline, " \n\r\t"); + char* token = strtok(cmdline, delimiters); if (token != NULL) { if (strcmp(token, "?") == 0) @@ -306,6 +330,8 @@ static void debug(void) cmd_delete_watchpoint(); else if (strcmp(token, "m") == 0) cmd_memory(); + else if (strcmp(token, "u") == 0) + cmd_unassemble(); else if (strcmp(token, "s") == 0) { singlestepping = true; From a91ab5c59995342cbe4a1d7d400ebea6660290f0 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 8 Feb 2019 21:35:14 +0100 Subject: [PATCH 7/8] Somehow the implementation of rst 2 got lost, with hilarious results. Also fix some register corruption issues (I hope). --- mach/i80/libem/rst.s | 22 ++++++++++++++++++++++ mach/i80/ncg/table | 7 +++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/mach/i80/libem/rst.s b/mach/i80/libem/rst.s index 37025ef17..c0d5984d8 100644 --- a/mach/i80/libem/rst.s +++ b/mach/i80/libem/rst.s @@ -9,8 +9,11 @@ .rst_init: mvi a, 0xc3 ! jmp sta 0x08 + sta 0x10 lxi h, rst1 shld 0x09 + lxi h, rst2 + shld 0x11 ret ! de = [bc+const1] (remember bc is the frame pointer) @@ -30,3 +33,22 @@ rst1: inx h mov d, m ret + + ! [bc+const1] = de (remember bc is the frame pointer) +rst2: + pop h + mov a, m + inx h + push h + + mov l, a + ral + sbb a + mov h, a + + dad b + mov m, e + inx h + mov m, d + ret + diff --git a/mach/i80/ncg/table b/mach/i80/ncg/table index ab99b882e..0e3864a44 100644 --- a/mach/i80/ncg/table +++ b/mach/i80/ncg/table @@ -245,8 +245,7 @@ pat ldc yields {const2,highw($1)} #ifdef USE_I80_RSTS pat lol sfit($1, 8) - kills hlreg - uses hlreg, dereg + uses hlreg, areg, dereg gen rst {const1, 1} data1 {const1, $1} @@ -462,8 +461,8 @@ with dereg yields de de leaving stl $1 #ifdef USE_I80_RSTS pat stl sfit($1, 8) - with dereg - kills hlreg, areg + with dereg + uses hlreg, areg gen rst {const1, 2} data1 {const1, $1} From 19f5ee3399b7530d2760c0f5dfa58bd3852bd314 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 8 Feb 2019 21:43:52 +0100 Subject: [PATCH 8/8] CP/M sbrk now handles overflow correctly. --- plat/cpm/libsys/brk.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/plat/cpm/libsys/brk.c b/plat/cpm/libsys/brk.c index 0b83b2523..6c139dd2a 100644 --- a/plat/cpm/libsys/brk.c +++ b/plat/cpm/libsys/brk.c @@ -31,13 +31,25 @@ int brk(void* newend) void* sbrk(int increment) { char* old; + char* new; if (increment == 0) return current; old = current; - if (brk(old + increment) < 0) - return OUT_OF_MEMORY; - + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; + return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; }