home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 363_01 / miscel.c < prev    next >
C/C++ Source or Header  |  1991-12-17  |  30KB  |  958 lines

  1. /***********************************************************************
  2.  *
  3.  *      MISCEL - Routines for 68020 Assembler
  4.  *      Routines for instructions:
  5.  *          BKPT, CALLM,
  6.  *
  7.  *  All functions accept the same parameters:
  8.  *
  9.  *      tablePtr - pointer to the instruction table,
  10.  *      size      - not used. Included for compatibility with the opDescriptor
  11.  *                  struct definition.
  12.  *      label    - pointer to the label string, empty string if no label
  13.  *      op       - pointer to the input string,
  14.  *      errorPtr - pointer to the error flag.
  15.  *
  16.  *   and return integer flag.
  17.  *
  18.  *   The functions return an error code in *errorPtr using the standard
  19.  *   mechanism.
  20.  *
  21.  *
  22.  *      Author: Andrew E. Romer. Version 1.0
  23.  *      38 Bolsover Road, Worthing, West Sussex, England BN13 1NT.
  24.  *
  25.  *      Date: May 1991
  26.  *
  27.  ***********************************************************************/
  28.  
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <string.h>
  33. #include "asm.h"
  34.  
  35. extern long loc;
  36. extern char pass2;
  37.  
  38. /***********************************************************************
  39.  *
  40.  *  Function bkPoint builds the instruction
  41.  *   BKPT #<data>
  42.  *
  43.  ***********************************************************************/
  44.  
  45. #define     BKPT_MASK       0x4848
  46.  
  47. int bkPoint(instruction *tablePtr, int size, char *label, char *op,
  48.                                                             int *errorPtr)
  49.     {
  50.     opDescriptor source;
  51.  
  52. /* op points to the first character of the operand field */
  53.  
  54. /* Move location counter to a word boundary and fix the listing before
  55.  * assembling the instruction */
  56.  
  57.     if (loc & 1)                         /* if not at word boundary */
  58.         {
  59.         loc++;
  60.         listLoc();
  61.         }
  62.  
  63.     if (*label)
  64.         {
  65.         create(label, loc, errorPtr);
  66.         if (*errorPtr > SEVERE)
  67.             return NORMAL;
  68.         }
  69.  
  70.     if (size)
  71.         NEWERROR(*errorPtr, UNSIZED);
  72.  
  73.     op = opParse(op, &source, errorPtr);
  74.     if (*errorPtr > SEVERE)
  75.         return NORMAL;
  76.     if (source.mode != Immediate)
  77.         {
  78.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  79.         return NULL;
  80.         }
  81.     if (!isspace(*op) && *op != '\0')
  82.                             /* if operand field contains
  83.                              * superfluous characters */
  84.         {
  85.         NEWERROR(*errorPtr, SYNTAX);
  86.         return NORMAL;
  87.         }
  88.     if (pass2)
  89.         {
  90.         output( (long) (BKPT_MASK | (source.data & 0x7)), WORD);
  91.         if (source.data < 0 || source.data > 7)
  92.             NEWERROR(*errorPtr, INV_3_BIT_DATA);
  93.         }
  94.     loc += 2;
  95.     }
  96.  
  97. /***********************************************************************
  98.  *
  99.  *  Function callModule builds the instruction
  100.  *   CALLM #<data>,<ea>
  101.  *
  102.  ***********************************************************************/
  103.  
  104. #define     CALLM_MASK      0x06c0
  105.  
  106. int callModule(instruction *tablePtr, int size, char *label, char *op,
  107.                                                             int *errorPtr)
  108.     {
  109.     opDescriptor source, dest;
  110.  
  111. /* op points to the first character of the operand field */
  112.  
  113. /* Move location counter to a word boundary and fix the listing before
  114.  * assembling the instruction */
  115.  
  116.     if (loc & 1)                         /* if not at word boundary */
  117.         {
  118.         loc++;
  119.         listLoc();
  120.         }
  121.  
  122.     if (*label)
  123.         {
  124.         create(label, loc, errorPtr);
  125.         if (*errorPtr > SEVERE)
  126.             return NORMAL;
  127.         }
  128.  
  129.     if (size)
  130.         NEWERROR(*errorPtr, UNSIZED);
  131.  
  132.     op = opParse(op, &source, errorPtr);                /* parse source */
  133.     if (*errorPtr > SEVERE)
  134.         return NORMAL;
  135.     if (source.mode != Immediate)
  136.         {
  137.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  138.         return NULL;
  139.         }
  140.     if (*op != ',')             /* missing source/destination separator */
  141.         {
  142.         NEWERROR(*errorPtr, SYNTAX);
  143.         return NORMAL;
  144.         }
  145.     op = opParse(op+1, &dest, errorPtr);
  146.     if (*errorPtr > SEVERE)
  147.         return NORMAL;
  148.     if ((dest.mode & Control) == 0)
  149.         {
  150.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  151.         return NULL;
  152.         }
  153.     if (!isspace(*op) && *op != '\0')
  154.                             /* if operand field contains
  155.                              * superfluous characters */
  156.         {
  157.         NEWERROR(*errorPtr, SYNTAX);
  158.         return NORMAL;
  159.         }
  160.     if (pass2)
  161.         output( (long) (CALLM_MASK | effAddr(&dest)), WORD);
  162.     loc += 2;
  163.     if (pass2)
  164.         {
  165.         output( (long) (source.data & 0xff), WORD);
  166.  
  167.         if (source.data < 0 || source.data > 255)
  168.             NEWERROR(*errorPtr, INV_8_BIT_DATA);
  169.         }
  170.     loc += 2;
  171.     extWords(&dest, size, errorPtr);
  172.     return NORMAL;
  173.     }
  174.  
  175. /***********************************************************************
  176.  *
  177.  *  Function comSwap builds the instruction
  178.  *   CAS Dc,Du,<ea>
  179.  *
  180.  ***********************************************************************/
  181.  
  182. #define     isRegNum(c)     ((c >= '0') && (c <= '7'))
  183. #define     CAS_BYTEMASK    0x0ac0
  184. #define     CAS_WORDMASK    0x0cc0
  185. #define     CAS_LONGMASK    0x0ec0
  186.  
  187. int compSwap(instruction *tablePtr, int size, char *label, char *op,
  188.                                                             int *errorPtr)
  189.     {
  190.     opDescriptor source;
  191.     char regc, regu;
  192.  
  193. /* op points to the first character of the operand field */
  194.  
  195. /* Move location counter to a word boundary and fix the listing before
  196.  * assembling the instruction */
  197.  
  198.     if (loc & 1)                         /* if not at word boundary */
  199.         {
  200.         loc++;
  201.         listLoc();
  202.         }
  203.  
  204.     if (*label)
  205.         {
  206.         create(label, loc, errorPtr);
  207.         if (*errorPtr > SEVERE)
  208.             return NORMAL;
  209.         }
  210. /* Parse Dc and Du */
  211.     if (op[0] == 'D' && isRegNum(op[1]) && op[2] == ',' && op[3] == 'D'
  212.                     && isRegNum(op[4]) && op[5] == ',')
  213.         {
  214.         regc = op[1] - '0';
  215.         regu = op[4] - '0';
  216.         }
  217.     else
  218.         {
  219.         NEWERROR(*errorPtr, SYNTAX);
  220.         return NORMAL;
  221.         }
  222.  
  223. /* Parse effective address */
  224.     op = opParse(op+6, &source, errorPtr);
  225.     if (*errorPtr > SEVERE)
  226.         return NORMAL;
  227.     if ((source.mode & MemAlt) == 0)
  228.         {
  229.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  230.         return NULL;
  231.         }
  232.     if (!isspace(*op) && *op != '\0')
  233.                             /* if operand field contains
  234.                              * superfluous characters */
  235.         {
  236.         NEWERROR(*errorPtr, SYNTAX);
  237.         return NORMAL;
  238.         }
  239. /* generate output */
  240.     if (pass2)
  241.         switch (size)
  242.             {
  243.             case BYTE:
  244.                 output( (long) (CAS_BYTEMASK | effAddr(&source)), WORD);
  245.                 break;
  246.             case LONG:
  247.                 output( (long) (CAS_LONGMASK | effAddr(&source)), WORD);
  248.                 break;
  249.             default:        /* size == WORD || size == 0 */
  250.                 output( (long) (CAS_WORDMASK | effAddr(&source)), WORD);
  251.                 break;
  252.             }
  253.     loc += 2;
  254.     if (pass2)
  255.         output( (long) ((regu << 6) | regc), WORD);
  256.     loc += 2;
  257.     extWords(&source, size, errorPtr);
  258.     return NORMAL;
  259.     }
  260.  
  261. /***********************************************************************
  262.  *
  263.  *  Function comSwap2 builds the instruction
  264.  *   CAS2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
  265.  *
  266.  ***********************************************************************/
  267.  
  268. #define     CAS2_WORDMASK   0x0cfc
  269. #define     CAS2_LONGMASK   0x0efc
  270.  
  271. int compSwap2(instruction *tablePtr, int size, char *label, char *op,
  272.                                                             int *errorPtr)
  273.     {
  274.     opDescriptor source, dest;
  275.     char regc1, regc2, regu1, regu2, regn1, regn2;
  276.  
  277. /* op points to the first character of the operand field */
  278.  
  279. /* Move location counter to a word boundary and fix the listing before
  280.  * assembling the instruction */
  281.  
  282.     if (loc & 1)                         /* if not at word boundary */
  283.         {
  284.         loc++;
  285.         listLoc();
  286.         }
  287.  
  288.     if (*label)
  289.         {
  290.         create(label, loc, errorPtr);
  291.         if (*errorPtr > SEVERE)
  292.             return NORMAL;
  293.         }
  294.  
  295. /* Parse operand string "Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)" */
  296.  
  297.     if  (    op[0] == 'D' && isRegNum(op[1]) && op[2] == ':'        /* Dc1: */
  298.               && op[3] == 'D' && isRegNum(op[4]) && op[5] == ','    /* Dc2, */
  299.               && op[6] == 'D' && isRegNum(op[7]) && op[8] == ':'    /* Du1: */
  300.               && op[9] == 'D' && isRegNum(op[10]) && op[11] == ','  /* Du2, */
  301.               && op[12] == '(' && (op[13] == 'D' || op[13] == 'A')  /* (R1 */
  302.               && isRegNum(op[14]) && op[15] == ')'&& op[16] == ':'  /* n): */
  303.               && op[17] == '(' && (op[18] == 'D' || op[18] == 'A')  /* (R2 */
  304.               && isRegNum(op[19]) && op[20] == ')' )                /* n) */
  305.         {
  306.         regc1 = op[1] - '0';
  307.         regc2 = op[4] - '0';
  308.         regu1 = op[7] - '0';
  309.         regu2 = op[10] - '0';
  310.         regn1 = op[14] - '0';
  311.         regn2 = op[19] - '0';
  312.         if (op[13] == 'A')
  313.             regn1 |= 8;
  314.         if (op[18] == 'A')
  315.             regn2 |= 8;
  316.         }
  317.     else
  318.         {
  319.         NEWERROR(*errorPtr, SYNTAX);
  320.         return NORMAL;
  321.         }
  322.  
  323.     if (!isspace(op[21]) && op[21] != '\0')
  324.                             /* if operand field contains
  325.                              * superfluous characters */
  326.         {
  327.         NEWERROR(*errorPtr, SYNTAX);
  328.         return NORMAL;
  329.         }
  330.  
  331.     if (pass2)
  332.         switch (size)
  333.             {
  334.             case WORD:
  335.             case 0:
  336.                 output( (long) CAS2_WORDMASK, WORD);
  337.                 break;
  338.             case LONG:
  339.                 output( (long) CAS2_LONGMASK, WORD);
  340.                 break;
  341.             default:
  342.                 output ( (long) CAS2_WORDMASK, WORD);
  343.                 NEWERROR(*errorPtr, IGNORED_SIZE);
  344.             }
  345.         loc += 2;
  346.         if (pass2)
  347.             output( (long) (regc1 | (regu1 << 6 ) | (regn1 << 12)), WORD);
  348.         loc += 2;
  349.         if (pass2)
  350.             output( (long) (regc2 | (regu2 << 6 ) | (regn2 << 12)), WORD);
  351.         loc += 2;
  352.  
  353.         return NORMAL;
  354.     }
  355.  
  356. /***********************************************************************
  357.  *
  358.  *  Function checkReg builds the instruction
  359.  *   CHK2 <ea>,Rn
  360.  *
  361.  ***********************************************************************/
  362.  
  363. #define     CHK2_BYTEMASK   0x00c0
  364. #define     CHK2_WORDMASK   0x02c0
  365. #define     CHK2_LONGMASK   0x04c0
  366.  
  367. int checkReg(instruction *tablePtr, int size, char *label, char *op,
  368.                                                             int *errorPtr)
  369.  
  370.     {
  371.     opDescriptor source, dest;
  372.  
  373. /* op points to the first character of the operand field */
  374.  
  375. /* Move location counter to a word boundary and fix the listing before
  376.  * assembling the instruction */
  377.  
  378.     if (loc & 1)                         /* if not at word boundary */
  379.         {
  380.         loc++;
  381.         listLoc();
  382.         }
  383.  
  384.     if (*label)
  385.         {
  386.         create(label, loc, errorPtr);
  387.         if (*errorPtr > SEVERE)
  388.             return NORMAL;
  389.         }
  390.  
  391. /* Parse source effective address */
  392.     op = opParse(op, &source, errorPtr);
  393.     if (*errorPtr > SEVERE)
  394.         return NORMAL;
  395.     if ((source.mode & Control) == 0)
  396.         {
  397.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  398.         return NULL;
  399.         }
  400.  
  401.     if (*op != ',')
  402.                     /* missing source/destination separator */
  403.     {
  404.     NEWERROR(*errorPtr, SYNTAX);
  405.     return NORMAL;
  406.     }
  407.  
  408. /* Parse dest effective address */
  409.     op = opParse(op+1, &dest, errorPtr);
  410.     if (*errorPtr > SEVERE)
  411.         return NORMAL;
  412.     if ((dest.mode & GenReg) == 0)
  413.         {
  414.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  415.         return NULL;
  416.         }
  417.     if (dest.mode == AnDirect)
  418.         dest.reg |= 8;
  419.  
  420.     if (!isspace(*op) && *op != '\0')
  421.                             /* if operand field contains
  422.                              * superfluous characters */
  423.         {
  424.         NEWERROR(*errorPtr, SYNTAX);
  425.         return NORMAL;
  426.         }
  427.  
  428. /* generate output */
  429.     if (pass2)
  430.         switch (size)
  431.             {
  432.             case BYTE:
  433.                 output( (long) (CHK2_BYTEMASK | effAddr(&source)), WORD);
  434.                 break;
  435.             case LONG:
  436.                 output( (long) (CHK2_LONGMASK | effAddr(&source)), WORD);
  437.                 break;
  438.             default:        /* size == WORD || size == 0 */
  439.                 output( (long) (CHK2_WORDMASK | effAddr(&source)), WORD);
  440.                 break;
  441.             }
  442.     loc += 2;
  443.     if (pass2)
  444.         if (strcmp(tablePtr->mnemonic, "CHK2") == 0)
  445.             output( (long) ((dest.reg << 12) | 0x800), WORD);
  446.         else                /* (strcmp(tablePtr->mnemonic, "CMP2") == 0) */
  447.             output( (long) (dest.reg << 12), WORD);
  448.     loc += 2;
  449.     extWords(&source, size, errorPtr);
  450.     return NORMAL;
  451.     }
  452.  
  453. /***********************************************************************
  454.  *
  455.  *  Functions divsop, divslop, divuop, divulop and divide build the
  456.  *  following instructions:
  457.  *   DIVS <ea>,Dn
  458.  *   DIVS <ea>,Dq
  459.  *   DIVS <ea>,Dr:Dq
  460.  *   DIVSL <ea>,Dr,Dq
  461.  *   DIVU <ea>,Dn
  462.  *   DIVU <ea>,Dq
  463.  *   DIVU <ea>,Dr:Dq
  464.  *   DIVUL <ea>,Dr:Dq
  465.  *
  466.  ***********************************************************************/
  467.  
  468. #define     DIVS_W          1
  469. #define     DIVS_L          2
  470. #define     DIVS_2L         3
  471. #define     DIVSL_2L        4
  472. #define     DIVU_W          5
  473. #define     DIVU_L          6
  474. #define     DIVU_2L         7
  475. #define     DIVUL_2L        8
  476.  
  477. #define     DIVS_W_MASK             0x81c0
  478. #define     DIVS_L_MASK             0x4c40
  479. #define     DIVS_L_64BIT_XMASK      0x0c00
  480. #define     DIVS_L_32BIT_XMASK      0x0800
  481.  
  482. #define     DIVU_W_MASK             0x80c0
  483. #define     DIVU_L_MASK             0x4c40
  484.                                      /* same as DIVS_L_MASK, for all LONG */
  485. #define     DIVU_L_64BIT_XMASK      0x0400
  486. #define     DIVU_L_32BIT_XMASK      0x0000
  487.                                     /* unnecessary, included for symmetry */
  488.  
  489. int divide(int inst_flag, int size, char *label, opDescriptor source,
  490.                                                     char *op, int *errorPtr)
  491.     {
  492.  
  493. /* op points to the first character of the destination part of the operand
  494.  * field */
  495.  
  496. /* Move location counter to a word boundary and fix the listing before
  497.  * assembling the instruction */
  498.  
  499.     if (loc & 1)                         /* if not at word boundary */
  500.         {
  501.         loc++;
  502.         listLoc();
  503.         }
  504.  
  505.     if (*label)
  506.         {
  507.         create(label, loc, errorPtr);
  508.         if (*errorPtr > SEVERE)
  509.             return NORMAL;
  510.         }
  511.     switch (inst_flag)
  512.         {
  513.         case DIVS_W:
  514.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2]))
  515.                 if (!isspace(op[3]) && op[3] != '\0')
  516.                                                 /* if operand field contains
  517.                                                  * superfluous characters */
  518.                     {
  519.                     NEWERROR(*errorPtr, SYNTAX);
  520.                     return NORMAL;
  521.                     }
  522.                 else
  523.                     {
  524.                     if (pass2)
  525.                         output( (long) (DIVS_W_MASK | effAddr(&source)
  526.                                 | ((op[2] - '0') << 9)), WORD);
  527.                     loc += 2;
  528.                     extWords(&source, size, errorPtr);
  529.                     return NORMAL;
  530.                     }
  531.             else
  532.                 {
  533.                 NEWERROR(*errorPtr, SYNTAX);
  534.                 return NORMAL;
  535.                 }
  536.  
  537.         case DIVS_L:
  538.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2]))
  539.                 if (!isspace(op[3]) && op[3] != '\0')
  540.                                                 /* if operand field contains
  541.                                                  * superfluous characters */
  542.                     {
  543.                     NEWERROR(*errorPtr, SYNTAX);
  544.                     return NORMAL;
  545.                     }
  546.                 else
  547.                     {
  548.                     if (pass2)
  549.                         output( (long) (DIVS_L_MASK | effAddr(&source)), WORD);
  550.                     loc += 2;
  551.                     if (pass2)
  552.                         output( (long) (DIVS_L_32BIT_XMASK |
  553.                             ((op[2] - '0') << 12) | (op[2] - '0')),WORD);
  554.                     loc += 2;
  555.                     extWords(&source, size, errorPtr);
  556.                     return NORMAL;
  557.                     }
  558.             else
  559.                 {
  560.                 NEWERROR(*errorPtr, SYNTAX);
  561.                 return NORMAL;
  562.                 }
  563.  
  564.         case DIVS_2L:
  565.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2])
  566.                         && op[3] == ':' && op[4] == 'D' && isRegNum(op[5]))
  567.                 if (!isspace(op[6]) && op[6] != '\0')
  568.                                                 /* if operand field contains
  569.                                                  * superfluous characters */
  570.                     {
  571.                     NEWERROR(*errorPtr, SYNTAX);
  572.                     return NORMAL;
  573.                     }
  574.                 else
  575.                     {
  576.                     if (pass2)
  577.                         output( (long) (DIVS_L_MASK | effAddr(&source)), WORD);
  578.                     loc += 2;
  579.                     if (pass2)
  580.                         output( (long) (DIVS_L_64BIT_XMASK |
  581.                             ((op[5] - '0') << 12) | (op[2] - '0')), WORD);
  582.                     loc += 2;
  583.                     extWords(&source, size, errorPtr);
  584.                     return NORMAL;
  585.                     }
  586.  
  587.         case DIVSL_2L:
  588.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2])
  589.                         && op[3] == ':' && op[4] == 'D' && isRegNum(op[5]))
  590.                 if (!isspace(op[6]) && op[6] != '\0')
  591.                                                 /* if operand field contains
  592.                                                  * superfluous characters */
  593.                     {
  594.                     NEWERROR(*errorPtr, SYNTAX);
  595.                     return NORMAL;
  596.                     }
  597.                 else
  598.                     {
  599.                     if (pass2)
  600.                         output( (long) (DIVS_L_MASK | effAddr(&source)), WORD);
  601.                     loc += 2;
  602.                     if (pass2)
  603.                         output( (long) (DIVS_L_32BIT_XMASK |
  604.                             ((op[5] - '0') << 12) | (op[2] - '0')), WORD);
  605.                     loc += 2;
  606.                     extWords(&source, size, errorPtr);
  607.                     return NORMAL;
  608.                     }
  609.  
  610.         case DIVU_W:
  611.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2]))
  612.                 if (!isspace(op[3]) && op[3] != '\0')
  613.                                                 /* if operand field contains
  614.                                                  * superfluous characters */
  615.                     {
  616.                     NEWERROR(*errorPtr, SYNTAX);
  617.                     return NORMAL;
  618.                     }
  619.                 else
  620.                     {
  621.                     if (pass2)
  622.                         output( (long) (DIVU_W_MASK | effAddr(&source)
  623.                                 | ((op[2] - '0') << 9)), WORD);
  624.                     loc += 2;
  625.                     extWords(&source, size, errorPtr);
  626.                     return NORMAL;
  627.                     }
  628.             else
  629.                 {
  630.                 NEWERROR(*errorPtr, SYNTAX);
  631.                 return NORMAL;
  632.                 }
  633.  
  634.         case DIVU_L:
  635.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2]))
  636.                 if (!isspace(op[3]) && op[3] != '\0')
  637.                                                 /* if operand field contains
  638.                                                  * superfluous characters */
  639.                     {
  640.                     NEWERROR(*errorPtr, SYNTAX);
  641.                     return NORMAL;
  642.                     }
  643.                 else
  644.                     {
  645.                     if (pass2)
  646.                         output( (long) (DIVU_L_MASK | effAddr(&source)), WORD);
  647.                     loc += 2;
  648.                     if (pass2)
  649.                         output( (long) (DIVU_L_32BIT_XMASK |
  650.                             ((op[2] - '0') << 12) | (op[2] - '0')), WORD);
  651.                     loc += 2;
  652.                     extWords(&source, size, errorPtr);
  653.                     return NORMAL;
  654.                     }
  655.             else
  656.                 {
  657.                 NEWERROR(*errorPtr, SYNTAX);
  658.                 return NORMAL;
  659.                 }
  660.  
  661.         case DIVU_2L:
  662.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2])
  663.                         && op[3] == ':' && op[4] == 'D' && isRegNum(op[5]))
  664.                 if (!isspace(op[6]) && op[6] != '\0')
  665.                                                 /* if operand field contains
  666.                                                  * superfluous characters */
  667.                     {
  668.                     NEWERROR(*errorPtr, SYNTAX);
  669.                     return NORMAL;
  670.                     }
  671.                 else
  672.                     {
  673.                     if (pass2)
  674.                         output( (long) (DIVU_L_MASK | effAddr(&source)), WORD);
  675.                     loc += 2;
  676.                     if (pass2)
  677.                         output( (long) (DIVU_L_64BIT_XMASK |
  678.                             ((op[5] - '0') << 12) | (op[2] - '0')), WORD);
  679.                     loc += 2;
  680.                     extWords(&source, size, errorPtr);
  681.                     return NORMAL;
  682.                     }
  683.  
  684.         case DIVUL_2L:
  685.             if (op[0] == ',' && op[1] == 'D' && isRegNum(op[2])
  686.                         && op[3] == ':' && op[4] == 'D' && isRegNum(op[5]))
  687.                 if (!isspace(op[6]) && op[6] != '\0')
  688.                                                 /* if operand field contains
  689.                                                  * superfluous characters */
  690.                     {
  691.                     NEWERROR(*errorPtr, SYNTAX);
  692.                     return NORMAL;
  693.                     }
  694.                 else
  695.                     {
  696.                     if (pass2)
  697.                         output( (long) (DIVU_L_MASK | effAddr(&source)), WORD);
  698.                     loc += 2;
  699.                     if (pass2)
  700.                         output( (long) (DIVU_L_32BIT_XMASK |
  701.                             ((op[5] - '0') << 12) | (op[2] - '0')), WORD);
  702.                     loc += 2;
  703.                     extWords(&source, size, errorPtr);
  704.                     return NORMAL;
  705.                     }
  706.  
  707.         default:
  708.             {
  709.             NEWERROR(*errorPtr, SYNTAX);
  710.             return NORMAL;
  711.             }
  712.         }
  713. /*  return NORMAL; */               /* superfluous, safety measure */
  714.     }
  715.  
  716. int divsop(instruction *tablePtr, int size, char *label, char *op,
  717.                                                             int *errorPtr)
  718.     {
  719.     opDescriptor source;
  720.  
  721. /* Parse source effective address */
  722.     op = opParse(op, &source, errorPtr);
  723.     if (*errorPtr > SEVERE)
  724.         return NORMAL;
  725.  
  726.     if ((source.mode & Data) == 0)
  727.         {
  728.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  729.         return NORMAL;
  730.         }
  731.  
  732.     if (!size || size == WORD)      /* accept unsized default */
  733.         return divide(DIVS_W, size, label, source, op, errorPtr);
  734.     else if (size == LONG)
  735.         {
  736.  
  737. /* Establish destination format: either Dq, or Dr:Dq */
  738.         if (op[0] == ',' && op[3] == ':')           /* Dr:Dq */
  739.             return divide(DIVS_2L, size, label, source, op, errorPtr);
  740.         else                                        /* Dq */
  741.             return divide(DIVS_L, size, label, source, op, errorPtr);
  742.         }
  743.     else
  744.         {
  745.         NEWERROR(*errorPtr, SYNTAX);
  746.         return NORMAL;
  747.         }
  748.     }
  749.  
  750. int divslop(instruction *tablePtr, int size, char *label, char *op,
  751.                                                             int *errorPtr)
  752.     {
  753.     opDescriptor source;
  754.  
  755. /* Parse source effective address */
  756.     op = opParse(op, &source, errorPtr);
  757.     if (*errorPtr > SEVERE)
  758.         return NORMAL;
  759.  
  760.     if ((source.mode & Data) == 0)
  761.         {
  762.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  763.         return NORMAL;
  764.         }
  765.  
  766.     return divide(DIVSL_2L, size, label, source, op, errorPtr);
  767.     }
  768.  
  769. int divuop(instruction *tablePtr, int size, char *label, char *op,
  770.                                                             int *errorPtr)
  771.     {
  772.     opDescriptor source;
  773.  
  774. /* Parse source effective address */
  775.     op = opParse(op, &source, errorPtr);
  776.     if (*errorPtr > SEVERE)
  777.         return NORMAL;
  778.  
  779.     if ((source.mode & Data) == 0)
  780.         {
  781.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  782.         return NORMAL;
  783.         }
  784.  
  785.     if (!size || size == WORD)      /* accept unsized default */
  786.         return divide(DIVU_W, size, label, source, op, errorPtr);
  787.     else if (size == LONG)
  788.         {
  789.  
  790. /* Establish destination format: either Dq, or Dr:Dq */
  791.         if (op[0] == ',' && op[3] == ':')           /* Dr:Dq */
  792.             return divide(DIVU_2L, size, label, source, op, errorPtr);
  793.         else                                        /* Dq */
  794.             return divide(DIVU_L, size, label, source, op, errorPtr);
  795.         }
  796.     else
  797.         {
  798.         NEWERROR(*errorPtr, SYNTAX);
  799.         return NORMAL;
  800.         }
  801.     }
  802.  
  803. int divulop(instruction *tablePtr, int size, char *label, char *op,
  804.                                                             int *errorPtr)
  805.     {
  806.     opDescriptor source;
  807.  
  808. /* Parse source effective address */
  809.     op = opParse(op, &source, errorPtr);
  810.   if (*errorPtr > SEVERE)
  811.         return NORMAL;
  812.  
  813.     if ((source.mode & Data) == 0)
  814.         {
  815.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  816.         return NORMAL;
  817.         }
  818.  
  819.     return divide(DIVUL_2L, size, label, source, op, errorPtr);
  820.     }
  821.  
  822.   /***********************************************************************
  823.  *
  824.  *  Function rtm builds the instruction
  825.  *   RTM Rn
  826.  *
  827.  ***********************************************************************/
  828.  
  829. #define     RTMMASK    0x06c0
  830.  
  831. int rtm(instruction *tablePtr, int size, char *label, char *op,
  832.                                                             int *errorPtr)
  833.     {
  834.     int reg;
  835.  
  836. /* Move location counter to a word boundary and fix the listing before
  837.  * assembling the instruction */
  838.  
  839.     if (loc & 1)                         /* if not at word boundary */
  840.         {
  841.         loc++;
  842.         listLoc();
  843.         }
  844.  
  845.     if (*label)
  846.         {
  847.         create(label, loc, errorPtr);
  848.         if (*errorPtr > SEVERE)
  849.             return NORMAL;
  850.         }
  851.  
  852.     if (size)
  853.         NEWERROR(*errorPtr, IGNORED_SIZE);
  854.  
  855.     if ((op[0] == 'D' || op[0] == 'A') && isRegNum(op[1]))
  856.         if (!isspace(op[2]) && op[2] != '\0')
  857.                                 /* if operand field contains
  858.                                  * superfluous characters */
  859.             {
  860.             NEWERROR(*errorPtr, SYNTAX);
  861.             return NORMAL;
  862.             }
  863.         else
  864.             {
  865.             reg = op[1] - '0';
  866.             if (op[0] == 'A')
  867.                 reg |= 8;               /* set the D/A bit */
  868.             if (pass2)
  869.                 output( (long) (RTMMASK | reg), WORD);
  870.             loc += 2;
  871.             }
  872.     }
  873.  
  874.  
  875.   /***********************************************************************
  876.  *
  877.  *  Function pck builds the instructions
  878.  *   PACK -(Ax),-(Ay),#<adjustment>
  879.  *   PACK Dx,Dy,#<adjustment>
  880.  *   UNPK -(Ax),-(Ay),#<adjustment>
  881.  *   UNPK Dx,Dy,#<adjustment>
  882.  *
  883.  ***********************************************************************/
  884.  
  885. int pck(int mask, char *label, char *op, int *errorPtr)
  886.     {
  887.     long value;
  888.     char backRef;
  889.  
  890. /* Move location counter to a word boundary and fix the listing before
  891.  * assembling the instruction */
  892.  
  893.     if (loc & 1)                         /* if not at word boundary */
  894.         {
  895.         loc++;
  896.         listLoc();
  897.         }
  898.  
  899.     if (*label)
  900.         {
  901.         create(label, loc, errorPtr);
  902.         if (*errorPtr > SEVERE)
  903.             return NORMAL;
  904.         }
  905.  
  906.     if (op[0] == '-' && op[1] == '(' && op[2] == 'A' && isRegNum(op[3])
  907.             && op[4] == ')' && op[5] == ','
  908.             && op[6] == '-' && op[7] == '(' && op[8] == 'A' && isRegNum(op[9])
  909.             && op[10] == ')' && op[11] == ',' && op[12] == '#')
  910.         {
  911.         mask |= 8 | (op[3] - '0') | ((op[9] - '0') << 9);
  912.         op += 13;
  913.         }
  914.     else if (op[0] == 'D' && isRegNum(op[1]) && op[2] == ','
  915.             && op[3] == 'D' && isRegNum(op[4]) && op[5] == ',' && op[6] == '#')
  916.         {
  917.         mask |= (op[1] - '0') | ((op[4] - '0') << 9);
  918.         op += 7;
  919.         }
  920.     else
  921.         {
  922.         NEWERROR(*errorPtr, SYNTAX);
  923.         return NORMAL;
  924.         }
  925.     op = eval(op, &value, &backRef, errorPtr);
  926.     if (*errorPtr > SEVERE)
  927.         return NORMAL;
  928.     if (pass2)
  929.         output( (long) mask, WORD);
  930.     loc += 2;
  931.     if (pass2)
  932.         output( (long) (value & 0xFFFF), WORD);
  933.     loc += 2;
  934.     if (value < -32768 || value > 32767)
  935.         NEWERROR(*errorPtr, INV_16_BIT_DATA);
  936.     return NORMAL;
  937.     }
  938.  
  939. #define     PACKMASK    0x8140
  940. #define     UNPKMASK    0x8180
  941.  
  942. int pack(instruction *tablePtr, int size, char *label, char *op,
  943.                                                             int *errorPtr)
  944.     {
  945.     if (size)
  946.         NEWERROR(*errorPtr, IGNORED_SIZE);
  947.     return pck(PACKMASK, label, op, errorPtr);
  948.     }
  949.  
  950.  
  951. int unpack(instruction *tablePtr, int size, char *label, char *op,
  952.                                                             int *errorPtr)
  953.     {
  954.     if (size)
  955.         NEWERROR(*errorPtr, IGNORED_SIZE);
  956.     return pck(UNPKMASK, label, op, errorPtr);
  957.     }
  958.