/*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Object code generator - January 6, 1989 */ /* */ /* This program may be copied for personal, non-commercial use */ /* only, provided that the above copyright notice is included */ /* on all copies of the source code. Copying for any other use */ /* without the consent of the author is prohibited. */ /* */ /*------------------------------------------------------------------*/ /* */ /* Originally published (in Modula-2) in */ /* Dr. Dobb's Journal, April, May, and June 1986. */ /* */ /* AmigaDOS conversion copyright 1989 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ #include #include "a68kdef.h" #include "a68kglb.h" /* Functions */ extern int LineParts(), Instructions(), ObjDir(); extern int GetInstModeSize(), GetMultReg(), CountNest(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue(); extern char *AddName(), *GetField(); extern struct SymTab *NextSym(); extern struct SymTab **HashIt(); GetObjectCode (dummy) int dummy; /* Determines the object code for the operation as well as the operands */ /* Returns each (up to 3 fields), along with the length of each. */ { int quick; int ExtL; /* Bit pattern for instruction extension word */ long templong; char tempop[MAXLINE]; register int i, j; i = Instructions (OpLoc); /* Analyze the opcode */ if (Dir != None) { ObjDir (dummy); /* Process directives */ return; } if ((Label[0] != '\0') || (OpCode[0] != '\0')) PrntAddr = TRUE; /* Print address at least */ if (OpCode[0] == '\0') { MakeHunk |= PrntAddr; return; /* No op code, exit now */ } if (!i) { /* Unrecognized opcode */ if ((Quiet < 0) && (InF->UPtr == 0)) ShowLine (InF->Line); /* Show where we are */ if (OpCode[0] == '*') { Error (OpLoc, NoCode); /* Don't try to open the console! */ return; } if (Size == Byte) /* Set up \0 parameter */ MacSize[0] = 'B'; else if (Size == Long) MacSize[0] = 'L'; else MacSize[0] = 'W'; AddrAdv = InstSize = 0; PrntAddr = FALSE; Dir = MacCall; /* Assume it's a macro call */ if (InF->UPtr == 0) { /* If we're reading from a file */ InF->Pos = lseek (In.fd, 0L,1); /* remember where we are. */ InF->Pos -= In.Lim - In.Ptr; } tempop[0] = ' '; tempop[1] = '\0'; strcat (tempop, OpCode); /* Prepend a blank to OpCode */ if (ReadSymTab (tempop)) { /* Search for user macro */ AddRef (LineCount); if(Sym->Defn < LineCount) { /* Only if previously defined! */ InFNum++; if (--InF < LowInF) LowInF = InF; MacCount++; Heap2Space (0); /* Check for space */ InF->UPtr = (char *) Hunk2; /* MACRO statement */ InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it */ InF->NPtr = NextFNS; /* New stack pointer */ InF->Line = 0; /* Line number in macro */ InF->NArg=GetArgs (""); /* Get arguments */ InF->MCnt = MacCount; /* Macro number */ if (OuterMac == 0) OuterMac = InFNum; /* Outer macro */ return; } } if (!OpenIncl (OpCode, InclList)) { Error (OpLoc, NoCode); /* Couldn't open file */ Dir = BadMac; /* Invalid macro */ if (InF->UPtr == 0) { In.fd = open (InF->NPtr, 0); lseek (In.fd, InF->Pos, 0); In.Ptr = In.Lim = In.Buf; } return; /* Return to outer file */ } InFNum++; /* Bump nesting level */ if (--InF < LowInF) LowInF = InF; MacCount++; Heap2Space (0); /* Check for space */ InF->UPtr = 0; /* Not a user macro */ InF->NPtr = NextFNS; /* New stack pointer */ InF->Line = 0; /* Line number in macro */ InF->NArg = GetArgs (OpCode); /* Get arguments */ InF->MCnt = MacCount; /* Macro number */ if (OuterMac == 0) OuterMac = InFNum; /* Outer macro */ return; } MakeHunk = TRUE; /* We have something for a hunk */ AddrCnt = AddrBndW (AddrCnt); /* It'll be word-aligned */ if ((AdrModeA != 0) || (AdrModeB != 0)) { Src.Loc = SrcLoc; Dest.Loc = DestLoc; GetOperand (SrcOp, &Src, SrcPC IN AdrModeB ? 2 : 0); GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0); } if (EA05z IN AdrModeB) { /* MOVEM */ if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) { OpCode[4] = '\0'; /* MOVEM of a single register */ Instructions (OpLoc); /* becomes a straight MOVE */ } } if ((Src.Mode == Imm) /* Immediate instructions */ && (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount) && (((EA611 IN AdrModeB) && (Dest.Mode == DReg) /* MOVE */ && (Size == Long) && (Src.Value >= -128) && (Src.Value <= 127)) || ((EA05y IN AdrModeB) /* ADD/SUB */ && (Src.Value > 0) && (Src.Value <= 8)))) { strcat (OpCode, "Q"); /* Make it ADDQ/SUBQ/MOVEQ */ Instructions (OpLoc); } else if ((Dest.Mode == ARDir) && (Src.Mode <= 12) && (((EA05y | EA611) IN AdrModeB) /* ADD, SUB, or MOVE */ || (OpM68C IN AdrModeA))) { /* CMP */ strcat (OpCode, "A"); /* ADD op,An becomes ADDA etc. */ Instructions (OpLoc); } else if ((Src.Mode == Imm) /* Immediate instructions */ && ((OpM68D | OpM68C | OpM68X) IN AdrModeA)) { strcat (OpCode, "I"); /* ADD/AND/OR/SUB, CMP, EOR */ Instructions (OpLoc); /* ADD #op,d becomes ADDI etc. */ } else if ((Src.Mode == ARPost) && (Dest.Mode == ARPost) && (OpM68C IN AdrModeA)) { /* CMP */ strcat (OpCode, "M"); /* Generate CMPM if necessary */ Instructions (OpLoc); } /*=================== Operand validation routines ====================*/ if (Pass2) { /* If an immediate operand isn't absolute, it must be a long word */ if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK)) Error (SrcLoc, RelErr); /* ------- Check for instructions with too many operands. ------- */ /* Some specialized instruction routines contain their own tests. */ if (AdrModeA == 0) { /* Should have only one operand */ if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) { if (Dest.Mode != Null) Error (DestLoc, OperErr); /* } else if (AdrModeB == 0) { */ /* Should have no operands */ /* if (Src.Mode != Null) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); De-activated for now */ } } if ((AdrModeA != 0) || (AdrModeB != 0)) { if(Dest.Mode != NULL) { /* We should never find 3 operands */ j = DestLoc + strlen (DestOp); if ((Line[j] != '\0') && (Line[j] != ';') && (!isspace (Line[j]))) { Error (j, OperErr); } } /* ---------------- Check for missing operands. ----------------- */ if (Src.Mode == Null) { Error (OpLoc+strlen(OpCode), OperErr); /* No source */ } else if (Dest.Mode == Null) { if (((ImmMode & AdrModeB) == ImmMode) || (TwoOpsA IN AdrModeA) || (TwoOpsB IN AdrModeB)) { Error (SrcLoc+strlen(SrcOp), OperErr); /* No dest. */ } } } } /*====================================================================*/ /* ---------------- Decrement and Branch (DBcc) ----------------- */ if (DecBr IN AdrModeA) { if (Pass2) { if (Src.Mode != DReg) Error (SrcLoc, ModeErr); if (Dest.Value & 1) Error (DestLoc, AlignErr); /* Boundary alignment error */ if (Dest.Hunk == CurrHunk) { ObjSrc = Dest.Value-AddrCnt-2; /* Relative branch distance */ Dest.Hunk = ABSHUNK; /* Displacement is absolute */ } else ObjSrc = 0; /* Let the linker worry about it */ if ((ObjSrc > 32767) || (ObjSrc < -32768)) Error (DestLoc,BraErr); /* Too far to branch */ if (Dest.Hunk!=CurrHunk) { /* DBcc to another section */ templong = AddrCnt + 2; /* 16-bit relocatable */ PutRel (templong, Dest.Hunk, 2); } ObjOp = Op | Src.Rn; } AddrAdv = 4; nO = nS = 2; return; } /* ------------ Branch (Bcc, including BRA and BSR) ------------- */ if (Brnch IN AdrModeA) { if (Src.Value & 1) Error (SrcLoc, AlignErr); /* Boundary alignment error */ if (Src.Hunk == CurrHunk) { ObjSrc=Src.Value-AddrCnt-2; /* Relative branch distance */ Src.Hunk = ABSHUNK; /* Displacement is absolute */ if (Size != Byte) { if ((ObjSrc >= -128) && (ObjSrc <= 127) && (ObjSrc != 0)) if (DefLine2 < LineCount) Size = Byte; /* Short branch if possible */ else if (Pass2 && FwdProc && (Size != Byte)) FwdShort=TRUE; /* Fwd. ref. could be made short */ } if ((Size == Byte) && (ObjSrc == 0)) Error (SrcLoc, BccSDsp0); /* Can't do this! */ } else { ObjSrc = 0; /* Let the linker worry about it */ if (Size == Byte) Error (SrcLoc, BraErr); /* No external short branches! */ } if (Size != Byte) { InstSize = 4; nS = 2; templong = 32767; } else { InstSize = 2; Op |= (ObjSrc & 0x00FF); templong = 127; } if ((ObjSrc > templong) || (ObjSrc < -templong-1)) Error (SrcLoc, BraErr); /* Too far to branch */ if (Dest.Mode != Null) Error (DestLoc, OperErr); /* No Destination operand! */ AddrAdv = InstSize; ObjOp = Op; nO = 2; if (Src.Hunk != CurrHunk) { /* Bcc to another section */ templong = AddrCnt + 2; /* 16-bit relocatable */ PutRel (templong, Src.Hunk, 2); } return; } /* ------------ Check for short (16-bit) JMP or JSR ------------- */ if ((Op == JMP) || (Op == JSR)) if ((Size == Byte) && (Src.Mode == AbsL)) Src.Mode = AbsW; /* Uses information from Instructions & GetOperand (among others) */ /* to complete calculation of Object Code. */ /* Op, AdrModeA, AdrModeB, Size, and Src & Dest records are all */ /* Global variables imported from the SyntaxAnalyzer MODULE. */ ExtL = 0; quick = FALSE; /* ------------ Check for boundary alignment errors. ------------ */ /* BCHG, BCLR, BSET, BTST, LEA, NBCD, PEA, Scc, TAS are exempt. */ if (Pass2) { if ((Size != Byte) && (Op != LEA) && (Op != PEA) && !((AdrModeA == 0) && (AdrModeB == 0)) && !(AdrModeB & EA05c) /* BTST */ && !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) { if (Src.Value & 1) if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX)) Error (SrcLoc, AlignErr); if (Dest.Value & 1) if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX)) Error (DestLoc, AlignErr); } /* Check for 5 special cases first */ if (Op == STOP) { if (Src.Mode != Imm) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } if (Op == LINK) { Op |= Src.Rn; if (Src.Mode != ARDir) Error (SrcLoc, ModeErr); if (Dest.Mode != Imm) Error (DestLoc, ModeErr); else if (Dest.Value & 1) Error (DestLoc, AlignErr); /* Boundary alignment error */ } if (Op == SWAP) { if (!(EA05f IN AdrModeB)) { /* Ignore if PEA instruction */ Op |= Src.Rn; if (Src.Mode != DReg) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } } if (Op == UNLK) { Op |= Src.Rn; if (Src.Mode != ARDir) Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } /* Now do generalized address modes */ if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) { /* 2 registers */ if (Op == CMPM) { /* Special routine for CMPM */ Op |= Src.Rn | (Dest.Rn << 9); if (Src.Mode != ARPost) Error (SrcLoc, ModeErr); if (Dest.Mode != ARPost) Error (DestLoc, ModeErr); } else { /* Other two-register instructions */ Op |= Src.Rn | (Dest.Rn << 9); if (RegMem3 IN AdrModeA) { if (Src.Mode == DReg) { if (Dest.Mode != DReg) Error (DestLoc, ModeErr); } else if (Src.Mode == ARPre) { Op |= 0x0008; if (Dest.Mode != ARPre) Error (DestLoc, ModeErr); } else Error (SrcLoc, OperErr); } else { if (Src.Mode == ARPost) if (Dest.Mode != ARPost) Error (DestLoc, ModeErr); else Error (SrcLoc, OperErr); } } } } if (Data911 IN AdrModeA) { /* Data in 9-11 (ADDQ/SUBQ) */ quick = TRUE; if (Src.Mode == Imm) if ((Src.Value > 0) && (Src.Value <= 8)) { if (Src.Value < 8) /* Data of 8 is coded as 000 */ Op |= Src.Value << 9; } else Error (SrcLoc, SizeErr); else Error (SrcLoc, OperErr); } if (CntR911 IN AdrModeA) { /* Only Shift/Rotate use this */ if (Dest.Mode == DReg) { Op = (Op & 0xF9FF) | Dest.Rn; if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; if (Src.Mode == DReg) Op |= 0x0020 | (Src.Rn << 9); else if (Src.Mode == Imm) { quick = TRUE; /* Range Check */ if ((Src.Value > 0) && (Src.Value <= 8)) { if (Src.Value < 8) /* Data of 8 is coded as 000 */ Op |= (Src.Value << 9); } else Error (SrcLoc, SizeErr); } else Error (SrcLoc, OperErr); } else if (Dest.Mode == Null) { Op = (Op & 0xFFE7) | 0x00C0; EffAdr (&Src, (mea | aea)); } else Error (SrcLoc, OperErr); } if (Data03 IN AdrModeA) { /* TRAP Vector in 0-3 */ quick = TRUE; if (Src.Mode == Imm) if ((Src.Value >= 0) && (Src.Value < 16)) Op |= Src.Value; else Error (SrcLoc, SizeErr); else Error (SrcLoc, OperErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); } if (Data07 IN AdrModeA) { /* Data in 0-7 (MOVEQ) */ quick = TRUE; Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9); if (Src.Mode != Imm) Error (SrcLoc, ModeErr); else if (Dest.Mode != DReg) Error (DestLoc, ModeErr); else if ((Src.Value < -128) || (Src.Value > 127)) Error (SrcLoc, SizeErr); } if (Pass2) { if (OpM68D IN AdrModeA) { /* DReg in 6-8 (ADD/AND/OR/SUB) */ if (Dest.Mode == DReg) { Op |= (Dest.Rn << 9); if ((Src.Mode == ARDir) && (Size == Byte)) Error (SrcLoc, SizeErr); } else /* Assume Src.Mode = DReg -- Error trapped elsewhere */ Op |= (Src.Rn << 9) | 0x0100; if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; } if (OpM68A IN AdrModeA) { /* AReg in 6-8 (ADDA/CMPA/SUBA) */ if (Dest.Mode == ARDir) Op |= (Dest.Rn << 9); else Error (DestLoc, ModeErr); if (Size == Byte) Error (OpLoc+5, SizeErr); if (Size == Word) Op |= 0x00C0; if (Size == Long) Op |= 0x01C0; } if (OpM68C IN AdrModeA) { /* CMP (Compare) */ if (Dest.Mode == DReg) Op |= (Dest.Rn << 9); else Error (DestLoc, ModeErr); if (Size == Byte) { if (Src.Mode == ARDir) Error (OpLoc+4, SizeErr); } if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; } if (OpM68X IN AdrModeA) { /* EOR (Exclusive or) */ if (Src.Mode == DReg) Op |= (Src.Rn << 9); else Error (SrcLoc, ModeErr); if (Size == Byte) Op |= 0x0100; if (Size == Word) Op |= 0x0140; if (Size == Long) Op |= 0x0180; } if (OpM68S IN AdrModeA) { /* EXT (Sign extension) */ if (Src.Mode == DReg) Op |= Src.Rn; else Error (SrcLoc, ModeErr); if (Dest.Mode != Null) Error (DestLoc, OperErr); if (Size == Byte) Error (OpLoc+4, SizeErr); if (Size == Word) Op |= 0x0080; if (Size == Long) Op |= 0x00C0; } if (OpM68R IN AdrModeA) { /* MOVEP (Register/memory) */ if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) { if (Size == Byte) Error (OpLoc+6, SizeErr); if (Size == Word) Op |= 0x0180; if (Size == Long) Op |= 0x01C0; Op |= (Src.Rn << 9) | Dest.Rn; } else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) { if (Size == Byte) Error (OpLoc+6, SizeErr); if (Size == Word) Op |= 0x0100; if (Size == Long) Op |= 0x0140; Op |= Src.Rn | (Dest.Rn << 9); } else Error (SrcLoc, ModeErr); } if (OpM37 IN AdrModeA) { /* EXG (Exchange registers) */ if ((Src.Mode == DReg) && (Dest.Mode == DReg)) Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn; else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir)) Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn; else if ((Src.Mode == ARDir) && (Dest.Mode == DReg)) Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn; else if ((Src.Mode == DReg) && (Dest.Mode == ARDir)) Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn; else Error (SrcLoc, ModeErr); } if (Bit811 IN AdrModeB) { /* Bit operations using bits 8-11 */ Size = Word; /* Ignore size specification */ if (Src.Mode == DReg) Op |= 0x0100 | (Src.Rn << 9); else if (Src.Mode == Imm) Op |= 0x0800; else Error (SrcLoc, ModeErr); } if (Size67 IN AdrModeB) { /* Size in bits 6-7 */ /* if (Size == Byte) ; No action -- bits are already 0 */ if (Size == Word) Op |= 0x0040; if (Size == Long) Op |= 0x0080; } if (Size6 IN AdrModeB) { /* Size in bit 6 (MOVEM) */ if (Size == Byte) Error (OpLoc+6, SizeErr); /* if (Size == Word) ; No Action -- bit is already 0 */ if (Size == Long) Op |= 0x0040; } if (Sz1213A IN AdrModeB) { /* Size in 12-13 (MOVE) */ if (Size == Byte) Op |= 0x1000; if (Size == Word) Op |= 0x3000; if (Size == Long) Op |= 0x2000; } if (Sz1213 IN AdrModeB) { /* Size in 12-13 (MOVEA) */ if (Dest.Mode == DReg) /* Can't be to data register! */ Error(DestLoc,ModeErr); /* (Others are caught elsewhere) */ Op |= (Dest.Rn << 9); if (Size == Byte) Error (OpLoc+6, SizeErr); if (Size == Word) Op |= 0x3000; if (Size == Long) Op |= 0x2000; } if (EA05a IN AdrModeB) /* Effective address - all */ if ((Dest.Mode == DReg) || (Dest.Mode == ARDir)) EffAdr (&Src, ea); else Error (DestLoc, ModeErr); if (EA05b IN AdrModeB) /* Eff. Addr. - all except ARDir */ if (Dest.Mode == DReg) { EffAdr (&Src, dea); Op |= (Dest.Rn << 9); } else Error (DestLoc, ModeErr); if (EA05c IN AdrModeB) /* BTST */ EffAdr (&Dest, 0x0802); /* All but ARDir/Imm */ if(EA05d IN AdrModeB) { /* All but PC relative & immediate */ EffAdr (&Dest, aea); if ((Dest.Mode == ARDir) && (Size == Byte)) Error (OpLoc+5, SizeErr); } if(EA05e IN AdrModeB) { /* All but ARDir, PC relative, Imm */ if (Dest.Mode == Null) EffAdr (&Src, (dea | aea)); else if ((Src.Mode == Imm) || (Src.Mode == DReg)) EffAdr (&Dest, (dea | aea)); else Error (SrcLoc, ModeErr); } if (EA05f IN AdrModeB) { /* JMP, JSR, LEA, and PEA */ EffAdr (&Src, cea); if (Rx911 IN AdrModeA) if (Dest.Mode == ARDir) Op |= (Dest.Rn << 9); /* Address Reg. for LEA */ else Error(DestLoc,ModeErr); /* Must load Address Reg. */ else if (Dest.Mode != Null) Error (DestLoc, OperErr); /* No Dest. unless LEA */ } if (EA05x IN AdrModeB) { /* AND and OR */ if (Dest.Mode == DReg) EffAdr (&Src, dea); else if (Src.Mode == DReg) EffAdr (&Dest, mea | aea); else Error (SrcLoc, OperErr); } if (EA05y IN AdrModeB) { /* ADD and SUB */ if (Dest.Mode == DReg) { EffAdr (&Src, ea); if ((Src.Mode == ARDir) && (Size == Byte)) Error (OpLoc+4, SizeErr); } else if (Src.Mode == DReg) EffAdr (&Dest, (mea | aea)); else Error (SrcLoc, ModeErr); } } if (EA05z IN AdrModeB) { /* MOVEM */ if (Pass2) { if (Src.Mode == MultiM) { /* Move to memory */ EffAdr (&Dest, (mea | aea | 0x0008)); ExtL = Src.Value; i = (Dest.Mode == ARPre); /* ExtL flip indicator */ } else if (Dest.Mode == MultiM) { /* Move from memory */ Op |= 0x0400; /* Set direction */ EffAdr (&Src, (mea | 0x0810)); ExtL = Dest.Value; i = (Src.Mode == ARPre); } else { Error (SrcLoc, OperErr); i = FALSE; } if (i) { /* Flip ExtL if ARPre */ j = 0; for (i = 0; i < 8; i++) j |= (ExtL & (1<> (i*2-15); ExtL = j; } } nO += 2; /* Extension is part of OpCode */ InstSize += 2; } if (Pass2) { if (EA611 IN AdrModeB) { /* Eff. Addr. in 6-11 (MOVE) */ if (Dest.Mode == CCR) { /* MOVE to CCR */ Op = 0x44C0; EffAdr (&Src, dea); } else if (Dest.Mode == SR) { /* MOVE to SR */ Op = 0x46C0; EffAdr (&Src, dea); } else if (Src.Mode == SR) { /* MOVE from SR */ Op = 0x40C0; EffAdr (&Dest, dea | aea); } else if (Dest.Mode == USP) { /* MOVE to USP */ Op = 0x4E60; if (Src.Mode == ARDir) Op |= Src.Rn; else Error (SrcLoc, ModeErr); } else if (Src.Mode == USP) { /* MOVE from USP */ Op = 0x4E68; if (Dest.Mode == ARDir) Op |= Dest.Rn; else Error (DestLoc, ModeErr); } else { /* General MOVE instruction */ EffAdr (&Src, (ea | xxx)); if ((Size == Byte) && (Src.Mode == ARDir)) Error (SrcLoc, SizeErr); if (Src.Mode > 12) Error (SrcLoc, ModeErr); if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12)) Error (DestLoc, ModeErr); else if (Dest.Mode < 8) /* Register direct or indirect */ Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn << 9); else /* Absolute, PC relative, or immediate */ Op |= 0x01C0 | ((Dest.Mode - 8) << 9); OperExt (&Dest); /* Set up extension word */ } } if ((Dest.Mode == CCR) && (Src.Mode == Imm)) { if ((Size67 IN AdrModeB) && (EA05e IN AdrModeB) && (Exten IN AdrModeB)) if (0x0400 IN Op) /* not ANDI/EORI/ORI */ Error (DestLoc, ModeErr); else Op = (Op & 0xFF00) | 0x003C; } if ((Dest.Mode == SR) && (Src.Mode == Imm)) { if ((Size67 IN AdrModeB) && (EA05e IN AdrModeB) && (Exten IN AdrModeB)) if (0x0400 IN Op) /* not ANDI/EORI/ORI */ Error (DestLoc, ModeErr); else Op = (Op & 0xFF00) | 0x007C; } } ObjOp = Op; InstSize += 2; nO += 2; if (nO > 2) { templong = ExtL; /* Add extension word */ ObjOp = (ObjOp << 16) | (templong & 0x0000FFFFL); } if ((AdrModeA != 0) || (AdrModeB != 0)) { InstSize += (nS = GetInstModeSize (Src.Mode)); ObjSrc = Src.Value; InstSize += (nD = GetInstModeSize (Dest.Mode)); ObjDest = Dest.Value; } if (quick) { InstSize -= nS; /* Source operand is in Op */ nS = 0; } if (Pass2) { if ((nS!=0) && (Src.Hunk!=ABSHUNK)) { /* SrcOp relocatable */ if ((Src.Mode == AbsL) || (Src.Mode == AbsW) || (Src.Mode == ARDisp) || (Src.Mode == PCDisp) || (Src.Mode == Imm)) { templong = AddrCnt+nO; /* 32- or 16-bit relocatable */ PutRel (templong, Src.Hunk, nS); } if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) { templong = AddrCnt + nO + 1; /* 8-bit relocatable */ PutRel (templong, Src.Hunk, 1); } } if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) { /* DestOp relocatable */ if ((Dest.Mode == AbsL) || (Dest.Mode == AbsW) || (Dest.Mode == ARDisp) || (Dest.Mode == PCDisp) || (Dest.Mode == Imm)) { templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */ PutRel (templong, Dest.Hunk, nD); } if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) { templong = AddrCnt+nO+nS+1; /* 8-bit relocatable */ PutRel (templong, Dest.Hunk, 1); } } } AddrAdv = InstSize; }