sumacc/ 775 0 12 0 3671443374 5233 sumacc/cc/ 775 0 12 0 3540162153 5604 sumacc/cc/as/ 775 0 12 0 3540162156 6212 sumacc/cc/as/.netupd_log 444 0 12 7757 3470501535 10454 Sat Apr 28 17:55:42 1984 created file a68.hdr[coyote], author: mann on Sat Apr 7 02:03:15 1984 Sat Apr 28 17:55:46 1984 created file as.c[coyote], author: ds on Sat Apr 7 02:01:46 1984 Sat Apr 28 17:55:50 1984 created file as.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:56:06 1984 created file as68[coyote], author: ds on Sat Apr 7 02:04:52 1984 Sat Apr 28 17:56:10 1984 created file as68.1[coyote], author: mogul on Mon Apr 9 23:00:58 1984 Sat Apr 28 17:56:14 1984 created file cond.c[coyote], author: ds on Sat Apr 7 02:01:57 1984 Sat Apr 28 17:56:19 1984 created file cond.o[coyote], author: mann on Sat Apr 7 02:04:38 1984 Sat Apr 28 17:56:22 1984 created file error.c[coyote], author: ds on Sat Apr 7 02:01:59 1984 Sat Apr 28 17:56:26 1984 created file error.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:56:32 1984 created file eval.c[coyote], author: ds on Sat Apr 7 02:02:03 1984 Sat Apr 28 17:56:35 1984 created file eval.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:56:39 1984 created file init.c[coyote], author: ds on Sat Apr 7 02:02:06 1984 Sat Apr 28 17:56:44 1984 created file init.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:56:54 1984 created file ins.c[coyote], author: ds on Sat Apr 7 02:02:13 1984 Sat Apr 28 17:57:02 1984 created file ins.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:57:06 1984 created file inst.h[coyote], author: ds on Sat Apr 7 02:02:16 1984 Sat Apr 28 17:57:12 1984 created file mac.c[coyote], author: ds on Sat Apr 7 02:02:20 1984 Sat Apr 28 17:57:17 1984 created file mac.h[coyote], author: ds on Sat Apr 7 02:02:22 1984 Sat Apr 28 17:57:22 1984 created file mac.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:57:24 1984 created file makefile[coyote], author: ds on Sat Apr 7 02:02:24 1984 Sat Apr 28 17:57:29 1984 created file mical.h[coyote], author: ds on Sat Apr 7 02:02:25 1984 Sat Apr 28 17:57:33 1984 created file oper.c[coyote], author: ds on Sat Apr 7 02:02:26 1984 Sat Apr 28 17:57:37 1984 created file oper.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:57:43 1984 created file print.c[coyote], author: ds on Sat Apr 7 02:02:28 1984 Sat Apr 28 17:57:48 1984 created file print.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:57:54 1984 created file ps.c[coyote], author: ds on Sat Apr 7 02:02:30 1984 Sat Apr 28 17:57:58 1984 created file ps.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:03 1984 created file ps1.c[coyote], author: ds on Sat Apr 7 02:02:32 1984 Sat Apr 28 17:58:08 1984 created file ps1.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:13 1984 created file ps2.c[coyote], author: ds on Sat Apr 7 02:02:34 1984 Sat Apr 28 17:58:17 1984 created file ps2.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:20 1984 created file ps3.c[coyote], author: ds on Sat Apr 7 02:02:37 1984 Sat Apr 28 17:58:23 1984 created file ps3.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:29 1984 created file random.c[coyote], author: ds on Sat Apr 7 02:02:39 1984 Sat Apr 28 17:58:32 1984 created file random.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:37 1984 created file rel.c[coyote], author: ds on Sat Apr 7 02:02:40 1984 Sat Apr 28 17:58:42 1984 created file rel.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:48 1984 created file sdi.c[coyote], author: ds on Sat Apr 7 02:02:42 1984 Sat Apr 28 17:58:54 1984 created file sdi.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:58 1984 created file spawn.c[coyote], author: ds on Sat Apr 7 02:02:44 1984 Sat Apr 28 17:59:02 1984 created file spawn.o[coyote], author: ds on Sat Apr 7 02:04:20 1984 Sat Apr 28 17:59:09 1984 created file sym.c[coyote], author: ds on Sat Apr 7 02:02:48 1984 Sat Apr 28 17:59:13 1984 created file sym.o[coyote], author: ds on Sat Apr 7 02:04:20 1984 file oper.c[coyosumacc/cc/as/a68.hdr 444 0 12 1373 3470501535 7374 | Pre-Assembly Code | The remainder of this file consists of statements that are | interpreted before every 68000 program. | Define Register Names .defrs d0, 0., d1, 1., d2, 2., d3, 3. .defrs d4, 4., d5, 5., d6, 6., d7, 7. .defrs a0, 8., a1, 9., a2, 10., a3, 11. .defrs a4, 12., a5, 13., a6, 14., a7, 15. .defrs sp, 15., pc, 16., cc, 17., sr, 18., usp, 19. | Next line is for 68010. --TPM .defrs sfc, 20., dfc, 21., vbr 22. | Set Input and Output Radices .radix in, decimal .radix out, hex | Define registers for movem | D3 means just d3, D3+A2 means d3 and a2, A2-D3 means a1,a0,d7,...,d4,d3 D0 = /1 D1 = /2 D2 = /4 D3 = /8 D4 = /10 D5 = /20 D6 = /40 D7 = /80 A0 = /100 A1 = /200 A2 = /400 A3 = /800 A4 = /1000 A5 = /2000 A6 = /4000 A7 = /8000 ALL = 0 hor: ds on Sat Apr 7 02:02:34 1984 Sat Apr 28 17:58:17 1984 created file ps2.o[coyote], author: ds on Sat Apr 7 02:04:19 1984 Sat Apr 28 17:58:20 1984 created file ps3.c[coyote], author: ds on Sat Apr 7 02:02:37 1984 Sat Apr 28 17:58:23 1984 created fisumacc/cc/as/as.c 444 0 12 3555 3470501535 7052 # /* This is the main loop of the 68000 assembler. Written by Mike Patrick, Fall 76. Modified by C. Terman 5/79 Hacked by J. Gula 10/79 */ #include "mical.h" /* when Done is nonzero, the assembler is finished. This is the normal means of exit */ int Done = 0; main(argc,argv) int argc; char *argv[]; { extern struct sym_bkt *Dot_bkt; /* ptr to symbol bucket for location counter */ extern struct csect *Cur_csect; /* ptr to current csect */ extern int Errors; /* number of assembly errors */ if (Init(argc,argv)){ /* Init returns 1 if it is able to open all source files, read the descriptor file, and generally set things up */ while (Done == 0) { /* Done becomes 1 when the assembler is finished, on an unexpected eof, or on an assembler error */ Read_Line(); /* Read the next line, from source files or macro expansions */ /* Each of the functions in the following nested if statement will return TRUE if it wasn't able to process the current line entirely */ if (Cond()) /* Cond handles all conditional pseudo-ops */ if (Label()) /* Label picks up all label fields, as well as "=" statements */ if (Pseudo()) /* Pseudo handles all assembler directives, (including .macro), other than .if, .iif, etc */ if (Macro()) /* Macro recognizes macro calls, and sets up things so that Read_Line will read them */ if (Instruction()) /* Instruction handles the normal machine instruction statements */ ByteWord(2); /* If all else fails, assume the line is an expression, and call the */ /* .word pseudo-op handler to process it */ Dot += BC; /* increment dot by number of machine addresses */ Cur_csect->dot_cs = Dot_bkt->value_s = Dot; if (Dot > Cur_csect->len_cs) /* Update Dot bucket and Current csect length */ Cur_csect->len_cs = Dot; } } exit(Errors? -1: 0); /* if assembly errors, return -1; otherwise 0 */ } hor: ds on Sat Apr 7 02:02:48 1984 Sat Apr 28 17:59:13 1984 created file sym.o[coyote], author: ds on Sat Apr 7 02:04:20 1984 file oper.c[coyosumacc/cc/as/as68.1 444 0 12 1562 3470501536 7143 .TH AS68 1 MC68000 .SU .SH NAME as68 \- .a68 -> .b assembler component of cc68 .SH SYNOPSIS .B as68 [ -godspel ] filename .SH DESCRIPTION .I As68 is the 68000 assembler. The input is taken from filename.a68, if present, otherwise from filename. The output is sent to filename.b. More than one input file can be specified, but only a single output is generated. The available flags are .TP .B -g Undefined symbols are automatically declared global for later resolution by the loader. .TP .B -o " filename" Direct output to filename. .TP .B -d Print info helpful for debugging the assembler .TP .B -s Put symbol table in list.out (relocatable values only) .TP .B -p Print listing on stdout .TP .B -e External symbols only in output .TP .B -l produces a listing, filename.list .SH FILES /usr/sun/a68 /usr/bin/as68 /usr/sun/doc/a68opcodes .SH SEE ALSO cc68 (1), pc68(1), ld68 (1). functions in the following nested if statement will return TRUE if it wasn't able to process the current line entirely */ if (Cond()sumacc/cc/as/cond.c 444 0 12 14154 3470501536 7410 # #include "mical.h" /*************************************************** * * * Mical Assembler - conditional assembly handlers * * * ***************************************************/ /* * Modified by Bill Nowicki Januray 1982 for V7 C syntax */ #define IF 1 #define IFT 2 #define IFF 3 #define IFTF 4 /* Ignore flag, set when processing an unsatisfied conditional block */ FLAG Ignore; /* Cond_level: level of nested conditional blocks. */ int Cond_level = 0; /* Condition and Subcondition block bit vectors. [Sub]Condition[Cond_level] == true whenever current [sub]conditional block is satisfied. The outermost conditional block [initial block] is satisfied. */ FLAG Condition[COND_MAX] = true; /* sets Condition[0] true */ FLAG Subcondition[COND_MAX] = true; /* Cond() - check for conditional pseudo-ops. If we are currently in an unsatisfied conditional block [Ignore == true], then check for the two statements ".endc" (which ends the block) and ".iff" (which causes a new conditional block if the current one is unsatisfied). */ FLAG Eval_Cond(); Cond() { char S[STR_MAX]; int Save; Save = Position; /* save our current position on the input line */ if ( Get_Token(S)) { /* Pick up first token */ /* and call the appropriate routine */ /* The following five checks should appear before the check of Ignore */ if (seq(S,".endc")) Endc(); else if (seq(S,".ift")) Iftf(IFT); else if (seq(S,".iff")) Iftf(IFF); else if (seq(S,".iftf")) Iftf(IFTF); else if (seq(S,".if")) If(); /* If Ignore is set, then disregard the line (just print it out); */ else if (Ignore) { Print_Line(P_NONE); /* print the line */ return(FALSE); } /* signifying that processing of the current line is complete */ else if (seq(S,".iif")) /* immediate conditional */ if (Eval_Cond()) { Non_Blank(); /* skip comma */ if (Line[Position] == ',') Position++; return(TRUE); } /* it's true, so continue processing this line */ else { Print_Line(P_NONE); /* it's false, so just print this line, and be done with it */ return(FALSE); } /* No pseudo-op was found, so restore things and continue processing on the line */ else { Position = Save; return(TRUE); } /* We found a directive and have processed it */ return(FALSE); } /* No token was found, so restore Position and continue processing the line */ Position = Save; return(TRUE); } Endc() { if (Cond_level > 0) Cond_level--; /* decrement condition block level */ else Prog_Warning(E_ENDC); Ignore = Subcondition[Cond_level] ? false : true; /* Ignore is the opposition of the value of the outer subconditional block */ Print_Line(P_NONE); } /* Enter a new conditional block. Format of statement is: .IF <LOGOP>, <expr>[,<expr>] If the <expr> satisfies the the logical operator <LOGOP>, then the conditional block is said to have a value of "true", and normal processing continues. If <expr> does not satisfy <LOGOP>, then the block is said to have a value of "false", and all normal statements in this block are ignored; (exceptions are the subconditional statements .ift, .iff, & .iftf). If the block itself is supposed to be ignored, (Ignore == true when encountering the .if statement), then act as if the expression was not satisfied. */ If(Which) int Which; { if (Cond_level >= COND_MAX-1) Prog_Warning(E_LEVELS); else { Cond_level++; /* enter a new cond block */ Condition[Cond_level] = Subcondition[Cond_level] = Ignore? false: Eval_Cond(); /* set the block value accordingly */ Ignore = Subcondition[Cond_level] ? false : true; /* set Ignore flag to opposite of block value */ } Print_Line(P_NONE); } /* Enter a subconditional block. This is analogous to entering a new conditional block given that the current conditional block is true (.IFT), is false (.IFF) or either (.IFTF). */ Iftf(Which) int Which; { switch(Which) { case IFT: Subcondition[Cond_level] = Condition[Cond_level]; break; case IFF: Subcondition[Cond_level] = Condition[Cond_level] ? false : true; break; case IFTF: Subcondition[Cond_level] = true; break; default: Sys_Error("Iftf called with bad option: %d", Which); } Ignore = Subcondition[Cond_level] ? false : true; /* set Ignore to oppositie of subconditional block level */ Print_Line(P_NONE); } /* Evaluate a condition of the form <LOGOP>, <expr>[,<expr>] */ #define ZERO 01 #define POSITIVE 02 #define NEGATIVE 04 struct { char *condition; /* char string representing logical operator */ char relation; /* status of <expr> for condition to be true */ } cond_table[] = { "eq", ZERO, "z", ZERO, "ne", POSITIVE|NEGATIVE, "nz", POSITIVE|NEGATIVE, "gt", POSITIVE, "g", POSITIVE, "ge", POSITIVE|ZERO, "lt", NEGATIVE, "l", NEGATIVE, "le", NEGATIVE|ZERO, 0 } ; FLAG Eval_Cond() { int i,V; char S[STR_MAX]; FLAG df, def; struct sym_bkt *sbp; extern struct sym_bkt *Lookup(); if (Get_Token(S) == 0) { /* get condition code */ Prog_Error(E_CONDITION); return(false); } Lower(S); /* convert to lower case */ Non_Blank(); /* skip comma */ if (Line[Position] == ',') Position++; Non_Blank(); df = false; /* true if he wants "df" condition */ if ((df = seq(S,"df")) || seq(S,"ndf")) { /* check for symbol-defined conditions */ if (Get_Token(S) == 0) { /* pick up symbol name */ Prog_Error(E_SYMBOL); /* complain if it isn't there */ return(false); } sbp = Lookup(S); /* get symbol bucket for it */ def = (sbp->attr_s & S_DEF) ? true : false; /* set def to true if symbol is defined */ if (df) return(def); /* return whatever sense he wants */ else return(df? false : true); } Get_Operand(&Operand); /* evaluate <expr> and load into Operand structure */ V = Operand.value_o; /* V get operand value */ for (i = 0; cond_table[i].condition; i++) /* find condition, and return appropriately */ if (seq(S,cond_table[i].condition)) if (V > 0 && cond_table[i].relation & POSITIVE) return(true); else if (V == 0 && cond_table[i].relation & ZERO) return(true); else if (V < 0 && cond_table[i].relation & NEGATIVE) return(true); else return(false); Prog_Error(E_CONDITION); return(false); } ound, so restore things and continue processing on the line */ else { Position = Save; return(TRUE); } /* We found a directive and have processed it */ return(FALSE); } /* No token was found, so restore Position and continue processing the line */ Position = Save; return(TRUE); } Endc() { if (Cond_level > 0) Cond_level--; /* decrement condition block level */ else Prog_Warninsumacc/cc/as/error.c 444 0 12 12457 3470501536 7622 #include "mical.h" char *error = "~|^`s.error.c R1.3 on 1/3/80"; /* * * Sys_Error(), Prog_Error(), and Describe_Error() for mical assembler * */ char *E_messages[] = { /* 0 */ "<unused>", /* 1 */ "Missing .end statement", /* 2 */ "Invalid character", /* 3 */ "Multiply defined symbol", /* 4 */ "Symbol storage exceeded", /* 5 */ "Offset too large", /* 6 */ "Symbol too long", /* 7 */ "Undefined symbol", /* 8 */ "Invalid constant", /* 9 */ "Invalid term", /* 10 */ "Invalid operator", /* 11 */ "Non-relocatable expression", /* 12 */ "Wrong type for instruction", /* 13 */ "Invalid operand", /* 14 */ "Invalid symbol", /* 15 */ "Invalid assignment", /* 16 */ "Too many labels", /* 17 */ "Invalid op-code", /* 18 */ "Invalid entry point", /* 19 */ "Invalid string", /* 20 */ "Bad filename or too many levels", /* 21 */ "Warning--attribute ignored", /* 22 */ ".Error statement", /* 23 */ "Too many levels: statement ignored", /* 24 */ "Invalid condition", /* 25 */ "Wrong number of operands", /* 26 */ "Line too long", /* 27 */ "Invalid register expression", /* 28 */ "Invalid machine address", /* 29 */ "Unimplemented directive", /* 30 */ "Cannot open inserted file", /* 31 */ "Invalid string", /* 32 */ "Too many macro arguments", /* 33 */ "Invalid macro argument", /* 34 */ "Invalid formal argument", /* 35 */ "Inappropriate .endc statement; ignored", /* 36 */ "Warning--relative address may be out of range", /* 37 */ "Warning--invalid argument; ignored", /* 38 */ "Invalid instruction vector index", /* 39 */ "Invalid instruction vector", /* 40 */ "Invalid macro name", /* 41 */ "Unable to expand time macro", /* 42 */ "Bad csect", /* 43 */ "Odd address", 0 } ; int Errors = 0; /* Number of errors in this pass */ int Warnings = 0; /* Number of warnings on this pass */ int Err_code = 0; /* error code. reset each statement */ int E_pass1; /* error code for unignored pass 1 error */ int Err_list[ERR_MAX]; /* list of all error codes in this pass */ int Err_load = 0; /* subscript to load into Err_list */ char E_warn = ' '; /* 'W' if warning present. reset each stmnt */ extern FILE *listout; /* use this file for listings *//* Sys_Error is called when a System Error occurs, that is, something is wrong with the assembler itself. Each routine of the assembler usually checks the arguments passed to it for validity, and calls this routine if its parameters are invalid. Explanation is a string suitable for a printf control string which explains the error, and Number is the value of the offending parameter. This routine will not return. */ Sys_Error(Explanation,Number) char *Explanation; { fprintf(stderr, "Assembler Error-- "); fprintf(stderr, Explanation,Number); abort(); } /* This is called whenever the assembler recognizes an error in the current statement. It registers the error, so that an error code will be listed with the statement, and a description of the error will be printed at the end of the listing */ Prog_Error(code) register int code; { register int i; if (Pass != 2) return; /* no errors on pass 1 */ if (E_warn == 'W') { /* Override a warning */ E_warn = ' '; /* by turning off warning flag */ --Warnings; } /* decrementing warning count */ /* but not removing the error description */ else if (Err_code) return; /* If there's a previous error (not warning) on this statement, ignore this one */ Err_code = code; /* set the current error */ Errors++; /* increment error count */ for (i=0; i < Err_load; i++) if (Err_list[i] == code) return; Err_list[Err_load++] = code; } /* Prog_Warning registers a warning on a statement. A warning is like an error, in that something is probably amiss, but the assembler will still try to generate the .rel file. */ Prog_Warning(code){ if (Pass != 2) return; if (Err_code) return; /* If an error is already registered, ignore this one */ Prog_Error(code); /* Try to register it as an error */ Errors--; /* Change error to warning */ Warnings++; E_warn = 'W'; } /* Error_Describe is called at the end of pass 2 to describe the errors incurred in the program */ Error_Describe() { /* print the trailer info to the error output stream, and also to the listing file, if need be */ extern FLAG O_list; /* set if listing requested */ Error_Endprint(stdout); if (O_list) Error_Endprint(listout); return; } /* Error_Endprint actually prints the error descriptions, but sends them to outfile, which should be a file descriptor */ Error_Endprint(outfile) FILE *outfile; { register int i; extern char O_debug; /* debug switch, set from command line */ if ((Errors == 0) && (Warnings == 0)) return; fprintf(outfile, "\n\n\t%d Error(s) and %d Warning(s)\n\t #\tDescription of Error(s)\n\n",Errors,Warnings); if (O_debug > 5) fprintf(outfile, "\n Err_load=%d\n",Err_load); for (i=0;i<Err_load;i++) /* Describe the errors in Err_list */ fprintf(outfile, "\t%d\t%s\n",Err_list[i],E_messages[Err_list[i]]); } /* print a text line so user can see the error */ Print_Error() { int fsave; extern int Err_code, Line_no; extern FLAG O_list; if (Err_code == 0) return; /* nothing to say */ if (O_list) return; /* he's going to see it anyway */ O_list = true; /* set O_list, so Print_Line will work */ listout = stdout; /* print to standard output */ Print_Line(P_ALL); /* print the line */ O_list = false; /* reset O_list */ } / "Inappropriate .endc statement; ignored", /* 36 */ "Warning--relative address may be out of range", /* 37 */ "Warning--invalid argument; ignored", /* 38 */ "Invalid instruction vector index", /* 39 */ "Invalsumacc/cc/as/eval.c 444 0 12 27551 3470501536 7421 #include "mical.h" char *eval = "~|^`s.eval.c R1.8 on 1/7/80"; int In_radix = 10; /* Default input radix for numbers */ char Operators[] = "+-*/&!^<>%"; /* valid operator characters */ /* Prefixes for temporary radix changes */ char Prefix_tab[] = { '/', '^', '%', 0 } ; /* The prefixes */ int Radix_tab[] = { 16, 8, 2, 0 } ; /* and radices they represent*/ char Escape_tab[] = { /* character escape table */ 'n', '\n', /* newline, (linefeed) */ 't', '\t', /* tab */ 'f', '\014', /* form feed */ 'r', '\r', /* return */ 'b', '\b', /* backspace */ 0 } ; /* Evaluate(Arg1): * This routine evaluates expressions by calling Get_Term to evaluate * each of the two terms for binary operations, and then performing the * operation on the two terms. Get_Term itself evaluates unary operations. * Arg1 is a pointer to an oper structure, which Evaluate uses to * store the left hand term, and eventually to store the value of then * entire expression. Thus, grouping is left to right, with no operator * precedence. * This routine can be called recursively by Get_Term, if Get_Term * encounters an expression in brackets ([]). * Position is moved to the first char after the expression. */ Evaluate(Arg1) register struct oper *Arg1; { struct oper Arg2; /* holds value of right hand term */ register char Op; /* operator character */ Non_Blank(); /* Find the operator */ if (Op_Delim(Line[Position])) { /* nil operand is zero */ Arg1->sym_o = 0; Arg1->value_o = 0; return(TRUE); } if (Get_Term(Arg1) == FALSE) return(FALSE); /* Pick up the first term */ Non_Blank(); for (;(Op_Delim(Op = Line[Position]) == FALSE) && (Op != '('); Non_Blank()) { /* But don't go past end of operand */ if ((Op=='>') || (Op=='<')) Op = Line[++Position]; /* so the operators ">>" and "<<" are one char */ if (member(Op,Operators)) { /* Did we find an operator? */ Position++; /* Yep, so move past it */ if (Get_Term(&Arg2) == FALSE) return(FALSE); /* Pick up the second term */ switch(Op) { /* And perform the operation */ case '+': if (Arg1->type_o==t_reg || Arg2.type_o==t_reg) break; /* no arithmetic on registers */ if (Arg1->sym_o && Arg2.sym_o) break; /* Both can't be relocatable */ if (Arg2.sym_o) Arg1->sym_o = Arg2.sym_o; /* Put the offset into Arg1 */ Arg1->value_o += Arg2.value_o; Arg1->flags_o |= Arg2.flags_o&O_COMPLEX; continue; /* go on to next operator */ case '-': /* A-B has the following relocatability: (abs = absolute, rel = relocatable) A B A-B abs abs abs abs rel <error- nonrelocatable> rel abs rel rel rel if A and B have offsets in the same csect, then A-B is absolute, otherwise, an <error> */ if (Arg1->type_o==t_reg || Arg2.type_o==t_reg) break; /* no arithmetic on registers */ if (Arg2.sym_o) /* if B is relocatable, */ if (Arg1->sym_o) /* and A is relocatable, */ /* then make sure both have offsets in the same csect */ if (Arg2.sym_o->csect_s != Arg1->sym_o->csect_s) break; /* break into error */ else { Arg1->sym_o = 0; /* result is absolute (no offset) */ Arg1->flags_o |= O_COMPLEX; /* but not a simple address for sdi's */ } else break; /* if B rel., and A is not, then break into relocation error */ Arg1->value_o -= Arg2.value_o; continue; case '*': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o *= Arg2.value_o; continue; case '/': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o /= Arg2.value_o; continue; case '&': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o &= Arg2.value_o; continue; case '!': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o |= Arg2.value_o; continue; case '^': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o %= Arg2.value_o; continue; case '<': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o <<= Arg2.value_o; continue; case '>': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o >>= Arg2.value_o; continue; case '%': if (Arg1->sym_o || Arg2.sym_o) break; Arg1->value_o = Arg1->value_o<<24 | Arg2.value_o; continue; default: Sys_Error("Operators[] and Evaluate() incompaitible for: %c\n",Op); } /* switch */ Prog_Error(E_RELOCATE); /* if break form switch statement, relocation error */ return(FALSE); } /* if operator present */ Prog_Error(E_OPERATOR); /* No operator when expected */ return(FALSE); } /* while not end of operand */ return(TRUE); } /* Get_Term(Vp) * Vp is a ptr to an operand value structure. This routine picks up one * "term", which is * 1) A symbol, such as a label; or * 2) A constant, which can be prefixed with "/", "^", or "%" for * hex, octal, or binary representations resp., or suffixed with a * ".", for decimal input. (Default radix is set in the descriptor * file); or * 3) A character constant, which is a <"> followed by two non-line * terminating characters, or a <'> followed by one. * In addition, Get_Term evaluates the three unary operators "+", * "-", and "~" (logical not); or * 5) An expression enclosed in brackets ([]). * */ rev(x) {int c, y = 0; for (c=0; c<16; c++) {y = (y<<1) | (x&1); x >>= 1; } return y; } Get_Term(Vp) register struct oper *Vp; { register char S[STR_MAX], /* working string */ flag; /* to save value of Evaluate in a recursive call to it */ int i,index,v_length; struct sym_bkt *sbp,*Lookup(); struct ins_bkt *ibp,*Get_Ins_Bkt(); /* instruction bkt ptr */ extern char O_global; /* if 1, undefined symbols are ext */ extern struct csect *Cur_csect; /* ptr to current csect */ extern char *lastc(); extern int *Insv_ptrs[]; /* instruction vector pointers */ extern char Mnemonic[]; /* name of last executable instruction assembled */ Non_Blank(); /* Find first char of term */ if (Line[Position] == '+') { /* If its a unary "+" */ Position++; /* skip over it */ return(Get_Term(Vp)); } /* and just return the next term */ if (Line[Position] == '-') { /* If it's a unary "-" */ Position++; /* skip over it */ if (Get_Term(Vp) == FALSE) return(FALSE); /* and pick up the next term */ if (Vp->sym_o) { /* Make sure the negated term is relocatable */ Prog_Error(E_RELOCATE); } Vp->value_o = -(Vp->value_o); /* and finally do it */ return(TRUE); } if (Line[Position] == '!') { /* If it's a unary '!', reversal */ Position++; /* skip over it */ if (Get_Term(Vp) == FALSE) return(FALSE); /* and pick up the next term */ if (Vp->sym_o) { /* Make sure the final term is relocatable */ Prog_Error(E_RELOCATE); } Vp->value_o = rev(Vp->value_o); /* and reverse the term */ return(TRUE); } if (Line[Position] == '~') { /* If it's a unary '~', logical negation */ Position++; /* skip over it */ if (Get_Term(Vp) == FALSE) return(FALSE); /* and pick up the next term */ if (Vp->sym_o) { /* Make sure the final term is relocatable */ Prog_Error(E_RELOCATE); } Vp->value_o = ~(Vp->value_o); /* and logically negate the term */ return(TRUE); } if (Get_Token(S)) { /* Pick up a Token, which can be either */ /* a symbol, a number with no prefix, or a decimal number (ending with '.') */ if ((S[0] < '0') || (S[0] > '9') || (*lastc(S) == '$')) { /* If it's a symbol */ sbp = Lookup(S); /* find its symbol bucket */ if ((sbp->attr_s & S_DEC) == 0) /* Make sure it's declared */ if (O_global == 0) Prog_Error(E_SYMDEF); if (sbp->attr_s & S_DEF) /* if it's defined, use its value */ Vp->value_o = sbp->value_s; else { if ((sbp->attr_s & S_EXT) == 0) /* error if not external */ Prog_Error(E_SYMDEF); Vp->value_o = 0; } if (sbp->attr_s & S_REG) Vp->type_o = t_reg; else { /* and offset is the symbol itself */ Vp->sym_o = (sbp->attr_s & S_DEF) && (sbp->csect_s == 0 || (sbp->csect_s->attr_cs & R_ABS)) ? 0 : sbp; Vp->type_o = t_normal; } return(TRUE); } return(Num_Value(S,In_radix,Vp)); } /* Since not a symbol, must be a number */ for (i=0;Prefix_tab[i]; i++) /* Check for number prefixes */ if (Line[Position] == Prefix_tab[i]) { /* if there is one */ Position++; /* move past it */ if (Get_Token(S) == 0) { /* Pick up the digits */ Prog_Error(E_CONSTANT); return(FALSE); } return(Num_Value(S,Radix_tab[i],Vp)); } /* and evaluate the digits in the proper radix */ if (Line[Position] == '\047') return(Char_Value(1,Vp)); /* Check for character constants */ if (Line[Position] == '\"') return(Char_Value(2,Vp)); if (Line[Position] == '[') { /* Check for enclosed expression */ Position++; /* Move past '[' */ flag = Evaluate(Vp); /* evaluate the expression */ if (Line[Position] == ']') Position++; /* Move past ']' */ else Prog_Error(E_TERM); return(flag); } /* and return with the status from evaluate */ Prog_Error(E_TERM); return(FALSE); } /* Num_Value(S,Radix,Vp) interprets the digits in the char string 'S' in the * radix 'Radix' and stores the value into the oper_value pointed to * by 'Vp'. */ Num_Value(S,Radix,Vp) char *S; struct oper *Vp; { long val; /* temporary value holder */ register char *cp; /* current char in S */ register int C; extern char *lastc(); val = 0; /* start with zero */ Lower(S); /* to get lower case hex letters */ if (*(cp = lastc(S)) == '.') { /* if it ends with '.' */ Radix = 10; *cp = 0; } /* assume decimal radix, and remove '.' */ if ((*S == '0') && (*(S+1) == 'x')) { /* allow 0x hex notation */ Radix = 16; S += 2; } for(cp = S; C = *cp; cp++) { /* for each digit, */ /* At the end of this switch statement, C will contain the value of the digit, or -1 if no valid digit */ if (C < '0') C = -1; else switch (Radix) { case 10: if (C > '9') C= -1; else C = C - '0'; break; case 8: if (C > '7') C= -1; else C = C - '0'; break; case 2: if (C > '2') C= -1; else C = C - '0'; break; case 16: if ((C >= 'a') && (C <= 'f')) C = C - 'a' + 10; else if (C <= '9') C = C - '0'; else C = -1; } if (C == -1) { Prog_Error(E_CONSTANT); return(FALSE); } else val = val * Radix + C; } Vp->value_o = val; /* Move value into oper_value */ Vp->sym_o = 0; /* and there's no offset */ Vp->type_o = t_normal; /* normal operand type */ return(TRUE); } /* Char_Value(N,Vp) reads the next N, (1 or 2), non-newline chars from the * input Line, and places them in the oper value pointed at by Vp. * The chars are loaded low byte first. */ Char_Value(N,Vp) struct oper *Vp; { register int val,i,C; Position++; val = 0; for (i = 0; (i<N) && (Line[Position] != '\n') && (Line[Position] != '\014'); i++) { if ((C = Grab_Char()) != -1) val= val<<8 | (C&0177) ; else return(FALSE); } Vp->value_o = val; Vp->sym_o = 0; return(TRUE); } /* Grab_Char() is used for reading chars in character constants and in * character strings. It's main function ins to recognise characters of * the form \c or \nnn where c is a special character and n is an octal * digit. * Returns the value of the character read, or -1 on an error. */ Grab_Char() { register int i; register char *cp,C; if ((C = Line[Position]) == '\\') { /* if escaped character, */ C = Line[++Position]; /* move past '/' */ for (cp=Escape_tab; *cp; cp += 2) /* see if special escape char present */ if (*cp == C){ Position++; return(*(++cp)); } for((i=0,C=0); i<3; i++) /* check for '\nnn' */ if (Line[Position] >= '0' && Line[Position] <= '7') { C = C*8 + Line[Position] - '0'; Position++; } else break; if (i) return(C); /* if there were any digits, return the char we calculated */ C = Line[Position]; } /* Otherwise, just use whats there */ if (((C < ' ') || (C > '~')) && (C != '\t')) { /* Check char for validity */ Prog_Error(E_BADCHAR); return(-1); } Position++; return(C); } = (sbp->attr_s & S_DEF) && (sbp->csect_s == 0 || (sbp->csect_s->attr_cs & R_ABS)) ? 0 : sbp; Vp->type_o = t_normal; } return(Tsumacc/cc/as/init.c 444 0 12 21414 3470501536 7425 #include "mical.h" #include "inst.h" #ifdef Stanford #define HEADER "/lib/a68.hdr" #define ROOT "/usr/sun" #else Stanford #include <bootstrap.h> #define HEADER "/include/as.h" #endif Stanford #define TRUE 1 #define FALSE 0 char header[64], Title[STR_MAX]; /* Command line options */ char O_list = 0; /* 1 if listing requested */ char *O_listname = 0;/* name of listing file if -L option is used */ char O_symtab = 0; /*1 if symbol table desired */ char O_debug = 0; /* >0 if debugging desired */ char O_ext_only = 0; /* 1 if external symbols only in .rel file */ char O_print = 0; /* 1 if listing printed on terminal */ char O_global = 0; /* 1 if undefined symbols are to be made global */ char O_outfile = 0; /* 1 if .rel file name is specified by user */ /* * The source stack. Ss_top contains the subscript of the top of the stack, which then points to the iobuffer of the current input source file * */ FILE *Source_stack[SSTACK_MAX+1]; int Ss_top = -1; /* Source stack top */ int Pass = 0; /* initialize Pass. */ char File_name[STR_MAX]; char Temp_name[STR_MAX]; /* Name of temporary file to hold source between passes 1 and 2 */ FILE *Temp_file; /* Ptr to iobuf of that file */ char Rel_name[STR_MAX]; /* Name of .rel file */ FILE *Rel_file; /* and ptr to it */ FILE *listout; /* file to write listings to */ struct sym_bkt *Dot_bkt ; /* Ptr to location counter's symbol bucket */ struct op_entry { char *op_name; int op_number;}; struct op_entry op_codes[] = { /* List of 68000 op codes */ "abcd", i_abcd, "addb", i_addb, "addw", i_addw, "addl", i_addl, "addqb", i_addqb, "addqw", i_addqw, "addql", i_addql, "addxb", i_addxb, "addxw", i_addxw, "addxl", i_addxl, "andb", i_andb, "andw", i_andw, "andl", i_andl, "aslb", i_aslb, "aslw", i_aslw, "asll", i_asll, "asrb", i_asrb, "asrw", i_asrw, "asrl", i_asrl, "bcc", i_bcc, "bccs", i_bccs, "bchg", i_bchg, "bclr", i_bclr, "bcs", i_bcs, "bcss", i_bcss, "beq", i_beq, "beqs", i_beqs, "bge", i_bge, "bges", i_bges, "bgt", i_bgt, "bgts", i_bgts, "bhi", i_bhi, "bhis", i_bhis, "ble", i_ble, "bles", i_bles, "bls", i_bls, "blss", i_blss, "blt", i_blt, "blts", i_blts, "bmi", i_bmi, "bmis", i_bmis, "bne", i_bne, "bnes", i_bnes, "bpl", i_bpl, "bpls", i_bpls, "bra", i_bra, "bras", i_bras, "bset", i_bset, "bsr", i_bsr, "bsrs", i_bsrs, "btst", i_btst, "bvc", i_bvc, "bvcs", i_bvcs, "bvs", i_bvs, "bvss", i_bvss, "chk", i_chk, "clrb", i_clrb, "clrw", i_clrw, "clrl", i_clrl, "cmpb", i_cmpb, "cmpw", i_cmpw, "cmpl", i_cmpl, "cmpmb", i_cmpmb, "cmpmw", i_cmpmw, "cmpml", i_cmpml, "dbcc", i_dbcc, "dbcs", i_dbcs, "dbeq", i_dbeq, "dbf", i_dbf, "dbra", i_dbra, "dbge", i_dbge, "dbgt", i_dbgt, "dbhi", i_dbhi, "dble", i_dble, "dbls", i_dbls, "dblt", i_dblt, "dbmi", i_dbmi, "dbne", i_dbne, "dbpl", i_dbpl, "dbt", i_dbt, "dbvc", i_dbvc, "dbvs", i_dbvs, "divs", i_divs, "divu", i_divu, "eorb", i_eorb, "eorw", i_eorw, "eorl", i_eorl, "exg", i_exg, "extw", i_extw, "extl", i_extl, "jbsr", i_jbsr, "jcc", i_jcc, "jcs", i_jcs, "jeq", i_jeq, "jge", i_jge, "jgt", i_jgt, "jhi", i_jhi, "jle", i_jle, "jls", i_jls, "jlt", i_jlt, "jmi", i_jmi, "jmp", i_jmp, "jne", i_jne, "jpl", i_jpl, "jra", i_jra, "jsr", i_jsr, "jvc", i_jvc, "jvs", i_jvs, "lea", i_lea, "link", i_link, "lslb", i_lslb, "lslw", i_lslw, "lsll", i_lsll, "lsrb", i_lsrb, "lsrw", i_lsrw, "lsrl", i_lsrl, "movb", i_movb, "movw", i_movw, "movl", i_movl, "movc", i_movc, /* 68010 TPM */ "movsb", i_movsb, /* 68010 TPM */ "movsw", i_movsw, /* 68010 TPM */ "movsl", i_movsl, /* 68010 TPM */ "movemw", i_movemw, "moveml", i_moveml, "movepw", i_movepw, "movepl", i_movepl, "moveq", i_moveq, "muls", i_muls, "mulu", i_mulu, "nbcd", i_nbcd, "negb", i_negb, "negw", i_negw, "negl", i_negl, "negxb", i_negxb, "negxw", i_negxw, "negxl", i_negxl, "nop", i_nop, "notb", i_notb, "notw", i_notw, "notl", i_notl, "orb", i_orb, "orw", i_orw, "orl", i_orl, "pea", i_pea, "reset", i_reset, "rolb", i_rolb, "rolw", i_rolw, "roll", i_roll, "rorb", i_rorb, "rorw", i_rorw, "rorl", i_rorl, "roxlb", i_roxlb, "roxlw", i_roxlw, "roxll", i_roxll, "roxrb", i_roxrb, "roxrw", i_roxrw, "roxrl", i_roxrl, "rte", i_rte, "rtr", i_rtr, "rts", i_rts, "sbcd", i_sbcd, "scc", i_scc, "scs", i_scs, "seq", i_seq, "sf", i_sf, "sge", i_sge, "sgt", i_sgt, "shi", i_shi, "sle", i_sle, "sls", i_sls, "slt", i_slt, "smi", i_smi, "sne", i_sne, "spl", i_spl, "st", i_st, "stop", i_stop, "subb", i_subb, "subw", i_subw, "subl", i_subl, "subqb", i_subqb, "subqw", i_subqw, "subql", i_subql, "subxb", i_subxb, "subxw", i_subxw, "subxl", i_subxl, "svc", i_svc, "svs", i_svs, "swap", i_swap, "tas", i_tas, "trap", i_trap, "trapv", i_trapv, "tstb", i_tstb, "tstw", i_tstw, "tstl", i_tstl, "unlk", i_unlk, 0 }; /* * Init is the primary routine of this file. It is called by the top level (main) to process the arguments of the command line. * */ int canum = 1; /* command argument number */ Init(argc,argv) char *argv[]; { register char *cp; register int i,j; FILE *src; /* ptr to iobufs for source and descriptor files */ struct sym_bkt *Lookup(); extern struct csect *Cur_csect; /* ptr to current csect */ if (argc < 2 ) { printf("usage: as68 [-godspel] sourcefilename\n"); exit(1); } Options(argv); /* get options, leaves argv[canum] */ /* as the first unoptioned command */ /* argument, and presumably the source filename */ /* get source file name */ for (i=0; Title[i]=argv[canum][i]; i++); /* copy filename */ Concat(File_name,argv[canum],".s"); if ((src = fopen(File_name,"r")) == NULL) /* open source file */ { Concat(File_name,argv[canum],".a68"); if ((src = fopen(File_name,"r")) == NULL) /* try .a68 extension */ { Concat(File_name,argv[canum],""); if ((src = fopen(File_name,"r")) == NULL) /* try without .s */ { printf("Can't open source file: %s.s\n",File_name); exit(1); } } } else canum++; Options(argv); Push_Source(src); /* push the input file onto the source stack */ /* Open default header file */ strcpy (header, ROOT); strcat (header, HEADER); if ((src = fopen(header,"r")) != NULL) Push_Source(src); else printf("Can't open header file %s\n", header ); /* Open temporary output file */ Concat(Temp_name,Title,".temp"); if ((Temp_file = fopen(Temp_name,"w")) == NULL) { printf("Can't create output file: %s\n",Temp_name); return(FALSE); } /* Open listing file, if necessary */ if (O_list) { char List_name[STR_MAX]; Concat(List_name, Title, ".list"); if ((listout = fopen(O_listname?O_listname:List_name, "w")) == NULL) { printf("Can't create listing file: %s\n", List_name); return(FALSE); } } /* Check to see if we can open output file */ if(!O_outfile) Concat(Rel_name,Title,".b"); if ((Rel_file = fopen(Rel_name,"w")) == NULL) { printf("Can't create output file: %s\n",Rel_name); return(FALSE); } fclose(Rel_file); /* Rel_Header will open properly */ /* Initialize symbols */ Sym_Init(); Dot_bkt = Lookup("."); /* make bucket for location counter */ Dot_bkt->csect_s = Cur_csect; Dot_bkt->attr_s = S_DEC | S_DEF | S_LABEL; /* "S_LABEL" so it cant be redefined as a label */ Init_Macro(); /* initialize macro package */ d_ins(); /* set up opcode hash table */ return(TRUE); } d_ins() { register struct ins_bkt *insp; register int i,save; i = 0; while (op_codes[i].op_name) { insp = (struct ins_bkt *) malloc(sizeof ins_example); /* allocate ins_bkt */ insp->text_i = op_codes[i].op_name; /* pointer to asciz op code */ insp->code_i = op_codes[i++].op_number; /* index for dispatching */ insp->next_i = ins_hash_tab[save = Hash(insp->text_i)]; /* ptr to ins_bkt */ ins_hash_tab[save] = insp; } return(TRUE); } /* Routine to push a ptr to an iobuffer on the "source stack". The top of the * stack points to the buffer of the current source file. src is the io buffer ptr. */ Push_Source(src) FILE *src; { register int top; if (++Ss_top >= SSTACK_MAX) /* Get stack top, complain if invalid. (will exit) */ Sys_Error("Source stack overflow: %d",top); Source_stack[Ss_top] = src; } /* Reads options on command line. *ap is a ptr to the index of the current argument */ Options(argv) char **argv; { register char *cp; while(argv[canum][0] == '-'){ for (cp = &argv[canum++][1];*cp;cp++) switch(*cp){ case 'd': O_debug = 1; if (*(cp+1)>='0' && *(cp+1)<='9') O_debug = *(++cp) - '0'; break; case 'p': O_print = 1; break; case 'e': O_ext_only = 1; break; case 'L': O_listname = argv[canum++]; case 'l': O_list = 1; break; case 's': O_symtab= 1; break; case 'g': O_global = 1; break; case 'o': O_outfile = 1; if(argv[canum]) Concat(Rel_name, argv[canum++], ""); break; default: printf("Unknown option '%c' ignored.\n",*cp); } } } k, 0 }; /* * Init is the primary routine of this file. It is called by the top level (main) to process the arguments of the command line. * */ int canum = 1; /* command argument number */ Init(argc,argv) char *argv[]; { register chasumacc/cc/as/ins.c 444 0 12 101310 3470501537 7266 /* Mike Nielsen, 3 Dec 81 - bug fix to stop instruction from no operands * to one immediate word operand. * * Mike Nielsen, 3 Dec 81 - bug fix to coerce clrw sr to movw #0,sr as the * former is an illegal instruction. * * Per Bothner, 30 Jun 82 - the postinc routine (used only by the cmpm * instructions) reversed the operands. Fixed it. * * Tim Mann, 6 April 1984 - Added new 68010 instructions. */ #include "mical.h" #include "inst.h" char *ins = "~|^`s.ins.c R1.2 on 6/27/80"; #define A 0 /* must be an areg */ #define D 1 /* must be a dreg */ char Mnemonic[MNEM_MAX]; /* instruction mnemonic of current line */ char Code_length; /* Number of bytes in the current instruction*/ int *WCode = (int *)Code; struct oper operands[OPERANDS_MAX]; /* where all the operands go */ int numops; /* # of operands to the current instruction */ /* functions used in this module */ struct ins_bkt *Get_Ins_Bkt(); /* Instruction -- 68000 assembler * This program is called from the main loop. It checks to see if the * operator field is a valid instruction mnemonic. If so, it calls the * operand evaluator and generates the machine code for the instrucion. * On pass 2 it prints the listing line for the current statement */ Instruction() { register int i; /* gen purpose index */ struct ins_bkt *ibp; /* gen purpose ptr to instruction bucket */ int save_pos; /* temp save of Position and Errors */ save_pos = Position; /* save current posn on input line */ if (Get_Token(Mnemonic) == 0) /* pick up instruction mnemonic */ goto noinst; /* if not there, try something else */ Lower(Mnemonic); /* Convert it to lower case */ if ((ibp = Get_Ins_Bkt(Mnemonic)) == 0) { noinst: Position = save_pos; /* if no op code, restore Position */ return(TRUE); /* and try for something else */ }; if (Dot&1) Prog_Error(E_ODDADDR); Code_length = 2; /* always at least 2 bytes of code */ for(i=0;i < CODE_MAX; i++) { Code[i] = 0; } /* Clear buffer for generated code */ numops = Scan_Operand_Field(operands); switch (ibp->code_i) { /* dispatch to handle each inst */ /* instruction classes */ case i_reset: no_op(0x4E70); break; case i_nop: no_op(0x4E71); break; case i_rte: no_op(0x4E73); break; case i_trapv: no_op(0x4E76); break; case i_rtr: no_op(0x4E77); break; case i_negxb: one_op(0x4000, B); break; case i_negxw: one_op(0x4040, W); break; case i_negxl: one_op(0x4080, L); break; case i_negb: one_op(0x4400, B); break; case i_negw: one_op(0x4440, W); break; case i_negl: one_op(0x4480, L); break; case i_notb: one_op(0x4600, B); break; case i_notw: one_op(0x4640, W); break; case i_notl: one_op(0x4680, L); break; case i_tstb: one_op(0x4A00, B); break; case i_tstw: one_op(0x4A40, W); break; case i_tstl: one_op(0x4A80, L); break; case i_tas: one_op(0x4AC0, B); break; case i_nbcd: one_op(0x4800, B); break; case i_st: one_op(0x50C0, B); break; case i_sf: one_op(0x51C0, B); break; case i_shi: one_op(0x52C0, B); break; case i_sls: one_op(0x53C0, B); break; case i_scc: one_op(0x54C0, B); break; case i_scs: one_op(0x55C0, B); break; case i_sne: one_op(0x56C0, B); break; case i_seq: one_op(0x57C0, B); break; case i_svc: one_op(0x58C0, B); break; case i_svs: one_op(0x59C0, B); break; case i_spl: one_op(0x5AC0, B); break; case i_smi: one_op(0x5BC0, B); break; case i_sge: one_op(0x5CC0, B); break; case i_slt: one_op(0x5DC0, B); break; case i_sgt: one_op(0x5EC0, B); break; case i_sle: one_op(0x5FC0, B); break; case i_clrb: clr_op(0x4200, B); break; case i_clrw: clr_op(0x4240, W); break; case i_clrl: clr_op(0x4280, L); break; case i_pea: ctrl_op(0x4840); break; case i_jmp: ctrl_op(0x4EC0); break; case i_jsr: ctrl_op(0x4E80); break; case i_movb: move_op(0x1000, B); break; case i_movw: move_op(0x3000, W); break; case i_movl: move_op(0x2000, L); break; case i_orb: two_op(0x8000, 0x0000, B, 0); break; case i_orw: two_op(0x8000, 0x0000, W, 0); break; case i_orl: two_op(0x8000, 0x0000, L, 0); break; case i_subb: two_op(0x9000, 0x0400, B, 0); break; case i_subw: two_op(0x9000, 0x0400, W, 0); break; case i_subl: two_op(0x9000, 0x0400, L, 0); break; case i_cmpb: two_op(0xB000, 0x0C00, B, 0); break; case i_cmpw: two_op(0xB000, 0x0C00, W, 0); break; case i_cmpl: two_op(0xB000, 0x0C00, L, 0); break; case i_eorb: two_op(0xB100, 0x0A00, B, 0); break; case i_eorw: two_op(0xB100, 0x0A00, W, 0); break; case i_eorl: two_op(0xB100, 0x0A00, L, 0); break; case i_andb: two_op(0xC000, 0x0200, B, 0); break; case i_andw: two_op(0xC000, 0x0200, W, 0); break; case i_andl: two_op(0xC000, 0x0200, L, 0); break; case i_addb: two_op(0xD000, 0x0600, B, 0); break; case i_addw: two_op(0xD000, 0x0600, W, 0); break; case i_addl: two_op(0xD000, 0x0600, L, 0); break; case i_addqb: two_op(0x5000, 0x5000, B, 1); break; case i_addqw: two_op(0x5000, 0x5000, W, 1); break; case i_addql: two_op(0x5000, 0x5000, L, 1); break; case i_subqb: two_op(0x5100, 0x5100, B, 1); break; case i_subqw: two_op(0x5100, 0x5100, W, 1); break; case i_subql: two_op(0x5100, 0x5100, L, 1); break; case i_jra: jbrnch(0x6000,0x4EC0); break; case i_jhi: cbrnch(0x6200); break; case i_jcc: cbrnch(0x6400); break; case i_jne: cbrnch(0x6600); break; case i_jvc: cbrnch(0x6800); break; case i_jpl: cbrnch(0x6A00); break; case i_jge: cbrnch(0x6C00); break; case i_jgt: cbrnch(0x6E00); break; case i_jbsr: jbrnch(0x6100,0x4E80); break; case i_jls: cbrnch(0x6300); break; case i_jcs: cbrnch(0x6500); break; case i_jeq: cbrnch(0x6700); break; case i_jvs: cbrnch(0x6900); break; case i_jmi: cbrnch(0x6B00); break; case i_jlt: cbrnch(0x6D00); break; case i_jle: cbrnch(0x6F00); break; case i_bra: branch(0x6000); break; case i_bhi: branch(0x6200); break; case i_bcc: branch(0x6400); break; case i_bne: branch(0x6600); break; case i_bvc: branch(0x6800); break; case i_bpl: branch(0x6A00); break; case i_bge: branch(0x6C00); break; case i_bgt: branch(0x6E00); break; case i_bsr: branch(0x6100); break; case i_bls: branch(0x6300); break; case i_bcs: branch(0x6500); break; case i_beq: branch(0x6700); break; case i_bvs: branch(0x6900); break; case i_bmi: branch(0x6B00); break; case i_blt: branch(0x6D00); break; case i_ble: branch(0x6F00); break; case i_bras: brnchs(0x6000); break; case i_bhis: brnchs(0x6200); break; case i_bccs: brnchs(0x6400); break; case i_bnes: brnchs(0x6600); break; case i_bvcs: brnchs(0x6800); break; case i_bpls: brnchs(0x6A00); break; case i_bges: brnchs(0x6C00); break; case i_bgts: brnchs(0x6E00); break; case i_bsrs: brnchs(0x6100); break; case i_blss: brnchs(0x6300); break; case i_bcss: brnchs(0x6500); break; case i_beqs: brnchs(0x6700); break; case i_bvss: brnchs(0x6900); break; case i_bmis: brnchs(0x6B00); break; case i_blts: brnchs(0x6D00); break; case i_bles: brnchs(0x6F00); break; case i_abcd: regmem(0xC100); break; case i_sbcd: regmem(0x8100); break; case i_addxb: regmem(0xD100); break; case i_addxw: regmem(0xD140); break; case i_addxl: regmem(0xD180); break; case i_subxb: regmem(0x9100); break; case i_subxw: regmem(0x9140); break; case i_subxl: regmem(0x9180); break; case i_asrb: shift_op(0xE000); break; case i_asrw: shift_op(0xE040); break; case i_asrl: shift_op(0xE080); break; case i_aslb: shift_op(0xE100); break; case i_aslw: shift_op(0xE140); break; case i_asll: shift_op(0xE180); break; case i_lsrb: shift_op(0xE008); break; case i_lsrw: shift_op(0xE048); break; case i_lsrl: shift_op(0xE088); break; case i_lslb: shift_op(0xE108); break; case i_lslw: shift_op(0xE148); break; case i_lsll: shift_op(0xE188); break; case i_rorb: shift_op(0xE018); break; case i_rorw: shift_op(0xE058); break; case i_rorl: shift_op(0xE098); break; case i_rolb: shift_op(0xE118); break; case i_rolw: shift_op(0xE158); break; case i_roll: shift_op(0xE198); break; case i_roxrb: shift_op(0xE010); break; case i_roxrw: shift_op(0xE050); break; case i_roxrl: shift_op(0xE090); break; case i_roxlb: shift_op(0xE110); break; case i_roxlw: shift_op(0xE150); break; case i_roxll: shift_op(0xE190); break; case i_swap: reg_op(0x4840, D); break; case i_extw: reg_op(0x4880, D); break; case i_extl: reg_op(0x48C0, D); break; case i_unlk: reg_op(0x4E58, A); break; case i_cmpmb: postinc(0xB108); break; case i_cmpmw: postinc(0xB148); break; case i_cmpml: postinc(0xB188); break; case i_bchg: bit_op(0x0040); break; case i_bclr: bit_op(0x0080); break; case i_bset: bit_op(0x00C0); break; case i_btst: bit_op(0x0000); break; case i_chk: memreg(0x4180); break; case i_divs: memreg(0x81C0); break; case i_divu: memreg(0x80C0); break; case i_muls: memreg(0xC1C0); break; case i_mulu: memreg(0xC0C0); break; /* miscellaneous classes */ case i_dbcc: regbrnch(0x54C8); break; case i_dbcs: regbrnch(0x55C8); break; case i_dbeq: regbrnch(0x57C8); break; case i_dbra: case i_dbf: regbrnch(0x51C8); break; case i_dbge: regbrnch(0x5CC8); break; case i_dbgt: regbrnch(0x5EC8); break; case i_dbhi: regbrnch(0x52C8); break; case i_dble: regbrnch(0x5FC8); break; case i_dbls: regbrnch(0x53C8); break; case i_dblt: regbrnch(0x5DC8); break; case i_dbmi: regbrnch(0x5BC8); break; case i_dbne: regbrnch(0x56C8); break; case i_dbpl: regbrnch(0x5AC8); break; case i_dbt: regbrnch(0x50C8); break; case i_dbvc: regbrnch(0x58C8); break; case i_dbvs: regbrnch(0x59C8); break; case i_exg: exg_op(0xC100); break; case i_lea: addr_op(0x41C0, L); break; case i_link: link_op(0x4E50); break; case i_movemw: movem_op(0x4880); break; case i_moveml: movem_op(0x48C0); break; case i_movepw: movep_op(0x0108); break; case i_movepl: movep_op(0x0148); break; case i_movsb: movs_op(0x0E00, B); break; /* 68010 TPM */ case i_movsw: movs_op(0x0E40, W); break; /* 68010 TPM */ case i_movsl: movs_op(0x0E80, L); break; /* 68010 TPM */ case i_movc: movc_op(0x4E7A); break; /* 68010 TPM */ case i_moveq: moveq(0x7000); break; case i_stop: stop_op(0x4E72); break; case i_rts: rts_op(0x4E74); break; /* 68010 TPM */ case i_trap: trap(0x4E40); break; default: Prog_Error(E_OPCODE); }; Put_Words(Code,Code_length); /* output text */ Print_Line(P_ALL); /* Print the line */ BC = Code_length; /* increment LC */ return(FALSE); /* and return false, since no more needs to be done */ } /* * Get_Ins_Bkt(M) returns ptr to instruction bucket for instruction whose name * is M; 0 if no such instruction. */ struct ins_bkt *Get_Ins_Bkt(M) char *M; { register struct ins_bkt *ibp; /* returned value */ ibp = ins_hash_tab[Hash(M)]; while(ibp) { if (seq(ibp->text_i,M)) break; ibp = ibp->next_i; } return(ibp); } /* move_op - uses two effective addresses */ move_op(opr, size) { register struct oper *op1, *op2; int r1, r2; op1 = operands; op2 = &operands[1]; r1 = (int)op1->value_o; r2 = (int)op2->value_o; if (numops != 2) Prog_Error(E_NUMOPS); else if (op1->type_o == t_reg && srreg(r1) && data_addr(op2) && alt_addr(op2)) { WCode[0] = 0x40C0; eaddr(op2, W); } else if (op1->type_o == t_reg && ccreg(r1) && /*************/ data_addr(op2) && alt_addr(op2)) /* */ { /* 68010 TPM */ WCode[0] = 0x42C0; /* */ eaddr(op2, W); /*************/ } else if (op2->type_o == t_reg && ccreg(r2) && data_addr(op1)) { WCode[0] = 0x44C0; eaddr(op1, W); } else if (op2->type_o == t_reg && srreg(r2) && data_addr(op1)) { WCode[0] = 0x46C0; eaddr(op1, W); } else if (op1->type_o == t_reg && uspreg(r1)) { if (op2->type_o != t_reg || !areg(r2)) Prog_Error(E_REG); WCode[0] = 0x4E68 | (r2 & 07); } else if (op2->type_o == t_reg && uspreg(r2)) { if (op1->type_o != t_reg || !areg(r1)) Prog_Error(E_REG); WCode[0] = 0x4E60 | (r1 & 07); } else if (adrbyte(op1, size) && data_addr(op2) && alt_addr(op2)) { char reg, mode; int source; WCode[0] = 0; eaddr(op1, size); /* get source address */ source = WCode[0]; /* save it */ WCode[0] = 0; eaddr(op2, size); /* get destination address */ reg = WCode[0] & 07; mode = (WCode[0] >> 3) & 07; WCode[0] = opr | (reg << 9) | (mode << 6) | source; } else if (op2->type_o == t_reg && areg(r2) && size != B) { WCode[0] = 0x0040|((size==W)?0x3000:0x2000)|((r2 & 07)<<9); eaddr(op1, size); } else { WCode[0] = 0; Prog_Error(E_OPERAND); } } /* movs_op - uses one effective address and one register (68010 TPM) */ movs_op(opr, size) { register struct oper *op1, *op2; int r1, r2; op1 = operands; op2 = &operands[1]; r1 = (int)op1->value_o; r2 = (int)op2->value_o; if (numops != 2) Prog_Error(E_NUMOPS); else if (op1->type_o == t_reg && mem_addr(op2) && alt_addr(op2)) { /* First case: moving from a register to memory */ WCode[0] = opr; WCode[1] = (r1<<12) | (1<<11); Code_length = 4; /* so far */ eaddr(op2, size); } else if (op2->type_o == t_reg && mem_addr(op1) && alt_addr(op1)) { /* Second case: moving from memory to a register */ WCode[0] = opr; WCode[1] = r2<<12; Code_length = 4; /* so far */ eaddr(op1, size); } else { WCode[0] = 0; Prog_Error(E_OPERAND); } } /* movc_op - one ordinary register and one control register (68010 TPM) */ movc_op(opr) { register struct oper *op1, *op2; int r1, r2; op1 = operands; op2 = &operands[1]; r1 = (int)op1->value_o; r2 = (int)op2->value_o; if (numops != 2) Prog_Error(E_NUMOPS); else if (op1->type_o != t_reg || op2->type_o != t_reg) Prog_Error(E_OPERAND); else if ( (areg(r1) || dreg(r1)) ) { WCode[0] = opr | 1; WCode[1] = r1<<12; if (sfcreg(r2)) WCode[1] |= 0x000; else if (dfcreg(r2)) WCode[1] |= 0x001; else if (uspreg(r2)) WCode[1] |= 0x800; else if (vbrreg(r2)) WCode[1] |= 0x801; else Prog_Error(E_OPERAND); Code_length = 4; } else if ( (areg(r2) || dreg(r2)) ) { WCode[0] = opr; WCode[1] = r2<<12; if (sfcreg(r1)) WCode[1] |= 0x000; else if (dfcreg(r1)) WCode[1] |= 0x001; else if (uspreg(r1)) WCode[1] |= 0x800; else if (vbrreg(r1)) WCode[1] |= 0x801; else Prog_Error(E_OPERAND); Code_length = 4; } else { WCode[0] = 0; Prog_Error(E_OPERAND); } } /* two_ops - these are of the forms: xxx Dn,<eaddr> xxx <eaddr>,Dn xxx #yyy,<eaddr> xxx <eaddr>,An */ two_op(opr, iopr, size, quick) int opr; /* normal operand field */ int iopr; /* operand if immediate */ int size; /* B, W, or L for the size of the operation */ int quick; /* 1 => quick immediate instruction */ { register struct oper *op1, *op2; int r1, r2; int flag; /* use to analyze addressing modes */ op1 = operands; op2 = &operands[1]; r1 = (int)op1->value_o; r2 = (int)op2->value_o; WCode[0] = opr | (size << 6); if (numops != 2) Prog_Error(E_NUMOPS); if (op1->type_o == t_immed) { WCode[0] = iopr | (size << 6); if (quick) { if (op1->value_o > 8 || op1->value_o < 0) Prog_Error(E_CONSTANT); if (op1->value_o == 8) r1 = 0; /* 0 represents 8 */ WCode[0] |= (r1 & 07) << 9; if (alt_addr(op2)&&adrbyte(op2, size))eaddr(op2,size); else Prog_Error(E_OPERAND); return; } else { switch(opr) { case 0x0600: /* add */ case 0x0400: /* sub */ case 0x0C00: /* cmp */ flag = data_addr(op2) & alt_addr(op2); break; default: flag = (data_addr(op2) & alt_addr(op2)) | sr_addr(op2); break; } if (flag) { rel_val(op1, (size == L)? L:W); /* bytes to W*/ eaddr(op2, size); return; } } } WCode[0] = opr | (size << 6); if (op1->type_o == t_reg && dreg((int)op1->value_o)) { switch(opr) { case 0xB000: /* cmp */ flag = 0; /* not allowed */ break; case 0xB100: /* eor */ flag = data_addr(op2) & alt_addr(op2); break; default: flag = mem_addr(op2) & alt_addr(op2); break; } if (flag) { WCode[0] |= 0400|(((int)op1->value_o&07)<<9); eaddr(op2, size); return; } } if (op2->type_o == t_reg && dreg((int)op2->value_o)) { switch(opr) { case 0xB000: /* cmp */ case 0xD000: /* add */ case 0x9000: /* sub */ flag = adrbyte(op1, size); break; case 0xB100: /* eor */ flag = 0; break; default: flag = data_addr(op1); break; } if (flag) { WCode[0] |= (((int)op2->value_o & 07) << 9); eaddr(op1, size); return; } } if (op2->type_o == t_reg && areg(r2) && size != B) { int op_mode; op_mode = (size == W)? 0300: 0700; switch(opr) { case 0xD000: /* add */ case 0x9000: /* sub */ case 0xB000: /* cmp */ WCode[0] = opr | ((r2 & 07) << 9) | op_mode; eaddr(op1, size); return; default: ; } } Prog_Error(E_OPERAND); } /* one_ops - install opr, check for exactly one operand and compute eaddr */ one_op(opr, size) { register struct oper *op = operands; WCode[0] = opr; if (numops != 1) Prog_Error(E_NUMOPS); if (data_addr(op) && alt_addr(op)) eaddr(op, size); else Prog_Error(E_OPERAND); } /* clr_op - coerce clrw sr to movw #0,sr otherwise like one_op */ clr_op(opr, size) { register struct oper *op = operands; int reg = (int)op->value_o; if (numops != 1) Prog_Error(E_NUMOPS); else if (op->type_o == t_reg && srreg(reg)) { WCode[0] = 0x46FC; WCode[1] = 0; Code_length += 2; } else { WCode[0] = opr; if (data_addr(op) && alt_addr(op)) eaddr(op, size); else Prog_Error(E_OPERAND); } } /* ctrl_op - like one op but requires control addressing modes */ ctrl_op(opr) { register struct oper *op = operands; WCode[0] = opr; if (numops != 1) Prog_Error(E_NUMOPS); if (ctrl_addr(op)) eaddr(op, W); else Prog_Error(E_OPERAND); } /* no_op(opr) -- places opr in WCode[0]. Ensures there are no operands. */ no_op(opr) { WCode[0] = opr; if (numops != 0) Prog_Error(E_NUMOPS); }; /* branch - process branch offsets */ branch(opr) { long offs = 0; register struct oper *opp = operands; extern struct csect *Cur_csect; WCode[0] = opr; if (numops != 1) Prog_Error(E_NUMOPS); else if (opp->type_o == t_reg) Prog_Error(E_REG); else if (opp->sym_o == 0 || opp->sym_o->csect_s != Cur_csect) Prog_Error(E_RELOCATE); else { offs = opp->value_o - (Dot + 2); if (offs > 32767L || offs < -32768L) Prog_Error(E_OFFSET); } opp->value_o = (int)offs; opp->sym_o = 0; /* mark as none relocateable expression */ rel_val(opp, W); } brnchs(opr) { long offs = 0; register struct oper *opp = operands; extern struct csect *Cur_csect; WCode[0] = opr; if (numops != 1) Prog_Error(E_NUMOPS); else if (opp->type_o == t_reg) Prog_Error(E_REG); else if (opp->sym_o == 0 || opp->sym_o->csect_s != Cur_csect) Prog_Error(E_RELOCATE); else { offs = opp->value_o - (Dot + 2); if (offs > 127 || offs < -128) Prog_Error(E_OFFSET); } if (offs != 0) WCode[0] |= offs&0377; else if (opr != 0x6100) /* not a bsr, offset 0 => long address, so do a nop instead */ WCode[0] = 0x4e71; else Prog_Error(E_OFFSET); } /* * generate a short or a long branch instruction as appropriate * note that: * jra foo * foo: * is translated (by brnchs) to a nop. If we attempt to * optimize this to generate no code, then after resolving * the span-dependent instructions, the value of * foo is the same as the address of the jra instruction. * Therefore, on pass 2, the jra looks like a jra . * Presumably, this could be fixed by keeping more information * after the sdi's are resolved */ jbrnch(opr,lopr) { long offs = 0; register struct oper *opp = operands; extern struct csect *Cur_csect; if (numops != 1) Prog_Error(E_NUMOPS); else if (opp->type_o != t_normal) /* not a direct address */ ctrl_op(lopr); /* jmp or jsr as appropriate */ else { offs = opp->value_o - (Dot + 2); if (opp->flags_o & O_COMPLEX) /* not a simple address */ ctrl_op(lopr); /* use the long form */ else if (Pass == 1) Code_length = makesdi(opp, 6, Dot + 2, sdi_bound(2, -128L, 127L, sdi_bound(4, -32768L, 32767L, 0))); #ifndef Stanford else if (opp->sym_o == 0 /* absolute address */ || opp->sym_o->csect_s != Cur_csect /* not in the same csect */ #else Stanford else if (opp->sym_o->csect_s != Cur_csect /* not in the same csect */ #endif Stanford || offs < -32768L || offs > 32767L) /* offset too large */ ctrl_op(lopr); /* not in the same csect */ else if (offs > 127 || offs < -128) branch(opr); else brnchs(opr); } } /* * generate a short or a long conditional branch instruction as appropriate * see the comments preceding jbrnch */ cbrnch(opr) { long offs = 0; register struct oper *opp = operands; extern struct csect *Cur_csect; if (numops != 1) Prog_Error(E_NUMOPS); else if (opp->type_o != t_normal) /* not a direct address */ baround(opr); else { offs = opp->value_o - (Dot + 2); if (opp->flags_o & O_COMPLEX) /* not a simple address */ baround(opr); else if (Pass == 1) Code_length = makesdi(opp, 6, Dot + 2, sdi_bound(2, -128L, 127L, sdi_bound(4, -32768L, 32767L, 0))); else if (opp->sym_o == 0 /* absolute address */ || opp->sym_o->csect_s != Cur_csect /* not in the same csect */ || offs < -32768L || offs > 32767L) /* offset too large */ baround(opr); else if (offs > 127 || offs < -128) branch(opr); else brnchs(opr); } } /* * generate a conditional branch around a jmp */ baround(opr) { WCode[0] = opr ^ 0X106; /* reverse the sense of the condition */ WCode[1] = 0x4EC0 | 072; /* jmp xxxxxx */ Code_length = 4; /* so far */ rel_val(&operands[0], L); /* the address */ } /* regmem - either register register or memory memory instructions */ regmem(opr) { register struct oper *op1, *op2; /* operands */ int sr, dr; /* registers */ op1 = operands; op2 = &operands[1]; sr = (int)op1->value_o; dr = (int)op2->value_o; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); else switch(op1->type_o) { case t_reg: if (op2->type_o == t_reg && dreg(sr) && dreg(dr)) WCode[0] |= sr | (dr << 9); else Prog_Error(E_OPERAND); break; case t_predec: if (op2->type_o == t_predec && areg(sr) && areg(dr)) WCode[0] |= (dr & 07) | ((sr & 07) << 9) | 010; else Prog_Error(E_OPERAND); break; default: Prog_Error(E_OPERAND); } } /* addr_op - things of the form lea <eaddr>,ax */ addr_op(opr, size) { register struct oper *op1, *op2; int ar; /* address register */ op1 = operands; op2 = &operands[1]; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); eaddr(op1, size); /* get source */ ar = (int)op2->value_o; if (op2->type_o == t_reg && areg(ar)) WCode[0] |= (ar & 07) << 9; else Prog_Error(E_OPERAND); } /* shift op - shift either a register or an effective address */ shift_op(opr) { register struct oper *op1, *op2; op1 = &operands[0]; op2 = &operands[1]; WCode[0] = opr; if (numops == 1) { WCode[0] |= 0300; /* size field 3 for eaddr */ if (mem_addr(op1) && alt_addr(op1)) eaddr(op1, W); else Prog_Error(E_OPERAND); return; } if (numops == 2) { int val1, val2; val1 = (int)op1->value_o; val2 = (int)op2->value_o; if (op1->type_o==t_immed && op2->type_o == t_reg && dreg(val2)) { if ((op1->value_o <= 0) || (op1->value_o > 8)) Prog_Error(E_CONSTANT); if (val1 == 8) val1 = 0; WCode[0] |= ((val1 & 07) << 9) | (val2 & 07); return; } else if (op1->type_o==t_reg && dreg(val1) && op2->type_o == t_reg && dreg(val2)) { WCode[0] |= ((val1 & 07) << 9) | (val2 & 07) | 040; return; } } Prog_Error(E_OPERAND); } /* bit_op - of the form xxx Dn,<eaddr> or xxx #nnn,<eaddr> */ bit_op(opr) { register struct oper *op1, *op2; op1 = operands; op2 = &operands[1]; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); else if (op1->type_o == t_reg && dreg((int)op1->value_o) && data_addr(op2) && alt_addr(op2)) { /* <eaddr> is destination */ WCode[0] |= 0400 | ((int)op1->value_o << 9); eaddr(op2, W); } else if (op1->type_o == t_immed && data_addr(op2) && alt_addr(op2)) { WCode[0] |= 04000; rel_val(op1, W); eaddr(op2, W); } else Prog_Error(E_OPERAND); } /* memreg - instructions of the form xxx <eaddr>,Dn eg. divu */ memreg(opr) { register struct oper *op1, *op2; int dr; /* data register */ op1 = operands; op2 = &operands[1]; WCode[0] = opr; dr = (int)op2->value_o; if (numops != 2) Prog_Error(E_NUMOPS); if (data_addr(op1) && op2->type_o == t_reg && dreg(dr)) { WCode[0] |= (dr & 07) << 9; eaddr(op1, W); /* get source */ } else Prog_Error(E_OPERAND); } /* postinc - instructions of the form xxx Ay@+,Ax@+, i.e. cmpm */ postinc(opr) { register struct oper *op1, *op2; int ar1, ar2; op1 = operands; op2 = &operands[1]; ar1 = (int)op1->value_o; ar2 = (int)op2->value_o; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); else if (op1->type_o == t_postinc && areg(ar1) && op2->type_o == t_postinc && areg(ar2)) /* Swapped ar1 and ar2 below. Bothner Jun 82 */ WCode[0] |= ((ar2 & 07) << 9) | (ar1 & 07); else Prog_Error(E_OPERAND); } /* regbrnch - instructions like DBcc Dn,<label> */ regbrnch(opr) { long offs = 0; int dr; register struct oper *op1, *op2; op1 = operands; op2 = &operands[1]; dr = (int)op1->value_o; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); /* we should check here for relocatable expression */ else if (op1->type_o == t_reg && dreg(dr)) { WCode[0] |= dr; offs = op2->value_o - (Dot + 2); if (((offs<<16)>>16) != offs) Prog_Error(E_OFFSET); WCode[1] = offs; Code_length = 4; } } /* exg_op - instructions like exg rx,ry */ exg_op(opr) { int r1, r2; register struct oper *op1, *op2; op1 = operands; op2 = &operands[1]; r1 = (int)op1->value_o; r2 = (int)op2->value_o; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); else if (op1->type_o == t_reg && op2->type_o == t_reg) { if (dreg(r1) && dreg(r2)) WCode[0] |= 0100 | (r1 << 9) | r2; else if (areg(r1) && areg(r2)) WCode[0] |= 0110 | ((r1 & 07) << 9) | (r2 & 07); else if (areg(r1) && dreg(r2)) WCode[0] |= 0210 | (r2 << 9) | (r1 & 07); else if (dreg(r1) && areg(r2)) WCode[0] |= 0210 | (r1 << 9) | (r2 & 07); else Prog_Error(E_REG); } else Prog_Error(E_OPERAND); } /* reg_op - instructions of the form xxx dn, if flag == D else xxx an */ reg_op(opr, flag) { register struct oper *opp = operands; int reg = (int)opp->value_o; if (numops != 1) Prog_Error(E_NUMOPS); if (opp->type_o != t_reg) Prog_Error(E_OPERAND); if ((flag == D && !dreg(reg)) || (flag == A && !areg(reg))) Prog_Error(E_REG); WCode[0] = opr | (reg & 07); } /* link_op - form: link An,#<disp> */ link_op(opr) { int ar; register struct oper *op1, *op2; op1 = operands; op2 = &operands[1]; if (numops != 2) Prog_Error(E_NUMOPS); if (op1->type_o != t_reg || op2->type_o != t_immed) Prog_Error(E_OPERAND); ar = (int)op1->value_o; if (!areg(ar)) Prog_Error(E_REG); WCode[0] = opr | (ar & 07); rel_val(op2, W); } /* movem_op - of the form: movem #xxx,<eaddr> or movem <eaddr>,#xxx */ movem_op(opr) { register struct oper *op1, *op2; op1 = operands; op2 = &operands[1]; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); if (op1->type_o == t_immed && (ctrl_addr(op2)||op2->type_o==t_predec)) { rel_val(op1, W); eaddr(op2, W); } else if(op2->type_o == t_immed && (ctrl_addr(op1) || op1->type_o == t_postinc)) { WCode[0] |= 02000; /* memory to register flag */ rel_val(op2, W); eaddr(op1, W); } else Prog_Error(E_OPERAND); } /* movep_op - of the form: movep Dx,Ay@(d) or movep Ay@(d),Dx */ movep_op(opr) { register struct oper *op1, *op2; int r1, r2; op1 = operands; op2 = &operands[1]; r1 = (int)op1->value_o; r2 = (int)op2->value_o; WCode[0] = opr; if (numops != 2) Prog_Error(E_NUMOPS); if (op1->type_o == t_reg && dreg(r1)) { if (op2->type_o != t_displ || !areg(op2->reg_o)) Prog_Error(E_OPERAND); WCode[0] |= (r1 << 9) | 0600 | (op2->reg_o & 07); rel_val(op2, W); } else if (op2->type_o == t_reg && dreg(r2)) { if (op1->type_o != t_displ || !areg(op1->reg_o)) Prog_Error(E_OPERAND); WCode[0] |= (r2 << 9) | 0400 | (op1->reg_o & 07); rel_val(op1, W); } else Prog_Error(E_OPERAND); } /* moveq - form: moveq #<data>,Dn */ moveq(opr) { register struct oper *op1, *op2; int r2; op1 = operands; op2 = &operands[1]; r2 = (int)op2->value_o; if (op1->value_o > 0177 || op1->value_o < -0200) Prog_Error(E_CONSTANT); WCode[0] = opr | ((r2 & 07) << 9) | ((short)op1->value_o & 0377); if (numops != 2) Prog_Error(E_NUMOPS); if (op1->type_o != t_immed || op2->type_o != t_reg || !dreg(r2)) Prog_Error(E_OPERAND); } /* stop_op - form: stop #xxxx */ stop_op(opr) { register struct oper *opp = operands; WCode[0] = opr; if (numops != 1) Prog_Error(E_NUMOPS); if (opp->type_o != t_immed) Prog_Error(E_OPERAND); rel_val(opp, W); } /* rts_op - form: rts OR rts #xxxx (68010 TPM) */ rts_op(opr) { register struct oper *opp = operands; if (numops == 0) { WCode[0] = opr | 1; return; } if (numops != 1) Prog_Error(E_NUMOPS); WCode[0] = opr; if (opp->type_o != t_immed) Prog_Error(E_OPERAND); rel_val(opp, W); } /* trap - form: trap #xxxx */ trap(opr) { register struct oper *opp = operands; if (numops != 1) Prog_Error(E_NUMOPS); if (opp->type_o != t_immed) Prog_Error(E_OPERAND); WCode[0] = opr | (((char)opp->value_o) & 017); } /* eaddr - put in stuff for an effective address */ eaddr(opptr, size) register struct oper *opptr; { int reg = (int)opptr->value_o; switch(opptr->type_o) { case t_reg: if (areg(reg) || dreg(reg)) WCode[0] |= (int)opptr->value_o; else if (srreg(reg) || ccreg(reg)) WCode[0] |= 074; else Prog_Error(E_REG); break; case t_defer: if (areg(reg)) WCode[0] |= (((int)opptr->value_o) & 07) | 020; else Prog_Error(E_REG); break; case t_postinc: if (areg(reg)) WCode[0] |= (((int)opptr->value_o) & 07) | 030; else Prog_Error(E_REG); break; case t_predec: if (areg(reg)) WCode[0] |= (reg & 07) | 040; else Prog_Error(E_REG); break; case t_displ: if (areg(opptr->reg_o)) { WCode[0] |= (opptr->reg_o & 07) | 050; rel_val(opptr, W); /* install displacement */ } else if (pcreg(opptr->reg_o)) { WCode[0] |= 072; rel_val(opptr, W); /* install displacement */ } else Prog_Error(E_REG); break; case t_index: if (areg(opptr->reg_o)) { WCode[0] |= (opptr->reg_o & 07) | 060; index(opptr); /* compute index word */ rel_val(opptr, W); /* install index word */ } else if (pcreg(opptr->reg_o)) { WCode[0] |= 073; index(opptr); /* compute index word */ rel_val(opptr, W); /* install index word */ } else Prog_Error(E_REG); break; case t_abss: WCode[0] |= 070; rel_val(opptr, W); /* install short address */ break; case t_normal: case t_absl: WCode[0] |= 071; rel_val(opptr, L); break; case t_immed: WCode[0] |= 074; rel_val(opptr, (size == L)? L:W); /* change bytes to W */ break; default: Sys_Error("Unrecognized address mode in line %s", Line); } } /* index - Use data in operand structure to compute and index word and leave the word in the operand value */ index(opptr) register struct oper *opptr; { int indexval = 0; if (areg((int)opptr->value_o) || dreg((int)opptr->value_o)) indexval = (int)opptr->value_o << 12; else Prog_Error(E_REG); if (opptr->flags_o == O_LINDEX) indexval |= 0x0800; /* else word */ #ifndef Stanford if (opptr->disp_o < 0400) indexval |= opptr->disp_o; #else Stanford if (-0200 <= opptr->disp_o && opptr->disp_o < 0200) indexval |= (unsigned char)opptr->disp_o; #endif Stanford else Prog_Error(E_OFFSET); opptr->value_o = indexval; } /* areg - Returns 1 if reg is an address register */ areg(reg) { return(reg >= 8 && reg < 16); } /* dreg - Returns 1 if reg is a data register */ dreg(reg) { return(reg >= 0 && reg < 8); } /* uspreg - Returns 1 if reg is usp */ uspreg(reg) { return(reg == 19); } /* pcreg - Returns 1 if reg is pc */ pcreg(reg) { return(reg == 16); } /* srreg - Returns 1 if reg is sr */ srreg(reg) { return(reg == 18); } /* ccreg - Returns 1 if reg is cc */ ccreg(reg) { return(reg == 17); } /* sfcreg - Returns 1 if reg is sfc (68010 TPM) */ sfcreg(reg) { return(reg == 20); } /* dfcreg - Returns 1 if reg is dfc (68010 TPM) */ dfcreg(reg) { return(reg == 21); } /* vbrreg - Returns 1 if reg is vbr (68010 TPM) */ vbrreg(reg) { return(reg == 22); } /* check for a data addressing mode */ data_addr(op) register struct oper *op; { switch(op->type_o) { case t_reg: if (areg((int)op->value_o)) return(0); default: return(1); } } /* check for an alterable data addressing mode */ alt_addr(op) register struct oper *op; { switch(op->type_o) { case t_displ: case t_index: if (pcreg(op->reg_o)) return(0); default: return(1); } } /* check for a memory addressing mode */ mem_addr(op) register struct oper *op; { switch(op->type_o) { case t_reg: return(0); default: return(1); } } /* check for a control addressing mode */ ctrl_addr(op) register struct oper *op; { switch(op->type_o) { case t_reg: case t_postinc: case t_predec: case t_immed: return(0); default: return(1); } } /* sr_addr - check to see if addressing mode is sr */ sr_addr(op) register struct oper *op; { int reg = (int)op->value_o; if (op->type_o == t_reg && (srreg(reg) || ccreg(reg))) return(1); return(0); } /* check to make sure that addr mode is not addr register direct if size = B */ adrbyte(op, size) register struct oper *op; register int size; /* B,W or L */ { if (op->type_o == t_reg && size == B && areg((int)op->value_o)) return(0); return(1); } g(reg)) WCode[0] |= (int)opptr->value_o; else if (srreg(reg) || ccreg(reg)) WCode[0] |= 074; else Prog_Error(E_REG); break; case t_defer: if (areg(reg)) WCode[0] |= (((int)opptr->value_o) & 07) | 020; else Prog_Error(E_REG); break; case t_postinc: if (areg(reg)) WCode[0] |= (((int)opsumacc/cc/as/inst.h 444 0 12 7463 3470501537 7435 /* dispatch numbers for 68000 instructions. These numbers are placed in * the code_i component of each instruction bucket by init.c and are used * by ins.c for dispatching. */ #define i_abcd 1 #define i_addb 2 #define i_addw 3 #define i_addl 4 #define i_addqb 5 #define i_addqw 6 #define i_addql 7 #define i_addxb 8 #define i_addxw 9 #define i_addxl 10 #define i_andb 11 #define i_andw 12 #define i_andl 13 #define i_aslb 14 #define i_aslw 15 #define i_asll 16 #define i_asrb 17 #define i_asrw 18 #define i_asrl 19 #define i_bcc 20 #define i_bccs 21 #define i_bchg 22 #define i_bclr 23 #define i_bcs 24 #define i_bcss 25 #define i_beq 26 #define i_beqs 27 #define i_bge 28 #define i_bges 29 #define i_bgt 30 #define i_bgts 31 #define i_bhi 32 #define i_bhis 33 #define i_ble 34 #define i_bles 35 #define i_bls 36 #define i_blss 37 #define i_blt 38 #define i_blts 39 #define i_bmi 40 #define i_bmis 41 #define i_bne 42 #define i_bnes 43 #define i_bpl 44 #define i_bpls 45 #define i_bra 46 #define i_bras 47 #define i_bset 48 #define i_bsr 49 #define i_bsrs 50 #define i_btst 51 #define i_bvc 52 #define i_bvcs 53 #define i_bvs 54 #define i_bvss 55 #define i_chk 56 #define i_clrb 57 #define i_clrw 58 #define i_clrl 59 #define i_cmpb 60 #define i_cmpw 61 #define i_cmpl 62 #define i_cmpmb 63 #define i_cmpmw 64 #define i_cmpml 65 #define i_dbcc 66 #define i_dbcs 67 #define i_dbeq 68 #define i_dbf 69 #define i_dbra 70 #define i_dbge 71 #define i_dbgt 72 #define i_dbhi 73 #define i_dble 74 #define i_dbls 75 #define i_dblt 76 #define i_dbmi 77 #define i_dbne 78 #define i_dbpl 79 #define i_dbt 80 #define i_dbvc 81 #define i_dbvs 82 #define i_divs 83 #define i_divu 84 #define i_eorb 85 #define i_eorw 86 #define i_eorl 87 #define i_exg 88 #define i_extw 89 #define i_extl 90 #define i_jbsr 91 #define i_jcc 92 #define i_jcs 93 #define i_jeq 94 #define i_jge 95 #define i_jgt 96 #define i_jhi 97 #define i_jle 98 #define i_jls 99 #define i_jlt 100 #define i_jmi 101 #define i_jmp 102 #define i_jne 103 #define i_jpl 104 #define i_jra 105 #define i_jsr 106 #define i_jvc 107 #define i_jvs 108 #define i_lea 109 #define i_link 110 #define i_lslb 111 #define i_lslw 112 #define i_lsll 113 #define i_lsrb 114 #define i_lsrw 115 #define i_lsrl 116 #define i_movb 117 #define i_movw 118 #define i_movl 119 #define i_movemw 120 #define i_moveml 121 #define i_movepw 122 #define i_movepl 123 #define i_moveq 124 #define i_muls 125 #define i_mulu 126 #define i_nbcd 127 #define i_negb 128 #define i_negw 129 #define i_negl 130 #define i_negxb 131 #define i_negxw 132 #define i_negxl 133 #define i_nop 134 #define i_notb 135 #define i_notw 136 #define i_notl 137 #define i_orb 138 #define i_orw 139 #define i_orl 140 #define i_orib 141 #define i_oriw 142 #define i_oril 143 #define i_pea 144 #define i_reset 145 #define i_rolb 146 #define i_rolw 147 #define i_roll 148 #define i_rorb 149 #define i_rorw 150 #define i_rorl 151 #define i_roxlb 152 #define i_roxlw 153 #define i_roxll 154 #define i_roxrb 155 #define i_roxrw 156 #define i_roxrl 157 #define i_rte 158 #define i_rtr 159 #define i_rts 160 #define i_sbcd 161 #define i_scc 162 #define i_scs 163 #define i_seq 164 #define i_sf 165 #define i_sge 166 #define i_sgt 167 #define i_shi 168 #define i_sle 169 #define i_sls 170 #define i_slt 171 #define i_smi 172 #define i_sne 173 #define i_spl 174 #define i_st 175 #define i_stop 176 #define i_subb 177 #define i_subw 178 #define i_subl 179 #define i_subqb 180 #define i_subqw 181 #define i_subql 182 #define i_subxb 183 #define i_subxw 184 #define i_subxl 185 #define i_svc 186 #define i_svs 187 #define i_swap 188 #define i_tas 189 #define i_trap 190 #define i_trapv 191 #define i_tstb 192 #define i_tstw 193 #define i_tstl 194 #define i_unlk 195 #define i_movsb 196 /* 68010 TPM */ #define i_movsw 197 /* 68010 TPM */ #define i_movsl 198 /* 68010 TPM */ #define i_movc 199 /* 68010 TPM */ ine i_addxb 8 #define i_addxw 9 #define i_addxl 10 #define i_andb 11 #define i_andw 12 #define i_andl 13 #define i_aslb 14 #define i_aslw 15 #define i_asll 16 #define i_asrb 17 #define i_asrw 18 #define i_sumacc/cc/as/mac.c 444 0 12 54517 3470501537 7235 # #include "mical.h" #include "mac.h" char *mac = "~|^`s.mac.c R1.2 on 12/5/79"; /* macro bucket states */ #define DEFINING 1 #define EXPANDING 2 /* macro token types */ #define SPACE 0 #define TIK 1 #define EOL 2 #define WORD 3 #define ARG 4 #define NIL 5 /* arguments to Load_Macro */ #define MACRO 0 #define REPT 1 /**************************************************************************** * * * MICAL Assembler -- Macro Implementation * * * * The overall purpose of the following procedures is explained in * * mac.h. * * * ****************************************************************************/ /* * External Variables */ FLAG Expanding = FALSE; /* TRUE when expanding a macro, FALSE otherwise */ int Top_of_M_stack = -1; /* initialize macro call stack ptr */ extern char *Store_String(); extern struct sym_bkt *Lookup(); /* Define_Macro() This is called by Pseudo() (ps.c) when a .macro pseudo-op is recognized on the source line. It allocates a macro bucket for the macro, and places it on the macro table, which is organized in a hashed, chained method as is the assembler's normal symbol table. Define_Macro processes the remainder of the .macro line, reading in the formal arguments of the macro, loading pertinent information into the external structure, M_defining. Finally, it puts the assembler into macro defining mode by calling Load_Macro. All of the above is done on pass 1. On pass 2, the assembler merely prints the text of the macro definition. */ /* Macro hash table, each entry is the head of a linked list of macro buckets. This structure is initialized by the routine Init_Macro(), which is called by the assembler's initialization routine Init(); */ struct M_bkt *Mac_hash_tab[HASH_MAX]; Init_Macro(){ register int i; for (i=0; i<HASH_MAX; i++) Mac_hash_tab[i] = 0; } /* typ_mask is an array of mask bits. The name "typ_mask" is used to share this structure with the "typ_mask" array of sym.c, where the array is defined */ int typ_mask[16] = { 01, 02, 04, 010, 020, 040, 0100, 0200, 0400, 01000, 02000, 04000, 010000, 020000, 040000, 0100000 }; struct { /* Listing flags */ char any_lf; /* master switch. If 0, no listing at all is done */ char bin_lf; /* binary code field of listing line */ char bex_lf; /* binary extensions (e.g. from .word) */ char md_lf; /* macro definitions */ char mc_lf; /* macro calls */ char me_lf; /* macro expansions */ char cnd_lf; /* unsatisfied conditional blocks */ char ld_lf; /* listing directives */ } Lflags ; Define_Macro(){ char S[STR_MAX]; register char *cp; register struct M_bkt *mdp; int save; /* index of chain in Mac_hash_tab of macro name */ register int load; /* next available character in M_defining.buff[] */ int count; /* number of formal arguments to the macro */ extern int E_pass1; /* error code for errors detected in pass 1 */ /* Pass2: list the current (.macro) line, and call Print_Macro to list the rest of the macro definition */ if (Pass == 2) { if (Lflags.md_lf) { /* if macro definitions listed, do it */ Print_Line(P_NONE); Print_Macro(); } return; } /* Pass1: */ /* Get the name of the macro */ if (Get_Token(S) == 0) Prog_Error(E_pass1 = E_MACRO); else { /* Create a macro bucket for this macro, and enter it in the macro symbol table */ mdp = (struct M_bkt *)malloc(sizeof _M_bkt); mdp->name_m = Store_String(S); mdp->next_m = Mac_hash_tab[save = Hash(S)]; mdp->text_m = 0; mdp->state_m = DEFINING; mdp->ACS_m = 0; Mac_hash_tab[save] = mdp; /* Load the M_defining structure */ M_defining.bkt_md = mdp; M_defining.nargs_md = 0; load = 0; for (count = 0; count < MARGS_MAX; count++) { /* load formal macro arguments */ Non_Blank(); if (Line[Position] == ',') Position++; Non_Blank(); if (Line[Position] == '?') { /* Check for automatically created symbol */ mdp->ACS_m |= typ_mask[count]; Position++; } if (Get_Token(S) == 0) break; /* Get the formal argument */ M_defining.args_md[count] = & (M_defining.buff_md[load]); /* load it into M_defining */ for (cp = S; *cp && load < MARGCHAR_MAX-1; cp++,load++) M_defining.buff_md[load] = *cp; M_defining.buff_md[load++] = 0; if (load >= MARGCHAR_MAX) { Prog_Warning(E_MLENGTH); break; } } M_defining.nargs_md = count; /* count of number of arguments */ mdp->state_m = 0; /* macro args have been read, make sure we're at end of line */ if (Line_Delim(Line[Position]) == false) Prog_Error(E_pass1 = E_MACARG); } /* List the .macro line */ Print_Line(P_NONE); /* Load the rest of the macro definition */ Load_Macro(mdp,MACRO); /* call from Define_Macro */ return; } /* MLHold is a buffer to hold a line of the macro as it is scanned for macro arguments */ char MLHold[LINE_MAX] = 0; /* Load_Macro This is called on pass 1 to store the text of the macro currently being defined. arguments: mdp, a ptr to the macro bucket for the macro. caller, a flag that is the constant MACRO if we are called from Define_Macro and the constant REPT if we're called from Rept(). returns: nothing; Side Effects: The text_m component of the macro's bucket becomes the head of a linked list of M_line's, where the Nth M_line points to the Nth line of the macro. */ Load_Macro(mdp,caller) struct M_bkt *mdp; int caller; { char S[STR_MAX]; /* all-purpose char string */ struct M_line *Cur_mline; /* current macro line */ int Nested; /* depth of .macro definitions */ int Last,This; /* Macro token types */ extern int E_pass1; /* error code for errors detected in pass 1 */ struct M_line *Load_Arg(), *Load_String(); Cur_mline = mdp->text_m = (struct M_line *)malloc(sizeof _M_line); /* allocate initial M_line */ Nested = 0; MLHold[0] = 0; /* initialize line buffer for Load_String */ while(1) { /* For the duration of the macro definition, */ Read_Line(); /* read the next source line */ if (Get_Token(S)) /* does a valid token begin the line? */ if (seq(S,".macro") || /* Yes, check for macro definition delimiters */ seq(S,".rept")) Nested++; /* if starting a nested macro definition, incr depth count */ else if ((seq(S,".endm")|| seq(S,".endr")) /* if ending a macro definition, */ && (--Nested) < 0) { /* decrement depth count */ Print_Line(P_NONE); /* list the .endm statement */ return; } /* and return */ /* Process the current source line of the macro. This consists mainly of identifying the arguments to the macro and replacing them with a special character which indicates their argument number */ Position = 0; /* reset Position after the previous Get_Token() */ /* if a .rept block is being loaded, just load the current line. If a macro is being loaded, then scan the line for formal args */ /* The purpose of the next if..else do {} statement is to store the current line away, placing it on a linked list of macro lines. For .rept lines, no formal arguments need to be extracted; for .macro lines, much hair is involved in locating a formal argument and storing an argument code for is rather than the text itself. */ if (caller == REPT) Cur_mline = Load_String(Line,Cur_mline); else do { /* For the rest of the input line, */ Last = This; /* Save the type of the last token */ This = Get_Mtoken(S); /* Get the next token; Get_Mtoken returns the type of the token loaded into S */ if (This == ARG) { /* if it is a macro argument, */ Cur_mline = Load_Arg(S,Cur_mline); /* load the special character for it in place of the argument */ continue; } /* Check for concatenation */ if (Last == TIK) /* if the last token was a tik (') */ Cur_mline = Load_String("'",Cur_mline); /* load the tik, since it wasn't used for concatenation */ if (This == TIK) { /* if the current token is a tik, */ if (Last = ARG) /* and if the last token was an argument, then concatenation is being done, so */ This = NIL; /* ignore the current tik mark */ continue; } if (This == NIL) { /* if Get_Mtoken failed to get a token, complain */ Prog_Error(E_pass1 = E_MACFORMAL); break; } /* Finally, load the current macro token */ Cur_mline = Load_String(S,Cur_mline); } while (This != EOL); /* stop at the end of the source line */ Print_Line(P_NONE); /* list the current line */ } /* The macro has been defined */ /* return; */ } /* Print_Macro() is called on pass 2 to simply list a macro definition. Any errors in the definition will have been detected in pass 1 */ Print_Macro() { int Nested; char S[STR_MAX]; Nested = 0; while(1) { Read_Line(); Print_Line(P_NONE); Get_Token(S); if ( seq(S,".macro") || seq(S,".rept") ) Nested++; else if ((seq(S,".endm") || seq(S,".endr")) && (--Nested) < 0) return; } } /* Load_String -- Loads a char string into a macro line. arguments: char *S, the string to be loaded, struct M_line *mline, a ptr to the M_line to be modified. results: returns a M_line ptr which is to be used in the next Load_String operation. method: If S is not a newline character, then the string S is appended to the static char array MLHold, (macro line hold), and Load_String returns the same M_line that was passed to it. If S is a newline, then the char string in MLHold is copied (via Store_String in sym.c) and a ptr to this copy is put into the Text component of mline. A new macro line is allocated, and it's address loaded into mline->next_ml. This ptr to the newly allocated macro line is returned. */ struct M_line *Load_String(S,mline) char *S; register struct M_line *mline; { register char *cp; register int i; char *lastc(); /* returns ptr to last char of string argument */ cp = S; for (i=0; MLHold[i]; i++); /* find end of MLHold */ for(; *cp && i < LINE_MAX-1; (cp++,i++)) /* append S to MLHold */ MLHold[i] = *cp; MLHold[i] = 0; if ((*lastc(S))=='\n') { /* Is this the end of a line? */ mline->text_ml = Store_String(MLHold); /* yes, so copy the line, and save a ptr to it */ MLHold[0] = 0; /* clear MLHold */ mline->next_ml = (struct M_line *)malloc(sizeof _M_line); /* allocate the next M_line on the linked list of M_lines for this macro */ (mline->next_ml)->text_ml = NULL; (mline->next_ml)->next_ml = NULL; /* initialize the new M_line */ return(mline->next_ml); /* and return with a ptr to it */ } return(mline); /* still loading current line, so return with the same M_line */ } /* Load_Arg loads the special character code for a macro argument appearing in the text of the macro. A macro argument appearing in the text of a macro is represented by a single byte with value 0200 + <argument index>, where the Nth macro argument on the .macro line has argument index N. */ struct M_line *Load_Arg(form_arg,mline) char *form_arg; struct M_line *mline; { register char S[2]; int N; N = Form_Arg_No(form_arg); if (N<1 || N > M_defining.nargs_md) Sys_Error("Invalid formal parameterpassed to Load_Arg",0); S[0] = 0200 + N; S[1] = 0; return(Load_String(S,mline)); } /* Form_Arg_No returns N if it's argument is the Nth argument of the current macro being defined. Otherwise it returns 0 */ int Form_Arg_No(S) register char *S; { register int i; for(i = 0; i<M_defining.nargs_md; i++) if (seq(S,M_defining.args_md[i])) return(i+1); return(0); } /* Get_Mtoken-- Get Macro Token The text of a macro is partitioned into 5 types of tokens: SPACE's: a string of spaces or tabs; TIK's: a single apostrophe character ('); EOL's: a newline or formfeed character; WORD's: any sequence of characters not containing SPACE's, TIK's, or EOL's; ARG's: a special kind of WORD, one which is a formal argument to the current macro being defined. */ int Get_Mtoken(S) register char *S; { register int i; register char C; C = Line[Position]; for (i = 0; i < STR_MAX-1; i++) /* check for string of spaces */ if ((C == ' ') || C == '\t') { S[i] = C; C = Line[++Position]; } else break; if (i) { S[i] = 0; return(SPACE); } if (Get_Token(S)) /* attempt to read a word */ if (Form_Arg_No(S)) return(ARG); /* if word found, check if it's an argument */ else return(WORD); if (C == '\n' || C == '\014') { /* Check for newline char */ Position++; S[0] = C; S[1] = 0; return(EOL); } if (C == '\'') { /* Check for apostrophe */ Position++; S[0] = C; S[1] = 0; return(TIK); } if (C < ' ' || C > '~') { /* Invalid character, just return a nil token */ Position++; /* skip over the bad char */ return(NIL); } S[0] = C; S[1] = 0; /* just return the character (operator, colon, etc.) */ Position++; return(SPACE); /* This could return SPACE or WORD */ } /* Macro() -- handles macro calls This is called by the main loop to recognize macro calls. Any labels on the current line have already been processed, so the first token we grab is a candidate for a macro call. Expansion is done on the fly during pass 1, so that on pass 2, all we need do is list the macro call. On pass 1, this routine reads the actual arguments to the macro, and sets up a macro-call (M_call) structure for the macro activation. */ Macro() { int Save,count,level,i,load; register char S[STR_MAX],C; char rdelim,ldelim; struct M_bkt *mbp,*Get_Mac_Bkt(); register struct M_call *mcp; struct sym_bkt *sbp; Save = Position; /* remember current position on input source line */ if (Get_Token(S) == 0) /* Pick up the next token on line */ return(true); /* if none, we can't do anything */ /* Search macro table for token */ if ((mbp = Get_Mac_Bkt(S)) == 0) { Position = Save; /* if not found, not a macro call */ return (true); } if (Pass == 2) { /* On pass 2, just list the macro call */ if (Lflags.mc_lf) Print_Line(P_NONE); return(false); } /* since we're finished with this line */ /* Set up macro call structure */ if (Top_of_M_stack >= MDEPTH_MAX) { Prog_Warning(E_LEVELS); goto done; } mcp = M_stack[++Top_of_M_stack] = (struct M_call *)malloc(sizeof _M_call); /* allocate M_call bucket */ mcp->bkt_mc = mbp; /* ptr to permanent macro bucket for the macro */ mcp->line_mc = mbp->text_m; /* first line of the macro */ mcp->rc_mc = 1; /* repeat count is zero */ /* Load macro arguments in M_call structure */ /* Argument strings are stored sequentially in mcp->buff_mc */ load = 0; /* position in buff_mc to load next char */ /* For each macro argument, */ for (count = 0; (count < MARGS_MAX) && (load < MARGCHAR_MAX); count ++) { mcp->args_mc[count] = & (mcp->buff_mc[load]); /* set the ptr to its copy in buff_mc */ Skip_Comma(); /* find first char of argument */ C = Line[Position]; /* switch statement places one macro argument into the buff_mc array of the macro call structure */ switch(C){ /* Argument enclosed between delimiter chars */ case '^': /* explicitly declared delimiter character follows */ rdelim = ldelim = Line[++Position]; goto arg_encl; case '<': /* normal delimiters */ ldelim = '<'; rdelim = '>'; arg_encl: /* pick up enclosed argument */ if (Enclosed(ldelim,rdelim,S) != 0) { /* extract macro argument */ Prog_Error(E_MACARG); goto done; } for(i=0; mcp->buff_mc[load++] = S[i] && load < MARGCHAR_MAX; i++); /* copy macro arg to buffer */ break; /* continue for loop, reading macro arguments /* load a numeric argument in a symbol. The value of the symbol is converted to its ASCII representation (in octal) and this representation becomes the macro argument. */ case '\\': /* the expression is preceded by a backslash */ Position++; /* move past '\' */ if (Get_Token(S)) { /* pick up the symbol */ sbp = Lookup(S); /* get a ptr to its bucket */ if (sbp->attr_s & S_DEF) /* check that it's defined */ octalize(sbp->value_s,S); /* move its value expressed in octal into S */ else Prog_Error(E_SYMDEF); /* if it's not defined, then complain */ for(i=0; mcp->buff_mc[load++] = S[i] && load < MARGCHAR_MAX; i++); /* copy S into buff_mc */ } else { Prog_Error(E_SYMBOL); goto done; } /* if invalid symbol, complain */ break; default: /* regular argument */ /* Regular macro argument. Pick up all chars up to a legal separator (blank or comma), or end-of-statement */ while (C != ' ' && C != ',' && C != '\t' && !Line_Delim(C) && load < MARGCHAR_MAX-1) { mcp->buff_mc[load++] = C; C = Line[++Position]; } mcp->buff_mc[load++] = 0; /* end of macro arg */ } } done: if (load >= MARGCHAR_MAX) Prog_Error(E_MLENGTH); /* check if macro argument storage exceeded */ Print_Line(P_NONE); /* put the macro call into temp file (we're on pass 1) */ return(false); /* and return false since we're done with this line */ } /* Automatically Created Symbol count. This is used to create unique local symbols withing macro expansions. The count starts at 01000 to allow the programmer to use local symbols 0$ to 0777$. */ int ACS_count = 01000; /* Read_Macro_Line This is called from Read_Line() to read the next line of the macro currently being expanded. It returns true if it successfully read a macro line, false otherwise (implying end of macro expansion). */ Read_Macro_Line() { register int i,j,k; int index,C; struct M_call *mcp; struct M_line *mlp; char *orig_line, *arg, S[STR_MAX]; /* It is assumed that Macro() has set up the M_call stack, in which case M_stack[Top_of_M_stack] contains a ptr to a M_call structure for the current macro call */ if (Top_of_M_stack < 0) return(Expanding = false); /* no macro being expanded */ Expanding = true; mcp = M_stack[Top_of_M_stack]; /* get ptr to current macro call structure */ mlp = mcp->line_mc; /* ptr to current macro line structure */ if (mlp == 0 || (mlp->next_ml == 0)) { /* if this points to [0,0] m_line, then end of macro */ if ((--(mcp->rc_mc)) > 0) /* but if its a .rept statement, and this is not the last expansion, */ mcp->line_mc = (mcp->bkt_mc)->text_m; /* then move current line ptr back to start of text */ else { /* if we are indeed finished expanding, */ free( M_stack[Top_of_M_stack]); /* free the macro_expanding structure */ Top_of_M_stack--; /* decrement stack pointer */ } return(Read_Macro_Line()); /* and try again */ } orig_line = mlp->text_ml; /* actual source line */ /* Now step through the line char by char looking for the occurrence of a macro argument. This is represented by a single char with value 0200+N, where N is the index of the argument in the macro's definition. Load the resulting line into Line[]. */ for (i = 0, j = 0; orig_line[i] && j < LINE_MAX-1; i++) { C = orig_line[i] & 0377; if (C < 0200) Line[j++] = C; /* normal text char, just copy into Line[] */ else { /* argument occurrence */ index = C - 0200 - 1; /* index of argument (0 => 1st, 1=> 2nd, etc) */ arg = mcp->args_mc[index]; /* actual argument string */ /* Create automatically created symbols */ if (*arg == 0 && (((mcp->bkt_mc)->ACS_m) & (1 << index))) { /* actual arg must be absent */ octalize(ACS_count++, S); /* put octal rep of ACS_count into string S */ append("$",S); /* append $ to create a name of a unique local symbol */ arg = S; /* and let the generated symbol be the argument */ } for (k = 0; arg[k] && j<LINE_MAX-1; k++) /* copy it into actual line */ Line[j++] = arg[k]; } } Line[j] = 0; /* end of line */ Start_Line(); /* initialize per-line variables */ mcp->line_mc = (mcp->line_mc)->next_ml; /* step down list of linked macro lines */ return(true); } /* Rept: .rept handler [ Warning: this implementation is painfully inefficient: it keeps the text of a .rept block in core and forgets it when the block is completed, i.e. the memory is lost. Future implementations should either use the free storage pkg to hold the text, or use a file. ] .REPT blocks are handled similarly to .macro blocks: 1. A macro_bucket is created for the block, but no name is associated with the macro; furthermore, the macro bucket is not placed in the macro hash table. 2. The text of the .rept block is read into core, and each line of the text is stored as a macro_line structure. 3. After the text of the macro is stored, a macro_call structure is created and placed on the macro call stact, with a repeat count equal to the number in the operand field of the .rept statement. 4. Control is returned to the assembler. Read_Line will pick up the text of the .rept block via the macro call structure. When the .rept block has been repeated enough times, the macro call structure will be destroyed, also losing the pointer to the macro lines containing the text of the .rept block. */ Rept(){ struct M_call *mcp; struct M_bkt *mdp; int RC; /* repeat count*/ Print_Line(P_NONE); /* list the .rept statment */ if (Pass == 2) { /* ignore .rept statement on pass 2 */ Print_Macro(); /* print definition of macro */ return; } /* Get the repeat count */ if ((Get_Operand() == false) || /* evaluate the operand field */ (RC = Operand.value_o) < 0) { /* assign the value to RC */ Print_Line(); /* if the repeat count is invalid, print the .rept statement, */ Print_Macro(); /* and the rest of the .rept block */ return; } /* Create macro bucket for this .rept block, but don't enter it into the macro hash table */ mdp = (struct M_bkt *)malloc(sizeof _M_bkt); mdp->name_m = 0; mdp->next_m = 0; mdp->text_m = 0; mdp->state_m = DEFINING; mdp->ACS_m = 0; Load_Macro(mdp,REPT); /* load text of macro */ mcp = M_stack[++Top_of_M_stack] = (struct M_call *)malloc(sizeof _M_call); mcp->bkt_mc = mdp; mcp->line_mc = mdp->text_m; mcp->rc_mc = RC; /* load repeat count into macro call structure */ return; } /* octalize(N,S) puts the octal representation of N into string S) */ octalize(N,S) int N; register char *S; { register char buff[7]; register int i; long NN; NN = N & 0177777; i = 5; /* put octal representation into rhs of buff */ do { buff[i--] = NN % 8 + '0'; NN = NN/8; } while (NN > 0); while (i < 5) *S++ = buff[++i]; /* copy octal rep into S */ *S = 0; } /* * Get_Mac_Bkt(Name) returns a ptr to the M_bkt structure for the macro named "Name". * If no such macro exists, 0 is returned. */ struct M_bkt *Get_Mac_Bkt(Name) char Name[]; { struct M_bkt *mbp; for (mbp=Mac_hash_tab[Hash(Name)]; mbp != 0; mbp = mbp->next_m) if (seq(Name,mbp->name_m)) return (mbp); return(0); } esented by a single char with value 0200+N, where N is the index of the argument in the macro's definition. Load the resulting line into Line[]. */ for (i = 0, j = 0; orsumacc/cc/as/mac.h 444 0 12 11612 3470501537 7227 # /****************************************************************************** * * * MICAL Assembler Macro Header * * * * These are the structure definitions and external declarations used to * * implement macros in the MICAL assembler. This file also contains a des- * * cription of the implementation. * * * ******************************************************************************/ /* MACRO IMPLEMENTATION Overview ________ The MICAL assembler defines and expands macros during the first pass. No preprocessor is used. When a .macro instruction is encountered during the first pass, the assembler enters a separate macro defining mode, implemented by the "Define_Macro" procedure in "mac.c". In this mode, text is read in verbatim from the input file and associated with the name of the macro being defined until a .end or .endm statement is encountered. Thus, no processing of the statements (i.e. execution of pseudo-ops) within a macro is done at the time the macro is defined. Processing of the statements in a macro is done only when the macro is expanded. Thus only one macro is being defined at any given time. One may have the definition of macro M2 within the definition of macro M1, but M2 will actually be defined only when M1 is being expanded. When a .endm pseudo-op is identified during macro definition, the assembler returns to normal assembly mode. When a macro is identified in the operation field of an statement [Macro()], a structure containing the necessary information for the expansion of the macro is created, and placed on a stack of such macro calls [Expand_Macro()]. The use of a stack allows nested macro calls, and even recursive macro calls. The maximum depth of nested (recursive) macro calls is the defined parameter, MDEPTH_MAX. Whenever a macro is being expanded (identified by a structure on the M_Stack) the routine Read_Line() will read in a source line from the current macro being expanded instead of from the input file. Since Define_Macro() uses Read_Line to get the text of a macro definition, this allows macro definition during macro expansion. When a macro is expanded, the macro call itself and the expansion are loaded into the temporary file which holds the source text between passes 1 and 2. In the second pass, when a .macro is encountered, the assembler again goes into a special mode similar to pass 1's. Each source line is merely printed out, until either a .end or .endm statement is encountered, whereupon normal processing resumes. When a macro call is encountered in pass 2, it is simply listed. Presumably the code for the macro expansion already follows the macro call. Macro Definition ----- ---------- The major data structure for macro definition is the M_defining structure, reproduced below: */ /* Number of arguments to a macro */ #define MARGS_MAX 16 /* Number of characters in all macro arguments combined (per macro call) */ #define MARGCHAR_MAX 80 /* Number of nested macro calls */ #define MDEPTH_MAX 16 /* Number of conditional macros */ #define COND_MACROS 16 /* Macro definition information */ struct { struct M_bkt *bkt_md; /* bkt for defined macro */ char buff_md[MARGCHAR_MAX]; /* storage for macro arguments */ char *args_md[MARGS_MAX]; /* ptrs into buff_md. These are the actual arguments */ int nargs_md; /* number of (formal) arguments */ } M_defining ; /* Permanent macro information. These are organized like the symbol table (see sym.c) */ struct M_bkt { int state_m; /* Defining or Expanding */ char *name_m; /* name of the macro */ struct M_bkt *next_m; /* ptr to next bkt on chain */ struct M_line *text_m; /* head of linked list of M_lines, which contain the text of the macro */ int ACS_m; /* Automatically Created Symbol flags, one per possible macro argument */ } _M_bkt; /* Macro Expansion information. Each bucket is allocated upon expansion of a macro. They are maintained in a stack via M_Stack */ struct M_call { struct M_bkt *bkt_mc; /* ptr to permanent info for this macro */ char buff_mc[MARGCHAR_MAX]; /* storage for actual arguments of macro call */ char *args_mc[MARGS_MAX]; /* ptrs into buff_mc, one per actual argument. */ struct M_line *line_mc; /* ptr to next M_line to expand */ int rc_mc; /* repeat count, for .irpb and .irpc */ } _M_call; /* Text Storage. Each line of a macro is stored separately, and is linked to the following line of the macro. */ struct M_line { struct M_line *next_ml; /* ptr to next line of the macro */ char *text_ml; /* ptr to the char string for the line */ } _M_line; /* Macro Expansion Stack. Each time a macro is expanded, a ptr to it's M_call structure is placed on this stack. This allows nested and recursive macros. */ struct M_call *M_stack[MDEPTH_MAX]; int Top_of_M_stack ; /* Conditional Macro Test list */ int CM_top; char *CM_tests[COND_MACROS]; til a .end or .endm statement is encountered. Thus, no processing of the statements (i.e. execution of pseudo-ops) witsumacc/cc/as/makefile 444 0 12 666 3470501537 7765 # Description file for 68000 assembler CFLAGS = -c -O -I/usr/sun/include -DBOOTSTRAP -DStanford OFILES = as.o cond.o error.o eval.o init.o ins.o mac.o oper.o print.o\ ps.o ps1.o ps2.o ps3.o random.o rel.o sdi.o spawn.o sym.o as68: $(OFILES) cc -o as68 $(OFILES) $(OFILES): mical.h mac.o: mical.h mac.h init.o ins.c: mical.h inst.h install: cp as68 /usr/sun/bin/as68 cp a68.hdr /usr/sun/lib clean: rm -f *CKP *BAK *.o as68 macro. */ struct M_line { struct M_line *next_ml; /* ptr to next linsumacc/cc/as/mical.h 444 0 12 10702 3470501540 7545 #ifdef BOOTSTRAP #include "/usr/include/stdio.h" #else #include <stdio.h> #endif /* Assembler parameters */ #define STR_MAX 32 /* number of chars in any single token */ #define OPERANDS_MAX 4 /* number of operands allowed per instruction */ #define MNEM_MAX 8 /* number of chars in instruction mnemonic */ #define LINE_MAX 132 /* Number of chars in input line */ #define FILEID_MAX 15 /* number of files open at any one time */ #define HASH_MAX 32 /* size of symbol, command, and macro hash tables */ #define CONT_MAX 3 /* number of chars in control field of operand */ #define CODE_MAX 12 /* number of bytes generated for 1 machine instruction */ #define SSTACK_MAX 10 /* Max number of input source files open at any time */ #define ERR_MAX 50 /* Max number of different error codes */ #define CSECT_MAX 200 /* number of control sections */ #define COND_MAX 16 /* maximum depth of nested conditional blocks */ /* Error Codes */ #define E_END 1 #define E_BADCHAR 2 #define E_MULTSYM 3 #define E_NOSPACE 4 #define E_OFFSET 5 #define E_SYMLEN 6 #define E_SYMDEF 7 #define E_CONSTANT 8 #define E_TERM 9 #define E_OPERATOR 10 #define E_RELOCATE 11 #define E_TYPE 12 #define E_OPERAND 13 #define E_SYMBOL 14 #define E_EQUALS 15 #define E_NLABELS 16 #define E_OPCODE 17 #define E_ENTRY 18 #define E_STRING 19 #define E_INSRT 20 #define E_ATTRIBUTE 21 #define E_.ERROR 22 #define E_LEVELS 23 #define E_CONDITION 24 #define E_NUMOPS 25 #define E_LINELONG 26 #define E_REG 27 #define E_IADDR 28 #define E_UNIMPL 29 #define E_FILE 30 #define E_MLENGTH 32 #define E_MACARG 33 #define E_MACFORMAL 34 #define E_ENDC 35 #define E_RELADDR 36 #define E_ARGUMENT 37 #define E_VECINDEX 38 #define E_VECMNEM 39 #define E_MACRO 40 #define E_TMACRO 41 #define E_CSECT 42 #define E_ODDADDR 43 /* Size Codes - These should agree with Rel size codes in b.h */ #define B 0 /* byte */ #define W 1 /* word */ #define L 2 /* long */ /* Print Codes */ #define P_ALL 0 #define P_LC 1 #define P_NONE 2 /* Symbol attributes */ #define S_DEC 01 #define S_DEF 02 #define S_EXT 04 #define S_LABEL 010 #define S_MACRO 020 #define S_REG 040 #define S_LOCAL 0100 #define S_COMM 0200 #define S_PERM 0400 /* Rel file and Csect attributes */ #define R_EXT 01 #define R_ISPC 02 #define R_PURE 04 #define R_ABS 010 #define R_DEC 020 /* Operand flags */ #define O_WINDEX 1 #define O_LINDEX 2 #define O_COMPLEX 4 /* Abbreviations */ #define FLAG char #define TRUE 1 #define FALSE 0 #define true 1 #define false 0 /* operand types */ #define t_reg 1 #define t_defer 2 #define t_postinc 3 #define t_predec 4 #define t_displ 5 #define t_index 6 #define t_abss 7 #define t_absl 8 #define t_immed 9 #define t_normal 10 /* Instruction Hash Table */ struct ins_bkt { struct ins_bkt *next_i; /* ptr to next bkt on the list */ char *text_i; /* ptr to asciz instruction mnemonic */ int code_i; /* opcode index for dispatching */ } ins_example; /* example of ins_bkt, used for sizeof operation */ /* The instruction hash table itself. Each entry is the head of a linearly linked list * of ins_bkts. */ struct ins_bkt *ins_hash_tab[HASH_MAX]; /* Csect descriptor */ struct csect { char *name_cs; /* Name, usually stored with Store_String */ long len_cs; /* Length in machine addresses, i.e., highest address referenced */ long dot_cs; /* current dot in this cs, in machine addresses */ int id_cs; /* ID # for output file */ int attr_cs; /* attributes */ } ; /* Symbol bucket definition */ struct sym_bkt{ struct sym_bkt *next_s; /* next bkt on linked list */ char *name_s; /* symbol identifier */ long value_s; /* it's value */ int id_s; /* id number for .rel file */ struct csect *csect_s; /* ptr to it's csect */ int attr_s; /* attributes */ } ; /* Code[], buffer for the generated code */ char Code[CODE_MAX]; struct oper { char type_o; /* operand type info */ char flags_o; /* operand flags */ char reg_o; /* Register subfield value */ struct sym_bkt *sym_o; /* symbol used for relocation */ long value_o; /* Value subfield */ long disp_o; /* displacement value for index mode */ } Operand ; /* VIP variables */ int Pass ; /* Pass number */ long Dot ; /* Assembly location counter */ char Line[LINE_MAX+1]; /* buffer for source statement */ int Position ; /* current position in Line */ int BC; /* Byte count of current line */ long tsize; /* size of the text segment, valid on pass2 */ long dsize; /* size of the data segment */ long bsize; /* size of the bss segment */ #define MARGCHAR_MAX 80 /* Number of nested macro calls */ #sumacc/cc/as/oper.c 444 0 12 7675 3470501540 7417 #include "mical.h" char *oper = "~|^`s.oper.c R1.2 on 12/17/79"; /* Scan_Operand_Field(operands) puts the type of each operand encountered in the operands array, and returns the number of operands altogether. */ Scan_Operand_Field(operands) struct oper operands[]; { int numops,save; Non_Blank(); save = Position; numops = 0; do { if (Line_Delim(Line[Position])) break; Get_Operand(operands++); numops++; Non_Blank(); } while (numops < 4); Position = save; return(numops); } /* Op_Delim Returns TRUE if c marks the end of an operand field */ Op_Delim(c) char c; { register char *cp; for (cp = "\n|,:()@\014]"; *cp; cp++) if (c == *cp) return(TRUE); return(FALSE); } /* Num_Operands() returns the number of operand fields on the current statement, each of them separated by commas. */ Num_Operands() { register int i,count; /* index and num of operands */ register char C; int skip; /* number of chars to skip in scanning the field */ int save; char S[STR_MAX]; Non_Blank(); /* Move Position to first non_blank char */ if (Line_Delim(Line[Position])) return(0); /* If no chars left, no operands */ count = 1; /* at least one operand is there */ skip = 0; /* don't skip any chars */ save = Position; while(Line_Delim(C = Line[Position]) == FALSE){ /* Look at rest of line */ if (skip) skip--; else if (C == '<' || C == '{') { /* if enclosed expression */ Enclosed(C,C+2,S); /* skip over it; C+2 is the ascii rep of > and } resp. */ continue; } /* Position is already past enclosed position */ else if (C == '\'') skip = 1; else if (C == '\"') skip = 2; else if (C == ',') count++; /* ',' separates operands */ Position++; } Position = save; /* restore Position */ return(count); } /* * Fetches operand value and register subfields and loads them into * the operand structure. This routine will fetch only one set of value * and register subfields. It will move Position past a ',', so that * subsequent calls to Get_Operand will get succesive operands. * It will return FALSE if there were any programmer errors in the * operand, TRUE otherwise. */ Get_Operand(opnd) struct oper *opnd; { char c; opnd->type_o=opnd->flags_o=opnd->reg_o=opnd->value_o=opnd->disp_o = 0; if (Line[Position] == '#') { Position++; /* skip # */ if (!Evaluate(opnd)) return; if (opnd->type_o == t_reg) Prog_Error(E_REG); opnd->type_o = t_immed; } else if (!Evaluate(opnd)) return; Non_Blank(); while (c = Line[Position++]) switch(c) { case '\014': case '|': case '\n': Position--; /* don't scan these */ case ',': return; /* i'm done */ case ':': switch(Line[Position++]) { case 'W': case 'w': opnd->type_o = t_abss; continue; case 'L': case 'l': opnd->type_o = t_absl; continue; default: return; } case '@': if (opnd->type_o != t_reg) return; opnd->type_o = t_defer; continue; case '+': if (opnd->type_o != t_defer) return; opnd->type_o = t_postinc; continue; case '-': if (opnd->type_o != t_defer) return; opnd->type_o = t_predec; continue; case '(': if (!Get_Defer(opnd)) return; continue; default: return; } return; } /* Get_Defer Process Displacement or Index Deferred Suboperands */ Get_Defer(opnd) register struct oper *opnd; { if (opnd->type_o != t_defer) return(FALSE); opnd->reg_o = opnd->value_o; if (!Evaluate(opnd)) return(FALSE); Non_Blank(); switch(Line[Position++]) { case ')': opnd->type_o = t_displ; break; case ',': opnd->disp_o = opnd->value_o; if (!Evaluate(opnd)) return(FALSE); if (opnd->type_o != t_reg) return(FALSE); if (Line[Position++] != ':') return(FALSE); switch(Line[Position++]) { case 'W': case 'w': opnd->flags_o |= O_WINDEX; break; case 'L': case 'l': opnd->flags_o |= O_LINDEX; break; default: return(FALSE); } Non_Blank(); if (Line[Position++] != ')') return(FALSE); opnd->type_o = t_index; break; default: return(FALSE); } return(TRUE); } ganized like the symbol table (see sym.c) */ struct M_bkt { isumacc/cc/as/print.c 444 0 12 20246 3470501540 7613 #include "mical.h" char *print = "~|^`s.print.c R1.5 on 1/22/80"; extern int *WCode; extern FILE *listout; /* Print_Line, Print_No ; Print_Line() prints the current line to the appropriate file, depending on the pass. Pass 0: (Descriptor file code) Nothing is printed; Pass 1: The current error code and the source line is printed into the temproary file, for subsequent input to pass 2; Pass 2: A regular assembly listing line is generated and printed into the standard output. Possible 'option's are: P_NONE: List only the line number, error code (if any), and the source line. P_LC: Same as P_NONE, but list value of location counter also. P_ALL: Same as P_LC, but list the binary code generated as well. On pass 2, if the command line flag 'O_list' is zero (meaning no listing requested), then the line number and error code of illegal statements is printed to the standard output. */ /* parameters to Print_No() */ #define ZS 0 #define ZP 1 /* External listing parameters */ int L_radix = 16; /* Radix for numbers in listing. Default is octal */ int L_ndigits = 2; /* Number of digits to express one byte in L_radix */ /* Listing option flags; set by .LIST and .NLIST directives */ struct { char any_lf; /* master switch. If 0, no listing at all is done */ char bin_lf; /* binary code field of listing line */ char bex_lf; /* binary extensions (e.g. from .word) */ char md_lf; /* macro definitions */ char mc_lf; /* macro calls */ char me_lf; /* macro expansions */ char cnd_lf; /* unsatisfied conditional blocks */ char ld_lf; /* listing directives */ } Lflags = { 1,1,1,1,1,1,1,0 } ; Print_Line(option){ register int i; /* gen index */ int fsave; extern FLAG Ignore, /* True if in unsatisfied conditional block, false otherwise */ Expanding; /* True if expanding a macro */ extern int Pass, /* Pass number, obviously */ Line_no, /* Line number in source file */ Code_length, /* Number of bytes generated on this instruction */ E_pass1, /* Error code for pass 1 */ Err_code; /* Error code generated for current statement, valid only in pass 2 */ extern char Rel_mark, /* (') if relocatable address generated, (<blank>) if not */ E_warn, /* (W) if current error is only a warning */ O_print, O_list; /* command line option, 1 if listing requested, 0 otherwise */ extern FILE *Temp_file; /* iobuf for intermediate file */ extern char *lastc(); if (Pass == 0) { /* If in header file (pre-assembly code) */ if (Err_code) Print_Error(); /* if error, print a msg on error output device */ return; /* otherwise, don't list anything */ } if (Pass == 1) { /* On pass 1, create a line in the temporary file */ putc(E_pass1,Temp_file); /* put out error code in binary form */ putc(Expanding?'*':' ',Temp_file); /* put out * if macro expansion, blank otherwise */ fputs(Line,Temp_file); /* and put out source line */ return; } if (O_list == 0 ) { /* if no listing wanted , give him one anyway it there's an error */ if (Err_code) Print_Error(); return; } if (Lflags.cnd_lf == 0 && Ignore) return; /* if unsatisfied cond blocks not listed, don't */ /* Check listing flags if line is to be listed. If there's an error, block is listed regardless of the flags. */ if (Err_code == 0) if ( (Lflags.any_lf == false) || /* .NLIST in effect */ (Expanding && (Lflags.me_lf == false)) /* Macro expansion */ ) return; /* * Print listing line for pass 2; There are six fields: Line number, Expanding Flag, Location counter, Code, Error, and Source. Each field is separated with 3 blanks; within a field, individual numbers are separated by one blank, except for the Source field. Any changes made in the listing line format should be reflected in the routine Extend() in the file ps1.c, which does the listing for binary extension instructions (e.g. .WORD). * */ /* Line number and expanding flag */ fprintf(listout, "%4d%c ",Line_no,Expanding?'*':' '); /* Print line number for all options */ /* Location counter */ if (option == P_NONE) Space_(3*L_ndigits+3); else { Print_No((Dot>>24)&0177,L_radix,L_ndigits,ZP); Space_(1); Print_No(Dot&0xFFFF,L_radix,2*L_ndigits,ZP); Space_(2); } /* Code */ if (option == P_ALL && Lflags.bin_lf) { /* If binary code listing desired */ for(i=0;i<CODE_MAX/2;i++) /* For each possible word of generated code */ if (i >= Code_length/2) Space_(2*L_ndigits+2); /* Skip enough space if it wasn't actually generated */ else { /* If it was, print it out. */ Print_No(0XFFFFL&((long)WCode[i]),L_radix,2*L_ndigits,ZP); /* if (i == Rel_byte_no) putc(Rel_mark, listout); /* If this could be the low byte of a */ /* relocatable address, mark it */ /* else */ Space_(2); } /* otherwise skip a space */ } else Space_((CODE_MAX/2)*(2*L_ndigits+2)); /* If we don't want code listed, skip enough space for it */ /* Error */ Space_(2); /* separate from other fields */ if (Err_code) Print_No((long)Err_code,10,2,ZS); /* if any error, print it's code */ else Space_(2); /* otherwise skip the field */ putc(E_warn, listout); /* put out 'W' if its a warning */ Space_(2); /* separate fields */ /* Source line */ fputs(Line, listout); /* Nothing hard about that */ /* if Line ends with form-feed, supply carriage return */ if (*lastc(Line) == '\014') putc('\015', listout); return; } /* Space_(Numspaces) just puts 'Numspaces' blanks out */ Space_(Numspaces) register int Numspaces; { register int i; for(i=0;i<Numspaces;i++) putc(' ',listout); } /* Print_No(val,radix,width,z) : Argument Explanation value: number to be printed; radix: 8,10, or 16 for octal, decimal, or hexadecimal notation respictively; width: field width--number is placed right-justified with left padding of blanks or zeroes; zflag: ZP for zero left padding, ZS for blank (zero-suppress) padding; It treats 'value' as a 16 bit unsigned integer */ Print_No(val,radix,width,zflag) long val; { register char Buf[16]; register int bl,T; bl = 15; /* load buffer from the end */ val &= 0177777L; /* mask to 16 bits */ do { /* do...while so that a value of zero gets printed */ T = val % radix; /* get value of digit */ if (val<0) T += radix; Buf[bl] = (T<10) ? (T+'0') : (T+'A'-10); /* load ascii value of digit */ val = val / radix; /* set up for next digit */ --bl; --width; } while (val>0 && width>0 && bl >= 0) ; /* we've got all of the digits */ for(; width>0 && bl>=0; (--bl, --width)) /* left pad with zeroes or blanks */ Buf[bl] = zflag ? '0' : ' '; for(bl++; bl<16; bl++) putc(Buf[bl],listout); /* and print the buffer */ } /* NList() -- implements .list, .nlist directives. Listing options are noted in a Listing Flag table: Lflags, defined above. Entries are 1 if option is listed, 0 if not. These flags are checked in the various routines that call Print_Line, and in Print_Line itself. This routine merely processes a .list or .nlist directive, which sets/resets the various listing flags. The argument Which is 1 for .list directives, 0 for .nlist. Nlist() is called from Pseudo(), in ps.c. */ NList(Which) FLAG Which; { char S[STR_MAX]; /* utility char string */ FLAG args_there; /* set if any arguments to .list/.nlist */ extern Lower(); /* convert to lower case function */ if (Pass == 1) { /* On pass 1, just copy line to temp file */ Print_Line(P_NONE); return; } if (Lflags.ld_lf) Print_Line(P_NONE); /* if listing directives are listed, then do so */ /* Loop through the arguments, setting the appropriate listing flags */ /* If no arguments, set master switch */ args_there = false; while (Get_Token(S)) { /* pickup next argument */ Lower(S); /* convert to lower case */ args_there = true; if (seq(S,"bin")) Lflags.bin_lf = Which; else if (seq(S,"bex")) Lflags.bex_lf = Which; else if (seq(S,"md")) Lflags.md_lf = Which; else if (seq(S,"mc")) Lflags.mc_lf = Which; else if (seq(S,"me")) Lflags.me_lf = Which; else if (seq(S,"cnd")) Lflags.cnd_lf = Which; else if (seq(S,"ld")) Lflags.ld_lf = Which; else Prog_Warning(E_ARGUMENT); /* invalid argument */ Non_Blank(); if (Line[Position]==',') Position++; /* skip comma */ } if (args_there == false) Lflags.any_lf = Which; /* if no args, then master switch set */ return; } P_ALL && Lflags.bin_lf) { /* If binary code listing desired */ for(i=0;i<CODE_MAX/2;i++) /* For each possible word of generated code */ if (i >= Code_length/2) Space_(2*L_ndigits+2); /* Skip enough space if it wasn't actually generated */ else { /* If it was, print it out. */ Print_No(0XFFFFL&((long)WCode[i]),L_radix,2*L_ndigsumacc/cc/as/ps.c 444 0 12 22344 3470501540 7102 #include "mical.h" #ifndef Stanford #include <a.out.h> #else Stanford #include "b.out.h" #endif Stanford struct csect *Text_csect,*Data_csect,*Bss_csect; #ifndef Stanford struct exec filhdr; #else Stanford struct bhdr filhdr; #endif Stanford char Ignore; /* if nonzero, ignore code,e.g. unsatified conditional block */ /* Pseudo() is called from the main loop to process assembler directives. If finds a pseudo-op, it returns FALSE, to discontinue processing on the current line. Otherwise, it returns TRUE. It also detects direct assignment statements. If the assembler is in Ignore mode, i.e. processing lines in an unsatisfied conditional block, then Pseudo will list the line. Each of the separate directive handlers, e.g. Byte(), is responsible for listing the line if it is called. */ Pseudo() { char String[MNEM_MAX+1]; /* storage for the mnemonic */ register char *S; /* what we'll work with */ int Save; /* temp storage for Position */ extern char O_debug; char D; D = O_debug; S = String; /* load the register */ Save = Position; /* Save the current position */ if (Get_Token(S) == FALSE) /* Pick up next token, */ return(TRUE); /* if not there, return */ Lower(S); /* Convert token to lower case */ if (S[0] != '.') { /* If not start with '.', ignore it */ Position = Save; return(TRUE); } if (seq(S,".end")) End(); else if (Ignore) Print_Line(P_NONE); else if (seq(S,".long")) { if (Dot & 1) Prog_Error(E_ODDADDR); ByteWord(4); } else if (seq(S,".word")) { if (Dot & 1) Prog_Error(E_ODDADDR); ByteWord(2); } else if (seq(S,".byte")) ByteWord(1); else if (seq(S,".macro")) Define_Macro(); else if (seq(S,".rept")) Rept(); else if (seq(S,".ascii")) Asciiz(0); else if (seq(S,".asciz")) Asciiz(1); else if (seq(S,".blkb")) Blkbw(1); else if (seq(S,".blkw")) Blkbw(2); else if (seq(S,".blkl")) Blkbw(4); else if (seq(S,".list")) NList(TRUE); else if (seq(S,".nlist")) NList(FALSE); else if (seq(S,".insrt")) Insrt(); else if (seq(S,".text")) { New_Csect(Text_csect); Print_Line(P_NONE); } else if (seq(S,".data")) { New_Csect(Data_csect); Print_Line(P_NONE); } else if (seq(S,".bss")) { New_Csect(Bss_csect); Print_Line(P_NONE); } else if (seq(S,".globl")) Globl(); else if (seq(S,".comm")) Comm(); else if (seq(S,".radix")) Radix(); else if (seq(S,".typef")) EPrintf('T'); else if (seq(S,".printf")) EPrintf('P'); else if (seq(S,".error")) EPrintf('E'); else if (seq(S,".page")) Page(); else if (seq(S,".defrs")) Defrs(); else if (seq(S,".even")) Even(); else { Position = Save; return(TRUE); }; return(FALSE); } /* End()-- .end handler Preconditions: Position is just after ".end". Side Effects: Temp_file is closed and switched to source file; Per-pass variables are initialized; Header for .rel file is generated. On pass two, descriptions of errors are printed, along with symbol table, (at end of listing) and Done flag is set. Entry point is determined. */ struct sym_bkt Entry_point ; /* Entry point of assembly program, optional */ char EntryFlag = 0; /* non-zero if entry point is specified */ char Done ; /* when 1, assembly complete */ End(){ extern FILE *Source_stack[]; extern int Ss_top; extern char O_symtab,O_debug,O_global; /* Set in init.c */ extern FILE *Temp_file; extern char Temp_name[]; extern struct csect Csects[]; extern int Csect_load; /* next available csect in Csects[] */ register int i; register struct csect *p; Print_Line(P_LC); /* Whichever pass, print the line */ /* Pass 2 */ if (O_debug >2) printf("\n End: Position=%d, ",Position); if (Pass > 1) { /* On the second pass, */ Error_Describe(); /* Print error descriptions, */ if (O_debug == 0) unlink(Temp_name); /* if not debugging, remove temporary file */ if (O_symtab) Pr_Sym_Tab(); /* Print symbol table, */ Fix_Rel(); /* patch up object file */ Done = 1; /* stop assembler */ return; } /* Pass 1 */ fclose(Temp_file); if ((Temp_file = fopen(Temp_name, "r")) == NULL) Sys_Error("Cannot reopen temporary file %s", Temp_name); for(; Ss_top>=0; Ss_top--) /* By clearing source stack */ fclose(Source_stack[Ss_top]); Push_Source(Temp_file); /* Pick up entry point */ if (Num_Operands() > 0 && Get_Operand(&Operand)) { Entry_point.value_s = Operand.value_o; EntryFlag = 1; } sdi_resolve(); /* resolve span dependent instructions */ for (p = &Csects[0], i=0; i < Csect_load; i++, p++) p->len_cs += sdi_inc(p, p->len_cs); /* Will need to remove following if Pratt's algorithm for locating instructions is to work. */ tsize = (Text_csect->len_cs + 3) & ~3; /* make long aligned */ dsize = (Data_csect->len_cs + 3) & ~3; bsize = (Bss_csect->len_cs + 3) & ~3; Sym_Fix(); /* relocate and globalize */ sdi_free(); /* release sdi blocks */ Rel_Header(); /* Initialize output stuff */ Start_Pass(); /* Init per-pass variables */ return; } /* Ehead() handles end of header file The header file consists of source statements that are executed before every program, and is included in the source descriptor file for the machine. When end_of_file is reached on this file, this program is called. Assumptions: Pass is 0, that is, the header file. Side_effects: Starts pass 1 by calling Start_Pass; Aborts if any assembly errors in descriptor file */ Ehead(){ extern int Errors; /* count of errors in this pass */ if (Errors) Sys_Error("%d errors in descriptor file\n",Errors); Perm(); /* make all symbols permanent */ Start_Pass(); } /* Initialize per-pass variables */ Start_Pass() { extern int Errors,Warnings,Err_load,Line_no; extern struct sym_bkt *Last_symbol; /* ptr to last defined sym */ extern struct sym_bkt *Dot_bkt; /* ptr to sym_bkt for Dot */ extern char O_debug; extern struct csect Csects[]; extern int Csect_load; register int i; Line_no = 0; Errors = 0; Warnings = 0; Err_load = 0; Pass++; if (Pass != 2) for (i=0; i<Csect_load; i++) Csects[i].dot_cs = 0; else { Text_csect->dot_cs = 0; Data_csect->dot_cs = tsize; Bss_csect->dot_cs = tsize + dsize; } Last_symbol = Dot_bkt; /*ONLY defined symbol at the start of a pass */ New_Csect(&Csects[0]); /* start in text segment */ if (O_debug > 2) printf("\n Start_Pass: Pass=%d\n",Pass); } /* Defrs(): DEFine Register Symbol. * This routine is called in the header code to define those symbols * that represent registers, accumulators, etc. on the machine. These * symbols have the S_REG flag set as an attribute, so that an error is * generated when their value is attempted to be changed. * Syntax is: * .defrs <name>,<value>[,<name>,<value>]... */ Defrs() { char S[STR_MAX]; /* working string */ register struct sym_bkt *sbp; struct sym_bkt *Lookup(); while(Get_Token(S)) { /* Pick up the name of the symbol */ sbp = Lookup(S); /* Make a sym_bkt for it */ Non_Blank(); /* find the ',' */ if (Line[Position] == ',') Position++; /* move past it */ if ((Get_Operand(&Operand) == 0) || Operand.sym_o ) { /* Evaluate the expression, must be absolute */ /* This moves Position past second ',' */ Prog_Error(E_OPERAND); break; } sbp->value_s = Operand.value_o; /* Load the sym_bkt */ sbp->csect_s = 0; sbp->attr_s = S_DEC | S_DEF | S_REG; } Print_Line(P_NONE); return; } /* #define CMD_LCS 27 */ /* Equals() is called from Label() to evaluate the operand field of a direct assignment statement and then to assign this value to the symbols on the left side of the '='. The array Label_list is a list of ptrs to the sym_bkt structures of each variable that is to be assigned. */ Equals() { register int i,Got; /* Got is TRUE if the operand field has been evaluated */ register struct sym_bkt *sbp; extern struct sym_bkt *Label_list[]; /* ptrs to the symbols on the left side */ extern int Label_count; /* num of symbols on left side */ /* extern char Cmd_buffer[]; /* buffer of commands for the current text block of .rel file */ extern struct csect *Cur_csect; /* ptr the the current csect */ extern int E_pass1; /* if nonzero on pass1, causes non-ignored error */ extern struct sym_bkt *Dot_bkt; /* ptr to symbol bucket for dot */ Got = 0; /* haven't read operand yet */ for(i=0;i<Label_count; i++) { /* For each symbol to be defined, */ sbp = Label_list[i]; /* pick up the ptr to it */ if (Label_list[i] == Dot_bkt) { /* Treat the ". = " statement specially */ if (Got == 0) { /* Pick up the operand if we haven't already */ if (Get_Operand(&Operand) == FALSE) { /* if any error, */ E_pass1 = E_OPERAND; break; } /* Cause an error in pass 1 */ Got++; } /* Make sure expression is in current csect, or is absolute */ if (Operand.sym_o && Operand.sym_o->csect_s != Cur_csect) { E_pass1 = E_OPERAND; break; } Dot = Operand.value_o; /* assign location counter */ } else { /* If it's not a .= statement, */ if ((Got++ == 0) && (Get_Operand(&Operand) == FALSE)) break; /* Evaluate the operand */ sbp->value_s = Operand.value_o; /* Load value of expression into symbol */ sbp->csect_s = Operand.sym_o? Operand.sym_o->csect_s:0; if (sbp->attr_s & S_LABEL) Prog_Error(E_EQUALS); else sbp->attr_s = Operand.sym_o ? (Operand.sym_o->attr_s&~(S_LABEL|S_PERM)): (S_DEC|S_DEF); } } Print_Line(P_NONE); return; } /* * .even handler */ Even() { if (Dot&1) { Dot++; Code[0] = 0; Put_Text(Code,1); } Print_Line(P_LC); } extern int Errors; /* count of errors in this pass */ if (Errors) Sys_Error("%d errors in descriptor file\n",Errors); Perm(); /* make all symbols permanent */ Start_Pass(); } /* Initialize per-pass variables */ Start_Pass() { extern int Errors,Warnings,Err_load,Line_no; esumacc/cc/as/ps1.c 444 0 12 15454 3470501540 7167 #include "mical.h" char *ps1 = "~|^`s.ps1.c R1.9 on 12/18/79"; /* * mical assembler-- .byte, .word, .long, .ascii, and .asciz handlers * */ /* Print_No zero-suppress and zero-pad flags */ #define ZS 0 #define ZP 1 /* Extend()'s flush flag */ #define NOFLUSH 0 #define FLUSH 1 /* initialized static variables for Extend() */ long Ext_buf[CODE_MAX]; /* the buffer for values */ char Ext_mark[CODE_MAX]; /* the buffer for corresponding Rel_mark */ int Ext_load = 0; /* num of values in Ext_buf */ char Extension = 0; /* 1 if first listing line printed already */ int Ext_nbytes = 0; /* set by the calling routine, number of bytes to print for each value */ /* ByteWord(Which): Which is 1 if a .BYTE was found by Pseudo(), and 2 if a .WORD was found, 4 is .LONG was found */ struct { char any_lf; /* master switch. If 0, no listing is done */ char bin_lf; /* binary code field of listing line */ char bex_lf; /* binary extensions (e.g. from .word) */ char md_lf; /* macro definitions */ char mc_lf; /* macro calls */ char me_lf; /* macro expansions */ char cnd_lf; /* unsatisfied conditional blocks */ char ld_lf; /* listing directives */ } Lflags ; /* ByteWord - Generate Constant Data */ ByteWord(Which) register int Which; { register int i; int Num; /* number of bytes/words to pick up */ extern char O_list, /* flag, 1 if listing requested */ Code[]; /* generated code used by Put_Rel */ extern int Err_code; int *WCode = (int *)&Code[0]; Ext_nbytes = Which==1?1:2; Num = Num_Operands(); for (i = 0; i < Num; i++) /* for each byte/word, */ { Get_Operand(&Operand); if (Operand.type_o != t_normal) { Operand.sym_o = 0; Operand.type_o = t_normal; Operand.value_o = 0; Prog_Error(E_OPERAND); } else { if (Operand.sym_o) Put_Rel(&Operand, Which==1?B:Which==2?W:L, Dot+i*Which); } if (Which == 4) { WCode[0] = Operand.value_o >> 16; WCode[1] = Operand.value_o; } else WCode[0] = Operand.value_o; if (Which == 1) Put_Text(WCode, Which); else Put_Words(WCode, Which); if (Pass == 2 && O_list) { if (Which == 4) { Extend(Operand.value_o >> 16, NOFLUSH); Extend(Operand.value_o & 0xFFFF, NOFLUSH); } else Extend(Operand.value_o,NOFLUSH); } } if (Pass == 1) Print_Line(P_NONE); /* copy line to temp */ else if (O_list) Extend(0L,FLUSH); /* list all of the values */ else if (Err_code) Print_Error(); /* tell him about the error */ BC = Num*Which; /* increment byte count */ } /* * Asciiz(Z): called from Pseudo() with Z=0 for .ASCII and Z=1 for .ASCIZ * * Format of statement: * .ASCII "<chars>" * where <chars> may include special escaped chars (see Grab_Char() ) */ Asciiz(Z) int Z; { register int C; /* the current character */ register int count; /* num of chars in string */ register char delim; /* string delimiter */ extern int Code_length; /* num of bytes of generated code */ extern FLAG O_list; /* listing flag */ extern int Err_code; /* error code */ Non_Blank(); /* first non-blank is delimiter */ delim = Line[Position]; if (Line_Delim(delim)){ /* no string, so nothing to do */ Print_Line(P_LC); return; } Position++; /* move up to first char */ Code_length = Ext_nbytes = 1; /* handling one-byte animals */ /* changed to allow | in the middle of user strings -- JEA 5/5/81 */ /* changed to allow \delimiter -- Per Bothner@Stanford 82/Oct/14 */ /* changed (C=Grab_Char())>0 to >=0 -- Bothner@Stanford 83/Dec/21 */ for(count=0; ( !Line_Delim(C = Line[Position]) || C == '|') && C != delim && (C = Grab_Char()) >= 0; count++) LoadChar(C); /* Handle the string proper */ if (C != delim) Prog_Error(E_STRING); if (Z && C>0) { LoadChar(0); count++; } /* do final zero if needed */ if (Pass == 1) Print_Line(P_NONE); else if (O_list) Extend(0L,FLUSH); /* flush the listing line */ else if (Err_code) Print_Error(); BC = count; /* and increment Dot */ return; } /* routine to load a char into the .rel file and list it */ LoadChar(C) register int C; { extern char O_list; /* 1 if listing wanted */ Code[0] = C; /* move char into code buffer, so */ Put_Text(Code,1); if (Pass == 2 && O_list) Extend ((long)C,NOFLUSH); } /* Extend(Value,Fflag): * lists the current line, and any extensions for binary code. * A buffer is kept of values to be listed in the code portion of the * listing line. When this buffer is full, the current line (or extension) is * printed out. * Fflag, the flush flag, is 1 when this buffer is to be flushed, and * the last listing line is to be printed. Fflag should be zero otherwise. */ Extend(Value,Fflag) long Value; int Fflag; { register int i; extern FILE *listout; /* file id of listing file */ extern int L_radix, /* listing radix, for Print_No() */ L_ndigits, /* also for Print_No() */ Line_no, /* current line number */ Err_code; /* current error code */ extern char Rel_mark, /* ' if operand value is relocatable */ E_warn; /* W if current error is warning */ extern FLAG Expanding; /* macro expansion flag */ if (Lflags.any_lf == false) return; /* if in .nlist mode, no listing at all */ if (Fflag || (Ext_load * Ext_nbytes) >= CODE_MAX) { /* If we need to flush the buffer, */ if (Extension == 0) { /* Check if this is the first listing line, */ fprintf(listout, "%4d%c ",Line_no,Expanding?'*':' '); /* and if so, give him line number and Dot */ Print_No((Dot>>24)&0177,L_radix,L_ndigits,ZP); Space_(1); Print_No(Dot,L_radix,2*L_ndigits,ZP); Space_(2); } else Space_(3*L_ndigits+11); /* if it's an extension, skip Line number and Dot listing fields */ if (Extension && (Lflags.bex_lf == false)) return; /* if binary extension disabled, skip it */ for (i=0; i < Ext_load; i++) { /* List the binary code */ Print_No(Ext_buf[i], L_radix, Ext_nbytes * L_ndigits, ZP); /* as words or bytes */ putc(Ext_mark[i], listout); if (Ext_nbytes == 2) putc(' ', listout); else if (Ext_nbytes == 4) fprintf(listout, " "); } for(i= Ext_load*Ext_nbytes; i < CODE_MAX; i++) Space_(L_ndigits+1); /* skip to end of code field */ Space_(2); /* skip to error field */ if (Err_code) Print_No((long)Err_code,10,2,ZS); /* and print error code, if any */ else Space_(2); putc(E_warn, listout); Space_(2); if (Extension == 0) { /* if this is the first line, */ Extension++; /* the next one's an extension */ fprintf(listout, "%s",Line); } /* List the source line */ else putc('\n', listout); /* if it's already an extension, just end the line */ Ext_load = 0; Err_code = 0; /* since we just printed it */ } if (Fflag == 0) /* if we're not flushing, load the value into buffer */ { Ext_buf[Ext_load] = Value; Ext_mark[Ext_load++] = Rel_mark; }; if (Fflag) { /* if this was our last call for the current source line, */ Extension = 0; /* reset the static variables */ Ext_nbytes = 0; } return; } miter */ extern int Code_length; /* num of bytes of generated code */ extern FLAG O_list; /* listing flag */ extern int Err_code; /* error code */ Non_Blank(); /* first non-blank is delimiter */ delim =sumacc/cc/as/ps2.c 444 0 12 15627 3470501540 7172 #include "mical.h" char *ps2 = "~|^`s.ps2.c R1.4 on 12/13/79"; /* * * Handlers for pseudo-ops-- * * .BLKB, .BLKW, .BLKL * .CSECT, .ASECT * .RADIX */ /* size of radix_tab */ #define RTSIZE 8 struct csect Csects[CSECT_MAX] = { ".text",0,0,0,R_ISPC|R_PURE, /* text csect */ ".data",0,0,0,0, /* data csect */ ".bss",0,0,0,0 /* uninitialized csect */ } ; int Csect_load = 4; /* Next available csect in Csects[] */ struct csect *Cur_csect = &(Csects[0]); /* ptr to current csect */ struct csect *Text_csect = &(Csects[0]); struct csect *Data_csect = &(Csects[1]); struct csect *Bss_csect = &(Csects[2]); extern char *Store_String(); extern struct sym_bkt *Lookup(); /* Blkbw(Which)-- .blkb, .blkw, .blkl handler * * Which is 1 for .blkb, 2 for .blkw, 4 for .blkl * Reads an operand specifying the number of bytes/words to reserve space * for, and moves the location counter past this block. */ Blkbw(Which) register int Which; { register int Num; extern int E_pass1; /* for errors in pass 1 */ long int fill = 0; register int i; if (Get_Operand(&Operand) && (Operand.sym_o == 0) && ((Num = Operand.value_o) >= 0)) BC = Num * Which; /* this many bytes */ else Prog_Error(E_pass1 = E_CONSTANT); for (i=0; i<Num; i++) /* have to output filler bytes */ Put_Text((char *)&fill, Which); Print_Line(P_LC); } /* * * Csect()-- .csect handler * * Format: .csect [<name>] [[,<attr>],<attr>] * <name> is any legal symbol name, <attr> is either EXT or ABS, for * external and absolute attributes. * if <name> is absent the default (unnamed) csect is entered. * */ Csect() { register struct csect *csp; register int i; register char S[STR_MAX]; FLAG Defining, /* when csect being entered for first time */ Warn; /* when he uses illegal attributes */ extern struct csect Csects[], /* collection of csects */ *Cur_csect; extern int Csect_load; /* next available csect in Csects[] */ Defining = Warn = FALSE; if (((i = Get_Token(S)) == 0) && (Line_Delim(Line[Position]) == false)) Prog_Error(E_SYMBOL); else { if (i == 0) csp = &Csects[0]; else { for (i=0; i< Csect_load; i++) if (seq(Csects[i].name_cs,S)) break; csp = &(Csects[i]); if (i == Csect_load) { /* Make a new csect */ Defining = TRUE; Csect_load++; csp->name_cs = Store_String(S); csp->len_cs = csp->id_cs = csp->attr_cs = csp->dot_cs = 0; } Non_Blank(); do { if (Line[Position] == ',') Position++; if (Get_Token(S) == 0) { if (Line_Delim(Line[Position]) == 0) Warn = TRUE; break; } Lower(S); if (seq(S,"abs")) if ((Defining == FALSE) && ((csp->attr_cs & R_ABS) == 0)) Warn = TRUE; /* redeclared attribute */ else csp->attr_cs |= R_ABS; else if (seq(S,"ext")) if ((Defining == FALSE) && (( csp->attr_cs & R_EXT) == 0)) Warn = TRUE; else csp->attr_cs |= R_EXT; else Warn = TRUE; Non_Blank(); } while (Line[Position] == ','); if (Warn) Prog_Warning(E_ATTRIBUTE); } New_Csect(csp); /* move to new csect */ } Print_Line(P_NONE); } /* New_Csect(csp) * Input: argument csp is a ptr to csect structure * Side effects: 1. "The current csect" is made to be *csp. * 2. A symbol with the same name as the new csect is created, with the value of zero in that csect * 3. The appropriate command for the .rel file is loaded on pass 2. * Called From: Csect() */ New_Csect(csp) register struct csect *csp; { register struct sym_bkt *sbp; /* for defining new symbol */ extern struct csect *Cur_csect; /* ptr to current csect */ extern struct sym_bkt *Last_symbol; /* used for local symbols */ extern struct sym_bkt *Dot_bkt; /* sym_bkt for location counter */ Cur_csect = csp; Dot = csp->dot_cs; Dot_bkt->csect_s = Cur_csect; /* update dot's csect. Dot_bkt->value_s will be updated in the main loop */ sbp = Lookup(csp->name_cs); sbp->attr_s |= S_DEC | S_DEF | S_LOCAL; /* local attribute so it won't be listed in symbol table */ sbp->csect_s = Cur_csect; sbp->value_s = 0; Last_symbol = sbp; } /* * Radix()-- .radix handler * * Format: .radix {in,out}, <radixname> * "in" refers to the default radix for numbers in source statements * "out" refers to the radix of the LC and Code fields on the output listing. * <radixname> is one of the following strings: * '2','8','10','16','binary','octal','decimal', or 'hex'. */ struct rt_entry { char *name_r; /* name of radix */ int value_r, cpb_r; /* value and chars per byte */ } radix_tab[RTSIZE] = {"octal", 8, 3, "8", 8, 3, "decimal", 10, 3, "10", 10, 3, "hex", 16, 2, "16", 16, 2, "binary", 2, 8, "2", 2, 8 }; Radix() { register int i; register char S[STR_MAX]; register int rad; FLAG Got,In,Error; extern int In_radix,L_ndigits,L_radix; if (Get_Token(S)== 0) Error++; else { Lower(S); Got = FALSE; In = FALSE; if (seq(S,"out")) In = FALSE; else if (seq(S,"in")) In = TRUE; else Got = TRUE; /* got the radix */ Error = 0; Non_Blank(); if (Line[Position] == ',') Position++; if (Got || Get_Token(S)) { /* pick up radixname, if we don't have it yet); */ for (i=0; i<RTSIZE; i++) if (seq(radix_tab[i].name_r,S)) { rad = radix_tab[i].value_r; if (In) { In_radix = rad; break; } else { L_radix = rad; L_ndigits = radix_tab[i].cpb_r; break; } } if (i>=RTSIZE) Error++; } } if (Error) Prog_Error(E_OPERAND); Print_Line(P_NONE); return; } /* Insrt()- .insrt handler * source line is: .insrt /<filename>/ * * where / means any character and <filename> is a valid UNIX filename. * Side Effects: opens filename for reading and pushes an io-buffer for * it onto Source_stack. This causes input to the assembler to come from the * indicated file. Upon eof, input resumes from the previous input file. * .insrt's can be nested to a depth of SSTACK_MAX files. */ Insrt() { register char C; extern int E_pass1; char filename[STR_MAX], delim; FILE *iop; FLAG eflag = false; int i; if (Pass == 2) { Print_Line(P_NONE); return; } /* Pick up name of file */ Non_Blank(); /* locate delimiter character of string containing filename */ delim = Line[Position]; if (Line_Delim(delim)) eflag = true; /* no filename specified */ else { Position++; /* move past delimiter */ for (i=0; (C=Grab_Char()) > 0 && C != delim && i < STR_MAX-1 && !Line_Delim(C); i++) filename[i] = C; /* pick up string */ if (C != delim) Prog_Error(E_pass1 = E_STRING); /* invalid string representation */ else { filename[i] = 0; /* end of filename */ Position++; /* move past closing delimiter */ if ((iop = fopen(filename,"r")) !=NULL) Push_Source(iop); else eflag = true; } } if (eflag) Prog_Error(E_pass1 = E_FILE); Print_Line(P_LC); return; } Page() { extern int Line_no; extern FILE *listout; extern int O_list; Line_no--; if (Pass == 1) { Print_Line(P_NONE); return; } if (O_list) fprintf(listout, "\014\n"); } while (Line[Position] == ','); if (Warn) Prog_Warning(E_ATTRIBUTE); } New_Csect(csp); /* move tsumacc/cc/as/ps3.c 444 0 12 11610 3470501541 7160 # #include "mical.h" char *ps3 = "~|^`s.ps3.c R1.6 on 5/19/80"; extern struct sym_bkt *Lookup(); /* Globl() -- .GLOBL directive handler Format of statement: .GLOBL <sym> [<sym>]... This directive declares global symbols, which are symbols that are declared (and hence may appear in expressions) but are not defined (have a value). */ Globl() { char S[STR_MAX]; struct sym_bkt *sbp; Non_Blank(); if (Pass ==1) do { if (Line[Position] == ',') Position++; Non_Blank(); if (Get_Token(S) == 0) { if (! Line_Delim(Line[Position])) Prog_Error(E_SYMBOL); break; } sbp = Lookup(S); /* get symbol bucket */ sbp->csect_s = 0; /* don't know which */ sbp->attr_s |= S_DEC | S_EXT; /* declared and external */ Non_Blank(); /* any more symbols to define*/ } while(! Line_Delim(Line[Position])) ; Print_Line(P_NONE); return; } /* Comm - .comm directive handler Format of statement: .COMM <sym>,<length> Comm symbols are sort of like globals but have a length property. */ Comm() { char S[STR_MAX]; struct oper op; struct sym_bkt *sbp; Non_Blank(); if (Pass ==1) do { if (Line[Position] == ',') Position++; Non_Blank(); if (Get_Token(S) == 0) { if (! Line_Delim(Line[Position])) Prog_Error(E_SYMBOL); break; } sbp = Lookup(S); sbp->csect_s = 0; /* make it undefined */ sbp->attr_s |= S_DEC | S_EXT | S_COMM; Non_Blank(); if (Line[Position++] != ',') Prog_Error(E_OPERAND); Evaluate(&op); if (op.type_o == t_reg) Prog_Error(E_REG); sbp->value_s = op.value_o; Non_Blank(); } while(! Line_Delim(Line[Position])) ; Print_Line(P_NONE); return; } /* Print Symbol Table */ Pr_Sym_Tab() { register int attr; register struct sym_bkt *sbp; char Name[STR_MAX]; /* <title>.sym, to temporarily hold symbol table */ int hash_index; int Sta[3]; /* Status table for spawn routine */ extern char Title[]; extern FLAG O_symtab; extern int L_ndigits, L_radix; extern struct sym_bkt *sym_hash_tab[]; FILE *symout; if (O_symtab == false) return; /* O_symtab flag must be set */ /* Open a file to hold the symbol table listing */ Concat(Name,Title,".sym"); /* make the name of the file */ if ((symout = fopen(Name, "w")) == NULL) { printf("Can't open symbol file: %s\n",Name); return; } /* (output of printf will now go to the file just created) */ /* walk down symbol table, creating a line for each symbol to be listed */ for (hash_index = 0; hash_index < HASH_MAX; hash_index++) for (sbp = sym_hash_tab[hash_index]; sbp; sbp = sbp->next_s) { attr = sbp->attr_s; if (attr & (S_REG | S_MACRO | S_LOCAL | S_PERM)) continue; /* skip register, macro, local and permanent variables */ fprintf(symout, "%-10s ",sbp->name_s); /* print symbol name */ fprintf(symout,"%O", sbp->value_s); fprintf(symout," %c%c", attr&S_DEF? ' ' : 'U', /* print "Undefined" and "External" flags */ attr&S_EXT? 'E' : ' '); fprintf(symout, "\n"); } /* create a sub-process to sort the symbol table listing */ fclose(symout); #ifndef Stanford spawnl(Sta,"/bin/sort","sort",Name,"-o",Name,0); /* spawn a process to execute a sort command */ #else Stanford spawnl(Sta,"/usr/bin/sort","sort",Name,"-o",Name,0); /* spawn a process to execute a sort command */ #endif Stanford wait(0); } /* EPrintf -- hands .printf and .errorf statements The single argument is a character which is 'P' for a .printf statement, and 'E' for .errorf. */ EPrintf(EP) char EP; { extern FILE *listout; /* listing file id */ int Arg[10]; /* numerical arguments to printf statement */ int i; char C, /* Current Character */ Format_String[LINE_MAX]; /* ptr to start of format string */ if (Pass == 1) { /* ignore during pass1 */ Print_Line(P_NONE); return; } Non_Blank(); /* Find start of format string in MICAL statement */ if (Line[Position++] != '\"') goto Error_return; for (i=0; i < LINE_MAX; i++) { /* This loop exits when 1. The end of the format string is encountered ("); or 2. A premature end of line is encountered. */ /* Grab_Char grabs the next char on the source line, doing escape processing ( see eval.c) */ if (Line[Position] == '\n' || Line[Position] == '\014' || (C = Grab_Char()) == -1) /* get next char */ goto Error_return; if (C == '\"') { /* proper end of string */ Format_String[i] = 0; break; } else Format_String[i] = C; /* otherwise load into format string */ } for (i=0; i<10 && ! Line_Delim(Line[Position]); i++) { /* pickup up to 10 numeric arguments */ Non_Blank(); if (Line[Position] == ',') Position++; Get_Operand(&Operand); Arg[i] = Operand.value_o; } if (EP == 'E') Prog_Error(22); /* Cause error if .error statement */ fprintf((EP == 'T')?stdout:listout, Format_String, Arg[0],Arg[1],Arg[2],Arg[3],Arg[4],Arg[5],Arg[6],Arg[7],Arg[8],Arg[9]); Print_Line(P_NONE); return; Error_return: Prog_Error(31); /* Invalid string error */ Print_Line(P_NONE); return; } nt value_r, cpb_r; /* value and chars per byte */ } radix_tab[RTSIZE] = {"octal", 8, 3, "8", 8, 3, "decimal", sumacc/cc/as/random.c 444 0 12 15622 3470501541 7742 #include "mical.h" char *random = "~|^`s.random.c R1.3 on 11/8/79"; /* Various useful subroutines */ /* Get_Token(S) reads the next Token, or symbol, from the input line, starting at the current Position. It returns the number of chars in the token that was found. */ Get_Token(S) register char S[]; { register char C; register int i; extern char O_debug; for (;((C=Line[Position]) == ' ') || (C == '\t');Position++); for(i=0; (( (C = Line[Position]) >='0' && C <= '9') || (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') || (C == '_') || (C == '.') || (C == '$')); (Position++,i++) ) { if (i >= STR_MAX) { Prog_Error(E_SYMLEN); i--; break; } S[i] = C; } S[i] = 0; return(i); } /* * * Parsing Routines: Non_Blank(), Skip_Comma(), Line_Delim(), Enclosed() * */ /* Move Position to the next non-blank character in the input Line */ Non_Blank(){ register char C; for (;((C=Line[Position]) == ' ') || (C == '\t');Position++); } /* Move Position past any comma and to the next non-blank */ Skip_Comma() { Non_Blank(); if (Line[Position] == ',') Position++; Non_Blank(); } /* List of possible line delimiters */ char Line_end_tab[] = { '\n', '|', '\014', 0 } ; /* Line_Delim(c) returns true if c marks the end of a statement */ Line_Delim(C) register char C; { register char *cp; for(cp= Line_end_tab; *cp; cp++) if (C == *cp) return(TRUE); return(FALSE); } /* * Enclosed(left, right, S) * Extracts char strings enclosed (possibly nested) within delimiter characters * Current line position must be at left delimiter (i.e. Line[Position] == left;) . * "left" and "right", and places result in string S. * Returns number of chars in S. */ Enclosed(left,right,S) char left,right,S[]; { register char C; register int i; int level; if ((C=Line[Position]) != left) return(0); for (i=0,level=1; i<STR_MAX && ! Line_Delim(C); i++) { C = S[i] = Line[++Position]; if ((C == right) && (--level) <= 0) { Position++; S[i] = 0; return(i); } else if (C == left) level++; } return(0); } /* * Get_Encl_String(S) -- Get Enclosed String * * Extract char string from current line position of the form: * <string> * (string) * "string" * ^%string% , % any character. * String is placed in S. * Returns # chars in S. */ Get_String(S) register char S[]; { register char C; register int i; Non_Blank(); C = Line[Position]; if (C == '(') return(Enclosed('(',')',S)); if (C == '<') return(Enclosed('<','>',S)); if (C == '\"') return(Enclosed(C,C,S)); if (C == '^') { if (Line_Delim( C = Line[++Position])) { Prog_Error(E_STRING); return(0); } return(Enclosed(C,C,S)); } /* normal, non-enclosed string. Pick up all contiguous non-blank chars */ for (i=0; C!=' ' && C!='\t' && !Line_Delim(C) ; i++) { *S++ = C; /* load char into string */ C = Line[++Position]; } *S = 0; return(i); } /* * * String Hacking Routines: * append, Concat, Copy, seq, member, lastc, Lower * */ /* Concatenates string a and b in that order and stores result in c. Returns ptr to c */ char *Concat(c,a,b) char *a,*c,*b; { register char *cp1,*cp2; cp1 = c; for (cp2 = a; *cp1 = *cp2; cp1++,cp2++) ; for (cp2 = b; *cp1 = *cp2; cp1++,cp2++) ; return(c); } /* appends string S1 to string S2 */ char *append(S1,S2) char *S1,*S2; { register int i,j; for (i=0; S2[i]; i++); /* locate end of S2 */ for (j=0; S1[j] && i < STR_MAX-1;i++,j++) /* append S1 to S2 */ S2[i] = S1[j]; S2[i] = 0; return(S2); } /* returns length of string */ Length(S) char *S; { register int i; for (i=0; S[i]; i++); return(i); } /* Copy string S1 to S2 */ Copy(S1,S2) char *S1,*S2; { *S2 = 0; /* empty S2 */ append(S1,S2); /* copy S1 to S2 */ } /* Hashing routine for Symbol and Instruction hash tables */ Hash(S) register char *S; { register int A,i; for(A=0,i=0;S[i];i++)A = A + (S[i]<<(i&01?8:1)); return(((A*A)>>10)&037); } /* string comparison function (String EQuals) */ seq(s1,s2) register char *s1,*s2; { while (*s1 == *s2) if (*s1 == 0) return(TRUE); else { s1++; s2++; } return(FALSE); } /* Converts all upper case alphabetic chars in string S to lower case. Special chars are unaffected */ Lower(S) register char *S; { for(;*S;S++) if (*S >= 'A' && *S <= 'Z') *S |= 040; } /* member(C,S) return true if character C is in string S, false otherwise */ member(C,S) register char C,*S; { for (;*S;S++) if (C == *S) return(TRUE); return(FALSE); } /* lastc(S) returns ptr last char in string S */ char *lastc(S) register char *S; { while (*S) S++; return (--S); } /* Read_Line() is called from the main loop to read the next source line. It calls Start_Line, which initializes all "per_line" external variables. It returns TRUE if it successfully read a line, and aborts (via Sys_Error if it could not. */ FILE *Temp_file; /* Temporary to hold source between pass 1 and 2 */ int Line_no = 0; /* Current line number */ Read_Line() { register int C,i; char D; FILE *In; extern char O_debug; extern FILE *Source_stack[]; /* Source stack */ extern int Ss_top; /* Stack ptr for above */ extern int Top_of_M_stack; extern FLAG Expanding; /* macro expansion flag */ if ((D = O_debug)>4) printf("Entering Read_Line\n"); Start_Line(); /* Initialize externla variables */ if (Top_of_M_stack >= 0) /* Check if expanding macro */ if (Read_Macro_Line()) return(true); In = Source_stack[Ss_top]; while ((C = getc(In)) == EOF) { fclose(Source_stack[Ss_top]); if (Pass == 0) Ehead(); if ((--Ss_top) < 0) { Prog_Error(E_END); Concat(Line,".end\n",""); Line_no++; return(true); } In = Source_stack[Ss_top]; } /* In temporary file, format of every line is: <error byte> <'*' or ' '> <source line> */ if (In == Temp_file) { if(C) Prog_Error(C); /* get pass1 errors */ C = getc(In); /* get '*' or ' ' */ if (C == '*') Expanding = true; else Expanding = false; C = getc(In); } /* Finally, read the line in */ for(i=0;(((Line[i]=C) != '\n') && (C!='\014') && (i<LINE_MAX)); i++) if ((C=getc(In))==EOF) break; /* stop on eof or error */ Line[i+1] = 0; /* make the end of string */ if (i>=LINE_MAX) /* If didn't get whole line, */ { Line[i] = '\n'; /* put an artificial eol */ Prog_Warning(E_LINELONG); /* and complain */ } Line_no++; if(D > 1) printf("%d: %s",Line_no,Line); return(TRUE); } int Label_count; /* Number of labels on the current line */ int Err_code,E_pass1; /* Error code for pass 1&2, and just for pass 1 */ char E_warn, /* -'W' if current error is a warning */ Rel_mark, /* =''' if code generated is relative */ Rel_flag; /* =1 iff fancy relocation required */ /* Start_Line() resets variables which change from line to line */ Start_Line(){ register int i; extern int Code_length; Position = 0; Label_count = 0; Err_code = 0; E_pass1 = 0; E_warn = ' '; Rel_mark = ' '; Rel_flag = 0; BC = 0; Code_length = 0; Operand.type_o = Operand.value_o = 0; Operand.sym_o = NULL; Operand.reg_o = 0; } Concat, Copy, seq, member, lastc, Lower * */ /* Concatenates string a and b in that order and stores resultsumacc/cc/as/rel.c 444 0 12 14052 3470501541 7240 #include "mical.h" #ifndef Stanford #include <a.out.h> #else Stanford #include "b.out.h" #endif Stanford /* Handle output file processing for b.out files */ /* V. Pratt Dec 12 1981 incorporated jks fix to Put_Words (cc[1] fix) */ FILE *tout; /* text portion of output file */ FILE *dout; /* data portion of output file */ FILE *rtout; /* text relocation commands */ FILE *rdout; /* data relocation commands */ long rtsize; /* size of text relocation area */ long rdsize; /* size of data relocation area */ char rtname[STR_MAX]; /* name of file for text relocation commands */ char rdname[STR_MAX]; /* name of file for data relocation commands */ #ifndef Stanford struct exec filhdr; /* header for b.out files, contains sizes */ #else Stanford struct bhdr filhdr; /* header for b.out files, contains sizes */ #endif Stanford extern struct csect *Bss_csect, *Data_csect, *Text_csect, *Cur_csect; /* Initialize files for output and write out the header */ Rel_Header() { long Sym_Write(); extern char *Rel_name; extern char EntryFlag, Title[]; extern struct sym_bkt Entry_point; if ((tout = fopen(&Rel_name, "w")) == NULL || (dout = fopen(&Rel_name, "a")) == NULL) Sys_Error("open on output file %s failed", &Rel_name); Concat(rtname, Title, ".rtmpr"); if ((rtout = fopen(rtname, "w")) == NULL) Sys_Error("open on output file %s failed", rtname); Concat(rdname, Title, ".dtmpr"); if ((rdout = fopen(rdname, "w")) == NULL) Sys_Error("open on output file %s failed", rdname); filhdr.fmagic = FMAGIC; filhdr.tsize = tsize; filhdr.dsize = dsize; filhdr.bsize = bsize; fseek(tout, (long)(SYMPOS), 0); filhdr.ssize = Sym_Write(tout); filhdr.rtsize = rtsize; filhdr.rdsize = rdsize; filhdr.entry = EntryFlag? Entry_point.value_s: 0; fseek(tout, 0L, 0); fwrite(&filhdr, sizeof(filhdr), 1, tout); fseek(tout, (long)(TEXTPOS), 0); /* seek to start of text */ fseek(dout, (long)(DATAPOS), 0); rtsize = 0; rdsize = 0; } /* * Fix_Rel - Fix up the object file * For .b files, we have to * 1) append the relocation segments * 2) fix up the rtsize and rdsize in the header * 3) delete the temporary file for relocation commands */ Fix_Rel() { long ortsize; long i; register FILE *fint, *find, *fout; ortsize = filhdr.rtsize; filhdr.rtsize = rtsize; filhdr.rdsize = rdsize; fclose(rtout); fclose(rdout); if ((fint = fopen(rtname, "r")) == NULL) Sys_Error("cannot reopen text relocation file %s", rtname); if ((find = fopen(rdname, "r")) == NULL) Sys_Error("cannot reopen data relocation file %s", rdname); fout = tout; /* first write text relocation commands */ fseek(fout, (long)(RTEXTPOS), 0); for (i=0; i<rtsize; i++) putc(getc(fint), fout); for (i=0; i<rdsize; i++) putc(getc(find), fout); /* now re-write header */ fseek(fout, 0, 0); fwrite(&filhdr, sizeof(filhdr), 1, fout); fclose(fint); unlink(rtname); fclose(find); unlink(rdname); } /* rel_val - Puts value of operand into next bytes of Code * updating Code_length. Put_Rel is called to handle possible relocation. * If size=L a longword is stored, otherwise a word is stored */ rel_val(opnd,size) register struct oper *opnd; { register int i; register struct sym_bkt *sp; long val; extern int *WCode; /* buffer for code in ins.c */ extern char Code_length; /* number of bytes in WCode */ char *CCode; /* char version of this */ i = Code_length>>1; /* get index into WCode */ if (sp = opnd->sym_o) Put_Rel(opnd, size, Dot + Code_length); val = opnd->value_o; switch(size) { case L: WCode[i++] = val>>16; Code_length += 2; case W: WCode[i] = val; Code_length += 2; break; case B: CCode = (char *)WCode; CCode[Code_length++] = val; } } /* Version of Put_Text which puts whole words, thus enforcing the mapping * of bytes to words. */ Put_Words(code,nbytes) register char *code; { register char *cc, ch; register int i,j; char tcode[100]; #ifdef BOOTSTRAP cc = tcode; for (j=i=0; i<nbytes;) /*skips over bogus bytes on a vax*/ {tcode[i++] = code[j++]; tcode[i++]=code[j++];j+=2;} i = nbytes>>1; if (nbytes & 1) Sys_Error("Put_Words given odd nbytes=%d\n",nbytes); while (i--) { ch = *cc; *cc = *(char*)((int)cc+1); *++cc = ch; cc++; } Put_Text(tcode,nbytes); #else cc = tcode; for (j=i=0; i<nbytes;) /*skips over bogus bytes on a 68000*/ {j+=2; tcode[i++] = code[j++];tcode[i++]=code[j++];} i = nbytes>>1; if (nbytes & 1) Sys_Error("Put_Words given odd nbytes=%d\n",nbytes); Put_Text(tcode,nbytes); #endif } /* Put_Text - Write out text to proper portion of file */ Put_Text(code,length) register char *code; { if (Pass != 2) return; if (Cur_csect == Text_csect) fwrite(code, length, 1, tout); else if (Cur_csect == Data_csect) fwrite(code, length, 1, dout); else return; /* ignore if bss segment */ } /* set up relocation word for operand: * opnd pointer to operand structure * size 0 = byte, 1 = word, 2 = long/address * offset offset into WCode & WReloc array */ Put_Rel(opnd,size,offset) struct oper *opnd; int size; long offset; { struct reloc r; if (opnd->sym_o == 0) return; /* no relocation */ if (Cur_csect == Text_csect) rtsize += rel_cmd(&r, opnd, size, offset, rtout); else if (Cur_csect == Data_csect) rdsize += rel_cmd(&r, opnd, size, offset - tsize, rdout); else return; /* just ignore if bss segment */ } /* rel_cmd - Generate a relocation command and output */ rel_cmd(rp, opnd, size, offset, file) register struct reloc *rp; struct oper *opnd; int size; long offset; FILE *file; { int csid; /* reloc csect identifier */ register struct csect *csp; /* pointer to csect of sym */ register struct sym_bkt *sp; /* pointer to symbol */ sp = opnd->sym_o; csp = sp->csect_s; if (Pass == 2) { rp->rsymbol = 0; if (!(sp->attr_s & S_DEF) && (sp->attr_s & S_EXT)) { rp->rsegment = REXT; rp->rsymbol = sp->id_s; } else if (csp == Text_csect) rp->rsegment = RTEXT; else if (csp == Data_csect) rp->rsegment = RDATA; else if (csp == Bss_csect) rp->rsegment = RBSS; else Prog_Error(E_RELOCATE); rp->rpos = offset; rp->rsize = size; rp->rdisp = 0; fwrite(rp, sizeof *rp, 1, file); } return(sizeof *rp); } rdsize in the header * 3) delete the temporary file for relocation commands */ Fix_Rel() { long ortsize; long i; register FILE *fint, *find, *fout; ortsize = filhdr.rtsize; filhdr.rtsize = rtsize; filhdr.rdsize = rdsize; fclose(rtout); fclose(rdout); if ((fint = fopen(rtname, "r")) == NULL) Sys_Error("cannot reopen text relocation file %s", rtname); if ((find = fopen(rdname, "r")) == NULL) Sys_Error("cannot reopen data relocation file %s", rdname); sumacc/cc/as/sdi.c 444 0 12 13174 3470501541 7241 #include "mical.h" static char *sdi = "~|^`s.sdi.c R1.7 on 6/27/80"; /* * module to handle span-dependent instructions, e.g. jbr * see CACM Vol 21 No 4 April 1978 for a description of the * algorithm for resolving sdi's between the 1st and 2nd pass */ struct sdi { /* information for span dependent instructions (sdi's) */ struct sdi *sdi_next; /* next sdi in list */ struct csect *sdi_csect; /* csect of the sdi */ long int sdi_loc; /* location of the sdi */ struct sym_bkt *sdi_sym; /* symbol part of the sdi address */ long int sdi_off; /* offset part of the sdi address */ int sdi_gleng; /* length of the most general form */ int sdi_leng; /* actual length of the sdi */ long int sdi_span; /* span of the sdi */ long int sdi_base; /* origin of the span of the sdi */ struct blist *sdi_bounds; /* length & bounds info for forms of sdi */ } *sdi_list = 0; /* linked list of sdi's descriptors */ struct blist { /* length and bounds information for various forms of sdi's */ struct blist *b_next; /* next element in list */ int b_length; /* length of this form of the sdi */ long int b_lbound; /* lower and upper bound on the span */ long int b_ubound; /* for this form of the sdi */ }; /* * routine to create a sdi descriptor and insert it into the list */ makesdi(op, gleng, base, bounds) struct oper *op; /* the operand of the sdi */ int gleng; /* the length of the most general form of the sdi */ long int base; /* origin of the the initial span of the sdi, to be */ /* corrected between pass1 and pass2 by subtracting */ /* from the value of the symbol of the operand */ /* i.e. 0 for resolving short absolute address modes */ /* Dot[+increment] for PC relative addresses */ struct blist *bounds; /* list of lengths & bounds for the sdi */ { register struct sdi *s, **p; extern struct csect *Cur_csect; extern char *malloc(); if (op->flags_o&O_COMPLEX) /* not a simple address */ return; if ((s = (struct sdi *)malloc(sizeof *s)) == (struct sdi *)-1) Sys_Error("sdi storage exceeded\n"); s->sdi_loc = Dot; s->sdi_csect = Cur_csect; s->sdi_sym = op->sym_o; s->sdi_off = op->value_o; s->sdi_gleng = gleng; s->sdi_base = base; s->sdi_span = - base; s->sdi_bounds = bounds; s->sdi_leng = bounds->b_length; /* shortest length */ for (p = &sdi_list; *p; p = &(*p)->sdi_next) if (s->sdi_loc < (*p)->sdi_loc) break; s->sdi_next = *p; *p = s; return(s->sdi_leng); /* return the current length */ } /* * insert a new blist element into a blist * The blist is sorted by increasing b_length */ struct blist *sdi_bound(leng, lbound, ubound, next) int leng; /* length of this form of the sdi */ long int lbound; /* lower bound of span */ long int ubound; /* upper bound */ struct blist *next; /* target blist */ { register struct blist *b, **p; if ((b = (struct blist *)malloc(sizeof *b)) == (struct blist *)-1) Sys_Error("sdi bound list storage exceeded\n"); b->b_length = leng; b->b_lbound = lbound; b->b_ubound = ubound; for (p = &next; *p; p = &(*p)->b_next) if (leng <= (*p)->b_length) break; b->b_next = *p; *p = b; return(*p); } /* * resolve sdi's between pass1 and pass2 * basic algorithm is to repeatedly look for sdi that must use the * long form, and update the span of other sdi's. * When this terminates, all remaining sdi's can use the short form */ sdi_resolve() { register struct sdi *s; register struct sym_bkt *p; register int t; int changed; for (s = sdi_list; s; s = s->sdi_next) { p = s->sdi_sym; if (s->sdi_csect == p->csect_s && (p->attr_s & S_DEF)) s->sdi_span += s->sdi_sym->value_s; } do { changed = 0; for (s = sdi_list; s; s = s->sdi_next) { if ((t = sdi_len(s) - s->sdi_leng) > 0) { longsdi(s, t); changed = 1; } else if (t < 0) Sys_Error("Pathological sdi\n"); } } while (changed); } /* * update sdi list assuming the specified sdi must be long */ longsdi(s, delta) struct sdi *s; register int delta; { register struct sdi *t; long loc; s->sdi_leng += delta; /* update the length of this sdi */ /* get the real location of the sdi */ loc = s->sdi_loc + sdi_inc(s->sdi_csect, s->sdi_loc); for (t = sdi_list; t; t = t->sdi_next) if (t != s && s->sdi_csect == t->sdi_sym->csect_s) { if (t->sdi_span < 0 && t->sdi_span+t->sdi_base <= loc && loc < t->sdi_base) t->sdi_span -= delta; else if (t->sdi_span >= 0 && t->sdi_base <= loc && loc < t->sdi_span+t->sdi_base) t->sdi_span += delta; if (t->sdi_base > loc) t->sdi_base += delta; } } /* * compute the length of the specified sdi by searching the bounds list */ sdi_len(s) register struct sdi *s; { register struct blist *b; if (!(s->sdi_sym->attr_s & S_DEF) || s->sdi_csect != s->sdi_sym->csect_s) return(s->sdi_gleng); for (b = s->sdi_bounds; b; b = b->b_next) if (b->b_lbound <= s->sdi_span && s->sdi_span <= b->b_ubound) return(b->b_length); return(s->sdi_gleng); } /* * return the total number of extra bytes due to long sdi's before * the specified offset in the specified csect */ sdi_inc(csect, offset) register struct csect *csect; long int offset; { register struct sdi *s; register int total; for (s = sdi_list, total = 0; s; s = s->sdi_next) { if (csect == s->sdi_csect) { if (offset <= s->sdi_loc) break; total += s->sdi_leng - s->sdi_bounds->b_length; } } return(total); } /* * release all sdi descriptors */ sdi_free() { register struct sdi *s, *t; for (s = sdi_list; s; s = t) { t = s->sdi_next; b_free(s->sdi_bounds); free(s); } sdi_list = (struct sdi *)0; } /* * release a bounds list */ b_free(p) register struct blist *p; { register struct blist *q; while(p) { q = p->b_next; free(p); p = q; } } a_csect) fwrite(code, length, 1, dout); else return; /* ignore if bss segment */ } /* set up relocation word for operand: * opnd pointer to operand structure * size 0 = byte, 1 = word, 2 = long/address * offset offset into WCode & WReloc array */ Put_Rel(opnd,size,offset) struct oper *opnd; int size; long offset; { struct reloc r; if (opnd->sym_o == 0) return; /* no relocsumacc/cc/as/spawn.c 444 0 12 3577 3470501541 7600 /* * Utility Subroutines for "Simple" Creation of Processes * * Calling sequence is similar to that for "execl" and "execv", * with exception of extra first argument, which is a pointer * to an int[3] array. On return, the array will contain the * process number [0], the fileID of a pipe coming from the * spawned process [1], and the fileID of a pipe going to the * spawned process [2]; A zero returned code means success, a * negative code means failure. All open files are preserved * by this call for the parent process, although the child will * only have fileID's for its standard input, output, and error * files. * * Written by j. pershing - all rights reversed * * Modifications: * 08/11/76 j. pershing * Usage of registers added. * 08/20/76 j. pershing * Usage of registers removed due to c-compiler bug. * 08/18/77 T. Eliot * Added access call, exit call after exec, so if bad arguments are given * to us we don't bomb quite so badly. */ extern int errno; spawnl(Ptr, Name, Etc) int Ptr[3]; char *Name, *Etc; { return(spawnv(Ptr, Name, &Etc)); } spawnv(Ptr, Name, Vec) int Ptr[3]; char *Name, **Vec; { register int Status, Old0, Old1; int Temp[3]; Old0 = dup(0); Old1 = dup(1); if (0 <= Old0 && Old0 <= 1) while((Old0 = dup(Old0)) <= 1); if (0 <= Old1 && Old1 <= 1) while((Old1 = dup(Old1)) <= 1); close(0); close(1); if ((Status = pipe(&Temp[1])) < 0) goto Err; Ptr[1] = dup(Temp[1]); close(0); if ((Status = pipe(&Temp[1])) < 0) goto Err; Ptr[2] = Temp[2]; if ((Status = access(Name,1))) goto Err; if ((Status = fork()) == -1) goto Err; if ((Ptr[0] = Status) == 0) { for (Status = 3; Status < 20; close(Status++)); (execv(Name, Vec)); exit(errno); /* Performed only if execv fails */ } Status = 0; Err: close(0); close(1); open("/dev/null", 0); dup(Old1); close(Old1); close(0); dup(Old0); close(Old0); return(Status); } ter int delta; { register struct sdi *t; long loc; s->sdi_leng += delta; /* update the length of this sdi */ /* get the realsumacc/cc/as/sym.c 444 0 12 25145 3470501541 7273 #include "mical.h" #ifndef Stanford #include <a.out.h> #else Stanford #include "b.out.h" #endif Stanford /* Modified by V. Pratt 7/31/81 to include symbol length in table */ #define NLABELS_MAX 10 /* Allocation increments for symbol buckets and character blocks */ #define SYM_INCR 200 #define CBLOCK_INCR 512 struct sym_bkt *sym_hash_tab[HASH_MAX]; /* Symbol hash table. */ struct sym_bkt sym_heap[SYM_INCR]; /* initial heap of sym bkts */ struct sym_bkt *sym_free; /* head of free list */ int Sym_heap_count = 1; /* number heaps allocated */ char Cblock[CBLOCK_INCR]; /* used to store texts */ char *Ccblock = Cblock; /* ptr to "current" cblock */ int Cb_nextc = 0; /* next available char */ int Cb_count = 1; /* number blocks allocated */ struct sym_bkt *Last_symbol; /* ptr to last defined symbol*/ struct csect *Data_csect, *Text_csect, *Bss_csect; /* * Lookup(S) * * Input: char string S * Output: returns pointer to symbol bucket whose name is S * Purpose: To place a symbol in the symbol table. * Method: The symbol table is a hash table, where each entry * is a linearly linked list of symbol buckets. * Local symbols are implemented by just replacing the * '$' at the end of a local symbol with the name of the last * defined label or csect. * Side Effects: If the symbol S is not on the symbol table, an * entry is made for it. */ struct sym_bkt *Lookup(S) register char *S; { register struct sym_bkt *sbp; /* general purpose ptr */ register int Save; /* save subscript in sym_hash_tab */ char local[STR_MAX]; /* buffer for generated local strings*/ char *cp; extern char O_debug; char *Store_String(),*lastc(); struct sym_bkt *get_sym_bkt(); if (S == 0) Sys_Error("Lookup of null symbol"); if (strcmp(S, " ") == 0) Sys_Error("Bad Symbol"); if (O_debug >= 9) printf("\n Lookup: S=%s, ",S); /* Gen local symbol by replacing final '$' with name of last defined symbol */ if (*(cp=lastc(S)) == '$') { *cp = 0; Concat(local,S,Last_symbol->name_s); S = local; } /* pretend we were called with the local symbol itself */ /* if the symbol is already in here, return a ptr to it */ for (sbp=sym_hash_tab[Save=Hash(S)]; sbp; sbp = sbp->next_s) if (seq(sbp->name_s,S)){ if (O_debug >= 9) printf("found\n"); return(sbp); } /* Since it's not, make a bucket for it, and put the bucket in the symbol table */ sbp = get_sym_bkt(); /* get the bucket */ sbp->name_s = Store_String(S); /* Store it's name */ sbp->value_s = NULL; sbp->id_s = NULL; sbp->csect_s = NULL; sbp->attr_s = NULL; sbp->next_s = sym_hash_tab[Save]; /* and insert on top of list */ return(sym_hash_tab[Save] = sbp); } /* get_sym_bkt(): Routine to grab a new symbol bucket off of the free list, and allocate space for a new free list if necessary */ struct sym_bkt *get_sym_bkt(){ register struct sym_bkt *sbp, /* general ptr */ *heap; /* ptr to array of unused symbol bkts, a "heap" */ struct sym_bkt *sym_link(); extern char O_debug; /* debugging switch */ sbp = sym_free; /* get the first unused sym_bkt from the free list */ while ((sym_free = sym_free->next_s) == 0) { /* and move the freelist header down */ /* if end of free list, allocate a new heap, and link the sym_bkts together to form a new free list */ if ((heap = (struct sym_bkt *)malloc(sizeof sym_heap)) == 0) Sys_Error("Symbol storage exceeded\n",0); Sym_heap_count++; if (O_debug >=4) printf("--sym heap allocated, #%d --",Sym_heap_count); sym_free = sym_link(heap); } return(sbp); } /* sym_link(heap): Routine to link the array of sym_bkts "heap" in a linear list. Returns ptr to top of list. It is assumed that the array has SYM_INCR sym_bkts in it */ struct sym_bkt *(sym_link(heap)) struct sym_bkt *heap; { register int i; register struct sym_bkt *top; /* top of list */ top = 0; /* zero marks end of list */ for(i = SYM_INCR-1; i >= 0; --i) { heap[i].next_s = top; top = &(heap[i]); } return(top); } /* Sym_Init: Routine to initialize the first sym_heap */ Sym_Init() { struct sym_bkt *sym_link(); sym_free = sym_link(sym_heap); } /* Store_String(String): Routine to store character strings. * MICAL does not have fixed length variable names. This routine allocates * storage in CBLOCK_INCR size chunks, and then sub-allocates space in this * to hold character strings. S is the char string you want to store * Returns ptr to the string. */ char *Store_String(String) char *String; { register char *S; /* working char string */ char *Start; /* value returned; location of allocated char string */ Start = &(Ccblock[Cb_nextc]); /* starting location of allocated char string */ for(S = String; Cb_nextc < CBLOCK_INCR; S++) /* load the char string into the current cblock */ if ((Ccblock[Cb_nextc++] = *S) == 0) return(Start); /* overflowed the current character block, so allocate a new one and try again */ Ccblock = (char *)malloc(CBLOCK_INCR); Cb_nextc = 0; Cb_count++; return(Store_String(String)); } /* Label() label and direct assignment handler * This routine picks up labels of the form <symbol>: on the source line * and enters them in the symbol table. It sets up Label_list, a list of * symbol bucket pointers for the labels in the statement. * In addition, it recognizes direct assignment statements. */ struct sym_bkt *Label_list[NLABELS_MAX]; /* list of sym_bkts for labels on a line */ int Label_count; /* number of such symbols */ Label() { register struct sym_bkt *sbp; /* general ptr */ int Save; /* save Position on Line */ register char S[STR_MAX]; /* string to hold symbol name */ char Got, /* 1 if we've picked up a valid symbol yet, 0 otherwise */ Which, /* 1 if processing label, 0 if processing direct assignment (d.a.) statement */ LS, /* set if local symbol label */ C; /* temp char */ extern int E_pass1; /* Error code for non-correctable pass 1 errors */ extern struct sym_bkt *Last_sym;/* Last symbol defined */ extern struct csect *Cur_csect; /* Current csect */ char *lastc(); Save = Position; /* Remember current position */ Got = 0; /* We haven't picked up a symbol yet */ Label_count = Which = 0; while (Get_Token(S)){ /* Pick up the first token */ Got++; /* Set the flag that says so */ LS = 0; Non_Blank(); /* skip to first non_blank */ if ((C = Line[Position]) != ':' && (C != '=')) break; /* if we didn't pick up a label, quit trying */ if (Label_count == 0) { /* If this is the first symbol we've picked up, */ Which = (C == ':') ? 1 : 2; /* Determine which operation we're doing. */ Got++; } /* So we don't do this again */ Position++; /* move Position past : or = */ /* check if valid symbol */ if ((S[0] >= '0') && (S[0] <= '9') && !(LS = (*lastc(S) == '$'))) { Prog_Error(E_SYMBOL); return(TRUE); } sbp = Lookup(S); /* Find the symbol bucket for this symbol */ if ((Pass==1) && Which==1) { /* On pass 1, initialize the label's symbol bucket */ if (sbp->attr_s & S_LABEL) /* If this label's already defined, complain */ E_pass1 = E_MULTSYM; sbp->attr_s |= S_LABEL | S_DEC | S_DEF; /* Symbol is a label, it's declared and defined */ if (LS) sbp->attr_s |= S_LOCAL; /* mark local symbols as such */ sbp->csect_s = Cur_csect; /* it's csect is the current one */ sbp->value_s = Dot; } /* it's value is the location counter */ if (LS == false && Which == 1) Last_symbol = sbp; /* make Last_symbol last defined label */ if (sbp->attr_s & S_REG) Prog_Warning(E_MULTSYM); /* Warn him if he's using a register symbol */ if (Label_count < NLABELS_MAX) /* if we don't have too many labels, */ Label_list[Label_count++] = sbp; /* put this one on the Label list */ else Prog_Warning(E_NLABELS); /* otherwise complain */ Save = Position; /* Move the last "safe" position up now */ } if ((Got==0) && Line_Delim(Line[Position])) { /* If the line had nothing left on it, */ Print_Line(P_NONE); return(FALSE); } /* print it, and we're through with this line */ Position = Save; /* Otherwise, move Position back to it's last safe value */ if (Which == 2) { /* If this is a d.a. statement, */ Equals(); return(FALSE); } /* Process it */ return(TRUE); /* and continue processing on this line */ } /* Sym_Fix - Assigns index numbers to the symbols. Also performs relocation of the symbols assuming data segment follows text and bss follows the data. If global flag, make all undefined symbols defined to be externals. */ Sym_Fix() { register struct sym_bkt **sbp1, *sbp2; int i = 0; extern char O_global; extern struct sym_bkt *Dot_bkt; for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) if (sbp2 = *sbp1) for(; sbp2; sbp2 = sbp2->next_s) { if (O_global && (sbp2->attr_s & (S_DEC|S_DEF)) == 0) { sbp2->attr_s |= S_EXT | S_DEC; sbp2->csect_s = 0; } sbp2->value_s += sdi_inc(sbp2->csect_s, sbp2->value_s); if (sbp2->csect_s == Data_csect) sbp2->value_s += tsize; else if (sbp2->csect_s == Bss_csect) sbp2->value_s += tsize + dsize; if (sbp2 == Dot_bkt || sbp2->attr_s & (S_REG|S_MACRO|S_LOCAL|S_PERM)) sbp2->id_s = -1; else sbp2->id_s = i++; } } /* Sym_Write - Write out the symbols to the specified file in b.out format, while computing size of the symbol segment in output file. */ long Sym_Write(file) FILE *file; { long size = 0; register struct sym_bkt **sbp1, *sbp2; register char *sp; #ifndef Stanford int slength; #endif Stanford struct sym s; for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) if (sbp2 = *sbp1) for (; sbp2; sbp2 = sbp2->next_s) { if (sbp2->id_s != -1) { if ((sbp2->attr_s&S_DEF)== 0)s.stype = UNDEF; else if (sbp2->csect_s == Text_csect) s.stype = TEXT; else if (sbp2->csect_s == Data_csect) s.stype = DATA; else if (sbp2->csect_s == Bss_csect) s.stype = BSS; else s.stype = ABS; if (sbp2->attr_s & S_EXT) s.stype |= EXTERN; s.svalue = sbp2->value_s; sp = sbp2->name_s; #ifndef Stanford fwrite(&s, sizeof s, 1, file); slength = 0; do /* write out asciz string and compute length */ { putc(*sp, file); slength++; } while(*sp++); size =+ sizeof(s) + slength; #else Stanford s.slength = strlen(sp); fwrite(&s, sizeof s, 1, file); fprintf(file,"%s",sp); putc('\0',file); size += sizeof s + s.slength + 1; #endif Stanford } } return(size); } /* * Perm Flags all currently defined symbols as permanent (and therefore * ineligible for redefinition. Also prevents them from being output * in the object file). */ Perm() { register struct sym_bkt **sbp1, *sbp2; for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++) for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s) sbp2->attr_s |= S_PERM; } '0') && (S[0] <= '9') && !(LS = (*lastc(S) == '$'))) { Prog_Error(E_SYMBOL); return(TRUE); } sbp = Lookup(S); /* Find the symbol bucket for this symbol */ if ((Pass==1) && Which==1) { /* On pass 1, initialize the label's symbol bucket */ if (sbp->attr_s & S_LABEL) /* If this label's already defined, complain */ E_pass1 = E_MULTSYM; sbp->attr_s |= S_LABEL | S_DEC | S_DEF; /* Symbol is a lsumacc/cc/c2/ 775 0 12 0 3540162160 6106 sumacc/cc/c2/.netupd_log 444 0 12 2030 3470501542 10326 Sat Apr 28 17:59:39 1984 created file c268[coyote], author: ds on Mon Jan 23 03:34:52 1984 Sat Apr 28 17:59:42 1984 created file makefile[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:46 1984 created file makefile_b[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:49 1984 created file makefile_o[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:53 1984 created file makefile_t[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:59 1984 created file o.h[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 18:00:06 1984 created file o0.c[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 18:00:12 1984 created file o0.o[coyote], author: ds on Mon Jan 23 03:34:08 1984 Sat Apr 28 18:00:19 1984 created file o1.c[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 18:00:24 1984 created file o1.o[coyote], author: ds on Mon Jan 23 03:34:48 1984 Sat Apr 28 18:00:26 1984 created file o68.1[coyote], author: mogul on Mon Apr 9 23:01:24 1984 created file c268[coyote], author: ds on Mon Jan 23 03:34:52 1984 Sat Apr 28 17:59:42 1984 created file makefile[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:46 1984 created file makefile_b[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:49 1984 created file makefile_o[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:53 1984 created file makefile_t[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:59 1984 sumacc/cc/c2/makefile 444 0 12 300 3470501542 7643 t: @make -f makefile_t install: @make -f makefile_t install help: @echo "usage: make {o b t clean}" o: @make -f makefile_o b: @make -f makefile_b clean: rm -f *.o *.b c2 c268 t Apr 28 17:59:46 1984 created file makefile_b[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:49 1984 created file makefile_o[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:53 1984 created file makefile_t[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 17:59:59 1984 sumacc/cc/c2/makefile_b 444 0 12 1220 3470501542 10166 #---------------------------------------------------------------------------- # These coded statements, instructions, and computer programs # contain unpublished proprietary information and are protected # by Federal copyright law. They may not be disclosed to third # parties or copied or duplicated in any form without the prior # written consent of Lucasfilm Ltd. # # Modifications to Unix V7 by John Seamons, Lucasfilm Ltd. #---------------------------------------------------------------------------- .SUFFIXES: .c .b CFLAGS = -c BFILES = o0.b o1.b c2: $(BFILES) cc68 -r -n -s -o ../../../bin/c2 $(BFILES) .c.b: o.h cc68 $(CFLAGS) $*.c 3 03:33:13 1984 Sat Apr 28 18:00:12 1984 created file o0.o[coyote], author: ds on Mon Jan 23 03:34:08 1984 Sat Apr 28 18:00:19 1984 created file o1.c[coyote], author: ds on Mon Jan 23 03:33:13 1984 Sat Apr 28 18:00:24 1984 created file o1.o[coyote], author: ds on Mon Jan 23 03:34:48 1984 Sat Apr 28 18:00:26 1984 created file o68.1[coyote], author: mogul on Msumacc/cc/c2/makefile_o 444 0 12 1202 3470501542 10203 #---------------------------------------------------------------------------- # These coded statements, instructions, and computer programs # contain unpublished proprietary information and are protected # by Federal copyright law. They may not be disclosed to third # parties or copied or duplicated in any form without the prior # written consent of Lucasfilm Ltd. # # Modifications to Unix V7 by John Seamons, Lucasfilm Ltd. #---------------------------------------------------------------------------- .SUFFIXES: .c .o CFLAGS = -c OFILES = o0.o o1.o c2: $(OFILES) cc -o ../../../bin/c2 $(OFILES) .c.o: o.h cc $(CFLAGS) $*.c er programs # contain unpublished proprietary information and are protected # by Federal copyright law. They may not be disclosed to third # parties or copied or duplicated in any form without the prior # written consent of Lucasfilm Ltd. # # Modifications to Unix V7 by John Seamons, Lucasfilm Ltd. #---------------------------------------------------------------------------- .Ssumacc/cc/c2/makefile_t 444 0 12 333 3470501543 10175 # cross version of the optimizer makefile .SUFFIXES: .c .o CFLAGS = -c -O -DBOOTSTRAP OFILES = o0.o o1.o c268: $(OFILES) cc -o c268 $(OFILES) .c.o: o.h cc $(CFLAGS) $*.c install: c268 cp c268 /usr/sun/bin copyright law. They may not be disclosed to third # parties or copied or duplicated in any form without the prior # written consent of Lucasfilm Ltd. # # Modifications to Unix V7 by John Seamons, Lucasfilm Ltd. #---------------------------------------------------------------------------- .Ssumacc/cc/c2/o.h 444 0 12 4714 3470501543 6610 #ifdef BOOTSTRAP #include "/usr/include/stdio.h" #else #include <stdio.h> #endif /* * Header for object code improver * Added some comments. 1982/Jan Per Bothner */ #define NCHNAM 32 #define JBR 1 #define CBR 2 #define JMP 3 #define LABEL 4 #define DLABEL 5 #define EROU 6 /* End of subroutine */ #define MOV 7 #define CLR 8 #define NOT 9 #define ADDQ 10 #define SUBQ 11 #define NEG 12 #define TST 13 #define ASR 14 #define ASL 15 #define LSR 16 #define LSL 17 #define EXT 18 #define CMP 20 #define ADD 21 #define SUB 22 #define AND 23 #define OR 24 #define EOR 25 #define LEA 26 #define PEA 27 #define MOVEM 28 #define LINK 29 #define UNLK 30 #define JSR 31 #define TEXT 32 #define DATA 33 #define BSS 34 #define EVEN 35 #define END 36 #define JSW 37 #define MOVEQ 38 #define MULS 39 #define MULU 40 #define DIVS 41 #define DIVU 42 #define DBF 43 /* PB - Dec 1982 */ #define JEQ 0 #define JNE 1 #define JLE 2 #define JGE 3 #define JLT 4 #define JGT 5 #define JLO 6 #define JHI 7 #define JLOS 8 #define JHIS 9 #define BYTE 100 #define WORD 101 #define LONG 102 struct node { char op; char subop; struct node *forw; /* Next node */ struct node *back; /* Previous node */ struct node *ref; /* Node to jump to, if any. Also used to link free list */ int labno; /* Label no. used in label and jump nodes */ char *code; /* Sometimes points to assembler string */ int refc; /* Reference count for labels */ }; struct optab { char *opstring; int opcode; } optab[]; char line[1024]; struct node first; /* List head for node list */ struct node *freenodes; /* Free list pointer */ char *curlp; int nbrbr; int nsaddr; int redunm; int iaftbr; int njp1; int nrlab; int nxjump; int ncmot; int nrevbr; int loopiv; int nredunj; int nskip; int ncomj; int nsob; int nrtst; int nlit; int nchange; /* Positive if changes this iteration */ int isn; int debug; char *lasta; char *lastr; char *firstr; char revbr[]; char regs[16][NCHNAM+1]; /* Contents of register: d0-d7,a0-a5,"source","dest" */ char conloc[NCHNAM+1]; /* A memory address ... */ char conval[NCHNAM+1]; /* ... containing this value. */ char ccloc[NCHNAM+1]; #define RT1 14 /* regs[RT1] is "source" register */ #define RT2 15 /* regs[RT2] is "destination" register */ #define NREG 14 #define LABHS 127 /* Size of hash table for labels */ #define OPHS 57 struct optab *ophash[OPHS]; struct { char lbyte; }; struct node *getnode(); struct node *nonlab(); struct node *insertl(); struct node *codemove(); char *findcon(); char *copy(); LSL 17 #define EXT 18 #define CMP 20 #define ADD 21 sumacc/cc/c2/o0.c 444 0 12 32316 3470501543 6702 /* * C object code improver * * Syntax: c2 [+] [-] [infile [outfile]] * The plus indicates debug mode on. Minus to print out statistics. * infile and outfile both default to stdin & stdout. * The input and output are both 68000 assembler. * * Modified by Bill Nowicki, Stanford, June 1982 * - Made it compile without error messages * Added dbf (see o1.c for motivation) - Per Bothner, Dec 1982 */ #include "o.h" struct optab optab[] = { "bra", JBR, "beq", CBR | JEQ<<8, "bne", CBR | JNE<<8, "ble", CBR | JLE<<8, "bge", CBR | JGE<<8, "blt", CBR | JLT<<8, "bgt", CBR | JGT<<8, "bcs", CBR | JLO<<8, "bhi", CBR | JHI<<8, "bls", CBR | JLOS<<8, "bcc", CBR | JHIS<<8, "jmp", JMP, ".globl",EROU, ".long",JSW, "mov", MOV, "clr", CLR, "not", NOT, "addq", ADDQ, "subq", SUBQ, "neg", NEG, "tst", TST, "asr", ASR, "asl", ASL, "lsr", LSR, "lsl", LSL, "ext", EXT, "cmp", CMP, "add", ADD, "sub", SUB, "and", AND, "or", OR, "eor", EOR, "muls", MULS, "mulu", MULU, "divs", DIVS, "divu", DIVU, "dbf", DBF, /* PB - Dec 1982 */ "jsr", JSR, "lea", LEA, "pea", PEA, "movem",MOVEM, "moveq",MOVEQ, "link", LINK, "unlk", UNLK, ".text",TEXT, ".data",DATA, ".bss", BSS, ".even",EVEN, ".end", END, 0, 0}; char revbr[] = { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO }; int isn = 20000; FILE *infile,*outfile; main(argc, argv) char **argv; { register int niter, maxiter, isend; extern end; int nflag; if (argc>1 && argv[1][0]=='+') { argc--; argv++; debug++; } nflag = 0; if (argc>1 && argv[1][0]=='-') { argc--; argv++; nflag++; } if (argc>1) { if ((infile = fopen(argv[1], "r")) == NULL) { fprintf(stderr,"C2: can't find %s\n", argv[1]); exit(1); } } else infile = stdin; if (argc>2) { if ((outfile = fopen(argv[2], "w")) == NULL) { fprintf(stderr,"C2: can't create %s\n", argv[2]); exit(1); } } else outfile = stdout; freenodes = 0; maxiter = 0; opsetup(); do { isend = input(); movedat(); nchange = niter = 0; do { refcount(); do { if (debug) printf("iterate\n"); iterate(); clearreg(); niter++; } while (nchange); if (debug) printf("comjump\n"); comjump(); if (debug) printf("rmove\n"); rmove(); } while (nchange || jumpsw()); output(1); fflush(outfile); if (niter > maxiter) maxiter = niter; } while (isend); fflush(outfile); if (nflag) { fprintf(stderr,"%d iterations\n", maxiter); fprintf(stderr,"%d jumps to jumps\n", nbrbr); fprintf(stderr,"%d inst. after jumps\n", iaftbr); fprintf(stderr,"%d jumps to .+2\n", njp1); fprintf(stderr,"%d redundant labels\n", nrlab); fprintf(stderr,"%d cross-jumps\n", nxjump); fprintf(stderr,"%d code motions\n", ncmot); fprintf(stderr,"%d branches reversed\n", nrevbr); fprintf(stderr,"%d redundant moves\n", redunm); fprintf(stderr,"%d simplified addresses\n", nsaddr); fprintf(stderr,"%d loops inverted\n", loopiv); fprintf(stderr,"%d redundant jumps\n", nredunj); fprintf(stderr,"%d common seqs before jmp's\n", ncomj); fprintf(stderr,"%d skips over jumps\n", nskip); fprintf(stderr,"%d redundant tst's\n", nrtst); fflush(stderr); } exit(0); } /* Read one subroutine */ input() { register struct node *p, *lastp; register int op; int subop; lastp = &first; for (;;) { op = getline(); subop = (op>>8)&0377; op &= 0377; switch (op) { case LABEL: p = getnode(); if (line[0]=='.' && line[1]=='L') { p->labno = getnum(line+2); p->op = LABEL; p->code = 0; } else { p->op = DLABEL; p->labno = 0; p->code = copy(line); } break; case JSW: p = getnode(); p->op = JSW; p->subop = 0; if (*curlp=='.' && *(curlp+1)=='L') { curlp += 2; p->labno = getnum(curlp); while ('0' <= *curlp && *curlp <= '9') curlp++; /* if (strcmp(curlp,"-0") != 0) { * p->op = 0; * p->labno = 0; * p->code = copy(line); * break; * } */ break; } notjsw: p->op = 0; p->labno = 0; p->code = copy(line); break; case JBR: case CBR: case JMP: p = getnode(); p->op = op; p->subop = subop; if (*curlp=='.' && *(curlp+1)=='L') { p->labno = getnum(curlp+2); p->code = 0; } else if (*curlp=='p' && *(curlp+1)=='c' && *(curlp+2)=='@') { p->op = p->subop = p->labno = 0; p->code = copy(line); } else { p->labno = 0; p->code = copy(curlp); } break; default: p = getnode(); p->op = op; p->subop = subop; p->labno = 0; p->code = copy(curlp); break; } p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p; p->ref = 0; if (op==EROU) return(1); if (op==END) return(0); } } getline() { register char *lp; register c; register ftab; again: lp = line; ftab = 0; while ((c = getc(infile)) != EOF) { if (!ftab && c==':') { *lp++ = 0; return(LABEL); } if (c=='\n') { if (lp==line) goto again; *lp++ = 0; return(oplook()); } if (c=='\t') ftab++; *lp++ = c; } *lp++ = 0; return(END); } getnum(ap) char *ap; { register char *p; register n, c; p = ap; n = 0; while ((c = *p++) >= '0' && c <= '9') n = n*10 + c - '0'; if (*--p!=0 && *p!='-') return(0); return(n); } /* Output node list, optionally flushing the list. (Not flushing it (flush==0) is intended to help debugging.) */ output(flush) { register struct node *t; register struct optab *op; register int byte; struct node *temp; t = first.forw; while (t) { switch (t->op) { case END: return; case LABEL: fprintf(outfile,".L%d:\n", t->labno); break; case DLABEL: fprintf(outfile,"%s:\n", t->code); if (flush) cfree(t->code); break; default: byte = t->subop; if (byte==BYTE || byte==WORD || byte==LONG) t->subop = 0; for (op = optab; op->opstring!=0; op++) if (op->opcode == (t->op | (t->subop<<8))) { if (t->op==CBR || t->op==JBR) fprintf(outfile,"\tj%s", op->opstring+1); else fprintf(outfile,"\t%s", op->opstring); if (byte==BYTE) fprintf(outfile,"b"); if (byte==WORD) fprintf(outfile,"w"); if (byte==LONG) fprintf(outfile,"l"); break; } if (t->op==JSW) { fprintf(outfile,"\t.L%d\n",t->labno); } else if (t->code) { fprintf(outfile,"\t%s\n", t->code); if (flush) cfree(t->code); } else if (t->op==JBR || t->op==CBR) fprintf(outfile,"\t.L%d\n", t->labno); else fprintf(outfile,"\n"); break; case 0: if (t->code) { fprintf(outfile,"%s", t->code); if (flush) cfree(t->code); } fprintf(outfile,"\n"); break; } temp = t->forw; if (flush) { t->ref = freenodes; freenodes = t; }; t = temp; } } char *copy(p) register char *p; { register char *onp; register int n = strlen(p); if (n==0) return(0); onp = (char *) calloc(n+1,1); strcpy(onp,p); return(onp); } opsetup() { register struct optab *optp, **ophp; register char *p; for (optp = optab; p = optp->opstring; optp++) { ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS]; while (*ophp++) if (ophp > &ophash[OPHS]) ophp = ophash; *--ophp = optp; } } oplook() { register struct optab *optp; register char *lp, *op; static char tmpop[32]; struct optab **ophp; op = tmpop; *op = *(op+1) = *(op+2) = 0; lp = line; while (*lp=='\t' || *lp==' ') lp++; while (*lp && *lp!=' ' && *lp!='\t') *op++ = *lp++; *op++ = 0; while (*lp=='\t' || *lp==' ') lp++; curlp = lp; ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS]; while (optp = *ophp) { op = optp->opstring; lp = tmpop; while (*lp == *op++) if (*lp++ == 0) return(optp->opcode); op--; if (*lp=='b' && *(lp+1)==0 && *op==0) return(optp->opcode + (BYTE<<8)); if (*lp=='w' && *(lp+1)==0 && *op==0) return(optp->opcode + (WORD<<8)); if (*lp=='l' && *(lp+1)==0 && *op==0) return(optp->opcode + (LONG<<8)); ophp++; if (ophp >= &ophash[OPHS]) ophp = ophash; } curlp = line; return(0); } /* Set p->ref so jumps point directly to label node. Set p->refc for labels to number of jumps which refer to them. */ refcount() { register struct node *p, *lp; static struct node *labhash[LABHS]; register struct node **hp; for (hp = labhash; hp < &labhash[LABHS];) *hp++ = 0; for (p = first.forw; p!=0; p = p->forw) if (p->op==LABEL) { labhash[p->labno % LABHS] = p; p->refc = 0; } for (p = first.forw; p!=0; p = p->forw) { if (p->op==JBR || p->op==CBR || p->op==JSW) { p->ref = 0; lp = labhash[p->labno % LABHS]; if (lp==0 || p->labno!=lp->labno) for (lp = first.forw; lp!=0; lp = lp->forw) { if (lp->op==LABEL && p->labno==lp->labno) break; } if (lp) { register struct node *hp; hp = nonlab(lp)->back; if (hp!=lp) { p->labno = hp->labno; lp = hp; } p->ref = lp; lp->refc++; } } } for (p = first.forw; p!=0; p = lp) { lp = p->forw; if (p->op==LABEL && p->refc==0 && lp && lp->op!=0 && lp->op!=JSW) decref(p); } } iterate() { register struct node *p, *rp, *p1; nchange = 0; for (p = first.forw; p!=0; p = p->forw) { /* Remove jumps to jumps */ if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { rp = nonlab(p->ref); if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { nbrbr++; p->labno = rp->labno; decref(p->ref); rp->ref->refc++; p->ref = rp->ref; nchange++; } } if (p->op==CBR && (p1 = p->forw)->op==JBR) { rp = p->ref; do rp = rp->back; while (rp->op==LABEL); if (rp==p1) { decref(p->ref); p->ref = p1->ref; p->labno = p1->labno; p1->forw->back = p; p->forw = p1->forw; p->subop = revbr[p->subop]; p1->ref = freenodes; freenodes = p1; nchange++; nskip++; } } /* Delete dead code */ if (p->op==JBR || p->op==JMP) { while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL && p->forw->op!=EROU && p->forw->op!=END && p->forw->op!=0 && p->forw->op!=DATA && p->forw->op!=BSS) { nchange++; iaftbr++; if (p->forw->ref) decref(p->forw->ref); p1 = p->forw; p->forw = p->forw->forw; p->forw->back = p; p1->ref = freenodes; freenodes = p1; } rp = p->forw; while (rp && rp->op==LABEL) { if (p->ref == rp) { p->back->forw = p->forw; p->forw->back = p->back; p->ref = freenodes; freenodes = p; p = p->back; decref(rp); nchange++; njp1++; break; } rp = rp->forw; } xjump(p); p = codemove(p); } } } /* Cross-jumping */ xjump(ap) struct node *ap; { register struct node *p1, *p2, *p3; int nxj; nxj = 0; p1 = ap; if ((p2 = p1->ref)==0) return(0); for (;;) { p1 = p1->back; /* Deleted: while ((p1 = p1->back) && p1->op==LABEL); 82/Jan PB */ while ((p2 = p2->back) && p2->op==LABEL); if (!equop(p1, p2) || p1==p2) return(nxj); p3 = insertl(p2); p1->op = JBR; p1->subop = 0; p1->ref = p3; p1->labno = p3->labno; p1->code = 0; nxj++; nxjump++; nchange++; } } /* Return a label pointing at ap. */ struct node *insertl(ap) struct node *ap; { register struct node *lp, *op; op = ap; if (op->op == LABEL) { op->refc++; return(op); } if (op->back->op == LABEL) { op = op->back; op->refc++; return(op); } lp = getnode(); lp->op = LABEL; lp->labno = isn++; lp->ref = 0; lp->code = 0; lp->refc = 1; lp->back = op->back; lp->forw = op; op->back->forw = lp; op->back = lp; return(lp); } struct node *codemove(ap) struct node *ap; { register struct node *p1, *p2, *p3; struct node *t, *tl; int n; p1 = ap; if (p1->op!=JBR || (p2 = p1->ref)==0) return(p1); while (p2->op == LABEL) if ((p2 = p2->back) == 0) return(p1); if (p2->op==JBR || p2->op==JMP) { p2 = p2->forw; p3 = p1->ref; while (p3) { if (p3->op==JBR || p3->op==JMP) { if (p1==p3) return(p1); ncmot++; nchange++; p1->back->forw = p2; p1->forw->back = p3; p2->back->forw = p3->forw; p3->forw->back = p2->back; p2->back = p1->back; p3->forw = p1->forw; decref(p1->ref); return(p2); } else p3 = p3->forw; } return(p1); }; if (p1->forw->op!=LABEL) return(p1); p3 = p2 = p2->forw; n = 16; do { if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) return(p1); } while (p3->op!=CBR || p3->labno!=p1->forw->labno); do if ((p1 = p1->back) == 0) return(ap); while (p1!=p3); p1 = ap; tl = insertl(p1); p3->subop = revbr[p3->subop]; decref(p3->ref); p2->back->forw = p1; p3->forw->back = p1; p1->back->forw = p2; p1->forw->back = p3; t = p1->back; p1->back = p2->back; p2->back = t; t = p1->forw; p1->forw = p3->forw; p3->forw = t; p2 = insertl(p1->forw); p3->labno = p2->labno; p3->ref = p2; decref(tl); if (tl->refc<=0) nrlab--; loopiv++; nchange++; return(p3); } comjump() { register struct node *p1, *p2, *p3; for (p1 = first.forw; p1!=0; p1 = p1->forw) if (p1->op==JBR && (p2 = p1->ref) && p2->refc > 1) for (p3 = p1->forw; p3!=0; p3 = p3->forw) if (p3->op==JBR && p3->ref == p2) backjmp(p1, p3); } backjmp(ap1, ap2) struct node *ap1, *ap2; { register struct node *p1, *p2, *p3, *ptemp; p1 = ap1; p2 = ap2; for(;;) { while ((p1 = p1->back) && p1->op==LABEL); p2 = p2->back; if (equop(p1, p2)) { p3 = insertl(p1); p2->back->forw = p2->forw; p2->forw->back = p2->back; ptemp = p2; p2 = p2->forw; ptemp->ref = freenodes; freenodes = ptemp; decref(p2->ref); p2->labno = p3->labno; p2->ref = p3; nchange++; ncomj++; } else return; } } rp = rp->back; while (rp->op==LABEL); if (rp==p1) { decref(p->ref); p->ref = p1->ref; p->labno = p1->labno; p1->forw->back = p; p->forw = p1->forw; p->subop = revbr[p->subop]; p1->ref = freenodes; freenodes = p1; nchange++; nskip++; } } /* Delete deadsumacc/cc/c2/o1.c 444 0 12 33617 3470501543 6710 # /* * C object code improver-- second part * Removed bug in equop (it thought two .TEXT's coulde be replaced by one), * and added some comments. 1982/Jan Per Bothner * Changed so MOVEQ, ADDQ, SUBQ never try loading from reg. 82/Jan PB * Fixed findcon to test for null locations. 82/Jan/21 PB * Undid pratt's fix in decref() which made it into a no-op. 82/Mar/24 PB * * Bill Nowicki, Stanford, June 1982 * - Made it compile without error messages * * Per Bothner, Stanford, Dec 1982 * - Added a hack in rmove (case CMP) that can halve the loop overhead * for loop that are done a fixed number of times. * In particular, the sequence: subql #1,dreg; cmpw #-1,dreg; jne label * becomes: dbf dreg,label * The former sequence is generated by cc for: * if (--r != -1) ... and do {...} while (--r != -1); * assuming that: register short r; * * Philip Almquist, Stanford, Feb 1984 * - Fixed redunbr to understand the CMP instruction: it thought * that CMP <op1> <op2> set the condition codes based on the value of * <op1> - <op2>, whereas it really sets the condition codes based on * the value of <op2> - <op1>. Thus: * * CLRL D7 register i; * .L0: CMPL #10,D7 <==> for (i=0; i<10; ... * JGE .L9 * * would be incorrectly optimized into: * * CLRL D7 * JRA .L9 * .L0: CMPL #10,D7 * JGE .L9 * * Extra credit problems for another day: this really should generate * something like: * * CLRL D7 CLRL D7 * JRA .L1 and then .L1: . * .L0: CMPL #10,D7 . * JGE .L9 .L0: CMPL #10,D7 * .L1: JLT .L1 * .L9: */ #include "o.h" /* Improve register usage by using any operands which might already be in registers */ rmove() { register struct node *p; register char *cp; register int r; int r1; struct node *ptemp; for (p=first.forw; p!=0; p = p->forw) { if (debug) { for (r=0; r<NREG; r++) if (regs[r][0]) printf("%d: %s ", r, regs[r]); printf("-\n"); } switch (p->op) { case MOVEQ: case MOV: if (p->subop==BYTE || p->subop==WORD) goto badmov; dualop(p); if (equstr(regs[RT1],regs[RT2]) || (r = findrand(regs[RT1])) >= 0 && r == isreg(regs[RT2]) && p->forw->op!=CBR) { p->forw->back = p->back; p->back->forw = p->forw; p->ref = freenodes; freenodes = p; redunm++; continue; } if (p->op != MOVEQ) repladdr(p, 0, 1); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2]); if (r >= 0) if (r1 >= 0) savereg(r1, regs[r]); else savereg(r, regs[RT2]); else if (r1 >= 0) savereg(r1, regs[RT1]); else setcon(regs[RT1], regs[RT2]); source(regs[RT1]); /* setcc(regs[RT2]); */ continue; case ADDQ: case SUBQ: dualop(p); dest(regs[RT2]); ccloc[0] = 0; continue; case MULS: case MULU: case DIVS: case DIVU: case ADD: case SUB: case AND: case OR: case EOR: badmov: dualop(p); repladdr(p, 0, 1); source(regs[RT1]); dest(regs[RT2]); ccloc[0] = 0; continue; case CLR: case NOT: case NEG: case EXT: singop(p); dest(regs[RT1]); if (p->op==CLR) if ((r = isreg(regs[RT1])) >= 0) savereg(r, "#0"); else setcon("#0", regs[RT1]); ccloc[0] = 0; continue; case TST: singop(p); repladdr(p, 0, 0); source(regs[RT1]); if (regs[RT1][0] && equstr(regs[RT1], ccloc)) { p->back->forw = p->forw; p->forw->back = p->back; ptemp = p; p = p->back; ptemp->ref = freenodes; freenodes = ptemp; nrtst++; nchange++; } continue; case CMP: dualop(p); /* first test if we can replace (subqw;cmpw;bne) by dbf */ /* This will speed up SOME loops - see top of file. PB. Dec 82 */ if (p->subop==WORD && (ptemp=p->back,ptemp->op==SUBQ) && p->forw->op==CBR && p->forw->subop==JNE && ptemp->subop==WORD && equstr(regs[RT1], "#-1") && (r=isreg(regs[RT2]))>=0 && r<=7) { dualop(ptemp); if (equstr(regs[RT1], "#1") && r==isreg(regs[RT2])) { char tempstr[50]; p->ref = freenodes; ptemp->ref = p; freenodes = ptemp; p = p->forw; /* jne --> dbf */ p->op = DBF; p->subop = 0; if (p->code) sprintf(tempstr, "d%d,%s", r, p->code); else { sprintf(tempstr, "d%d,.L%d", r, p->labno); p->labno = 0; } p->code = copy(tempstr); ptemp = ptemp->back; ptemp->forw = p; p->back = ptemp; nchange++; continue; } else dualop(p); } source(regs[RT1]); source(regs[RT2]); repladdr(p, 1, 1); ccloc[0] = 0; continue; case CBR: ccloc[0] = 0; continue; case JBR: redunbr(p); default: clearreg(); } } } jumpsw() { register struct node *p, *p1, *temp; register t; int nj; t = 0; nj = 0; for (p=first.forw; p!=0; p = p->forw) p->refc = ++t; for (p=first.forw; p!=0; p = p1) { p1 = p->forw; if (p->op == CBR && p1->op==JBR && p->ref && p1->ref && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) { if (p->ref==p1->ref) continue; p->subop = revbr[p->subop]; temp = p1->ref; p1->ref = p->ref; p->ref = temp; t = p1->labno; p1->labno = p->labno; p->labno = t; nrevbr++; nj++; } } return(nj); } abs(x) { return(x<0? -x: x); } /* Test if p1 and p2 are "equal". */ equop(p1, p2) register struct node *p1, *p2; { register char *cp1, *cp2; if (p1->op!=p2->op || p1->subop!=p2->subop) return(0); if (p1->op>0 && p1->op<MOV) return(0); /* Added 1982/Jan -Per Bothner */ if (p1->op>=TEXT) return(0); cp1 = p1->code; cp2 = p2->code; if (cp1==0 && cp2==0) return(1); if (cp1==0 || cp2==0) return(0); while (*cp1 == *cp2++) if (*cp1++ == 0) return(1); return(0); } /* Decrement no. of references to label ap, and if 0 delete it */ decref(ap) struct node *ap; { register struct node *p; /********** This makes switch statements fail, because word offsets are used instead of longs. Sigh p = ap; if (p->op != LABEL) return; if (--p->refc <= 0) { nrlab++; p->back->forw = p->forw; p->forw->back = p->back; p->ref = freenodes; freenodes = p; } ****** WIN Jul 1982 */ } /* Return first node after ap (inclusive) which is not a label */ struct node *nonlab(ap) struct node *ap; { register struct node *p; p = ap; while (p && p->op==LABEL) p = p->forw; return(p); } /* Return a new node */ struct node *getnode() { register struct node *p; if (p = freenodes) { freenodes = p->ref; p->subop = 0; return(p); } return ( (struct node *)calloc(1,sizeof first)); } clearreg() { register int i; for (i=0; i<NREG; i++) regs[i][0] = '\0'; conloc[0] = 0; ccloc[0] = 0; } savereg(ai, as) char *as; { register char *p, *s, *sp; sp = p = regs[ai]; s = as; if (source(s)) return; /* if (s[0]=='a' && s[1]<'6' && s[2]=='@') { * *sp = 0; * return; * } */ while (*p++ = *s) { if (*s++ == ',') break; } *--p = '\0'; } /* look through register contents table, clearing entries * based on value of address register 'reg'. */ areg(reg) { register int i; register char *p; for (i = 0; i < RT2; i++) { p = regs[i]; if (*p++ == 'a' && *p == (reg - 8 + '0')) regs[i][0] = 0; } } /* update register contents table assuming operand passed as argument * was affected by instruction */ dest(as) char *as; { register char *s; register int i; s = as; source(s); /* if dest was a register, update registers table entry */ if ((i = isreg(s)) >= 0) regs[i][0] = 0; /* if dest was an address reg, clear table entries for regs that * were loaded using that address reg. */ if (i >= 8) areg(i); /* clear any regs that claim to have copy of dest's value */ while ((i = findrand(s)) >= 0) regs[i][0] = 0; /* if there is any indirection, we don't know anything afterward */ if (*s++=='a' && *s>='0' && *s++<='5' && *s=='@') { for (i=0; i<NREG; i++) { if (regs[i][0] != '#') regs[i][0] = 0; conloc[0] = 0; } } } /* set RT1 (source) "register" from assy. language code */ singop(ap) struct node *ap; { register char *p1, *p2; p1 = ap->code; p2 = regs[RT1]; while (*p2++ = *p1++); regs[RT2][0] = 0; } /* set RT1 (source) and RT2 (dest) "registers" from assy. language code */ dualop(ap) struct node *ap; { register char *p1, *p2; register struct node *p; p = ap; p1 = p->code; p2 = regs[RT1]; while (*p1 && *p1!=',') *p2++ = *p1++; *p2++ = 0; p2 = regs[RT2]; *p2 = 0; if (*p1++ !=',') return; while (*p1==' ' || *p1=='\t') p1++; while (*p2++ = *p1++); } /* return register number of reg that already contains operand passed as * arg, -1 otherwise. */ findrand(as) char *as; { register int i; if (*as) for (i = 0; i<NREG; i++) { if (equstr(regs[i], as)) return(i); } return(-1); } /* return register number if operand corresponds to register, else -1 */ isreg(as) char *as; { register char *s; s = as; if (s[0]=='d' && s[1]>='0' && s[1]<='7' && s[2]==0) return(s[1]-'0'); if (s[0]=='a' && s[1]>='0' && s[1]<='5' && s[2]==0) return(s[1]-'0'+8); return(-1); } check() { register struct node *p, *lp; lp = &first; for (p=first.forw; p!=0; p = p->forw) { if (p->back != lp) abort(); lp = p; } } /* look for operands of the form an@+ or an@-; if found, reset register contents * table for register n and for any regs based on address register n. */ source(ap) char *ap; { register char *p1, *p2; register int i; p1 = ap; p2 = p1; if (*p1==0) return(0); while (*p2++); if (*(p2-2)=='+' || *(p2-2)=='-') { if (*p1++=='a' && *p1>='0' && *p1<='5') { regs[(i = *p1 - '0' + 8)][0] = 0; areg(i); } return(1); } return(0); } /* Replace address fields of instruction 'p' of args already in regs. * If 'f', arg2 is second source instead of destination. * If 'g', address register may be used as replacement, else only data. */ repladdr(p, f, g) struct node *p; { register r; int r1; register char *p1, *p2; static char rt1[50], rt2[50]; if (f) r1 = findrand(regs[RT2]); else r1 = -1; r = findrand(regs[RT1]); if (r>=0 || r1>=0) { p2 = regs[RT1]; for (p1 = rt1; *p1++ = *p2++;); if (regs[RT2][0]) { p1 = rt2; *p1++ = ','; for (p2 = regs[RT2]; *p1++ = *p2++;); } else rt2[0] = 0; if (r>=0) { if (r>7) { if (!g) return; rt1[0] = 'a'; rt1[1] = r - 8 + '0'; } else { rt1[0] = 'd'; rt1[1] = r + '0'; } rt1[2] = 0; nsaddr++; } if (r1>=0) { if (r1>7) { if (!g) return; rt2[1] = 'a'; rt2[2] = r1 - 8 + '0'; } else { rt2[1] = 'd'; rt2[2] = r1 + '0'; } rt2[3] = 0; nsaddr++; } strcat(rt1,rt2); p->code = copy(rt1); } } movedat() { register struct node *p1, *p2; struct node *p3; register seg; struct node data; struct node *datp; if (first.forw == 0) return; /* data.forw = 0; datp = &data; for (p1 = first.forw; p1!=0; p1 = p1->forw) { if (p1->op == DATA) { p2 = p1->forw; while (p2 && p2->op!=TEXT) p2 = p2->forw; if (p2==0) break; p3 = p1->back; p1->back->forw = p2->forw; p2->forw->back = p3; p2->forw = 0; datp->forw = p1; p1->back = datp; p1 = p3; datp = p2; } } if (data.forw) { datp->forw = first.forw; first.forw->back = datp; data.forw->back = &first; first.forw = data.forw; } */ /* Remove redundant TEXT, DATA, and BSS nodes. */ seg = -1; for (p1 = first.forw; p1!=0; p1 = p1->forw) { if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) { if (p1->op == seg || (p1->forw && (p1->forw->op==TEXT||p1->forw->op==DATA||p1->forw->op==BSS))) { p1->back->forw = p1->forw; p1->forw->back = p1->back; p1->ref = freenodes; freenodes = p1; p1 = p1->back; continue; } else seg = p1->op; } } } redunbr(ap) struct node *ap; { register struct node *p, *p1; register char *ap1; char *ap2; if ((p1 = p->ref) == 0) return; p1 = nonlab(p1); if (p1->op==TST) { singop(p1); savereg(RT2, "#0"); ap1 = findcon(RT1); ap2 = findcon(RT2); } else if (p1->op==CMP) { dualop(p1); /* CMP tests "backwards" (see edit log) - PDA, 2/13/84 */ ap2 = findcon(RT1); ap1 = findcon(RT2); } else return; if (p1->forw->op!=CBR) return; p1 = p1->forw; if (compare(p1->subop, ap1, ap2)) { nredunj++; nchange++; decref(p->ref); p->ref = p1->ref; p->labno = p1->labno; p->ref->refc++; } } /* Return code which is equal to contents of reg. i, preferably a constant */ char *findcon(i) { register char *p; register maxiter = 14; do { p = regs[i]; if (*p=='#') return(p); } while ((i = isreg(p)) >= 0 && --maxiter); if (*p && equstr(p, conloc)) return(conval); return(p); } /* Test: acp1 op acp2. * Return 1 if test succeeds; 0 if not or can't tell. */ compare(op, acp1, acp2) char *acp1, *acp2; { register char *cp1, *cp2; register n1; int n2; struct { int i;}; cp1 = acp1; cp2 = acp2; if (*cp1++ != '#' || *cp2++ != '#') return(0); n1 = 0; while (*cp2 >= '0' && *cp2 <= '9') { n1 *= 10; n1 += *cp2++ - '0'; } n2 = n1; n1 = 0; while (*cp1 >= '0' && *cp1 <= '9') { n1 *= 10; n1 += *cp1++ - '0'; } if (*cp1=='+') cp1++; if (*cp2=='+') cp2++; do { if (*cp1++ != *cp2) return(0); } while (*cp2++); cp1 = (char *)n1; cp2 = (char *)n2; switch(op) { case JEQ: return(cp1 == cp2); case JNE: return(cp1 != cp2); case JLE: return((int)cp1 <= (int)cp2); case JGE: return((int)cp1 >= (int)cp2); case JLT: return((int)cp1 < (int)cp2); case JGT: return((int)cp1 > (int)cp2); case JLO: return(cp1 < cp2); case JHI: return(cp1 > cp2); case JLOS: return(cp1 <= cp2); case JHIS: return(cp1 >= cp2); } return(0); } setcon(ar1, ar2) char *ar1, *ar2; { register char *cl, *cv, *p; cl = ar2; cv = ar1; if (*cv != '#') return; if (!natural(cl)) return; p = conloc; while (*p++ = *cl++); p = conval; while (*p++ = *cv++); } equstr(ap1, ap2) char *ap1, *ap2; { char *p1, *p2; p1 = ap1; p2 = ap2; do { if (*p1++ != *p2) return(0); } while (*p2++); return(1); } setcc(ap) char *ap; { register char *p, *p1; p = ap; if (!natural(p)) { ccloc[0] = 0; return; } p1 = ccloc; while (*p1++ = *p++); } natural(ap) char *ap; { register char *p; p = ap; if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(') return(0); while (*p++); p--; if (*--p == '+' || *p ==')' && *--p != '5') return(0); return(1); } (r>7) { if (!g) return; rt1[0] = 'a'; rt1[1] = r - 8 + '0'; } else { rt1[0] = 'd'; rt1[1] = r sumacc/cc/c2/o68.1 444 0 12 463 3470501543 6654 .TH O68 1 MC68000 .SU .SH NAME o68 \- .s -> .s optimizer component of cc68 .SH SYNOPSIS .B o68 .SH DESCRIPTION .I O68 is a 68000 assembly language optimizer. It takes its input from stdin and sends its output to stdout. .PP .SH FILES /usr/sun/c68/o0.c /usr/sun/c68/o1.c /usr/bin/o68 .SH SEE ALSO cc68 (1) if (!natural(cl)) return; p = conloc; while (*p++ = *cl++); p = conval; while (*p++ = *cv++); } equstr(ap1, ap2) char *ap1, *ap2; { char *p1, *p2; p1 = ap1; p2 = ap2; do { if (*p1++ != *p2) sumacc/cc/ccom/ 775 0 12 0 3540162164 6527 sumacc/cc/ccom/.netupd_log 444 0 12 10346 3470501544 10776 Sat Apr 28 18:01:17 1984 created file allo.c[coyote], author: ds on Mon Dec 5 17:16:27 1983 Sat Apr 28 18:01:21 1984 created file allo.o[coyote], author: ds on Mon Dec 5 20:51:40 1983 Sat Apr 28 18:01:40 1984 created file ccom68[coyote], author: ds on Mon Dec 5 20:52:43 1983 Sat Apr 28 18:01:43 1984 created file ccom68.1[coyote], author: mogul on Mon Apr 9 23:01:16 1984 Sat Apr 28 18:01:55 1984 created file cgram.c[coyote], author: ds on Mon Dec 5 20:40:30 1983 Sat Apr 28 18:02:03 1984 created file cgram.o[coyote], author: ds on Mon Dec 5 20:42:08 1983 Sat Apr 28 18:02:10 1984 created file cgram.y[coyote], author: ds on Mon Dec 5 17:16:46 1983 Sat Apr 28 18:02:14 1984 created file code.c[coyote], author: ds on Mon Dec 5 17:16:50 1983 Sat Apr 28 18:02:20 1984 created file code.o[coyote], author: ds on Mon Dec 5 20:47:06 1983 Sat Apr 28 18:02:22 1984 created file comm1.c[coyote], author: ds on Mon Dec 5 17:16:51 1983 Sat Apr 28 18:02:26 1984 created file comm1.o[coyote], author: ds on Mon Dec 5 20:52:01 1983 Sat Apr 28 18:02:32 1984 created file common[coyote], author: ds on Mon Dec 5 17:16:54 1983 Sat Apr 28 18:02:38 1984 created file local.c[coyote], author: ds on Mon Dec 5 17:16:59 1983 Sat Apr 28 18:02:41 1984 created file local.o[coyote], author: ds on Mon Dec 5 20:47:29 1983 Sat Apr 28 18:02:50 1984 created file local2.c[coyote], author: ds on Mon Dec 5 17:17:05 1983 Sat Apr 28 18:02:55 1984 created file local2.o[coyote], author: ds on Mon Dec 5 20:49:43 1983 Sat Apr 28 18:02:59 1984 created file mac2defs[coyote], author: ds on Mon Dec 5 17:17:06 1983 Sat Apr 28 18:03:02 1984 created file macdefs[coyote], author: ds on Mon Dec 5 17:17:07 1983 Sat Apr 28 18:03:04 1984 created file makefile[coyote], author: ds on Mon Dec 5 17:17:09 1983 Sat Apr 28 18:03:07 1984 created file makefile_b[coyote], author: ds on Mon Dec 5 17:17:10 1983 Sat Apr 28 18:03:09 1984 created file makefile_o[coyote], author: ds on Mon Dec 5 17:17:10 1983 Sat Apr 28 18:03:12 1984 created file makefile_t[coyote], author: ds on Mon Jan 23 03:25:59 1984 Sat Apr 28 18:03:17 1984 created file manifest[coyote], author: ds on Mon Dec 5 17:17:14 1983 Sat Apr 28 18:03:24 1984 created file match.c[coyote], author: ds on Mon Dec 5 17:17:18 1983 Sat Apr 28 18:03:28 1984 created file match.o[coyote], author: ds on Mon Dec 5 20:51:03 1983 Sat Apr 28 18:03:33 1984 created file mfile1[coyote], author: ds on Mon Dec 5 17:17:19 1983 Sat Apr 28 18:03:38 1984 created file mfile2[coyote], author: ds on Mon Dec 5 17:17:22 1983 Sat Apr 28 18:03:42 1984 created file optim.c[coyote], author: ds on Mon Dec 5 17:17:23 1983 Sat Apr 28 18:03:45 1984 created file optim.o[coyote], author: ds on Mon Dec 5 20:46:38 1983 Sat Apr 28 18:03:51 1984 created file order.c[coyote], author: ds on Mon Dec 5 17:17:32 1983 Sat Apr 28 18:03:57 1984 created file order.o[coyote], author: ds on Mon Dec 5 20:50:38 1983 Sat Apr 28 18:04:09 1984 created file pftn.c[coyote], author: ds on Mon Dec 5 17:17:43 1983 Sat Apr 28 18:04:16 1984 created file pftn.o[coyote], author: ds on Mon Dec 5 20:44:52 1983 Sat Apr 28 18:04:27 1984 created file reader.c[coyote], author: ds on Mon Dec 5 17:17:48 1983 Sat Apr 28 18:04:32 1984 created file reader.o[coyote], author: ds on Mon Dec 5 20:48:36 1983 Sat Apr 28 18:04:39 1984 created file scan.c[coyote], author: ds on Mon Dec 5 17:17:54 1983 Sat Apr 28 18:04:44 1984 created file scan.o[coyote], author: ds on Mon Dec 5 20:43:15 1983 Sat Apr 28 18:04:49 1984 created file table.c[coyote], author: ds on Mon Dec 5 17:17:57 1983 Sat Apr 28 18:04:52 1984 created file table.o[coyote], author: ds on Mon Dec 5 20:52:33 1983 Sat Apr 28 18:04:55 1984 created file test.c[coyote], author: ds on Mon Dec 5 17:17:58 1983 Sat Apr 28 18:04:59 1984 created file test.s[coyote], author: ds on Mon Jan 23 03:31:58 1984 Sat Apr 28 18:05:12 1984 created file trees.c[coyote], author: ds on Mon Dec 5 17:18:06 1983 Sat Apr 28 18:05:21 1984 created file trees.o[coyote], author: ds on Mon Dec 5 20:46:19 1983 Sat Apr 28 18:05:26 1984 created file xdefs.c[coyote], author: ds on Mon Dec 5 17:18:08 1983 Sat Apr 28 18:05:29 1984 created file xdefs.o[coyote], author: ds on Mon Dec 5 20:42:17 1983 acp2. * Return 1 if test succeeds; 0 if not or can't tell. */ compare(op, acp1, acp2) char *acp1, *acp2; { register char *cp1, *cp2; register n1; int n2; struct { int i;}; cp1 = acp1; cp2 = acp2; if (*cp1++ != '#' || *cp2++ != '#') return(0); n1 = 0; while (*cp2 >= 'sumacc/cc/ccom/allo.c 444 0 12 22550 3470501544 7730 # include "mfile2" NODE resc[3]; int busy[REGSZ]; int maxa, mina, maxb, minb; allo0(){ /* free everything */ register i; maxa = maxb = -1; mina = minb = 0; REGLOOP(i){ busy[i] = 0; if( rstatus[i] & STAREG ){ if( maxa<0 ) mina = i; maxa = i; } if( rstatus[i] & STBREG ){ if( maxb<0 ) minb = i; maxb = i; } } } # define TBUSY 01000 allo( p, q ) NODE *p; struct optab *q; { register n, i, j; n = q->needs; i = 0; while( n & NACOUNT ){ resc[i].in.op = REG; resc[i].tn.rval = freereg( p, n&NAMASK ); resc[i].tn.lval = 0; #ifdef FLEXNAMES resc[i].in.name = ""; #else resc[i].in.name[0] = '\0'; #endif n -= NAREG; ++i; } while( n & NBCOUNT ){ resc[i].in.op = REG; resc[i].tn.rval = freereg( p, n&NBMASK ); resc[i].tn.lval = 0; #ifdef FLEXNAMES resc[i].in.name = ""; #else resc[i].in.name[0] = '\0'; #endif n -= NBREG; ++i; } if( n & NTMASK ){ resc[i].in.op = OREG; resc[i].tn.rval = TMPREG; if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){ resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT ); } else { resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP ); } #ifdef FLEXNAMES resc[i].in.name = ""; #else resc[i].in.name[0] = '\0'; #endif resc[i].tn.lval = BITOOR(resc[i].tn.lval); ++i; } /* turn off "temporarily busy" bit */ REGLOOP(j){ busy[j] &= ~TBUSY; } for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0); return(1); } freetemp( k ){ /* allocate k integers worth of temp space */ /* we also make the convention that, if the number of words is more than 1, /* it must be aligned for storing doubles... */ # ifndef BACKTEMP int t; if( k>1 ){ SETOFF( tmpoff, ALDOUBLE ); } t = tmpoff; tmpoff += k*SZINT; if( tmpoff > maxoff ) maxoff = tmpoff; if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff; return(t); # else tmpoff += k*SZINT; if( k>1 ) { SETOFF( tmpoff, ALDOUBLE ); } if( tmpoff > maxoff ) maxoff = tmpoff; if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff; return( -tmpoff ); # endif } freereg( p, n ) NODE *p; { /* allocate a register of type n */ /* p gives the type, if floating */ register j; /* not general; means that only one register (the result) OK for call */ if( callop(p->in.op) ){ j = callreg(p); if( usable( p, n, j ) ) return( j ); /* have allocated callreg first */ } j = p->in.rall & ~MUSTDO; if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */ return( j ); } if( n&NAMASK ){ for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){ if( usable(p,n,j) ){ return( j ); } } } else if( n &NBMASK ){ for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){ if( usable(p,n,j) ){ return(j); } } } return( -1 ); } usable( p, n, r ) NODE *p; { /* decide if register r is usable in tree p to satisfy need n */ /* checks, for the moment */ if( !istreg(r) ) cerror( "usable asked about nontemp register" ); if( busy[r] > 1 ) return(0); if(((n&NAMASK) && !(rstatus[r]&SAREG)) || ((n&NBMASK) && !(rstatus[r]&SBREG))) return(0); if( (szty(p->in.type) == 2) ){ /* only do the pairing for real regs */ if( r&01 ) return(0); if( !istreg(r+1) ) return( 0 ); if( busy[r+1] > 1 ) return( 0 ); if( busy[r] == 0 && busy[r+1] == 0 || busy[r+1] == 0 && shareit( p, r, n ) || busy[r] == 0 && shareit( p, r+1, n ) ){ busy[r] |= TBUSY; busy[r+1] |= TBUSY; return(1); } else return(0); } if( busy[r] == 0 ) { busy[r] |= TBUSY; return(1); } /* busy[r] is 1: is there chance for sharing */ return( shareit( p, r, n ) ); } shareit( p, r, n ) NODE *p; { /* can we make register r available by sharing from p given that the need is n */ if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1); if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1); return(0); } ushare( p, f, r ) NODE *p; { /* can we find a register r to share on the left or right (as f=='L' or 'R', respectively) of p */ p = getlr( p, f ); if( p->in.op == UNARY MUL ) p = p->in.left; if( p->in.op == OREG ){ if( R2TEST(p->tn.rval) ){ return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) ); } else return( r == p->tn.rval ); } if( p->in.op == REG ){ return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) ); } return(0); } recl2( p ) register NODE *p; { register r = p->tn.rval; if( p->in.op == REG ) rfree( r, p->in.type ); else if( p->in.op == OREG ) { if( R2TEST( r ) ) { rfree( R2UPK1( r ), PTR+INT ); rfree( R2UPK2( r ), INT ); } else { rfree( r, PTR+INT ); } } } int rdebug = 0; rfree( r, t ) TWORD t; { /* mark register r free, if it is legal to do so */ /* t is the type */ if( rdebug ){ printf( "rfree( %s ), size %d\n", rnames[r], szty(t) ); } if( istreg(r) ){ if( --busy[r] < 0 ) cerror( "register overfreed"); if( szty(t) == 2 ){ if( (r&01) ) cerror( "illegal free" ); if( --busy[r+1] < 0 ) cerror( "register overfreed" ); } } } rbusy(r,t) TWORD t; { /* mark register r busy */ /* t is the type */ if( rdebug ){ printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) ); } if( istreg(r) ) ++busy[r]; if( szty(t) == 2 ){ if( istreg(r+1) ) ++busy[r+1]; if( (r&01) ) cerror( "illegal register pair freed" ); } } rwprint( rw ){ /* print rewriting rule */ register i, flag; static char * rwnames[] = { "RLEFT", "RRIGHT", "RESC1", "RESC2", "RESC3", 0, }; if( rw == RNULL ){ printf( "RNULL" ); return; } if( rw == RNOP ){ printf( "RNOP" ); return; } flag = 0; for( i=0; rwnames[i]; ++i ){ if( rw & (1<<i) ){ if( flag ) printf( "|" ); ++flag; printf( rwnames[i] ); } } } reclaim( p, rw, cookie ) NODE *p; { register NODE **qq; register NODE *q; register i; NODE *recres[5]; struct respref *r; /* get back stuff */ if( rdebug ){ printf( "reclaim( %o, ", p ); rwprint( rw ); printf( ", " ); prcook( cookie ); printf( " )\n" ); } if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */ walkf( p, recl2 ); if( callop(p->in.op) ){ /* check that all scratch regs are free */ callchk(p); /* ordinarily, this is the same as allchk() */ } if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */ tfree(p); return; } /* handle condition codes specially */ if( (cookie & FORCC) && (rw&RESCC)) { /* result is CC register */ tfree(p); p->in.op = CCODES; p->tn.lval = 0; p->tn.rval = 0; return; } /* locate results */ qq = recres; if( rw&RLEFT) *qq++ = getlr( p, 'L' );; if( rw&RRIGHT ) *qq++ = getlr( p, 'R' ); if( rw&RESC1 ) *qq++ = &resc[0]; if( rw&RESC2 ) *qq++ = &resc[1]; if( rw&RESC3 ) *qq++ = &resc[2]; if( qq == recres ){ cerror( "illegal reclaim"); } *qq = NIL; /* now, select the best result, based on the cookie */ for( r=respref; r->cform; ++r ){ if( cookie & r->cform ){ for( qq=recres; (q= *qq) != NIL; ++qq ){ if( tshape( q, r->mform ) ) goto gotit; } } } /* we can't do it; die */ cerror( "cannot reclaim"); gotit: if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */ q->in.type = p->in.type; /* to make multi-register allocations work */ /* maybe there is a better way! */ q = tcopy(q); tfree(p); p->in.op = q->in.op; p->tn.lval = q->tn.lval; p->tn.rval = q->tn.rval; #ifdef FLEXNAMES p->in.name = q->in.name; #else for( i=0; i<NCHNAM; ++i ) p->in.name[i] = q->in.name[i]; #endif q->in.op = FREE; /* if the thing is in a register, adjust the type */ switch( p->in.op ){ case REG: if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */ i = p->in.rall & ~MUSTDO; if( i & NOPREF ) return; if( i != p->tn.rval ){ if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){ cerror( "faulty register move" ); } rbusy( i, p->in.type ); rfree( p->tn.rval, p->in.type ); rmove( i, p->tn.rval, p->in.type ); p->tn.rval = i; } case OREG: if( R2TEST(p->tn.rval) ){ int r1, r2; r1 = R2UPK1(p->tn.rval); r2 = R2UPK2(p->tn.rval); if( (busy[r1]>1 && istreg(r1)) || (busy[r2]>1 && istreg(r2)) ){ cerror( "potential register overwrite" ); } } else if( (busy[p->tn.rval]>1) && istreg(p->tn.rval) ) cerror( "potential register overwrite"); } } ncopy( q, p ) NODE *p, *q; { /* copy the contents of p into q, without any feeling for the contents */ /* this code assume that copying rval and lval does the job; in general, it might be necessary to special case the operator types */ register i; q->in.op = p->in.op; q->in.rall = p->in.rall; q->in.type = p->in.type; q->tn.lval = p->tn.lval; q->tn.rval = p->tn.rval; #ifdef FLEXNAMES q->in.name = p->in.name; #else for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i]; #endif } NODE * tcopy( p ) register NODE *p; { /* make a fresh copy of p */ register NODE *q; register r; ncopy( q=talloc(), p ); r = p->tn.rval; if( p->in.op == REG ) rbusy( r, p->in.type ); else if( p->in.op == OREG ) { if( R2TEST(r) ){ rbusy( R2UPK1(r), PTR+INT ); rbusy( R2UPK2(r), INT ); } else { rbusy( r, PTR+INT ); } } switch( optype(q->in.op) ){ case BITYPE: q->in.right = tcopy(p->in.right); case UTYPE: q->in.left = tcopy(p->in.left); } return(q); } allchk(){ /* check to ensure that all register are free */ register i; REGLOOP(i){ if( istreg(i) && busy[i] ){ cerror( "register allocation error"); } } } ", "RESC2", "RESC3", 0, }; if( rw == RNULL ){ printf( "RNULL" ); return; } if( rw == RNOP ){ printf( "RNOP" ); return; } flag sumacc/cc/ccom/ccom68.1 444 0 12 1116 3470501544 7771 .TH CCOM68 1 MC68000 .SU .SH NAME ccom68 \- .c -> .s translator component of cc68 .SH SYNOPSIS .B ccom68 [ -lXp ] .SH DESCRIPTION .I Ccom68 is the UNIX C compiler modified for the MC68000. It takes its input from stdin and the resulting assembly code is printed on stdout. .PP The -l option generates line numbers in the output. The -p option causes the profile forming instruction "jbsr mcount" to be inserted at the entry to each function. The latter option must be preceded by X, which signals that it is a pass 2 option. .SH FILES /usr/sun/c68 /usr/bin/ccom68 .SH SEE ALSO cc68 (1) al; #ifdef FLEXNAMES q->in.name = p->in.name; #else for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i]; #endif } NODE * tcopy( p ) register NODE *p; { /* make a fresh copy of p */ register NODE *q; register r; ncopy( q=talloc(), p ); r = p->tn.rval; if( p->in.op == REG ) rbusy( r, p->in.type ); else if( p->in.op == OREG ) { if( R2TEST(r) ){ rbusy( R2UPK1(r), PTR+INT ); rbusy( R2UPK2(r), INT ); } esumacc/cc/ccom/cgram.c 444 0 12 114361 3470501545 10115 # define NAME 2 # define STRING 3 # define ICON 4 # define FCON 5 # define PLUS 6 # define MINUS 8 # define MUL 11 # define AND 14 # define OR 17 # define ER 19 # define QUEST 21 # define COLON 22 # define ANDAND 23 # define OROR 24 # define ASOP 25 # define RELOP 26 # define EQUOP 27 # define DIVOP 28 # define SHIFTOP 29 # define INCOP 30 # define UNOP 31 # define STROP 32 # define TYPE 33 # define CLASS 34 # define STRUCT 35 # define RETURN 36 # define GOTO 37 # define IF 38 # define ELSE 39 # define SWITCH 40 # define BREAK 41 # define CONTINUE 42 # define WHILE 43 # define DO 44 # define FOR 45 # define DEFAULT 46 # define CASE 47 # define SIZEOF 48 # define ENUM 49 # define LP 50 # define RP 51 # define LC 52 # define RC 53 # define LB 54 # define RB 55 # define CM 56 # define SM 57 # define ASSIGN 58 # line 108 "cgram.y" # include "mfile1" #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar; extern short yyerrflag; #ifndef YYMAXDEPTH #define YYMAXDEPTH 150 #endif YYSTYPE yylval, yyval; # line 127 "cgram.y" static int fake = 0; #ifndef FLEXNAMES static char fakename[NCHNAM+1]; #else static char fakename[24]; #endif # define YYERRCODE 256 # line 800 "cgram.y" NODE * mkty( t, d, s ) unsigned t; { return( block( TYPE, NIL, NIL, t, d, s ) ); } NODE * bdty( op, p, v ) NODE *p; { register NODE *q; q = block( op, p, NIL, INT, 0, INT ); switch( op ){ case UNARY MUL: case UNARY CALL: break; case LB: q->in.right = bcon(v); break; case NAME: q->tn.rval = v; break; default: cerror( "bad bdty" ); } return( q ); } dstash( n ){ /* put n into the dimension table */ if( curdim >= DIMTABSZ-1 ){ cerror( "dimension table overflow"); } dimtab[ curdim++ ] = n; } savebc() { if( psavbc > & asavbc[BCSZ-4 ] ){ cerror( "whiles, fors, etc. too deeply nested"); } *psavbc++ = brklab; *psavbc++ = contlab; *psavbc++ = flostat; *psavbc++ = swx; flostat = 0; } resetbc(mask){ swx = *--psavbc; flostat = *--psavbc | (flostat&mask); contlab = *--psavbc; brklab = *--psavbc; } addcase(p) NODE *p; { /* add case to switch */ p = optim( p ); /* change enum to ints */ if( p->in.op != ICON ){ uerror( "non-constant case expression"); return; } if( swp == swtab ){ uerror( "case not in switch"); return; } if( swp >= &swtab[SWITSZ] ){ cerror( "switch table overflow"); } swp->sval = p->tn.lval; deflab( swp->slab = getlab() ); ++swp; tfree(p); } adddef(){ /* add default case to switch */ if( swtab[swx].slab >= 0 ){ uerror( "duplicate default in switch"); return; } if( swp == swtab ){ uerror( "default not inside switch"); return; } deflab( swtab[swx].slab = getlab() ); } swstart(){ /* begin a switch block */ if( swp >= &swtab[SWITSZ] ){ cerror( "switch table overflow"); } swx = swp - swtab; swp->slab = -1; ++swp; } swend(){ /* end a switch block */ register struct sw *swbeg, *p, *q, *r, *r1; CONSZ temp; int tempi; swbeg = &swtab[swx+1]; /* sort */ r1 = swbeg; r = swp-1; while( swbeg < r ){ /* bubble largest to end */ for( q=swbeg; q<r; ++q ){ if( q->sval > (q+1)->sval ){ /* swap */ r1 = q+1; temp = q->sval; q->sval = r1->sval; r1->sval = temp; tempi = q->slab; q->slab = r1->slab; r1->slab = tempi; } } r = r1; r1 = swbeg; } /* it is now sorted */ for( p = swbeg+1; p<swp; ++p ){ if( p->sval == (p-1)->sval ){ uerror( "duplicate case in switch, %d", tempi=p->sval ); return; } } genswitch( swbeg-1, swp-swbeg ); swp = swbeg-1; } short yyexca[] ={ -1, 1, 0, -1, 2, 18, 11, 18, 50, 18, 57, 18, -2, 0, -1, 19, 56, 76, 57, 76, -2, 7, -1, 24, 56, 75, 57, 75, -2, 73, -1, 26, 56, 79, 57, 79, -2, 74, -1, 32, 52, 41, -2, 39, -1, 34, 52, 33, -2, 31, }; # define YYNPROD 178 # define YYLAST 1173 short yyact[]={ 229, 18, 263, 93, 194, 130, 145, 100, 59, 129, 227, 6, 77, 98, 249, 89, 87, 88, 27, 27, 80, 56, 97, 78, 102, 230, 79, 21, 21, 10, 9, 14, 27, 95, 46, 20, 92, 51, 66, 304, 272, 21, 82, 81, 271, 16, 36, 257, 239, 240, 244, 75, 248, 237, 238, 245, 246, 247, 251, 250, 83, 99, 84, 303, 108, 228, 22, 22, 110, 241, 8, 154, 201, 225, 17, 106, 298, 131, 28, 287, 22, 36, 35, 45, 267, 146, 150, 187, 74, 105, 266, 138, 139, 140, 141, 142, 143, 103, 198, 91, 53, 70, 57, 197, 154, 101, 71, 155, 281, 24, 158, 254, 112, 153, 162, 163, 164, 166, 168, 170, 172, 174, 175, 177, 179, 181, 182, 183, 184, 185, 109, 40, 42, 131, 156, 48, 189, 186, 73, 49, 38, 159, 188, 160, 39, 146, 38, 69, 48, 68, 39, 191, 49, 219, 256, 147, 134, 219, 136, 48, 65, 253, 57, 49, 213, 157, 204, 94, 205, 152, 206, 33, 207, 202, 208, 31, 137, 209, 293, 210, 135, 211, 285, 249, 89, 87, 88, 217, 131, 80, 192, 72, 78, 214, 200, 79, 215, 64, 223, 294, 221, 222, 196, 224, 226, 218, 278, 40, 282, 42, 196, 82, 81, 252, 277, 147, 94, 239, 240, 244, 276, 248, 237, 238, 245, 246, 247, 251, 250, 83, 218, 84, 275, 108, 151, 274, 264, 98, 241, 27, 269, 195, 259, 260, 261, 262, 97, 265, 21, 195, 220, 279, 4, 151, 273, 10, 9, 14, 255, 52, 284, 9, 283, 54, 10, 9, 14, 96, 242, 30, 270, 16, 26, 26, 108, 288, 289, 264, 291, 290, 16, 10, 280, 14, 7, 99, 26, 22, 47, 119, 190, 60, 111, 29, 34, 300, 295, 16, 32, 264, 116, 301, 117, 67, 243, 119, 115, 107, 121, 94, 104, 122, 132, 123, 50, 126, 19, 124, 125, 127, 113, 120, 115, 118, 116, 25, 117, 61, 44, 119, 199, 90, 41, 43, 55, 58, 116, 161, 117, 203, 63, 119, 62, 37, 121, 302, 115, 122, 3, 123, 114, 126, 128, 124, 125, 127, 113, 120, 115, 118, 2, 149, 85, 11, 12, 5, 23, 13, 15, 236, 234, 235, 116, 233, 117, 231, 232, 119, 1, 0, 121, 299, 0, 122, 0, 123, 114, 126, 128, 124, 125, 127, 113, 120, 115, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 117, 0, 0, 119, 0, 0, 121, 297, 0, 122, 0, 123, 114, 126, 128, 124, 125, 127, 113, 120, 115, 118, 0, 116, 0, 117, 0, 242, 119, 0, 0, 0, 0, 0, 0, 0, 116, 0, 117, 0, 0, 119, 0, 296, 121, 115, 118, 122, 114, 123, 128, 126, 292, 124, 125, 127, 113, 120, 115, 118, 116, 0, 117, 0, 0, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 126, 0, 124, 125, 127, 113, 120, 115, 118, 0, 116, 114, 117, 128, 0, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 126, 0, 124, 125, 127, 113, 120, 115, 118, 0, 114, 286, 128, 0, 0, 0, 0, 0, 0, 116, 0, 117, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 258, 128, 116, 113, 117, 115, 118, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 126, 0, 124, 125, 127, 113, 120, 115, 118, 116, 0, 117, 0, 0, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 126, 212, 124, 125, 127, 113, 120, 115, 118, 0, 216, 114, 0, 128, 0, 0, 0, 0, 0, 0, 0, 116, 0, 117, 0, 116, 119, 117, 0, 121, 119, 0, 122, 121, 123, 114, 126, 128, 124, 125, 127, 113, 120, 115, 118, 113, 120, 115, 118, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 117, 0, 0, 119, 0, 0, 121, 193, 0, 122, 0, 123, 114, 126, 128, 124, 125, 127, 113, 120, 115, 118, 116, 0, 117, 0, 0, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 126, 0, 124, 125, 127, 113, 120, 115, 118, 0, 0, 114, 0, 128, 86, 89, 87, 88, 0, 0, 80, 0, 0, 78, 0, 0, 79, 86, 89, 87, 88, 0, 0, 80, 0, 0, 78, 128, 0, 79, 0, 0, 82, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 81, 0, 0, 0, 83, 0, 84, 0, 0, 86, 89, 87, 88, 0, 180, 80, 0, 83, 78, 84, 0, 79, 86, 89, 87, 88, 0, 178, 80, 0, 0, 78, 0, 0, 79, 0, 0, 82, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 81, 0, 0, 0, 83, 0, 84, 0, 0, 86, 89, 87, 88, 0, 176, 80, 0, 83, 78, 84, 0, 79, 86, 89, 87, 88, 0, 173, 80, 0, 0, 78, 0, 0, 79, 0, 0, 82, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 81, 0, 0, 0, 83, 0, 84, 0, 0, 86, 89, 87, 88, 0, 171, 80, 0, 83, 78, 84, 0, 79, 86, 89, 87, 88, 0, 169, 80, 0, 0, 78, 0, 0, 79, 0, 0, 82, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 81, 0, 0, 0, 83, 0, 84, 0, 0, 86, 89, 87, 88, 0, 167, 80, 0, 83, 78, 84, 0, 79, 86, 89, 87, 88, 0, 165, 80, 0, 0, 78, 0, 0, 79, 0, 0, 82, 81, 116, 0, 117, 0, 0, 119, 0, 0, 121, 0, 0, 82, 81, 123, 0, 0, 83, 0, 84, 0, 113, 120, 115, 118, 0, 268, 0, 0, 0, 83, 0, 84, 0, 133, 86, 89, 87, 88, 0, 0, 80, 0, 0, 78, 0, 0, 79, 86, 89, 87, 88, 0, 0, 80, 0, 0, 78, 0, 0, 79, 0, 0, 82, 81, 0, 10, 0, 14, 0, 0, 0, 0, 0, 0, 0, 82, 81, 0, 0, 0, 83, 16, 84, 0, 0, 0, 0, 86, 89, 87, 88, 0, 0, 83, 0, 84, 0, 76, 86, 89, 87, 88, 0, 0, 80, 0, 0, 78, 0, 0, 79, 86, 89, 87, 88, 82, 81, 80, 0, 0, 78, 0, 0, 79, 0, 0, 82, 81, 0, 0, 0, 0, 0, 83, 0, 84, 0, 0, 0, 82, 81, 0, 0, 116, 83, 117, 84, 148, 119, 86, 89, 87, 88, 0, 0, 80, 0, 83, 78, 84, 0, 79, 0, 113, 120, 115, 118, 0, 116, 0, 117, 0, 0, 119, 0, 0, 121, 82, 81, 122, 0, 123, 0, 126, 0, 124, 125, 0, 113, 120, 115, 118, 0, 0, 116, 83, 117, 144, 0, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 0, 0, 124, 0, 0, 113, 120, 115, 118, 116, 0, 117, 0, 0, 119, 0, 0, 121, 0, 0, 122, 0, 123, 0, 0, 0, 0, 0, 0, 113, 120, 115, 118 }; short yypact[]={ -1000, -4,-1000,-1000,-1000, 17,-1000, 248, 227,-1000, 236,-1000,-1000, 123, 296, 119, 292,-1000, 25, 90, -1000, 237, 237, 32, 109, -21,-1000, 209,-1000, 248, 230, 248,-1000, 289,-1000,-1000,-1000,-1000, 146, 105, 109, 90, 98, 96, 50,-1000,-1000,-1000, 140, 83, 976,-1000,-1000,-1000,-1000, 42,-1000, 11, 49,-1000, -34, 30,-1000, 222,-1000,-1000, 75,1040,-1000,-1000, -1000, 290,-1000,-1000, 57, 662, 912, 126,1040,1040, 1040,1040,1040,1078, 963,1027, 203,-1000,-1000,-1000, 116, 248, 48,-1000, 85,-1000,-1000, 235,-1000, 235, 112, 289,-1000,-1000, 90,-1000, 11,-1000,-1000,-1000, 662,-1000,-1000,1040,1040, 861, 848, 810, 797, 759, 1040, 746, 708, 695,1040,1040,1040,1040,1040, 31, -1000, 662, 912,-1000,-1000,1040, 288,-1000, 126, 126, 126, 126, 126, 126, 963, 139, 602, 191,-1000, 47, 662,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 15, 231, 427, 662,-1000,1040, 278,1040, 278,1040, 318,1040,-1000,1040, 523,1068,1040, 925,1040, 606, 1040,1143,1119, 566, 662, 662, 111, 912, 31, 542, -1000, 136,1040,-1000, 99, 199, 191,1040,-1000, 11, -1000,-1000, 16, 12, 662, 662, 662, 662, 662, 662, 662, 662,1040,-1000,-1000, 108,-1000,1016, 126, 56, -1000, 103, 99, 662,-1000,-1000, -10,-1000,-1000, 489, -1000, 181, 181, 181, 181,1040, 181, 33, 27, 899, 268,-1000, -13, 181, 185, 182,-1000, 170, 164, 184, 1040, 260,1093,-1000,-1000, 53, 158,-1000,-1000, 223, -1000,-1000, 217, 131, 638,-1000,-1000,-1000,-1000, 464, 22,-1000,-1000,-1000,1040,1040,1040,1040,-1000, 440, -1000,-1000, 127,-1000, 149, 181,-1000,-1000, 402, 366, 19, 330,-1000,-1000,1040,-1000,-1000,-1000,1040,-1000, 294, 6, -18,-1000,-1000 }; short yypgo[]={ 0, 378, 38, 376, 375, 373, 371, 370, 369, 368, 367, 366, 0, 2, 12, 11, 365, 70, 364, 363, 6, 4, 362, 3, 310, 109, 361, 360, 348, 1, 343, 342, 340, 25, 36, 339, 10, 337, 284, 335, 7, 8, 334, 331, 21, 330, 328, 35, 327, 325, 314, 9, 5, 312, 307, 304, 303 }; short yyr1[]={ 0, 1, 1, 27, 27, 28, 28, 30, 28, 31, 32, 32, 35, 35, 37, 37, 37, 16, 16, 15, 15, 15, 15, 15, 38, 17, 17, 17, 17, 17, 18, 18, 9, 9, 39, 39, 41, 41, 19, 19, 10, 10, 42, 42, 44, 44, 34, 45, 34, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 24, 11, 46, 46, 46, 29, 48, 29, 49, 49, 47, 47, 47, 47, 47, 51, 51, 52, 52, 40, 40, 43, 43, 50, 50, 53, 33, 54, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 55, 55, 55, 7, 4, 3, 5, 6, 8, 56, 2, 13, 13, 26, 26, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22 }; short yyr2[]={ 0, 2, 0, 1, 1, 2, 3, 0, 4, 2, 4, 0, 2, 0, 3, 4, 0, 1, 0, 2, 2, 1, 1, 3, 1, 1, 2, 3, 1, 1, 5, 2, 1, 2, 1, 3, 1, 3, 5, 2, 1, 2, 1, 3, 2, 1, 1, 0, 4, 1, 3, 2, 1, 2, 3, 3, 4, 1, 3, 2, 3, 3, 4, 3, 3, 2, 2, 1, 3, 1, 1, 0, 4, 1, 1, 1, 1, 3, 6, 1, 1, 3, 1, 4, 0, 1, 0, 1, 0, 1, 1, 4, 1, 2, 1, 2, 2, 2, 7, 4, 2, 2, 2, 2, 3, 3, 1, 2, 2, 2, 2, 3, 2, 1, 4, 3, 4, 6, 4, 0, 2, 1, 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 3, 1, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 2, 3, 3, 1, 1, 1, 1, 3, 2, 0, 2, 5, 2, 3, 4, 3, 2, 2 }; short yychk[]={ -1000, -1, -27, -28, 256, -16, -15, -38, -17, 34, 33, -19, -18, -10, 35, -9, 49, 57, -29, -24, -47, 11, 50, -11, -25, -49, 256, 2, -17, -38, 33, 52, 2, 52, 2, 57, 56, -30, 50, 54, -25, -24, -25, -24, -46, 51, 2, 256, 50, 54, -50, 58, 50, -17, 33, -42, -44, -17, -39, -41, 2, -48, -31, -32, 51, 55, -2, -56, 51, 51, 51, 56, 51, 55, -2, -12, 52, -14, 11, 14, 8, 31, 30, 48, 50, -22, 2, 4, 5, 3, -43, 57, -34, -23, -25, 22, 256, 11, 2, 50, -40, 56, 58, -47, -24, -33, -15, -54, 52, 55, -12, 2, 55, 26, 56, 28, 6, 8, 29, 11, 27, 14, 17, 19, 23, 24, 21, 25, 58, -51, -52, -12, -53, 52, 30, 54, 32, 50, -14, -14, -14, -14, -14, -14, 50, -20, -12, -17, 51, -26, -12, 50, 53, -44, 56, 22, -2, 53, -41, -2, -34, -37, -12, -12, -12, 58, -12, 58, -12, 58, -12, 58, -12, 58, -12, -12, 58, -12, 58, -12, 58, -12, -12, -12, -12, -12, -40, 56, -51, -12, 2, -20, 51, 51, -21, 50, 11, 56, 51, -45, -2, 57, -15, -35, -12, -12, -12, -12, -12, -12, -12, -12, 22, 53, -52, -40, 55, 51, -14, 54, 51, -21, -21, -12, -23, 57, -29, -36, 53, -12, -33, -4, -3, -5, -7, -6, -8, 41, 42, 36, 37, 57, 256, -55, 38, 43, 44, 45, 40, 2, 47, 46, -12, 53, 55, -2, 51, 57, 57, -36, -36, -36, -36, -13, -12, -36, 57, 57, 57, -12, 2, 57, 53, -36, 50, 50, 50, 50, 22, -12, 22, 55, 50, 39, 43, 51, 57, 57, -12, -12, -13, -12, 22, 51, 50, -36, 51, 51, 57, 51, -12, -13, 51, 57, 57 }; short yydef[]={ 2, -2, 1, 3, 4, 0, 17, 21, 22, 24, 25, 28, 29, 0, 40, 0, 32, 5, 0, -2, 70, 0, 0, 0, -2, 88, -2, 57, 19, 20, 26, 0, -2, 0, -2, 6, 71, 11, 0, 119, 53, 59, 0, 0, 0, 65, 67, 69, 0, 119, 0, 89, 66, 23, 27, 86, 42, 45, 84, 34, 36, 0, 8, 0, 60, 61, 0, 0, 58, 63, 64, 0, 54, 55, 0, 77, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 163, 164, 165, 166, 0, 87, 44, 46, 49, 119, 52, 0, 57, 0, 0, 85, 119, 72, 76, 9, 0, 16, 92, 62, 120, 68, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 80, 82, 0, 90, 150, 0, 0, 177, 151, 152, 153, 154, 155, 156, 0, 0, 0, 169, 160, 0, 123, 176, 38, 43, 47, 119, 51, 30, 35, 37, 0, 13, 125, 126, 127, 0, 128, 0, 129, 0, 130, 0, 131, 0, 132, 133, 0, 134, 0, 135, 0, 136, 137, 0, 147, 148, 0, 85, 84, 0, 162, 0, 0, 167, 168, 169, 169, 0, 161, 0, 50, 10, 0, 0, 139, 140, 141, 142, 138, 143, 144, 145, 0, 78, 81, 0, 159, 158, 157, 119, 170, 0, 172, 124, 48, 14, 0, 12, 91, 0, 94, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 106, 0, 0, 0, 0, 113, 0, 0, 163, 0, 0, 146, 83, 173, 0, 175, 15, 93, 95, 96, 97, 0, 0, 121, 100, 101, 102, 103, 0, 0, 107, 108, 109, 0, 0, 122, 0, 110, 0, 112, 174, 0, 115, 0, 0, 104, 105, 0, 0, 0, 0, 111, 171, 0, 99, 114, 116, 122, 118, 0, 0, 0, 117, 98 }; #ifndef lint static char yaccpar_sccsid[] = "@(#)yaccpar 4.1 (Berkeley) 2/11/83"; #endif not lint # # define YYFLAG -1000 # define YYERROR goto yyerrlab # define YYACCEPT return(0) # define YYABORT return(1) /* parser for yacc output */ #ifdef YYDEBUG int yydebug = 0; /* 1 for debugging */ #endif YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ int yychar = -1; /* current input token number */ int yynerrs = 0; /* number of errors */ short yyerrflag = 0; /* error recovery flag */ yyparse() { short yys[YYMAXDEPTH]; short yyj, yym; register YYSTYPE *yypvt; register short yystate, *yyps, yyn; register YYSTYPE *yypv; register short *yyxi; yystate = 0; yychar = -1; yynerrs = 0; yyerrflag = 0; yyps= &yys[-1]; yypv= &yyv[-1]; yystack: /* put a state and value onto the stack */ #ifdef YYDEBUG if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar ); #endif if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } *yyps = yystate; ++yypv; *yypv = yyval; yynewstate: yyn = yypact[yystate]; if( yyn<= YYFLAG ) goto yydefault; /* simple state */ if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ yychar = -1; yyval = yylval; yystate = yyn; if( yyerrflag > 0 ) --yyerrflag; goto yystack; } yydefault: /* default state action */ if( (yyn=yydef[yystate]) == -2 ) { if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; /* look through exception table */ for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ while( *(yyxi+=2) >= 0 ){ if( *yyxi == yychar ) break; } if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ } if( yyn == 0 ){ /* error */ /* error ... attempt to resume parsing */ switch( yyerrflag ){ case 0: /* brand new error */ yyerror( "syntax error" ); yyerrlab: ++yynerrs; case 1: case 2: /* incompletely recovered error ... try again */ yyerrflag = 3; /* find a state where "error" is a legal shift action */ while ( yyps >= yys ) { yyn = yypact[*yyps] + YYERRCODE; if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ yystate = yyact[yyn]; /* simulate a shift of "error" */ goto yystack; } yyn = yypact[*yyps]; /* the current yyps has no shift onn "error", pop stack */ #ifdef YYDEBUG if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); #endif --yyps; --yypv; } /* there is no state on the stack with an error shift ... abort */ yyabort: return(1); case 3: /* no shift yet; clobber input char */ #ifdef YYDEBUG if( yydebug ) printf( "error recovery discards char %d\n", yychar ); #endif if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ yychar = -1; goto yynewstate; /* try again in the same state */ } } /* reduction by production yyn */ #ifdef YYDEBUG if( yydebug ) printf("reduce %d\n",yyn); #endif yyps -= yyr2[yyn]; yypvt = yypv; yypv -= yyr2[yyn]; yyval = yypv[1]; yym=yyn; /* consult goto table to find next state */ yyn = yyr1[yyn]; yyj = yypgo[yyn] + *yyps + 1; if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; switch(yym){ case 2: # line 137 "cgram.y" ftnend(); break; case 3: # line 140 "cgram.y" { curclass = SNULL; blevel = 0; } break; case 4: # line 142 "cgram.y" { curclass = SNULL; blevel = 0; } break; case 5: # line 146 "cgram.y" { yypvt[-1].nodep->in.op = FREE; } break; case 6: # line 148 "cgram.y" { yypvt[-2].nodep->in.op = FREE; } break; case 7: # line 149 "cgram.y" { defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass==STATIC?STATIC:EXTDEF ); } break; case 8: # line 152 "cgram.y" { if( blevel ) cerror( "function level error" ); if( reached ) retstat |= NRETVAL; yypvt[-3].nodep->in.op = FREE; ftnend(); } break; case 10: # line 163 "cgram.y" { curclass = SNULL; yypvt[-2].nodep->in.op = FREE; } break; case 11: # line 164 "cgram.y" { blevel = 1; } break; case 13: # line 169 "cgram.y" { bccode(); locctr(PROG); } break; case 14: # line 175 "cgram.y" { yypvt[-1].nodep->in.op = FREE; } break; case 15: # line 177 "cgram.y" { yypvt[-2].nodep->in.op = FREE; } break; case 18: # line 183 "cgram.y" { yyval.nodep = mkty(INT,0,INT); curclass = SNULL; } break; case 19: # line 186 "cgram.y" { yyval.nodep = yypvt[-0].nodep; } break; case 21: # line 189 "cgram.y" { yyval.nodep = mkty(INT,0,INT); } break; case 22: # line 191 "cgram.y" { curclass = SNULL ; } break; case 23: # line 193 "cgram.y" { yypvt[-2].nodep->in.type = types( yypvt[-2].nodep->in.type, yypvt[-0].nodep->in.type, UNDEF ); yypvt[-0].nodep->in.op = FREE; } break; case 24: # line 200 "cgram.y" { curclass = yypvt[-0].intval; } break; case 26: # line 205 "cgram.y" { yypvt[-1].nodep->in.type = types( yypvt[-1].nodep->in.type, yypvt[-0].nodep->in.type, UNDEF ); yypvt[-0].nodep->in.op = FREE; } break; case 27: # line 209 "cgram.y" { yypvt[-2].nodep->in.type = types( yypvt[-2].nodep->in.type, yypvt[-1].nodep->in.type, yypvt[-0].nodep->in.type ); yypvt[-1].nodep->in.op = yypvt[-0].nodep->in.op = FREE; } break; case 30: # line 217 "cgram.y" { yyval.nodep = dclstruct(yypvt[-4].intval); } break; case 31: # line 219 "cgram.y" { yyval.nodep = rstruct(yypvt[-0].intval,0); stwart = instruct; } break; case 32: # line 223 "cgram.y" { yyval.intval = bstruct(-1,0); stwart = SEENAME; } break; case 33: # line 225 "cgram.y" { yyval.intval = bstruct(yypvt[-0].intval,0); stwart = SEENAME; } break; case 36: # line 233 "cgram.y" { moedef( yypvt[-0].intval ); } break; case 37: # line 235 "cgram.y" { strucoff = yypvt[-0].intval; moedef( yypvt[-2].intval ); } break; case 38: # line 239 "cgram.y" { yyval.nodep = dclstruct(yypvt[-4].intval); } break; case 39: # line 241 "cgram.y" { yyval.nodep = rstruct(yypvt[-0].intval,yypvt[-1].intval); } break; case 40: # line 245 "cgram.y" { yyval.intval = bstruct(-1,yypvt[-0].intval); stwart=0; } break; case 41: # line 247 "cgram.y" { yyval.intval = bstruct(yypvt[-0].intval,yypvt[-1].intval); stwart=0; } break; case 44: # line 255 "cgram.y" { curclass = SNULL; stwart=0; yypvt[-1].nodep->in.op = FREE; } break; case 45: # line 257 "cgram.y" { if( curclass != MOU ){ curclass = SNULL; } else { sprintf( fakename, "$%dFAKE", fake++ ); #ifdef FLEXNAMES /* TD810306 */ /* No need to hash this, we won't look it up */ defid( tymerge(yypvt[-0].nodep, bdty(NAME,NIL,lookup( savestr(fakename), SMOS ))), curclass ); #else defid( tymerge(yypvt[-0].nodep, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass ); #endif werror("structure typed union member must be named"); } stwart = 0; yypvt[-0].nodep->in.op = FREE; } break; case 46: # line 277 "cgram.y" { defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass); stwart = instruct; } break; case 47: # line 278 "cgram.y" {yyval.nodep=yypvt[-2].nodep;} break; case 48: # line 279 "cgram.y" { defid( tymerge(yypvt[-4].nodep,yypvt[-0].nodep), curclass); stwart = instruct; } break; case 50: # line 284 "cgram.y" { if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); if( yypvt[-0].intval<0 || yypvt[-0].intval >= FIELD ){ uerror( "illegal field size" ); yypvt[-0].intval = 1; } defid( tymerge(yypvt[-3].nodep,yypvt[-2].nodep), FIELD|yypvt[-0].intval ); yyval.nodep = NIL; } break; case 51: # line 294 "cgram.y" { if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); falloc( stab, yypvt[-0].intval, -1, yypvt[-2].nodep ); /* alignment or hole */ yyval.nodep = NIL; } break; case 52: # line 299 "cgram.y" { yyval.nodep = NIL; } break; case 53: # line 304 "cgram.y" { umul: yyval.nodep = bdty( UNARY MUL, yypvt[-0].nodep, 0 ); } break; case 54: # line 307 "cgram.y" { uftn: yyval.nodep = bdty( UNARY CALL, yypvt[-2].nodep, 0 ); } break; case 55: # line 310 "cgram.y" { uary: yyval.nodep = bdty( LB, yypvt[-2].nodep, 0 ); } break; case 56: # line 313 "cgram.y" { bary: if( (int)yypvt[-1].intval <= 0 ) werror( "zero or negative subscript" ); yyval.nodep = bdty( LB, yypvt[-3].nodep, yypvt[-1].intval ); } break; case 57: # line 317 "cgram.y" { yyval.nodep = bdty( NAME, NIL, yypvt[-0].intval ); } break; case 58: # line 319 "cgram.y" { yyval.nodep=yypvt[-1].nodep; } break; case 59: # line 322 "cgram.y" { goto umul; } break; case 60: # line 324 "cgram.y" { goto uftn; } break; case 61: # line 326 "cgram.y" { goto uary; } break; case 62: # line 328 "cgram.y" { goto bary; } break; case 63: # line 330 "cgram.y" { yyval.nodep = yypvt[-1].nodep; } break; case 64: # line 332 "cgram.y" { if( blevel!=0 ) uerror("function declaration in bad context"); yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,yypvt[-2].intval), 0 ); stwart = 0; } break; case 65: # line 338 "cgram.y" { yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,yypvt[-1].intval), 0 ); stwart = 0; } break; case 66: # line 345 "cgram.y" { /* turn off typedefs for argument names */ stwart = SEENAME; if( stab[yypvt[-1].intval].sclass == SNULL ) stab[yypvt[-1].intval].stype = FTN; } break; case 67: # line 354 "cgram.y" { ftnarg( yypvt[-0].intval ); stwart = SEENAME; } break; case 68: # line 356 "cgram.y" { ftnarg( yypvt[-0].intval ); stwart = SEENAME; } break; case 71: # line 362 "cgram.y" {yyval.nodep=yypvt[-2].nodep;} break; case 73: # line 366 "cgram.y" { defid( yypvt[-0].nodep = tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass); beginit(yypvt[-0].nodep->tn.rval); } break; case 75: # line 373 "cgram.y" { nidcl( tymerge(yypvt[-1].nodep,yypvt[-0].nodep) ); } break; case 76: # line 375 "cgram.y" { defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), uclass(curclass) ); } break; case 77: # line 379 "cgram.y" { doinit( yypvt[-0].nodep ); endinit(); } break; case 78: # line 382 "cgram.y" { endinit(); } break; case 82: # line 392 "cgram.y" { doinit( yypvt[-0].nodep ); } break; case 83: # line 394 "cgram.y" { irbrace(); } break; case 88: # line 406 "cgram.y" { werror( "old-fashioned initialization: use =" ); } break; case 90: # line 411 "cgram.y" { ilbrace(); } break; case 91: # line 417 "cgram.y" { --blevel; if( blevel == 1 ) blevel = 0; clearst( blevel ); checkst( blevel ); autooff = *--psavbc; regvar = *--psavbc; } break; case 92: # line 427 "cgram.y" { if( blevel == 1 ) dclargs(); ++blevel; if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" ); *psavbc++ = regvar; *psavbc++ = autooff; } break; case 93: # line 436 "cgram.y" { ecomp( yypvt[-1].nodep ); } break; case 95: # line 439 "cgram.y" { deflab(yypvt[-1].intval); reached = 1; } break; case 96: # line 443 "cgram.y" { if( yypvt[-1].intval != NOLAB ){ deflab( yypvt[-1].intval ); reached = 1; } } break; case 97: # line 449 "cgram.y" { branch( contlab ); deflab( brklab ); if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1; else reached = 0; resetbc(0); } break; case 98: # line 456 "cgram.y" { deflab( contlab ); if( flostat & FCONT ) reached = 1; ecomp( buildtree( CBRANCH, buildtree( NOT, yypvt[-2].nodep, NIL ), bcon( yypvt[-6].intval ) ) ); deflab( brklab ); reached = 1; resetbc(0); } break; case 99: # line 464 "cgram.y" { deflab( contlab ); if( flostat&FCONT ) reached = 1; if( yypvt[-2].nodep ) ecomp( yypvt[-2].nodep ); branch( yypvt[-3].intval ); deflab( brklab ); if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; else reached = 0; resetbc(0); } break; case 100: # line 474 "cgram.y" { if( reached ) branch( brklab ); deflab( yypvt[-1].intval ); swend(); deflab(brklab); if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; resetbc(FCONT); } break; case 101: # line 482 "cgram.y" { if( brklab == NOLAB ) uerror( "illegal break"); else if(reached) branch( brklab ); flostat |= FBRK; if( brkflag ) goto rch; reached = 0; } break; case 102: # line 489 "cgram.y" { if( contlab == NOLAB ) uerror( "illegal continue"); else branch( contlab ); flostat |= FCONT; goto rch; } break; case 103: # line 495 "cgram.y" { retstat |= NRETVAL; branch( retlab ); rch: if( !reached ) werror( "statement not reached"); reached = 0; } break; case 104: # line 502 "cgram.y" { register NODE *temp; idname = curftn; temp = buildtree( NAME, NIL, NIL ); if(temp->in.type == TVOID) uerror("void function %s cannot return value", stab[idname].sname); temp->in.type = DECREF( temp->in.type ); temp = buildtree( RETURN, temp, yypvt[-1].nodep ); /* now, we have the type of the RHS correct */ tfree(temp->in.left); temp->in.op = FREE; ecomp( buildtree( FORCE, temp->in.right, NIL ) ); retstat |= RETVAL; branch( retlab ); reached = 0; } break; case 105: # line 519 "cgram.y" { register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); q->tn.rval = idname = yypvt[-1].intval; defid( q, ULABEL ); stab[idname].suse = -lineno; branch( stab[idname].offset ); goto rch; } break; case 110: # line 533 "cgram.y" { register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); q->tn.rval = yypvt[-1].intval; defid( q, LABEL ); reached = 1; } break; case 111: # line 540 "cgram.y" { addcase(yypvt[-1].nodep); reached = 1; } break; case 112: # line 544 "cgram.y" { reached = 1; adddef(); flostat |= FDEF; } break; case 113: # line 550 "cgram.y" { savebc(); if( !reached ) werror( "loop not entered at top"); brklab = getlab(); contlab = getlab(); deflab( yyval.intval = getlab() ); reached = 1; } break; case 114: # line 559 "cgram.y" { ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( yyval.intval=getlab()) ) ) ; reached = 1; } break; case 115: # line 564 "cgram.y" { if( reached ) branch( yyval.intval = getlab() ); else yyval.intval = NOLAB; deflab( yypvt[-2].intval ); reached = 1; } break; case 116: # line 572 "cgram.y" { savebc(); if( !reached ) werror( "loop not entered at top"); if( yypvt[-1].nodep->in.op == ICON && yypvt[-1].nodep->tn.lval != 0 ) flostat = FLOOP; deflab( contlab = getlab() ); reached = 1; brklab = getlab(); if( flostat == FLOOP ) tfree( yypvt[-1].nodep ); else ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( brklab) ) ); } break; case 117: # line 583 "cgram.y" { if( yypvt[-3].nodep ) ecomp( yypvt[-3].nodep ); else if( !reached ) werror( "loop not entered at top"); savebc(); contlab = getlab(); brklab = getlab(); deflab( yyval.intval = getlab() ); reached = 1; if( yypvt[-1].nodep ) ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( brklab) ) ); else flostat |= FLOOP; } break; case 118: # line 595 "cgram.y" { savebc(); brklab = getlab(); ecomp( buildtree( FORCE, makety(yypvt[-1].nodep,INT,0,INT), NIL ) ); branch( yyval.intval = getlab() ); swstart(); reached = 0; } break; case 119: # line 604 "cgram.y" { yyval.intval=instruct; stwart=instruct=0; } break; case 120: # line 606 "cgram.y" { yyval.intval = icons( yypvt[-0].nodep ); instruct=yypvt[-1].intval; } break; case 122: # line 610 "cgram.y" { yyval.nodep=0; } break; case 124: # line 615 "cgram.y" { goto bop; } break; case 125: # line 619 "cgram.y" { preconf: if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){ precplaint: if( hflag ) werror( "precedence confusion possible: parenthesize!" ); } bop: yyval.nodep = buildtree( yypvt[-1].intval, yypvt[-2].nodep, yypvt[-0].nodep ); } break; case 126: # line 629 "cgram.y" { yypvt[-1].intval = COMOP; goto bop; } break; case 127: # line 633 "cgram.y" { goto bop; } break; case 128: # line 635 "cgram.y" { if(yychar==SHIFTOP) goto precplaint; else goto bop; } break; case 129: # line 637 "cgram.y" { if(yychar==SHIFTOP ) goto precplaint; else goto bop; } break; case 130: # line 639 "cgram.y" { if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } break; case 131: # line 641 "cgram.y" { goto bop; } break; case 132: # line 643 "cgram.y" { goto preconf; } break; case 133: # line 645 "cgram.y" { if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } break; case 134: # line 647 "cgram.y" { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } break; case 135: # line 649 "cgram.y" { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } break; case 136: # line 651 "cgram.y" { goto bop; } break; case 137: # line 653 "cgram.y" { goto bop; } break; case 138: # line 655 "cgram.y" { abop: yyval.nodep = buildtree( ASG yypvt[-2].intval, yypvt[-3].nodep, yypvt[-0].nodep ); } break; case 139: # line 659 "cgram.y" { goto abop; } break; case 140: # line 661 "cgram.y" { goto abop; } break; case 141: # line 663 "cgram.y" { goto abop; } break; case 142: # line 665 "cgram.y" { goto abop; } break; case 143: # line 667 "cgram.y" { goto abop; } break; case 144: # line 669 "cgram.y" { goto abop; } break; case 145: # line 671 "cgram.y" { goto abop; } break; case 146: # line 673 "cgram.y" { yyval.nodep=buildtree(QUEST, yypvt[-4].nodep, buildtree( COLON, yypvt[-2].nodep, yypvt[-0].nodep ) ); } break; case 147: # line 676 "cgram.y" { werror( "old-fashioned assignment operator" ); goto bop; } break; case 148: # line 678 "cgram.y" { goto bop; } break; case 150: # line 682 "cgram.y" { yyval.nodep = buildtree( yypvt[-0].intval, yypvt[-1].nodep, bcon(1) ); } break; case 151: # line 684 "cgram.y" { ubop: yyval.nodep = buildtree( UNARY yypvt[-1].intval, yypvt[-0].nodep, NIL ); } break; case 152: # line 688 "cgram.y" { if( ISFTN(yypvt[-0].nodep->in.type) || ISARY(yypvt[-0].nodep->in.type) ){ werror( "& before array or function: ignored" ); yyval.nodep = yypvt[-0].nodep; } else goto ubop; } break; case 153: # line 695 "cgram.y" { goto ubop; } break; case 154: # line 697 "cgram.y" { yyval.nodep = buildtree( yypvt[-1].intval, yypvt[-0].nodep, NIL ); } break; case 155: # line 701 "cgram.y" { yyval.nodep = buildtree( yypvt[-1].intval==INCR ? ASG PLUS : ASG MINUS, yypvt[-0].nodep, bcon(1) ); } break; case 156: # line 706 "cgram.y" { yyval.nodep = doszof( yypvt[-0].nodep ); } break; case 157: # line 708 "cgram.y" { yyval.nodep = buildtree( CAST, yypvt[-2].nodep, yypvt[-0].nodep ); yyval.nodep->in.left->in.op = FREE; yyval.nodep->in.op = FREE; yyval.nodep = yyval.nodep->in.right; } break; case 158: # line 714 "cgram.y" { yyval.nodep = doszof( yypvt[-1].nodep ); } break; case 159: # line 716 "cgram.y" { yyval.nodep = buildtree( UNARY MUL, buildtree( PLUS, yypvt[-3].nodep, yypvt[-1].nodep ), NIL ); } break; case 160: # line 718 "cgram.y" { yyval.nodep=buildtree(UNARY CALL,yypvt[-1].nodep,NIL); } break; case 161: # line 720 "cgram.y" { yyval.nodep=buildtree(CALL,yypvt[-2].nodep,yypvt[-1].nodep); } break; case 162: # line 722 "cgram.y" { if( yypvt[-1].intval == DOT ){ if( notlval( yypvt[-2].nodep ) )uerror("structure reference must be addressable"); yypvt[-2].nodep = buildtree( UNARY AND, yypvt[-2].nodep, NIL ); } idname = yypvt[-0].intval; yyval.nodep = buildtree( STREF, yypvt[-2].nodep, buildtree( NAME, NIL, NIL ) ); } break; case 163: # line 730 "cgram.y" { idname = yypvt[-0].intval; /* recognize identifiers in initializations */ if( blevel==0 && stab[idname].stype == UNDEF ) { register NODE *q; #ifndef FLEXNAMES werror( "undeclared initializer name %.8s", stab[idname].sname ); #else werror( "undeclared initializer name %s", stab[idname].sname ); #endif q = block( FREE, NIL, NIL, INT, 0, INT ); q->tn.rval = idname; defid( q, EXTERN ); } yyval.nodep=buildtree(NAME,NIL,NIL); stab[yypvt[-0].intval].suse = -lineno; } break; case 164: # line 748 "cgram.y" { yyval.nodep=bcon(0); yyval.nodep->tn.lval = lastcon; yyval.nodep->tn.rval = NONAME; if( yypvt[-0].intval ) yyval.nodep->fn.csiz = yyval.nodep->in.type = ctype(LONG); } break; case 165: # line 754 "cgram.y" { yyval.nodep=buildtree(FCON,NIL,NIL); yyval.nodep->fpn.dval = dcon; } break; case 166: # line 758 "cgram.y" { yyval.nodep = getstr(); /* get string contents */ } break; case 167: # line 760 "cgram.y" { yyval.nodep=yypvt[-1].nodep; } break; case 168: # line 764 "cgram.y" { yyval.nodep = tymerge( yypvt[-1].nodep, yypvt[-0].nodep ); yyval.nodep->in.op = NAME; yypvt[-1].nodep->in.op = FREE; } break; case 169: # line 772 "cgram.y" { yyval.nodep = bdty( NAME, NIL, -1 ); } break; case 170: # line 774 "cgram.y" { yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } break; case 171: # line 776 "cgram.y" { yyval.nodep = bdty( UNARY CALL, yypvt[-3].nodep, 0 ); } break; case 172: # line 778 "cgram.y" { goto umul; } break; case 173: # line 780 "cgram.y" { goto uary; } break; case 174: # line 782 "cgram.y" { goto bary; } break; case 175: # line 784 "cgram.y" { yyval.nodep = yypvt[-1].nodep; } break; case 176: # line 788 "cgram.y" { if( stab[yypvt[-1].intval].stype == UNDEF ){ register NODE *q; q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); q->tn.rval = yypvt[-1].intval; defid( q, EXTERN ); } idname = yypvt[-1].intval; yyval.nodep=buildtree(NAME,NIL,NIL); stab[idname].suse = -lineno; } break; } goto yystack; /* stack new state and value */ } ine 682 "cgram.y" { yyval.nodep = buildtree( yypvt[-0].intval, yypvt[-1].nodep, bcon(1) ); } break; case 151: # line 684 "cgram.y" { ubop: yyval.nodep = buildtree( UNARY yypvt[-1].intval, yypvt[-0].nodep, NIL ); } break; case 152: # line 688 "cgram.y" { isumacc/cc/ccom/cgram.y 444 0 12 47506 3470501545 10131 %term NAME 2 %term STRING 3 %term ICON 4 %term FCON 5 %term PLUS 6 %term MINUS 8 %term MUL 11 %term AND 14 %term OR 17 %term ER 19 %term QUEST 21 %term COLON 22 %term ANDAND 23 %term OROR 24 /* special interfaces for yacc alone */ /* These serve as abbreviations of 2 or more ops: ASOP =, = ops RELOP LE,LT,GE,GT EQUOP EQ,NE DIVOP DIV,MOD SHIFTOP LS,RS ICOP ICR,DECR UNOP NOT,COMPL STROP DOT,STREF */ %term ASOP 25 %term RELOP 26 %term EQUOP 27 %term DIVOP 28 %term SHIFTOP 29 %term INCOP 30 %term UNOP 31 %term STROP 32 /* reserved words, etc */ %term TYPE 33 %term CLASS 34 %term STRUCT 35 %term RETURN 36 %term GOTO 37 %term IF 38 %term ELSE 39 %term SWITCH 40 %term BREAK 41 %term CONTINUE 42 %term WHILE 43 %term DO 44 %term FOR 45 %term DEFAULT 46 %term CASE 47 %term SIZEOF 48 %term ENUM 49 /* little symbols, etc. */ /* namely, LP ( RP ) LC { RC } LB [ RB ] CM , SM ; */ %term LP 50 %term RP 51 %term LC 52 %term RC 53 %term LB 54 %term RB 55 %term CM 56 %term SM 57 %term ASSIGN 58 /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts /* these involved: if/else recognizing functions in various contexts, including declarations error recovery */ %left CM %right ASOP ASSIGN %right QUEST COLON %left OROR %left ANDAND %left OR %left ER %left AND %left EQUOP %left RELOP %left SHIFTOP %left PLUS MINUS %left MUL DIVOP %right UNOP %right INCOP SIZEOF %left LB LP STROP %{ # include "mfile1" %} /* define types */ %start ext_def_list %type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart enum_head str_head name_lp %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl cast_type null_decl funct_idn declarator fdeclarator nfdeclarator elist %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ER ANDAND OROR ASSIGN STROP INCOP UNOP ICON %token <nodep> TYPE %% %{ static int fake = 0; #ifndef FLEXNAMES static char fakename[NCHNAM+1]; #else static char fakename[24]; #endif %} ext_def_list: ext_def_list external_def | =ftnend(); ; external_def: data_def ={ curclass = SNULL; blevel = 0; } | error ={ curclass = SNULL; blevel = 0; } ; data_def: oattributes SM ={ $1->in.op = FREE; } | oattributes init_dcl_list SM ={ $1->in.op = FREE; } | oattributes fdeclarator { defid( tymerge($1,$2), curclass==STATIC?STATIC:EXTDEF ); } function_body ={ if( blevel ) cerror( "function level error" ); if( reached ) retstat |= NRETVAL; $1->in.op = FREE; ftnend(); } ; function_body: arg_dcl_list compoundstmt ; arg_dcl_list: arg_dcl_list attributes declarator_list SM ={ curclass = SNULL; $2->in.op = FREE; } | ={ blevel = 1; } ; stmt_list: stmt_list statement | /* empty */ ={ bccode(); locctr(PROG); } ; dcl_stat_list : dcl_stat_list attributes SM ={ $2->in.op = FREE; } | dcl_stat_list attributes init_dcl_list SM ={ $2->in.op = FREE; } | /* empty */ ; oattributes: attributes | /* VOID */ ={ $$ = mkty(INT,0,INT); curclass = SNULL; } ; attributes: class type ={ $$ = $2; } | type class | class ={ $$ = mkty(INT,0,INT); } | type ={ curclass = SNULL ; } | type class type ={ $1->in.type = types( $1->in.type, $3->in.type, UNDEF ); $3->in.op = FREE; } ; class: CLASS ={ curclass = $1; } ; type: TYPE | TYPE TYPE ={ $1->in.type = types( $1->in.type, $2->in.type, UNDEF ); $2->in.op = FREE; } | TYPE TYPE TYPE ={ $1->in.type = types( $1->in.type, $2->in.type, $3->in.type ); $2->in.op = $3->in.op = FREE; } | struct_dcl | enum_dcl ; enum_dcl: enum_head LC moe_list optcomma RC ={ $$ = dclstruct($1); } | ENUM NAME ={ $$ = rstruct($2,0); stwart = instruct; } ; enum_head: ENUM ={ $$ = bstruct(-1,0); stwart = SEENAME; } | ENUM NAME ={ $$ = bstruct($2,0); stwart = SEENAME; } ; moe_list: moe | moe_list CM moe ; moe: NAME ={ moedef( $1 ); } | NAME ASSIGN con_e ={ strucoff = $3; moedef( $1 ); } ; struct_dcl: str_head LC type_dcl_list optsemi RC ={ $$ = dclstruct($1); } | STRUCT NAME ={ $$ = rstruct($2,$1); } ; str_head: STRUCT ={ $$ = bstruct(-1,$1); stwart=0; } | STRUCT NAME ={ $$ = bstruct($2,$1); stwart=0; } ; type_dcl_list: type_declaration | type_dcl_list SM type_declaration ; type_declaration: type declarator_list ={ curclass = SNULL; stwart=0; $1->in.op = FREE; } | type ={ if( curclass != MOU ){ curclass = SNULL; } else { sprintf( fakename, "$%dFAKE", fake++ ); #ifdef FLEXNAMES /* TD810306 */ /* No need to hash this, we won't look it up */ defid( tymerge($1, bdty(NAME,NIL,lookup( savestr(fakename), SMOS ))), curclass ); #else defid( tymerge($1, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass ); #endif werror("structure typed union member must be named"); } stwart = 0; $1->in.op = FREE; } ; declarator_list: declarator ={ defid( tymerge($<nodep>0,$1), curclass); stwart = instruct; } | declarator_list CM {$<nodep>$=$<nodep>0;} declarator ={ defid( tymerge($<nodep>0,$4), curclass); stwart = instruct; } ; declarator: nfdeclarator | nfdeclarator COLON con_e %prec CM ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); if( $3<0 || $3 >= FIELD ){ uerror( "illegal field size" ); $3 = 1; } defid( tymerge($<nodep>0,$1), FIELD|$3 ); $$ = NIL; } | COLON con_e %prec CM ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); falloc( stab, $2, -1, $<nodep>0 ); /* alignment or hole */ $$ = NIL; } | error ={ $$ = NIL; } ; /* int (a)(); is not a function --- sorry! */ nfdeclarator: MUL nfdeclarator ={ umul: $$ = bdty( UNARY MUL, $2, 0 ); } | nfdeclarator LP RP ={ uftn: $$ = bdty( UNARY CALL, $1, 0 ); } | nfdeclarator LB RB ={ uary: $$ = bdty( LB, $1, 0 ); } | nfdeclarator LB con_e RB ={ bary: if( (int)$3 <= 0 ) werror( "zero or negative subscript" ); $$ = bdty( LB, $1, $3 ); } | NAME ={ $$ = bdty( NAME, NIL, $1 ); } | LP nfdeclarator RP ={ $$=$2; } ; fdeclarator: MUL fdeclarator ={ goto umul; } | fdeclarator LP RP ={ goto uftn; } | fdeclarator LB RB ={ goto uary; } | fdeclarator LB con_e RB ={ goto bary; } | LP fdeclarator RP ={ $$ = $2; } | name_lp name_list RP ={ if( blevel!=0 ) uerror("function declaration in bad context"); $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); stwart = 0; } | name_lp RP ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); stwart = 0; } ; name_lp: NAME LP ={ /* turn off typedefs for argument names */ stwart = SEENAME; if( stab[$1].sclass == SNULL ) stab[$1].stype = FTN; } ; name_list: NAME ={ ftnarg( $1 ); stwart = SEENAME; } | name_list CM NAME ={ ftnarg( $3 ); stwart = SEENAME; } | error ; /* always preceeded by attributes: thus the $<nodep>0's */ init_dcl_list: init_declarator %prec CM | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator ; /* always preceeded by attributes */ xnfdeclarator: nfdeclarator ={ defid( $1 = tymerge($<nodep>0,$1), curclass); beginit($1->tn.rval); } | error ; /* always preceeded by attributes */ init_declarator: nfdeclarator ={ nidcl( tymerge($<nodep>0,$1) ); } | fdeclarator ={ defid( tymerge($<nodep>0,$1), uclass(curclass) ); } | xnfdeclarator optasgn e %prec CM ={ doinit( $3 ); endinit(); } | xnfdeclarator optasgn LC init_list optcomma RC ={ endinit(); } | error ; init_list: initializer %prec CM | init_list CM initializer ; initializer: e %prec CM ={ doinit( $1 ); } | ibrace init_list optcomma RC ={ irbrace(); } ; optcomma : /* VOID */ | CM ; optsemi : /* VOID */ | SM ; optasgn : /* VOID */ ={ werror( "old-fashioned initialization: use =" ); } | ASSIGN ; ibrace : LC ={ ilbrace(); } ; /* STATEMENTS */ compoundstmt: begin dcl_stat_list stmt_list RC ={ --blevel; if( blevel == 1 ) blevel = 0; clearst( blevel ); checkst( blevel ); autooff = *--psavbc; regvar = *--psavbc; } ; begin: LC ={ if( blevel == 1 ) dclargs(); ++blevel; if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" ); *psavbc++ = regvar; *psavbc++ = autooff; } ; statement: e SM ={ ecomp( $1 ); } | compoundstmt | ifprefix statement ={ deflab($1); reached = 1; } | ifelprefix statement ={ if( $1 != NOLAB ){ deflab( $1 ); reached = 1; } } | whprefix statement ={ branch( contlab ); deflab( brklab ); if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1; else reached = 0; resetbc(0); } | doprefix statement WHILE LP e RP SM ={ deflab( contlab ); if( flostat & FCONT ) reached = 1; ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) ); deflab( brklab ); reached = 1; resetbc(0); } | forprefix .e RP statement ={ deflab( contlab ); if( flostat&FCONT ) reached = 1; if( $2 ) ecomp( $2 ); branch( $1 ); deflab( brklab ); if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; else reached = 0; resetbc(0); } | switchpart statement ={ if( reached ) branch( brklab ); deflab( $1 ); swend(); deflab(brklab); if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; resetbc(FCONT); } | BREAK SM ={ if( brklab == NOLAB ) uerror( "illegal break"); else if(reached) branch( brklab ); flostat |= FBRK; if( brkflag ) goto rch; reached = 0; } | CONTINUE SM ={ if( contlab == NOLAB ) uerror( "illegal continue"); else branch( contlab ); flostat |= FCONT; goto rch; } | RETURN SM ={ retstat |= NRETVAL; branch( retlab ); rch: if( !reached ) werror( "statement not reached"); reached = 0; } | RETURN e SM ={ register NODE *temp; idname = curftn; temp = buildtree( NAME, NIL, NIL ); if(temp->in.type == TVOID) uerror("void function %s cannot return value", stab[idname].sname); temp->in.type = DECREF( temp->in.type ); temp = buildtree( RETURN, temp, $2 ); /* now, we have the type of the RHS correct */ tfree(temp->in.left); temp->in.op = FREE; ecomp( buildtree( FORCE, temp->in.right, NIL ) ); retstat |= RETVAL; branch( retlab ); reached = 0; } | GOTO NAME SM ={ register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); q->tn.rval = idname = $2; defid( q, ULABEL ); stab[idname].suse = -lineno; branch( stab[idname].offset ); goto rch; } | SM | error SM | error RC | label statement ; label: NAME COLON ={ register NODE *q; q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); q->tn.rval = $1; defid( q, LABEL ); reached = 1; } | CASE e COLON ={ addcase($2); reached = 1; } | DEFAULT COLON ={ reached = 1; adddef(); flostat |= FDEF; } ; doprefix: DO ={ savebc(); if( !reached ) werror( "loop not entered at top"); brklab = getlab(); contlab = getlab(); deflab( $$ = getlab() ); reached = 1; } ; ifprefix: IF LP e RP ={ ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ; reached = 1; } ; ifelprefix: ifprefix statement ELSE ={ if( reached ) branch( $$ = getlab() ); else $$ = NOLAB; deflab( $1 ); reached = 1; } ; whprefix: WHILE LP e RP ={ savebc(); if( !reached ) werror( "loop not entered at top"); if( $3->in.op == ICON && $3->tn.lval != 0 ) flostat = FLOOP; deflab( contlab = getlab() ); reached = 1; brklab = getlab(); if( flostat == FLOOP ) tfree( $3 ); else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) ); } ; forprefix: FOR LP .e SM .e SM ={ if( $3 ) ecomp( $3 ); else if( !reached ) werror( "loop not entered at top"); savebc(); contlab = getlab(); brklab = getlab(); deflab( $$ = getlab() ); reached = 1; if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) ); else flostat |= FLOOP; } ; switchpart: SWITCH LP e RP ={ savebc(); brklab = getlab(); ecomp( buildtree( FORCE, makety($3,INT,0,INT), NIL ) ); branch( $$ = getlab() ); swstart(); reached = 0; } ; /* EXPRESSIONS */ con_e: { $<intval>$=instruct; stwart=instruct=0; } e %prec CM ={ $$ = icons( $2 ); instruct=$<intval>1; } ; .e: e | ={ $$=0; } ; elist: e %prec CM | elist CM e ={ goto bop; } ; e: e RELOP e ={ preconf: if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){ precplaint: if( hflag ) werror( "precedence confusion possible: parenthesize!" ); } bop: $$ = buildtree( $2, $1, $3 ); } | e CM e ={ $2 = COMOP; goto bop; } | e DIVOP e ={ goto bop; } | e PLUS e ={ if(yychar==SHIFTOP) goto precplaint; else goto bop; } | e MINUS e ={ if(yychar==SHIFTOP ) goto precplaint; else goto bop; } | e SHIFTOP e ={ if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } | e MUL e ={ goto bop; } | e EQUOP e ={ goto preconf; } | e AND e ={ if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } | e OR e ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } | e ER e ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } | e ANDAND e ={ goto bop; } | e OROR e ={ goto bop; } | e MUL ASSIGN e ={ abop: $$ = buildtree( ASG $2, $1, $4 ); } | e DIVOP ASSIGN e ={ goto abop; } | e PLUS ASSIGN e ={ goto abop; } | e MINUS ASSIGN e ={ goto abop; } | e SHIFTOP ASSIGN e ={ goto abop; } | e AND ASSIGN e ={ goto abop; } | e OR ASSIGN e ={ goto abop; } | e ER ASSIGN e ={ goto abop; } | e QUEST e COLON e ={ $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) ); } | e ASOP e ={ werror( "old-fashioned assignment operator" ); goto bop; } | e ASSIGN e ={ goto bop; } | term ; term: term INCOP ={ $$ = buildtree( $2, $1, bcon(1) ); } | MUL term ={ ubop: $$ = buildtree( UNARY $1, $2, NIL ); } | AND term ={ if( ISFTN($2->in.type) || ISARY($2->in.type) ){ werror( "& before array or function: ignored" ); $$ = $2; } else goto ubop; } | MINUS term ={ goto ubop; } | UNOP term ={ $$ = buildtree( $1, $2, NIL ); } | INCOP term ={ $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS, $2, bcon(1) ); } | SIZEOF term ={ $$ = doszof( $2 ); } | LP cast_type RP term %prec INCOP ={ $$ = buildtree( CAST, $2, $4 ); $$->in.left->in.op = FREE; $$->in.op = FREE; $$ = $$->in.right; } | SIZEOF LP cast_type RP %prec SIZEOF ={ $$ = doszof( $3 ); } | term LB e RB ={ $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); } | funct_idn RP ={ $$=buildtree(UNARY CALL,$1,NIL); } | funct_idn elist RP ={ $$=buildtree(CALL,$1,$2); } | term STROP NAME ={ if( $2 == DOT ){ if( notlval( $1 ) )uerror("structure reference must be addressable"); $1 = buildtree( UNARY AND, $1, NIL ); } idname = $3; $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) ); } | NAME ={ idname = $1; /* recognize identifiers in initializations */ if( blevel==0 && stab[idname].stype == UNDEF ) { register NODE *q; #ifndef FLEXNAMES werror( "undeclared initializer name %.8s", stab[idname].sname ); #else werror( "undeclared initializer name %s", stab[idname].sname ); #endif q = block( FREE, NIL, NIL, INT, 0, INT ); q->tn.rval = idname; defid( q, EXTERN ); } $$=buildtree(NAME,NIL,NIL); stab[$1].suse = -lineno; } | ICON ={ $$=bcon(0); $$->tn.lval = lastcon; $$->tn.rval = NONAME; if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG); } | FCON ={ $$=buildtree(FCON,NIL,NIL); $$->fpn.dval = dcon; } | STRING ={ $$ = getstr(); /* get string contents */ } | LP e RP ={ $$=$2; } ; cast_type: type null_decl ={ $$ = tymerge( $1, $2 ); $$->in.op = NAME; $1->in.op = FREE; } ; null_decl: /* empty */ ={ $$ = bdty( NAME, NIL, -1 ); } | LP RP ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } | LP null_decl RP LP RP ={ $$ = bdty( UNARY CALL, $2, 0 ); } | MUL null_decl ={ goto umul; } | null_decl LB RB ={ goto uary; } | null_decl LB con_e RB ={ goto bary; } | LP null_decl RP ={ $$ = $2; } ; funct_idn: NAME LP ={ if( stab[$1].stype == UNDEF ){ register NODE *q; q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); q->tn.rval = $1; defid( q, EXTERN ); } idname = $1; $$=buildtree(NAME,NIL,NIL); stab[idname].suse = -lineno; } | term LP ; %% NODE * mkty( t, d, s ) unsigned t; { return( block( TYPE, NIL, NIL, t, d, s ) ); } NODE * bdty( op, p, v ) NODE *p; { register NODE *q; q = block( op, p, NIL, INT, 0, INT ); switch( op ){ case UNARY MUL: case UNARY CALL: break; case LB: q->in.right = bcon(v); break; case NAME: q->tn.rval = v; break; default: cerror( "bad bdty" ); } return( q ); } dstash( n ){ /* put n into the dimension table */ if( curdim >= DIMTABSZ-1 ){ cerror( "dimension table overflow"); } dimtab[ curdim++ ] = n; } savebc() { if( psavbc > & asavbc[BCSZ-4 ] ){ cerror( "whiles, fors, etc. too deeply nested"); } *psavbc++ = brklab; *psavbc++ = contlab; *psavbc++ = flostat; *psavbc++ = swx; flostat = 0; } resetbc(mask){ swx = *--psavbc; flostat = *--psavbc | (flostat&mask); contlab = *--psavbc; brklab = *--psavbc; } addcase(p) NODE *p; { /* add case to switch */ p = optim( p ); /* change enum to ints */ if( p->in.op != ICON ){ uerror( "non-constant case expression"); return; } if( swp == swtab ){ uerror( "case not in switch"); return; } if( swp >= &swtab[SWITSZ] ){ cerror( "switch table overflow"); } swp->sval = p->tn.lval; deflab( swp->slab = getlab() ); ++swp; tfree(p); } adddef(){ /* add default case to switch */ if( swtab[swx].slab >= 0 ){ uerror( "duplicate default in switch"); return; } if( swp == swtab ){ uerror( "default not inside switch"); return; } deflab( swtab[swx].slab = getlab() ); } swstart(){ /* begin a switch block */ if( swp >= &swtab[SWITSZ] ){ cerror( "switch table overflow"); } swx = swp - swtab; swp->slab = -1; ++swp; } swend(){ /* end a switch block */ register struct sw *swbeg, *p, *q, *r, *r1; CONSZ temp; int tempi; swbeg = &swtab[swx+1]; /* sort */ r1 = swbeg; r = swp-1; while( swbeg < r ){ /* bubble largest to end */ for( q=swbeg; q<r; ++q ){ if( q->sval > (q+1)->sval ){ /* swap */ r1 = q+1; temp = q->sval; q->sval = r1->sval; r1->sval = temp; tempi = q->slab; q->slab = r1->slab; r1->slab = tempi; } } r = r1; r1 = swbeg; } /* it is now sorted */ for( p = swbeg+1; p<swp; ++p ){ if( p->sval == (p-1)->sval ){ uerror( "duplicate case in switch, %d", tempi=p->sval ); return; } } genswitch( swbeg-1, swp-swbeg ); swp = swbeg-1; } D, $1, NIL ); } idname = $3; $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) ); } | NAME ={ idname = $1; /* recognize identifiers in initialsumacc/cc/ccom/code.c 444 0 12 20230 3470501546 7706 #ifdef BOOTSTRAP #include "/usr/include/stdio.h" #include "/usr/include/signal.h" #else BOOTSTRAP # include <stdio.h> # include <signal.h> #endif BOOTSTRAP # include "mfile1" extern int usedregs; /* bit == 1 if reg was used in subroutine */ extern char *rnames[]; int proflag; extern int nospflag; /* nonzero if suppress stack probe in prolog */ int proflg = 0; int strftn = 0; /* is the current function one which returns a value */ FILE *tmpfile; FILE *outfile = stdout; branch( n ){ /* output a branch to label n */ /* exception is an ordinary function branching to retlab: then, return */ if( n == retlab && !strftn ) printf( " bra .L%d\n", retlab ); else printf( " bra .L%d\n", n ); } int lastloc = PROG; defalign(n) { /* cause the alignment to become a multiple of n */ n /= SZCHAR; if( lastloc != PROG && n > 1 ) printf( " .even\n" ); } locctr( l ){ register temp; /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */ if( l == lastloc ) return(l); temp = lastloc; lastloc = l; switch( l ){ case PROG: outfile = stdout; printf( " .text\n" ); break; case DATA: case ADATA: outfile = stdout; if( temp != DATA && temp != ADATA ) printf( " .data\n" ); break; case STRNG: case ISTRNG: outfile = tmpfile; break; case STAB: cerror( "locctr: STAB unused" ); break; default: cerror( "illegal location counter" ); } return( temp ); } deflab( n ){ /* output something to define the current position as label n */ fprintf( outfile, ".L%d:\n", n ); } int crslab = 10; getlab(){ /* return a number usable for a label */ return( ++crslab ); } efcode(){ /* code for the end of a function */ if( strftn ){ /* copy output (in r0) to caller */ register struct symtab *p; register int stlab; register int count; int size; p = &stab[curftn]; deflab( retlab ); retlab = getlab(); stlab = getlab(); printf( " movl d0,a0\n" ); printf( " movl #.L%d,a1\n" , stlab ); size = tsize( DECREF(p->stype), p->dimoff, p->sizoff ) / SZCHAR; count = size/4; while( count-- ) { printf( " movl a0@+,a1@+\n" ); } if (size&2) { printf( " movw a0@+,a1@+\n" ); } if (size&1) { printf( " movb a0@+,a1@+\n" ); } printf( " movl #.L%d,d0\n", stlab ); printf( " .bss\n .even\n.L%d:\n .=.+%d.\n .text\n", stlab, size ); /* turn off strftn flag, so return sequence will be generated */ strftn = 0; } branch( retlab ); p2bend(); } bfcode( a, n ) int a[]; { /* code for the beginning of a function; a is an array of indices in stab for the arguments; n is the number */ register i; register temp; register struct symtab *p; int off; char type; locctr( PROG ); p = &stab[curftn]; defnam( p ); temp = p->stype; temp = DECREF(temp); strftn = (temp==STRTY) || (temp==UNIONTY); retlab = getlab(); if( proflag ){ int plab; plab = getlab(); printf( " movl #.L%d,a0\n", plab ); printf( " jbsr mcount\n" ); printf( " .data\n.L%d: .long 0\n .text\n", plab ); } /* routine prolog */ printf( " link a6,#-_F%d\n", ftnno ); #ifdef STACKPROBE if( !nospflag ) printf( " tstl sp@(-_P%d)\n", ftnno ); #endif /* of ifdef STACKPROBE */ printf( " moveml #_S%d,a6@(-_F%d)\n", ftnno, ftnno ); usedregs = 0; off = ARGINIT; for( i=0; i<n; ++i ){ p = &stab[a[i]]; if( p->sclass == REGISTER ){ temp = p->offset; /* save register number */ p->sclass = PARAM; /* forget that it is a register */ p->offset = NOOFFSET; oalloc( p, &off ); if (p->stype==CHAR || p->stype==UCHAR) type = 'b'; else if (p->stype==SHORT || p->stype==USHORT) type = 'w'; else type = 'l'; printf( " mov%c a6@(%d),%s\n", type, p->offset/SZCHAR, rnames[temp] ); usedregs |= 1<<temp; p->offset = temp; /* remember register number */ p->sclass = REGISTER; /* remember that it is a register */ } else { if( oalloc( p, &off ) ) cerror( "bad argument" ); } } printf("| A%d = %d\n", ftnno, off/SZCHAR); } bccode(){ /* called just before the first executable statment */ /* by now, the automatics and register variables are allocated */ SETOFF( autooff, SZINT ); /* set aside store area offset */ p2bbeg( autooff, regvar ); } ejobcode( flag ){ /* called just before final exit */ /* flag is 1 if errors, 0 if none */ } aobeg(){ /* called before removing automatics from stab */ } aocode(p) struct symtab *p; { /* called when automatic p removed from stab */ } aoend(){ /* called after removing all automatics from stab */ } defnam( p ) register struct symtab *p; { /* define the current location as the name p->sname */ if( p->sclass == EXTDEF ){ printf( " .globl %s\n", exname( p->sname ) ); } if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset ); else printf( "%s:\n", exname( p->sname ) ); } bycode( t, i ){ /* put byte i+1 in a string */ i &= 07; if( t < 0 ){ /* end of the string */ if( i != 0 ) fprintf( outfile, "\n" ); } else { /* stash byte t into string */ if( i == 0 ) fprintf( outfile, " .byte " ); else fprintf( outfile, "," ); fprintf( outfile, "%d", t ); if( i == 07 ) fprintf( outfile, "\n" ); } } zecode( n ){ /* n integer words of zeros */ OFFSZ temp; register i; if( n <= 0 ) return; for( i=1; i<=n; i++ ) printf( " .long 0\n" ); temp = n; inoff += temp*SZINT; } fldal( t ) unsigned t; { /* return the alignment of field of type t */ uerror( "illegal field type" ); return( ALINT ); } fldty( p ) struct symtab *p; { /* fix up type of field p */ ; } where(c){ /* print location of error */ /* c is either 'u', 'c', or 'w' */ fprintf( stderr, "%s, line %d: ", ftitle, lineno ); } char *tmpname = "/tmp/pcXXXXXX"; main( argc, argv ) char *argv[]; { int dexit(); register int c; register int i; int r; for( i=1; i<argc; ++i ) if( argv[i][0] == '-' && argv[i][1] == 'X' && argv[i][2] == 'p' ) { proflag = 1; } mktemp(tmpname); if(signal( SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, dexit); if(signal( SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, dexit); if(signal( SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, dexit); tmpfile = fopen( tmpname, "w" ); if(tmpfile == NULL) cerror( "Cannot open temp file" ); r = mainp1( argc, argv ); tmpfile = freopen( tmpname, "r", tmpfile ); if( tmpfile != NULL ) while((c=getc(tmpfile)) != EOF ) putchar(c); else cerror( "Lost temp file" ); unlink(tmpname); return( r ); } dexit( v ) { unlink(tmpname); exit(1); } genswitch(p,n) register struct sw *p;{ /* p points to an array of structures, each consisting of a constant value and a label. The first is >=0 if there is a default label; its value is the label number The entries p[1] to p[n] are the nontrivial cases */ register i; register CONSZ j, range; register dlab, swlab; range = p[n].sval-p[1].sval; if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */ dlab = p->slab >= 0 ? p->slab : getlab(); if( p[1].sval ){ printf( " subl #" ); printf( CONFMT, p[1].sval ); printf( ",d0\n" ); } /* note that this is a cl; it thus checks for numbers below range as well as out of range. */ #ifdef BOOTSTRAP printf( " cmpl #%d,d0\n", range ); #else BOOTSTRAP printf( " cmpl #%ld,d0\n", range ); #endif BOOTSTRAP printf( " bhi .L%d\n", dlab ); printf( " addw d0,d0\n" ); printf( " movw pc@(6,d0:w),d0\n" ); printf( " jmp pc@(2,d0:w)\n" ); /* output table */ printf( ".L%d = .\n", swlab=getlab() ); for( i=1,j=p[1].sval; i<=n; ++j ){ printf( " .word .L%d-.L%d\n", ( j == p[i].sval ) ? p[i++].slab : dlab, swlab ); } if( p->slab< 0 ) deflab( dlab ); return; } genbinary(p,1,n,0); } genbinary(p,lo,hi,lab) register struct sw *p; { register int i,lab1; if (lab) printf(".L%d:",lab); /* print label, if any */ if (hi-lo > 4) { /* if lots more, do another level */ i = lo + ((hi-lo)>>1); /* index at which we'll break this time */ printf( " cmpl #" ); printf( CONFMT, p[i].sval ); printf( ",d0\n beq .L%d\n", p[i].slab ); printf( " bgt .L%d\n", lab1=getlab() ); genbinary(p,lo,i-1,0); genbinary(p,i+1,hi,lab1); } else { /* simple switch code for remaining cases */ for( i=lo; i<=hi; ++i ) { printf( " cmpl #" ); printf( CONFMT, p[i].sval ); printf( ",d0\n beq .L%d\n", p[i].slab ); } if( p->slab>=0 ) branch( p->slab ); } } ors, 0 if none */ } aobeg(){ /* called before removing automatics from stab */ } aocode(p) struct symtab *p; { /* called when automatic p removed from stab */ } aoend(){ /* called after removing all automatics from stab */ } defnam( p ) register struct symtab *p; { /* define the current location as the name p->sname */ if( p->sclass == EXTDEF )sumacc/cc/ccom/comm1.c 444 0 12 50 3470501546 7726 # include "mfile1" # include "common" OFFSZ temp; register i; if( n <= 0 ) return; for( i=1; i<=n; i++ ) printf( " .long 0\n" ); temp = n; inoff += temp*SZINT; } fldal( t ) unsigned t; { /* return the alignment of field of type t */ uerror( "illegal field type" ); return( ALINT ); } fldty( p ) struct symtab *p; { /* fix up type of field p */ ; } where(c){ /* print location of error */ /* c is either 'u', 'c', or 'w' */ fprintf( stderr, "%s, line %d: ", ftitle, lineno ); } char *tmpnasumacc/cc/ccom/common 444 0 12 14077 3470501547 10060 # ifndef EXIT # define EXIT exit # endif int nerrors = 0; /* number of errors */ unsigned int offsz; unsigned caloff(){ register i; unsigned int temp; unsigned int off; temp = 1; i = 0; do { temp <<= 1; ++i; } while( temp > 0 ); off = 1 << (i-1); return (off); } NODE *lastfree; /* pointer to last free node; (for allocator) */ /* VARARGS1 */ uerror( s, a ) char *s; { /* nonfatal error message */ /* the routine where is different for pass 1 and pass 2; /* it tells where the error took place */ ++nerrors; where('u'); fprintf( stderr, s, a ); fprintf( stderr, "\n" ); if( nerrors > 30 ) cerror( "too many errors"); } /* VARARGS1 */ cerror( s, a, b, c ) char *s; { /* compiler error: die */ where('c'); if( nerrors && nerrors <= 30 ){ /* give the compiler the benefit of the doubt */ fprintf( stderr, "cannot recover from earlier errors: goodbye!\n" ); } else { fprintf( stderr, "compiler error: " ); fprintf( stderr, s, a, b, c ); fprintf( stderr, "\n" ); } EXIT(1); } /* VARARGS1 */ werror( s, a, b ) char *s; { /* warning */ where('w'); fprintf( stderr, "warning: " ); fprintf( stderr, s, a, b ); fprintf( stderr, "\n" ); } tinit(){ /* initialize expression tree search */ NODE *p; for( p=node; p<= &node[TREESZ-1]; ++p ) p->in.op = FREE; lastfree = node; } # define TNEXT(p) (p== &node[TREESZ-1]?node:p+1) NODE * talloc(){ NODE *p, *q; q = lastfree; for( p = TNEXT(q); p!=q; p= TNEXT(p)) if( p->in.op ==FREE ) return(lastfree=p); cerror( "out of tree space; simplify expression"); /* NOTREACHED */ } tcheck(){ /* ensure that all nodes have been freed */ NODE *p; if( !nerrors ) for( p=node; p<= &node[TREESZ-1]; ++p ) if( p->in.op != FREE ) cerror( "wasted space: %o", p ); tinit(); } tfree( p ) NODE *p; { /* free the tree p */ extern tfree1(); if( p->in.op != FREE ) walkf( p, tfree1 ); } tfree1(p) NODE *p; { if( p == 0 ) cerror( "freeing blank tree!"); else p->in.op = FREE; } fwalk( t, f, down ) register NODE *t; int (*f)(); { int down1, down2; more: down1 = down2 = 0; (*f)( t, down, &down1, &down2 ); switch( optype( t->in.op ) ){ case BITYPE: fwalk( t->in.left, f, down1 ); t = t->in.right; down = down2; goto more; case UTYPE: t = t->in.left; down = down1; goto more; } } walkf( t, f ) register NODE *t; int (*f)(); { register opty; opty = optype(t->in.op); if( opty != LTYPE ) walkf( t->in.left, f ); if( opty == BITYPE ) walkf( t->in.right, f ); (*f)( t ); } int dope[ DSIZE ]; char *opst[DSIZE]; struct dopest { int dopeop; char opst[8]; int dopeval; } indope[] = { NAME, "NAME", LTYPE, STRING, "STRING", LTYPE, REG, "REG", LTYPE, OREG, "OREG", LTYPE, ICON, "ICON", LTYPE, FCON, "FCON", LTYPE, CCODES, "CCODES", LTYPE, UNARY MINUS, "U-", UTYPE, UNARY MUL, "U*", UTYPE, UNARY AND, "U&", UTYPE, UNARY CALL, "UCALL", UTYPE|CALLFLG, UNARY FORTCALL, "UFCALL", UTYPE|CALLFLG, NOT, "!", UTYPE|LOGFLG, COMPL, "~", UTYPE, FORCE, "FORCE", UTYPE, INIT, "INIT", UTYPE, SCONV, "SCONV", UTYPE, PCONV, "PCONV", UTYPE, PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, ASG PLUS, "+=", BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG, MINUS, "-", BITYPE|FLOFLG|SIMPFLG, ASG MINUS, "-=", BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG, MUL, "*", BITYPE|FLOFLG|MULFLG, ASG MUL, "*=", BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG, AND, "&", BITYPE|SIMPFLG|COMMFLG, ASG AND, "&=", BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG, QUEST, "?", BITYPE, COLON, ":", BITYPE, ANDAND, "&&", BITYPE|LOGFLG, OROR, "||", BITYPE|LOGFLG, CM, ",", BITYPE, COMOP, ",OP", BITYPE, ASSIGN, "=", BITYPE|ASGFLG, DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG, ASG DIV, "/=", BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG, MOD, "%", BITYPE|DIVFLG, ASG MOD, "%=", BITYPE|DIVFLG|ASGFLG|ASGOPFLG, LS, "<<", BITYPE|SHFFLG, ASG LS, "<<=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG, RS, ">>", BITYPE|SHFFLG, ASG RS, ">>=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG, OR, "|", BITYPE|COMMFLG|SIMPFLG, ASG OR, "|=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG, ER, "^", BITYPE|COMMFLG, ASG ER, "^=", BITYPE|COMMFLG|ASGFLG|ASGOPFLG, INCR, "++", BITYPE|ASGFLG, DECR, "--", BITYPE|ASGFLG, STREF, "->", BITYPE, CALL, "CALL", BITYPE|CALLFLG, FORTCALL, "FCALL", BITYPE|CALLFLG, EQ, "==", BITYPE|LOGFLG, NE, "!=", BITYPE|LOGFLG, LE, "<=", BITYPE|LOGFLG, LT, "<", BITYPE|LOGFLG, GE, ">", BITYPE|LOGFLG, GT, ">", BITYPE|LOGFLG, UGT, "UGT", BITYPE|LOGFLG, UGE, "UGE", BITYPE|LOGFLG, ULT, "ULT", BITYPE|LOGFLG, ULE, "ULE", BITYPE|LOGFLG, ARS, "A>>", BITYPE, TYPE, "TYPE", LTYPE, LB, "[", BITYPE, CBRANCH, "CBRANCH", BITYPE, FLD, "FLD", UTYPE, PMCONV, "PMCONV", BITYPE, PVCONV, "PVCONV", BITYPE, RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG, CAST, "CAST", BITYPE|ASGFLG|ASGOPFLG, GOTO, "GOTO", UTYPE, STASG, "STASG", BITYPE|ASGFLG, STARG, "STARG", UTYPE, STCALL, "STCALL", BITYPE|CALLFLG, UNARY STCALL, "USTCALL", UTYPE|CALLFLG, -1, 0 }; mkdope(){ register struct dopest *q; for( q = indope; q->dopeop >= 0; ++q ){ dope[q->dopeop] = q->dopeval; opst[q->dopeop] = q->opst; } } # ifndef BUG4 tprint( t ) TWORD t; { /* output a nice description of the type of t */ static char * tnames[] = { "undef", "farg", "char", "short", "int", "long", "float", "double", "strty", "unionty", "enumty", "moety", "uchar", "ushort", "unsigned", "ulong", "?", "?" }; for(;; t = DECREF(t) ){ if( ISPTR(t) ) printf( "PTR " ); else if( ISFTN(t) ) printf( "FTN " ); else if( ISARY(t) ) printf( "ARY " ); else { printf( "%s", tnames[t] ); return; } } } # endif #ifdef FLEXNAMES #define NTSTRBUF 40 #define TSTRSZ 2048 char itstrbuf[TSTRSZ]; char *tstrbuf[NTSTRBUF] = { itstrbuf }; char **curtstr = tstrbuf; int tstrused; char * tstr(cp) register char *cp; { register int i = strlen(cp); register char *dp; if (tstrused + i >= TSTRSZ) { if (++curtstr >= &tstrbuf[NTSTRBUF]) cerror("out of temporary string space"); tstrused = 0; if (*curtstr == 0) { dp = (char *)malloc(TSTRSZ); if (dp == 0) cerror("out of memory (tstr)"); *curtstr = dp; } } strcpy(dp = *curtstr+tstrused, cp); tstrused += i + 1; return (dp); } #endif rintf( ",d0\n beq .L%d\n", p[i].slab ); } if( p->slab>=0 ) branch( p->slab ); } } ors, 0 if none */ } aobeg(){ /* called before removing automatics from stab */ } aocode(p) struct symtab *p; { /* called when automatic p removed from stab */ } aoend(){ /* called after removing all automatics from stab */ } defnam( p ) register struct symtab *p; { /* define the current location as the name p->sname */ if( p->sclass == EXTDEF )sumacc/cc/ccom/local.c 444 0 12 16745 3470501547 10107 # include "mfile1" /* this file contains code which is dependent on the target machine */ /* V. Pratt Dec. 12 incorporated jks fix to fincode (insert sw) */ /* W. Nowicki July 1982 merged Stanford and LucasFilm changes */ NODE * cast( p, t ) register NODE *p; TWORD t; { /* cast node p to type t */ p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); p->in.left->in.op = FREE; p->in.op = FREE; return( p->in.right ); } NODE * clocal(p) NODE *p; { /* this is called to do local transformations on an expression tree preparitory to its being written out in intermediate code. */ /* the major essential job is rewriting the automatic variables and arguments in terms of REG and OREG nodes */ /* conversion ops which are not necessary are also clobbered here */ /* in addition, any special features (such as rewriting exclusive or) are easily handled here as well */ register struct symtab *q; register NODE *r; register o; register m, ml; switch( o = p->in.op ){ case NAME: if( p->tn.rval<0 || p->tn.rval==NONAME ) { /* already processed; ignore... */ return(p); } q = &stab[p->tn.rval]; switch( q->sclass ){ case AUTO: case PARAM: /* fake up a structure reference */ r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); r->tn.lval = 0; r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG); p = stref( block( STREF, r, p, 0, 0, 0 ) ); break; case ULABEL: case LABEL: case STATIC: if( q->slevel == 0 ) break; p->tn.lval = 0; p->tn.rval = -q->offset; break; case REGISTER: p->in.op = REG; p->tn.lval = 0; p->tn.rval = q->offset; break; } break; case LT: case LE: case GT: case GE: if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){ p->in.op += (ULT-LT); } break; case PCONV: /* do pointer conversions for char and shorts */ ml = p->in.left->in.type; if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) { p->in.op = SCONV; break; } /* pointers all have the same representation; the type is inherited */ p->in.left->in.type = p->in.type; p->in.left->fn.cdim = p->fn.cdim; p->in.left->fn.csiz = p->fn.csiz; p->in.op = FREE; return( p->in.left ); case SCONV: m = (p->in.type == FLOAT || p->in.type == DOUBLE ); ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE ); if( m != ml ) break; /* now, look for conversions downwards */ m = p->in.type; ml = p->in.left->in.type; if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ CONSZ val; val = p->in.left->tn.lval; switch( m ){ case CHAR: p->in.left->tn.lval = (char) val; break; case UCHAR: p->in.left->tn.lval = val & 0XFF; break; case USHORT: p->in.left->tn.lval = val & 0XFFFFL; break; case SHORT: p->in.left->tn.lval = (short)val; break; } p->in.left->in.type = m; } else if( p->in.left->in.op == FCON ){ /* simulate the conversion here */ p->in.left->in.type = m; } else break; /* clobber conversion */ p->in.op = FREE; return( p->in.left ); /* conversion gets clobbered */ case PVCONV: case PMCONV: if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); p->in.op = FREE; return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); } return(p); } andable( p ) NODE *p; { return(1); /* all names can have & taken on them */ } cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ autooff = AUTOINIT; } cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ switch (t) { case INT: case UNSIGNED: case SHORT: case USHORT: case CHAR: case UCHAR: return(1); default: if ( ISPTR(t) ) return(1); return(0); } } NODE * offcon( off, t, d, s ) OFFSZ off; TWORD t; { /* return a node, for structure references, which is suitable for being added to a pointer of type t, in order to be off bits offset into a structure */ register NODE *p; /* t, d, and s are the type, dimension offset, and sizeoffset */ /* in general they are necessary for offcon, but not on H'well */ p = bcon(0); p->tn.lval = off/SZCHAR; return(p); } static inwd /* current bit offset in word */; static long word /* word being built from fields */; incode( p, sz ) register NODE *p; { /* generate initialization code for assigning a constant c to a field of width sz */ /* we assume that the proper alignment has been obtained */ /* inoff is updated to have the proper final value */ /* we also assume sz < SZINT */ if((sz+inwd) > SZINT) cerror("incode: field > int"); word |= (p->tn.lval & ((1 << sz) -1)) << (SZINT - sz - inwd); inwd += sz; inoff += sz; while (inwd >= 16) { #ifdef BOOTSTRAP printf( " .word %d\n", (word>>16)&0xFFFFL ); #else printf( " .word %ld\n", (word>>16)&0xFFFFL ); #endif word <<= 16; inwd -= 16; } } #define sw(x) ((x>>16)&0xFFFF | (x<<16) & 0xFFFF0000) fincode( d, sz ) double d; { /* output code to initialize space of size sz to the value d */ /* the proper alignment has been obtained */ /* inoff is updated to have the proper final value */ /* on the target machine, write it out in octal! */ register long *mi = (int *)&d; if( sz==SZDOUBLE ) #ifdef BOOTSTRAP printf( " .long %d, %d\n", sw(mi[0]), sw(mi[1]) ); #else BOOTSTRAP printf( " .long 0x%X, 0x%X\n", mi[0], mi[1]); #endif BOOTSTRAP else #ifdef BOOTSTRAP printf( " .long %d\n", sw(mi[0]) ); #else BOOTSTRAP printf(" .long 0x%X\n", mi[0]); #endif BOOTSTRAP inoff += sz; } cinit( p, sz ) NODE *p; { /* arrange for the initialization of p into a space of size sz */ /* the proper alignment has been opbtained */ /* inoff is updated to have the proper final value */ ecode( p ); inoff += sz; } vfdzero( n ){ /* define n bits of zeros in a vfd */ if( n <= 0 ) return; inwd += n; inoff += n; while (inwd >= 16) { #ifdef BOOTSTRAP printf( " .word %d\n", (word>>16)&0xFFFFL ); #else printf( " .word %ld\n", (word>>16)&0xFFFFL ); #endif word <<= 16; inwd -= 16; } } char * exname( p ) char *p; { /* make a name look like an external name in the local machine */ #ifndef FLEXNAMES static char text[NCHNAM+1]; #else static char text[BUFSIZ+1]; #endif register i; #ifndef FLEXNAMES for( i=0; *p&&i<NCHNAM; ++i ){ #else for( i=0; *p; ++i){ #endif text[i] = *p++; } text[i] = '\0'; #ifndef FLEXNAMES text[NCHNAM] = '\0'; /* truncate */ #endif return( text ); } ctype( type ) TWORD type; { /* map types which are not defined on the local machine */ switch( BTYPE(type) ){ case LONG: MODTYPE(type,INT); break; case ULONG: MODTYPE(type,UNSIGNED); } return( type ); } noinit() { /* curid is a variable which is defined but is not initialized (and not a function ); This routine returns the stroage class for an uninitialized declaration */ return(EXTERN); } commdec( id ){ /* make a common declaration for id, if reasonable */ register struct symtab *q; OFFSZ off; q = &stab[id]; printf( " .comm %s,", exname( q->sname ) ); off = tsize( q->stype, q->dimoff, q->sizoff ); printf( CONFMT, off/SZCHAR ); printf( "\n" ); } isitlong( cb, ce ){ /* is lastcon to be long or short */ /* cb is the first character of the representation, ce the last */ if( ce == 'l' || ce == 'L' || lastcon >= (1L << (SZINT-1) ) ) return (1); return(0); } isitfloat( s ) char *s; { double atof(); dcon = atof(s); return( FCON ); } ecode( p ) NODE *p; { /* walk the tree and write out the nodes.. */ if( nerrors ) return; p2tree( p ); p2compile( p ); } cisreg( t ) TWORD t; { /* sumacc/cc/ccom/local2.c 444 0 12 53510 3470501547 10160 # include "mfile2" /* a lot of the machine dependent parts of the second pass */ /* Incorporated Terman fix to rmove - V. Pratt 2/17/82 */ /* W. Nowicki July 1982 merged Stanford and LucasFilm fixes */ /* W. Nowicki August 1982 incorporated MITs fix to multiply */ # define BITMASK(n) ((1L<<n)-1) lineid( l, fn ) char *fn; { /* identify line l and file fn */ printf( "| line %d, file %s\n", l, fn ); } int usedregs; /* flag word for registers used in current routine */ int maxtoff = 0; cntbits(i) register int i; { register int j,ans; for (ans=0, j=0; i!=0 && j<16; j++) { if (i&1) ans++; i>>= 1; } return(ans); } eobl2(){ extern int retlab; OFFSZ spoff; /* offset from stack pointer */ spoff = maxoff; spoff /= SZCHAR; SETOFF(spoff,2); usedregs &= 036374; /* only save regs used for reg vars */ spoff += 4*cntbits(usedregs); /* save at base of stack frame */ printf( ".L%d:", retlab); if (usedregs) printf( " moveml a6@(-_F%d),#%d\n", ftnno, usedregs ); printf( " unlk a6\n" ); printf( " rts\n" ); printf( "_F%d = %d\n", ftnno, spoff ); printf( "_S%d = %d\n", ftnno, usedregs ); #ifdef STACKPROBE printf( "_P%d = %d\n", ftnno, maxtoff + 8 ); #else /* not STACKPROBE */ printf( "| M%d = %d\n", ftnno, maxtoff ); #endif /* of ifdef STACKPROBE */ maxtoff = 0; if( fltused ) { fltused = 0; printf( " .globl fltused\n" ); } } struct hoptab { int opmask; char * opstring; } ioptab[]= { ASG PLUS, "add", ASG MINUS, "sub", ASG OR, "or", ASG AND, "and", ASG ER, "eor", ASG MUL, "mul", ASG DIV, "div", ASG MOD, "div", ASG LS, "sl", ASG RS, "sr", -1, "" }; hopcode( f, o ){ /* output the appropriate string from the above table */ register struct hoptab *q; for( q = ioptab; q->opmask>=0; ++q ){ if( q->opmask == o ){ printf( "%s", q->opstring ); if( f == 'F' ) printf( "f" ); return; } } cerror( "no hoptab for %s", opst[o] ); } char * rnames[]= { /* keyed to register number tokens */ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" }; int rstatus[] = { SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG, SBREG, }; NODE *brnode; int brcase; int toff = 0; /* number of stack locations used for args */ zzzcode( p, c ) NODE *p; { register m,temp; switch( c ){ case 'C': switch (p->in.left->in.op) { case ICON: printf("\tjbsr\t"); acon(p->in.left); return; case REG: printf("\tjbsr\t"); adrput(p->in.left); printf("@"); return; case NAME: case OREG: printf("\tmovl\t"); adrput(p->in.left); printf(",a0\n\tjbsr\ta0@"); return; default: cerror("bad subroutine name"); } case 'L': m = p->in.left->in.type; goto suffix; case 'R': m = p->in.right->in.type; goto suffix; case 'B': m = p->in.type; /* fall into suffix: */ suffix: if( m == CHAR || m == UCHAR ) printf( "b" ); else if( m == SHORT || m == USHORT ) printf( "w" ); else printf( "l" ); return; case 'N': /* logical ops, turned into 0-1 */ /* use register given by register 1 */ cbgen( 0, m=getlab(), 'I' ); deflab( p->bn.label ); printf( " clrl %s\n", rnames[temp = getlr( p, '1' )->tn.rval] ); usedregs |= 1<<temp; deflab( m ); p->in.type = INT; return; case 'I': cbgen( p->in.op, p->bn.label, c ); return; /* stack management macros */ case '-': printf( "sp@-" ); case 'P': toff += 4; if (toff > maxtoff) maxtoff = toff; return; case '0': toff = 0; return; case '~': /* complimented CR */ p->in.right->tn.lval = ~p->in.right->tn.lval; conput( getlr( p, 'R' ) ); p->in.right->tn.lval = ~p->in.right->tn.lval; return; case 'M': /* negated CR */ p->in.right->tn.lval = -p->in.right->tn.lval; case 'O': conput( getlr( p, 'R' ) ); p->in.right->tn.lval = -p->in.right->tn.lval; return; case 'T': /* Truncate longs for type conversions: INT|UNSIGNED -> CHAR|UCHAR|SHORT|USHORT increment offset to second word */ m = p->in.type; p = p->in.left; switch( p->in.op ){ case NAME: case OREG: if (p->in.type==SHORT || p->in.type==USHORT) p->tn.lval += (m==CHAR || m==UCHAR) ? 1 : 0; else p->tn.lval += (m==CHAR || m==UCHAR) ? 3 : 2; return; case REG: return; default: cerror( "Illegal ZT type conversion" ); return; } case 'U': cerror( "Illegal ZU" ); /* NO RETURN */ case 'W': /* structure size */ if( p->in.op == STASG ) printf( "%d", p->stn.stsize); else cerror( "Not a structure" ); return; case 'S': /* structure assignment */ { register NODE *l, *r; register size, i; if( p->in.op == STASG ){ l = p->in.left; r = p->in.right; } else if( p->in.op == STARG ){ /* store an arg onto the stack */ r = p->in.left; } else cerror( "STASG bad" ); if( r->in.op == ICON ) r->in.op = NAME; else if( r->in.op == REG ) r->in.op = OREG; else if( r->in.op != OREG ) cerror( "STASG-r" ); size = p->stn.stsize; r->tn.lval += size; l->tn.lval += size; while( size ){ /* simple load/store loop */ i = (size > 2) ? 4 : 2; r->tn.lval -= i; expand( r, FOREFF,(i==2)?"\tmovw\tAR,":"\tmovl\tAR," ); l->tn.lval -= i; expand( l, FOREFF, "AR\n" ); size -= i; } if( r->in.op == NAME ) r->in.op = ICON; else if( r->in.op == OREG ) r->in.op = REG; } break; default: cerror( "illegal zzzcode" ); } } rmove( rt, rs, t ) TWORD t; { if ( t == DOUBLE ) { printf( " movl %s,%s\n", rnames[rs+1], rnames[rt+1] ); usedregs |= 1<<(rs+1); usedregs |= 1<<(rt+1); } printf( " movl %s,%s\n", rnames[rs], rnames[rt] ); usedregs |= 1<<rs; usedregs |= 1<<rt; } struct respref respref[] = { INTAREG|INTBREG, INTAREG|INTBREG, INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|SNAME|STARNM|SCON, INTEMP, INTEMP, FORARG, FORARG, #ifndef Stanford INTAREG, SOREG|SNAME|INAREG, #else Stanford INTAREG, SOREG|SNAME, #endif Stanford 0, 0 }; setregs(){ /* set up temporary registers */ register i; register int naregs = (maxtreg>>8)&0377; /* use any unused variable registers as scratch registers */ maxtreg & = 0377; fregs = maxtreg>=MINRVAR ? maxtreg + 1 : MINRVAR; if( xdebug ){ /* -x changes number of free regs to 2, -xx to 3, etc. */ if( (xdebug+1) < fregs ) fregs = xdebug+1; } for( i=MINRVAR; i<=MAXRVAR; i++ ) rstatus[i] = i<fregs ? SAREG|STAREG : SAREG; for( i=MINRVAR; i<=MAXRVAR; i++ ) rstatus[i+8] = i<naregs ? SBREG|STBREG : SBREG; } szty(t) TWORD t; { /* size, in words, needed to hold thing of type t */ /* really is the number of registers to hold type t */ return(t==DOUBLE ? 2 : 1); } rewfld( p ) NODE *p; { return(1); } callreg(p) NODE *p; { return( D0 ); } shltype( o, p ) NODE *p; { if( o == NAME|| o==REG || o == ICON || o == OREG ) return( 1 ); return( o==UNARY MUL && shumul(p->in.left) ); } flshape( p ) register NODE *p; { register o = p->in.op; if( o==NAME || o==REG || o==ICON || o==OREG ) return( 1 ); return( o==UNARY MUL && shumul(p->in.left)==STARNM ); } shtemp( p ) register NODE *p; { if( p->in.op == UNARY MUL ) p = p->in.left; if( p->in.op == REG || p->in.op == OREG ) return( !istreg( p->tn.rval ) ); return( p->in.op == NAME || p->in.op == ICON ); } spsz( t, v ) TWORD t; CONSZ v; { /* is v the size to increment something of type t */ if( !ISPTR(t) ) return( 0 ); t = DECREF(t); if( ISPTR(t) ) return( v == 4 ); switch( t ){ case UCHAR: case CHAR: return( v == 1 ); case SHORT: case USHORT: return( v == 2 ); case INT: case UNSIGNED: case FLOAT: return( v == 4 ); case DOUBLE: return( v == 8 ); } return( 0 ); } indexreg( p ) register NODE *p; { if ( p->in.op==REG && p->tn.rval>=A0 && p->tn.rval<=SP) return(1); return(0); } shumul( p ) register NODE *p; { register o; o = p->in.op; if( indexreg(p) ) return( STARNM ); if( o == INCR && indexreg(p->in.left) && p->in.right->in.op==ICON && p->in.right->in.name[0] == '\0' && spsz( p->in.left->in.type, p->in.right->tn.lval ) ) return( STARREG ); return( 0 ); } adrcon( val ) CONSZ val; { printf( CONFMT, val ); } conput( p ) register NODE *p; { switch( p->in.op ){ case ICON: acon( p ); return; case REG: printf( "%s", rnames[p->tn.rval] ); usedregs |= 1<<p->tn.rval; return; default: cerror( "illegal conput" ); } } insput( p ) NODE *p; { cerror( "insput" ); } upput( p ) NODE *p; { /* output the address of the second word in the pair pointed to by p (for LONGs)*/ CONSZ save; if( p->in.op == FLD ){ p = p->in.left; } save = p->tn.lval; switch( p->in.op ){ case NAME: p->tn.lval += SZINT/SZCHAR; acon( p ); break; case ICON: /* addressable value of the constant */ p->tn.lval &= BITMASK(SZINT); printf( "#" ); acon( p ); break; case REG: printf( "%s", rnames[p->tn.rval+1] ); usedregs |= 1<<(p->tn.rval + 1); break; case OREG: p->tn.lval += SZINT/SZCHAR; if( p->tn.rval == A6 ){ /* in the argument region */ if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); } printf( "%s@", rnames[p->tn.rval] ); usedregs |= 1<<p->tn.rval; if( p->tn.lval != 0 || p->in.name[0] != '\0' ) { printf("("); acon( p ); printf(")"); } break; default: cerror( "illegal upper address" ); break; } p->tn.lval = save; } adrput( p ) register NODE *p; { /* output an address, with offsets, from p */ if( p->in.op == FLD ){ p = p->in.left; } switch( p->in.op ){ case NAME: acon( p ); return; case ICON: /* addressable value of the constant */ if( szty( p->in.type ) == 2 ) { /* print the high order value */ CONSZ save; save = p->tn.lval; p->tn.lval = ( p->tn.lval >> SZINT ) & BITMASK(SZINT); printf( "#" ); acon( p ); p->tn.lval = save; return; } printf( "#" ); acon( p ); return; case REG: printf( "%s", rnames[p->tn.rval] ); usedregs |= 1<<p->tn.rval; return; case OREG: if( p->tn.rval == A6 ){ /* in the argument region */ if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); printf( "a6@(" ); printf( CONFMT, p->tn.lval ); printf( ")" ); return; } printf( "%s@", rnames[p->tn.rval] ); usedregs |= 1<<p->tn.rval; if( p->tn.lval != 0 || p->in.name[0] != '\0' ) { printf("("); acon( p ); printf(")"); } break; case UNARY MUL: /* STARNM or STARREG found */ if( tshape(p, STARNM) ) { adrput( p->in.left); printf( "@" ); } else { /* STARREG - really auto inc or dec */ /* turn into OREG so replacement node will reflect the value of the expression */ register i; register NODE *q, *l; l = p->in.left; q = l->in.left; p->in.op = OREG; p->in.rall = q->in.rall; p->tn.lval = q->tn.lval; p->tn.rval = q->tn.rval; #ifndef FLEXNAMES for( i=0; i<NCHNAM; i++ ) p->in.name[i] = q->in.name[i]; #else p->in.name = q->in.name; #endif if( l->in.op == INCR ) { adrput( p ); printf( "+" ); p->tn.lval -= l->in.right->tn.lval; } else { /* l->in.op == ASG MINUS */ printf( "-" ); adrput( p ); } tfree( l ); } return; default: cerror( "illegal address" ); return; } } acon( p ) register NODE *p; { /* print out a constant */ if( p->in.name[0] == '\0' ){ /* constant only */ printf( CONFMT, p->tn.lval); } else if( p->tn.lval == 0 ) { /* name only */ #ifndef FLEXNAMES printf( "%.8s", p->in.name ); #else printf( "%s", p->in.name ); #endif } else { /* name + offset */ #ifndef FLEXNAMES printf( "%.8s+", p->in.name ); #else printf( "%s+", p->in.name); #endif printf( CONFMT, p->tn.lval ); } } genscall( p, cookie ) register NODE *p; { /* structure valued call */ return( gencall( p, cookie ) ); } gencall( p, cookie ) register NODE *p; { /* generate the call given by p */ register temp; register m; if( p->in.right ) temp = argsize( p->in.right ); else temp = 0; if( p->in.right ){ /* generate args */ genargs( p->in.right ); } if( !shltype( p->in.left->in.op, p->in.left ) ) { order( p->in.left, INBREG|SOREG ); } p->in.op = UNARY CALL; m = match( p, INTAREG|INTBREG ); popargs( temp ); return(m != MDONE); } popargs( size ) register size; { /* pop arguments from stack */ toff -= size/2; if( toff == 0 && size >= 2 ) size -= 2; switch( size ) { case 0: break; default: printf( "\t%s\t#%d,sp\n", size<=8 ? "addql":"addl", size); } } char * ccbranches[] = { " beq .L%d\n", " bne .L%d\n", " ble .L%d\n", " blt .L%d\n", " bge .L%d\n", " bgt .L%d\n", " bls .L%d\n", " bcs .L%d\n", /* blo */ " bcc .L%d\n", /* bhis */ " bhi .L%d\n", }; /* long branch table This table, when indexed by a logical operator, selects a set of three logical conditions required to generate long comparisons and branches. A zero entry indicates that no branch is required. E.G.: The <= operator would generate: cmp AL,AR jlt lable / 1st entry LT -> lable jgt 1f / 2nd entry GT -> 1f cmp UL,UR jlos lable / 3rd entry ULE -> lable 1: */ int lbranches[][3] = { /*EQ*/ 0, NE, EQ, /*NE*/ NE, 0, NE, /*LE*/ LT, GT, ULE, /*LT*/ LT, GT, ULT, /*GE*/ GT, LT, UGE, /*GT*/ GT, LT, UGT, /*ULE*/ ULT, UGT, ULE, /*ULT*/ ULT, UGT, ULT, /*UGE*/ UGT, ULT, UGE, /*UGT*/ UGT, ULT, UGT, }; /* logical relations when compared in reverse order (cmp R,L) */ extern short revrel[] ; cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ register *plb; int lab1f; if( o == 0 ) printf( " bra .L%d\n", lab ); else if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); else { switch( brcase ) { case 'A': case 'C': plb = lbranches[ o-EQ ]; lab1f = getlab(); expand( brnode, FORCC, brcase=='C' ? "\tcmp\tAL,AR\n" : "\ttst\tAR\n" ); if( *plb != 0 ) printf( ccbranches[*plb-EQ], lab); if( *++plb != 0 ) printf( ccbranches[*plb-EQ], lab1f); expand( brnode, FORCC, brcase=='C' ? "\tcmp\tUL,UR\n" : "\ttst\tUR\n" ); printf( ccbranches[*++plb-EQ], lab); deflab( lab1f ); reclaim( brnode, RNULL, 0 ); break; default: if( mode=='F' ) o = revrel[ o-EQ ]; printf( ccbranches[o-EQ], lab ); break; } brcase = 0; brnode = 0; } } nextcook( p, cookie ) NODE *p; { /* we have failed to match p with cookie; try another */ if( cookie == FORREW ) return( 0 ); /* hopeless! */ if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); return( FORREW ); } lastchance( p, cook ) NODE *p; { /* forget it! */ return(0); } struct functbl { int fop; TWORD ftype; char *func; } opfunc[] = { MUL, INT, "lmul", DIV, INT, "ldiv", MOD, INT, "lrem", ASG MUL, INT, "almul", ASG DIV, INT, "aldiv", ASG MOD, INT, "alrem", MUL, UNSIGNED, "ulmul", DIV, UNSIGNED, "uldiv", MOD, UNSIGNED, "ulrem", ASG MUL, UNSIGNED, "aulmul", ASG DIV, UNSIGNED, "auldiv", ASG MOD, UNSIGNED, "aulrem", PLUS, DOUBLE, "fadd", MINUS, DOUBLE, "fsub", MUL, DOUBLE, "fmul", DIV, DOUBLE, "fdiv", UNARY MINUS, DOUBLE, "fneg", UNARY MINUS, FLOAT, "fneg", ASG PLUS, DOUBLE, "afadd", ASG MINUS, DOUBLE, "afsub", ASG MUL, DOUBLE, "afmul", ASG DIV, DOUBLE, "afdiv", ASG PLUS, FLOAT, "afaddf", ASG MINUS, FLOAT, "afsubf", ASG MUL, FLOAT, "afmulf", ASG DIV, FLOAT, "afdivf", 0, 0, 0 }; hardops(p) register NODE *p; { /* change hard to do operators into function calls. */ register NODE *q; register struct functbl *f; register o; register TWORD t; o = p->in.op; t = (o == MUL) ? p->in.left->in.type : p->in.type; if (o==SCONV) { hardconv(p); return; } for( f=opfunc; f->fop; f++ ) { if( o==f->fop && t==f->ftype ) goto convert; } return; /* need address of left node for ASG OP */ /* WARNING - this won't work for long in a REG */ convert: if( asgop( o ) ) { switch( p->in.left->in.op ) { case UNARY MUL: /* convert to address */ p->in.left->in.op = FREE; p->in.left = p->in.left->in.left; break; case NAME: /* convert to ICON pointer */ p->in.left->in.op = ICON; p->in.left->in.type = INCREF( p->in.left->in.type ); break; case OREG: /* convert OREG to address */ p->in.left->in.op = REG; p->in.left->in.type = INCREF( p->in.left->in.type ); if( p->in.left->tn.lval != 0 ) { q = talloc(); q->in.op = PLUS; q->in.rall = NOPREF; q->in.type = p->in.left->in.type; q->in.left = p->in.left; q->in.right = talloc(); q->in.right->in.op = ICON; q->in.right->in.rall = NOPREF; q->in.right->in.type = INT; q->in.right->in.name[0] = '\0'; q->in.right->tn.lval = p->in.left->tn.lval; q->in.right->tn.rval = 0; p->in.left->tn.lval = 0; p->in.left = q; } break; /* rewrite "foo <op>= bar" as "foo = foo <op> bar" for foo in a reg */ case REG: q = talloc(); q->in.op = p->in.op - 1; /* change <op>= to <op> */ q->in.rall = p->in.rall; q->in.type = p->in.type; q->in.left = talloc(); q->in.right = p->in.right; p->in.op = ASSIGN; p->in.right = q; q = q->in.left; /* make a copy of "foo" */ q->in.op = p->in.left->in.op; q->in.rall = p->in.left->in.rall; q->in.type = p->in.left->in.type; q->tn.lval = p->in.left->tn.lval; q->tn.rval = p->in.left->tn.rval; hardops(p->in.right); return; default: cerror( "Bad address for hard ops" ); /* NO RETURN */ } } /* build comma op for args to function */ if ( optype(p->in.op) == BITYPE ) { q = talloc(); q->in.op = CM; q->in.rall = NOPREF; q->in.type = INT; q->in.left = p->in.left; q->in.right = p->in.right; } else q = p->in.left; p->in.op = CALL; p->in.right = q; /* put function name in left node of call */ p->in.left = q = talloc(); q->in.op = ICON; q->in.rall = NOPREF; q->in.type = INCREF( FTN + p->in.type ); #ifndef FLEXNAMES strcpy( q->in.name, f->func ); #else q->in.name = f->func; #endif q->tn.lval = 0; q->tn.rval = 0; return; } /* do fix and float conversions */ hardconv(p) register NODE *p; { register NODE *q; register TWORD t,tl; int m,ml; t = p->in.type; tl = p->in.left->in.type; m = t==DOUBLE || t==FLOAT; ml = tl==DOUBLE || tl==FLOAT; if (m==ml || logop(p->in.left->in.op)) return; p->in.op = CALL; p->in.right = p->in.left; /* put function name in left node of call */ p->in.left = q = talloc(); q->in.op = ICON; q->in.rall = NOPREF; q->in.type = INCREF( FTN + p->in.type ); #ifndef FLEXNAMES strcpy( q->in.name, m ? "float" : "fix" ); #else q->in.name = m ? "float" : "fix"; #endif q->tn.lval = 0; q->tn.rval = 0; } /* return 1 if node is a SCONV from short to int */ shortconv( p ) register NODE *p; { if ( p->in.op==SCONV && p->in.type==INT && p->in.left->in.type==SHORT) return( 1 ); return( 0 ); } /* return 1 if node is a SCONV from Float to Double */ floatconv( p ) register NODE *p; { if ( p->in.op==SCONV && p->in.type==DOUBLE && p->in.left->in.type==FLOAT) return( 1 ); return( 0 ); } /* do local tree transformations and optimizations */ optim2( p ) register NODE *p; { register NODE *q; /* multiply of two shorts to produce an int can be done directly * in the hardware. */ if ( p->in.op==MUL && p->in.type==INT && shortconv(p->in.left) && (shortconv(p->in.right) || (p->in.right->in.op==ICON && p->in.right->in.name[0] == '\0' && p->in.right->tn.lval>=-32768L && p->in.right->tn.lval<=32767L))) { p->in.left = (q = p->in.left)->in.left; q->in.op = FREE; if ( p->in.right->in.op==ICON ) p->in.right->in.type = SHORT; else { p->in.right = (q = p->in.right)->in.left; q->in.op = FREE; } } /* * The following valiant attempt at optimizing floating * compares depends on the floating representation to be * reasonable, which it is not, so I am undoing it except for * The equality operators. Sigh. * WIN 8-82 */ if (logop(p->in.op) && (p->in.op==EQ || p->in.op==NE) && ((q = p->in.left)->in.type==FLOAT || q->in.type==DOUBLE) && ((q = p->in.right)->in.type==FLOAT || q->in.type==DOUBLE)) { if ( floatconv(p->in.left) && floatconv(p->in.right) ) { p->in.left = (q = p->in.left)->in.left; q->in.op = FREE; p->in.right = (q = p->in.right)->in.left; q->in.op = FREE; } # ifndef Stanford else { /* change <flt exp>1 <logop> <flt exp>2 to * (<exp>1 - <exp>2) <logop> 0.0 */ q = talloc(); q->in.op = MINUS; q->in.rall = NOPREF; q->in.type = DOUBLE; q->in.left = p->in.left; q->in.right = p->in.right; p->in.left = q; p->in.right = q = talloc(); q->tn.op = ICON; q->tn.type = DOUBLE; #ifdef FLEXNAMES q->tn.name = ""; #else q->tn.name[0] = '\0'; #endif q->tn.rval = 0; q->tn.lval = 0; } # endif Stanford } } myreader(p) register NODE *p; { walkf( p, optim2 ); walkf( p, hardops ); /* convert ops to function calls */ canon( p ); /* expands r-vals for fileds */ toff = 0; /* stack offset swindle */ } special( p, shape ) register NODE *p; { /* special shape matching routine */ switch( shape ) { case SCCON: if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= -128 && p->tn.lval <=127 ) return( 1 ); break; case SICON: if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= 0 && p->tn.lval <=32767 ) return( 1 ); break; case S8CON: if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= 1 && p->tn.lval <= 8) return( 1 ); break; default: cerror( "bad special shape" ); } return( 0 ); } # ifndef ONEPASS main( argc, argv ) char *argv[]; { return( mainp2( argc, argv ) ); } # endif # ifdef MULTILEVEL # include "mldec.h" struct ml_node mltree[] ={ DEFINCDEC, INCR, 0, INCR, SANY, TANY, OPANY, SAREG|STAREG, TANY, OPANY, SCON, TANY, DEFINCDEC, ASG MINUS, 0, ASG MINUS, SANY, TANY, REG, SANY, TANY, ICON, SANY, TANY, TSOREG, 1, 0, UNARY MUL, SANY, TANY, REG, SANY, TANY, TSOREG, 2, 0, UNARY MUL, SANY, TANY, PLUS, SANY, TANY, REG, SANY, TANY, ICON, SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT, TSOREG, 2, 0, UNARY MUL, SANY, TANY, MINUS, SANY, TANY, REG, SANY, TANY, ICON, SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT, 0,0,0}; # endif e; m = t==DOUBLE || t==FLOAT; ml = tl==DOUBLE || tl==FLOAT; if (m==ml || logop(p->in.left->in.op)) return; p->in.op = CALL; p->in.right = p->in.left; /* put function name in sumacc/cc/ccom/mac2defs 444 0 12 1740 3470501547 10225 /* 68000 Registers */ /* registers */ # define D0 0 # define D1 1 # define D2 2 # define D3 3 # define D4 4 # define D5 5 # define D6 6 # define D7 7 # define A0 8 # define A1 9 # define A2 10 # define A3 11 # define A4 12 # define A5 13 # define A6 14 # define SP 15 # define SAVEREGION 8 /* number of bytes for save area */ # define BYTEOFF(x) ((x)&01) # define wdal(k) (BYTEOFF(k)==0) # define BITOOR(x) ((x)>>3) /* bit offset to oreg offset */ # define REGSZ 16 # define TMPREG A6 # define STOARG(p) /* just evaluate the arguments, and be done with it... */ # define STOFARG(p) # define STOSTARG(p) # define genfcall(a,b) gencall(a,b) /* shape for constants between -128 and 127 */ # define SCCON (SPECIAL+100) /* shape for constants between 0 and 32767 */ # define SICON (SPECIAL+101) /* shape for constants between 1 and 8 */ # define S8CON (SPECIAL+102) # define MYREADER(p) myreader(p) extern int fltused; /* calls can be nested on the 68000 */ # define NESTCALLS n.op == ICON && p->in.name[0]=='sumacc/cc/ccom/macdefs 444 0 12 2570 3470501550 10137 # define makecc(val,i) lastcon = i ? (val<<8)|lastcon : val # define ARGINIT 64 # define AUTOINIT 0 # define SZCHAR 8 # define SZINT 32 # define SZFLOAT 32 # define SZDOUBLE 64 # define SZLONG 32 # define SZSHORT 16 # define SZPOINT 32 # define ALCHAR 8 # define ALINT 16 # define ALFLOAT 16 # define ALDOUBLE 16 # define ALLONG 16 # define ALSHORT 16 # define ALPOINT 16 # define ALSTRUCT 16 # define ALSTACK 16 /* size in which constants are converted */ /* should be long if feasable */ # define CONSZ long #ifdef BOOTSTRAP # define CONFMT "%d" #else # define CONFMT "%Ld" #endif /* size in which offsets are kept /* should be large enough to cover address space in bits */ # define OFFSZ long /* character set macro */ # define CCTRANS(x) x /* register cookie for stack poINTer */ # define STKREG 14 # define ARGREG 14 /* maximum and minimum register variables */ # define MAXRVAR 7 # define MINRVAR 2 /* various standard pieces of code are used */ # define STDPRTREE # define LABFMT ".L%d" /* definition indicates automatics and/or temporaries are on a negative growing stack */ # define BACKAUTO # define BACKTEMP # ifndef FORT # define ONEPASS # endif # ifndef FORT # define EXIT dexit # endif # define ENUMSIZE(high,low) INT # ifndef Stanford # define STACKPROBE /* stick stack probe instructions in */ /* in procedure prolog. */ # endif Stanford ON, TANY, DEFINCDEC, ASG MINUS, 0, ASG MINUS, SANY, TANY, REG, SANY, TANY, ICON, SANY, TANY, TSOREG, 1, 0, UNARY MUL, SANY, TANYsumacc/cc/ccom/makefile 444 0 12 352 3470501550 10266 # Master makefile for the 68000 compiler t: @make -f makefile_t ./ccom68 test.c >test.s o: @make -f makefile_o b: @make -f makefile_b clean: rm -f *.s *.o *.b *BAK *CKP ccom ccom68 install: @make -f makefile_t install ine SZPOINT 32 # define ALCHAR 8 # define ALINT 16 # define ALFLOAT 16 # define ALDOUBLE 16 # define ALLONG 16 # define ALSHORT 16 # define ALPOINT 16 # define ALSTRUCT 16 # define ALSTACK 16 /* size in which constants are converted */ /* should be long if feasable */ # defsumacc/cc/ccom/makefile_b 444 0 12 637 3470501550 10575 # Makefile for 68000 compiler - Vax compiler making 68000 version .SUFFIXES: .c .b CFLAGS = -c -DFLEXNAMES BFILES = cgram.b xdefs.b scan.b pftn.b trees.b optim.b code.b local.b\ reader.b local2.b order.b match.b allo.b comm1.b table.b DEST = . #DEST = ../../../bin ccom: $(BFILES) cc68 -r -n -s -o $(DEST)/ccom $(BFILES) .c.b: cc68 $(CFLAGS) $*.c cgram.c: cgram.y yacc cgram.y mv y.tab.c cgram.c e ALSTACK 16 /* size in which constants are converted */ /* should be long if feasable */ # defsumacc/cc/ccom/makefile_o 444 0 12 546 3470501550 10611 # Native Unix version of 68000 compiler makefile .SUFFIXES: .c .o CFLAGS = -c -DFLEXNAMES OFILES = cgram.o xdefs.o scan.o pftn.o trees.o optim.o code.o local.o\ reader.o local2.o order.o match.o allo.o comm1.o table.o ccom: $(OFILES) cc -o ../../../bin/ccom $(OFILES) .c.o: cc $(CFLAGS) $*.c cgram.c: cgram.y yacc cgram.y mv y.tab.c cgram.c .c cgram.c: cgram.y yacc cgram.y mv y.tab.c cgram.c e ALSTACK 16 /* size in which constants are converted */ /* should be long if feasable */ # defsumacc/cc/ccom/makefile_t 444 0 12 725 3470501550 10615 # Cross version of 68000 Compiler makefile .SUFFIXES: .c .o CFLAGS = -c -O -I/usr/sun/include -DBOOTSTRAP -DFLEXNAMES -DStanford OFILES = cgram.o xdefs.o scan.o pftn.o trees.o optim.o code.o local.o\ reader.o local2.o order.o match.o allo.o comm1.o table.o DEST = . BINDIR = /usr/sun/bin ccom68: $(OFILES) cc -o $(DEST)/ccom68 $(OFILES) .c.o: cc $(CFLAGS) $*.c cgram.c: cgram.y yacc cgram.y mv y.tab.c cgram.c install: ccom68 cp ccom68 $(BINDIR) */ /* should be long if feasable */ # defsumacc/cc/ccom/manifest 444 0 12 15264 3470501551 10370 #ifdef BOOTSTRAP #include "/usr/include/stdio.h" #else #include <stdio.h> #endif /* manifest constant file for the lex/yacc interface */ # define ERROR 1 # define NAME 2 # define STRING 3 # define ICON 4 # define FCON 5 # define PLUS 6 # define MINUS 8 # define MUL 11 # define AND 14 # define OR 17 # define ER 19 # define QUEST 21 # define COLON 22 # define ANDAND 23 # define OROR 24 /* special interfaces for yacc alone */ /* These serve as abbreviations of 2 or more ops: ASOP =, = ops RELOP LE,LT,GE,GT EQUOP EQ,NE DIVOP DIV,MOD SHIFTOP LS,RS ICOP ICR,DECR UNOP NOT,COMPL STROP DOT,STREF */ # define ASOP 25 # define RELOP 26 # define EQUOP 27 # define DIVOP 28 # define SHIFTOP 29 # define INCOP 30 # define UNOP 31 # define STROP 32 /* reserved words, etc */ # define TYPE 33 # define CLASS 34 # define STRUCT 35 # define RETURN 36 # define GOTO 37 # define IF 38 # define ELSE 39 # define SWITCH 40 # define BREAK 41 # define CONTINUE 42 # define WHILE 43 # define DO 44 # define FOR 45 # define DEFAULT 46 # define CASE 47 # define SIZEOF 48 # define ENUM 49 /* little symbols, etc. */ /* namely, LP ( RP ) LC { RC } LB [ RB ] CM , SM ; */ # define LP 50 # define RP 51 # define LC 52 # define RC 53 # define LB 54 # define RB 55 # define CM 56 # define SM 57 # define ASSIGN 58 /* END OF YACC */ /* left over tree building operators */ # define COMOP 59 # define DIV 60 # define MOD 62 # define LS 64 # define RS 66 # define DOT 68 # define STREF 69 # define CALL 70 # define FORTCALL 73 # define NOT 76 # define COMPL 77 # define INCR 78 # define DECR 79 # define EQ 80 # define NE 81 # define LE 82 # define LT 83 # define GE 84 # define GT 85 # define ULE 86 # define ULT 87 # define UGE 88 # define UGT 89 # define SETBIT 90 # define TESTBIT 91 # define RESETBIT 92 # define ARS 93 # define REG 94 # define OREG 95 # define CCODES 96 # define FREE 97 # define STASG 98 # define STARG 99 # define STCALL 100 /* some conversion operators */ # define FLD 103 # define SCONV 104 # define PCONV 105 # define PMCONV 106 # define PVCONV 107 /* special node operators, used for special contexts */ # define FORCE 108 # define CBRANCH 109 # define INIT 110 # define CAST 111 /* node types */ # define LTYPE 02 # define UTYPE 04 # define BITYPE 010 /* DSIZE is the size of the dope array */ # define DSIZE CAST+1 /* type names, used in symbol table building */ # define TNULL PTR /* pointer to UNDEF */ # define TVOID FTN /* function returning UNDEF (for void) */ # define UNDEF 0 # define FARG 1 # define CHAR 2 # define SHORT 3 # define INT 4 # define LONG 5 # define FLOAT 6 # define DOUBLE 7 # define STRTY 8 # define UNIONTY 9 # define ENUMTY 10 # define MOETY 11 # define UCHAR 12 # define USHORT 13 # define UNSIGNED 14 # define ULONG 15 # define ASG 1+ # define UNARY 2+ # define NOASG (-1)+ # define NOUNARY (-2)+ /* various flags */ # define NOLAB (-1) /* type modifiers */ # define PTR 020 # define FTN 040 # define ARY 060 /* type packing constants */ # define TMASK 060 # define TMASK1 0300 # define TMASK2 0360 # define BTMASK 017 # define BTSHIFT 4 # define TSHIFT 2 /* macros */ # define MODTYPE(x,y) x = (x&(~BTMASK))|y /* set basic type of x to y */ # define BTYPE(x) (x&BTMASK) /* basic type of x */ # define ISUNSIGNED(x) ((x)<=ULONG&&(x)>=UCHAR) # define UNSIGNABLE(x) ((x)<=LONG&&(x)>=CHAR) # define ENUNSIGN(x) ((x)+(UNSIGNED-INT)) # define DEUNSIGN(x) ((x)+(INT-UNSIGNED)) # define ISPTR(x) ((x&TMASK)==PTR) # define ISFTN(x) ((x&TMASK)==FTN) /* is x a function type */ # define ISARY(x) ((x&TMASK)==ARY) /* is x an array type */ # define INCREF(x) (((x&~BTMASK)<<TSHIFT)|PTR|(x&BTMASK)) # define DECREF(x) (((x>>TSHIFT)&~BTMASK)|(x&BTMASK)) # define SETOFF(x,y) if( x%y != 0 ) x = ( (x/y + 1) * y) /* advance x to a multiple of y */ # define NOFIT(x,y,z) ( (x%z + y) > z ) /* can y bits be added to x without overflowing z */ /* pack and unpack field descriptors (size and offset) */ # define PKFIELD(s,o) ((o<<6)|s) # define UPKFSZ(v) (v&077) # define UPKFOFF(v) (v>>6) /* operator information */ # define TYFLG 016 # define ASGFLG 01 # define LOGFLG 020 # define SIMPFLG 040 # define COMMFLG 0100 # define DIVFLG 0200 # define FLOFLG 0400 # define LTYFLG 01000 # define CALLFLG 02000 # define MULFLG 04000 # define SHFFLG 010000 # define ASGOPFLG 020000 # define SPFLG 040000 #define optype(o) (dope[o]&TYFLG) #define asgop(o) (dope[o]&ASGFLG) #define logop(o) (dope[o]&LOGFLG) #define callop(o) (dope[o]&CALLFLG) /* table sizes */ # define BCSZ 100 /* size of the table to save break and continue labels */ # define SYMTSZ 1600 /* size of the symbol table (was 550) */ # define DIMTABSZ 2000 /* size of the dimension/size table (was 800) */ # define PARAMSZ 150 /* size of the parameter stack */ # ifndef FORT # define TREESZ 350 /* space for building parse tree */ # else # define TREESZ 1000 # endif # define SWITSZ 250 /* size of switch table */ #ifndef FLEXNAMES # define NCHNAM 8 /* number of characters in a name */ #else char *hash(); char *savestr(); char *tstr(); int tstrused; char *tstrbuf[], **curtstr; #define freetstr() curtstr = tstrbuf, tstrused = 0 #endif /* common defined variables */ extern int nerrors; /* number of errors seen so far */ typedef union ndu NODE; typedef unsigned int TWORD; # define NIL (NODE *)0 extern int dope[]; /* a vector containing operator information */ extern char *opst[]; /* a vector containing names for ops */ # ifdef ONEPASS /* in one-pass operation, define the tree nodes */ union ndu { struct { int op; int rall; TWORD type; int su; #ifndef FLEXNAMES char name[NCHNAM]; #else char *name; int stalign; #endif NODE *left; NODE *right; }in; /* interior node */ struct { int op; int rall; TWORD type; int su; #ifndef FLEXNAMES char name[NCHNAM]; #else char *name; int stalign; #endif CONSZ lval; int rval; }tn; /* terminal node */ struct { int op, rall; TWORD type; int su; int label; /* for use with branching */ }bn; /* branch node */ struct { int op, rall; TWORD type; int su; int stsize; /* sizes of structure objects */ int stalign; /* alignment of structure objects */ }stn; /* structure node */ struct { int op; int cdim; TWORD type; int csiz; }fn; /* front node */ struct { /* this structure is used when a floating point constant is being computed */ int op; int cdim; TWORD type; int csiz; double dval; }fpn; /* floating point node */ }; # endif # ifdef BUG2 # define BUG1 # endif # ifdef BUG3 # define BUG2 # define BUG1 # endif # ifdef BUG4 # define BUG1 # define BUG2 # define BUG3 # endif # ifndef ONEPASS # ifndef EXPR # define EXPR '.' # endif # ifndef BBEG # define BBEG '[' # endif # ifndef BEND # define BEND ']' # endif # endif ne USHORT 13 # define UNSIGNED 14 # define ULONG 15 # define ASG 1+ # define UNARY 2+ # define NOASG (-1)+ # define NOUNARY (-2)+ /* various flags */ # define NOLAB (-1) /* type modifiers */ # define PTR 020 # define FTN 040 # define ARY 060 /* type packing constants */ # define TMASK 060 # define TMASK1 0300 # define TMAsumacc/cc/ccom/match.c 444 0 12 32066 3470501551 10076 # include "mfile2" /* WIN - VRP's Short field fix incorporated into LFL's version July 1982 */ extern xdebug; int fldsz, fldshf, fldtyp, ty; static int mamask[] = { /* masks for matching dope with shapes */ SIMPFLG, /* OPSIMP */ SIMPFLG|ASGFLG, /* ASG OPSIMP */ COMMFLG, /* OPCOMM */ COMMFLG|ASGFLG, /* ASG OPCOMM */ MULFLG, /* OPMUL */ MULFLG|ASGFLG, /* ASG OPMUL */ DIVFLG, /* OPDIV */ DIVFLG|ASGFLG, /* ASG OPDIV */ UTYPE, /* OPUNARY */ TYFLG, /* ASG OPUNARY is senseless */ LTYPE, /* OPLEAF */ TYFLG, /* ASG OPLEAF is senseless */ 0, /* OPANY */ ASGOPFLG|ASGFLG, /* ASG OPANY */ LOGFLG, /* OPLOG */ TYFLG, /* ASG OPLOG is senseless */ FLOFLG, /* OPFLOAT */ FLOFLG|ASGFLG, /* ASG OPFLOAT */ SHFFLG, /* OPSHFT */ SHFFLG|ASGFLG, /* ASG OPSHIFT */ SPFLG, /* OPLTYPE */ TYFLG, /* ASG OPLTYPE is senseless */ }; int sdebug = 0; tshape( p, shape ) NODE *p; { /* return true if shape is appropriate for the node p side effect for SFLD is to set up fldsz,etc */ register o, mask; o = p->in.op; if( sdebug ){ printf( "tshape( %o, %o), op = %d\n", p, shape, o ); } if( shape & SPECIAL ){ switch( shape ){ case SZERO: case SONE: case SMONE: if( o != ICON || p->in.name[0] ) return(0); if( p->tn.lval == 0 && shape == SZERO ) return(1); else if( p->tn.lval == 1 && shape == SONE ) return(1); else if( p->tn.lval == -1 && shape == SMONE ) return(1); else return(0); default: # ifdef MULTILEVEL if( shape & MULTILEVEL ) return( mlmatch(p,shape,0) ); else # endif return( special( p, shape ) ); } } if( shape & SANY ) return(1); if( (shape&INTEMP) && shtemp(p) ) return(1); if( (shape&SWADD) && (o==NAME||o==OREG) ){ if( BYTEOFF(p->tn.lval) ) return(0); } switch( o ){ case NAME: return( shape&SNAME ); case ICON: mask = SCON; return( shape & mask ); case FLD: if( shape & SFLD ){ if( !flshape( p->in.left ) ) return(0); /* it is a FIELD shape; make side-effects */ o = p->tn.rval; fldsz = UPKFSZ(o); fldshf = UPKFOFF(o); if (fldsz +fldshf <= 16) { ty = USHORT; fldtyp = SZSHORT; } else { ty = ULONG; fldtyp = SZLONG; } # ifndef RTOLBYTES fldshf = fldtyp - fldsz - UPKFOFF(o); # endif RTOLBYTES return(1); } return(0); case CCODES: return( shape&SCC ); case REG: /* distinctions: SAREG any scalar register STAREG any temporary scalar register SBREG any lvalue (index) register STBREG any temporary lvalue register */ mask = isbreg( p->tn.rval ) ? SBREG : SAREG; if( istreg( p->tn.rval ) && busy[p->tn.rval]<=1 ) mask |= mask==SAREG ? STAREG : STBREG; return( shape & mask ); case OREG: return( shape & SOREG ); case UNARY MUL: /* return STARNM or STARREG or 0 */ return( shumul(p->in.left) & shape ); } return(0); } int tdebug = 0; ttype( t, tword ) TWORD t; { /* does the type t match tword */ if( tword & TANY ) return(1); if( tdebug ){ printf( "ttype( %o, %o )\n", t, tword ); } if( ISPTR(t) && (tword&TPTRTO) ) { do { t = DECREF(t); } while ( ISARY(t) ); /* arrays that are left are usually only in structure references... */ return( ttype( t, tword&(~TPTRTO) ) ); } if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */ if( tword & TPTRTO ) return(0); switch( t ){ case CHAR: return( tword & TCHAR ); case SHORT: return( tword & TSHORT ); case STRTY: case UNIONTY: return( tword & TSTRUCT ); case INT: return( tword & TINT ); case UNSIGNED: return( tword & TUNSIGNED ); case USHORT: return( tword & TUSHORT ); case UCHAR: return( tword & TUCHAR ); case ULONG: return( tword & TULONG ); case LONG: return( tword & TLONG ); case FLOAT: return( tword & TFLOAT ); case DOUBLE: return( tword & TDOUBLE ); } return(0); } struct optab *rwtable; struct optab *opptr[DSIZE]; setrew(){ /* set rwtable to first value which allows rewrite */ register struct optab *q; register int i; # ifdef MULTILEVEL /* also initialize multi-level tree links */ mlinit(); # endif for( q = table; q->op != FREE; ++q ){ if( q->needs == REWRITE ){ rwtable = q; goto more; } } cerror( "bad setrew" ); more: for( i=0; i<DSIZE; ++i ){ if( dope[i] ){ /* there is an op... */ for( q=table; q->op != FREE; ++q ){ /* beware; things like LTYPE that match multiple things in the tree must not try to look at the NIL at this stage of things! Put something else first in table.c */ /* at one point, the operator matching was 15% of the total comile time; thus, the function call that was here was removed... */ if( q->op < OPSIMP ){ if( q->op==i ) break; } else { register opmtemp; if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){ if( i==NAME || i==ICON || i==OREG ) break; else if( shltype( i, NIL ) ) break; } else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break; } } opptr[i] = q; } } } match( p, cookie ) NODE *p; { /* called by: order, gencall look for match in table and generate code if found unless entry specified REWRITE. returns MDONE, MNOPE, or rewrite specification from table */ register struct optab *q; register NODE *r; rcount(); if( cookie == FORREW ) q = rwtable; else q = opptr[p->in.op]; for( ; q->op != FREE; ++q ){ /* at one point the call that was here was over 15% of the total time; thus the function call was expanded inline */ if( q->op < OPSIMP ){ if( q->op!=p->in.op ) continue; } else { register opmtemp; if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){ if( p->in.op!=NAME && p->in.op!=ICON && p->in.op!= OREG && ! shltype( p->in.op, p ) ) continue; } else if( (dope[p->in.op]&(opmtemp|ASGFLG)) != opmtemp ) continue; } if( !(q->visit & cookie ) ) continue; r = getlr( p, 'L' ); /* see if left child matches */ if( !tshape( r, q->lshape ) ) continue; if( !ttype( r->in.type, q->ltype ) ) continue; r = getlr( p, 'R' ); /* see if right child matches */ if( !tshape( r, q->rshape ) ) continue; if( !ttype( r->in.type, q->rtype ) ) continue; /* REWRITE means no code from this match but go ahead and rewrite node to help future match */ if( q->needs & REWRITE ) return( q->rewrite ); if( !allo( p, q ) ) continue; /* if can't generate code, skip entry */ /* resources are available */ expand( p, cookie, q->cstring ); /* generate code */ reclaim( p, q->rewrite, cookie ); return(MDONE); } return(MNOPE); } int rtyflg = 0; expand( p, cookie, cp ) NODE *p; register char *cp; { /* generate code by interpreting table entry */ CONSZ val; rtyflg = 0; for( ; *cp; ++cp ){ switch( *cp ){ default: PUTCHAR( *cp ); continue; /* this is the usual case... */ case 'T': /* rewrite register type is suppressed */ rtyflg = 1; continue; case 'Z': /* special machine dependent operations */ zzzcode( p, *++cp ); continue; case 'F': /* this line deleted if FOREFF is active */ if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */ continue; case 'S': /* field size */ printf( "%d", fldsz ); continue; case 'H': /* field shift */ printf( "%d", fldshf ); continue; case 'Y': /* field type */ printf( "%c", ty==USHORT? 'w' : 'l'); continue; case 'M': /* field mask */ case 'N': /* complement of field mask */ val = 1; val <<= fldsz; --val; val <<= fldshf; adrcon( *cp=='M' ? val : ~val ); continue; case 'L': /* output special label field */ printf( "%d", p->bn.label ); continue; case 'O': /* opcode string */ hopcode( *++cp, p->in.op ); continue; case 'B': /* byte offset in word */ val = getlr(p,*++cp)->tn.lval; val = BYTEOFF(val); printf( CONFMT, val ); continue; case 'C': /* for constant value only */ conput( getlr( p, *++cp ) ); continue; case 'I': /* in instruction */ insput( getlr( p, *++cp ) ); continue; case 'A': /* address of */ adrput( getlr( p, *++cp ) ); continue; case 'U': /* for upper half of address, only */ upput( getlr( p, *++cp ) ); continue; } } } NODE * getlr( p, c ) NODE *p; { /* return the pointer to the left or right side of p, or p itself, depending on the optype of p */ switch( c ) { case '1': case '2': case '3': return( &resc[c-'1'] ); case 'L': return( optype( p->in.op ) == LTYPE ? p : p->in.left ); case 'R': return( optype( p->in.op ) != BITYPE ? p : p->in.right ); } cerror( "bad getlr: %c", c ); /* NOTREACHED */ } # ifdef MULTILEVEL union mltemplate{ struct ml_head{ int tag; /* identifies class of tree */ int subtag; /* subclass of tree */ union mltemplate * nexthead; /* linked by mlinit() */ } mlhead; struct ml_node{ int op; /* either an operator or op description */ int nshape; /* shape of node */ /* both op and nshape must match the node. * where the work is to be done entirely by * op, nshape can be SANY, visa versa, op can * be OPANY. */ int ntype; /* type descriptor from mfile2 */ } mlnode; }; # define MLSZ 30 extern union mltemplate mltree[]; int mlstack[MLSZ]; int *mlsp; /* pointing into mlstack */ NODE * ststack[MLSZ]; NODE **stp; /* pointing into ststack */ mlinit(){ union mltemplate **lastlink; register union mltemplate *n; register mlop; lastlink = &(mltree[0].nexthead); n = &mltree[0]; for( ; (n++)->mlhead.tag != 0; *lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){ if( xdebug )printf("mlinit: %d\n",(n-1)->mlhead.tag); /* wander thru a tree with a stack finding * its structure so the next header can be located. */ mlsp = mlstack; for( ;; ++n ){ if( (mlop = n->mlnode.op) < OPSIMP ){ switch( optype(mlop) ){ default: cerror("(1)unknown opcode: %o",mlop); case BITYPE: goto binary; case UTYPE: break; case LTYPE: goto leaf; } } else{ if( mamask[mlop-OPSIMP] & (SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){ binary: *mlsp++ = BITYPE; } else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */ leaf: if( mlsp == mlstack ) goto tree_end; else if ( *--mlsp != BITYPE ) cerror("(1)bad multi-level tree descriptor around mltree[%d]", n-mltree); } } } tree_end: /* n points to final leaf */ ; } if( xdebug > 3 ){ printf("mltree={\n"); for( n= &(mltree[0]); n->mlhead.tag != 0; ++n) printf("%o: %d, %d, %o,\n",n, n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead); printf(" }\n"); } } mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarget;{ /* * does subtree match a multi-level tree with * tag "target"? Return zero on failure, * non-zero subtag on success (or MDONE if * there is a zero subtag field). */ union mltemplate *head; /* current template header */ register union mltemplate *n; /* node being matched */ NODE * st; /* subtree being matched */ register int mlop; if( xdebug ) printf("mlmatch(%o,%d)\n",subtree,target); for( head = &(mltree[0]); head->mlhead.tag != 0; head=head->mlhead.nexthead){ if( xdebug > 1 )printf("mlmatch head(%o) tag(%d)\n", head->mlhead.tag); if( head->mlhead.tag != target )continue; if( subtarget && head->mlhead.subtag != subtarget)continue; if( xdebug ) printf("mlmatch for %d\n",target); /* potential for match */ n = head + 1; st = subtree; stp = ststack; mlsp = mlstack; /* compare n->op, ->nshape, ->ntype to * the subtree node st */ for( ;; ++n ){ /* for each node in multi-level template */ /* opmatch */ if( n->op < OPSIMP ){ if( st->op != n->op )break; } else { register opmtemp; if((opmtemp=mamask[n->op-OPSIMP])&SPFLG){ if(st->op!=NAME && st->op!=ICON && st->op!=OREG && ! shltype(st->op,st)) break; } else if((dope[st->op]&(opmtemp|ASGFLG))!=opmtemp) break; } /* check shape and type */ if( ! tshape( st, n->mlnode.nshape ) ) break; if( ! ttype( st->type, n->mlnode.ntype ) ) break; /* that node matched, let's try another */ /* must advance both st and n and halt at right time */ if( (mlop = n->mlnode.op) < OPSIMP ){ switch( optype(mlop) ){ default: cerror("(2)unknown opcode: %o",mlop); case BITYPE: goto binary; case UTYPE: st = st->left; break; case LTYPE: goto leaf; } } else{ if( mamask[mlop - OPSIMP] & (SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){ binary: *mlsp++ = BITYPE; *stp++ = st; st = st->left; } else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */ leaf: if( mlsp == mlstack ) goto matched; else if ( *--mlsp != BITYPE ) cerror("(2)bad multi-level tree descriptor around mltree[%d]", n-mltree); st = (*--stp)->right; } else /* UNARY */ st = st->left; } continue; matched: /* complete multi-level match successful */ if( xdebug ) printf("mlmatch() success\n"); if( head->mlhead.subtag == 0 ) return( MDONE ); else { if( xdebug )printf("\treturns %d\n", head->mlhead.subtag ); return( head->mlhead.subtag ); } } } return( 0 ); } # endif nto mlstack */ NODE * ststack[MLSZ]; NODE **stp; /* pointing into ststack */ mlinit(){ union mltemplate **lastlink; register union mltemplate *n; register mlop; lastlink = &(mltree[0].nexthead); n = &mltree[0]; for( ; (n++)->mlhead.tag != 0; *lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){ if( xdebug )printf("mlinit: %d\n",(n-1)->mlhead.tag); /* wander thru a tree with a stack finding * its structure so the next header can be located. sumacc/cc/ccom/mfile1 444 0 12 10374 3470501551 7734 # include "macdefs" # include "manifest" /* storage classes */ # define SNULL 0 # define AUTO 1 # define EXTERN 2 # define STATIC 3 # define REGISTER 4 # define EXTDEF 5 # define LABEL 6 # define ULABEL 7 # define MOS 8 # define PARAM 9 # define STNAME 10 # define MOU 11 # define UNAME 12 # define TYPEDEF 13 # define FORTRAN 14 # define ENAME 15 # define MOE 16 # define UFORTRAN 17 # define USTATIC 18 /* field size is ORed in */ # define FIELD 0100 # define FLDSIZ 077 # ifndef BUG1 extern char *scnames(); # endif /* location counters */ # define PROG 0 # define DATA 1 # define ADATA 2 # define STRNG 3 # define ISTRNG 4 # define STAB 5 /* symbol table flags */ # define SMOS 01 # define SHIDDEN 02 # define SHIDES 04 # define SSET 010 # define SREF 020 # define SNONUNIQ 040 # define STAG 0100 # ifndef FIXDEF # define FIXDEF(p) #endif # ifndef FIXARG # define FIXARG(p) # endif # ifndef FIXSTRUCT # define FIXSTRUCT(a,b) # endif /* alignment of initialized quantities */ # ifndef AL_INIT # define AL_INIT ALINT # endif struct symtab { #ifndef FLEXNAMES char sname[NCHNAM]; #else char *sname; #endif TWORD stype; /* type word */ char sclass; /* storage class */ char slevel; /* scope level */ char sflags; /* flags for set, use, hidden, mos, etc. */ int offset; /* offset or value */ short dimoff; /* offset into the dimension table */ short sizoff; /* offset into the size table */ short suse; /* line number of last use of the variable */ }; # ifdef ONEPASS /* NOPREF must be defined for use in first pass tree machine */ # define NOPREF 020000 /* no preference for register assignment */ #else union ndu { struct { int op; TWORD type; int cdim, csiz; }fn; /* front node */ struct { int op; TWORD type; int cdim, csiz; NODE *left; NODE * right; }in; /* interior node */ struct { /* this structure is the same as above, but is used when a value, rather than address, is kept in +left */ int op; TWORD type; int cdim, csiz; CONSZ lval; int rval; }tn; /* terminal node */ struct { /* this structure is used when a floating point constant is being computed */ int op; TWORD type; int cdim, csiz; double dval; }fpn; /* floating point node */ }; # endif struct sw { CONSZ sval; int slab; }; extern struct sw swtab[]; extern struct sw *swp; extern int swx; extern int ftnno; extern int blevel; extern int instruct, stwart; extern int lineno, nerrors; typedef union { int intval; NODE * nodep; } YYSTYPE; extern YYSTYPE yylval; extern CONSZ lastcon; extern double dcon; extern char ftitle[]; extern struct symtab stab[]; extern int curftn; extern int curclass; extern int curdim; extern int dimtab[]; extern int paramstk[]; extern int paramno; extern int autooff, argoff, strucoff; extern int regvar; extern int minrvar; extern int brkflag; extern char yytext[]; extern int strflg; extern OFFSZ inoff; extern int reached; /* tunnel to buildtree for name id's */ extern int idname; extern NODE node[]; extern NODE *lastfree; extern int cflag, hflag, pflag; /* various labels */ extern int brklab; extern int contlab; extern int flostat; extern int retlab; extern int retstat; extern int asavbc[], *psavbc; /* flags used in structures/unions */ # define SEENAME 01 # define INSTRUCT 02 # define INUNION 04 # define FUNNYNAME 010 # define TAGNAME 020 /* flags used in the (elementary) flow analysis ... */ # define FBRK 02 # define FCONT 04 # define FDEF 010 # define FLOOP 020 /* flags used for return status */ # define RETVAL 1 # define NRETVAL 2 /* used to mark a constant with no name field */ # define NONAME 040000 /* mark an offset which is undefined */ # define NOOFFSET (-10201) /* declarations of various functions */ extern NODE *buildtree(), *bdty(), *mkty(), *rstruct(), *dclstruct(), *getstr(), *tymerge(), *stref(), *offcon(), *bcon(), *bpsize(), *convert(), *pconvert(), *oconvert(), *ptmatch(), *tymatch(), *makety(), *block(), *doszof(), *talloc(), *optim(), *strargs(), *clocal(); OFFSZ tsize(), psize(); TWORD types(); double atof(); char *exname(), *exdcon(); # define checkst(x) # ifndef CHARCAST /* to make character constants into character connstants */ /* this is a macro to defend against cross-compilers, etc. */ # define CHARCAST(x) (char)(x) # endif rintf("mltree={\n"); for( n= &(mltree[0]); n->mlhead.tag != 0; ++n) printf("%o: %d, %d, %o,\n",n, n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead); printf(" }\n"); } } mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarsumacc/cc/ccom/mfile2 444 0 12 12545 3470501551 7737 # include "macdefs" # include "mac2defs" # include "manifest" # ifdef ONEPASS /* bunch of stuff for putting the passes together... */ # define crslab crs2lab # define where where2 # define xdebug x2debug # define tdebug t2debug # define deflab def2lab # define edebug e2debug # define eprint e2print # define getlab get2lab # define filename ftitle # endif /* cookies, used as arguments to codgen */ # define FOREFF 01 /* compute for effects only */ # define INAREG 02 /* compute into a register */ # define INTAREG 04 /* compute into a scratch register */ # define INBREG 010 /* compute into a lvalue register */ # define INTBREG 020 /* compute into a scratch lvalue register */ # define FORCC 040 /* compute for condition codes only */ # define INTEMP 010000 /* compute into a temporary location */ # define FORARG 020000 /* compute for an argument of a function */ # define FORREW 040000 /* search the table, looking for a rewrite rule */ /* OP descriptors */ /* the ASG operator may be used on some of these */ # define OPSIMP 010000 /* +, -, &, |, ^ */ # define OPCOMM 010002 /* +, &, |, ^ */ # define OPMUL 010004 /* *, / */ # define OPDIV 010006 /* /, % */ # define OPUNARY 010010 /* unary ops */ # define OPLEAF 010012 /* leaves */ # define OPANY 010014 /* any op... */ # define OPLOG 010016 /* logical ops */ # define OPFLOAT 010020 /* +, -, *, or / (for floats) */ # define OPSHFT 010022 /* <<, >> */ # define OPLTYPE 010024 /* leaf type nodes (e.g, NAME, ICON, etc. ) */ /* match returns */ # define MNOPE 010000 # define MDONE 010001 /* shapes */ # define SANY 01 /* same as FOREFF */ # define SAREG 02 /* same as INAREG */ # define STAREG 04 /* same as INTAREG */ # define SBREG 010 /* same as INBREG */ # define STBREG 020 /* same as INTBREG */ # define SCC 040 /* same as FORCC */ # define SNAME 0100 # define SCON 0200 # define SFLD 0400 # define SOREG 01000 # define STARNM 02000 # define STARREG 04000 # define SWADD 040000 # define SPECIAL 0100000 # define SZERO SPECIAL # define SONE (SPECIAL|1) # define SMONE (SPECIAL|2) /* FORARG and INTEMP are carefully not conflicting with shapes */ /* types */ # define TCHAR 01 # define TSHORT 02 # define TINT 04 # define TLONG 010 # define TFLOAT 020 # define TDOUBLE 040 # define TPOINT 0100 # define TUCHAR 0200 # define TUSHORT 0400 # define TUNSIGNED 01000 # define TULONG 02000 # define TPTRTO 04000 /* pointer to one of the above */ # define TANY 010000 /* matches anything within reason */ # define TSTRUCT 020000 /* structure or union */ /* reclamation cookies */ # define RNULL 0 /* clobber result */ # define RLEFT 01 # define RRIGHT 02 # define RESC1 04 # define RESC2 010 # define RESC3 020 # define RESCC 04000 # define RNOP 010000 /* DANGER: can cause loops.. */ /* needs */ # define NAREG 01 # define NACOUNT 03 # define NAMASK 017 # define NASL 04 /* share left register */ # define NASR 010 /* share right register */ # define NBREG 020 # define NBCOUNT 060 # define NBMASK 0360 # define NBSL 0100 # define NBSR 0200 # define NTEMP 0400 # define NTMASK 07400 # define REWRITE 010000 # define MUSTDO 010000 /* force register requirements */ # define NOPREF 020000 /* no preference for register assignment */ /* register allocation */ extern int rstatus[]; extern int busy[]; extern struct respref { int cform; int mform; } respref[]; # define isbreg(r) (rstatus[r]&SBREG) # define istreg(r) (rstatus[r]&(STBREG|STAREG)) # define istnode(p) (p->in.op==REG && istreg(p->tn.rval)) # define TBUSY 01000 # define REGLOOP(i) for(i=0;i<REGSZ;++i) # define SETSTO(x,y) (stotree=(x),stocook=(y)) extern int stocook; # define DELAYS 20 extern NODE *deltrees[DELAYS]; extern int deli; /* mmmmm */ extern NODE *stotree; extern int callflag; extern int fregs; # ifndef ONEPASS union ndu { struct { int op; int rall; TWORD type; int su; #ifndef FLEXNAMES char name[NCHNAM]; #else char *name; #endif NODE *left; NODE *right; }in; /* interior node */ struct { int op; int rall; TWORD type; int su; #ifndef FLEXNAMES char name[NCHNAM]; #else char *name; #endif CONSZ lval; int rval; }tn; /* terminal node */ struct { int op, rall; TWORD type; int su; int label; /* for use with branching */ }bn; /* branch node */ struct { int op, rall; TWORD type; int su; int stsize; /* sizes of structure objects */ int stalign; /* alignment of structure objects */ }stn; /* structure node */ }; #endif extern NODE node[]; extern struct optab { int op; int visit; int lshape; int ltype; int rshape; int rtype; int needs; int rewrite; char * cstring; } table[]; extern NODE resc[]; extern OFFSZ tmpoff; extern OFFSZ maxoff; extern OFFSZ baseoff; extern OFFSZ maxtemp; extern int maxtreg; extern int ftnno; extern int rtyflg; extern int nrecur; /* flag to keep track of recursions */ # define NRECUR (10*TREESZ) extern NODE *talloc(), *eread(), *tcopy(), *getlr(); extern CONSZ rdin(); extern int eprint(); extern char *rnames[]; extern int lineno; extern char filename[]; extern int fldshf, fldsz; extern int lflag, xdebug, udebug, edebug, odebug, rdebug, radebug, tdebug, sdebug; #ifndef callchk #define callchk(x) allchk() #endif #ifndef PUTCHAR # define PUTCHAR(x) putchar(x) #endif /* macros for doing double indexing */ # define R2PACK(x,y) (0200*((x)+1)+y) # define R2UPK1(x) ((((x)>>7)&0177)-1) # define R2UPK2(x) ((x)&0177) # define R2TEST(x) ((x)>=0200) 01000 # define STARNM 02000 # define STARREG 04000 # define SWADD 040000 # define SPECIAL 0100000 # define SZERO SPECIAL # define SONE (SPECIAL|1) # definesumacc/cc/ccom/optim.c 444 0 12 10170 3470501551 10122 # include "mfile1" # define SWAP(p,q) {sp=p; p=q; q=sp;} # define RCON(p) (p->in.right->in.op==ICON) # define RO(p) p->in.right->in.op # define RV(p) p->in.right->tn.lval # define LCON(p) (p->in.left->in.op==ICON) # define LO(p) p->in.left->in.op # define LV(p) p->in.left->tn.lval int oflag = 0; NODE * fortarg( p ) NODE *p; { /* fortran function arguments */ if( p->in.op == CM ){ p->in.left = fortarg( p->in.left ); p->in.right = fortarg( p->in.right ); return(p); } while( ISPTR(p->in.type) ){ p = buildtree( UNARY MUL, p, NIL ); } return( optim(p) ); } /* mapping relationals when the sides are reversed */ short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT }; NODE * optim(p) register NODE *p; { /* local optimizations, most of which are probably machine independent */ register o, ty; NODE *sp; int i; TWORD t; if( (t=BTYPE(p->in.type))==ENUMTY || t==MOETY ) econvert(p); if( oflag ) return(p); ty = optype( o=p->in.op); if( ty == LTYPE ) return(p); if( ty == BITYPE ) p->in.right = optim(p->in.right); p->in.left = optim(p->in.left); /* collect constants */ switch(o){ case SCONV: case PCONV: return( clocal(p) ); case FORTCALL: p->in.right = fortarg( p->in.right ); break; case UNARY AND: if( LO(p) != NAME ) cerror( "& error" ); if( !andable(p->in.left) ) return(p); LO(p) = ICON; setuleft: /* paint over the type of the left hand side with the type of the top */ p->in.left->in.type = p->in.type; p->in.left->fn.cdim = p->fn.cdim; p->in.left->fn.csiz = p->fn.csiz; p->in.op = FREE; return( p->in.left ); case UNARY MUL: if( LO(p) != ICON ) break; LO(p) = NAME; goto setuleft; case MINUS: if( !nncon(p->in.right) ) break; RV(p) = -RV(p); o = p->in.op = PLUS; case MUL: case PLUS: case AND: case OR: case ER: /* commutative ops; for now, just collect constants */ /* someday, do it right */ if( nncon(p->in.left) || ( LCON(p) && !RCON(p) ) ) SWAP( p->in.left, p->in.right ); /* make ops tower to the left, not the right */ if( RO(p) == o ){ NODE *t1, *t2, *t3; t1 = p->in.left; sp = p->in.right; t2 = sp->in.left; t3 = sp->in.right; /* now, put together again */ p->in.left = sp; sp->in.left = t1; sp->in.right = t2; p->in.right = t3; } if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) && conval(p->in.right, MINUS, p->in.left->in.right)){ zapleft: RO(p->in.left) = FREE; LO(p) = FREE; p->in.left = p->in.left->in.left; } if( RCON(p) && LO(p)==o && RCON(p->in.left) && conval( p->in.right, o, p->in.left->in.right ) ){ goto zapleft; } else if( LCON(p) && RCON(p) && conval( p->in.left, o, p->in.right ) ){ zapright: RO(p) = FREE; p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz ); p->in.op = FREE; return( clocal( p->in.left ) ); } /* throw out addition/subtraction by 0 */ if( o == PLUS || o == MINUS || o == OR || o == ER ) { if( nncon( p->in.right ) && RV(p) == 0 ) goto zapright; } /* change muls to shifts */ if( o==MUL && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){ if( i == 0 ){ /* multiplication by 1 */ goto zapright; } o = p->in.op = LS; p->in.right->in.type = p->in.right->fn.csiz = INT; RV(p) = i; } /* change +'s of negative consts back to - */ if( o==PLUS && nncon(p->in.right) && RV(p)<0 ){ RV(p) = -RV(p); o = p->in.op = MINUS; } break; case DIV: if( nncon( p->in.right ) && p->in.right->tn.lval == 1 ) goto zapright; break; case EQ: case NE: case LT: case LE: case GT: case GE: case ULT: case ULE: case UGT: case UGE: if( !LCON(p) ) break; /* exchange operands */ sp = p->in.left; p->in.left = p->in.right; p->in.right = sp; p->in.op = revrel[p->in.op - EQ ]; break; case ASG PLUS: case ASG MINUS: case ASG OR: case ASG ER: if( nncon( p->in.right ) && RV(p) == 0 ) goto zapright; break; } return(p); } ispow2( c ) CONSZ c; { register i; if( c <= 0 || (c&(c-1)) ) return(-1); for( i=0; c>1; ++i) c >>= 1; return(i); } nncon( p ) NODE *p; { /* is p a constant without a name */ return( p->in.op == ICON && p->tn.rval == NONAME ); } 2 010 # define RESC3 020 # define RESCC 04000 # define RNOP 010000 /* DANGER: can cause loops.. */ /* needs */ # define NAREG 01 # define NACOUNT 03 # define NAMASK 017 # define NASL 04 /* share left register */ # define NASR 010 /* share right register */ # define NBREG 020 # define NBCOUNT 060 # define NBMASK 0360 # define NBSL 0100 # define NBSR 0200 # define NTEMP 0400 # define Nsumacc/cc/ccom/order.c 444 0 12 40207 3470501551 10111 # include "mfile2" int fltused = 0; stoasg( p, o ) register NODE *p; { /* should the assignment op p be stored, given that it lies as the right operand of o (or the left, if o==UNARY MUL) */ return( shltype(p->in.left->in.op, p->in.left ) ); } deltest( p ) register NODE *p; { /* should we delay the INCR or DECR operation p */ # ifndef MULTILEVEL if( p->in.op == INCR && p->in.left->in.op == REG && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){ /* STARREG */ return( 0 ); } # else if( mlmatch(p,DEFINCDEC,INCR) && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){ /* STARREG */ return( 0 ); } # endif p = p->in.left; if( p->in.op == UNARY MUL ) p = p->in.left; return( p->in.op == NAME || p->in.op == OREG || p->in.op == REG ); } mkadrs(p) register NODE *p; { register o; o = p->in.op; if( asgop(o) ){ if( p->in.left->in.su >= p->in.right->in.su ){ if( p->in.left->in.op == UNARY MUL ){ if( p->in.left->in.su > 0 ) SETSTO( p->in.left->in.left, INTEMP ); else { if( p->in.right->in.su > 0 ) SETSTO( p->in.right, INTEMP ); else cerror( "store finds both sides trivial" ); } } else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ SETSTO( p->in.left->in.left->in.left, INTEMP ); } else { /* should be only structure assignment */ SETSTO( p->in.left, INTEMP ); } } else SETSTO( p->in.right, INTEMP ); } else { if( p->in.left->in.su > p->in.right->in.su ){ SETSTO( p->in.left, INTEMP ); } else { SETSTO( p->in.right, INTEMP ); } } } notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; { /* is it legal to make an OREG or NAME entry which has an /* offset of off, (from a register of r), if the /* resulting thing had type t */ if ( off>=-32768 && off<=32767 && *cp=='\0' && r>=A0 && r<=SP ) return(0); /* YES */ return( 1 ); /* NO */ } # define max(x,y) ((x)<(y)?(y):(x)) # define min(x,y) ((x)<(y)?(x):(y)) # define ZCHAR 01 # define ZLONG 02 # define ZFLOAT 04 zum( p, zap ) register NODE *p; { /* zap Sethi-Ullman number for chars, longs, floats */ /* in the case of longs, only STARNM's are zapped */ /* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */ register su; su = p->in.su; switch( p->in.type ){ case CHAR: case UCHAR: if( !(zap&ZCHAR) ) break; if( su==0 && p->in.op!=ICON ) p->in.su = su = 1; break; case LONG: case ULONG: if( !(zap&ZLONG) ) break; if( p->in.op == UNARY MUL && su == 0 ) p->in.su = su = 2; break; case FLOAT: if( !(zap&ZFLOAT) ) break; if( su == 0 ) p->in.su = su = 1; } return( su ); } sucomp( p ) register NODE *p; { /* set the su field in the node to the sethi-ullman number, or local equivalent */ register o, ty, sul, sur; register nr; ty = optype( o=p->in.op); nr = szty( p->in.type ); p->in.su = 0; if( ty == LTYPE ) { if( p->in.type==FLOAT ) p->in.su = 1; return; } else if( ty == UTYPE ){ switch( o ) { case UNARY CALL: case UNARY STCALL: p->in.su = fregs; /* all regs needed */ return; case UNARY MUL: if( shumul( p->in.left ) ) return; default: p->in.su = max( p->in.left->in.su, nr); return; } } /* If rhs needs n, lhs needs m, regular su computation */ sul = p->in.left->in.su; sur = p->in.right->in.su; if( o == ASSIGN ){ asop: /* also used for +=, etc., to memory */ if( sul==0 ){ /* don't need to worry about the left side */ p->in.su = max( sur, nr ); } else { /* right, left address, op */ if( sur == 0 ){ /* just get the lhs address into a register, and mov */ /* the `nr' covers the case where value is in reg afterwards */ p->in.su = max( sul, nr ); } else { /* right, left address, op */ p->in.su = max( sur, nr+sul ); } } return; } if( o == CALL || o == STCALL ){ /* in effect, takes all free registers */ p->in.su = fregs; return; } if( o == STASG ){ /* right, then left */ p->in.su = max( max( sul+nr, sur), fregs ); return; } if( logop(o) ){ /* do the harder side, then the easier side, into registers */ /* left then right, max(sul,sur+nr) */ /* right then left, max(sur,sul+nr) */ /* to hold both sides in regs: nr+nr */ nr = szty( p->in.left->in.type ); sul = zum( p->in.left, ZLONG|ZCHAR|ZFLOAT ); sur = zum( p->in.right, ZLONG|ZCHAR|ZFLOAT ); p->in.su = min( max(sul,sur+nr), max(sur,sul+nr) ); return; } if( asgop(o) ){ /* computed by doing right, doing left address, doing left, op, and store */ switch( o ) { case INCR: case DECR: /* do as binary op */ break; case ASG PLUS: case ASG MINUS: case ASG AND: case ASG ER: case ASG OR: if( p->in.type == INT || p->in.type == UNSIGNED || ISPTR(p->in.type) ) goto asop; gencase: default: sur = zum( p->in.right, ZCHAR|ZLONG|ZFLOAT ); if( sur == 0 ){ /* easy case: if addressable, do left value, op, store */ if( sul == 0 ) p->in.su = nr; /* harder: left adr, val, op, store */ else p->in.su = max( sul, nr+1 ); } else { /* do right, left adr, left value, op, store */ if( sul == 0 ){ /* right, left value, op, store */ p->in.su = max( sur, nr+nr ); } else { p->in.su = max( sur, max( sul+nr, 1+nr+nr ) ); } } return; } } switch( o ){ case ANDAND: case OROR: case QUEST: case COLON: case COMOP: p->in.su = max( max(sul,sur), nr); return; } if( ( o==DIV || o==MOD || o==MUL ) && p->in.type!=FLOAT && p->in.type!=DOUBLE ) nr = fregs; if( o==PLUS || o==MUL || o==OR || o==ER ){ /* AND is ruined by the hardware */ /* permute: get the harder on the left */ register rt, lt; if( istnode( p->in.left ) || sul > sur ) goto noswap; /* don't do it! */ /* look for a funny type on the left, one on the right */ lt = p->in.left->in.type; rt = p->in.right->in.type; if( rt == FLOAT && lt == DOUBLE ) goto swap; if( (rt==CHAR||rt==UCHAR) && (lt==INT||lt==UNSIGNED||ISPTR(lt)) ) goto swap; if( lt==LONG || lt==ULONG ){ if( rt==LONG || rt==ULONG ){ /* if one is a STARNM, swap */ if( p->in.left->in.op == UNARY MUL && sul==0 ) goto noswap; if( p->in.right->in.op == UNARY MUL && p->in.left->in.op != UNARY MUL ) goto swap; goto noswap; } else if( p->in.left->in.op == UNARY MUL && sul == 0 ) goto noswap; else goto swap; /* put long on right, unless STARNM */ } /* we are finished with the type stuff now; if one is addressable, put it on the right */ if( sul == 0 && sur != 0 ){ NODE *s; int ssu; swap: ssu = sul; sul = sur; sur = ssu; s = p->in.left; p->in.left = p->in.right; p->in.right = s; } } noswap: sur = zum( p->in.right, ZCHAR|ZLONG|ZFLOAT ); if( sur == 0 ){ /* get left value into a register, do op */ p->in.su = max( nr, sul ); } else { /* do harder into a register, then easier */ p->in.su = max( nr+nr, min( max( sul, nr+sur ), max( sur, nr+sul ) ) ); } } int radebug = 0; mkrall( p, r ) register NODE *p; { /* insure that the use of p gets done with register r; in effect, */ /* simulate offstar */ if( p->in.op == FLD ){ p->in.left->in.rall = p->in.rall; p = p->in.left; } if( p->in.op != UNARY MUL ) return; /* no more to do */ p = p->in.left; if( p->in.op == UNARY MUL ){ p->in.rall = r; p = p->in.left; } if( p->in.op == PLUS && p->in.right->in.op == ICON ){ p->in.rall = r; p = p->in.left; } rallo( p, r ); } rallo( p, down ) register NODE *p; { /* do register allocation */ register o, type, down1, down2, ty; if( radebug ) printf( "rallo( %o, %o )\n", p, down ); down2 = NOPREF; p->in.rall = down; down1 = ( down &= ~MUSTDO ); ty = optype( o = p->in.op ); type = p->in.type; if( type == DOUBLE || type == FLOAT ){ if( o == FORCE ) down1 = D0|MUSTDO; ++fltused; } else switch( o ) { case ASSIGN: down1 = NOPREF; down2 = down; break; case ASG MUL: case ASG DIV: case ASG MOD: /* keep the addresses out of the hair of (r0,r1) */ if(fregs == 2 ){ /* lhs in (r0,r1), nothing else matters */ down1 = D1|MUSTDO; down2 = NOPREF; break; } /* at least 3 regs free */ /* compute lhs in (r0,r1), address of left in r2 */ p->in.left->in.rall = D1|MUSTDO; mkrall( p->in.left, D2|MUSTDO ); /* now, deal with right */ if( fregs == 3 ) rallo( p->in.right, NOPREF ); else { /* put address of long or value here */ p->in.right->in.rall = D3|MUSTDO; mkrall( p->in.right, D3|MUSTDO ); } return; case MUL: case DIV: case MOD: rallo( p->in.left, D1|MUSTDO ); if( fregs == 2 ){ rallo( p->in.right, NOPREF ); return; } /* compute addresses, stay away from (r0,r1) */ p->in.right->in.rall = (fregs==3) ? D2|MUSTDO : D3|MUSTDO ; mkrall( p->in.right, D2|MUSTDO ); return; case CALL: case STASG: case EQ: case NE: case GT: case GE: case LT: case LE: case NOT: case ANDAND: case OROR: down1 = NOPREF; break; case FORCE: down1 = D0|MUSTDO; break; } if( ty != LTYPE ) rallo( p->in.left, down1 ); if( ty == BITYPE ) rallo( p->in.right, down2 ); } offstar( p ) register NODE *p; { /* handle indirections */ if( p->in.op == UNARY MUL ) p = p->in.left; if( p->in.op == PLUS || p->in.op == MINUS ){ if( p->in.right->in.op == ICON && p->in.right->in.name[0]=='\0' && p->in.right->tn.lval>=-32768 && p->in.right->tn.lval<=32767 ){ order( p->in.left , INTBREG|INBREG ); return; } } order( p, INTBREG|INBREG ); } setincr( p ) NODE *p; { return( 0 ); /* for the moment, don't bother */ } niceuty( p ) register NODE *p; { register TWORD t; return( p->in.op == UNARY MUL && (t=p->in.type)!=CHAR && t!= UCHAR && t!= FLOAT && shumul( p->in.left) != STARREG ); } setbin( p ) register NODE *p; { register NODE *r, *l; r = p->in.right; l = p->in.left; if( p->in.right->in.su == 0 ){ /* rhs is addressable */ if( logop( p->in.op ) ){ if( l->in.op == UNARY MUL && l->in.type != FLOAT && shumul( l->in.left ) != STARREG ) offstar( l->in.left ); else order( l, INAREG|INTAREG|INBREG|INTBREG|INTEMP ); return( 1 ); } if( !istnode( l ) ){ order( l, INTAREG|INTBREG ); return( 1 ); } /* rewrite */ return( 0 ); } /* now, rhs is complicated: must do both sides into registers */ /* do the harder side first */ if( logop( p->in.op ) ){ /* relational: do both sides into regs if need be */ if( r->in.su > l->in.su ){ if( niceuty(r) ){ offstar( r->in.left ); return( 1 ); } else if( !istnode( r ) ){ order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); return( 1 ); } } if( niceuty(l) ){ offstar( l->in.left ); return( 1 ); } else if( !istnode( l ) ){ order( l, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); return( 1 ); } else if( niceuty(r) ){ offstar( r->in.left ); return( 1 ); } if( !istnode( r ) ){ order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); return( 1 ); } cerror( "setbin can't deal with %s", opst[p->in.op] ); } /* ordinary operator */ if( !istnode(r) && r->in.su > l->in.su ){ /* if there is a chance of making it addressable, try it... */ if( niceuty(r) ){ offstar( r->in.left ); return( 1 ); /* hopefully, it is addressable by now */ } order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); /* anything goes on rhs */ return( 1 ); } else { if( !istnode( l ) ){ order( l, INTAREG|INTBREG ); return( 1 ); } /* rewrite */ return( 0 ); } } setstr( p ) register NODE *p; { /* structure assignment */ if( p->in.right->in.op != REG ){ order( p->in.right, INTBREG ); return(1); } p = p->in.left; if( p->in.op != NAME && p->in.op != OREG ){ if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); order( p->in.left, INTBREG ); return( 1 ); } return( 0 ); } setasg( p ) register NODE *p; { /* setup for assignment operator */ if( p->in.right->in.su != 0 && p->in.right->in.op != REG ) { if( p->in.right->in.op == UNARY MUL ) offstar( p->in.right->in.left ); else order( p->in.right, INAREG|INBREG|SOREG|SNAME|SCON ); return(1); } if( p->in.left->in.op == UNARY MUL && !tshape( p->in.left, STARREG|STARNM ) ){ offstar( p->in.left->in.left ); return(1); } if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ offstar( p->in.left->in.left->in.left ); return(1); } /* if things are really strange, get rhs into a register */ if( p->in.right->in.op != REG ){ order( p->in.right, INAREG|INBREG ); return( 1 ); } return(0); } setasop( p ) register NODE *p; { /* setup for =ops */ register sul, sur; register NODE *q, *p2; sul = p->in.left->in.su; sur = p->in.right->in.su; switch( p->in.op ){ case ASG PLUS: case ASG MINUS: case ASG OR: case ASG ER: case ASG AND: if (p->in.right->in.op != REG && sul == 0) { order(p->in.right,INAREG|INTAREG); return(1); } else break; case ASG LS: case ASG RS: if (p->in.left->in.op != REG) return(0); if (p->in.right->in.op == REG || (p->in.right->in.op==ICON && p->in.right->tn.lval>=1 && p->in.right->tn.lval<=8)) break; order(p->in.right,INAREG|INTAREG); return(1); case ASG MUL: case ASG DIV: case ASG MOD: if (p->in.left->in.op != REG) return(0); } if( sur == 0 ){ leftadr: /* easy case: if addressable, do left value, op, store */ if( sul == 0 ) goto rew; /* rewrite */ /* harder; make aleft address, val, op, and store */ if( p->in.left->in.op == UNARY MUL ){ offstar( p->in.left->in.left ); return( 1 ); } if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ offstar( p->in.left->in.left->in.left ); return( 1 ); } rew: /* rewrite, accounting for autoincrement and autodecrement */ q = p->in.left; if( q->in.op == FLD ) q = q->in.left; if( q->in.op != UNARY MUL || shumul(q->in.left) != STARREG ) return(0); /* let reader.c do it */ /* mimic code from reader.c */ p2 = tcopy( p ); p->in.op = ASSIGN; reclaim( p->in.right, RNULL, 0 ); p->in.right = p2; /* now, zap INCR on right, ASG MINUS on left */ if( q->in.left->in.op == INCR ){ q = p2->in.left; if( q->in.op == FLD ) q = q->in.left; if( q->in.left->in.op != INCR ) cerror( "bad incr rewrite" ); } else if( q->in.left->in.op != ASG MINUS ) cerror( " bad -= rewrite" ); q->in.left->in.right->in.op = FREE; q->in.left->in.op = FREE; q->in.left = q->in.left->in.left; /* now, resume reader.c rewriting code */ canon(p); rallo( p, p->in.rall ); order( p2->in.left, INTBREG|INTAREG ); order( p2, INTBREG|INTAREG ); return( 1 ); } /* harder case: do right, left address, left value, op, store */ if( p->in.right->in.op == UNARY MUL && p->in.left->in.op==REG){ offstar( p->in.right->in.left ); return( 1 ); } /* sur> 0, since otherwise, done above */ if( p->in.right->in.op == REG ) goto leftadr; /* make lhs addressable */ order( p->in.right, INAREG|INBREG ); return( 1 ); } int crslab = 10000; getlab(){ return( crslab++ ); } deflab( l ){ printf( ".L%d:\n", l ); } genargs( p) register NODE *p; { register size,inc; /* generate code for the arguments */ /* first, do the arguments on the right (last->first) */ while( p->in.op == CM ){ genargs( p->in.right ); p->in.op = FREE; p = p->in.left; } if( p->in.op == STARG ){ /* structure valued argument */ size = p->stn.stsize; if( p->in.left->in.op == ICON ){ /* make into a name node */ p->in.op = FREE; p= p->in.left; p->in.op = NAME; } else { /* make it look beautiful... */ p->in.op = UNARY MUL; canon( p ); /* turn it into an oreg */ if( p->in.op != OREG ){ offstar( p->in.left ); canon( p ); if( p->in.op != OREG ) cerror( "stuck starg" ); } } p->tn.lval += size; /* end of structure */ /* put on stack backwards */ for( ; size>0; size -= inc ){ inc = (size>2) ? 4 : 2; p->tn.lval -= inc; expand( p, RNOP,(inc==4)?"\tmovl\tAR,Z-\n":"\tmovw\tAR,Z-\n" ); } reclaim( p, RNULL, 0 ); return; } /* ordinary case */ order( p, FORARG ); } argsize( p ) register NODE *p; { register t; t = 0; if( p->in.op == CM ){ t = argsize( p->in.left ); p = p->in.right; } if( p->in.type == DOUBLE || p->in.type == FLOAT ){ SETOFF( t, 2 ); return( t+8 ); } else if( p->in.op == STARG ){ SETOFF( t, p->stn.stalign ); /* alignment */ return( t + p->stn.stsize ); /* size */ } else { SETOFF( t, 2 ); return( t+4 ); } } s into a register */ if( p->in.right->in.op != REG ){ order( p->in.right, INAREG|INBREG ); return( 1 ); } return(0); } setasop( p ) register NODE *p; { /* setup for =ops */ register sul, sur; register NODE *q, *p2; sul = p->in.left->in.su; sur = p->in.right->in.su; switch( p->in.op ){ case ASG PLUS: case ASG MINUS: case ASG OR: case ASG ER: csumacc/cc/ccom/pftn.c 444 0 12 117514 3470501552 7774 # include "mfile1" unsigned int offsz; struct instk { int in_sz; /* size of array element */ int in_x; /* current index for structure member in structure initializations */ int in_n; /* number of initializations seen */ int in_s; /* sizoff */ int in_d; /* dimoff */ TWORD in_t; /* type */ int in_id; /* stab index */ int in_fl; /* flag which says if this level is controlled by {} */ OFFSZ in_off; /* offset of the beginning of this level */ } instack[10], *pstk; /* defines used for getting things off of the initialization stack */ struct symtab *relook(); int ddebug = 0; struct symtab * mknonuniq(); defid( q, class ) NODE *q; { register struct symtab *p; int idp; TWORD type; TWORD stp; int scl; int dsym, ddef; int slev, temp; if( q == NIL ) return; /* an error was detected */ if( q < node || q >= &node[TREESZ] ) cerror( "defid call" ); idp = q->tn.rval; if( idp < 0 ) cerror( "tyreduce" ); p = &stab[idp]; # ifndef BUG1 if( ddebug ){ #ifndef FLEXNAMES printf( "defid( %.8s (%d), ", p->sname, idp ); #else printf( "defid( %s (%d), ", p->sname, idp ); #endif tprint( q->in.type ); printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->fn.cdim, q->fn.csiz, blevel ); } # endif fixtype( q, class ); type = q->in.type; class = fixclass( class, type ); stp = p->stype; slev = p->slevel; # ifndef BUG1 if( ddebug ){ printf( " modified to " ); tprint( type ); printf( ", %s\n", scnames(class) ); printf( " previous def'n: " ); tprint( stp ); printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev ); } # endif if( stp == FTN && p->sclass == SNULL )goto enter; /* name encountered as function, not yet defined */ /* BUG here! can't incompatibly declare func. in inner block */ if( stp == UNDEF|| stp == FARG ){ if( blevel==1 && stp!=FARG ) switch( class ){ default: #ifndef FLEXNAMES if(!(class&FIELD)) uerror( "declared argument %.8s is missing", p->sname ); #else if(!(class&FIELD)) uerror( "declared argument %s is missing", p->sname ); #endif case MOS: case STNAME: case MOU: case UNAME: case MOE: case ENAME: case TYPEDEF: ; } goto enter; } if( type != stp ) goto mismatch; /* test (and possibly adjust) dimensions */ dsym = p->dimoff; ddef = q->fn.cdim; for( temp=type; temp&TMASK; temp = DECREF(temp) ){ if( ISARY(temp) ){ if( dimtab[dsym] == 0 ) dimtab[dsym] = dimtab[ddef]; else if( dimtab[ddef]!=0 && dimtab[dsym] != dimtab[ddef] ){ goto mismatch; } ++dsym; ++ddef; } } /* check that redeclarations are to the same structure */ if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz && class!=STNAME && class!=UNAME && class!=ENAME ){ goto mismatch; } scl = ( p->sclass ); # ifndef BUG1 if( ddebug ){ printf( " previous class: %s\n", scnames(scl) ); } # endif if( class&FIELD ){ /* redefinition */ if( !falloc( p, class&FLDSIZ, 1, NIL ) ) { /* successful allocation */ psave( idp ); return; } /* blew it: resume at end of switch... */ } else switch( class ){ case EXTERN: switch( scl ){ case STATIC: case USTATIC: if( slev==0 ) return; break; case EXTDEF: case EXTERN: case FORTRAN: case UFORTRAN: return; } break; case STATIC: if( scl==USTATIC || (scl==EXTERN && blevel==0) ){ p->sclass = STATIC; if( ISFTN(type) ) curftn = idp; return; } break; case USTATIC: if( scl==STATIC || scl==USTATIC ) return; break; case LABEL: if( scl == ULABEL ){ p->sclass = LABEL; deflab( p->offset ); return; } break; case TYPEDEF: if( scl == class ) return; break; case UFORTRAN: if( scl == UFORTRAN || scl == FORTRAN ) return; break; case FORTRAN: if( scl == UFORTRAN ){ p->sclass = FORTRAN; if( ISFTN(type) ) curftn = idp; return; } break; case MOU: case MOS: if( scl == class ) { if( oalloc( p, &strucoff ) ) break; if( class == MOU ) strucoff = 0; psave( idp ); return; } break; case MOE: if( scl == class ){ if( p->offset!= strucoff++ ) break; psave( idp ); } break; case EXTDEF: if( scl == EXTERN ) { p->sclass = EXTDEF; if( ISFTN(type) ) curftn = idp; return; } break; case STNAME: case UNAME: case ENAME: if( scl != class ) break; if( dimtab[p->sizoff] == 0 ) return; /* previous entry just a mention */ break; case ULABEL: if( scl == LABEL || scl == ULABEL ) return; case PARAM: case AUTO: case REGISTER: ; /* mismatch.. */ } mismatch: /* allow nonunique structure/union member names */ if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */ int * memp; p->sflags |= SNONUNIQ; /* old entry is nonunique */ /* determine if name has occurred in this structure/union */ for( memp = ¶mstk[paramno-1]; /* while */ *memp>=0 && stab[*memp].sclass != STNAME && stab[*memp].sclass != UNAME; /* iterate */ --memp){ char * cname, * oname; if( stab[*memp].sflags & SNONUNIQ ){int k; cname=p->sname; oname=stab[*memp].sname; #ifndef FLEXNAMES for(k=1; k<=NCHNAM; ++k){ if(*cname++ != *oname)goto diff; if(!*oname++)break; } #else if (cname != oname) goto diff; #endif uerror("redeclaration of: %s",p->sname); break; diff: continue; } } p = mknonuniq( &idp ); /* update p and idp to new entry */ goto enter; } if( blevel > slev && class != EXTERN && class != FORTRAN && class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){ q->tn.rval = idp = hide( p ); p = &stab[idp]; goto enter; } #ifndef FLEXNAMES uerror( "redeclaration of %.8s", p->sname ); #else uerror( "redeclaration of %s", p->sname ); #endif if( class==EXTDEF && ISFTN(type) ) curftn = idp; return; enter: /* make a new entry */ # ifndef BUG1 if( ddebug ) printf( " new entry made\n" ); # endif if( type == UNDEF ) uerror("void type for %s",p->sname); p->stype = type; p->sclass = class; p->slevel = blevel; p->offset = NOOFFSET; p->suse = lineno; if( class == STNAME || class == UNAME || class == ENAME ) { p->sizoff = curdim; dstash( 0 ); /* size */ dstash( -1 ); /* index to members of str or union */ dstash( ALSTRUCT ); /* alignment */ dstash( idp ); /* name index */ } else { switch( BTYPE(type) ){ case STRTY: case UNIONTY: case ENUMTY: p->sizoff = q->fn.csiz; break; default: p->sizoff = BTYPE(type); } } /* copy dimensions */ p->dimoff = q->fn.cdim; /* allocate offsets */ if( class&FIELD ){ falloc( p, class&FLDSIZ, 0, NIL ); /* new entry */ psave( idp ); } else switch( class ){ case AUTO: oalloc( p, &autooff ); break; case STATIC: case EXTDEF: p->offset = getlab(); if( ISFTN(type) ) curftn = idp; break; case ULABEL: case LABEL: p->offset = getlab(); p->slevel = 2; if( class == LABEL ){ locctr( PROG ); deflab( p->offset ); } break; case EXTERN: case UFORTRAN: case FORTRAN: p->offset = getlab(); p->slevel = 0; break; case MOU: case MOS: oalloc( p, &strucoff ); if( class == MOU ) strucoff = 0; psave( idp ); break; case MOE: p->offset = strucoff++; psave( idp ); break; case REGISTER: if ( ISPTR(type) ) { p->offset = (regvar>>8)+8; regvar -= 1<<8; if ((regvar&~0377) < (minrvar&~0377)) { minrvar &= 0377; minrvar |= regvar&~0377; } } else { p->offset = regvar&0377; regvar = ((regvar&0377)-1) | (regvar&~0377); if ((regvar&0377) < (minrvar&0377)) { minrvar &= ~0377; minrvar |= regvar&0377; } } if( blevel == 1 ) p->sflags |= SSET; break; } /* user-supplied routine to fix up new definitions */ FIXDEF(p); # ifndef BUG1 if( ddebug ) printf( " dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset ); # endif } psave( i ){ if( paramno >= PARAMSZ ){ cerror( "parameter stack overflow"); } paramstk[ paramno++ ] = i; } ftnend(){ /* end of function */ if( retlab != NOLAB ){ /* inside a real function */ efcode(); } checkst(0); retstat = 0; tcheck(); curclass = SNULL; brklab = contlab = retlab = NOLAB; flostat = 0; if( nerrors == 0 ){ if( psavbc != & asavbc[0] ) cerror("bcsave error"); if( paramno != 0 ) cerror("parameter reset error"); if( swx != 0 ) cerror( "switch error"); } psavbc = &asavbc[0]; paramno = 0; autooff = AUTOINIT; minrvar = regvar = MAXRVAR | ((MAXRVAR-2)<<8); reached = 1; swx = 0; swp = swtab; locctr(DATA); } dclargs(){ register i, j; register struct symtab *p; register NODE *q; argoff = ARGINIT; # ifndef BUG1 if( ddebug > 2) printf("dclargs()\n"); # endif for( i=0; i<paramno; ++i ){ if( (j = paramstk[i]) < 0 ) continue; p = &stab[j]; # ifndef BUG1 if( ddebug > 2 ){ printf("\t%s (%d) ",p->sname, j); tprint(p->stype); printf("\n"); } # endif if( p->stype == FARG ) { q = block(FREE,NIL,NIL,INT,0,INT); q->tn.rval = j; defid( q, PARAM ); } oalloc( p, &argoff ); /* always set aside space, even for register arguments */ FIXARG(p); /* local arg hook, eg. for sym. debugger */ } cendarg(); locctr(PROG); defalign(ALINT); ++ftnno; bfcode( paramstk, paramno ); paramno = 0; } NODE * rstruct( idn, soru ){ /* reference to a structure or union, with no definition */ register struct symtab *p; register NODE *q; p = &stab[idn]; switch( p->stype ){ case UNDEF: def: q = block( FREE, NIL, NIL, 0, 0, 0 ); q->tn.rval = idn; q->in.type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY ); defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) ); break; case STRTY: if( soru & INSTRUCT ) break; goto def; case UNIONTY: if( soru & INUNION ) break; goto def; case ENUMTY: if( !(soru&(INUNION|INSTRUCT)) ) break; goto def; } stwart = instruct; return( mkty( p->stype, 0, p->sizoff ) ); } moedef( idn ){ register NODE *q; q = block( FREE, NIL, NIL, MOETY, 0, 0 ); q->tn.rval = idn; if( idn>=0 ) defid( q, MOE ); } bstruct( idn, soru ){ /* begining of structure or union declaration */ register NODE *q; psave( instruct ); psave( curclass ); psave( strucoff ); strucoff = 0; instruct = soru; q = block( FREE, NIL, NIL, 0, 0, 0 ); q->tn.rval = idn; if( instruct==INSTRUCT ){ curclass = MOS; q->in.type = STRTY; if( idn >= 0 ) defid( q, STNAME ); } else if( instruct == INUNION ) { curclass = MOU; q->in.type = UNIONTY; if( idn >= 0 ) defid( q, UNAME ); } else { /* enum */ curclass = MOE; q->in.type = ENUMTY; if( idn >= 0 ) defid( q, ENAME ); } psave( idn = q->tn.rval ); /* the "real" definition is where the members are seen */ if( idn >= 0 ) stab[idn].suse = lineno; return( paramno-4 ); } NODE * dclstruct( oparam ){ register struct symtab *p; register i, al, sa, j, sz, szindex; register TWORD temp; register high, low; /* paramstack contains: paramstack[ oparam ] = previous instruct paramstack[ oparam+1 ] = previous class paramstk[ oparam+2 ] = previous strucoff paramstk[ oparam+3 ] = structure name paramstk[ oparam+4, ... ] = member stab indices */ if( (i=paramstk[oparam+3]) < 0 ){ szindex = curdim; dstash( 0 ); /* size */ dstash( -1 ); /* index to member names */ dstash( ALSTRUCT ); /* alignment */ dstash( -lineno ); /* name of structure */ } else { szindex = stab[i].sizoff; } # ifndef BUG1 if( ddebug ){ #ifndef FLEXNAMES printf( "dclstruct( %.8s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex ); #else printf( "dclstruct( %s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex ); #endif } # endif temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY); stwart = instruct = paramstk[ oparam ]; curclass = paramstk[ oparam+1 ]; dimtab[ szindex+1 ] = curdim; al = ALSTRUCT; high = low = 0; for( i = oparam+4; i< paramno; ++i ){ dstash( j=paramstk[i] ); if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" ); p = &stab[j]; if( temp == ENUMTY ){ if( p->offset < low ) low = p->offset; if( p->offset > high ) high = p->offset; p->sizoff = szindex; continue; } sa = talign( p->stype, p->sizoff ); if( p->sclass & FIELD ){ sz = p->sclass&FLDSIZ; } else { sz = tsize( p->stype, p->dimoff, p->sizoff ); } if( sz == 0 ){ #ifndef FLEXNAMES werror( "illegal zero sized structure member: %.8s", p->sname ); #else werror( "illegal zero sized structure member: %s", p->sname ); #endif } if( sz > strucoff ) strucoff = sz; /* for use with unions */ SETOFF( al, sa ); /* set al, the alignment, to the lcm of the alignments of the members */ } dstash( -1 ); /* endmarker */ SETOFF( strucoff, al ); if( temp == ENUMTY ){ register TWORD ty; # ifdef ENUMSIZE ty = ENUMSIZE(high,low); # else if( (char)high == high && (char)low == low ) ty = ctype( CHAR ); else if( (short)high == high && (short)low == low ) ty = ctype( SHORT ); else ty = ctype(INT); #endif strucoff = tsize( ty, 0, (int)ty ); dimtab[ szindex+2 ] = al = talign( ty, (int)ty ); } if( strucoff == 0 ) uerror( "zero sized structure" ); dimtab[ szindex ] = strucoff; dimtab[ szindex+2 ] = al; dimtab[ szindex+3 ] = paramstk[ oparam+3 ]; /* name index */ FIXSTRUCT( szindex, oparam ); /* local hook, eg. for sym debugger */ # ifndef BUG1 if( ddebug>1 ){ printf( "\tdimtab[%d,%d,%d,%d] = %d,%d,%d,%d\n", szindex,szindex+1,szindex+2,szindex+3, dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2], dimtab[szindex+3] ); for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){ #ifndef FLEXNAMES printf( "\tmember %.8s(%d)\n", stab[dimtab[i]].sname, dimtab[i] ); #else printf( "\tmember %s(%d)\n", stab[dimtab[i]].sname, dimtab[i] ); #endif } } # endif strucoff = paramstk[ oparam+2 ]; paramno = oparam; return( mkty( temp, 0, szindex ) ); } /* VARARGS */ yyerror( s ) char *s; { /* error printing routine in parser */ uerror( s ); } yyaccpt(){ ftnend(); } ftnarg( idn ) { switch( stab[idn].stype ){ case UNDEF: /* this parameter, entered at scan */ break; case FARG: #ifndef FLEXNAMES uerror("redeclaration of formal parameter, %.8s", #else uerror("redeclaration of formal parameter, %s", #endif stab[idn].sname); /* fall thru */ case FTN: /* the name of this function matches parm */ /* fall thru */ default: idn = hide( &stab[idn]); break; case TNULL: /* unused entry, fill it */ ; } stab[idn].stype = FARG; stab[idn].sclass = PARAM; psave( idn ); } talign( ty, s) register unsigned ty; register s; { /* compute the alignment of an object with type ty, sizeoff index s */ register i; if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT #ifdef LONGFIELDS && ty!=LONG && ty!=ULONG #endif ){ return( fldal( ty ) ); } for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){ switch( (ty>>i)&TMASK ){ case FTN: cerror( "compiler takes alignment of function"); case PTR: return( ALPOINT ); case ARY: continue; case 0: break; } } switch( BTYPE(ty) ){ case UNIONTY: case ENUMTY: case STRTY: return( (unsigned int) dimtab[ s+2 ] ); case CHAR: case UCHAR: return( ALCHAR ); case FLOAT: return( ALFLOAT ); case DOUBLE: return( ALDOUBLE ); case LONG: case ULONG: return( ALLONG ); case SHORT: case USHORT: return( ALSHORT ); default: return( ALINT ); } } OFFSZ tsize( ty, d, s ) TWORD ty; { /* compute the size associated with type ty, dimoff d, and sizoff s */ /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */ int i; OFFSZ mult; mult = 1; for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){ switch( (ty>>i)&TMASK ){ case FTN: cerror( "compiler takes size of function"); case PTR: return( SZPOINT * mult ); case ARY: mult *= (unsigned int) dimtab[ d++ ]; continue; case 0: break; } } if( dimtab[s]==0 ) { uerror( "unknown size"); return( SZINT ); } return( (unsigned int) dimtab[ s ] * mult ); } inforce( n ) OFFSZ n; { /* force inoff to have the value n */ /* inoff is updated to have the value n */ OFFSZ wb; register rest; /* rest is used to do a lot of conversion to ints... */ if( inoff == n ) return; if( inoff > n ) { cerror( "initialization alignment error"); } wb = inoff; SETOFF( wb, SZINT ); /* wb now has the next higher word boundary */ if( wb >= n ){ /* in the same word */ rest = n - inoff; vfdzero( rest ); return; } /* otherwise, extend inoff to be word aligned */ rest = wb - inoff; vfdzero( rest ); /* now, skip full words until near to n */ rest = (n-inoff)/SZINT; zecode( rest ); /* now, the remainder of the last word */ rest = n-inoff; vfdzero( rest ); if( inoff != n ) cerror( "inoff error"); } vfdalign( n ){ /* make inoff have the offset the next alignment of n */ OFFSZ m; m = inoff; SETOFF( m, n ); inforce( m ); } int idebug = 0; int ibseen = 0; /* the number of } constructions which have been filled */ int iclass; /* storage class of thing being initialized */ int ilocctr = 0; /* location counter for current initialization */ beginit(curid){ /* beginning of initilization; set location ctr and set type */ register struct symtab *p; # ifndef BUG1 if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid ); # endif p = &stab[curid]; iclass = p->sclass; if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN; switch( iclass ){ case UNAME: case EXTERN: return; case AUTO: case REGISTER: break; case EXTDEF: case STATIC: ilocctr = ISARY(p->stype)?ADATA:DATA; locctr( ilocctr ); defalign( talign( p->stype, p->sizoff ) ); defnam( p ); } inoff = 0; ibseen = 0; pstk = 0; instk( curid, p->stype, p->dimoff, p->sizoff, inoff ); } instk( id, t, d, s, off ) OFFSZ off; TWORD t; { /* make a new entry on the parameter stack to initialize id */ register struct symtab *p; for(;;){ # ifndef BUG1 if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off ); # endif /* save information on the stack */ if( !pstk ) pstk = instack; else ++pstk; pstk->in_fl = 0; /* { flag */ pstk->in_id = id ; pstk->in_t = t ; pstk->in_d = d ; pstk->in_s = s ; pstk->in_n = 0; /* number seen */ pstk->in_x = t==STRTY ?dimtab[s+1] : 0 ; pstk->in_off = off; /* offset at the beginning of this element */ /* if t is an array, DECREF(t) can't be a field */ /* INS_sz has size of array elements, and -size for fields */ if( ISARY(t) ){ pstk->in_sz = tsize( DECREF(t), d+1, s ); } else if( stab[id].sclass & FIELD ){ pstk->in_sz = - ( stab[id].sclass & FLDSIZ ); } else { pstk->in_sz = 0; } if( (iclass==AUTO || iclass == REGISTER ) && (ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" ); /* now, if this is not a scalar, put on another element */ if( ISARY(t) ){ t = DECREF(t); ++d; continue; } else if( t == STRTY ){ id = dimtab[pstk->in_x]; p = &stab[id]; if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" ); t = p->stype; d = p->dimoff; s = p->sizoff; off += p->offset; continue; } else return; } } NODE * getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */ register l, temp; register NODE *p; if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) && pstk!=instack && ISARY( pstk[-1].in_t ) ){ /* treat "abc" as { 'a', 'b', 'c', 0 } */ strflg = 1; ilbrace(); /* simulate { */ inforce( pstk->in_off ); /* if the array is inflexible (not top level), pass in the size and be prepared to throw away unwanted initializers */ lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0); /* get the contents */ irbrace(); /* simulate } */ return( NIL ); } else { /* make a label, and get the contents and stash them away */ if( iclass != SNULL ){ /* initializing */ /* fill out previous word, to permit pointer */ vfdalign( ALPOINT ); } temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */ deflab( l = getlab() ); strflg = 0; lxstr(0); /* get the contents */ locctr( blevel==0?ilocctr:temp ); p = buildtree( STRING, NIL, NIL ); p->tn.rval = -l; return(p); } } putbyte( v ){ /* simulate byte v appearing in a list of integer values */ register NODE *p; p = bcon(v); incode( p, SZCHAR ); tfree( p ); gotscal(); } endinit(){ register TWORD t; register d, s, n, d1; # ifndef BUG1 if( idebug ) printf( "endinit(), inoff = %d\n", inoff ); # endif switch( iclass ){ case EXTERN: case AUTO: case REGISTER: return; } pstk = instack; t = pstk->in_t; d = pstk->in_d; s = pstk->in_s; n = pstk->in_n; if( ISARY(t) ){ d1 = dimtab[d]; vfdalign( pstk->in_sz ); /* fill out part of the last element, if needed */ n = inoff/pstk->in_sz; /* real number of initializers */ if( d1 >= n ){ /* once again, t is an array, so no fields */ inforce( tsize( t, d, s ) ); n = d1; } if( d1!=0 && d1!=n ) uerror( "too many initializers"); if( n==0 ) werror( "empty array declaration"); dimtab[d] = n; } else if( t == STRTY || t == UNIONTY ){ /* clearly not fields either */ inforce( tsize( t, d, s ) ); } else if( n > 1 ) uerror( "bad scalar initialization"); /* this will never be called with a field element... */ else inforce( tsize(t,d,s) ); paramno = 0; vfdalign( AL_INIT ); inoff = 0; iclass = SNULL; } doinit( p ) register NODE *p; { /* take care of generating a value for the initializer p */ /* inoff has the current offset (last bit written) in the current word being generated */ register sz, d, s; register TWORD t; /* note: size of an individual initializer is assumed to fit into an int */ if( iclass < 0 ) goto leave; if( iclass == EXTERN || iclass == UNAME ){ uerror( "cannot initialize extern or union" ); iclass = -1; goto leave; } if( iclass == AUTO || iclass == REGISTER ){ /* do the initialization and get out, without regard for filing out the variable with zeros, etc. */ bccode(); idname = pstk->in_id; p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p ); ecomp(p); return; } if( p == NIL ) return; /* for throwing away strings that have been turned into lists */ if( ibseen ){ uerror( "} expected"); goto leave; } # ifndef BUG1 if( idebug > 1 ) printf( "doinit(%o)\n", p ); # endif t = pstk->in_t; /* type required */ d = pstk->in_d; s = pstk->in_s; if( pstk->in_sz < 0 ){ /* bit field */ sz = -pstk->in_sz; } else { sz = tsize( t, d, s ); } inforce( pstk->in_off ); p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p ); p->in.left->in.op = FREE; p->in.left = p->in.right; p->in.right = NIL; p->in.left = optim( p->in.left ); if( p->in.left->in.op == UNARY AND ){ p->in.left->in.op = FREE; p->in.left = p->in.left->in.left; } p->in.op = INIT; if( sz < SZINT ){ /* special case: bit fields, etc. */ if( p->in.left->in.op != ICON ) uerror( "illegal initialization" ); else incode( p->in.left, sz ); } else if( p->in.left->in.op == FCON ){ fincode( p->in.left->fpn.dval, sz ); } else { cinit( optim(p), sz ); } gotscal(); leave: tfree(p); } gotscal(){ register t, ix; register n, id; struct symtab *p; OFFSZ temp; for( ; pstk > instack; ) { if( pstk->in_fl ) ++ibseen; --pstk; t = pstk->in_t; if( t == STRTY ){ ix = ++pstk->in_x; if( (id=dimtab[ix]) < 0 ) continue; /* otherwise, put next element on the stack */ p = &stab[id]; instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off ); return; } else if( ISARY(t) ){ n = ++pstk->in_n; if( n >= dimtab[pstk->in_d] && pstk > instack ) continue; /* put the new element onto the stack */ temp = pstk->in_sz; instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s, pstk->in_off+n*temp ); return; } } } ilbrace(){ /* process an initializer's left brace */ register t; struct instk *temp; temp = pstk; for( ; pstk > instack; --pstk ){ t = pstk->in_t; if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */ if( pstk->in_fl ){ /* already associated with a { */ if( pstk->in_n ) uerror( "illegal {"); continue; } /* we have one ... */ pstk->in_fl = 1; break; } /* cannot find one */ /* ignore such right braces */ pstk = temp; } irbrace(){ /* called when a '}' is seen */ # ifndef BUG1 if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno ); # endif if( ibseen ) { --ibseen; return; } for( ; pstk > instack; --pstk ){ if( !pstk->in_fl ) continue; /* we have one now */ pstk->in_fl = 0; /* cancel { */ gotscal(); /* take it away... */ return; } /* these right braces match ignored left braces: throw out */ } upoff( size, alignment, poff ) register alignment, *poff; { /* update the offset pointed to by poff; return the /* offset of a value of size `size', alignment `alignment', /* given that off is increasing */ register off; off = *poff; SETOFF( off, alignment ); if( (offsz-off) <= size ){ if( instruct!=INSTRUCT )cerror("too many local variables"); else cerror("Structure too large"); } *poff = off+size; return( off ); } oalloc( p, poff ) register struct symtab *p; register *poff; { /* allocate p with offset *poff, and update *poff */ register al, off, tsz; int noff; al = talign( p->stype, p->sizoff ); noff = off = *poff; tsz = tsize( p->stype, p->dimoff, p->sizoff ); #ifdef BACKAUTO if( p->sclass == AUTO ){ if( (offsz-off) <= tsz ) cerror("too many local variables"); noff = off + tsz; SETOFF( noff, al ); off = -noff; } else #endif if( (p->sclass==PARAM || p->sclass==REGISTER) && ( tsz < SZINT ) ){ off = upoff( SZINT, ALINT, &noff ); # ifndef RTOLBYTES off = noff - tsz; #endif } else { off = upoff( tsz, al, &noff ); } if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */ if( p->offset == NOOFFSET ) p->offset = off; else if( off != p->offset ) return(1); } *poff = noff; return(0); } falloc( p, w, new, pty ) register struct symtab *p; NODE *pty; { /* allocate a field of width w */ /* new is 0 if new entry, 1 if redefinition, -1 if alignment */ register al,sz,type; type = (new<0)? pty->in.type : p->stype; /* this must be fixed to use the current type in alignments */ switch( new<0?pty->in.type:p->stype ){ case ENUMTY: { int s; s = new<0 ? pty->fn.csiz : p->sizoff; al = dimtab[s+2]; sz = dimtab[s]; break; } case CHAR: case UCHAR: al = ALCHAR; sz = SZCHAR; break; case SHORT: case USHORT: al = ALSHORT; sz = SZSHORT; break; case INT: case UNSIGNED: al = ALINT; sz = SZINT; break; #ifdef LONGFIELDS case LONG: case ULONG: al = ALLONG; sz = SZLONG; break; #endif default: if( new < 0 ) { uerror( "illegal field type" ); al = ALINT; } else { al = fldal( p->stype ); sz =SZINT; } } if( w > sz ) { uerror( "field too big"); w = sz; } if( w == 0 ){ /* align only */ SETOFF( strucoff, al ); if( new >= 0 ) uerror( "zero size field"); return(0); } if( strucoff%al + w > sz ) SETOFF( strucoff, al ); if( new < 0 ) { if( (offsz-strucoff) <= w ) cerror("structure too large"); strucoff += w; /* we know it will fit */ return(0); } /* establish the field */ if( new == 1 ) { /* previous definition */ if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1); } p->offset = strucoff; if( (offsz-strucoff) <= w ) cerror("structure too large"); strucoff += w; p->stype = type; fldty( p ); return(0); } nidcl( p ) NODE *p; { /* handle unitialized declarations */ /* assumed to be not functions */ register class; register commflag; /* flag for labelled common declarations */ commflag = 0; /* compute class */ if( (class=curclass) == SNULL ){ if( blevel > 1 ) class = AUTO; else if( blevel != 0 || instruct ) cerror( "nidcl error" ); else { /* blevel = 0 */ class = noinit(); if( class == EXTERN ) commflag = 1; } } defid( p, class ); if( class==EXTDEF || class==STATIC ){ /* simulate initialization by 0 */ beginit(p->tn.rval); endinit(); } if( commflag ) commdec( p->tn.rval ); } TWORD types( t1, t2, t3 ) TWORD t1, t2, t3; { /* return a basic type from basic types t1, t2, and t3 */ TWORD t[3], noun, adj, unsg; register i; t[0] = t1; t[1] = t2; t[2] = t3; unsg = INT; /* INT or UNSIGNED */ noun = UNDEF; /* INT, CHAR, or FLOAT */ adj = INT; /* INT, LONG, or SHORT */ for( i=0; i<3; ++i ){ switch( t[i] ){ default: bad: uerror( "illegal type combination" ); return( INT ); case UNDEF: continue; case UNSIGNED: if( unsg != INT ) goto bad; unsg = UNSIGNED; continue; case LONG: case SHORT: if( adj != INT ) goto bad; adj = t[i]; continue; case INT: case CHAR: case FLOAT: if( noun != UNDEF ) goto bad; noun = t[i]; continue; } } /* now, construct final type */ if( noun == UNDEF ) noun = INT; else if( noun == FLOAT ){ if( unsg != INT || adj == SHORT ) goto bad; return( adj==LONG ? DOUBLE : FLOAT ); } else if( noun == CHAR && adj != INT ) goto bad; /* now, noun is INT or CHAR */ if( adj != INT ) noun = adj; if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) ); else return( noun ); } NODE * tymerge( typ, idp ) NODE *typ, *idp; { /* merge type typ with identifier idp */ register unsigned t; register i; extern int eprint(); if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" ); if(idp == NIL ) return( NIL ); # ifndef BUG1 if( ddebug > 2 ) fwalk( idp, eprint, 0 ); # endif idp->in.type = typ->in.type; idp->fn.cdim = curdim; tyreduce( idp ); idp->fn.csiz = typ->fn.csiz; for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){ if( ISARY(t) ) dstash( dimtab[i++] ); } /* now idp is a single node: fix up type */ idp->in.type = ctype( idp->in.type ); if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){ idp->fn.csiz = t; /* in case ctype has rewritten things */ } return( idp ); } tyreduce( p ) register NODE *p; { /* build a type, and stash away dimensions, from a parse tree of the declaration */ /* the type is build top down, the dimensions bottom up */ register o, temp; register unsigned t; o = p->in.op; p->in.op = FREE; if( o == NAME ) return; t = INCREF( p->in.type ); if( o == UNARY CALL ) t += (FTN-PTR); else if( o == LB ){ t += (ARY-PTR); temp = p->in.right->tn.lval; p->in.right->in.op = FREE; } p->in.left->in.type = t; tyreduce( p->in.left ); if( o == LB ) dstash( temp ); p->tn.rval = p->in.left->tn.rval; p->in.type = p->in.left->in.type; } fixtype( p, class ) register NODE *p; { register unsigned t, type; register mod1, mod2; /* fix up the types, and check for legality */ if( (type = p->in.type) == UNDEF ) return; if( mod2 = (type&TMASK) ){ t = DECREF(type); while( mod1=mod2, mod2 = (t&TMASK) ){ if( mod1 == ARY && mod2 == FTN ){ uerror( "array of functions is illegal" ); type = 0; } else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){ uerror( "function returns illegal type" ); type = 0; } t = DECREF(t); } } /* detect function arguments, watching out for structure declarations */ /* for example, beware of f(x) struct [ int a[10]; } *x; { ... } */ /* the danger is that "a" will be converted to a pointer */ if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) ) class = PARAM; if( class == PARAM || ( class==REGISTER && blevel==1 ) ){ if( type == FLOAT ) type = DOUBLE; else if( ISARY(type) ){ ++p->fn.cdim; type += (PTR-ARY); } else if( ISFTN(type) ){ werror( "a function is declared as an argument" ); type = INCREF(type); } } if( instruct && ISFTN(type) ){ uerror( "function illegal in structure or union" ); type = INCREF(type); } p->in.type = type; } uclass( class ) register class; { /* give undefined version of class */ if( class == SNULL ) return( EXTERN ); else if( class == STATIC ) return( USTATIC ); else if( class == FORTRAN ) return( UFORTRAN ); else return( class ); } fixclass( class, type ) TWORD type; { /* first, fix null class */ if( class == SNULL ){ if( instruct&INSTRUCT ) class = MOS; else if( instruct&INUNION ) class = MOU; else if( blevel == 0 ) class = EXTDEF; else if( blevel == 1 ) class = PARAM; else class = AUTO; } /* now, do general checking */ if( ISFTN( type ) ){ switch( class ) { default: uerror( "function has illegal storage class" ); case AUTO: class = EXTERN; case EXTERN: case EXTDEF: case FORTRAN: case TYPEDEF: case STATIC: case UFORTRAN: case USTATIC: ; } } if( class&FIELD ){ if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" ); return( class ); } switch( class ){ case MOU: if( !(instruct&INUNION) ) uerror( "illegal class" ); return( class ); case MOS: if( !(instruct&INSTRUCT) ) uerror( "illegal class" ); return( class ); case MOE: if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" ); return( class ); case REGISTER: if( blevel == 0 ) uerror( "illegal register declaration" ); else if ( ISPTR(type) ) { if( ((regvar>>8)&0377) >= MINRVAR && cisreg( type ) ) return( class ); } else { if( (regvar&0377) >= MINRVAR && cisreg( type ) ) return( class ); } if( blevel == 1 ) return( PARAM ); else return( AUTO ); case AUTO: case LABEL: case ULABEL: if( blevel < 2 ) uerror( "illegal class" ); return( class ); case PARAM: if( blevel != 1 ) uerror( "illegal class" ); return( class ); case UFORTRAN: case FORTRAN: # ifdef NOFORTRAN NOFORTRAN; /* a condition which can regulate the FORTRAN usage */ # endif if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" ); else { type = DECREF(type); if( ISFTN(type) || ISARY(type) || ISPTR(type) ) { uerror( "fortran function has wrong type" ); } } case STNAME: case UNAME: case ENAME: case EXTERN: case STATIC: case EXTDEF: case TYPEDEF: case USTATIC: return( class ); default: cerror( "illegal class: %d", class ); /* NOTREACHED */ } } struct symtab * mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */ /* an occurrence of a nonunique structure member name */ /* or field */ register i; register struct symtab * sp; char *p,*q; sp = & stab[ i= *idindex ]; /* position search at old entry */ while( sp->stype != TNULL ){ /* locate unused entry */ if( ++i >= SYMTSZ ){/* wrap around symbol table */ i = 0; sp = stab; } else ++sp; if( i == *idindex ) cerror("Symbol table full"); } sp->sflags = SNONUNIQ | SMOS; p = sp->sname; q = stab[*idindex].sname; /* old entry name */ #ifdef FLEXNAMES sp->sname = stab[*idindex].sname; #endif # ifndef BUG1 if( ddebug ){ printf("\tnonunique entry for %s from %d to %d\n", q, *idindex, i ); } # endif *idindex = i; #ifndef FLEXNAMES for( i=1; i<=NCHNAM; ++i ){ /* copy name */ if( *p++ = *q /* assign */ ) ++q; } #endif return ( sp ); } lookup( name, s) char *name; { /* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */ register char *p, *q; int i, j, ii; register struct symtab *sp; /* compute initial hash index */ # ifndef BUG1 if( ddebug > 2 ){ printf( "lookup( %.8s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct ); } # endif i = 0; #ifndef FLEXNAMES for( p=name, j=0; *p != '\0'; ++p ){ i += *p; if( ++j >= NCHNAM ) break; } #else i = (int)name; #endif /* this will not have overflowed, since NCHNAM is small relative to /* the wordsize... */ i = i%SYMTSZ; sp = &stab[ii=i]; for(;;){ /* look for name */ if( sp->stype == TNULL ){ /* empty slot */ sp->sflags = s; /* set STAG, SMOS if needed, turn off all others */ #ifndef FLEXNAMES p = sp->sname; for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name; #else sp->sname = name; #endif sp->stype = UNDEF; sp->sclass = SNULL; return( i ); } if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next; p = sp->sname; q = name; #ifndef FLEXNAMES for( j=0; j<NCHNAM;++j ){ if( *p++ != *q ) goto next; if( !*q++ ) break; } return( i ); #else if (p == q) return ( i ); #endif next: if( ++i >= SYMTSZ ){ i = 0; sp = stab; } else ++sp; if( i == ii ) cerror( "symbol table full" ); } } #ifndef checkst /* if not debugging, make checkst a macro */ checkst(lev){ register int s, i, j; register struct symtab *p, *q; for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){ if( p->stype == TNULL ) continue; j = lookup( p->sname, p->sflags&(SMOS|STAG) ); if( j != i ){ q = &stab[j]; if( q->stype == UNDEF || q->slevel <= p->slevel ){ #ifndef FLEXNAMES cerror( "check error: %.8s", q->sname ); #else cerror( "check error: %s", q->sname ); #endif } } #ifndef FLEXNAMES else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev ); #else else if( p->slevel > lev ) cerror( "%s check at level %d", p->sname, lev ); #endif } } #endif struct symtab * relook(p) register struct symtab *p; { /* look up p again, and see where it lies */ register struct symtab *q; /* I'm not sure that this handles towers of several hidden definitions in all cases */ q = &stab[lookup( p->sname, p->sflags&(STAG|SMOS|SHIDDEN) )]; /* make relook always point to either p or an empty cell */ if( q->stype == UNDEF ){ q->stype = TNULL; return(q); } while( q != p ){ if( q->stype == TNULL ) break; if( ++q >= &stab[SYMTSZ] ) q=stab; } return(q); } clearst( lev ){ /* clear entries of internal scope from the symbol table */ register struct symtab *p, *q, *r; register int temp, rehash; temp = lineno; aobeg(); /* first, find an empty slot to prevent newly hashed entries from being slopped into... */ for( q=stab; q< &stab[SYMTSZ]; ++q ){ if( q->stype == TNULL )goto search; } cerror( "symbol table full"); search: p = q; for(;;){ if( p->stype == TNULL ) { rehash = 0; goto next; } lineno = p->suse; if( lineno < 0 ) lineno = - lineno; if( p->slevel>lev ){ /* must clobber */ if( p->stype == UNDEF || ( p->sclass == ULABEL && lev < 2 ) ){ lineno = temp; #ifndef FLEXNAMES uerror( "%.8s undefined", p->sname ); #else uerror( "%s undefined", p->sname ); #endif } else aocode(p); # ifndef BUG1 #ifndef FLEXNAMES if (ddebug) printf("removing %8s from stab[ %d], flags %o level %d\n", #else if (ddebug) printf("removing %s from stab[ %d], flags %o level %d\n", #endif p->sname,p-stab,p->sflags,p->slevel); # endif if( p->sflags & SHIDES ) unhide(p); p->stype = TNULL; rehash = 1; goto next; } if( rehash ){ if( (r=relook(p)) != p ){ movestab( r, p ); p->stype = TNULL; } } next: if( ++p >= &stab[SYMTSZ] ) p = stab; if( p == q ) break; } lineno = temp; aoend(); } movestab( p, q ) register struct symtab *p, *q; { int k; /* structure assignment: *p = *q; */ p->stype = q->stype; p->sclass = q->sclass; p->slevel = q->slevel; p->offset = q->offset; p->sflags = q->sflags; p->dimoff = q->dimoff; p->sizoff = q->sizoff; p->suse = q->suse; #ifndef FLEXNAMES for( k=0; k<NCHNAM; ++k ){ p->sname[k] = q->sname[k]; } #else p->sname = q->sname; #endif } hide( p ) register struct symtab *p; { register struct symtab *q; for( q=p+1; ; ++q ){ if( q >= &stab[SYMTSZ] ) q = stab; if( q == p ) cerror( "symbol table full" ); if( q->stype == TNULL ) break; } movestab( q, p ); p->sflags |= SHIDDEN; q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES; #ifndef FLEXNAMES if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname ); #else if( hflag ) werror( "%s redefinition hides earlier one", p->sname ); #endif # ifndef BUG1 if( ddebug ) printf( " %d hidden in %d\n", p-stab, q-stab ); # endif return( idname = q-stab ); } unhide( p ) register struct symtab *p; { register struct symtab *q; register s, j; s = p->sflags & (SMOS|STAG); q = p; for(;;){ if( q == stab ) q = &stab[SYMTSZ-1]; else --q; if( q == p ) break; if( (q->sflags&(SMOS|STAG)) == s ){ #ifndef FLEXNAMES for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break; if( j == NCHNAM ){ /* found the name */ #else if (p->sname == q->sname) { #endif q->sflags &= ~SHIDDEN; # ifndef BUG1 if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab); # endif return; } } } cerror( "unhide fails" ); } ebugging, make checkst a macro */ checkst(lev){ register int s, i, j; register struct symtab *p, *q; for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){ if( p->stype == TNULL ) continue;sumacc/cc/ccom/reader.c 444 0 12 62037 3470501552 10246 # include "mfile2" /* some storage declarations */ # ifndef ONEPASS NODE node[TREESZ]; char filename[100] = ""; /* the name of the file */ int ftnno; /* number of current function */ int lineno; # else # define NOMAIN #endif int nrecur; int lflag; int nospflag; int edebug = 0; int xdebug = 0; int udebug = 0; OFFSZ tmpoff; /* offset for first temporary, in bits for current block */ OFFSZ maxoff; /* maximum temporary offset over all blocks in current ftn, in bits */ int maxtreg; NODE *stotree; int stocook; OFFSZ baseoff = 0; OFFSZ maxtemp = 0; int fldtyp; p2init( argc, argv ) char *argv[];{ /* set the values of the pass 2 arguments */ register int c; register char *cp; register files; allo0(); /* free all regs */ files = 0; for( c=1; c<argc; ++c ){ if( *(cp=argv[c]) == '-' ){ while( *++cp ){ switch( *cp ){ case 'X': /* pass1 flags */ while( *++cp ) { /* VOID */ } --cp; break; case 'l': /* linenos */ ++lflag; break; case 'e': /* expressions */ ++edebug; break; case 'o': /* orders */ ++odebug; break; case 'r': /* register allocation */ ++rdebug; break; case 'a': /* rallo */ ++radebug; break; case 't': /* ttype calls */ ++tdebug; break; case 's': /* suppress stack probe ? */ if( cp[1] == 'p' ) { nospflag++; cp++; } else /* or shapes */ ++sdebug; break; case 'u': /* Sethi-Ullman testing (machine dependent) */ ++udebug; break; case 'x': /* general machine-dependent debugging flag */ ++xdebug; break; default: cerror( "bad option: %c", *cp ); } } } else files = 1; /* assumed to be a filename */ } mkdope(); setrew(); return( files ); } # ifndef NOMAIN mainp2( argc, argv ) char *argv[]; { register files; register temp; register c; register char *cp; register NODE *p; files = p2init( argc, argv ); tinit(); reread: if( files ){ while( files < argc && argv[files][0] == '-' ) { ++files; } if( files > argc ) return( nerrors ); freopen( argv[files], "r", stdin ); } while( (c=getchar()) > 0 ) switch( c ){ case ')': /* copy line unchanged */ while( (c=getchar()) > 0 ){ PUTCHAR(c); if( c == '\n' ) break; } continue; case '[': /* beginning of a block */ temp = rdin(10); /* ftnno */ tmpoff = baseoff = rdin(10); /* autooff for block gives max offset of autos in block */ maxtreg = rdin(10); if( getchar() != '\n' ) cerror( "intermediate file format error"); if( temp != ftnno ){ /* beginning of function */ maxoff = baseoff; ftnno = temp; maxtemp = 0; } else { if( baseoff > maxoff ) maxoff = baseoff; /* maxoff at end of ftn is max of autos and temps over all blocks in the function */ } setregs(); continue; case ']': /* end of block */ SETOFF( maxoff, ALSTACK ); eobl2(); while( (c=getchar()) != '\n' ){ if( c <= 0 ) cerror( "intermediate file format eof" ); } continue; case '.': /* compile code for an expression */ lineno = rdin( 10 ); for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */ *cp = '\0'; if( lflag ) lineid( lineno, filename ); tmpoff = baseoff; /* expression at top level reuses temps */ p = eread(); # ifndef BUG4 if( edebug ) fwalk( p, eprint, 0 ); # endif # ifdef MYREADER MYREADER(p); /* do your own laundering of the input */ # endif nrecur = 0; delay( p ); /* expression statement throws out results */ reclaim( p, RNULL, 0 ); allchk(); tcheck(); continue; default: cerror( "intermediate file format error" ); } /* EOF */ if( files ) goto reread; return(nerrors); } # endif # ifdef ONEPASS p2compile( p ) NODE *p; { if( lflag ) lineid( lineno, filename ); tmpoff = baseoff; /* expression at top level reuses temps */ /* generate code for the tree p */ # ifndef BUG4 if( edebug ) fwalk( p, eprint, 0 ); # endif # ifdef MYREADER MYREADER(p); /* do your own laundering of the input */ # endif nrecur = 0; delay( p ); /* do the code generation */ reclaim( p, RNULL, 0 ); allchk(); /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */ /* first pass will do it... */ } p2bbeg( aoff, myreg ) { static int myftn = -1; tmpoff = baseoff = aoff; maxtreg = myreg; if( myftn != ftnno ){ /* beginning of function */ maxoff = baseoff; myftn = ftnno; maxtemp = 0; } else { if( baseoff > maxoff ) maxoff = baseoff; /* maxoff at end of ftn is max of autos and temps over all blocks */ } setregs(); } p2bend(){ SETOFF( maxoff, ALSTACK ); eobl2(); } # endif NODE *deltrees[DELAYS]; int deli; delay( p ) register NODE *p; { /* look in all legal places for COMOP's and ++ and -- ops to delay */ /* note; don't delay ++ and -- within calls or things like /* getchar (in their macro forms) will start behaving strangely */ register i; /* look for visible COMOPS, and rewrite repeatedly */ while( delay1( p ) ) { /* VOID */ } /* look for visible, delayable ++ and -- */ deli = 0; delay2( p ); codgen( p, FOREFF ); /* do what is left */ for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF ); /* do the rest */ } delay1( p ) register NODE *p; { /* look for COMOPS */ register o, ty; o = p->in.op; ty = optype( o ); if( ty == LTYPE ) return( 0 ); else if( ty == UTYPE ) return( delay1( p->in.left ) ); switch( o ){ case QUEST: case ANDAND: case OROR: /* don't look on RHS */ return( delay1(p->in.left ) ); case COMOP: /* the meat of the routine */ delay( p->in.left ); /* completely evaluate the LHS */ /* rewrite the COMOP */ { register NODE *q; q = p->in.right; ncopy( p, p->in.right ); q->in.op = FREE; } return( 1 ); } return( delay1(p->in.left) || delay1(p->in.right ) ); } delay2( p ) register NODE *p; { /* look for delayable ++ and -- operators */ register o, ty; o = p->in.op; ty = optype( o ); switch( o ){ case NOT: case QUEST: case ANDAND: case OROR: case CALL: case UNARY CALL: case STCALL: case UNARY STCALL: case FORTCALL: case UNARY FORTCALL: case COMOP: case CBRANCH: /* for the moment, don7t delay past a conditional context, or /* inside of a call */ return; case INCR: case DECR: if( deltest( p ) ){ if( deli < DELAYS ){ register NODE *q; deltrees[deli++] = tcopy(p); q = p->in.left; p->in.right->in.op = FREE; /* zap constant */ ncopy( p, q ); q->in.op = FREE; return; } } } if( ty == BITYPE ) delay2( p->in.right ); if( ty != LTYPE ) delay2( p->in.left ); } codgen( p, cookie ) NODE *p; { /* generate the code for p; order may call codgen recursively */ /* cookie is used to describe the context */ for(;;){ canon(p); /* creats OREG from * if possible and does sucomp */ stotree = NIL; # ifndef BUG4 if( edebug ){ printf( "store called on:\n" ); fwalk( p, eprint, 0 ); } # endif store(p); if( stotree==NIL ) break; /* because it's minimal, can do w.o. stores */ order( stotree, stocook ); } order( p, cookie ); } # ifndef BUG4 char *cnames[] = { "SANY", "SAREG", "STAREG", "SBREG", "STBREG", "SCC", "SNAME", "SCON", "SFLD", "SOREG", "STARNM", "STARREG", "INTEMP", "FORARG", "SWADD", 0, }; prcook( cookie ){ /* print a nice-looking description of cookie */ int i, flag; if( cookie & SPECIAL ){ if( cookie == SZERO ) printf( "SZERO" ); else if( cookie == SONE ) printf( "SONE" ); else if( cookie == SMONE ) printf( "SMONE" ); else printf( "SPECIAL+%d", cookie & ~SPECIAL ); return; } flag = 0; for( i=0; cnames[i]; ++i ){ if( cookie & (1<<i) ){ if( flag ) printf( "|" ); ++flag; printf( cnames[i] ); } } } # endif int odebug = 0; order(p,cook) NODE *p; { register o, ty, m; int m1; int cookie; NODE *p1, *p2; cookie = cook; rcount(); canon(p); rallo( p, p->in.rall ); goto first; /* by this time, p should be able to be generated without stores; the only question is how */ again: cookie = cook; rcount(); canon(p); rallo( p, p->in.rall ); /* if any rewriting and canonicalization has put * the tree (p) into a shape that cook is happy * with (exclusive of FOREFF, FORREW, and INTEMP) * then we are done. * this allows us to call order with shapes in * addition to cookies and stop short if possible. */ if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return; first: # ifndef BUG4 if( odebug ){ printf( "order( %o, ", p ); prcook( cookie ); printf( " )\n" ); fwalk( p, eprint, 0 ); } # endif o = p->in.op; ty = optype(o); /* first of all, for most ops, see if it is in the table */ /* look for ops */ switch( m = p->in.op ){ default: /* look for op in table */ for(;;){ if( (m = match( p, cookie ) ) == MDONE ) goto cleanup; else if( m == MNOPE ){ if( !(cookie = nextcook( p, cookie ) ) ) goto nomat; continue; } else break; } break; case COMOP: case FORCE: case CBRANCH: case QUEST: case ANDAND: case OROR: case NOT: case UNARY CALL: case CALL: case UNARY STCALL: case STCALL: case UNARY FORTCALL: case FORTCALL: /* don't even go near the table... */ ; } /* get here to do rewriting if no match or fall through from above for hard ops */ p1 = p->in.left; if( ty == BITYPE ) p2 = p->in.right; else p2 = NIL; # ifndef BUG4 if( odebug ){ printf( "order( %o, ", p ); prcook( cook ); printf( " ), cookie " ); prcook( cookie ); printf( ", rewrite %s\n", opst[m] ); } # endif switch( m ){ default: nomat: cerror( "no table entry for op %s", opst[p->in.op] ); case COMOP: codgen( p1, FOREFF ); p2->in.rall = p->in.rall; codgen( p2, cookie ); ncopy( p, p2 ); p2->in.op = FREE; goto cleanup; case FORCE: /* recurse, letting the work be done by rallo */ p = p->in.left; cook = INTAREG|INTBREG; goto again; case CBRANCH: o = p2->tn.lval; cbranch( p1, -1, o ); p2->in.op = FREE; p->in.op = FREE; return; case QUEST: cbranch( p1, -1, m=getlab() ); p2->in.left->in.rall = p->in.rall; codgen( p2->in.left, INTAREG|INTBREG ); /* force right to compute result into same reg used by left */ p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO; reclaim( p2->in.left, RNULL, 0 ); cbgen( 0, m1 = getlab(), 'I' ); deflab( m ); codgen( p2->in.right, INTAREG|INTBREG ); deflab( m1 ); p->in.op = REG; /* set up node describing result */ p->tn.lval = 0; p->tn.rval = p2->in.right->tn.rval; p->in.type = p2->in.right->in.type; tfree( p2->in.right ); p2->in.op = FREE; goto cleanup; case ANDAND: case OROR: case NOT: /* logical operators */ /* if here, must be a logical operator for 0-1 value */ cbranch( p, -1, m=getlab() ); p->in.op = CCODES; p->bn.label = m; order( p, INTAREG ); goto cleanup; case FLD: /* fields of funny type */ if ( p1->in.op == UNARY MUL ){ offstar( p1->in.left, cookie ); goto again; } case UNARY MINUS: order( p1, INBREG|INAREG ); goto again; case NAME: /* all leaves end up here ... */ if( o == REG ) goto nomat; order( p, INTAREG|INTBREG ); goto again; case INIT: uerror( "illegal initialization" ); return; case UNARY FORTCALL: p->in.right = NIL; case FORTCALL: o = p->in.op = UNARY FORTCALL; if( genfcall( p, cookie ) ) goto nomat; goto cleanup; case UNARY CALL: p->in.right = NIL; case CALL: o = p->in.op = UNARY CALL; if( gencall( p, cookie ) ) goto nomat; goto cleanup; case UNARY STCALL: p->in.right = NIL; case STCALL: o = p->in.op = UNARY STCALL; if( genscall( p, cookie ) ) goto nomat; goto cleanup; /* if arguments are passed in register, care must be taken that reclaim /* not throw away the register which now has the result... */ case UNARY MUL: if( cook == FOREFF ){ /* do nothing */ order( p->in.left, FOREFF ); p->in.op = FREE; return; } offstar( p->in.left, cookie ); goto again; case INCR: /* INCR and DECR */ if( setincr(p, cookie) ) goto again; /* x++ becomes (x += 1) -1; */ if( cook & FOREFF ){ /* result not needed so inc or dec and be done with it */ /* x++ => x += 1 */ p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS; goto again; } p1 = tcopy(p); reclaim( p->in.left, RNULL, 0 ); p->in.left = p1; p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS; p->in.op = (p->in.op==INCR)?MINUS:PLUS; goto again; case STASG: if( setstr( p, cookie ) ) goto again; goto nomat; case ASG PLUS: /* and other assignment ops */ if( setasop(p, cookie) ) goto again; /* there are assumed to be no side effects in LHS */ p2 = tcopy(p); p->in.op = ASSIGN; reclaim( p->in.right, RNULL, 0 ); p->in.right = p2; canon(p); rallo( p, p->in.rall ); # ifndef BUG4 if( odebug ) fwalk( p, eprint, 0 ); # endif order( p2->in.left, INTBREG|INTAREG ); order( p2, INTBREG|INTAREG ); goto again; case ASSIGN: if( setasg( p, cookie ) ) goto again; goto nomat; case BITYPE: if( setbin( p, cookie ) ) goto again; /* try to replace binary ops by =ops */ switch(o){ case PLUS: case MINUS: case MUL: case DIV: case MOD: case AND: case OR: case ER: case LS: case RS: p->in.op = ASG o; goto again; } goto nomat; } cleanup: /* if it is not yet in the right state, put it there */ if( cook & FOREFF ){ reclaim( p, RNULL, 0 ); return; } if( p->in.op==FREE ) return; if( tshape( p, cook ) ) return; if( (m=match(p,cook) ) == MDONE ) return; /* we are in bad shape, try one last chance */ if( lastchance( p, cook ) ) goto again; goto nomat; } int callflag; int fregs; store( p ) register NODE *p; { /* find a subtree of p which should be stored */ register o, ty; o = p->in.op; ty = optype(o); if( ty == LTYPE ) return; switch( o ){ case UNARY CALL: case UNARY FORTCALL: case UNARY STCALL: ++callflag; break; case UNARY MUL: if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL ); break; case CALL: case FORTCALL: case STCALL: store( p->in.left ); stoarg( p->in.right, o ); ++callflag; return; case COMOP: markcall( p->in.right ); if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP ); store( p->in.left ); return; case ANDAND: case OROR: case QUEST: markcall( p->in.right ); if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP ); case CBRANCH: /* to prevent complicated expressions on the LHS from being stored */ case NOT: constore( p->in.left ); return; } if( ty == UTYPE ){ store( p->in.left ); return; } if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o ); if( p->in.su>fregs ){ /* must store */ mkadrs( p ); /* set up stotree and stocook to subtree that must be stored */ } store( p->in.right ); store( p->in.left ); } constore( p ) register NODE *p; { /* store conditional expressions */ /* the point is, avoid storing expressions in conditional conditional context, since the evaluation order is predetermined */ switch( p->in.op ) { case ANDAND: case OROR: case QUEST: markcall( p->in.right ); case NOT: constore( p->in.left ); return; } store( p ); } markcall( p ) register NODE *p; { /* mark off calls below the current node */ again: switch( p->in.op ){ case UNARY CALL: case UNARY STCALL: case UNARY FORTCALL: case CALL: case STCALL: case FORTCALL: ++callflag; return; } switch( optype( p->in.op ) ){ case BITYPE: markcall( p->in.right ); case UTYPE: p = p->in.left; /* eliminate recursion (aren't I clever...) */ goto again; case LTYPE: return; } } stoarg( p, calltype ) register NODE *p; { /* arrange to store the args */ if( p->in.op == CM ){ stoarg( p->in.left, calltype ); p = p->in.right ; } if( calltype == CALL ){ STOARG(p); } else if( calltype == STCALL ){ STOSTARG(p); } else { STOFARG(p); } callflag = 0; store(p); # ifndef NESTCALLS if( callflag ){ /* prevent two calls from being active at once */ SETSTO(p,INTEMP); store(p); /* do again to preserve bottom up nature.... */ } #endif } int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */ cbranch( p, true, false ) NODE *p; { /* evaluate p for truth value, and branch to true or false /* accordingly: label <0 means fall through */ register o, lab, flab, tlab; lab = -1; switch( o=p->in.op ){ case ULE: case ULT: case UGE: case UGT: case EQ: case NE: case LE: case LT: case GE: case GT: if( true < 0 ){ o = p->in.op = negrel[ o-EQ ]; true = false; false = -1; } #ifndef NOOPT if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){ switch( o ){ case UGT: case ULE: o = p->in.op = (o==UGT)?NE:EQ; case EQ: case NE: case LE: case LT: case GE: case GT: if( logop(p->in.left->in.op) ){ /* strange situation: e.g., (a!=0) == 0 */ /* must prevent reference to p->in.left->lable, so get 0/1 */ /* we could optimize, but why bother */ codgen( p->in.left, INAREG|INBREG ); } codgen( p->in.left, FORCC ); cbgen( o, true, 'I' ); break; case UGE: codgen(p->in.left, FORCC); cbgen( 0, true, 'I' ); /* unconditional branch */ break; case ULT: codgen(p->in.left, FORCC); } } else #endif { p->bn.label = true; codgen( p, FORCC ); } if( false>=0 ) cbgen( 0, false, 'I' ); reclaim( p, RNULL, 0 ); return; case ANDAND: lab = false<0 ? getlab() : false ; cbranch( p->in.left, -1, lab ); cbranch( p->in.right, true, false ); if( false < 0 ) deflab( lab ); p->in.op = FREE; return; case OROR: lab = true<0 ? getlab() : true; cbranch( p->in.left, lab, -1 ); cbranch( p->in.right, true, false ); if( true < 0 ) deflab( lab ); p->in.op = FREE; return; case NOT: cbranch( p->in.left, false, true ); p->in.op = FREE; break; case COMOP: codgen( p->in.left, FOREFF ); p->in.op = FREE; cbranch( p->in.right, true, false ); return; case QUEST: flab = false<0 ? getlab() : false; tlab = true<0 ? getlab() : true; cbranch( p->in.left, -1, lab = getlab() ); cbranch( p->in.right->in.left, tlab, flab ); deflab( lab ); cbranch( p->in.right->in.right, true, false ); if( true < 0 ) deflab( tlab); if( false < 0 ) deflab( flab ); p->in.right->in.op = FREE; p->in.op = FREE; return; case ICON: if( p->in.type != FLOAT && p->in.type != DOUBLE ){ if( p->tn.lval || p->in.name[0] ){ /* addresses of C objects are never 0 */ if( true>=0 ) cbgen( 0, true, 'I' ); } else if( false>=0 ) cbgen( 0, false, 'I' ); p->in.op = FREE; return; } /* fall through to default with other strange constants */ default: /* get condition codes */ codgen( p, FORCC ); if( true >= 0 ) cbgen( NE, true, 'I' ); if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' ); reclaim( p, RNULL, 0 ); return; } } rcount(){ /* count recursions */ if( ++nrecur > NRECUR ){ cerror( "expression causes compiler loop: try simplifying" ); } } # ifndef BUG4 eprint( p, down, a, b ) NODE *p; int *a, *b; { *a = *b = down+1; while( down >= 2 ){ printf( "\t" ); down -= 2; } if( down-- ) printf( " " ); printf( "%o) %s", p, opst[p->in.op] ); switch( p->in.op ) { /* special cases */ case REG: printf( " %s", rnames[p->tn.rval] ); break; case ICON: case NAME: case OREG: printf( " " ); adrput( p ); break; case STCALL: case UNARY STCALL: case STARG: case STASG: printf( " size=%d", p->stn.stsize ); printf( " align=%d", p->stn.stalign ); break; } printf( ", " ); tprint( p->in.type ); printf( ", " ); if( p->in.rall == NOPREF ) printf( "NOPREF" ); else { if( p->in.rall & MUSTDO ) printf( "MUSTDO " ); else printf( "PREF " ); printf( "%s", rnames[p->in.rall&~MUSTDO]); } printf( ", SU= %d\n", p->in.su ); } # endif # ifndef NOMAIN NODE * eread(){ /* call eread recursively to get subtrees, if any */ register NODE *p; register i, c; register char *pc; register j; i = rdin( 10 ); p = talloc(); p->in.op = i; i = optype(i); if( i == LTYPE ) p->tn.lval = rdin( 10 ); if( i != BITYPE ) p->tn.rval = rdin( 10 ); p->in.type = rdin(8 ); p->in.rall = NOPREF; /* register allocation information */ if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){ p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR; p->stn.stalign = rdin(10) / SZCHAR; if( getchar() != '\n' ) cerror( "illegal \n" ); } else { /* usual case */ if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type ); /* non usually, but sometimes justified */ #ifndef FLEXNAMES for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){ if( j < NCHNAM ) *pc++ = c; } if( j < NCHNAM ) *pc = '\0'; #else { char buf[BUFSIZ]; for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){ if( j < BUFSIZ ) *pc++ = c; } if( j < BUFSIZ ) *pc = '\0'; p->in.name = tstr(buf); } #endif } /* now, recursively read descendents, if any */ if( i != LTYPE ) p->in.left = eread(); if( i == BITYPE ) p->in.right = eread(); return( p ); } CONSZ rdin( base ){ register sign, c; CONSZ val; sign = 1; val = 0; while( (c=getchar()) > 0 ) { if( c == '-' ){ if( val != 0 ) cerror( "illegal -"); sign = -sign; continue; } if( c == '\t' ) break; if( c>='0' && c<='9' ) { val *= base; if( sign > 0 ) val += c-'0'; else val -= c-'0'; continue; } cerror( "illegal character `%c' on intermediate file", c ); break; } if( c <= 0 ) { cerror( "unexpected EOF"); } return( val ); } # endif #ifndef FIELDOPS /* do this if there is no special hardware support for fields */ ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; { /* look for fields that are not in an lvalue context, and rewrite them... */ register NODE *shp; register s, o, v, ty; *down1 = asgop( p->in.op ); *down2 = 0; if( !down && p->in.op == FLD ){ /* rewrite the node */ if( !rewfld(p) ) return; v = p->tn.rval; s = UPKFSZ(v); o = UPKFOFF(v); /* amount to shift */ fldtyp = o+s <= SZSHORT? SZSHORT: SZLONG; ty = fldtyp==SZSHORT? USHORT: INT; # ifndef RTOLBYTES o = fldtyp - s - o; /* amount to shift */ #endif /* make & mask part */ p->in.left->in.type = ty; p->in.op = AND; p->in.right = talloc(); p->in.right->in.op = ICON; p->in.right->in.rall = NOPREF; p->in.right->in.type = ty; p->in.right->tn.lval = 1; p->in.right->tn.rval = 0; #ifndef FLEXNAMES p->in.right->in.name[0] = '\0'; #else p->in.right->in.name = ""; #endif p->in.right->tn.lval <<= s; p->in.right->tn.lval--; /* now, if a shift is needed, do it */ if( o != 0 ){ shp = talloc(); shp->in.op = RS; shp->in.rall = NOPREF; shp->in.type = ty; shp->in.left = p->in.left; shp->in.right = talloc(); shp->in.right->in.op = ICON; shp->in.right->in.rall = NOPREF; shp->in.right->in.type = ty; shp->in.right->tn.rval = 0; shp->in.right->tn.lval = o; /* amount to shift */ #ifndef FLEXNAMES shp->in.right->in.name[0] = '\0'; #else shp->in.right->in.name = ""; #endif p->in.left = shp; /* whew! */ } } } #endif oreg2( p ) register NODE *p; { /* look for situations where we can turn * into OREG */ NODE *q; register i; register r; register char *cp; register NODE *ql, *qr; CONSZ temp; if( p->in.op == UNARY MUL ){ q = p->in.left; if( q->in.op == REG ){ temp = q->tn.lval; r = q->tn.rval; cp = q->in.name; goto ormake; } if( q->in.op != PLUS && q->in.op != MINUS ) return; ql = q->in.left; qr = q->in.right; #ifdef R2REGS /* look for doubly indexed expressions */ if( q->in.op==PLUS && qr->in.op==REG && ql->in.op==REG && (szty(ql->in.type)==1||szty(qr->in.type)==1) ) { temp = 0; cp = ql->in.name; if( *cp ){ if( *qr->in.name ) return; } else { cp = qr->in.name; } if( szty(qr->in.type)>1) r = R2PACK(qr->tn.rval,ql->tn.rval); else r = R2PACK(ql->tn.rval,qr->tn.rval); goto ormake; } if( (q->in.op==PLUS||q->in.op==MINUS) && qr->in.op==ICON && ql->in.op==PLUS && ql->in.left->in.op==REG && ql->in.right->in.op==REG ){ temp = qr->tn.lval; cp = qr->in.name; if( q->in.op == MINUS ){ if( *cp ) return; temp = -temp; } if( *cp ){ if( *ql->in.name ) return; } else { cp = ql->in.name; } r = R2PACK(ql->in.left->tn.rval,ql->in.right->tn.rval); goto ormake; } #endif R2REGS if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON && ql->in.op==REG && szty(qr->in.type)==1) { temp = qr->tn.lval; if( q->in.op == MINUS ) temp = -temp; r = ql->tn.rval; temp += ql->tn.lval; cp = qr->in.name; if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return; if( !*cp ) cp = ql->in.name; ormake: if( notoff( p->in.type, r, temp, cp ) ) return; p->in.op = OREG; p->tn.rval = r; p->tn.lval = temp; #ifndef FLEXNAMES for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; #else p->in.name = cp; #endif tfree(q); return; } } } canon(p) NODE *p; { /* put p in canonical form */ int oreg2(), sucomp(); #ifndef FIELDOPS int ffld(); fwalk( p, ffld, 0 ); /* look for field operators */ # endif walkf( p, oreg2 ); /* look for and create OREG nodes */ #ifdef MYCANON MYCANON(p); /* your own canonicalization routine(s) */ #endif walkf( p, sucomp ); /* do the Sethi-Ullman computation */ } l *= base; if( sign > 0 ) val += c-'0'; else val -= c-'0'; continue; } cerror( "illegal character `%c' on intermediate file", c ); break; } if( c <= 0 ) { cerror( "unexpected EOF"); } return( val ); } # endif #ifndef FIELDOPS /* do this if there is no special hardware support for fields */ ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; { /* look for fields that are not in an lvalue context, and rewrite them... */ register NODsumacc/cc/ccom/scan.c 444 0 12 51407 3470501553 7730 # include "mfile1" #ifdef BOOTSTRAP #include "/usr/include/ctype.h" #else # include <ctype.h> #endif /* temporarily */ int asm_esc = 0; /* asm escaped used in file */ /* lexical actions */ # define A_ERR 0 /* illegal character */ # define A_LET 1 /* saw a letter */ # define A_DIG 2 /* saw a digit */ # define A_1C 3 /* return a single character */ # define A_STR 4 /* string */ # define A_CC 5 /* character constant */ # define A_BCD 6 /* GCOS BCD constant */ # define A_SL 7 /* saw a / */ # define A_DOT 8 /* saw a . */ # define A_PL 9 /* + */ # define A_MI 10 /* - */ # define A_EQ 11 /* = */ # define A_NOT 12 /* ! */ # define A_LT 13 /* < */ # define A_GT 14 /* > */ # define A_AND 16 /* & */ # define A_OR 17 /* | */ # define A_WS 18 /* whitespace (not \n) */ # define A_NL 19 /* \n */ /* character classes */ # define LEXLET 01 # define LEXDIG 02 # define LEXOCT 04 # define LEXHEX 010 # define LEXWS 020 # define LEXDOT 040 /* reserved word actions */ # define AR_TY 0 /* type word */ # define AR_RW 1 /* simple reserved word */ # define AR_CL 2 /* storage class word */ # define AR_S 3 /* struct */ # define AR_U 4 /* union */ # define AR_E 5 /* enum */ # define AR_A 6 /* asm */ /* text buffer */ #ifndef FLEXNAMES # define LXTSZ 100 #else #define LXTSZ BUFSIZ #endif char yytext[LXTSZ]; char * lxgcp; unsigned caloff(); /* ARGSUSED */ mainp1( argc, argv ) int argc; char *argv[]; { /* control multiple files */ register i; register char *cp; int fdef=0; extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug; extern unsigned int offsz; offsz = caloff(); for( i=1; i<argc; ++i ){ if( *(cp=argv[i]) == '-' && *++cp == 'X' ){ while( *++cp ){ switch( *cp ){ case 'd': ++ddebug; break; case 'i': ++idebug; break; case 'b': ++bdebug; break; case 't': ++tdebug; break; case 'e': ++edebug; break; case 'x': ++xdebug; break; } } } else if( *(argv[i]) != '-' ) switch( fdef++ ) { case 0: case 1: if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) { fprintf(stderr, "ccom:can't open %s\n", argv[i]); exit(1); } break; default: ; } } # ifdef ONEPASS p2init( argc, argv ); # endif for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL; lxinit(); tinit(); mkdope(); lineno = 1; /* dimension table initialization */ dimtab[NULL] = 0; dimtab[CHAR] = SZCHAR; dimtab[INT] = SZINT; dimtab[FLOAT] = SZFLOAT; dimtab[DOUBLE] = SZDOUBLE; dimtab[LONG] = SZLONG; dimtab[SHORT] = SZSHORT; dimtab[UCHAR] = SZCHAR; dimtab[USHORT] = SZSHORT; dimtab[UNSIGNED] = SZINT; dimtab[ULONG] = SZLONG; /* starts past any of the above */ curdim = 16; reached = 1; yyparse(); yyaccpt(); ejobcode( nerrors ? 1 : 0 ); return(nerrors?1:0); } # ifdef ibm # define CSMASK 0377 # define CSSZ 256 # else # define CSMASK 0177 # define CSSZ 128 # endif short lxmask[CSSZ+1]; lxenter( s, m ) register char *s; register short m; { /* enter a mask into lxmask */ register c; while( c= *s++ ) lxmask[c+1] |= m; } # define lxget(c,m) (lxgcp=yytext,lxmore(c,m)) lxmore( c, m ) register c, m; { register char *cp; *(cp = lxgcp) = c; while( c=getchar(), lxmask[c+1]&m ){ if( cp < &yytext[LXTSZ-1] ){ *++cp = c; } } ungetc(c,stdin); *(lxgcp = cp+1) = '\0'; } struct lxdope { short lxch; /* the character */ short lxact; /* the action to be performed */ short lxtok; /* the token number to be returned */ short lxval; /* the value to be returned */ } lxdope[] = { '$', A_ERR, 0, 0, /* illegal characters go here... */ '_', A_LET, 0, 0, /* letters point here */ '0', A_DIG, 0, 0, /* digits point here */ ' ', A_WS, 0, 0, /* whitespace goes here */ '\n', A_NL, 0, 0, '"', A_STR, 0, 0, /* character string */ '\'', A_CC, 0, 0, /* character constant */ '`', A_BCD, 0, 0, /* GCOS BCD constant */ '(', A_1C, LP, 0, ')', A_1C, RP, 0, '{', A_1C, LC, 0, '}', A_1C, RC, 0, '[', A_1C, LB, 0, ']', A_1C, RB, 0, '*', A_1C, MUL, MUL, '?', A_1C, QUEST, 0, ':', A_1C, COLON, 0, '+', A_PL, PLUS, PLUS, '-', A_MI, MINUS, MINUS, '/', A_SL, DIVOP, DIV, '%', A_1C, DIVOP, MOD, '&', A_AND, AND, AND, '|', A_OR, OR, OR, '^', A_1C, ER, ER, '!', A_NOT, UNOP, NOT, '~', A_1C, UNOP, COMPL, ',', A_1C, CM, CM, ';', A_1C, SM, 0, '.', A_DOT, STROP, DOT, '<', A_LT, RELOP, LT, '>', A_GT, RELOP, GT, '=', A_EQ, ASSIGN, ASSIGN, -1, A_1C, 0, 0, }; struct lxdope *lxcp[CSSZ+1]; lxinit(){ register struct lxdope *p; register i; register char *cp; /* set up character classes */ lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET ); lxenter( "0123456789", LEXDIG ); lxenter( "0123456789abcdefABCDEF", LEXHEX ); /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */ lxenter( " \t\r\b\f\013", LEXWS ); lxenter( "01234567", LEXOCT ); lxmask['.'+1] |= LEXDOT; /* make lxcp point to appropriate lxdope entry for each character */ /* initialize error entries */ for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope; /* make unique entries */ for( p=lxdope; ; ++p ) { lxcp[p->lxch+1] = p; if( p->lxch < 0 ) break; } /* handle letters, digits, and whitespace */ /* by convention, first, second, and third places */ cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; while( *cp ) lxcp[*cp++ + 1] = &lxdope[1]; cp = "123456789"; while( *cp ) lxcp[*cp++ + 1] = &lxdope[2]; cp = "\t\b\r\f\013"; while( *cp ) lxcp[*cp++ + 1] = &lxdope[3]; /* first line might have title */ lxtitle(); } int lxmatch; /* character to be matched in char or string constant */ lxstr(ct){ /* match a string or character constant, up to lxmatch */ register c; register val; register i; i=0; while( (c=getchar()) != lxmatch ){ switch( c ) { case EOF: uerror( "unexpected EOF" ); break; case '\n': uerror( "newline in string or char constant" ); ++lineno; break; case '\\': switch( c = getchar() ){ case '\n': ++lineno; continue; default: val = c; goto mkcc; case 'n': val = '\n'; goto mkcc; case 'r': val = '\r'; goto mkcc; case 'b': val = '\b'; goto mkcc; case 't': val = '\t'; goto mkcc; case 'f': val = '\f'; goto mkcc; case 'v': val = '\013'; goto mkcc; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': val = c-'0'; c=getchar(); /* try for 2 */ if( lxmask[c+1] & LEXOCT ){ val = (val<<3) | (c-'0'); c = getchar(); /* try for 3 */ if( lxmask[c+1] & LEXOCT ){ val = (val<<3) | (c-'0'); } else ungetc( c ,stdin); } else ungetc( c ,stdin); goto mkcc1; } default: val =c; mkcc: val = CCTRANS(val); mkcc1: if( lxmatch == '\'' ){ val = CHARCAST(val); /* it is, after all, a "character" constant */ makecc( val, i ); } else { /* stash the byte into the string */ if( strflg ) { if( ct==0 || i<ct ) putbyte( val ); else if( i == ct ) werror( "non-null byte ignored in string initializer" ); } else bycode( val & 0377, i ); } ++i; continue; } break; } /* end of string or char constant */ if( lxmatch == '"' ){ if( strflg ){ /* end the string */ if( ct==0 || i<ct ) putbyte( 0 ); /* the null at the end */ } else { /* the initializer gets a null byte */ bycode( 0, i++ ); bycode( -1, i ); dimtab[curdim] = i; /* in case of later sizeof ... */ } } else { /* end the character constant */ if( i == 0 ) uerror( "empty character constant" ); if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) ) uerror( "too many characters in character constant" ); } } lxcom(){ register c; /* saw a /*: process a comment */ for(;;){ switch( c = getchar() ){ case EOF: uerror( "unexpected EOF" ); return; case '\n': ++lineno; default: continue; case '*': if( (c = getchar()) == '/' ) return; else ungetc( c ,stdin); continue; # ifdef LINT case 'V': lxget( c, LEXLET|LEXDIG ); { extern int vaflag; int i; i = yytext[7]?yytext[7]-'0':0; yytext[7] = '\0'; if( strcmp( yytext, "VARARGS" ) ) continue; vaflag = i; continue; } case 'L': lxget( c, LEXLET ); if( strcmp( yytext, "LINTLIBRARY" ) ) continue; { extern int libflag; libflag = 1; } continue; case 'A': lxget( c, LEXLET ); if( strcmp( yytext, "ARGSUSED" ) ) continue; { extern int argflag, vflag; argflag = 1; vflag = 0; } continue; case 'N': lxget( c, LEXLET ); if( strcmp( yytext, "NOTREACHED" ) ) continue; reached = 0; continue; # endif } } } yylex(){ for(;;){ register lxchar; register struct lxdope *p; register struct symtab *sp; int id; switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){ onechar: ungetc( lxchar ,stdin); case A_1C: /* eat up a single character, and return an opcode */ yylval.intval = p->lxval; return( p->lxtok ); case A_ERR: uerror( "illegal character: %03o (octal)", lxchar ); break; case A_LET: /* collect an identifier, check for reserved word, and return */ lxget( lxchar, LEXLET|LEXDIG ); if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */ if( lxchar== 0 ) continue; #ifdef FLEXNAMES id = lookup( hash(yytext), #else id = lookup( yytext, #endif /* tag name for struct/union/enum */ (stwart&TAGNAME)? STAG: /* member name for struct/union */ (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 ); sp = &stab[id]; if( sp->sclass == TYPEDEF && !stwart ){ stwart = instruct; yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff ); return( TYPE ); } stwart = (stwart&SEENAME) ? instruct : 0; yylval.intval = id; return( NAME ); case A_DIG: /* collect a digit string, then look at last one... */ lastcon = 0; lxget( lxchar, LEXDIG ); switch( lxchar=getchar() ){ case 'x': case 'X': if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" ); lxmore( lxchar, LEXHEX ); /* convert the value */ { register char *cp; for( cp = yytext+2; *cp; ++cp ){ /* this code won't work for all wild character sets, but seems ok for ascii and ebcdic */ lastcon <<= 4; if( isdigit( *cp ) ) lastcon += *cp-'0'; else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10; else lastcon += *cp - 'a'+ 10; } } hexlong: /* criterion for longness for hex and octal constants is that it fit within 0177777 */ if( lastcon & ~0177777L ) yylval.intval = 1; else yylval.intval = 0; goto islong; case '.': lxmore( lxchar, LEXDIG ); getfp: if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */ case 'e': case 'E': if( (lxchar=getchar()) == '+' || lxchar == '-' ){ *lxgcp++ = 'e'; } else { ungetc(lxchar,stdin); lxchar = 'e'; } lxmore( lxchar, LEXDIG ); /* now have the whole thing... */ } else { /* no exponent */ ungetc( lxchar ,stdin); } return( isitfloat( yytext ) ); default: ungetc( lxchar ,stdin); if( yytext[0] == '0' ){ /* convert in octal */ register char *cp; for( cp = yytext+1; *cp; ++cp ){ lastcon <<= 3; lastcon += *cp - '0'; } goto hexlong; } else { /* convert in decimal */ register char *cp; for( cp = yytext; *cp; ++cp ){ lastcon = lastcon * 10 + *cp - '0'; } } /* decide if it is long or not (decimal case) */ /* if it is positive and fits in 15 bits, or negative and and fits in 15 bits plus an extended sign, it is int; otherwise long */ /* if there is an l or L following, all bets are off... */ { CONSZ v; v = lastcon & ~077777L; if( v == 0 || v == ~077777L ) yylval.intval = 0; else yylval.intval = 1; } islong: /* finally, look for trailing L or l */ if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1; else ungetc( lxchar ,stdin); return( ICON ); } case A_DOT: /* look for a dot: if followed by a digit, floating point */ lxchar = getchar(); if( lxmask[lxchar+1] & LEXDIG ){ ungetc(lxchar,stdin); lxget( '.', LEXDIG ); goto getfp; } stwart = FUNNYNAME; goto onechar; case A_STR: /* string constant */ lxmatch = '"'; return( STRING ); case A_CC: /* character constant */ lxmatch = '\''; lastcon = 0; lxstr(0); yylval.intval = 0; return( ICON ); case A_BCD: { register i; int j; for( i=0; i<LXTSZ; ++i ){ if( ( j = getchar() ) == '`' ) break; if( j == '\n' ){ uerror( "newline in BCD constant" ); break; } yytext[i] = j; } yytext[i] = '\0'; if( i>6 ) uerror( "BCD constant exceeds 6 characters" ); # ifdef gcos else strtob( yytext, &lastcon, i ); lastcon >>= 6*(6-i); # else uerror( "gcos BCD constant illegal" ); # endif yylval.intval = 0; /* not long */ return( ICON ); } case A_SL: /* / */ if( (lxchar=getchar()) != '*' ) goto onechar; lxcom(); case A_WS: continue; case A_NL: ++lineno; lxtitle(); continue; case A_NOT: /* ! */ if( (lxchar=getchar()) != '=' ) goto onechar; yylval.intval = NE; return( EQUOP ); case A_MI: /* - */ if( (lxchar=getchar()) == '-' ){ yylval.intval = DECR; return( INCOP ); } if( lxchar != '>' ) goto onechar; stwart = FUNNYNAME; yylval.intval=STREF; return( STROP ); case A_PL: /* + */ if( (lxchar=getchar()) != '+' ) goto onechar; yylval.intval = INCR; return( INCOP ); case A_AND: /* & */ if( (lxchar=getchar()) != '&' ) goto onechar; return( yylval.intval = ANDAND ); case A_OR: /* | */ if( (lxchar=getchar()) != '|' ) goto onechar; return( yylval.intval = OROR ); case A_LT: /* < */ if( (lxchar=getchar()) == '<' ){ yylval.intval = LS; return( SHIFTOP ); } if( lxchar != '=' ) goto onechar; yylval.intval = LE; return( RELOP ); case A_GT: /* > */ if( (lxchar=getchar()) == '>' ){ yylval.intval = RS; return(SHIFTOP ); } if( lxchar != '=' ) goto onechar; yylval.intval = GE; return( RELOP ); case A_EQ: /* = */ switch( lxchar = getchar() ){ case '=': yylval.intval = EQ; return( EQUOP ); case '+': yylval.intval = ASG PLUS; break; case '-': yylval.intval = ASG MINUS; warn: if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){ werror( "ambiguous assignment: assignment op taken" ); } ungetc( lxchar ,stdin); break; case '*': yylval.intval = ASG MUL; goto warn; case '/': yylval.intval = ASG DIV; break; case '%': yylval.intval = ASG MOD; break; case '&': yylval.intval = ASG AND; break; case '|': yylval.intval = ASG OR; break; case '^': yylval.intval = ASG ER; break; case '<': if( (lxchar=getchar()) != '<' ){ uerror( "=<%c illegal", lxchar ); } yylval.intval = ASG LS; break; case '>': if( (lxchar=getchar()) != '>' ){ uerror( "=>%c illegal", lxchar ); } yylval.intval = ASG RS; break; default: goto onechar; } return( ASOP ); default: cerror( "yylex error, character %03o (octal)", lxchar ); } /* ordinarily, repeat here... */ cerror( "out of switch in yylex" ); } } struct lxrdope { /* dope for reserved, in alphabetical order */ char *lxrch; /* name of reserved word */ short lxract; /* reserved word action */ short lxrval; /* value to be returned */ } lxrdope[] = { "asm", AR_A, 0, "auto", AR_CL, AUTO, "break", AR_RW, BREAK, "char", AR_TY, CHAR, "case", AR_RW, CASE, "continue", AR_RW, CONTINUE, "double", AR_TY, DOUBLE, "default", AR_RW, DEFAULT, "do", AR_RW, DO, "extern", AR_CL, EXTERN, "else", AR_RW, ELSE, "enum", AR_E, ENUM, "for", AR_RW, FOR, "float", AR_TY, FLOAT, "fortran", AR_CL, FORTRAN, "goto", AR_RW, GOTO, "if", AR_RW, IF, "int", AR_TY, INT, "long", AR_TY, LONG, "return", AR_RW, RETURN, "register", AR_CL, REGISTER, "switch", AR_RW, SWITCH, "struct", AR_S, 0, "sizeof", AR_RW, SIZEOF, "short", AR_TY, SHORT, "static", AR_CL, STATIC, "typedef", AR_CL, TYPEDEF, "unsigned", AR_TY, UNSIGNED, "union", AR_U, 0, "void", AR_TY, UNDEF, /* tymerge adds FTN */ "while", AR_RW, WHILE, "", 0, 0, /* to stop the search */ }; lxres() { /* check to see of yytext is reserved; if so, /* do the appropriate action and return */ /* otherwise, return -1 */ register c, ch; register struct lxrdope *p; ch = yytext[0]; if( !islower(ch) ) return( -1 ); switch( ch ){ case 'a': c=0; break; case 'b': c=2; break; case 'c': c=3; break; case 'd': c=6; break; case 'e': c=9; break; case 'f': c=12; break; case 'g': c=15; break; case 'i': c=16; break; case 'l': c=18; break; case 'r': c=19; break; case 's': c=21; break; case 't': c=26; break; case 'u': c=27; break; case 'v': c=29; break; case 'w': c=30; break; default: return( -1 ); } for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){ if( !strcmp( yytext, p->lxrch ) ){ /* match */ switch( p->lxract ){ case AR_TY: /* type word */ stwart = instruct; yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval ); return( TYPE ); case AR_RW: /* ordinary reserved word */ return( yylval.intval = p->lxrval ); case AR_CL: /* class word */ yylval.intval = p->lxrval; return( CLASS ); case AR_S: /* struct */ stwart = INSTRUCT|SEENAME|TAGNAME; yylval.intval = INSTRUCT; return( STRUCT ); case AR_U: /* union */ stwart = INUNION|SEENAME|TAGNAME; yylval.intval = INUNION; return( STRUCT ); case AR_E: /* enums */ stwart = SEENAME|TAGNAME; return( yylval.intval = ENUM ); case AR_A: /* asm */ asm_esc = 1; /* warn the world! */ lxget( ' ', LEXWS ); if( getchar() != '(' ) goto badasm; lxget( ' ', LEXWS ); if( getchar() != '"' ) goto badasm; # ifndef ONEPASS # ifndef LINT putchar(')'); # endif # endif while( (c=getchar()) != '"' ){ if( c=='\n' || c==EOF ) goto badasm; # ifndef LINT putchar(c); # endif } lxget( ' ', LEXWS ); if( getchar() != ')' ) goto badasm; # ifndef LINT putchar('\n'); # endif return( 0 ); badasm: uerror( "bad asm construction" ); return( 0 ); default: cerror( "bad AR_?? action" ); } } } return( -1 ); } lxtitle(){ /* called after a newline; set linenumber and file name */ register c, val; register char *cp; for(;;){ /* might be several such lines in a row */ if( (c=getchar()) != '#' ){ if( c != EOF ) ungetc(c,stdin); return; } lxget( ' ', LEXWS ); val = 0; for( c=getchar(); isdigit(c); c=getchar() ){ val = val*10+ c - '0'; } ungetc( c, stdin ); lineno = val; lxget( ' ', LEXWS ); if( (c=getchar()) != '\n' ){ for( cp=ftitle; c!='\n'; c=getchar(),++cp ){ *cp = c; } *cp = '\0'; } } } #ifdef FLEXNAMES #define NSAVETAB 4096 char *savetab; int saveleft; char * savestr(cp) register char *cp; { register int len; len = strlen(cp) + 1; if (len > saveleft) { saveleft = NSAVETAB; if (len > saveleft) saveleft = len; savetab = (char *)malloc(saveleft); if (savetab == 0) cerror("Ran out of memory (savestr)"); } strncpy(savetab, cp, len); cp = savetab; savetab += len; saveleft -= len; return (cp); } /* * The definition for the segmented hash tables. */ #define MAXHASH 20 #define HASHINC 1013 struct ht { char **ht_low; char **ht_high; int ht_used; } htab[MAXHASH]; char * hash(s) char *s; { register char **h; register i; register char *cp; struct ht *htp; int sh; /* * The hash function is a modular hash of * the sum of the characters with the sum * doubled before each successive character * is added. */ cp = s; i = 0; while (*cp) i = i*2 + *cp++; sh = (i&077777) % HASHINC; cp = s; /* * There are as many as MAXHASH active * hash tables at any given point in time. * The search starts with the first table * and continues through the active tables * as necessary. */ for (htp = htab; htp < &htab[MAXHASH]; htp++) { if (htp->ht_low == 0) { register char **hp = (char **) calloc(sizeof (char **), HASHINC); if (hp == 0) cerror("ran out of memory (hash)"); htp->ht_low = hp; htp->ht_high = htp->ht_low + HASHINC; } h = htp->ht_low + sh; /* * quadratic rehash increment * starts at 1 and incremented * by two each rehash. */ i = 1; do { if (*h == 0) { if (htp->ht_used > (HASHINC * 3)/4) break; htp->ht_used++; *h = savestr(cp); return (*h); } if (**h == *cp && strcmp(*h, cp) == 0) return (*h); h += i; i += 2; if (h >= htp->ht_high) h -= HASHINC; } while (i < HASHINC); } cerror("ran out of hash tables"); } #endif k; case 'l': c=18; break; case 'r': c=19; break; case 's': c=21; break; case 't': c=26; break; case 'u': c=27; break; case 'v': c=29; break; case 'w': c=30; break; default: return( -1 ); } for( p= lxrdope+c; p->lxrch[0] sumacc/cc/ccom/table.c 444 0 12 31406 3470501553 10070 /* * missing \n fixed by Bill Nowicki December 1981 * * Merged Stanford and LFL versions July 1982 */ # include "mfile2" # define TSCALAR TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT # define EA SNAME|SOREG|SCON|STARREG|SAREG|SBREG # define EAA SNAME|SOREG|SCON|STARREG|SAREG # define EB SBREG struct optab table[] = { ASSIGN, INAREG|FOREFF|FORCC, EAA, TSCALAR|TFLOAT, SZERO, TANY, 0, RLEFT|RRIGHT|RESCC, " clrZB AL\n", ASSIGN, INAREG|FOREFF|FORCC, EAA, TDOUBLE, SZERO, TANY, 0, RLEFT|RRIGHT|RESCC, " clrl AL\n clrl UL\n", ASSIGN, INAREG|FOREFF|FORCC, SAREG|STAREG, TSCALAR, SCCON, TSCALAR, 0, RLEFT|RRIGHT|RESCC, " moveq AR,AL\n", ASSIGN, INAREG|FOREFF|FORCC, EAA, TSCALAR|TFLOAT, EA, TSCALAR|TFLOAT, 0, RLEFT|RRIGHT|RESCC, " movZB AR,AL\n", ASSIGN, INAREG|FOREFF, EAA, TDOUBLE, EA, TDOUBLE, 0, RLEFT|RRIGHT, " movl AR,AL\n movl UR,UL\n", ASSIGN, INAREG|FOREFF, EAA, TFLOAT, EA, TDOUBLE, 0, RLEFT|RRIGHT, " movl AR,AL\n", ASSIGN, INBREG|FOREFF, EB, TSCALAR, EA, TSCALAR, 0, RLEFT|RRIGHT|RESCC, " movZB AR,AL\n", ASSIGN, INAREG|FOREFF, SFLD, TANY, SZERO, TANY, 0, RRIGHT, " andY #N,AL\n", ASSIGN, INTAREG|INAREG|FOREFF, SFLD, TANY, STAREG, TANY, NAREG, RRIGHT, "F\tmovl\tAR,sp@-\n\tmovl\t#H,A1\n\tlslY\tA1,AR\n\tandY\t#M,AR\n\tandY\t#N,AL\n\torY\tAR,AL\nF\tmovl\tsp@+,AR\n", ASSIGN, INAREG|FOREFF, SFLD, TANY, EA, TANY, 2*NAREG, RRIGHT, "\tmovZB\tAR,A1\n\tmovl\t#H,A2\n\tlslY\tA2,A1\n\tandY\t#M,A1\n\tandY\t#N,AL\n\torY\tA1,AL\n", /* put this here so UNARY MUL nodes match OPLTYPE when appropriate */ UNARY MUL, INTAREG|INAREG|FORCC, SBREG, TSCALAR, SANY, TANY, NAREG|NASR, RESC1|RESCC, " movZB AL@,A1\n", OPLTYPE, FOREFF, SANY, TANY, EA, TANY, 0, RRIGHT, "", /* this entry throws away computations which don't do anything */ OPLTYPE, FORCC, SANY, TANY, #ifndef Stanford EAA, TSCALAR|TFLOAT|TDOUBLE, #else Stanford /* * You really need to compare all 64 bits for doubles. * But if you don't have this, the code in local2.c does not * work. */ EAA, TSCALAR|TFLOAT, #endif Stanford 0, RESCC, " tstZB AR\n", OPLTYPE, FORCC, SANY, TANY, EB, TSCALAR, 0, RESCC, " cmpZB #0,AR\n", OPLTYPE, INTAREG|INAREG|FORCC, SANY, TANY, SZERO, TSCALAR, NAREG|NASR, RESC1|RESCC, " clrZB A1\n", OPLTYPE, INTAREG|INAREG|FORCC, SANY, TANY, SCCON, TSCALAR, NAREG|NASR, RESC1|RESCC, " moveq AR,A1\n", OPLTYPE, INTAREG|INAREG|FORCC, SANY, TANY, EA, TSCALAR, NAREG|NASR, RESC1|RESCC, " movZB AR,A1\n", OPLTYPE, INTAREG|INAREG, SANY, TANY, EA, TDOUBLE, NAREG|NASR, RESC1, " movl AR,A1\n movl UR,U1\n", OPLTYPE, INTAREG|INAREG, SANY, TANY, EA, TFLOAT, NAREG|NASR, RESC1, " movl AR,A1\n", OPLTYPE, INTBREG|INBREG|FORCC, SANY, TANY, EA, TSCALAR, NBREG|NBSR, RESC1|RESCC, " movZB AR,A1\n", /* Old template */ /* * LFL commented this out, but then it seems to create a bug in which * a movl is used instead of a movw. * If you comment it out, the cmpZL's must be changed to cmpZB's */ OPLTYPE, INTEMP|FORCC, SANY, TANY, EA, TSCALAR, NTEMP, RESC1|RESCC, " movZB AR,A1\n", # ifndef Stanford /* New templates */ OPLTYPE, INTEMP|FORCC, SANY, TANY, EA, TINT|TUNSIGNED|TPOINT, NTEMP, RESC1|RESCC, " movl AR,A1\n", # endif Stanford /* * Bill Nowicki August 1982 * This has to make sure AR is a d register! */ OPLTYPE, INTEMP|FORCC, SANY, TANY, SCON|STARREG|SAREG|SBREG, TSHORT, NTEMP, RESC1|RESCC, " extl AR\n movl AR,A1\n", OPLTYPE, INTEMP, SANY, TANY, EA, TFLOAT, NTEMP, RESC1, " movl AR,A1\n", OPLTYPE, INTEMP, SANY, TANY, EA, TDOUBLE, NTEMP, RESC1, " movl AR,A1\n movl UR,U1\n", OPLTYPE, FORARG, SANY, TANY, SBREG, TINT|TUNSIGNED|TPOINT, 0, RNULL, " pea AR@\nZP", OPLTYPE, FORARG, SANY, TANY, EA, TINT|TUNSIGNED|TPOINT, 0, RNULL, " movl AR,Z-\n", OPLTYPE, FORARG, SANY, TANY, EA, TSHORT, NBREG|NBSR, RNULL, " movw AR,A1\n movl A1,Z-\n", OPLTYPE, FORARG, SANY, TANY, EA, TUSHORT, NAREG|NASR, RNULL, " clrl A1\n movw AR,A1\n movl A1,Z-\n", OPLTYPE, FORARG, SANY, TANY, EA, TCHAR, NAREG|NASR, RNULL, " movb AR,A1\n extw A1\n extl A1\n movl A1,Z-\n", OPLTYPE, FORARG, SANY, TANY, EA, TUCHAR, NAREG|NASR, RNULL, " clrl A1\n movb AR,A1\n movl A1,Z-\n", OPLTYPE, FORARG, SANY, TANY, EA, TFLOAT, 0, RNULL, " clrl Z-\n movl AR,Z-\n", OPLTYPE, FORARG, SANY, TANY, EA, TDOUBLE, 0, RNULL, " movl UR,Z-\n movl AR,Z-\n", OPLOG, FORCC, SAREG|STAREG|SBREG|STBREG, TSCALAR, EA, TSCALAR, 0, RESCC, " cmpZL AR,AL\nZI", /* * Added by Bill Nowicki August 1982 * and next template also fixed to not compare two constants. */ OPLOG, FORCC, SAREG|STAREG|SBREG|STBREG, TFLOAT, EA, TFLOAT, 0, RESCC, " cmpZL AR,AL\nZI", OPLOG, FORCC, SNAME|SOREG|STARREG|SAREG, TSCALAR, SCON, TSCALAR, 0, RESCC, " cmpZL AR,AL\nZI", #ifdef Stanford OPLOG, FORCC, EA, TDOUBLE, EA, TDOUBLE, 0, RESCC, "\tmovl\tUR,Z-\n\tmovl\tAR,Z-\n\tmovl\tUL,Z-\n\tmovl\tAL,Z-\n\tjbsr\tfcmp\n\taddl\t#16,sp\n\ttstl\td0\nZ0ZI", #endif Stanford CCODES, INTAREG|INAREG, SANY, TANY, SANY, TANY, NAREG, RESC1, " moveq #1,A1\nZN", UNARY MINUS, INTAREG|INAREG, STAREG, TSCALAR, SANY, TANY, 0, RLEFT, " negZB AL\n", COMPL, INTAREG|INAREG, STAREG, TSCALAR, SANY, TANY, 0, RLEFT, " notZB AL\n", INCR, INTAREG|INAREG|FOREFF, EAA, TSCALAR, S8CON, TSCALAR, NAREG, RESC1, "F movZB AL,A1\n addqZB AR,AL\n", DECR, INTAREG|INAREG|FOREFF, EAA, TSCALAR, S8CON, TSCALAR, NAREG, RESC1, "F movZB AL,A1\n subqZB AR,AL\n", INCR, INTAREG|INAREG|FOREFF, EAA, TSCALAR, SCON, TSCALAR, NAREG, RESC1, "F movZB AL,A1\n addZB AR,AL\n", DECR, INTAREG|INAREG|FOREFF, EAA, TSCALAR, SCON, TSCALAR, NAREG, RESC1, "F movZB AL,A1\n subZB AR,AL\n", INCR, INTBREG|INBREG|FOREFF, EB, TSCALAR, S8CON, TSCALAR, NBREG, RESC1, "F movZB AL,A1\n addqZB AR,AL\n", DECR, INTBREG|INBREG|FOREFF, EB, TSCALAR, S8CON, TSCALAR, NBREG, RESC1, "F movZB AL,A1\n subqZB AR,AL\n", INCR, INTBREG|INBREG|FOREFF, EB, TSCALAR, SCON, TSCALAR, NBREG, RESC1, "F movZB AL,A1\n addZB AR,AL\n", DECR, INTBREG|INBREG|FOREFF, EB, TSCALAR, SCON, TSCALAR, NBREG, RESC1, "F movZB AL,A1\n subZB AR,AL\n", PLUS, INBREG|INTBREG, SBREG, TPOINT, SICON, TANY, NBREG|NBSL, RESC1, " lea AL@(ZO),A1\n", PLUS, FORARG, SBREG, TPOINT, SICON, TANY, 0, RNULL, " pea AL@(ZO)\nZP", MINUS, INBREG|INTBREG, SBREG, TPOINT, SICON, TANY, NBREG|NBSL, RESC1, " lea AL@(ZM),A1\n", MINUS, FORARG, SBREG, TPOINT, SICON, TANY, 0, RNULL, " pea AL@(ZM)\nZP", ASG PLUS, INAREG|FORCC, EAA, TSCALAR, S8CON, TSCALAR, 0, RLEFT|RESCC, " addqZB AR,AL\n", ASG PLUS, INBREG|FORCC, EB, TSCALAR, S8CON, TSCALAR, 0, RLEFT|RESCC, " addqZB AR,AL\n", ASG PLUS, INAREG|FORCC, SAREG|STAREG, TSCALAR, EA, TSCALAR, 0, RLEFT|RESCC, " addZB AR,AL\n", ASG PLUS, INBREG, SBREG|STBREG, TSCALAR, EA, TSCALAR, 0, RLEFT, " addZB AR,AL\n", ASG PLUS, INAREG|FORCC, EAA, TSCALAR, SAREG|STAREG, TSCALAR, 0, RLEFT|RESCC, " addZB AR,AL\n", ASG MINUS, INAREG|FORCC, EAA, TSCALAR, S8CON, TSCALAR, 0, RLEFT|RESCC, " subqZB AR,AL\n", ASG MINUS, INBREG|FORCC, EB, TSCALAR, S8CON, TSCALAR, 0, RLEFT|RESCC, " subqZB AR,AL\n", ASG MINUS, INAREG|FORCC, SAREG|STAREG, TSCALAR, EA, TSCALAR, 0, RLEFT|RESCC, " subZB AR,AL\n", ASG MINUS, INBREG, SBREG|STBREG, TSCALAR, EA, TSCALAR, 0, RLEFT, " subZB AR,AL\n", ASG MINUS, INAREG|FORCC, EAA, TSCALAR, SAREG|STAREG, TSCALAR, 0, RLEFT|RESCC, " subZB AR,AL\n", ASG ER, INAREG|FORCC, EAA, TSCALAR, SCON, TSCALAR, 0, RLEFT|RESCC, " eorZB AR,AL\n", ASG ER, INAREG|FORCC, EAA, TSCALAR, SAREG|STAREG, TSCALAR, 0, RLEFT|RESCC, " eorZB AR,AL\n", ASG OPSIMP, INAREG|FORCC, SAREG|STAREG, TSCALAR, EAA, TSCALAR, 0, RLEFT|RESCC, " OIZB AR,AL\n", ASG OPSIMP, INAREG|FORCC, EAA, TSCALAR, SCON, TSCALAR, 0, RLEFT|RESCC, " OIZB AR,AL\n", ASG OPSIMP, INAREG|FORCC, EAA, TSCALAR, SAREG|STAREG, TSCALAR, 0, RLEFT|RESCC, " OIZB AR,AL\n", ASG MUL, INAREG|FORCC, SAREG|STAREG, TSHORT, EAA, TSHORT, 0, RLEFT|RESCC, " muls AR,AL\n", ASG MUL, INAREG|FORCC, SAREG|STAREG, TUSHORT, EAA, TUSHORT|TSHORT, 0, RLEFT|RESCC, " mulu AR,AL\n", ASG MUL, INAREG|FORCC, SAREG|STAREG, TSHORT, EAA, TUSHORT, 0, RLEFT|RESCC, " mulu AR,AL\n", ASG MUL, INAREG, SAREG|STAREG, TCHAR, EAA, TCHAR, NAREG, RLEFT, "\textw AL\n\tmovb AR,A1\n\textw A1\n\tmuls A1,AL\n", ASG MUL, INAREG, SAREG|STAREG, TUCHAR, EAA, TUCHAR|TCHAR, NAREG, RLEFT, "\tandw #255,AL\n\tclrw A1\n\tmovb AR,A1\n\tmuls A1,AL\n", ASG DIV, INAREG|FORCC, SAREG|STAREG, TSHORT, EAA, TSHORT, 0, RLEFT|RESCC, " extl AL\n divs AR,AL\n", ASG DIV, INAREG|FORCC, SAREG|STAREG, TUSHORT, EAA, TUSHORT|TSHORT, 0, RLEFT|RESCC, " andl #65535,AL\n divu AR,AL\n", ASG DIV, INAREG|FORCC, SAREG|STAREG, TSHORT, EAA, TUSHORT, 0, RLEFT|RESCC, " andl #65535,AL\n divu AR,AL\n", ASG DIV, INAREG, SAREG|STAREG, TCHAR, EAA, TCHAR, NAREG, RLEFT, "\textw AL\n\tmovb AR,A1\n\textw A1\n\tdivs A1,AL\n", ASG DIV, INAREG, SAREG|STAREG, TUCHAR, EAA, TUCHAR|TCHAR, NAREG, RLEFT, "\tandw #255,AL\n\tclrw A1\n\tmovb AR,A1\n\tdivs A1,AL\n", ASG MOD, INAREG, SAREG|STAREG, TSHORT, EAA, TSHORT, 0, RLEFT, " extl AL\n divs AR,AL\n swap AL\n", ASG MOD, INAREG, SAREG|STAREG, TUSHORT, EAA, TUSHORT|TSHORT, 0, RLEFT, " andl #65535,AL\n divu AR,AL\n swap AL\n", ASG MOD, INAREG, SAREG|STAREG, TSHORT, EAA, TUSHORT, 0, RLEFT, " andl #65535,AL\n divu AR,AL\n swap AL\n", ASG MOD, INAREG, SAREG|STAREG, TCHAR, EAA, TCHAR, NAREG, RLEFT, "\textw AL\n\tmovb AR,A1\n\textw A1\n\tdivs A1,AL\n swap AL\n", ASG MOD, INAREG, SAREG|STAREG, TUCHAR, EAA, TUCHAR|TCHAR, NAREG, RLEFT, "\tandw #255,AL\n\tclrw A1\n\tmovb AR,A1\n\tdivs A1,AL\n swap AL\n", ASG OPSHFT, INAREG|FORCC, SAREG, TINT|TSHORT|TCHAR, S8CON, TSCALAR, 0, RLEFT|RESCC, " aOIZB AR,AL\n", ASG OPSHFT, INAREG|FORCC, SNAME|SOREG, TSHORT, SONE, TSCALAR, 0, RLEFT|RESCC, " aOIw AL\n", ASG OPSHFT, INAREG|FORCC, SAREG, TINT|TSHORT|TCHAR, SAREG, TSCALAR, 0, RLEFT|RESCC, " aOIZB AR,AL\n", ASG OPSHFT, INAREG|FORCC, SAREG, TUNSIGNED|TUSHORT|TUCHAR, S8CON, TSCALAR, 0, RLEFT|RESCC, " lOIZB AR,AL\n", ASG OPSHFT, INAREG|FORCC|RESCC, EA, TUSHORT, SONE, TSCALAR, 0, RLEFT, " lOIw AL\n", ASG OPSHFT, INAREG|FORCC, SAREG, TUNSIGNED|TUSHORT|TUCHAR, SAREG, TSCALAR, 0, RLEFT|RESCC, " lOIZB AR,AL\n", UNARY CALL, INTAREG, SBREG|SNAME|SOREG|SCON, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be register 0 */ "ZC\n", SCONV, INTAREG, STAREG, TINT|TUNSIGNED|TPOINT, SANY, TINT|TUNSIGNED|TPOINT, 0, RLEFT, "", SCONV, INTAREG, STAREG, TSCALAR, SANY, TUCHAR, 0, RLEFT, " andl #255,AL\n", SCONV, INTAREG, STAREG, TINT|TUNSIGNED|TPOINT, SANY, TUSHORT, 0, RLEFT, " andl #65535,AL\n", SCONV, INTAREG, STAREG, TINT|TUNSIGNED|TPOINT, SANY, TSHORT|TCHAR, 0, RLEFT, "", SCONV, INTAREG, STAREG, TCHAR, SANY, TSHORT|TUSHORT, 0, RLEFT, " extw AL\n", SCONV, INTAREG, STAREG, TCHAR, SANY, TINT|TUNSIGNED|TPOINT, 0, RLEFT, " extw AL\n extl AL\n", SCONV, INTAREG, STAREG, TSHORT, SANY, TINT|TUNSIGNED|TPOINT, 0, RLEFT, " extl AL\n", SCONV, INTAREG, STAREG, TUCHAR, SANY, TSCALAR, 0, RLEFT, " andl #255,AL\n", SCONV, INTAREG, STAREG, TUSHORT, SANY, TINT|TUNSIGNED|TPOINT, 0, RLEFT, " andl #65535,AL\n", SCONV, INAREG|INTAREG, #ifndef Stanford /* * SU adds in STAREG and SBREG; which is correct??? */ SNAME|SOREG|SCON|SAREG, TINT|TUNSIGNED|TPOINT|TSHORT|TUSHORT, #else Stanford EA, TINT|TUNSIGNED|TPOINT|TSHORT|TUSHORT, #endif Stanford SANY, TSHORT|TUSHORT|TCHAR|TUCHAR, 0, RLEFT, "ZT", SCONV, INAREG|INTAREG, EA, TDOUBLE, SANY, TFLOAT, 0, RLEFT, "", SCONV, INAREG|INTAREG, EA, TFLOAT, SANY, TDOUBLE, NAREG|NASR, RESC1, " movl AL,A1\n clrl U1\n", SCONV, FORARG, EA, TFLOAT, SANY, TDOUBLE, 0, RNULL, " clrl Z-\n movl AL,Z-\n", STASG, FOREFF, SNAME|SOREG, TANY, #ifndef Stanford SCON|SBREG, TANY, #else Stanford SCON|SOREG|SBREG, TANY, #endif Stanford 0, RNOP, "ZS", STASG, INTBREG|INBREG, SNAME|SOREG, TANY, STBREG, TANY, 0, RRIGHT, "ZS", STASG, INBREG|INTBREG, SNAME|SOREG, TANY, SCON|SBREG, TANY, NBREG, RESC1, "ZS movl AR,A1\n", INIT, FOREFF, SCON, TANY, SANY, TINT|TUNSIGNED|TPOINT, 0, RNOP, " .long CL\n", INIT, FOREFF, SCON, TANY, SANY, TSHORT|TUSHORT, 0, RNOP, " .word CL\n", INIT, FOREFF, SCON, TANY, SANY, TCHAR|TUCHAR, 0, RNOP, " .byte CL\n", /* Default actions for hard trees ... */ # define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" UNARY MUL, DF( UNARY MUL ), INCR, DF(INCR), DECR, DF(INCR), ASSIGN, DF(ASSIGN), STASG, DF(STASG), OPLEAF, DF(NAME), OPLOG, FORCC, SANY, TANY, SANY, TANY, REWRITE, BITYPE, "", OPLOG, DF(NOT), COMOP, DF(COMOP), INIT, DF(INIT), OPUNARY, DF(UNARY MINUS), ASG OPANY, DF(ASG PLUS), OPANY, DF(BITYPE), FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }; REG, SAREG|STAREG, TCHAR, EAA, TCHAR, NAREG, RLEFT, "\textw AL\n\tmovb AR,A1\n\textw A1\n\tdivs A1,AL\n", ASG DIV, INAREG, SAREG|STAREG, TUCHAR, EAA, TUCHAR|TCHAR, NAREG, RLEFT, "\tandw #255,AL\n\tclrw A1\n\tmovb AR,A1\n\tdivs A1,AL\n", sumacc/cc/ccom/test.c 444 0 12 273 3470501553 7716 test() { short test2(); return( test2(1) >= test2(2) ); } struct s { short a, b; } *p; short test2(a, b, c) short a,b,c; { if ( p->b == b) return( a*b + a*c ); } 0, RNULL, " clrl Z-\n movl AL,Z-\n", STASG, FOREFF, SNAME|SOREG, TANY, #ifndef Stanford SCON|SBREG, TANY, #else Stanford SCON|SOREG|SBREG, TANY, #endif Stanford 0, RNOP, "ZS", STASG, INTBREG|INBREG, SNAME|SOREG, TANY, STBREG, TANY, 0, RRIGHT, "ZS", STASG, INBREG|INTBREG, SNAME|SOREG, TANY, SCON|SBREG, TAsumacc/cc/ccom/trees.c 444 0 12 100002 3470501553 10130 # include "mfile1" /* corrections when in violation of lint */ /* some special actions, used in finding the type of nodes */ # define NCVT 01 # define PUN 02 # define TYPL 04 # define TYPR 010 # define TYMATCH 040 # define LVAL 0100 # define CVTO 0200 # define CVTL 0400 # define CVTR 01000 # define PTMATCH 02000 # define OTHER 04000 # define NCVTR 010000 # define RINT 020000 # define LINT 040000 /* node conventions: NAME: rval>0 is stab index for external rval<0 is -inlabel number lval is offset in bits ICON: lval has the value rval has the STAB index, or - label number, if a name whose address is in the constant rval = NONAME means no name REG: rval is reg. identification cookie */ int bdebug = 0; extern ddebug; NODE * buildtree( o, l, r ) register NODE *l, *r; { register NODE *p, *q; register actions; register opty; register struct symtab *sp; register NODE *lr, *ll; int i; extern int eprint(); # ifndef BUG1 if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); # endif opty = optype(o); /* check for constants */ if( opty == UTYPE && l->in.op == ICON ){ switch( o ){ case NOT: if( hflag ) werror( "constant argument to NOT" ); case UNARY MINUS: case COMPL: if( conval( l, o, l ) ) return(l); break; } } else if( o==UNARY MINUS && l->in.op==FCON ){ l->fpn.dval = -l->fpn.dval; return(l); } else if( o==QUEST && l->in.op==ICON ) { l->in.op = FREE; r->in.op = FREE; if( l->tn.lval ){ tfree( r->in.right ); return( r->in.left ); } else { tfree( r->in.left ); return( r->in.right ); } } else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ switch( o ){ case ULT: case UGT: case ULE: case UGE: case LT: case GT: case LE: case GE: case EQ: case NE: case ANDAND: case OROR: case CBRANCH: ccwarn: if( hflag ) werror( "constant in conditional context" ); case PLUS: case MINUS: case MUL: case DIV: case MOD: case AND: case OR: case ER: case LS: case RS: if( conval( l, o, r ) ) { r->in.op = FREE; return(l); } break; } } else if( opty == BITYPE && (l->in.op==FCON||l->in.op==ICON) && (r->in.op==FCON||r->in.op==ICON) ){ switch(o){ case PLUS: case MINUS: case MUL: case DIV: if( l->in.op == ICON ){ l->fpn.dval = l->tn.lval; } if( r->in.op == ICON ){ r->fpn.dval = r->tn.lval; } l->in.op = FCON; l->in.type = l->fn.csiz = DOUBLE; r->in.op = FREE; switch(o){ case PLUS: l->fpn.dval += r->fpn.dval; return(l); case MINUS: l->fpn.dval -= r->fpn.dval; return(l); case MUL: l->fpn.dval *= r->fpn.dval; return(l); case DIV: if( r->fpn.dval == 0 ) uerror( "division by 0." ); else l->fpn.dval /= r->fpn.dval; return(l); } } } /* its real; we must make a new node */ p = block( o, l, r, INT, 0, INT ); actions = opact(p); if( actions&LVAL ){ /* check left descendent */ if( notlval(p->in.left) ) { uerror( "illegal lhs of assignment operator" ); } } if( actions & NCVTR ){ p->in.left = pconvert( p->in.left ); } else if( !(actions & NCVT ) ){ switch( opty ){ case BITYPE: p->in.right = pconvert( p->in.right ); case UTYPE: p->in.left = pconvert( p->in.left ); } } if( (actions&PUN) && (o!=CAST||cflag) ){ chkpun(p); } if (actions & RINT) p->in.right = makety( p->in.right, INT, 0, INT ); if (actions & LINT) p->in.left = makety( p->in.left, INT, 0, INT ); if( actions & (TYPL|TYPR) ){ q = (actions&TYPL) ? p->in.left : p->in.right; p->in.type = q->in.type; p->fn.cdim = q->fn.cdim; p->fn.csiz = q->fn.csiz; } if( actions & CVTL ) p = convert( p, CVTL ); if( actions & CVTR ) p = convert( p, CVTR ); if( actions & TYMATCH ) p = tymatch(p); if( actions & PTMATCH ) p = ptmatch(p); if( actions & OTHER ){ l = p->in.left; r = p->in.right; switch(o){ case NAME: sp = &stab[idname]; if( sp->stype == UNDEF ){ #ifndef FLEXNAMES uerror( "%.8s undefined", sp->sname ); #else uerror( "%s undefined", sp->sname ); #endif /* make p look reasonable */ p->in.type = p->fn.cdim = p->fn.csiz = INT; p->tn.rval = idname; p->tn.lval = 0; defid( p, SNULL ); break; } p->in.type = sp->stype; p->fn.cdim = sp->dimoff; p->fn.csiz = sp->sizoff; p->tn.lval = 0; p->tn.rval = idname; /* special case: MOETY is really an ICON... */ if( p->in.type == MOETY ){ p->tn.rval = NONAME; p->tn.lval = sp->offset; p->fn.cdim = 0; p->in.type = ENUMTY; p->in.op = ICON; } break; case ICON: p->fn.cdim = 0; p->fn.csiz = INT; break; case STRING: p->in.op = NAME; p->in.type = CHAR+ARY; p->tn.lval = 0; p->tn.rval = NOLAB; p->fn.cdim = curdim; p->fn.csiz = CHAR; break; case FCON: p->tn.lval = 0; p->tn.rval = 0; p->in.type = DOUBLE; p->fn.cdim = 0; p->fn.csiz = DOUBLE; break; case STREF: /* p->x turned into *(p+offset) */ /* rhs must be a name; check correctness */ i = r->tn.rval; if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ uerror( "member of structure or union required" ); }else /* if this name is non-unique, find right one */ if( stab[i].sflags & SNONUNIQ && (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && (l->fn.csiz +1) >= 0 ){ /* nonunique name && structure defined */ char * memnam, * tabnam; register k; int j; int memi; j=dimtab[l->fn.csiz+1]; for( ; (memi=dimtab[j]) >= 0; ++j ){ tabnam = stab[memi].sname; memnam = stab[i].sname; # ifndef BUG1 if( ddebug>1 ){ #ifndef FLEXNAMES printf("member %.8s==%.8s?\n", #else printf("member %s==%s?\n", #endif memnam, tabnam); } # endif if( stab[memi].sflags & SNONUNIQ ){ #ifndef FLEXNAMES for( k=0; k<NCHNAM; ++k ){ if(*memnam++!=*tabnam) goto next; if(!*tabnam++) break; } #else if (memnam != tabnam) goto next; #endif r->tn.rval = i = memi; break; } next: continue; } if( memi < 0 ) #ifndef FLEXNAMES uerror("illegal member use: %.8s", #else uerror("illegal member use: %s", #endif stab[i].sname); } else { register j; if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ if( stab[i].sflags & SNONUNIQ ){ uerror( "nonunique name demands struct/union or struct/union pointer" ); } else werror( "struct/union or struct/union pointer required" ); } else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ #ifndef FLEXNAMES werror( "illegal member use: %.8s", stab[i].sname ); #else werror( "illegal member use: %s", stab[i].sname ); #endif } } p = stref( p ); break; case UNARY MUL: if( l->in.op == UNARY AND ){ p->in.op = l->in.op = FREE; p = l->in.left; } if( !ISPTR(l->in.type))uerror("illegal indirection"); p->in.type = DECREF(l->in.type); p->fn.cdim = l->fn.cdim; p->fn.csiz = l->fn.csiz; break; case UNARY AND: switch( l->in.op ){ case UNARY MUL: p->in.op = l->in.op = FREE; p = l->in.left; case NAME: p->in.type = INCREF( l->in.type ); p->fn.cdim = l->fn.cdim; p->fn.csiz = l->fn.csiz; break; case COMOP: lr = buildtree( UNARY AND, l->in.right, NIL ); p->in.op = l->in.op = FREE; p = buildtree( COMOP, l->in.left, lr ); break; case QUEST: lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); p->in.op = l->in.op = l->in.right->in.op = FREE; p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); break; # ifdef ADDROREG case OREG: /* OREG was built in clocal() * for an auto or formal parameter * now its address is being taken * local code must unwind it * back to PLUS/MINUS REG ICON * according to local conventions */ { extern NODE * addroreg(); p->in.op = FREE; p = addroreg( l ); } break; # endif default: uerror( "unacceptable operand of &" ); break; } break; case LS: case RS: case ASG LS: case ASG RS: if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) p->in.right = makety(p->in.right, INT, 0, INT ); break; case RETURN: case ASSIGN: case CAST: /* structure assignment */ /* take the addresses of the two sides; then make an /* operator using STASG and /* the addresses of left and right */ { register TWORD t; register d, s; if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); r = buildtree( UNARY AND, r, NIL ); t = r->in.type; d = r->fn.cdim; s = r->fn.csiz; l = block( STASG, l, r, t, d, s ); if( o == RETURN ){ p->in.op = FREE; p = l; break; } p->in.op = UNARY MUL; p->in.left = l; p->in.right = NIL; break; } case COLON: /* structure colon */ if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); break; case CALL: p->in.right = r = strargs( p->in.right ); case UNARY CALL: if( !ISPTR(l->in.type)) uerror("illegal function"); p->in.type = DECREF(l->in.type); if( !ISFTN(p->in.type)) uerror("illegal function"); p->in.type = DECREF( p->in.type ); p->fn.cdim = l->fn.cdim; p->fn.csiz = l->fn.csiz; if( l->in.op == UNARY AND && l->in.left->in.op == NAME && l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ p->in.op += (FORTCALL-CALL); } if( p->in.type == STRTY || p->in.type == UNIONTY ){ /* function returning structure */ /* make function really return ptr to str., with * */ p->in.op += STCALL-CALL; p->in.type = INCREF( p->in.type ); p = buildtree( UNARY MUL, p, NIL ); } break; default: cerror( "other code %d", o ); } } if( actions & CVTO ) p = oconvert(p); p = clocal(p); # ifndef BUG1 if( bdebug ) fwalk( p, eprint, 0 ); # endif return(p); } NODE * strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */ if( p->in.op == CM ){ p->in.left = strargs( p->in.left ); p->in.right = strargs( p->in.right ); return( p ); } if( p->in.type == STRTY || p->in.type == UNIONTY ){ p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); p->in.left = buildtree( UNARY AND, p->in.left, NIL ); p = clocal(p); } else if (p->in.type==CHAR || p->in.type==UCHAR || p->in.type==SHORT || p->in.type==USHORT) p = makety(p, INT, 0, INT); return( p ); } chkstr( i, j, type ) TWORD type; { /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ /* i has been checked to contain a MOS or MOU */ /* j is the index in dimtab of the members... */ int k, kk; extern int ddebug; # ifndef BUG1 #ifndef FLEXNAMES if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); #else if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); #endif # endif if( (k = j) < 0 ) uerror( "undefined structure or union" ); else { for( ; (kk = dimtab[k] ) >= 0; ++k ){ if( kk >= SYMTSZ ){ cerror( "gummy structure" ); return(1); } if( kk == i ) return( 1 ); switch( stab[kk].stype ){ case STRTY: case UNIONTY: if( type == STRTY ) continue; /* no recursive looking for strs */ if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ werror( #ifndef FLEXNAMES "illegal member use: perhaps %.8s.%.8s?", #else "illegal member use: perhaps %s.%s?", #endif stab[kk].sname, stab[i].sname ); return(1); } } } } return( 0 ); } conval( p, o, q ) register NODE *p, *q; { /* apply the op o to the lval part of p; if binary, rhs is val */ int i, u; CONSZ val; val = q->tn.lval; u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); if( q->tn.rval != NONAME && o!=PLUS ) return(0); if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); switch( o ){ case PLUS: p->tn.lval += val; if( p->tn.rval == NONAME ){ p->tn.rval = q->tn.rval; p->in.type = q->in.type; } break; case MINUS: p->tn.lval -= val; break; case MUL: p->tn.lval *= val; break; case DIV: if( val == 0 ) uerror( "division by 0" ); else p->tn.lval /= val; break; case MOD: if( val == 0 ) uerror( "division by 0" ); else p->tn.lval %= val; break; case AND: p->tn.lval &= val; break; case OR: p->tn.lval |= val; break; case ER: p->tn.lval ^= val; break; case LS: i = val; p->tn.lval = p->tn.lval << i; break; case RS: i = val; p->tn.lval = p->tn.lval >> i; break; case UNARY MINUS: p->tn.lval = - p->tn.lval; break; case COMPL: p->tn.lval = ~p->tn.lval; break; case NOT: p->tn.lval = !p->tn.lval; break; case LT: p->tn.lval = p->tn.lval < val; break; case LE: p->tn.lval = p->tn.lval <= val; break; case GT: p->tn.lval = p->tn.lval > val; break; case GE: p->tn.lval = p->tn.lval >= val; break; case ULT: p->tn.lval = (p->tn.lval-val)<0; break; case ULE: p->tn.lval = (p->tn.lval-val)<=0; break; case UGE: p->tn.lval = (p->tn.lval-val)>=0; break; case UGT: p->tn.lval = (p->tn.lval-val)>0; break; case EQ: p->tn.lval = p->tn.lval == val; break; case NE: p->tn.lval = p->tn.lval != val; break; default: return(0); } return(1); } chkpun(p) register NODE *p; { /* checks p for the existance of a pun */ /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ /* one case is when enumerations are used: this applies only to lint */ /* in the other case, one operand is a pointer, the other integer type */ /* we check that this integer is in fact a constant zero... */ /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ /* this falls out, because the LHS is never 0 */ register NODE *q; register t1, t2; register d1, d2; t1 = p->in.left->in.type; t2 = p->in.right->in.type; if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) { uerror( "illegal comparison of enums" ); return; } if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return; if( t2==ENUMTY && logop(p->in.right->in.op) ) return; /* cjt */ werror( "enumeration type clash, operator %s", opst[p->in.op] ); return; } if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; else q = p->in.left; if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ if( q->in.op != ICON || q->tn.lval != 0 ){ combo( "pointer/integer", p ); } } else { d1 = p->in.left->fn.cdim; d2 = p->in.right->fn.cdim; for( ;; ){ if( t1 == t2 ) {; if(p->in.left->fn.csiz!=p->in.right->fn.csiz) { combo( "structure pointer", p ); } return; } if( ISARY(t1) || ISPTR(t1) ){ if( !ISARY(t2) && !ISPTR(t2) ) break; if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ combo( "array size", p ); return; } if( ISARY(t1) ) ++d1; if( ISARY(t2) ) ++d2; } else break; t1 = DECREF(t1); t2 = DECREF(t2); } combo( "pointer", p ); } } combo( s, p ) char *s; register NODE *p; { char buf[100]; sprintf( buf, "illegal %s combination, op %s", s, opst[p->tn.op] ); werror( buf ); } NODE * stref( p ) register NODE *p; { TWORD t; int d, s, dsc, align; OFFSZ off; register struct symtab *q; /* make p->x */ /* this is also used to reference automatic variables */ q = &stab[p->in.right->tn.rval]; p->in.right->in.op = FREE; p->in.op = FREE; p = pconvert( p->in.left ); /* make p look like ptr to x */ if( !ISPTR(p->in.type)){ p->in.type = PTR+UNIONTY; } t = INCREF( q->stype ); d = q->dimoff; s = q->sizoff; p = makety( p, t, d, s ); /* compute the offset to be added */ off = q->offset; dsc = q->sclass; if( dsc & FIELD ) { /* normalize offset */ switch(q->stype) { case CHAR: case UCHAR: align = ALCHAR; s = CHAR; break; case SHORT: case USHORT: align = ALSHORT; s = SHORT; break; case INT: case UNSIGNED: align = ALINT; s = INT; break; # ifdef LONGFIELDS case LONG: case ULONG: align = ALLONG; s = LONG; break; # endif default: cerror( "undefined bit field type" ); } off = (off/align)*align; } if( off != 0 ) p = clocal( block( PLUS, p, makety(offcon( off, t, d, s ),INT,0,INT), t, d, s ) ); p = buildtree( UNARY MUL, p, NIL ); /* if field, build field info */ if( dsc & FIELD ){ p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); } return( clocal(p) ); } notlval(p) register NODE *p; { /* return 0 if p an lvalue, 1 otherwise */ again: switch( p->in.op ){ case FLD: p = p->in.left; goto again; case UNARY MUL: /* fix the &(a=b) bug, given that a and b are structures */ if( p->in.left->in.op == STASG ) return( 1 ); /* and the f().a bug, given that f returns a structure */ if( p->in.left->in.op == UNARY STCALL || p->in.left->in.op == STCALL ) return( 1 ); case NAME: case OREG: if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); case REG: return(0); default: return(1); } } NODE * bcon( i ){ /* make a constant node with value i */ register NODE *p; p = block( ICON, NIL, NIL, INT, 0, INT ); if (p->tn.lval>=-128 && p->tn.lval<=127) p->tn.type = CHAR; else if (p->tn.lval>=-32768 && p->tn.lval<=32767) p->tn.type = SHORT; else p->tn.type = INT; p->tn.lval = i; p->tn.rval = NONAME; return( clocal(p) ); } NODE * bpsize(p) register NODE *p; { return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); } OFFSZ psize( p ) NODE *p; { /* p is a node of type pointer; psize returns the size of the thing pointed to */ if( !ISPTR(p->in.type) ){ uerror( "pointer required"); return( SZINT ); } /* note: no pointers to fields */ return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); } NODE * convert( p, f ) register NODE *p; { /* convert an operand of p f is either CVTL or CVTR operand has type int, and is converted by the size of the other side */ register NODE *q, *r; q = (f==CVTL)?p->in.left:p->in.right; r = block( PMCONV, q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); r = clocal(r); if( f == CVTL ) p->in.left = r; else p->in.right = r; return(p); } econvert( p ) register NODE *p; { /* change enums to ints, or appropriate types */ register TWORD ty; if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; else ty = LONG; ty = ctype( ty ); p->fn.csiz = ty; MODTYPE(p->in.type,ty); if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; } } NODE * pconvert( p ) register NODE *p; { /* if p should be changed into a pointer, do so */ if( ISARY( p->in.type) ){ p->in.type = DECREF( p->in.type ); ++p->fn.cdim; return( buildtree( UNARY AND, p, NIL ) ); } if( ISFTN( p->in.type) ) return( buildtree( UNARY AND, p, NIL ) ); return( p ); } NODE * oconvert(p) register NODE *p; { /* convert the result itself: used for pointer and unsigned */ switch(p->in.op) { case LE: case LT: case GE: case GT: if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); case EQ: case NE: return( p ); case MINUS: return( clocal( block( PVCONV, p, bpsize(p->in.left), INT, 0, INT ) ) ); } cerror( "illegal oconvert: %d", p->in.op ); return(p); } NODE * ptmatch(p) register NODE *p; { /* makes the operands of p agree; they are either pointers or integers, by this time */ /* with MINUS, the sizes must be the same */ /* with COLON, the types must be the same */ TWORD t1, t2, t; int o, d2, d, s2, s; o = p->in.op; t = t1 = p->in.left->in.type; t2 = p->in.right->in.type; d = p->in.left->fn.cdim; d2 = p->in.right->fn.cdim; s = p->in.left->fn.csiz; s2 = p->in.right->fn.csiz; switch( o ){ case ASSIGN: case RETURN: case CAST: { break; } case MINUS: { if( psize(p->in.left) != psize(p->in.right) ){ uerror( "illegal pointer subtraction"); } break; } case COLON: { if( t1 != t2 ) uerror( "illegal types in :"); break; } default: /* must work harder: relationals or comparisons */ if( !ISPTR(t1) ){ t = t2; d = d2; s = s2; break; } if( !ISPTR(t2) ){ break; } /* both are pointers */ if( talign(t2,s2) < talign(t,s) ){ t = t2; s = s2; } break; } p->in.left = makety( p->in.left, t, d, s ); p->in.right = makety( p->in.right, t, d, s ); if( o!=MINUS ){ p->in.type = t; p->fn.cdim = d; p->fn.csiz = s; } return(clocal(p)); } int tdebug = 0; NODE * tymatch(p) register NODE *p; { /* satisfy the types of various arithmetic binary ops */ /* rules are: if assignment, op, type of LHS if any float or doubles, make double if any longs, make long otherwise, make int if either operand is unsigned, the result is... */ register TWORD t1, t2, t, tu; register o, u; o = p->in.op; t1 = p->in.left->in.type; t2 = p->in.right->in.type; if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) uerror("void type illegal in expression"); u = 0; if( ISUNSIGNED(t1) ){ u = 1; t1 = DEUNSIGN(t1); } if( ISUNSIGNED(t2) ){ u = 1; t2 = DEUNSIGN(t2); } if ( logop(o) ) switch (t1) { case FLOAT: case DOUBLE: t = DOUBLE; break; case INT: t = INT; break; case SHORT: t = t2==INT ? INT : SHORT; break; case CHAR: t = t2; break; } else if (t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE; else t = INT; if( asgop(o) ){ tu = p->in.left->in.type; t = t1; } else { tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; } /* because expressions have values that are at least as wide as INT or UNSIGNED, the only conversions needed are those involving FLOAT/DOUBLE, and those from LONG to INT and ULONG to UNSIGNED */ if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu ); if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); if( asgop(o) ){ p->in.type = p->in.left->in.type; p->fn.cdim = p->in.left->fn.cdim; p->fn.csiz = p->in.left->fn.csiz; } else { if ( logop(o) ) p->in.type = INT; else p->in.type = tu; p->fn.cdim = 0; p->fn.csiz = t; } # ifndef BUG1 if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); # endif return(p); } NODE * makety( p, t, d, s ) register NODE *p; TWORD t; { /* make p into type t by inserting a conversion */ if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); if( t == p->in.type ){ p->fn.cdim = d; p->fn.csiz = s; return( p ); } if( t & TMASK ){ /* non-simple type */ return( block( PCONV, p, NIL, t, d, s ) ); } if( p->in.op == ICON ){ if( t==DOUBLE||t==FLOAT ){ p->in.op = FCON; if( ISUNSIGNED(p->in.type) ){ p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval; } else { p->fpn.dval = p->tn.lval; } p->in.type = p->fn.csiz = t; return( clocal(p) ); } } return( block( SCONV, p, NIL, t, d, s ) ); } NODE * block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { register NODE *p; p = talloc(); p->in.op = o; p->in.left = l; p->in.right = r; p->in.type = t; p->fn.cdim = d; p->fn.csiz = s; return(p); } icons(p) register NODE *p; { /* if p is an integer constant, return its value */ int val; if( p->in.op != ICON ){ uerror( "constant expected"); val = 1; } else { val = p->tn.lval; if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); } tfree( p ); return(val); } /* the intent of this table is to examine the operators, and to check them for correctness. The table is searched for the op and the modified type (where this is one of the types INT (includes char and short), LONG, DOUBLE (includes FLOAT), and POINTER The default action is to make the node type integer The actions taken include: PUN check for puns CVTL convert the left operand CVTR convert the right operand TYPL the type is determined by the left operand TYPR the type is determined by the right operand TYMATCH force type of left and right to match, by inserting conversions PTMATCH like TYMATCH, but for pointers LVAL left operand must be lval CVTO convert the op NCVT do not convert the operands OTHER handled by code NCVTR convert the left operand, not the right... */ # define MINT 01 /* integer */ # define MDBI 02 /* integer or double */ # define MSTR 04 /* structure */ # define MPTR 010 /* pointer */ # define MPTI 020 /* pointer or integer */ # define MENU 040 /* enumeration variable or member */ opact( p ) NODE *p; { register mt12, mt1, mt2, o; mt12 = 0; switch( optype(o=p->in.op) ){ case BITYPE: mt12=mt2 = moditype( p->in.right->in.type ); case UTYPE: mt12 &= (mt1 = moditype( p->in.left->in.type )); } switch( o ){ case NAME : case STRING : case ICON : case FCON : case CALL : case UNARY CALL: case UNARY MUL: { return( OTHER ); } case UNARY MINUS: if( mt1 & MDBI ) return( TYPL ); break; case COMPL: if( mt1 & MINT ) return( TYPL ); break; case UNARY AND: { return( NCVT+OTHER ); } case INIT: case CM: case NOT: case CBRANCH: case ANDAND: case OROR: return( 0 ); case MUL: case DIV: if( mt12 & MDBI ) return( TYMATCH ); break; case MOD: case AND: case OR: case ER: if( mt12 & MINT ) return( TYMATCH ); break; case LS: case RS: if( mt12 & MINT ) return( TYMATCH+OTHER ); break; case EQ: case NE: case LT: case LE: case GT: case GE: if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); if( mt12 & MDBI ) return( TYMATCH+CVTO ); else if( mt12 & MPTR ) return( PTMATCH+PUN ); else if( mt12 & MPTI ) return( PTMATCH+PUN ); else if ( (mt1&MPTR) && (p->in.right->in.op==ICON)) return ( PTMATCH+PUN+RINT ); else if ( (mt2&MPTR) && (p->in.left->in.op==ICON)) return ( PTMATCH+PUN+LINT ); else break; case QUEST: case COMOP: if( mt2&MENU ) return( TYPR+NCVTR ); return( TYPR ); case STREF: return( NCVTR+OTHER ); case FORCE: return( TYPL ); case COLON: if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); else if( mt12 & MDBI ) return( TYMATCH ); else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN+LINT ); else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN+RINT ); else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); break; case ASSIGN: case RETURN: if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); case CAST: if(o==CAST && mt1==0)return(TYPL+TYMATCH); if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); else if( mt12 == 0 ) break; else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); break; case ASG LS: case ASG RS: if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); break; case ASG MUL: case ASG DIV: if( mt12 & MDBI ) return( LVAL+TYMATCH ); break; case ASG MOD: case ASG AND: case ASG OR: case ASG ER: if( mt12 & MINT ) return( LVAL+TYMATCH ); break; case ASG PLUS: case ASG MINUS: case INCR: case DECR: if( mt12 & MDBI ) return( TYMATCH+LVAL ); else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR+RINT ); break; case MINUS: if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); if( mt2 & MPTR ) break; case PLUS: if( mt12 & MDBI ) return( TYMATCH ); else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR+RINT ); else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL+LINT ); } uerror( "operands of %s have incompatible types", opst[o] ); return( NCVT ); } moditype( ty ) TWORD ty; { switch( ty ){ case TVOID: case UNDEF: return(0); /* type is void */ case ENUMTY: case MOETY: return( MENU ); case STRTY: case UNIONTY: return( MSTR ); case CHAR: case SHORT: case UCHAR: case USHORT: return( MINT|MPTI|MDBI ); case UNSIGNED: case ULONG: case INT: case LONG: return( MINT|MDBI|MPTI ); case FLOAT: case DOUBLE: return( MDBI ); default: return( MPTR|MPTI ); } } NODE * doszof( p ) register NODE *p; { /* do sizeof p */ int i; /* whatever is the meaning of this if it is a bitfield? */ i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; tfree(p); if( i <= 0 ) werror( "sizeof returns 0" ); return( bcon( i ) ); } # ifndef BUG2 eprint( p, down, a, b ) register NODE *p; int *a, *b; { register ty; *a = *b = down+1; while( down > 1 ){ printf( "\t" ); down -= 2; } if( down ) printf( " " ); ty = optype( p->in.op ); printf("%o) %s, ", p, opst[p->in.op] ); if( ty == LTYPE ){ printf( CONFMT, p->tn.lval ); printf( ", %d, ", p->tn.rval ); } tprint( p->in.type ); printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); fflush( stdout ); } # endif prtdcon( p ) register NODE *p; { int i; if( p->in.op == FCON ){ locctr( DATA ); defalign( ALDOUBLE ); deflab( i = getlab() ); fincode( p->fpn.dval, SZDOUBLE ); p->tn.lval = 0; p->tn.rval = -i; p->in.type = DOUBLE; p->in.op = NAME; } } int edebug = 0; ecomp( p ) register NODE *p; { # ifndef BUG2 if( edebug ) fwalk( p, eprint, 0 ); # endif if( !reached ){ werror( "statement not reached" ); reached = 1; } p = optim(p); walkf( p, prtdcon ); locctr( PROG ); ecode( p ); tfree(p); } # ifdef STDPRTREE # ifndef ONEPASS prtree(p) register NODE *p; { register struct symtab *q; register ty; # ifdef MYPRTREE MYPRTREE(p); /* local action can be taken here; then return... */ #endif ty = optype(p->in.op); printf( "%d\t", p->in.op ); if( ty == LTYPE ) { printf( CONFMT, p->tn.lval ); printf( "\t" ); } if( ty != BITYPE ) { if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); else printf( "%d\t", p->tn.rval ); } printf( "%o\t", p->in.type ); /* handle special cases */ switch( p->in.op ){ case NAME: case ICON: /* print external name */ if( p->tn.rval == NONAME ) printf( "\n" ); else if( p->tn.rval >= 0 ){ q = &stab[p->tn.rval]; printf( "%s\n", exname(q->sname) ); } else { /* label */ printf( LABFMT, -p->tn.rval ); } break; case STARG: case STASG: case STCALL: case UNARY STCALL: /* print out size */ /* use lhs size, in order to avoid hassles with the structure `.' operator */ /* note: p->in.left not a field... */ printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); break; default: printf( "\n" ); } if( ty != LTYPE ) prtree( p->in.left ); if( ty == BITYPE ) prtree( p->in.right ); } # else p2tree(p) register NODE *p; { register ty; # ifdef MYP2TREE MYP2TREE(p); /* local action can be taken here; then return... */ # endif ty = optype(p->in.op); switch( p->in.op ){ case NAME: case ICON: #ifndef FLEXNAMES if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; #else if( p->tn.rval == NONAME ) p->in.name = ""; #endif else if( p->tn.rval >= 0 ){ /* copy name from exname */ register char *cp; register i; cp = exname( stab[p->tn.rval].sname ); #ifndef FLEXNAMES for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; #else p->in.name = tstr(cp); #endif } #ifndef FLEXNAMES else sprintf( p->in.name, LABFMT, -p->tn.rval ); #else else { char temp[32]; sprintf( temp, LABFMT, -p->tn.rval ); p->in.name = tstr(temp); } #endif break; case STARG: case STASG: case STCALL: case UNARY STCALL: /* set up size parameters */ p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; break; case REG: rbusy( p->tn.rval, p->in.type ); default: #ifndef FLEXNAMES p->in.name[0] = '\0'; #else p->in.name = ""; #endif } p->in.rall = NOPREF; if( ty != LTYPE ) p2tree( p->in.left ); if( ty == BITYPE ) p2tree( p->in.right ); } # endif # endif n( MSTR ); case CHAR: case SHORT: case UCHAR: case USHORT: return( MINT|MPTI|MDBI ); case UNSIGNED: case ULONG: case INT: case LONG: return( MINT|MDBI|MPTI ); case FLOAT: case DOUBLE: return( MDBI ); default: return( MPTR|MPTI ); } } NODE * doszof( p ) register NODE *p; { /* do sizeof p */ int i; /* whatever is the meaning of this if it is a bitfield? */ i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; tfree(p); if( i <= 0 ) werror( "sizeof returns 0" ); return( bsumacc/cc/ccom/xdefs.c 444 0 12 5066 3470501553 10075 # include "mfile1" /* communication between lexical routines */ char ftitle[100] = ""; /* title of the file */ int lineno; /* line number of the input file */ CONSZ lastcon; /* the last constant read by the lexical analyzer */ double dcon; /* the last double read by the lexical analyzer */ /* symbol table maintainence */ struct symtab stab[SYMTSZ+1]; /* one extra slot for scratch */ int curftn; /* "current" function */ int ftnno; /* "current" function number */ int curclass, /* current storage class */ instruct, /* "in structure" flag */ stwart, /* for accessing names which are structure members or names */ blevel, /* block level: 0 for extern, 1 for ftn args, >=2 inside function */ curdim; /* current offset into the dimension table */ int dimtab[ DIMTABSZ ]; int paramstk[ PARAMSZ ]; /* used in the definition of function parameters */ int paramno; /* the number of parameters */ int autooff, /* the next unused automatic offset */ argoff, /* the next unused argument offset */ strucoff; /* the next structure offset position */ int regvar; /* the next free register for register variables */ int minrvar; /* the smallest that regvar gets witing a function */ OFFSZ inoff; /* offset of external element being initialized */ int brkflag = 0; /* complain about break statements not reached */ struct sw swtab[SWITSZ]; /* table for cases within a switch */ struct sw *swp; /* pointer to next free entry in swtab */ int swx; /* index of beginning of cases for current switch */ /* debugging flag */ int xdebug = 0; int strflg; /* if on, strings are to be treated as lists */ int reached; /* true if statement can be reached... */ int idname; /* tunnel to buildtree for name id's */ NODE node[TREESZ]; int cflag = 0; /* do we check for funny casts */ int hflag = 0; /* do we check for various heuristics which may indicate errors */ int pflag = 0; /* do we check for portable constructions */ int brklab; int contlab; int flostat; int retlab = NOLAB; int retstat; /* save array for break, continue labels, and flostat */ int asavbc[BCSZ]; int *psavbc = asavbc ; # ifndef BUG1 static char * ccnames[] = { /* names of storage classes */ "SNULL", "AUTO", "EXTERN", "STATIC", "REGISTER", "EXTDEF", "LABEL", "ULABEL", "MOS", "PARAM", "STNAME", "MOU", "UNAME", "TYPEDEF", "FORTRAN", "ENAME", "MOE", "UFORTRAN", "USTATIC", }; char * scnames( c ) register c; { /* return the name for storage class c */ static char buf[12]; if( c&FIELD ){ sprintf( buf, "FIELD[%d]", c&FLDSIZ ); return( buf ); } return( ccnames[c] ); } # endif CALL: /* set up size parameters */ p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; break; case REG: rbusy( p->tn.rval, p->in.type ); default: #ifndef FLEXNAMES p->in.name[0] = '\0'; #else p->in.name = ""; #endif } p->in.rall = NOPREF; if( ty != LTYPE ) p2tree( p->in.left ); if( ty == BITYPE ) p2tree( p->in.right ); } # endif # endisumacc/cc/ddt68/ 775 0 12 0 3470501557 6544 sumacc/cc/ddt68/.netupd_log 444 0 12 2775 3470501554 10776 Sat Apr 28 18:05:59 1984 created file Makefile[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:04 1984 created file bpt.s[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:09 1984 created file dasmsub.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:16 1984 created file ddt.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:23 1984 created file ddt.h[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:27 1984 created file ddt68.1[coyote], author: mogul on Mon Apr 9 23:01:34 1984 Sat Apr 28 18:06:30 1984 created file ea68[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:33 1984 created file ea68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:37 1984 created file fddt68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:42 1984 created file ins.f[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:46 1984 created file inscom.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:49 1984 created file ops68[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:53 1984 created file ops68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:57 1984 created file vea68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:07:03 1984 created file vinscom.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:07:07 1984 created file vops68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 bugsumacc/cc/ddt68/Makefile 444 0 12 2110 3470501554 10254 # Makefile for ddt68 # Documented by Bill Nowicki January 1982 S = /usr/sun M = bpt.b ddt.b dasmsub.b OBJVAX = ddt.o dasmsub.o CC = cc -g .SUFFIXES: .b .s .a68 .dl .c.b .s.b .a68.b: cc68 -c $< #all: fddt68 ddt68 ddt68.dl DDT68.dl #install: # cp ddt68 $S/bootfile $S/lib/libddt.a: $M ar ruv $S/lib/libddt.a $M ddt68: $M cc68 $M -r -o ddt68 ddt68.dl: $M cc68 -s -d -T 1a000 $M -o ddt68.dl fddt68: $(OBJVAX) $(CC) $(OBJVAX) -o fddt68 DDT68.dl: bpt.b ddt.b dmdasmsub.b cc68 -s -vm -d -T 5000 bpt.b ddt.b dmdasmsub.b -o DDT68.dl ddt.b: ddt.h ddt.c ddt.o: ddt.h ddt.c dasmsub.b: ddt.h dasmsub.c ea68.c ops68.c dmdasmsub.b: ddt.h dasmsub.c ea68.c ops68.c cc68 -DDM -c dasmsub.c -o dmdasmsub.b dasmsub.o: ddt.h dasmsub.c vea68.c vops68.c ea68.c: ea68 inscom inscom < ea68 > ea68.c ops68.c: ops68 inscom inscom < ops68 > ops68.c vea68.c: ea68 vinscom vinscom < ea68 > vea68.c vops68.c: ops68 vinscom vinscom < ops68 > vops68.c inscom: inscom.c cc inscom.c -o inscom vinscom: vinscom.c cc vinscom.c -o vinscom clean: rm -f *.b *.o *.out *.dl ddt68 inscom fddt68 vinscom 8[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:53 1984 created file ops68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:06:57 1984 created file vea68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:07:03 1984 created file vinscom.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 Sat Apr 28 18:07:07 1984 created file vops68.c[coyote], author: ds on Thu Feb 5 22:28:16 1970 bugsumacc/cc/ddt68/bpt.s 444 0 12 3152 3470501554 7574 | This file is the low level interface to ddt. It saves registers and passes | control to ddt. .text .globl ddtinit |initial entry point .globl ddtbpt |trap #14 vector .globl ddtbrk |C-level trap routine .globl ddttrct |trace vector .globl ddttrace |C-level trace routine .globl ddtosr |old status register .globl ddtopc |old program counter .globl ddtsvregs |saved gp regs | Here from a ddtinit() call, normally from crtsun.s | Must already be in system state ddtinit: addql #2,sp@ |anticipate following subql #2,sp@ movw sr,sp@- |push status register on stack | here on a breakpoint trap ddtbpt: movw #0x2600,sr | mask off interrupts < 7 movw sp@+,ddtosr |old status register subql #2.,sp@ |point back to bp instruction movl sp@+,ddtopc |old program counter moveml #/FFFF,ddtsvregs |save registers btst #5,ddtosr |see if user state bne callddt |no movl usp,a0 |yes, get user's sp movl a0,ddtsvregs+60 |and save it callddt: jsr ddtbrk |call ddt traprt: btst #5,ddtosr |again see if user state bne restor movl ddtsvregs+60,a0 |get user sp movl a0,usp |and restore it to usp restor: moveml ddtsvregs,#/FFFF |restore registers movl ddtopc,sp@- |push pc on the stack movw ddtosr,sp@- |push sr on the stack rte |execute broken instruction ddttrct: movw #0x2600,sr | mask off interrupts < 7 movw sp@+,ddtosr |save status register movl sp@+,ddtopc |save pc moveml #/FFFF,ddtsvregs |save registers btst #5,ddtosr |see if user state bne calltr |no movl usp,a0 |yes, get user's sp movl a0,ddtsvregs+60 |and save it calltr: jsr ddttrace |call tracer bra traprt * true if statement can be reached... */ int idname; /* tunnel to buildtree for name id's */ NODE node[TREESZ]; int cflag = 0; /* do we check for funny casts */ int hflag = 0; /* do we check for various heuristics which may indicate errors */ int pflag = 0; /* do we check for portable constructions */ int brklab; int contlab; int flostat; int retlab = NOLAB; int retstat; /* save array for breaksumacc/cc/ddt68/dasmsub.c 444 0 12 27111 3470501554 10446 /* 68000 Disassembler * V.R. Pratt * Jan., 1981 */ #include "ddt.h" #define NOARGS 6 /* maximum number of opcode arguments */ #define NEARGS 3 /* maximum number of eff.adr. arguments */ /* Symbols external to dasmsub */ char legal; /* keeps track of *'s */ /* Symbols global to dasmsub but not external. */ static long opargs[NOARGS], /* where to put opcode args */ eargs[NEARGS]; /* where to put ea args */ static int argno; /* global pointer into args */ static int nwords; /* words in instruction */ static unsigned short *mpc, /* main program counter */ *spc; /* start pc */ static char longflag; /* 1 -> long */ static char sym; /* 1 -> symbolic addresses */ static char sizmod; /* 1 -> one-bit size field */ /* Some general routines. * * We don't actually talk to the outside world directly. Output is dumped * dumped into one of two global buffers and we leave it up to the caller * to decide what is to be done with it. */ struct cbuffr bfr1, bfr2; /* the two buffers */ struct cbuffr *cbfp; /* pointer to active one */ /* As characters are placed in the output buffer, we keep track of the * column position and watch out for the special character '*'. This is * indication that we have just attempted to disassemble an illegal * instruction and the global flag "legal" is cleared. */ dasmput(c) register char c; { register int lcol = cbfp->col; if ( c != '\t' ) lcol++; else lcol = ( ( lcol + 8 ) / 8 ) * 8; if ((cbfp->buf[cbfp->pnt++] = c) == '*') legal = 0; cbfp->col = lcol; } /* The usual routines for numeric conversion. * * First, an external routine to output a number in some radix. */ extern void numout(); /* type a number in current radix */ /* Convert a long to it's ascii hex representation regardless of the * "current radix". */ static hex(n) register unsigned long n; { if ( n > 15 ) hex( n >> 4 ); n &= 15; dasmput((char)( n + ( n>9 ? '7': '0'))); } /* Convert an integer to it's ascii hex representation in exactly four * digits. Insert leading zeroes if required. */ static whex(n) register unsigned int n; { register int i; register char c; for( i = 12; i >= 0; i -= 4) { c = n>>i & 15; dasmput( c + ( c>9? '7': '0')); } } /* This is a compact disassembler intended for use in the 68000 design * module. * * Principles of Operation * * The disassembler has the following components. * * 1. A list of instruction patterns and their assembler forms, * each serving as the head of a function definition. * * 2. A list of effective addresses and their assembler forms, each serving * as the body of a function definition. * * 3. A function to locate the first entry in the appropriate list matching * a given instruction or effective address, serving as the * function-identification component of an eval. * * 4. A function to bind the actual parameters in the instruction or * effective address to the formal parameters in the function head. * * 5. A function to substitute the formal parameters into the function body. * * * Lists * * The two lists are machine readable forms of those given in /usr/pratt/ins68 * (see /usr/pratt/ins.f for the format of this file). In the machine * readable form each entry has the following structure. */ typedef struct Entry {char length; char modifier; unsigned short mask; unsigned short pattern; } *entry; /* Following each entry is a character string, considered part of the entry. * The entries are concatenated to form a table. The entry boundaries are * determined only by the length member, the tables being intended to be * searched forwards linearly. Entries are aligned on word boundaries. * * The length of an entry is the number of bytes in the entry, which may be * odd in which case the following entry is one byte further along than * indicated by length. * * Fparams is an array of 6 formal parameters, each an unsigned nybble (4-bit * integer) encoding the type of that parameter. * * The mask and the pattern together are used to tell whether an item such * as an opcode matches entry e, by the test: */ #define match(item,ent) ((item ^ ent->pattern) & ent->mask) == 0 /* Match is used by the locate routine, which locates the first entry in the * given table matching the given code. */ static entry locate(code,tab) register code; register entry tab; { while (1) /* guaranteed to find something */ { if (match(code,tab)) break; tab = (entry)((long)tab + tab->length + 1 & -2);/* go to next entry */ } return(tab); } /* The mask and pattern are also used to extract the arguments from an item * such as an opcode or an effective address. These are extracted * right-to-left from the item by the function bind and stored in * in successive locations of the area args supplied to bind. */ #define shft {item >>= 1; pattern >>= 1; mask >>= 1;} static bind(item,pattern,mask,args) register short unsigned item, pattern, mask; long args[]; { while (1) /* loop per argument */ { while (mask&1) shft; /* skip masked part */ if (!pattern) break; /* stopping cond. */ args[argno++] = (long)(char)(item&(pattern ^ pattern-1)); /* bind */ while (!(pattern&1)) shft; shft; /* skip field */ } } static bindmod(m,args) register char m; /* bind modifier */ register long args[]; /* bind arg */ { /*n*/ if (m&1 && (!(m&2) || !longflag)) args[argno++] = (short) getwpc((short*)mpc++); /*i*/ if (m&2 && (!(m&1) || longflag)) {args[argno++] = getlpc((long*)mpc++); mpc++;} /*g*/ if (m&8) { args[argno++] = (unsigned)getwpc(mpc)>>8; args[argno++] = getbpc((char *)mpc++ + 1); } /*l*/ if (m&16) longflag = 1; /*p*/ if (m&32) sym = 1; /*t*/ if (m&64) sizmod = 1; /*u*/ if (m&128) args[argno++] = getwpc(mpc++); } /* Symbols are dealt with as follows: * * Output a symbol's name. */ static putsymbol(c) register char *c; { register int i=MAXSYMLEN; while (*c != ' ' && *c != '\0' && i--) dasmput(*c++); } /* Given a long value "n", and pointer to a symbol table definition, * find the symbol entry whose value is 'closest' to "n". */ struct sym * dasmsymbol(n, table) register long n; symtabdef *table; { register struct sym *current, *best; register long bestvalue = 0; #ifdef DM for (current = table->start; current < table->limit; current++) #else for (current = table->start; current < table->limit; current = (struct sym *)((int)(current+1) + current->slength + ADJ)) #endif DM if (bestvalue < current->svalue && current->svalue <= n) { best = current; bestvalue = current->svalue; } return(bestvalue && n - bestvalue < 1000? best: 0); } /* Given a value "v", look for a symbol whose value is 'closest' to "v". * If one is found, output the name of that symbol, otherwise, output the * numeric value of "v" in the current radix. */ struct sym *dasmsymbolic(v, table) register long v; symtabdef *table; { register struct sym *e = dasmsymbol(v, table); if (e) { putsymbol(e+1); if (e->svalue < v) { dasmput('+'); numout(v - e->svalue); } } else numout(v); return( e ); } /* Given a long "y", return it's bit reversal. */ static long rev(y) long y; { register long z=0; register n=16; while (n--) { z = z<<1|(y&1); y>>=1; } return(z); } /* The tables of opcodes and eacodes (for effective addresses) are kept on * separate files ops68.c and ea68.c. */ static unsigned char optab[] = { #ifdef MC68000 #include "ops68.c" #else ndef MC68000 #include "vops68.c" #endif MC68000 }; static unsigned char eatab[] = { #ifdef MC68000 #include "ea68.c" #else ndef MC68000 #include "vea68.c" #endif MC68000 }; /* The heart of this file is instr(), which returns the assembler form * of the instruction presently pointed to by mpc. As a side effect it * advances mpc to the word following the instruction. */ static instr() /* process next instruction */ { sizmod = 0; /* assume two-bit size field */ longflag = 0; /* assume short data */ legal = 1; /* innocent till proved g'ty */ sym = 0; /* assume nonsymbolic data */ spc = mpc; /* remember mpc */ if( getwpc(mpc) ) /* if word at pc isn't 0 */ translate( getwpc(mpc++),optab,opargs); /* translate opcode */ else legal = 0; /* assume data */ if (!legal) { mpc = spc+1; /* assume one word */ } } /* The function translate(item,tab,args) translates item, which is either * an opcode or an effective address, using the appropriate table tab, either * optab or eatab, using args as the base address of the stack of * arguments extracted from the item in the course of translation, by the * binding mechanisms. */ static translate(item,tab,args) unsigned short item; char *tab; long args[]; { entry ent = locate(item,tab); /* locate entry for opcode */ argno = 0; /* where to store args */ bind(item,ent->pattern,ent->mask,args); /* bind item arguments */ bindmod(ent->modifier,args); /* bind modifier arguments */ subst((long)ent+6,(long)ent+ent->length,args); /* substitute args */ } /* The function subst takes a pair of pointers pointing to the two ends of * a string whose free variables are to be instantiated, and a pointer to * a stack of arguments to be bound to those variables. */ static subst(cod,lim,args) char *cod, *lim; long args[]; { while (cod<lim) /* substitute up to lim */ if (*cod >= 0) dasmput(*cod++); /* copy the char directly */ else /* execute the command *cod */ { register long v = args[(*cod >> 4) & 7];/* get value v */ char *siz = "bwl*"; char *cc = "rasrhilscccsneeqvcvsplmigeltgtle";/* condition codes */ char r = 'a'; switch (*cod++ & 15) /*k*/ {case 0: if (v<128) r += 3; dasmput(r); dasmput('0'+((v>>4)&7)); dasmput(':'); dasmput(v&8? 'l': 'w'); break; /*d*/ case 1: r += 3; /* do a->d conversion */ /*a*/ case 2: dasmput(r); dasmput('0'+(v&7)); break; /*E*/ case 3: v = ((v&7)<<3)|(v>>3); /*e*/ case 4: translate((short)v,eatab,eargs); break; /*s*/ case 5: v+=sizmod; dasmput(siz[v]); if (v==2) longflag = 1; break; /*v*/ case 6: if (v == 0) v = 8; /*n*/ case 7: if (v<0) { dasmput('-'); numout((long)-v); break; } /*u*/ case 8: dasmsymbolic((long)v, USRSYMS); break; /*y*/ case 9: v = rev((long)v); /*x*/ case 10: hex((long)(v&0xffff)); break; /*m*/ case 11: if (v) cod += *cod; else cod++; break; /*f*/ case 12: while (v--) while (*cod++ != ','); while (*cod != ',' && *cod != ')') dasmput(*cod++); while (*cod++ != ')'); break; /*c*/ case 13: dasmput(cc[v*2]); dasmput(cc[v*2+1]); break; /*r*/ case 14: dasmsymbolic((long)spc+2+v, USRSYMS); break; } } } /* Finally, the main entry point to this collection of routines. * Given a word address, we interpret the word(s) at that address * as a 68000 instruction and disassemble them putting the disassembled * "source" text in one output buffer, and the hex ascii representation * in another. The number of words disassembled is returned. */ int dasm(address) unsigned short *address; { mpc = address; bfr1.pnt = bfr2.pnt = 0; bfr1.col = bfr2.col = 1; cbfp = &bfr1; /* start off in first buffer */ dasmsymbolic((long)mpc, USRSYMS); if (cbfp->col <= 8) dasmput('\t'); dasmput('\t'); instr(); /* dis-assemble the instruction */ dasmput('\0'); cbfp = &bfr2; /* switch to second for hex */ hex((long)spc); /* address in hex */ dasmput('\t'); do { whex( getwpc(spc++) ); dasmput(' '); } while (spc < mpc); while (cbfp->col < 32) dasmput('\t'); dasmput('\0'); return((int) (mpc - address) ); } 68000 #include "vea68.c" #endif MC68000 }; /* The heart of this file is instr(), which returns the assembler form * of the instruction presently pointed to by mpc. As a side effect it * advances mpc to the word following the instruction. */ static instr() /* process next instruction */ { sizmod = 0; /* assume two-bit size field */ longflag = 0; /* assume short data */ legal = 1; /* innocent till provesumacc/cc/ddt68/ddt.c 444 0 12 104503 3470501555 7605 /* 68000 DDT * Jim Lawson and Vaughan Pratt - 1981 * Added 's' command to print stack. Per Bothner 1982/June NOT FINISHED!!! * */ #ifdef MC68000 #define NULL 0 /* from stdio.h */ #define BPTADR *(int(**)())0xb8 /* trap 14 address */ #define TRCADR *(int(**)())0x24 /* trace address */ extern char emt_getchar(); #else ifndef MC68000 #include <stdio.h> #endif MC68000 #include "ddt.h" extern struct cbuffr bfr1, bfr2; extern struct cbuffr *cbfp; extern short dasm(); extern ddtbpt(), ddttrct(); extern char legal; /* if last instruction disassembled was */ extern struct sym *dasmsymbol(); /* lookup symbol given value */ extern struct sym *dasmsymbolic(); /* output symbol given value */ static struct bpstr bp[BPMAX + 1] = { 0 }; /* breakpoint structures */ #define SSBP 0 /* plus one for single stepping */ /* over subroutine calls. */ #define BSRINST 0x6100 /* one flavour of subroutine call */ #define JSRINST 0x4E80 /* another flavour */ #define TRAPINST 0x4e40 /* a third flavour */ #define oddpc ((int)pc&1) static struct bpstr * cbptr = bp; /* current breakpoint or NULL */ static char ssflag = 0; /* flag set non-zero if single stepping */ static char single = 0; /* says to set trace bit on exit */ static long sscount = 1; /* how many single steps */ static short bpno; /* current bpt if any, else -1 */ short *ddtopc; /* pc at breakpoint */ short ddtosr; /* status register at breakpoint */ long ddtsvregs[16] = {0}; /* registers at time of breakpoint */ static short *quitpc; /* exit pc */ static short quitsr; /* exit status reg */ static long quitsp; /* exit stack pointer */ static long smask; /* string mask - masks chars read */ static long tmask; /* temporary mask used in search */ static short iradix = DEFRADIX; /* input radix */ static short oradix = DEFRADIX; /* output radix */ static long mask = ~0; /* search mask */ static char *lowlimit, *hilimit;/* search limits */ static char gotarg; /* true if argument supplied on command */ static long comarg; /* value of argument */ static char compfx; /* command prefix */ static int dspbyte(); static int dspword(); static int dsplong(); static int dspsymb(); static int dspstrg(); static int (*dspdata[])() = { /* array of pointers to int functions */ dsplong, /* default */ dspbyte, dspbyte, dspword, dsplong, dspsymb, dspstrg }; static int putbyte(); static int putword(); static int putlong(); static int putstrg(); static int (*depdata[])() = { putlong, /* default deposit */ putbyte, putbyte, putword, putlong, putword, putstrg }; static long lgetbpc(); static long lgetwpc(); static long lgetlpc(); static long lgetspc(); static long (*getldata[])() = { lgetlpc, /* default search mode */ lgetbpc, lgetbpc, lgetwpc, lgetlpc, lgetwpc, lgetspc }; symtabdef ddtusrsyms = {0, 0}; /* start,limit of user symbols */ static char symtype; /* type of last symbol found */ static char tomode = 0, tmptomode = 0, dtype = 0; /* type-out mode */ static short escno; /* number of escape chars typed */ static char *dot = (char *) 0x1000; /* last location examined */ static char das = 'u'; /* address space */ static char *symterms = "+- |\r\n/=\\<>?";/* characters which delimit symbols */ static char *argterms = "\r\n*/=\\<>?"; /* ditto for arguments */ #define COMCHRS "/qgpsxbr=*t\\<>?m\n\r" /* * fetch various flavours of data from memory, returning a long. */ static long lgetbpc(pc) char *pc; { return( getbpc(pc) ); } static long lgetwpc(pc) char *pc; { return getwpc(pc) ; } static long lgetlpc(pc) char *pc; { return getlpc(pc) ; } static long lgetspc(pc) char *pc; { switch ( smask) { case 0: case 0x7f7f7f7f:return oddpc?(getlpc(pc-1)<<8)|getbpc(pc+3):getlpc(pc); case 0x7f: return getbpc(pc); case 0x7f7f: return oddpc?(getbpc(pc)<<8) | getbpc(pc+1):getwpc(pc); case 0x7f7f7f: return (oddpc? getlpc(pc-1): getlpc(pc)>>8) & 0xffffff; } } symtabdef ddtsymdef; /* Special ddt symbols */ struct {struct sym a; char name[4];} ddtsyms[] = { { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[0]}, { '$','d','0',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[1]}, { '$','d','1',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[2]}, { '$','d','2',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[3]}, { '$','d','3',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[4]}, { '$','d','4',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[5]}, { '$','d','5',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[6]}, { '$','d','6',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[7]}, { '$','d','7',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[8]}, { '$','a','0',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[9]}, { '$','a','1',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[10]}, { '$','a','2',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[11]}, { '$','a','3',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[12]}, { '$','a','4',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[13]}, { '$','a','5',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[14]}, { '$','f','p',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[14]}, { '$','a','6',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[15]}, { '$','s','p',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtsvregs[15]}, { '$','a','7',0 } }, { { LONGTYPE|DDTSYM, 3, (long) &ddtopc}, { '$','p','c',0 } }, { { WORDTYPE|DDTSYM, 3, (long) &ddtosr}, { '$','s','r',0 } }, { { POINTERTYPE|DDTSYM, 3, (long) &dot}, {'.',0,0,0 } }, { { 0, 0, 0}, {0,0,0,0} } }; /* * Output a string. */ static putstring( sp ) register char *sp; { while( *sp ) emt_putchar( *sp++ ); } /* * Force a character to upper case. */ static char forceupper(c) char c; { if( (c) >= 'a' && (c) <= 'z') c = c - 'a' + 'A'; return(c); } /* * Convert a character to a format suitable for symbols. */ static char macify(c) char c; { #ifdef DM return( forceupper(c) ); #else return( c ); #endif } /* * Validate candidate for new radix. */ static short setradix(value) long value; { if( value > 0 && value < 26L ) /* possible radix ? */ return((short) value); else return(DEFRADIX); /* return default */ } /* * Convert a number to its ascii representation in the current output radix. */ void numout(number) unsigned long number; { register unsigned short c; c = number % oradix; if( number /= oradix ) numout( number ); c &= 0xFF; c += (c > 9) ? ( 'A' - 10 ) : '0'; dasmput(c); } /* * Print a number in the current output radix. */ static void printnum(number) long number; { bfr1.pnt= 0; bfr1.col= 1; cbfp = &bfr1; numout( number ); /* output value of arg */ dasmput('\0'); putstring(bfr1.buf); } /* * Print address at pc in a suitable format. */ static void printadrs( pc ) long pc; { symtabdef *table; register struct sym *sp; if( das == 'd' ) /* in ddt's address space ? */ table = &ddtsymdef; else table = USRSYMS; bfr1.pnt= 0; bfr1.col= 1; cbfp = &bfr1; dasmsymbolic( pc, table ); dasmput('\0'); putstring(bfr1.buf); } /* * Test character set membership. */ static short oneof(c,string) register char c, *string; { register char m; while(( m = *string++ )) if( c == m ) return(1); return(0); } /* * Check a character to see if it's a valid digit in the current radix. */ static short isdig(c, d) register char c; short *d; { register short valid; *d = 0; c = forceupper(c); if( c < '0' ) valid = 0; /* not a digit no how */ else if( iradix <= 10 ) if( c > ( '0' + iradix - 1 ) ) valid = 0; else { valid = 1; *d = c - '0'; } else if( c <= '9' ) { valid = 1; *d = c - '0'; } else if( c > ( 'A' + iradix -10 -1 ) ) valid = 0; else { valid = 1; *d = c - 'A' + 10; } return(valid); } /* * Build a number and return the character that delimited it. */ static char getnum(string, value) char *string; long *value; { char c; short d; register long n = 0; while( isdig((c = *string++), &d)) /* while we're eating digits...*/ { n = n * iradix + d; } *value = n; return(c); } /* * Look up a string in the symbol table. Return a pointer to entry if found, * NULL if not. */ static struct sym* findsym(string, table) char *string; symtabdef *table; { register struct sym *current; for( current = table->start; current < table->limit; current = (struct sym *)((int)(current+1) + current->slength + ADJ)) { register char *sym = string; register char *name = (char *)(current+1); register short i; for( i = MAXSYMLEN; i; i-- ) { if( *sym == '\0' ) if( *name == ' ' || *name == '\0' ) return(current); /* found it */ if( *sym++ != *name++) break; } if( i == 0 ) return( current ); } return((struct sym *) NULL); } /* * Add a symbol to the symbol table. Returns a pointer to the new * symbol entry if successful, NULL otherwise. */ static struct sym* addsym( string, value, table ) register char *string; long value; symtabdef *table; { register struct sym *sp = table->limit++; register char *name = (char *)(sp+1); register short i; for( i = MAXSYMLEN; i; i-- ) { if( *string != '\0' ) /* end of string ? */ *name++ = *string++; /* if not, copy characters */ else *name++ = '\0'; /* otherwise, spaces */ } sp->svalue = value; /* set the value of the symbol */ return( sp ); } /* * Scan characters into a symbol, set the value of the symbol, * and return the character that delimited the symbol. Set gotarg to 1 * if a symbol was successfully scanned. */ static char getsym(symvalue) register long *symvalue; { char c, symbol[40]; register char *sptr = symbol; register struct sym *symadr; /* insert characters into symbol until we hit an argument terminator */ smask = 0; *symvalue = 0; while( !oneof( ( c = emt_getchar()), symterms)) if (c == 127) { if (sptr > symbol) { sptr--; putstring("\b \b"); } } else *sptr++ = macify(c); *sptr = '\0'; if(( sptr - symbol ) == 0 ) return c; /* case of reading nothing */ das = 'u'; /* assume user's address space */ gotarg = 1; /* we have an argument */ /* if starts with '"' it must be a string - get last 4 chars */ if ( symbol[0] == '"') { char *sptr = symbol+1; *symvalue = 0; while ( sptr[0] && (sptr[0] != '"' || sptr[1] == '"' )) { *symvalue = (*symvalue<<8) | sptr[0]; smask = (smask<<8) | 0x7f; if (sptr[0] == '"') sptr++; sptr++; } return c; } /* assume what we have is a symbol and look for it in ddt's symbol table */ if((symadr = findsym(symbol, &ddtsymdef))) das = 'd'; /* ddt's address space */ /* if we don't find it there, look for it in the user's symbol table */ else symadr = findsym( symbol, USRSYMS ); if( symadr ) { /* if either returned an address, we found it. */ symtype = symadr->stype; /* remember symbol type */ if(( symtype & DDTSYM ) && ( symtype & POINTERTYPE )) { *symvalue = *(long *) symadr->svalue; das = 'u'; /* really user address space */ } else *symvalue = symadr->svalue; /* return its value */ } else { /* assume it's a numeric constant */ symtype = 0; /* type is unknown */ if( getnum(symbol, symvalue) != '\0') { c = BADARG; gotarg = 0; *symvalue = 0; } } return c; } /* * Ascertain the correct type-out mode for the current display. * If the user has specified a type-out mode (or symbol type) use * that, else, if the symbol type is known, use that, otherwise, * carry on using the current mode. */ static settomode( pc ) char *pc; { symtabdef *table; register struct sym *sp; if( das == 'd' ) /* ddt symbol ? */ table = &ddtsymdef; else table = USRSYMS; sp = dasmsymbol( pc, table ); /* find nearest symbol */ symtype = sp? sp->stype: 0; if( tmptomode ) /* over-riding default mode ? */ dtype = tmptomode; else if( tomode ) /* user-specified type ? */ dtype = tomode; /* use that */ else dtype = symtype; dtype &= TYPEFIELDMASK; } /* * Convert single character type specification into appropriate type-out * mode. */ static short gettomode( c ) char c; { short totype; switch( c ) { case 'c': totype = CHARTYPE; break; case 'h': totype = BYTETYPE; break; case 'w': totype = WORDTYPE; break; case 'l': totype = LONGTYPE; break; case 'i': totype = INSTTYPE; break; case 's': totype = STRTYPE; break; default: totype = 0; break; } return( totype ); } /* * Make sure pc contains a valid word address */ static char * wordadr( pc ) register long pc; { return ((char *) ( pc & ~1 )); /* better be even */ } /* * Here to display data */ static int display( type, adrs ) char *adrs; short type; { return( (*dspdata[type])(adrs) ); } /* * Here to deposit data */ static int deposit( type, adrs, data ) short type; char *adrs; long data; { return( (*depdata[type])(adrs, data) ); } /* * Here to increment pc. */ static char * inc_pc( pc, inc ) register char *pc; register int inc; { return( (char *) pc + inc ); } /* * Function to decrement pc. Returns pc - inc. */ static char * dec_pc( pc, dec ) register char *pc; register int dec; { register int nwords = 0, i; register short *pos = (short *) wordadr( pc ) - 6; if( dtype == INSTTYPE ) { for( i = 5; i > 0; i--) { if (getbpc(++pos) != -1) { nwords = dasm(pos); /* attempt to disassemble */ if( legal && ( nwords == i ) ) return( (char *) pos ); } } if (getbpc(wordadr(pc)) == -1) return wordadr(pos); else return wordadr(pos)-1; } if (dtype == STRTYPE) { while (getbpc(--pc) == 0); while (getbpc(--pc) > 0); if (getbpc(pc) == -1) pc++; return pc; } return((char *) pc - dec ); } /* * Here to get data from memory for search comparision */ static long getsearchval( type, pc ) char *pc; short type; { return( (*getldata[type])( pc ) ); } /* Commands consist of an argument terminated by one or more argument * terminators, followed by a single character command. Arguments may be * numeric constants, symbols or register specifications. */ static char getarg() { long symvalue; char c, nxdel; gotarg = 0; comarg = 0; c = getsym(&comarg); /* eat a symbol */ while(!oneof(c, argterms)) { nxdel = getsym(&symvalue); /* eat another symbol */ switch(c) { case '|': comarg |= symvalue; break; case '+': comarg += symvalue; break; case '-': comarg -= symvalue; break; default: comarg = symvalue; break; } c = nxdel; } return(c); } static char getcom() { char c; escno = 0; c = getarg(); /* get argument */ while( c == ESCCHR ) { escno++; /* count escapes */ emt_putchar(0); /* render escape harmless to tty */ emt_putchar('$'); /* and echo dollar */ c = emt_getchar(); } return(c); } /* * Interpret the command argument (if there is one) as a pc. */ static short setpc(pcptr) char **pcptr; { if( gotarg ) /* was an argument supplied ? */ { if( !comarg || ( comarg & 1 ) ) /* better be non-zero and even */ { return(0); /* otherwise, don't do anything */ } *pcptr = (char *) comarg; /* set pc */ } return(1); } /* * Function to display data at pc in symbolic format. Returns number * of bytes displayed. */ static int dspsymb(pc) char *pc; { int nbytes; pc = wordadr( pc ); /* legal word address */ nbytes = dasm( pc ) * 2; /* disassemble and return size */ putstring(bfr2.buf); /* print hex pc and contents */ putstring(bfr1.buf); /* print symbolic " */ return( nbytes ); } /* * Function to display pc and contents as a single byte. Returns number * of bytes displayed (i.e. 1) */ static int dspbyte(pc) char *pc; { printadrs( pc ); /* type out pc value */ emt_putchar(' '); if( dtype == CHARTYPE) { emt_putchar('\''); if (getbpc(pc) == '\'') emt_putchar('\\'); nicechar( getbpc( pc ) ); emt_putchar('\''); } else printnum( (long) ( getbpc( pc ) & 0xFF ) ); return( 1 ); } /* * Function to deposit byte of data at pc. */ static int putbyte( pc, longdata) char *pc; long longdata; { putbpc(pc, longdata); return( 1 ); } /* Function to display pc and contents as a single word. Returns number of * bytes displayed (i.e. 2). */ static int dspword(pc) char *pc; { pc = wordadr( pc ); /* valid word address */ printadrs(pc); /* print pc in hex */ emt_putchar(' '); printnum( (long) ( getwpc(pc) & 0xFFFF ) ); /* print word contents */ return( 2 ); /* always display 2 bytes */ } /* * Function to deposit word of data at pc. */ static int putword( pc, longdata) char *pc; long longdata; { putwpc(pc, longdata); return( 2 ); } /* * Function to display pc and contents as a long. Returns number of bytes * displayed (i.e. 4) */ static int dsplong( pc ) char *pc; { pc = wordadr( pc ); /* legal word address */ printadrs( pc ); emt_putchar(' '); printnum( getlpc( pc ) ); return( 4 ); /* always display 4 bytes */ } /* * Function to deposit long at pc. */ static int putlong( pc, longdata) long *pc; long longdata; { putlpc(pc, longdata); return ( 4 ); } static nicechar(c) char c; { if (' ' <= c && c < 127) emt_putchar(c); else switch(c) { case '\b': putstring("\\b"); break; case '\t': putstring("\\t"); break; case '\r': putstring("\\r"); break; case '\n': putstring("\\n"); break; case '\\': putstring("\\\\"); break; case 127: putstring("^?"); break; default: if (0 <= c && c < ' ') { emt_putchar('^'); emt_putchar(c+64); } else { emt_putchar('\\'); emt_putchar('0'+((c>>6)&3)); emt_putchar('0'+((c>>3)&7)); emt_putchar('0'+(c&7)); break; } } } /* * display string pointed to by pc */ static int dspstrg( pc ) char *pc; { int c, len=0; printadrs( pc ); putstring(" \""); while ((c = getbpc(pc++)) > 0) { if (c == '"') emt_putchar('\\'); nicechar(c); len++; } emt_putchar('"'); return len+1; } /* * deposit string starting at pc */ static int putstrg(pc, s) char *pc, *s; { int len = 0; while (*s) { putbpc(pc++, *s++); len++; } putbpc(pc++, '\0'); return len; } #ifdef MC68000 /* Breakpoint routines. * * Breakpoint 0 is reserved for single stepping over subroutine calls. */ #define ALLBPLOOP(i, p) for( i = 0, p = &bp[0]; i <= BPMAX; i++, p++ ) #define USERBPLOOP( i, p) for( i = 1, p = &bp[1]; i <= BPMAX; i++, p++ ) /* Here to remove breakpoints, i.e. stick original instructions back * in the calling program. In addition, it returns the one-origin index * breakpoint id. */ static short rmovebps() { register struct bpstr *bpptr; register short i, bpno = -1; ALLBPLOOP( i, bpptr ) { if( bpptr->pc != NULL ) /* this breakpoint in use ? */ { if( *bpptr->pc == BPINST ) /* was it actually set ? */ { if( ddtopc == bpptr->pc ) /* find the breakpoint ? */ bpno = i; /* save breakpoint index */ *bpptr->pc = bpptr->oldinst;/* replace original instruction */ } } } return( bpno ); /* indicate which breakpoint it was */ } /* Here to plant breakpoints. Returns the number of breakpoints set. */ static short plantbps() { register struct bpstr *bpptr; register short i, nbp = 0; ALLBPLOOP( i, bpptr ) { if( bpptr->pc != NULL ) /* if breakpoint pc is non-zero, */ { nbp++; /* one more bp set. */ if( *bpptr->pc != BPINST ) /* forget this if already there */ { bpptr->oldinst = *bpptr->pc;/* save old instruction */ *bpptr->pc = BPINST; /* set breakpoint instruction */ } } } return( nbp ); } /* Here to clear breakpoints, just set breakpoint pc to 0. By this time * the original instructions should already be back in the calling program. */ static void clearbps() { register struct bpstr *bpptr; register short i; ALLBPLOOP( i, bpptr ) bpptr->pc = NULL; /* no longer in use */ } /* Set a breakpoint. */ static setabp( adrs, bpno ) register short *adrs; register char bpno; { register short i; register struct bpstr *bpptr, *fbp = NULL; USERBPLOOP( i, bpptr ) /* go through the breakpoint array, */ { /* removing any breakpoints already */ if( bpptr->pc == adrs ) bpptr->pc = NULL; /* set at this location, */ if( ( fbp == NULL ) && ( bpptr->pc == NULL ) ) /* and */ fbp = bpptr; /* remember likely candidates for */ } /* new breakpoint. */ if( bpno ) /* if user supplied specific bp no. */ fbp = &bp[bpno]; /* use it. */ if( fbp == NULL ) /* do we know where to put this bp ?*/ putstring( "no bp\n" ); /* complain if not...*/ else fbp->pc = adrs; } /* Clear a breakpoint. */ static clearabp( bpno ) register char bpno; { if( bpno ) /* specific bp to clear ? */ bp[bpno].pc = NULL; else clearbps(); /* remove all breakpoints */ } /* Print breakpoints. */ static printbps() { register struct bpstr *bpptr; register short i; char *bppos = "B0 @ "; emt_putchar('\n'); USERBPLOOP( i, bpptr ) { if( bpptr->pc ) { bppos[1] = i + '0'; putstring(bppos); printadrs( bpptr->pc ); emt_putchar('\n'); } } } /* Print out stack, upto depth abs(depth). * If depth > 0, also print arguments to procedure. */ static printstack(depth) int depth; { register int dep = (depth > 0 ? depth : depth < 0 ? -depth : 9999), i, jumpfrom, *fp = ddtsvregs[14]; short inst; while (dep--) { putstring("At about "); jumpfrom = fp[1]; numparams = 0; inst = *(short *)jumpfrom; if ((inst & 0xF1FF) == 0x508F) /* addql #n,sp */ {numparams = (inst&0x0E00) >> 8; if (!numparams) numparams = 8;} else if (inst == 0xDEFC) /* addaw #n,sp */ numparams = ((word *)jumpfrom)[1]; else if (inst == 0xDFFC) /* addal #n,sp */ numparams = ((int *)jumpfrom)[1]; if (numparams & 3) numparams = 0 else numparams >>= 2; jumpfrom -= 2; if ((*(short *)jumpfrom & 0xFF00) = 0x6100) jumpfrom = jumpfrom + (signed char)(*(short *)jumpfrom & 0xFF); /* ... */ printadrs (jumpfrom); putstring(" call of "); /* printadrs (...); */ if (depth >= 0) { /* print parameters to call */ i = 1; putstring(" ("); while (i < numparam) {numout (fp[(i++)+1]); emt_putchar(',');} if (numparam > 0) numout(fp[i+1]); emt_putchar (")"); } emt_putchar ('\n'); if (*fp && *fp < fp) fp = *fp else return; } } #endif MC68000 /* Major command loop. Process commands until we get a "go" or "continue". */ static comloop() { char c, go = 0, lopen = 0; short nbytes, inc; char *adrs; long temp; long test, searchvalue; char searchmode; emt_putchar('\n'); if ((ssflag && sscount>0 && (!cbptr || cbptr->count>0)) || (!ssflag && cbptr && cbptr->count>0)) return; ssflag = 0; /* out of single step mode */ while (!go) { if( !lopen ) putstring("."); compfx = 0; /* no command prefix */ c = getcom(); /* get argument and command */ if( !oneof( c, COMCHRS ) ) /* if this isn't a command, */ { compfx = c; /* assume it's a prefix and */ c = emt_getchar(); /* get another character. */ } switch(c) /* dispatch on delimiter */ { badcom: default: case BADARG: putstring("?"); break; case '/': case '\\': if( lopen ) { if( gotarg ) nbytes = deposit( dtype, dot, comarg ); dot = ( c == '/' ) ? inc_pc( dot, nbytes ) : dec_pc( dot, nbytes ); } else { if( gotarg ) dot = (char *) comarg; } settomode( dot ); if (dtype == STRTYPE) while (!getbpc(dot)) dot++; emt_putchar('\n'); nbytes = display( dtype, dot ); emt_putchar(' '); lopen = 1; /* location is open */ break; case '\r': case '\n': if( lopen ) { if( gotarg ) deposit( dtype, dot, comarg ); lopen = 0; } tmptomode = 0; /* clear default type-out */ break; case 'm': if( gotarg ) mask = comarg; break; case '<': if( gotarg ) lowlimit = (char *) comarg; c = getarg(); /* get next argument */ if( c == '>' ) { /* no break */ case '>': if( gotarg ) hilimit = (char *) comarg; c = getarg(); /* get next argument */ } if( c != '?' ) goto badcom; /* no break */ case '?': if( gotarg ) searchvalue = comarg; settomode( dot ); searchmode = smask? STRTYPE: dtype; tmask = smask? smask: mask; inc = ( searchmode == CHARTYPE || searchmode == BYTETYPE || searchmode == STRTYPE)? 1: 2; for( adrs = lowlimit; adrs < hilimit; adrs += inc) { test = getsearchval( searchmode, adrs); if( ( test & tmask ) == ( searchvalue & tmask ) ) { emt_putchar('\n'); display( searchmode, adrs ); } } break; #ifdef MC68000 case 'g': if( setpc( &ddtopc) ) /* valid pc ? */ go = 1; else goto badcom; break; case 'p': if( cbptr) /* inside a break point ? */ cbptr->count = gotarg? (short) comarg : 1; go = 1; break; case 's': /* Print call stack. Per Bothner June 82 */ printstack (gotarg ? comarg : 0); break; case 'x': sscount = 1; if (gotarg) sscount = comarg; ssflag = escno; /* do single step */ go = 1; break; case 'b': if( gotarg ) /* get any argument ? */ { /* if we got a prefix, this is a specific breakpoint specification */ if( compfx ) { compfx -= '0'; if( compfx <= 0 || compfx > BPMAX ) goto badcom; } if( comarg ) /* non-zero ? */ { if( !setpc( &comarg ) ) /* legal pc address */ goto badcom; setabp( comarg, compfx ); if ( comarg == (long)ddtopc ) bpno = 1; /* > 0 */ } else { clearabp( compfx ); if ( !compfx || compfx == bpno) bpno = -1; } } else printbps(); break; #endif MC68000 case 'r': temp = setradix( comarg ); if( compfx == 'i' ) iradix = temp; else if( compfx == 'o' ) oradix = temp; else goto badcom; break; case '=': printnum( comarg ); break; case 't': if( escno > 1 ) { tomode = gettomode( compfx ); tmptomode = 0; } else tmptomode = gettomode( compfx ); break; case '': break; #ifndef MC68000 case 'q': ddtopc = quitpc; /* reset pc */ ddtosr = quitsr; /* status register */ ddtsvregs[15] = quitsp; /* and stack */ go = 1; break; #endif } if (!lopen) emt_putchar('\n'); } } #ifdef MC68000 /* Here on a trace trap. */ ddttrace() { if( ssflag == 1 ) /* are we single stepping */ { /* everything ? */ ddtbrk(); } else /* this is breakpoint cleanup */ plantbps(); /* or subroutine single step */ } #endif MC68000 /* * Onceonly code to be executed on initial startup. */ char ddtfirst = 1; #ifdef MC68000 extern struct {short skip; struct sym *symstart;} _start; /* crtsun structure*/ #endif /* Initialize slength member of symbol table entry */ static setlen(sp) struct sym *sp; { return ( sp->slength = strlen(sp+1) ); } static void onceonly(x) { register struct sym *sp; if( ddtfirst ) { ddtfirst = 0; ddtsymdef.start = (struct sym *)ddtsyms; for( sp = (struct sym *)ddtsyms; *(char*)(sp+1) != '\0'; sp = (struct sym *)((int)(sp+1) + setlen(sp) + ADJ)); ddtsymdef.limit = sp; if (!(USRSYMS->start)) { USRSYMS->start = _start.symstart; USRSYMS->limit = (struct sym *)((int)(_start.symstart) + ((int*)(_start.symstart))[-1] - 18); } for (sp = USRSYMS->start; sp < USRSYMS->limit; sp = (struct sym *)((int)(sp+1) + setlen(sp) + ADJ)) switch (sp->stype & 7) { case TEXT: sp->stype = INSTTYPE; break; case BSS: case DATA: sp->stype = LONGTYPE; break; default: sp->stype = 0; break; } /* memorize initial entry conditions */ quitpc = ddtopc; /* save original pc */ quitsr = ddtosr; /* save status reg */ quitsp = ddtsvregs[15]; /* save stack */ #ifdef MC68000 BPTADR = ddtbpt; /* set trap vector */ TRCADR = ddttrct; /* set trace vector */ #endif } } /* Here from the breakpoint trap instruction. Figure out which breakpoint it is and print the appropriate message. */ ddtbrk() { char *bpstring = "B0> "; onceonly(); /* do once only code */ #ifdef MC68000 ddtosr &= 0x7fff; /* clear trace bit in sr */ bpno = rmovebps(); /* remove breakpoints */ if( bpno == SSBP ) /* if this was the subroutine ss, */ bp[SSBP].pc = NULL; /* its gone now. */ bpstring[1] = bpno + '0'; /* indicate which bp or ss */ putstring(bpstring); /* output breakpoint header */ while (!dasm(ddtopc)) ddtopc--; /* back up to legal instruction */ putstring(bfr2.buf); /* and display it */ putstring(bfr1.buf); if (ssflag) sscount--; /* count down single step */ if( bpno > SSBP ) { /* if breakpoint, */ cbptr = &bp[bpno]; /* remember appropriate pointer */ cbptr->count--; /* count down the breakpoint counter */ } else cbptr = NULL; dot = (char *) ddtopc; /* dot defaults to here */ #endif MC68000 comloop(); /* process commands */ /* we are about to return to the calling program. set breakpoints or * turn on tracing. */ #ifdef MC68000 if(ssflag) { if (escno > 1 ) /* should we worry about subroutines? */ if( ( ( *ddtopc & 0xFF00 ) == BSRINST ) || ( ( *ddtopc & 0xFFC0 ) == JSRINST ) || ( ( *ddtopc & 0xFFF0 ) == TRAPINST ) ) { bp[SSBP].pc = ddtopc + dasm( ddtopc );/* set bp at return */ ssflag = escno; } else ssflag = 1; /* same as ordinary single step */ } if( ssflag || bpno > 0 ) /* if single-stepping, */ { /* or it's time for bp cleanup, */ ddtosr |= 0x8000; /* turn on the trace bit */ } else /* otherwise, */ { plantbps(); /* plant breakpoints */ } #endif MC68000 } #ifndef MC68000 #include <signal.h> #include <sgtty.h> #define R 0 /* read-only mode */ #define RW 2 /* open for read/write */ #define FBLK 512 /* 512 byte reads */ #define MAXSYMLEN 10 /* must agree with ddt and dl68 */ struct sgttyb ttystate, *ttystatep = &ttystate; short oflags; /* place to remember the original tty flags */ int cleanup(); int (*cleanupptr)() = cleanup; /* pointer to cleanup function */ struct bhdr filhdr; unsigned char fbfr[FBLK] = { 0 }; int ifile; unsigned char *bfrendpc, *bfrbegpc; char bfrchnge; unsigned char *origin = (unsigned char *)0x1000; extern int open(); extern int read(); /* fetch a buffer that contains the byte pointed to by pc */ int getbfr( pc ) unsigned char *pc; { int nchars; long fpc; if (pc < origin) { putstring("pc too small"); return -1; } fpc = pc - origin + sizeof(filhdr); lseek( ifile, fpc, 0); /* position the file */ bfrendpc = bfrbegpc = pc; nchars = read( ifile, fbfr, FBLK); if( nchars > 0 ) bfrendpc += nchars; else { putstring("pc too large"); return -1; } return( nchars ); } /* see if location desired is in the buffer */ int inbfr( pc ) unsigned char *pc; { if( bfrbegpc <= pc && pc <= bfrendpc ) return(1); else return(0); } /* fetch the byte at pc */ getbpc(pc) unsigned char *pc; { if( das == 'd' ) /* fetch from ddt's address space ? */ { return( (int)*pc ); } if( !inbfr( pc ) ) if (getbfr( pc ) == -1) return -1; return( (int)fbfr[pc - bfrbegpc] ); } /* * Write the byte at pc. */ void putbpc(pc, data ) unsigned char data; unsigned char *pc; { if( das == 'd' ) { *pc = data; } else { if( !inbfr( pc ) ) getbfr( pc ); fbfr[pc - bfrbegpc] = data; bfrchnge = 1; } } /* fetch the word at pc */ short getwpc(pc) char *pc; { short word; if( das == 'd' ) /* fetch from ddt's address space ? */ { word = *(short *) pc; } else { word = getbpc(pc) << 8; /* get byte */ word |= getbpc(pc+1) & 0xFF; } return( word ); } /* * Write the word at pc */ void putwpc( pc, data ) char *pc; short data; { if( das == 'd' ) { *(short *)pc = data; } else { putbpc( pc, (char) ( data >> 8 ) ); putbpc( pc + 1, (char) ( data & 0xFF ) ); } } /* fetch a long at pc */ long getlpc(pc) char *pc; { long lword; if( das == 'd' ) { lword = *(long *)pc; } else { lword = getwpc(pc) << 16; lword |= getwpc(pc+2) & 0xFFFF; } return( lword ); } /* * Write the long at pc. */ void putlpc( pc, data ) char *pc; long data; { if( das == 'd' ) { *(long *)pc = data; } else { putwpc( pc, (short) ( data >> 16 ) ); putwpc( pc + 2, (short) ( data &0xFFFF ) ); } } reverse(lwrd) unsigned lwrd; {return((lwrd>>24) | (lwrd>>8 & 0xff00) | (lwrd<<8 & 0xff0000)| (lwrd<<24) ); } readsyms(filename) char *filename; { FILE *sfile; struct sym s; int symno, chrno; char c; struct sym *sp; if( ( sfile = fopen(filename, "r", sfile)) == NULL ) { fprintf( stderr, "Can't open symbol file %s\n", filename); exit(2); } fseek(sfile, SYMPOS, 0); sp = ddtusrsyms.start = (struct sym *) malloc(filhdr.ssize); ddtusrsyms.limit = (struct sym *)((int)sp + filhdr.ssize); fread(sp,filhdr.ssize,1,sfile); /* Get symbol table */ fclose( sfile ); /* close the symbol file */ } /* * reset the tty state to what it was originally. */ void resettty() { ttystate.sg_flags = oflags; /* restore original flags */ stty( 0, ttystatep); /* restore original tty state */ } /* Here on a signal interrupt. reset the tty state and exit */ int cleanup(signo) int signo; { resettty(); exit(4); } main(argc, argv) int argc; char *argv[]; { int nchrs; if( argc != 2 ) { fprintf( stderr, "usage: %s filename\n", argv[0]); cleanup(); } if( ( ifile = open(argv[1], R ) ) == -1 ) { fprintf( stderr, "Can't open %s\n", argv[1]); cleanup(); } nchrs = read( ifile, &filhdr, sizeof(filhdr)); if( nchrs <= 0 ) { fprintf( stderr, "Unexpected eof or error on %s\n", argv[1]); cleanup(); } if( filhdr.fmagic != FMAGIC ) { fprintf( stderr, "%s doesn't look like a .out file \n", argv[1] ); cleanup(); } printf("text size: %ld\n", filhdr.tsize); printf("data size: %ld\n", filhdr.dsize); printf("bss size: %ld\n", filhdr.bsize); printf("symbol table size: %ld\n", filhdr.ssize); printf("text relocation size: %ld\n", filhdr.rtsize); printf("data relocation size: %ld\n", filhdr.rdsize); printf("entry point: 0x%lx\n", filhdr.entry); origin = (unsigned char *)filhdr.entry; if(filhdr.ssize > 0 ) readsyms(argv[1]); else ddtusrsyms.start = ddtusrsyms.limit = 0; /* now prepare for cbreak'ing */ if( isatty(0) ) /* if we are connected to a tty */ { int sig; gtty( 0, ttystatep); /* get current tty state */ oflags = ttystate.sg_flags; /* save old flags */ for( sig = 1; sig <= NSIG; sig++) signal(sig, cleanup); /* arrange to clean-up before exit */ ttystate.sg_flags |= CBREAK; /* turn on CBREAK */ stty( 0, ttystatep); } ddt(); resettty(); putstring( "\n" ); } #endif d is in the buffer */ int inbfr( pc ) unsigned char *pc; { if( bfrbegpc <= pc && pc <= bfrendpc ) return(1); else return(0); } /* fetch the byte at pc */ getbpc(pc) unsigned char *sumacc/cc/ddt68/ddt.h 444 0 12 4072 3470501555 7552 /* ddt.h */ #include "b.out.h" #define LITSYMS /* this must agree with dl68 */ #define BPMAX 8 /* number of breakpoints allowed */ #define BADARG '*' /* bad command */ #define ESCCHR '' /* argument delimiter */ #define BPINST 0x4E4E /* trap #14 instruction */ #define TRACEBIT 0x8000 /* trace bit in status register */ #define DEFRADIX 16 /* default radix */ #define MAXSYMLEN 10 /* maximum length of symbol */ /*** must agree with dl68 ***/ /* type-out structure for the disassembler */ struct cbuffr { char buf[40]; /* the output buffer */ int pnt; /* pointer into output buffer */ int col; /* output column # */ }; /* Type field definitions */ #define CHARTYPE 0x01 /* character type */ #define BYTETYPE 0x02 /* byte */ #define WORDTYPE 0x03 /* word */ #define LONGTYPE 0x04 /* long */ #define INSTTYPE 0x05 /* instruction */ #define STRTYPE 0x06 /* string */ #define TYPEFIELDMASK 0x07 /* mask for type field */ #define SIGNEDTYPE 0x08 /* basic signed type */ #define POINTERTYPE 0x10 /* pointer to something */ #define USERTYPE 0x20 /* user-defined type */ #define DDTSYM 0x80 /* symbol is an internal ddt symbol */ #define DEFTOMODE INSTTYPE /* * structure of a symbol table definition */ typedef struct Symtabdef { struct sym *start; struct sym *limit; } symtabdef; #ifdef DM #define USRSYMS (symtabdef *) 0x570 /* pointer to start of symbols */ #else extern symtabdef ddtusrsyms; #define USRSYMS (&ddtusrsyms) #endif DM #ifdef MC68000 #define ADJ 2 & -2 #define getbpc(pc) *(char *)(pc) #define putbpc(pc, byte) *(char *)(pc) = (char) (byte) #define getwpc(pc) *(short *) (pc) #define putwpc(pc, word) *(short *)(pc) = (short) (word) #define getlpc(pc) *(long *) (pc) #define putlpc(pc, llong) *(long *)(pc) = (long) (llong) #else ndef MC68000 #define ADJ 1 extern getbpc(); extern void putbpc(); extern short getwpc(); extern void putwpc(); extern long getlpc(); extern void putlpc(); #endif MC68000 /* breakpoint mechanism */ struct bpstr { short *pc; /* pc at breakpoint */ short oldinst; /* old instruction */ short count; /* proceed counter */ }; is must agree with dl68 */ #define BPMAX 8 /* number of breakpoints allowed */ #define BADARG '*' /* bad command */ #define ESCCHR '' /* argument delimiter */ #define BPINST 0x4E4E /* trap #14 instruction */ #define TRACEBIT 0x8000 /* trace bit in status register */ #define DEFRADIX 16 /* default radix */ #define MAXSYMLEN 10 /* maximum length of symbol */ /*** must agree with dl68 ***/ /* type-out structure for the disassembler */ struct csumacc/cc/ddt68/ddt68.1 444 0 12 13513 3470501555 7661 .TH DDT68 1 MC68000 .SU .SH NAME ddt68, fddt68 \- symbolic debugger for 68000 .SH SYNOPSIS .B fddt68 b.out .br .B cc68 ... -lddt (Sun) .SH DESCRIPTION .I fddt68 is a symbolic disassembler for b.out files created by the 68000 linker (ld68). Its main purpose is to allow testing of ddt logic in a more hospitable environment than the 68000. It also gives a way of inspecting the assembly language form of a program without having to produce a .s file. In addition it gives a check on the operation of as68 and ld68. It is called by typing: .sp fddt68 .I filename .sp on the Vax. .PP .I ddt68 is a symbolic debugger for the 68000. It is loaded at link edit time with the cc68 flag -lddt. On starting a program with ddt loaded the user will be at the ddt command level. Breakpoints may be set, and the program started, using the commands described below. .SH COMMANDS .I ddt68 recognizes the following commands (\fI$\fP is used for \fI<esc>\fP): .TP .IB expression / .TP .IB expression \e open the location at \fIexpression\fP and display the contents in the current typeout mode. The user may then optionally type an expression, whose value replaces the contents of the open location. Finally the location is \fIclosed\fP by typing one of \fIreturn\fP (to return to \fIddt\fP's main command loop), \fI/\fP (to open the next location), or \fI\\\fP (to open the previous location). .TP .IB expression $g go - plant any breakpoints set with the \fI$b\fP command, load the registers, and start execution at \fIexpression\fP. If \fIexpression\fP is unspecified or zero, execution resumes starting from the current value of \fI$pc\fP (normally the point where the program was last interrupted). .TP .IB expression $x execute the next \fIexpression\fP instructions, starting from the current value of \fI$pc\fP and printing out all executed instructions. If \fIexpression\fP is omitted, 1 is assumed. .TP .IB expression $$x same as above except execute subroutine calls and traps as single instructions, i.e. do not descend into the called subroutine. .TP .IB expression $p proceed - like \fIgo\fP with no argument, except that if we are presently at a breakpoint then \fIexpression\fP counts the number of times to pass this breakpoint before breaking. \fI1$p\fP is synonymous with \fI$g\fP. .TP .IB expression $ bno b set breakpoint \fIbno\fP (in the range 1-9) at \fIexpression\fP. If \fIbno\fP is omitted the first unused breakpoint number is assigned (the commonest usage). If \fIexpression\fP is 0 the named breakpoint is cleared, or if there is no named breakpoint (\fIbno\fP is omitted) all breakpoints are cleared. If \fIexpression\fP is omitted all breakpoints are printed, whether or not \fIbno\fP is present. .TP .BI $ rspec / .TP .BI $ rspec \e examine register \fIrspec\fP where \fIrspec\fP is one of: .RS .TP .B d0-d7 data registers 0-7 .TP .B a0-a7 address registers 0-7 .TP .B fp frame pointer (synonym for \fIa6\fP) .TP .B sp stack pointer (synonym for \fIa7\fP) .TP .B pc program counter .TP .B sr status register .RE .TP .IB expression $= type out \fIexpression\fP in current output radix. .TP .IB lowlimit < highlimit > pattern ? search for \fIpattern\fP in the range \fIlowlimit\fP (inclusive) to \fIhighlimit\fP (exclusive). The pattern is interpreted as an object of the type in force as the current typeout mode, with instructions and strings being treated as 2-byte words. Objects are assumed to be aligned on word (2-byte) boundaries except for 1-byte types and strings which are aligned on byte boundaries. A mask (set with the following command) determines how much of the pattern is significant in the search, except that if the pattern is a string constant a separate mask matched to the length of the string is used. The three arguments to the search command are sticky; thus if \fIlowlimit<\fP (resp. \fIhighlimit\fP>) is omitted, the most recent lowlimit (resp. highlimit) applies. While \fIpattern\fP may be omitted, the final ? may not be omitted. .TP .IB expression $m set the search mask to \fIexpression\fP. \fI-1$m\fP forces a complete match, \fIf$m\fP checks only the low order 4 bits, \fI0$m\fP will make the search pattern match anything. .TP .IB base $ir set input radix to \fIbase\fP. (Note \fI10$i\fP can never change the radix.) If \fIbase\fP is omitted hexadecimal is assumed. .TP .IB base $or set output radix to \fIbase\fP. If \fIbase\fP is omitted hexadecimal is assumed. .TP .BI $ type t temporarily set typeout mode to \fItype\fP where \fItype\fP is one of: .RS .TP .B <space> deduce type from type of nearest symbol .TP .B c type out bytes as ascii characters. .TP .B h type out bytes in current output radix. .TP .B w type out words in current radix. .TP .B l type out longs in current radix. .TP .B s type out strings in current radix. (In this mode new values cannot be entered.) .TP .B i type out as 68000 symbolic instructions. (In this mode only the first two bytes of the opened location may be changed; the new value is typed in as a numeric expression rather than as a symbolic instruction.) .RE The new typeout mode stays in effect until a \fIreturn\fP is typed. .TP .BI $$ type t permanently set typeout mode to \fItype\fP. .PP An \fIexpression\fP is composed of symbols, numeric constants, string constants, and the operators \fI+\fP, \fI-\fP, and \fI|\fP representing 2's complement addition, subtraction, and inclusive bitwise or. Symbols are delimited by operators or \fI<esc>\fP. A string constant has from 1 to 4 characters which are packed right justified into one long to form a numeric constant; thus "did"=646A64. String constants are particularly useful in conjunction witht the search command for searching for a string. The single character \fI.\fP (dot) as a symbol on its own represents the address of the currently open memory location. All operations are carried out using 32 bit arithmetic and evaluated strictly left to right. .SH AUTHORS Jim Lawson and Vaughan Pratt TP .B fp frame pointer (synonym for \fIa6\fP) .TP .B sp stack pointer (synonym for \fIa7\fP) .TP .B pc program counter .TP .B sr status register .RE .TP .IB expression $= type out \sumacc/cc/ddt68/ea68 444 0 12 460 3470501556 7272 ..........000ddd d ..........001aaa a ..........010aaa a@ ..........011aaa a@+ ..........100aaa a@- ..........101aaa,n a@(n) ..........110aaa,g a@(n,k) ..........111000,n n ..........111001,i i ..........111010,n pc@(n) ..........111011,g pc@(n,k) ..........111100,j #j ..........nnnnnn * treated as 2-byte words. Objects are assumed to be aligned on word (2-byte) boundaries except for 1-byte types and strings which are aligned on byte boundaries. A mask (set with the following command) detesumacc/cc/ddt68/ea68.c 444 0 12 560 3470501556 7514 7,0,0,56,0,4,129,32, 7,0,0,56,0,12,130,32, 8,0,0,56,0,20,130,64, 9,0,0,56,0,28,130,64,43,32, 9,0,0,56,0,36,130,64,45,32, 11,1,0,56,0,44,130,64,40,151,41,32, 13,8,0,56,0,52,130,64,40,167,44,144,41,32, 7,1,0,63,0,56,135,32, 7,2,0,63,0,57,135,32, 12,1,0,63,0,58,112,99,64,40,135,41, 14,8,0,63,0,59,112,99,64,40,151,44,128,41, 8,3,0,63,0,60,35,135, 7,0,0,0,0,32,42,32, 0 word (2-byte) boundaries except for 1-byte types and strings which are aligned on byte boundaries. A mask (set with the following command) detesumacc/cc/ddt68/fddt68.c 444 0 12 12246 3470501556 10114 #include "ddt.h" #include <stdio.h> #include <signal.h> #include <sgtty.h> #define R 0 /* read-only mode */ #define RW 2 /* open for read/write */ #define FBLK 512 /* 512 byte reads */ #define MAXSYMLEN 10 /* must agree with ddt and dl68 */ struct sgttyb ttystate, *ttystatep = &ttystate; short oflags; /* place to remember the original tty flags */ int cleanup(); int (*cleanupptr)() = cleanup; /* pointer to cleanup function */ extern char das; /* address space 'u' = user, 'd' = ddt */ struct bhdr filhdr; unsigned char fbfr[FBLK] = { 0 }; int ifile; unsigned char *bfrendpc, *bfrbegpc; char bfrchnge; unsigned char *origin = (unsigned char *)0x1000; extern int open(); extern int read(); /* fetch a buffer that contains the byte pointed to by pc */ int getbfr( pc ) unsigned char *pc; { int nchars; long fpc; if (pc < origin) { putstring("pc too small"); return -1; } fpc = pc - origin + sizeof(filhdr); lseek( ifile, fpc, 0); /* position the file */ bfrendpc = bfrbegpc = pc; nchars = read( ifile, fbfr, FBLK); if( nchars > 0 ) bfrendpc += nchars; else { putstring("pc too large"); return -1; } return( nchars ); } /* see if location desired is in the buffer */ int inbfr( pc ) unsigned char *pc; { if( bfrbegpc <= pc && pc <= bfrendpc ) return(1); else return(0); } /* fetch the byte at pc */ getbpc(pc) unsigned char *pc; { if( das == 'd' ) /* fetch from ddt's address space ? */ { return( (int)*pc ); } if( !inbfr( pc ) ) if (getbfr( pc ) == -1) return -1; return( (int)fbfr[pc - bfrbegpc] ); } /* * Write the byte at pc. */ void putbpc(pc, data ) unsigned char data; unsigned char *pc; { if( das == 'd' ) { *pc = data; } else { if( !inbfr( pc ) ) getbfr( pc ); fbfr[pc - bfrbegpc] = data; bfrchnge = 1; } } /* fetch the word at pc */ short getwpc(pc) char *pc; { short word; if( das == 'd' ) /* fetch from ddt's address space ? */ { word = *(short *) pc; } else { word = getbpc(pc) << 8; /* get byte */ word |= getbpc(pc+1) & 0xFF; } return( word ); } /* * Write the word at pc */ void putwpc( pc, data ) char *pc; short data; { if( das == 'd' ) { *(short *)pc = data; } else { putbpc( pc, (char) ( data >> 8 ) ); putbpc( pc + 1, (char) ( data & 0xFF ) ); } } /* fetch a long at pc */ long getlpc(pc) char *pc; { long lword; if( das == 'd' ) { lword = *(long *)pc; } else { lword = getwpc(pc) << 16; lword |= getwpc(pc+2) & 0xFFFF; } return( lword ); } /* * Write the long at pc. */ void putlpc( pc, data ) char *pc; long data; { if( das == 'd' ) { *(long *)pc = data; } else { putwpc( pc, (short) ( data >> 16 ) ); putwpc( pc + 2, (short) ( data &0xFFFF ) ); } } reverse(lwrd) unsigned lwrd; {return((lwrd>>24) | (lwrd>>8 & 0xff00) | (lwrd<<8 & 0xff0000)| (lwrd<<24) ); } readsyms(filename) char *filename; { FILE *sfile; struct sym s; int symno, chrno; char c; struct sym *sp; if( ( sfile = fopen(filename, "r", sfile)) == NULL ) { fprintf( stderr, "Can't open symbol file %s\n", filename); exit(2); } fseek(sfile, SYMPOS, 0); sp = usrsyms.start = (struct sym *) malloc(filhdr.ssize); usrsyms.limit = (struct sym *)((int)sp + filhdr.ssize); fread(sp,filhdr.ssize,1,sfile); /* Get symbol table */ fclose( sfile ); /* close the symbol file */ } /* * reset the tty state to what it was originally. */ void resettty() { ttystate.sg_flags = oflags; /* restore original flags */ stty( 0, ttystatep); /* restore original tty state */ } /* Here on a signal interrupt. reset the tty state and exit */ int cleanup(signo) int signo; { resettty(); exit(4); } main(argc, argv) int argc; char *argv[]; { int nchrs; if( argc != 2 ) { fprintf( stderr, "usage: %s filename\n", argv[0]); cleanup(); } if( ( ifile = open(argv[1], R ) ) == -1 ) { fprintf( stderr, "Can't open %s\n", argv[1]); cleanup(); } nchrs = read( ifile, &filhdr, sizeof(filhdr)); if( nchrs <= 0 ) { fprintf( stderr, "Unexpected eof or error on %s\n", argv[1]); cleanup(); } if( filhdr.fmagic != FMAGIC ) { fprintf( stderr, "%s doesn't look like a .out file \n", argv[1] ); cleanup(); } printf("text size: %ld\n", filhdr.tsize); printf("data size: %ld\n", filhdr.dsize); printf("bss size: %ld\n", filhdr.bsize); printf("symbol table size: %ld\n", filhdr.ssize); printf("text relocation size: %ld\n", filhdr.rtsize); printf("data relocation size: %ld\n", filhdr.rdsize); printf("entry point: 0x%lx\n", filhdr.entry); origin = (unsigned char *)filhdr.entry; if(filhdr.ssize > 0 ) readsyms(argv[1]); else usrsyms.start = usrsyms.limit = 0; /* now prepare for cbreak'ing */ if( isatty(0) ) /* if we are connected to a tty */ { int sig; gtty( 0, ttystatep); /* get current tty state */ oflags = ttystate.sg_flags; /* save old flags */ for( sig = 1; sig <= NSIG; sig++) signal(sig, cleanup); /* arrange to clean-up before exit */ ttystate.sg_flags |= CBREAK; /* turn on CBREAK */ stty( 0, ttystatep); } ddt(); resettty(); putstring( "\n" ); } urrently open memory location. All operations are carried out using 32 bit arithmetic and evaluated strictly left to right. .SH AUTHORS Jim Lawson and Vaughan Pratt TP .B fp frame pointer (synonym for \fIa6\fP) .TP .B sp stack pointer (synonym for \fIa7\fP) .TP .B pc program counter .TP .B sr status register .RE .TP .IB expression $= type out \sumacc/cc/ddt68/ins.f 444 0 12 13044 3470501556 7606 Format of the file ins68 V.R. Pratt Jan., 1981 The file ins68 contains a compacted list of all the instructions of the 68000, together with the assembler form of each instruction. It also contains the format of the effective address field. Instruction List Format The format of the instruction list is as follows. Each entry is terminated with \n. An entry consists of a bit form and an assembler form; the two forms are separated by at least one tab. The bit form is a list of words separated by commas. Each word is either one character or 16 characters. A one character word such as n is considered merely an abbreviation for the 16-character word nnnnnnnnnnnnnnnn. Here is a simple entry. 0100111001110110 trapv This says that the instruction with hex opcode 4E76 has the assembler form trapv. Not all instructions consist merely of 0's and 1's; consider 0100100001000ddd swap d This says that the instruction 4840 is swap d0, 4841 is swap d1, etc., up to 4847. The block of d's in the word defines a field. The interpretation of the field depends on the letter used for the field. The following letters have special interpretations. d data register a address register e effective address s size: 0 = w, 1 = l, 00 = b, 01 = w, 10 = l, 11 = * (illegal) n signed short integer, decimal in assembler form b like n, but bivalent: length agrees with most recent value of s x unsigned short integer, hex in assembler form y like x but bit-reversed in assembler form m m = 1 -> reverse arguments in assembler form f function defined locally (as in f(div,mul) meaning 0 = div, 1 = mul) c condition code (for branch, decrement-and-branch, and conditional set) r relative program point; an address to be printed symbolically if possible, otherwise in hex if pc is known, otherwise in hex but relative to the pc When two separate fields require the same letter, the two fields are distinguished by case, e.g. d versus D. The field E is treated specially; its register and mode fields are interchanged relative to e, for which a handy informal mnemonic is E = RRRMMM, e = mmmrrr. The bits within the register and mode fields are not themselves reversed in either case. Here are further examples. 00ffEEEEEEeeeeee mov.f(,b,l,w) e,E This is the move instruction. Since the size field is nonstandard we define it locally as 01 = b, 10 = l, 11 = w. There are two effective addresses, e and E, respectively source and destination. The . is a delimiter that is removed, thus 0010111000000011 becomes movl d3,d7. Here are the instructions to logically combine n with either the condition code register (a byte operation) or the status register (a word operation). 0000fff00F111100,n f(or,and,*,*,*,eor,*,*) #n,F(ccr,sr) For example 0000101000111100,0000000000100101 would be eor #37,ccr. (Remember that n is merely an abbreviation for nnnnnnnnnnnnnnnn.) There are two locally defined functions, hence f and F. When * appears in the assembler form this denotes an illegal instruction. It is permissible for a bit pattern to match more than one form. For example 0100000011000000 matches both of the following two patterns; the intended match is always the earlier in such a case. 0100000011eeeeee move sr,e 01000000sseeeeee negx.s e The one place where bit-reversal is used is in 01001m001seeeeee,y movem.s y,e This prints the bits of y to correspond to the register sequence d0 d1 ... d7 a0 a1 ... a7. All movem's print in this order, regardless of the order actually used in saving and restoring registers. It is almost never needed to know the physical order of saving, only the set saved. (Incidentally note the one-bit s; 0 = w, 1 = l.) The following illustrates condition codes and relative program points. 0101cccc11001ddd,r db.c d,r Thus 0101011111001101,1111111111110010 would be dbeq d5,.-14. assuming no symbol was available for this address. Here is an example of the signed integer n appearing as a field in the move-quick instruction. 0111ddd0nnnnnnnn moveq #n,d Here is an example of the use of b (both word and long constant possible). 0000fff0sseeeeee,b f(or,and,sub,add,,eor,cmp,).s #b,e Both 0000000000000000,0000000000000000 and 0000000001000000,0000000000000000 match this pattern; 0000000010000000,0000000000000000,0000000000000000 also matches because s = 10 = l. Effective Address Format In addition to the instructions, the file ins68 gives the format of the effective address, using the same conventions. The following examples should be self-explanatory. 000ddd d 001aaa a 101aaa,n a@(n) 110aaa,00000dddnnnnnnnn a@(n,d) (note how the second word cannot be abbrev'd.) 110aaa,00001aaannnnnnnn a@(n,a) (note how d and a are dealt with in the ext'n) 11100s,b b (here s is used only to control the size of b) 111100,b #b (the size of b depends on s defined outside e) Note the ambiguity resulting from both the instruction proper and the effective address wanting arguments. The rule is that arguments for the instruction proper come first in the instruction being matched to a pattern. Caveat Any word list no initial segment of which matches a pattern in the instruction list does not start out with a legal instruction. The converse is not true; some illegal instructions match some pattern. Most of these have assembler forms containing an asterisk, but in the present table there exist exceptions. We would be grateful if someone would make the necessary additions to the table to eliminate those exceptions; this is done by putting the exceptions in the table ahead of the patterns they match and supplying them with an assembler form of *. defined locally (as in f(div,mul) meaning 0 = div, 1 = mul) c condition code (for branch, decrement-and-branch, and conditional set) r relative program point; an address to be printed symbolically if possible, otherwise in hex if pc is known, otherwise in hex but relative to the pc When two separate fields require the same letter, the two fields are distinguished by case, e.g. d versus D. The field E is treated specially; its register and mode fields are interchangsumacc/cc/ddt68/inscom.c 444 0 12 7473 3470501556 10273 /* Compiler for ins68 * V.R. Pratt * Jan., 1981 */ #include <stdio.h> #define TABSIZ 128 #define WORDSIZ 16 int line=0, argno, mask, pattern, i, pnt, comma, postc, space; char modif, length, string[64], prev=0, current=0, next=0, sizmod, revargs, more = 1, table[TABSIZ]; /* Translation tables */ char *mcod = "nijuxyrglpt"; /* modifiers */ char *trm = "01D77703456"; /* modifier formats */ char *pcod = "dDaAeEsnuvmfFcrijxyrk"; /* permissible parameters */ char *pfmt = "ddaaeEsnuvmffcrnnxyrk"; /* parameter formats */ char *fcod = "kdaEesvnuyxmfcr"; /* case order for formats */ main() {get(); get(); while (more) {i=TABSIZ; while (i) table[--i] = -1; while (more && current != '\n') get(); /* skip to end of line */ while (more && next == '\n') get(); /* skip nl's */ if (next == EOF) break; line++; modif = argno = sizmod = revargs = mask = pattern = 0; for (i=WORDSIZ;i--;) /* process 16-bit word */ {mask <<= 1; pattern <<= 1; if ((get()&-2) == '0') {mask++; pattern += current&1;} else if (table[current] < 0) /* new argument */ {if (current != '.') /* . is dummy arg */ {table[current] = argno++; pattern++; /* leading 1 delimits field */ if (current == 'm') revargs = 1; if (current == 's') sizmod = 1; } } else if (current == prev) {if (current == 's') sizmod = 0;} else fprintf(stderr,"Repeat arg on line %d\n",line); } for (i=TABSIZ;i--;) if (table[i]>=0) table[i] = argno-table[i]-1; if (get() == ',') while (more && get() != '\t') {i = pos(current,mcod); modif |= trm[i]=='D'? 3: 1<<(trm[i]-'0'); if (current == 'g') /* g is 0000kkkknnnnnnnn */ {table['k'] = argno++; /* d/a index register */ table['n'] = argno++; /* 8-bit signed displacement */ } else if (i<8) /* nijuxyrg denote an arg */ table[current] = argno++; } if (sizmod) modif |= 64; while (next == '\t') get(); /* skip tabs */ pnt = 0; /* initialize output buffer */ while (more && get() != '\n') compchar();/* compile string */ if (revargs) {string[pnt++] = (char)(0213|(table['m']<<4)); string[space] = postc+1-space; string[comma] = pnt+1-comma; string[postc] = space+1-postc; string[pnt] = comma+1-pnt; pnt++; } length = 6+pnt; pnt = 0; out(length); out(modif); out(mask>>8); out(mask&255); out(pattern>>8); out(pattern&255); while (pnt<length-6) out(string[pnt++]); if (length&1) out(' '); putchar('\n'); } printf("0 \n"); } char norm(x) char x; {return('A' <= x && x <= 'Z'? x+32: x);} compchar() {if (current < 'A' || prev > '@' || next > '@' || table[current] < 0) {if (current != '.') /* . is dummy */ {string[pnt++] = current; if (revargs) {if (current == ',') {string[pnt++] = 0213|(table['m']<<4); postc = pnt++; } if (current == ' ') {string[pnt++] = 0213|(table['m']<<4); space = pnt++; } } } } else {string[pnt++] = 0200| /* identifying bit */ (table[current] << 4)| /* arg no */ pos(pfmt[pos(current,pcod)],fcod);/* format */ if (norm(current) == 'f') {get(); /* erase ( */ do {string[pnt++] = get();} while (current != ')'); /* skip commas */ } } if (revargs && next == ',') {string[pnt++] = 0213|(table['m']<<4); comma = pnt++; } } get() {prev = current; current = next; if (next != EOF) next = getchar(); if (current == EOF) more = 0; return (current);} pos(c,s) char c, *s; {int i=0; while (s[i] && s[i] != c) i++; if (s[i]) return(i); else fprintf(stderr, "Unexpected char %o on line %d in %c%c%c\n",c,line,prev,current,next); } out(c) unsigned char c; {printf("%d,",c);} +; /* 8-bit signed displacement */ } else if (i<8) /* nijuxyrg denote an arg */ table[current] = argno++; } if (sizmod) modif |= 64; while (next == '\t') get(); /* skip sumacc/cc/ddt68/ops68 444 0 12 3424 3470501556 7531 0000fff00F111100,x f(or,and,*,*,*,eor,*,*) #/x,F(ccr,sr) 00001000ffeeeeee,u f(btst,bchg,bclr,bset) #u,e 0000fff010eeeeee,i f(or,and,sub,add,,eor,cmp,)l #i,e 0000fff0sseeeeee,n f(or,and,sub,add,,eor,cmp,).s #n,e 0000ddd1ms001aaa,n movep.s a@(n),d 0000ddd1ffeeeeee f(btst,bchg,bclr,bset) d,e 0010EEEEEEeeeeee,l movl e,E 00ffEEEEEEeeeeee mov.f(,b,,w) e,E 0100000011eeeeee move sr,e 01000000sseeeeee negx.s e 01000010sseeeeee clr.s e 01000100sseeeeee neg.s e 0100010011eeeeee move e,ccr 0100011011eeeeee move e,sr 01000110sseeeeee not.s e 0100100000eeeeee nbcd e 0100100001000ddd swap d 0100100001eeeeee,p pea e 010010001s000ddd ext.s d 010010001s100aaa,x movem.s /x,a@- 01001m001seeeeee,y movem.s /y,e 0100101011eeeeee tas e 01001010sseeeeee tst.s e 010011100100uuuu trap #u 0100111001010aaa,n link a,#n 0100111001011aaa unlk a 010011100110maaa move a,usp 0100111001110010,x stop #/x 0100111001110fff f(reset,nop,,rte,*,rts,trapv,rtr) 010011101feeeeee,p f(jsr,jmp) e 0100ddd110eeeeee chk e,d 0100aaa111eeeeee,p lea e,a 0101cccc11001ddd,r db.c d,r 0101cccc11eeeeee s.c e 0101vvvfsseeeeee f(addq,subq).s #v,e 0110cccc00000000,r b.c r 0110ccccrrrrrrrr b.c r 0111ddd0nnnnnnnn moveq #n,d 1f00DDD100000ddd f(sbcd,abcd) d,D 1f00AAA100001aaa f(sbcd,abcd) a@-,A@- 1f00dddF11eeeeee f(div,mul).F(u,s) e,d 1f00dddmsseeeeee f(or,and).s e,d 1f01aaas11eeeeee f(sub,add).s e,a 1f01DDD1ss000ddd f(subx,addx).s d,D 1f01AAA1ss001aaa f(subx,addx).s a@-,A@- 1f01dddmsseeeeee f(sub,add).s e,d 1011aaas11eeeeee cmp.s e,a 1011ddd0sseeeeee cmp.s e,d 1011AAA1ss001aaa cmp.s a@+,A@+ 1011ddd1sseeeeee eor.s d,e 1100DDD101000ddd exg d,D 1100AAA101001aaa exg a,A 1100ddd110001aaa exg a,d 11100ffF11eeeeee f(as,ls,rox,ro).F(r,l)w e 1110vvvFss0ffddd f(as,ls,rox,ro).F(r,l).s #v,d 1110DDDFss1ffddd f(as,ls,rox,ro).F(r,l).s D,d nnnnnnnnnnnnnnnn * bclr,bset) d,e 0010EEEEEEeeeeee,l movl e,E 00ffEEEEEEeeeeee mov.f(,b,,w) e,E 0100000011eeeeee move sr,e 01000000sseeeeee negx.s e 01000010sseeeeee clr.s e 01000100sseeeeee neg.s e 0100010011eeeeee move e,ccr 0100011011eeeeee move e,sr 0sumacc/cc/ddt68/ops68.c 444 0 12 7467 3470501557 7766 41,128,241,191,8,124,156,111,114,44,97,110,100,44,42,44,42,44,42,44,101,111,114,44,42,44,42,41,32,35,47,170,44,140,99,99,114,44,115,114,41,32, 32,128,255,0,8,160,156,98,116,115,116,44,98,99,104,103,44,98,99,108,114,44,98,115,101,116,41,32,35,168,44,132, 38,2,241,192,8,160,156,111,114,44,97,110,100,44,115,117,98,44,97,100,100,44,44,101,111,114,44,99,109,112,44,41,108,32,35,167,44,132, 38,1,241,0,8,160,172,111,114,44,97,110,100,44,115,117,98,44,97,100,100,44,44,101,111,114,44,99,109,112,44,41,149,32,35,183,44,132, 28,65,241,56,9,204,109,111,118,101,112,149,32,171,11,130,64,40,199,41,171,7,44,171,247,177,171,251, 31,0,241,0,9,160,156,98,116,115,116,44,98,99,104,103,44,98,99,108,114,44,98,115,101,116,41,32,161,44,132,32, 14,16,240,0,40,32,109,111,118,108,32,132,44,147, 20,0,192,0,40,32,109,111,118,172,44,98,44,44,119,41,32,132,44,147, 15,0,255,192,64,224,109,111,118,101,32,115,114,44,132,32, 13,0,255,0,64,160,110,101,103,120,149,32,132,32, 12,0,255,0,66,160,99,108,114,149,32,132, 12,0,255,0,68,160,110,101,103,149,32,132, 16,0,255,192,68,224,109,111,118,101,32,132,44,99,99,114, 15,0,255,192,70,224,109,111,118,101,32,132,44,115,114,32, 12,0,255,0,70,160,110,111,116,149,32,132, 12,0,255,192,72,32,110,98,99,100,32,132, 12,0,255,248,72,68,115,119,97,112,32,129, 11,32,255,192,72,96,112,101,97,32,132,32, 12,64,255,184,72,196,101,120,116,149,32,129, 19,192,255,184,72,228,109,111,118,101,109,149,32,47,170,44,130,64,45,32, 25,192,251,128,76,224,109,111,118,101,109,149,32,171,8,47,185,171,7,44,171,250,132,171,251,32, 11,0,255,192,74,224,116,97,115,32,132,32, 12,0,255,0,74,160,116,115,116,149,32,132, 13,0,255,240,78,72,116,114,97,112,32,35,136,32, 15,1,255,248,78,84,108,105,110,107,32,130,44,35,151,32, 12,0,255,248,78,92,117,110,108,107,32,130, 24,0,255,240,78,108,109,111,118,101,32,155,7,130,155,9,44,155,251,117,115,112,155,249, 14,128,255,255,78,114,115,116,111,112,32,35,47,138, 38,0,255,248,78,116,140,114,101,115,101,116,44,110,111,112,44,44,114,116,101,44,42,44,114,116,115,44,116,114,97,112,118,44,114,116,114,41, 17,32,255,128,78,224,156,106,115,114,44,106,109,112,41,32,132,32, 13,0,241,192,73,160,99,104,107,32,132,44,145,32, 13,32,241,192,73,224,108,101,97,32,132,44,146,32, 13,1,240,248,88,204,100,98,157,32,129,44,174,32, 10,0,240,192,88,224,115,157,32,132, 23,0,240,0,89,160,172,97,100,100,113,44,115,117,98,113,41,149,32,35,182,44,132,32, 10,1,240,255,104,0,98,141,32,158, 10,0,240,0,104,128,98,157,32,142, 16,0,241,0,120,128,109,111,118,101,113,32,35,135,44,145, 21,0,177,248,201,4,172,115,98,99,100,44,97,98,99,100,41,32,129,44,145,32, 25,0,177,248,201,12,172,115,98,99,100,44,97,98,99,100,41,32,130,64,45,44,146,64,45,32, 24,0,176,192,201,224,188,100,105,118,44,109,117,108,41,156,117,44,115,41,32,132,44,161, 27,0,176,0,201,160,204,111,114,44,97,110,100,41,149,32,171,7,132,171,7,44,171,251,177,171,251,32, 20,64,176,192,217,224,188,115,117,98,44,97,100,100,41,149,32,132,44,162, 22,0,177,56,217,132,188,115,117,98,120,44,97,100,100,120,41,149,32,129,44,161, 26,0,177,56,217,140,188,115,117,98,120,44,97,100,100,120,41,149,32,130,64,45,44,162,64,45, 28,0,176,0,217,160,204,115,117,98,44,97,100,100,41,149,32,171,7,132,171,7,44,171,251,177,171,251, 14,64,240,192,185,224,99,109,112,149,32,132,44,162, 14,0,241,0,184,160,99,109,112,149,32,132,44,161, 18,0,241,56,185,140,99,109,112,149,32,130,64,43,44,162,64,43, 14,0,241,0,185,160,101,111,114,149,32,161,44,132, 13,0,241,248,201,68,101,120,103,32,129,44,145,32, 13,0,241,248,201,76,101,120,103,32,130,44,146,32, 13,0,241,248,201,140,101,120,103,32,130,44,145,32, 28,0,248,192,229,224,172,97,115,44,108,115,44,114,111,120,44,114,111,41,156,114,44,108,41,119,32,132, 31,0,240,32,233,148,156,97,115,44,108,115,44,114,111,120,44,114,111,41,188,114,44,108,41,165,32,35,198,44,129,32, 30,0,240,32,233,180,156,97,115,44,108,115,44,114,111,120,44,114,111,41,188,114,44,108,41,165,32,193,44,129, 7,0,0,0,128,0,42,32, 0 9,41,32,132,44,147, 15,0,255,192,64,224,109,111,118,101,32,115,114,44,132,32, 13,0,255,0,64,160,110,101,103,120,149,32,132,32, 12,0,255,0,66,160,99,108,114,149,32,132, 12,0,255,0,68,160,110,101,103,149sumacc/cc/ddt68/vea68.c 444 0 12 560 3470501557 7703 7,0,56,0,4,0,129,32, 7,0,56,0,12,0,130,32, 8,0,56,0,20,0,130,64, 9,0,56,0,28,0,130,64,43,32, 9,0,56,0,36,0,130,64,45,32, 11,1,56,0,44,0,130,64,40,151,41,32, 13,8,56,0,52,0,130,64,40,167,44,144,41,32, 7,1,63,0,56,0,135,32, 7,2,63,0,57,0,135,32, 12,1,63,0,58,0,112,99,64,40,135,41, 14,8,63,0,59,0,112,99,64,40,151,44,128,41, 8,3,63,0,60,0,35,135, 7,0,0,0,32,0,42,32, 0 5,32, 13,0,241,248,201,76,101,120,103,32,130,44,146,32, 13,0,241,248,201,140,101,120,103,32,130,44,145,32, 28,0,248,192,229,224,172,97,115,44,10sumacc/cc/ddt68/vinscom.c 444 0 12 7745 3470501557 10464 /* Compiler for ins68 * V.R. Pratt * Jan., 1981 * modified jun 81 by jrl @ Lucasfilm for dissassembler to run on the vax */ #include <stdio.h> #define TABSIZ 128 #define WORDSIZ 16 int line=0, argno, mask, pattern, i, pnt, comma, postc, space; char modif, length, string[64], prev=0, current=0, next=0, sizmod, revargs, more = 1, table[TABSIZ]; /* Translation tables */ char *mcod = "nijuxyrglpt"; /* modifiers */ char *trm = "01D77703456"; /* modifier formats */ char *pcod = "dDaAeEsnuvmfFcrijxyrk"; /* permissible parameters */ char *pfmt = "ddaaeEsnuvmffcrnnxyrk"; /* parameter formats */ char *fcod = "kdaEesvnuyxmfcr"; /* case order for formats */ main() {get(); get(); while (more) {i=TABSIZ; while (i) table[--i] = -1; while (more && current != '\n') get(); /* skip to end of line */ while (more && next == '\n') get(); /* skip nl's */ if (next == EOF) break; line++; modif = argno = sizmod = revargs = mask = pattern = 0; for (i=WORDSIZ;i--;) /* process 16-bit word */ {mask <<= 1; pattern <<= 1; if ((get()&-2) == '0') {mask++; pattern += current&1;} else if (table[current] < 0) /* new argument */ {if (current != '.') /* . is dummy arg */ {table[current] = argno++; pattern++; /* leading 1 delimits field */ if (current == 'm') revargs = 1; if (current == 's') sizmod = 1; } } else if (current == prev) {if (current == 's') sizmod = 0;} else fprintf(stderr,"Repeat arg on line %d\n",line); } for (i=TABSIZ;i--;) if (table[i]>=0) table[i] = argno-table[i]-1; if (get() == ',') while (more && get() != '\t') {i = pos(current,mcod); modif |= trm[i]=='D'? 3: 1<<(trm[i]-'0'); if (current == 'g') /* g is 0000kkkknnnnnnnn */ {table['k'] = argno++; /* d/a index register */ table['n'] = argno++; /* 8-bit signed displacement */ } else if (i<8) /* nijuxyrg denote an arg */ table[current] = argno++; } if (sizmod) modif |= 64; while (next == '\t') get(); /* skip tabs */ pnt = 0; /* initialize output buffer */ while (more && get() != '\n') compchar();/* compile string */ if (revargs) {string[pnt++] = (char)(0213|(table['m']<<4)); string[space] = postc+1-space; string[comma] = pnt+1-comma; string[postc] = space+1-postc; string[pnt] = comma+1-pnt; pnt++; } length = 6+pnt; pnt = 0; out(length); out(modif); /* invert this for Vax out(mask>>8); out(mask&255); out(pattern>>8); out(pattern&255); */ out(mask&255); out(mask>>8); out(pattern&255); out(pattern>>8); while (pnt<length-6) out(string[pnt++]); if (length&1) out(' '); putchar('\n'); } printf("0 \n"); } char norm(x) char x; {return('A' <= x && x <= 'Z'? x+32: x);} compchar() {if (current < 'A' || prev > '@' || next > '@' || table[current] < 0) {if (current != '.') /* . is dummy */ {string[pnt++] = current; if (revargs) {if (current == ',') {string[pnt++] = 0213|(table['m']<<4); postc = pnt++; } if (current == ' ') {string[pnt++] = 0213|(table['m']<<4); space = pnt++; } } } } else {string[pnt++] = 0200| /* identifying bit */ (table[current] << 4)| /* arg no */ pos(pfmt[pos(current,pcod)],fcod);/* format */ if (norm(current) == 'f') {get(); /* erase ( */ do {string[pnt++] = get();} while (current != ')'); /* skip commas */ } } if (revargs && next == ',') {string[pnt++] = 0213|(table['m']<<4); comma = pnt++; } } get() {prev = current; current = next; if (next != EOF) next = getchar(); if (current == EOF) more = 0; return (current);} pos(c,s) char c, *s; {int i=0; while (s[i] && s[i] != c) i++; if (s[i]) return(i); else fprintf(stderr, "Unexpected char %o on line %d in %c%c%c\n",c,line,prev,current,next); } out(c) unsigned char c; {printf("%d,",c);} 4,97,98,99,100,41,32,129,44sumacc/cc/ddt68/vops68.c 444 0 12 7467 3470501557 10154 41,128,191,241,124,8,156,111,114,44,97,110,100,44,42,44,42,44,42,44,101,111,114,44,42,44,42,41,32,35,47,170,44,140,99,99,114,44,115,114,41,32, 32,128,0,255,160,8,156,98,116,115,116,44,98,99,104,103,44,98,99,108,114,44,98,115,101,116,41,32,35,168,44,132, 38,2,192,241,160,8,156,111,114,44,97,110,100,44,115,117,98,44,97,100,100,44,44,101,111,114,44,99,109,112,44,41,108,32,35,167,44,132, 38,1,0,241,160,8,172,111,114,44,97,110,100,44,115,117,98,44,97,100,100,44,44,101,111,114,44,99,109,112,44,41,149,32,35,183,44,132, 28,65,56,241,204,9,109,111,118,101,112,149,32,171,11,130,64,40,199,41,171,7,44,171,247,177,171,251, 31,0,0,241,160,9,156,98,116,115,116,44,98,99,104,103,44,98,99,108,114,44,98,115,101,116,41,32,161,44,132,32, 14,16,0,240,32,40,109,111,118,108,32,132,44,147, 20,0,0,192,32,40,109,111,118,172,44,98,44,44,119,41,32,132,44,147, 15,0,192,255,224,64,109,111,118,101,32,115,114,44,132,32, 13,0,0,255,160,64,110,101,103,120,149,32,132,32, 12,0,0,255,160,66,99,108,114,149,32,132, 12,0,0,255,160,68,110,101,103,149,32,132, 16,0,192,255,224,68,109,111,118,101,32,132,44,99,99,114, 15,0,192,255,224,70,109,111,118,101,32,132,44,115,114,32, 12,0,0,255,160,70,110,111,116,149,32,132, 12,0,192,255,32,72,110,98,99,100,32,132, 12,0,248,255,68,72,115,119,97,112,32,129, 11,32,192,255,96,72,112,101,97,32,132,32, 12,64,184,255,196,72,101,120,116,149,32,129, 19,192,184,255,228,72,109,111,118,101,109,149,32,47,170,44,130,64,45,32, 25,192,128,251,224,76,109,111,118,101,109,149,32,171,8,47,185,171,7,44,171,250,132,171,251,32, 11,0,192,255,224,74,116,97,115,32,132,32, 12,0,0,255,160,74,116,115,116,149,32,132, 13,0,240,255,72,78,116,114,97,112,32,35,136,32, 15,1,248,255,84,78,108,105,110,107,32,130,44,35,151,32, 12,0,248,255,92,78,117,110,108,107,32,130, 24,0,240,255,108,78,109,111,118,101,32,155,7,130,155,9,44,155,251,117,115,112,155,249, 14,128,255,255,114,78,115,116,111,112,32,35,47,138, 38,0,248,255,116,78,140,114,101,115,101,116,44,110,111,112,44,44,114,116,101,44,42,44,114,116,115,44,116,114,97,112,118,44,114,116,114,41, 17,32,128,255,224,78,156,106,115,114,44,106,109,112,41,32,132,32, 13,0,192,241,160,73,99,104,107,32,132,44,145,32, 13,32,192,241,224,73,108,101,97,32,132,44,146,32, 13,1,248,240,204,88,100,98,157,32,129,44,174,32, 10,0,192,240,224,88,115,157,32,132, 23,0,0,240,160,89,172,97,100,100,113,44,115,117,98,113,41,149,32,35,182,44,132,32, 10,1,255,240,0,104,98,141,32,158, 10,0,0,240,128,104,98,157,32,142, 16,0,0,241,128,120,109,111,118,101,113,32,35,135,44,145, 21,0,248,177,4,201,172,115,98,99,100,44,97,98,99,100,41,32,129,44,145,32, 25,0,248,177,12,201,172,115,98,99,100,44,97,98,99,100,41,32,130,64,45,44,146,64,45,32, 24,0,192,176,224,201,188,100,105,118,44,109,117,108,41,156,117,44,115,41,32,132,44,161, 27,0,0,176,160,201,204,111,114,44,97,110,100,41,149,32,171,7,132,171,7,44,171,251,177,171,251,32, 20,64,192,176,224,217,188,115,117,98,44,97,100,100,41,149,32,132,44,162, 22,0,56,177,132,217,188,115,117,98,120,44,97,100,100,120,41,149,32,129,44,161, 26,0,56,177,140,217,188,115,117,98,120,44,97,100,100,120,41,149,32,130,64,45,44,162,64,45, 28,0,0,176,160,217,204,115,117,98,44,97,100,100,41,149,32,171,7,132,171,7,44,171,251,177,171,251, 14,64,192,240,224,185,99,109,112,149,32,132,44,162, 14,0,0,241,160,184,99,109,112,149,32,132,44,161, 18,0,56,241,140,185,99,109,112,149,32,130,64,43,44,162,64,43, 14,0,0,241,160,185,101,111,114,149,32,161,44,132, 13,0,248,241,68,201,101,120,103,32,129,44,145,32, 13,0,248,241,76,201,101,120,103,32,130,44,146,32, 13,0,248,241,140,201,101,120,103,32,130,44,145,32, 28,0,192,248,224,229,172,97,115,44,108,115,44,114,111,120,44,114,111,41,156,114,44,108,41,119,32,132, 31,0,32,240,148,233,156,97,115,44,108,115,44,114,111,120,44,114,111,41,188,114,44,108,41,165,32,35,198,44,129,32, 30,0,32,240,180,233,156,97,115,44,108,115,44,114,111,120,44,114,111,41,188,114,44,108,41,165,32,193,44,129, 7,0,0,0,0,128,42,32, 0 ,117,98,44,97,100,100,41,149,32,132,44,162, 22,0,177,56,217,132,188,115,117,98,120,44,97,100,100,120,41,149,32,129,44,161, 26,0,177,56,217,140,188,115,117,98,120,44,97,100,100,120,41,149,32,130,64,45,4sumacc/cc/ld/ 775 0 12 0 3540162171 6203 sumacc/cc/ld/Makefile 444 0 12 2357 3470501557 7742 #Description file for .b file linker and utilities #Say 'make' to bring all command files in ld up to date. Say 'make install' #to copy any new command files to BIN. BIN = /usr/sun/bin INCLUDE = /usr/sun/include all: ld68 nm68 rl68 size68 pr68 rev68 dl68 ranlib68 ld68: ld.c cc -o ld68 -O -DStanford -DBOOTSTRAP -I$(INCLUDE) ld.c nm68: nm68.c cc -o nm68 -O -I$(INCLUDE) nm68.c rl68: rl68.c cc -o rl68 -O -I$(INCLUDE) rl68.c size68: size68.c cc -o size68 -O -I$(INCLUDE) size68.c pr68: pr68.c cc -o pr68 -O -I$(INCLUDE) pr68.c rev68: rev68.c cc -o rev68 -O -I$(INCLUDE) rev68.c dl68: dl68.c cc -o dl68 -O -I$(INCLUDE) dl68.c ranlib68: ranlib68.c cc -o ranlib68 -O -I/usr/include -I$(INCLUDE) ranlib68.c install: $(BIN)/ld68 $(BIN)/nm68 $(BIN)/rl68 $(BIN)/size68 $(BIN)/pr68 $(BIN)/rev68 $(BIN)/dl68 $(BIN)/lorder68 $(BIN)/ld68: ld68 cp ld68 $(BIN) $(BIN)/nm68: nm68 cp nm68 $(BIN) $(BIN)/rl68: rl68 cp rl68 $(BIN) $(BIN)/size68: size68 cp size68 $(BIN) $(BIN)/pr68: pr68 cp pr68 $(BIN) $(BIN)/rev68: rev68 cp rev68 $(BIN) $(BIN)/dl68: dl68 cp dl68 $(BIN) $(BIN)/lorder68: cp lorder68.sh $(BIN)/lorder68 clean: rm -f *.o dl68 ld68 nm68 pr68 rev68 rl68 size68 ranlib68 rm -f *.BAK *.CKP .emacs* .netup* 23,0,0,240,160,89,172,97,100,100,113,44,115,117,98,113,41,149,32,35,182,44,132,32, 10,1,255,240,0,104,98,141,32,158, 10,0,0,240,128,104,98,157,32,142, 16,0,0,241,128,120,109,111,118,101,113,32,35,135,44,145, 21,0,248,177,4,201,172,115,98,99,100,44,97,98,99,100,41,32,129,44sumacc/cc/ld/dl68.1 444 0 12 2055 3470501560 7126 .TH DL68 1 MC68000 .SU .SH NAME dl68 \- b.out -> .dl downloader component of cc68 .SH SYNOPSIS .B dl68 [ -T -v -o -s ] filename .SH DESCRIPTION .I Dl68 is a downloader for the Motorola 68000 Design Module. It takes its input, a b.out format file, from filename and in the absence of the -o option sends its output to stdout. .PP If there are any symbols these are loaded, starting at 0x6BA on vm (the Design Module) or 0x1F000 on v1 (the Sun1 prototype). The start and end of the symbol table are stored at 0x570 and 0x574 respectively on either board. .PP The options are: .TP .BI \-T " textorigin " specifies where the text (code) is to be loaded. .TP .BI \-v n specifies the board version. Default is v1 (Sun1 prototype). vm denotes the Motorola Design Module. .TP .BI \-o " filename " specifies the output file. Defaults to stdout. .TP .BI \-s DE specifies the .I data/end record types to generate. The default is s28, 24 bit addresses. The s19 format, 16 bit addresses, is used by the Data I/O programmers. .PP .SH FILES /usr/sun/ld68/down.c /usr/bin/dl68 $(BIN) $(BIN)/dl68: dl68 cp dl68 $(BIN) $(BIN)/lorder68: cp lorder68.sh $(BIN)/lorder68 clean: rm -f *.o dl68 ld68 nm68 pr68 rev68 rl68 size68 ranlib68 rm -f *.BAK *.CKP .emacs* .netup* 23,0,0,240,160,89,172,97,100,100,113,44,115,117,98,113,41,149,32,35,182,44,132,32, 10,1,255,240,0,104,98,141,32,158, 10,0,0,240,128,104,98,157,32,142, 16,0,0,241,128,120,109,111,118,101,113,32,35,135,44,145, 21,0,248,177,4,201,172,115,98,99,100,44,97,98,99,100,41,32,129,44sumacc/cc/ld/dl68.c 444 0 12 17222 3470501560 7232 /* Downloader for MACSBUG. Author Anonymous. Modified to store symbols: V. Pratt, Jan. 1981. Assumed to run on a machine with VAX-type byte order in a word, namely first text byte is least significant byte. Modify the function reverse(lwrd) appropriately to run on another machine. Jan. 1982 - V. Pratt - Modified to load symbol table where the Sun bootloader puts it */ #include "b.out.h" #include <stdio.h> #define STARTADDR 0x1000 /* Default start address */ #define RCDSIZE 32 /* Size of Motorola S-type records */ #define MACSSYMTAB 0x6BA /* Symbol table starts here - MACSBUG */ #define SUNSYMTAB 0x1f000 /* Symbol table starts here - SUN */ #define SYMTAB (vflag=='m'?MACSSYMTAB:SUNSYMTAB) #define SYMTABADDR 0x570 /* Boundaries of symbol table here */ #define MAXSYMS (vflag=='m'?((0x1000-0x6BA)/12):(0x1000/12)) #define MAXSYMST (0x1000/12) /* Max size of symbol table for either SUN or MACSBUG */ #define hex(c) c>9 ? c+0X37 : c+0X30 /* macro for hex convert */ struct bhdr filhdr; struct sym68 { /* fake sym for 68000 */ short dummy1; /* ignored */ char stype; /* type */ char slength; /* length */ long svalue; }; char Sdata=2; /* Default to S2/S8 records (24 bit addr) */ char Send=8; char vflag=0; /* 1 -> Design Module */ FILE *infile, *outfile; char infilename[30], outfilename[30] = {0}; int syms = 0; puthex(b) /* print byte as two hex chars */ char b; { register char c1,c2; c1=(b>>4) & 0XF; c2=b & 0XF; c1=hex(c1); c2=hex(c2); fprintf(outfile,"%c%c",c1,c2); } typedef struct Msymtab /* structure of the MACSBUG symbol space */ {char name[8]; int value; } msymtab; reverse(lwrd) unsigned lwrd; {return((lwrd>>24) | (lwrd>>8 & 0xff00) | (lwrd<<8 & 0xff0000)| (lwrd<<24) ); } int checksum; checkout(c) char c; {checksum += c; puthex(c);} /* Procedure to print out one ExorMacs record of given type */ print_exormacs_record(type,buffer,Dcount,addr) char *buffer; int Dcount, addr; {fprintf(outfile,"S%d",type); checksum = 0; if (type == 2 || type == 8) {checkout((char) Dcount+4); checkout((char) (addr>>16)); } else checkout((char) Dcount+3); checkout((char) (addr>>8)); checkout((char) addr); while (Dcount--) checkout(*buffer++); puthex(~(checksum & 0XFF)); fprintf(outfile,"\n"); } /* Procedure that puts out records from a buffer */ outbuf(buffer,addr,size) char *buffer; int addr, size; { int count, /* counts total number of bytes processed*/ Dcount; /* number of bytes in current record */ for(count=0; count<size; count += RCDSIZE) {Dcount= (size-count<RCDSIZE) ? size-count : RCDSIZE; print_exormacs_record(Sdata,buffer,Dcount,addr); buffer += Dcount; addr += Dcount; } } /* Procedure that puts out records from a file */ outbin(file,addr,size) FILE *file; int addr, size; { int count, /* counts total number of bytes processed*/ Dcount; /* number of bytes in current record */ char buffer[RCDSIZE]; /* buffer for data */ for(count=0; count<size; count += RCDSIZE) {Dcount= (size-count<RCDSIZE) ? size-count : RCDSIZE; if(fread(buffer,Dcount,1,file) != 1) {fprintf(stderr,"Read error\n"); exit(1);} print_exormacs_record(Sdata,buffer,Dcount,addr); addr += Dcount; } } #define lower(c) 'a' <= c && c <= 'z' #define upper(c) 'A' <= c && c <= 'Z' #define digit(c) '0' <= c && c <= '9' macify(c) char c; /* convert c to a form acceptable to MACSBUG */ {return (lower(c)? c-32: upper(c)? c: digit(c)? c: c == '_'? '.': /*default*/ '$' /* rags to riches */ ); } /* Procedure to convert symbol table to .r format */ rbuild(table,source,size) struct sym68 *table; FILE *source; int *size; {struct sym s; int symno, chrno; char c; struct sym68 *s68 = table; int pos; for (pos=0; pos < filhdr.ssize; ) {if (!fread(&s,sizeof s,1,source)) break;/* Get symbol descriptor */ pos += sizeof s; s68 = (struct sym68 *)((int)s68 -2); /* kludge */ s68->stype = s.stype; s68->slength = s.slength; s68->svalue = reverse(s.svalue); s68++; while (*(char *)s68 = getc(source)) { s68 = (struct sym68 *)((int)s68 + 1); pos++; } s68 = (struct sym68 *)((int)s68 + strlen(s68)+1); if ((int)s68 & 1) { *((char *)s68) = 0; /* clear extra byte */ s68 = (struct sym68 *)((int)s68 + 1); /* word align */ } } *size = (int)s68 - (int)table; } /* Procedure to convert symbol table to MACSBUG format */ build(table,source,size) msymtab table[]; FILE *source; int *size; {struct sym s; int symno, chrno; char c; for (symno=0; symno<MAXSYMS; symno++) /* Keep count of symbols */ {if (!fread(&s,sizeof s,1,source)) break;/* Get symbol descriptor */ chrno = 0; while ((c = getc(source)) && chrno<8) table[symno].name[chrno++] = macify(c);/* Write chars of sym.*/ while (chrno<8) /* Pad rest with spaces */ table[symno].name[chrno++] = ' '; while (c) c = getc(source); /* discard symbol tail */ table[symno].value = reverse(s.svalue); /* Supply symbol value */ } *size = symno * 12; /* return size of table */ return((int)table); /* return address of table */ } main(argc,argv) int argc; char *argv[]; { int Sa, Daddr=STARTADDR, i; msymtab table[MAXSYMST]; if(argc<2) {fprintf(stderr,"Usage: dl68 infile [ > outfile ]\n"); exit(1); } for (i=1; i<argc; i++) /* get options */ if (argv[i][0] == '-') switch (argv[i][1]) { case 'T': if (i++ < argc) sscanf(argv[i],"%x",&Daddr); break; case 'v': vflag = argv[i][2]; break; case 'o': if (i++ < argc) strcpy(outfilename,argv[i]); break; case 's': Sdata = argv[i][2] - '0'; Send = argv[i][3] - '0'; break; } else strcpy(infilename,argv[i]); if((infile=fopen(infilename,"r"))==NULL) /* open infile */ {strcat(infilename,".68"); /* try .68 form */ if ((infile=fopen(infilename,"r"))==NULL) {fprintf(stderr,"dl68: Can't open %s\n",infilename); exit(1); } } if (*outfilename) { if ((outfile = fopen(outfilename,"w")) == NULL) { fprintf(stderr,"dl68: Can't open %s\n",outfilename); exit(1); } } else outfile = stdout; if(fread(&filhdr, sizeof(struct bhdr),1,infile) != 1)/* get header info */ {fprintf(stderr,"dl68: %s wrong format\n",infilename); exit(1); } if(filhdr.fmagic != FMAGIC) { /* check magic number */ fprintf(stderr,"dl68: %s not proper b.out file\n",infilename); exit(1); } Sa = Daddr; /* Output records for TEXT portion */ outbin(infile,Daddr,filhdr.tsize); Daddr += filhdr.tsize; /* adjust output address */ fseek(infile,DATAPOS,0); /* seek to DATA portion */ /* Output records for DATA segment */ outbin(infile,Daddr,filhdr.dsize); Daddr += filhdr.dsize; /* adjust output address */ fseek(infile,SYMPOS,0); /* seek to SYM portion */ if (filhdr.ssize) { int sz; if (vflag != 'm') { /* Output symbol table in boot loader format */ int ssize68; static char stable[8192]; /* enough? */ (char*)rbuild(stable,infile,&sz); ssize68 = reverse(sz); Daddr += filhdr.bsize; /* skip bss (should be 0 really) */ print_exormacs_record(Sdata,&ssize68,4,Daddr); Daddr += 4; outbuf(stable,Daddr,sz); } else { int tabpnt[2]; msymtab table[MAXSYMST]; char *bbuf; bbuf = (char*)build(table,infile,&sz); outbuf(bbuf,SYMTAB,sz); tabpnt[0] = reverse(SYMTAB); /* Lower limit */ tabpnt[1] = reverse(SYMTAB+sz); /* Upper limit */ outbuf(tabpnt,SYMTABADDR,sizeof tabpnt);/* Output pointers */ } } /* Output entry point: as in file header, else default to start address */ print_exormacs_record(Send,0,0,filhdr.entry? filhdr.entry: Sa); } uct sym68 *table; FILE *source; int *size; {struct sym s; int symno, chrno; char c; struct sym68 *s68 = table; int pos; for (pos=0; pos < filhdr.ssize; ) {if (!fread(&s,sizeof s,1,source)) break;/* Get symbol descriptor */ pos += sizeof s; s68 = (struct sym68 *)((int)s68 -2); /* kludge */ s68->stype = s.stype; s68->slength = s.slength; sumacc/cc/ld/ld.c 444 0 12 102477 3470501560 7103 /* * ld.c - 68000 Linking Loader * * July 1982 Bill Nowicki Stanford * - merged LucasFilms and Stanford versions * - made symbol table larger * * 1 Aug 82 - Mike Nielsen @ Stanford * - added qflag * - quicksort symbols in b.out by numerical value if qflag in finishout * * 1 Oct 82 - Per Bothner @ Stanford * - added -f flag: fold case, making upper and lower case letters equal * * May 83 - Per Bothner, Stanford * - ld68 now ignores __.SYMDEF files as produced by ranlib68 * [Really should use __.SYMDEF to speed up loading at some point] */ #ifdef BOOTSTRAP #include "/usr/include/stdio.h" #else #include <stdio.h> #endif #ifndef Stanford /* Unix -specific stuff */ #include <sys/autoconf.h> /* to get U_VA */ #include <a.out.h> #include <ar.h> /* V7 archive header */ #include <ar.bky.h> /* UC Berkeley archive header */ #include <bootstrap.h> #else Stanford #include <b.out.h> #include <ar.h> /* UC Berkeley archive header */ #define ROOT "/usr/sun" #endif Stanford /* * link editor */ #define TRUE 1 #define FALSE 0 /* Warning! segsize is assumed to be <= the largest segment size * in any hardware implmentation. segsize determines where the * data/bss segment is placed in mode 410 files (seperate R/O text segment). * It MUST agree with a similar definition in the kernel (machdep.c). */ #define segsize 64*1024 /* text/data segment seperate size */ struct archdir /* Don't use this on UCB Unix */ { char aname[14]; long atime; char auid, agid; short amode; long asize; }; #define NOVLY 16 #define NROUT 256 #define TABSZ 700 #ifndef Stanford #define NSYM 4507 /* symbol table size */ /* LucasFlim had 4000, MIT had 1503 */ #define NSYMPR 1200 #define ORG U_VA /* default text origin */ #else Stanford #define NSYM 8191 /* symbol table size */ #define NSYMPR 8000 #define ORG 0x1000 #endif Stanford #ifdef BOOTSTRAP #define DOTOUT "b.out" #define BIN 'b' #else #define DOTOUT "a.out" #define BIN 'o' #endif typedef struct symbol *symp; struct symbol { struct sym s; /* type and value */ char *sname; /* pointer to asciz name */ int snlength; /* length of name in bytes */ symp *shash; /* hash table index */ unsigned sindex; /* id of symbol in symtab */ }; typedef struct arg_link *arg; struct arg_link { char *arg_name; /* the acutal argument string */ arg arg_next; /* next one in linked list */ }; typedef struct arc_entry *arce; struct arc_entry { long arc_offs; /* offset in the file of this entry */ arce arc_e_next; /* next entry, NULL if none */ }; typedef struct arc_link *arcp; struct arc_link { arce arc_e_list; /* list of archive entries */ arcp arc_next; /* next archive */ }; /* global variables */ arg arglist; /* linked list of arguments */ #ifndef Stanford struct ar_hdr v7_archdr; /* directory part of v7 archive */ struct bky_ar_hdr bky_archdr; /* directory part of bky archive */ #else Stanford struct ar_hdr archdr; /* directory part of archive */ #endif Stanford arcp arclist = NULL; /* list of archives */ arcp arclast = NULL; /* last archive on arclist */ arce arcelast = NULL; /* last entry in this entry list */ #ifndef Stanford struct exec filhdr; /* header file for current file */ #else Stanford struct bhdr filhdr; /* header file for current file */ #endif Stanford struct symbol cursym; /* current symbol */ char csymbuf[SYMLENGTH]; /* buffer for current symbol name */ struct symbol symtab[NSYM]; /* actual symbols */ symp lastsym; /* last symbol entered */ int symindex; /* next available symbol table entry */ symp hshtab[NSYM+2]; /* hash table for symbols */ symp local[NSYMPR]; /* symbols in current file */ int nloc; /* number of local symbols per file */ int nund = 0; /* number of undefined syms in pass 2*/ symp entrypt = 0; /* pointer to entry point symbol */ int argnum; /* current argument number */ char *ofilename = DOTOUT; /* output file, default init */ FILE *text; /* file descriptor for input file */ FILE *rtext; /* used to access relocation */ char *filename; /* name of current input file */ char *mfilename; /* name of Macsbug input file */ char tfilename[100]; /* copy of filename */ char xfilename[100]; /* copy of filename */ FILE *tout; /* text portion */ FILE *dout; /* data portion */ FILE *trout; /* text relocation commands */ FILE *drout; /* data relocation commands */ FILE *Lout; /* list symbols */ /* flags */ int xflag; /* discard local symbols */ int Xflag; /* discard locals starting with '.L' */ int Sflag; /* discard all except locals and globals*/ int rflag; /* preserve relocation bits, don't define common */ int sflag; /* discard all symbols */ int vflag=1; /* what version? presently default to 1 */ int dflag; /* define common even with rflag */ int Lflag; /* list symbols on list.out */ int nflag = 0; /* create a 410 file */ int Bflag; /* set origin of common/bss segment */ int qflag; /* quick sorts symbols by numerical value */ /* used after pass 1 */ long torigin; /* origin of text segment in final output */ long dorigin; /* origin of data segment in final output */ long doffset; /* current position in output data segment */ long borigin; /* origin of bss segment in final output */ long corigin; /* origin of common area */ /* cumulative sizes set in pass 1 */ long tsize; /* size of text data */ long dsize; /* size of data segment */ long bsize; /* size of bss segment */ long csize; /* size of common area */ long rtsize; /* size of text relocation area */ long rdsize; /* size of data relocation area */ long ssize = 0; /* size of symbol area */ /* symbol relocation; both passes */ long ctrel; long cdrel; long cbrel; /* error messages */ char *e1 = "missing argument following command option -%c"; char *e2 = "unrecognized option: -%c"; char *e3 = "premature end of file %s"; char *e4 = "read error on file %s"; char *e5 = "unknown type of file %s"; char *e5a = "unknown type of file %s in readhdr"; char *e6 = "multiply defined symbol %s in file %s"; char *e7 = "entry point not in text"; char *e8 = "cannot create file %s"; char *e9 = "cannot reopen output file"; char *e10 = "local symbol overflow"; char *e11 = "internal error - undefined symbol %s in file %s"; char *e12 = "format error in file %s, bad relocation size"; char *e13 = "format error in file %s, relocation outside of segment"; char *e14 = "error writing file %s"; char *e15 = "file %s not found"; char *e16 = "hash table overflow"; char *e17 = "symbol table overflow"; char *e18 = "format error in file %s, null symbol name"; char *e19 = "format error in file %s, invalid symbol id in relocation command"; char *e20 = "%s references %s"; char *e21 = "format error in file %s, bad address in relocation command"; char *e22 = "bad header in archive %s, ARFMAG is 0x%x 0x%x"; char *e23 = "unknown archive magic, 0x%x 0x%x 0x%x 0x%x"; /* functions */ long getsym(); symp lookup(); symp slookup(); symp *hash(); long relext(); long relcmd(); long atox(); long foldstrcmp(); long strcmp(); long (*mystrcmp)() = strcmp; /* points to either strcmp or foldstrcmp depending on the '-f' flag */ /* main - The link editor works in two passes. In pass 1, symbols are defined. In pass 2, the actual text and data will be output along with any relocation commands and symbols */ main(argc, argv) int argc; char **argv; { arg argp; /* current argument */ torigin = ORG; /* set with -T flag */ procargs(argc, argv); for (argp = arglist; argp; argp = argp->arg_next) load1arg(filename = argp->arg_name); middle(); setupout(); for (argp = arglist; argp; argp = argp->arg_next) load2arg(filename = argp->arg_name); finishout(); exit(0); } /* progargs - Process command arguments */ procargs(argc, argv) int argc; char **argv; { for (argnum = 1; argnum < argc; argnum++) /* for each arg */ { if (argv[argnum][0] == '-') procflags(argc, argv); else newarg(argv[argnum]); /* build linked list */ } } /* newarg - Create a new member of linked list of arguments */ newarg(name) char *name; { arg a1, a2; a1 = (arg)calloc(1, sizeof(*a1)); a1->arg_name = name; a1->arg_next = NULL; if (arglist == NULL) arglist = a1; else /* link new one on end */ { for (a2 = arglist; a2->arg_next; a2 = a2->arg_next); a2->arg_next = a1; } } /* procflags - Process flag arguments. */ procflags(argc, argv) int argc; char **argv; { char *flagp = &argv[argnum][1]; char c; while(c = *flagp++) switch(c) { case 'o': if (++argnum >= argc) error(e1, c); else ofilename = argv[argnum]; break; case 'u': if (++argnum >= argc) error(e1, c); else enter(slookup(argv[argnum])); break; case 'e': if (++argnum >= argc) error(e1, c); else enter(slookup(argv[argnum])); entrypt = lastsym; break; case 'D': if (++argnum >= argc) error(e1, c); else dsize = atol(argv[argnum]); break; case 'T': if (++argnum >= argc) error(e1, c); else torigin = atox(argv[argnum]); break; case 'B': if (++argnum >= argc) error(e1, c); else borigin = atox(argv[argnum]); Bflag++; break; case 'l': newarg(argv[argnum]); while (*++flagp); break; case 'x': xflag++; break; case 'X': Xflag++; break; case 'S': Sflag++; break; case 'r': rflag++; break; case 's': sflag++; xflag++; break; case 'v': vflag = *flagp++; break; case 'd': dflag++; break; case 'n': nflag++; break; case 'L': Lflag++; break; case 'M': Lflag++; break; case 'q': qflag++; break; case 'f': mystrcmp = foldstrcmp; break; default: error(e2, c); } } /* Like strcmp, but insensitive to cases of letters */ foldstrcmp(s1, s2) register char *s1, *s2; { register char c1, c2; do { c1 = *s1++; c2 = *s2++; if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; if (c1 -= c2) return(c1); } while (c2 != '\0'); return (0); } long atox(s) char *s; { long result = 0; for (; *s != 0; *s++) if (*s >= '0' && *s <= '9') result = (result<<4) + *s-'0'; else if (*s >= 'a' && *s <= 'f') result = (result<<4) + *s-'a'+10; else if (*s >= 'A' && *s <= 'F') result = (result<<4) + *s-'A'+10; else error("atox: illegal hex argument (%c)",*s); return(result); } /* scan file to find defined symbols */ load1arg(cp) register char *cp; { long position = 0, n; arcp ap; /* pointer to new archive list element */ switch (getfile(cp)) /* open file and read first word */ { case FMAGIC: fseek(text, 0L, 0); /* back to start of file */ load1(0L, 0); /* pass1 on regular file */ break; #ifndef Stanford /* V7 archive */ case ARMAG: #else Stanford /* regular archive */ case ARCMAGIC: #endif Stanford ap = (arcp)calloc(1, sizeof(*ap)); ap->arc_next = NULL; ap->arc_e_list = NULL; if (arclist) { arclast->arc_next = ap; arclast = ap; } else arclast = arclist = ap; #ifndef Stanford position = 2; fseek(text, 2L, 0); /* skip magic */ while (fread(&v7_archdr, sizeof v7_archdr, 1, text) && !feof(text)) { position += sizeof(v7_archdr); #else Stanford position = SARMAG; fseek(text, SARMAG, 0); /* skip magic */ while (fread(&archdr, sizeof archdr, 1, text) && !feof(text)) { position += sizeof(archdr); if (strncmp(archdr.ar_name, "__.SYMDEF ", 16)) #endif Stanford if (load1(position, 1)) /* arc pass1 */ { arce ae = (arce)calloc(1, sizeof(*ae)); ae->arc_e_next = NULL; ae->arc_offs = position; if (arclast->arc_e_list) { arcelast->arc_e_next = ae; arcelast = ae; } else arclast->arc_e_list = arcelast = ae; } #ifndef Stanford position += (v7_archdr.ar_size+1)&~1; fseek(text, position, 0); } break; /* Berkeley archive */ case BKYARCHIVE: ap = (arcp)calloc(1, sizeof(*ap)); ap->arc_next = NULL; ap->arc_e_list = NULL; if (arclist) { arclast->arc_next = ap; arclast = ap; } else arclast = arclist = ap; position = BKYSARMAG; fseek(text, BKYSARMAG, 0); /* skip magic */ while (fread(&bky_archdr, sizeof bky_archdr, 1, text) && !feof(text)) { if (strcmpn(bky_archdr.bky_fmag, BKYARFMAG, sizeof BKYARFMAG) != 0) fatal (e22, filename, bky_archdr.bky_fmag[0], bky_archdr.bky_fmag[1]); position += sizeof(bky_archdr); if (load1(position, 1)) /* arc pass1 */ { arce ae = (arce)calloc(1, sizeof(*ae)); ae->arc_e_next = NULL; ae->arc_offs = position; if (arclast->arc_e_list) { arcelast->arc_e_next = ae; arcelast = ae; } else arclast->arc_e_list = arcelast = ae; } sscanf(bky_archdr.bky_size,"%d",&n); #else Stanford sscanf(archdr.ar_size,"%d",&n); #endif Stanford position += (n+1)&~1; fseek(text, position, 0); } break; default: fatal(e5, filename); } fclose(text); fclose(rtext); } /* load1 - Accumulate file sizes and symbols for single file or archive member. Relocate each symbol as it is processed to its relative position in it csect. If libflg == 1, then file is an archive hence throw it away unless it defines some symbols. Here we also accumulate .comm symbol values. */ load1(sloc, libflg) long sloc; /* location of first byte of this file */ int libflg; /* 1 => loading a library, 0 else */ { long loc = sloc;/* current position in file */ long endpos; /* position after symbol table */ int savindex; /* symbol table index on entry */ int ndef; /* number of symbols defined */ readhdr(sloc); ctrel = tsize; cdrel += dsize; cbrel += bsize; ndef = 0; nloc = 0; savindex = symindex; loc += SYMPOS; fseek(text,loc, 0); /* skip to symbols */ endpos = loc + filhdr.ssize; while (loc < endpos) { loc += getsym(); ndef += sym1(); /* process one symbol */ } if (libflg==0 || ndef) { tsize += filhdr.tsize; dsize += filhdr.dsize; bsize += filhdr.bsize; ssize += nloc; /* count local symbols */ rtsize += filhdr.rtsize; rdsize += filhdr.rdsize; return(1); } /* * No symbols defined by this library member. * Rip out the hash table entries and reset the symbol table. */ while (symindex>savindex) *symtab[--symindex].shash = 0; return(0); } /* sym1 - Process pass1 symbol definitions. This involves flushing un-needed symbols, and entering the rest in the symbol table. Returns 1 if a symbol was defined and 0 else. */ sym1() { register symp sp; int type = cursym.s.stype; /* type of the current symbol */ #ifdef Stanford int len = cursym.s.slength; /* length of the current symbol */ #endif Stanford if (Sflag) switch(type& 037) { case TEXT: case BSS: case DATA: break; default: return(0); } if ((type&EXTERN) == 0) { if (xflag || (Xflag && (cursym.sname[0] == '.') && (cursym.sname[1] == 'L'))); else nloc += sizeof(cursym.s) + cursym.snlength + 1; return(0); } symreloc(); /* relocate symbol in file */ if (enter(lookup())) return(0); /* install symbol in table */ /* If we get here, then symbol was already present. If symbol is already defined then return, multiple definitions are caught later. If current symbol is not EXTERN eg it is local, let the new one override */ if ((sp = lastsym)->s.stype & EXTERN) { if ((sp->s.stype & 037) != UNDEF) return(0); } else if (!(cursym.s.stype & EXTERN)) return(0); if (cursym.s.stype == EXTERN+UNDEF) { /* check for .comm symbols */ if (cursym.s.svalue>sp->s.svalue) sp->s.svalue=cursym.s.svalue; return(0); } if (sp->s.svalue!=0 && cursym.s.stype == EXTERN+TEXT) return(0); sp->s.stype = cursym.s.stype; /* define something new */ #ifdef Stanford sp->s.slength = cursym.snlength; #endif Stanford sp->s.svalue = cursym.s.svalue; return(1); } /* middle - Finalize the symbol table by adding the origins of each csect to symbols. Also define the end stuff, adjusting the boundries of the csect depending on options. */ middle() { register symp sp; int col=1, Lokay=TRUE; enter(slookup("_etext")); enter(slookup("_edata")); enter(slookup("_end")); /* * Assign common locations. */ csize = 0; if (dflag || rflag==0) { ldrsym(slookup("_etext"), tsize, EXTERN+TEXT); /* set value */ ldrsym(slookup("_edata"), dsize, EXTERN+DATA); ldrsym(slookup("_end"), bsize, EXTERN+BSS); common(); } /* * Now set symbols to their final value */ #ifndef Stanford tsize = (tsize + 1) & ~01; /* move to word boundary */ /* move data/bss segment up to segment boundary for mode 410 files */ if (nflag) dorigin = torigin + ((tsize + (segsize-1)) & ~(segsize-1)); #else Stanford tsize += tsize&1; /* move to word boundry */ if (nflag) { /* -n -> move to seg bdy */ torigin = torigin + (SEGSIZE - 1) & -SEGSIZE; dorigin = torigin+(tsize+(SEGSIZE - 1)) & -SEGSIZE; } #endif Stanford else dorigin = torigin + tsize; #ifndef Stanford dsize = (dsize + 1) & ~01; /* move to word boundary */ if (Bflag) { corigin = borigin; /* put comm/bss elsewhere */ borigin += csize; } else { #else Stanford dsize += dsize&1; /* move to word boundry */ #endif Stanford corigin = dorigin + dsize; /* common after data */ borigin = corigin + csize; /* bss after common area */ #ifndef Stanford } #endif Stanford nund = 0; /* no undefined initially */ /* ssize = size of local symbols to be entered in load2 */ doffset = 0; /* beginning of data seg */ Lokay = TRUE; if (Lflag) if ((Lout = fopen("sym.out", "w")) == NULL) {error(e8, "list.out"); Lokay = FALSE; } for (sp = symtab; sp < &symtab[symindex]; sp++) {sym2(sp); if (Lokay && Lflag) fprintf(Lout, col++%4?"%s %x\t":"%s %x\n", sp->sname, sp->s.svalue); } bsize += csize; } /* common - Set up the common area. */ common() { register symp sp; long val; csize = 0; for (sp = symtab; sp < &symtab[symindex]; sp++) if (sp->s.stype == EXTERN+UNDEF && ((val = sp->s.svalue) != 0)) { val = (val + 1) & ~01; /* word boundry */ sp->s.svalue = csize; sp->s.stype = EXTERN+COMM; csize += val; } } /* sym2 - Assign external symbols their final value and compute ssize */ sym2(sp) register symp sp; { ssize += sizeof(sp->s) + sp->snlength + 1; switch (sp->s.stype) { case EXTERN+UNDEF: if ((rflag == 0 || dflag) && sp->s.svalue == 0) { if (nund==0) printf("Undefined:\n"); nund++; printf("%s\n", sp->sname); } break; case EXTERN+ABS: default: break; case EXTERN+TEXT: sp->s.svalue += torigin; break; case EXTERN+DATA: sp->s.svalue += dorigin; break; case EXTERN+BSS: sp->s.svalue += borigin; break; case EXTERN+COMM: sp->s.stype = EXTERN+BSS; sp->s.svalue += corigin; break; } } /* ldrsym - Force the definition of a symbol */ ldrsym(asp, val, type) symp asp; long val; /* value of the symbol */ char type; /* its type */ { register symp sp; if ((sp = asp) == 0) return; if (sp->s.stype != EXTERN+UNDEF || sp->s.svalue) { error(e6, sp->sname, filename); return; } sp->s.stype = type; sp->s.svalue = val; } /* setupout - Set up for output. Create output file and a temporary files for the data area and relocation commands if necessary. Write the header on the output file. */ setupout() { if (nflag) filhdr.fmagic = NMAGIC; else filhdr.fmagic = FMAGIC; filhdr.tsize = tsize; filhdr.dsize = dsize; filhdr.bsize = bsize; filhdr.rtsize = rflag? rtsize: 0; filhdr.rdsize = rflag? rdsize: 0; filhdr.ssize = sflag? 0:ssize; if (!entrypt && slookup("_start") != NULL) entrypt = slookup("_start"); if (entrypt) { if (entrypt->s.stype!=EXTERN+TEXT) error(e7); else filhdr.entry = entrypt->s.svalue; } else filhdr.entry = torigin; if ((tout = fopen(ofilename, "w")) == NULL) fatal(e8, ofilename); if ((dout = fopen(ofilename, "a")) == NULL) fatal(e9); fseek(dout, (long)(DATAPOS), 0); if (rflag) { if ((trout = fopen(ofilename, "a")) == NULL) fatal(e9); fseek(trout, (long)RTEXTPOS, 0); /* start of text relocation */ if ((drout = fopen(ofilename, "a")) == NULL) fatal(e9); fseek(drout, (long)RDATAPOS, 0); /* to data reloc */ } fwrite(&filhdr, sizeof(filhdr), 1, tout); } /* load2arg - Load a named file or an archive */ load2arg(cp) char *cp; { long position = 0; /* position in input file */ arce entry; /* pointer to current entry */ switch (getfile(cp)) { case FMAGIC: /* normal file */ dread(&filhdr, sizeof filhdr, 1, text); load2(0L); break; #ifndef Stanford case ARMAG: /* V7 archive */ #else Stanford case ARCMAGIC: /* archive */ #endif Stanford for(entry=arclist->arc_e_list; entry; entry=entry->arc_e_next) { position = entry->arc_offs; fseek(text, position, 0); dread(&filhdr, sizeof filhdr, 1, text); load2(position); /* load the file */ } arclist = arclist->arc_next; break; #ifndef Stanford case BKYARCHIVE: /* Berkeley archive */ for(entry=arclist->arc_e_list; entry; entry=entry->arc_e_next) { position = entry->arc_offs; fseek(text, position, 0); dread(&filhdr, sizeof filhdr, 1, text); load2(position); /* load the file */ } arclist = arclist->arc_next; break; #endif Stanford default: bletch("bad file type on second pass"); } fclose(text); fclose(rtext); } /* load2 - Actually output the text, performing relocation as necessary. */ load2(sloc) long sloc; /* position of filhdr in current input file */ { register symp sp; long loc=sloc; /* current position in file */ long endpos; /* end of symbol segment */ int symno = 0; int type; readhdr(sloc); ctrel = torigin; cdrel += dorigin; cbrel += borigin; /* * Reread the symbol table, recording the numbering * of symbols for fixing external references. */ loc += SYMPOS; fseek(text, loc, 0); endpos = loc + filhdr.ssize; while(loc < endpos) { loc += getsym(); symno++; if (symno >= NSYMPR) fatal(e10); symreloc(); type = cursym.s.stype; if (Sflag) { switch(type&037) { case TEXT: case BSS: case DATA: break; default: continue; } } if ((type&EXTERN) == 0) /* enter local symbols now */ { if (xflag || (Xflag && (cursym.sname[0] == '.') && (cursym.sname[1] == 'L'))); else enter(lookup()); continue; } if ((sp = lookup()) == NULL) fatal(e11,cursym.sname,filename); local[symno - 1] = sp; if (cursym.s.stype != EXTERN+UNDEF && (cursym.s.stype != sp->s.stype || cursym.s.svalue != sp->s.svalue)) error(e6, cursym.sname, filename); } fseek(text, sloc+TEXTPOS, 0); fseek(rtext, sloc+RTEXTPOS, 0); load2td(tout, trout, torigin, filhdr.tsize, filhdr.rtsize); fseek(text, sloc+DATAPOS, 0); fseek(rtext, sloc+RDATAPOS, 0); load2td(dout, drout, doffset, filhdr.dsize, filhdr.rdsize); torigin += filhdr.tsize; dorigin += filhdr.dsize; doffset += filhdr.dsize; borigin += filhdr.bsize; } /* load the text or data section of a file performing relocation */ load2td(outf, outrf, txtstart, txtsize, rsize) FILE *outf; /* text or data portion of output file */ FILE *outrf; /* text or data relocation part of output file */ long txtstart; /* initial offset of text or data segment */ long txtsize; /* number of bytes in segment */ long rsize; /* size of appropriate relocation data */ { struct reloc rel; /* the current relocation command */ int size; /* number of bytes to relocate */ long offs; /* value of offset to use */ long rcount; /* number of relocation commands */ long pos = 0; /* current input position */ rcount = rsize/sizeof rel; while(rcount--) /* for each relocation command */ { if (pos >= txtsize) bletch("relocation after end of segment"); dread(&rel, sizeof rel, 1, rtext); switch(rel.rsegment) { case REXT: offs = relext(&rel); break; case RTEXT: offs = torigin; break; case RDATA: offs = dorigin - filhdr.tsize; break; case RBSS: offs = borigin - (filhdr.tsize + filhdr.dsize); break; } if (rel.rdisp) offs -= rel.rpos + txtstart; switch(rel.rsize) { case RBYTE: size = 1; break; case RWORD: size = 2; break; case RLONG: size = 4; break; default: fatal(e12, filename); } if (rel.rpos > txtsize) fatal(e13, filename); else pos = relcmd(pos, rel.rpos, size, offs, outf); if (rflag && rel.rdisp==0) /* write out relocation commands */ { rel.rpos += txtstart; rel.rsymbol = (rel.rsegment == REXT)? local[rel.rsymbol]->sindex: 0; fwrite(&rel, sizeof rel, 1, outrf); } } dcopy(text, outf, txtsize - pos); } /* relext - Find the offset of an REXT command and fix up the rel cmd. */ long relext(r) register struct reloc *r; { register symp sp; /* pointer to symbol for EXT's */ long offs; /* return value */ if ((r->rsymbol < 0 || r->rsymbol >= NSYMPR) || ((sp = local[r->rsymbol]) == NULL)) { error(e19, filename); offs = 0; } else { offs = sp->s.svalue; switch(sp->s.stype & 037) { case TEXT: r->rsegment = RTEXT; break; case DATA: r->rsegment = RDATA; break; case BSS: r->rsegment = RBSS; break; case UNDEF: if (rflag && (sp->s.stype & EXTERN)) { r->rsegment = REXT; break; } default: error(e20, filename, sp->sname); } } return(offs); } /* relcmd - Seek to <position> in file by copying from text to outf, then Add an offset to the next <size> bytes in the text and write out to outf. */ long relcmd(current, position, size, offs, outf) long current; /* current position in file */ long position; /* where in file to perform relocation */ int size; /* number of bytes to fix up */ long offs; /* the number to fix up by */ FILE *outf; /* where to write to */ { register int i, c; long buf = 0; if (position < current) { error(e21, filename); return(current); } dcopy(text, outf, position - current); for (i = 0; i < size; i++) { if ((c = getc(text)) == EOF) fatal(e3, filename); buf = (buf << 8) | (c & 0377); } buf += offs; for (i = size - 1; i >= 0; i--) { c = (buf >> (i * 8)) & 0377; putc(c, outf); } return(position + size); } /* sym_sort - Quick sort of symbols by numerical value for debugger */ sym_sort(l,r,tabs) int l,r; int tabs; { register i,j; register value; struct symbol temp; i = l; j = r; value = symtab[(l+r)/2].s.svalue; do { while (symtab[i].s.svalue < value) i++; while (value < symtab[j].s.svalue) j--; if ((i < j) && (symtab[i].s.svalue != symtab[j].s.svalue)) { temp = symtab[i]; symtab[i] = symtab[j]; symtab[j] = temp; } if (i <= j) { i++; j--; } } while (i <= j); if (l < j) sym_sort(l,j,tabs+1); if (i < r) sym_sort(i,r,tabs+1); } /* finishout Finish off the output file by writing out symbol table */ finishout() { register symp sp; fseek(tout, sizeof filhdr + tsize + dsize, 0); if (qflag) sym_sort(0,symindex-1,0); if (sflag == 0) for (sp = symtab; sp < &symtab[symindex]; sp++) { register int i; register char *cp; fwrite(&sp->s, sizeof sp->s, 1, tout); if ((i = sp->snlength) == 0) bletch("zero length symbol"); cp = sp->sname; while (i--) { if (*cp <= ' ') bletch("bad character in symbol %s",sp->sname); putc(*cp++, tout); } putc('\0', tout); if (ferror(tout)) fatal(e14, ofilename); } fclose(tout); fclose(dout); if (rflag) { fclose(trout); fclose(drout); } #ifndef Stanford if(nund==0) chmod(ofilename, 0777); #endif Stanford } /* getfile - Open an input file as text. Returns the first word of file but leaves the file pointer at zero */ getfile(cp) register char *cp; /* name of the file to open */ { register int c; long magic; #ifndef Stanford char smagic[BKYSARMAG]; #endif Stanford #ifndef Stanford v7_archdr.ar_name[0] = '\0'; bky_archdr.bky_name[0] = '\0'; #else Stanford archdr.ar_name[0] = '\0'; #endif Stanford filename = cp; text = NULL; if (cp[0]=='-' && cp[1]=='l') { if(cp[2] == '\0') cp = "-la"; strcpy(xfilename, ROOT); strcat(xfilename,"/lib/lib"); filename = xfilename; strcpy(filename+strlen(xfilename),cp+2); strcat(filename,".a"); if (vflag=='m') { mfilename = "/usr/sun/dm/lib/libxxxxxxxxxxxxxxx"; strcpy(mfilename+19,cp+2); strcat(mfilename,".a"); if ((rtext=fopen(mfilename)) != NULL) { fclose(rtext); strcpy(filename,mfilename); } } if (vflag=='x') { /* one good kludge deserves another */ mfilename = "/usr/sun/xlib/libxxxxxxxxxxxxxxx"; strcpy(mfilename+17,cp+2); strcat(mfilename,".a"); if ((rtext=fopen(mfilename)) != NULL) { fclose(rtext); strcpy(filename,mfilename); } } } strcpy(tfilename,filename); {int len = strlen(tfilename); if (len < 3 || tfilename[len-1] != BIN && tfilename[len-1] != 'a' || tfilename[len-2] != '.') { strcat(tfilename,"."); strcat(tfilename,BIN); } } if (text == NULL && (text = fopen(tfilename, "r")) == NULL) fatal(e15, filename); if ((rtext = fopen(tfilename, "r")) == NULL) fatal(e15, filename); dread(&magic, sizeof magic, 1, text); #ifndef Stanford fseek(text, 0L, 0); if ((magic == FMAGIC) || ((magic>>16) == ARMAG)) return (magic); dread(smagic, sizeof smagic, 1, text); if (strcmpn(smagic, BKYARMAG, sizeof smagic) == 0) return (BKYARCHIVE); fatal(e23, smagic[0], smagic[1], smagic[2], smagic[3]); #else Stanford fseek(text, 0L, 0); /* reset file pointer */ return magic == FMAGIC || magic == ARCMAGIC? magic: 0; #endif Stanford } /* lookup - Returns the pointer into symtab of a symbol with the same name cursym.sname or NULL if none. */ symp lookup() { return(*hash(cursym.sname)); } /* hash - Return a pointer to where in the hash table a symbol should go. */ symp *hash(s) char *s; { register int i = 0, cmpv; register int initial; register char *cp; /* Note that assuming the character set is ascii, * the hashing algorithm is case-insentive because of the 0xDF. */ i = 0; for (cp = s; *cp;) i = (i<<1) + ((*cp++) & 0xDF); initial = i =(i&077777)%NSYM+2; while(hshtab[i]) { cmpv = (*mystrcmp)(hshtab[i]->sname, cursym.sname); if ((cmpv != 0) || ((hshtab[i]->s.stype & EXTERN) == 0)) { if (++i == NSYM+2) i = 0; } else break; if (i == initial) fatal(e16); } return(&hshtab[i]); } /* slookup - Like lookup but with an arbitrary string argument */ symp slookup(s) char *s; { cursym.sname = s; cursym.snlength = strlen(s); cursym.s.stype = EXTERN+UNDEF; cursym.s.svalue = 0; return(lookup()); } /* enter - Make sure that cursym is installed in symbol table. Called with a pointer to a symbol with the same name or NULL if lookup failed. Returns 1 if the symbol was new, or 0 if it was already present. */ enter(sp) register symp sp; { symp *hp; /* pointer to place in hash table */ if (sp == NULL) { hp = hash(cursym.sname); if (symindex>=NSYM) fatal(e17); lastsym = sp = &symtab[symindex]; if (*hp) bletch("hash table conflict"); *hp = sp; if((sp->sname = (char *)calloc(1, cursym.snlength+1)) == NULL) fatal(e17); strcpy(sp->sname, cursym.sname); if (*(sp->sname) == 0) bletch("null symbol entered"); #ifndef Stanford sp->snlength = cursym.snlength; #else Stanford sp->s.slength = sp->snlength = cursym.snlength; #endif Stanford sp->s.stype = cursym.s.stype; sp->s.svalue = cursym.s.svalue; sp->shash = hp; sp->sindex = symindex++; return(1); } else { lastsym = sp; return(0); } } /* symrel - Perform partial relocation of symbol. Each symbol is relocated twice. The first time, it is adjusted to is relative position within its segment. The second time, it is adjusted by the start of the final segment to which that symbol refers. This routine only performs the first relocation. */ symreloc() { switch (cursym.s.stype) { case TEXT: case EXTERN+TEXT: cursym.s.svalue += ctrel; return; case DATA: case EXTERN+DATA: cursym.s.svalue += cdrel; return; case BSS: case EXTERN+BSS: cursym.s.svalue += cbrel; return; case EXTERN+UNDEF: return; } if (cursym.s.stype&EXTERN) cursym.s.stype = EXTERN+ABS; } /* readhdr - Read in an a.out header, adjusting relocation offsets */ readhdr(pos) long pos; { register long st, sd; fseek(text, pos, 0); dread(&filhdr, sizeof filhdr, 1, text); if (filhdr.fmagic != FMAGIC) fatal(e5a, filename); st = (filhdr.tsize+1) & ~1; filhdr.tsize = st; cdrel = -st; sd = (filhdr.dsize+1) & ~1; cbrel = - (st + sd); filhdr.bsize = (filhdr.bsize+1) & ~1; } /* getsym - Read in a symbol from txt, leaving data in cursym. Return length of stuff read in. */ long getsym() { register int c; register int i; /* read upto name */ fread(&cursym.s, sizeof cursym.s, 1, text); if (feof(text)) fatal(e3, filename); for (i = 0; i < SYMLENGTH; i++) { if ((c = getc(text)) == EOF) fatal(e3, filename); else if ((csymbuf[i] = c) == 0) { if ((cursym.snlength = i) == 0) error(e18, filename); cursym.sname = csymbuf; return(sizeof(cursym.s) + i + 1); } } csymbuf[SYMLENGTH] = '\0'; /* make sure asciz */ return(sizeof(cursym.s) + i); } /* error - Print out error messages and give up if they are severe. */ /*VARARGS1*/ error(fmt, a1, a2, a3, a4, a5) char *fmt; { printf("ld68: "); printf(fmt, a1, a2, a3, a4, a5); printf("\n"); } /* fatal - Print error message and exit */ /*VARARGS1*/ fatal(fmt, a1, a2, a3, a4, a5) char *fmt; { error(fmt, a1, a2, a3, a4, a5); exit(1); } /* bletch - Print out a message and abort. Used for internal errors. */ /*VARARGS1*/ bletch(fmt, a1, a2, a3, a4, a5) char *fmt; { error(fmt, a1, a2, a3, a4, a5); abort(); } /* dread - Like fread but checks for errors and eof */ dread(pos, size, count, file) char *pos; int size; int count; FILE *file; { if (fread(pos, size, count, file) == size * count) return; if (feof(file)) fatal(e3, filename); if (ferror(file)) fatal(e4, filename); } /* dcopy - Copy input to output, checking for errors */ dcopy(in, out, count) FILE *in, *out; long count; { register int c; long n = count; if (n < 0) bletch("bad count to dcopy"); while(n--) { if ((c = getc(in)) == EOF) { if (feof(in)) fatal(e3, filename); if (ferror(out)) fatal(e4, filename); } putc(c, out); } } ]->s.stype & EXTERN) == 0)) { if (++i == NSYM+2) i = 0; } else break; if (i == initial) fatal(e16); } return(&hshtab[i]); } /* slookup - Like lookup but with an arbitrary stringsumacc/cc/ld/ld68.1 444 0 12 12126 3470501561 7147 .TH LD68 1 .SU .SH NAME ld68 \- .b -> b.out linker for the MC68000 .SH SYNOPSIS .B ld68 [ option ] ... file ... .SH DESCRIPTION .I Ld68 combines several object programs into one, resolves external references, and searches libraries. In the simplest case several object .I files are given, and .I ld68 combines them, producing an object module which can be either executed or become the input for a further .I ld68 run. (In the latter case, the .B \-r option must be given to preserve the relocation bits.)\ The output of .I ld68 is left on .BR b.out . This file is made executable only if no errors occurred during the load. .PP The argument routines are concatenated in the order specified. .PP The entry point of the output is determined by the first applicable item of the following list: the \fB\-e\fP option if given, the value of the symbol _start if defined, or the text origin (first instruction). .PP If any argument is a library, it is searched exactly once at the point it is encountered in the argument list. Only those routines defining an unresolved external reference are loaded. If a routine from a library references another routine in the library, the referenced routine must appear after the referencing routine in the library. Thus the order of programs within libraries may be important. .PP The symbols `\_etext', `\_edata' and `\_end' (`etext', `edata' and `end' in C) are reserved, and if referred to, are set to the first location above the program, the first location above initialized data, and the first location above all data respectively. It is erroneous to define these symbols. .PP .I Ld68 understands several options. Except for .BR \-l , they should appear before the file names. .TP .B \-D Take the next argument as a decimal number and pad the data segment with zero bytes to the indicated length. .TP .B \-d Force definition of common storage even if the .B \-r flag is present. .TP .B \-e The following argument is taken to be the name of the entry point of the loaded program; location 0x1000 is the default. .TP .B \-f Fold case on identifiers. That is, upper and lower case letters are not distinguished. Used to link with Pascal routines, for example. .TP .BI \-l x This option is an abbreviation for the library name .RI `/usr/sun/lib/lib x .a', where .I x is a string. A library is searched when its name is encountered, so the placement of a .B \-l is significant. .TP .BI \-v x This denotes board version .I x which may at present only be 'm' for Motorola Design Module. The default board version is the Sun1 prototype, v1. .TP .B \-M Create a human-readable list of symbols in ``sym.out''. .TP .B \-n Arrange (by giving the output file a 0410 "magic number") that when the output file is executed, the text portion will be read-only and shared among all users executing the file. This involves moving the data areas up to the first possible 64K byte boundary following the end of the text (not really useful yet). .TP .B \-o The .I name argument after .B \-o is used as the name of the .I ld68 output file, instead of .BR b.out . .TP .B \-q Quicksort symbols in .BR b.out in ascending numerical order. .TP .B \-r Generate relocation bits in the output file so that it can be the subject of another .I ld68 run. This flag also prevents final definitions from being given to common symbols, and suppresses the `undefined symbol' diagnostics. .TP .B \-S `Strip' the output by removing all symbols except locals and globals. .TP .B \-s `Strip' the output, that is, remove the symbol table and relocation bits to save space (but impair the usefulness of the debuggers). This information can also be removed by .IR strip (1). .TP .B \-T The next argument is a hexadecimal number which sets the text segment origin. The default origin is 0x1000. If you intend to use the output as input to another run of ld68, you must specify -T 0. .TP .B \-B The next argument is a hexadecimal number which sets the common/bss segment origin. The default origin is immediately after the data segment. .TP .B \-u Take the following argument as a symbol and enter it as undefined in the symbol table. This is useful for loading wholly from a library, since initially the symbol table is empty and an unresolved reference is needed to force the loading of the first routine. .TP .B \-X Save local symbols except for those whose names begin with `L'. This option is used by .IR cc (1) to discard internally-generated labels while retaining symbols local to routines. .TP .B \-x Do not preserve local (non-.globl) symbols in the output symbol table; only enter external symbols. This option saves some space in the output file. .SH FILES .ta \w'/usr/local/lib/lib*.a\ \ 'u /usr/sun/lib/lib*.a libraries .br b.out output file .SH "SEE ALSO" ar(1), cc68(1), a68(1) .SH BUGS The b.out format header does not contain any indication of the text segment origin, so if you specify something other than the default origin -T 1000, you will have to remember this value and specify it again to dl68 when you download. The standard Sun monitor cannot netload files with origins other than 1000, so you must either use dl68 or write a special loader for such programs. case EXTERN+BSS: cursym.s.svalue += cbrel; return; case EXTERN+UNDEF: return; } if (cursym.s.stype&EXTERN) cursym.s.stype = EXTERN+ABS; } /* readhdr - Read in an a.out header, adjusting relocation offsets */ readhdr(pos) long pos; { register long st, sd; fseek(text, pos, 0); dread(&filhdr, sizeof filhdr, 1, text); if (filhdr.fmagic != FMAGIC) fatal(e5a, filename); st = (filhdr.tsize+1) & ~1; filhdr.tsumacc/cc/ld/lorder68.1 444 0 12 1500 3470501561 10011 .TH LORDER68 1 .UC 4 .SH NAME lorder68 \- find ordering relation for an MC68000 object library .SH SYNOPSIS .B lorder68 file ... .SH DESCRIPTION The input is one or more object .I files. The standard output is a list of pairs of object file names, meaning that the first file of the pair refers to external identifiers defined in the second. The output may be processed by .IR tsort (1) to find an ordering of a library suitable for one-pass access by .IR ld68 (1). .PP This brash one-liner intends to build a new library from existing `.b' files. .IP ar cr library \`\|lorder68 *.b | tsort\` .SH FILES *symref, *symdef .br nm(1), sed(1), sort(1), join(1) .SH "SEE ALSO" tsort(1), ld68(1), .SH BUGS The names of object files, in and out of libraries, must end with `.b'; nonsense results otherwise. .PP Doesn't handle libraries. , so the placement of a .B \-l is significant. .TP .BI \-v x This denotes board version .I x which may at present only be 'm' for Motorola Design Module. The default board version is the Susumacc/cc/ld/lorder68.sh 555 0 12 643 3470501561 10255 #! /bin/sh trap "rm -f $$sym?ef; exit" 0 1 2 13 15 case $# in 0) echo usage: lorder68 file ... exit ;; 1) case $1 in *.b) set $1 $1 esac esac nm68 -g -f $* | sed ' /^$/d /:$/{ /\.b:/!d s/:// h s/.*/& &/ p d } /[TD] /{ s/.* // G s/\n/ / w '$$symdef' d } s/.* // G s/\n/ / w '$$symref' d ' sort $$symdef -o $$symdef sort $$symref -o $$symref join $$symref $$symdef | sed 's/[^ ]* *//' ry suitable for one-pass access by .IR ld68 (1). .PP This brash one-liner intends to build asumacc/cc/ld/nm68.1 444 0 12 2634 3470501561 7145 .TH NM68 1 .SU .SH NAME nm68 \- print name list of MC68000 object files .SH SYNOPSIS .B nm68 [ .B \-cgnfopruh ] [ file ... ] .SH DESCRIPTION .I Nm68 prints the name list (symbol table) of each object .I file in the argument list. If an argument is an archive, a listing for each object file in the archive will be produced. .PP Each symbol name is preceded by its value in hex and one of the letters .SM .B U (undefined), .SM .B A (absolute), .SM .B T (text segment symbol), .SM .B D (data segment symbol), .SM .B B (bss segment symbol), If the symbol is local (non-external) the type letter is in lower case. The output is sorted alphabetically. .PP Options are: .TP .B \-g Print only global (external) symbols. .TP .B \-n Sort numerically rather than alphabetically. .TP .B \-o Prepend file or archive element name to each output line rather than only once. .TP .B \-p Don't sort; print in symbol-table order. .TP .B \-r Sort in reverse order. .TP .B \-d Print only defined symbols. .TP .B \-u Print only undefined symbols. .TP .B \-h Print values in hex rather than in octal. ( .B \-x is a synonym for .B \-h \.) .TP .B \-c Print only C-style symbols (those beginning with `~' or `_'.) .TP .B \-f Give the name of each object file as it is processed. This implies a .B \-p flag. (If the .B \-p flag is not present, nm68 sorts symbols without regard to which object file they came from.) .SH SEE ALSO ar(1), ar(5), b.out(5) ndefined), .SM .B A (absolute), .SM .B T (text segment symbol), .SM .B D (data segment symbol), .SMsumacc/cc/ld/nm68.c 444 0 12 21364 3470501561 7250 #include <stdio.h> #include "b.out.h" #include "ar.h" /* nm68 Print symbol table Modified: Jeffrey Mogul 10 March 1981 added -f flag; prints filenames if given multiple files, like nm.c Modified: Vaughan Pratt 10 March 1981 added archive capability added -o flag analogous to nm's oflag added -d flag */ /* type and structure definitions */ typedef struct name_seg *nlink; struct name_seg { char *nname; /* pointer to name */ nlink nnext; /* next name in list */ }; /* global variables */ int argnum; /* number of current argument being processed */ nlink namelist = NULL; /* list of filenames to process */ char *filename; /* input file name */ FILE *infile; /* id of input file */ struct bhdr filhdr; /* header of input file */ char cflag = 0; /* list only C-style symbols: those beginning with _ */ char gflag = 0; /* print only external (global) symbols */ char nflag = 0; /* sort by value instead of name */ char fflag = 0; /* print filenames if more than one */ char oflag = 0; /* print filename per symbol */ char pflag = 0; /* don't sort */ char rflag = 0; /* sort in reverse order */ char uflag = 0; /* print only undefined symbols */ char dflag = 0; /* print only defined symbols */ char hflag = 0; /* print in hex rather than octal */ long offset = 0; /* -o option: add offset to value of each symbol */ char *sortname = "/usr/bin/sort"; /* name of command used to sort */ /* Internal functions */ char *nextname(); /* Error Messages */ char *e1 = "filename required following -%c option"; char *e2 = "unrecognized option: %c"; char *e3 = "file %s not found"; char *e4 = "unrecognized magic number %O"; char *e5 = "unrecognized type %o on symbol %s"; char *e6 = "could not reopen pipe as stdout"; char *e7 = "could not reopen pipe as stdin"; char *e8 = "could not exec %s"; char *e9 = "file %s format error, unexpected eof"; char *e10 = "pipe failed"; char *e11 = "dup failed or returned wrong value"; char *e12 = "fork failed"; /************************************************************************* main - process arguments, call major loop and go away *************************************************************************/ main(argc, argv) int argc; char *argv[]; { procargs(argc, argv); startup(); while((filename = nextname()) != NULL) nm(); cleanup(); exit(0); } /************************************************************************* procargs - process command arguments *************************************************************************/ procargs(argc, argv) int argc; char *argv[]; { for (argnum = 1; argnum < argc; argnum++) { if (argv[argnum][0] == '-' ) procflags(&argv[argnum][1], argc, argv); else newname(argv[argnum]); } } /************************************************************************* procflags - process flags *************************************************************************/ procflags(flagptr, argc, argv) char *flagptr; int argc; char *argv[]; { char c; while (c = *flagptr++) switch(c) { case 'c': cflag++; break; case 'd': dflag++; break; case 'f': fflag++; pflag++; break; /* fflag is useless without pflag */ case 'g': gflag++; break; case 'n': nflag++; break; case 'o': oflag++; pflag++; break; case 'p': pflag++; break; case 'r': rflag++; break; case 'u': uflag++; break; case 'x': case 'h': hflag++; break; case 'O': offset = atoi(flagptr); return; default: error(e2, c); } } /************************************************************************* error - type a message on error stream *************************************************************************/ /*VARARGS1*/ error(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr, "nm68: "); fprintf(stderr, fmt, a1, a2, a3, a4, a5); fprintf(stderr, "\n"); } /************************************************************************* fatal - type an error message and abort *************************************************************************/ /*VARARGS1*/ fatal(fmt, a1, a2, a3, a4, a5) char *fmt; { error(fmt, a1, a2, a3, a4, a5); exit(1); } /************************************************************************* startup - Fork off a trailing process to sort symbols. *************************************************************************/ startup() { if (pflag == 0) { char *option1, *option2; /* options to sort */ option1 = (nflag)? "+0": "+2"; /* value or id sort ? */ option2 = (rflag)? "-r": 0; /* reverse order? */ pipeline(sortname, sortname, "-t ", option1, option2, 0); } } /************************************************************************* cleanup - *************************************************************************/ cleanup() { } /************************************************************************* newname - Attach a new name to the list of names in name list. *************************************************************************/ newname(name) char *name; { nlink np1, np2; np1 = (nlink)malloc(sizeof(*np1)); np1->nname = name; np1->nnext = NULL; if (namelist == NULL) namelist = np1; else { np2 = namelist; while(np2->nnext != NULL) np2 = np2->nnext; np2->nnext = np1; } } /************************************************************************* nextname - Return the next name from the list of names being processed. *************************************************************************/ char *nextname() { nlink np; if (namelist == NULL) return(NULL); np = namelist; namelist = np->nnext; return(np->nname); } /************************************************************************* pipeline - Connect a child process stdout via a pipe. *************************************************************************/ /* VARARGS */ pipeline(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { int child; /* proc id of child process */ int fildes[2]; if (pipe(fildes) < 0) fatal(e10); if ((child = fork()) != 0) /* i am parent */ { if (child < 0) fatal(e12); close(0); if (dup(fildes[0]) != 0) fatal(e11); close(fildes[0]); close(fildes[1]); execl(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); fatal(e8); } else /* i am child */ { close(1); if (dup(fildes[1]) != 1) fatal(e11); close(fildes[0]); close(fildes[1]); } } /************************************************************************* nm - Print symbols *************************************************************************/ copytospace(a,b) char *a, *b; { while (*a != ' ') *b++ = *a++; *b++ = 0; } nm() {struct ar_hdr archdr; /* directory part of archive */ long position, n; if (fflag) { /* print names of files as they are seen */ printf("\n%s:\n",filename); } if ((infile = fopen(filename, "r")) == NULL) { error(e3, filename); return; } fread(&filhdr, sizeof filhdr, 1, infile); switch((int)filhdr.fmagic) { case OMAGIC: case FMAGIC: case NMAGIC: case IMAGIC: nmf(SYMPOS,0); break; case ARCMAGIC: position = SARMAG; fseek(infile, SARMAG, 0); /* skip magic */ while (fread(&archdr, sizeof archdr, 1, infile) && !feof(infile)) {char arname[50]; copytospace(archdr.ar_name,arname); fread(&filhdr, sizeof filhdr, 1, infile); /* if (fflag) printf("\narchive file %s\n",arname); */ position += sizeof(archdr); nmf(position + SYMPOS,arname); sscanf(archdr.ar_size,"%d",&n); position += (n+1)&~1; fseek(infile, position, 0); } break; default: error(e4, filhdr.fmagic); return; } fclose(infile); } nmf(sympos,arname) char *arname; { struct sym s; char type; long pos; char symbuf[SYMLENGTH]; register char *sp; register int c; fseek(infile, sympos, 0); for(pos = 0; pos < filhdr.ssize; pos += sizeof s + strlen(symbuf) + 1) { fread(&s, sizeof s, 1, infile); if (feof(infile)) error(e9, filename); for(sp = symbuf; sp < &symbuf[SYMLENGTH - 1]; sp++) { if ((c = getc(infile)) == EOF) { error(e9, filename); return; } if (c == 0) break; *sp = c; } *sp = 0; /* make asciz */ if (cflag) if (symbuf[0] == '~' || symbuf[0] == '_') { register char *cp1 = &symbuf[0]; register char *cp2 = &symbuf[1]; while (*cp1++ = *cp2++); *--cp1 = ' '; } else continue; if (gflag && (s.stype & EXTERN) == 0) continue; if (uflag && (s.stype & 037) != UNDEF) continue; if (dflag && (s.stype & 037) == UNDEF) continue; switch(s.stype & 037) { case UNDEF: type = 'U'; break; case ABS: type = 'A'; break; case TEXT: type = 'T'; break; case DATA: type = 'D'; break; case BSS: type = 'B'; break; default: error(e5, s.stype, symbuf); } s.svalue += offset; if (oflag) {printf("%s:",filename); if (arname) printf("%s:",arname); } if ((s.stype & EXTERN) == 0) type |= 040; if (hflag) printf("%06X %c %s\n",(long)s.svalue,type,symbuf); else printf("%08O %c %s\n", (long)s.svalue, type, symbuf); } } name to the list of names in name list. *************************************************************************/ newname(name) char *name; { nlink np1, np2; np1 = (nlink)malloc(sizeof(*np1)); np1->nname = name; np1->nnext = NULL; if (namelist == NULL) namelistsumacc/cc/ld/pagsiz.h 444 0 12 274 3470501561 7717 #define NBPG 512 #define PGOFSET 511 #define CLSIZE 2 #define CLOFSET 1023 #define BSIZE 1024 #define BMASK 1023 #define BSHIFT 10 #define PAGSIZ (NBPG*CLSIZE) #define PAGRND ((PAGSIZ)-1) OS,arname); sscanf(archdr.ar_size,"%d",&n); position += (n+1)&~1; fseek(infile, position, 0); } break; default: error(e4, filhdr.fmagic); return; } fclose(infile); } nmf(sympos,arname) char *arname; { struct sym s; char type; long pos; char symbuf[SYMLENGTH]; register char *sp; register int c; sumacc/cc/ld/pr68.1 444 0 12 453 3470501561 7131 .TH PR68 1 .SU .SH NAME pr68 \- print extended statistics on .b file .SH SYNOPSIS .B pr68 file .SH DESCRIPTION .I Pr68 prints the header information, symbol table, and relocation commands of a .b or .68 file. Verifies that the text and data segments are multiples of 4. .PP .SH AUTHOR C.J. Terman eak; default: error(e4, filhdr.fmagic); return; } fclose(infile); } nmf(sympos,arname) char *arname; { struct sym s; char type; long pos; char symbuf[SYMLENGTH]; register char *sp; register int c; sumacc/cc/ld/pr68.c 444 0 12 5546 3470501562 7244 #include <stdio.h> #include "b.out.h" FILE *in; struct bhdr bhdr; main(argc,argv) int argc; char *argv[]; { if (argc != 2) error('f',"Usage: pr68 filename"); in = fopen(argv[1],"r"); if (in == NULL) error('f',"Couldn't open %s for input",argv[1]); header(); text(); data(); symbols(); rtext(); rdata(); } header() { if (fread(&bhdr,sizeof bhdr,1,in) != 1) error('w',"error reading header"); printf("Magic Number: %ld\n",bhdr.fmagic); printf("Text Size: %ld bytes\n",bhdr.tsize); printf("Data Size: %ld bytes\n",bhdr.dsize); printf("BSS Size: %ld bytes\n",bhdr.bsize); printf("Symbol Table Size: %ld bytes\n",bhdr.ssize); printf("Text Relocation Size: %ld bytes\n",bhdr.rtsize); printf("Data Relocation Size: %ld bytes\n",bhdr.rdsize); printf("Entry Location: %ld\n",bhdr.entry); } text() { long i; char l[4]; printf("\nText Segment\n"); if (bhdr.tsize%4 != 0) error('w',"text size not multiple of 4"); for (i=0; i<bhdr.tsize; i+=4) { if (fread(l,sizeof l,1,in) != 1) error('w',"read error in text section"); /* printf("%ld: %3d %3d %3d %3d\n",i,l[0],l[1],l[2],l[3]); */ } } data() { long i; char l[4]; printf("\nData Segment\n"); if (bhdr.tsize%4 != 0) error('w',"data size not multiple of 4"); for (i=0; i<bhdr.dsize; i+=4) { if (fread(l,sizeof l,1,in) != 1) error('w',"read error in text section"); /* printf("%ld: %3d %3d %3d %3d\n",i,l[0],l[1],l[2],l[3]); */ } } symbols() { short count = 0; long i; struct sym sym; char s[SYMLENGTH],*sp; printf("\nSymbol Table\n"); for (i=0; i < bhdr.ssize; i+=sizeof sym) { if (fread(&sym,sizeof sym,1,in) != 1) error('w',"read error in symbol table section"); for (sp=s; *sp = getc(in); sp++) i++; i++; printf("%d: %c%c %ld %s\n",count++, " E??????"[sym.stype/040], "UATDBCR?????????????????????????"[sym.stype&037], sym.svalue,s); } } rtext() { long i; struct reloc reloc; printf("\nText Relocation Commands\n"); for (i=0; i<bhdr.rtsize; i+=sizeof reloc) { if (fread(&reloc,sizeof reloc,1,in) != 1) error('w',"error reading text relocation commands"); printf("%c %c %c %d %ld\n","TDBE"[reloc.rsegment], "BWL?"[reloc.rsize]," D"[reloc.rdisp],reloc.rsymbol, reloc.rpos); } } rdata() { long i; struct reloc reloc; printf("\nData Relocation Commands\n"); for (i=0; i<bhdr.rdsize; i+=sizeof reloc) { if (fread(&reloc,sizeof reloc,1,in) != 1) error('w',"error reading data relocation commands"); printf("%c %c %c %d %ld\n","TDBE"[reloc.rsegment], "BWL?"[reloc.rsize]," D"[reloc.rdisp],reloc.rsymbol, reloc.rpos); } } /* VARAGRS 2 */ error(t,s,a,b,c,d,e,f,g,h,i,j) char t; char *s; { fprintf(stderr,"pr68: "); fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j); fprintf(stderr,"\n"); switch (t) { case 'w': return; case 'f': exit(1); case 'a': abort(); default: error('w',"Illegal error type: '%c'",t); } } arent */ { if (child < 0) fatal(e12); close(0); if (dup(fildes[0]) != 0) fatal(e11); close(fildes[0]); close(fildes[1]); execl(a0, a1, a2, a3sumacc/cc/ld/ranlib68.c 444 0 12 13170 3470501562 10102 /* * ranlib - create table of contents for archive; string table version * Version hacked up to handle 68000 .b files * Per Bothner. May 1983. */ #include <sys/types.h> #include <ar.h> #include <ranlib.h> #include "pagsiz.h" #include <b.out.h> #undef OMAGIC #undef NMAGIC #undef FMAGIC #undef IMAGIC #include <a.out.h> /* Note that OMAGIC in a.out.h is 0407 and in b.out.h is 0405 ! */ #include <stdio.h> struct ar_hdr archdr; #define OARMAG 0177545 long arsize; struct exec exp; FILE *fi, *fo; long off, oldoff; long atol(), ftell(); #define TABSZ 5000 struct ranlib tab[TABSZ]; int tnum; #define STRTABSZ 75000 char tstrtab[STRTABSZ]; int tssiz; char *strtab; int ssiz; int new; char tempnm[] = "__.SYMDEF"; char firstname[17]; main(argc, argv) char **argv; { char cmdbuf[BUFSIZ]; char magbuf[SARMAG+1]; --argc; while(argc--) { fi = fopen(*++argv,"r"); if (fi == NULL) { fprintf(stderr, "ranlib: cannot open %s\n", *argv); continue; } off = SARMAG; fread(magbuf, 1, SARMAG, fi); if (strncmp(magbuf, ARMAG, SARMAG)) { if (*(int *)magbuf == OARMAG) fprintf(stderr, "old format "); else fprintf(stderr, "not an "); fprintf(stderr, "archive: %s\n", *argv); continue; } fseek(fi, 0L, 0); new = tnum = 0; if (nextel(fi) == 0) { fclose(fi); continue; } do { /* for each component ... */ long o; fread((char *)&exp, 1, sizeof(struct exec), fi); if (N_BADMAG(exp)) continue; if (exp.a_syms == 0) { fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name); continue; } o = N_STROFF(exp) - sizeof (struct exec); if (strcmp(archdr.ar_name+strlen(archdr.ar_name)-2, ".o")) parse_b_out_syms(); else if (ftell(fi)+o+sizeof(ssiz) >= off) { fprintf(stderr, "ranlib: %s(%s): old format .o file\n", *argv, archdr.ar_name); exit(1); } else { fseek(fi, o, 1); parse_a_out_syms(); } } while(nextel(fi)); new = fixsize(); fclose(fi); fo = fopen(tempnm, "w"); if(fo == NULL) { fprintf(stderr, "can't create temporary\n"); exit(1); } tnum *= sizeof (struct ranlib); fwrite(&tnum, 1, sizeof (tnum), fo); tnum /= sizeof (struct ranlib); fwrite((char *)tab, tnum, sizeof(struct ranlib), fo); fwrite(&tssiz, 1, sizeof (tssiz), fo); fwrite(tstrtab, tssiz, 1, fo); fclose(fo); if(new) sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm); else sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm); if(system(cmdbuf)) fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf); else fixdate(*argv); unlink(tempnm); } exit(0); } parse_a_out_syms() { register n; struct nlist sym; fread((char *)&ssiz, 1, sizeof (ssiz), fi); strtab = (char *)calloc(1, ssiz); if (strtab == 0) { fprintf(stderr, "ranlib: ran out of memory\n"); exit(1); } fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi); fseek(fi, -(exp.a_syms+ssiz), 1); n = exp.a_syms / sizeof(struct nlist); while (--n >= 0) { fread((char *)&sym, 1, sizeof(sym), fi); if (sym.n_un.n_strx == 0) continue; sym.n_un.n_name = strtab + sym.n_un.n_strx; if ((sym.n_type&N_EXT)==0) continue; if (sym.n_type&N_TYPE != N_UNDF || sym.n_value!=0) stash(sym.n_un.n_name); } } parse_b_out_syms() { struct sym bsym; #define filhdr (*(struct bhdr *)&exp) fseek(fi, SYMPOS - TEXTPOS, 1); while (exp.a_syms > 0) { fread(&bsym, sizeof(bsym), 1, fi); exp.a_syms -= sizeof(bsym); if (tssiz + bsym.slength >= STRTABSZ) { fprintf(stderr, "ranlib: string table overflow\n"); exit(1); } fread(tstrtab + tssiz, bsym.slength, 1, fi); exp.a_syms -= bsym.slength; getc(fi); exp.a_syms--; /* skip null byte */ if (bsym.stype & EXTERN && (bsym.stype & 0xF || bsym.svalue)) { if (tnum >= TABSZ) { fprintf(stderr, "ranlib: symbol table overflow\n"); exit(1); } tab[tnum].ran_un.ran_strx = tssiz; tab[tnum].ran_off = oldoff; tnum++; tssiz += bsym.slength; tstrtab[tssiz++] = 0; } } } nextel(af) FILE *af; { register r; register char *cp; oldoff = off; fseek(af, off, 0); r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); if (r != sizeof(struct ar_hdr)) return(0); for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++) if (*cp == ' ') *cp = '\0'; archdr.ar_name[sizeof(archdr.ar_name)] = 0; arsize = atol(archdr.ar_size); if (arsize & 1) arsize++; off = ftell(af) + arsize; return(1); } stash(s) register char *s; { int i; if(tnum >= TABSZ) { fprintf(stderr, "ranlib: symbol table overflow\n"); exit(1); } tab[tnum].ran_un.ran_strx = tssiz; tab[tnum].ran_off = oldoff; while (tstrtab[tssiz++] = *s++) if (tssiz > STRTABSZ) { fprintf(stderr, "ranlib: string table overflow\n"); exit(1); } tnum++; } fixsize() { int i; off_t offdelta; if (tssiz&1) tssiz++; offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) + sizeof (tssiz) + tssiz; off = SARMAG; nextel(fi); if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) { new = 0; offdelta -= sizeof(archdr) + arsize; } else { new = 1; strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name)); } for(i=0; i<tnum; i++) tab[i].ran_off += offdelta; return(new); } /* patch time */ fixdate(s) char *s; { long time(); char buf[24]; int fd; fd = open(s, 1); if(fd < 0) { fprintf(stderr, "ranlib: can't reopen %s\n", s); return; } sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0); write(fd, buf, sizeof(archdr.ar_date)); close(fd); } e+strlen(archdr.ar_name)-2, ".o")) parse_b_out_syms(); else if (ftell(fi)+o+sizeof(ssiz) >= off) { fprintf(stderr, "ranlib: %s(%s): old format .o file\n", *argv, archdr.ar_name); exit(1); } else { fseek(fi, o, 1); parse_a_out_syms(); } } while(nextel(fi)); new = fixsize(); fclose(fi); fo = fopen(tempnm, "w"); if(fo == NULL) { fprintf(stderr,sumacc/cc/ld/rev68.1 444 0 12 2360 3470501562 7324 .TH REV68 1 .SU .SH NAME rev68 \- reverse byte order in 68000 .b and .68 (b.out) files .SH SYNOPSIS .B rev68 infile [ outfile ... ] .SH DESCRIPTION .I Rev68 translates .b and .68 (b.out) files into a form readable by the 68000. This entails reversing the byte order within short and long words, and rearranging structs to agree with the c68 interpretation of structs. .PP The transformations that take place are: the 8 longs in the header (including the magic number) are each byte reversed; the text and data segments are unchanged; the symbol segment is modified so that the struct defining the type and value of the symbol fits in 6 bytes instead of 8 (to agree with the c68 interpretation of struct sym in /usr/sun/ld68/b.out.h); each symbol is padded with an extra 0 if necessary to force word alignment; and the relocation commands are repacked to agree with the c68 interpretation of struct reloc in /usr/sun/ld68/b.out.h. .PP The output is written to outfile, which if not specified defaults to r.out. The output will be smaller than the input unless there are no symbols or relocation commands. .PP The intent is that r.out files not be the input to any Unix program, but that they be sent directly to the 68000 as a byte stream. .SH AUTHOR V.R. Pratt return(new); } /* patch time */ fixdate(s) char *s; { long time(); char buf[24]; int fd; fd = open(s, 1); if(fd < 0) { fprintf(stderr, "ranlib: can't reopen %s\n", s); return; } sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); lseek(sumacc/cc/ld/rev68.c 544 0 12 7505 3470501562 7415 /* Reformat b.out file so that longs are byte-reversed to permit convenient reading by the 68000. Relocation commands are fixed to agree with the c68 convention for packing fields, to permit reuse of struct reloc. Author: V.R. Pratt Date: March, 1981 */ #include "b.out.h" #include <stdio.h> struct sym68 { /* fake sym for 68000 */ short dummy1; /* ignored */ char stype; /* type */ char slength; /* length */ long svalue; }; struct reloc68 { /* fake reloc for 68000 */ unsigned dummy1:3; /* to complete the byte */ unsigned rdisp:1; /* 1 => a displacement */ unsigned rsize:2; /* RBYTE, RWORD, or RLONG */ unsigned rsegment:2; /* RTEXT, RDATA, RBSS, or REXTERN */ char dummy2; /* needs to be zero */ short rsymbol; /* id of the symbol of external relocations */ long rpos; /* position of relocation in segment */ }; reverse(lwrd) unsigned lwrd; {return((lwrd>>24) | (lwrd>>8 & 0xff00) | (lwrd<<8 & 0xff0000)| (lwrd<<24) ); } sreverse(wrd) unsigned wrd; {return((wrd>>8 & 0xff) | (wrd<<8 & 0xff00) ); } #define RCDSIZE 256 outbin(file,size,ofile) FILE *file, *ofile; { int count, /* counts total number of bytes processed*/ Dcount; /* number of bytes in current record */ char buffer[RCDSIZE]; /* buffer for data */ for(count=0; count<size; count += RCDSIZE) {Dcount= (size-count<RCDSIZE) ? size-count : RCDSIZE; if(fread(buffer,Dcount,1,file) != 1) {printf("Read error\n"); exit(1);} fwrite(buffer,Dcount,1,ofile); } } struct reloc relcom; struct reloc68 orelcom; main(argc,argv) int argc; char *argv[]; { struct bhdr filhdr, nfilhdr; FILE *infile, *outfile; char filename[30], ofilename[30]; int i; struct sym s; struct sym68 s68; char c; int pos, poso=0; if(argc<2) {printf("Usage: rev68 filename [ outfile ]\n"); /* Default: r.out */ exit(1); } strcpy(filename,argv[1]); /* extract file name */ if((infile=fopen(filename,"r"))==NULL) /* open object file*/ {strcat(filename,".68"); /* try .68 form */ if ((infile=fopen(filename,"r"))==NULL) {printf("rev68: Can't open %s\n",filename); exit(1); } } if(fread(&filhdr, sizeof(struct bhdr),1,infile) != 1) {printf("rev68: %s wrong format\n",filename);/*get header information*/ exit(1); } if(filhdr.fmagic != FMAGIC && filhdr.fmagic != NMAGIC) /* check magic number */ {printf("rev68: %s not proper .68 file\n",filename); exit(1);} if (argc >= 3) strcpy(ofilename, argv[2]); else strcpy(ofilename, "r.out"); if ((outfile = fopen(ofilename,"w")) == NULL) {printf("rev68: Can't write %s\n", ofilename); exit(1); } {int n, *hdr = (int*)&filhdr, *nhdr = (int*)&nfilhdr; for (n=0; n<8; n++) *nhdr++ = reverse(*hdr++); /* even reverse magic */ } fwrite(&nfilhdr, sizeof(struct bhdr), 1, outfile); outbin(infile, filhdr.tsize + filhdr.dsize, outfile); for (pos=0; pos < filhdr.ssize; ) {if (!fread(&s,sizeof s,1,infile)) break;/* Get symbol descriptor */ pos += sizeof s; s68.stype = s.stype; s68.slength = s.slength; s68.svalue = reverse(s.svalue); fwrite((int)&s68+2,6,1,outfile); poso += 6; while (c = getc(infile)) {putc(c, outfile); pos++; poso++; } putc(0, outfile); pos++; poso++; if (poso&1) {putc(0, outfile); /* word align for 68000 */ poso++; } } while (fread(&relcom, sizeof relcom,1,infile)) {orelcom.rdisp = relcom.rdisp; orelcom.rsize = relcom.rsize; orelcom.rsegment = relcom.rsegment; orelcom.rsymbol = sreverse(relcom.rsymbol); orelcom.rpos = reverse(relcom.rpos); orelcom.dummy1 = 0; orelcom.dummy2 = 0; fwrite(&orelcom, sizeof orelcom, 1, outfile); } poso = reverse(poso); fseek(outfile, 16, 0); fwrite(&poso, sizeof poso, 1, outfile); /* adjust filhdr.ssize */ fclose(infile); fclose(outfile); } ake sym for 68000 */ short dummy1; /* ignored */ char stype; /* type */ char slength; /* length */ long svalue; }; struct reloc68 { /* fake reloc for 68000 */ unsigned dummy1:3;sumacc/cc/ld/rl68.1 444 0 12 2124 3470501562 7143 .TH RL68 1 .SU .SH NAME rl68 \- print relocation commands in a .b file for the 68000 .SH SYNOPSIS .B rl68 infile .SH DESCRIPTION .I Rl68 prints the relocation commands in a 68000 .b file. The format for each command is: .PP AREA SEGMENT SIZE Displacement Symbol .PP The AREA is one of T or D according to whether the command acts on Text or Data. The SEGMENT is one of T, D, B, or E, according to whether the object linked to is in Text, Data, or Bss, or is External. The SIZE is one of B, W, or L, according to whether the object linked to is of size Byte, Word, or Long. The Displacement indicates where in the AREA the command is to be applied. The Symbol is the symbolic name of the object linked to if any. .PP The correspondence with struct reloc (defined in /usr/sun/ld68/b.out.h) is as follows. SEGMENT is rsegment and SIZE is rsize. Displacement is rdisp. Symbol is determined from rsymbol, a short which is the symbol id. AREA is determined by the area in which the relocation command is found, there being two such areas. .SH RELATED nm68, size68, pr68, lorder68 .SH AUTHOR C.J. Terman ) FILE *file, *ofile; { int count, /* counts total number of bytes processed*/ Dcount; /* number of bytes in current record */ char buffer[RCDSIZE]; /* buffer for data */ for(count=0; count<size; count += RCDSIZE) {Dcount= (size-count<RCDSIZE) ? size-count : RCDSIZE; if(fread(buffer,Dcount,1,file) != 1) {printf("Read error\n"); exit(1);} fwrite(buffer,Dcount,1,ofile); } } struct reloc relcom; strusumacc/cc/ld/rl68.c 444 0 12 17312 3470501562 7252 #include <stdio.h> #include "b.out.h" /* rl68 - Print relocation commands */ #define NSYM 1000 /* number of symbols */ /* type and structure definitions */ struct symbol { struct sym s; char *sname; int snlength; }; typedef struct symbol *symp; typedef struct name_seg *nlink; struct name_seg { char *nname; /* pointer to name */ nlink nnext; /* next name in list */ }; /* global variables */ struct symbol symtab[NSYM]; int nextsym = 0; /* next free slot in symbol table */ int argnum; /* number of current argument being processed */ nlink namelist = NULL; /* list of filenames to process */ char *filename; /* input file name */ FILE *infile; /* id of input file */ struct bhdr filhdr; /* header of input file */ char cflag = 0; /* list only C-style symbols: those beginning with _ */ char gflag = 0; /* print only external (global) symbols */ char nflag = 0; /* sort by value instead of name */ char pflag = 0; /* don't sort */ char rflag = 0; /* sort in reverse order */ char uflag = 0; /* print only undefined symbols */ char *sortname = "/bin/sort"; /* name of command used to sort */ /* Internal functions */ char *nextname(); /* Error Messages */ char *e1 = "filename required following -%c option"; char *e2 = "unrecognized option: %c"; char *e3 = "file %s not found"; char *e4 = "unrecognized magic number %O"; char *e5 = "unrecognized type %o on symbol %s"; char *e6 = "could not reopen pipe as stdout"; char *e7 = "could not reopen pipe as stdin"; char *e8 = "could not exec %s"; char *e9 = "file %s format error, unexpected eof"; char *e10 = "pipe failed"; char *e11 = "dup failed or returned wrong value"; char *e12 = "fork failed"; char *e13 = "symbol table overflow"; /************************************************************************* main - process arguments, call major loop and go away *************************************************************************/ main(argc, argv) int argc; char *argv[]; { procargs(argc, argv); startup(); while((filename = nextname()) != NULL) { if ((infile = fopen(filename, "r")) == NULL) { error(e3, filename); continue; } fread(&filhdr, sizeof filhdr, 1, infile); switch((int)filhdr.fmagic) { case FMAGIC: case NMAGIC: break; default: error(e4, filhdr.fmagic); continue; } getsyms(); printcmds(); fclose(infile); } cleanup(); exit(0); } /************************************************************************* procargs - process command arguments *************************************************************************/ procargs(argc, argv) int argc; char *argv[]; { for (argnum = 1; argnum < argc; argnum++) { if (argv[argnum][0] == '-' ) procflags(&argv[argnum][1], argc, argv); else newname(argv[argnum]); } } /************************************************************************* procflags - process flags *************************************************************************/ procflags(flagptr, argc, argv) char *flagptr; int argc; char *argv[]; { char c; while (c = *flagptr++) switch(c) { default: error(e2, c); } } /************************************************************************* error - type a message on error stream *************************************************************************/ /*VARARGS1*/ error(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr, "rl68: "); fprintf(stderr, fmt, a1, a2, a3, a4, a5); fprintf(stderr, "\n"); } /************************************************************************* fatal - type an error message and abort *************************************************************************/ /*VARARGS1*/ fatal(fmt, a1, a2, a3, a4, a5) char *fmt; { error(fmt, a1, a2, a3, a4, a5); exit(1); } /************************************************************************* startup - Fork off a trailing process to sort symbols. *************************************************************************/ startup() { } /************************************************************************* cleanup - *************************************************************************/ cleanup() { } /************************************************************************* newname - Attach a new name to the list of names in name list. *************************************************************************/ newname(name) char *name; { nlink np1, np2; np1 = (nlink)malloc(sizeof(*np1)); np1->nname = name; np1->nnext = NULL; if (namelist == NULL) namelist = np1; else { np2 = namelist; while(np2->nnext != NULL) np2 = np2->nnext; np2->nnext = np1; } } /************************************************************************* nextname - Return the next name from the list of names being processed. *************************************************************************/ char *nextname() { nlink np; if (namelist == NULL) return(NULL); np = namelist; namelist = np->nnext; return(np->nname); } /************************************************************************* pipeline - Connect a child process stdout via a pipe. *************************************************************************/ /* VARARGS */ pipeline(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { int child; /* proc id of child process */ int fildes[2]; if (pipe(fildes) < 0) fatal(e10); if ((child = fork()) != 0) /* i am parent */ { if (child < 0) fatal(e12); close(0); if (dup(fildes[0]) != 0) fatal(e11); close(fildes[0]); close(fildes[1]); execl(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); fatal(e8); } else /* i am child */ { close(1); if (dup(fildes[1]) != 1) fatal(e11); close(fildes[0]); close(fildes[1]); } } /************************************************************************* getsyms - Read in the symbol table. *************************************************************************/ getsyms() { struct sym s; char type; long pos; char symbuf[SYMLENGTH]; struct symbol *sp; register char *scp; register int c; int slength; fseek(infile, (long)(SYMPOS), 0); for(pos = 0; pos < filhdr.ssize; pos += sizeof(sp->s) + slength + 1) { if (nextsym >= NSYM) error(e13); sp = &symtab[nextsym++]; fread(&sp->s, sizeof sp->s, 1, infile); if (feof(infile)) error(e9, filename); slength = 0; for(scp = symbuf; scp < &symbuf[SYMLENGTH - 1]; scp++) { if ((c = getc(infile)) == EOF) { error(e9, filename); return; } if (c == 0) break; *scp = c; slength++; } *scp = 0; /* make asciz */ sp->snlength = slength; sp->sname = (char*)calloc(1, slength+1); strcat(sp->sname, symbuf); } } /************************************************************************* printcmds - Print relocation commands. *************************************************************************/ printcmds() { long size; struct reloc rcmd; fseek(infile, RTEXTPOS, 0); for (size = 0; size < filhdr.rtsize; size += sizeof(rcmd)) cmd('T'); fseek(infile, RDATAPOS, 0); for (size = 0; size < filhdr.rdsize; size += sizeof(rcmd)) cmd('D'); } /************************************************************************* cmd - Read and print one command. *************************************************************************/ cmd(area) int area; { struct reloc rcmd; char seg, size; char *sym; char idbuf[100]; fread(&rcmd, sizeof(rcmd), 1, infile); if (feof(infile)) error(e9, filename); if (ferror(infile)) error(e9, filename); seg = "TDBE"[rcmd.rsegment]; size = "BWL?"[rcmd.rsize]; if (seg == 'E') { if (rcmd.rsymbol >= 0 && rcmd.rsymbol < nextsym) sym = symtab[rcmd.rsymbol].sname; else { sprintf(idbuf,"??????? bad symbol id %d",rcmd.rsymbol); sym = idbuf; } printf("%c %c %c %011O %s\n",area,seg,size,rcmd.rpos,sym); } else printf("%c %c %c %011O\n", area, seg, size, rcmd.rpos); } ******************************************* startup - Fork off a trailing process to sort symbols. *************************************************************************/ startup() { } /************************************************************************* cleanup - ***************************sumacc/cc/ld/size68.1 444 0 12 1136 3470501563 7503 .TH SIZE68 1 .SU .SH NAME size68 \- prints sizes of segments in a .b or .68 file .SH SYNOPSIS .B size68 [ -hl ] file .SH DESCRIPTION .I Size68 prints the sizes of the text, data, and bss segments of a .b or .68 file, in decimal; the total size is also given in both decimal and octal. The -h flag causes the sizes to be given in hexadecimal. The -l flag causes a complete printout in decimal (hex if -h is given) of the values of the 8 header words, namely the magic number, the sizes of the three segments, the size of the symbol table, and the sizes of the relocation commands. .SH AUTHOR C.J. Terman .B size68 [ -hl ] file .SH DESCRIPTION .I Size68 prints the sizes of the text, data, and bss segments of a .b or .68 file, in decimal; the total size is also given in both decimal and octal. The -h flag causes the sizes to be given in hexadecimal. The -l flag causes a complete printout in decimal (hex if -h is given) of the values of the 8 header words, namely the magic number, the sizes of the three segments, tsumacc/cc/ld/size68.c 444 0 12 14574 3470501563 7617 #include <stdio.h> #include "b.out.h" /* sizer68 [-hl] <file1> ... <filen> Print sizes of segments. -h print in hex format -l print long format */ /* type and structure definitions */ typedef struct name_seg *nlink; struct name_seg { char *nname; /* pointer to name */ nlink nnext; /* next name in list */ }; /* global variables */ int argnum; /* number of current argument being processed */ nlink namelist = NULL; /* list of filenames to process */ char *filename; /* input file name */ FILE *infile; /* id of input file */ char hflag = 0; /* print in hex */ char lflag = 0; /* print long form */ char nflag = 0; /* print names of files */ char rflag = 0; /* .r file */ struct bhdr filhdr; /* header of input file */ /* Internal functions */ char *nextname(); /* Error Messages */ char *e1 = "filename required following -%c option"; char *e2 = "unrecognized option: %c"; char *e3 = "file %s not found"; char *e4 = "unrecognized magic number %O"; char *e5 = "unrecognized type %o on symbol %s"; char *e6 = "could not reopen pipe as stdout"; char *e7 = "could not reopen pipe as stdin"; char *e8 = "could not exec %s"; char *e9 = "file %s format error, unexpected eof"; char *e10 = "pipe failed"; char *e11 = "dup failed or returned wrong value"; char *e12 = "fork failed"; /************************************************************************* main - process arguments, call major loop and go away *************************************************************************/ main(argc, argv) int argc; char *argv[]; { procargs(argc, argv); startup(); while((filename = nextname()) != NULL) size(); cleanup(); exit(0); } /************************************************************************* procargs - process command arguments *************************************************************************/ procargs(argc, argv) int argc; char *argv[]; { if (argc > 2) nflag = 1; for (argnum = 1; argnum < argc; argnum++) { if (argv[argnum][0] == '-' ) procflags(&argv[argnum][1], argc, argv); else newname(argv[argnum]); } } /************************************************************************* procflags - process flags *************************************************************************/ procflags(flagptr, argc, argv) char *flagptr; int argc; char *argv[]; { char c; while (c = *flagptr++) switch(c) { case 'h': hflag = 1; break; case 'l': lflag = 1; break; case 'n': nflag = 1; break; default: error(e2, c); } } /************************************************************************* error - type a message on error stream *************************************************************************/ /*VARARGS1*/ error(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr, "size68: "); fprintf(stderr, fmt, a1, a2, a3, a4, a5); fprintf(stderr, "\n"); } /************************************************************************* fatal - type an error message and abort *************************************************************************/ /*VARARGS1*/ fatal(fmt, a1, a2, a3, a4, a5) char *fmt; { error(fmt, a1, a2, a3, a4, a5); exit(1); } /************************************************************************* startup - Fork off a trailing process to sort symbols. *************************************************************************/ startup() { } /************************************************************************* cleanup - *************************************************************************/ cleanup() { } /************************************************************************* newname - Attach a new name to the list of names in name list. *************************************************************************/ newname(name) char *name; { nlink np1, np2; np1 = (nlink)malloc(sizeof(*np1)); np1->nname = name; np1->nnext = NULL; if (namelist == NULL) namelist = np1; else { np2 = namelist; while(np2->nnext != NULL) np2 = np2->nnext; np2->nnext = np1; } } /************************************************************************* nextname - Return the next name from the list of names being processed. *************************************************************************/ char *nextname() { nlink np; if (namelist == NULL) return(NULL); np = namelist; namelist = np->nnext; return(np->nname); } /************************************************************************* size - Print segment sizes *************************************************************************/ size() { long t; if ((infile = fopen(filename, "r")) == NULL) { error(e3, filename); return; } fread(&filhdr, sizeof filhdr, 1, infile); switch(filhdr.fmagic) { default: rflag++; switch(reverse(filhdr.fmagic)) { case OMAGIC: case FMAGIC: case NMAGIC: case IMAGIC: break; default: error(e4, filhdr.fmagic); fclose(infile); return; } case OMAGIC: case FMAGIC: case NMAGIC: case IMAGIC: break; } t = reverse(filhdr.tsize) + reverse(filhdr.dsize) + reverse(filhdr.bsize); if (nflag) { printf("%s: ", filename); if (lflag) printf("\n"); } if (hflag) { if (lflag) { printf("fmagic:\t0%O\n", filhdr.fmagic); printf("tsize:\t0x%X\n", reverse(filhdr.tsize)); printf("dsize:\t0x%X\n", reverse(filhdr.dsize)); printf("bsize:\t0x%X\n", reverse(filhdr.bsize)); printf("ssize:\t0x%X\n", reverse(filhdr.ssize)); printf("rtsize:\t0x%X\n", reverse(filhdr.rtsize)); printf("rdsize:\t0x%X\n", reverse(filhdr.rdsize)); printf("entry:\t0x%X\n", reverse(filhdr.entry)); } else printf("0x%X+0x%X+0x%X = %D = 0x%X\n", reverse(filhdr.tsize), reverse(filhdr.dsize), reverse(filhdr.bsize), t, t); } else { if (lflag) { printf("fmagic:\t0%O\n", filhdr.fmagic); printf("tsize:\t%D\n", reverse(filhdr.tsize)); printf("dsize:\t%D\n", reverse(filhdr.dsize)); printf("bsize:\t%D\n", reverse(filhdr.bsize)); printf("ssize:\t%D\n", reverse(filhdr.ssize)); printf("rtsize:\t%D\n", reverse(filhdr.rtsize)); printf("rdsize:\t%D\n", reverse(filhdr.rdsize)); printf("entry:\t0%O\n", reverse(filhdr.entry)); } else printf("%D+%D+%D = %D = 0%O\n", reverse(filhdr.tsize), reverse(filhdr.dsize), reverse(filhdr.bsize), t, t); } fclose(infile); } reverse(lwrd) unsigned lwrd; { if (rflag) return (lwrd>>24) | (lwrd>>8 & 0xff00) | (lwrd<<8 & 0xff0000)| (lwrd<<24); else return lwrd; } e; np1->nnext = NULL; if (namelist == NULL) namelist = np1; else { np2 = namelist; while(np2->nnext != NULL) np2 = np2->nnext;sumacc/cc/lorder68.sh 444 0 12 643 3470501563 7655 #! /bin/sh trap "rm -f $$sym?ef; exit" 0 1 2 13 15 case $# in 0) echo usage: lorder68 file ... exit ;; 1) case $1 in *.b) set $1 $1 esac esac nm68 -g -f $* | sed ' /^$/d /:$/{ /\.b:/!d s/:// h s/.*/& &/ p d } /[TD] /{ s/.* // G s/\n/ / w '$$symdef' d } s/.* // G s/\n/ / w '$$symref' d ' sort $$symdef -o $$symdef sort $$symref -o $$symref join $$symref $$symdef | sed 's/[^ ]* *//' ******************************************/ cleanup() { } /******************************sumacc/cc/makefile 444 0 12 1356 3470503024 7370 # sun command makefile # Bill Nowicki December 1981 # merged a bunch of uncommented files # March 15, 1982 (win) changed /usr/bin to /usr/sun/bin DESTDIR= /usr/sun/bin all : cc68 compiler assembler loader install cc68: cc68.c cc -o cc68 cc68.c compiler: cd ccom; make assembler: cd as; make loader: cd ld; make install: install-cc68 \ install-compiler install-assembler install-loader $(DESTDIR)/lorder68 install-cc68: cp cc68 $(DESTDIR)/cc68 install-compiler: cd c2; make install cd ccom; make install install-assembler: cd as; make install install-loader: cd ld; make install clean: rm -f dll cc68 dlx *.b *.o *BAK *CKP -cd as; make clean -cd c2; make clean -cd ccom; make clean -cd ddt68; make clean -cd ld; make clean nlink)malloc(sizeof(*np1)); np1->nname = name; np1->nnext = NULL; if (namelist == NULL) namelist = np1; else { np2 = namelist; while(np2->nnext != NULL) np2 = np2->nnext; np2->nnext = np1; } } /********************************************************************sumacc/cc/cc68.c 444 0 12 36516 3470501563 6633 /* * cc68 - front end for MC68000 C compiler * * Jeffrey Mogul @ Stanford February 10 1981 * - hacked up from cc.c * * V. Pratt March 1981 * -v (version), -d (dl68), -r (rev68) options * * Bill Nowicki February 1982 * - Changed exec's with full pathnames to use search path * - "-ifilename" option added to substitute file for crt0.b * - Merged Pratt's "single module" check of Januray 1982 * - Merged in Mogul's undocumented .ls hack * - Merged in Pratt's "-u" hack * * March 1982 (jcm, vrp, win) * - Fixed bug regarding linking a single .b file * - Removed Jeff's ANNOYING #ifdef * - Added -vL for LucasFilms "temporary" kludge * - files with no suffix assumed to be b.out format * - Changed back to absolute path names (sigh) * * November 1982 (win) * - Added -V option for V environment: -T 10000, -iteamroot.b, -lV * - Added /usr/local/include to include path * * June 1983 (Per Bothner) * - -V option now also does -DVsystem * * July 1983 (win) * - Added -vx option to use experimental versions * * January 21 1984 (Marvin M. Theimer) * - Changed DIRSIZ to MAXNAMLEN for 4.2 directory names. * - Changed /usr/local to /usr/stanford (WIN) * * May 1984 (croft) * - added "-m" switch for Macintosh environment */ #define BSD42 1 #include <sys/types.h> #include <stdio.h> #include <ctype.h> #include <signal.h> #ifdef BSD42 #include <sys/dir.h> #else #include <dir.h> #define MAXNAMLEN DIRSIZ #endif # define LucasKludge "/mnt/lunix/bin/" # define BinDirectory "/usr/sun/bin/" char *cpp = "/lib/cpp"; /* C preprocessor */ char *ccom = "ccom68"; /* Johnson's portable C compiler */ char *c2 = "c268"; /* Terman's .s->.s optimizer */ char *as = "as68"; /* Patrick's 68k assembler */ char *ld = "ld68"; /* 68k link editor */ char *dl = "dl68"; /* MACSBUG downloader */ char *rev = "rev68"; /* Pratt's .b 68k reformatter */ /* run-time start-up */ char *crt0 = "/usr/sun/lib/crtsun.b"; char *macroot = "/usr/sun/lib/crtmac.b"; char *teamroot = "/usr/sun/lib/teamroot.b"; char *xteamroot = "/usr/sun/xlib/teamroot.b"; char *sunincludes = "-I/usr/sun/include"; char *sunxincludes = "-I/usr/sun/xinclude"; char *localincludes = "-I/usr/stanford/include"; char *dmincludes = "-I/usr/sun/dm/include"; char *defines = "-DMC68000"; /* tell cpp this is a 68000 */ char tmp0[30]; /* big enough for /tmp/ctm%05.5d */ char *tmp1, *tmp2, *tmp3, *tmp4, *tmp5; char *infile=0, *outfile=0; char *savestr(), *strspl(), *setsuf(), *setlongsuf(); char *type; int idexit(); char **av, **clist, **llist, **flist, **ulist, **plist; int cflag=0, /* skip link editing, result is filename.b */ dflag=0, /* 1 -> apply dl68 to yield filename.d */ eflag=0, /* error flag; records errors */ gflag=0, /* 1 -> ccom68 generates info for sdb68 (nonexistent)*/ lflag=0, /* 1 -> as68 generates listing */ oflag=0, /* optimization flag; 1 -> invoke o68 */ pflag=0, /* 1 -> don't delete temporary files */ rflag=0, /* 1 -> apply rev68 to yield filename.r */ Rflag=0, /* 1 -> ld68 preserves relocation bits */ sflag=0, /* 1 -> skip assembly, result is filename.s */ wflag=0, /* -w flag passed to ccom68 */ zflag=0, /* print exec() trace */ exflag=0, /* 1 -> only apply cpp, result to stdout */ noxflag=0, /* 1 -> -x flag off -> output local symbols */ Vflag=0, /* 1 -> V kernel environment */ mflag=0, /* 1 -> Macintosh environment */ proflag=0; /* profile flag: generate jbsr mcount for each fctn */ int exfail; char *chpass=0, *version=0, /* version: -vm, -v1, -v2, ... */ *Torg=0, /* Text origin */ *entrypt=0, /* entry point */ *npassname=0; int nc=0, /* no of programs for ccom */ nl=0, /* no of .b inputs for ld (including libraries) */ nm=0, /* no of modules (excluding libraries) */ nf=0, /* no of flags for ld68 */ nu=0, /* no of files of unknown type */ np=0, /* no of args for cpp */ na=0; /* no of args to each callsys */ #define cunlink(s) if (s&&!zflag) unlink(s) main(argc, argv) char **argv; { char *t; char *assource; int i, j, c; /* ld currently adds upto 5 args; 20 is room to spare */ /* [Does this apply to ld68? - pratt] */ av = (char **)calloc(argc+20, sizeof (char **)); clist = (char **)calloc(argc, sizeof (char **)); llist = (char **)calloc(argc, sizeof (char **)); flist = (char **)calloc(argc, sizeof (char **)); ulist = (char **)calloc(argc, sizeof (char **)); plist = (char **)calloc(argc, sizeof (char **)); for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (argv[i][1]) { case '-': /* negate some default */ switch(argv[i][2]) { case 'x': noxflag++; break; } break; case 'S': sflag++; cflag++; break; case 'e': if (++i < argc) entrypt = argv[i]; break; case 'o': if (++i < argc) { outfile = argv[i]; switch (getsuf(outfile)) { case 'c': error("-o would overwrite %s", outfile); exit(8); } } break; case 'T': if (++i < argc) Torg = argv[i]; break; case 'u': if (++i < argc) { llist[nl++] = "-u"; llist[nl++] = argv[i]; } break; case 'O': oflag++; break; case 'p': proflag++; break; case 'g': gflag++; break; case 'L': /* WIN */ lflag++; break; case 'w': wflag++; break; case 'E': exflag++; case 'P': pflag++; if (argv[i][1]=='P') fprintf(stderr, "cc68: warning: -P option obsolete; you should use -E instead\n"); plist[np++] = argv[i]; break; case 'c': cflag++; break; case 'd': dflag++; break; case 'r': rflag++; break; case 'R': Rflag++; break; case 'D': case 'I': case 'U': case 'C': plist[np++] = argv[i]; break; case 't': if (chpass) error("-t overwrites earlier option", 0); chpass = argv[i]+2; if (chpass[0]==0) chpass = "012p"; break; case 'B': if (npassname) error("-B overwrites earlier option", 0); npassname = argv[i]+2; if (npassname[0]==0) npassname = "/usr/c/o"; break; case 'l': llist[nl++] = argv[i];/* NOT flist, order matters! */ break; case 'v': version = argv[i]; break; case 'i': crt0 = argv[i]+2; break; case 'z': /* trace exec() calls */ zflag++; break; case 'V': /* V environment */ crt0 = (version && version[2]=='x') ? xteamroot : teamroot; Torg = "10000"; Vflag++; break; case 'm': /* Macintosh environment */ crt0 = macroot; Torg = "0"; entrypt = "_start"; mflag++; Rflag++; break; default: flist[nf++] = argv[i]; break; } else { /* not a flag */ t = argv[i]; c = getsuf(t); if (c=='c' || c=='s' || exflag) { clist[nc++] = t; t = setsuf(t, 'b'); c = 'b'; } if (c=='a' || c=='b') { if (nodup(llist, t)) { llist[nl++] = t; nm++; /* count programs */ } } else if (!strcmp(t,"b.out") || !index(t,'.') ) infile = t; else { ulist[nu++] = t; /* Unrecognized suffix */ nm++; } } } /* End of loop to process arguments */ for (i=0; i<nu; i++) { if (exflag||sflag||cflag) { clist[nc++] = ulist[i]; type = "C code (type .c)"; } else if (dflag||rflag) { infile = ulist[i]; type = "b.out format"; } else { llist[nl++] = ulist[i]; type = "relocatable binary (type .b)"; } fprintf(stderr, "cc68: warning: %s has unrecognized suffix, taken to be %s\n", infile,type); } if (version && version[2]=='m') crt0 = "/usr/sun/lib/crt0.b"; if (version && version[2]=='x') crt0 = xteamroot; if (!nl && !infile) { fprintf(stderr,"cc68: no input specified\n"); exit(8); } if ((eflag||sflag||cflag) && (dflag || rflag)) { fprintf(stderr,"cc68: warning: -E,-S,-c disable -d,-r\n"); dflag = 0; rflag = 0; } if (gflag) { if (oflag) fprintf(stderr, "cc68: warning: -g disables -O\n"); oflag = 0; } if (npassname && chpass ==0) chpass = "012p"; if (chpass && npassname==0) npassname = "/usr/new"; if (chpass) for (t=chpass; *t; t++) { switch (*t) { case '0': ccom = strspl(npassname, "ccom"); continue; case '2': c2 = strspl(npassname, "c2"); continue; case 'p': cpp = strspl(npassname, "cpp"); continue; } } if (proflag) crt0 = "/usr/sun/lib/mcrt0.b"; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, idexit); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, idexit); if (pflag==0) sprintf(tmp0, "/tmp/ctm%05.5d", getpid()); tmp1 = strspl(tmp0, "1"); if (nc==0) goto nocom; tmp2 = strspl(tmp0, "2"); tmp3 = strspl(tmp0, "3"); if (pflag==0) tmp4 = strspl(tmp0, "4"); if (oflag) tmp5 = strspl(tmp0, "5"); for (i=0; i<nc; i++) { if (nc > 1) { printf("%s:\n", clist[i]); fflush(stdout); } if (getsuf(clist[i]) == 's') { assource = clist[i]; goto assemble; /* thereby skipping ccom68 */ } else assource = tmp3; if (pflag) tmp4 = setsuf(clist[i], 'i'); av[0] = "cpp"; av[1] = clist[i]; av[2] = exflag ? "-" : tmp4; na = 3; for (j = 0; j < np; j++) av[na++] = plist[j]; if (version) if (strcmp(version,"-vx") == 0) av[na++] = sunxincludes; if (version) if (strcmp(version,"-vm") == 0) av[na++] = dmincludes; av[na++]=sunincludes; av[na++]=localincludes; av[na++]=defines; if (Vflag) av[na++] = "-DVsystem"; av[na++] = 0; if (callsys(cpp, av)) { exfail++; eflag++; } if (pflag || exfail) { cflag++; continue; } if (sflag) assource = tmp3 = setsuf(clist[i], 's'); av[0] = "ccom"; av[1] = tmp4; av[2] = oflag?tmp5:tmp3; na = 3; if (proflag) av[na++] = "-XP"; if (gflag) av[na++] = "-Xg"; if (wflag) av[na++] = "-w"; av[na] = 0; /* if (callsys(ccom, av)) { cflag++; eflag++; continue; } */ { /* this is a hack. */ char command[100]; sprintf(command,"%s <%s >%s",ccom,av[1],av[2]); if (zflag) printf( "\t%s\n", command ); if(system(command)) { eflag++; continue; } } if (oflag) { av[0] = "c2"; av[1] = tmp5; av[2] = tmp3; av[3] = 0; if (callsys(c2, av)) { unlink(tmp3); tmp3 = assource = tmp5; } else unlink(tmp5); } if (sflag) continue; assemble: cunlink(tmp1); cunlink(tmp2); cunlink(tmp4); na = 0; av[na++] = "as68"; av[na++] = "-o"; if (cflag && nc == 1 && outfile) av[na++] = outfile; else av[na++] = setsuf(clist[i], 'b'); av[na++] = "-g"; /* permits undefined symbols in as68 */ if (lflag) { av[na++] = "-L"; av[na++] = setlongsuf(clist[i], "ls"); } av[na++] = assource; av[na] = 0; if (callsys(as, av) > 1) { cflag++; eflag++; continue; } } /* End of loop to produce .b files */ nocom: /* link edit files in llist[0:nl-1] */ if (cflag==0 && nl!=0) { na = 0; av[na++] = "ld"; av[na++] = "-X"; if (Rflag) av[na++] = "-r"; if (mflag) av[na++] = "-d"; if (version) av[na++] = version; if (entrypt) { av[na++] = "-e"; av[na++] = entrypt; } if (Torg) { av[na++] = "-T"; av[na++] = Torg; } av[na++] = crt0; /* startup */ if (dflag || rflag) { /* if dl or rev then just output to */ av[na++] = "-o";/* temporary file */ av[na++] = infile = tmp1; } else if (outfile) { /* else if outfile exists then */ av[na++] = "-o";/* output to it. Default is b.out */ av[na++] = outfile; } for (i=0; i<nf; i++) /* supply all flags */ av[na++] = flist[i]; for (i=0; i<nl; i++) /* supply all .b arguments */ av[na++] = llist[i]; if (gflag) av[na++] = "-lg"; if (mflag) av[na++] = "-lmac"; if (Vflag) av[na++] = "-lV"; else av[na++] = "-lc"; /* libc.a only if not V */ if (!noxflag) /* add -x by default unless --x given */ av[na++] = "-x"; av[na++] = 0; /* argument delimiter */ eflag |= callsys(ld, av); /* invoke ld68 */ if (nc==1 && nm==1 && eflag==0) /* * If we have only one module AND it was compiled * (as opposed to just linked) then remove the .b file. */ unlink(setsuf(clist[0], 'b')); } dnload: if (dflag && eflag==0) { na = 0; av[na++] = "dl"; av[na++] = infile; if (version) av[na++] = version; if (Torg) { av[na++] = "-T"; av[na++] = Torg; } av[na++] = "-o"; av[na++] = outfile? outfile: nl? strspl(setsuf(llist[0],'d'),"l"): "d.out"; av[na++] = 0; eflag |= callsys(dl, av); /* invoke dl68 */ } reverse: if (rflag && eflag==0) { na = 0; av[na++] = "rev"; av[na++] = infile; av[na++] = outfile && !dflag? outfile: nl? setsuf(llist[0],'r'): "r.out"; av[na++] = 0; eflag |= callsys(rev, av); } dexit(); } idexit() { eflag = 100; dexit(); } dexit() { if (!pflag) { cunlink(tmp1); cunlink(tmp2); if (sflag==0) cunlink(tmp3); cunlink(tmp4); cunlink(tmp5); } exit(eflag); } error(s, x) char *s, *x; { FILE *diag = exflag ? stderr : stdout; fprintf(diag, "cc68: "); fprintf(diag, s, x); putc('\n', diag); exfail++; cflag++; eflag++; } getsuf(as) char as[]; { register int c; register char *s; register int t; s = as; c = 0; while (t = *s++) if (t=='/') c = 0; else c++; s -= 3; if (c <= MAXNAMLEN && c > 2 && *s++ == '.') return (*s); return (0); } char * setsuf(as, ch) char *as; { register char *s, *s1; s = s1 = savestr(as); while (*s) if (*s++ == '/') s1 = s; s[-1] = ch; return (s1); } char * setlongsuf(as, suff) char *as; char *suff; { register char *s, *s1; register int suflen = strlen(suff); s = s1 = savestr(as); while (*s) if (*s++ == '/') s1 = s; s[-1] = 0; if (strlen(s1) > (MAXNAMLEN - suflen)) { s[-suflen] = 0; s[-(suflen-1)] = '.'; } return(strspl(s1,suff)); } callsys(f, v) char *f, **v; { int t, status; char cmd[256]; if (version && version[2]=='L' && *f!='/') { /* * We substitute the LucasFilms versions of the loader, * compiler, assembler, etc. if the -vL option was set, * and we have an unqualified pathname. */ strcpy( cmd, LucasKludge); strcat( cmd, f); } else if (*f!='/') { /* * add the binary directory at the begining if not * already specified, so you can have other versions * in your path without screwing up. */ strcpy( cmd, BinDirectory); strcat( cmd, f); } else strcpy( cmd, f); if (zflag) { /* * print out a trace of all commands executed */ char **arg = v+1; printf( "\t%s ", cmd); while (*arg) printf( "%s ", *arg++); printf("\n"); } t = vfork(); if (t == -1) { printf("No more processes\n"); return (100); } if (t == 0) { execvp( cmd, v); printf("Can't find %s\n", cmd); fflush(stdout); _exit(100); } while (t != wait(&status)) ; if ((t=(status&0377)) != 0 && t!=14) { if (t!=2) { printf("Fatal error in %s\n", cmd); eflag = 8; } dexit(); } return ((status>>8) & 0377); } nodup(l, os) char **l, *os; { register char *t, *s; register int c; s = os; if (getsuf(s) != 'b') return (1); while (t = *l++) { while (c = *s++) if (c != *t++) break; if (*t==0 && c==0) return (0); s = os; } return (1); } #define NSAVETAB 1024 char *savetab; int saveleft; char * savestr(cp) register char *cp; { register int len; len = strlen(cp) + 1; if (len > saveleft) { saveleft = NSAVETAB; if (len > saveleft) saveleft = len; savetab = (char *)malloc(saveleft); if (savetab == 0) { fprintf(stderr, "ran out of memory (savestr)\n"); exit(1); } } strncpy(savetab, cp, len); cp = savetab; savetab += len; saveleft -= len; return (cp); } char * strspl(left, right) char *left, *right; { char buf[BUFSIZ]; strcpy(buf, left); strcat(buf, right); return (savestr(buf)); } ibc.a only if not V */ if (!noxflag) /* add -x by default unless --x given */ av[na++] = "-x"; av[na++] = 0; /* argument delimiter */ eflag |= callsys(ld, av); sumacc/cc42/ 775 0 12 0 3540162151 5750 sumacc/cc42/cc68.c 444 0 12 36523 3470501266 6777 /* * cc68 - front end for MC68000 C compiler * * Jeffrey Mogul @ Stanford February 10 1981 * - hacked up from cc.c * * V. Pratt March 1981 * -v (version), -d (dl68), -r (rev68) options * * Bill Nowicki February 1982 * - Changed exec's with full pathnames to use search path * - "-ifilename" option added to substitute file for crt0.b * - Merged Pratt's "single module" check of Januray 1982 * - Merged in Mogul's undocumented .ls hack * - Merged in Pratt's "-u" hack * * March 1982 (jcm, vrp, win) * - Fixed bug regarding linking a single .b file * - Removed Jeff's ANNOYING #ifdef * - Added -vL for LucasFilms "temporary" kludge * - files with no suffix assumed to be b.out format * - Changed back to absolute path names (sigh) * * November 1982 (win) * - Added -V option for V environment: -T 10000, -iteamroot.b, -lV * - Added /usr/local/include to include path * * June 1983 (Per Bothner) * - -V option now also does -DVsystem * * July 1983 (win) * - Added -vx option to use experimental versions * * January 21 1984 (Marvin M. Theimer) * - Changed DIRSIZ to MAXNAMLEN for 4.2 directory names. * - Changed /usr/local to /usr/stanford (WIN) * * May 1984 (croft) * - added "-m" switch for Macintosh environment */ #define BSD42 1 #include <sys/types.h> #include <stdio.h> #include <ctype.h> #include <signal.h> #ifdef BSD42 #include <sys/dir.h> #else #include <dir.h> #define MAXNAMLEN DIRSIZ #endif # define LucasKludge "/mnt/lunix/bin/" # define BinDirectory "/usr/stanford/bin/" char *cpp = "/lib/cpp"; /* C preprocessor */ char *ccom = "ccom68"; /* Johnson's portable C compiler */ char *c2 = "c268"; /* Terman's .s->.s optimizer */ char *as = "as68"; /* Patrick's 68k assembler */ char *ld = "ld68"; /* 68k link editor */ char *dl = "dl68"; /* MACSBUG downloader */ char *rev = "rev68"; /* Pratt's .b 68k reformatter */ /* run-time start-up */ char *crt0 = "/usr/sun/lib/crtsun.b"; char *macroot = "/usr/sun/lib/crtmac.b"; char *teamroot = "/usr/sun/lib/teamroot.b"; char *xteamroot = "/usr/sun/xlib/teamroot.b"; char *sunincludes = "-I/usr/sun/include"; char *sunxincludes = "-I/usr/sun/xinclude"; char *localincludes = "-I/usr/stanford/include"; char *dmincludes = "-I/usr/sun/dm/include"; char *defines = "-DMC68000"; /* tell cpp this is a 68000 */ char tmp0[30]; /* big enough for /tmp/ctm%05.5d */ char *tmp1, *tmp2, *tmp3, *tmp4, *tmp5; char *infile=0, *outfile=0; char *savestr(), *strspl(), *setsuf(), *setlongsuf(); char *type; int idexit(); char **av, **clist, **llist, **flist, **ulist, **plist; int cflag=0, /* skip link editing, result is filename.b */ dflag=0, /* 1 -> apply dl68 to yield filename.d */ eflag=0, /* error flag; records errors */ gflag=0, /* 1 -> ccom68 generates info for sdb68 (nonexistent)*/ lflag=0, /* 1 -> as68 generates listing */ oflag=0, /* optimization flag; 1 -> invoke o68 */ pflag=0, /* 1 -> don't delete temporary files */ rflag=0, /* 1 -> apply rev68 to yield filename.r */ Rflag=0, /* 1 -> ld68 preserves relocation bits */ sflag=0, /* 1 -> skip assembly, result is filename.s */ wflag=0, /* -w flag passed to ccom68 */ zflag=0, /* print exec() trace */ exflag=0, /* 1 -> only apply cpp, result to stdout */ noxflag=0, /* 1 -> -x flag off -> output local symbols */ Vflag=0, /* 1 -> V kernel environment */ mflag=0, /* 1 -> Macintosh environment */ proflag=0; /* profile flag: generate jbsr mcount for each fctn */ int exfail; char *chpass=0, *version=0, /* version: -vm, -v1, -v2, ... */ *Torg=0, /* Text origin */ *entrypt=0, /* entry point */ *npassname=0; int nc=0, /* no of programs for ccom */ nl=0, /* no of .b inputs for ld (including libraries) */ nm=0, /* no of modules (excluding libraries) */ nf=0, /* no of flags for ld68 */ nu=0, /* no of files of unknown type */ np=0, /* no of args for cpp */ na=0; /* no of args to each callsys */ #define cunlink(s) if (s&&!zflag) unlink(s) main(argc, argv) char **argv; { char *t; char *assource; int i, j, c; /* ld currently adds upto 5 args; 20 is room to spare */ /* [Does this apply to ld68? - pratt] */ av = (char **)calloc(argc+20, sizeof (char **)); clist = (char **)calloc(argc, sizeof (char **)); llist = (char **)calloc(argc, sizeof (char **)); flist = (char **)calloc(argc, sizeof (char **)); ulist = (char **)calloc(argc, sizeof (char **)); plist = (char **)calloc(argc, sizeof (char **)); for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (argv[i][1]) { case '-': /* negate some default */ switch(argv[i][2]) { case 'x': noxflag++; break; } break; case 'S': sflag++; cflag++; break; case 'e': if (++i < argc) entrypt = argv[i]; break; case 'o': if (++i < argc) { outfile = argv[i]; switch (getsuf(outfile)) { case 'c': error("-o would overwrite %s", outfile); exit(8); } } break; case 'T': if (++i < argc) Torg = argv[i]; break; case 'u': if (++i < argc) { llist[nl++] = "-u"; llist[nl++] = argv[i]; } break; case 'O': oflag++; break; case 'p': proflag++; break; case 'g': gflag++; break; case 'L': /* WIN */ lflag++; break; case 'w': wflag++; break; case 'E': exflag++; case 'P': pflag++; if (argv[i][1]=='P') fprintf(stderr, "cc68: warning: -P option obsolete; you should use -E instead\n"); plist[np++] = argv[i]; break; case 'c': cflag++; break; case 'd': dflag++; break; case 'r': rflag++; break; case 'R': Rflag++; break; case 'D': case 'I': case 'U': case 'C': plist[np++] = argv[i]; break; case 't': if (chpass) error("-t overwrites earlier option", 0); chpass = argv[i]+2; if (chpass[0]==0) chpass = "012p"; break; case 'B': if (npassname) error("-B overwrites earlier option", 0); npassname = argv[i]+2; if (npassname[0]==0) npassname = "/usr/c/o"; break; case 'l': llist[nl++] = argv[i];/* NOT flist, order matters! */ break; case 'v': version = argv[i]; break; case 'i': crt0 = argv[i]+2; break; case 'z': /* trace exec() calls */ zflag++; break; case 'V': /* V environment */ crt0 = (version && version[2]=='x') ? xteamroot : teamroot; Torg = "10000"; Vflag++; break; case 'm': /* Macintosh environment */ crt0 = macroot; Torg = "0"; entrypt = "_start"; mflag++; Rflag++; break; default: flist[nf++] = argv[i]; break; } else { /* not a flag */ t = argv[i]; c = getsuf(t); if (c=='c' || c=='s' || exflag) { clist[nc++] = t; t = setsuf(t, 'b'); c = 'b'; } if (c=='a' || c=='b') { if (nodup(llist, t)) { llist[nl++] = t; nm++; /* count programs */ } } else if (!strcmp(t,"b.out") || !index(t,'.') ) infile = t; else { ulist[nu++] = t; /* Unrecognized suffix */ nm++; } } } /* End of loop to process arguments */ for (i=0; i<nu; i++) { if (exflag||sflag||cflag) { clist[nc++] = ulist[i]; type = "C code (type .c)"; } else if (dflag||rflag) { infile = ulist[i]; type = "b.out format"; } else { llist[nl++] = ulist[i]; type = "relocatable binary (type .b)"; } fprintf(stderr, "cc68: warning: %s has unrecognized suffix, taken to be %s\n", infile,type); } if (version && version[2]=='m') crt0 = "/usr/sun/lib/crt0.b"; if (version && version[2]=='x') crt0 = xteamroot; if (!nl && !infile) { fprintf(stderr,"cc68: no input specified\n"); exit(8); } if ((eflag||sflag||cflag) && (dflag || rflag)) { fprintf(stderr,"cc68: warning: -E,-S,-c disable -d,-r\n"); dflag = 0; rflag = 0; } if (gflag) { if (oflag) fprintf(stderr, "cc68: warning: -g disables -O\n"); oflag = 0; } if (npassname && chpass ==0) chpass = "012p"; if (chpass && npassname==0) npassname = "/usr/new"; if (chpass) for (t=chpass; *t; t++) { switch (*t) { case '0': ccom = strspl(npassname, "ccom"); continue; case '2': c2 = strspl(npassname, "c2"); continue; case 'p': cpp = strspl(npassname, "cpp"); continue; } } if (proflag) crt0 = "/usr/sun/lib/mcrt0.b"; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, idexit); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, idexit); if (pflag==0) sprintf(tmp0, "/tmp/ctm%05.5d", getpid()); tmp1 = strspl(tmp0, "1"); if (nc==0) goto nocom; tmp2 = strspl(tmp0, "2"); tmp3 = strspl(tmp0, "3"); if (pflag==0) tmp4 = strspl(tmp0, "4"); if (oflag) tmp5 = strspl(tmp0, "5"); for (i=0; i<nc; i++) { if (nc > 1) { printf("%s:\n", clist[i]); fflush(stdout); } if (getsuf(clist[i]) == 's') { assource = clist[i]; goto assemble; /* thereby skipping ccom68 */ } else assource = tmp3; if (pflag) tmp4 = setsuf(clist[i], 'i'); av[0] = "cpp"; av[1] = clist[i]; av[2] = exflag ? "-" : tmp4; na = 3; for (j = 0; j < np; j++) av[na++] = plist[j]; if (version) if (strcmp(version,"-vx") == 0) av[na++] = sunxincludes; if (version) if (strcmp(version,"-vm") == 0) av[na++] = dmincludes; av[na++]=sunincludes; av[na++]=localincludes; av[na++]=defines; if (Vflag) av[na++] = "-DVsystem"; av[na++] = 0; if (callsys(cpp, av)) { exfail++; eflag++; } if (pflag || exfail) { cflag++; continue; } if (sflag) assource = tmp3 = setsuf(clist[i], 's'); av[0] = "ccom"; av[1] = tmp4; av[2] = oflag?tmp5:tmp3; na = 3; if (proflag) av[na++] = "-XP"; if (gflag) av[na++] = "-Xg"; if (wflag) av[na++] = "-w"; av[na] = 0; /* if (callsys(ccom, av)) { cflag++; eflag++; continue; } */ { /* this is a hack. */ char command[100]; sprintf(command,"%s <%s >%s",ccom,av[1],av[2]); if (zflag) printf( "\t%s\n", command ); if(system(command)) { eflag++; continue; } } if (oflag) { av[0] = "c2"; av[1] = tmp5; av[2] = tmp3; av[3] = 0; if (callsys(c2, av)) { unlink(tmp3); tmp3 = assource = tmp5; } else unlink(tmp5); } if (sflag) continue; assemble: cunlink(tmp1); cunlink(tmp2); cunlink(tmp4); na = 0; av[na++] = "as68"; av[na++] = "-o"; if (cflag && nc == 1 && outfile) av[na++] = outfile; else av[na++] = setsuf(clist[i], 'b'); av[na++] = "-g"; /* permits undefined symbols in as68 */ if (lflag) { av[na++] = "-L"; av[na++] = setlongsuf(clist[i], "ls"); } av[na++] = assource; av[na] = 0; if (callsys(as, av) > 1) { cflag++; eflag++; continue; } } /* End of loop to produce .b files */ nocom: /* link edit files in llist[0:nl-1] */ if (cflag==0 && nl!=0) { na = 0; av[na++] = "ld"; av[na++] = "-X"; if (Rflag) av[na++] = "-r"; if (mflag) av[na++] = "-d"; if (version) av[na++] = version; if (entrypt) { av[na++] = "-e"; av[na++] = entrypt; } if (Torg) { av[na++] = "-T"; av[na++] = Torg; } av[na++] = crt0; /* startup */ if (dflag || rflag) { /* if dl or rev then just output to */ av[na++] = "-o";/* temporary file */ av[na++] = infile = tmp1; } else if (outfile) { /* else if outfile exists then */ av[na++] = "-o";/* output to it. Default is b.out */ av[na++] = outfile; } for (i=0; i<nf; i++) /* supply all flags */ av[na++] = flist[i]; for (i=0; i<nl; i++) /* supply all .b arguments */ av[na++] = llist[i]; if (gflag) av[na++] = "-lg"; if (mflag) av[na++] = "-lmac"; if (Vflag) av[na++] = "-lV"; else av[na++] = "-lc"; /* libc.a only if not V */ if (!noxflag) /* add -x by default unless --x given */ av[na++] = "-x"; av[na++] = 0; /* argument delimiter */ eflag |= callsys(ld, av); /* invoke ld68 */ if (nc==1 && nm==1 && eflag==0) /* * If we have only one module AND it was compiled * (as opposed to just linked) then remove the .b file. */ unlink(setsuf(clist[0], 'b')); } dnload: if (dflag && eflag==0) { na = 0; av[na++] = "dl"; av[na++] = infile; if (version) av[na++] = version; if (Torg) { av[na++] = "-T"; av[na++] = Torg; } av[na++] = "-o"; av[na++] = outfile? outfile: nl? strspl(setsuf(llist[0],'d'),"l"): "d.out"; av[na++] = 0; eflag |= callsys(dl, av); /* invoke dl68 */ } reverse: if (rflag && eflag==0) { na = 0; av[na++] = "rev"; av[na++] = infile; av[na++] = outfile && !dflag? outfile: nl? setsuf(llist[0],'r'): "r.out"; av[na++] = 0; eflag |= callsys(rev, av); } dexit(); } idexit() { eflag = 100; dexit(); } dexit() { if (!pflag) { cunlink(tmp1); cunlink(tmp2); if (sflag==0) cunlink(tmp3); cunlink(tmp4); cunlink(tmp5); } exit(eflag); } error(s, x) char *s, *x; { FILE *diag = exflag ? stderr : stdout; fprintf(diag, "cc68: "); fprintf(diag, s, x); putc('\n', diag); exfail++; cflag++; eflag++; } getsuf(as) char as[]; { register int c; register char *s; register int t; s = as; c = 0; while (t = *s++) if (t=='/') c = 0; else c++; s -= 3; if (c <= MAXNAMLEN && c > 2 && *s++ == '.') return (*s); return (0); } char * setsuf(as, ch) char *as; { register char *s, *s1; s = s1 = savestr(as); while (*s) if (*s++ == '/') s1 = s; s[-1] = ch; return (s1); } char * setlongsuf(as, suff) char *as; char *suff; { register char *s, *s1; register int suflen = strlen(suff); s = s1 = savestr(as); while (*s) if (*s++ == '/') s1 = s; s[-1] = 0; if (strlen(s1) > (MAXNAMLEN - suflen)) { s[-suflen] = 0; s[-(suflen-1)] = '.'; } return(strspl(s1,suff)); } callsys(f, v) char *f, **v; { int t, status; char cmd[256]; if (version && version[2]=='L' && *f!='/') { /* * We substitute the LucasFilms versions of the loader, * compiler, assembler, etc. if the -vL option was set, * and we have an unqualified pathname. */ strcpy( cmd, LucasKludge); strcat( cmd, f); } else if (*f!='/') { /* * add the binary directory at the begining if not * already specified, so you can have other versions * in your path without screwing up. */ strcpy( cmd, BinDirectory); strcat( cmd, f); } else strcpy( cmd, f); if (zflag) { /* * print out a trace of all commands executed */ char **arg = v+1; printf( "\t%s ", cmd); while (*arg) printf( "%s ", *arg++); printf("\n"); } t = vfork(); if (t == -1) { printf("No more processes\n"); return (100); } if (t == 0) { execvp( cmd, v); printf("Can't find %s\n", cmd); fflush(stdout); _exit(100); } while (t != wait(&status)) ; if ((t=(status&0377)) != 0 && t!=14) { if (t!=2) { printf("Fatal error in %s\n", cmd); eflag = 8; } dexit(); } return ((status>>8) & 0377); } nodup(l, os) char **l, *os; { register char *t, *s; register int c; s = os; if (getsuf(s) != 'b') return (1); while (t = *l++) { while (c = *s++) if (c != *t++) break; if (*t==0 && c==0) return (0); s = os; } return (1); } #define NSAVETAB 1024 char *savetab; int saveleft; char * savestr(cp) register char *cp; { register int len; len = strlen(cp) + 1; if (len > saveleft) { saveleft = NSAVETAB; if (len > saveleft) saveleft = len; savetab = (char *)malloc(saveleft); if (savetab == 0) { fprintf(stderr, "ran out of memory (savestr)\n"); exit(1); } } strncpy(savetab, cp, len); cp = savetab; savetab += len; saveleft -= len; return (cp); } char * strspl(left, right) char *left, *right; { char buf[BUFSIZ]; strcpy(buf, left); strcat(buf, right); return (savestr(buf)); } ibc.a only if not V */ if (!noxflag) /* add -x by default unless --x given */ av[na++] = "-x"; av[na++] = 0; /* argument delimiter */ eflag |= callsys(ld, sumacc/cc42/Makefile 444 0 12 331 3472475542 7465 DP=/usr/sun/bin DL=/usr/sun/lib PRGS=cc68 as68 c268 ccom68 ld68 lorder68 nm68 pr68 rl68 size68 LIBS=a68.hdr install: cc68 cp $(LIBS) $(DL) # cp $(PRGS) $(DP) cc68: cc68.o cc -o cc68 cc68.o clean: rm -f cc68 *.o s1 = s; s[-1] = 0; if (strlen(s1) > (MAXNAMLEN - suflen)) { s[-suflen] = 0; s[-(suflen-1)] = '.'; } return(strspl(s1,suff)); } callsys(f, v) char *f, **v; { int t, status; char cmd[256]; if (version && version[2]=='L' && *f!='/') { /* * We substitute the LucasFilms versumacc/cc42/lorder68 555 0 12 643 3470501274 7414 #! /bin/sh trap "rm -f $$sym?ef; exit" 0 1 2 13 15 case $# in 0) echo usage: lorder68 file ... exit ;; 1) case $1 in *.b) set $1 $1 esac esac nm68 -g -f $* | sed ' /^$/d /:$/{ /\.b:/!d s/:// h s/.*/& &/ p d } /[TD] /{ s/.* // G s/\n/ / w '$$symdef' d } s/.* // G s/\n/ / w '$$symref' d ' sort $$symdef -o $$symdef sort $$symref -o $$symref join $$symref $$symdef | sed 's/[^ ]* *//' if (version && version[2]=='L' && *f!='/') { /* * We substitute the LucasFilms versumacc/cc42/a68.hdr 444 0 12 1373 3470501301 7126 | Pre-Assembly Code | The remainder of this file consists of statements that are | interpreted before every 68000 program. | Define Register Names .defrs d0, 0., d1, 1., d2, 2., d3, 3. .defrs d4, 4., d5, 5., d6, 6., d7, 7. .defrs a0, 8., a1, 9., a2, 10., a3, 11. .defrs a4, 12., a5, 13., a6, 14., a7, 15. .defrs sp, 15., pc, 16., cc, 17., sr, 18., usp, 19. | Next line is for 68010. --TPM .defrs sfc, 20., dfc, 21., vbr 22. | Set Input and Output Radices .radix in, decimal .radix out, hex | Define registers for movem | D3 means just d3, D3+A2 means d3 and a2, A2-D3 means a1,a0,d7,...,d4,d3 D0 = /1 D1 = /2 D2 = /4 D3 = /8 D4 = /10 D5 = /20 D6 = /40 D7 = /80 A0 = /100 A1 = /200 A2 = /400 A3 = /800 A4 = /1000 A5 = /2000 A6 = /4000 A7 = /8000 ALL = 0 rectory at the begining if not * already specified, so you can have other versions * in your path without screwing up. */ strcpy( cmd, BinDirectory); strcat( cmd, f); } else strcpy( cmd, f); if (zflag) { /* * print out a tracesumacc/cc42/libc.a 444 0 12 253672 3470501304 7162 !<arch> clrerr.b 406162685 11 21 100664 118 ` 6 NVÿüHî ÿü*n mÿÏ Lî ÿüN^Nu _S1 _F1 " clearerr .L18 fgetc.b 406162738 11 21 100664 203 ` @ c NV Hî n Sm n R¨ ( S€ @H€HÀ€ ÿ`/. N¹ XN^Nu _filbuf _S1 0 .L10000 <