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 >
Wrap
C/C++ Source or Header
|
1989-02-26
|
23KB
|
790 lines
/*------------------------------------------------------------------*/
/* */
/* 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 <stdio.h>
#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)) << (15-i*2);
for (i = 8; i < 16; i++)
j |= (ExtL & (1<<i)) >> (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;
}