Path: utzoo!censor!geac!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!inria!litp!pda From: pda@litp.ibp.fr (Pierre DAVID) Newsgroups: comp.sys.handhelds Subject: Saturn Assembler (Part 6/8) Message-ID: <3307@litp.ibp.fr> Date: 5 Jul 90 16:25:05 GMT Reply-To: pda@litp.ibp.fr.UUCP (Pierre DAVID) Organization: M.A.S.I., Universite P. & M. Curie, Paris, FRANCE Lines: 2053 #---------------------------------- cut here ---------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Pierre David on Sun Jul 1 12:33:03 1990 # # This archive contains: # areuh/assembler/ainput.c areuh/assembler/alabel.c # areuh/assembler/alist.c areuh/assembler/amain.c # areuh/assembler/amnemo.c areuh/assembler/aobj.c # areuh/assembler/aopc1.c # # Error checking via wc(1) will be performed. LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH echo x - areuh/assembler/ainput.c cat >areuh/assembler/ainput.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** TITAN ASSEMBLER INPUT STREAM READING & PARSING read_line, parse_line, next_token, stcp ******************************************************************************/ #include "aglobal.h" /****************************************************************************** READ_LINE synopsis : int read_line (fd, line) FILE *fd uchar *line description : read_line reads a line from the source file, or stdin. note : read_line returns -1 if EOF reached, 0 otherwise. ******************************************************************************/ int read_line (fd, line) FILE *fd ; uchar line[] ; { int c, i = -1 ; do { c = getc (fd) ; if (i'z')) ? 0 : 32 ; /* modifier parse */ i = next_token (line, i) ; if (i<0) return ; strcpy (modif, line+i) ; } /****************************************************************************** NEXT_TOKEN synopsis : int next_token (line, i) uchar *line int i descrption : next_token looks the line, from the i-th position, for the next non-blank character or end of line. If end-of-line is reached, a negative value (-1) is returned to caller. Otherwise, the position of character is returned, which permits to reassign the line index (i=next_token(line, i)). ******************************************************************************/ int next_token (line, i) uchar *line ; int i ; { while ((line[i]!=EOL)&&((line[i]==' ')||(line[i]=='\t'))) i++ ; return ((line[i]) ? i : -1); } /****************************************************************************** STCP synopsis : int stcp (str1, str2, i, lmax) uchar *str1, *str2 int i, lmax description : stcp is an alternate name for "string_copy". In fact, stcp copies str2 (from i-th position) into str1 (from 0-th position) until a blank character of end-of-line is reached. If lmax (max length of str1) is is reached, the rest of the field is ignored. The returned value is the new line index value. note : we assume that stcp works well. No error value is returned. replace with "strncpy" in C library for future releases ******************************************************************************/ int stcp (str1, str2, i, lmax) uchar *str1, *str2; int i, lmax; { int j=0; do { if (jareuh/assembler/alabel.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** TITAN ASSEMBLER LABEL PROCESSING ps_label, find_label, add_label, label_value, s_init ******************************************************************************/ #include "aglobal.h" extern saddr calc_expression() ; extern uchar *memoire() ; struct symbol *find_label(), *add_label() ; /****************************************************************************** PS_LABEL synopsis : void ps_label (label, mnemo, modif) uchar *label, *mnemo, *modif description : "pass" function call "ps_label" when a label is encoutered. Thus, in function of pass number, we must process the label. If pass one, the label is declared and its value is assigned (if possible, else -1), only if it is not yet declared. If pass two, the label is declared. We calculate the value of the label. If it had a value, we compare both. If not, the value is assigned. ******************************************************************************/ void ps_label (label, mnemo, modif) uchar *label, *mnemo, *modif; { struct symbol *ad; saddr val ; /* la ligne ci-dessous teste si la partie "utile" du label est "FiLeNd" */ if (strcmp(label + (*label=='='), "FiLeNd")==0) error (ERRFLN, "") ; ad = find_label (label) ; /* during pass two, label must be found. Otherwise, the assembler is bug-full !!! */ if (strcmp (mnemo, "EQU")) { /* implicit declaration */ switch (passnb) { case 1 : if (ad==NULL) add_label (label, pc, "", LREL, 0) ; else if ((ad->s_value==LBL_UDF)||(ad->s_value==LBL_EXT)) { ad->s_value = pc ; ad->s_type = LREL ; } break ; case 2 : if ((ad->s_value!=pc)||(ad->s_type!=LREL)) error (WRNDUP, ""); /* duplicate label */ break ; } } else /* explicit declaration (EQU) */ { val = calc_expression (modif) ; switch (passnb) { case 1: if (ad==NULL) { if (val >= 0L) { add_label (label, val, "", relabs, 0) ; } else if (val == EXP_ERR) { add_label (label, LBL_IVL, "", LUDF, 0) ; } else /* (val == EXP_EXT) */ { if (*label=='=') add_label (label, LBL_XEQ, extexp, LUDF, 0) ; else add_label (label, LBL_SEQ, extexp, LUDF, 0) ; } } else if ((ad->s_value==LBL_UDF)||(ad->s_value==LBL_EXT)) { if (val >= 0L) { ad->s_value = val ; ad->s_type = relabs ; } else if (val == EXP_ERR) { ad->s_value = LBL_IVL ; ad->s_type = LUDF ; } else /* (val == EXP_EXT) */ { ad->s_value = (*label=='=') ? LBL_XEQ : LBL_SEQ ; ad->s_def = memoire (strlen (extexp) + 1) ; strcpy (ad->s_def, extexp) ; ad->s_type = LUDF ; } } break; /* du 'case pass one' */ case 2: if (ad->s_value >= 0L) /* first value of label in first pass */ if (val!=ad->s_value) error (WRNDUP, "") ; else if (ad->s_value == LBL_IVL) { if (val >= 0L) { ad->s_value = val ; ad->s_type = relabs ; } else if (val == EXP_ERR) { ad->s_value = 0L ; ad->s_type = LABS ; } else /* EXP_EXT */ { ad->s_def = memoire (strlen(extexp)+1); if (ad->s_def == (uchar *) NULL) error (ERRMEM, "") ; strcpy (ad->s_def, extexp) ; ad->s_value = (*label=='=')? LBL_XEQ :LBL_SEQ ; ad->s_type = LUDF ; } } else if ((ad->s_value == LBL_XEQ) || (ad->s_value == LBL_SEQ)) { if (val == EXP_EXT) { if (strcmp(ad->s_def, extexp)) error (WRNDUP, "") ; /* duplicate label */ } else { ad->s_value = val ; ad->s_type = relabs ; } } break; /* end of 'case pass 2' */ } } } /****************************************************************************** FIND_LABEL synopsis : struct symbol *find_label (label) uchar *label description : find_label searches the symbol list for a given label. If the search is succesful, find_label returns a pointer to the structure. If not, NULL is returned. ******************************************************************************/ struct symbol *find_label (label) uchar *label ; { struct symbol *p ; int test ; if ((!modular)&&(*label=='=')) label++ ; p = h_label[(int) ((*label=='=') ? label[1] : label[0])]->s_next ; while (p) { test = strcmp (label, p->s_name) ; if (test==0) break ; p = p->s_next ; if (test<0) p = NULL ; /* label < p->s_name : not found */ } return (p) ; } /****************************************************************************** ADD_LABEL synopsis : struct symbol *add_label (label, val, exp, type, os) uchar *label, *exp saddr val uchar type, os description : add_label inserts the label (name and value) in the symbol list. note : the symbol list is always sorted by label name. ******************************************************************************/ struct symbol *add_label (label, val, exp, type, os) uchar *label, *exp ; saddr val ; uchar type, os ; { struct symbol *p, *s ; int b=1 ; if ((!modular)&&(*label=='=')) label++ ; p = h_label[(int) ((*label=='=') ? label[1] : label[0]) ] ; s = p ; while ((b) && (s)) { if (strcmp(label, s->s_name)<0) b = 0 ; else { p = s ; s = s->s_next ; } } s = (struct symbol *) memoire (sizeof(struct symbol)) ; if (s) { s->s_next = p->s_next ; p->s_next = s ; strcpy (s->s_name, label) ; s->s_decl = (sint) linenb ; s->s_xref = (struct xtable *) NULL ; s->s_value = val ; s->s_type = type ; s->s_os = os ; if ((val==LBL_XEQ)||(val==LBL_SEQ)) { s->s_def = memoire (strlen (exp) + 1) ; strcpy (s->s_def, exp) ; } else s->s_def = (uchar *) NULL ; } else error (ERRMEM, "") ; return (s) ; } /****************************************************************************** SYMBOL_VALUE synopsis : saddr symbol_value (label) uchar *label description : label_value returns the value of the label, knowing its name. If it doesn't exist, and this occurs during the second pass, an error message is generated. note : if symbol not found in the symbol list, -1 is returned. It's to the caller (label_value) to report the error "unrecognized label". ******************************************************************************/ saddr symbol_value (label) uchar *label ; { struct symbol *ad; struct xtable *x ; saddr val ; ad = find_label (label) ; if (ad) val = ad->s_value ; else { val = ((*label=='=')&&(modular)) ? LBL_EXT : LBL_UDF ; ad = add_label (label, val, "", LUDF, 0) ; } if (passnb==2) { /* label must be found in pass two */ if (xref) /* need to store it in cross-ref. table */ { x = (struct xtable *) memoire (sizeof(struct xtable)) ; if (x) { x->x_next = ad->s_xref ; if (ad->s_xref) ad->s_xref->x_prev = x ; ad->s_xref = x ; x->x_prev = (struct xtable *) NULL ; x->x_line = (sint) linenb ; } else error (ERRMEM, "") ; } if (val==LBL_UDF) error (WRNULB, "") ; /* undefined label */ } if (val==LBL_SEQ) xlabel = ad->s_def ; ad->s_os = 0 ; /* (O.S.) label is used */ relabs = ad->s_type ; return (val) ; } /****************************************************************************** S_INIT synopsis : void s_init () description : initializes the symbol list. It is structured as follow : - a table (0..255) which points to a list of labels beginning with the character (index in this table is the first char.) - a chained list of labels, - a doubly linked list of references on this label. This is not initialized here. ******************************************************************************/ void s_init () { struct symbol *s ; int i ; s = (struct symbol *) memoire (256*sizeof(struct symbol)) ; if (!(s)) error (ERRMEM, "") ; for (i=0; i<256; i++) { strcpy (s->s_name, "") ; s->s_value = (saddr) 0 ; s->s_type = LUDF ; s->s_decl = (sint) 0 ; s->s_xref = (struct xtable *) NULL ; s->s_next = (struct symbol *) NULL ; h_label[i] = s++ ; } } @EOF set `wc -lwc areuh/assembler/alist.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** AREUH ASSEMBLER LISTING FILE PROCESSING l_init, l_flush, l_print, l_new_page, l_line, l_page ******************************************************************************/ #include "aglobal.h" int l_line, l_page ; void l_new_page (), l_page_header () ; uchar fstdout [] = "stdout" ; /****************************************************************************** L_INIT synopsis : l_init() description : initiates the listing mechanism, if necessary. ******************************************************************************/ void l_init() { uchar tmp [MAXLEN+1] ; switch (cntlist) { case 0 : break ; case 1 : fd_l = stdout ; break ; case 2 : dfl_extension (tmp, fsource, "al") ; look_obj (flisting, tmp) ; if ((fd_l = fopen (flisting, "w")) == NULL) error (ERROPN, flisting) ; break ; } l_page = 0 ; if (cntlist) l_page_header () ; } /****************************************************************************** L_FLUSH synospsis : void l_flush () description : forces a new page, then closes the listing file if necessary. ******************************************************************************/ void l_flush() { if (cntlist==0) return ; l_new_page(0) ; if (cntlist == 2) { if (fclose (fd_l)) error (ERRCLO, flisting) ; } } /****************************************************************************** L_PRINT synopsis : void l_print (pc, code, msg, flags) saddr pc uchar *code, *msg int flags description : prints a line on the listing file. The line may contain - program counter value F_PC - line number F_LN - generated code F_GC - text line F_TL according the "flags" variable. E.g. : to print pc and generated code, call l_print(pc, gen_code, "", F_PC + F_GC) ******************************************************************************/ void l_print (address, code, msg, flags) saddr address ; uchar *code, *msg ; int flags ; { uchar line[MAXLEN+1], tmp[MAXLEN+1] ; if (!(cntlist)) return ; if (flags==F_TL) { sprintf (line, "%.79s", msg) ; } else { if (flags & F_LN) sprintf (line, "%04d ", linenb) ; /* 5 chars */ else strcpy (line, " ") ; if (flags & F_PC) /* 6 chars */ { hex5 (tmp, address) ; strcat (line, tmp) ; strcat (line, " ") ; } else strcat (line, " ") ; if (flags & F_GC) /* 9 chars */ { sprintf (tmp, "%-9.8s", code) ; strcat (line, tmp) ; } else strcat (line, " ") ; if (flags & F_TL) /* 60 chars */ { sprintf (tmp, "%.60s", msg) ; strcat (line, tmp) ; } } if (l_line==(page_size-6)) l_new_page (1) ; fprintf (fd_l, "%s\n", line) ; if (ferror (fd_l)) error (ERRWRT, (cntlist == 1) ? fstdout : flisting) ; l_line++ ; if (strlen(code)>8) l_print (address+8, code+8, "", F_PC + F_GC) ; } /****************************************************************************** L_NEW_PAGE synopsis : void l_new_page (flag) int flag description : forces a new page on listing file, and if flag # 0, prints a header composed by page number, l_stitle and l_title. ******************************************************************************/ void l_new_page (flag) int flag ; { if (!(cntlist)) return ; for (; l_lineareuh/assembler/amain.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** TITAN ASSEMBLER MAIN FONCTION main, prompt ******************************************************************************/ #include "aglobal.h" struct symbol *h_label[256] ; struct xused *headxu ; uchar fsource [MAXLEN+1], flisting [MAXLEN+1], fobject [MAXLEN+1] ; FILE *fd_s, *fd_l, *fd_o ; int cntlist, cntlist_ref ; int page_size ; uchar l_title[MAXLEN+1], l_stitle[MAXLEN+1]; int errcnt, error_this_line ; int print_this_line ; int xref ; int running ; int passnb ; int linenb ; saddr pc ; int gen_len ; uchar gen_code[19] ; int prev_test ; int exec, in_if, in_else ; int modular, linker ; extern void init(), between(), term(), pass() ; extern int read_line() ; /****************************************************************************** MAIN synopsis : aas [-p] [-l n] [-A] [-a afile] [-o objfile] [file1 [... filen]] description : Aas is a cross assembler which runs on UNIX based machines. Aas assembles the named file, or the standard input if no file is specified. The optional arguments -a or -A may be used to obtain an assembly listing. If -A is used, listing goes to standard output. If -a is used, the listing goes to afile. -l option specifies page length. The output of assembly is left in the filoe objfile; if that is omitted, then the output is left in a file "lex". ******************************************************************************/ main (argc, argv) int argc ; char *argv[] ; { int r = 0, c, i ; int errflg = 0 ; int errrep = 0 ; char saveo [MAXLEN+1], savel [MAXLEN+1] ; extern char *optarg ; extern int optind, opterr ; opterr = 0 ; /* par defaut, on a : */ xref = 0 ; /* pas de cross ref */ page_size = 0 ; /* taille de page non fournie */ cntlist_ref = 0 ; /* pas de listing */ strcpy (fobject, "") ; /* fichier objet := "" */ strcpy (fsource, "") ; /* fichier source := "" */ strcpy (flisting, "") ; /* fichier listing := "" */ /* analyse des options */ while ((c = getopt(argc, argv, "xa:Apl:o:")) != EOF) switch (c) { case 'x' : /* cross-ref */ xref = 1 ; break ; case 'a' : /* listing sur fichier */ strcpy (flisting, optarg) ; cntlist_ref = 2 ; break ; case 'A' : /* listing sur stdout */ cntlist_ref = 1 ; break ; case 'p' : /* prompt */ r++ ; /* r := 1 */ break ; case 'l' : /* page length */ sscanf (optarg, "%d", &page_size) ; /* page_size := -l */ break ; case 'o' : /* object file */ strcpy (fobject, optarg) ; break ; case '?' : /* non reconnu */ errflg++ ; break ; } /* si on a demande "-p", ou si pas d'argument : interface interactive */ if ((r)||(argc==1)) prompt () ; /* si option non reconnue ou si pas de nom de source, alors erreur */ if (errflg || ((optind==argc)&&(fsource[0]==EOL))) error (ERRUSA, "") ; /* page_size = 72 par defaut */ if (page_size==0) page_size = 72 ; if (*fsource) /* got source file name with prompt() */ { init() ; pass() ; between() ; pass() ; term() ; errrep = errcnt ; } else { for (i=optind; iareuh/assembler/amnemo.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** AREUH ASSEMBLER MNEMONIC PROCESSING ps_mnemo, find_mnemo, hex, dec ******************************************************************************/ #include "aglobal.h" extern void regtest(), regarith(), reglogic(), branches(), rtnyes(), ptrtest(), stattest(), setptr(), setstat(), dparith(), datatrans(), nibhex(), lchex(), dxhex(), nibasc(), lcasc(), bss(), eject(), endx(), list(), title(), stitle(), lex(), id(), msg(), poll(), entryx(), charx(), key(), token(), bin(), chain(), endtxt(), endifx(), absx(), rdsymb(), elsex(), ifx() ; /****************************************************************************** PROCESS_MNEMO synopsis : ps_mnemo (line, modif, ad) uchar *line, *modif struct mnemo_desc *ad description : pass control to the appropriate routine, to process the opcode. ******************************************************************************/ ps_mnemo (line, modif, ad) uchar *line, *modif ; struct mnemo_desc *ad ; { switch (ad->m_class) { case 1 : regtest(ad, modif) ; break ; case 2 : regarith(ad, modif) ; break ; case 3 : reglogic(modif) ; break ; case 4 : branches(ad, modif) ; break ; case 7 : rtnyes() ; break ; case 8 : ptrtest(modif) ; break ; case 9 : stattest(modif) ; break ; case 10 : setptr(modif) ; break ; case 11 : setstat(modif) ; break ; case 12 : dparith(modif) ; break ; case 13 : datatrans(modif) ; break ; case 14 : nibhex(modif) ; break ; case 15 : lchex(modif) ; break ; case 16 : dxhex(modif) ; break ; case 17 : nibasc(modif) ; break ; case 18 : lcasc(modif) ; break ; case 19 : bss(modif) ; break ; case 20 : eject() ; break ; case 21 : endx() ; break ; case 23 : list(modif) ; break ; case 24 : title(modif) ; break ; case 25 : stitle(modif) ; break ; case 28 : lex(modif, line) ; break ; case 29 : id(modif, line) ; break ; case 30 : msg(modif, line) ; break ; case 31 : poll(modif, line) ; break ; case 32 : entryx(modif, line) ; break ; case 33 : charx(modif, line) ; break ; case 34 : key(modif, line) ; break ; case 35 : token(modif, line) ; break ; case 36 : bin(modif, line) ; break ; case 38 : chain(modif, line) ; break ; case 39 : endtxt(line) ; break ; case 40 : endifx() ; break ; case 41 : absx(modif) ; break ; case 42 : rdsymb(modif) ; break ; case 43 : elsex() ; break ; case 44 : ifx(modif) ; break ; } } /****************************************************************************** FIND_MNEMO synopsis : struct mnemo_desc *find_mnemo (mnemo) char *mnemo description : finds index of a mnemonic in mnemo_table, and returns it, -1 if not found. ******************************************************************************/ struct mnemo_desc *find_mnemo (mnemo) uchar *mnemo ; { int i, m, b = 1 ; long int h = 0 ; for (i=0; i<6; i++) h = (h<<3) + ((b) ? ((b=(int)mnemo[i])&7) : 0) ; h %= 43 ; i = h_opcode[h] ; m = h_opcode[++h] ; while (iareuh/assembler/aobj.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** AREUH ASSEMBLER OBJECT FILE UTILITIES o_init (), o_print (), dump_linker_infos () ******************************************************************************/ #include "aglobal.h" #define fputl(lg,fd) fwrite((char *)(&(lg)),sizeof(long int),1,fd) long int zero = 0L ; long int magic ; /****************************************************************************** O_INIT synopsis : void o_init () description : open object file and, if modular assembly, mark information for linker (address of second part of file, and size of code in nibs). ******************************************************************************/ void o_init () { uchar dfl [MAXLEN+1] ; if (modular) dfl_extension (dfl, fsource, "ao") ; else strcpy (dfl, "lex") ; look_obj (fobject, dfl) ; /* ensure name validity */ if (modular) fd_o = fopen (fobject, WAO_MODE) ; /* untranslated mode */ else fd_o =fopen (fobject, "w") ; /* text mode */ if (fd_o==NULL) error (ERROPN, fobject) ; /* error opening file */ if (modular) { magic = AO_MAGIC ; fputl (magic, fd_o) ; fputl (zero, fd_o) ; fputl (zero, fd_o) ; } else { magic = AL_MAGIC ; fputl (magic, fd_o) ; } if (ferror (fd_o)) error (ERRWRT, fobject) ; } /****************************************************************************** O_PRINT synopsis : void o_print (str, len) uchar *str int len description : burp ******************************************************************************/ void o_print (str, len) uchar *str ; int len ; { int i ; if (len) { if (len>18) for (i=0; is_next ; while (pl) { if ((pl->s_name[0]=='=')&&(pl->s_value!=LBL_EXT) &&(pl->s_value!=LBL_IVL)) { nl++ ; fprintf (fd_o, "%s\n", pl->s_name) ; fputl (pl->s_value, fd_o) ; if (pl->s_value<0L) fprintf (fd_o, "%s\n", pl->s_def) ; else fputc (pl->s_type, fd_o) ; } pl = pl->s_next ; } } p3 = ftell (fd_o) ; /* begin of third part */ fputl (zero, fd_o) ; /* # used in third part */ while (headxu) { nu++ ; l = (long int) headxu->u_characteristic ; fputl (l, fd_o) ; fputl (headxu->u_pc, fd_o) ; fprintf (fd_o, "%s\n", headxu->u_expression) ; h = headxu ; headxu = headxu->u_next ; free ((char *) h) ; } fseek (fd_o, zero, 0) ; fputl (magic, fd_o) ; fputl (p2, fd_o) ; /* begin of second part */ fputl (pc, fd_o) ; /* # nibs in the code */ fseek (fd_o, p2, 0) ; fputl (p3, fd_o) ; /* begin of third part */ fputl (nl, fd_o) ; /* # labels defined in this module */ fseek (fd_o, p3, 0) ; fputl (nu, fd_o) ; /* # unresolved references here */ if (ferror (fd_o)) error (ERRWRT, fobject) ; } @EOF set `wc -lwc areuh/assembler/aopc1.c <<'@EOF' /* * Authors : * Pierre DAVID (pda@masi.ibp.fr or pda@frunip62.bitnet) * Janick TAILLANDIER * * This program can be freely used or distributed as long as this * note is kept. * * This program is provided "as is". */ /****************************************************************************** AREUH ASSEMBLER OPCODE PROCESSING (PART 1) ******************************************************************************/ #include "aglobal.h" #include "agen.h" #define UPRC(c) ((((c)>='a')&&((c)<='z')) ? (c)-32 : (c)) extern uchar *memoire() ; extern saddr calc_expression () ; extern uchar hex () ; /****************************************************************************** ADD_XUSED synopsis : void add_xused (type, pc, len, exp) int type, len saddr pc uchar *exp description : adds the parameters about the use of an expression containing external references. ******************************************************************************/ void add_xused (type, addr, len, exp) int type, len ; saddr addr ; uchar *exp ; { struct xused *xu ; xu = (struct xused *) memoire (sizeof (struct xused)) ; if (xu==(struct xused *) NULL) error (ERRMEM, "") ; xu->u_characteristic = (uchar) (type + len) ; xu->u_pc = addr ; xu->u_expression = memoire (strlen (exp) + 1) ; if (xu->u_expression==(uchar *)NULL) error (ERRMEM, "") ; strcpy (xu->u_expression, exp) ; xu->u_next = headxu ; /* queue it */ headxu = xu ; /* before the previous head */ } /****************************************************************************** FIELD_SELECT synopsis : field_select (modif) uchar *modif description : to be described, in a (far) future... ******************************************************************************/ int field_select (modif) uchar *modif ; { int r = 0 ; char c ; switch (UPRC(*modif)) { case 'P' : r = 1 ; break ; case 'W' : if (UPRC(modif[1])=='P') { r = 2 ; modif++ ; } else r = 8 ; break ; case 'X' : if (UPRC(modif[1])=='S') { r = 3 ; modif++ ; } else r = 4 ; break ; case 'S' : r = 5 ; break ; case 'M' : r = 6 ; break ; case 'B' : r = fs_B ; break ; case 'A' : r = fs_A ; break ; } c = *(++modif) ; if ((c!=' ')&&(c!=EOL)&&(c!='\t')) r = 0 ; return (r) ; } void regtest(ad, modif) struct mnemo_desc *ad ; uchar *modif ; { int r ; if (r=field_select(modif) ) { if (r==fs_A) { gen_code[1] = hex (r + ad->m_a) ; } else { gen_code[0] = '9' ; gen_code[1] = hex ((ad->m_a==2) ? r+7 : r-1) ; } } else error (WRNIWS, "") ; } void regarith (ad, modif) struct mnemo_desc *ad ; uchar *modif ; { int r ; if (r=field_select(modif)) { /* gen_len is 3 by default */ if (r==fs_A) gen_len = 2 ; if (passnb==2) { if (r==fs_A) { gen_code[0] = hex (ad->m_a + 11) ; gen_code[1] = gen_code[2] ; gen_code[2] = EOL ; } else { gen_code[0] = hex(((ad->m_a==ar_C)||(ad->m_a==ar_D))?10:11) ; gen_code[1] = hex(((ad->m_a==ar_C)||(ad->m_a==ar_E))?r-1:r+7) ; } } } else error (WRNIWS, "") ; } void reglogic (modif) uchar *modif ; { int r ; if (r=field_select(modif)) gen_code[2] = (r==fs_A) ? 'F' : hex(r-1) ; else error (WRNIWS, "") ; } int range (org, dest, nibs, offset) saddr org, dest, *offset ; int nibs ; { saddr Sixtine, Fiftine ; int r ; Sixtine = ((saddr) 1) << (nibs*4) ; Fiftine = Sixtine >> 1 ; *offset = dest - org ; r = ((*offset >= -Fiftine) && (*offset < Fiftine)) ; if (*offset<0) (*offset) += Sixtine ; /* -128 = 128 ; -1 = 255 */ return (r) ; } void branches (ad, modif) struct mnemo_desc *ad ; uchar *modif ; { saddr val, offset, pc_bis ; int fits, i, j ; uchar hex_var[MAXLEN+1] ; if ((ad->m_flag & F_GOYS) && (!(prev_test))) error (WRNTST, "") ; /* needs previous test instruction */ else { val = calc_expression (modif) ; if (val >= 0L) { if (ad->m_flag & F_ABSL) { fits = 1 ; offset = val ; } else { if (ad->m_flag & F_GSUB) pc_bis = pc + (long int) gen_len ; else pc_bis = pc + (long int) (ad->m_a) - 1L ; fits = range (pc_bis, val, ad->m_b, &offset) ; } if (!(fits)) { offset = 0L ; error (WRNJVL, "") ; /* Jump or value too large */ } hex6 (hex_var, offset) ; for (i=1, j=5; i<=ad->m_b; i++, j--) { gen_code[ad->m_a + i - 2] = hex_var[j] ; } gen_code[gen_len] = EOL ; } else /* EXP_ERR or EXP_EXT */ { if (val == EXP_EXT) { switch (ad->m_flag & (F_GSUB | F_ABSL)) { case F_GSUB : i = XRGSB ; break ; case F_ABSL : case F_ABSL | F_GSUB : i = XABSL ; break ; default : i = XRGTO ; break ; } add_xused (i, pc + (long int) ad->m_a - 1L, ad->m_b, extexp) ; } for (i=0; im_b; i++) gen_code [ad->m_a - 1 + i] = '0' ; gen_code [gen_len] = EOL ; } } } void rtnyes() { if (!(prev_test)) error (WRNTST, "") ; /* needs previous test instr. */ } void ptrtest (modif) uchar *modif ; { saddr val ; val = calc_expression (modif) ; if (val == EXP_EXT) { add_xused (XABSL, pc + 2L, 1, extexp) ; val = (saddr) 0 ; /* FALLS INTO FOLLOWING */ } if (val == EXP_ERR) val = (saddr) 0 ; /* FALLS INTO FOLLOWING */ if (val>15L) error (WRNIPP, "") ; /* illegal pointer position */ else gen_code[2] = hex ((int) val) ; } void stattest (modif) uchar *modif ; { saddr val ; val = calc_expression (modif) ; if (val == EXP_EXT) { add_xused (XABSL, pc + 2L, 1, extexp) ; val = (saddr) 0 ; /* FALLS INTO FOLLOWING */ } if (val == EXP_ERR) val = (saddr) 0 ; /* FALLS INTO FOLLOWING */ if (val>15L) error (WRNISB, "") ; /* illegal status bit */ else gen_code[2] = hex ((int) val) ; } void setptr (modif) uchar *modif ; { saddr val ; val = calc_expression (modif) ; if (val == EXP_EXT) { add_xused (XABSL, pc + (long int) gen_len - 1L, 1, extexp) ; val = (saddr) 0 ; } /* FALLS INTO FOLLOWING */ if (val == EXP_ERR) val = (saddr) 0 ; /* FALLS INTO FOLLOWING */ if (val>15L) error (WRNIPP, "") ; /* illegal pointer position */ else gen_code[gen_len-1] = hex ((int) val) ; } void setstat (modif) uchar *modif ; { saddr val ; val = calc_expression (modif) ; if (val == EXP_EXT) { add_xused (XABSL, pc + 2L, 1, extexp) ; val = (saddr) 0 ; } /* FALLS INTO FOLLOWING */ if (val == EXP_ERR) val = (saddr) 0 ; /* FALLS INTO FOLLOWING */ if (val>15L) error (WRNISB, "") ; /* illegal status bit */ else gen_code[2] = hex ((int) val) ; } void dparith (modif) uchar *modif ; { saddr val ; val = calc_expression (modif) ; if (val >= 0L) { if ((val<1L)||(val>16L)) error (WRNIDP, "") ; /* illegal dp arithmetic value */ else gen_code[2] = hex (val - 1L) ; } else if (val == EXP_EXT) { add_xused (XABSO, pc + 2L, 1, extexp) ; val = (saddr) 1 ; } else /* (val == EXP_ERR) */ { val = (saddr) 1 ; } } void datatrans (modif) uchar *modif ; { saddr val ; int r ; r=field_select (modif) ; if ((r==fs_A)||(r==fs_B)) gen_len = 3 ; if (passnb == 2) { switch (r) { case 0 : /* expression instead of field selector */ val = calc_expression (modif) ; if (val >= 0L) { if ((val<1L)||(val>16)) error (WRNTFR, "") ; /* illegal transfer value */ else { gen_code[2] = hex (dec(gen_code[2])+8) ; gen_code[3] = hex ((int) val - 1L) ; } } else if (val == EXP_EXT) { add_xused (XABSO, pc + 3L, 1, extexp) ; gen_code[2] = hex (dec(gen_code[2])+8) ; /* ajout */ val = 1L ; } else /* (val == EXP_EXT) */ { val = 1L ; } break ; case fs_A : gen_len = 3 ; gen_code[1] = '4' ; gen_code[3] = EOL ; break ; case fs_B : gen_len = 3 ; gen_code[1] = '4' ; gen_code[2] = hex ( dec(gen_code[2]) + 8) ; gen_code[3] = EOL ; break ; default : gen_code[3] = hex (r-1) ; break ; } } } int hex_len (modif) /* aCLCHX : AS5 : ED094 */ uchar *modif ; { int i = 0 ; if (*modif=='#') modif++ ; while (((*modif>='0')&&(*modif<='9'))|| ((*modif>='A')&&(*modif<='F'))|| ((*modif>='a')&&(*modif<='f'))) { modif++ ; i++ ; } return ((i>16) ? 16 : i) ; } void check_last_hex (digit) uchar digit ; { if ((digit!=EOL)&&(digit!='\t')&&(digit!=' ')) { if ((digit<'0')|| ((digit>'9')&&(digit<'A'))|| ((digit>'F')&&(digit<'a'))|| (digit>'f')) error (WRNTMH, "") ; /* too many hex digit present */ else error (WRNNHX, "") ; /* non hexadecimal digit present */ } } void nibhex (modif) uchar *modif ; { int i ; gen_len = hex_len (modif) ; if (passnb==2) { if (*modif=='#') modif++ ; for (i=0; i='a') gen_code[i] = modif[i] - 32 ; else gen_code[i] = modif[i] ; } gen_code[gen_len] = EOL ; check_last_hex (modif[gen_len]) ; } } void lchex (modif) uchar *modif ; { int i, j ; gen_len = hex_len (modif) ; if (passnb==2) { if (*modif=='#') modif++ ; if (gen_len) { gen_code[1] = hex (gen_len - 1) ; for (i=0, j=gen_len-1; i='a') gen_code[2+i] = modif[j] - 32 ; else gen_code[2+i] = modif[j] ; } gen_code[gen_len + 2] = EOL ; check_last_hex (modif[gen_len]) ; } else { gen_code[0] = EOL ; error (WRNNHX, "") ; /* non hex present (in fact, there is no) */ } } gen_len = (gen_len) ? gen_len+2 : 0 ; } void dxhex (modif) uchar *modif ; { int i, j, r ; r = hex_len (modif) ; if (passnb==2) { if ((r!=2)&&(r!=4)&&(r!=5)) error (WRNIHX, "") ; /* illegal hex const (number of digits) */ else { if (*modif=='#') modif++ ; /* if 2, no change to the opcode */ /* if 4, add 1, if 5 add two */ if (r!=2) gen_code[1] = hex (dec(gen_code[1]) + r - 3) ; for (i=0, j=r-1; i='a') gen_code[2+i] = modif[j] - 32 ; else gen_code[2+i] = modif[j] ; } gen_code[r+2] = EOL ; check_last_hex (modif[r]) ; } } gen_len = ((r==4)||(r==5)) ? r+2 : 4 ; } int ascii_len (modif) uchar *modif ; { uchar limit ; int i = 0 ; switch (*modif) { case '\'' : case '\\' : limit = *modif++ ; while ((*modif!=limit)&&(*modif)) { modif++ ; i++ ; } break ; } return ((i>8) ? 8 : i) ; } void nibasc (modif) uchar *modif ; { uchar limit ; int i ; gen_len = ascii_len (modif) ; if (passnb==2) { limit = *modif ; for (i=1; i<=gen_len; i++) { gen_code[2*(i-1)] = hex (((int) modif[i]) % 16) ; gen_code[2*i-1] = hex (((int) modif[i]) / 16) ; } gen_code[2*gen_len] = EOL ; switch (modif[gen_len + 1]) { case '\'' : case '\\' : if (modif[gen_len + 1]!=limit) error (WRNTMA, "") ; /* too many ascii chars present */ break ; case EOL : error (WRNASC, "") ; /* illegal ascii constant */ break ; default : error (WRNTMA, "") ; /* too many ascii chars present */ break ; } } gen_len *= 2 ; } void lcasc (modif) uchar *modif ; { uchar limit ; int i ; gen_len = ascii_len (modif) ; if (passnb==2) { limit = *modif ; for (i=1; i<=gen_len; i++) { gen_code[2*i] = hex (((int) modif[gen_len - i + 1]) % 16) ; gen_code[2*i+1] = hex (((int) modif[gen_len - i + 1]) / 16) ; } gen_code[2+2*gen_len] = EOL ; switch (modif[gen_len + 1]) { case '\'' : case '\\' : if (modif[gen_len + 1]!=limit) error (WRNTMA, "") ; /* too many ascii chars present */ break ; case EOL : error (WRNASC, "") ; /* illegal ascii constant */ break ; default : error (WRNTMA, "") ; /* too many ascii chars present */ break ; } gen_code[1] = hex (2*gen_len - 1) ; } gen_len = (gen_len) ? 2+2*gen_len : 0 ; } @EOF set `wc -lwc