diff --git a/crossassemblers/macro11/.gitignore b/crossassemblers/macro11/.gitignore new file mode 100644 index 0000000..6c9e6c9 --- /dev/null +++ b/crossassemblers/macro11/.gitignore @@ -0,0 +1,11 @@ +git-info.h +*.d +*.o +dumpobj +macro11 +tests/*.lst +tests/*.obj +tests/*.objd +x/* +tests/2.11BSD/l11 +tests/2.11BSD-*.mac diff --git a/crossassemblers/macro11/.gitlab-ci.yml b/crossassemblers/macro11/.gitlab-ci.yml new file mode 100644 index 0000000..0ead23d --- /dev/null +++ b/crossassemblers/macro11/.gitlab-ci.yml @@ -0,0 +1,32 @@ +# Minimized from https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/ +# https://github.com/gitlabhq/gitlabhq/blob/master/vendor/gitlab-ci-yml/C%2B%2B.gitlab-ci.yml + +# use the official gcc image, based on debian +# can use verions as well, like gcc:5.2 +# see https://hub.docker.com/_/gcc/ +#image: gcc + +before_script: + - apt-get update + +# Defines stages which are to be executed +stages: + - build-gcc + - build-clang + +# Stage "build" +run-build-gcc: + stage: build-gcc + script: + - apt-get install -y gcc + - make + - cd tests && ./RunTests + +# Stage "build-clang" +run-build-clang: + stage: build-clang + script: + - apt-get install -y clang + - CC=clang make + - cd tests && ./RunTests + diff --git a/crossassemblers/macro11/.travis.yml b/crossassemblers/macro11/.travis.yml new file mode 100644 index 0000000..70150df --- /dev/null +++ b/crossassemblers/macro11/.travis.yml @@ -0,0 +1,12 @@ +language: c +dist: bionic +os: + - linux + - osx +compiler: + - gcc + - clang +script: + - make + - cd tests + - ./RunTests diff --git a/crossassemblers/macro11/CHANGES b/crossassemblers/macro11/CHANGES index 1f24aed..b43027d 100644 --- a/crossassemblers/macro11/CHANGES +++ b/crossassemblers/macro11/CHANGES @@ -1,3 +1,60 @@ +05.01.2022: Rhialto + version 0.7.2: + - Improved error messages for bad addressing modes + (due to gitlab issue #10) + - Undefined symbols are now listed in the symbol table. + - The weird way the unary "operator" % works in expressions is + now implemented. + The docs on page 3-8/9 aren't very precise but testing showed + that any expression with a register in it can be used as a + register, and (if used to define a symbol) is listed in the + symbol table as such. %3+1 is <%3>+1 is R4. + - Fixed registers being used in .word or immediate operands: + no longer generated as being relocatable expressions. + - 'make tests' works more portably. + +16.05.2021: Rhialto + version 0.7.1: + - Fixed immediate source operand of LDEXP, LD[IL][FD] + which is an integer, unlike several other FPP instructions. + (gitlab issue #7) + - Start each pass with .DSABL LSB (gitlab issue #8) + +19.03.2021: Rhialto + version 0.7: + - Fixed the end-of-line check for MARK, EMT, TRAP. + - Left/right shift operator _; disabled when the -yus option is used. + Contributed by Stephen Casner. + - Added some missing instructions: LDCFD, CSM, TSTSET, WRTLCK. + +13.02.2021: Rhialto + version 0.6: + - Fixed rounding issues with floating point literals. + - Fixed FPP instructions which take fp immediate operands. + - Fixed bounds check on FPP AC0-3 operands. + - Fix listing to show a % before values that represent a register + number. + - Added checks for junk text following correct code. This revealed + some small other issues, now fixed. + - Added CIS instructions; as an extension, for the Inline variants + you can specify the descriptor addresses etc as arguments to + the instruction (much like an implied .word). + +25.04.2020: Rhialto + version 0.5: + - Fixed bug with checking addressing mode for JSR and bugs + with .REPT 0, unneeded relocation on pc-relative mode. + - Very simple .LIST and .NLIST implementation. + - Add ^pl and ^ph expressions from 2.11BSD's m11. + - Object-ified macro libraries with an eye to support the .sml + files from 2.11BSD's m11. But since the given file does not + just contain .MACROs (it even contains conditionals) I'm not + sure how it is supposed to work. + - Added 2.11BSD/m11 as test files. To make this reasonable, a + few small features they use have been recognized and ignored. + - Add -rsx and -rt11 to switch object file format (from Kevin Handy) + - Add obj2bin from https://github.com/AK6DN/obj2bin.git + 09.11.2015: Rhialto version 0.4: - Fixed various bugs. The most notable was extensive use- diff --git a/crossassemblers/macro11/Makefile b/crossassemblers/macro11/Makefile index a330a95..5f7df01 100644 --- a/crossassemblers/macro11/Makefile +++ b/crossassemblers/macro11/Makefile @@ -3,13 +3,17 @@ # Makefile for macro11 and dumpobj # -WARNS ?= -Wall -Wshadow -Wextra -pedantic -Woverflow -Wstrict-overflow -CFLAGS ?= -O -ggdb -std=gnu99 $(WARNS) +WARNS ?= -Wall -Wshadow -Wextra -pedantic -Woverflow -Wstrict-overflow +OBJFORMAT ?= -DDEFAULT_OBJECTFORMAT_RT11=0 +#SANITIZE ?= -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fno-omit-frame-pointer +DEBUG ?= -ggdb $(SANITIZE) +OPT ?= -O3 +CFLAGS ?= -std=gnu99 $(WARNS) $(DEBUG) $(OPT) $(OBJFORMAT) MACRO11_SRCS = macro11.c \ assemble.c assemble_globals.c assemble_aux.c \ extree.c listing.c macros.c parse.c rept_irpc.c symbols.c \ - mlb-rsx.c object.c stream2.c util.c rad50.c + mlb2.c mlb-rsx.c mlb-rt11.c object.c stream2.c util.c rad50.c MACRO11_OBJS = $(MACRO11_SRCS:.c=.o) @@ -39,6 +43,7 @@ git-info.h: # Bootstrap dependency on the git header file, which otherwise # gets generated too late. macro11.o: git-info.h +macro11.c: git-info.h clean: -rm -f $(MACRO11_OBJS) $(DUMPOBJ_OBJS) macro11 dumpobj @@ -52,20 +57,20 @@ clean: argtests: macro11 @ for OPT in -e -d -m -p -o -l -ysl ; do \ ./macro11 foo.mac $$OPT 2> /dev/null; \ - if (( $$? == 1 )); then echo PASS; else echo FAIL; fi; \ + if [ $$? = 1 ]; then echo PASS; else echo FAIL; fi; \ echo " $$OPT missing value"; \ ./macro11 foo.mac $$OPT -v 2> /dev/null; \ - if (( $$? == 1 )); then echo PASS; else echo FAIL; fi; \ + if [ $$? = 1 ]; then echo PASS; else echo FAIL; fi; \ echo " $$OPT fol. by option"; \ done @ ./macro11 foo.mac $$OPT -x -v 2> /dev/null; \ - if (( $$? == 1 )); then echo PASS; else echo FAIL; fi; \ + if [ $$? = 1 ]; then echo PASS; else echo FAIL; fi; \ echo " -x must be the last option" +LSAN_OPTIONS=suppressions=../macro11.supp + tests: macro11 argtests - @ ACTUAL=`./macro11 tests/test-undef.mac 2>&1`; \ - if [ "tests/test-undef.mac:1: ***ERROR MACRO .TTYOU not found" == "$$ACTUAL" ]; then echo PASS; else echo FAIL; fi; \ - echo " test-undef.mac" + cd tests && env LSAN_OPTIONS="${LSAN_OPTIONS}" ./RunTests # Automatic dependency generation diff --git a/crossassemblers/macro11/README b/crossassemblers/macro11/README index a57ad01..8d70c6b 100644 --- a/crossassemblers/macro11/README +++ b/crossassemblers/macro11/README @@ -32,7 +32,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. modified 2009 by Joerg Hoppe, -modified 2015 by Olaf 'Rhialto' Seibert. +modified 2015-2017,2020,2021 by Olaf 'Rhialto' Seibert. Files: macro11.c Command line parsing and driving the passes. @@ -46,7 +46,8 @@ Files: rept_irpc.c stream2 subclass for processing .REPT and .IREPT. object.c Functions for writing RSX-11 compatible .OBJ files. mlb-rsx.c Classes (!) for reading RSX-11 macro libraries. - mlb.c Classes (!) for reading RT-11 macro libraries. + mlb-rt11.c Classes (!) for reading RT-11 macro libraries. + mlb2.c Glue functions for macro libraries in general. stream2.c Functions for managing input streams and buffers. rad50.c Functions for converting text to and from RAD50. util.c A few general utility fuctions. @@ -149,6 +150,11 @@ Options: This also works for extracting an object library (.OLB) file. + -rsx Tells macro11 to generate rsx style object files. + This is the default. + + -rt11 Tells macro11 to generate rt11 style object files. + Various options starting with -y enable extensions: -ysl Allow longer symbols up to the given length. @@ -167,3 +173,11 @@ Options: You may define the MCALL and INCLUDE environment variable prior to invoking macro11, as a path to directories containing macros or files to be included, respectively. + +======================================================================= + +Included in subdirectory obj2bin is a Perl script from Don North, +copied from https://github.com/AK6DN/obj2bin. The copied version may +get out of date; when in doubt check the original. + +======================================================================= diff --git a/crossassemblers/macro11/TODO b/crossassemblers/macro11/TODO index 9cf9f53..c94749a 100644 --- a/crossassemblers/macro11/TODO +++ b/crossassemblers/macro11/TODO @@ -1,8 +1,13 @@ + .packed pdf page 80 listing format errors: ignore whitespace of input documentation: print supported directives +register symbols: %3+1 is the same as %4 (pdf page 3-9 aka 35), +but where precisely register symbols can be used, and how, +isn't specified. + --------------------------------------- I was not able to locate a Macro-11 language reference manual any more recent than for RT11 version *3*, so I used that plus my recollection diff --git a/crossassemblers/macro11/assemble.c b/crossassemblers/macro11/assemble.c index a837551..be85e08 100644 --- a/crossassemblers/macro11/assemble.c +++ b/crossassemblers/macro11/assemble.c @@ -25,6 +25,8 @@ +#define CHECK_EOL check_eol(stack, cp) + /* assemble - read a line from the input stack, assemble it. */ /* This function is way way too large, because I just coded most of @@ -107,6 +109,8 @@ static int assemble( /* The line may begin with "label:[:]" */ + /* PSEUDO P_IIF jumps here. */ + reassemble: opcp = cp; if ((label = get_symbol(cp, &ncp, &local)) != NULL) { int flag = SYMBOLFLAG_PERMANENT | SYMBOLFLAG_DEFINITION | local; @@ -140,8 +144,6 @@ static int assemble( } } - /* PSEUDO P_IIF jumps here. */ - reassemble: cp = skipwhite(cp); if (EOL(*cp)) @@ -176,6 +178,7 @@ static int assemble( cp = skipwhite(cp); value = parse_expr(cp, 0); + cp = value->cp; /* Special code: if the symbol is the program counter, this is harder. */ @@ -190,13 +193,13 @@ static int assemble( section must = current. */ if (!express_sym_offset(value, &symb, &offset)) { - report(stack->top, "Illegal ORG\n"); - } else if ((symb->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) { + report(stack->top, "Illegal ORG (for relocatable section)\n"); + } else if (SYM_IS_IMPORTED(symb)) { report(stack->top, "Can't ORG to external location\n"); } else if (symb->flags & SYMBOLFLAG_UNDEFINED) { report(stack->top, "Can't ORG to undefined sym\n"); } else if (symb->section != current_pc->section) { - report(stack->top, "Can't ORG to alternate section " "(use PSECT)\n"); + report(stack->top, "Can't ORG to alternate section (use PSECT)\n"); } else { DOT = symb->value + offset; list_value(stack->top, DOT); @@ -217,7 +220,7 @@ static int assemble( } free_tree(value); free(label); - return 1; + return CHECK_EOL; } /* regular symbols */ @@ -226,7 +229,7 @@ static int assemble( } else if (value->type == EX_SYM || value->type == EX_TEMP_SYM) { sym = add_sym(label, value->data.symbol->value, flags, value->data.symbol->section, &symbol_st); } else { - report(stack->top, "Complex expression cannot be assigned " "to a symbol\n"); + report(stack->top, "Complex expression cannot be assigned to a symbol\n"); if (!pass) { /* This may work better in pass 2 - something in @@ -243,7 +246,7 @@ static int assemble( free_tree(value); free(label); - return sym != NULL; + return sym != NULL && CHECK_EOL; } /* Try to resolve macro */ @@ -274,15 +277,26 @@ static int assemble( switch (op->section->type) { case SECTION_PSEUDO: switch (op->value) { - case P_ENDR: - case P_ENDM: - case P_SBTTL: - case P_LIST: - case P_NLIST: + case P_PAGE: case P_PRINT: + case P_SBTTL: return 1; /* Accepted, ignored. (An obvious need: get assembly listing - controls working. ) */ + controls working fully. ) */ + case P_LIST: + if (pass > 0) { + cp = skipwhite(cp); + if (EOL(*cp)) + list_level++; + } + return 1; + case P_NLIST: + if (pass > 0) { + cp = skipwhite(cp); + if (EOL(*cp)) + list_level--; + } + return 1; case P_IDENT: { @@ -305,7 +319,8 @@ static int assemble( ident[len] = 0; upcase(ident); - return 1; + cp += len + 1; + return CHECK_EOL; } case P_RADIX: @@ -318,7 +333,7 @@ static int assemble( report(stack->top, "Illegal radix\n"); return 0; } - return 1; + return CHECK_EOL; } case P_FLT4: @@ -343,7 +358,7 @@ static int assemble( } cp = skipdelim(cp); } - return ok; + return ok && CHECK_EOL; } case P_ERROR: @@ -358,7 +373,7 @@ static int assemble( sect_sp++; sect_stack[sect_sp] = current_pc->section; dot_stack[sect_sp] = DOT; - return 1; + return CHECK_EOL; case P_RESTORE: if (sect_sp < 0) { @@ -373,7 +388,7 @@ static int assemble( } sect_sp--; } - return 1; + return CHECK_EOL; case P_NARG: { @@ -405,7 +420,7 @@ static int assemble( &symbol_st); free(label); list_value(stack->top, mstr->nargs); - return 1; + return CHECK_EOL; } case P_NCHR: @@ -428,13 +443,14 @@ static int assemble( &symbol_st); free(label); free(string); - return 1; + return CHECK_EOL; } case P_NTYPE: { ADDR_MODE mode; int islocal; + char *error; label = get_symbol(cp, &cp, &islocal); if (label == NULL) { @@ -444,8 +460,9 @@ static int assemble( cp = skipdelim(cp); - if (!get_mode(cp, &cp, &mode)) { - report(stack->top, "Bad .NTYPE addressing mode\n"); + if (!get_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Bad .NTYPE addressing mode (%s)\n", error); free(label); return 0; } @@ -454,7 +471,7 @@ static int assemble( free_addr_mode(&mode); free(label); - return 1; + return CHECK_EOL; } case P_INCLUDE: @@ -469,13 +486,15 @@ static int assemble( } my_searchenv(name, "INCLUDE", hitfile, sizeof(hitfile)); - free(name); if (hitfile[0] == '\0') { report(stack->top, "Unable to find .INCLUDE file \"%s\"\n", name); + free(name); return 0; } + free(name); + incl = new_file_stream(hitfile); if (incl == NULL) { report(stack->top, "Unable to open .INCLUDE file \"%s\"\n", hitfile); @@ -484,7 +503,7 @@ static int assemble( stack_push(stack, incl); - return 1; + return CHECK_EOL; } case P_REM: @@ -547,7 +566,7 @@ static int assemble( } free(name); } - return 1; + return CHECK_EOL; case P_MCALL: { @@ -566,6 +585,18 @@ static int assemble( if (EOL(*cp)) return 1; + /* (lib)macro syntax. Ignore (lib) for now. */ + if (*cp == '(') { + char *close = strchr(cp + 1, ')'); + + if (close != NULL) { + char *libname = cp + 1; + (void)libname; + *close = '\0'; + cp = close + 1; + } + } + label = get_symbol(cp, &cp, NULL); if (!label) { report(stack->top, "Illegal .MCALL format\n"); @@ -591,8 +622,14 @@ static int assemble( macstr = new_buffer_stream(macbuf, label); buffer_free(macbuf); } else { - strncpy(macfile, label, sizeof(macfile)); - strncat(macfile, ".MAC", sizeof(macfile) - strlen(macfile) - 1); + char *bufend = &macfile[sizeof(macfile)], + *end; + end = stpncpy(macfile, label, sizeof(macfile) - 5); + if (end >= bufend - 5) { + report(stack->top, ".MCALL: name too long: '%s'\n", label); + return 0; + } + stpncpy(end, ".MAC", bufend - end); my_searchenv(macfile, "MCALL", hitfile, sizeof(hitfile)); if (hitfile[0]) macstr = new_file_stream(hitfile); @@ -626,9 +663,9 @@ static int assemble( saveline = stmtno; list_level = -1; - mac = defmacro(maccp, &macstack, TRUE); + mac = defmacro(maccp, &macstack, CALLED_NOLIST); if (mac == NULL) { - report(stack->top, "Failed to define macro " "called %s\n", label); + report(stack->top, "Failed to define macro called %s\n", label); } stmtno = saveline; @@ -641,12 +678,13 @@ static int assemble( free(label); } + /* NOTREACHED */ } return 1; case P_MACRO: { - MACRO *mac = defmacro(cp, stack, FALSE); + MACRO *mac = defmacro(cp, stack, CALLED_NORMAL); return mac != NULL; } @@ -668,7 +706,7 @@ static int assemble( /* and finally, pop the macro */ stack_pop(stack); - return 1; + return CHECK_EOL; } case P_REPT: @@ -693,6 +731,8 @@ static int assemble( enabl_gbl = 1; } else if (strcmp(label, "LC") == 0) { enabl_lc = 1; + } else if (strcmp(label, "LCM") == 0) { + enabl_lcm = 1; } free(label); cp = skipdelim(cp); @@ -712,6 +752,8 @@ static int assemble( enabl_gbl = 0; } else if (strcmp(label, "LC") == 0) { enabl_lc = 0; + } else if (strcmp(label, "LCM") == 0) { + enabl_lcm = 0; } free(label); cp = skipdelim(cp); @@ -720,7 +762,7 @@ static int assemble( case P_LIMIT: store_limits(stack->top, tr); - return 1; + return CHECK_EOL; case P_TITLE: /* accquire module name */ @@ -737,35 +779,49 @@ static int assemble( if (xfer_address) free_tree(xfer_address); xfer_address = parse_expr(cp, 0); + cp = xfer_address->cp; } - return 1; + return CHECK_EOL; case P_IFDF: opcp = skipwhite(opcp); cp = opcp + 3; /* Point cp at the "DF" or "NDF" part */ - /* Falls into... */ + /* FALLS THROUGH */ case P_IIF: case P_IF: { EX_TREE *value; - int ok; + int ok = FALSE; label = get_symbol(cp, &cp, NULL); /* Get condition */ cp = skipdelim(cp); - if (strcmp(label, "DF") == 0) { - value = parse_expr(cp, 1); + if (!label) { + report(stack->top, "Missing .(I)IF condition\n"); + } else if (strcmp(label, "DF") == 0) { + value = parse_expr(cp, EVALUATE_DEFINEDNESS); cp = value->cp; ok = eval_defined(value); free_tree(value); } else if (strcmp(label, "NDF") == 0) { - value = parse_expr(cp, 1); + value = parse_expr(cp, EVALUATE_DEFINEDNESS); cp = value->cp; ok = eval_undefined(value); free_tree(value); } else if (strcmp(label, "B") == 0 || strcmp(label, "NB") == 0) { + /* + * Page 6-46 footnote 1 says + * "A macro argument (a form of symbolic argument) + * is enclosed within angle brackets or delimited + * by the circumflex construction, as described in + * section 7.3. For example, + * + * ^/124/" + * but we don't enforce that here (yet) by using + * simply getstring(). + */ cp = skipwhite(cp); if (EOL(*cp)) { ok = 1; @@ -791,6 +847,12 @@ static int assemble( thing2 = getstring(cp, &cp); else thing2 = memcheck(strdup("")); + + if (!enabl_lcm) { + upcase(thing1); + upcase(thing2); + } + ok = (strcmp(thing1, thing2) == 0); if (label[0] == 'D') { ok = !ok; @@ -822,7 +884,7 @@ static int assemble( /* FIXME I don't know if the following is portable enough. */ if (tvalue->data.lit & 0x8000) - sword |= ~0xFFFF; /* Render negative */ + sword |= ~0x7FFF; /* Render negative */ /* Reduce unsigned value to 16 bits */ uword = tvalue->data.lit & 0xffff; @@ -857,10 +919,10 @@ static int assemble( /* The "immediate if" */ /* Only slightly tricky. */ cp = skipdelim(cp); - label = get_symbol(cp, &ncp, &local); goto reassemble; } - return 1; + return 1; /* Ignore rest of line if + condition is false */ } push_cond(ok, stack->top); @@ -870,7 +932,7 @@ static int assemble( suppressed until .ENDC */ } - return 1; + return CHECK_EOL; case P_IFF: if (last_cond < 0) { @@ -880,7 +942,7 @@ static int assemble( if (conds[last_cond].ok) /* Suppress if last cond is true */ suppressed++; - return 1; + return CHECK_EOL; case P_IFT: if (last_cond < 0) { @@ -890,14 +952,14 @@ static int assemble( if (!conds[last_cond].ok) /* Suppress if last cond is false */ suppressed++; - return 1; + return CHECK_EOL; case P_IFTF: if (last_cond < 0) { report(stack->top, "No conditional block active\n"); return 0; } - return 1; /* Don't suppress. */ + return CHECK_EOL; /* Don't suppress. */ case P_ENDC: if (last_cond < 0) { @@ -906,9 +968,21 @@ static int assemble( } pop_cond(last_cond - 1); - return 1; + return CHECK_EOL; + + case P_ENDM: + report(stack->top, "No macro definition block active\n"); + return 0; + + case P_ENDR: + report(stack->top, "No repeat block active\n"); + return 0; case P_EVEN: + cp = skipwhite(cp); + if (!EOL(*cp)) { + report(stack->top, ".EVEN must not have an argument\n"); + } if (DOT & 1) { list_word(stack->top, DOT, 0, 1, ""); DOT++; @@ -917,6 +991,9 @@ static int assemble( return 1; case P_ODD: + if (!EOL(*cp)) { + report(stack->top, ".ODD must not have an argument\n"); + } if (!(DOT & 1)) { list_word(stack->top, DOT, 0, 1, ""); DOT++; @@ -930,7 +1007,7 @@ static int assemble( } go_section(tr, &absolute_section); list_location(stack->top, DOT); - return 1; + return CHECK_EOL; case P_CSECT: case P_PSECT: @@ -963,7 +1040,7 @@ static int assemble( sect->size = 0; sect->type = SECTION_USER; sections[sector++] = sect; - sectsym = add_sym(label, 0, 0, sect, §ion_st); + sectsym = add_sym(label, 0, SYMBOLFLAG_DEFINITION, sect, §ion_st); /* page 6-41 table 6-5 */ if (op->value == P_PSECT) { @@ -1008,7 +1085,7 @@ static int assemble( } else if (strcmp(label, "LCL") == 0) { sect->flags &= ~PSECT_GBL; /* Local */ } else { - report(stack->top, "Unknown flag %s given to " ".PSECT directive\n", label); + report(stack->top, "Unknown flag %s given to .PSECT directive\n", label); free(label); return 0; } @@ -1046,7 +1123,7 @@ static int assemble( go_section(tr, sect); list_location(stack->top, DOT); - return 1; + return CHECK_EOL; } /* end PSECT code */ break; @@ -1054,13 +1131,19 @@ static int assemble( case P_GLOBL: { SYMBOL *sym; + int islocal = 0; while (!EOL(*cp)) { /* Loop and make definitions for comma-separated symbols */ - label = get_symbol(cp, &ncp, NULL); + label = get_symbol(cp, &ncp, &islocal); if (label == NULL) { - report(stack->top, "Illegal .GLOBL/.WEAK " "syntax\n"); + report(stack->top, "Illegal .GLOBL/.WEAK syntax\n"); + return 0; + } + + if (islocal) { + report(stack->top, "Local label used in .GLOBL/.WEAK\n"); return 0; } @@ -1076,7 +1159,7 @@ static int assemble( cp = skipdelim(ncp); } } - return 1; + return CHECK_EOL; case P_WORD: { @@ -1084,7 +1167,7 @@ static int assemble( is an implicit .WORD 0 */ if (EOL(*cp)) { if (DOT & 1) { - report(stack->top, ".WORD on odd " "boundary\n"); + report(stack->top, ".WORD on odd boundary\n"); DOT++; /* Fix it, too */ } store_word(stack->top, tr, 2, 0); @@ -1104,11 +1187,22 @@ static int assemble( case P_BLKW: case P_BLKB: { - EX_TREE *value = parse_expr(cp, 0); + EX_TREE *value; int ok = 1; + cp = skipwhite(cp); + if (EOL(*cp)) { + /* If no argument, assume 1. Documented but + * discouraged. Par 6.5.3, page 6-32. */ + /* warning(stack->top, "Argument to .BLKB/.BLKW should be present; 1 assumed\n"); */ + value = new_ex_lit(1); + } else { + value = parse_expr(cp, 0); + cp = value->cp; + } + if (value->type != EX_LIT) { - report(stack->top, "Argument to .BLKB/.BLKW " "must be constant\n"); + report(stack->top, "Argument to .BLKB/.BLKW must be constant\n"); ok = 0; } else { list_value(stack->top, DOT); @@ -1116,7 +1210,7 @@ static int assemble( change_dot(tr, 0); } free_tree(value); - return ok; + return ok && CHECK_EOL; } case P_ASCIZ: @@ -1151,7 +1245,7 @@ static int assemble( case P_RAD50: if (DOT & 1) { - report(stack->top, ".RAD50 on odd " "boundary\n"); + report(stack->top, ".RAD50 on odd boundary\n"); DOT++; /* Fix it */ } { @@ -1228,7 +1322,7 @@ static int assemble( case OC_NONE: /* No operands. */ store_word(stack->top, tr, 2, op->value); - return 1; + return CHECK_EOL; case OC_MARK: /* MARK, EMT, TRAP */ { @@ -1240,29 +1334,38 @@ static int assemble( cp++; /* Allow the hash, but don't require it */ value = parse_expr(cp, 0); + cp = value->cp; if (value->type != EX_LIT) { - report(stack->top, "Instruction requires " "simple literal operand\n"); + report(stack->top, "Instruction requires simple literal operand\n"); word = op->value; } else { + unsigned int max = (op->value == I_MARK)? 077 : 0377; + + if (value->data.lit > max) { + report(stack->top, "Literal operand too large (%d. > %d.)\n", value->data.lit, max); + value->data.lit = max; + } word = op->value | value->data.lit; } store_word(stack->top, tr, 2, word); free_tree(value); } - return 1; + return CHECK_EOL; case OC_1GEN: /* One general addressing mode */ { ADDR_MODE mode; unsigned word; + char *error; - if (!get_mode(cp, &cp, &mode)) { - report(stack->top, "Illegal addressing mode\n"); + if (!get_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Invalid addressing mode (%s)\n", error); return 0; } - if (op->value == 0100 && (mode.type & 070) == 0) { + if (op->value == I_JMP && (mode.type & 070) == 0) { report(stack->top, "JMP Rn is illegal\n"); /* But encode it anyway... */ } @@ -1272,28 +1375,33 @@ static int assemble( store_word(stack->top, tr, 2, word); mode_extension(tr, &mode, stack->top); } - return 1; + return CHECK_EOL; case OC_2GEN: /* Two general addressing modes */ { ADDR_MODE left, right; unsigned word; + char *error; - if (!get_mode(cp, &cp, &left)) { - report(stack->top, "Illegal addressing mode\n"); + if (!get_mode(cp, &cp, &left, &error)) { + report(stack->top, + "Invalid addressing mode (1st operand: %s)\n", + error); return 0; } cp = skipwhite(cp); if (*cp++ != ',') { - report(stack->top, "Illegal syntax\n"); + report(stack->top, "Invalid syntax (comma expected)\n"); free_addr_mode(&left); return 0; } - if (!get_mode(cp, &cp, &right)) { - report(stack->top, "Illegal addressing mode\n"); + if (!get_mode(cp, &cp, &right, &error)) { + report(stack->top, + "Invalid addressing mode (2nd operand: %s)\n", + error); free_addr_mode(&left); return 0; } @@ -1304,7 +1412,7 @@ static int assemble( mode_extension(tr, &left, stack->top); mode_extension(tr, &right, stack->top); } - return 1; + return CHECK_EOL; case OC_BR: /* branches */ { @@ -1364,7 +1472,7 @@ static int assemble( free_tree(value); } - return 1; + return CHECK_EOL; case OC_SOB: { @@ -1378,13 +1486,13 @@ static int assemble( reg = get_register(value); free_tree(value); if (reg == NO_REG) { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid addressing mode (register expected)\n"); return 0; } cp = skipwhite(cp); if (*cp++ != ',') { - report(stack->top, "Illegal syntax\n"); + report(stack->top, "Invalid syntax (comma expected)\n"); return 0; } @@ -1428,7 +1536,7 @@ static int assemble( free_tree(value); } - return 1; + return CHECK_EOL; case OC_ASH: /* First op is gen, second is register. */ { @@ -1436,15 +1544,18 @@ static int assemble( EX_TREE *value; unsigned reg; unsigned word; + char *error; - if (!get_mode(cp, &cp, &mode)) { - report(stack->top, "Illegal addressing mode\n"); + if (!get_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Invalid addressing mode (1st operand: %s)\n", + error); return 0; } cp = skipwhite(cp); if (*cp++ != ',') { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid syntax (comma expected)\n"); free_addr_mode(&mode); return 0; } @@ -1453,7 +1564,7 @@ static int assemble( reg = get_register(value); if (reg == NO_REG) { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid addressing mode (2nd operand: register expected)\n"); free_tree(value); free_addr_mode(&mode); return 0; @@ -1465,38 +1576,41 @@ static int assemble( mode_extension(tr, &mode, stack->top); free_tree(value); } - return 1; + return CHECK_EOL; case OC_JSR: - /* First op is register, second is gen. */ { + /* For JSR and XOR, first op is register, second is gen. */ { ADDR_MODE mode; EX_TREE *value; unsigned reg; unsigned word; + char *error; value = parse_expr(cp, 0); cp = value->cp; reg = get_register(value); if (reg == NO_REG) { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid addressing mode (1st operand: register exected)\n"); free_tree(value); return 0; } cp = skipwhite(cp); if (*cp++ != ',') { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid syntax (comma expected)\n"); return 0; } - if (!get_mode(cp, &cp, &mode)) { - report(stack->top, "Illegal addressing mode\n"); + if (!get_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Invalid addressing mode (2nd operand: %s)\n", + error); free_tree(value); return 0; } - if ((mode.type & 070) == 0) { + if (op->value == I_JSR && (mode.type & 070) == 0) { report(stack->top, "JSR Rn,Rm is illegal\n"); /* But encode it anyway... */ } @@ -1506,10 +1620,10 @@ static int assemble( mode_extension(tr, &mode, stack->top); free_tree(value); } - return 1; + return CHECK_EOL; case OC_1REG: - /* One register (RTS) */ { + /* One register (RTS,FADD,FSUB,FMUL,FDIV,SPL) */ { EX_TREE *value; unsigned reg; @@ -1517,31 +1631,68 @@ static int assemble( cp = value->cp; reg = get_register(value); if (reg == NO_REG) { - report(stack->top, "Illegal addressing mode\n"); - free_tree(value); + report(stack->top, "Invalid addressing mode (register expected)\n"); reg = 0; } store_word(stack->top, tr, 2, op->value | reg); free_tree(value); } - return 1; + return CHECK_EOL; - case OC_1FIS: - /* One one gen and one reg 0-3 */ { +#if 0 +/* + * Although it is arguable that the FPP TSTF/TSTD instruction has 1 + * operand which is a floating point source, the PDP11 Architecture + * Handbook describes it as a destination, and MACRO11 V05.05 doesn't + * allow a FP literal argument. + */ + case OC_FPP_FSRC: + /* One fp immediate or a general addressing mode */ { ADDR_MODE mode; - EX_TREE *value; - unsigned reg; unsigned word; - if (!get_mode(cp, &cp, &mode)) { + if (!get_fp_src_mode(cp, &cp, &mode)) { report(stack->top, "Illegal addressing mode\n"); return 0; } + /* Build instruction word */ + word = op->value | mode.type; + store_word(stack->top, tr, 2, word); + mode_extension(tr, &mode, stack->top); + } + return CHECK_EOL; +#endif + + case OC_FPP_SRCAC: + case OC_FPP_FSRCAC: + /* One gen and one reg 0-3 */ { + ADDR_MODE mode; + EX_TREE *value; + unsigned reg; + unsigned word; + char *error; + + if ((op->flags & OC_MASK) == OC_FPP_FSRCAC) { + if (!get_fp_src_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Invalid addressing mode (1st operand, fsrc: %s)\n", + error); + return 0; + } + } else { + if (!get_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Invalid addressing mode (1st operand: %s)\n", + error); + return 0; + } + } + cp = skipwhite(cp); if (*cp++ != ',') { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid syntax (comma expected)\n"); free_addr_mode(&mode); return 0; } @@ -1550,53 +1701,116 @@ static int assemble( cp = value->cp; reg = get_register(value); - if (reg == NO_REG || reg > 4) { - report(stack->top, "Invalid destination register\n"); + if (reg == NO_REG || reg > 3) { + report(stack->top, "Invalid destination fp register\n"); reg = 0; } + /* + * We could check here that the general mode + * is not AC6 or AC7, but the original Macro11 + * doesn't do that either. + */ word = op->value | mode.type | (reg << 6); store_word(stack->top, tr, 2, word); mode_extension(tr, &mode, stack->top); free_tree(value); } - return 1; + return CHECK_EOL; - case OC_2FIS: - /* One reg 0-3 and one gen */ { + case OC_FPP_ACFDST: + /* One reg 0-3 and one fdst */ { ADDR_MODE mode; EX_TREE *value; unsigned reg; unsigned word; + char *error; value = parse_expr(cp, 0); cp = value->cp; reg = get_register(value); - if (reg == NO_REG || reg > 4) { - report(stack->top, "Illegal source register\n"); + if (reg == NO_REG || reg > 3) { + report(stack->top, "Invalid source fp register\n"); reg = 0; } cp = skipwhite(cp); if (*cp++ != ',') { - report(stack->top, "Illegal addressing mode\n"); + report(stack->top, "Invalid syntax (comma expected)\n"); free_tree(value); return 0; } - if (!get_mode(cp, &cp, &mode)) { - report(stack->top, "Illegal addressing mode\n"); + if (!get_mode(cp, &cp, &mode, &error)) { + report(stack->top, + "Invalid addressing mode (2nd operand: %s)\n", + error); free_tree(value); return 0; } + /* + * We could check here that the general mode + * is not AC6 or AC7, but the original Macro11 + * doesn't do that either. + * + * For some (mostly STore instructions) the + * destination isn't a FDST but a plain DST. + */ word = op->value | mode.type | (reg << 6); store_word(stack->top, tr, 2, word); mode_extension(tr, &mode, stack->top); free_tree(value); } - return 1; + return CHECK_EOL; + + { int nwords; + EX_TREE *expr[4]; + case OC_CIS2: + /* Either no operands or 2 (mostly) address operand words + * (extension) */ + nwords = 2; + goto cis_common; + case OC_CIS3: + /* Either no operands or 3 (mostly) address operand words + * (extension) */ + nwords = 3; + goto cis_common; + case OC_CIS4: + /* Either no operands or 4 (mostly) address operand words + * (extension) */ + nwords = 4; + cis_common: + if (!EOL(*cp)) { + for (int i = 0; i < nwords; i++) { + if (i > 0) { + cp = skipwhite(cp); + if (*cp++ != ',') { + report(stack->top, "Invalid syntax (operand %d: comma expected)\n", i+1); + cp--; + } + } + EX_TREE *ex = parse_expr(cp, 0); + if (!expr_ok(ex)) { + report(stack->top, "Invalid expression (operand %d)\n", i+1); + } + cp = ex->cp; + expr[i] = ex; + } + } else { + expr[0] = NULL; + } + + store_word(stack->top, tr, 2, op->value); + + if (expr[0]) { + for (int i = 0; i < nwords; i++) { + store_value(stack, tr, 2, expr[i]); + } + } + } + return CHECK_EOL; default: report(stack->top, "Unimplemented instruction format\n"); diff --git a/crossassemblers/macro11/assemble_aux.c b/crossassemblers/macro11/assemble_aux.c index a5b7180..b00fb3a 100644 --- a/crossassemblers/macro11/assemble_aux.c +++ b/crossassemblers/macro11/assemble_aux.c @@ -194,47 +194,59 @@ unsigned get_register( /* implicit_gbl is a self-recursive routine that adds undefined symbols - to the "implicit globals" symbol table. + to the "implicit globals" symbol table, or alternatively adds the + symbol as an UNDEFINED symbol. */ void implicit_gbl( EX_TREE *value) { - if (pass) + if (pass || !value) return; /* Only do this in first pass */ - if (!enabl_gbl) - return; /* Option not enabled, don't do it. */ - - switch (value->type) { - case EX_UNDEFINED_SYM: - { - if (!(value->data.symbol->flags & SYMBOLFLAG_LOCAL)) { /* Unless it's a - local symbol, */ - add_sym(value->data.symbol->label, 0, SYMBOLFLAG_GLOBAL, &absolute_section, &implicit_st); + switch (num_subtrees(value)) { + case 0: + switch (value->type) { + case EX_UNDEFINED_SYM: + { + if (!(value->data.symbol->flags & SYMBOLFLAG_LOCAL)) { + /* Unless it's a local symbol, */ + if (enabl_gbl) { + /* either make the undefined symbol into an + implicit global */ + add_sym(value->data.symbol->label, 0, SYMBOLFLAG_GLOBAL, + &absolute_section, &implicit_st); + } else { + /* or add it to the undefined symbol table, + purely for listing purposes. + It also works to add it to symbol_st, + all code is carefully made for that. */ +#define ADD_UNDEFINED_SYMBOLS_TO_MAIN_SYMBOL_TABLE 0 +#if ADD_UNDEFINED_SYMBOLS_TO_MAIN_SYMBOL_TABLE + add_sym(value->data.symbol->label, 0, SYMBOLFLAG_UNDEFINED, + &absolute_section, &symbol_st); +#else + add_sym(value->data.symbol->label, 0, SYMBOLFLAG_UNDEFINED, + &absolute_section, &undefined_st); +#endif + } + } } + break; + case EX_LIT: + case EX_SYM: + case EX_TEMP_SYM: // Impossible on this pass + return; + default: + break; } break; - case EX_LIT: - case EX_SYM: - case EX_TEMP_SYM: // Impossible on this pass - return; - case EX_ADD: - case EX_SUB: - case EX_MUL: - case EX_DIV: - case EX_AND: - case EX_OR: + case 2: implicit_gbl(value->data.child.right); - /* falls into... */ - case EX_COM: - case EX_NEG: + /* FALLS THROUGH */ + case 1: implicit_gbl(value->data.child.left); break; - case EX_ERR: - if (value->data.child.left) - implicit_gbl(value->data.child.left); - break; } } @@ -260,6 +272,28 @@ void migrate_implicit( } } +/* Done between second pass and listing */ +/* Migrates the symbols from the "undefined" table into the main table. */ + +void migrate_undefined( + void) +{ + SYMBOL_ITER iter; + SYMBOL *isym, + *sym; + + for (isym = first_sym(&undefined_st, &iter); isym != NULL; isym = next_sym(&undefined_st, &iter)) { + sym = lookup_sym(isym->label, &symbol_st); + if (sym) { + continue; /* It's already in there. Great. */ + } + isym->flags |= SYMBOLFLAG_UNDEFINED; /* Just in case */ + sym = add_sym(isym->label, isym->value, isym->flags, isym->section, &symbol_st); + /* Just one other thing - migrate the stmtno */ + sym->stmtno = isym->stmtno; + } +} + int express_sym_offset( EX_TREE *value, SYMBOL **sym, @@ -322,7 +356,12 @@ int complex_tree( { SYMBOL *sym = tree->data.symbol; - if ((sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) { + /* This check may not be needed; so far it made no difference. */ + if (sym->flags & SYMBOLFLAG_UNDEFINED) { + return 0; + } + + if (SYM_IS_IMPORTED(sym)) { text_complex_global(tx, sym->label); } else { text_complex_psect(tx, sym->section->sector, sym->value); @@ -412,7 +451,7 @@ static void store_complex( text_complex_begin(&tx); /* Open complex expression */ if (!complex_tree(&tx, value)) { /* Translate */ - report(refstr, "Invalid expression\n"); + report(refstr, "Invalid expression (complex relocation)\n"); store_word(refstr, tr, size, 0); } else { list_word(refstr, DOT, 0, size, "C"); @@ -438,7 +477,7 @@ static void store_complex_displaced( text_complex_begin(&tx); if (!complex_tree(&tx, value)) { - report(refstr, "Invalid expression\n"); + report(refstr, "Invalid expression (complex displaced relocation)\n"); store_word(refstr, tr, size, 0); } else { list_word(refstr, DOT, 0, size, "C"); @@ -467,32 +506,42 @@ void mode_extension( } if (value->type == EX_LIT) { - if (mode->rel) /* PC-relative? */ - store_displaced_word(str, tr, 2, value->data.lit); - else + if (mode->pcrel) { /* PC-relative? */ + if (current_pc->section->flags & PSECT_REL) { + store_displaced_word(str, tr, 2, value->data.lit); + } else { + /* I can compute this myself. */ + store_word(str, tr, 2, value->data.lit - DOT - 2); + } + } else { store_word(str, tr, 2, value->data.lit); /* Just a known value. */ + } } else if (express_sym_offset(value, &sym, &offset)) { - if ((sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) { + if (SYM_IS_IMPORTED(sym)) { /* Reference to a global symbol. */ /* Global symbol plus offset */ - if (mode->rel) + if (mode->pcrel) store_global_displaced_offset_word(str, tr, 2, offset, sym->label); else store_global_offset_word(str, tr, 2, offset, sym->label); + } else if (sym->section->type == SECTION_REGISTER) { + /* Delayed action: evaluate() excludes SECTION_REGISTER when + * turning symbols into EX_LIT. Do it here now. */ + store_word(str, tr, 2, sym->value + offset); } else { /* Relative to non-external symbol. */ if (current_pc->section == sym->section) { /* In the same section */ - if (mode->rel) { + if (mode->pcrel) { /* I can compute this myself. */ store_word(str, tr, 2, sym->value + offset - DOT - 2); } else store_internal_word(str, tr, 2, sym->value + offset); } else { /* In a different section */ - if (mode->rel) + if (mode->pcrel) store_psect_displaced_offset_word(str, tr, 2, sym->value + offset, sym->section->label); else store_psect_offset_word(str, tr, 2, sym->value + offset, sym->section->label); @@ -501,7 +550,7 @@ void mode_extension( } else { /* Complex relocation */ - if (mode->rel) + if (mode->pcrel) store_complex_displaced(str, tr, 2, mode->offset); else store_complex(str, tr, 2, mode->offset); @@ -553,7 +602,7 @@ int eval_undefined( } /* push_cond - a new conditional (.IF) block has been activated. Push - it's context. */ + its context. */ void push_cond( int ok, @@ -619,8 +668,12 @@ void store_value( } else if (!express_sym_offset(value, &sym, &offset)) { store_complex(stack->top, tr, size, value); } else { - if ((sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) { + if (SYM_IS_IMPORTED(sym)) { store_global_offset_word(stack->top, tr, size, sym->value + offset, sym->label); + } else if (sym->section->type == SECTION_REGISTER) { + /* Delayed action: evaluate() excludes SECTION_REGISTER when + * turning symbols into EX_LIT. Do it here now. */ + store_word(stack->top, tr, size, sym->value + offset); } else if (sym->section != current_pc->section) { store_psect_offset_word(stack->top, tr, size, sym->value + offset, sym->section->label); } else { @@ -653,7 +706,7 @@ int do_word( } else { EX_TREE *value = parse_expr(cp, 0); - if (value->cp > cp) { + if (value->type != EX_ERR && value->cp > cp) { store_value(stack, tr, size, value); cp = value->cp; @@ -686,6 +739,10 @@ int check_branch( { int s_offset; + if (offset & 1) { + report(stack->top, "Bad branch target (odd address)\n"); + } + /* Sign-extend */ if (offset & 0100000) s_offset = offset | ~0177777; @@ -731,7 +788,7 @@ void write_globals( if (ident) gsd_ident(&gsd, ident); - /* write out each PSECT with it's global stuff */ + /* write out each PSECT with its global stuff */ /* Sections must be written out in the order that they appear in the assembly file. */ for (isect = 0; isect < sector; isect++) { @@ -745,11 +802,10 @@ void write_globals( while (sym) { if ((sym->flags & SYMBOLFLAG_GLOBAL) && sym->section == psect) { gsd_global(&gsd, sym->label, - (sym-> - flags & SYMBOLFLAG_DEFINITION ? GLOBAL_DEF : 0) | ((sym-> - flags & SYMBOLFLAG_WEAK) ? - GLOBAL_WEAK : 0) - | ((sym->section->flags & PSECT_REL) ? GLOBAL_REL : 0) | 0100, + ((sym->flags & SYMBOLFLAG_DEFINITION) ? GLOBAL_DEF : 0) | + ((sym->flags & SYMBOLFLAG_WEAK) ? GLOBAL_WEAK : 0) | + ((sym->section->flags & PSECT_REL) ? GLOBAL_REL : 0) | + 0100, /* Looks undefined, but add it in anyway */ sym->value); } diff --git a/crossassemblers/macro11/assemble_aux.h b/crossassemblers/macro11/assemble_aux.h index 98ab12a..10cea84 100644 --- a/crossassemblers/macro11/assemble_aux.h +++ b/crossassemblers/macro11/assemble_aux.h @@ -15,10 +15,17 @@ typedef struct addr_mode { /* bit 3 is indirect */ /* bits 4:6 are mode, where 0=Rn, 1=(Rn)+, 2=-(Rn), 3=offset(Rn) */ - int rel; /* the addressing mode is PC-relative */ + int pcrel; /* the addressing mode is PC-relative */ EX_TREE *offset; /* Expression giving the offset */ } ADDR_MODE; +#define MODE_INDIRECT 010 /* (R0), @(R0)+, @-(R0), @42(R0) */ +#define MODE_REG 000 /* R0 */ +#define MODE_AUTO_INCR 020 /* (R0)+ */ +#define MODE_AUTO_DECR 040 /* -(R0) */ +#define MODE_OFFSET 060 /* 42(R0) */ +#define MODE_PC 007 + void push_cond( int ok, STREAM *str); @@ -85,7 +92,7 @@ void write_globals( FILE *obj); void migrate_implicit( void); - - +void migrate_undefined( + void); #endif diff --git a/crossassemblers/macro11/assemble_globals.c b/crossassemblers/macro11/assemble_globals.c index 40742b3..e0ac75e 100644 --- a/crossassemblers/macro11/assemble_globals.c +++ b/crossassemblers/macro11/assemble_globals.c @@ -24,9 +24,10 @@ int last_locsym = 32768; /* The last local symbol number generate int enabl_debug = 0; /* Whether assembler debugging is enabled */ -int enabl_ama = 0; /* When set, chooses absolute (037) versus +int opt_enabl_ama = 0; /* May be changed by command line */ +int enabl_ama; /* When set, chooses absolute (037) versus PC-relative */ -/* (067) addressing mode */ + /* (067) addressing mode */ int enabl_lsb = 0; /* When set, stops non-local symbol definitions from delimiting local symbol sections. */ @@ -36,6 +37,9 @@ int enabl_gbl = 1; /* Implicit definition of global symbols */ int enabl_lc = 1; /* If lowercase disabled, convert assembler source to upper case. */ +int enabl_lcm = 0; /* If lowercase disabled, .IF IDN/DIF are + case-sensitive. */ + int suppressed = 0; /* Assembly suppressed by failed conditional */ @@ -59,26 +63,26 @@ EX_TREE *xfer_address = NULL; /* The transfer address */ SYMBOL *current_pc; /* The current program counter */ unsigned last_dot_addr; /* Last coded PC... */ -SECTION *last_dot_section; /* ...and it's program section */ +SECTION *last_dot_section; /* ...and its program section */ /* The following are dummy psects for symbols which have meaning to the assembler: */ SECTION register_section = { - "", SECTION_REGISTER, 0, 0, 0, 0 + "*REGISTERS*", SECTION_REGISTER, 0, 0, 0, 0 }; /* the section containing the registers */ SECTION pseudo_section = { - "", SECTION_PSEUDO, 0, 0, 0, 0 + "*PSEUDO*", SECTION_PSEUDO, 0, 0, 0, 0 }; /* the section containing the pseudo-operations */ SECTION instruction_section = { - ". ABS.", SECTION_INSTRUCTION, 0, 0, 0, 0 + "*INSTR*", SECTION_INSTRUCTION, 0, 0, 0, 0 }; /* the section containing instructions */ SECTION macro_section = { - "", SECTION_SYSTEM, 0, 0, 0, 0 + "*MACRO*", SECTION_SYSTEM, 0, 0, 0, 0 }; /* Section for macros */ /* These are real psects that get written out to the object file */ diff --git a/crossassemblers/macro11/assemble_globals.h b/crossassemblers/macro11/assemble_globals.h index ea5ff01..4a21eb2 100644 --- a/crossassemblers/macro11/assemble_globals.h +++ b/crossassemblers/macro11/assemble_globals.h @@ -35,9 +35,11 @@ extern int last_locsym; /* The last local symbol number generated */ extern int enabl_debug; /* Whether assembler debugging is enabled */ +extern int opt_enabl_ama; /* May be changed by command line */ + extern int enabl_ama; /* When set, chooses absolute (037) versus PC-relative */ -/* (067) addressing mode */ + /* (067) addressing mode */ extern int enabl_lsb; /* When set, stops non-local symbol definitions from delimiting local symbol sections. */ @@ -46,6 +48,8 @@ extern int enabl_gbl; /* Implicit definition of global symbols */ extern int enabl_lc; /* If lowercase disabled, convert assembler source to upper case. */ +extern int enabl_lcm; /* If lowercase disabled, .IF IDN/DIF are + case-sensitive. */ extern int suppressed; /* Assembly suppressed by failed conditional */ extern MLB *mlbs[MAX_MLBS]; /* macro libraries specified on the command line */ @@ -67,7 +71,7 @@ extern EX_TREE *xfer_address; /* The transfer address */ extern SYMBOL *current_pc; /* The current program counter */ extern unsigned last_dot_addr; /* Last coded PC... */ -extern SECTION *last_dot_section; /* ...and it's program section */ +extern SECTION *last_dot_section; /* ...and its program section */ /* The following are dummy psects for symbols which have meaning to the assembler: */ diff --git a/crossassemblers/macro11/dumpobj.c b/crossassemblers/macro11/dumpobj.c index 7260784..c81aeaa 100644 --- a/crossassemblers/macro11/dumpobj.c +++ b/crossassemblers/macro11/dumpobj.c @@ -49,15 +49,33 @@ DAMAGE. #define NPSECTS 256 +#ifndef DEFAULT_OBJECTFORMAT_RT11 +#define DEFAULT_OBJECTFORMAT_RT11 0 +#endif + int psectid = 0; char *psects[NPSECTS]; FILE *bin = NULL; int badbin = 0; int xferad = 1; +/* memcheck - crash out if a pointer (returned from malloc) is NULL. */ + +void *memcheck( + void *ptr) +{ + if (ptr == NULL) { + fprintf(stderr, "Out of memory.\n"); + exit(EXIT_FAILURE); + } + + return ptr; +} + char *readrec( FILE *fp, - int *len) + int *len, + int rt11) { int c, i; @@ -66,33 +84,33 @@ char *readrec( chksum = 0; -#if RT11 - while (c = fgetc(fp), c != EOF && c == 0) ; + if (rt11) { + while (c = fgetc(fp), c != EOF && c == 0) ; - if (c == EOF) - return NULL; + if (c == EOF) + return NULL; - if (c != 1) { - fprintf(stderr, "Improperly formatted OBJ file (1)\n"); - return NULL; /* Not a properly formatted file. */ + if (c != 1) { + fprintf(stderr, "Improperly formatted OBJ file (1)\n"); + return NULL; /* Not a properly formatted file. */ + } + + chksum -= c; + + c = fgetc(fp); + if (c != 0) { + fprintf(stderr, "Improperly formatted OBJ file (2)\n"); + return NULL; /* Not properly formatted */ + } + + chksum -= c; /* even though for 0 the checksum isn't changed... */ } - chksum -= c; - - c = fgetc(fp); - if (c != 0) { - fprintf(stderr, "Improperly formatted OBJ file (2)\n"); - return NULL; /* Not properly formatted */ - } - - chksum -= c; /* even though for 0 the checksum isn't changed... */ -#endif /* RT11 */ - c = fgetc(fp); if (c == EOF) { -#if RT11 - fprintf(stderr, "Improperly formatted OBJ file (3)\n"); -#endif /* RT11 */ + if (rt11) { + fprintf(stderr, "Improperly formatted OBJ file (3)\n"); + } return NULL; } *len = c; @@ -109,9 +127,10 @@ char *readrec( chksum -= c; -#if RT11 - *len -= 4; /* Subtract header and length bytes from length */ -#endif + if (rt11) { + *len -= 4; /* Subtract header and length bytes from length */ + } + if (*len < 0) { fprintf(stderr, "Improperly formatted OBJ file (5)\n"); return NULL; @@ -133,28 +152,28 @@ char *readrec( for (i = 0; i < *len; i++) chksum -= (buf[i] & 0xff); -#if RT11 - c = fgetc(fp); - c &= 0xff; - chksum &= 0xff; - - if (c != chksum) { - free(buf); - fprintf(stderr, "Bad record checksum, " "calculated=$%04x, recorded=$%04x\n", chksum, c); - return NULL; - } -#else - if (*len & 1) { - /* skip 1 byte of padding */ + if (rt11) { c = fgetc(fp); - if (c == EOF) { + c &= 0xff; + chksum &= 0xff; + + if (c != chksum) { free(buf); - fprintf(stderr, "EOF where padding byte should be\n"); + fprintf(stderr, "Bad record checksum, " "calculated=$%04x, recorded=$%04x\n", chksum, c); return NULL; } + } else { + if (*len & 1) { + /* skip 1 byte of padding */ + c = fgetc(fp); + if (c == EOF) { + free(buf); + fprintf(stderr, "EOF where padding byte should be\n"); + return NULL; + } + } } -#endif /* RT11 */ return buf; } @@ -300,11 +319,7 @@ void add_gsdline( { if (nr_gsds >= gsdsize || all_gsds == NULL) { gsdsize += 128; - all_gsds = realloc(all_gsds, gsdsize * sizeof(char *)); - if (all_gsds == NULL) { - fprintf(stderr, "Out of memory\n"); - exit(EXIT_FAILURE); - } + all_gsds = memcheck(realloc(all_gsds, gsdsize * sizeof(char *))); } all_gsds[nr_gsds++] = line; @@ -322,11 +337,7 @@ void got_gsd( unsigned value; unsigned flags; - gsdline = malloc(256); - if (gsdline == NULL) { - fprintf(stderr, "Out of memory\n"); - exit(EXIT_FAILURE); - } + gsdline = memcheck(malloc(256)); unrad50(WORD(cp + i), name); unrad50(WORD(cp + i + 2), name + 3); @@ -367,7 +378,7 @@ void got_gsd( flags & 0100 ? "GBL" : "LCL", flags & 0200 ? "D" : "I", flags); - psects[psectid] = strdup(name); + psects[psectid] = memcheck(strdup(name)); trim(psects[psectid++]); psectid %= NPSECTS; break; @@ -385,7 +396,7 @@ void got_gsd( break; } - gsdline = realloc(gsdline, strlen(gsdline) + 1); + gsdline = memcheck(realloc(gsdline, strlen(gsdline) + 1)); add_gsdline(gsdline); } } @@ -395,7 +406,7 @@ int compare_gsdlines( const void *p2) { const char *const *l1 = p1, - *const *l2 = p2; + *const *l2 = p2; return strcmp(*l1, *l2); } @@ -683,23 +694,58 @@ int main( { int len; FILE *fp; - char *cp; + int arg; + int rt11 = DEFAULT_OBJECTFORMAT_RT11; + char *infile = 0; + char *outfile = 0; - if (argc < 2) { - fprintf(stderr, "Usage: dumpobj input.obj [ output.obj ]\n"); + for (arg = 1; arg < argc; arg++) { + if (*argv[arg] == '-') { + char *cp; + + cp = argv[arg] + 1; + if (!strcasecmp(cp, "rt11")) { + rt11 = 1; + } else if (!strcasecmp(cp, "rsx")) { + rt11 = 0; + } else { + fprintf(stderr, "Unknown option %s\n", argv[arg]); + exit(EXIT_FAILURE); + } + } + else if (infile == 0) { + infile = argv[arg]; + } + else if (outfile == 0) { + outfile = argv[arg]; + } + else { + fprintf(stderr, "Extra parameter %s\n", argv[arg]); + exit(EXIT_FAILURE); + } + } + + if (infile == 0) { + fprintf(stderr, "Usage: dumpobj [ -rt11 ] [ -rsx ] input.obj [ output.obj ]\n"); exit(1); } - fp = fopen(argv[1], "rb"); - if (fp == NULL) + fp = fopen(infile, "rb"); + if (fp == NULL) { + fprintf(stderr, "Unable to open %s\n", infile); return EXIT_FAILURE; - if (argc > 2 && argv[2]) { - bin = fopen(argv[2], "wb"); - if (bin == NULL) + } + if (outfile != 0) { + bin = fopen(outfile, "wb"); + if (bin == NULL) { + fprintf(stderr, "Unable to open %s\n", outfile); return EXIT_FAILURE; + } } - while ((cp = readrec(fp, &len)) != NULL) { + char *cp; + + while ((cp = readrec(fp, &len, rt11)) != NULL) { switch (cp[0] & 0xff) { case 1: got_gsd(cp, len); diff --git a/crossassemblers/macro11/extree.c b/crossassemblers/macro11/extree.c index 37970cc..2ee90fe 100644 --- a/crossassemblers/macro11/extree.c +++ b/crossassemblers/macro11/extree.c @@ -1,15 +1,17 @@ -#define EXTREE__C - #include #include #include +#include #include "extree.h" /* my own definitions */ #include "util.h" #include "assemble_globals.h" +#include "assemble_aux.h" +#include "listing.h" #include "object.h" +#define DEBUG_REGEXPR 0 /* Diagnostic: print an expression tree. I used this in various places to help me diagnose parse problems, by putting in calls to @@ -25,6 +27,10 @@ void print_tree( { SYMBOL *sym; + if (printfile == NULL) { + return; + } + if (tp == NULL) { fprintf(printfile, "(null)"); return; @@ -58,6 +64,12 @@ void print_tree( fputc('>', printfile); break; + case EX_REG: + fprintf(printfile, "%%<"); + print_tree(printfile, tp->data.child.left, depth + 4); + fputc('>', printfile); + break; + case EX_ERR: fprintf(printfile, "{expression error}"); if (tp->data.child.left) { @@ -114,37 +126,42 @@ void print_tree( print_tree(printfile, tp->data.child.right, depth + 4); fputc('>', printfile); break; + + case EX_LSH: + fputc('<', printfile); + print_tree(printfile, tp->data.child.left, depth + 4); + fputc('_', printfile); + print_tree(printfile, tp->data.child.right, depth + 4); + fputc('>', printfile); + break; + + default: + fprintf(printfile, "(node %d)", tp->type); + break; } if (depth == 0) fputc('\n', printfile); } -/* free_tree frees an expression tree. */ +/* num_subtrees tells you how many subtrees this EX_TREE has. */ -void free_tree( +int num_subtrees( EX_TREE *tp) { switch (tp->type) { case EX_UNDEFINED_SYM: case EX_TEMP_SYM: - free(tp->data.symbol->label); - free(tp->data.symbol); - break; - - case EX_LIT: case EX_SYM: + case EX_LIT: + return 0; break; case EX_COM: case EX_NEG: - free_tree(tp->data.child.left); - break; - + case EX_REG: case EX_ERR: - if (tp->data.child.left) - free_tree(tp->data.child.left); - break; + return 1; case EX_ADD: case EX_SUB: @@ -152,10 +169,47 @@ void free_tree( case EX_DIV: case EX_AND: case EX_OR: - free_tree(tp->data.child.left); - free_tree(tp->data.child.right); - break; + case EX_LSH: + return 2; } + + return 0; +} + +/* free_tree frees an expression tree. */ + +void free_tree( + EX_TREE *tp) +{ + if (!tp) + return; + + switch (num_subtrees(tp)) { + case 0: + switch (tp->type) { + case EX_UNDEFINED_SYM: + case EX_TEMP_SYM: + free(tp->data.symbol->label); + free(tp->data.symbol); + break; + + case EX_SYM: + case EX_LIT: + break; + + default: + assert(0); + break; + } + break; + case 2: + free_tree(tp->data.child.right); + /* FALLTHROUGH */ + case 1: + free_tree(tp->data.child.left); + break; + } + free(tp); } @@ -172,14 +226,13 @@ static EX_TREE *new_temp_sym( sym = memcheck(malloc(sizeof(SYMBOL))); sym->label = memcheck(strdup(label)); - sym->flags = 0; + sym->flags = SYMBOLFLAG_DEFINITION; sym->stmtno = stmtno; sym->next = NULL; sym->section = section; sym->value = value; - tp = new_ex_tree(); - tp->type = EX_TEMP_SYM; + tp = new_ex_tree(EX_TEMP_SYM); tp->data.symbol = sym; return tp; @@ -215,40 +268,37 @@ EX_TREE *dup_tree( return NULL; } - res = new_ex_tree(); - res->type = tp->type; + res = new_ex_tree(tp->type); res->cp = tp->cp; - switch (tp->type) { - case EX_UNDEFINED_SYM: - case EX_TEMP_SYM: - res->data.symbol = dup_symbol(tp->data.symbol); - break; + switch (num_subtrees(tp)) { + case 0: + switch (tp->type) { + case EX_UNDEFINED_SYM: + case EX_TEMP_SYM: + res->data.symbol = dup_symbol(tp->data.symbol); + break; - /* The symbol reference in EX_SYM is not freed in free_tree() */ - case EX_SYM: - res->data.symbol = tp->data.symbol; - break; + /* The symbol reference in EX_SYM is not freed in free_tree() */ + case EX_SYM: + res->data.symbol = tp->data.symbol; + break; - case EX_LIT: - res->data.lit = tp->data.lit; - break; + case EX_LIT: + res->data.lit = tp->data.lit; + break; - case EX_COM: - case EX_NEG: - case EX_ERR: - res->data.child.left = dup_tree(tp->data.child.left); - break; - - case EX_ADD: - case EX_SUB: - case EX_MUL: - case EX_DIV: - case EX_AND: - case EX_OR: - res->data.child.left = dup_tree(tp->data.child.left); - res->data.child.right = dup_tree(tp->data.child.right); + default: + assert(0); + break; + } break; + case 2: + res->data.child.right = dup_tree(tp->data.child.right); + /* FALLTHROUGH */ + case 1: + res->data.child.left = dup_tree(tp->data.child.left); + break; } return res; @@ -258,10 +308,12 @@ EX_TREE *dup_tree( (tp)->data.symbol->section->flags & PSECT_REL) /* evaluate "evaluates" an EX_TREE, ideally trying to produce a - constant value, else a symbol plus an offset. */ -EX_TREE *evaluate( + constant value, else a symbol plus an offset. + Leaves the input tree untouched and creates a new tree as result. */ +EX_TREE *evaluate_rec( EX_TREE *tp, - int undef) + int flags, + int *outflags) { EX_TREE *res; char *cp = tp->cp; @@ -273,22 +325,26 @@ EX_TREE *evaluate( /* Change some symbols to "undefined" */ - if (undef) { - int change = 0; + if (flags & EVALUATE_DEFINEDNESS) { + int is_undefined = 0; /* I'd prefer this behavior, but MACRO.SAV is a bit too primitive. */ #if 0 /* A temporary symbol defined later is "undefined." */ if (!(sym->flags & PERMANENT) && sym->stmtno > stmtno) - change = 1; + is_undefined = 1; #endif /* A global symbol with no assignment is "undefined." */ /* Go figure. */ - if ((sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) - change = 1; + if (SYM_IS_IMPORTED(sym)) + is_undefined = 1; - if (change) { + /* A symbol marked as undefined is undefined */ + if (sym->flags & SYMBOLFLAG_UNDEFINED) + is_undefined = 1; + + if (is_undefined) { res = new_temp_sym(tp->data.symbol->label, tp->data.symbol->section, tp->data.symbol->value); res->type = EX_UNDEFINED_SYM; @@ -298,9 +354,13 @@ EX_TREE *evaluate( /* Turn defined absolute symbol to a literal */ if (!(sym->section->flags & PSECT_REL) - && (sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) != SYMBOLFLAG_GLOBAL - && sym->section->type != SECTION_REGISTER) { + && !SYM_IS_IMPORTED(sym)) { res = new_ex_lit(sym->value); + + if (sym->section->type == SECTION_REGISTER) { + *outflags |= EVALUATE_OUT_IS_REGISTER; + } + break; } @@ -330,23 +390,20 @@ EX_TREE *evaluate( case EX_COM: /* Complement */ - tp = evaluate(tp->data.child.left, undef); + tp = evaluate_rec(tp->data.child.left, flags, outflags); if (tp->type == EX_LIT) { /* Complement the literal */ res = new_ex_lit(~tp->data.lit); free_tree(tp); } else { /* Copy verbatim. */ - res = new_ex_tree(); - res->type = EX_COM; - res->cp = tp->cp; - res->data.child.left = tp; + res = new_ex_una(EX_COM, tp); } break; case EX_NEG: - tp = evaluate(tp->data.child.left, undef); + tp = evaluate_rec(tp->data.child.left, flags, outflags); if (tp->type == EX_LIT) { /* negate literal */ res = new_ex_lit((unsigned) -(int) tp->data.lit); @@ -357,18 +414,20 @@ EX_TREE *evaluate( /* Make a temp sym with the negative value of the given sym (this works for symbols within relocatable sections too) */ - res = new_temp_sym("*TEMP", tp->data.symbol->section, (unsigned) -(int) tp->data.symbol->value); + res = new_temp_sym("*NEG", tp->data.symbol->section, (unsigned) -(int) tp->data.symbol->value); res->cp = tp->cp; free_tree(tp); } else { /* Copy verbatim. */ - res = new_ex_tree(); - res->type = EX_NEG; - res->cp = tp->cp; - res->data.child.left = tp; + res = new_ex_una(EX_NEG, tp); } break; + case EX_REG: + res = evaluate_rec(tp->data.child.left, flags, outflags); + *outflags |= EVALUATE_OUT_IS_REGISTER; + break; + case EX_ERR: /* Copy */ res = dup_tree(tp); @@ -379,8 +438,8 @@ EX_TREE *evaluate( EX_TREE *left, *right; - left = evaluate(tp->data.child.left, undef); - right = evaluate(tp->data.child.right, undef); + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); /* Both literals? Sum them and return result. */ if (left->type == EX_LIT && right->type == EX_LIT) { @@ -455,8 +514,8 @@ EX_TREE *evaluate( EX_TREE *left, *right; - left = evaluate(tp->data.child.left, undef); - right = evaluate(tp->data.child.right, undef); + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); /* Both literals? Subtract them and return a lit. */ if (left->type == EX_LIT && right->type == EX_LIT) { @@ -531,8 +590,8 @@ EX_TREE *evaluate( EX_TREE *left, *right; - left = evaluate(tp->data.child.left, undef); - right = evaluate(tp->data.child.right, undef); + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); /* Can only multiply if both are literals */ if (left->type == EX_LIT && right->type == EX_LIT) { @@ -593,8 +652,8 @@ EX_TREE *evaluate( EX_TREE *left, *right; - left = evaluate(tp->data.child.left, undef); - right = evaluate(tp->data.child.right, undef); + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); /* Can only divide if both are literals */ if (left->type == EX_LIT && right->type == EX_LIT) { @@ -621,8 +680,8 @@ EX_TREE *evaluate( EX_TREE *left, *right; - left = evaluate(tp->data.child.left, undef); - right = evaluate(tp->data.child.right, undef); + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); /* Operate if both are literals */ if (left->type == EX_LIT && right->type == EX_LIT) { @@ -666,8 +725,8 @@ EX_TREE *evaluate( EX_TREE *left, *right; - left = evaluate(tp->data.child.left, undef); - right = evaluate(tp->data.child.right, undef); + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); /* Operate if both are literals */ if (left->type == EX_LIT && right->type == EX_LIT) { @@ -705,12 +764,117 @@ EX_TREE *evaluate( res = new_ex_bin(EX_OR, left, right); } break; + + case EX_LSH: + { + EX_TREE *left, + *right; + + left = evaluate_rec(tp->data.child.left, flags, outflags); + right = evaluate_rec(tp->data.child.right, flags, outflags); + + /* Operate if both are literals */ + if (left->type == EX_LIT && right->type == EX_LIT) { + int shift = right->data.lit; + if (shift < 0) + res = new_ex_lit(left->data.lit >> -shift); + else + res = new_ex_lit(left->data.lit << shift); + free_tree(left); + free_tree(right); + break; + } + + if (right->type == EX_LIT && /* Symbol shifted 0 == symbol */ + right->data.lit == 0) { + res = left; + free_tree(right); + break; + } + + if (right->type == EX_LIT && /* Anything shifted 16 == 0 */ + ((int)right->data.lit > 15 || + (int)right->data.lit < -15)) { + res = new_ex_lit(0); + free_tree(left); + free_tree(right); + break; + } + + if (right->type == EX_LIT) { /* Other shifts become * or / */ + int shift = right->data.lit; + if (shift > 0) + res = new_ex_bin(EX_MUL, left, new_ex_lit(1 << shift)); + else + res = new_ex_bin(EX_DIV, left, new_ex_lit(1 << -shift)); + free_tree(right); + break; + } + + /* Anything else returns verbatim */ + res = new_ex_bin(EX_LSH, left, right); + } + break; + default: - fprintf(stderr, "Invalid tree\n"); + fprintf(stderr, "evaluate_rec: Invalid tree: "); + print_tree(stderr, tp, 0); return NULL; } res->cp = cp; + + return res; +} + +EX_TREE *evaluate( + EX_TREE *tp, + int flags) +{ + EX_TREE *res; + int outflags = 0; + +#if DEBUG_REGEXPR + fprintf(stderr, "evaluate: "); + print_tree(stderr, tp, 0); +#endif /* DEBUG_REGEXPR */ + /* + * Check the common simple case for register references: R0...PC. + * Copy those directly, without going into the recursion. + * Therefore, in the recursion it can be assumed that the expression + * is more complex, and it is worth the overhead of converting them + * to an EX_LIT plus the EVALUATE_OUT_IS_REGISTER flag + * (and back again, up here). + */ + if (tp->type == EX_SYM && + tp->data.symbol->section->type == SECTION_REGISTER && + !SYM_IS_IMPORTED(tp->data.symbol)) { + res = dup_tree(tp); + } else { + res = evaluate_rec(tp, flags, &outflags); + + if (outflags & EVALUATE_OUT_IS_REGISTER) { + int regno = get_register(res); + + if (regno == NO_REG) { + report(NULL, "Register expression out of range.\n"); +#if DEBUG_REGEXPR + print_tree(stderr, tp, 0); + print_tree(stderr, res, 0); +#endif /* DEBUG_REGEXPR */ + /* TODO: maybe make this a EX_TEMP_SYM? */ + res = ex_err(res, res->cp); + } else { + EX_TREE *newresult = new_ex_tree(EX_SYM); + + newresult->cp = res->cp; + newresult->data.symbol = reg_sym[regno]; + free_tree(res); + res = newresult; + } + } + } + return res; } @@ -718,9 +882,11 @@ EX_TREE *evaluate( /* Allocate an EX_TREE */ EX_TREE *new_ex_tree( - void) + int type) { - EX_TREE *tr = memcheck(malloc(sizeof(EX_TREE))); + EX_TREE *tr = memcheck(calloc(1, sizeof(EX_TREE))); + + tr->type = type; return tr; } @@ -734,9 +900,8 @@ EX_TREE *ex_err( { EX_TREE *errtp; - errtp = new_ex_tree(); + errtp = new_ex_tree(EX_ERR); errtp->cp = cp; - errtp->type = EX_ERR; errtp->data.child.left = tp; return errtp; @@ -749,8 +914,7 @@ EX_TREE *new_ex_lit( { EX_TREE *tp; - tp = new_ex_tree(); - tp->type = EX_LIT; + tp = new_ex_tree(EX_LIT); tp->data.lit = value; return tp; @@ -765,11 +929,29 @@ EX_TREE *new_ex_bin( { EX_TREE *tp; - tp = new_ex_tree(); - tp->type = type; + tp = new_ex_tree(type); tp->data.child.left = left; tp->data.child.right = right; + tp->cp = right->cp; + + return tp; +} + +/* Create an EX_TREE representing a unary expression */ + +EX_TREE *new_ex_una( + int type, + EX_TREE *left) +{ + EX_TREE *tp; + + tp = new_ex_tree(type); + tp->data.child.left = left; + tp->data.child.right = NULL; + + tp->cp = left->cp; + return tp; } diff --git a/crossassemblers/macro11/extree.h b/crossassemblers/macro11/extree.h index ee72a00..6dce952 100644 --- a/crossassemblers/macro11/extree.h +++ b/crossassemblers/macro11/extree.h @@ -5,10 +5,12 @@ #include "symbols.h" typedef struct ex_tree { - enum ex_type { EX_LIT = 1, + enum ex_type { + EX_LIT = 1, /* Expression is a literal value */ EX_SYM = 2, - /* Expression has a symbol reference */ + /* Expression has a symbol reference + * (symbol from symbol table, so not freed) */ EX_UNDEFINED_SYM = 3, /* Expression is undefined sym reference */ EX_TEMP_SYM = 4, @@ -18,20 +20,25 @@ typedef struct ex_tree { /* One's complement */ EX_NEG = 6, /* Negate */ - EX_ERR = 7, + EX_REG = 7, + /* register value (%) */ + EX_ERR = 8, /* Expression with an error */ - EX_ADD = 8, + EX_ADD = 9, /* Add */ - EX_SUB = 9, + EX_SUB = 10, /* Subtract */ - EX_MUL = 10, + EX_MUL = 11, /* Multiply */ - EX_DIV = 11, + EX_DIV = 12, /* Divide */ - EX_AND = 12, + EX_AND = 13, /* bitwise and */ - EX_OR = 13 /* bitwise or */ + EX_OR = 14, + /* bitwise or */ + EX_LSH = 15, + /* left shift */ } type; char *cp; /* points to end of parsed expression */ @@ -48,7 +55,7 @@ typedef struct ex_tree { EX_TREE *new_ex_tree( - void); + int type); void free_tree( EX_TREE *tp); @@ -61,10 +68,17 @@ EX_TREE *new_ex_bin( int type, EX_TREE *left, EX_TREE *right); - +EX_TREE *new_ex_una( + int type, + EX_TREE *left); +int num_subtrees( + EX_TREE *tp); EX_TREE *evaluate( EX_TREE *tp, - int undef); + int flags); +#define EVALUATE_DEFINEDNESS 1 + +#define EVALUATE_OUT_IS_REGISTER 1 #endif diff --git a/crossassemblers/macro11/macro11.c b/crossassemblers/macro11/macro11.c index ef50f88..4debd12 100644 --- a/crossassemblers/macro11/macro11.c +++ b/crossassemblers/macro11/macro11.c @@ -53,9 +53,6 @@ DAMAGE. #include "object.h" #include "symbols.h" -#define stricmp strcasecmp - - /* enable_tf is called by command argument parsing to enable and disable named options. */ @@ -64,9 +61,9 @@ static void enable_tf( int tf) { if (strcmp(opt, "AMA") == 0) - enabl_ama = tf; + opt_enabl_ama = tf; else if (strcmp(opt, "GBL") == 0) - enabl_gbl = tf; + enabl_gbl = tf; /* Unused in pass 2 */ else if (strcmp(opt, "ME") == 0) list_me = tf; else if (strcmp(opt, "BEX") == 0) @@ -83,7 +80,7 @@ static void print_version( fprintf(strm, " Version %s\n", VERSIONSTR); fprintf(strm, " Copyright 2001 Richard Krehbiel,\n"); fprintf(strm, " modified 2009 by Joerg Hoppe,\n"); - fprintf(strm, " modified 2015 by Olaf 'Rhialto' Seibert.\n"); + fprintf(strm, " modified 2015-2017,2020-2021 by Olaf 'Rhialto' Seibert.\n"); } static void append_env( @@ -133,7 +130,7 @@ static void print_help( printf("-h print this help\n"); printf("-l gives the listing file name (.LST)\n"); printf(" -l - enables listing to stdout.\n"); - printf("-m load RT-11 compatible macro library from which\n"); + printf("-m load RSX-11 or RT-11 compatible macro library from which\n"); printf(" .MCALLed macros can be found.\n"); printf(" Multiple allowed.\n"); printf("-o gives the object file name (.OBJ)\n"); @@ -148,6 +145,10 @@ static void print_help( printf(" libraries (see -m) into individual .MAC files in the current\n"); printf(" directory. No assembly of input is done.\n"); printf(" This must be the last command line option!\n"); + printf("-rsx Generate RSX style object files%s.\n", + (rt11 ? "": " (default)")); + printf("-rt11 Generate RT11 style object files.%s\n", + (rt11 ? " (default)": "")); printf("-ysl Syntax extension: change length of symbols from \n"); printf(" default = %d to larger values, max %d.\n", SYMMAX_DEFAULT, SYMMAX_MAX); printf("-yus Syntax extension: allow underscore \"_\" in symbols.\n"); @@ -170,6 +171,43 @@ void usage(char *message) { exit(EXIT_FAILURE); } +void prepare_pass(int this_pass, STACK *stack, int nr_files, char **fnames) +{ + int i; + + stack_init(stack); + + /* Push the files onto the input stream in reverse order */ + for (i = nr_files - 1; i >= 0; --i) { + STREAM *str = new_file_stream(fnames[i]); + + if (str == NULL) { + report(NULL, "Unable to open file %s\n", fnames[i]); + exit(EXIT_FAILURE); + } + stack_push(stack, str); + } + + DOT = 0; + current_pc->section = &blank_section; + last_dot_section = NULL; + pass = this_pass; + stmtno = 0; + lsb = 0; + next_lsb = 1; + lsb_used = 0; + last_macro_lsb = -1; + last_locsym = 32767; + last_cond = -1; + sect_sp = -1; + suppressed = 0; + enabl_lc = 1; + enabl_lcm = 0; + enabl_lsb = 0; + enabl_ama = opt_enabl_ama; + enabl_gbl = 1; +} + int main( int argc, char *argv[]) @@ -195,11 +233,11 @@ int main( char *cp; cp = argv[arg] + 1; - if (!stricmp(cp, "h")) { + if (!strcasecmp(cp, "h")) { print_help(); - } else if (!stricmp(cp, "v")) { + } else if (!strcasecmp(cp, "v")) { print_version(stderr); - } else if (!stricmp(cp, "e")) { + } else if (!strcasecmp(cp, "e")) { /* Followed by options to enable */ /* Since /SHOW and /ENABL option names don't overlap, I consolidate. */ @@ -208,14 +246,14 @@ int main( } upcase(argv[++arg]); enable_tf(argv[arg], 1); - } else if (!stricmp(cp, "d")) { + } else if (!strcasecmp(cp, "d")) { /* Followed by an option to disable */ if(arg >= argc-1 || !isalpha((unsigned char)*argv[arg+1])) { usage("-d must be followed by an option to disable\n"); } upcase(argv[++arg]); enable_tf(argv[arg], 0); - } else if (!stricmp(cp, "m")) { + } else if (!strcasecmp(cp, "m")) { /* Macro library */ /* This option gives the name of an RT-11 compatible macro library from which .MCALLed macros can be @@ -231,7 +269,7 @@ int main( exit(EXIT_FAILURE); } nr_mlbs++; - } else if (!stricmp(cp, "p")) { + } else if (!strcasecmp(cp, "p")) { /* P for search path */ /* The -p option gives the name of a directory in which .MCALLed macros may be found. */ { @@ -243,7 +281,7 @@ int main( append_env("MCALL", argv[arg+1]); arg++; } - } else if (!stricmp(cp, "I")) { + } else if (!strcasecmp(cp, "I")) { /* I for include path */ /* The -I option gives the name of a directory in which .included files may be found. */ { @@ -255,14 +293,14 @@ int main( arg++; } - } else if (!stricmp(cp, "o")) { + } else if (!strcasecmp(cp, "o")) { /* The -o option gives the object file name (.OBJ) */ if(arg >= argc-1 || *argv[arg+1] == '-') { usage("-o must be followed by the object file name\n"); } ++arg; objname = argv[arg]; - } else if (!stricmp(cp, "l")) { + } else if (!strcasecmp(cp, "l")) { /* The option -l gives the listing file name (.LST) */ /* -l - enables listing to stdout. */ if(arg >= argc-1 || @@ -274,7 +312,7 @@ int main( lstfile = stdout; else lstfile = fopen(lstname, "w"); - } else if (!stricmp(cp, "x")) { + } else if (!strcasecmp(cp, "x")) { /* The -x option invokes macro11 to expand the contents of the registered macro libraries (see -m) into individual .MAC files in the current @@ -288,7 +326,7 @@ int main( for (m = 0; m < nr_mlbs; m++) mlb_extract(mlbs[m]); return EXIT_SUCCESS; - } else if (!stricmp(cp, "ysl")) { + } else if (!strcasecmp(cp, "ysl")) { /* set symbol_len */ if (arg >= argc-1) { usage("-s must be followed by a number\n"); @@ -302,14 +340,18 @@ int main( } symbol_len = sl; } - } else if (!stricmp(cp, "yus")) { + } else if (!strcasecmp(cp, "yus")) { /* allow underscores */ symbol_allow_underscores = 1; - } else if (!stricmp(cp, "yl1")) { + } else if (!strcasecmp(cp, "yl1")) { /* list the first pass, in addition to the second */ list_pass_0++; - } else if (!stricmp(cp, "yd")) { + } else if (!strcasecmp(cp, "yd")) { enabl_debug++; + } else if (!strcasecmp(cp, "rt11")) { + rt11 = 1; + } else if (!strcasecmp(cp, "rsx")) { + rt11 = 0; } else { fprintf(stderr, "Unknown option %s\n", argv[arg]); print_help(); @@ -326,39 +368,11 @@ int main( } add_symbols(&blank_section); - - text_init(&tr, NULL, 0); - module_name = memcheck(strdup(".MAIN.")); - xfer_address = new_ex_lit(1); /* The undefined transfer address */ - stack_init(&stack); - /* Push the files onto the input stream in reverse order */ - for (i = nr_files - 1; i >= 0; --i) { - STREAM *str = new_file_stream(fnames[i]); - - if (str == NULL) { - report(NULL, "Unable to open file %s\n", fnames[i]); - exit(EXIT_FAILURE); - } - stack_push(&stack, str); - } - - DOT = 0; - current_pc->section = &blank_section; - last_dot_section = NULL; - pass = 0; - stmtno = 0; - lsb = 0; - next_lsb = 1; - lsb_used = 0; - last_macro_lsb = -1; - last_locsym = 32767; - last_cond = -1; - sect_sp = -1; - suppressed = 0; - + text_init(&tr, NULL, 0); + prepare_pass(0, &stack, nr_files, fnames); assemble_stack(&stack, &tr); if (list_pass_0 && lstfile) { @@ -378,37 +392,9 @@ int main( sym_hist(&symbol_st, "symbol_st"); /* Draw a symbol table histogram */ #endif - - text_init(&tr, obj, 0); - - stack_init(&stack); /* Superfluous... */ - /* Re-push the files onto the input stream in reverse order */ - for (i = nr_files - 1; i >= 0; --i) { - STREAM *str = new_file_stream(fnames[i]); - - if (str == NULL) { - report(NULL, "Unable to open file %s\n", fnames[i]); - exit(EXIT_FAILURE); - } - stack_push(&stack, str); - } - - DOT = 0; - - current_pc->section = &blank_section; - last_dot_section = NULL; - - pass = 1; - stmtno = 0; - lsb = 0; - next_lsb = 1; - lsb_used = 0; - last_macro_lsb = -1; - last_locsym = 32767; pop_cond(-1); - sect_sp = -1; - suppressed = 0; - + text_init(&tr, obj, 0); + prepare_pass(1, &stack, nr_files, fnames); errcount = assemble_stack(&stack, &tr); text_flush(&tr); @@ -431,6 +417,7 @@ int main( fprintf(stderr, "%d Errors\n", errcount); if (lstfile) { + migrate_undefined(); /* Migrate the undefined symbols */ list_symbol_table(); } diff --git a/crossassemblers/macro11/macro11.h b/crossassemblers/macro11/macro11.h index d8cc5ba..366fc46 100644 --- a/crossassemblers/macro11/macro11.h +++ b/crossassemblers/macro11/macro11.h @@ -3,12 +3,12 @@ #include "git-info.h" -#define BASE_VERSION "0.4" +#define BASE_VERSION "0.7.2" #if defined(GIT_VERSION) #define VERSIONSTR BASE_VERSION" ("GIT_VERSION"\n\t"GIT_AUTHOR_DATE")" #else -#define VERSIONSTR BASE_VERSION" (21 June 2015)" +#define VERSIONSTR BASE_VERSION" (05 Jan 2022)" /*#define VERSIONSTR "0.3 (April 21, 2009)" */ /*#define VERSIONSTR "0.2 July 15, 2001" */ #endif diff --git a/crossassemblers/macro11/macro11.supp b/crossassemblers/macro11/macro11.supp new file mode 100644 index 0000000..b9328bc --- /dev/null +++ b/crossassemblers/macro11/macro11.supp @@ -0,0 +1 @@ +leak:atexit_handler_alloc diff --git a/crossassemblers/macro11/macros.c b/crossassemblers/macro11/macros.c index c1f4490..58ca443 100644 --- a/crossassemblers/macro11/macros.c +++ b/crossassemblers/macro11/macros.c @@ -91,7 +91,8 @@ void read_body( break; } - if (!called && (list_level - 1 + list_md) > 0) { + if (!(called & CALLED_NOLIST) && + (list_level - 1 + list_md) > 0) { list_flush(); list_source(stack->top, nextline); } @@ -185,17 +186,21 @@ MACRO *defmacro( return NULL; } - /* Allow redefinition of a macro; new definition replaces the old. */ - mac = (MACRO *) lookup_sym(label, ¯o_st); - if (mac) { - /* Remove from the symbol table... */ - remove_sym(&mac->sym, ¯o_st); - free_macro(mac); + if (!(called & CALLED_NODEFINE)) { + /* Allow redefinition of a macro; new definition replaces the old. */ + mac = (MACRO *) lookup_sym(label, ¯o_st); + if (mac) { + /* Remove from the symbol table... */ + remove_sym(&mac->sym, ¯o_st); + free_macro(mac); + } } mac = new_macro(label); - add_table(&mac->sym, ¯o_st); + if (!(called & CALLED_NODEFINE)) { + add_table(&mac->sym, ¯o_st); + } argtail = &mac->args; cp = skipdelim(cp); @@ -245,7 +250,7 @@ MACRO *defmacro( gb = new_buffer(); - if (!called && !list_md) { + if ((called & CALLED_NOLIST) && !list_md) { list_level--; levelmod = 1; } @@ -579,7 +584,7 @@ MACRO *new_macro( { MACRO *mac = memcheck(malloc(sizeof(MACRO))); - mac->sym.flags = 0; + mac->sym.flags = SYMBOLFLAG_DEFINITION; mac->sym.label = label; mac->sym.stmtno = stmtno; mac->sym.next = NULL; @@ -591,7 +596,7 @@ MACRO *new_macro( return mac; } -/* free a macro, it's args, it's text, etc. */ +/* free a macro, its args, its text, etc. */ void free_macro( MACRO *mac) { diff --git a/crossassemblers/macro11/macros.h b/crossassemblers/macro11/macros.h index 212ecc7..b4af2a6 100644 --- a/crossassemblers/macro11/macros.h +++ b/crossassemblers/macro11/macros.h @@ -46,6 +46,10 @@ MACRO *defmacro( STACK *stack, int called); +#define CALLED_NORMAL 0 +#define CALLED_NOLIST 1 +#define CALLED_NODEFINE 2 + STREAM *expandmacro( STREAM *refstr, MACRO *mac, diff --git a/crossassemblers/macro11/mlb-rsx.c b/crossassemblers/macro11/mlb-rsx.c index 9e3545a..c86bc62 100644 --- a/crossassemblers/macro11/mlb-rsx.c +++ b/crossassemblers/macro11/mlb-rsx.c @@ -3,7 +3,7 @@ */ /* Copyright (c) 2001, Richard Krehbiel -Copyright (c) 2015, Olaf Seibert +Copyright (c) 2015, 2017, Olaf Seibert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -156,6 +156,24 @@ DAMAGE. #include "mlb.h" #include "util.h" +static MLB *mlb_rsx_open( + char *name, + int allow_object_library); +static BUFFER *mlb_rsx_entry( + MLB *mlb, + char *name); +static void mlb_rsx_close( + MLB *mlb); +static void mlb_rsx_extract( + MLB *mlb); + +struct mlb_vtbl mlb_rsx_vtbl = { + mlb_rsx_open, + mlb_rsx_entry, + mlb_rsx_extract, + mlb_rsx_close, +}; + #define BLOCKSIZE 512 #define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8)) @@ -178,7 +196,7 @@ static void trim( /* mlb_open opens a file which is given to be a macro library. */ /* Returns NULL on failure. */ -MLB *mlb_open( +MLB *mlb_rsx_open( char *name, int allow_objlib) { @@ -189,11 +207,12 @@ MLB *mlb_open( unsigned start_block; int i; + mlb->vtbl = &mlb_rsx_vtbl; mlb->directory = NULL; mlb->fp = fopen(name, "rb"); if (mlb->fp == NULL) { - mlb_close(mlb); + mlb_rsx_close(mlb); return NULL; } @@ -201,7 +220,7 @@ MLB *mlb_open( if (fread(buff, 1, 060, mlb->fp) < 060) { fprintf(stderr, "error: can't read full header\n"); - mlb_close(mlb); + mlb_rsx_close(mlb); free(buff); return NULL; } @@ -210,8 +229,9 @@ MLB *mlb_open( if (allow_objlib && WORD(buff) == 01000) { /* Is it an object library? */ mlb->is_objlib = 1; } else if (WORD(buff) != 01001) { /* Is this really a macro library? */ - fprintf(stderr, "error: first word not correct value\n"); - mlb_close(mlb); /* Nope. */ + /* fprintf(stderr, "error: first word not correct value\n"); */ + mlb_rsx_close(mlb); /* Nope. */ + free(buff); return NULL; } @@ -222,7 +242,7 @@ MLB *mlb_open( directory */ if (entsize < 8) { /* Is this really a macro library? */ - mlb_close(mlb); /* Nope. */ + mlb_rsx_close(mlb); /* Nope. */ fprintf(stderr, "error: entsize too small: %d\n", entsize); return NULL; } @@ -237,7 +257,7 @@ MLB *mlb_open( /* Read the disk directory */ if (fread(buff, entsize, nr_entries, mlb->fp) < nr_entries) { - mlb_close(mlb); /* Sorry, read error. */ + mlb_rsx_close(mlb); /* Sorry, read error. */ free(buff); return NULL; } @@ -306,8 +326,8 @@ MLB *mlb_open( return mlb; } -/* mlb_close discards MLB and closes the file. */ -void mlb_close( +/* mlb_rsx_close discards MLB and closes the file. */ +void mlb_rsx_close( MLB *mlb) { if (mlb) { @@ -326,15 +346,15 @@ void mlb_close( } } -/* mlb_entry returns a BUFFER containing the specified entry from the +/* mlb_rsx_entry returns a BUFFER containing the specified entry from the macro library, or NULL if not found. */ -BUFFER *mlb_entry( +BUFFER *mlb_rsx_entry( MLB *mlb, char *name) { int i; - MLBENT *ent; + MLBENT *ent = NULL; BUFFER *buf; char *bp; int c; @@ -347,17 +367,17 @@ BUFFER *mlb_entry( } if (i >= mlb->nentries) { -// fprintf(stderr, "mlb_entry: %s not found\n", name); +// fprintf(stderr, "mlb_rsx_entry: %s not found\n", name); return NULL; } fseek(mlb->fp, ent->position, SEEK_SET); -// fprintf(stderr, "mlb_entry: %s at position %ld\n", name, (long)ent->position); +// fprintf(stderr, "mlb_rsx_entry: %s at position %ld\n", name, (long)ent->position); #define MODULE_HEADER_SIZE 022 if (fread(module_header, MODULE_HEADER_SIZE, 1, mlb->fp) < 1) { -// fprintf(stderr, "mlb_entry: %s at position %lx can't read 022 bytes\n", name, (long)ent->position); +// fprintf(stderr, "mlb_rsx_entry: %s at position %lx can't read 022 bytes\n", name, (long)ent->position); return NULL; } @@ -368,10 +388,10 @@ BUFFER *mlb_entry( ent->length = (WORD(module_header + 04) << 16) + WORD(module_header + 06); ent->length -= MODULE_HEADER_SIZE; /* length is including this header */ -// fprintf(stderr, "mlb_entry: %s at position %lx length = %d\n", name, (long)ent->position, ent->length); +// fprintf(stderr, "mlb_rsx_entry: %s at position %lx length = %d\n", name, (long)ent->position, ent->length); if (module_header[02] == 1) { - fprintf(stderr, "mlb_entry: %s at position %lx deleted entry\n", name, (long)ent->position); + fprintf(stderr, "mlb_rsx_entry: %s at position %lx deleted entry\n", name, (long)ent->position); /* Deleted Entry */ return NULL; } @@ -398,7 +418,7 @@ BUFFER *mlb_entry( i = fread(bp, 1, ent->length, mlb->fp); bp += i; } else if (module_header[0] & 0x10) { -// fprintf(stderr, "mlb_entry: %s at position %lx variable length records\n", name, (long)ent->position); +// fprintf(stderr, "mlb_rsx_entry: %s at position %lx variable length records\n", name, (long)ent->position); /* Variable length records with size before them */ i = ent->length; while (i > 0) { @@ -437,7 +457,7 @@ BUFFER *mlb_entry( } } } else { -// fprintf(stderr, "mlb_entry: %s at position %lx byte stream records\n", name, (long)ent->position); +// fprintf(stderr, "mlb_rsx_entry: %s at position %lx byte stream records\n", name, (long)ent->position); for (i = 0; i < ent->length; i++) { c = fgetc(mlb->fp); /* Get macro byte */ if (c == '\r' || c == 0) /* If it's a carriage return or 0, @@ -453,7 +473,7 @@ BUFFER *mlb_entry( return buf; } -/* mlb_extract - walk thru a macro library and store its contents +/* mlb_rsx_extract - walk thru a macro library and store its contents into files in the current directory. See, I had decided not to bother writing macro library maintenance @@ -463,7 +483,7 @@ BUFFER *mlb_entry( in the file system from thence forward. */ -void mlb_extract( +void mlb_rsx_extract( MLB *mlb) { int i; diff --git a/crossassemblers/macro11/mlb.c b/crossassemblers/macro11/mlb-rt11.c similarity index 88% rename from crossassemblers/macro11/mlb.c rename to crossassemblers/macro11/mlb-rt11.c index 8ec62c3..2e10f88 100644 --- a/crossassemblers/macro11/mlb.c +++ b/crossassemblers/macro11/mlb-rt11.c @@ -2,6 +2,7 @@ /* Copyright (c) 2001, Richard Krehbiel +Copyright (c) 2017, Olaf Seibert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -44,10 +45,26 @@ DAMAGE. #include "mlb.h" -#include "macro11.h" - #include "util.h" +static MLB *mlb_rt11_open( + char *name, + int allow_object_library); +static BUFFER *mlb_rt11_entry( + MLB *mlb, + char *name); +static void mlb_rt11_close( + MLB *mlb); +static void mlb_rt11_extract( + MLB *mlb); + +struct mlb_vtbl mlb_rt11_vtbl = { + mlb_rt11_open, + mlb_rt11_entry, + mlb_rt11_extract, + mlb_rt11_close, +}; + #define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8)) /* BYTEPOS calculates the byte position within the macro libray file. @@ -84,11 +101,13 @@ static void trim( *cp = 0; } -/* mlb_open opens a file which is given to be a macro library. */ +/* mlb_rt11_open opens a file which is given to be a macro library. */ /* Returns NULL on failure. */ -MLB *mlb_open( - char *name) +static +MLB *mlb_rt11_open( + char *name, + int allow_object_library) { MLB *mlb = memcheck(malloc(sizeof(MLB))); char *buff; @@ -97,24 +116,26 @@ MLB *mlb_open( unsigned start_block; int i; + (void)allow_object_library; /* This parameter is not supported */ + mlb->vtbl = &mlb_rt11_vtbl; mlb->directory = NULL; mlb->fp = fopen(name, "rb"); if (mlb->fp == NULL) { - mlb_close(mlb); + mlb_rt11_close(mlb); return NULL; } buff = memcheck(malloc(044)); /* Size of MLB library header */ if (fread(buff, 1, 044, mlb->fp) < 044) { - mlb_close(mlb); + mlb_rt11_close(mlb); free(buff); return NULL; } if (WORD(buff) != 01001) { /* Is this really a macro library? */ - mlb_close(mlb); /* Nope. */ + mlb_rt11_close(mlb); /* Nope. */ return NULL; } @@ -132,7 +153,7 @@ MLB *mlb_open( /* Read the disk directory */ if (fread(buff, entsize, nr_entries, mlb->fp) < nr_entries) { - mlb_close(mlb); /* Sorry, read error. */ + mlb_rt11_close(mlb); /* Sorry, read error. */ free(buff); return NULL; } @@ -214,8 +235,9 @@ MLB *mlb_open( return mlb; } -/* mlb_close discards MLB and closes the file. */ -void mlb_close( +/* mlb_rt11_close discards MLB and closes the file. */ +static +void mlb_rt11_close( MLB *mlb) { if (mlb) { @@ -234,15 +256,16 @@ void mlb_close( } } -/* mlb_entry returns a BUFFER containing the specified entry from the +/* mlb_rt11_entry returns a BUFFER containing the specified entry from the macro library, or NULL if not found. */ -BUFFER *mlb_entry( +static +BUFFER *mlb_rt11_entry( MLB *mlb, char *name) { int i; - MLBENT *ent; + MLBENT *ent = NULL; BUFFER *buf; char *bp; int c; @@ -278,7 +301,7 @@ BUFFER *mlb_entry( return buf; } -/* mlb_extract - walk thru a macro library and store it's contents +/* mlb_rt11_extract - walk thru a macro library and store its contents into files in the current directory. See, I had decided not to bother writing macro library maintenance @@ -288,7 +311,8 @@ BUFFER *mlb_entry( in the file system from thence forward. */ -void mlb_extract( +static +void mlb_rt11_extract( MLB *mlb) { int i; diff --git a/crossassemblers/macro11/mlb.h b/crossassemblers/macro11/mlb.h index 4d65202..e9db913 100644 --- a/crossassemblers/macro11/mlb.h +++ b/crossassemblers/macro11/mlb.h @@ -46,13 +46,24 @@ typedef struct mlbent { int length; } MLBENT; +struct mlb_vtbl; + typedef struct mlb { + struct mlb_vtbl *vtbl; + char *name; FILE *fp; MLBENT *directory; int nentries; int is_objlib; /* is really an object library */ } MLB; +typedef struct mlb_vtbl { + MLB *(*mlb_open)(char *name, int allow_object_library); + BUFFER *(*mlb_entry)(MLB *mlb, char *name); + void (*mlb_extract)(MLB *mlb); + void (*mlb_close)(MLB *mlb); +} MLB_VTBL; + extern MLB *mlb_open( char *name, int allow_object_library); @@ -64,4 +75,7 @@ extern void mlb_close( extern void mlb_extract( MLB *mlb); +extern struct mlb_vtbl mlb_rsx_vtbl; +extern struct mlb_vtbl mlb_rt11_vtbl; + #endif /* MLB_H */ diff --git a/crossassemblers/macro11/mlb2.c b/crossassemblers/macro11/mlb2.c new file mode 100644 index 0000000..9d58953 --- /dev/null +++ b/crossassemblers/macro11/mlb2.c @@ -0,0 +1,84 @@ +/* +Copyright (c) 2017, Olaf Seibert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +o Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +o Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#include +#include +#include "util.h" +#include "mlb.h" + +MLB_VTBL *mlb_vtbls[] = { + &mlb_rsx_vtbl, + &mlb_rt11_vtbl, + NULL +}; + +MLB *mlb_open( + char *name, + int allow_object_library) +{ + MLB_VTBL *vtbl; + MLB *mlb = NULL; + int i; + + for (i = 0; (vtbl = mlb_vtbls[i]); i++) { + mlb = vtbl->mlb_open(name, allow_object_library); + if (mlb != NULL) { + mlb->name = memcheck(strdup(name)); + break; + } + } + + return mlb; +} + +BUFFER *mlb_entry( + MLB *mlb, + char *name) +{ + return mlb->vtbl->mlb_entry(mlb, name); +} + +void mlb_close( + MLB *mlb) +{ + free(mlb->name); + mlb->vtbl->mlb_close(mlb); +} + +void mlb_extract( + MLB *mlb) +{ + mlb->vtbl->mlb_extract(mlb); +} + + diff --git a/crossassemblers/macro11/obj2bin/.gitignore b/crossassemblers/macro11/obj2bin/.gitignore new file mode 100644 index 0000000..a09a578 --- /dev/null +++ b/crossassemblers/macro11/obj2bin/.gitignore @@ -0,0 +1,4 @@ +# ignore these files: +# ignore these directories: +tests/ +# the end diff --git a/crossassemblers/macro11/obj2bin/README.md b/crossassemblers/macro11/obj2bin/README.md new file mode 100644 index 0000000..e39fccd --- /dev/null +++ b/crossassemblers/macro11/obj2bin/README.md @@ -0,0 +1,162 @@ +obj2bin.pl is a PDP-11 object file translator / linker, transforming an .obj file as output from macro11 into an absolute binary load image file (.bin) or other useful formats (.hex). + +If run with no options, it prints a usage screen: + +``` +obj2bin.pl v2.1 by Don North (perl 5.03) +Usage: ./obj2bin.pl [options...] arguments + --help output manpage and exit + --debug enable debug mode + --verbose verbose status reporting + --boot M9312 boot prom .hex + --console M9312 console/diagnostic prom .hex + --binary binary program load image .bin [default] + --ascii ascii m9312 program load image .txt + --rt11 read .obj files in RT11 format + --rsx11 read .obj files in RSX11 format [default] + --bytes=N bytes per block on output hex format + --nocrc inhibit output of CRC-16 in hex format + --logfile=LOGFILE logging message file + --outfile=OUTFILE output .hex/.txt/.bin file + OBJFILE... macro11 object .obj file(s) +Aborted due to command line errors. +``` + +If run with the --help option it prints a longer manual page: + +``` +NAME + obj2bin.pl - Convert a Macro-11 program image to PROM/load format + +SYNOPSIS + obj2bin.pl [--help] [--debug] [--verbose] [--boot] [--console] [--binary] + [--ascii] [--rt11] [--rsx11] [--bytes=N] [--nocrc] [--logfile=LOGFILE] + --outfile=BINFILE OBJFILE + +DESCRIPTION + Converts a Macro-11 object files to various output formats, including + M9312 boot and console PROM, straight binary records, ASCII format for + M9312 console load commands, and loadable absolute binary program images + (.BIN) files. + + Multiple .psect/.asect ops are supported, as well as all local + (non-global) relocation directory entries. + + Supports either RT-11 or RSX-11 format object files. + +OPTIONS + The following options are available: + + --help + Output this manpage and exit the program. + + --debug + Enable debug mode; print input file records as parsed. + + --verbose + Verbose status; output status messages during processing. + + --boot + Generate a hex PROM file image suitable for programming into an M9312 + boot prom (512x4 geometry, only low half used). + + --console + Generate a hex PROM file image suitable for programming into an M9312 + console/diagnostic prom (1024x4 geometry). + + --ascii + Generate a a sequence of 'L addr' / 'D data' commands for downloading + a program via a terminal emulator thru the M9312 user command + interface. Suitable only for really small test programs. + + --binary + Generate binary format load records of the program image (paper tape + format) for loading into SIMH or compatible simulators. These files + can also be copied onto XXDP filesystems to generate runnable program + images (used to write custom diaqnostics). + + Binary format is the default if no other option is specified. If more + than one option is specified the last one takes effect. + + --rt11 + Read input object files in RT-11 format. + + --rsx11 + Read input object files in RSX-11 format. + + RSX-11 object file format is the default if no other option is + specified. If more than one option is specified the last one takes + effect. + + --bytes=N + For hex format output files, output N bytes per line (default 16). + + --nocrc + For hex format output files, don't automatically stuff the computed + CRC-16 as the last word in the ROM. + + --logfile=FILENAME + Generate debug output into this file. + + --outfile=FILENAME + Output binary file in format selected by user option. + + OBJFILE... + Input object file(s) in .obj format. + +ERRORS + The following diagnostic error messages can be produced on STDERR. The + meaning should be fairly self explanatory. + + "Aborted due to command line errors" -- bad option or missing file(s) + + "Can't open input file '$file'" -- bad filename or unreadable file + + "Error: Improper object file format (1)" -- valid RT-11 record must start + with 0x01 + + "Error: Improper object file format (2)" -- second RT-11 byte must be 0x00 + + "Error: Improper object file format (3)" -- third byte is low byte of + record length + + "Error: Improper object file format (4)" -- fourth byte is high byte of + record length + + "Error: Improper object file format (5)" -- bytes five thru end-1 are data + bytes + + "Error: Improper object file format (6)" -- last RT-11 byte is checksum + + "Error: Bad checksum exp=0x%02X rcv=0x%02X" -- compare rcv'ed checksum vs + exp'ed checksum + +EXAMPLES + Some examples of common usage: + + obj2bin.pl --help + + obj2bin.pl --verbose --boot --out 23-751A9.hex 23-751A9.obj + + obj2bin.pl --verbose --binary --rt11 --out memtest.bin memtest.obj + + obj2bin.pl --verbose --binary --rsx11 --out prftst.bin prftst.obj mac/printf.obj + +AUTHOR + Don North - donorth + +HISTORY + Modification history: + + 2005-05-05 v1.0 donorth - Initial version. + 2016-01-15 v1.1 donorth - Added RLD(IR) processing, moved sub's to end. + 2016-01-18 v1.2 donorth - Added GSD processing, improved debug output. + 2016-01-20 v1.3 donorth - Initial support for linking multiple PSECTs. + 2016-01-22 v1.4 donorth - Added objfile/outfile/logfile switches vs stdio. + 2016-01-28 v1.5 donorth - Added RLD processing, especially complex. + 2017-04-01 v1.9 donorth - Renamed from obj2hex.pl to obj2bin.pl + 2017-05-04 v1.95 donorth - Updated capability to read multiple input .obj files. + 2020-03-06 v2.0 donorth - Updated help documentation and README.md file. + 2020-03-10 v2.1 donorth - Broke down and added RSX-11 input format option. + +``` diff --git a/crossassemblers/macro11/obj2bin/obj2bin.pl b/crossassemblers/macro11/obj2bin/obj2bin.pl new file mode 100644 index 0000000..ca395ba --- /dev/null +++ b/crossassemblers/macro11/obj2bin/obj2bin.pl @@ -0,0 +1,1271 @@ +#!/usr/bin/perl -w +#!/usr/local/bin/perl -w + +# Copyright (c) 2005-2016 Don North +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# o Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# o Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# o Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +require 5.008; + +=head1 NAME + +obj2bin.pl - Convert a Macro-11 program image to PROM/load format + +=head1 SYNOPSIS + +obj2bin.pl +S<[--help]> +S<[--debug]> +S<[--verbose]> +S<[--boot]> +S<[--console]> +S<[--binary]> +S<[--ascii]> +S<[--rt11]> +S<[--rsx11]> +S<[--bytes=N]> +S<[--nocrc]> +S<[--logfile=LOGFILE]> +S<--outfile=BINFILE> +S + +=head1 DESCRIPTION + +Converts a Macro-11 object files to various output formats, +including M9312 boot and console PROM, straight binary records, +ASCII format for M9312 console load commands, and loadable absolute +binary program images (.BIN) files. + +Multiple .psect/.asect ops are supported, as well as all local +(non-global) relocation directory entries. + +Supports either RT-11 or RSX-11 format object files. + +=head1 OPTIONS + +The following options are available: + +=over + +=item B<--help> + +Output this manpage and exit the program. + +=item B<--debug> + +Enable debug mode; print input file records as parsed. + +=item B<--verbose> + +Verbose status; output status messages during processing. + +=item B<--boot> + +Generate a hex PROM file image suitable for programming into +an M9312 boot prom (512x4 geometry, only low half used). + +=item B<--console> + +Generate a hex PROM file image suitable for programming into +an M9312 console/diagnostic prom (1024x4 geometry). + +=item B<--ascii> + +Generate a a sequence of 'L addr' / 'D data' commands for downloading +a program via a terminal emulator thru the M9312 user command interface. +Suitable only for really small test programs. + +=item B<--binary> + +Generate binary format load records of the program image (paper +tape format) for loading into SIMH or compatible simulators. +These files can also be copied onto XXDP filesystems to generate +runnable program images (used to write custom diaqnostics). + +Binary format is the default if no other option is specified. +If more than one option is specified the last one takes effect. + +=item B<--rt11> + +Read input object files in RT-11 format. + +=item B<--rsx11> + +Read input object files in RSX-11 format. + +RSX-11 object file format is the default if no other option is specified. +If more than one option is specified the last one takes effect. + +=item B<--bytes=N> + +For hex format output files, output N bytes per line (default 16). + +=item B<--nocrc> + +For hex format output files, don't automatically stuff the computed +CRC-16 as the last word in the ROM. + +=item B<--logfile=FILENAME> + +Generate debug output into this file. + +=item B<--outfile=FILENAME> + +Output binary file in format selected by user option. + +=item B + +Input object file(s) in .obj format. + +=back + +=head1 ERRORS + +The following diagnostic error messages can be produced on STDERR. +The meaning should be fairly self explanatory. + +C -- bad option or missing file(s) + +C -- bad filename or unreadable file + +C -- valid RT-11 record must start with 0x01 + +C -- second RT-11 byte must be 0x00 + +C -- third byte is low byte of record length + +C -- fourth byte is high byte of record length + +C -- bytes five thru end-1 are data bytes + +C -- last RT-11 byte is checksum + +C -- compare rcv'ed checksum vs exp'ed checksum + +=head1 EXAMPLES + +Some examples of common usage: + + obj2bin.pl --help + + obj2bin.pl --verbose --boot --out 23-751A9.hex 23-751A9.obj + + obj2bin.pl --verbose --binary --rt11 --out memtest.bin memtest.obj + + obj2bin.pl --verbose --binary --rsx11 --out prftst.bin prftst.obj mac/printf.obj + +=head1 AUTHOR + +Don North - donorth + +=head1 HISTORY + +Modification history: + + 2005-05-05 v1.0 donorth - Initial version. + 2016-01-15 v1.1 donorth - Added RLD(IR) processing, moved sub's to end. + 2016-01-18 v1.2 donorth - Added GSD processing, improved debug output. + 2016-01-20 v1.3 donorth - Initial support for linking multiple PSECTs. + 2016-01-22 v1.4 donorth - Added objfile/outfile/logfile switches vs stdio. + 2016-01-28 v1.5 donorth - Added RLD processing, especially complex. + 2017-04-01 v1.9 donorth - Renamed from obj2hex.pl to obj2bin.pl + 2017-05-04 v1.95 donorth - Updated capability to read multiple input .obj files. + 2020-03-06 v2.0 donorth - Updated help documentation and README.md file. + 2020-03-10 v2.1 donorth - Broke down and added RSX-11 input format option. + +=cut + +# options +use strict; + +# external standard modules +use Getopt::Long; +use Pod::Text; +use FindBin; +use FileHandle; + +# external local modules search path +BEGIN { unshift(@INC, $FindBin::Bin); + unshift(@INC, $ENV{PERL5LIB}) if defined($ENV{PERL5LIB}); # cygwin bugfix + unshift(@INC, '.'); } + +# external local modules + +# generic defaults +my $VERSION = 'v2.1'; # version of code +my $HELP = 0; # set to 1 for man page output +my $DEBUG = 0; # set to 1 for debug messages +my $VERBOSE = 0; # set to 1 for verbose messages + +# specific defaults +my $crctype = 'CRC-16'; # type of crc calc to do +my $memsize; # number of instruction bytes allowed +my $memfill; # memory fill pattern +my %excaddr; # words to be skipped in rom crc calc +my $rombase; # base address of rom image +my $romsize; # number of rom addresses +my $romfill; # rom fill pattern +my $romtype = 'BINA'; # default rom type is BINARY +my $objtype = 'RSX11'; # default object file format is RSX11 +my $bytesper = -1; # bytes per block in output file +my $nocrc = 0; # output CRC16 as last word unless set +my $outfile = undef; # output filename +my $logfile = undef; # log filename + +# process command line arguments +my $NOERROR = GetOptions( "help" => \$HELP, + "debug" => \$DEBUG, + "verbose" => \$VERBOSE, + "boot" => sub { $romtype = 'BOOT'; }, + "console" => sub { $romtype = 'DIAG'; }, + "binary" => sub { $romtype = 'BINA'; }, + "ascii" => sub { $romtype = 'ASC9'; }, + "rt11" => sub { $objtype = 'RT11'; }, + "rsx11" => sub { $objtype = 'RSX11'; }, + "bytes=i" => \$bytesper, + "nocrc" => \$nocrc, + "outfile=s" => \$outfile, + "logfile=s" => \$logfile, + ); + +# init +$VERBOSE = 1 if $DEBUG; # debug implies verbose messages + +# output the documentation +if ($HELP) { + # output a man page if we can + if (ref(Pod::Text->can('new')) eq 'CODE') { + # try the new way if appears to exist + my $parser = Pod::Text->new(sentence=>0, width=>78); + printf STDOUT "\n"; $parser->parse_from_file($0); + } else { + # else must use the old way + printf STDOUT "\n"; Pod::Text::pod2text(-78, $0); + }; + exit(1); +} + +# check for correct arguments present, print usage if errors +unless ($NOERROR + && scalar(@ARGV) >= 1 + && defined($outfile) + && $romtype ne 'NONE' + ) { + printf STDERR "obj2bin.pl %s by Don North (perl %g)\n", $VERSION, $]; + print STDERR "Usage: $0 [options...] arguments\n"; + print STDERR <<"EOF"; + --help output manpage and exit + --debug enable debug mode + --verbose verbose status reporting + --boot M9312 boot prom .hex + --console M9312 console/diagnostic prom .hex + --binary binary program load image .bin [default] + --ascii ascii m9312 program load image .txt + --rt11 read .obj files in RT11 format + --rsx11 read .obj files in RSX11 format [default] + --bytes=N bytes per block on output hex format + --nocrc inhibit output of CRC-16 in hex format + --logfile=LOGFILE logging message file + --outfile=OUTFILE output .hex/.txt/.bin file + OBJFILE... macro11 object .obj file(s) +EOF + # exit if errors... + die "Aborted due to command line errors.\n"; +} + +# setup log file as a file, defaults to STDERR if not supplied +my $LOG = defined($logfile) ? FileHandle->new("> ".$logfile) : FileHandle->new_from_fd(fileno(STDERR),"w"); + +#---------------------------------------------------------------------------------------------------- + +# subroutine prototypes + +sub trim ($); +sub chksum (@); +sub rad2asc (@); +sub crc (%); +sub sym2psect ($$); +sub read_rec ($); +sub get_global ($); +sub parse_rec ($$$); + +#---------------------------------------------------------------------------------------------------- + +# fill in the parameters of the device + +if ($romtype eq 'BOOT') { + + # M9312 512x4 boot prom + %excaddr = ( 024=>1, 025=>1 ); # bytes to be skipped in rom crc calc + $memsize = 128; # number of instruction bytes allowed + $memfill = 0x00; # memory fill pattern + $romsize = 512; # number of rom addresses (must be a power of two) + $romfill = 0x00; # rom fill pattern + $rombase = 0173000; # base address of rom + +} elsif ($romtype eq 'DIAG') { + + # M9312 1024x4 diagnostic/console prom + %excaddr = ( ); # bytes to be skipped in rom crc calc + $memsize = 512; # number of instruction bytes allowed + $memfill = 0x00; # memory fill pattern + $romsize = 1024; # number of rom addresses (must be a power of two) + $romfill = 0x00; # rom fill pattern + $rombase = 0165000; # base address of rom + +} elsif ($romtype eq 'BINA' || $romtype eq 'ASC9') { + + # program load image ... 56KB address space maximum + %excaddr = ( ); # bytes to be skipped in rom crc calc + $memsize = 7*8192; # number of instruction bytes allowed + $memfill = 0x00; # memory fill pattern + $romsize = 8*8192; # number of rom addresses (must be a power of two) + $romfill = 0x00; # image fill pattern + $rombase = 0; # base address of binary image + +} else { + + # unknown ROM type code + die "ROM type '$romtype' is not supported!\n"; + +} + +if ($VERBOSE) { + printf $LOG "ROM type is '%s'\n", $romtype; + printf $LOG "ROM space is %d. bytes\n", $memsize; + printf $LOG "ROM length is %d. addresses\n", $romsize; + printf $LOG "ROM base address is 0%06o\n", $rombase; +} + +#---------------------------------------------------------------------------------------------------- + +# read/process the input object file records + +# real pdp11 memory data words in boot prom +my @mem = ((0) x $memsize); + +# min/max address limits in object file +my ($adrmin,$adrmax) = ('',''); + +# state variables in processing object records +my $rommsk = ($romsize-1)>>1; # address bit mask +my $adrmsk = 0xFFFF; # 16b addr mask +my $datmsk = 0xFFFF; # 16b data mask +my $memmsk = 0xFF; # 8b memory data mask + +# databases +my %gblsym = (); +my %psect = (); +my @psect = (); +my %program = (); +my $psectname = sprintf("%02d:%s",1,'. ABS.'); +my $psectaddr = 0; +my $psectnumb = -1; +my $textaddr = 0; + +# program defaults +$program{START}{ADDRESS} = 1; +$program{START}{VALUE} = 1; +$program{START}{PSECT} = $psectname; + +# two passes, first is headers, second is data records +foreach my $pass (1..2) { + foreach my $numb (0..$#ARGV) { + my $objfile = $ARGV[$numb]; + my $OBJ = FileHandle->new("< ".$objfile); + die "Error: can't open input object file '$objfile'\n" unless defined $OBJ; + printf $LOG "\n\nPROCESS PASS %d FILE %d '%s'\n\n", $pass, $numb+1, $objfile if $DEBUG; + while (my @rec = &read_rec($OBJ)) { &parse_rec($numb+1, $pass, \@rec); } + $OBJ->close; + } +} + +#---------------------------------------------------------------------------------------------------- + +# compute CRC if required, copy memory image to output buffer + +my @buf = ($romfill) x $romsize; # physical PROM data bytes, filled background pattern + +# only compute CRC on M9312 ROMs +if ($romtype eq 'BOOT' || $romtype eq 'DIAG') { + + # compute CRC-16 of the prom contents (except exception words) and store at last location + my $crctab = &crc(-name=>$crctype, -new=>1); + my $crc = &crc(-name=>$crctype, -init=>1); + for (my $adr = 0; $adr < $memsize-2; $adr += 1) { + next if exists($excaddr{$adr}); # skip these addresses + $mem[$rombase+$adr] = $memfill unless defined($mem[$rombase+$adr]); + $crc = &crc(-name=>$crctype, -table=>$crctab, -crc=>$crc, -byte=>$mem[$rombase+$adr]); + } + $crc = &crc(-name=>$crctype, -crc=>$crc, -last=>1); + unless ($nocrc) { + # output computed CRC-16 as last word in the ROM file + $mem[$rombase+$memsize-2] = ($crc>>0)&0xFF; + $mem[$rombase+$memsize-1] = ($crc>>8)&0xFF; + } + printf $LOG "ROM %s is %06o (0x%04X)\n", $crctype, ($crc) x 2 if $VERBOSE; + + # process data words to actual PROM byte data + # put 4bit nibble in low 4b of each 8b data byte, zero the upper 4b + # only copy the above instruction portion over + for (my $idx = 0; $idx < $memsize<<1; $idx += 4) { + my $dat = ($mem[$rombase+($idx>>1)+1]<<8) | ($mem[$rombase+($idx>>1)+0]<<0); + $buf[$idx+0] = ($dat&0xE)|(($dat>>8)&0x1); # bits 3 2 1 8 + $buf[$idx+1] = ($dat>>4)&0xF; # bits 7 6 5 4 + $buf[$idx+2] = ((($dat>>8)&0xE)|($dat&0x1))^0xC; # bits ~11 ~10 9 0 + $buf[$idx+3] = (($dat>>12)&0xF)^0x1; # bits 15 14 13 ~12 + } + +} elsif ($romtype eq 'BINA' || $romtype eq 'ASC9') { + + # only copy the above instruction portion over + for (my $adr = 0; $adr < $memsize; $adr += 1) { + $mem[$rombase+$adr] = $memfill unless defined($mem[$rombase+$adr]); + $buf[$adr] = $mem[$rombase+$adr]; + } + +} + +if ($VERBOSE) { + + # print checksum of entire device + my $chksum = 0; map($chksum += $_, @buf); + printf $LOG "ROM checksum is %06o (0x%04X)\n", $chksum, $chksum; + +} + +#---------------------------------------------------------------------------------------------------- + +# output the linked/processed binary file image in the desired format + +my $OUT = FileHandle->new("> ".$outfile); +die "Error: can't open output file '$outfile'\n" unless defined $OUT; + +if ($romtype eq 'BOOT' || $romtype eq 'DIAG') { + + # output the entire PROM buffer as an intel hex file + + $bytesper = 16 if $bytesper <= 0; + + for (my $idx = 0; $idx < $romsize; $idx += $bytesper) { + my $cnt = $idx+$bytesper <= $romsize ? $bytesper : $romsize-$idx; # N bytes or whatever is left + my @dat = @buf[$idx..($idx+$cnt-1)]; # get the data + my $dat = join('', map(sprintf("%02X",$_),@dat)); # map to ascii text + printf $OUT ":%02X%04X%02X%s%02X\n", $cnt, $idx, 0x00, $dat, &chksum($cnt, $idx>>0, $idx>>8, 0x00, @dat); + } + + printf $OUT ":%02X%04X%02X%s%02X\n", 0x00, 0x0000, 0x01, '', &chksum(0x0, 0x0000>>0, 0x0000>>8, 0x01); + +} elsif ($romtype eq 'BINA') { + + # Loader format consists of blocks, optionally preceded, separated, and + # followed by zeroes. Each block consists of: + # + # 001 --- + # 000 | + # lo(length) | + # hi(length) | + # lo(address) > 'length' bytes + # hi(address) | + # databyte1 | + # : | + # databyteN --- + # checksum + # + # If the byte length is exactly six, the block is the last on the tape, and + # there is no checksum. If the origin is not 000001, then the origin is + # the PC at which to start the program. + + $bytesper = 128 if $bytesper <= 0; + + my $start = $program{START}{ADDRESS}; + + sub m ($) { $_[0] & 0xFF; } + + # output the entire PROM buffer as a binary loader file + for (my $idx = $adrmin; $idx < $adrmax+1; $idx += $bytesper) { + my $cnt = $idx+$bytesper <= $adrmax+1 ? $bytesper : $adrmax+1-$idx; # N bytes or whatever is left + my @dat = @buf[$idx..($idx+$cnt-1)]; # get the data + my $len = $cnt+6; + my @rec = (0x01, 0x00, &m($len>>0), &m($len>>8), &m($idx>>0), &m($idx>>8), @dat); + print $OUT pack("C*", @rec, &chksum(@rec)); + } + my @end = (0x01, 0x00, 0x06, 0x00, &m($start>>0), &m($start>>8)); + print $OUT pack("C*", @end, &chksum(@end)); + +} elsif ($romtype eq 'ASC9') { + + # ascii interface to M9312 console emulator + + sub n ($) { $_[0] & 0xFF; } + + # start program load here + printf $OUT "L %o\r\n", $adrmin; + + # output the PROM buffer as an ascii load file + for (my $idx = $adrmin; $idx < $adrmax+1; $idx += 2) { + printf $OUT "D %06o\r\n", (&n($buf[$idx+1])<<8) | &n($buf[$idx+0]); + } + + # start program exec here + printf $OUT "L %o\r\nS\r\n", $adrmin; + +} + +# all done +$OUT->close; + +#---------------------------------------------------------------------------------------------------- + +# really done +$LOG->close; +exit; + +#---------------------------------------------------------------------------------------------------- +#---------------------------------------------------------------------------------------------------- + +# trim leading/trailing spaces on a string + +sub trim ($) { + + my ($str) = @_; + + $str =~ s/\s+$//; + $str =~ s/^\s+//; + + return $str; +} + +#---------------------------------------------------------------------------------------------------- + +# compute checksum (twos complement of the sum of bytes) + +sub chksum (@) { + + my $sum = 0; + + map($sum += $_, @_); + + return (-$sum) & 0xFF; +} + +#---------------------------------------------------------------------------------------------------- + +# RAD50 to ASCII decode + +sub rad2asc (@) { + + my @str = split(//, ' ABCDEFGHIJKLMNOPQRSTUVWXYZ$.%0123456789'); # RAD50 character subset + + my $ascii = ""; + foreach my $rad50 (@_) { + $ascii .= $str[int($rad50/1600)%40] . $str[int($rad50/40)%40] . $str[$rad50%40]; + } + + return $ascii; +} + +#---------------------------------------------------------------------------------------------------- + +# symbol to psect name converter + +sub sym2psect ($$) { + + return sprintf("%02d:%-6s", @_); +} + +#---------------------------------------------------------------------------------------------------- + +# crc computation routine + +sub crc (%) { + + # pass all args by name + my %args = @_; + + # all the crcs we know how to compute + my %crcdat = ( 'CRC-16' => [ 0xA001, 2, 0x0000, 0x0000 ], + 'CRC-32' => [ 0xEDB88320, 4, 0xFFFFFFFF, 0xFFFFFFFF ] ); + + # run next byte thru crc computation, return updated crc + return $args{-table}[($args{-crc}^$args{-byte}) & 0xFF]^($args{-crc}>>8) if exists($args{-byte}); + + # return initial crc value + return $crcdat{$args{-name}}->[2] if exists($args{-init}); + + # return final crc value xored with xorout + return $args{-crc} ^ $crcdat{$args{-name}}->[3] if exists($args{-last}); + + # compute the crc lookup table, return a pointer to it + if (exists($args{-new})) { + my $crctab = []; + my $poly = $crcdat{$args{-name}}->[0]; + foreach my $byte (0..255) { + my $data = $byte; + foreach (1..8) { $data = ($data>>1) ^ ($data&1 ? $poly : 0); } + $$crctab[$byte] = $data; + } + return $crctab; + } +} + +#---------------------------------------------------------------------------------------------------- + +# read a record from the object file + +sub read_rec ($) { + + my ($fh) = @_; + + my ($buf, $cnt, $len, $err) = (0,0,0,0); + my @pre = (); + my @dat = (); + my @suf = (); + + if ($objtype eq 'RT11') { + + # RT-11 object file format consists of blocks, optionally preceded, separated, and + # followed by zeroes. Each block consists of: + # + # 001 --- + # 000 | + # lo(length) | + # hi(length) > 'length' bytes + # databyte1 | + # : | + # databyteN --- + # checksum + # + + # skip over strings of 0x00; exit OK if hit EOF + do { return () unless $cnt = read($fh, $buf, 1); } while (ord($buf) == 0); + + # valid record starts with (1) + $err = 1 unless $cnt == 1 && ord($buf) == 1; + push(@pre, ord($buf)); + + # second byte must be (0) + $cnt = read($fh, $buf, 1); + $err = 2 unless $cnt == 1 && ord($buf) == 0; + push(@pre, ord($buf)); + + # third byte is low byte of record length + $cnt = read($fh, $buf, 1); + $err = 3 unless $cnt == 1; + $len = ord($buf); + push(@pre, ord($buf)); + + # fourth byte is high byte of record length + $cnt = read($fh, $buf, 1); + $err = 4 unless $cnt == 1; + $len += ord($buf)<<8; + push(@pre, ord($buf)); + + # bytes five thru end-1 are data bytes + $cnt = read($fh, $buf, $len-4); + $err = 5 unless $cnt == $len-4 && $len >= 4; + @dat = unpack("C*", $buf); + + # last byte is checksum + $cnt = read($fh, $buf, 1); + $err = 6 unless $cnt == 1; + my $rcv = ord($buf); + push(@suf, ord($buf)); + + # compare rcv'ed checksum vs exp'ed checksum + my $exp = &chksum(0x01, $len>>0, $len>>8, @dat); + warn sprintf("Warning: Bad checksum exp=0x%02X rcv=0x%02X", $exp, $rcv) unless $exp == $rcv; + + } elsif ($objtype eq 'RSX11') { + + # RSX-11 object file format consists of blocks of data in the following format. + # Each block consists of: + # + # lo(length) + # hi(length) + # databyte1 --- + # : | + # : > 'length' bytes + # : | + # databyteN --- + # zeroFill present if length is ODD; else not present + # + + # first byte is low byte of record length + $cnt = read($fh, $buf, 1); + # but exit OK if hit EOF + return () if $cnt == 0; + $err = 10 unless $cnt == 1; + $len = ord($buf); + push(@pre, ord($buf)); + + # second byte is high byte of record length + $cnt = read($fh, $buf, 1); + $err = 11 unless $cnt == 1; + $len += ord($buf)<<8; + push(@pre, ord($buf)); + + # bytes three thru end are data bytes + $cnt = read($fh, $buf, $len); + $err = 12 unless $cnt == $len && $len >= 0; + @dat = unpack("C*", $buf); + + # optional pad byte if length is odd + $cnt = ($len & 1) ? read($fh, $buf, 1) : 2; + $err = 13 unless $cnt == 1 && ord($buf) == 0 || $cnt == 2; + + } + + # output the record if debugging + if ($DEBUG >= 2) { + my $fmt = "%03o"; + my $n = 16; + my $pre = sprintf("RECORD: [%s] ",join(" ",map(sprintf($fmt,$_),@pre))); + printf $LOG "\n\n%s", $pre; + my $k = length($pre); + my @tmp = @dat; + while (@tmp > $n) { + printf $LOG "%s\n%*s", join(" ",map(sprintf($fmt,$_),splice(@tmp,0,$n))), $k, ''; + } + printf $LOG "%s", join(" ",map(sprintf($fmt,$_),@tmp)) if @tmp; + printf $LOG " [%s]\n\n", join(" ",map(sprintf($fmt,$_),@suf)); + } + + # check we have a well formatted record + warn sprintf("Warning: invalid %s object file record format (%d)", $objtype, $err) if $err; + + # all is well, return the record + return @dat; +} + +#---------------------------------------------------------------------------------------------------- + +# get a global symbol target value + +sub get_global ($) { + + my ($sym) = @_; + + # return target value if exists + return $gblsym{$sym}{DEF}{ADDRESS} if exists $gblsym{$sym}{DEF}{ADDRESS}; + + # issue a warning for multiple definition with a different address + warn sprintf("Warning: global symbol undefined: symbol=%s, assuming value of 000000\n", $sym); + + # and return nil + return 0; +} + +#---------------------------------------------------------------------------------------------------- + +# parse an input object file record, update data structures + +sub parse_rec ($$$) { + + my ($file,$pass,$rec) = (@_); + + # type is first byte of record + my $key = $rec->[0]; + + if ($key == 001 && $pass == 1) { # GSD + + # iterate over GSD subrecords + for (my $i = 2; $i < scalar(@$rec); ) { + # GSD records are fixed 8B length all in the same format + my $sym = &rad2asc(($rec->[$i+1]<<8)|($rec->[$i+0]<<0),($rec->[$i+3]<<8)|($rec->[$i+2]<<0)); + my $flg = $rec->[$i+4]; + my $ent = $rec->[$i+5]; + my $val = ($rec->[$i+7]<<8)|($rec->[$i+6]<<0); + my @ent = ('MODULE','CSECT','INTSYM','XFRADR','GBLSYM','PSECT','IDENT','VSECT'); + my $def = undef; + if ($ent == 3) { + # XFRADR + $program{START}{PSECT} = &sym2psect($file,$sym); + $program{START}{VALUE} = $val; + if ($DEBUG) { + printf $LOG "..GSD: type='%-6s'(%03o) name='%s' value=%06o\n", + $ent[$ent], $ent, $program{START}{PSECT}, $program{START}{VALUE}; + } + } elsif ($ent == 4) { + # GBLSYM flags + my $adr = $val + $psect{$psectname}{START}; + $def = $flg&(1<<3) ? "DEF" : "REF"; + if ($def eq "DEF" && exists $gblsym{$sym}{$def} && $adr != $gblsym{$sym}{$def}{ADDRESS}) { + # issue a warning for multiple definition with a different address + warn sprintf("Warning: global symbol redefinition: symbol=%s (address/psect) old=%06o/%s new=%06o/%s -- IGNORING\n", + &trim($sym), $gblsym{$sym}{$def}{ADDRESS}, &trim($gblsym{$sym}{$def}{PSECT}), $adr, &trim($psectname)); + } else { + # define first time only ... ignore any redefinition attempt + $gblsym{$sym}{$def}{FLG}{$flg&(1<<0) ? "WEA" : "STR"}++; + $gblsym{$sym}{$def}{FLG}{$flg&(1<<3) ? "DEF" : "REF"}++; + $gblsym{$sym}{$def}{FLG}{$flg&(1<<5) ? "REL" : "ABS"}++; + $gblsym{$sym}{$def}{PSECT} = $psectname; + $gblsym{$sym}{$def}{VALUE} = $val; + $gblsym{$sym}{$def}{ADDRESS} = $adr; + } + if ($DEBUG) { + printf $LOG "..GSD: type='%-6s'(%03o) name='%s' value=%06o", $ent[$ent], $ent, $sym, $val; + printf $LOG " psect='%s' value=%06o", $gblsym{$sym}{$def}{PSECT}, $gblsym{$sym}{$def}{VALUE}; + printf $LOG " flags=%s\n", join(",", sort(keys(%{$gblsym{$sym}{$def}{FLG}}))); + } + } elsif ($ent == 5) { + # PSECT flags + my $nam = &sym2psect($file,$sym); + $psect[++$psectnumb] = $nam; + $psect{$nam}{FILE} = $file; + $psect{$nam}{NUMBER} = $psectnumb; + $psect{$nam}{FLG}{$flg&(1<<0) ? "GBL" : $flg&(1<<6) ? "GBL" : "LCL"}++; + $psect{$nam}{FLG}{$flg&(1<<2) ? "OVR" : "CON"}++; + $psect{$nam}{FLG}{$flg&(1<<4) ? "R/O" : "R/W"}++; + $psect{$nam}{FLG}{$flg&(1<<5) ? "REL" : "ABS"}++; + $psect{$nam}{FLG}{$flg&(1<<7) ? "D" : "I/D"}++; + $psectname = $nam; + if ($psect{$nam}{FLG}{ABS}) { + # absolute + if ($psect{$nam}{FLG}{CON}) { + # concatenated + warn sprintf("Warning: psect ABS,CON is not supported, psect='%s'\n", $psectname); + } elsif ($psect{$nam}{FLG}{OVR}) { + # overlaid + $psect{$nam}{LENGTH} = $val; + $psect{$nam}{START} = 0; + } + } elsif ($psect{$nam}{FLG}{REL}) { + # relative + if ($psect{$nam}{FLG}{CON}) { + # concatenated + $psect{$nam}{LENGTH} = $val; + $psect{$nam}{START} = $psectaddr & 1 ? ++$psectaddr : $psectaddr; + $psectaddr += $val; + } elsif ($psect{$nam}{FLG}{OVR}) { + # overlaid + warn sprintf("Warning: psect REL,OVR is not supported, psect='%s'\n", $psectname); + } + } + if ($DEBUG) { + printf $LOG "..GSD: type='%-6s'(%03o) name='%s' value=%06o", $ent[$ent], $ent, $nam, $val; + printf $LOG " length=%06o start=%06o", $psect{$nam}{LENGTH}, $psect{$nam}{START}; + printf $LOG " flags=%s\n", join(",", sort(keys(%{$psect{$nam}{FLG}}))); + } + } + $i += 8; + } + + } elsif ($key == 002 && $pass == 1) { # ENDGSD + + # just say we saw it + printf $LOG "..ENDGSD\n\n" if $DEBUG; + + $program{END}{ADDRESS} = 0; + foreach my $nam (sort({$psect{$a}{START} == $psect{$b}{START} ? $psect{$a}{NUMBER} <=> $psect{$b}{NUMBER} : $psect{$a}{START} <=> $psect{$b}{START}} keys(%psect))) { + my $start = $psect{$nam}{START}; + my $length = $psect{$nam}{LENGTH}; + my $end = $length ? $start + $length - 1 : $start; + $program{END}{ADDRESS} = $end if $end > $program{END}{ADDRESS}; + printf $LOG "....PSECT[%02d](%s) START=%06o END=%06o LENGTH=%06o\n", + $psect{$nam}{NUMBER}, $nam, $start, $end, $length if $length && $DEBUG; + } + + printf $LOG "\n" if $DEBUG; + foreach my $nam (sort(keys(%gblsym))) { + if (exists $gblsym{$nam}{DEF}) { + printf $LOG "....GBLSYM(%s) PSECT='%s' VALUE=%06o : ADDRESS=%06o\n", + $nam, $gblsym{$nam}{DEF}{PSECT}, $gblsym{$nam}{DEF}{VALUE}, $gblsym{$nam}{DEF}{ADDRESS} if $DEBUG; + } + } + + if ($program{START}{ADDRESS} == 1) { + $program{START}{ADDRESS} = $program{START}{VALUE} + $psect{$program{START}{PSECT}}{START}; + } + printf $LOG "\n....PROG(ADDRESS) START=%06o END=%06o\n", + $program{START}{ADDRESS}, $program{END}{ADDRESS} if $DEBUG; + + } elsif ($key == 003 && $pass == 2) { # TXT + + # process text record + my $off = ($rec->[3]<<8)|($rec->[2]<<0); + my $len = scalar(@$rec)-4; + my $base = $psect{$psectname}{START}; + my $adr = ($base + $off) & $adrmsk; + foreach my $i (1..$len) { $mem[$adr+$i-1] = $rec->[4+$i-1]; } + if ($DEBUG) { + printf $LOG "..TXT OFFSET=%06o LENGTH=%o BASE=%06o PSECTNAME='%s'\n", $off, $len, $base, $psectname; + for (my $i = 0; $i < $len; $i += 2) { + printf $LOG " %06o: ", ($adr+$i)&~1 if $i%8 == 0; + printf $LOG " %03o...", $mem[$adr+$i++] if ($adr+$i)&1; + printf $LOG " %06o", ($mem[$adr+$i+1]<<8)|($mem[$adr+$i+0]<<0) if $i < $len-1; + printf $LOG " ...%03o", $mem[$adr+$i] if $i == $len-1; + printf $LOG "\n" if $i%8 >= 6 && $i < $len-2; + } + printf $LOG "\n"; + } + $adrmin = $adr if $adrmin eq '' || $adr < $adrmin; + $adrmax = $adr+$len-1 if $adrmax eq '' || $adr+$len-1 > $adrmax; + $textaddr = $adr; + + } elsif ($key == 004 && $pass == 2) { # RLD + + # iterate over RLD subrecords + for (my $i = 2; $i < scalar(@$rec); ) { + # first byte is entry type and flags + my $ent = $rec->[$i+0] & 0x7F; # entry type + my $flg = $rec->[$i+0] & 0x80; # modification flag (0=word, 1=byte) + # process an entry + if ($ent == 001) { + # internal relocation ... OK + my $dis = $rec->[$i+1]; + my $con = ($rec->[$i+3]<<8)|($rec->[$i+2]<<0); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ($psect{$psectname}{START} + $con); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(IR): adr=%06o val=%06o ; dis=%06o con=%06o\n", + $adr, $val, $dis, $con if $DEBUG; + $i += 4; + } elsif ($ent == 003) { + # internal displaced relocation ... OK + my $dis = $rec->[$i+1]; + my $con = ($rec->[$i+3]<<8)|($rec->[$i+2]<<0); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ($con - ($adr+2)); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(IDR): adr=%06o val=%06o ; dis=%06o con=%06o\n", + $adr, $val, $dis, $con if $DEBUG; + $i += 4; + } elsif ($ent == 012) { + # psect relocation ... OK + my $dis = $rec->[$i+1]; + my $nam = &sym2psect($file,&rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0))); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ($psect{$nam}{START}); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(PR): adr=%06o val=%06o ; dis=%06o nam='%s'\n", + $adr, $val, $dis, $nam if $DEBUG; + $i += 6; + } elsif ($ent == 014) { + # psect displaced relocation ... OK + my $dis = $rec->[$i+1]; + my $nam = &sym2psect($file,&rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0))); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ($psect{$nam}{START} - ($adr+2)); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(PDR): adr=%06o val=%06o ; dis=%06o nam='%s'\n", + $adr, $val, $dis, $nam if $DEBUG; + $i += 6; + } elsif ($ent == 015) { + # psect additive relocation ... OK + my $dis = $rec->[$i+1]; + my $nam = &sym2psect($file,&rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0))); + my $con = ($rec->[$i+7]<<8)|($rec->[$i+6]<<0); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ($psect{$nam}{START} + $con); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(PAR): adr=%06o val=%06o ; dis=%06o con=%06o nam='%s'\n", + $adr, $val, $dis, $con, $nam if $DEBUG; + $i += 8; + } elsif ($ent == 016) { + # psect additive displaced relocation ... OK + my $dis = $rec->[$i+1]; + my $nam = &sym2psect($file,&rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0))); + my $con = ($rec->[$i+7]<<8)|($rec->[$i+6]<<0); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ($psect{$nam}{START} + $con - ($adr+2)); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(PADR): adr=%06o val=%06o ; dis=%06o con=%06o nam='%s'\n", + $adr, $val, $dis, $con, $nam if $DEBUG; + $i += 8; + } elsif ($ent == 002) { + # global relocation ... OK + my $dis = $rec->[$i+1]; + my $sym = &rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0)); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & (&get_global($sym)); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(GR): adr=%06o val=%06o ; dis=%06o sym='%s'\n", + $adr, $val, $dis, $sym if $DEBUG; + $i += 6; + } elsif ($ent == 004) { + # global displaced relocation ... OK + my $dis = $rec->[$i+1]; + my $sym = &rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0)); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & (&get_global($sym) - ($adr+2)); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(GDR): adr=%06o val=%06o ; dis=%06o sym='%s'\n", + $adr, $val, $dis, $sym if $DEBUG; + $i += 6; + } elsif ($ent == 005) { + # global additive relocation ... OK + my $dis = $rec->[$i+1]; + my $sym = &rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0)); + my $con = ($rec->[$i+7]<<8)|($rec->[$i+6]<<0); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & (&get_global($sym) + $con); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(GAR): adr=%06o val=%06o ; dis=%06o con=%06o sym='%s'\n", + $adr, $val, $dis, $con, $sym if $DEBUG; + $i += 8; + } elsif ($ent == 006) { + # global additive displaced relocation ... OK + my $dis = $rec->[$i+1]; + my $sym = &rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0)); + my $con = ($rec->[$i+7]<<8)|($rec->[$i+6]<<0); + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & (&get_global($sym) + $con - ($adr+2)); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(GADR): adr=%06o val=%06o ; dis=%06o con=%06o sym='%s'\n", + $adr, $val, $dis, $con, $sym if $DEBUG; + $i += 8; + } elsif ($ent == 007) { + # location counter definition ... OK + my $dis = $rec->[$i+1]; + my $nam = &sym2psect($file,&rad2asc(($rec->[$i+3]<<8)|($rec->[$i+2]<<0),($rec->[$i+5]<<8)|($rec->[$i+4]<<0))); + my $con = ($rec->[$i+7]<<8)|($rec->[$i+6]<<0); + # process + $psectname = $nam; + $textaddr = $datmsk & ($con); + # print + printf $LOG "..RLD(LCD): adr=%06o ; dis=%06o con=%06o nam='%s'\n", + $textaddr, $dis, $con, $nam if $DEBUG; + $i += 8; + } elsif ($ent == 010) { + # location counter modification ... OK + my $dis = $rec->[$i+1]; + my $con = ($rec->[$i+3]<<8)|($rec->[$i+2]<<0); + # process + $textaddr = $datmsk & ($con); + # print + printf $LOG "..RLD(LCM): adr=%06o ; dis=%06o con=%06o\n", + $textaddr, $dis, $con if $DEBUG; + $i += 4; + } elsif ($ent == 011) { + # program limits ... OK, mostly + my $dis = $rec->[$i+1]; + # process + my $adr = $adrmsk & ($textaddr + $dis - 4); + my $val = $datmsk & ( 01000 ); # make this up, no easy way to compute it + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(LIM1): adr=%06o val=%06o ; dis=%06o\n", + $adr, $val, $dis if $DEBUG; + # process + $dis += 2; + $adr += 2; + $val = $datmsk & ($program{END}{ADDRESS}); + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + # print + printf $LOG "..RLD(LIM2): adr=%06o val=%06o ; dis=%06o\n", + $adr, $val, $dis if $DEBUG; + $i += 2; + } elsif ($ent == 017) { + # complex relocation ... OK + my $dis = $rec->[$i+1]; + my $nam = &sym2psect($file,'. ABS.'); + my $con = 0; + # process + my $adr = 0; + my $loc = 0; + my $val = 0; + my $opc = ""; + my @stk = (); + my $dun = 0; + for ($i += 2; !$dun; $i += 1) { + if ($rec->[$i] == 000) { + # NOP do nothing + $opc = "NOP"; + } elsif ($rec->[$i] == 001) { + # ADD : pop + pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[0] + $arg[1]); + $opc = "ADD"; + } elsif ($rec->[$i] == 002) { + # SUB : pop - pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[0] - $arg[1]); + $opc = "SUB"; + } elsif ($rec->[$i] == 003) { + # MUL : pop * pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[0] * $arg[1]); + $opc = "MUL"; + } elsif ($rec->[$i] == 004) { + # DIV : pop / pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[1] == 0 ? 0 : int($arg[0] / $arg[1])); + $opc = "DIV"; + } elsif ($rec->[$i] == 005) { + # AND : pop & pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[0] & $arg[1]); + $opc = "AND"; + } elsif ($rec->[$i] == 006) { + # IOR : pop | pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[0] | $arg[1]); + $opc = "IOR"; + } elsif ($rec->[$i] == 007) { + # XOR : pop ^ pop => push + my @arg = splice(@stk,-2,2); + push(@stk, $arg[0] ^ $arg[1]); + $opc = "XOR"; + } elsif ($rec->[$i] == 010) { + # NEG : pop - => push + my @arg = splice(@stk,-1,1); + push(@stk, -$arg[0]); + $opc = "NEG"; + } elsif ($rec->[$i] == 011) { + # COM : pop ~ => push + my @arg = splice(@stk,-1,1); + push(@stk, ~$arg[0]); + $opc = "COM"; + } elsif ($rec->[$i] == 012) { + # STO : pop => store @ address + my @arg = splice(@stk,-1,1); + $adr = $adrmsk & ($textaddr + $dis - 4); + $val = $datmsk & ($arg[0]); + $opc = "STO"; + $dun = 1; + } elsif ($rec->[$i] == 013) { + # STO : pop => store @ address + disp + my @arg = splice(@stk,-1,1); + $adr = $adrmsk & ($textaddr + $dis - 4); + $val = $datmsk & ($arg[0] - ($adr+2)); + $opc = "STO+DIS"; + $dun = 1; + } elsif ($rec->[$i] == 016) { + # FET : global => push + $nam = &rad2asc(($rec->[$i+2]<<8)|($rec->[$i+1]<<0),($rec->[$i+4]<<8)|($rec->[$i+3]<<0)); + $con = &get_global($nam); + push(@stk, $con); + $opc = sprintf("GLB[%s]=(%o)", &trim($nam), $con); + $i += 4; + } elsif ($rec->[$i] == 017) { + # FET : local => push + $nam = $psect[$rec->[$i+1]]; + $con = ($rec->[$i+3]<<8) | ($rec->[$i+2]<<0); + $loc = $psect{$nam}{START} + $con; + push(@stk, $loc); + $opc = sprintf("FET[%s+%o]=(%o)", &trim($nam), $con, $loc); + $i += 3; + } elsif ($rec->[$i] == 020) { + # CONstant : value => push + $con = ($rec->[$i+2]<<8) | ($rec->[$i+1]<<0); + push(@stk, $con); + $opc = "CON"; + $i += 2; + } + $stk[-1] = $datmsk & $stk[-1] if @stk; + printf $LOG "....OPC=%-20s STK=(%s)\n", $opc, join(",",map(sprintf("%o",$_),@stk)) if $DEBUG; + } + # print + printf $LOG "..RLD(CPXR): adr=%06o val=%06o ; dis=%06o\n", $adr, $val, $dis if $DEBUG; + # store + $mem[($adr+0)&$adrmsk] = $memmsk & ($val>>0); + $mem[($adr+1)&$adrmsk] = $memmsk & ($val>>8); + } else { + warn sprintf("Warning: Unknown RLD entry 0%o (%d)", $ent, $ent); + } + } + + } elsif ($key == 005) { # ISD + + # ignore + printf $LOG "..ISD: ignored\n" if $DEBUG; + + } elsif ($key == 006) { # ENDMOD + + # just say we saw it + printf $LOG "..ENDMOD\n\n\n" if $DEBUG; + + } elsif ($key == 007) { # LIBHDR + + # ignore + printf $LOG "..LIBHDR: ignored\n" if $DEBUG; + + } elsif ($key == 010) { # LIBEND + + # ignore + printf $LOG "..LIBEND: ignored\n" if $DEBUG; + + } elsif ($key == 000 || $key >= 011) { # unknown + + # invalid record type in the object file + warn sprintf("Warning: unknown record type 0%o (%d)", $key, $key); + + } + + return; +} + +#---------------------------------------------------------------------------------------------------- + +# the end diff --git a/crossassemblers/macro11/object.c b/crossassemblers/macro11/object.c index 997cf26..1e76355 100644 --- a/crossassemblers/macro11/object.c +++ b/crossassemblers/macro11/object.c @@ -47,6 +47,12 @@ DAMAGE. #include "rad50.h" #include "object.h" +#ifndef DEFAULT_OBJECTFORMAT_RT11 +#define DEFAULT_OBJECTFORMAT_RT11 0 +#endif + +int rt11 = DEFAULT_OBJECTFORMAT_RT11; + /* writerec writes "formatted binary records." Each is preceeded by any number of 0 bytes, begins with a 1,0 pair, @@ -66,24 +72,27 @@ static int writerec( int chksum; /* Checksum is negative sum of all bytes including header and length */ int i; -#if RT11 - unsigned hdrlen = len + 4; -#else - unsigned hdrlen = len; -#endif + unsigned hdrlen; + + if (rt11) { + hdrlen = len + 4; + } else { + hdrlen = len; + } if (fp == NULL) return 1; /* Silently ignore this attempt to write. */ chksum = 0; -#if RT11 - if (fputc(FBR_LEAD1, fp) == EOF) /* All recs begin with 1,0 */ - return 0; - chksum -= FBR_LEAD1; - if (fputc(FBR_LEAD2, fp) == EOF) - return 0; - chksum -= FBR_LEAD2; -#endif /* RT11 */ + + if (rt11) { + if (fputc(FBR_LEAD1, fp) == EOF) /* All recs begin with 1,0 */ + return 0; + chksum -= FBR_LEAD1; + if (fputc(FBR_LEAD2, fp) == EOF) + return 0; + chksum -= FBR_LEAD2; + } /* RT11 */ i = hdrlen & 0xff; /* length, lsb */ chksum -= i; @@ -106,13 +115,13 @@ static int writerec( chksum &= 0xff; -#if RT11 - fputc(chksum, fp); /* Followed by the checksum byte */ -#else /* RT11 */ - if (hdrlen & 1) { - fputc(0, fp); /* Padding to even boundary */ + if (rt11) { + fputc(chksum, fp); /* Followed by the checksum byte */ + } else { /* RT11 */ + if (hdrlen & 1) { + fputc(0, fp); /* Padding to even boundary */ } -#endif /* RT11 */ +} /* RT11 */ return 1; /* Worked okay. */ } @@ -786,7 +795,7 @@ void text_complex_begin( } /* text_complex_fit checks if a complex expression will fit and - returns a pointer to it's location */ + returns a pointer to its location */ static char *text_complex_fit( TEXT_COMPLEX *tx, diff --git a/crossassemblers/macro11/object.h b/crossassemblers/macro11/object.h index bc35f44..80e706d 100644 --- a/crossassemblers/macro11/object.h +++ b/crossassemblers/macro11/object.h @@ -121,6 +121,8 @@ DAMAGE. number" and two bytes offset */ #define CPLX_CONST 020 /* Followed by two bytes constant value */ +extern int rt11; /* Use RT11 object file format */ + typedef struct gsd { FILE *fp; /* The file assigned for output */ char buf[122]; /* space for 15 GSD entries */ diff --git a/crossassemblers/macro11/parse.c b/crossassemblers/macro11/parse.c index 78a3119..859979f 100644 --- a/crossassemblers/macro11/parse.c +++ b/crossassemblers/macro11/parse.c @@ -1,8 +1,8 @@ -#define PARSE__C - #include +#include #include #include +#include #include #include "parse.h" /* my own definitions */ @@ -50,6 +50,25 @@ char *skipdelim_comma( return cp; } +/* + * check_eol - check that we're at the end of a line. + * Complain if not. + */ +int check_eol( + STACK *stack, + char *cp) +{ + cp = skipwhite(cp); + + if (EOL(*cp)) { + return 1; + } + + report(stack->top, "Junk at end of line ('%.20s')\n", cp); + + return 0; +} + /* Parses a string from the input stream. */ /* If not bracketed by <...> or ^/.../, then */ /* the string is delimited by trailing comma or whitespace. */ @@ -169,30 +188,38 @@ SYMBOL *get_op( int get_mode( char *cp, char **endp, - ADDR_MODE *mode) + ADDR_MODE *mode, + char **error) { EX_TREE *value; mode->offset = NULL; - mode->rel = 0; - mode->type = 0; + mode->pcrel = 0; + mode->type = MODE_REG; cp = skipwhite(cp); /* @ means "indirect," sets bit 3 */ if (*cp == '@') { cp++; - mode->type |= 010; + mode->type |= MODE_INDIRECT; } /* Immediate modes #imm and @#imm */ if (*cp == '#') { cp++; - mode->type |= 027; + mode->type |= MODE_AUTO_INCR | MODE_PC; + mode->offset = parse_expr(cp, 0); if (endp) *endp = mode->offset->cp; - return TRUE; + int ok = expr_ok(mode->offset); + if (!ok) { + *error = "Invalid expression after '#'"; + free_tree(mode->offset); + mode->offset = NULL; + } + return ok; } /* Check for -(Rn) */ @@ -206,11 +233,17 @@ int get_mode( /* It's -(Rn) */ value = parse_expr(tcp, 0); reg = get_register(value); - if (reg == NO_REG || (tcp = skipwhite(value->cp), *tcp++ != ')')) { + if (reg == NO_REG) { + *error = "Register expected after '-('"; free_tree(value); return FALSE; } - mode->type |= 040 | reg; + if (tcp = skipwhite(value->cp), *tcp++ != ')') { + *error = "')' expected after register"; + free_tree(value); + return FALSE; + } + mode->type |= MODE_AUTO_DECR | reg; if (endp) *endp = tcp; free_tree(value); @@ -226,7 +259,13 @@ int get_mode( value = parse_expr(cp + 1, 0); reg = get_register(value); - if (reg == NO_REG || (tcp = skipwhite(value->cp), *tcp++ != ')')) { + if (reg == NO_REG) { + *error = "Register expected after '('"; + free_tree(value); + return FALSE; + } + if (tcp = skipwhite(value->cp), *tcp++ != ')') { + *error = "')' expected after register"; free_tree(value); return FALSE; } @@ -236,22 +275,23 @@ int get_mode( tcp++; /* It's (Rn)+ */ if (endp) *endp = tcp; - mode->type |= 020 | reg; + mode->type |= MODE_AUTO_INCR | reg; free_tree(value); return TRUE; } - if (mode->type == 010) { /* For @(Rn) there's an implied 0 offset */ + if (mode->type == MODE_INDIRECT) { /* For @(Rn) there's an + implied 0 offset */ mode->offset = new_ex_lit(0); - mode->type |= 060 | reg; + mode->type |= MODE_OFFSET | reg; free_tree(value); if (endp) *endp = tcp; return TRUE; } - mode->type |= 010 | reg; /* Mode 10 is register indirect as - in (Rn) */ + mode->type |= MODE_INDIRECT | reg; /* Mode 10 is register indirect + as in (Rn) */ free_tree(value); if (endp) *endp = tcp; @@ -262,6 +302,13 @@ int get_mode( mode->offset = parse_expr(cp, 0); + if (!expr_ok(mode->offset)) { + *error = "Invalid expression"; + free_tree(mode->offset); + mode->offset = NULL; + return FALSE; + } + cp = skipwhite(mode->offset->cp); if (*cp == '(') { @@ -270,12 +317,22 @@ int get_mode( /* indirect register plus offset */ value = parse_expr(cp + 1, 0); reg = get_register(value); - if (reg == NO_REG || (cp = skipwhite(value->cp), *cp++ != ')')) { + if (reg == NO_REG) { + *error = "Register expected after 'offset('"; free_tree(value); + free_tree(mode->offset); + mode->offset = NULL; + return FALSE; /* Syntax error in addressing mode */ + } + if (cp = skipwhite(value->cp), *cp++ != ')') { + *error = "')' expected after 'offset(register'"; + free_tree(value); + free_tree(mode->offset); + mode->offset = NULL; return FALSE; /* Syntax error in addressing mode */ } - mode->type |= 060 | reg; + mode->type |= MODE_OFFSET | reg; free_tree(value); @@ -304,26 +361,122 @@ int get_mode( /* It's either 067 (PC-relative) or 037 (absolute) mode, depending */ /* on user option. */ - if (mode->type & 010) { /* Have already noted indirection? */ - mode->type |= 067; /* If so, then PC-relative is the only + if (mode->type & MODE_INDIRECT) { /* Have already noted indirection? */ + mode->type |= MODE_OFFSET|MODE_PC;/* If so, then PC-relative is the only option */ - mode->rel = 1; /* Note PC-relative */ + mode->pcrel = 1; /* Note PC-relative */ } else if (enabl_ama) { /* User asked for absolute adressing? */ - mode->type |= 037; /* Give it to him. */ + mode->type |= MODE_INDIRECT|MODE_AUTO_INCR|MODE_PC; + /* Give it to him. */ } else { - mode->type |= 067; /* PC-relative */ - mode->rel = 1; /* Note PC-relative */ + mode->type |= MODE_OFFSET|MODE_PC; /* PC-relative */ + mode->pcrel = 1; /* Note PC-relative */ } return TRUE; } +/* get_fp_src_mode - parse an immediate fp literal or a general mode */ + +int get_fp_src_mode( + char *cp, + char **endp, + ADDR_MODE *mode, + char **error) +{ + cp = skipwhite(cp); + + char *savecp = cp; + + if (cp[0] == '#') { + unsigned flt[1]; + char *fltendp = NULL; + + cp = skipwhite(cp + 1); + + int ret = parse_float(cp, &fltendp, 1, flt); + + if (ret) { + mode->type = MODE_AUTO_INCR | MODE_PC; + mode->pcrel = 0; + mode->offset = new_ex_lit(flt[0]); + mode->offset->cp = fltendp; + + if (endp) + *endp = mode->offset->cp; + + return TRUE; + } else if (fltendp) { + /* it looked like a fp number but something was wrong with it */ + } + } + + int ret = get_mode(savecp, endp, mode, error); + + return ret; +} + +#define DEBUG_FLOAT 0 +#if DEBUG_FLOAT + +void +printflt(unsigned *flt, int size) +{ + printf("%06o: ", flt[0]); + printf("sign: %d ", (flt[0] & 0x8000) >> 15); + printf("uexp: %x ", (flt[0] & 0x7F80) >> 7); + printf("ufrac: %02x", flt[0] & 0x007F); + + for (int i = 1; i < size; i++) { + printf(" %04x", flt[i]); + } + + printf("\n"); +} + +#define DF(x) printf x +#else +#define DF(x) +#endif + +/* + * We need 56 bits of mantissa. + * + * Try to detect if it is needed, possible and useful to use + * long double instead of double, when parsing floating point numbers. + */ + +#if DBL_MANT_DIG >= 56 +/* plain double seems big enough */ +# define USE_LONG_DOUBLE 0 +/* long double exists and seems big enough */ +#elif LDBL_MANT_DIG >= 56 +# define USE_LONG_DOUBLE 1 +#elif defined(LDBL_MANT_DIG) +/* long double exists but is probably still too small */ +# define USE_LONG_DOUBLE 1 +#else +/* long double does not exist and plain double is too small */ +# define USE_LONG_DOUBLE 0 +#endif + +#if USE_LONG_DOUBLE +# define DOUBLE long double +# define SCANF_FMT "%Lf" +# define FREXP frexpl +#else +# define DOUBLE double +# define SCANF_FMT "%lf" +# define FREXP frexp +#endif + + /* Parse PDP-11 64-bit floating point format. */ /* Give a pointer to "size" words to receive the result. */ /* Note: there are probably degenerate cases that store incorrect results. For example, I think rounding up a FLT2 might cause exponent overflow. Sorry. */ -/* Note also that the full 49 bits of precision probably aren't +/* Note also that the full 56 bits of precision probably aren't always available on the source platform, given the widespread application of IEEE floating point formats, so expect some differences. Sorry again. */ @@ -334,55 +487,131 @@ int parse_float( int size, unsigned *flt) { - double d; /* value */ - double frac; /* fractional value */ - ulong64 ufrac; /* fraction converted to 49 bit + DOUBLE d; /* value */ + DOUBLE frac; /* fractional value */ + uint64_t ufrac; /* fraction converted to 56 bit unsigned integer */ + uint64_t onehalf; /* one half of the smallest bit + (used for rounding) */ int i; /* Number of fields converted by sscanf */ int n; /* Number of characters converted by sscanf */ int sexp; /* Signed exponent */ unsigned uexp; /* Unsigned excess-128 exponent */ unsigned sign = 0; /* Sign mask */ - i = sscanf(cp, "%lf%n", &d, &n); + i = sscanf(cp, SCANF_FMT "%n", &d, &n); if (i == 0) return 0; /* Wasn't able to convert */ + DF(("LDBL_MANT_DIG: %d\n", LDBL_MANT_DIG)); + DF(("%Lf input: %s", d, cp)); cp += n; if (endp) *endp = cp; if (d == 0.0) { - flt[0] = flt[1] = flt[2] = flt[3] = 0; /* All-bits-zero equals zero */ + for (i = 0; i < size; i++) { + flt[i] = 0; /* All-bits-zero equals zero */ + } return 1; /* Good job. */ } - frac = frexp(d, &sexp); /* Separate into exponent and mantissa */ - if (sexp < -128 || sexp > 127) + frac = FREXP(d, &sexp); /* Separate into exponent and mantissa */ + DF(("frac: %Lf %La sexp: %d\n", frac, frac, sexp)); + if (sexp < -127 || sexp > 127) return 0; /* Exponent out of range. */ uexp = sexp + 128; /* Make excess-128 mode */ uexp &= 0xff; /* express in 8 bits */ + DF(("uexp: %02x\n", uexp)); + + /* + * frexp guarantees its fractional return value is + * abs(frac) >= 0.5 and abs(frac) < 1.0 + * Another way to think of this is that: + * abs(frac) >= 2**-1 and abs(frac) < 2**0 + */ if (frac < 0) { - sign = 0100000; /* Negative sign */ + sign = (1 << 15); /* Negative sign */ frac = -frac; /* fix the mantissa */ } - /* The following big literal is 2 to the 49th power: */ - ufrac = (ulong64) (frac * 72057594037927936.0); /* Align fraction bits */ + /* + * For the PDP-11 floating point representation the + * fractional part is 7 bits (for 16-bit floating point + * literals), 23 bits (for 32-bit floating point values), + * or 55 bits (for 64-bit floating point values). + * However the bit immediately above the MSB is always 1 + * because the value is normalized. So it's actually + * 8 bits, 24 bits, or 56 bits. + * We effectively multiply the fractional part of our value by + * 2**56 to fully expose all of those bits (including + * the MSB which is 1). + * However as an intermediate step, we really multiply by + * 2**57, so we get one lsb for possible later rounding + * purposes. After that, we divide by 2 again. + */ - /* Round from FLT4 to FLT2 */ - if (size < 4) { - ufrac += 0x80000000; /* Round to nearest 32-bit - representation */ + /* The following big literal is 2 to the 57th power: */ + ufrac = (uint64_t) (frac * 144115188075855872.0); /* Align fraction bits */ + DF(("ufrac: %016lx\n", ufrac)); + DF(("56 : %016lx\n", (1UL<<57) - 2)); - if (ufrac > 0x200000000000) { /* Overflow? */ + /* + * ufrac is now >= 2**56 and < 2**57. + * This means it's normalized: bit [56] is 1 + * and all higher bits are 0. + */ + + /* Round from 57-bits to 56, 24, or 8. + * We do this by: + * + first adding a value equal to one half of the + * least significant bit (the value 'onehalf') + * + (possibly) dealing with any carrying that + * causes the value to no longer be normalized + * (with bit [56] = 1 and all higher bits = 0) + * + shifting right by 1 bit (which throws away + * the 0 bit). Note this step could be rolled + * into the next step. + * + taking the remaining highest order 8, + * 24, or 56 bits. + * + * +--+--------+-------+ +--------+--------+ + * |15|14 7|6 0| |15 | 0| + * +--+--------+-------+ +--------+--------+ + * | S|EEEEEEEE|MMMMMMM| |MMMMMMMM|MMMMMMMM| ...maybe 2 more words... + * +--+--------+-------+ +--------+--------+ + * Sign (1 bit) + * Exponent (8 bits) + * Mantissa (7 bits) + */ + + onehalf = 1ULL << (16 * (4-size)); + ufrac += onehalf; + DF(("onehalf=%016lx, ufrac+onehalf: %016lx\n", onehalf, ufrac)); + + /* Did it roll up to a value 2**56? */ + if ((ufrac >> 57) > 0) { /* Overflow? */ + if (uexp < 0xFF) { ufrac >>= 1; /* Normalize */ - uexp--; + uexp++; + DF(("ufrac: %016lx uexp: %02x (normalized)\n", ufrac, uexp)); + } else { + /* + * If rounding and then normalisation would cause the exponent to + * overflow, just don't round: the cure is worse than the disease. + * We could detect ahead of time but the conditions for all size + * values may be a bit complicated, and so rare, that it is more + * readable to just undo it here. + */ + ufrac -= onehalf; + DF(("don't round: exponent overflow")); } } + ufrac >>= 1; /* Go from 57 bits to 56 */ + flt[0] = (unsigned) (sign | (uexp << 7) | ((ufrac >> 48) & 0x7F)); if (size > 1) { flt[1] = (unsigned) ((ufrac >> 32) & 0xffff); @@ -407,6 +636,7 @@ int parse_float( #define MUL_PREC 1 #define AND_PREC 1 #define OR_PREC 1 +#define LSH_PREC 1 EX_TREE *parse_unary( char *cp); /* Prototype for forward calls */ @@ -435,7 +665,6 @@ EX_TREE *parse_binary( rightp = parse_binary(cp + 1, term, ADD_PREC); tp = new_ex_bin(EX_ADD, leftp, rightp); - tp->cp = rightp->cp; leftp = tp; break; @@ -445,7 +674,6 @@ EX_TREE *parse_binary( rightp = parse_binary(cp + 1, term, ADD_PREC); tp = new_ex_bin(EX_SUB, leftp, rightp); - tp->cp = rightp->cp; leftp = tp; break; @@ -455,7 +683,6 @@ EX_TREE *parse_binary( rightp = parse_binary(cp + 1, term, MUL_PREC); tp = new_ex_bin(EX_MUL, leftp, rightp); - tp->cp = rightp->cp; leftp = tp; break; @@ -465,7 +692,6 @@ EX_TREE *parse_binary( rightp = parse_binary(cp + 1, term, MUL_PREC); tp = new_ex_bin(EX_DIV, leftp, rightp); - tp->cp = rightp->cp; leftp = tp; break; @@ -475,7 +701,6 @@ EX_TREE *parse_binary( rightp = parse_binary(cp + 1, term, OR_PREC); tp = new_ex_bin(EX_OR, leftp, rightp); - tp->cp = rightp->cp; leftp = tp; break; @@ -485,7 +710,15 @@ EX_TREE *parse_binary( rightp = parse_binary(cp + 1, term, AND_PREC); tp = new_ex_bin(EX_AND, leftp, rightp); - tp->cp = rightp->cp; + leftp = tp; + break; + + case '_': + if (symbol_allow_underscores || depth >= LSH_PREC) + return leftp; + + rightp = parse_binary(cp + 1, term, LSH_PREC); + tp = new_ex_bin(EX_LSH, leftp, rightp); leftp = tp; break; @@ -594,58 +827,56 @@ int brackrange( int *length, char **endp) { - char endstr[6]; - int endlen; + char endstr[] = "x\n"; + int len = 0; int nest; - int len; switch (*cp) { - case '^': + case '^': /* ^/text/ */ endstr[0] = cp[1]; - strcpy(endstr + 1, "\n"); *start = 2; - endlen = 1; + cp += *start; + len = strcspn(cp, endstr); break; - case '<': - strcpy(endstr, "<>\n"); - endlen = 1; + case '<': /* nested> */ *start = 1; - break; - default: - return FALSE; - } - - cp += *start; - - len = 0; - if (endstr[1] == '>') { /* <>\n */ + cp += *start; nest = 1; - while (nest) { + + while (nest > 0) { int sublen; - sublen = strcspn(cp + len, endstr); + sublen = strcspn(cp + len, "<>\n"); if (cp[len + sublen] == '<') { nest++; - sublen++; /* avoid infinite loop when sublen == 0 */ + sublen++; /* include nested starting delimiter */ } else { nest--; if (nest > 0 && cp[len + sublen] == '>') - sublen++; /* avoid infinite loop when sublen == 0 */ + sublen++; /* include nested ending delimiter */ } len += sublen; if (sublen == 0) break; } - } else { - int sublen; + break; + default: + return FALSE; + } - sublen = strcspn(cp + len, endstr); - len += sublen; + /* + * If we see a newline here, the proper terminator must be missing. + * Don't use EOL() to check: it recognizes ';' too. + * Unfortunately we can't issue a diagnostic here. + */ + if (!cp[len] || cp[len] == '\n') { + return FALSE; } *length = len; - if (endp) - *endp = cp + len + endlen; + if (endp) { + *endp = cp + len + 1; /* skip over ending delimiter */ + } return 1; } @@ -661,27 +892,13 @@ EX_TREE *parse_unary( cp = skipwhite(cp); if (*cp == '%') { /* Register notation */ - unsigned reg; - - cp++; - reg = strtoul(cp, &cp, 8); - if (reg > 7) - return ex_err(NULL, cp); - - /* This returns references to the built-in register symbols */ - tp = new_ex_tree(); - tp->type = EX_SYM; - tp->data.symbol = reg_sym[reg]; - tp->cp = cp; + tp = new_ex_una(EX_REG, parse_unary(cp + 1)); return tp; } /* Unary negate */ if (*cp == '-') { - tp = new_ex_tree(); - tp->type = EX_NEG; - tp->data.child.left = parse_unary(cp + 1); - tp->cp = tp->data.child.left->cp; + tp = new_ex_una(EX_NEG, parse_unary(cp + 1)); return tp; } @@ -695,10 +912,7 @@ EX_TREE *parse_unary( switch (tolower((unsigned char)cp[1])) { case 'c': /* ^C, ones complement */ - tp = new_ex_tree(); - tp->type = EX_COM; - tp->data.child.left = parse_unary(cp + 2); - tp->cp = tp->data.child.left->cp; + tp = new_ex_una(EX_COM, parse_unary(cp + 2)); return tp; case 'b': /* ^B, binary radix modifier */ @@ -755,6 +969,53 @@ EX_TREE *parse_unary( tp = new_ex_lit(flt[0]); tp->cp = endcp; } + return tp; + } + case 'p': + /* psect limits, low or high */ { + char bound = tolower((unsigned char)cp[2]); + char *cp2 = skipwhite(cp + 3); + int islocal = 0; + char *endcp = NULL; + char *psectname = get_symbol(cp2, &endcp, &islocal); + SYMBOL *sectsym = psectname ? lookup_sym(psectname, §ion_st) : NULL; + + if (sectsym && !islocal) { + SECTION *psect = sectsym->section; + + tp = new_ex_tree(EX_SYM); + tp->data.symbol = sectsym; + tp->cp = cp; + + if (bound == 'l') { + ; /* that's it */ + } else if (bound == 'h') { + EX_TREE *rightp = new_ex_lit(psect->size); + tp = new_ex_bin(EX_ADD, tp, rightp); + } else { + tp = ex_err(tp, endcp); + /* report(stack->top, "^p: %c not recognized\n", bound); */ + } + } else { + /* report(stack->top, "psect name %s not found\n", psectname); */ + if (!endcp) { + endcp = cp; + } + if (pass == 0) { + /* + * During the first pass it is expected that the psect is not + * found. Return a dummy value of the expected size, so that + * the size of the psect keeps in sync. + */ + tp = new_ex_lit(0); + } else { + tp = ex_err(new_ex_lit(0), endcp); + } + } + free(psectname); + tp->cp = endcp; + cp = endcp; + return tp; } } @@ -847,7 +1108,6 @@ EX_TREE *parse_unary( get_symbol a second time. */ if (!(label = get_symbol(cp, &cp, &local))) { - cp++; /*JH: eat first char of illegal label, else endless loop on implied .WORD */ tp = ex_err(NULL, cp); /* Not a valid label. */ return tp; } @@ -859,10 +1119,9 @@ EX_TREE *parse_unary( sym = lookup_sym(label, &system_st); } - if (sym != NULL) { - tp = new_ex_tree(); + if (sym != NULL && !(sym->flags & SYMBOLFLAG_UNDEFINED)) { + tp = new_ex_tree(EX_SYM); tp->cp = cp; - tp->type = EX_SYM; tp->data.symbol = sym; free(label); @@ -870,7 +1129,11 @@ EX_TREE *parse_unary( } /* The symbol was not found. Create an "undefined symbol" - reference. */ + reference. These symbols are freed in free_tree(), + in contrast to the symbol used in EX_SYM. + implicit_gbl() will either make it an implicit global, + or an undefined non-global symbol. + */ sym = memcheck(malloc(sizeof(SYMBOL))); sym->label = label; sym->flags = SYMBOLFLAG_UNDEFINED | local; @@ -879,9 +1142,8 @@ EX_TREE *parse_unary( sym->section = &absolute_section; sym->value = 0; - tp = new_ex_tree(); + tp = new_ex_tree(EX_UNDEFINED_SYM); tp->cp = cp; - tp->type = EX_UNDEFINED_SYM; tp->data.symbol = sym; return tp; @@ -895,13 +1157,13 @@ EX_TREE *parse_unary( EX_TREE *parse_expr( char *cp, - int undef) + int flags) { EX_TREE *expr; EX_TREE *value; expr = parse_binary(cp, 0, 0); /* Parse into a tree */ - value = evaluate(expr, undef); /* Perform the arithmetic */ + value = evaluate(expr, flags); /* Perform the arithmetic */ value->cp = expr->cp; /* Pointer to end of text is part of the rootmost node */ free_tree(expr); /* Discard parse in favor of @@ -918,13 +1180,13 @@ EX_TREE *parse_expr( EX_TREE *parse_unary_expr( char *cp, - int undef) + int flags) { EX_TREE *expr; EX_TREE *value; expr = parse_unary(cp); /* Parse into a tree */ - value = evaluate(expr, undef); /* Perform the arithmetic */ + value = evaluate(expr, flags); /* Perform the arithmetic */ value->cp = expr->cp; /* Pointer to end of text is part of the rootmost node */ free_tree(expr); /* Discard parse in favor of @@ -932,3 +1194,13 @@ EX_TREE *parse_unary_expr( return value; } + +/* + * expr_ok Returns TRUE if there was a valid expression parsed. + */ + +int expr_ok( + EX_TREE *expr) +{ + return expr != NULL && expr->type != EX_ERR; +} diff --git a/crossassemblers/macro11/parse.h b/crossassemblers/macro11/parse.h index 84f50d9..499a249 100644 --- a/crossassemblers/macro11/parse.h +++ b/crossassemblers/macro11/parse.h @@ -8,8 +8,8 @@ // is char 'c' part of a symbol? #define issym(c) (isalpha(c) || isdigit(c) \ - || (c) == '.' || (c) == '$' \ - || (symbol_allow_underscores && (c) == '_')) + || (c) == '.' || (c) == '$' \ + || (symbol_allow_underscores && (c) == '_')) char *skipwhite( @@ -23,6 +23,9 @@ char *skipdelim_comma( SYMBOL *get_op( char *cp, char **endp); +int check_eol( + STACK *stack, + char *cp); char *getstring( char *cp, char **endp); @@ -36,14 +39,22 @@ char *get_symbol( int get_mode( char *cp, char **endp, - ADDR_MODE *mode); + ADDR_MODE *mode, + char **error); +int get_fp_src_mode( + char *cp, + char **endp, + ADDR_MODE *mode, + char **error); EX_TREE *parse_expr( char *cp, - int undef); + int flags); EX_TREE *parse_unary_expr( char *cp, - int undef); + int flags); +int expr_ok( + EX_TREE *expr); int parse_float( char *cp, char **endp, diff --git a/crossassemblers/macro11/rept_irpc.c b/crossassemblers/macro11/rept_irpc.c index 5ba5fb4..65f59b6 100644 --- a/crossassemblers/macro11/rept_irpc.c +++ b/crossassemblers/macro11/rept_irpc.c @@ -29,7 +29,7 @@ typedef struct rept_stream { /* rept_stream_gets gets a line from a repeat stream. At the end of each count, the coutdown is decreated and the stream is reset to - it's beginning. */ + its beginning. */ char *rept_stream_gets( STREAM *str) @@ -38,13 +38,14 @@ char *rept_stream_gets( char *cp; for (;;) { + if (rstr->count <= 0) + return NULL; + if ((cp = buffer_stream_gets(str)) != NULL) return cp; - if (--rstr->count <= 0) - return NULL; - buffer_stream_rewind(str); + rstr->count--; } } @@ -83,6 +84,14 @@ STREAM *expand_rept( free_tree(value); return NULL; } + /* + * Reading the next lines-to-be-repeated overwrites the line buffer + * that the caller is using. So for junk-at-end-of-line checking we + * need to do it here. + */ + check_eol(stack, value->cp); + + list_value(stack->top, value->data.lit); gb = new_buffer(); @@ -211,6 +220,8 @@ STREAM *expand_irp( return NULL; } + check_eol(stack, cp); + gb = new_buffer(); levelmod = 0; @@ -339,6 +350,8 @@ STREAM *expand_irpc( return NULL; } + check_eol(stack, cp); + gb = new_buffer(); levelmod = 0; diff --git a/crossassemblers/macro11/stream2.c b/crossassemblers/macro11/stream2.c index 28a8257..7a2bbb5 100644 --- a/crossassemblers/macro11/stream2.c +++ b/crossassemblers/macro11/stream2.c @@ -239,10 +239,11 @@ void buffer_stream_construct( bstr->stream.vtbl = &buffer_stream_vtbl; bstr->stream.name = memcheck(strdup(name)); + bstr->stream.line = 0; + bstr->stream.next = NULL; bstr->buffer = buffer_clone(buf); bstr->offset = 0; - bstr->stream.line = 0; } void buffer_stream_set_buffer( @@ -350,9 +351,10 @@ STREAM *new_file_stream( str->stream.vtbl = &file_stream_vtbl; str->stream.name = memcheck(strdup(filename)); + str->stream.line = 0; + str->stream.next = NULL; str->buffer = memcheck(malloc(STREAM_BUFFER_SIZE)); str->fp = fp; - str->stream.line = 0; return &str->stream; } diff --git a/crossassemblers/macro11/symbols.c b/crossassemblers/macro11/symbols.c index 50d1c91..0e8cae3 100644 --- a/crossassemblers/macro11/symbols.c +++ b/crossassemblers/macro11/symbols.c @@ -30,9 +30,101 @@ SYMBOL_TABLE macro_st; /* Macros */ SYMBOL_TABLE implicit_st; /* The symbols which may be implicit globals */ +SYMBOL_TABLE undefined_st; /* The symbols which may be undefined */ + void list_section(SECTION *sec); +static void +dump_sym(SYMBOL *sym) +{ + report(NULL, "'%s': %06o, stmt %d, flags %o:%s%s%s%s%s%s\n", + sym->label, + sym->value, + sym->stmtno, + sym->flags, + ((sym->flags & SYMBOLFLAG_PERMANENT)? " PERMANENT" : ""), + ((sym->flags & SYMBOLFLAG_GLOBAL)? " GLOBAL" : ""), + ((sym->flags & SYMBOLFLAG_WEAK)? " WEAK" : ""), + ((sym->flags & SYMBOLFLAG_DEFINITION)? " DEFINITION" : ""), + ((sym->flags & SYMBOLFLAG_UNDEFINED)? " UNDEFINED" : ""), + ((sym->flags & SYMBOLFLAG_LOCAL)? " LOCAL" : ""), + ((sym->flags & SYMBOLFLAG_IMPLICIT_GLOBAL)? " IMPLICIT_GLOBAL" : "")); +} + +void +check_sym_invariants(SYMBOL *sym, char *file, int line) +{ + int dump = 0; + + if (sym->section == &instruction_section) { + /* The instructions use the flags field differently */ + if ((sym->flags & ~OC_MASK) != 0) { + report(NULL, "%s %d: Instruction symbol %s has wrong flags\n", file, line, sym->label); + dump_sym(sym); + } + return; + } + + /* + * A symbol is GLOBAL if it appears in the object file's symbol table. + * It can be either exported (if defined) or imported (if not defined). + * + * A common test like this + * + * if ((sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) + * + * tests if a symbol is imported. + */ + + switch (sym->flags & (SYMBOLFLAG_PERMANENT|SYMBOLFLAG_GLOBAL|SYMBOLFLAG_DEFINITION|SYMBOLFLAG_UNDEFINED)) { + /* A DEFINITION can independently be PERMANENT and/or GLOBAL */ + case SYMBOLFLAG_PERMANENT|SYMBOLFLAG_GLOBAL|SYMBOLFLAG_DEFINITION: + case SYMBOLFLAG_GLOBAL|SYMBOLFLAG_DEFINITION: + case SYMBOLFLAG_PERMANENT| SYMBOLFLAG_DEFINITION: + case SYMBOLFLAG_DEFINITION: + break; + /* A GLOBAL can also be undefined, but then it's still usable */ + case SYMBOLFLAG_GLOBAL: + break; + /* A truly UNDEFINED symbol is an error to use */ + /* (this seems logically equivalent to all of these flags cleared) */ + case SYMBOLFLAG_UNDEFINED: + break; + default: + report(NULL, "%s %d: Symbol %s definedness is inconsistent\n", file, line, sym->label); + dump++; + } + + if ( (sym->flags & SYMBOLFLAG_IMPLICIT_GLOBAL) && + !(sym->flags & SYMBOLFLAG_GLOBAL)) { + report(NULL, "%s %d: Symbol %s globalness is inconsistent\n", file, line, sym->label); + dump++; + } + + if ( (sym->flags & SYMBOLFLAG_LOCAL) && + (sym->flags & SYMBOLFLAG_GLOBAL)) { + report(NULL, "%s %d: Symbol %s is local and global\n", file, line, sym->label); + dump++; + } + + if ( (sym->flags & SYMBOLFLAG_PERMANENT) && + !(sym->flags & SYMBOLFLAG_DEFINITION)) { + report(NULL, "%s %d: Symbol %s is permanent without definition\n", file, line, sym->label); + dump++; + } + + if ( (sym->flags & SYMBOLFLAG_WEAK) && + !(sym->flags & SYMBOLFLAG_GLOBAL)) { + report(NULL, "%s %d: Symbol %s weak/global is inconsistent\n", file, line, sym->label); + dump++; + } + + if (dump) { + dump_sym(sym); + } +} + /* hash_name hashes a name into a value from 0-HASH_SIZE */ int hash_name( @@ -91,13 +183,14 @@ void free_sym( SYMBOL *sym) { if (sym->label) { + check_sym_invariants(sym, __FILE__, __LINE__); free(sym->label); sym->label = NULL; } free(sym); } -/* remove_sym removes a symbol from it's symbol table. */ +/* remove_sym removes a symbol from its symbol table. */ void remove_sym( SYMBOL *sym, @@ -107,6 +200,7 @@ void remove_sym( *symp; int hash; + check_sym_invariants(sym, __FILE__, __LINE__); hash = hash_name(sym->label); prevp = &table->hash[hash]; while (symp = *prevp, symp != NULL && symp != sym) @@ -131,6 +225,9 @@ SYMBOL *lookup_sym( while (sym && strcmp(sym->label, label) != 0) sym = sym->next; + if (sym) { + check_sym_invariants(sym, __FILE__, __LINE__); + } return sym; } @@ -176,6 +273,7 @@ void add_table( sym->next = table->hash[hash]; table->hash[hash] = sym; + check_sym_invariants(sym, __FILE__, __LINE__); } /* add_sym - used throughout to add or update symbols in a symbol @@ -204,14 +302,20 @@ SYMBOL *add_sym( sym = lookup_sym(label, table); if (sym != NULL) { // A symbol registered as "undefined" can be changed. + // + check_sym_invariants(sym, __FILE__, __LINE__); if ((sym->flags & SYMBOLFLAG_UNDEFINED) && !(flags & SYMBOLFLAG_UNDEFINED)) { sym->flags &= ~(SYMBOLFLAG_PERMANENT | SYMBOLFLAG_UNDEFINED); } - + else if (!(sym->flags & SYMBOLFLAG_UNDEFINED) && (flags & SYMBOLFLAG_UNDEFINED)) { + report(NULL, "INTERNAL ERROR: Turning defined symbol '%s' into undefined\n", label); + return sym; + } /* Check for compatible definition */ else if (sym->section == section && sym->value == value) { sym->flags |= flags; /* Merge flags quietly */ + check_sym_invariants(sym, __FILE__, __LINE__); return sym; /* 's okay */ } @@ -220,6 +324,7 @@ SYMBOL *add_sym( sym->value = value; sym->flags |= flags; sym->section = section; + check_sym_invariants(sym, __FILE__, __LINE__); return sym; } @@ -242,73 +347,78 @@ SYMBOL *add_sym( void add_symbols( SECTION *current_section) { - current_pc = add_sym(".", 0, 0, current_section, &symbol_st); + current_pc = add_sym(".", 0, SYMBOLFLAG_DEFINITION, current_section, &symbol_st); - reg_sym[0] = add_sym("R0", 0, 0, ®ister_section, &system_st); - reg_sym[1] = add_sym("R1", 1, 0, ®ister_section, &system_st); - reg_sym[2] = add_sym("R2", 2, 0, ®ister_section, &system_st); - reg_sym[3] = add_sym("R3", 3, 0, ®ister_section, &system_st); - reg_sym[4] = add_sym("R4", 4, 0, ®ister_section, &system_st); - reg_sym[5] = add_sym("R5", 5, 0, ®ister_section, &system_st); - reg_sym[6] = add_sym("SP", 6, 0, ®ister_section, &system_st); - reg_sym[7] = add_sym("PC", 7, 0, ®ister_section, &system_st); +#define S (SYMBOLFLAG_PERMANENT | SYMBOLFLAG_DEFINITION) + + reg_sym[0] = add_sym("R0", 0, S, ®ister_section, &system_st); + reg_sym[1] = add_sym("R1", 1, S, ®ister_section, &system_st); + reg_sym[2] = add_sym("R2", 2, S, ®ister_section, &system_st); + reg_sym[3] = add_sym("R3", 3, S, ®ister_section, &system_st); + reg_sym[4] = add_sym("R4", 4, S, ®ister_section, &system_st); + reg_sym[5] = add_sym("R5", 5, S, ®ister_section, &system_st); + reg_sym[6] = add_sym("SP", 6, S, ®ister_section, &system_st); + reg_sym[7] = add_sym("PC", 7, S, ®ister_section, &system_st); //JH: symbols longer than current SYMMAX will be truncated. SYMMAX=6 is minimum! - add_sym(".ASCII", P_ASCII, 0, &pseudo_section, &system_st); - add_sym(".ASCIZ", P_ASCIZ, 0, &pseudo_section, &system_st); - add_sym(".ASECT", P_ASECT, 0, &pseudo_section, &system_st); - add_sym(".BLKB", P_BLKB, 0, &pseudo_section, &system_st); - add_sym(".BLKW", P_BLKW, 0, &pseudo_section, &system_st); - add_sym(".BYTE", P_BYTE, 0, &pseudo_section, &system_st); - add_sym(".CSECT", P_CSECT, 0, &pseudo_section, &system_st); - add_sym(".DSABL", P_DSABL, 0, &pseudo_section, &system_st); - add_sym(".ENABL", P_ENABL, 0, &pseudo_section, &system_st); - add_sym(".END", P_END, 0, &pseudo_section, &system_st); - add_sym(".ENDC", P_ENDC, 0, &pseudo_section, &system_st); - add_sym(".ENDM", P_ENDM, 0, &pseudo_section, &system_st); - add_sym(".ENDR", P_ENDR, 0, &pseudo_section, &system_st); - add_sym(".EOT", P_EOT, 0, &pseudo_section, &system_st); - add_sym(".ERROR", P_ERROR, 0, &pseudo_section, &system_st); - add_sym(".EVEN", P_EVEN, 0, &pseudo_section, &system_st); - add_sym(".FLT2", P_FLT2, 0, &pseudo_section, &system_st); - add_sym(".FLT4", P_FLT4, 0, &pseudo_section, &system_st); - add_sym(".GLOBL", P_GLOBL, 0, &pseudo_section, &system_st); - add_sym(".IDENT", P_IDENT, 0, &pseudo_section, &system_st); - add_sym(".IF", P_IF, 0, &pseudo_section, &system_st); - add_sym(".IFDF", P_IFDF, 0, &pseudo_section, &system_st); - add_sym(".IFNDF", P_IFDF, 0, &pseudo_section, &system_st); - add_sym(".IFF", P_IFF, 0, &pseudo_section, &system_st); - add_sym(".IFT", P_IFT, 0, &pseudo_section, &system_st); - add_sym(".IFTF", P_IFTF, 0, &pseudo_section, &system_st); - add_sym(".IIF", P_IIF, 0, &pseudo_section, &system_st); - add_sym(".INCLUDE", P_INCLUDE, 0, &pseudo_section, &system_st); - add_sym(".IRP", P_IRP, 0, &pseudo_section, &system_st); - add_sym(".IRPC", P_IRPC, 0, &pseudo_section, &system_st); - add_sym(".LIBRARY", P_LIBRARY, 0, &pseudo_section, &system_st); - add_sym(".LIMIT", P_LIMIT, 0, &pseudo_section, &system_st); - add_sym(".LIST", P_LIST, 0, &pseudo_section, &system_st); - add_sym(".MCALL", P_MCALL, 0, &pseudo_section, &system_st); - add_sym(".MEXIT", P_MEXIT, 0, &pseudo_section, &system_st); - add_sym(".NARG", P_NARG, 0, &pseudo_section, &system_st); - add_sym(".NCHR", P_NCHR, 0, &pseudo_section, &system_st); - add_sym(".NLIST", P_NLIST, 0, &pseudo_section, &system_st); - add_sym(".NTYPE", P_NTYPE, 0, &pseudo_section, &system_st); - add_sym(".ODD", P_ODD, 0, &pseudo_section, &system_st); - add_sym(".PACKED", P_PACKED, 0, &pseudo_section, &system_st); - add_sym(".PAGE", P_PAGE, 0, &pseudo_section, &system_st); - add_sym(".PRINT", P_PRINT, 0, &pseudo_section, &system_st); - add_sym(".PSECT", P_PSECT, 0, &pseudo_section, &system_st); - add_sym(".RADIX", P_RADIX, 0, &pseudo_section, &system_st); - add_sym(".RAD50", P_RAD50, 0, &pseudo_section, &system_st); - add_sym(".REM", P_REM, 0, &pseudo_section, &system_st); - add_sym(".REPT", P_REPT, 0, &pseudo_section, &system_st); - add_sym(".RESTORE", P_RESTORE, 0, &pseudo_section, &system_st); - add_sym(".SAVE", P_SAVE, 0, &pseudo_section, &system_st); - add_sym(".SBTTL", P_SBTTL, 0, &pseudo_section, &system_st); - add_sym(".TITLE", P_TITLE, 0, &pseudo_section, &system_st); - add_sym(".WORD", P_WORD, 0, &pseudo_section, &system_st); - add_sym(".MACRO", P_MACRO, 0, &pseudo_section, &system_st); - add_sym(".WEAK", P_WEAK, 0, &pseudo_section, &system_st); + + add_sym(".ASCII", P_ASCII, S, &pseudo_section, &system_st); + add_sym(".ASCIZ", P_ASCIZ, S, &pseudo_section, &system_st); + add_sym(".ASECT", P_ASECT, S, &pseudo_section, &system_st); + add_sym(".BLKB", P_BLKB, S, &pseudo_section, &system_st); + add_sym(".BLKW", P_BLKW, S, &pseudo_section, &system_st); + add_sym(".BYTE", P_BYTE, S, &pseudo_section, &system_st); + add_sym(".CSECT", P_CSECT, S, &pseudo_section, &system_st); + add_sym(".DSABL", P_DSABL, S, &pseudo_section, &system_st); + add_sym(".ENABL", P_ENABL, S, &pseudo_section, &system_st); + add_sym(".END", P_END, S, &pseudo_section, &system_st); + add_sym(".ENDC", P_ENDC, S, &pseudo_section, &system_st); + add_sym(".ENDM", P_ENDM, S, &pseudo_section, &system_st); + add_sym(".ENDR", P_ENDR, S, &pseudo_section, &system_st); + add_sym(".EOT", P_EOT, S, &pseudo_section, &system_st); + add_sym(".ERROR", P_ERROR, S, &pseudo_section, &system_st); + add_sym(".EVEN", P_EVEN, S, &pseudo_section, &system_st); + add_sym(".FLT2", P_FLT2, S, &pseudo_section, &system_st); + add_sym(".FLT4", P_FLT4, S, &pseudo_section, &system_st); + add_sym(".GLOBL", P_GLOBL, S, &pseudo_section, &system_st); + add_sym(".IDENT", P_IDENT, S, &pseudo_section, &system_st); + add_sym(".IF", P_IF, S, &pseudo_section, &system_st); + add_sym(".IFDF", P_IFDF, S, &pseudo_section, &system_st); + add_sym(".IFNDF", P_IFDF, S, &pseudo_section, &system_st); + add_sym(".IFF", P_IFF, S, &pseudo_section, &system_st); + add_sym(".IFT", P_IFT, S, &pseudo_section, &system_st); + add_sym(".IFTF", P_IFTF, S, &pseudo_section, &system_st); + add_sym(".IIF", P_IIF, S, &pseudo_section, &system_st); + add_sym(".INCLUDE", P_INCLUDE, S, &pseudo_section, &system_st); + add_sym(".IRP", P_IRP, S, &pseudo_section, &system_st); + add_sym(".IRPC", P_IRPC, S, &pseudo_section, &system_st); + add_sym(".LIBRARY", P_LIBRARY, S, &pseudo_section, &system_st); + add_sym(".LIMIT", P_LIMIT, S, &pseudo_section, &system_st); + add_sym(".LIST", P_LIST, S, &pseudo_section, &system_st); + add_sym(".MCALL", P_MCALL, S, &pseudo_section, &system_st); + add_sym(".MEXIT", P_MEXIT, S, &pseudo_section, &system_st); + add_sym(".NARG", P_NARG, S, &pseudo_section, &system_st); + add_sym(".NCHR", P_NCHR, S, &pseudo_section, &system_st); + add_sym(".NLIST", P_NLIST, S, &pseudo_section, &system_st); + add_sym(".NTYPE", P_NTYPE, S, &pseudo_section, &system_st); + add_sym(".ODD", P_ODD, S, &pseudo_section, &system_st); + add_sym(".PACKED", P_PACKED, S, &pseudo_section, &system_st); + add_sym(".PAGE", P_PAGE, S, &pseudo_section, &system_st); + add_sym(".PRINT", P_PRINT, S, &pseudo_section, &system_st); + add_sym(".PSECT", P_PSECT, S, &pseudo_section, &system_st); + add_sym(".RADIX", P_RADIX, S, &pseudo_section, &system_st); + add_sym(".RAD50", P_RAD50, S, &pseudo_section, &system_st); + add_sym(".REM", P_REM, S, &pseudo_section, &system_st); + add_sym(".REPT", P_REPT, S, &pseudo_section, &system_st); + add_sym(".RESTORE", P_RESTORE, S, &pseudo_section, &system_st); + add_sym(".SAVE", P_SAVE, S, &pseudo_section, &system_st); + add_sym(".SBTTL", P_SBTTL, S, &pseudo_section, &system_st); + add_sym(".TITLE", P_TITLE, S, &pseudo_section, &system_st); + add_sym(".WORD", P_WORD, S, &pseudo_section, &system_st); + add_sym(".MACRO", P_MACRO, S, &pseudo_section, &system_st); + add_sym(".WEAK", P_WEAK, S, &pseudo_section, &system_st); + +#undef S add_sym("ADC", I_ADC, OC_1GEN, &instruction_section, &system_st); add_sym("ADCB", I_ADCB, OC_1GEN, &instruction_section, &system_st); @@ -413,56 +523,127 @@ void add_symbols( add_sym("XFC", I_XFC, OC_NONE, &instruction_section, &system_st); add_sym("XOR", I_XOR, OC_JSR, &instruction_section, &system_st); add_sym("MFPT", I_MFPT, OC_NONE, &instruction_section, &system_st); + add_sym("CSM", I_CSM, OC_1GEN, &instruction_section, &system_st); + add_sym("TSTSET", I_TSTSET, OC_1GEN, &instruction_section, &system_st); + add_sym("WRTLCK", I_WRTLCK, OC_1GEN, &instruction_section, &system_st); - add_sym("ABSD", I_ABSD, OC_1GEN, &instruction_section, &system_st); - add_sym("ABSF", I_ABSF, OC_1GEN, &instruction_section, &system_st); - add_sym("ADDD", I_ADDD, OC_1FIS, &instruction_section, &system_st); - add_sym("ADDF", I_ADDF, OC_1FIS, &instruction_section, &system_st); + /* FPP instructions */ + add_sym("ABSD", I_ABSD, OC_FPP_FDST, &instruction_section, &system_st); + add_sym("ABSF", I_ABSF, OC_FPP_FDST, &instruction_section, &system_st); + add_sym("ADDD", I_ADDD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("ADDF", I_ADDF, OC_FPP_FSRCAC, &instruction_section, &system_st); add_sym("CFCC", I_CFCC, OC_NONE, &instruction_section, &system_st); - add_sym("CLRD", I_CLRD, OC_1GEN, &instruction_section, &system_st); - add_sym("CLRF", I_CLRF, OC_1GEN, &instruction_section, &system_st); - add_sym("CMPD", I_CMPD, OC_1FIS, &instruction_section, &system_st); - add_sym("CMPF", I_CMPF, OC_1FIS, &instruction_section, &system_st); - add_sym("DIVD", I_DIVD, OC_1FIS, &instruction_section, &system_st); - add_sym("DIVF", I_DIVF, OC_1FIS, &instruction_section, &system_st); - add_sym("LDCDF", I_LDCDF, OC_1FIS, &instruction_section, &system_st); - add_sym("LDCID", I_LDCID, OC_1FIS, &instruction_section, &system_st); - add_sym("LDCIF", I_LDCIF, OC_1FIS, &instruction_section, &system_st); - add_sym("LDCLD", I_LDCLD, OC_1FIS, &instruction_section, &system_st); - add_sym("LDCLF", I_LDCLF, OC_1FIS, &instruction_section, &system_st); - add_sym("LDD", I_LDD, OC_1FIS, &instruction_section, &system_st); - add_sym("LDEXP", I_LDEXP, OC_1FIS, &instruction_section, &system_st); - add_sym("LDF", I_LDF, OC_1FIS, &instruction_section, &system_st); + add_sym("CLRD", I_CLRD, OC_FPP_FDST, &instruction_section, &system_st); + add_sym("CLRF", I_CLRF, OC_FPP_FDST, &instruction_section, &system_st); + add_sym("CMPD", I_CMPD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("CMPF", I_CMPF, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("DIVD", I_DIVD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("DIVF", I_DIVF, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("LDCDF", I_LDCDF, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("LDCFD", I_LDCFD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("LDCID", I_LDCID, OC_FPP_SRCAC, &instruction_section, &system_st); + add_sym("LDCIF", I_LDCIF, OC_FPP_SRCAC, &instruction_section, &system_st); + add_sym("LDCLD", I_LDCLD, OC_FPP_SRCAC, &instruction_section, &system_st); + add_sym("LDCLF", I_LDCLF, OC_FPP_SRCAC, &instruction_section, &system_st); + add_sym("LDD", I_LDD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("LDEXP", I_LDEXP, OC_FPP_SRCAC, &instruction_section, &system_st); + add_sym("LDF", I_LDF, OC_FPP_FSRCAC, &instruction_section, &system_st); add_sym("LDFPS", I_LDFPS, OC_1GEN, &instruction_section, &system_st); - add_sym("MODD", I_MODD, OC_1FIS, &instruction_section, &system_st); - add_sym("MODF", I_MODF, OC_1FIS, &instruction_section, &system_st); - add_sym("MULD", I_MULD, OC_1FIS, &instruction_section, &system_st); - add_sym("MULF", I_MULF, OC_1FIS, &instruction_section, &system_st); - add_sym("NEGD", I_NEGD, OC_1GEN, &instruction_section, &system_st); - add_sym("NEGF", I_NEGF, OC_1GEN, &instruction_section, &system_st); + add_sym("MODD", I_MODD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("MODF", I_MODF, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("MULD", I_MULD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("MULF", I_MULF, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("NEGD", I_NEGD, OC_FPP_FDST, &instruction_section, &system_st); + add_sym("NEGF", I_NEGF, OC_FPP_FDST, &instruction_section, &system_st); add_sym("SETD", I_SETD, OC_NONE, &instruction_section, &system_st); add_sym("SETF", I_SETF, OC_NONE, &instruction_section, &system_st); add_sym("SETI", I_SETI, OC_NONE, &instruction_section, &system_st); add_sym("SETL", I_SETL, OC_NONE, &instruction_section, &system_st); add_sym("STA0", I_STA0, OC_NONE, &instruction_section, &system_st); add_sym("STB0", I_STB0, OC_NONE, &instruction_section, &system_st); - add_sym("STCDF", I_STCDF, OC_2FIS, &instruction_section, &system_st); - add_sym("STCDI", I_STCDI, OC_2FIS, &instruction_section, &system_st); - add_sym("STCDL", I_STCDL, OC_2FIS, &instruction_section, &system_st); - add_sym("STCFD", I_STCFD, OC_2FIS, &instruction_section, &system_st); - add_sym("STCFI", I_STCFI, OC_2FIS, &instruction_section, &system_st); - add_sym("STCFL", I_STCFL, OC_2FIS, &instruction_section, &system_st); - add_sym("STD", I_STD, OC_2FIS, &instruction_section, &system_st); - add_sym("STEXP", I_STEXP, OC_2FIS, &instruction_section, &system_st); - add_sym("STF", I_STF, OC_2FIS, &instruction_section, &system_st); + add_sym("STCDF", I_STCDF, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STCDI", I_STCDI, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STCDL", I_STCDL, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STCFD", I_STCFD, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STCFI", I_STCFI, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STCFL", I_STCFL, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STD", I_STD, OC_FPP_ACFDST, &instruction_section, &system_st); + add_sym("STEXP", I_STEXP, OC_FPP_ACDST, &instruction_section, &system_st); + add_sym("STF", I_STF, OC_FPP_ACFDST, &instruction_section, &system_st); add_sym("STFPS", I_STFPS, OC_1GEN, &instruction_section, &system_st); add_sym("STST", I_STST, OC_1GEN, &instruction_section, &system_st); - add_sym("SUBD", I_SUBD, OC_1FIS, &instruction_section, &system_st); - add_sym("SUBF", I_SUBF, OC_1FIS, &instruction_section, &system_st); - add_sym("TSTD", I_TSTD, OC_1GEN, &instruction_section, &system_st); - add_sym("TSTF", I_TSTF, OC_1GEN, &instruction_section, &system_st); + add_sym("SUBD", I_SUBD, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("SUBF", I_SUBF, OC_FPP_FSRCAC, &instruction_section, &system_st); + add_sym("TSTD", I_TSTD, OC_FPP_FDST, &instruction_section, &system_st); + add_sym("TSTF", I_TSTF, OC_FPP_FDST, &instruction_section, &system_st); - /* FIXME: The CIS instructions are missing! */ + /* The CIS instructions */ + add_sym("ADDNI", I_ADDN|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("ADDN", I_ADDN, OC_NONE, &instruction_section, &system_st); + add_sym("ADDPI", I_ADDP|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("ADDP", I_ADDP, OC_NONE, &instruction_section, &system_st); + add_sym("ASHNI", I_ASHN|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("ASHN", I_ASHN, OC_NONE, &instruction_section, &system_st); + add_sym("ASHPI", I_ASHP|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("ASHP", I_ASHP, OC_NONE, &instruction_section, &system_st); + add_sym("CMPCI", I_CMPC|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("CMPC", I_CMPC, OC_NONE, &instruction_section, &system_st); + add_sym("CMPNI", I_CMPN|I_CIS_I, OC_CIS2, &instruction_section, &system_st); + add_sym("CMPN", I_CMPN, OC_NONE, &instruction_section, &system_st); + add_sym("CMPPI", I_CMPP|I_CIS_I, OC_CIS2, &instruction_section, &system_st); + add_sym("CMPP", I_CMPP, OC_NONE, &instruction_section, &system_st); + add_sym("CVTLNI",I_CVTLN|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("CVTLN", I_CVTLN, OC_NONE, &instruction_section, &system_st); + add_sym("CVTLPI",I_CVTLP|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("CVTLP", I_CVTPL, OC_NONE, &instruction_section, &system_st); + add_sym("CVTNLI",I_CVTNL|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("CVTNL", I_CVTNL, OC_NONE, &instruction_section, &system_st); + add_sym("CVTPLI",I_CVTPL|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("CVTPL", I_CVTPL, OC_NONE, &instruction_section, &system_st); + add_sym("CVTNPI",I_CVTNP|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("CVTNP", I_CVTNP, OC_NONE, &instruction_section, &system_st); + add_sym("CVTPNI",I_CVTPN|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("CVTPN", I_CVTPN, OC_NONE, &instruction_section, &system_st); + add_sym("DIVPI", I_DIVP|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("DIVP", I_DIVP, OC_NONE, &instruction_section, &system_st); + add_sym("LOCCI", I_LOCC|I_CIS_I, OC_CIS2, &instruction_section, &system_st); + add_sym("LOCC", I_LOCC, OC_NONE, &instruction_section, &system_st); + add_sym("L2D0", I_L2Dr+0, OC_NONE, &instruction_section, &system_st); + add_sym("L2D1", I_L2Dr+1, OC_NONE, &instruction_section, &system_st); + add_sym("L2D2", I_L2Dr+2, OC_NONE, &instruction_section, &system_st); + add_sym("L2D3", I_L2Dr+3, OC_NONE, &instruction_section, &system_st); + add_sym("L2D4", I_L2Dr+4, OC_NONE, &instruction_section, &system_st); + add_sym("L2D5", I_L2Dr+5, OC_NONE, &instruction_section, &system_st); + add_sym("L2D6", I_L2Dr+6, OC_NONE, &instruction_section, &system_st); + add_sym("L2D7", I_L2Dr+7, OC_NONE, &instruction_section, &system_st); + add_sym("L3D0", I_L3Dr+0, OC_NONE, &instruction_section, &system_st); + add_sym("L3D1", I_L3Dr+1, OC_NONE, &instruction_section, &system_st); + add_sym("L3D2", I_L3Dr+2, OC_NONE, &instruction_section, &system_st); + add_sym("L3D3", I_L3Dr+3, OC_NONE, &instruction_section, &system_st); + add_sym("L3D4", I_L3Dr+4, OC_NONE, &instruction_section, &system_st); + add_sym("L3D5", I_L3Dr+5, OC_NONE, &instruction_section, &system_st); + add_sym("L3D6", I_L3Dr+6, OC_NONE, &instruction_section, &system_st); + add_sym("L3D7", I_L3Dr+7, OC_NONE, &instruction_section, &system_st); + add_sym("MATCI", I_MATC|I_CIS_I, OC_CIS2, &instruction_section, &system_st); + add_sym("MATC", I_MATC, OC_NONE, &instruction_section, &system_st); + add_sym("MOVCI", I_MOVC|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("MOVC", I_MOVC, OC_NONE, &instruction_section, &system_st); + add_sym("MOVRCI",I_MOVRC|I_CIS_I,OC_CIS3, &instruction_section, &system_st); + add_sym("MOVRC", I_MOVRC, OC_NONE, &instruction_section, &system_st); + add_sym("MOVTCI",I_MOVTC|I_CIS_I,OC_CIS4, &instruction_section, &system_st); + add_sym("MOVTC", I_MOVTC, OC_NONE, &instruction_section, &system_st); + add_sym("MULPI", I_MULP|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("MULP", I_MULP, OC_NONE, &instruction_section, &system_st); + add_sym("SCANCI",I_SCANC|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("SCANC", I_SCANC, OC_NONE, &instruction_section, &system_st); + add_sym("SKPCI", I_SKPC|I_CIS_I, OC_CIS2, &instruction_section, &system_st); + add_sym("SKPC", I_SKPC, OC_NONE, &instruction_section, &system_st); + add_sym("SPANCI",I_SPANC|I_CIS_I,OC_CIS2, &instruction_section, &system_st); + add_sym("SPANC", I_SPANC, OC_NONE, &instruction_section, &system_st); + add_sym("SUBNI", I_SUBN|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("SUBN", I_SUBN, OC_NONE, &instruction_section, &system_st); + add_sym("SUBPI", I_SUBP|I_CIS_I, OC_CIS3, &instruction_section, &system_st); + add_sym("SUBP", I_SUBP, OC_NONE, &instruction_section, &system_st); add_sym(current_section->label, 0, 0, current_section, §ion_st); } @@ -536,18 +717,19 @@ void list_symbol_table( symbolp = symbols; /* Print the listing in NCOLS columns. */ - int ncols = (132 / (longest_symbol + 18)); + int ncols = (132 / (longest_symbol + 19)); int nlines = (nsyms + ncols - 1) / ncols; int line; /* - * DIRER$ 004562RGX 006 - * ^ ^ ^ ^-- for R symbols: program segment number - * | | +-- Flags: R = relocatable - * | | G = global - * | | X = implicit global - * | | L = local - * | | W = weak - * | +- value, ****** for if it was not a definition + * DIRER$ =%004562RGX 006 + * ^ ^^ ^ ^-- for R symbols: program segment number + * | || +-- Flags: R = relocatable + * | || G = global + * | || X = implicit global + * | || L = local + * | || W = weak + * | |+- value, ****** for if it was not a definition + * | +-- % for a register * +- label name */ @@ -555,9 +737,11 @@ void list_symbol_table( int i; for (i = line; i < nsyms; i += nlines) { sym = symbols[i]; + check_sym_invariants(sym, __FILE__, __LINE__); fprintf(lstfile,"%-*s", longest_symbol, sym->label); fprintf(lstfile,"%c", (sym->section->flags & PSECT_REL) ? ' ' : '='); + fprintf(lstfile,"%c", (sym->section->type == SECTION_REGISTER) ? '%' : ' '); if (!(sym->flags & SYMBOLFLAG_DEFINITION)) { fprintf(lstfile,"******"); } else { @@ -585,6 +769,8 @@ void list_symbol_table( for (i = 0; i < sector; i++) { list_section(sections[i]); } + + free(symbols); } void list_section( diff --git a/crossassemblers/macro11/symbols.h b/crossassemblers/macro11/symbols.h index de2bf7c..42e0a6c 100644 --- a/crossassemblers/macro11/symbols.h +++ b/crossassemblers/macro11/symbols.h @@ -25,6 +25,8 @@ typedef struct section { unsigned sector; /* Used for complex relocation, and naught else */ } SECTION; +#define SYM_IS_IMPORTED(sym) ((sym->flags & (SYMBOLFLAG_GLOBAL | SYMBOLFLAG_DEFINITION)) == SYMBOLFLAG_GLOBAL) + /* Symbol table entries */ typedef struct symbol { @@ -104,7 +106,8 @@ enum pseudo_ops { P_ASCII, P_IFDF }; -enum instruction_ops { I_ADC = 0005500, +enum instruction_ops { + I_ADC = 0005500, I_ADCB = 0105500, I_ADD = 0060000, I_ASH = 0072000, @@ -154,10 +157,10 @@ enum instruction_ops { I_ADC = 0005500, I_DECB = 0105300, I_DIV = 0071000, I_EMT = 0104000, - I_FADD = 0075000, - I_FDIV = 0075030, - I_FMUL = 0075020, - I_FSUB = 0075010, + I_FADD = 0075000, /* FIS */ + I_FDIV = 0075030, /* FIS */ + I_FMUL = 0075020, /* FIS */ + I_FSUB = 0075010, /* FIS */ I_HALT = 0000000, I_INC = 0005200, I_INCB = 0105200, @@ -207,7 +210,39 @@ enum instruction_ops { I_ADC = 0005500, I_XFC = 0076700, I_XOR = 0074000, I_MFPT = 0000007, - /* CIS not implemented - maybe later */ + I_CSM = 0007000, + I_TSTSET = 0007200, + I_WRTLCK = 0007300, + /* CIS - Commercial Instruction Set */ + I_CIS_I = 0000100, /* Inline arguments */ + I_CIS_P = 0000020, /* Packed instead of Numeric */ + I_ADDN = 0076050, + I_ADDP = 0076070, + I_ASHN = 0076056, + I_ASHP = 0076076, + I_CMPC = 0076044, + I_CMPN = 0076052, + I_CMPP = 0076072, + I_CVTLN = 0076057, + I_CVTLP = 0076077, + I_CVTNL = 0076053, + I_CVTPL = 0076073, + I_CVTNP = 0076055, + I_CVTPN = 0076054, + I_DIVP = 0076075, + I_LOCC = 0076040, + I_L2Dr = 0076020, + I_L3Dr = 0076060, + I_MATC = 0076045, + I_MOVC = 0076030, + I_MOVRC= 0076031, + I_MOVTC= 0076032, + I_MULP = 0076074, + I_SCANC= 0076042, + I_SKPC = 0076041, + I_SPANC= 0076043, + I_SUBN = 0076051, + I_SUBP = 0076071, /* FPU */ I_ABSD = 0170600, I_ABSF = 0170600, @@ -279,10 +314,23 @@ enum operand_codes { OC_MASK = 0xff00, /* FADD, FSUB, FMUL, FDIV, RTS */ OC_SOB = 0x0800, /* SOB */ - OC_1FIS = 0x0900, - /* FIS (reg, gen) */ - OC_2FIS = 0x0a00, - /* FIS (gen, reg) */ + OC_FPP_FSRCAC = 0x0900, + /* FPP (fsrc gen, floating ac 0-3) */ + OC_FPP_SRCAC = 0x0a00, + /* FPP (src gen, floating ac 0-3) */ + OC_FPP_ACFDST = 0x0b00, + OC_FPP_ACDST = OC_FPP_ACFDST, + /* FPP (floating ac 0-3, fdst gen) */ + /* OC_FPP_FSRC = 0x0c00, */ + /* FPP fp source: immediate or fsrc gen */ + OC_FPP_FDST = OC_1GEN, + /* FPP fdst general destination */ + OC_CIS2 = 0x0d00, + /* CIS with 2 parameter words */ + OC_CIS3 = 0x0e00, + /* CIS with 3 parameter words */ + OC_CIS4 = 0x0f00, + /* CIS with 4 parameter words */ OC__LAST = 0xff00 }; @@ -322,6 +370,8 @@ extern SYMBOL_TABLE macro_st; /* Macros */ extern SYMBOL_TABLE implicit_st; /* The symbols which may be implicit globals */ +extern SYMBOL_TABLE undefined_st; /* The symbols which may be undefined */ + #endif int hash_name( diff --git a/crossassemblers/macro11/tests/2.11BSD-m11-code.lst.ok b/crossassemblers/macro11/tests/2.11BSD-m11-code.lst.ok new file mode 100644 index 0000000..ee7215a --- /dev/null +++ b/crossassemblers/macro11/tests/2.11BSD-m11-code.lst.ok @@ -0,0 +1,1293 @@ + 1 ;;;; Wrapper for 2.11BSD/m11/code.m11 + 2 .list + 3 .list + 4 .list + 5 000001 debug = 1 + 6 .include "2.11BSD/m11/at.sml" + 1 .title at.sml - assembler/translator system macros + 2 ; @(#)at.sml 1.3 11/3/82 + 3 + 4 .ident /10may4/ + 5 + 6 .macro always ;all files of macro + 7 + 8 .macro .data + 9 entsec .data + 10 .endm .data + 11 + 12 .macro .text + 13 entsec .text + 14 .endm + 15 + 16 .macro .bss + 17 entsec .bss + 18 .endm + 19 + 20 mk.symbol=1 ;one to make symbols, 0 otherwise + 21 x40= 0 + 22 pdpv45= 0 ; host machine has 'mul', 'div', sob' instrucs. + 23 ; if not you will have to write macros for them + 24 $timdf= 7 ; California Time Zone + 25 ; should really use ftime(2) for this and for + 26 ; DST. + 27 ;xfltg= 0 ;define to assmbl out floating hardware + 28 rsx11d = 0 ; rsx11d features + 29 debug = 0 ; <<< REEDS if non zero includes debug junk + 30 + 31 ft.id= 1 ;have set i & d. set =0 if not + 32 + 33 ft.unx = 1 ; this macro-11 is for UNIX. =0 if not. + 34 + 35 .nlist bex + 36 + 37 tab= 11 + 38 lf= 12 + 39 vt= 13 + 40 ff= 14 + 41 cr= 15 + 42 space= 40 + 43 + 44 bpmb = 20 ;bytes per macro block + 45 + 46 + 47 + 48 + 49 + 50 .psect .text con, shr, gbl,ins + 51 .psect .data con, dat, prv, gbl + 52 .psect .bss con, bss, gbl + 53 + 54 .psect dpure con, dat, prv, gbl + 55 .psect mixed con, prv, gbl + 56 .psect errmes con, dat, prv, gbl + 57 .psect impure con, bss, gbl + 58 .psect imppas con, bss, gbl + 59 .psect implin con, bss, gbl + 60 .psect swtsec con, dat, prv, gbl ; unix command line flags + 61 .psect cndsec con, dat, prv, gbl ; gt, le, equ, etc. for '.if' + 62 .psect crfsec con, dat, prv, gbl ; args for -cr flag + 63 .psect edtsec con, dat, prv, gbl ; args for .enabl + 64 .psect lctsec con, dat, prv, gbl ; args for .list + 65 .psect psasec con, dat, prv, gbl + 66 .psect pstsec con, dat, prv, gbl + 67 .psect rolbas con, dat, prv, gbl ; core allocation: starts of tables + 68 .psect rolsiz con, dat, prv, gbl ; sizes of table entries + 69 .psect roltop con, dat, prv, gbl ; tops of tables + 70 .psect xpcor con,bss , gbl ; this one MUST come last in core + 71 + 72 + 72 + 73 .macro entsec name ;init a section + 74 .psect name con + 75 .endm entsec + 76 + 77 + 78 + 79 .macro jeq x,?fred + 80 bne fred + 81 jmp x + 82 fred: + 83 .endm + 84 .macro jne x,?fred + 85 beq fred + 86 jmp x + 87 fred: + 88 .endm + 89 .macro xitsec + 90 entsec .text + 91 .endm xitsec + 92 + 93 + 94 .macro call address + 95 jsr pc,address + 96 .endm + 97 + 98 .macro return + 99 rts pc + 100 .endm + 101 + 102 + 103 .macro always + 104 .nlist bex + 105 .endm always + 106 .endm always + 107 + 108 + 109 000001 .if ne debug + 110 + 111 .macro ndebug n + 112 .globl ndebug,..z + 113 mov n,..z + 114 call ndebug + 115 .endm + 116 + 117 .macro sdebug string + 118 .globl sdebug,..z,..zbuf + 119 x = 0 + 120 .irpc t, + 121 movb #''t,..zbuf+x + 122 x = x+1 + 123 .endm + 124 movb #0,..zbuf+x + 125 mov #..zbuf,..z + 126 call sdebug + 127 .endm + 128 + 129 .iff + 130 + 131 .macro ndebug n + 132 .endm + 133 + 134 .macro sdebug string + 135 .endm + 136 + 137 .endc + 138 + 139 + 140 .macro param mne, value ;define default parameters + 141 .iif ndf mne, mne= value + 142 .list + 143 mne= mne + 144 .nlist + 145 .endm + 145 + 146 .macro putkb addr ;list to kb + 147 .globl putkb + 148 mov addr,r0 + 149 call putkb + 150 .endm + 151 + 152 .macro putlp addr ;list to lp + 153 .globl putlp + 154 mov addr,r0 + 155 call putlp + 156 .endm + 157 + 158 .macro putkbl addr ;list to kb and lp + 159 .globl putkbl + 160 mov addr,r0 + 161 call putkbl + 162 .endm + 163 + 164 + 165 .macro xmit wrdcnt ;move small # of words + 166 .globl xmit0 + 167 call xmit0- + 168 .endm xmit + 169 + 170 + 171 ;the macro "genswt" is used to specify a command + 172 ;string switch (1st argument) and the address of + 173 ;the routine to be called when encountered (2nd arg). + 174 ; the switch is made upper-case. + 175 + 176 .macro genswt mne,addr,?label + 177 entsec swtsec + 178 label: .irpc x,mne + 179 .if ge ''x-141 + 180 .if le ''x-172 + 181 .byte ''x-40 + 182 .iff + 183 .byte ''x + 184 .endc + 185 .iff + 186 .byte ''x + 187 .endc + 188 .endm + 189 .iif ne <.-label&1>, .byte 0 + 190 .word addr + 191 xitsec + 192 .endm + 192 + 193 .macro zread chan + 194 .globl zread + 195 mov #chan'chn,r0 + 196 call zread + 197 .endm zread + 198 + 199 .macro zwrite chan + 200 .globl zwrite + 201 mov #chan'chn,r0 + 202 call zwrite + 203 .endm zwrite + 203 + 204 .macro genedt mne,subr ;gen enable/disable table + 205 entsec edtsec + 206 .rad50 /mne/ + 207 .if nb subr + 208 .word subr + 209 .iff + 210 .word cpopj + 211 .endc + 212 .word ed.'mne + 213 xitsec + 214 .endm genedt + 215 + 216 + 217 ;the macro "gencnd" is used to specify conditional + 218 ;arguments. it takes two or three arguments: + 219 + 220 ; 1- mnemonic + 221 ; 2- subroutine to be called + 222 ; 3- if non-blank, complement condition + 223 + 224 .macro gencnd mne,subr,toggle ;generate conditional + 225 entsec cndsec + 226 .rad50 /mne/ + 227 .if b + 228 .word subr + 229 .iff + 230 .word subr+1 + 231 .endc + 232 xitsec + 233 .endm + 233 + 234 .macro ch.mne + 235 + 236 ch.ior= '! + 237 ch.qtm= '" + 238 ch.hsh= '# + 239 ch.dol= '$ + 240 ch.pct= '% + 241 ch.and= '& + 242 ch.xcl= '' + 243 + 244 ch.lp= '( + 245 ch.rp= ') + 246 ch.mul= '* + 247 ch.add= '+ + 248 ch.com= ', + 249 ch.sub= '- + 250 ch.dot= '. + 251 ch.div= '/ + 252 + 253 ch.col= ': + 254 ch.smc= '; + 255 ch.lab= '< + 256 ch.equ= '= + 257 ch.rab= '> + 258 ch.qm= '? + 259 + 260 ch.ind= '@ + 261 ch.bsl= '\ + 262 ch.uar= '^ + 263 + 264 let.a= 'a&^c40 + 265 let.b= 'b&^c40 + 266 let.c= 'c&^c40 + 267 let.d= 'd&^c40 + 268 let.e= 'e&^c40 + 269 let.f= 'f&^c40 + 270 let.g= 'g&^c40 + 271 let.o= 'o&^c40 + 272 let.p= 'p&^c40 + 273 let.r= 'r&^c40 + 274 let.z= 'z&^c40 + 275 + 276 dig.0= '0 + 277 dig.9= '9 + 278 .macro ch.mne + 279 .endm ch.mne + 280 .endm ch.mne + 281 + 282 .macro error num,arg, mess ,?x + 283 sdebug + 284 .globl err.'arg,ern'num, errbts,errref + 285 .if b + 286 deliberate error mistake + 287 .endc + 288 .if dif 0,num + 289 .globl err.xx + 290 tst err.xx + 291 bne x + 292 mov #ern'num,err.xx + 293 x: + 294 .endc + 295 bis #err.'arg,errbts + 296 .endm + 297 + 298 + 299 + 300 .macro setnz addr ;set addr to non-zero for t/f flags + 301 mov sp,addr + 302 .endm + 303 + 304 + 305 .macro bisbic arg ; used by .list/.nlist, .enabl/.dsabl + 306 .globl bisbic + 307 mov #arg,-(sp) + 308 call bisbic + 309 tst (sp)+ + 310 .endm + 310 + 311 ;roll handler calls + 312 + 313 .macro search rolnum ;binary search + 314 mov #rolnum,r0 + 315 .globl search + 316 call search + 317 .endm + 318 + 319 .macro scan rolnum ;linear scan + 320 mov #rolnum,r0 + 321 .globl scan + 322 call scan + 323 .endm + 324 + 325 .macro scanw rolnum ;linear scan, one word + 326 mov #rolnum,r0 + 327 .globl scanw + 328 call scanw + 329 .endm + 330 + 331 .macro next rolnum ;fetch next entry + 332 mov #rolnum,r0 + 333 .globl next + 334 call next + 335 .endm + 336 + 337 .macro append rolnum ;append to end of roll + 338 mov #rolnum,r0 + 339 .globl append + 340 call append + 341 .endm + 342 + 343 .macro zap rolnum ;clear roll + 344 mov #rolnum,r0 + 345 .globl zap + 346 call zap + 347 .endm + 348 + 349 ; call insert ;insert (must be preceded by one + 350 ;of the above to set pointers) + 351 ; call setrol ;save and set regs for above + 351 + 352 ;flags used in symbol table mode + 353 + 354 .macro st.flg + 355 + 356 .if le ft.unx + 357 + 358 ovrflg= 000004 ;overlay (psect only) + 359 defflg= 000010 ;defined + 360 relflg= 000040 ;relocatable + 361 glbflg= 000100 ;global + 362 dfgflg= 000200 ; default global ... reeds's guess + 363 + 364 + 365 .endc + 366 + 367 .if gt ft.unx + 368 + 369 ; ****** these should not be changed!! ****** + 370 shrflg= 000001 ;shareable (psect only) + 371 .if gt ft.id + 372 insflg= shrflg*2 ;instruction space (psect only) + 373 bssflg= insflg*2 ;blank section (psect only) + 374 m.idf= shrflg!insflg!bssflg ;mask to turn them off + 375 .iff + 376 bssflg= shrflg*2 + 377 m.idf= shrflg!bssflg + 378 .endc + 379 b.idf= 1 ;shift count to make above bits word offset + 380 ; *********************************** + 381 defflg= 000010 ;defined + 382 ovrflg= 000020 ;overlay (psect only) + 383 relflg= 000040 ;relocatable + 384 glbflg= 000100 ;global + 385 dfgflg= 000200 ; default global ... reeds's guess + 386 + 387 .endc + 388 + 389 ; + 390 ; default psect attribs. + 391 ; can be changed, but make sure all customers know about + 392 ; it, including all the linkers. + 393 ; + 394 pattrs=relflg!defflg ; For .psects and blank .csects + 395 aattrs=glbflg!defflg!ovrflg ; For .asect + 396 cattrs=glbflg!relflg!defflg!ovrflg ; For named .csects + 397 + 398 regflg= 000001 ;register + 399 lblflg= 000002 ;label + 400 mdfflg= 000004 ;multilpy defined + 401 .macro st.flg + 402 .endm + 403 .endm st.flg + 404 + 405 + 406 + 407 .macro ct.mne + 408 .globl cttbl + 409 ct.eol = 000 ; eol + 410 ct.com = 001 ; comma + 411 ct.tab = 002 ; tab + 412 ct.sp = 004 ; space + 413 ct.pcx = 010 ; printing character + 414 ct.num = 020 ; numeric + 415 ct.alp = 040 ; alpha, dot, dollar + 416 ct.lc = 100 ; lower case alpha + 417 ct.smc = 200 ; semi-colon (sign bit) + 418 + 419 ct.pc = ct.com!ct.smc!ct.pcx!ct.num!ct.alp + 420 .macro ct.mne + 421 .endm ct.mne + 422 .endm ct.mne + 423 + 424 + 425 .end + 425 + 7 .include "2.11BSD/m11/code.m11" + 1 .title code + 2 + 3 .ident /10may4/ + 4 + 5 .mcall (at)always,st.flg,xmit,zwrite + 6 000000 always + 1 + 2 .macro .data + 3 entsec .data + 4 .endm .data + 5 + 6 .macro .text + 7 entsec .text + 8 .endm + 9 + 10 .macro .bss + 11 entsec .bss + 12 .endm + 13 + 14 000001 mk.symbol=1 ;one to make symbols, 0 otherwise + 15 000000 x40= 0 + 16 000000 pdpv45= 0 ; host machine has 'mul', 'div', sob' instrucs. + 17 ; if not you will have to write macros for them + 18 000007 $timdf= 7 ; California Time Zone + 19 ; should really use ftime(2) for this and for + 20 ; DST. + 21 ;xfltg= 0 ;define to assmbl out floating hardware + 22 000000 rsx11d = 0 ; rsx11d features + 23 000000 debug = 0 ; <<< REEDS if non zero includes debug junk + 24 + 25 000001 ft.id= 1 ;have set i & d. set =0 if not + 26 + 27 000001 ft.unx = 1 ; this macro-11 is for UNIX. =0 if not. + 28 + 29 .nlist bex + 30 + 31 000011 tab= 11 + 32 000012 lf= 12 + 33 000013 vt= 13 + 34 000014 ff= 14 + 35 000015 cr= 15 + 36 000040 space= 40 + 37 + 38 000020 bpmb = 20 ;bytes per macro block + 39 + 40 + 41 + 42 + 43 +./2.11BSD/m11/code.m11:6->ALWAYS:44: ***ERROR Unknown flag SHR given to .PSECT directive + 44 .psect .text con, shr, gbl,ins +./2.11BSD/m11/code.m11:6->ALWAYS:45: ***ERROR Unknown flag DAT given to .PSECT directive + 45 .psect .data con, dat, prv, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:46: ***ERROR Unknown flag BSS given to .PSECT directive + 46 .psect .bss con, bss, gbl + 47 +./2.11BSD/m11/code.m11:6->ALWAYS:48: ***ERROR Unknown flag DAT given to .PSECT directive + 48 .psect dpure con, dat, prv, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:49: ***ERROR Unknown flag PRV given to .PSECT directive + 49 .psect mixed con, prv, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:50: ***ERROR Unknown flag DAT given to .PSECT directive + 50 .psect errmes con, dat, prv, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:51: ***ERROR Unknown flag BSS given to .PSECT directive + 51 .psect impure con, bss, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:52: ***ERROR Unknown flag BSS given to .PSECT directive + 52 .psect imppas con, bss, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:53: ***ERROR Unknown flag BSS given to .PSECT directive + 53 .psect implin con, bss, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:54: ***ERROR Unknown flag DAT given to .PSECT directive + 54 .psect swtsec con, dat, prv, gbl ; unix command line flags +./2.11BSD/m11/code.m11:6->ALWAYS:55: ***ERROR Unknown flag DAT given to .PSECT directive + 55 .psect cndsec con, dat, prv, gbl ; gt, le, equ, etc. for '.if' +./2.11BSD/m11/code.m11:6->ALWAYS:56: ***ERROR Unknown flag DAT given to .PSECT directive + 56 .psect crfsec con, dat, prv, gbl ; args for -cr flag +./2.11BSD/m11/code.m11:6->ALWAYS:57: ***ERROR Unknown flag DAT given to .PSECT directive + 57 .psect edtsec con, dat, prv, gbl ; args for .enabl +./2.11BSD/m11/code.m11:6->ALWAYS:58: ***ERROR Unknown flag DAT given to .PSECT directive + 58 .psect lctsec con, dat, prv, gbl ; args for .list +./2.11BSD/m11/code.m11:6->ALWAYS:59: ***ERROR Unknown flag DAT given to .PSECT directive + 59 .psect psasec con, dat, prv, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:60: ***ERROR Unknown flag DAT given to .PSECT directive + 60 .psect pstsec con, dat, prv, gbl +./2.11BSD/m11/code.m11:6->ALWAYS:61: ***ERROR Unknown flag DAT given to .PSECT directive + 61 .psect rolbas con, dat, prv, gbl ; core allocation: starts of tables +./2.11BSD/m11/code.m11:6->ALWAYS:62: ***ERROR Unknown flag DAT given to .PSECT directive + 62 .psect rolsiz con, dat, prv, gbl ; sizes of table entries +./2.11BSD/m11/code.m11:6->ALWAYS:63: ***ERROR Unknown flag DAT given to .PSECT directive + 63 .psect roltop con, dat, prv, gbl ; tops of tables +./2.11BSD/m11/code.m11:6->ALWAYS:64: ***ERROR Unknown flag BSS given to .PSECT directive + 64 .psect xpcor con,bss , gbl ; this one MUST come last in core + 65 + 66 + 67 + 68 .macro entsec name ;init a section + 69 .psect name con + 70 .endm entsec + 71 + 72 + 73 + 74 .macro jeq x,?fred + 75 bne fred + 76 jmp x + 77 fred: + 78 .endm + 79 .macro jne x,?fred + 80 beq fred + 81 jmp x + 82 fred: + 83 .endm + 84 .macro xitsec + 85 entsec .text + 86 .endm xitsec + 87 + 88 + 89 .macro call address + 90 jsr pc,address + 91 .endm + 92 + 93 .macro return + 94 rts pc + 95 .endm + 96 + 97 + 98 .macro always + 99 .nlist bex + 100 .endm always + 7 000000 st.flg + 1 + 2 000001 .if le ft.unx + 3 + 4 ovrflg= 000004 ;overlay (psect only) + 5 defflg= 000010 ;defined + 6 relflg= 000040 ;relocatable + 7 glbflg= 000100 ;global + 8 dfgflg= 000200 ; default global ... reeds's guess + 9 + 10 + 11 .endc + 12 + 13 000001 .if gt ft.unx + 14 + 15 ; ****** these should not be changed!! ****** + 16 000001 shrflg= 000001 ;shareable (psect only) + 17 000001 .if gt ft.id + 18 000002 insflg= shrflg*2 ;instruction space (psect only) + 19 000004 bssflg= insflg*2 ;blank section (psect only) + 20 000007 m.idf= shrflg!insflg!bssflg ;mask to turn them off + 21 .iff + 22 bssflg= shrflg*2 + 23 m.idf= shrflg!bssflg + 24 .endc + 25 000001 b.idf= 1 ;shift count to make above bits word offset + 26 ; *********************************** + 27 000010 defflg= 000010 ;defined + 28 000020 ovrflg= 000020 ;overlay (psect only) + 29 000040 relflg= 000040 ;relocatable + 30 000100 glbflg= 000100 ;global + 31 000200 dfgflg= 000200 ; default global ... reeds's guess + 32 + 33 .endc + 34 + 35 ; + 36 ; default psect attribs. + 37 ; can be changed, but make sure all customers know about + 38 ; it, including all the linkers. + 39 ; + 40 000050 pattrs=relflg!defflg ; For .psects and blank .csects + 41 000130 aattrs=glbflg!defflg!ovrflg ; For .asect + 42 000170 cattrs=glbflg!relflg!defflg!ovrflg ; For named .csects + 43 + 44 000001 regflg= 000001 ;register + 45 000002 lblflg= 000002 ;label + 46 000004 mdfflg= 000004 ;multilpy defined + 47 .macro st.flg + 48 .endm + 8 + 9 .mcall (at)genedt,setnz,next,append,zap,error + 10 + 11 .globl objchn, objlen + 12 .globl savreg, ioftbl, buftbl, cnttbl + 13 + 14 .globl dmprld, endp1c, endp2c, pcroll, prgttl + 15 .globl setdsp, setimm, setrld, stcode + 16 + 17 .globl abserr, clcloc, clcnam, clcsec + 18 .globl codrol, endvec, mode, objsec + 19 ;.globl pass, psaflg, rolupd, secrol + 20 .globl pass, rolupd, secrol + 21 .globl sector, setpf0, setpf1, setsec, setxpr + 22 .globl symbol, symrol, value + 23 .globl edmask, ed.abs, ed.pnc + 24 .globl dflgbm, opclas + 24 + 25 000040 cc.opr = 040 + 26 000020 cc.nam = 020 + 27 000010 cc.sec = 010 + 28 000004 cc.val = 004 + 29 000002 cc.dsp = 002 + 30 + 31 + 32 000000 gsdt00= 00*400 ; object module name + 33 000400 gsdt01= 01*400 ; program section name + 34 001000 gsdt02= 02*400 ; internal symbol table + 35 001400 gsdt03= 03*400 ; transfer address + 36 002000 gsdt04= 04*400 ; symbol declaration + 37 002400 gsdt05= 05*400 ; local section name + 38 003000 gsdt06= 06*400 ; version identification + 39 + 40 000001 blkt01= 01 ; gsd + 41 000002 blkt02= 02 ; gsd end + 42 000003 blkt03= 03 ; text block + 43 000004 blkt04= 04 ; rld block + 44 000005 blkt05= 05 ; isd + 45 000006 blkt06= 06 ; module end + 46 000017 blkt17= 17 + 46 + 47 .sbttl expression to code-roll conversions + 48 + 49 000000 xitsec ;start in default psect + 1 000000 entsec .text + 1 000000 .psect .text con + 50 + 51 setimm: ; + 52 000000 call savreg + 1 000000 004767 000000G jsr pc,savreg + 53 000004 call setxpr + 1 000004 004767 000000G jsr pc,setxpr + 54 000010 005046 clr -(sp) + 55 000012 132713 000100 bitb #glbflg,(r3) + 56 000016 001047 bne setds3 + 57 000020 032713 000040 bit #relflg,(r3) + 58 000024 001446 beq setdsx + 59 000026 121267 000000G cmpb (r2),clcsec + 60 000032 001022 bne setds1 + 61 000034 052716 000010 bis #cc.sec,(sp) + 62 000040 000440 br setdsx + 63 + 64 setdsp: + 65 000042 call savreg + 1 000042 004767 000000G jsr pc,savreg + 66 000046 call setxpr + 1 000046 004767 000000G jsr pc,setxpr + 67 000052 012746 000002 mov #cc.dsp,-(sp) + 68 000056 032713 000100 bit #glbflg,(r3) + 69 000062 001025 bne setds3 + 70 000064 121267 000000G cmpb (r2),clcsec + 71 000070 001410 beq setds2 + 72 000072 032713 000040 bit #relflg,(r3) + 73 000076 001421 beq setdsx + 74 000100 setds1: call setsec + 1 000100 004767 000000G jsr pc,setsec + 75 000104 052716 000030 bis #cc.sec!cc.nam,(sp) + 76 000110 000414 br setdsx + 77 + 78 000112 005013 setds2: clr (r3) + 79 000114 005016 clr (sp) + 80 000116 116700 000000C movb <^pl rolsiz>+codrol+1,r0 + 81 ;movb @(pc)+,r0 + 82 ; .word <^pl rolsiz>+codrol+1 + 83 000122 005200 inc r0 + 84 000124 006300 asl r0 + 85 000126 066700 000000G add clcloc,r0 + 86 000132 160014 sub r0,(r4) + 87 000134 000402 br setdsx + 88 + 89 000136 052716 000020 setds3: bis #cc.nam,(sp) + 90 000142 032767 000000G 000000G setdsx: bit #dflgbm,opclas + 91 000150 001415 beq 4$ + 92 000152 105724 tstb (r4)+ + 93 000154 111400 movb (r4),r0 + 94 000156 001402 beq 1$ + 95 000160 005200 inc r0 + 96 000162 001003 bne 2$ + 97 000164 032716 000010 1$: bit #cc.sec,(sp) + 98 000170 001402 beq 3$ + 99 000172 2$: call abserr + 1 000172 004767 000000G jsr pc,abserr + 100 000176 105014 3$: clrb (r4) + 101 000200 052716 000200 bis #200,(sp) + 102 000204 112612 4$: movb (sp)+,(r2) + 103 000206 return + 1 000206 000207 rts pc + 103 + 104 .globl limit + 105 + 106 limit: + 107 000210 call setrld + 1 000210 004767 001270 jsr pc,setrld + 108 000214 005203 1$: inc r3 + 109 000216 112722 000040 movb #cc.opr,(r2)+ + 110 000222 110322 movb r3,(r2)+ + 111 000224 110322 movb r3,(r2)+ + 112 000226 call dmprld + 1 000226 004767 001166 jsr pc,dmprld + 113 000232 012700 000000G mov #symbol,r0 + 114 000236 005020 clr (r0)+ + 115 000240 010320 mov r3,(r0)+ + 116 000242 012720 010000 mov #cc.nam*400,(r0)+ + 117 000246 005020 clr (r0)+ + 118 000250 call stcode + 1 000250 004767 000552 jsr pc,stcode + 119 000254 020327 000002 cmp r3,#2 + 120 000260 103755 blo 1$ + 121 000262 return + 1 000262 000207 rts pc + 122 + 123 .globl ident, rad50 + 124 ident: ;"ident" directive + 125 000264 call rad50 ;treat as rad 50 + 1 000264 004767 000000G jsr pc,rad50 + 126 000270 005067 000000G clr rolupd ;point to start of code roll + 127 000274 012702 000010' mov #prgidn,r2 ; and to ident block + 128 000300 1$: next codrol ;get the next entry + 1 000300 012700 000000G mov #codrol,r0 + 2 .globl next + 3 000304 call next + 1 000304 004767 000000G jsr pc,next + 129 000310 016722 000000G mov value,(r2)+ ;stuff it + 130 000314 020227 000014' cmp r2,#prgidn+4 ;two words? + 131 000320 103767 blo 1$ ; no + 132 000322 012722 003000 mov #gsdt06,(r2)+ ;yes, set gsd type + 133 000326 zap codrol ;clear code + 1 000326 012700 000000G mov #codrol,r0 + 2 .globl zap + 3 000332 call zap + 1 000332 004767 000000G jsr pc,zap + 134 000336 return + 1 000336 000207 rts pc + 135 + 136 + 137 000340 entsec impure + 1 000000 .psect impure con + 138 000000 prgttl: .blkw 4 ;title block + 139 000010 prgidn: .blkw 4 ;ident " + 140 000020 xitsec + 1 000020 entsec .text + 1 000340 .psect .text con + 140 + 141 .sbttl object code handlers + 142 + 143 endp1c: ;end pass1 code init + 144 000340 105767 000000C tstb ioftbl+objchn ;any obj file? + 145 000344 001522 beq 9$ ; no + 146 000346 call objini ;init output + 1 000346 004767 001030 jsr pc,objini + 147 000352 012777 000001 000000C mov #blkt01,@buftbl+objchn ;set block type 1 + 148 000360 012701 000000' mov #prgttl,r1 ;set "from" index + 149 000364 call gsddmp ;output gsd block + 1 000364 004767 000230 jsr pc,gsddmp + 150 000370 012701 000010' mov #prgidn,r1 ;point to sub-ttl buffer + 151 000374 005761 000004 tst 4(r1) ;set? + 152 000400 001402 beq 1$ ; no + 153 000402 call gsddmp ;yes, stuff it + 1 000402 004767 000212 jsr pc,gsddmp + 154 000406 005046 1$: clr -(sp) ;init for sector scan + 155 000410 012667 000000G 2$: mov (sp)+,rolupd ;set scan marker + 156 000414 next secrol ;get the next sector + 1 000414 012700 000000G mov #secrol,r0 + 2 .globl next + 3 000420 call next + 1 000420 004767 000000G jsr pc,next + 157 000424 001446 beq 6$ ;branch if through + 158 000426 016746 000000G mov rolupd,-(sp) ;save marker + 159 000432 012701 000002G mov #value+2,r1 + 160 000436 011141 mov (r1),-(r1) + 161 000440 005005 clr r5 + 162 000442 154105 bisb -(r1),r5 + 163 000444 112711 000005 movb #gsdt05/400,(r1) + 164 ;tst psaflg ; who cares? a .csect is a + 165 ;bne 3$ ;special kind of .psect + 166 ;movb #gsdt01/400,(r1) ; so dont need this code + 167 ;bicb #^c,-(r1) ; j reeds sept 81. + 168 000450 005067 000000G 3$: clr rolupd ;set for inner scan + 169 000454 012701 000000G 4$: mov #symbol,r1 + 170 000460 call gsddmp ;output this block + 1 000460 004767 000134 jsr pc,gsddmp + 171 000464 5$: next symrol ;fetch the next symbol + 1 000464 012700 000000G mov #symrol,r0 + 2 .globl next + 3 000470 call next + 1 000470 004767 000000G jsr pc,next + 172 000474 001745 beq 2$ ; finished with this guy + 173 000476 032767 000100 000000G bit #glbflg,mode ;global? + 174 000504 001767 beq 5$ ; no + 175 000506 032767 000001 000000G bit #regflg,mode ;is register (prevent god's wrath) + 176 000514 001363 bne 5$ ;no global registers with ==* + 177 000516 126705 000000G cmpb sector,r5 ;yes, proper sector? + 178 000522 001360 bne 5$ ; no + 179 000524 042767 177427 000000G bic #^c,mode ;clear most (leave hk up) + 180 000532 052767 002000 000000G bis #gsdt04,mode ;set type 4 + 181 000540 000745 br 4$ ;output it + 182 + 183 + 184 000542 042767 177737 000004G 6$: bic #^c,endvec+4 ;clear all but rel flag + 185 000550 052767 001410 000004G bis #gsdt03+defflg,endvec+4 + 186 000556 012701 000000G mov #endvec,r1 + 187 000562 call gsddmp ;output end block + 1 000562 004767 000032 jsr pc,gsddmp + 188 000566 call objdmp ;dump it + 1 000566 004767 000542 jsr pc,objdmp + 189 000572 012777 000002 000000C mov #blkt02,@buftbl+objchn ;set "end of gsd" + 190 000600 call objdmf + 1 000600 004767 000552 jsr pc,objdmf + 191 000604 012777 000017 000000C mov #blkt17,@buftbl+objchn ;init for text blocks + 192 9$: + 193 000612 005267 000000G inc pass ;set for pass 2 + 194 000616 return + 1 000616 000207 rts pc + 195 + 196 + 197 gsddmp: ;dump a gsd block + 198 000620 call setrld + 1 000620 004767 000660 jsr pc,setrld + 199 000624 xmit 4 + 1 .globl xmit0 + 2 000624 call xmit0-<4*2> + 1 000624 004767 177770G jsr pc,xmit0-<4*2> + 200 000630 000167 000564 jmp dmprld + 200 + 201 endp2c: + 202 000634 005767 000022' tst objpnt ;any object output? + 203 000640 001426 beq 1$ ; no + 204 000642 call objdmp ;yes, dump it + 1 000642 004767 000466 jsr pc,objdmp + 205 000001 .if ne,mk.symbol + 206 000646 005767 000020' tst out$ym + 207 000652 001422 beq 22$ + 208 .endc + 209 000654 012777 000006 000000C 32$: mov #blkt06,@buftbl+objchn ;set end + 210 000662 call objdmf ;dump it + 1 000662 004767 000470 jsr pc,objdmf + 211 .if ndf xedabs + 212 000666 032767 000000G 000000G bit #ed.abs,edmask ;abs output? + 213 000674 001010 bne 1$ ; no + 214 000676 016700 000022' mov objpnt,r0 + 215 000702 016720 000006G mov endvec+6,(r0)+ ;set end vector + 216 000706 010067 000022' mov r0,objpnt + 217 000712 call objdmp + 1 000712 004767 000416 jsr pc,objdmp + 218 .endc + 219 000716 1$: return + 1 000716 000207 rts pc + 220 + 221 000001 .if ne,mk.symbol + 222 000720 012777 000022 000000C 22$: mov #blkssym,@buftbl+objchn + 223 000726 005067 000000G clr rolupd + 224 000732 3$: next symrol + 1 000732 012700 000000G mov #symrol,r0 + 2 .globl next + 3 000736 call next + 1 000736 004767 000000G jsr pc,next + 225 000742 001411 beq 31$ + 226 000744 032767 000100 000000G bit #glbflg,mode + 227 000752 001367 bne 3$ + 228 000754 012701 000000G mov #symbol,r1 + 229 000760 call gsddmp + 1 000760 004767 177634 jsr pc,gsddmp + 230 000764 000762 br 3$ + 231 + 232 000766 005767 000022' 31$: tst objpnt + 233 000772 001402 beq 30$ + 234 000774 call objdmp + 1 000774 004767 000334 jsr pc,objdmp + 235 30$: + 236 001000 call locdmp + 1 001000 004767 000506 jsr pc,locdmp + 237 001004 012777 000021 000000C mov #blksye,@buftbl+objchn + 238 001012 005767 000022' tst objpnt + 239 001016 001716 beq 32$ + 240 001020 call objdmf + 1 001020 004767 000332 jsr pc,objdmf + 241 001024 000713 br 32$ + 242 + 243 001026 entsec impure + 1 000020 .psect impure con + 244 000020 out$ym: .blkw 1 + 245 000022 xitsec + 1 000022 entsec .text + 1 001026 .psect .text con + 246 + 247 000021 blksye=21 + 248 000022 blkssys=22 + 249 + 250 .globl out$ym + 251 .endc + 252 + 252 + 253 .sbttl code roll handlers + 254 + 255 001026 stcode: append codrol ;append to codrol + 1 001026 012700 000000G mov #codrol,r0 + 2 .globl append + 3 001032 call append + 1 001032 004767 000000G jsr pc,append + 256 001036 return + 1 001036 000207 rts pc + 257 + 258 .globl pcrcnt + 259 pcroll: ; + 260 001040 next codrol + 1 001040 012700 000000G mov #codrol,r0 + 2 .globl next + 3 001044 call next + 1 001044 004767 000000G jsr pc,next + 261 001050 001477 beq 9$ + 262 001052 call savreg + 1 001052 004767 000000G jsr pc,savreg + 263 001056 116704 000000G movb sector,r4 + 264 001062 005767 000000G tst pass + 265 001066 001453 beq 7$ + 266 001070 005267 000000' inc pcrcnt + 267 001074 001002 bne 1$ + 268 001076 call setpf0 + 1 001076 004767 000000G jsr pc,setpf0 + 269 001102 1$: call setpf1 + 1 001102 004767 000000G jsr pc,setpf1 + 270 001106 005767 000022' tst objpnt + 271 001112 001441 beq 7$ + 272 .if ndf xedpnc + 273 001114 032767 000000G 000000G bit #ed.pnc,edmask + 274 001122 001035 bne 7$ + 275 .endc + 276 001124 call setrld + 1 001124 004767 000354 jsr pc,setrld + 277 001130 010446 mov r4,-(sp) + 278 001132 012704 000070 mov #cc.sec!cc.nam!cc.opr,r4 + 279 001136 126767 000000G 000001' cmpb clcsec,objsec + 280 001144 001006 bne 2$ + 281 001146 026767 000000G 000002' cmp clcloc,objloc + 282 001154 001411 beq 3$ + 283 001156 042704 000020 bic #cc.nam,r4 + 284 001162 012701 000000G 2$: mov #clcnam,r1 + 285 001166 call pcrolx + 1 001166 004767 000060 jsr pc,pcrolx + 286 001172 105022 clrb (r2)+ + 287 001174 call dmprld + 1 001174 004767 000220 jsr pc,dmprld + 288 001200 012604 3$: mov (sp)+,r4 + 289 001202 012701 000000G mov #symbol,r1 + 290 001206 call pcrolx + 1 001206 004767 000040 jsr pc,pcrolx + 291 001212 call dmprld + 1 001212 004767 000202 jsr pc,dmprld + 292 001216 005267 000000G 7$: inc clcloc + 293 001222 105704 tstb r4 + 294 001224 100402 bmi 8$ + 295 001226 005267 000000G inc clcloc + 296 001232 116767 000000G 000001' 8$: movb clcsec,objsec + 297 001240 016767 000000G 000002' mov clcloc,objloc + 298 001246 setnz r0 + 1 001246 010600 mov sp,r0 + 299 001250 9$: return + 1 001250 000207 rts pc + 299 + 300 pcrolx: + 301 001252 110422 movb r4,(r2)+ + 302 001254 032704 000020 bit #cc.nam,r4 + 303 001260 001405 beq 3$ + 304 000004 .rept 4 + 305 movb (r1)+,(r2)+ + 306 .endm + 1 001262 112122 movb (r1)+,(r2)+ + 1 001264 112122 movb (r1)+,(r2)+ + 1 001266 112122 movb (r1)+,(r2)+ + 1 001270 112122 movb (r1)+,(r2)+ + 307 001272 024141 cmp -(r1),-(r1) + 308 001274 062701 000006 3$: add #6,r1 + 309 001300 005711 tst (r1) + 310 001302 001407 beq 4$ + 311 001304 112122 movb (r1)+,(r2)+ + 312 001306 152767 000004 000024' bisb #cc.val,rldtmp + 313 001314 105704 tstb r4 + 314 001316 100401 bmi 4$ + 315 001320 112122 movb (r1)+,(r2)+ + 316 001322 4$: return + 1 001322 000207 rts pc + 317 + 318 001324 entsec implin + 1 000000 .psect implin con + 319 000000 pcrcnt: .blkw ;extension line flag + 319 + 320 000002 entsec imppas + 1 000000 .psect imppas con + 321 000000 000 .odd + 322 000001 objsec: .blkb 1 ;object file sector + 323 000002 objloc: .blkw 1 ;object file location + 324 + 325 + 326 + 327 + 328 + 329 .if ndf xedpnc + 330 000004 genedt pnc,pncset ;punch control + 1 000004 entsec edtsec + 1 000000 .psect edtsec con + 2 000000 063063 .rad50 /pnc/ + 3 .if nb pncset + 4 000002 001324' .word pncset + 5 .iff + 6 .word cpopj + 7 .endc + 8 000004 000000G .word ed.pnc + 9 000006 xitsec + 1 000006 entsec .text + 1 001324 .psect .text con + 331 + 332 001324 112767 000377 000001' pncset: movb #377,objsec ;force sequence break + 333 001332 return + 1 001332 000207 rts pc + 334 .endc + 334 + 335 objdmp: ;dump the object buffer + 336 001334 005767 000022' tst objpnt + 337 001340 001426 beq objinx ;exit if not pre-set + 338 001342 016700 000000C mov buftbl+objchn,r0 + 339 001346 005720 tst (r0)+ ;ignore first word + 340 001350 026700 000022' cmp objpnt,r0 ;anything in rld? + 341 001354 101412 blos objini ; no, just init + 342 objdmf: + 343 001356 016777 000022' 000000C mov objpnt,@cnttbl+objchn + 344 001364 166777 000000C 000000C sub buftbl+objchn,@cnttbl+objchn ;compute byte count + 345 001372 zwrite obj + 1 .globl zwrite + 2 001372 012700 000000G mov #objchn,r0 + 3 001376 call zwrite + 1 001376 004767 000000G jsr pc,zwrite + 346 + 347 001402 016767 000000C 000022' objini: mov buftbl+objchn,objpnt + 348 001410 062767 000002 000022' add #2,objpnt ;reserve word for block type + 349 001416 objinx: return + 1 001416 000207 rts pc + 350 + 351 001420 005767 000022' dmprld: tst objpnt + 352 001424 001427 beq setrld + 353 001426 010146 mov r1,-(sp) ;save byte count + 354 001430 012701 000024' mov #rldtmp,r1 + 355 001434 010200 mov r2,r0 + 356 001436 160100 sub r1,r0 + 357 001440 001420 beq 9$ + 358 001442 066700 000022' add objpnt,r0 + 359 001446 166700 000000C sub buftbl+objchn,r0 + 360 001452 020027 000000G cmp r0,#objlen ;room to store? + 361 001456 101402 blos 1$ ; yes + 362 001460 call objdmp ;no, dump current + 1 001460 004767 177650 jsr pc,objdmp + 363 001464 016700 000022' 1$: mov objpnt,r0 ;return with pointer in r2 + 364 001470 112120 2$: movb (r1)+,(r0)+ + 365 001472 020102 cmp r1,r2 + 366 001474 103775 blo 2$ + 367 001476 010067 000022' mov r0,objpnt + 368 001502 012601 9$: mov (sp)+,r1 + 369 001504 012702 000024' setrld: mov #rldtmp,r2 + 370 001510 return + 1 001510 000207 rts pc + 371 + 372 001512 entsec impure + 1 000022 .psect impure con + 373 000022 objpnt: .blkw + 374 000024 rldtmp: .blkb 100. + 375 000170 xitsec + 1 000170 entsec .text + 1 001512 .psect .text con + 376 + 377 + 378 001512 xitsec + 1 001512 entsec .text + 1 001512 .psect .text con + 379 .globl sx.flg ,lsyrol + 380 locdmp: + 381 001512 call savreg + 1 001512 004767 000000G jsr pc,savreg + 382 001516 010046 mov r0,-(sp) + 383 001520 005767 000000G tst sx.flg + 384 001524 001427 beq 9$ + 385 001526 005067 000000G clr rolupd + 386 1$: + 387 001532 next lsyrol + 1 001532 012700 000000G mov #lsyrol,r0 + 2 .globl next + 3 001536 call next + 1 001536 004767 000000G jsr pc,next + 388 001542 001413 beq 2$ + 389 001544 032767 000100 000000G bit #glbflg,mode + 390 001552 001367 bne 1$ + 391 001554 call unlocl + 1 001554 004767 000030 jsr pc,unlocl + 392 001560 012701 000000G mov #symbol,r1 + 393 001564 call gsddmp + 1 001564 004767 177030 jsr pc,gsddmp + 394 001570 000760 br 1$ + 395 2$: + 396 001572 005767 000022' tst objpnt + 397 001576 001402 beq 9$ + 398 001600 call objdmp + 1 001600 004767 177530 jsr pc,objdmp + 399 9$: + 400 001604 012600 mov (sp)+,r0 + 401 001606 return + 1 001606 000207 rts pc + 402 + 403 .globl dnc ,chrpnt, getsym,..z + 404 unlocl: + 405 001610 call savreg + 1 001610 004767 000000G jsr pc,savreg + 406 001614 010046 mov r0,-(sp) + 407 001616 012702 000000' mov #work.x,r2 + 408 001622 016701 000002G mov symbol+2,r1 + 409 001626 call dnc + 1 001626 004767 000000G jsr pc,dnc + 410 001632 112722 000044 movb #'$,(r2)+ + 411 001636 112722 000000 movb #0,(r2)+ + 412 001642 call tor50 + 1 001642 004767 000004 jsr pc,tor50 + 413 001646 012600 mov (sp)+,r0 + 414 001650 return + 1 001650 000207 rts pc + 415 001652 entsec mixed + 1 000000 .psect mixed con + 416 000000 work.x: .blkw 5 + 417 000012 xitsec + 1 000012 entsec .text + 1 001652 .psect .text con + 418 tor50: + 419 001652 call savreg + 1 001652 004767 000000G jsr pc,savreg + 420 001656 012704 000000' mov #work.x,r4 + 421 001662 call 1$ + 1 001662 004767 000022 jsr pc,1$ + 422 001666 010067 000000G mov r0,symbol + 423 001672 012704 000003' mov #3+work.x,r4 + 424 001676 call 1$ + 1 001676 004767 000006 jsr pc,1$ + 425 001702 010067 000002G mov r0,2+symbol + 426 001706 return + 1 001706 000207 rts pc + 427 1$: + 428 001710 005003 clr r3 + 429 001712 105714 tstb (r4) + 430 001714 001402 beq 10$ + 431 001716 112400 movb (r4)+,r0 + 432 001720 000401 br 20$ + 433 001722 111400 10$: movb (r4),r0 + 434 001724 010002 20$: mov r0,r2 + 435 001726 call 40$ + 1 001726 004767 000062 jsr pc,40$ + 436 001732 010003 mov r0,r3 + 437 001734 010301 mov r3,r1 + 438 001736 070127 000050 mul #50,r1 + 439 001742 010103 mov r1,r3 + 440 001744 105714 tstb (r4) + 441 001746 001402 beq 12$ + 442 001750 112400 movb (r4)+,r0 + 443 001752 000401 br 21$ + 444 001754 111400 12$: movb (r4),r0 + 445 001756 010002 21$: mov r0,r2 + 446 001760 call 40$ + 1 001760 004767 000030 jsr pc,40$ + 447 001764 060003 add r0,r3 + 448 001766 010301 mov r3,r1 + 449 001770 070127 000050 mul #50,r1 + 450 001774 010103 mov r1,r3 + 451 001776 111400 movb (r4),r0 + 452 002000 010002 mov r0,r2 + 453 002002 call 40$ + 1 002002 004767 000006 jsr pc,40$ + 454 002006 060003 add r0,r3 + 455 002010 010300 mov r3,r0 + 456 002012 return + 1 002012 000207 rts pc + 457 40$: + 458 002014 122702 000044 cmpb #44,r2 + 459 002020 001005 bne 30$ + 460 002022 012700 000033 mov #33,r0 + 461 002026 000401 br 9$ + 462 002030 005000 14$: clr r0 + 463 002032 9$: return + 1 002032 000207 rts pc + 464 002034 105702 30$: tstb r2 + 465 002036 001774 beq 14$ + 466 002040 122702 000040 cmpb #40,r2 + 467 002044 001771 beq 14$ + 468 002046 110200 movb r2,r0 + 469 002050 062700 177756 add #-22,r0 + 470 002054 000766 br 9$ + 471 .end + 472 + 473 .end + 473 + 7 + + +Symbol table + +$TIMDF= 000007 4$6 001322R L 002 CLCLOC= ****** G LBLFLG= 000002 RLDTMP 000024R 008 +. 002056R 002 40$9 002014R L 002 CLCNAM= ****** G LF = 000012 ROLUPD= ****** G +..Z = ****** G 5$3 000464R L 002 CLCSEC= ****** G LIMIT 000210RG 002 RSX11D= 000000 +1$0 000164R L 002 6$3 000542R L 002 CNTTBL= ****** G LOCDMP 001512R 002 SAVREG= ****** G +1$1 000214R L 002 7$5 001216R L 002 CODROL= ****** G LSYROL= ****** G SECROL= ****** G +1$2 000300R L 002 8$5 001232R L 002 CR = 000015 M.IDF = 000007 SECTOR= ****** G +1$3 000406R L 002 9$3 000612R L 002 DEBUG = 000000 MDFFLG= 000004 SETDS1 000100R 002 +1$4 000716R L 002 9$5 001250R L 002 DEFFLG= 000010 MK.SYM= 000001 SETDS2 000112R 002 +1$5 001102R L 002 9$7 001502R L 002 DFGFLG= 000200 MODE = ****** G SETDS3 000136R 002 +1$7 001464R L 002 9$8 001604R L 002 DFLGBM= ****** G NEXT = ****** G SETDSP 000042RG 002 +1$8 001532R L 002 9$9 002032R L 002 DMPRLD 001420RG 002 OBJCHN= ****** G SETDSX 000142R 002 +1$9 001710R L 002 AATTRS= 000130 DNC = ****** G OBJDMF 001356R 002 SETIMM 000000RG 002 +10$9 001722R L 002 ABSERR= ****** G ED.ABS= ****** G OBJDMP 001334R 002 SETPF0= ****** G +12$9 001754R L 002 APPEND= ****** G ED.PNC= ****** G OBJINI 001402R 002 SETPF1= ****** G +14$9 002030R L 002 B.IDF = 000001 EDMASK= ****** G OBJINX 001416R 002 SETRLD 001504RG 002 +2$0 000172R L 002 BLKSSY= 000022 ENDP1C 000340RG 002 OBJLEN= ****** G SETSEC= ****** G +2$3 000410R L 002 BLKSYE= 000021 ENDP2C 000634RG 002 OBJLOC 000002R 009 SETXPR= ****** G +2$5 001162R L 002 BLKT01= 000001 ENDVEC= ****** G OBJPNT 000022R 008 SHRFLG= 000001 +2$7 001470R L 002 BLKT02= 000002 FF = 000014 OBJSEC 000001RG 009 SPACE = 000040 +2$8 001572R L 002 BLKT03= 000003 FT.ID = 000001 OPCLAS= ****** G STCODE 001026RG 002 +20$9 001724R L 002 BLKT04= 000004 FT.UNX= 000001 OUT$YM 000020RG 008 SX.FLG= ****** G +21$9 001756R L 002 BLKT05= 000005 GETSYM= ****** G OVRFLG= 000020 SYMBOL= ****** G +22$4 000720R L 002 BLKT06= 000006 GLBFLG= 000100 PASS = ****** G SYMROL= ****** G +3$0 000176R L 002 BLKT17= 000017 GSDDMP 000620R 002 PATTRS= 000050 TAB = 000011 +3$3 000450R L 002 BPMB = 000020 GSDT00= 000000 PCRCNT 000000RG 010 TOR50 001652R 002 +3$4 000732R L 002 BSSFLG= 000004 GSDT01= 000400 PCROLL 001040RG 002 UNLOCL 001610R 002 +3$5 001200R L 002 BUFTBL= ****** G GSDT02= 001000 PCROLX 001252R 002 VALUE = ****** G +3$6 001274R L 002 CATTRS= 000170 GSDT03= 001400 PDPV45= 000000 VT = 000013 +30$4 001000R L 002 CC.DSP= 000002 GSDT04= 002000 PNCSET 001324R 002 WORK.X 000000R 006 +30$9 002034R L 002 CC.NAM= 000020 GSDT05= 002400 PRGIDN 000010R 008 X40 = 000000 +31$4 000766R L 002 CC.OPR= 000040 GSDT06= 003000 PRGTTL 000000RG 008 XMIT0 = ****** G +32$4 000654R L 002 CC.SEC= 000010 IDENT 000264RG 002 RAD50 = ****** G ZAP = ****** G +4$0 000204R L 002 CC.VAL= 000004 INSFLG= 000002 REGFLG= 000001 ZWRITE= ****** G +4$3 000454R L 002 CHRPNT= ****** G IOFTBL= ****** G RELFLG= 000040 + + +Program sections: + +. ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV) + 000000 001 (RW,I,LCL,REL,CON,NOSAV) +.TEXT 002056 002 (RW,I,LCL,REL,CON,NOSAV) +.DATA 000000 003 (RW,I,LCL,REL,CON,NOSAV) +.BSS 000000 004 (RW,I,LCL,REL,CON,NOSAV) +DPURE 000000 005 (RW,I,LCL,REL,CON,NOSAV) +MIXED 000012 006 (RW,I,LCL,REL,CON,NOSAV) +ERRMES 000000 007 (RW,I,LCL,REL,CON,NOSAV) +IMPURE 000170 008 (RW,I,LCL,REL,CON,NOSAV) +IMPPAS 000004 009 (RW,I,LCL,REL,CON,NOSAV) +IMPLIN 000002 010 (RW,I,LCL,REL,CON,NOSAV) +SWTSEC 000000 011 (RW,I,LCL,REL,CON,NOSAV) +CNDSEC 000000 012 (RW,I,LCL,REL,CON,NOSAV) +CRFSEC 000000 013 (RW,I,LCL,REL,CON,NOSAV) +EDTSEC 000006 014 (RW,I,LCL,REL,CON,NOSAV) +LCTSEC 000000 015 (RW,I,LCL,REL,CON,NOSAV) +PSASEC 000000 016 (RW,I,LCL,REL,CON,NOSAV) +PSTSEC 000000 017 (RW,I,LCL,REL,CON,NOSAV) +ROLBAS 000000 018 (RW,I,LCL,REL,CON,NOSAV) +ROLSIZ 000000 019 (RW,I,LCL,REL,CON,NOSAV) +ROLTOP 000000 020 (RW,I,LCL,REL,CON,NOSAV) +XPCOR 000000 021 (RW,I,LCL,REL,CON,NOSAV) diff --git a/crossassemblers/macro11/tests/2.11BSD-m11-debug.lst.ok b/crossassemblers/macro11/tests/2.11BSD-m11-debug.lst.ok new file mode 100644 index 0000000..531f0d1 --- /dev/null +++ b/crossassemblers/macro11/tests/2.11BSD-m11-debug.lst.ok @@ -0,0 +1,658 @@ + 1 ;;;; Wrapper for 2.11BSD/m11/debug.m11 + 2 .list + 3 .list + 4 .list + 5 000001 debug = 1 + 6 .include "2.11BSD/m11/at.sml" + 1 .title at.sml - assembler/translator system macros + 2 ; @(#)at.sml 1.3 11/3/82 + 3 + 4 .ident /10may4/ + 5 + 6 .macro always ;all files of macro + 7 + 8 .macro .data + 9 entsec .data + 10 .endm .data + 11 + 12 .macro .text + 13 entsec .text + 14 .endm + 15 + 16 .macro .bss + 17 entsec .bss + 18 .endm + 19 + 20 mk.symbol=1 ;one to make symbols, 0 otherwise + 21 x40= 0 + 22 pdpv45= 0 ; host machine has 'mul', 'div', sob' instrucs. + 23 ; if not you will have to write macros for them + 24 $timdf= 7 ; California Time Zone + 25 ; should really use ftime(2) for this and for + 26 ; DST. + 27 ;xfltg= 0 ;define to assmbl out floating hardware + 28 rsx11d = 0 ; rsx11d features + 29 debug = 0 ; <<< REEDS if non zero includes debug junk + 30 + 31 ft.id= 1 ;have set i & d. set =0 if not + 32 + 33 ft.unx = 1 ; this macro-11 is for UNIX. =0 if not. + 34 + 35 .nlist bex + 36 + 37 tab= 11 + 38 lf= 12 + 39 vt= 13 + 40 ff= 14 + 41 cr= 15 + 42 space= 40 + 43 + 44 bpmb = 20 ;bytes per macro block + 45 + 46 + 47 + 48 + 49 + 50 .psect .text con, shr, gbl,ins + 51 .psect .data con, dat, prv, gbl + 52 .psect .bss con, bss, gbl + 53 + 54 .psect dpure con, dat, prv, gbl + 55 .psect mixed con, prv, gbl + 56 .psect errmes con, dat, prv, gbl + 57 .psect impure con, bss, gbl + 58 .psect imppas con, bss, gbl + 59 .psect implin con, bss, gbl + 60 .psect swtsec con, dat, prv, gbl ; unix command line flags + 61 .psect cndsec con, dat, prv, gbl ; gt, le, equ, etc. for '.if' + 62 .psect crfsec con, dat, prv, gbl ; args for -cr flag + 63 .psect edtsec con, dat, prv, gbl ; args for .enabl + 64 .psect lctsec con, dat, prv, gbl ; args for .list + 65 .psect psasec con, dat, prv, gbl + 66 .psect pstsec con, dat, prv, gbl + 67 .psect rolbas con, dat, prv, gbl ; core allocation: starts of tables + 68 .psect rolsiz con, dat, prv, gbl ; sizes of table entries + 69 .psect roltop con, dat, prv, gbl ; tops of tables + 70 .psect xpcor con,bss , gbl ; this one MUST come last in core + 71 + 72 + 72 + 73 .macro entsec name ;init a section + 74 .psect name con + 75 .endm entsec + 76 + 77 + 78 + 79 .macro jeq x,?fred + 80 bne fred + 81 jmp x + 82 fred: + 83 .endm + 84 .macro jne x,?fred + 85 beq fred + 86 jmp x + 87 fred: + 88 .endm + 89 .macro xitsec + 90 entsec .text + 91 .endm xitsec + 92 + 93 + 94 .macro call address + 95 jsr pc,address + 96 .endm + 97 + 98 .macro return + 99 rts pc + 100 .endm + 101 + 102 + 103 .macro always + 104 .nlist bex + 105 .endm always + 106 .endm always + 107 + 108 + 109 000001 .if ne debug + 110 + 111 .macro ndebug n + 112 .globl ndebug,..z + 113 mov n,..z + 114 call ndebug + 115 .endm + 116 + 117 .macro sdebug string + 118 .globl sdebug,..z,..zbuf + 119 x = 0 + 120 .irpc t, + 121 movb #''t,..zbuf+x + 122 x = x+1 + 123 .endm + 124 movb #0,..zbuf+x + 125 mov #..zbuf,..z + 126 call sdebug + 127 .endm + 128 + 129 .iff + 130 + 131 .macro ndebug n + 132 .endm + 133 + 134 .macro sdebug string + 135 .endm + 136 + 137 .endc + 138 + 139 + 140 .macro param mne, value ;define default parameters + 141 .iif ndf mne, mne= value + 142 .list + 143 mne= mne + 144 .nlist + 145 .endm + 145 + 146 .macro putkb addr ;list to kb + 147 .globl putkb + 148 mov addr,r0 + 149 call putkb + 150 .endm + 151 + 152 .macro putlp addr ;list to lp + 153 .globl putlp + 154 mov addr,r0 + 155 call putlp + 156 .endm + 157 + 158 .macro putkbl addr ;list to kb and lp + 159 .globl putkbl + 160 mov addr,r0 + 161 call putkbl + 162 .endm + 163 + 164 + 165 .macro xmit wrdcnt ;move small # of words + 166 .globl xmit0 + 167 call xmit0- + 168 .endm xmit + 169 + 170 + 171 ;the macro "genswt" is used to specify a command + 172 ;string switch (1st argument) and the address of + 173 ;the routine to be called when encountered (2nd arg). + 174 ; the switch is made upper-case. + 175 + 176 .macro genswt mne,addr,?label + 177 entsec swtsec + 178 label: .irpc x,mne + 179 .if ge ''x-141 + 180 .if le ''x-172 + 181 .byte ''x-40 + 182 .iff + 183 .byte ''x + 184 .endc + 185 .iff + 186 .byte ''x + 187 .endc + 188 .endm + 189 .iif ne <.-label&1>, .byte 0 + 190 .word addr + 191 xitsec + 192 .endm + 192 + 193 .macro zread chan + 194 .globl zread + 195 mov #chan'chn,r0 + 196 call zread + 197 .endm zread + 198 + 199 .macro zwrite chan + 200 .globl zwrite + 201 mov #chan'chn,r0 + 202 call zwrite + 203 .endm zwrite + 203 + 204 .macro genedt mne,subr ;gen enable/disable table + 205 entsec edtsec + 206 .rad50 /mne/ + 207 .if nb subr + 208 .word subr + 209 .iff + 210 .word cpopj + 211 .endc + 212 .word ed.'mne + 213 xitsec + 214 .endm genedt + 215 + 216 + 217 ;the macro "gencnd" is used to specify conditional + 218 ;arguments. it takes two or three arguments: + 219 + 220 ; 1- mnemonic + 221 ; 2- subroutine to be called + 222 ; 3- if non-blank, complement condition + 223 + 224 .macro gencnd mne,subr,toggle ;generate conditional + 225 entsec cndsec + 226 .rad50 /mne/ + 227 .if b + 228 .word subr + 229 .iff + 230 .word subr+1 + 231 .endc + 232 xitsec + 233 .endm + 233 + 234 .macro ch.mne + 235 + 236 ch.ior= '! + 237 ch.qtm= '" + 238 ch.hsh= '# + 239 ch.dol= '$ + 240 ch.pct= '% + 241 ch.and= '& + 242 ch.xcl= '' + 243 + 244 ch.lp= '( + 245 ch.rp= ') + 246 ch.mul= '* + 247 ch.add= '+ + 248 ch.com= ', + 249 ch.sub= '- + 250 ch.dot= '. + 251 ch.div= '/ + 252 + 253 ch.col= ': + 254 ch.smc= '; + 255 ch.lab= '< + 256 ch.equ= '= + 257 ch.rab= '> + 258 ch.qm= '? + 259 + 260 ch.ind= '@ + 261 ch.bsl= '\ + 262 ch.uar= '^ + 263 + 264 let.a= 'a&^c40 + 265 let.b= 'b&^c40 + 266 let.c= 'c&^c40 + 267 let.d= 'd&^c40 + 268 let.e= 'e&^c40 + 269 let.f= 'f&^c40 + 270 let.g= 'g&^c40 + 271 let.o= 'o&^c40 + 272 let.p= 'p&^c40 + 273 let.r= 'r&^c40 + 274 let.z= 'z&^c40 + 275 + 276 dig.0= '0 + 277 dig.9= '9 + 278 .macro ch.mne + 279 .endm ch.mne + 280 .endm ch.mne + 281 + 282 .macro error num,arg, mess ,?x + 283 sdebug + 284 .globl err.'arg,ern'num, errbts,errref + 285 .if b + 286 deliberate error mistake + 287 .endc + 288 .if dif 0,num + 289 .globl err.xx + 290 tst err.xx + 291 bne x + 292 mov #ern'num,err.xx + 293 x: + 294 .endc + 295 bis #err.'arg,errbts + 296 .endm + 297 + 298 + 299 + 300 .macro setnz addr ;set addr to non-zero for t/f flags + 301 mov sp,addr + 302 .endm + 303 + 304 + 305 .macro bisbic arg ; used by .list/.nlist, .enabl/.dsabl + 306 .globl bisbic + 307 mov #arg,-(sp) + 308 call bisbic + 309 tst (sp)+ + 310 .endm + 310 + 311 ;roll handler calls + 312 + 313 .macro search rolnum ;binary search + 314 mov #rolnum,r0 + 315 .globl search + 316 call search + 317 .endm + 318 + 319 .macro scan rolnum ;linear scan + 320 mov #rolnum,r0 + 321 .globl scan + 322 call scan + 323 .endm + 324 + 325 .macro scanw rolnum ;linear scan, one word + 326 mov #rolnum,r0 + 327 .globl scanw + 328 call scanw + 329 .endm + 330 + 331 .macro next rolnum ;fetch next entry + 332 mov #rolnum,r0 + 333 .globl next + 334 call next + 335 .endm + 336 + 337 .macro append rolnum ;append to end of roll + 338 mov #rolnum,r0 + 339 .globl append + 340 call append + 341 .endm + 342 + 343 .macro zap rolnum ;clear roll + 344 mov #rolnum,r0 + 345 .globl zap + 346 call zap + 347 .endm + 348 + 349 ; call insert ;insert (must be preceded by one + 350 ;of the above to set pointers) + 351 ; call setrol ;save and set regs for above + 351 + 352 ;flags used in symbol table mode + 353 + 354 .macro st.flg + 355 + 356 .if le ft.unx + 357 + 358 ovrflg= 000004 ;overlay (psect only) + 359 defflg= 000010 ;defined + 360 relflg= 000040 ;relocatable + 361 glbflg= 000100 ;global + 362 dfgflg= 000200 ; default global ... reeds's guess + 363 + 364 + 365 .endc + 366 + 367 .if gt ft.unx + 368 + 369 ; ****** these should not be changed!! ****** + 370 shrflg= 000001 ;shareable (psect only) + 371 .if gt ft.id + 372 insflg= shrflg*2 ;instruction space (psect only) + 373 bssflg= insflg*2 ;blank section (psect only) + 374 m.idf= shrflg!insflg!bssflg ;mask to turn them off + 375 .iff + 376 bssflg= shrflg*2 + 377 m.idf= shrflg!bssflg + 378 .endc + 379 b.idf= 1 ;shift count to make above bits word offset + 380 ; *********************************** + 381 defflg= 000010 ;defined + 382 ovrflg= 000020 ;overlay (psect only) + 383 relflg= 000040 ;relocatable + 384 glbflg= 000100 ;global + 385 dfgflg= 000200 ; default global ... reeds's guess + 386 + 387 .endc + 388 + 389 ; + 390 ; default psect attribs. + 391 ; can be changed, but make sure all customers know about + 392 ; it, including all the linkers. + 393 ; + 394 pattrs=relflg!defflg ; For .psects and blank .csects + 395 aattrs=glbflg!defflg!ovrflg ; For .asect + 396 cattrs=glbflg!relflg!defflg!ovrflg ; For named .csects + 397 + 398 regflg= 000001 ;register + 399 lblflg= 000002 ;label + 400 mdfflg= 000004 ;multilpy defined + 401 .macro st.flg + 402 .endm + 403 .endm st.flg + 404 + 405 + 406 + 407 .macro ct.mne + 408 .globl cttbl + 409 ct.eol = 000 ; eol + 410 ct.com = 001 ; comma + 411 ct.tab = 002 ; tab + 412 ct.sp = 004 ; space + 413 ct.pcx = 010 ; printing character + 414 ct.num = 020 ; numeric + 415 ct.alp = 040 ; alpha, dot, dollar + 416 ct.lc = 100 ; lower case alpha + 417 ct.smc = 200 ; semi-colon (sign bit) + 418 + 419 ct.pc = ct.com!ct.smc!ct.pcx!ct.num!ct.alp + 420 .macro ct.mne + 421 .endm ct.mne + 422 .endm ct.mne + 423 + 424 + 425 .end + 425 + 7 .include "2.11BSD/m11/debug.m11" + 1 .mcall (at) always + 2 .globl $write + 3 + 4 .globl ndebug,sdebug, ..z,..zbuf + 5 .globl savreg,dnc + 6 .globl xx.flg + 7 000000 always + 1 + 2 .macro .data + 3 entsec .data + 4 .endm .data + 5 + 6 .macro .text + 7 entsec .text + 8 .endm + 9 + 10 .macro .bss + 11 entsec .bss + 12 .endm + 13 + 14 000001 mk.symbol=1 ;one to make symbols, 0 otherwise + 15 000000 x40= 0 + 16 000000 pdpv45= 0 ; host machine has 'mul', 'div', sob' instrucs. + 17 ; if not you will have to write macros for them + 18 000007 $timdf= 7 ; California Time Zone + 19 ; should really use ftime(2) for this and for + 20 ; DST. + 21 ;xfltg= 0 ;define to assmbl out floating hardware + 22 000000 rsx11d = 0 ; rsx11d features + 23 000000 debug = 0 ; <<< REEDS if non zero includes debug junk + 24 + 25 000001 ft.id= 1 ;have set i & d. set =0 if not + 26 + 27 000001 ft.unx = 1 ; this macro-11 is for UNIX. =0 if not. + 28 + 29 .nlist bex + 30 + 31 000011 tab= 11 + 32 000012 lf= 12 + 33 000013 vt= 13 + 34 000014 ff= 14 + 35 000015 cr= 15 + 36 000040 space= 40 + 37 + 38 000020 bpmb = 20 ;bytes per macro block + 39 + 40 + 41 + 42 + 43 +./2.11BSD/m11/debug.m11:7->ALWAYS:44: ***ERROR Unknown flag SHR given to .PSECT directive + 44 .psect .text con, shr, gbl,ins +./2.11BSD/m11/debug.m11:7->ALWAYS:45: ***ERROR Unknown flag DAT given to .PSECT directive + 45 .psect .data con, dat, prv, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:46: ***ERROR Unknown flag BSS given to .PSECT directive + 46 .psect .bss con, bss, gbl + 47 +./2.11BSD/m11/debug.m11:7->ALWAYS:48: ***ERROR Unknown flag DAT given to .PSECT directive + 48 .psect dpure con, dat, prv, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:49: ***ERROR Unknown flag PRV given to .PSECT directive + 49 .psect mixed con, prv, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:50: ***ERROR Unknown flag DAT given to .PSECT directive + 50 .psect errmes con, dat, prv, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:51: ***ERROR Unknown flag BSS given to .PSECT directive + 51 .psect impure con, bss, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:52: ***ERROR Unknown flag BSS given to .PSECT directive + 52 .psect imppas con, bss, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:53: ***ERROR Unknown flag BSS given to .PSECT directive + 53 .psect implin con, bss, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:54: ***ERROR Unknown flag DAT given to .PSECT directive + 54 .psect swtsec con, dat, prv, gbl ; unix command line flags +./2.11BSD/m11/debug.m11:7->ALWAYS:55: ***ERROR Unknown flag DAT given to .PSECT directive + 55 .psect cndsec con, dat, prv, gbl ; gt, le, equ, etc. for '.if' +./2.11BSD/m11/debug.m11:7->ALWAYS:56: ***ERROR Unknown flag DAT given to .PSECT directive + 56 .psect crfsec con, dat, prv, gbl ; args for -cr flag +./2.11BSD/m11/debug.m11:7->ALWAYS:57: ***ERROR Unknown flag DAT given to .PSECT directive + 57 .psect edtsec con, dat, prv, gbl ; args for .enabl +./2.11BSD/m11/debug.m11:7->ALWAYS:58: ***ERROR Unknown flag DAT given to .PSECT directive + 58 .psect lctsec con, dat, prv, gbl ; args for .list +./2.11BSD/m11/debug.m11:7->ALWAYS:59: ***ERROR Unknown flag DAT given to .PSECT directive + 59 .psect psasec con, dat, prv, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:60: ***ERROR Unknown flag DAT given to .PSECT directive + 60 .psect pstsec con, dat, prv, gbl +./2.11BSD/m11/debug.m11:7->ALWAYS:61: ***ERROR Unknown flag DAT given to .PSECT directive + 61 .psect rolbas con, dat, prv, gbl ; core allocation: starts of tables +./2.11BSD/m11/debug.m11:7->ALWAYS:62: ***ERROR Unknown flag DAT given to .PSECT directive + 62 .psect rolsiz con, dat, prv, gbl ; sizes of table entries +./2.11BSD/m11/debug.m11:7->ALWAYS:63: ***ERROR Unknown flag DAT given to .PSECT directive + 63 .psect roltop con, dat, prv, gbl ; tops of tables +./2.11BSD/m11/debug.m11:7->ALWAYS:64: ***ERROR Unknown flag BSS given to .PSECT directive + 64 .psect xpcor con,bss , gbl ; this one MUST come last in core + 65 + 66 + 67 + 68 .macro entsec name ;init a section + 69 .psect name con + 70 .endm entsec + 71 + 72 + 73 + 74 .macro jeq x,?fred + 75 bne fred + 76 jmp x + 77 fred: + 78 .endm + 79 .macro jne x,?fred + 80 beq fred + 81 jmp x + 82 fred: + 83 .endm + 84 .macro xitsec + 85 entsec .text + 86 .endm xitsec + 87 + 88 + 89 .macro call address + 90 jsr pc,address + 91 .endm + 92 + 93 .macro return + 94 rts pc + 95 .endm + 96 + 97 + 98 .macro always + 99 .nlist bex + 100 .endm always + 8 + 9 000000 xitsec + 1 000000 entsec .text + 1 000000 .psect .text con + 10 sdebug: + 11 000000 call savreg + 1 000000 004767 000000G jsr pc,savreg + 12 000004 010046 mov r0,-(sp) + 13 + 14 000006 012702 000004' mov #..s,r2 + 15 000012 016703 000002' mov ..z,r3 + 16 000016 012700 000002 mov #2,r0 + 17 000022 112322 1$: movb (r3)+,(r2)+ + 18 000024 001402 beq 2$ + 19 000026 005200 inc r0 + 20 000030 000774 br 1$ + 21 2$: + 22 000032 112712 000012 movb #12,(r2) + 23 000036 010067 000000' mov r0,..n + 24 ddd: + 25 000042 005767 000000G tst xx.flg + 26 000046 001412 beq 100$ + 27 000050 016746 000000' mov ..n,-(sp) ;write(2, ..s, ..n) + 28 000054 012746 000004' mov #..s,-(sp) + 29 000060 012746 000002 mov #2,-(sp) + 30 000064 005746 tst -(sp) ;simulate return address stack spacing + 31 000066 000000G $write + 32 000070 062706 000010 add #8.,sp ;toss syscall cruft + 33 100$: + 34 000074 012600 mov (sp)+,r0 + 35 000076 return + 1 000076 000207 rts pc + 36 ndebug: + 37 000100 call savreg + 1 000100 004767 000000G jsr pc,savreg + 38 000104 010046 mov r0,-(sp) + 39 000106 012702 000004' mov #..s,r2 + 40 000112 016701 000002' mov ..z,r1 + 41 000116 call dnc + 1 000116 004767 000000G jsr pc,dnc + 42 000122 112722 000012 movb #12,(r2)+ + 43 000126 010267 000000' mov r2,..n + 44 000132 162767 000004' 000000' sub #..s,..n + 45 000140 000740 br ddd + 46 + 47 000142 entsec mixed + 1 000000 .psect mixed con + 48 000000 ..n: .blkw + 49 000002 000000 ..z: .word + 50 000004 ..s: .blkw 100 + 51 000204 ..zbuf: .blkw 100 + 52 + 53 .end + 53 + 7 + + +Symbol table + +$TIMDF= 000007 ..ZBUF 000204RG 006 DDD 000042R 002 LF = 000012 SDEBUG 000000RG 002 +$WRITE= ****** G 1$0 000022R L 002 DEBUG = 000000 MK.SYM= 000001 SPACE = 000040 +. 000404R 006 100$1 000074R L 002 DNC = ****** G NDEBUG 000100RG 002 TAB = 000011 +..N 000000R 006 2$0 000032R L 002 FF = 000014 PDPV45= 000000 VT = 000013 +..S 000004R 006 BPMB = 000020 FT.ID = 000001 RSX11D= 000000 X40 = 000000 +..Z 000002RG 006 CR = 000015 FT.UNX= 000001 SAVREG= ****** G XX.FLG= ****** G + + +Program sections: + +. ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV) + 000000 001 (RW,I,LCL,REL,CON,NOSAV) +.TEXT 000142 002 (RW,I,LCL,REL,CON,NOSAV) +.DATA 000000 003 (RW,I,LCL,REL,CON,NOSAV) +.BSS 000000 004 (RW,I,LCL,REL,CON,NOSAV) +DPURE 000000 005 (RW,I,LCL,REL,CON,NOSAV) +MIXED 000404 006 (RW,I,LCL,REL,CON,NOSAV) +ERRMES 000000 007 (RW,I,LCL,REL,CON,NOSAV) +IMPURE 000000 008 (RW,I,LCL,REL,CON,NOSAV) +IMPPAS 000000 009 (RW,I,LCL,REL,CON,NOSAV) +IMPLIN 000000 010 (RW,I,LCL,REL,CON,NOSAV) +SWTSEC 000000 011 (RW,I,LCL,REL,CON,NOSAV) +CNDSEC 000000 012 (RW,I,LCL,REL,CON,NOSAV) +CRFSEC 000000 013 (RW,I,LCL,REL,CON,NOSAV) +EDTSEC 000000 014 (RW,I,LCL,REL,CON,NOSAV) +LCTSEC 000000 015 (RW,I,LCL,REL,CON,NOSAV) +PSASEC 000000 016 (RW,I,LCL,REL,CON,NOSAV) +PSTSEC 000000 017 (RW,I,LCL,REL,CON,NOSAV) +ROLBAS 000000 018 (RW,I,LCL,REL,CON,NOSAV) +ROLSIZ 000000 019 (RW,I,LCL,REL,CON,NOSAV) +ROLTOP 000000 020 (RW,I,LCL,REL,CON,NOSAV) +XPCOR 000000 021 (RW,I,LCL,REL,CON,NOSAV) diff --git a/crossassemblers/macro11/tests/2.11BSD-m11-errs.lst.ok b/crossassemblers/macro11/tests/2.11BSD-m11-errs.lst.ok new file mode 100644 index 0000000..6a6dc56 --- /dev/null +++ b/crossassemblers/macro11/tests/2.11BSD-m11-errs.lst.ok @@ -0,0 +1,1246 @@ + 1 ;;;; Wrapper for 2.11BSD/m11/errs.m11 + 2 .list + 3 .list + 4 .list + 5 000001 debug = 1 + 6 .include "2.11BSD/m11/at.sml" + 1 .title at.sml - assembler/translator system macros + 2 ; @(#)at.sml 1.3 11/3/82 + 3 + 4 .ident /10may4/ + 5 + 6 .macro always ;all files of macro + 7 + 8 .macro .data + 9 entsec .data + 10 .endm .data + 11 + 12 .macro .text + 13 entsec .text + 14 .endm + 15 + 16 .macro .bss + 17 entsec .bss + 18 .endm + 19 + 20 mk.symbol=1 ;one to make symbols, 0 otherwise + 21 x40= 0 + 22 pdpv45= 0 ; host machine has 'mul', 'div', sob' instrucs. + 23 ; if not you will have to write macros for them + 24 $timdf= 7 ; California Time Zone + 25 ; should really use ftime(2) for this and for + 26 ; DST. + 27 ;xfltg= 0 ;define to assmbl out floating hardware + 28 rsx11d = 0 ; rsx11d features + 29 debug = 0 ; <<< REEDS if non zero includes debug junk + 30 + 31 ft.id= 1 ;have set i & d. set =0 if not + 32 + 33 ft.unx = 1 ; this macro-11 is for UNIX. =0 if not. + 34 + 35 .nlist bex + 36 + 37 tab= 11 + 38 lf= 12 + 39 vt= 13 + 40 ff= 14 + 41 cr= 15 + 42 space= 40 + 43 + 44 bpmb = 20 ;bytes per macro block + 45 + 46 + 47 + 48 + 49 + 50 .psect .text con, shr, gbl,ins + 51 .psect .data con, dat, prv, gbl + 52 .psect .bss con, bss, gbl + 53 + 54 .psect dpure con, dat, prv, gbl + 55 .psect mixed con, prv, gbl + 56 .psect errmes con, dat, prv, gbl + 57 .psect impure con, bss, gbl + 58 .psect imppas con, bss, gbl + 59 .psect implin con, bss, gbl + 60 .psect swtsec con, dat, prv, gbl ; unix command line flags + 61 .psect cndsec con, dat, prv, gbl ; gt, le, equ, etc. for '.if' + 62 .psect crfsec con, dat, prv, gbl ; args for -cr flag + 63 .psect edtsec con, dat, prv, gbl ; args for .enabl + 64 .psect lctsec con, dat, prv, gbl ; args for .list + 65 .psect psasec con, dat, prv, gbl + 66 .psect pstsec con, dat, prv, gbl + 67 .psect rolbas con, dat, prv, gbl ; core allocation: starts of tables + 68 .psect rolsiz con, dat, prv, gbl ; sizes of table entries + 69 .psect roltop con, dat, prv, gbl ; tops of tables + 70 .psect xpcor con,bss , gbl ; this one MUST come last in core + 71 + 72 + 72 + 73 .macro entsec name ;init a section + 74 .psect name con + 75 .endm entsec + 76 + 77 + 78 + 79 .macro jeq x,?fred + 80 bne fred + 81 jmp x + 82 fred: + 83 .endm + 84 .macro jne x,?fred + 85 beq fred + 86 jmp x + 87 fred: + 88 .endm + 89 .macro xitsec + 90 entsec .text + 91 .endm xitsec + 92 + 93 + 94 .macro call address + 95 jsr pc,address + 96 .endm + 97 + 98 .macro return + 99 rts pc + 100 .endm + 101 + 102 + 103 .macro always + 104 .nlist bex + 105 .endm always + 106 .endm always + 107 + 108 + 109 000001 .if ne debug + 110 + 111 .macro ndebug n + 112 .globl ndebug,..z + 113 mov n,..z + 114 call ndebug + 115 .endm + 116 + 117 .macro sdebug string + 118 .globl sdebug,..z,..zbuf + 119 x = 0 + 120 .irpc t, + 121 movb #''t,..zbuf+x + 122 x = x+1 + 123 .endm + 124 movb #0,..zbuf+x + 125 mov #..zbuf,..z + 126 call sdebug + 127 .endm + 128 + 129 .iff + 130 + 131 .macro ndebug n + 132 .endm + 133 + 134 .macro sdebug string + 135 .endm + 136 + 137 .endc + 138 + 139 + 140 .macro param mne, value ;define default parameters + 141 .iif ndf mne, mne= value + 142 .list + 143 mne= mne + 144 .nlist + 145 .endm + 145 + 146 .macro putkb addr ;list to kb + 147 .globl putkb + 148 mov addr,r0 + 149 call putkb + 150 .endm + 151 + 152 .macro putlp addr ;list to lp + 153 .globl putlp + 154 mov addr,r0 + 155 call putlp + 156 .endm + 157 + 158 .macro putkbl addr ;list to kb and lp + 159 .globl putkbl + 160 mov addr,r0 + 161 call putkbl + 162 .endm + 163 + 164 + 165 .macro xmit wrdcnt ;move small # of words + 166 .globl xmit0 + 167 call xmit0- + 168 .endm xmit + 169 + 170 + 171 ;the macro "genswt" is used to specify a command + 172 ;string switch (1st argument) and the address of + 173 ;the routine to be called when encountered (2nd arg). + 174 ; the switch is made upper-case. + 175 + 176 .macro genswt mne,addr,?label + 177 entsec swtsec + 178 label: .irpc x,mne + 179 .if ge ''x-141 + 180 .if le ''x-172 + 181 .byte ''x-40 + 182 .iff + 183 .byte ''x + 184 .endc + 185 .iff + 186 .byte ''x + 187 .endc + 188 .endm + 189 .iif ne <.-label&1>, .byte 0 + 190 .word addr + 191 xitsec + 192 .endm + 192 + 193 .macro zread chan + 194 .globl zread + 195 mov #chan'chn,r0 + 196 call zread + 197 .endm zread + 198 + 199 .macro zwrite chan + 200 .globl zwrite + 201 mov #chan'chn,r0 + 202 call zwrite + 203 .endm zwrite + 203 + 204 .macro genedt mne,subr ;gen enable/disable table + 205 entsec edtsec + 206 .rad50 /mne/ + 207 .if nb subr + 208 .word subr + 209 .iff + 210 .word cpopj + 211 .endc + 212 .word ed.'mne + 213 xitsec + 214 .endm genedt + 215 + 216 + 217 ;the macro "gencnd" is used to specify conditional + 218 ;arguments. it takes two or three arguments: + 219 + 220 ; 1- mnemonic + 221 ; 2- subroutine to be called + 222 ; 3- if non-blank, complement condition + 223 + 224 .macro gencnd mne,subr,toggle ;generate conditional + 225 entsec cndsec + 226 .rad50 /mne/ + 227 .if b + 228 .word subr + 229 .iff + 230 .word subr+1 + 231 .endc + 232 xitsec + 233 .endm + 233 + 234 .macro ch.mne + 235 + 236 ch.ior= '! + 237 ch.qtm= '" + 238 ch.hsh= '# + 239 ch.dol= '$ + 240 ch.pct= '% + 241 ch.and= '& + 242 ch.xcl= '' + 243 + 244 ch.lp= '( + 245 ch.rp= ') + 246 ch.mul= '* + 247 ch.add= '+ + 248 ch.com= ', + 249 ch.sub= '- + 250 ch.dot= '. + 251 ch.div= '/ + 252 + 253 ch.col= ': + 254 ch.smc= '; + 255 ch.lab= '< + 256 ch.equ= '= + 257 ch.rab= '> + 258 ch.qm= '? + 259 + 260 ch.ind= '@ + 261 ch.bsl= '\ + 262 ch.uar= '^ + 263 + 264 let.a= 'a&^c40 + 265 let.b= 'b&^c40 + 266 let.c= 'c&^c40 + 267 let.d= 'd&^c40 + 268 let.e= 'e&^c40 + 269 let.f= 'f&^c40 + 270 let.g= 'g&^c40 + 271 let.o= 'o&^c40 + 272 let.p= 'p&^c40 + 273 let.r= 'r&^c40 + 274 let.z= 'z&^c40 + 275 + 276 dig.0= '0 + 277 dig.9= '9 + 278 .macro ch.mne + 279 .endm ch.mne + 280 .endm ch.mne + 281 + 282 .macro error num,arg, mess ,?x + 283 sdebug + 284 .globl err.'arg,ern'num, errbts,errref + 285 .if b + 286 deliberate error mistake + 287 .endc + 288 .if dif 0,num + 289 .globl err.xx + 290 tst err.xx + 291 bne x + 292 mov #ern'num,err.xx + 293 x: + 294 .endc + 295 bis #err.'arg,errbts + 296 .endm + 297 + 298 + 299 + 300 .macro setnz addr ;set addr to non-zero for t/f flags + 301 mov sp,addr + 302 .endm + 303 + 304 + 305 .macro bisbic arg ; used by .list/.nlist, .enabl/.dsabl + 306 .globl bisbic + 307 mov #arg,-(sp) + 308 call bisbic + 309 tst (sp)+ + 310 .endm + 310 + 311 ;roll handler calls + 312 + 313 .macro search rolnum ;binary search + 314 mov #rolnum,r0 + 315 .globl search + 316 call search + 317 .endm + 318 + 319 .macro scan rolnum ;linear scan + 320 mov #rolnum,r0 + 321 .globl scan + 322 call scan + 323 .endm + 324 + 325 .macro scanw rolnum ;linear scan, one word + 326 mov #rolnum,r0 + 327 .globl scanw + 328 call scanw + 329 .endm + 330 + 331 .macro next rolnum ;fetch next entry + 332 mov #rolnum,r0 + 333 .globl next + 334 call next + 335 .endm + 336 + 337 .macro append rolnum ;append to end of roll + 338 mov #rolnum,r0 + 339 .globl append + 340 call append + 341 .endm + 342 + 343 .macro zap rolnum ;clear roll + 344 mov #rolnum,r0 + 345 .globl zap + 346 call zap + 347 .endm + 348 + 349 ; call insert ;insert (must be preceded by one + 350 ;of the above to set pointers) + 351 ; call setrol ;save and set regs for above + 351 + 352 ;flags used in symbol table mode + 353 + 354 .macro st.flg + 355 + 356 .if le ft.unx + 357 + 358 ovrflg= 000004 ;overlay (psect only) + 359 defflg= 000010 ;defined + 360 relflg= 000040 ;relocatable + 361 glbflg= 000100 ;global + 362 dfgflg= 000200 ; default global ... reeds's guess + 363 + 364 + 365 .endc + 366 + 367 .if gt ft.unx + 368 + 369 ; ****** these should not be changed!! ****** + 370 shrflg= 000001 ;shareable (psect only) + 371 .if gt ft.id + 372 insflg= shrflg*2 ;instruction space (psect only) + 373 bssflg= insflg*2 ;blank section (psect only) + 374 m.idf= shrflg!insflg!bssflg ;mask to turn them off + 375 .iff + 376 bssflg= shrflg*2 + 377 m.idf= shrflg!bssflg + 378 .endc + 379 b.idf= 1 ;shift count to make above bits word offset + 380 ; *********************************** + 381 defflg= 000010 ;defined + 382 ovrflg= 000020 ;overlay (psect only) + 383 relflg= 000040 ;relocatable + 384 glbflg= 000100 ;global + 385 dfgflg= 000200 ; default global ... reeds's guess + 386 + 387 .endc + 388 + 389 ; + 390 ; default psect attribs. + 391 ; can be changed, but make sure all customers know about + 392 ; it, including all the linkers. + 393 ; + 394 pattrs=relflg!defflg ; For .psects and blank .csects + 395 aattrs=glbflg!defflg!ovrflg ; For .asect + 396 cattrs=glbflg!relflg!defflg!ovrflg ; For named .csects + 397 + 398 regflg= 000001 ;register + 399 lblflg= 000002 ;label + 400 mdfflg= 000004 ;multilpy defined + 401 .macro st.flg + 402 .endm + 403 .endm st.flg + 404 + 405 + 406 + 407 .macro ct.mne + 408 .globl cttbl + 409 ct.eol = 000 ; eol + 410 ct.com = 001 ; comma + 411 ct.tab = 002 ; tab + 412 ct.sp = 004 ; space + 413 ct.pcx = 010 ; printing character + 414 ct.num = 020 ; numeric + 415 ct.alp = 040 ; alpha, dot, dollar + 416 ct.lc = 100 ; lower case alpha + 417 ct.smc = 200 ; semi-colon (sign bit) + 418 + 419 ct.pc = ct.com!ct.smc!ct.pcx!ct.num!ct.alp + 420 .macro ct.mne + 421 .endm ct.mne + 422 .endm ct.mne + 423 + 424 + 425 .end + 425 + 7 .include "2.11BSD/m11/errs.m11" + 1 ; + 2 ; m11 error messages + 3 ; jim reeds 4 july 1981 + 4 ; + 5 .mcall (at)always + 6 000000 always + 1 + 2 .macro .data + 3 entsec .data + 4 .endm .data + 5 + 6 .macro .text + 7 entsec .text + 8 .endm + 9 + 10 .macro .bss + 11 entsec .bss + 12 .endm + 13 + 14 000001 mk.symbol=1 ;one to make symbols, 0 otherwise + 15 000000 x40= 0 + 16 000000 pdpv45= 0 ; host machine has 'mul', 'div', sob' instrucs. + 17 ; if not you will have to write macros for them + 18 000007 $timdf= 7 ; California Time Zone + 19 ; should really use ftime(2) for this and for + 20 ; DST. + 21 ;xfltg= 0 ;define to assmbl out floating hardware + 22 000000 rsx11d = 0 ; rsx11d features + 23 000000 debug = 0 ; <<< REEDS if non zero includes debug junk + 24 + 25 000001 ft.id= 1 ;have set i & d. set =0 if not + 26 + 27 000001 ft.unx = 1 ; this macro-11 is for UNIX. =0 if not. + 28 + 29 .nlist bex + 30 + 31 000011 tab= 11 + 32 000012 lf= 12 + 33 000013 vt= 13 + 34 000014 ff= 14 + 35 000015 cr= 15 + 36 000040 space= 40 + 37 + 38 000020 bpmb = 20 ;bytes per macro block + 39 + 40 + 41 + 42 + 43 +./2.11BSD/m11/errs.m11:6->ALWAYS:44: ***ERROR Unknown flag SHR given to .PSECT directive + 44 .psect .text con, shr, gbl,ins +./2.11BSD/m11/errs.m11:6->ALWAYS:45: ***ERROR Unknown flag DAT given to .PSECT directive + 45 .psect .data con, dat, prv, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:46: ***ERROR Unknown flag BSS given to .PSECT directive + 46 .psect .bss con, bss, gbl + 47 +./2.11BSD/m11/errs.m11:6->ALWAYS:48: ***ERROR Unknown flag DAT given to .PSECT directive + 48 .psect dpure con, dat, prv, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:49: ***ERROR Unknown flag PRV given to .PSECT directive + 49 .psect mixed con, prv, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:50: ***ERROR Unknown flag DAT given to .PSECT directive + 50 .psect errmes con, dat, prv, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:51: ***ERROR Unknown flag BSS given to .PSECT directive + 51 .psect impure con, bss, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:52: ***ERROR Unknown flag BSS given to .PSECT directive + 52 .psect imppas con, bss, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:53: ***ERROR Unknown flag BSS given to .PSECT directive + 53 .psect implin con, bss, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:54: ***ERROR Unknown flag DAT given to .PSECT directive + 54 .psect swtsec con, dat, prv, gbl ; unix command line flags +./2.11BSD/m11/errs.m11:6->ALWAYS:55: ***ERROR Unknown flag DAT given to .PSECT directive + 55 .psect cndsec con, dat, prv, gbl ; gt, le, equ, etc. for '.if' +./2.11BSD/m11/errs.m11:6->ALWAYS:56: ***ERROR Unknown flag DAT given to .PSECT directive + 56 .psect crfsec con, dat, prv, gbl ; args for -cr flag +./2.11BSD/m11/errs.m11:6->ALWAYS:57: ***ERROR Unknown flag DAT given to .PSECT directive + 57 .psect edtsec con, dat, prv, gbl ; args for .enabl +./2.11BSD/m11/errs.m11:6->ALWAYS:58: ***ERROR Unknown flag DAT given to .PSECT directive + 58 .psect lctsec con, dat, prv, gbl ; args for .list +./2.11BSD/m11/errs.m11:6->ALWAYS:59: ***ERROR Unknown flag DAT given to .PSECT directive + 59 .psect psasec con, dat, prv, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:60: ***ERROR Unknown flag DAT given to .PSECT directive + 60 .psect pstsec con, dat, prv, gbl +./2.11BSD/m11/errs.m11:6->ALWAYS:61: ***ERROR Unknown flag DAT given to .PSECT directive + 61 .psect rolbas con, dat, prv, gbl ; core allocation: starts of tables +./2.11BSD/m11/errs.m11:6->ALWAYS:62: ***ERROR Unknown flag DAT given to .PSECT directive + 62 .psect rolsiz con, dat, prv, gbl ; sizes of table entries +./2.11BSD/m11/errs.m11:6->ALWAYS:63: ***ERROR Unknown flag DAT given to .PSECT directive + 63 .psect roltop con, dat, prv, gbl ; tops of tables +./2.11BSD/m11/errs.m11:6->ALWAYS:64: ***ERROR Unknown flag BSS given to .PSECT directive + 64 .psect xpcor con,bss , gbl ; this one MUST come last in core + 65 + 66 + 67 + 68 .macro entsec name ;init a section + 69 .psect name con + 70 .endm entsec + 71 + 72 + 73 + 74 .macro jeq x,?fred + 75 bne fred + 76 jmp x + 77 fred: + 78 .endm + 79 .macro jne x,?fred + 80 beq fred + 81 jmp x + 82 fred: + 83 .endm + 84 .macro xitsec + 85 entsec .text + 86 .endm xitsec + 87 + 88 + 89 .macro call address + 90 jsr pc,address + 91 .endm + 92 + 93 .macro return + 94 rts pc + 95 .endm + 96 + 97 + 98 .macro always + 99 .nlist bex + 100 .endm always + 7 + 8 000000 .data + 1 000000 entsec .data + 1 000000 .psect .data con + 9 .dsabl lc + 10 .LIST MD,ME,MC + 11 + 12 .MACRO ERRGEN NUM,CODE,TEXT + 13 ern'num:: .asciz \text\ + 14 .endm + 15 000000 ERRGEN 1,R, + 1 000000 103 101 116 ERN1:: .ASCIZ \CANNOT RELOCATE A REGISTER\ + 000003 116 117 124 + 000006 040 122 105 + 000011 114 117 103 + 000014 101 124 105 + 000017 040 101 040 + 000022 122 105 107 + 000025 111 123 124 + 000030 105 122 000 + 16 000033 ERRGEN 2,A, + 1 000033 111 115 120 ERN2:: .ASCIZ \IMPROPER RELOCATION\ + 000036 122 117 120 + 000041 105 122 040 + 000044 122 105 114 + 000047 117 103 101 + 000052 124 111 117 + 000055 116 000 + 17 000057 ERRGEN 3,A, + 1 000057 102 101 104 ERN3:: .ASCIZ \BAD EXPRESSION\ + 000062 040 105 130 + 000065 120 122 105 + 000070 123 123 111 + 000073 117 116 000 + 18 000076 ERRGEN 4,U, + 1 000076 125 116 104 ERN4:: .ASCIZ \UNDEFINED SYMBOL\ + 000101 105 106 111 + 000104 116 105 104 + 000107 040 123 131 + 000112 115 102 117 + 000115 114 000 + 19 000117 ERRGEN 5,M, + 1 000117 115 125 114 ERN5:: .ASCIZ \MULTIPLY DEFINED\ + 000122 124 111 120 + 000125 114 131 040 + 000130 104 105 106 + 000133 111 116 105 + 000136 104 000 + 20 000140 ERRGEN 6,N, + 1 000140 104 111 107 ERN6:: .ASCIZ \DIGIT ILLEGAL IN CURRENT RADIX\ + 000143 111 124 040 + 000146 111 114 114 + 000151 105 107 101 + 000154 114 040 111 + 000157 116 040 103 + 000162 125 122 122 + 000165 105 116 124 + 000170 040 122 101 + 000173 104 111 130 + 000176 000 + 21 000177 ERRGEN 7,T, + 1 000177 116 125 115 ERN7:: .ASCIZ \NUMBER TOO BIG\ + 000202 102 105 122 + 000205 040 124 117 + 000210 117 040 102 + 000213 111 107 000 + 22 000216 ERRGEN 8,U, + 1 000216 114 117 103 ERN8:: .ASCIZ \LOCAL SYMBOL NOT DEFINED\ + 000221 101 114 040 + 000224 123 131 115 + 000227 102 117 114 + 000232 040 116 117 + 000235 124 040 104 + 000240 105 106 111 + 000243 116 105 104 + 000246 000 + 23 000247 ERRGEN 9,A, + 1 000247 105 115 120 ERN9:: .ASCIZ \EMPTY FLOATING POINT NUMBER\ + 000252 124 131 040 + 000255 106 114 117 + 000260 101 124 111 + 000263 116 107 040 + 000266 120 117 111 + 000271 116 124 040 + 000274 116 125 115 + 000277 102 105 122 + 000302 000 + 24 000303 ERRGEN 10,N, + 1 000303 106 114 117 ERN10:: .ASCIZ \FLOATING POINT OVERFLOW\ + 000306 101 124 111 + 000311 116 107 040 + 000314 120 117 111 + 000317 116 124 040 + 000322 117 126 105 + 000325 122 106 114 + 000330 117 127 000 + 25 000333 ERRGEN 11,T, + 1 000333 124 122 125 ERN11:: .ASCIZ \TRUNCTATION ERROR\ + 000336 116 103 124 + 000341 101 124 111 + 000344 117 116 040 + 000347 105 122 122 + 000352 117 122 000 + 26 000355 ERRGEN 12,L, + 1 000355 114 111 116 ERN12:: .ASCIZ \LINE TOO LONG\ + 000360 105 040 124 + 000363 117 117 040 + 000366 114 117 116 + 000371 107 000 + 27 000373 ERRGEN 13,I, + 1 000373 111 114 114 ERN13:: .ASCIZ \ILLEGAL CHARACTER\ + 000376 105 107 101 + 000401 114 040 103 + 000404 110 101 122 + 000407 101 103 124 + 000412 105 122 000 + 28 000415 ERRGEN 14,E,<.END NOT FOUND> + 1 000415 056 105 116 ERN14:: .ASCIZ \.END NOT FOUND\ + 000420 104 040 116 + 000423 117 124 040 + 000426 106 117 125 + 000431 116 104 000 + 29 000434 ERRGEN 140,E, + 1 000434 105 116 104 ERN140:: .ASCIZ \END OF INPUT WITH UNTERMINATED MACRO OR REPEAT\ + 000437 040 117 106 + 000442 040 111 116 + 000445 120 125 124 + 000450 040 127 111 + 000453 124 110 040 + 000456 125 116 124 + 000461 105 122 115 + 000464 111 116 101 + 000467 124 105 104 + 000472 040 115 101 + 000475 103 122 117 + 000500 040 117 122 + 000503 040 122 105 + 000506 120 105 101 + 000511 124 000 + 30 000513 ERRGEN 15,O, + 1 000513 103 117 116 ERN15:: .ASCIZ \CONDITIONAL NOT IN PROGRESS\ + 000516 104 111 124 + 000521 111 117 116 + 000524 101 114 040 + 000527 116 117 124 + 000532 040 111 116 + 000535 040 120 122 + 000540 117 107 122 + 000543 105 123 123 + 000546 000 + 31 000547 ERRGEN 16,O, + 1 000547 124 117 117 ERN16:: .ASCIZ \TOO MANY NESTED CONDITIONALS\ + 000552 040 115 101 + 000555 116 131 040 + 000560 116 105 123 + 000563 124 105 104 + 000566 040 103 117 + 000571 116 104 111 + 000574 124 111 117 + 000577 116 101 114 + 000602 123 000 + 32 000604 ERRGEN 17,A, + 1 000604 103 117 116 ERN17:: .ASCIZ \CONDITIONAL ARGUMENT NOT SPECIFIED\ + 000607 104 111 124 + 000612 111 117 116 + 000615 101 114 040 + 000620 101 122 107 + 000623 125 115 105 + 000626 116 124 040 + 000631 116 117 124 + 000634 040 123 120 + 000637 105 103 111 + 000642 106 111 105 + 000645 104 000 + 33 000647 ERRGEN 18,T, + 1 000647 111 114 114 ERN18:: .ASCIZ \ILLEGAL LOCAL SYMBOL\ + 000652 105 107 101 + 000655 114 040 114 + 000660 117 103 101 + 000663 114 040 123 + 000666 131 115 102 + 000671 117 114 000 + 34 000674 ERRGEN 19,Q, + 1 000674 122 101 116 ERN19:: .ASCIZ \RANDOM JUNK AT END OF STATEMENT IGNORED\ + 000677 104 117 115 + 000702 040 112 125 + 000705 116 113 040 + 000710 101 124 040 + 000713 105 116 104 + 000716 040 117 106 + 000721 040 123 124 + 000724 101 124 105 + 000727 115 105 116 + 000732 124 040 111 + 000735 107 116 117 + 000740 122 105 104 + 000743 000 + 35 000744 ERRGEN 20,A, + 1 000744 115 111 123 ERN20:: .ASCIZ \MISSING TITLE\ + 000747 123 111 116 + 000752 107 040 124 + 000755 111 124 114 + 000760 105 000 + 36 000762 ERRGEN 0,<>, + 1 000762 125 123 105 ERN0:: .ASCIZ \USER GENERATED ERROR\ + 000765 122 040 107 + 000770 105 116 105 + 000773 122 101 124 + 000776 105 104 040 + 001001 105 122 122 + 001004 117 122 000 + 37 001007 ERRGEN 22,A, + 1 001007 115 111 123 ERN22:: .ASCIZ \MISSING DELIMITING CHARACTER\ + 001012 123 111 116 + 001015 107 040 104 + 001020 105 114 111 + 001023 115 111 124 + 001026 111 116 107 + 001031 040 103 110 + 001034 101 122 101 + 001037 103 124 105 + 001042 122 000 + 38 001044 ERRGEN 23,A, + 1 001044 125 116 113 ERN23:: .ASCIZ \UNKNOWN .LIST/.NLIST ARGUMENT\ + 001047 116 117 127 + 001052 116 040 056 + 001055 114 111 123 + 001060 124 057 056 + 001063 116 114 111 + 001066 123 124 040 + 001071 101 122 107 + 001074 125 115 105 + 001077 116 124 000 + 39 001102 ERRGEN 24,O, + 1 001102 117 120 103 ERN24:: .ASCIZ \OPCODE OUT OF CONTEXT\ + 001105 117 104 105 + 001110 040 117 125 + 001113 124 040 117 + 001116 106 040 103 + 001121 117 116 124 + 001124 105 130 124 + 001127 000 + 40 001130 ERRGEN 25,O, + 1 001130 115 111 123 ERN25:: .ASCIZ \MISSING MACRO NAME\ + 001133 123 111 116 + 001136 107 040 115 + 001141 101 103 122 + 001144 117 040 116 + 001147 101 115 105 + 001152 000 + 41 001153 ERRGEN 26,A,<.ENDM NAME DOESN'T MATCH .MACRO NAME> + 1 001153 056 105 116 ERN26:: .ASCIZ \.ENDM NAME DOESN'T MATCH .MACRO NAME\ + 001156 104 115 040 + 001161 116 101 115 + 001164 105 040 104 + 001167 117 105 123 + 001172 116 047 124 + 001175 040 115 101 + 001200 124 103 110 + 001203 040 056 115 + 001206 101 103 122 + 001211 117 040 116 + 001214 101 115 105 + 001217 000 + 42 001220 ERRGEN 27,A, + 1 001220 111 114 114 ERN27:: .ASCIZ \ILLEGAL ARGUMENTS\ + 001223 105 107 101 + 001226 114 040 101 + 001231 122 107 125 + 001234 115 105 116 + 001237 124 123 000 + 43 001242 ERRGEN 28,A, + 1 001242 116 117 040 ERN28:: .ASCIZ \NO SYMBOL TO ASSIGN TO\ + 001245 123 131 115 + 001250 102 117 114 + 001253 040 124 117 + 001256 040 101 123 + 001261 123 111 107 + 001264 116 040 124 + 001267 117 000 + 44 001271 ERRGEN 29,O, + 1 001271 125 116 102 ERN29:: .ASCIZ \UNBALANCED .ENDM\ + 001274 101 114 101 + 001277 116 103 105 + 001302 104 040 056 + 001305 105 116 104 + 001310 115 000 + 45 001312 ERRGEN 30,A, + 1 001312 115 111 123 ERN30:: .ASCIZ \MISSING ARGUMENT IN 'IF' CONSTRUCTION\ + 001315 123 111 116 + 001320 107 040 101 + 001323 122 107 125 + 001326 115 105 116 + 001331 124 040 111 + 001334 116 040 047 + 001337 111 106 047 + 001342 040 103 117 + 001345 116 123 124 + 001350 122 125 103 + 001353 124 111 117 + 001356 116 000 + 46 001360 ERRGEN 31,A, + 1 001360 115 111 123 ERN31:: .ASCIZ \MISSING ARGUMENT\ + 001363 123 111 116 + 001366 107 040 101 + 001371 122 107 125 + 001374 115 105 116 + 001377 124 000 + 47 001401 ERRGEN 70,A, + 1 001401 114 117 103 ERN70:: .ASCIZ \LOCAL OFFSET OUT OF RANGE\ + 001404 101 114 040 + 001407 117 106 106 + 001412 123 105 124 + 001415 040 117 125 + 001420 124 040 117 + 001423 106 040 122 + 001426 101 116 107 + 001431 105 000 + 48 001433 ERRGEN 71,A, + 1 001433 111 114 114 ERN71:: .ASCIZ \ILLEGAL REGISTER NUMBER\ + 001436 105 107 101 + 001441 114 040 122 + 001444 105 107 111 + 001447 123 124 105 + 001452 122 040 116 + 001455 125 115 102 + 001460 105 122 000 + 49 001463 ERRGEN 32,P, + 1 001463 120 110 101 ERN32:: .ASCIZ \PHASE ERROR IN LABEL DEFINITION\ + 001466 123 105 040 + 001471 105 122 122 + 001474 117 122 040 + 001477 111 116 040 + 001502 114 101 102 + 001505 105 114 040 + 001510 104 105 106 + 001513 111 116 111 + 001516 124 111 117 + 001521 116 000 + 50 001523 ERRGEN 33,Q, + 1 001523 111 114 114 ERN33:: .ASCIZ \ILLEGAL LABEL\ + 001526 105 107 101 + 001531 114 040 114 + 001534 101 102 105 + 001537 114 000 + 51 001541 ERRGEN 34,M,