home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 113_01 / a15asmln.c < prev    next >
Text File  |  1985-03-10  |  9KB  |  323 lines

  1. /*
  2.     HEADER:        CUG113;
  3.     TITLE:        1802 Cross-Assembler (BDS C Version);
  4.     FILENAME:    A15ASMLN.C;
  5.     VERSION:    1.2;
  6.     DATE:        07/22/1985;
  7.  
  8.     DESCRIPTION:    "This program lets you use your CP/M-80-based computer
  9.             to assemble code for the RCA 1802, 1804, 1805, 1805A,
  10.             1806, AND 1806A microprocessors.  The program is
  11.             written in BDS C for the best possible performance on
  12.             8-bit machines.  All assembler features are supported
  13.             except relocation, linkage, listing control, and
  14.             macros.";
  15.  
  16.     KEYWORDS:    Software Development, Assemblers, Cross-Assemblers,
  17.             RCA, CDP1802, CDP1805A;
  18.  
  19.     SEE-ALSO:    CUG149, 1805A Cross-Assembler (Portable);
  20.  
  21.     SYSTEM:        CP/M-80;
  22.     COMPILERS:    BDS C;
  23.  
  24.     WARNINGS:    "This package is specifically tailored to CP/M-80
  25.             machines and the rather non-standard, but high-
  26.             performance BDS C compiler.  For other environments,
  27.             use the portable version of this package on CUG149.";
  28.  
  29.     AUTHORS:    William C. Colley III;
  30. */
  31.  
  32. /*
  33.     1805A Cross-Assembler  v 1.2
  34.  
  35.     Copyright (c) 1980, 82, 83, 85 William C. Colley, III.
  36.  
  37.     July 1982 -- Adapted from my 1802 cross-assembler.  WCC3.
  38.  
  39.     Vers 1.0 -- March 1983 -- Added 1805A opcodes to the 1805 set.  WCC3.
  40.  
  41.     Vers 1.1 -- March 1983 -- Added CPU pseudo-op to combine 1802 and 1805A
  42.             cross-assemblers into a single program.  WCC3.
  43.  
  44.     Vers 1.2 -- June 1985 -- Fixed IF block nesting mechanism bug and bug
  45.             in 1805A SCAL opcode.  WCC3.
  46.  
  47. File:    a15asmln.c
  48.  
  49. Line assembly routine.
  50. */
  51.  
  52. /*  Get globals:  */
  53.  
  54. #include "a15.h"
  55.  
  56. /*
  57. This function is the workhorse of the assembler.  The routine
  58. gets any labels off the line and processes them, gets the opcode
  59. and builds the binary output as it evaluates the operand field.
  60. */
  61.  
  62. asmline()
  63. {
  64.     char c, label[2*SYMLEN], opcode, opattr, getchr();
  65.  
  66.     nbytes = 0;  address = pc;  directok = TRUE;
  67.     evalerr = FALSE;  hexflg = NOCODE;  label[0] = '\0';
  68.     binbuf[0] = binbuf[1] = binbuf[2] = binbuf[3] = 0xc4;
  69.  
  70.     switch (getchr(&c,NOSKIP)) {
  71.     case ALPHA:    backchr;  getname(label);
  72.             if (strcmp(label,"$") == 0 || chkoprat(label) !=
  73.                 NO_OPR) { markerr('L');  label[0] = '\0'; }
  74.             break;
  75.  
  76.     case END_LIN:    return;
  77.  
  78.     case BLANK:    break;
  79.  
  80.     default:    markerr('L');
  81.             while((c = getchr(&c,NOSKIP)) != BLANK && c !=
  82.                 END_LIN);
  83.             backchr;
  84.     }
  85.  
  86.     switch (getopcod(&opcode,&opattr)) {
  87.     case 0:        nbytes = 4;
  88.  
  89.     case -1:    opcode = 255;        /*  Set nil pseudo-op.    */
  90.             opattr = 0x80;
  91.  
  92.     case 1:     if ((opattr & (PSOP | IFGROUP)) == (PSOP | IFGROUP)) {
  93.             if (label[0] != '\0') markerr('L');
  94.             }
  95.             else {
  96.             if (ifstack[ifsp] != ON) return;
  97.             if (label[0] != '\0') {
  98.                 strcat(label,PADDING);
  99.                 if (pass == 1) {
  100.                 if (addsym(label)) {
  101.                     sympoint->symvalu = pc;
  102.                     if ((opattr & PSOP) && opcode == 10)
  103.                     sympoint->symname[1] |= 0x80;
  104.                 }
  105.                 }
  106.                 else {
  107.                 if (slookup(label)) {
  108.                     markerr('P');  label[0] = '\0';
  109.                 }
  110.                 else {
  111.                     if (sympoint->symvalu != pc ||
  112.                     (sympoint->symname[1] & 0x80))
  113.                     markerr('M');
  114.                     sympoint->symname[0] &= 0x7f;
  115.                 }
  116.                 }
  117.             }
  118.             }
  119.             hexflg = PUTCODE;
  120.             if (opattr & PSOP) _psop(opcode,label);
  121.             else _normop(opcode,opattr);
  122.             return;
  123.     }
  124. }
  125.  
  126. /*
  127. Internal function to process pseudo opcodes.
  128. */
  129.  
  130. _psop(opcode,label)
  131. char opcode, *label;
  132. {
  133.     char *bptr, c, d;
  134.     unsigned t, t2;
  135.     struct symbtbl *sptr;
  136.  
  137.     sptr = sympoint;  bptr = binbuf;
  138.  
  139.     switch (opcode) {
  140.     case 0:      t = eval(START);                /* ORG.    */
  141.              if (evalerr || !directok) { markerr('P');  return; }
  142.              address = pc = t;  hexflg = FLUSH;
  143.              if (label[0] == '\0') goto chkargs;
  144.              backitem(t,VALUE);  backchr;
  145.  
  146.     equlabl:
  147.     case 1:     if (label[0] == '\0') {            /* EQU.    */
  148.             markerr('L');  return;
  149.             }
  150.             if (!(sptr->symname[1] & 0x80) && errcode == 'M') {
  151.             errcode = ' ';  errcount--;
  152.             }
  153.             t = eval(START);
  154.             if (evalerr || !directok) {
  155.             markerr('P');  return;
  156.             }
  157.             address = sptr->symvalu;  sptr->symvalu = t;
  158.             if (address != t) markerr('M');
  159.             goto chkargs;
  160.  
  161.     case 2:                        /* BYTE.    */
  162.             while ((c = getitem(&t,SMALST)) != END_LIN) {
  163.             if (c == COMMA) {
  164.                 *bptr++ = 0;  nbytes++;  continue;
  165.             }
  166.             backitem(t,c);  t = eval(START);
  167.             if (t > 0xff && t < 0xff80) { markerr('V');  t = 0; }
  168.             *bptr++ = t;  nbytes++;
  169.             }
  170.             return;
  171.  
  172.     case 3:                        /* WORD.    */
  173.             while ((c = getitem(&t,SMALST)) != END_LIN) {
  174.             nbytes += 2;
  175.             if (c == COMMA) *bptr++ = *bptr++ = 0;
  176.             else {
  177.                 backitem(t,c);  t = eval(START);
  178.                 *bptr++ = t >> 8;  *bptr++ = t;
  179.             }
  180.             }
  181.             return;
  182.  
  183.     case 4:                        /* TEXT.    */
  184.             while ((c = getchr(&d,SKIP)) != END_LIN) {
  185.             if (c == COMMA) continue;
  186.             if (c != QUOTE) { markerr('"');  return; }
  187.             while ((c = *linptr++) != d) {
  188.                 if (c == '\n') { markerr('"');  return; }
  189.                 *bptr++ = c;  nbytes++;
  190.             }
  191.             }
  192.             return;
  193.  
  194.     case 5:     t = eval(START);                /* BLK.    */
  195.             if (evalerr || !directok) { markerr('P');  return; }
  196.             pc += t;  hexflg = FLUSH;  goto chkargs;
  197.  
  198.     case 6:     if (pass == 1) pass--;            /* END.    */
  199.             else { pass++;  if (ifsp != 0) markerr('I'); }
  200.             hexflg = NOMORE;  goto chkargs;
  201.  
  202.     case 7:                        /*  ELSE.    */
  203.     case 8:     hexflg = NOCODE;            /*  ENDI.    */
  204.             if (ifsp == 0) { markerr('I');  return; }
  205.             if (opcode == 8) ifsp--;
  206.             else ifstack[ifsp] = -ifstack[ifsp];
  207.             goto chkargs;
  208.  
  209.     case 9:     address = eval(START);            /* IF.    */
  210.             if (evalerr || !directok) {
  211.             markerr('P');  address = TRUE;
  212.             }
  213.             if (ifsp == IFDEPTH - 1) wipeout("\nIf stack overflow.\n");
  214.             if (ifstack[ifsp++] != ON) {
  215.             hexflg = NOCODE;  ifstack[ifsp] = NULL;
  216.             }
  217.             else ifstack[ifsp] = address ? ON : OFF;
  218.             goto chkargs;
  219.  
  220.     case 10:    if (label[0] == '\0') {            /* SET.    */
  221.             markerr('L');  return;
  222.             }
  223.             if ((sptr->symname[1] & 0x80) && errcode == 'M') {
  224.             errcode = ' ';  errcount--;
  225.             }
  226.             address = eval(START);
  227.             if (evalerr) return;
  228.             sptr->symvalu = address;
  229.             if (!directok) markerr('P');
  230.  
  231.     chkargs:    if (getitem(&c,SMALST) != END_LIN) markerr('T');
  232.             return;
  233.  
  234.     case 11:                    /*  PAGE.    */
  235.             address = pc = pc + 255 & 0xff00;  hexflg = FLUSH;
  236.             if (label[0] == '\0') goto chkargs;
  237.             while (getitem(&c,SMALST) != END_LIN) markerr('T');
  238.             backchr;  backitem(pc,VALUE);  goto equlabl;
  239.  
  240.     case 12:    nbytes = 6;                /*  LOAD.    */
  241.             binbuf[0] = binbuf[3] = 0xf8;  binbuf[1] = binbuf[4] = 0;
  242.             binbuf[2] = 0xb0;  binbuf[5] = 0xa0;
  243.             t = eval(START);  t2 = eval(START);
  244.             if (t > 15) { markerr('R');  t = 0; }
  245.             binbuf[1] = t2 >> 8;  binbuf[4] = t2 & 0xff;
  246.             binbuf[2] |= t;  binbuf[5] |= t;  goto chkargs;
  247.  
  248.     case 13:                            /* CPU. */
  249.             if (((t = eval(START)) != 1802 && t != 1805) || evalerr)
  250.             markerr('V');
  251.             else extend = t == 1805;
  252.             goto chkargs;
  253.  
  254.     case 255:   if (nbytes == 0) hexflg = NOCODE;    /*  NO OPCODE.    */
  255.             return;
  256.     }
  257. }
  258.  
  259. /*
  260. Internal function to process normal (non-pseudo) opcodes.
  261. */
  262.  
  263. _normop(opcode,attr)
  264. char opcode,attr;
  265. {
  266.     unsigned bindx, operand;
  267.  
  268.     nbytes = attr & BYTES;
  269.     if (pass == 1) return;
  270.     bindx = 0;
  271.     if (attr & XOPC) binbuf[bindx++] = 0x68;
  272.     if (attr & PROCNUM) operand = eval(START);
  273.  
  274.     switch (attr & PROCNUM) {
  275.     case 8:                    /*  Register Group.    */
  276.             if (operand < 16) opcode |= operand;
  277.             else markerr('R');
  278.             if (opcode == 0) { markerr('R');  opcode++; }
  279.  
  280.     case 0:     break;            /*  No-argument Group.    */
  281.  
  282.     case 16:                /*  Immediate Group.    */
  283.             if (operand > 0xff && operand < 0xff80) {
  284.             markerr('V');  operand = 0;
  285.             }
  286.             binbuf[bindx+1] = operand;  break;
  287.  
  288.     case 24:                /*  Short Branch Group.    */
  289.             if (evalerr || (operand & 0xff00) !=
  290.             (pc + (attr & XOPC ? 2 : 1) & 0xff00)) {
  291.             operand = pc;  markerr('B');
  292.             }
  293.             binbuf[bindx+1] = operand & 0xff;  break;
  294.  
  295.     case 56:    if (operand < 16) opcode |= operand;      /*  DBNZ  */
  296.             else markerr('R');
  297.             operand = eval(START);
  298.  
  299.     case 32:    if (evalerr) operand = pc;    /*  Long Branch Group.    */
  300.             binbuf[bindx+1] = operand >> 8;
  301.             binbuf[bindx+2] = operand & 0xff;  break;
  302.  
  303.     case 40:                /*  Input/Output Group.    */
  304.             if (operand == 0 || operand > 7) {
  305.             markerr('V');  operand = 1;
  306.             }
  307.             opcode |= operand;  break;
  308.  
  309.     case 48:    if (operand < 16) opcode |= operand;      /*  RLDI  */
  310.             else markerr('R');
  311.             binbuf[bindx+1] = (operand = eval(START)) >> 8;
  312.             binbuf[bindx+2] = operand & 0xff;  break;
  313.     }
  314.  
  315.     binbuf[bindx] = opcode;
  316.     if (getitem(&bindx,SMALST) != END_LIN) markerr('T');
  317.     return;
  318. }
  319. 
  320.             binbuf[bindx+1] = operand;  break;
  321.  
  322.     case 24:                /*  Short Branch Group.    */
  323.             if