home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d186 / a68k.lha / A68k / Codegen.c < prev    next >
C/C++ Source or Header  |  1989-02-26  |  23KB  |  790 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*          Object code generator - January 6, 1989            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*     AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), Instructions(), ObjDir();
  29. extern int  GetInstModeSize(), GetMultReg(), CountNest();
  30. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  31. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  32. extern char *AddName(),    *GetField();
  33. extern struct SymTab *NextSym();
  34. extern struct SymTab **HashIt();
  35.  
  36.  
  37.  
  38. GetObjectCode (dummy) int dummy;
  39. /* Determines the object code for the operation    as well    as the operands    */
  40. /* Returns each    (up to 3 fields), along    with the length    of each.     */
  41. {
  42.     int     quick;
  43.     int     ExtL;        /* Bit pattern for instruction extension word */
  44.     long templong;
  45.     char tempop[MAXLINE];
  46.     register int i, j;
  47.  
  48.     i =    Instructions (OpLoc);        /* Analyze the opcode */
  49.  
  50.     if (Dir != None) {
  51.     ObjDir (dummy);            /* Process directives */
  52.     return;
  53.     }
  54.     if ((Label[0] != '\0') || (OpCode[0] != '\0'))
  55.     PrntAddr = TRUE;        /* Print address at least */
  56.  
  57.     if (OpCode[0] == '\0') {
  58.     MakeHunk |= PrntAddr;
  59.     return;                /* No op code, exit now    */
  60.     }
  61.     if (!i) {                /* Unrecognized    opcode */
  62.     if ((Quiet < 0)    && (InF->UPtr == 0))
  63.         ShowLine (InF->Line);    /* Show    where we are */
  64.     if (OpCode[0] == '*') {
  65.         Error (OpLoc, NoCode);    /* Don't try to open the console! */
  66.         return;
  67.     }
  68.     if (Size == Byte)        /* Set up \0 parameter */
  69.         MacSize[0] = 'B';
  70.     else if    (Size == Long)
  71.         MacSize[0] = 'L';
  72.     else
  73.         MacSize[0] = 'W';
  74.  
  75.     AddrAdv    = InstSize = 0;
  76.     PrntAddr = FALSE;
  77.     Dir = MacCall;            /* Assume it's a macro call */
  78.     if (InF->UPtr == 0) {        /* If we're reading from a file */
  79.         InF->Pos = lseek (In.fd, 0L,1); /*    remember where we are.    */
  80.         InF->Pos -=    In.Lim - In.Ptr;
  81.     }
  82.     tempop[0] = ' ';
  83.     tempop[1] = '\0';
  84.     strcat (tempop,    OpCode);    /* Prepend a blank to OpCode */
  85.     if (ReadSymTab (tempop)) {    /* Search for user macro */
  86.         AddRef (LineCount);
  87.         if(Sym->Defn < LineCount) {    /* Only    if previously defined! */
  88.         InFNum++;
  89.         if (--InF < LowInF)
  90.             LowInF = InF;
  91.         MacCount++;
  92.         Heap2Space (0);            /* Check for space */
  93.         InF->UPtr = (char *) Hunk2;    /* MACRO statement */
  94.         InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it */
  95.         InF->NPtr = NextFNS;    /* New stack pointer */
  96.         InF->Line = 0;        /* Line    number in macro    */
  97.         InF->NArg=GetArgs (""); /* Get arguments */
  98.         InF->MCnt = MacCount;    /* Macro number    */
  99.         if (OuterMac ==    0)
  100.             OuterMac = InFNum;    /* Outer macro */
  101.         return;
  102.         }
  103.     }
  104.     if (!OpenIncl (OpCode, InclList)) {
  105.         Error (OpLoc, NoCode);    /* Couldn't open file */
  106.         Dir    = BadMac;        /* Invalid macro */
  107.         if (InF->UPtr == 0)    {
  108.         In.fd =    open (InF->NPtr, 0);
  109.         lseek (In.fd, InF->Pos,    0);
  110.         In.Ptr = In.Lim    = In.Buf;
  111.         }
  112.         return;            /* Return to outer file    */
  113.     }
  114.     InFNum++;            /* Bump    nesting    level */
  115.     if (--InF < LowInF)
  116.         LowInF = InF;
  117.     MacCount++;
  118.     Heap2Space (0);            /* Check for space */
  119.     InF->UPtr = 0;            /* Not a user macro */
  120.     InF->NPtr = NextFNS;        /* New stack pointer */
  121.     InF->Line = 0;            /* Line    number in macro    */
  122.     InF->NArg = GetArgs (OpCode);    /* Get arguments */
  123.     InF->MCnt = MacCount;        /* Macro number    */
  124.     if (OuterMac ==    0)
  125.         OuterMac = InFNum;        /* Outer macro */
  126.     return;
  127.     }
  128.  
  129.     MakeHunk = TRUE;            /* We have something for a hunk    */
  130.     AddrCnt = AddrBndW (AddrCnt);    /* It'll be word-aligned */
  131.  
  132.     if ((AdrModeA != 0)    || (AdrModeB !=    0)) {
  133.     Src.Loc    = SrcLoc;
  134.     Dest.Loc = DestLoc;
  135.     GetOperand (SrcOp, &Src, SrcPC IN AdrModeB ? 2 : 0);
  136.     GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0);
  137.     }
  138.     if (EA05z IN AdrModeB) {        /* MOVEM */
  139.     if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
  140.         OpCode[4] =    '\0';           /* MOVEM of a single register */
  141.         Instructions (OpLoc);    /*  becomes a straight MOVE   */
  142.     }
  143.     }
  144.     if ((Src.Mode == Imm)        /* Immediate instructions */
  145.     && (Src.Hunk == ABSHUNK) &&    (Src.Defn < LineCount)
  146.     &&       (((EA611 IN AdrModeB) && (Dest.Mode == DReg)    /* MOVE    */
  147.         && (Size ==    Long) && (Src.Value >= -128) &&    (Src.Value <= 127))
  148.     || ((EA05y IN AdrModeB)                /* ADD/SUB */
  149.         && (Src.Value > 0) && (Src.Value <=    8)))) {
  150.         strcat (OpCode,    "Q");   /* Make it ADDQ/SUBQ/MOVEQ */
  151.         Instructions (OpLoc);
  152.     }
  153.     else if ((Dest.Mode    == ARDir) && (Src.Mode <= 12)
  154.     && (((EA05y    | EA611) IN AdrModeB)    /* ADD,    SUB, or    MOVE */
  155.     || (OpM68C IN AdrModeA))) {    /* CMP */
  156.         strcat (OpCode, "A");       /* ADD op,An becomes ADDA etc. */
  157.         Instructions (OpLoc);
  158.     }
  159.     else if ((Src.Mode == Imm)        /* Immediate instructions */
  160.     && ((OpM68D    | OpM68C | OpM68X) IN AdrModeA)) {
  161.     strcat (OpCode,    "I");           /* ADD/AND/OR/SUB, CMP, EOR */
  162.     Instructions (OpLoc);        /* ADD #op,d becomes ADDI etc. */
  163.     }
  164.     else if ((Src.Mode == ARPost) && (Dest.Mode    == ARPost)
  165.     && (OpM68C IN AdrModeA)) {        /* CMP */
  166.     strcat (OpCode,    "M");           /* Generate CMPM if necessary */
  167.     Instructions (OpLoc);
  168.     }
  169.  
  170.  
  171. /*=================== Operand validation routines ====================*/
  172.  
  173.     if (Pass2) {
  174.  
  175.     /* If an immediate operand isn't absolute, it must be a long word */
  176.  
  177.     if ((Src.Mode == Imm) && (Size != Long)    && (Src.Hunk !=    ABSHUNK))
  178.         Error (SrcLoc, RelErr);
  179.  
  180.     /* ------- Check for instructions with too many operands. ------- */
  181.     /* Some specialized    instruction routines contain their own tests. */
  182.  
  183.     if (AdrModeA ==    0) {        /* Should have only one    operand    */
  184.         if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) {
  185.         if (Dest.Mode != Null)
  186.             Error (DestLoc, OperErr);
  187. /*        } else if (AdrModeB    == 0) {    */  /* Should have no operands */
  188. /*        if (Src.Mode !=    Null)
  189.             Error (SrcLoc, OperErr);
  190.         if (Dest.Mode != Null)
  191.             Error (DestLoc, OperErr); De-activated for now */
  192.         }
  193.     }
  194.     if ((AdrModeA != 0) || (AdrModeB != 0))    {
  195.         if(Dest.Mode != NULL) { /* We should never find 3 operands */
  196.         j = DestLoc + strlen (DestOp);
  197.         if ((Line[j] !=    '\0')
  198.         && (Line[j] != ';')
  199.         && (!isspace (Line[j]))) {
  200.             Error (j, OperErr);
  201.         }
  202.         }
  203.  
  204.     /* ----------------    Check for missing operands. ----------------- */
  205.  
  206.         if (Src.Mode == Null) {
  207.         Error (OpLoc+strlen(OpCode), OperErr);    /* No source */
  208.         } else if (Dest.Mode == Null) {
  209.         if (((ImmMode &    AdrModeB) == ImmMode)
  210.         || (TwoOpsA IN AdrModeA)
  211.         || (TwoOpsB IN AdrModeB)) {
  212.             Error (SrcLoc+strlen(SrcOp), OperErr);  /* No dest.    */
  213.         }
  214.         }
  215.     }
  216.     }
  217.  
  218. /*====================================================================*/
  219.  
  220.     /* ----------------    Decrement and Branch (DBcc) ----------------- */
  221.  
  222.     if (DecBr IN AdrModeA) {
  223.     if (Pass2) {
  224.         if (Src.Mode != DReg)
  225.         Error (SrcLoc, ModeErr);
  226.         if (Dest.Value & 1)
  227.         Error (DestLoc,    AlignErr);  /* Boundary    alignment error    */
  228.  
  229.         if (Dest.Hunk == CurrHunk) {
  230.         ObjSrc = Dest.Value-AddrCnt-2;    /* Relative branch distance */
  231.         Dest.Hunk = ABSHUNK;        /* Displacement    is absolute */
  232.         } else
  233.         ObjSrc = 0;        /* Let the linker worry    about it */
  234.  
  235.         if ((ObjSrc    > 32767) || (ObjSrc < -32768))
  236.         Error (DestLoc,BraErr);    /* Too far to branch */
  237.  
  238.         if (Dest.Hunk!=CurrHunk) {    /* DBcc    to another section */
  239.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  240.         PutRel (templong, Dest.Hunk, 2);
  241.         }
  242.         ObjOp = Op | Src.Rn;
  243.     }
  244.     AddrAdv    = 4;
  245.     nO = nS    = 2;
  246.     return;
  247.     }
  248.  
  249.     /* ------------ Branch (Bcc, including BRA and BSR)    ------------- */
  250.  
  251.     if (Brnch IN AdrModeA) {
  252.     if (Src.Value &    1)
  253.         Error (SrcLoc, AlignErr);    /* Boundary alignment error */
  254.  
  255.     if (Src.Hunk ==    CurrHunk) {
  256.         ObjSrc=Src.Value-AddrCnt-2;    /* Relative branch distance */
  257.         Src.Hunk = ABSHUNK;        /* Displacement    is absolute */
  258.         if (Size !=    Byte) {
  259.         if ((ObjSrc >= -128) &&    (ObjSrc    <= 127)    && (ObjSrc != 0))
  260.             if (DefLine2 < LineCount)
  261.             Size = Byte;    /* Short branch    if possible */
  262.             else if (Pass2 && FwdProc && (Size != Byte))
  263.             FwdShort=TRUE;    /* Fwd.    ref. could be made short */
  264.         }
  265.         if ((Size == Byte) && (ObjSrc == 0))
  266.         Error (SrcLoc, BccSDsp0);    /* Can't do this! */
  267.     } else {
  268.         ObjSrc = 0;            /* Let the linker worry    about it */
  269.         if (Size ==    Byte)
  270.         Error (SrcLoc, BraErr);    /* No external short branches! */
  271.     }
  272.  
  273.     if (Size != Byte) {
  274.         InstSize = 4;
  275.         nS = 2;
  276.         templong = 32767;
  277.     } else {
  278.         InstSize = 2;
  279.         Op |= (ObjSrc & 0x00FF);
  280.         templong = 127;
  281.     }
  282.     if ((ObjSrc > templong)    || (ObjSrc < -templong-1))
  283.         Error (SrcLoc, BraErr);    /* Too far to branch */
  284.  
  285.     if (Dest.Mode != Null)
  286.         Error (DestLoc, OperErr);    /* No Destination operand! */
  287.  
  288.     AddrAdv    = InstSize;
  289.     ObjOp =    Op;
  290.     nO = 2;
  291.     if (Src.Hunk !=    CurrHunk) {    /* Bcc to another section */
  292.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  293.         PutRel (templong, Src.Hunk,    2);
  294.     }
  295.     return;
  296.     }
  297.  
  298.     /* ------------ Check for short (16-bit) JMP or JSR    ------------- */
  299.  
  300.     if ((Op == JMP) || (Op == JSR))
  301.     if ((Size == Byte) && (Src.Mode    == AbsL))
  302.         Src.Mode = AbsW;
  303.  
  304. /*  Uses information from Instructions & GetOperand (among others)  */
  305. /*  to complete    calculation of Object Code.                */
  306. /*  Op,    AdrModeA, AdrModeB, Size, and Src & Dest records are all    */
  307. /*  Global variables imported from the SyntaxAnalyzer MODULE.        */
  308.  
  309.     ExtL = 0;
  310.     quick = FALSE;
  311.  
  312.     /* ------------ Check for boundary alignment errors. ------------ */
  313.     /*    BCHG, BCLR, BSET, BTST,    LEA, NBCD, PEA,    Scc, TAS are exempt.  */
  314.  
  315.     if (Pass2) {
  316.     if ((Size != Byte)
  317.     && (Op != LEA)
  318.     && (Op != PEA)
  319.     && !((AdrModeA == 0) &&    (AdrModeB == 0))
  320.     && !(AdrModeB &    EA05c)        /* BTST */
  321.     && !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) {
  322.         if (Src.Value & 1)
  323.         if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX))
  324.             Error (SrcLoc, AlignErr);
  325.         if (Dest.Value & 1)
  326.         if ((Dest.Mode >= ARDisp) && (Dest.Mode    <= PCDisX))
  327.             Error (DestLoc, AlignErr);
  328.     }
  329.  
  330. /* Check for 5 special cases first */
  331.  
  332.     if (Op == STOP)    {
  333.         if (Src.Mode != Imm)
  334.         Error (SrcLoc, OperErr);
  335.         if (Dest.Mode != Null)
  336.         Error (DestLoc,    OperErr);
  337.     }
  338.  
  339.     if (Op == LINK)    {
  340.         Op |= Src.Rn;
  341.         if (Src.Mode != ARDir)
  342.         Error (SrcLoc, ModeErr);
  343.         if (Dest.Mode != Imm)
  344.         Error (DestLoc,    ModeErr);
  345.         else if (Dest.Value    & 1)
  346.         Error (DestLoc,    AlignErr);  /* Boundary    alignment error    */
  347.     }
  348.  
  349.     if (Op == SWAP)    {
  350.         if (!(EA05f    IN AdrModeB)) {    /* Ignore if PEA instruction */
  351.         Op |= Src.Rn;
  352.         if (Src.Mode !=    DReg)
  353.             Error (SrcLoc, OperErr);
  354.         if (Dest.Mode != Null)
  355.             Error (DestLoc, OperErr);
  356.         }
  357.     }
  358.  
  359.     if (Op == UNLK)    {
  360.         Op |= Src.Rn;
  361.         if (Src.Mode != ARDir)
  362.         Error (SrcLoc, OperErr);
  363.         if (Dest.Mode != Null)
  364.         Error (DestLoc,    OperErr);
  365.     }
  366.  
  367. /* Now do generalized address modes */
  368.  
  369.     if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) {    /* 2 registers */
  370.         if (Op == CMPM) {        /* Special routine for CMPM */
  371.         Op |= Src.Rn | (Dest.Rn    << 9);
  372.         if (Src.Mode !=    ARPost)
  373.             Error (SrcLoc, ModeErr);
  374.         if (Dest.Mode != ARPost)
  375.             Error (DestLoc, ModeErr);
  376.         } else {        /* Other two-register instructions */
  377.         Op |= Src.Rn | (Dest.Rn    << 9);
  378.         if (RegMem3 IN AdrModeA) {
  379.             if (Src.Mode == DReg) {
  380.             if (Dest.Mode != DReg)
  381.                 Error (DestLoc, ModeErr);
  382.             } else if (Src.Mode    == ARPre) {
  383.             Op |= 0x0008;
  384.             if (Dest.Mode != ARPre)
  385.                 Error (DestLoc, ModeErr);
  386.             } else
  387.             Error (SrcLoc, OperErr);
  388.         } else {
  389.             if (Src.Mode == ARPost)
  390.             if (Dest.Mode != ARPost)
  391.                 Error (DestLoc, ModeErr);
  392.             else
  393.                 Error (SrcLoc, OperErr);
  394.         }
  395.         }
  396.     }
  397.     }
  398.     if (Data911    IN AdrModeA) {        /* Data    in 9-11    (ADDQ/SUBQ) */
  399.     quick =    TRUE;
  400.     if (Src.Mode ==    Imm)
  401.         if ((Src.Value > 0)    && (Src.Value <= 8)) {
  402.         if (Src.Value <    8)  /* Data of 8 is coded as 000 */
  403.             Op |= Src.Value << 9;
  404.         } else
  405.         Error (SrcLoc, SizeErr);
  406.     else
  407.         Error (SrcLoc, OperErr);
  408.     }
  409.  
  410.     if (CntR911    IN AdrModeA) {        /* Only    Shift/Rotate use this */
  411.     if (Dest.Mode == DReg) {
  412.         Op = (Op & 0xF9FF) | Dest.Rn;
  413.         if (Size ==    Word) Op |= 0x0040;
  414.         if (Size ==    Long) Op |= 0x0080;
  415.         if (Src.Mode == DReg)
  416.         Op |= 0x0020 | (Src.Rn << 9);
  417.         else if (Src.Mode == Imm) {
  418.         quick =    TRUE;
  419.         /* Range Check */
  420.         if ((Src.Value > 0) && (Src.Value <= 8)) {
  421.             if (Src.Value < 8) /* Data of 8 is coded as    000 */
  422.             Op |= (Src.Value << 9);
  423.         } else
  424.             Error (SrcLoc, SizeErr);
  425.         } else
  426.         Error (SrcLoc, OperErr);
  427.     } else if (Dest.Mode ==    Null) {
  428.         Op = (Op & 0xFFE7) | 0x00C0;
  429.         EffAdr (&Src, (mea | aea));
  430.     } else
  431.         Error (SrcLoc, OperErr);
  432.     }
  433.  
  434.     if (Data03 IN AdrModeA) {        /* TRAP    Vector in 0-3 */
  435.     quick =    TRUE;
  436.     if (Src.Mode ==    Imm)
  437.         if ((Src.Value >= 0) && (Src.Value < 16))
  438.         Op |= Src.Value;
  439.         else
  440.         Error (SrcLoc, SizeErr);
  441.     else
  442.         Error (SrcLoc, OperErr);
  443.  
  444.     if (Dest.Mode != Null)
  445.         Error (DestLoc, OperErr);
  446.     }
  447.  
  448.     if (Data07 IN AdrModeA) {        /* Data    in 0-7 (MOVEQ) */
  449.     quick =    TRUE;
  450.     Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
  451.     if (Src.Mode !=    Imm)
  452.         Error (SrcLoc, ModeErr);
  453.     else if    (Dest.Mode != DReg)
  454.         Error (DestLoc, ModeErr);
  455.     else if    ((Src.Value < -128) || (Src.Value > 127))
  456.         Error (SrcLoc, SizeErr);
  457.     }
  458.  
  459.     if (Pass2) {
  460.     if (OpM68D IN AdrModeA)    {   /* DReg in 6-8 (ADD/AND/OR/SUB) */
  461.         if (Dest.Mode == DReg) {
  462.         Op |= (Dest.Rn << 9);
  463.         if ((Src.Mode == ARDir)    && (Size == Byte))
  464.             Error (SrcLoc, SizeErr);
  465.         } else /* Assume Src.Mode =    DReg --    Error trapped elsewhere    */
  466.         Op |= (Src.Rn << 9) | 0x0100;
  467.  
  468.         if (Size ==    Word) Op |= 0x0040;
  469.         if (Size ==    Long) Op |= 0x0080;
  470.     }
  471.  
  472.     if (OpM68A IN AdrModeA)    {   /* AReg in 6-8 (ADDA/CMPA/SUBA) */
  473.         if (Dest.Mode == ARDir)
  474.         Op |= (Dest.Rn << 9);
  475.         else
  476.         Error (DestLoc,    ModeErr);
  477.  
  478.         if (Size ==    Byte) Error (OpLoc+5, SizeErr);
  479.         if (Size ==    Word) Op |= 0x00C0;
  480.         if (Size ==    Long) Op |= 0x01C0;
  481.     }
  482.  
  483.     if (OpM68C IN AdrModeA)    {    /* CMP (Compare) */
  484.         if (Dest.Mode == DReg)
  485.         Op |= (Dest.Rn << 9);
  486.         else
  487.         Error (DestLoc,    ModeErr);
  488.  
  489.         if (Size ==    Byte) {
  490.         if (Src.Mode ==    ARDir)
  491.             Error (OpLoc+4, SizeErr);
  492.         }
  493.         if (Size ==    Word) Op |= 0x0040;
  494.         if (Size ==    Long) Op |= 0x0080;
  495.     }
  496.  
  497.     if (OpM68X IN AdrModeA)    {    /* EOR (Exclusive or) */
  498.         if (Src.Mode == DReg)
  499.         Op |= (Src.Rn << 9);
  500.         else
  501.         Error (SrcLoc, ModeErr);
  502.  
  503.         if (Size ==    Byte) Op |= 0x0100;
  504.         if (Size ==    Word) Op |= 0x0140;
  505.         if (Size ==    Long) Op |= 0x0180;
  506.     }
  507.  
  508.     if (OpM68S IN AdrModeA)    {    /* EXT (Sign extension)    */
  509.         if (Src.Mode == DReg)
  510.         Op |= Src.Rn;
  511.         else
  512.         Error (SrcLoc, ModeErr);
  513.  
  514.         if (Dest.Mode != Null)
  515.         Error (DestLoc,    OperErr);
  516.  
  517.         if (Size ==    Byte) Error (OpLoc+4, SizeErr);
  518.         if (Size ==    Word) Op |= 0x0080;
  519.         if (Size ==    Long) Op |= 0x00C0;
  520.     }
  521.  
  522.     if (OpM68R IN AdrModeA)    {    /* MOVEP (Register/memory) */
  523.         if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) {
  524.         if (Size == Byte) Error    (OpLoc+6, SizeErr);
  525.         if (Size == Word) Op |=    0x0180;
  526.         if (Size == Long) Op |=    0x01C0;
  527.         Op |= (Src.Rn << 9) | Dest.Rn;
  528.         } else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) {
  529.         if (Size == Byte) Error    (OpLoc+6, SizeErr);
  530.         if (Size == Word) Op |=    0x0100;
  531.         if (Size == Long) Op |=    0x0140;
  532.         Op |= Src.Rn | (Dest.Rn    << 9);
  533.         } else
  534.         Error (SrcLoc, ModeErr);
  535.     }
  536.  
  537.     if (OpM37 IN AdrModeA) {    /* EXG (Exchange registers) */
  538.         if ((Src.Mode == DReg) && (Dest.Mode == DReg))
  539.         Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
  540.         else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir))
  541.         Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
  542.         else if ((Src.Mode == ARDir) && (Dest.Mode == DReg))
  543.         Op |= 0x0088 | (Dest.Rn    << 9) |    Src.Rn;
  544.         else if ((Src.Mode == DReg)    && (Dest.Mode == ARDir))
  545.         Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
  546.         else
  547.         Error (SrcLoc, ModeErr);
  548.     }
  549.  
  550.     if (Bit811 IN AdrModeB)    {   /* Bit operations using bits 8-11 */
  551.         Size = Word;        /* Ignore size specification */
  552.         if (Src.Mode == DReg)
  553.         Op |= 0x0100 | (Src.Rn << 9);
  554.         else if (Src.Mode == Imm)
  555.         Op |= 0x0800;
  556.         else
  557.         Error (SrcLoc, ModeErr);
  558.     }
  559.  
  560.     if (Size67 IN AdrModeB)    {    /* Size    in bits    6-7 */
  561.      /* if (Size ==    Byte) ;    No action -- bits are already 0    */
  562.         if (Size ==    Word) Op |= 0x0040;
  563.         if (Size ==    Long) Op |= 0x0080;
  564.     }
  565.  
  566.     if (Size6 IN AdrModeB) {    /* Size    in bit 6 (MOVEM) */
  567.         if (Size ==    Byte) Error (OpLoc+6, SizeErr);
  568.      /* if (Size ==    Word) ;    No Action -- bit is already 0 */
  569.         if (Size ==    Long) Op |= 0x0040;
  570.     }
  571.  
  572.     if (Sz1213A IN AdrModeB) {    /* Size    in 12-13 (MOVE)    */
  573.         if (Size ==    Byte) Op |= 0x1000;
  574.         if (Size ==    Word) Op |= 0x3000;
  575.         if (Size ==    Long) Op |= 0x2000;
  576.     }
  577.  
  578.     if (Sz1213 IN AdrModeB)    {    /* Size    in 12-13 (MOVEA) */
  579.         if (Dest.Mode == DReg)    /* Can't be to data register! */
  580.         Error(DestLoc,ModeErr);    /* (Others are caught elsewhere) */
  581.         Op |= (Dest.Rn << 9);
  582.         if (Size ==    Byte) Error (OpLoc+6, SizeErr);
  583.         if (Size ==    Word) Op |= 0x3000;
  584.         if (Size ==    Long) Op |= 0x2000;
  585.     }
  586.  
  587.     if (EA05a IN AdrModeB)        /* Effective address - all */
  588.         if ((Dest.Mode == DReg) || (Dest.Mode == ARDir))
  589.         EffAdr (&Src, ea);
  590.         else
  591.         Error (DestLoc,    ModeErr);
  592.  
  593.     if (EA05b IN AdrModeB)    /* Eff.    Addr. -    all except ARDir */
  594.         if (Dest.Mode == DReg) {
  595.         EffAdr (&Src, dea);
  596.         Op |= (Dest.Rn << 9);
  597.         } else
  598.         Error (DestLoc,    ModeErr);
  599.  
  600.     if (EA05c IN AdrModeB)        /* BTST    */
  601.         EffAdr (&Dest, 0x0802);    /* All but ARDir/Imm */
  602.  
  603.     if(EA05d IN AdrModeB) {    /* All but PC relative & immediate */
  604.         EffAdr (&Dest, aea);
  605.         if ((Dest.Mode == ARDir) &&    (Size == Byte))
  606.         Error (OpLoc+5,    SizeErr);
  607.     }
  608.  
  609.     if(EA05e IN AdrModeB) {    /* All but ARDir, PC relative, Imm */
  610.         if (Dest.Mode == Null)
  611.         EffAdr (&Src, (dea | aea));
  612.         else if ((Src.Mode == Imm) || (Src.Mode == DReg))
  613.         EffAdr (&Dest, (dea | aea));
  614.         else
  615.         Error (SrcLoc, ModeErr);
  616.     }
  617.  
  618.     if (EA05f IN AdrModeB) {    /* JMP,    JSR, LEA, and PEA */
  619.         EffAdr (&Src, cea);
  620.         if (Rx911 IN AdrModeA)
  621.         if (Dest.Mode == ARDir)
  622.             Op |= (Dest.Rn << 9);   /* Address Reg. for    LEA */
  623.         else
  624.             Error(DestLoc,ModeErr); /* Must load Address Reg. */
  625.         else
  626.         if (Dest.Mode != Null)
  627.             Error (DestLoc, OperErr);    /* No Dest. unless LEA */
  628.     }
  629.  
  630.     if (EA05x IN AdrModeB) {    /* AND and OR */
  631.         if (Dest.Mode == DReg)
  632.         EffAdr (&Src, dea);
  633.         else if (Src.Mode == DReg)
  634.         EffAdr (&Dest, mea | aea);
  635.         else
  636.         Error (SrcLoc, OperErr);
  637.     }
  638.  
  639.     if (EA05y IN AdrModeB) {    /* ADD and SUB */
  640.         if (Dest.Mode == DReg) {
  641.         EffAdr (&Src, ea);
  642.         if ((Src.Mode == ARDir)    && (Size == Byte))
  643.             Error (OpLoc+4, SizeErr);
  644.         } else if (Src.Mode    == DReg)
  645.         EffAdr (&Dest, (mea | aea));
  646.         else
  647.         Error (SrcLoc, ModeErr);
  648.     }
  649.     }
  650.  
  651.     if (EA05z IN AdrModeB) {        /* MOVEM */
  652.     if (Pass2) {
  653.         if (Src.Mode == MultiM) {        /* Move    to memory */
  654.         EffAdr (&Dest, (mea | aea | 0x0008));
  655.         ExtL = Src.Value;
  656.         i = (Dest.Mode == ARPre);    /* ExtL    flip indicator */
  657.         } else if (Dest.Mode == MultiM) {    /* Move    from memory */
  658.         Op |= 0x0400;            /* Set direction */
  659.         EffAdr (&Src, (mea | 0x0810));
  660.         ExtL = Dest.Value;
  661.         i = (Src.Mode == ARPre);
  662.         } else {
  663.         Error (SrcLoc, OperErr);
  664.         i = FALSE;
  665.         }
  666.         if (i) {                /* Flip    ExtL if    ARPre */
  667.         j = 0;
  668.         for (i = 0; i <    8; i++)
  669.             j |= (ExtL & (1<<i)) << (15-i*2);
  670.         for (i = 8; i <    16; i++)
  671.             j |= (ExtL & (1<<i)) >> (i*2-15);
  672.         ExtL = j;
  673.         }
  674.     }
  675.     nO += 2;    /* Extension is    part of    OpCode */
  676.     InstSize += 2;
  677.     }
  678.  
  679.     if (Pass2) {
  680.  
  681.     if (EA611 IN AdrModeB) {    /* Eff.    Addr. in 6-11 (MOVE) */
  682.         if (Dest.Mode == CCR) {        /* MOVE    to CCR */
  683.         Op = 0x44C0;
  684.         EffAdr (&Src, dea);
  685.         } else if (Dest.Mode == SR)    {    /* MOVE    to SR */
  686.         Op = 0x46C0;
  687.         EffAdr (&Src, dea);
  688.         } else if (Src.Mode    == SR) {    /* MOVE    from SR    */
  689.         Op = 0x40C0;
  690.         EffAdr (&Dest, dea | aea);
  691.         } else if (Dest.Mode == USP) {    /* MOVE    to USP */
  692.         Op = 0x4E60;
  693.         if (Src.Mode ==    ARDir)
  694.             Op |= Src.Rn;
  695.         else
  696.             Error (SrcLoc, ModeErr);
  697.         } else if (Src.Mode    == USP)    {    /* MOVE    from USP */
  698.         Op = 0x4E68;
  699.         if (Dest.Mode == ARDir)
  700.             Op |= Dest.Rn;
  701.         else
  702.             Error (DestLoc, ModeErr);
  703.         } else {            /* General MOVE    instruction */
  704.         EffAdr (&Src, (ea | xxx));
  705.         if ((Size == Byte) && (Src.Mode    == ARDir))
  706.             Error (SrcLoc, SizeErr);
  707.         if (Src.Mode > 12)
  708.             Error (SrcLoc, ModeErr);
  709.         if (((1<<(Dest.Mode-1))    IN (dea|aea)) || (Dest.Mode>12))
  710.             Error (DestLoc, ModeErr);
  711.         else if    (Dest.Mode < 8)    /* Register direct or indirect */
  712.             Op |= ((Dest.Mode -    1) << 6) | (Dest.Rn << 9);
  713.         else        /* Absolute, PC    relative, or immediate */
  714.             Op |= 0x01C0 | ((Dest.Mode - 8) << 9);
  715.         OperExt    (&Dest);        /* Set up extension    word */
  716.         }
  717.     }
  718.  
  719.     if ((Dest.Mode == CCR) && (Src.Mode == Imm)) {
  720.         if ((Size67    IN AdrModeB)
  721.         && (EA05e IN AdrModeB)
  722.         && (Exten IN AdrModeB))
  723.         if (0x0400 IN Op)    /* not ANDI/EORI/ORI */
  724.             Error (DestLoc, ModeErr);
  725.         else
  726.             Op = (Op & 0xFF00) | 0x003C;
  727.     }
  728.  
  729.     if ((Dest.Mode == SR) && (Src.Mode == Imm)) {
  730.         if ((Size67    IN AdrModeB)
  731.         && (EA05e IN AdrModeB)
  732.         && (Exten IN AdrModeB))
  733.         if (0x0400 IN Op)    /* not ANDI/EORI/ORI */
  734.             Error (DestLoc, ModeErr);
  735.         else
  736.             Op = (Op & 0xFF00) | 0x007C;
  737.     }
  738.     }
  739.  
  740.     ObjOp = Op;
  741.     InstSize +=    2;
  742.     nO += 2;
  743.     if (nO > 2)    {
  744.     templong = ExtL;            /* Add extension word */
  745.     ObjOp =    (ObjOp << 16) |    (templong & 0x0000FFFFL);
  746.     }
  747.     if ((AdrModeA != 0)    || (AdrModeB !=    0)) {
  748.     InstSize += (nS    = GetInstModeSize (Src.Mode));
  749.     ObjSrc = Src.Value;
  750.     InstSize += (nD    = GetInstModeSize (Dest.Mode));
  751.     ObjDest    = Dest.Value;
  752.     }
  753.     if (quick) {
  754.     InstSize -= nS;        /* Source operand is in    Op */
  755.     nS = 0;
  756.     }
  757.  
  758.     if (Pass2) {
  759.     if ((nS!=0) && (Src.Hunk!=ABSHUNK)) {    /* SrcOp relocatable */
  760.         if ((Src.Mode == AbsL)
  761.         || (Src.Mode == AbsW)
  762.         || (Src.Mode == ARDisp)
  763.         || (Src.Mode == PCDisp)
  764.         || (Src.Mode == Imm)) {
  765.         templong = AddrCnt+nO;    /* 32- or 16-bit relocatable */
  766.         PutRel (templong, Src.Hunk, nS);
  767.         }
  768.         if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
  769.         templong = AddrCnt + nO    + 1;    /* 8-bit relocatable */
  770.         PutRel (templong, Src.Hunk, 1);
  771.         }
  772.     }
  773.     if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) {    /* DestOp relocatable */
  774.         if ((Dest.Mode == AbsL)
  775.         || (Dest.Mode == AbsW)
  776.         || (Dest.Mode == ARDisp)
  777.         || (Dest.Mode == PCDisp)
  778.         || (Dest.Mode == Imm)) {
  779.         templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */
  780.         PutRel (templong, Dest.Hunk, nD);
  781.         }
  782.         if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) {
  783.         templong = AddrCnt+nO+nS+1;    /* 8-bit relocatable */
  784.         PutRel (templong, Dest.Hunk, 1);
  785.         }
  786.     }
  787.     }
  788.     AddrAdv = InstSize;
  789. }
  790.