home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume7 / micro.asm / part01 next >
Encoding:
Internet Message Format  |  1987-01-28  |  47.2 KB

  1. Subject:  v07i097:  Generic assembler for micros, Part01/02
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: seismo!cisden!lmc
  6. Mod.sources: Volume 7, Issue 97
  7. Archive-name: micro.asm/Part01
  8.  
  9. Yet another assembler.......
  10.  
  11. This one is for assembling absolute code (for prom loading, fer instance)
  12. for 8 and 16 bit microprocessors. I've used it successfully as a back-end
  13. for the small c compiler posted previously, and it works just fine, as
  14. long as you don't need any external subroutines loaded later on. Lints
  15. out as much as possible, but there are probably still some few errors
  16. within, particularly for 16 bit uPs. Feedback welcome. Also any newly
  17. generated machine tables.
  18.  
  19. Shouldn't be too hard to add relocation stuff - I just didn't have that
  20. need.
  21.  
  22. : This is a shar archieve.  Extract with sh, not csh.
  23. : The rest of this file will extract:
  24. : 6803reg.h Makefile README asm.1 asm.c asm.h asm_ops.5
  25. echo extracting - 6803reg.h
  26. sed 's/^X//' > 6803reg.h << '-FUNKY STUFF~'
  27. X
  28. X; control register & bit definition
  29. X;       assumes operating mode 2 or 3
  30. X
  31. Xp1ddr   equ     0       ; port 1 data direction
  32. Xp2ddr   equ     01      ; port 2 data direction
  33. Xp1dr    equ     02      ; port 1 data
  34. Xp2dr    equ     03      ; port 2 data
  35. X
  36. Xp2d_pc2     equ     080
  37. Xp2d_pc1     equ     040
  38. Xp2d_pc0     equ     020
  39. Xp2d_p24     equ     010
  40. Xscixmt      equ     p2d_p24
  41. Xp2d_p23     equ     08
  42. Xscircv      equ     p2d_p23
  43. Xp2d_p22     equ     04
  44. Xsciclock    equ     p2d_p22
  45. Xp2d_p21     equ     02
  46. Xtimerout    equ     p2d_p21
  47. Xp2d_p20     equ     01
  48. Xtimerin     equ     p2d_p20
  49. X
  50. Xtcsr    equ     08      ; timer control & status
  51. X
  52. Xtcs_icf     equ     080     ; input capture flag
  53. Xtcs_ocf     equ     040     ; output capture flag
  54. Xtcs_tof     equ     020     ; timer overflow flag
  55. Xtcs_eici    equ     010     ; enable input capture interrupt
  56. Xtcs_eoci    equ     08      ; enable output capture flag
  57. Xtcs_etoi    equ     04      ; enable timer overflow interrupt
  58. Xtcs_iedg    equ     02      ; input edge
  59. Xtcs_olvl    equ     01      ; output level
  60. X
  61. Xcounth  equ     09      ; timer counter msb
  62. Xcountl  equ     0a      ; timer counter lsb
  63. Xoutcmh  equ     0b      ; timer output compare msb
  64. Xoutcml  equ     0c      ; timer output compare lsb
  65. Xincaph  equ     0d      ; input capture msb
  66. Xincapl  equ     0e      ; input capture lsb
  67. Xrmcr    equ     010     ; SCI rate & mode control
  68. X
  69. Xrmc_cc1     equ     08
  70. Xrmc_cc0     equ     04
  71. Xrmc_cc      equ     0c      ; clock source and format
  72. Xrmc_ss1     equ     02
  73. Xrmc_ss0     equ     01
  74. Xrmc_ss      equ     03      ; clock speed select 0-3, hi-lo
  75. X
  76. Xtrcsr   equ     011     ; xmit/rcv control & status
  77. X
  78. Xtrc_rdf     equ     080     ; rcv data reg full
  79. Xtrc_ofe     equ     040     ; overrun or framing error
  80. Xtrc_tre     equ     020     ; xmit data reg empty
  81. Xtrc_rie     equ     010     ; rcv interrupt enable
  82. Xtrc_re      equ     08      ; receiver enable
  83. Xtrc_tie     equ     04      ; xmit interrupt enable
  84. Xtrc_te      equ     02      ; transmitter enable
  85. Xtrc_wu      equ     01      ; wakeup
  86. X
  87. Xscirdr  equ     012     ; SCI rcv data
  88. Xscitdr  equ     013     ; SCI xmit data
  89. Xramcr   equ     014     ; RAM control
  90. X
  91. Xram_sb      equ     080     ; stand-by power
  92. Xram_e       equ     040     ; internal RAM enabled
  93. X
  94. Xstintram equ    080
  95. Xenintram equ    0ff
  96. X
  97. X; interrupt vectors
  98. X
  99. Xvectors equ     0ff0
  100. Xscivec  equ     vectors+0
  101. Xtofvec  equ     vectors+02
  102. Xtocvec  equ     vectors+04
  103. Xticvec  equ     vectors+06
  104. Xrq1vec  equ     vectors+08
  105. Xswivec  equ     vectors+0a
  106. Xnmivec  equ     vectors+0c
  107. Xstartvec equ    vectors+0e
  108. -FUNKY STUFF~
  109. echo extracting - Makefile
  110. sed 's/^X//' > Makefile << '-FUNKY STUFF~'
  111. XCFLAGS=-O
  112. X
  113. Xasm:    asm.o
  114. X    cc asm.o -o asm
  115. X
  116. Xasm.o:  asm.h ops.h
  117. X
  118. Xclean:
  119. X    rm -f asm *.o
  120. -FUNKY STUFF~
  121. echo extracting - README
  122. sed 's/^X//' > README << '-FUNKY STUFF~'
  123. XSimplicity itself: just link one of the XXXX_ops.h files to ops.h,
  124. Xand say make. You've got an assembler.
  125. X
  126. X6803reg.h has some specific register names for special hardware registers
  127. Xon the 6803.
  128. X
  129. XI would appreciate getting back any new ops.h files anyone cares to
  130. Xgenerate (or maybe regenerate). Send them to hao!cisden!lmc, or to
  131. X
  132. X    Lyle McElhaney
  133. X    Contel, Inc.
  134. X    1101 W. Mineral Ave.
  135. X    Littleton, CO 80120
  136. -FUNKY STUFF~
  137. echo extracting - asm.1
  138. sed 's/^X//' > asm.1 << '-FUNKY STUFF~'
  139. X.so /usr/lib/tmac/tmac.e
  140. X.TH ASM 1 "1 May 1986"
  141. X.SH NAME
  142. Xasm \- generic assembler
  143. X.SH SYNOPSIS
  144. X.B asm
  145. X[
  146. X.B \-o
  147. Xbinname] [
  148. X.B \-l
  149. Xlistname] [
  150. X.B \-x
  151. Xxrefname] inputfile
  152. X.br
  153. X.SH DESCRIPTION
  154. XThe generic assembler is an attempt to build a quick-and-dirty meta-
  155. Xassembler, with which code for several types of microcomputers can be
  156. Xgenerated. It outputs absolute code in two passes, contains a minimum of
  157. Xpseudo-ops, and is quasi-portable between micro types. The opcodes and
  158. Xinstruction layout information is contained within tables, leaving the
  159. Xcode unchanged from micro to micro. There has been no effort expended to
  160. Xmake the assembler match any particular assembly format on the market, so
  161. Xdon't expect any miracles there.
  162. X
  163. XThe statup options specify various files for input and output. The basic
  164. Xoption is the name of the input file; normally it is suffixed by ".a",
  165. Xalthough this is not necessary. If no file is given, then input is taken
  166. Xfrom standard input. The
  167. X.B \-o
  168. Xoption introduces the name of the file to receive the binary
  169. Xoutput. If the option does not exist, the binary goes to standard output
  170. X(since the output is actually in ASCII format, it won't bolix your screen
  171. Xif you forget).  If the option is not followed immediately by a filename,
  172. Xthen the binary will be output to the input file name suffixed by ".o".
  173. XThe format of the binary output is "Intel Standard Hexadecimal Format" and
  174. Xis documented in the source code.
  175. XThe
  176. X.B \-l
  177. Xoption similarly specifies the file for the assembly listing; if the
  178. Xoption is not given, no listing is produced. If the option is alone, then
  179. Xthe listing will go into the input file name suffixed with ".l". The
  180. X.B \-x
  181. Xoption specifies the file to receive the cross-reference; it defaults to
  182. Xthe same filename as the listing, and is deleted if the option is not
  183. Xgiven.
  184. X.pp
  185. XThe assembler boasts (or at least admits) the following features:
  186. X.in +.5i
  187. X.ip \(bu
  188. XTwo pass, all labels are defined both forward and backward.
  189. X.ip \(bu
  190. XAbsolute format code only, no relocation information available.
  191. X.ip \(bu
  192. XTable driven instruction formats, including single opcodes and fixed
  193. Xnumbers of operands.
  194. X.ip \(bu
  195. XExpression evaluation in operands is left-to-right, no precedence or
  196. Xparentheses.
  197. X.ip \(bu
  198. XPredefined symbols accomodated.
  199. X.ip \(bu
  200. XPseudo-ops include org, equ, set (for changing manifest variables), bss,
  201. Xdata, data2 (two bytes!!), string, seg (for setting up data segments that
  202. Xare made contiguous right after pass 1)
  203. Xand end.
  204. X.ip \(bu
  205. XAtoms in operands include labels, ops add (+), subtract (-), multiply (*),
  206. Xinteger divide (/), mod (%), and (&), or (|), and exclusive or (^),
  207. Xdecimal constants, hexadecimal constants (with a leading zero), right
  208. Xjustified zero-filled single characters ('x) and double characters ("xx).
  209. XThe string pseudo-op supports strings surrounded by any unused delimiter.
  210. X.in -.5i
  211. X.pp
  212. XThe pseudo op syntax is as follows:
  213. X.in +.5i
  214. X.ip "[label] org     expr
  215. XSet the value of the symbol in label to the current location counter; set
  216. Xthe location counter to the value of the expression.
  217. X.ip "label   equ     expr
  218. XSet the value of the symbol in label to the value of the expression. Any
  219. Xsuch value may only be changed by a "set" pseudo.
  220. X.ip "label   set     expr
  221. XReset the value of a symbol to the value of the expression.
  222. X.ip "[label] bss     expr
  223. XSet the value of the symbol in the label to the current location counter,
  224. Xthen set the location counter to its current value plus the value of the
  225. Xexpression.
  226. X.ip "[label] data    [:count:]expr
  227. XSet the value of the label to the current location counter, and then
  228. Xgenerate count (default 1) bytes of data, each containing the value of the
  229. Xexpression. Count must contain no forward referenced symbols.
  230. X.ip "[label] data2   [:count:]expr
  231. XSet the value of the label to the current location counter, and then
  232. Xgenerate count (default 1) double-bytes of data, each double-byte
  233. Xcontaining the value of the expression.
  234. XCount must contain no forward referenced symbols.
  235. X.ip "[label] string  $string$
  236. XSet the value of the label to the current location counter, and then
  237. Xgenerate the string as bytes from left to right, appending a single nul
  238. Xbyte. The string delimiter shown above ($) may be any character that
  239. Xdoesn't appear in the string itself, except blank or tab. The special
  240. Xescapes \\t (tab), \\r (carriage return), \\n (newline), \\b (backspace),
  241. X\\? (del), \\^ (escape), \\nn (nn is any hex pair) and \\\\ (\\ itself)
  242. Xare allowed.
  243. X.ip "    seg   [name]
  244. XDeclare a new or reuse an older data segment, which defines it's own
  245. Xlocation counter. The segment that is predefined at the beginning of the
  246. Xassembler may be returned to by a
  247. X.b seg
  248. Xwith no argument.  Any number of segments may be invoked.  Each segment's
  249. Xlocation counter starts at zero during pass 1. When pass 1 is complete,
  250. Xthe segments are "stacked" in the order that they were created, so that
  251. Xthe second segment's lc starts at the first location following the end of
  252. Xthe first segment's highest lc.  These computed lc's are displayed in the
  253. Xpass 2 listing output.  The name used may be any non-blank-containing
  254. Xstring; it is also independent of the symbol name space. At this time,
  255. Xthere are no other definable characteristics of segments.
  256. X.in -.5i
  257. X.SH "OTHER FILES
  258. X/tmp/asm* - intermediate files.
  259. X.SH AUTHOR
  260. XLyle McElhaney
  261. -FUNKY STUFF~
  262. echo extracting - asm.c
  263. sed 's/^X//' > asm.c << '-FUNKY STUFF~'
  264. X#include <stdio.h>
  265. X
  266. X#include "asm.h"
  267. X
  268. Xopdclass o_none  = {0, 0, 0, 0};
  269. Xinsclass i_noopd = {1, 0, &o_none, &o_none, 0, 0};
  270. Xopdef pseudotab[] = {
  271. X    "bss"    , &i_noopd, 0x00, do_bss   ,
  272. X    "data"   , &i_noopd, 0x00, do_data  ,
  273. X    "data2"  , &i_noopd, 0x00, do_data2 ,
  274. X    "end"    , &i_noopd, 0x00, do_end   ,
  275. X    "equ"    , &i_noopd, 0x00, do_equ   ,
  276. X    "include", &i_noopd, 0x00, do_incl  ,
  277. X    "listoff", &i_noopd, 0x00, do_loff  ,
  278. X    "liston" , &i_noopd, 0x00, do_lon   ,
  279. X    "org"    , &i_noopd, 0x00, do_org   ,
  280. X    "seg"    , &i_noopd, 0x00, do_seg   ,
  281. X    "set"    , &i_noopd, 0x00, do_set   ,
  282. X    "string" , &i_noopd, 0x00, do_string,
  283. X};
  284. X#include "ops.h"
  285. X
  286. X#define pseudolen sizeof(pseudotab)/sizeof(opdef)
  287. X
  288. XFILE *input[INCLSTACK], *output, *list;
  289. XFILE *srcin, *binout;
  290. X
  291. Xint errorstat = 0;
  292. Xchar *name;
  293. Xchar *label, *op, *opd;
  294. Xchar buf[100], linecopy[100];
  295. Xchar *filename[INCLSTACK];
  296. Xint lineno[INCLSTACK];
  297. Xint currinput = 0;
  298. Xint pass = 0;
  299. Xint liston = YES;
  300. Xint listing = 0;
  301. Xint binary = 0;
  302. Xint xref = 0;
  303. Xint ignerr;
  304. Xsymbol *symtab;
  305. XMemad lc;
  306. XWord *dummy;
  307. Xsegmnt segmain = {0, 0, "", 0};
  308. Xsegmnt *seghd = &segmain;
  309. Xsegmnt *curseg = &segmain;
  310. Xsegmnt *exprseg;
  311. X
  312. Xmain (argc, argv)
  313. X    int argc;
  314. X    char **argv;
  315. X{
  316. X    char *t1, *t2;
  317. X
  318. X    srcin = stdin;
  319. X    filename[0] = "stdin";
  320. X    binout = stdout;
  321. X    getargs (argc, argv);
  322. X    init ();
  323. X    output = fopen ((t1 = mktemp ("/tmp/asm185XXXXXX")), "w+");
  324. X    input[0] = srcin;
  325. X    if (process ()) reporterr (E_PASS1);
  326. X    (void) fclose (input[0]);
  327. X    init2 ();
  328. X    rewind (output);
  329. X    input[0] = output;
  330. X    output = fopen ((t2 = mktemp ("/tmp/asm285XXXXXX")), "w+");
  331. X    if (process ()) reporterr (E_PASS2);
  332. X    (void) fclose (input[0]);
  333. X    (void) unlink (t1);
  334. X    input[0] = output;
  335. X    output = binout;
  336. X    rewind (input[0]);
  337. X    sort ();
  338. X    (void) fclose (input[0]);
  339. X    (void) unlink (t2);
  340. X    (void) fclose (output);
  341. X    if (xref) crossref ();
  342. X    exit (errorstat);
  343. X}
  344. X
  345. X
  346. X/*      Current arguments:
  347. X        infile  input file name (default stdin)
  348. X        -lfile  listing output to file (default no listing),
  349. X            (default file is infile.l);
  350. X        -ofile  binary output to file (default binary to stdout),
  351. X            (default file is infile.o);
  352. X        -xfile  cross reference output to listing file (default no xref);
  353. X*/
  354. Xvoid getargs (argc, argv)
  355. X    int argc;
  356. X    char **argv;
  357. X{
  358. X    char *cp, *arg, *lname, *oname;
  359. X
  360. X    while (--argc) {
  361. X        arg = *(++argv);
  362. X        if (*arg == '-') {
  363. X            switch (*(++arg)) {
  364. X            case 'l':
  365. X                listing ++;
  366. X                lname = ++arg;
  367. X                break;
  368. X            case 'o':
  369. X                binary ++;
  370. X                oname = ++arg;
  371. X                break;
  372. X            case 'x':
  373. X                xref ++;
  374. X                break;
  375. X            }
  376. X        } else {
  377. X            name = arg;
  378. X            if ((srcin = fopen (name, "r")) == NULL)
  379. X                reporterr (E_INPUT);
  380. X            filename[0] = strcpy (malloc ((unsigned) strlen (name) + 1), name);
  381. X            if (cp = index (name, '.'))
  382. X                *cp = '\0';
  383. X        }
  384. X    }
  385. X    if (binary) {
  386. X        if (!*oname) {
  387. X            (void) strcat (strcpy (buf, name), ".o");
  388. X            oname = buf;
  389. X        }
  390. X        binout = fopen (oname, "w");
  391. X    }
  392. X    if (listing || xref) {
  393. X        if (!*lname) {
  394. X            (void) strcat (strcpy (buf, name), ".l");
  395. X            lname = buf;
  396. X        }
  397. X        list = fopen (lname, "w");
  398. X    }
  399. X    return;
  400. X}
  401. X
  402. X
  403. Xvoid init ()
  404. X{
  405. X    symbol *spt;
  406. X    int i;
  407. X
  408. X    lc = seghd->lc = 0;
  409. X    symtab = (symbol *) malloc ((unsigned) sizeof (symbol) * NSYMS);
  410. X    for (i = 0; i < NSYMS; i++)
  411. X        symtab->name = (char *) 0;
  412. X    for (spt = predef; *(spt->name); spt++)
  413. X        insert (spt->name, spt->value, spt->type, spt->segp, NO);
  414. X    return;
  415. X}
  416. X
  417. X
  418. Xvoid init2 ()
  419. X{
  420. X    segmnt *sp;
  421. X    Memad acc;
  422. X
  423. X    acc = seghd->lc;
  424. X    seghd->lc = 0;
  425. X    for (sp = seghd->next; sp; sp = sp->next) {
  426. X        acc += sp->lc;
  427. X        sp->lc = sp->start = acc - sp->lc;
  428. X    }
  429. X    curseg = seghd;
  430. X    lc = curseg->lc;
  431. X    errorstat = 0;
  432. X    return;
  433. X}
  434. X
  435. X
  436. X
  437. X/*      Gross syntax rules:      <and the rest of us simply obey>
  438. X    Input line:     [label] op [operands]
  439. X    Comments: Blank lines and anything following ';'
  440. X    White space is any combination of blank and/or tab chars.
  441. X    Operands cannot contain white space (except within strings)
  442. X        and are separated by commas.
  443. X    Label must start in col 1 if it exists.
  444. X*/
  445. Xint process ()
  446. X{
  447. X    char *ipt;
  448. X    int i, done;
  449. X    static char *zit = "";
  450. X
  451. X    pass ++;
  452. X    lineno[0] = 0;
  453. Xcontproc:
  454. X    while (fgets (buf, sizeof buf, input[currinput]) != NULL) {
  455. X        (void) strcpy (linecopy, buf);
  456. X        linecopy[strlen(linecopy)-1] = 0;
  457. X        if (pass == 1) fputs (buf, output);
  458. X        lineno[currinput]++;
  459. X        ipt = buf;
  460. X        label = ipt;
  461. X        op = opd = zit;
  462. X        while (islabel (*ipt)) ipt++;
  463. X        if (iseol (*ipt)) {
  464. X            if (pass == 2)
  465. X                listit (linecopy, lc, dummy, 0);
  466. X            continue;
  467. X        }
  468. X        *ipt++ = 0;
  469. X        while (iswhite (*ipt)) ipt++;
  470. X        if (iseol (*ipt)) {
  471. X            if (pass == 2)
  472. X                listit (linecopy, lc, dummy, 0);
  473. X            continue;
  474. X        }
  475. X        op = ipt;
  476. X        while (isalnum (*ipt)) ipt++;
  477. X        if (iseol (*ipt)) {
  478. X            *ipt = 0;
  479. X            goto parsed;
  480. X        }
  481. X        *ipt++ = 0;
  482. X        while (iswhite (*ipt)) ipt++;
  483. X        opd = ipt;
  484. X        while (*ipt != '\n') ipt++;
  485. X        *ipt = 0;
  486. Xparsed:
  487. X        if ((i = opsrch (op, pseudotab, pseudolen)) >= 0) {
  488. X            done = (pseudotab[i].action) ();
  489. X        } else if ((i = opsrch (op, optab, oplen)) >= 0) {
  490. X            (void) (optab[i].action) (i);
  491. X        } else {
  492. X            reporterr (E_ILLOP);
  493. X            listit (linecopy, lc, dummy, 0);
  494. X        }
  495. X        if (done) break;
  496. X    }
  497. X    if (currinput > 0) {
  498. X        free (filename[currinput]);
  499. X        filename[currinput] = NULL;
  500. X        (void) fclose (input[currinput--]);
  501. X        goto contproc;
  502. X    }
  503. X    return (errorstat);
  504. X}
  505. X
  506. Xint opsrch (op, table, tablen)
  507. X    char *op;
  508. X    int tablen;
  509. X    opdef table[];
  510. X{
  511. X    int i;
  512. X
  513. X    for (i = 0; i < tablen; i++)
  514. X        if (strcmp (table[i].name, op) == 0)
  515. X            return (i);
  516. X    return (-1);
  517. X}
  518. X
  519. X
  520. Xint do_incl ()
  521. X{
  522. X    if (pass == 1) {
  523. X        char *ip;
  524. X
  525. X        if (++currinput > INCLSTACK)
  526. X            reporterr (E_INCL);
  527. X        opd++;
  528. X        if ((ip = index (opd, '"')) == 0)
  529. X            reporterr (E_INCLSYN);
  530. X        *ip = 0;
  531. X        if ((input[currinput] = fopen (opd, "r")) == NULL)
  532. X            reporterr (E_INPUT);
  533. X        filename[currinput] = strcpy (malloc ((unsigned) strlen (opd) + 1), opd);
  534. X        lineno[currinput] = 0;
  535. X    }
  536. X    return (0);
  537. X}
  538. X
  539. X
  540. Xint do_org ()
  541. X{
  542. X    if (label && *label)
  543. X        insert (label, (long) lc, &o_mem, curseg, NO);
  544. X    if (pass == 2)
  545. X        listit (linecopy, lc, dummy, 0);
  546. X    lc = (Memad) expr (&opd, &ignerr, NO);
  547. X    return (0);
  548. X}
  549. X
  550. X
  551. Xint do_loff ()
  552. X{
  553. X    liston = NO;
  554. X    return (0);
  555. X}
  556. X
  557. X
  558. Xint do_lon ()
  559. X{
  560. X    liston = YES;
  561. X    return (0);
  562. X}
  563. X
  564. X
  565. Xint do_equ ()
  566. X{
  567. X    long eqtemp;
  568. X
  569. X    eqtemp = expr (&opd, &ignerr, NO);
  570. X    if (label && *label)
  571. X        insert (label, eqtemp, &o_mem, exprseg, NO);
  572. X    if (pass == 2)
  573. X        listit (linecopy, eqtemp, dummy, 0);
  574. X    return (0);
  575. X}
  576. X
  577. X
  578. Xint do_seg ()
  579. X{
  580. X    segmnt *sp, *osp;
  581. X
  582. X    curseg->lc = lc;
  583. X    if (opd && *opd) {
  584. X        for (sp = seghd; sp; osp = sp, sp = sp->next) {
  585. X            if (strcmp (sp->name, opd) == 0) {
  586. X                lc = sp->lc;
  587. X                curseg = sp;
  588. X                goto fin_seg;
  589. X            }
  590. X        }
  591. X    } else {
  592. X        lc = seghd->lc;
  593. X        curseg = seghd;
  594. X    }
  595. X    curseg = osp->next = (segmnt *) malloc ((unsigned) sizeof (segmnt));
  596. X    curseg->name = strcpy (malloc ((unsigned) strlen (opd) + 1), opd);
  597. X    curseg->lc = lc = 0;
  598. X    curseg->next = (segmnt *) 0;
  599. Xfin_seg:
  600. X    if (pass == 2)
  601. X        listit (linecopy, lc, dummy, 0);
  602. X    return (0);
  603. X}
  604. X
  605. X
  606. Xint do_set ()
  607. X{
  608. X    long eqtemp;
  609. X
  610. X    eqtemp = expr (&opd, &ignerr, NO);
  611. X    if (label && *label)
  612. X        insert (label, eqtemp, &o_mem, exprseg, YES);
  613. X    if (pass == 2)
  614. X        listit (linecopy, eqtemp, dummy, 0);
  615. X    return (0);
  616. X}
  617. X
  618. X
  619. Xint do_bss ()
  620. X{
  621. X    if (label && *label)
  622. X        insert (label, (long) lc, &o_mem, curseg, NO);
  623. X    if (pass == 2)
  624. X        listit (linecopy, lc, dummy, 0);
  625. X    lc += (Memad) expr (&opd, &ignerr, NO);
  626. X    return (0);
  627. X}
  628. X
  629. X
  630. Xint do_end ()
  631. X{
  632. X    curseg->lc = lc;
  633. X    if (pass == 2) {
  634. X        listit (linecopy, lc, dummy, 0);
  635. X        lc = 0xffff;
  636. X        putoutbin (dummy, 0);
  637. X    }
  638. X    curseg = seghd;
  639. X    return (1);
  640. X}
  641. X
  642. X
  643. Xint do_data ()
  644. X{
  645. X    Word temp, templist[MAXBYTPERINS];
  646. X    char *tp;
  647. X    int count;
  648. X
  649. X    if (label && *label)
  650. X        insert (label, (long) lc, &o_mem, curseg, NO);
  651. X    tp = opd;
  652. X    count = 1;
  653. X    if (*opd == ':') {
  654. X        ++opd;
  655. X        count = expr (&opd, &ignerr, NO);
  656. X        if (*opd == ':') {
  657. X            opd ++;
  658. X        } else {
  659. X            reporterr (E_EXPR);
  660. X            count = 1;
  661. X            opd = tp;
  662. X        }
  663. X    }
  664. X    if (pass == 2) {
  665. X        int i, j;
  666. X
  667. X        temp = (Word) expr (&opd, &ignerr, NO);
  668. X        for (i = 0; i < MAXBYTPERINS; i++)
  669. X               templist[i] = temp;
  670. X        for (i = count; i > 0; i -= 3) {
  671. X            j = i > MAXBYTPERINS ? MAXBYTPERINS : i;
  672. X            listit (linecopy, lc, templist, j);
  673. X            lc += j;
  674. X            *linecopy = 0;
  675. X        }
  676. X        for (i = 0; i < count; i++)
  677. X            putoutbin (&temp, 1);
  678. X    } else
  679. X        lc += count;
  680. X    return (0);
  681. X}
  682. X
  683. X
  684. Xint do_data2 ()
  685. X{
  686. X    long temp;
  687. X    char *tp;
  688. X    int count;
  689. X
  690. X    if (label && *label)
  691. X        insert (label, (long) lc, &o_mem, curseg, NO);
  692. X    tp = opd;
  693. X    count = 1;
  694. X    if (*opd == ':') {
  695. X        ++opd;
  696. X        count = expr (&opd, &ignerr, NO);
  697. X        if (*opd == ':') {
  698. X            opd ++;
  699. X        } else {
  700. X            reporterr (E_EXPR);
  701. X            count = 1;
  702. X            opd = tp;
  703. X        }
  704. X    }
  705. X    if (pass == 2) {
  706. X        int i;
  707. X
  708. X        temp = expr (&opd, &ignerr, NO);
  709. X        for (i = 0; i < count; i++) {
  710. X            listit (linecopy, lc, (Word *)&temp, 2);
  711. X            lc += 2;
  712. X            *linecopy = 0;
  713. X            putoutbin ((Word *)&temp, 1);
  714. X        }
  715. X    } else
  716. X        lc += (count * 2);
  717. X    return (0);
  718. X}
  719. X
  720. X
  721. Xint do_string ()
  722. X{
  723. X    Word buf[120], *bp;
  724. X    Word delim;
  725. X    int len, i;
  726. X
  727. X    if (label && *label)
  728. X        insert (label, (long) lc, &o_mem, curseg, NO);
  729. X    delim = *opd++;
  730. X    bp = buf;
  731. X    while (*opd != delim) {
  732. X        if (*opd != '\\')
  733. X            *bp++ = *opd;
  734. X        else {
  735. X            ++opd;
  736. X            *bp++ = escape (&opd);
  737. X        }
  738. X        opd++;
  739. X    }
  740. X    *bp++ = '\0';
  741. X    len = bp - buf;
  742. X    if (pass == 2) {
  743. X        for (bp = buf, i = 0; i < len; i += 3, bp += 3) {
  744. X            listit (linecopy, lc + i, bp, len + buf - bp);
  745. X            *linecopy = 0;
  746. X        }
  747. X        putoutbin (buf, len);
  748. X    }
  749. X    lc += len;
  750. X    return (0);
  751. X}
  752. X
  753. X
  754. Xint choiceinstr (ins)
  755. X    int ins;
  756. X{
  757. X    choicedef *chpt;
  758. X    int num, i, fits;
  759. X    Long value;
  760. X    static char *opdpt;
  761. X
  762. X    if (label && *label)
  763. X        insert (label, (long) lc, &o_mem, curseg, NO);
  764. X    chpt = (choicedef *)optab[ins].class;
  765. X    num = chpt->field;
  766. X    for (opdpt = opd; num > 1; num --) {
  767. X        opdpt = index (opdpt, ',');
  768. X        if (opdpt == NULL) {
  769. X            reporterr (E_NOPS);
  770. X            return (0);
  771. X        }
  772. X        opdpt++;
  773. X    }
  774. X    value = expr (&opdpt, &i, YES);
  775. X    fits = i ? NO :
  776. X        (value >= chpt->lorange &&
  777. X         value <= chpt->hirange &&
  778. X         curseg == exprseg);
  779. X    if ((i = opsrch ((fits ? chpt->rname : chpt->nname), optab, oplen)) >= 0) {
  780. X        (optab[i].action) (i);
  781. X    } else {
  782. X        reporterr (E_ILLOP);
  783. X    }
  784. X    return (0);
  785. X}
  786. X
  787. X
  788. Xint geninstr (ins)
  789. X    int ins;
  790. X{
  791. X    int nargs, length, i, j, k;
  792. X    opdclass *oclass;
  793. X    insclass *iclass;
  794. X    Word itemtemp, obuf[MAXBYTPERINS];
  795. X    unsigned long mask;
  796. X    static unsigned long cons = ~0L;
  797. X    union itemitem {
  798. X        Word s[BYTPERLONG];
  799. X        unsigned long l;
  800. X        long ls;
  801. X    } item;
  802. X    char *nextopd;
  803. X
  804. X    if (label && *label)
  805. X        insert (label, (long) lc, &o_mem, curseg, NO);
  806. X    iclass = optab[ins].class;
  807. X    length = iclass->length;
  808. X    if (pass == 2) {
  809. X        nargs = iclass->mopds;
  810. X        item.l = 0L;
  811. X        for (i = 0; i < MAXBYTPERINS; i++)
  812. X            obuf[i] = 0;
  813. X        *obuf = optab[ins].mask;
  814. X        nextopd = opd;
  815. X        for (j = 0; j < nargs; j++) {
  816. X            if (j != 0) {
  817. X                if (*nextopd != ',') {
  818. X                    reporterr (E_NOPS);
  819. X                } else {
  820. X                    nextopd++;
  821. X                }
  822. X            }
  823. X            oclass = iclass->type[j];
  824. X            item.l = expr (&nextopd, &ignerr, NO) + oclass->offset -
  825. X                (oclass->relative ? lc : 0);
  826. X            mask = cons >> (LONGLEN - oclass->length);
  827. X            if (item.l < 0L && !oclass->signed)
  828. X                reporterr (E_NEG);
  829. X            if (((item.ls < 0L && oclass->signed) ? -item.ls : item.ls) & ~mask)
  830. X                reporterr (E_TOOBIG);
  831. X            item.l &= mask;
  832. X            if (oclass->byteswapped) {
  833. X                itemtemp = item.s[BYTPERLONG - 2];
  834. X                item.s[BYTPERLONG - 2] = item.s[BYTPERLONG - 1];
  835. X                item.s[BYTPERLONG - 1] = itemtemp;
  836. X            }
  837. X            item.l <<= (LONGLEN - 8 - iclass->offset[j]);
  838. X            for (k = 0; k < MAXBYTPERINS; k++)
  839. X                obuf[k] |= item.s[k];
  840. X        }
  841. X        putoutbin (obuf, length);
  842. X        listit (linecopy, lc, obuf, length);
  843. X    }
  844. X    lc += length;
  845. X    return (0);
  846. X}
  847. X
  848. Xlong expr (string, errind, test)
  849. X    char **string;
  850. X    int *errind;
  851. X    int test;
  852. X{
  853. X    long exp, val;
  854. X    int op, err;
  855. X    int uniop = 0;
  856. X    segmnt *seg1, *seg2;
  857. X
  858. X    *errind = NO;
  859. X    if (**string == '-')
  860. X        uniop = 1;
  861. X    else if (**string == '~')
  862. X        uniop = 2;
  863. X    if (uniop)
  864. X        (*string)++;
  865. X    exp = getval(string, &err, test, &seg1);
  866. X    if (err) goto errorexit;
  867. X    if (uniop == 2)
  868. X        exp = ~exp;
  869. X    else if (uniop == 1)
  870. X        exp = -exp;
  871. X    while (!isdelim(**string)) {
  872. X        if ((op = getop (string)) == NOOP) {
  873. X            if (!test) reporterr (E_EXPR);
  874. Xerrorexit:              for (; !isdelim (**string); *string++)  ;
  875. X            *errind = YES;
  876. X            return (0);
  877. X        }
  878. X        val = getval (string, &err, test, &seg2);
  879. X        if (err) goto errorexit;
  880. X        if (seg1 && seg2 && seg1 != seg2 && pass == 1)
  881. X            reporterr (E_SEG);
  882. X        switch (op) {
  883. X        case PLUS:
  884. X            exp += val;
  885. X            break;
  886. X        case MINUS:
  887. X            exp -= val;
  888. X            break;
  889. X        case MULT:
  890. X            exp *= val;
  891. X            break;
  892. X        case DIV:
  893. X            exp /= val;
  894. X            break;
  895. X        case MOD:
  896. X            exp %= val;
  897. X            break;
  898. X        case OR:
  899. X            exp |= val;
  900. X            break;
  901. X        case AND:
  902. X            exp &= val;
  903. X            break;
  904. X        case EXOR:
  905. X            exp ^= val;
  906. X            break;
  907. X        case SHLF:
  908. X            exp <<= val;
  909. X            break;
  910. X        case SHRT:
  911. X            exp >>= val;
  912. X            break;
  913. X        default:
  914. X            if (!test) reporterr (E_EXPR);
  915. X        }
  916. X        seg1 = seg2;
  917. X    }
  918. X    exprseg = seg1;
  919. X    return (exp);
  920. X}
  921. X
  922. X
  923. X/*      Snag literals and variable names. The literal classes are:
  924. X
  925. X    [digit]....[digit]      unsigned decimal number
  926. X    0[hexdigit]...[hexdigit]unsigned hexadecimal number
  927. X    $                       current location counter
  928. X    '[char]                 single character, right just, zero fill
  929. X    "[char][char]           character pair
  930. X
  931. X    Returns a 16 bit value. Unary operations taken care of in expr;
  932. X    byte swapping done if required by geninstr.
  933. X*/
  934. Xlong getval (strpt, errorret, test, segment)
  935. X    segmnt **segment;
  936. X    char **strpt;
  937. X    int *errorret;
  938. X    int test;
  939. X{
  940. X    long total;
  941. X    char name[33], *npt;
  942. X    int i;
  943. X
  944. X    *segment = (segmnt *) 0;
  945. X    *errorret = 0;
  946. X    total = 0L;
  947. X    if (isdigit (**strpt)) {
  948. X        if (**strpt == '0') {
  949. X            while (isxdigit (**strpt)) {
  950. X                total *= 16;
  951. X                total += xtod (**strpt);
  952. X                (*strpt)++;
  953. X            }
  954. X        } else {
  955. X            while (isdigit (**strpt)) {
  956. X                total *= 10;
  957. X                total += (Long)(**strpt - '0');
  958. X                (*strpt)++;
  959. X            }
  960. X        }
  961. X    } else if (islabel (**strpt)) {
  962. X        npt = name;
  963. X        while (islabel (**strpt)) {
  964. X            *npt++ = **strpt;
  965. X            (*strpt)++;
  966. X        }
  967. X        *npt = '\0';
  968. X        if ((i = lookup (name)) == -1) {
  969. X            if (pass == 2)
  970. X                if (!test) reporterr (E_UNDEF);
  971. X            *errorret = 1;
  972. X            total = 0L;
  973. X        } else {
  974. X            total = symtab[i].value;
  975. X            if (pass == 2 && symtab[i].segp)
  976. X                total += (symtab[i].segp)->start;
  977. X            *segment = symtab[i].segp;
  978. X        }
  979. X    } else if (**strpt == '\'') {
  980. X        (*strpt)++;
  981. X        if (**strpt == '\\') {
  982. X            (*strpt)++;
  983. X            total = escape (strpt);
  984. X        } else {
  985. X            total = **strpt;
  986. X            (*strpt)++;
  987. X        }
  988. X    } else if (**strpt == '"') {
  989. X        (*strpt)++;
  990. X        if (**strpt == '\\') {
  991. X            (*strpt)++;
  992. X            total = escape (strpt);
  993. X        } else {
  994. X            total = **strpt;
  995. X            (*strpt)++;
  996. X        }
  997. X        total <<= 8;
  998. X        if (**strpt == '\\') {
  999. X            (*strpt)++;
  1000. X            total |= escape (strpt);
  1001. X        } else {
  1002. X            total |= **strpt;
  1003. X            (*strpt)++;
  1004. X        }
  1005. X    } else if (**strpt == '$') {
  1006. X        total = lc;
  1007. X        *segment = curseg;
  1008. X        (*strpt)++;
  1009. X    } else {
  1010. X        if (!test) reporterr (E_EXPR);
  1011. X        *errorret = 1;
  1012. X    }
  1013. X    return (total);
  1014. X}
  1015. X
  1016. X
  1017. Xchar escape (st)
  1018. X    char **st;
  1019. X{
  1020. X    switch (*((*st)++)) {
  1021. X    case 'b':
  1022. X        return ('\b');
  1023. X    case 'n':
  1024. X        return ('\n');
  1025. X    case 'r':
  1026. X        return ('\r');
  1027. X    case '^':
  1028. X        return ('\033');
  1029. X    case 'f':
  1030. X        return ('\f');
  1031. X    case 't':
  1032. X        return ('\t');
  1033. X    case '?':
  1034. X        return ('\177');
  1035. X    case '\\':
  1036. X        return ('\\');
  1037. X    default:
  1038. X        (*st)--;
  1039. X        if (isxdigit (**st) && isxdigit (*(*st + 1))) {
  1040. X            *st += 2;
  1041. X            return (xtod (*(*st - 2)) << 4 | xtod (*(*st - 1)));
  1042. X        } else {
  1043. X            return (*(*st++));
  1044. X        }
  1045. X    }
  1046. X}
  1047. X
  1048. X
  1049. Xint xtod (c)
  1050. X    char c;
  1051. X{
  1052. X    return ((int) c - (c > '9' ? (c > 'F' ? 'W' : '7') : '0'));
  1053. X}
  1054. X
  1055. X
  1056. Xint getop (string)
  1057. X    char **string;
  1058. X{
  1059. X    static char ops[] = OPSTRING;
  1060. X    char *k;
  1061. X
  1062. X    for (k = ops; *k; k++)
  1063. X        if (*k == **string) {
  1064. X            (*string)++;
  1065. X            return ((int) (k - ops));
  1066. X        }
  1067. X    (*string)++;
  1068. X    return (NOOP);
  1069. X}
  1070. X
  1071. X
  1072. Xvoid listit (line, xlc, binbuf, length)
  1073. X    char *line;
  1074. X    Memad xlc;
  1075. X    Word *binbuf;
  1076. X    int length;
  1077. X{
  1078. X    int i;
  1079. X
  1080. X    if (listing && liston) {
  1081. X        (void) fprintf (list, "%4ld %04x: ", lineno[currinput], xlc);
  1082. X        if (length > 3) length = 3;
  1083. X        for (i = 0; i < length; i++)
  1084. X            (void) fprintf (list, "%02x ", binbuf[i]);
  1085. X        for (i = length; i < MAXBYTPERINS; i++)
  1086. X            (void) fprintf (list, "   ");
  1087. X        (void) fprintf (list, "    %s\n", line);
  1088. X    }
  1089. X    return;
  1090. X}
  1091. X
  1092. X
  1093. X/*      Binary output format:
  1094. X
  1095. X    Intel standard hexadecimal format!!!!
  1096. X
  1097. X        Output is a series of variable length records consisting of ascii
  1098. X        characters 0-9, A-F (0x30-0x39, 0x41-0x6). Each character contains
  1099. X        four bits of significant data; two such characters form a binary
  1100. X    byte of data, the binary equivalent to the hexadecimal ascii
  1101. X    characters.
  1102. X
  1103. X    The data records have the format:
  1104. X
  1105. X                        /  len covers this \
  1106. X    +---+---+---+---+---+---+---+---+---+--------//--------+---+---+
  1107. X    | : |  len  |    address    | 0 | 0 |    data bytes    | cksum |
  1108. X    +---+---+---+---+---+---+---+---+---+--------//--------+---+---+
  1109. X        \             checksum covers this                 /
  1110. X
  1111. X    Checksum computed such that sum of all bytes except ':' modulo
  1112. X    the bytelength is 0.
  1113. X
  1114. X    End Record:
  1115. X
  1116. X    +---+---+---+---+---+---+---+---+---+---+---+
  1117. X    | : | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | f | f |
  1118. X    +---+---+---+---+---+---+---+---+---+---+---+
  1119. X
  1120. X
  1121. X*/
  1122. Xvoid putoutbin (binbuf, length)
  1123. X    Word binbuf[];
  1124. X    int length;
  1125. X{
  1126. X    static Memad address;
  1127. X    static int count;
  1128. X    static Word checksum;
  1129. X    static Word array[BINBUFLEN];
  1130. X    static Word *curpt = 0;
  1131. X    static Memad binlc = ~0;
  1132. X    int i;
  1133. X
  1134. X    if (binlc != lc) {
  1135. X        if (curpt != 0) {
  1136. X            (void) fwrite (":", 1, 1, output);
  1137. X            putout ((Word) count);
  1138. X            putout ((Word) address >> 8);
  1139. X            putout ((Word) address & 0xff);
  1140. X            (void) fwrite ("00", 2, 1, output);
  1141. X            for (i = 0; i < count; i++)
  1142. X                putout (array[i]);
  1143. X            putout (checksum);
  1144. X            if (length == 0) {
  1145. X                (void) fwrite (":00000001ff", 11, 1, output);
  1146. X            }
  1147. X        }
  1148. X        curpt = array;
  1149. X        count = 0;
  1150. X        address = binlc = lc;
  1151. X        checksum = 0;
  1152. X    }
  1153. X    for (i = 0; i < length; i++) {
  1154. X        *curpt++ = binbuf[i];
  1155. X        checksum += binbuf[i];
  1156. X        count++;
  1157. X        binlc ++;
  1158. X    }
  1159. X    if (count > BINBUFLEN - MAXBYTPERINS)
  1160. X        binlc = 0;
  1161. X    return;
  1162. X}
  1163. X
  1164. X#define hex(x) x+(x<10?'0':'7')
  1165. X
  1166. Xvoid putout (c)
  1167. X    Word c;
  1168. X{
  1169. X    Word outc[2], t;
  1170. X
  1171. X    t = c>>4;
  1172. X    c &= 0xf;
  1173. X    outc[0] = hex(t);
  1174. X    outc[1] = hex(c);
  1175. X    (void) fwrite ((char *)outc, 2, 1, output);
  1176. X    return;
  1177. X}
  1178. X
  1179. X
  1180. Xvoid insert (name, value, type, segment, mult)
  1181. X    char *name;
  1182. X    long value;
  1183. X    opdclass *type;
  1184. X    segmnt *segment;
  1185. X    int mult;
  1186. X{
  1187. X    int x, y;
  1188. X    symbol *sp;
  1189. X
  1190. X    x = y = hash (name);
  1191. X    while ((sp = &symtab[x])->name != (char *) 0) {
  1192. X        if (strcmp (sp->name, name) == 0) {
  1193. X            if (!mult && value != sp->value && pass == 1) {
  1194. X                reporterr (E_MULT);
  1195. X                return;
  1196. X            }
  1197. X            break;
  1198. X        }
  1199. X        if (++x == y) reporterr (E_STOFLO);
  1200. X        if (x == NSYMS) x = 0;
  1201. X    }
  1202. X    sp->name = malloc ((unsigned) strlen (name) + 1);
  1203. X    (void) strcpy (sp->name, name);
  1204. X    sp->value = value;
  1205. X    sp->type = type;
  1206. X    sp->segp = segment;
  1207. X    return;
  1208. X}
  1209. X
  1210. X
  1211. Xint lookup (name)
  1212. X    char *name;
  1213. X{
  1214. X    int x, y;
  1215. X
  1216. X    x = y = hash (name);
  1217. X    while (symtab[x].name != (char *) 0) {
  1218. X        if (strcmp (name, symtab[x].name) == 0)
  1219. X            return (x);
  1220. X        x++;
  1221. X        if (x == y) return (-1);
  1222. X        if (x == NSYMS) x = 0;
  1223. X    }
  1224. X    return (-1);
  1225. X}
  1226. X
  1227. X
  1228. Xint hash (string)
  1229. X    char *string;
  1230. X{
  1231. X    char *pt;
  1232. X    int tot;
  1233. X
  1234. X    tot = 0;
  1235. X    for (pt = string; *pt; pt++)
  1236. X        tot += *pt;
  1237. X    if (NSYMS >= 256)
  1238. X        tot += (tot << 8);
  1239. X    return (tot % NSYMS);
  1240. X}
  1241. X
  1242. X
  1243. Xvoid reporterr (errcode)
  1244. X    int errcode;
  1245. X{
  1246. X    static char *elist[] = {
  1247. X        "",
  1248. X        "aborting at end of pass1",
  1249. X        "aborting at end of pass2",
  1250. X        "symbol table overflow",
  1251. X        "input file error",
  1252. X        "too many nested includes",
  1253. X        "include syntax error",
  1254. X        "illegal expression",
  1255. X        "undefined symbol",
  1256. X        "unknown op code",
  1257. X        "multiply defined symbol",
  1258. X        "insufficient operands",
  1259. X        "value too large for field",
  1260. X        "unsigned value negative",
  1261. X        "segment violation",
  1262. X    };
  1263. X
  1264. X    if (pass == 1) {
  1265. X        (void) fprintf (list, "----> Error in file %s, line %d: %s\n", filename[currinput], lineno[currinput], elist[errcode]);
  1266. X        (void) fprintf (stderr, "----> Error in file %s, line %d: %s\n", filename[currinput], lineno[currinput], elist[errcode]);
  1267. X    } else {
  1268. X        (void) fprintf (list, "----> %s: %s\n", filename[currinput], elist[errcode]);
  1269. X        (void) fprintf (stderr, "----> %s: %s\n", filename[currinput], elist[errcode]);
  1270. X    }
  1271. X    (void) fflush (list);
  1272. X    if (errcode <= A_MAX) {
  1273. X        (void) fprintf (stderr, "asm: Abort error: %s\n", elist[errcode]);
  1274. X        exit (1);
  1275. X    }
  1276. X    errorstat++;
  1277. X    return;
  1278. X}
  1279. X
  1280. X
  1281. Xvoid sort ()
  1282. X{
  1283. X    char c;
  1284. X
  1285. X    while ((c = getc (input[0])) > 0)
  1286. X        putc (c, output);
  1287. X    return;
  1288. X}
  1289. X
  1290. X
  1291. Xvoid crossref ()
  1292. X{
  1293. X    int i, j, k, gap;
  1294. X    symbol symtemp;
  1295. X
  1296. X    (void) fprintf (list, "\n\n\n                     Cross Reference\n\n");
  1297. X    k = 0;
  1298. X    for (i = 0; i < NSYMS; i++)
  1299. X        if (symtab[i].name && *symtab[i].name)
  1300. X            symtab[k++] = symtab[i];
  1301. X    for (gap = k / 2; gap > 0; gap /= 2)
  1302. X        for (i = gap; i < k; i++)
  1303. X            for (j = i - gap; j >= 0; j -= gap) {
  1304. X                if (strcmp (symtab[j].name,
  1305. X                          symtab[j+gap].name) <= 0)
  1306. X                    break;
  1307. X                symtemp = symtab[j];
  1308. X                symtab[j] = symtab[j+gap];
  1309. X                symtab[j+gap] = symtemp;
  1310. X            }
  1311. X    for (i = 0; i < k; i++)
  1312. X        (void) fprintf (list, "    %s: 0x%x\n", symtab[i].name,
  1313. X                            symtab[i].value);
  1314. X    return;
  1315. X}
  1316. -FUNKY STUFF~
  1317. echo extracting - asm.h
  1318. sed 's/^X//' > asm.h << '-FUNKY STUFF~'
  1319. X#include <ctype.h>
  1320. X#define YES 1
  1321. X#define NO 0
  1322. X
  1323. X#define NSYMS 253
  1324. X#define INCLSTACK 10
  1325. X#define MAXBYTPERINS 3
  1326. X#define BYTPERLONG 4
  1327. X#define LONGLEN 32
  1328. X#define MAXOPDS 2
  1329. X#define NHEAD 5                 /* words of overhead in binary header */
  1330. X#define BINBUFLEN 250
  1331. X
  1332. X#define iswhite(c) (c==' '||c=='\t')
  1333. X#define iseol(c) (c=='\0'||c==';'||c=='\n')
  1334. X#define isdelim(c) (c==','||c==':'||iseol(c)||iswhite(c))
  1335. X#define islabel(c) (isalnum(c)||c=='_')
  1336. X
  1337. X#define A_MAX 6         /* highest error code causing immediate abort */
  1338. X#define E_PASS1 1
  1339. X#define E_PASS2 2
  1340. X#define E_STOFLO 3
  1341. X#define E_INPUT 4
  1342. X#define E_INCL 5
  1343. X#define E_INCLSYN 6
  1344. X#define E_EXPR 7
  1345. X#define E_UNDEF 8
  1346. X#define E_ILLOP 9
  1347. X#define E_MULT 10
  1348. X#define E_NOPS 11
  1349. X#define E_TOOBIG 12
  1350. X#define E_NEG 13
  1351. X#define E_SEG 14
  1352. X
  1353. X#define NOOP -1
  1354. X#define PLUS 0
  1355. X#define MINUS 1
  1356. X#define MULT 2
  1357. X#define DIV 3
  1358. X#define MOD 4
  1359. X#define OR 5
  1360. X#define AND 6
  1361. X#define EXOR 7
  1362. X#define SHLF 8
  1363. X#define SHRT 9
  1364. X#define OPSTRING "+-*/%|&^<>"   /* same order as definitions above */
  1365. X
  1366. Xtypedef unsigned char Word;     /* instruction word */
  1367. Xtypedef short Long;             /* Long, that is, on an 8085: 16 bit data */
  1368. Xtypedef char  Short;            /* 8 bit data */
  1369. Xtypedef unsigned Long Memad;
  1370. Xtypedef char Flag;
  1371. X
  1372. Xtypedef struct opdclassitem {   /* This defines an instruction field */
  1373. X    int length;                     /* length in bits of field */
  1374. X    Flag signed;                    /* else unsigned */
  1375. X    Flag byteswapped;               /* data has bytes backwards */
  1376. X    Flag relative;                  /* field is relative to $ */
  1377. X    int offset;                     /* fixed value added to field */
  1378. X} opdclass;
  1379. X
  1380. Xtypedef struct insclassitem {   /* This defines an instruction type */
  1381. X    int length;                     /* instruction length in bytes */
  1382. X    int mopds;                      /* number of operands expected */
  1383. X    opdclass *type[MAXOPDS];        /* each operand's field type */
  1384. X    int offset[MAXOPDS];            /* each operand's bit offset,
  1385. X                       from right end of first byte */
  1386. X} insclass;
  1387. X
  1388. Xtypedef struct chcitem {        /* Defines the alternatives for instr choices */
  1389. X    char *rname;                    /* restrictive mnemonic */
  1390. X    char *nname;                    /* non-restrictive mnemonic */
  1391. X    int field;                      /* operand that is restricted */
  1392. X    int lorange, hirange;           /* range of restriction inclusive */
  1393. X    Flag relative;                  /* to current lc, else absolute value */
  1394. X} choicedef;
  1395. X
  1396. Xtypedef struct opdefitem {      /* Defines an instruction */
  1397. X    char *name;                     /* instruction mnemonic */
  1398. X    insclass *class;                /* instruction type */
  1399. X    Word mask;                      /* mask for first byte of instruction */
  1400. X    int (*action) ();               /* action routine for assembly */
  1401. X} opdef;
  1402. X
  1403. Xtypedef struct seg {            /* Defines a location counter segment */
  1404. X    Memad lc, start;                /* segment's lc and starting loc */
  1405. X    char *name;                     /* segment name */
  1406. X    struct seg *next;               /* pointer to next segment */
  1407. X} segmnt;
  1408. X
  1409. Xtypedef struct ltitem {         /* Defines a label table entry */
  1410. X    char *name;                     /* symbol name */
  1411. X    long value;                     /* symbol's current value */
  1412. X    opdclass *type;                 /* symbol type (defines fields it can fill) */
  1413. X    segmnt *segp;                   /* pointer to segment value's defined in */
  1414. X} symbol;
  1415. X
  1416. Xextern char *malloc();
  1417. Xextern char *strcpy();
  1418. Xextern char *strcat();
  1419. Xextern char *mktemp();
  1420. Xextern char *index();
  1421. Xextern int geninstr();
  1422. Xextern int choiceinstr();
  1423. Xextern int do_bss();
  1424. Xextern int do_data();
  1425. Xextern int do_data2();
  1426. Xextern int do_end();
  1427. Xextern int do_equ();
  1428. Xextern int do_seg();
  1429. Xextern int do_set();
  1430. Xextern int do_org();
  1431. Xextern int do_string();
  1432. Xextern int do_incl();
  1433. Xextern int do_loff();
  1434. Xextern int do_lon();
  1435. Xextern void getargs ();
  1436. Xextern void init ();
  1437. Xextern void init2 ();
  1438. Xextern int process ();
  1439. Xextern void listit ();
  1440. Xextern void insert ();
  1441. Xextern void reporterr ();
  1442. Xextern int hash ();
  1443. Xextern long expr ();
  1444. Xextern int getop ();
  1445. Xextern long getval ();
  1446. Xextern int lookup ();
  1447. Xextern void putoutbin ();
  1448. Xextern void crossref ();
  1449. Xextern void sort ();
  1450. Xextern void putout ();
  1451. Xextern int xtod ();
  1452. Xextern char escape ();
  1453. -FUNKY STUFF~
  1454. echo extracting - asm_ops.5
  1455. sed 's/^X//' > asm_ops.5 << '-FUNKY STUFF~'
  1456. X.so /usr/lib/tmac/tmac.e
  1457. X.TH ASM_OPS 5 "1 Nov 1986"
  1458. X.SH NAME
  1459. Xasm_ops \- generic assembler op-code tables
  1460. X.SH DESCRIPTION
  1461. XThe generic assembler
  1462. X.b asm
  1463. Xcan be made to assemble code for a number of different microprocessors. At
  1464. Xthe time of this writing, codes have been developed for the Intel 8085,
  1465. Xthe Motorola 6803, and the 6502 (Commodore 64). This manual page will
  1466. Xdescribe the format of the ops.h file, which contains the processor-specific
  1467. Xparts of the assembler. The structures described below are defined in the
  1468. Xfile asm.h.
  1469. X
  1470. XThe opd.h file consists in a series of structure initializations, that
  1471. Xgenerate tables in the assembler when it is compiled. All lines are of the
  1472. Xform:
  1473. X
  1474. X    table-type name = {value, ....., value};
  1475. X
  1476. Xwhere the names are arbitrary (within the c-compiler naming restrictions)
  1477. Xand the values may be integers, Flags (i.e., boolean-valued integers),
  1478. Xstrings (actually pointers to strings), pointers to other structures
  1479. Xwithin the file, and pointers to functions in the assembler itself. The
  1480. Xtype Word refers an unsigned byte and Memad refers to a type holding any
  1481. Xpossible memory address for the target machine.
  1482. X
  1483. XThe first structure is opdclass, which defines the kinds of operands that
  1484. Xmay appear in an instruction, and their encoding in the corresponding
  1485. Xinstruction word:
  1486. X
  1487. X.nf
  1488. Xtypedef struct opdclassitem {   /* This defines an instruction field */
  1489. X    int length;                     /* length in bits of field */
  1490. X    Flag signed;                    /* else unsigned */
  1491. X    Flag byteswapped;               /* data has bytes backwards */
  1492. X    Flag relative;                  /* field is relative to $ */
  1493. X    int offset;                     /* fixed value added to field */
  1494. X} opdclass;
  1495. X.fi
  1496. X
  1497. XAn operand's
  1498. X.b length
  1499. Xrefers to the number of bits that are allocated for it
  1500. Xin the instruction field. If that number is eight, then only numbers from
  1501. X-128 through +127 (two's complement assumed) can fit in the field. If the
  1502. Xnext flag,
  1503. X.b signed ,
  1504. Xis set then the range becomes 0 through 255, in this
  1505. Xexample. The
  1506. X.b byteswapped
  1507. Xflag is set if the bytes (in a multibyte field)
  1508. Xare to be loaded within a 2 byte word in right-to-left order, rather then
  1509. Xthe more conventional left-to-right. The
  1510. X.b relative
  1511. Xflag is set if the value
  1512. Xto be placed in the field must first be decremented by the value of the
  1513. Xlocation counter before insertion. Finally,
  1514. X.b offset
  1515. Xis an integer value
  1516. Xto be added to the value of the field before it is inserted. As an
  1517. Xexample, an entry for the 6805 reads:
  1518. X
  1519. Xopdclass o_rmem  = { 8, YES, NO , YES, -2};
  1520. X
  1521. XThis defines a field that is used in relative-mode instructions. The field
  1522. Xis eight bits long, is signed, and is relative to the current lc. In
  1523. Xaddition, it is expected to be decremented by two. Given all this, the
  1524. Xlegal range of a value to be placed in this field must be from (lc)-126
  1525. Xthrough (lc)+129 inclusive, where (lc) is the current value of the
  1526. Xlocation counter (which points to the first byte of the current
  1527. Xinstruction).
  1528. X
  1529. XThe second "set" of structures, insclass, define an instruction type.
  1530. XEvery generated instruction must fall within one of these types.  They
  1531. Xdefine the instruction structure (as a collection of fields) and the
  1532. Xwritten form of its invocation:
  1533. X
  1534. X.nf
  1535. Xtypedef struct insclassitem {   /* This defines an instruction type */
  1536. X    int length;                     /* instruction length in bytes */
  1537. X    int mopds;                      /* number of operands expected */
  1538. X    opdclass *type[MAXOPDS];        /* each operand's field type */
  1539. X    int offset[MAXOPDS];            /* each operand's bit offset,
  1540. X                       from right end of first byte */
  1541. X} insclass;
  1542. X.fi
  1543. X
  1544. XThe
  1545. X.b length
  1546. Xof an instruction type is the number of bytes in the
  1547. Xinstruction, including all the fields.  The number of operands expected
  1548. X.b mopd
  1549. Xmay be 0, 1, or 2 (making this larger would involve changes to asm.h and
  1550. Xasm.c). MAXOPDS enforces the current limit on operands to two.  The
  1551. Xmembers of the array
  1552. X.btype
  1553. Xare pointers to the appropriate opdclass defined
  1554. Xabove.  When the instruction is scanned, the first operand must fit the
  1555. Xfield described in the structure pointed to be xxx.type[0], the second by
  1556. Xxxx.type[1]. The array
  1557. X.b offset
  1558. Xdefines the amount of shifting to be done to
  1559. Xproperly align the field in the instruction.  An offset of zero states
  1560. Xthat the field's rightmost bit should be placed in the rightmost bit of
  1561. Xthe instruction's first byte; a negative offset requires the value to be
  1562. Xshifted left that many bits, and a positive value must be shifted right.
  1563. XAn example, again from the 6805, shows the format of a relative
  1564. Xinstruction:
  1565. X
  1566. Xinsclass i_rel   = {2, 1, &o_rmem, &o_none,  8, 0};
  1567. X
  1568. XSuch an instruction is two bytes long, and contains one operand. This
  1569. Xoperand is a relative memory operand (from the example above), and it must
  1570. Xbe shifted to the right 8 bits (which puts it in the second byte of the
  1571. Xinstruction exactly). The second operand must have an address even though
  1572. Xits not used; o_none fills this requirement.
  1573. X
  1574. XAll this is leading, of course to the definition of individual
  1575. Xinstructions. These are defined in the opdef structures:
  1576. X
  1577. X.nf
  1578. Xtypedef struct opdefitem {      /* Defines an instruction */
  1579. X    char *name;                     /* instruction mnemonic */
  1580. X    insclass *class;                /* instruction type */
  1581. X    Word mask;                      /* mask for first byte of instruction */
  1582. X    int (*action) ();               /* action routine for assembly */
  1583. X} opdef;
  1584. X.fi
  1585. X
  1586. XEach instruction has a
  1587. X.b name
  1588. Xthat is recognized during the source code
  1589. Xscanning. It also has a pointer to the insclass
  1590. X.b class
  1591. Xthat defines both what the
  1592. Xscanner should expect and how the finished instruction looks. The
  1593. X.b mask
  1594. Xis a value to be or'ed in with the assembled operand fields to complete the
  1595. Xinstruction. It normally contains the instruction-unique bits known as the
  1596. Xopcode. Finally, the routine
  1597. X.b action
  1598. Xdefined to assemble the instruction
  1599. Xmust be given. For all normal instructions, the routine is
  1600. X.u geninstr ,
  1601. Xwhich generates all normal instructions from the table data. This field is
  1602. Xdefined primarily so that pseudo-ops can also use the structure.
  1603. X
  1604. XNow, the opdef table is defined in a slightly different way than the other
  1605. Xtables. The entries in the other tables are all referenced by pointers,
  1606. Xso their order is of no consequence.  The opdef table (named optab), on
  1607. Xthe other hand, must be searched by the assembler. Therefore, each entry
  1608. Xis a member of the array optab, and not a separate statement. In addition,
  1609. Xthe entries are all arranged in alphabetical order by
  1610. X.b name .
  1611. X
  1612. XAn example of a defined instruction for the 6803 is
  1613. X
  1614. X.nf
  1615. Xopdef optab [] =
  1616. X    ....
  1617. X    "bra"    , &i_rel  , 0x20, geninstr,
  1618. X    ....
  1619. X};
  1620. X.fi
  1621. X
  1622. XThe unconditional branch instruction has its format defined by the i_rel
  1623. Xclass of instruction formats (which, as shown above, defines a two byte
  1624. Xinstruction with one operand, etc.).  The mask for the first byte of the
  1625. Xinstruction (the opcode for a branch) is hex 20. It is generated by the
  1626. Xgeninstr routine.
  1627. X
  1628. XFollowing the definition of optab is the statement
  1629. X
  1630. X#define oplen sizeof(optab)/sizeof(opdef)
  1631. X
  1632. Xwhich reveals the size of the optab to asm.c.
  1633. X
  1634. XWhat of the microprocessors that have two different instructions that may
  1635. Xbe used to perform an operation, such as the 6803 that can load a register
  1636. Xfrom a memory location with either a two byte relative instruction or a
  1637. Xthree byte extended instruction? The native assembler can generate the
  1638. Xshortest instruction that will fulfill the effect; so can the generic
  1639. Xassembler, under some circumstances. The third set of structures, called
  1640. Xchoicedef, is used in this case:
  1641. X
  1642. X.nf
  1643. Xtypedef struct chcitem {        /* Defines the alternatives for instr choices */
  1644. X    char *rname;                    /* restrictive mnemonic */
  1645. X    char *nname;                    /* non-restrictive mnemonic */
  1646. X    int field;                      /* operand that is restricted */
  1647. X    int lorange, hirange;           /* range of restriction inclusive */
  1648. X    Flag relative;                  /* to current lc, else absolute value */
  1649. X} choicedef;
  1650. X.fi
  1651. X
  1652. XAny choicedef that exists (there may be none, if the microprocessor has no
  1653. Xsuch overlapping instructions) describes the tradeoff to be made. The
  1654. X.b rname
  1655. Xis the mnemonic that may be used in the restrictive case of the
  1656. Xchoice (i.e., the one that is more desireable, usually leading to a
  1657. Xsmaller instruction).
  1658. X.b Nname
  1659. Xis the mnemonic to be used otherwise.
  1660. XPresumably, the two choices are mutually inclusive of all possibilities,
  1661. Xso that the nname mnemonic may be substituted in all cases to achieve the
  1662. Xdesired result. The field
  1663. X.b field
  1664. Xis either one or two, describing which
  1665. Xfield the choice hinges on. The
  1666. X.b lorange and
  1667. X.b hirange
  1668. Xvalues are the
  1669. Xinclusive limits of the values that the field must fall within in order to
  1670. Xqualify for the restrictive choice. Finally, the
  1671. X.b relative
  1672. Xflag staes that
  1673. Xthe ranges are or are not relative to the current location counter. (At
  1674. Xthis point, the relative flag is not implemented.)
  1675. X
  1676. XThe infamous example:
  1677. X
  1678. X    "add"    , (insclass *)&c_add, 0x00, choiceinstr,
  1679. X
  1680. XThis entry in the optab table defines an pseudo instruction called add. It
  1681. Xmay be expanded as the instruction adds, if conditions are right, or as
  1682. Xaddz in any case. Instead of pointing to an instruction class, the second
  1683. Xentry in the structure is the address of a choice structure, which is cast
  1684. Xas an insclass pointer to keep c and lint happy. The mask is defaulted
  1685. X(its value is not used), and the generating routine is changed to
  1686. Xchoiceinstr, which handles the cases. The choicedef entry pointed to is:
  1687. X
  1688. Xchoicedef c_add = {"adds" , "addz" , 2, 0, 0xff, NO};
  1689. X
  1690. XThis defines a choice of either the adds instruction or the addz
  1691. Xinstruction to add a memory location to an accumulator. The second field,
  1692. Xthe memory reference, is the key: if the reference is greater than or equal
  1693. Xto zero, and less than or equal to hex ff (decimal 255), then adds can be
  1694. Xused; otherwise only addz is allowed.
  1695. X
  1696. XAs I said above, the choice mechanism is restricted in the decisions that
  1697. Xit can make in attempting to use the shortest instruction.  Since the
  1698. Xchoices are all made during the first pass, the expression in the deciding
  1699. Xfield must be completely backward-defined.  That means that all symbols in the
  1700. Xexpression must be either constants, be predefined (see below) or have
  1701. Xbeen defined in the code physically before the line where the choice
  1702. Xresides. In addition, all symbols in the expression must be in the same
  1703. Xsegment as the code being generated. This is not to say that using a
  1704. Xchoice instruction containing a forward reference is an error; rather, the
  1705. Xassembler, in the absence of required data to make the decision, will opt
  1706. Xfor the "otherwise" form of the instruction, when it could be possible to
  1707. Xuse the other. As Captain Kirk says, "Sie la vie."
  1708. X
  1709. XThe last set of entries in the ops.h file is a group of predefined symbols
  1710. Xthat the assembler "knows" about for all assemblies on this
  1711. Xmicroprocessor. An example of these definitions is:
  1712. X
  1713. X.nf
  1714. Xsymbol predef[] = {
  1715. X    {"ra"        ,    0x0, &o_reg  , (struct seg *)0 },
  1716. X    {"rb"        ,    0x1, &o_reg  , (struct seg *)0 },
  1717. X    {"eq"        ,    0x7, &o_cond , (struct seg *)0 },
  1718. X    {"nc"        ,    0x4, &o_cond , (struct seg *)0 },
  1719. X    {""          ,    0x0, &o_none , (struct seg *)0 },
  1720. X};
  1721. X.fi
  1722. X
  1723. XThese predefine the symbols ra, rb, eq, and nc for use in instructions
  1724. Xthat reference register a, register b, and the branch conditions eq and nc
  1725. X(no carry). Each is given a value, points to an operand type (which is not
  1726. Xcurrently used), and defined in the null segment (that is, the only
  1727. Xpredefined, default segment). Note the null entry at the end of the table.
  1728. X
  1729. XNow, given the above description it should be possible to define an ops.h
  1730. Xfile to generate an assembler for most any machine. This scheme should
  1731. Xwork for almost any 8 or 16 bit microprocessor, although its only been
  1732. Xused with eights. Restrictions are enforced by the use of a long
  1733. Xvariable for expression solution and for instruction compilation, and
  1734. Xprobably other things that will become apparant when the assembler is
  1735. Xported to some wierd machine.
  1736. X
  1737. XChoices for instruction format are arbitrary, of course. I use a branch
  1738. Xconditional instruction with the conditional code as an operand to reduce
  1739. Xthe size of the optab (simply laziness); it would be easy to have
  1740. Xindividual branch instructions instead.
  1741. X
  1742. XSo it goes.
  1743. -FUNKY STUFF~
  1744.  
  1745.