Codegen.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. /*------------------------------------------------------------------*/
  2. /* */
  3. /* MC68000 Cross Assembler */
  4. /* */
  5. /* Copyright 1985 by Brian R. Anderson */
  6. /* */
  7. /* Object code generator - April 16, 1991 */
  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 1991 by Charlie Gibbs. */
  20. /* */
  21. /*------------------------------------------------------------------*/
  22. #include "A68kdef.h"
  23. #include "A68kglb.h"
  24. void GetObjectCode (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  25. /* Determines the object code for the operation as well as the operands */
  26. /* Returns each (up to 3 fields), along with the length of each. */
  27. {
  28. int quick;
  29. int ExtL; /* Bit pattern for instruction extension word */
  30. long templong;
  31. char tempop[MAXLINE];
  32. register int i, j;
  33. struct AddrDiff *SrcAddrDiffs=0; /* added by Kevin Kofler in v.2.71.F3l */
  34. struct AddrDiff *DestAddrDiffs=0; /* added by Kevin Kofler in v.2.71.F3l */
  35. long SrcVal; /* added by Kevin Kofler in v.2.71.F3l */
  36. /* register char *x; */ /* removed by Paul Froissart in v.2.71.F3c */
  37. i = Instructions (OpLoc); /* Analyze the opcode. */
  38. if (Dir != None) {
  39. ObjDir (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Process directives. */
  40. return;
  41. }
  42. if ((Label[0] != '\0') || (OpCode[0] != '\0'))
  43. PrntAddr = TRUE; /* Print address, at least. */
  44. if (OpCode[0] == '\0') {
  45. MakeHunk |= PrntAddr;
  46. return; /* No opcode, exit now. */
  47. }
  48. if (!i) { /* Unrecognized opcode */
  49. if ((Quiet < 0) && (InF->UPtr == 0))
  50. ShowLine (InF->Line); /* Show where we are. */
  51. if (Size == Byte) /* Set up \0 parameter. */
  52. MacSize[0] = 'B';
  53. else if (Size == Long)
  54. MacSize[0] = 'L';
  55. else
  56. MacSize[0] = 'W';
  57. AddrAdv = InstSize = 0;
  58. PrntAddr = FALSE;
  59. Dir = MacCall; /* Assume it's a macro call. */
  60. tempop[0] = ' ';
  61. tempop[1] = '\0';
  62. strcat (tempop, OpCode); /* Prepend a blank to OpCode. */
  63. if (ReadSymTab (tempop)) { /* Search for user macro. */
  64. AddRef (LineCount);
  65. if (InF->UPtr == 0) { /* If we're reading from a file */
  66. InF->Pos = lseek (In.fd, 0L,1); /* remember where we are. */
  67. InF->Pos -= In.Lim - In.Ptr;
  68. }
  69. if(Sym->Defn < LineCount) { /* Only if previously defined! */
  70. InFNum++;
  71. if (--InF < LowInF)
  72. LowInF = InF;
  73. MacCount++;
  74. Heap2Space (0); /* Check for space. */
  75. InF->UPtr = (char *) Hunk2; /* MACRO statement */
  76. InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it. */
  77. InF->NPtr = NextFNS; /* New stack pointer */
  78. InF->Line = 0; /* Line number in macro */
  79. InF->NArg=GetArgs (""); /* Get arguments. */
  80. InF->MCnt = MacCount; /* Macro number */
  81. if (OuterMac == 0)
  82. OuterMac = InFNum; /* Outer macro */
  83. return;
  84. }
  85. }
  86. if (!OpenIncl (OpCode, InclList)) {
  87. Error (OpLoc, NoCode); /* Couldn't open file. */
  88. Dir = BadMac; /* Invalid macro */
  89. return; /* Return to outer file. */
  90. }
  91. InFNum++; /* Bump nesting level. */
  92. if (--InF < LowInF)
  93. LowInF = InF;
  94. InF->UPtr = 0; /* Not a user macro. */
  95. InF->NPtr = NextFNS; /* New stack pointer */
  96. InF->Line = 0; /* Line number in macro */
  97. InF->MCnt = MacCount; /* Macro number */
  98. MacCount++;
  99. Heap2Space (0); /* Check for space. */
  100. InF->NArg = GetArgs (OpCode); /* Get arguments. */
  101. if (OuterMac == 0)
  102. OuterMac = InFNum; /* Outer macro */
  103. return;
  104. }
  105. MakeHunk = TRUE; /* We have something for a hunk. */
  106. /* AddrCnt = AddrBndW (AddrCnt); */ /* It'll be word-aligned. */
  107. if (!Unaligned) AddrCnt = AddrBndW (AddrCnt);
  108. /* It will be word-aligned unless -u is passed.
  109. -- Kevin Kofler, v.2.71.F3l */
  110. if ((AdrModeA != 0) || (AdrModeB != 0)) {
  111. Src.Loc = SrcLoc;
  112. Dest.Loc = DestLoc;
  113. if (SrcPC IN AdrModeB) /* Source operand can be PC-relative. */
  114. if (EA05z IN AdrModeB)
  115. i = 4; /* Displacement offset is 4 for MOVEM. */
  116. else
  117. i = 2; /* Offset is 2 for all others. */
  118. else
  119. i = 0; /* PC-relative modes are not allowed. */
  120. GetOperand (SrcOp, &Src, i);
  121. SrcAddrDiffs = AddrDiffs; /* added by Kevin Kofler in v.2.71.F3l */
  122. AddrDiffs = 0; /* added by Kevin Kofler in v.2.71.F3l */
  123. GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0);
  124. DestAddrDiffs = AddrDiffs; /* added by Kevin Kofler in v.2.71.F3l */
  125. AddrDiffs = 0; /* added by Kevin Kofler in v.2.71.F3l */
  126. }
  127. /* added by Kevin Kofler in v.2.71.F3l: */
  128. SrcVal=(long)((int)(Src.Value));
  129. {struct AddrDiff *p=SrcAddrDiffs;
  130. while (p) {
  131. SrcVal+=p->paddr-p->naddr;
  132. p=p->Link;
  133. }
  134. }
  135. /* if ((EA05z IN AdrModeB) && !NoOpt) { */ /* MOVEM */
  136. if ((EA05z IN AdrModeB) && !NoOpt && (optim&OPTIM_MOVEM)) { /* MOVEM */
  137. /* only if not disabled by -r switch - Paul Froissart, v.2.71.F3c */
  138. if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
  139. if (Src.Mode == Imm) { /* Assume source is a register mask. */
  140. j = 0; /* Flip it since A68k will flip it back again later. */
  141. for (i = 0; i < 16; i++)
  142. if (Src.Value & (1<<i))
  143. j |= (1 << (15-i));
  144. Src.Value = j;
  145. Src.Mode = MultiM;
  146. } else if (Dest.Mode == Imm) {
  147. Dest.Mode = MultiM; /* Assume dest. is a register mask. */
  148. } else {
  149. OpCode[4] = '\0'; /* MOVEM of a single register */
  150. Instructions (OpLoc); /* becomes a straight MOVE. */
  151. }
  152. }
  153. }
  154. if ((Src.Mode == Imm) /* Immediate instructions */
  155. && (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount)
  156. && !NoOpt
  157. && (((EA611 IN AdrModeB) && (Dest.Mode == DReg) /* MOVE */
  158. /* && (Size == Long) && (Src.Value >= -128) && (Src.Value <= 127)) */
  159. && (Size == Long) && (SrcVal >= -128) && (SrcVal <= 127)) /* 2.71.F3l */
  160. || ((EA05y IN AdrModeB) /* ADD/SUB */
  161. && !SrcAddrDiffs /* added by Kevin Kofler in v.2.71.F3e */
  162. && (Src.Value > 0) && (Src.Value <= 8)))) {
  163. strcat (OpCode, "Q"); /* Make it ADDQ/SUBQ/MOVEQ. */
  164. Instructions (OpLoc);
  165. }
  166. else if (!NoOpt && (optim&OPTIM_LEA) && (Dest.Mode == ARDir) && (Src.Mode == ARDisp)
  167. && (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount)
  168. /* bugfix: line added by Kevin Kofler in v.2.71.F3d:
  169. optimize only if it can be optimized in pass 1, else it will not work! */
  170. && !SrcAddrDiffs /* added by Kevin Kofler in v.2.71.F3l */
  171. && (abs(Src.Value) <= 8) && (Src.Value != 0) && (Src.Rn == Dest.Rn)
  172. && !strcasecmp(OpCode, "LEA")) { /* LEA x(An),An */
  173. /* optimization added by Paul Froissart in v.2.71.F3c */
  174. if (Src.Value>0) strcpy (OpCode, "ADDQ");
  175. else { Src.Value = -Src.Value;
  176. strcpy (OpCode, "SUBQ"); } /* make it ADDQ/SUBQ */
  177. Instructions (OpLoc);
  178. Src.Mode = Imm;
  179. }
  180. else if (!NoOpt && (optim&OPTIM_ADDA) && (Dest.Mode == ARDir) && (Src.Mode == Imm)
  181. && ((Size == Word) || ((Src.Hunk == ABSHUNK) && (Src.Defn < LineCount)))
  182. /* bugfix: line added by Kevin Kofler in v.2.71.F3d:
  183. optimize only if it can be optimized in pass 1, else it will not work! */
  184. /* && (abs(Src.Value) > 8) && (abs(Src.Value) <= 32767) */
  185. && (abs(SrcVal) > 8 || SrcAddrDiffs) && (abs(SrcVal) <= 32767)
  186. /* use SrcVal, not Src.Value, use LEA optimization for address differences where
  187. ADDQ/SUBQ optimization is impossible -- Kevin Kofler, v.2.71.F3l */
  188. && (EA05y IN AdrModeB)) { /* ADD or SUB */
  189. /* optimization added by Paul Froissart in v.2.71.F3c */
  190. /* if (OpCode[1]=='S') Src.Value=-Src.Value; */
  191. if (OpCode[0]=='S' || OpCode[0]=='s') {
  192. /* C arrays START WITH ZERO!!! Also, it can be both S and s.
  193. - Kevin Kofler, v.2.71.F3e */
  194. Src.Value=-Src.Value;
  195. /* added by Kevin Kofler in v.2.71.F3l: invert all address differences */
  196. {struct AddrDiff *p=SrcAddrDiffs;
  197. while (p) {
  198. p->phunk^=p->nhunk;p->nhunk^=p->phunk;p->phunk^=p->nhunk;
  199. p->paddr^=p->naddr;p->naddr^=p->paddr;p->paddr^=p->naddr;
  200. p=p->Link;
  201. }
  202. }
  203. }
  204. strcpy (OpCode, "LEA"); /* ADD #x,An x>8 becomes LEA x(An),An */
  205. Instructions (OpLoc);
  206. Src.Mode = ARDisp;
  207. Src.Rn = Dest.Rn; }
  208. else if ((Dest.Mode == ARDir) && (Src.Mode <= 12)
  209. && (((EA05y | EA611) IN AdrModeB) /* ADD, SUB, or MOVE */
  210. || (OpM68C IN AdrModeA))) { /* CMP */
  211. strcat (OpCode, "A"); /* ADD op,An becomes ADDA etc. */
  212. Instructions (OpLoc);
  213. }
  214. else if ((Src.Mode == Imm) /* Immediate instructions */
  215. && ((OpM68D | OpM68C | OpM68X) IN AdrModeA)) {
  216. strcat (OpCode, "I"); /* ADD/AND/OR/SUB, CMP, EOR */
  217. Instructions (OpLoc); /* ADD #op,d becomes ADDI etc. */
  218. }
  219. else if ((Src.Mode == ARPost) && (Dest.Mode == ARPost)
  220. && (OpM68C IN AdrModeA)) { /* CMP */
  221. strcat (OpCode, "M"); /* Generate CMPM if necessary. */
  222. Instructions (OpLoc);
  223. }
  224. /*=================== Operand validation routines ====================*/
  225. if (Pass2) {
  226. /* If an immediate operand isn't absolute, it must be a long word. */
  227. /*if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK))
  228. Error (SrcLoc, RelErr);*/
  229. /* ------- Check for instructions with too many operands. ------- */
  230. /* Some specialized instruction routines contain their own tests. */
  231. if (AdrModeA == 0) { /* Should have only one operand. */
  232. if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) {
  233. if (Dest.Mode != Null)
  234. Error (DestLoc, OperErr);
  235. /* } else if (AdrModeB == 0) { */ /* Should have no operands. */
  236. /* if (Src.Mode != Null)
  237. Error (SrcLoc, OperErr);
  238. if (Dest.Mode != Null)
  239. Error (DestLoc, OperErr); De-activated for now */
  240. }
  241. }
  242. if ((AdrModeA != 0) || (AdrModeB != 0)) {
  243. if(Dest.Mode != NOMODE) { /* We should never find 3 operands. */
  244. j = DestLoc + strlen (DestOp);
  245. if ((Line[j] != '\0')
  246. && (Line[j] != ';')
  247. && (!isspace (Line[j]))) {
  248. Error (j, OperErr);
  249. }
  250. }
  251. /* ---------------- Check for missing operands. ----------------- */
  252. if (Src.Mode == Null) {
  253. Error (OpLoc+strlen(OpCode), OperErr); /* No source */
  254. } else if (Dest.Mode == Null) {
  255. if (((ImmMode & AdrModeB) == ImmMode)
  256. || (TwoOpsA IN AdrModeA)
  257. || (TwoOpsB IN AdrModeB)) {
  258. Error (SrcLoc+strlen(SrcOp), OperErr); /* No dest. */
  259. }
  260. }
  261. }
  262. }
  263. /*====================================================================*/
  264. /* ---------------- Decrement and Branch (DBcc) ----------------- */
  265. if (DecBr IN AdrModeA) {
  266. if (Pass2) {
  267. if (Src.Mode != DReg)
  268. Error (SrcLoc, ModeErr);
  269. if (Dest.Value & 1)
  270. Error (DestLoc, AlignErr); /* Boundary alignment error */
  271. /* if (Dest.Hunk == CurrHunk) { */
  272. if (Dest.Hunk == CurrHunk && !AllRelocs) {
  273. /* Always let the linker worry about it in all-reloc mode
  274. -- Kevin Kofler, v.2.71.F3l */
  275. ObjSrc = Dest.Value-AddrCnt-2; /* Relative branch distance */
  276. Dest.Hunk = ABSHUNK; /* Displacement is absolute */
  277. } else
  278. ObjSrc = Dest.Value; /* Let the linker worry about it. */
  279. /* In all-reloc mode, we need to compute the distance here.
  280. -- Kevin Kofler, v.2.71.F3o */
  281. if ((AllRelocs && Dest.Hunk == CurrHunk) ?
  282. ((ObjSrc-AddrCnt-2 > 32767) || (ObjSrc-AddrCnt-2 < -32768)) :
  283. ((ObjSrc > 32767) || (ObjSrc < -32768)))
  284. /* if ((ObjSrc > 32767) || (ObjSrc < -32768))*/
  285. Error (DestLoc,BraErr); /* Too far to branch */
  286. /*if (Dest.Hunk!=CurrHunk) { */ /* DBcc to another section */
  287. if (Dest.Hunk!=CurrHunk || AllRelocs) { /* DBcc to another section
  288. or -a given -- Kevin Kofler, v.2.71.F3l */
  289. templong = AddrCnt + 2; /* 16-bit relocatable */
  290. PutRel (templong, Dest.Hunk, 2, 1);
  291. }
  292. ObjOp = Op | Src.Rn;
  293. /* Emit destination address diffs -- Kevin Kofler, v.2.71.F3l */
  294. AddrDiffs=DestAddrDiffs;
  295. templong = AddrCnt + 2; /* 16-bit relocatable */
  296. EmitAddrDiffs(templong, 2);
  297. DestAddrDiffs=0;
  298. }
  299. /* Get rid of leftover AddrDiffs lists -- Kevin Kofler, v.2.71.F3l */
  300. while (SrcAddrDiffs) {
  301. struct AddrDiff *next=SrcAddrDiffs->Link;
  302. free(SrcAddrDiffs);
  303. SrcAddrDiffs=next;
  304. }
  305. while (DestAddrDiffs) {
  306. struct AddrDiff *next=DestAddrDiffs->Link;
  307. free(DestAddrDiffs);
  308. DestAddrDiffs=next;
  309. }
  310. AddrAdv = 4;
  311. nO = nS = 2;
  312. return;
  313. }
  314. /* ------------ Branch (Bcc, including BRA and BSR) ------------- */
  315. if (Brnch IN AdrModeA) {
  316. if (Src.Value & 1)
  317. Error (SrcLoc, AlignErr); /* Boundary alignment error */
  318. /* if (!Pass2 && !NoOpt && (Size != Byte)) { */
  319. /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3b: */
  320. if (!Pass2 && !NoOpt && noExplicitSize && (Size != Byte)) {
  321. /* optimize only if no explicit size was given! */
  322. if ((Src.Defn < LineCount) /* Backward branch */
  323. && (Src.Hunk == CurrHunk)) {
  324. ObjSrc = Src.Value-AddrCnt-2; /* Relative branch distance */
  325. /*Src.Hunk = ABSHUNK;*/ /* Displacement is absolute.
  326. -- no, actually it sometimes isn't (all-relocs mode); if it is,
  327. that's handled by the code below. -- Kevin Kofler, v.2.71.F3q */
  328. if ((ObjSrc != 0) && (ObjSrc >= -128) && (ObjSrc <= 127)) {
  329. Size = Byte; /* Convert to a short branch. */
  330. if ((char *) FwdLim2 >= ((char *) FwdCurr + FWDSIZE)) {
  331. FwdCurr->Link = /* Get a new chunk. */
  332. (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  333. if (FwdCurr->Link == NULL)
  334. {/* Get rid of leftover AddrDiffs lists -- Kevin Kofler, v.2.71.F3l */
  335. while (SrcAddrDiffs) {
  336. struct AddrDiff *next=SrcAddrDiffs->Link;
  337. free(SrcAddrDiffs);
  338. SrcAddrDiffs=next;
  339. }
  340. while (DestAddrDiffs) {
  341. struct AddrDiff *next=DestAddrDiffs->Link;
  342. free(DestAddrDiffs);
  343. DestAddrDiffs=next;
  344. }
  345. quit_cleanup ("Out of memory!\n");
  346. }
  347. FwdCurr = FwdCurr->Link;
  348. FwdCurr->Link = NULL;
  349. FwdLim2 = (int *)
  350. ((char *) FwdCurr + sizeof (struct FwdTable *));
  351. }
  352. *FwdLim2++ = LineCount; /* Flag branch in pass 2. */
  353. }
  354. } else if (Src.Single && (Src.Defn == NODEF)) { /* Forward */
  355. if (!ReadSymTab (SrcOp)) {
  356. /* Store candidate target. */
  357. AddSymTab (SrcOp, 0L, (long)ABSHUNK, NODEF, 0);
  358. }
  359. PackFwdBranch (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Drop expired entries. */
  360. FwdLim1->Loc = AddrCnt; /* Location of candidate */
  361. FwdLim1->FwdSym = Sym; /* Symbol table entry for target */
  362. FwdLim1->Line = LineCount; /* Line number */
  363. FwdLim1++;
  364. }
  365. }
  366. /* if (Pass2 && !NoOpt && (Size != Byte)) { */ /* Pass 2 */
  367. /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3b: */
  368. if (Pass2 && !NoOpt && noExplicitSize && (Size != Byte)) { /* Pass 2 */
  369. /* optimize only if no explicit size was given! */
  370. FwdCurr = FwdStart; /* Scan the entire foward branch table. */
  371. FwdPtr = (int *) ((char *) FwdCurr + sizeof (struct FwdTable *));
  372. while (FwdPtr != FwdLim2) {
  373. if (*FwdPtr == LineCount) { /* We flagged it in pass 1. */
  374. Size = Byte; /* Make it a short branch */
  375. break;
  376. } else {
  377. FwdPtr++; /* Scan forward in table. */
  378. if (FwdPtr == FwdLim2) {
  379. break;
  380. }
  381. if ((char *) FwdPtr >= ((char *) FwdCurr + FWDSIZE)) {
  382. FwdCurr = FwdCurr->Link; /* Next chunk */
  383. FwdPtr = (int *)
  384. ((char *) FwdCurr + sizeof (struct FwdTable *));
  385. }
  386. }
  387. }
  388. }
  389. /* if (Src.Hunk == CurrHunk) { */
  390. if (Src.Hunk == CurrHunk && !AllRelocs) {
  391. /* Always let the linker worry about it in all-reloc mode
  392. -- Kevin Kofler, v.2.71.F3l */
  393. ObjSrc=Src.Value-AddrCnt-2; /* Relative branch distance */
  394. Src.Hunk = ABSHUNK; /* Displacement is absolute. */
  395. if ((Size == Byte) && (ObjSrc == 0))
  396. Error (SrcLoc, BccSDsp0); /* Can't do this! */
  397. /* if (Pass2 && FwdProc && (Size != Byte)
  398. && (ObjSrc >= -128) && (ObjSrc <= 129) && (ObjSrc != 2)) */
  399. /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3b: */
  400. if (Pass2 && FwdProc && (Size != Byte)
  401. && (ObjSrc >= -128) && (ObjSrc <= 129) && (ObjSrc != 2)
  402. && noExplicitSize)
  403. /* flag only if no explicit size was given! */
  404. FwdShort=TRUE; /* Forward reference could be made short. */
  405. } else {
  406. ObjSrc = Src.Value; /* Let the linker worry about it. */
  407. /* disabled by Kevin Kofler in v.2.71.F3l: */
  408. /* if (Size == Byte)
  409. Error (SrcLoc, BraErr);*/ /* No external short branches! */
  410. /* added by Kevin Kofler in v.2.71.F3l: */
  411. if (Size == Byte)
  412. ObjSrc--; /* The branch offset is relative to the byte FOLLOWING
  413. this one, so adjust the offset. */
  414. /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3b: */
  415. if (Src.Hunk != CurrHunk /* bugfix by Kevin Kofler in v.2.71.F3n */
  416. && SrcOp[0] == '\\')
  417. Error (SrcLoc, Undef); /* No external references to local labels! */
  418. }
  419. if (Size != Byte) {
  420. InstSize = 4;
  421. nS = 2;
  422. templong = 32767;
  423. } else {
  424. InstSize = 2;
  425. Op |= (ObjSrc & 0x00FF);
  426. templong = 127;
  427. /* added by Kevin Kofler in v.2.71.F3q: adjust the offset back for the range
  428. checking below */
  429. if (Src.Hunk != CurrHunk || AllRelocs)
  430. ObjSrc++;
  431. }
  432. /* In all-reloc mode, we need to compute the distance here.
  433. -- Kevin Kofler, v.2.71.F3o */
  434. if ((AllRelocs && Src.Hunk == CurrHunk) ?
  435. ((ObjSrc-AddrCnt-2 > templong) || (ObjSrc-AddrCnt-2 < -templong-1)) :
  436. ((ObjSrc > templong) || (ObjSrc < -templong-1)))
  437. /* bugfix by Kevin Kofler in v.2.71.F3l (the new fix above is cleaner):
  438. if ((Src.Hunk == CurrHunk) && ((Src.Value-AddrCnt-2 > templong)
  439. || (Src.Value-AddrCnt-2 < -templong-1))) */
  440. /* if ((ObjSrc > templong) || (ObjSrc < -templong-1))*/
  441. Error (SrcLoc, BraErr); /* Too far to branch */
  442. if (Dest.Mode != Null)
  443. Error (DestLoc, OperErr); /* No Destination operand! */
  444. AddrAdv = InstSize;
  445. ObjOp = Op;
  446. nO = 2;
  447. /* if (Src.Hunk != CurrHunk) { */ /* Bcc to another section, or external */
  448. if (Src.Hunk != CurrHunk || AllRelocs) { /* Bcc to another section, or
  449. external, or -a given -- Kevin Kofler, v.2.71.F3l */
  450. if (GlobalXREF && Pass2 && Src.Defn == NODEF && ReadSymTab (SrcOp))
  451. Src.Hunk = Sym->Hunk;
  452. if (Size != Byte) { /* support for 8-bit relocs added by Kevin Kofler,
  453. v.2.71.F3l */
  454. templong = AddrCnt + 2; /* 16-bit relocatable */
  455. /* Mark explicit word branches unoptimizable -- Kevin Kofler, v.2.71.F3t */
  456. if (!noExplicitSize) templong |= UNOPTIMIZABLE;
  457. PutRel (templong, Src.Hunk, 2, 1);
  458. /* Emit source address diffs -- Kevin Kofler, v.2.71.F3l */
  459. AddrDiffs=SrcAddrDiffs;
  460. EmitAddrDiffs(templong, 2);
  461. SrcAddrDiffs=0;
  462. } else { /* short branch -> 8-bit reloc */
  463. templong = AddrCnt + 1; /* 8-bit relocatable */
  464. PutRel (templong, Src.Hunk, 1, 1);
  465. /* Emit source address diffs -- Kevin Kofler, v.2.71.F3l */
  466. AddrDiffs=SrcAddrDiffs;
  467. EmitAddrDiffs(templong, 1);
  468. SrcAddrDiffs=0;
  469. }
  470. }
  471. /* Get rid of leftover AddrDiffs lists -- Kevin Kofler, v.2.71.F3l */
  472. while (SrcAddrDiffs) {
  473. struct AddrDiff *next=SrcAddrDiffs->Link;
  474. free(SrcAddrDiffs);
  475. SrcAddrDiffs=next;
  476. }
  477. while (DestAddrDiffs) {
  478. struct AddrDiff *next=DestAddrDiffs->Link;
  479. free(DestAddrDiffs);
  480. DestAddrDiffs=next;
  481. }
  482. return;
  483. }
  484. /* --------------- JSR.S and JMP.S are not valid! --------------- */
  485. if (((Op == JMP) || (Op == JSR)) && (Size == Byte))
  486. Error (OpLoc + 4, SizeErr);
  487. /* Uses information from Instructions & GetOperand (among others) */
  488. /* to complete calculation of Object Code. */
  489. /* Op, AdrModeA, AdrModeB, Size, and Src & Dest records are all */
  490. /* Global variables imported from the SyntaxAnalyzer MODULE. */
  491. ExtL = 0;
  492. quick = FALSE;
  493. /* Ignore size specification on BCHG, BCLR, BSET, and BTST. */
  494. if (Bit811 IN AdrModeB)
  495. Size = Word;
  496. /* ------------ Check for boundary alignment errors. ------------ */
  497. /* BCHG, BCLR, BSET, BTST, LEA, NBCD, PEA, Scc, TAS are exempt. */
  498. if (Pass2) {
  499. if ((Size != Byte)
  500. && (Op != LEA)
  501. && (Op != PEA)
  502. && !((AdrModeA == 0) && (AdrModeB == 0))
  503. && !(AdrModeB & EA05c) /* BTST */
  504. && !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) {
  505. if (Src.Value & 1)
  506. /* if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX))
  507. Error (SrcLoc, AlignErr);
  508. if (Dest.Value & 1)
  509. if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX))
  510. Error (DestLoc, AlignErr); */
  511. if ((Src.Mode >= AbsW) && (Src.Mode <= PCDisp))
  512. Error (SrcLoc, AlignErr);
  513. if (Dest.Value & 1)
  514. if ((Dest.Mode >= AbsW) && (Dest.Mode <= PCDisp))
  515. Error (DestLoc, AlignErr);
  516. /* An odd displacement does NOT mean that the resulting address is odd!!!
  517. Odd displacements are still flagged as errors for PC+displacement (but
  518. NOT PC+displacement+index), since PC is always even.
  519. Bugfix by Julien Muchembled -- committed in v.2.71.F3a */
  520. }
  521. /* Check for special cases first */
  522. if (Op == STOP) {
  523. if (Src.Mode != Imm)
  524. Error (SrcLoc, ModeErr);
  525. if (Dest.Mode != Null)
  526. Error (DestLoc, OperErr);
  527. }
  528. if (Op == LINK) {
  529. Op |= Src.Rn;
  530. if (Src.Mode != ARDir)
  531. Error (SrcLoc, ModeErr);
  532. if (Dest.Mode != Imm)
  533. Error (DestLoc, ModeErr);
  534. else if (Dest.Value & 1)
  535. Error (DestLoc, AlignErr); /* Boundary alignment error */
  536. }
  537. if (Op == SWAP) {
  538. if (!(EA05f IN AdrModeB)) { /* Ignore if PEA instruction. */
  539. Op |= Src.Rn;
  540. if (Src.Mode != DReg)
  541. Error (SrcLoc, ModeErr);
  542. if (Dest.Mode != Null)
  543. Error (DestLoc, OperErr);
  544. }
  545. }
  546. if (Op == UNLK) {
  547. Op |= Src.Rn;
  548. if (Src.Mode != ARDir)
  549. Error (SrcLoc, ModeErr);
  550. if (Dest.Mode != Null)
  551. Error (DestLoc, OperErr);
  552. }
  553. /* Now do generalized address modes */
  554. if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) { /* Two registers */
  555. if (Op == CMPM) { /* Special routine for CMPM */
  556. Op |= Src.Rn | (Dest.Rn << 9);
  557. if (Src.Mode != ARPost)
  558. Error (SrcLoc, ModeErr);
  559. if (Dest.Mode != ARPost)
  560. Error (DestLoc, ModeErr);
  561. } else { /* Other two-register instructions */
  562. Op |= Src.Rn | (Dest.Rn << 9);
  563. if (RegMem3 IN AdrModeA) {
  564. if (Src.Mode == DReg) {
  565. if (Dest.Mode != DReg)
  566. Error (DestLoc, ModeErr);
  567. } else if (Src.Mode == ARPre) {
  568. Op |= 0x0008;
  569. if (Dest.Mode != ARPre)
  570. Error (DestLoc, ModeErr);
  571. } else
  572. Error (SrcLoc, OperErr);
  573. } else {
  574. if (Src.Mode == ARPost)
  575. if (Dest.Mode != ARPost)
  576. Error (DestLoc, ModeErr);
  577. else
  578. Error (SrcLoc, OperErr);
  579. }
  580. }
  581. }
  582. }
  583. if (Data911 IN AdrModeA) { /* Data in 9-11 (ADDQ/SUBQ) */
  584. quick = TRUE;
  585. if (Src.Mode == Imm)
  586. if ((Src.Value > 0) && (Src.Value <= 8)) {
  587. if (Src.Value < 8) /* Data of 8 is coded as 000. */
  588. Op |= Src.Value << 9;
  589. } else
  590. Error (SrcLoc, SizeErr);
  591. else
  592. Error (SrcLoc, ModeErr);
  593. /* Address diffs not allowed here -- Kevin Kofler, v.2.71.F3l */
  594. if (SrcAddrDiffs) Error (SrcLoc, RelErr);
  595. }
  596. if (CntR911 IN AdrModeA) { /* Only Shift and Rotate use this. */
  597. if (Dest.Mode == DReg) {
  598. Op = (Op & 0xF9FF) | Dest.Rn;
  599. if (Size == Word) Op |= 0x0040;
  600. if (Size == Long) Op |= 0x0080;
  601. if (Src.Mode == DReg)
  602. Op |= 0x0020 | (Src.Rn << 9);
  603. else if (Src.Mode == Imm) {
  604. quick = TRUE;
  605. if ((Src.Value > 0) && (Src.Value <= 8)) { /* Range check */
  606. if (Src.Value < 8) /* Data of 8 is coded as 000. */
  607. Op |= (Src.Value << 9);
  608. } else
  609. Error (SrcLoc, SizeErr);
  610. } else
  611. Error (SrcLoc, OperErr);
  612. /* Address diffs not allowed here -- Kevin Kofler, v.2.71.F3l */
  613. if (SrcAddrDiffs) Error (SrcLoc, RelErr);
  614. } else if (Dest.Mode == Null) {
  615. Op = (Op & 0xFFE7) | 0x00C0;
  616. EffAdr (&Src, (mea | aea));
  617. } else
  618. Error (SrcLoc, ModeErr);
  619. }
  620. if (Data03 IN AdrModeA) { /* TRAP Vector in 0-3 */
  621. quick = TRUE;
  622. if (Src.Mode == Imm)
  623. if ((Src.Value >= 0) && (Src.Value < 16))
  624. Op |= Src.Value;
  625. else
  626. Error (SrcLoc, SizeErr);
  627. else
  628. Error (SrcLoc, ModeErr);
  629. /* Address diffs not allowed here -- Kevin Kofler, v.2.71.F3l */
  630. if (SrcAddrDiffs) Error (SrcLoc, RelErr);
  631. if (Dest.Mode != Null)
  632. Error (DestLoc, OperErr);
  633. }
  634. if (Data07 IN AdrModeA) { /* Data in 0-7 (MOVEQ) */
  635. quick = TRUE;
  636. Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
  637. /* Emit source address diffs -- Kevin Kofler, v.2.71.F3l */
  638. templong = AddrCnt + 1; /* 8-bit absolute */
  639. AddrDiffs=SrcAddrDiffs;
  640. EmitAddrDiffs(templong, 1);
  641. SrcAddrDiffs=0;
  642. if (Src.Mode != Imm)
  643. Error (SrcLoc, ModeErr);
  644. else if (Dest.Mode != DReg)
  645. Error (DestLoc, ModeErr);
  646. /* else if ((Src.Value < -128) || (Src.Value > 127)) */
  647. else if ((SrcVal < -128) || (SrcVal > 127))
  648. Error (SrcLoc, SizeErr);
  649. /* use SrcVal, not Src.Value -- Kevin Kofler, v.2.71.F3l */
  650. }
  651. if (Pass2) {
  652. if (OpM68D IN AdrModeA) { /* DReg in 6-8 (ADD/AND/OR/SUB) */
  653. if (Dest.Mode == DReg) {
  654. Op |= (Dest.Rn << 9);
  655. if ((Src.Mode == ARDir) && (Size == Byte))
  656. Error (SrcLoc, SizeErr);
  657. } else /* Assume Src.Mode = DReg -- errors are trapped elsewhere. */
  658. Op |= (Src.Rn << 9) | 0x0100;
  659. if (Size == Word) Op |= 0x0040;
  660. if (Size == Long) Op |= 0x0080;
  661. }
  662. if (OpM68A IN AdrModeA) { /* AReg in 6-8 (ADDA/CMPA/SUBA) */
  663. if (Dest.Mode == ARDir)
  664. Op |= (Dest.Rn << 9);
  665. else
  666. Error (DestLoc, ModeErr);
  667. if (Size == Byte) Error (OpLoc+5, SizeErr);
  668. if (Size == Word) Op |= 0x00C0;
  669. if (Size == Long) Op |= 0x01C0;
  670. }
  671. if (OpM68C IN AdrModeA) { /* CMP (Compare) */
  672. if (Dest.Mode == DReg)
  673. Op |= (Dest.Rn << 9);
  674. else
  675. Error (DestLoc, ModeErr);
  676. if (Size == Byte) {
  677. if (Src.Mode == ARDir)
  678. Error (OpLoc+4, SizeErr);
  679. }
  680. if (Size == Word) Op |= 0x0040;
  681. if (Size == Long) Op |= 0x0080;
  682. }
  683. if (OpM68X IN AdrModeA) { /* EOR (Exclusive or) */
  684. if (Src.Mode == DReg)
  685. Op |= (Src.Rn << 9);
  686. else
  687. Error (SrcLoc, ModeErr);
  688. if (Size == Byte) Op |= 0x0100;
  689. if (Size == Word) Op |= 0x0140;
  690. if (Size == Long) Op |= 0x0180;
  691. }
  692. if (OpM68S IN AdrModeA) { /* EXT (Sign extension) */
  693. if (Src.Mode == DReg)
  694. Op |= Src.Rn;
  695. else
  696. Error (SrcLoc, ModeErr);
  697. if (Dest.Mode != Null)
  698. Error (DestLoc, OperErr);
  699. if (Size == Byte) Error (OpLoc+4, SizeErr);
  700. if (Size == Word) Op |= 0x0080;
  701. if (Size == Long) Op |= 0x00C0;
  702. }
  703. if (OpM68R IN AdrModeA) { /* MOVEP (Register/memory) */
  704. if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) {
  705. if (Size == Byte) Error (OpLoc+6, SizeErr);
  706. if (Size == Word) Op |= 0x0180;
  707. if (Size == Long) Op |= 0x01C0;
  708. Op |= (Src.Rn << 9) | Dest.Rn;
  709. } else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) {
  710. if (Size == Byte) Error (OpLoc+6, SizeErr);
  711. if (Size == Word) Op |= 0x0100;
  712. if (Size == Long) Op |= 0x0140;
  713. Op |= Src.Rn | (Dest.Rn << 9);
  714. } else
  715. Error (SrcLoc, ModeErr);
  716. }
  717. if (OpM37 IN AdrModeA) { /* EXG (Exchange registers) */
  718. if ((Src.Mode == DReg) && (Dest.Mode == DReg))
  719. Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
  720. else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir))
  721. Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
  722. else if ((Src.Mode == ARDir) && (Dest.Mode == DReg))
  723. Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn;
  724. else if ((Src.Mode == DReg) && (Dest.Mode == ARDir))
  725. Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
  726. else
  727. Error (SrcLoc, ModeErr);
  728. }
  729. if (Bit811 IN AdrModeB) { /* Bit operations using bits 8-11 */
  730. if (Src.Mode == DReg)
  731. Op |= 0x0100 | (Src.Rn << 9);
  732. else if (Src.Mode == Imm)
  733. Op |= 0x0800;
  734. else
  735. Error (SrcLoc, ModeErr);
  736. }
  737. if (Size67 IN AdrModeB) { /* Size in bits 6-7 */
  738. /* if (Size == Byte) ; No action -- bits are already zero. */
  739. if (Size == Word) Op |= 0x0040;
  740. if (Size == Long) Op |= 0x0080;
  741. }
  742. if (Size6 IN AdrModeB) { /* Size in bit 6 (MOVEM) */
  743. if (Size == Byte) Error (OpLoc+6, SizeErr);
  744. /* if (Size == Word) ; No action -- bit is already zero. */
  745. if (Size == Long) Op |= 0x0040;
  746. }
  747. if (Sz1213A IN AdrModeB) { /* Size in 12-13 (MOVE) */
  748. if (Size == Byte) Op |= 0x1000;
  749. if (Size == Word) Op |= 0x3000;
  750. if (Size == Long) Op |= 0x2000;
  751. }
  752. if (Sz1213 IN AdrModeB) { /* Size in 12-13 (MOVEA) */
  753. if (Dest.Mode == DReg) /* Can't be to adata register! */
  754. Error(DestLoc,ModeErr); /* (Others are caught elsewhere). */
  755. Op |= (Dest.Rn << 9);
  756. if (Size == Byte) Error (OpLoc+6, SizeErr);
  757. if (Size == Word) Op |= 0x3000;
  758. if (Size == Long) Op |= 0x2000;
  759. }
  760. if (EA05a IN AdrModeB) /* Effective address - all */
  761. if ((Dest.Mode == DReg) || (Dest.Mode == ARDir))
  762. EffAdr (&Src, ea);
  763. else
  764. Error (DestLoc, ModeErr);
  765. if (EA05b IN AdrModeB) /* Eff. Addr. - all except ARDir */
  766. if (Dest.Mode == DReg) {
  767. EffAdr (&Src, dea);
  768. Op |= (Dest.Rn << 9);
  769. } else
  770. Error (DestLoc, ModeErr);
  771. if (EA05c IN AdrModeB) /* BTST */
  772. if (Src.Mode == DReg)
  773. EffAdr (&Dest, 0x0002); /* All but ARDir */
  774. else
  775. EffAdr (&Dest, 0x0802); /* All but ARDir/Imm */
  776. if(EA05d IN AdrModeB) { /* All but PC relative & immediate */
  777. EffAdr (&Dest, aea);
  778. if ((Dest.Mode == ARDir) && (Size == Byte))
  779. Error (OpLoc+5, SizeErr);
  780. }
  781. if(EA05e IN AdrModeB) { /* All but ARDir, PC relative, Imm */
  782. if (Dest.Mode == Null)
  783. EffAdr (&Src, (dea | aea));
  784. else if (Src.Mode == Imm)
  785. EffAdr (&Dest, (dea | aea));
  786. else if (Src.Mode == DReg) {
  787. if (AdrModeB == (Size67 | EA05e | Exten))
  788. Error (SrcLoc, ModeErr);
  789. EffAdr (&Dest, (dea | aea));
  790. } else
  791. Error (SrcLoc, ModeErr);
  792. }
  793. if (EA05f IN AdrModeB) { /* JMP, JSR, LEA, and PEA */
  794. EffAdr (&Src, cea);
  795. if (Rx911 IN AdrModeA)
  796. if (Dest.Mode == ARDir)
  797. Op |= (Dest.Rn << 9); /* Address Reg. for LEA */
  798. else
  799. Error(DestLoc,ModeErr); /* Must load Address Reg. */
  800. else
  801. if (Dest.Mode != Null)
  802. Error (DestLoc, OperErr); /* No Dest. unless LEA */
  803. }
  804. if (EA05x IN AdrModeB) { /* AND and OR */
  805. if (Dest.Mode == DReg)
  806. EffAdr (&Src, dea);
  807. else if (Src.Mode == DReg)
  808. EffAdr (&Dest, mea | aea);
  809. else
  810. Error (SrcLoc, OperErr);
  811. }
  812. if (EA05y IN AdrModeB) { /* ADD and SUB */
  813. if (Dest.Mode == DReg) {
  814. EffAdr (&Src, ea);
  815. if ((Src.Mode == ARDir) && (Size == Byte))
  816. Error (OpLoc+4, SizeErr);
  817. } else if (Src.Mode == DReg)
  818. EffAdr (&Dest, (mea | aea));
  819. else
  820. Error (SrcLoc, ModeErr);
  821. }
  822. }
  823. if (EA05z IN AdrModeB) { /* MOVEM */
  824. if (Pass2) {
  825. if (Src.Mode == MultiM) { /* Move to memory. */
  826. EffAdr (&Dest, (mea | aea | 0x0008));
  827. ExtL = Src.Value;
  828. i = (Dest.Mode == ARPre); /* ExtL flip indicator */
  829. } else if (Dest.Mode == MultiM) { /* Move from memory. */
  830. Op |= 0x0400; /* Set direction. */
  831. EffAdr (&Src, (mea | 0x0810));
  832. ExtL = Dest.Value;
  833. i = (Src.Mode == ARPre);
  834. } else {
  835. Error (SrcLoc, OperErr);
  836. i = FALSE;
  837. }
  838. if (i) { /* Flip ExtL if ARPre. */
  839. j = 0;
  840. for (i = 0; i < 8; i++)
  841. j |= (ExtL & (1<<i)) << (15-i*2);
  842. for (i = 8; i < 16; i++)
  843. j |= (ExtL & (1<<i)) >> (i*2-15);
  844. ExtL = j;
  845. }
  846. }
  847. nO += 2; /* Extension is part of OpCode. */
  848. InstSize += 2;
  849. }
  850. if (Pass2) {
  851. if (EA611 IN AdrModeB) { /* Eff. Addr. in 6-11 (MOVE) */
  852. if (Dest.Mode == CCR) { /* MOVE to CCR */
  853. Op = 0x44C0;
  854. EffAdr (&Src, dea);
  855. } else if (Dest.Mode == SR) { /* MOVE to SR */
  856. Op = 0x46C0;
  857. EffAdr (&Src, dea);
  858. } else if (Src.Mode == SR) { /* MOVE from SR */
  859. Op = 0x40C0;
  860. EffAdr (&Dest, dea | aea);
  861. } else if (Dest.Mode == USP) { /* MOVE to USP */
  862. Op = 0x4E60;
  863. if (Src.Mode == ARDir)
  864. Op |= Src.Rn;
  865. else
  866. Error (SrcLoc, ModeErr);
  867. } else if (Src.Mode == USP) { /* MOVE from USP */
  868. Op = 0x4E68;
  869. if (Dest.Mode == ARDir)
  870. Op |= Dest.Rn;
  871. else
  872. Error (DestLoc, ModeErr);
  873. } else { /* General MOVE instruction */
  874. EffAdr (&Src, (ea | xxx));
  875. if ((Size == Byte) && (Src.Mode == ARDir))
  876. Error (SrcLoc, SizeErr);
  877. if (Src.Mode > 12)
  878. Error (SrcLoc, ModeErr);
  879. if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12))
  880. Error (DestLoc, ModeErr);
  881. else if (Dest.Mode < 8) /* Register direct or indirect */
  882. Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn << 9);
  883. else /* Absolute, PC relative, or immediate */
  884. Op |= 0x01C0 | ((Dest.Mode - 8) << 9);
  885. OperExt (&Dest); /* Set up extension word. */
  886. }
  887. }
  888. if ((Dest.Mode == CCR) && (Src.Mode == Imm)) {
  889. if ((Size67 IN AdrModeB)
  890. && (EA05e IN AdrModeB)
  891. && (Exten IN AdrModeB))
  892. if (0x0400 IN Op) /* not ANDI/EORI/ORI */
  893. Error (DestLoc, ModeErr);
  894. else
  895. Op = (Op & 0xFF00) | 0x003C;
  896. }
  897. if ((Dest.Mode == SR) && (Src.Mode == Imm)) {
  898. if ((Size67 IN AdrModeB)
  899. && (EA05e IN AdrModeB)
  900. && (Exten IN AdrModeB))
  901. if (0x0400 IN Op) /* not ANDI/EORI/ORI */
  902. Error (DestLoc, ModeErr);
  903. else
  904. Op = (Op & 0xFF00) | 0x007C;
  905. }
  906. }
  907. ObjOp = Op;
  908. InstSize += 2;
  909. nO += 2;
  910. if (nO > 2) {
  911. templong = ExtL; /* Add extension word. */
  912. ObjOp = (ObjOp << 16) | (templong & 0x0000FFFFL);
  913. }
  914. if ((AdrModeA != 0) || (AdrModeB != 0)) {
  915. InstSize += (nS = GetInstModeSize (Src.Mode));
  916. ObjSrc = Src.Value;
  917. if ((Src.Mode == Imm) && (Size == Byte))
  918. ObjSrc &= 0xFF; /* Pad a byte value with zeros. */
  919. InstSize += (nD = GetInstModeSize (Dest.Mode));
  920. ObjDest = Dest.Value;
  921. }
  922. if (quick) {
  923. InstSize -= nS; /* Source operand is in Op. */
  924. nS = 0;
  925. }
  926. if (Pass2) {
  927. if (nS!=0) { /* Emit address diffs even when SrcOp is absolute.
  928. -- Kevin Kofler, v.2.71.F3l */
  929. /* if ((nS!=0) && (Src.Hunk!=ABSHUNK)) {*/ /* SrcOp is relocatable. */
  930. /* In global XREF mode, we need to handle ABSHUNK with NODEF properly.
  931. -- Kevin Kofler, v.2.71.F3t */
  932. if (GlobalXREF && Src.Defn == NODEF && Src.Hunk == ABSHUNK && ReadSymTab (SrcOp))
  933. Src.Hunk = Sym->Hunk;
  934. if ((Src.Mode == AbsL)
  935. || (Src.Mode == AbsW)
  936. || (Src.Mode == ARDisp)
  937. || (Src.Mode == PCDisp)
  938. || (Src.Mode == Imm)) {
  939. templong = AddrCnt+nO; /* 32- or 16-bit relocatable */
  940. /* Handle unoptimizable operands. -- Kevin Kofler, v.2.71.F3t */
  941. if (Src.Unopt) templong |= UNOPTIMIZABLE;
  942. if (Src.Hunk!=ABSHUNK) /* added by Kevin Kofler in v.2.71.F3l */
  943. PutRel (templong, Src.Hunk, nS, Src.Mode == PCDisp);
  944. /* Emit source address diffs -- Kevin Kofler, v.2.71.F3l */
  945. AddrDiffs=SrcAddrDiffs;
  946. EmitAddrDiffs(templong, nS);
  947. SrcAddrDiffs=0;
  948. }
  949. if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
  950. templong = AddrCnt + nO + 1; /* 8-bit relocatable */
  951. /* 8-bit sources are not optimizable. -- Kevin Kofler, v.2.71.F3s */
  952. templong |= UNOPTIMIZABLE;
  953. if (Src.Hunk!=ABSHUNK) /* added by Kevin Kofler in v.2.71.F3l */
  954. PutRel (templong, Src.Hunk, 1, Src.Mode == PCDisX);
  955. /* Emit source address diffs -- Kevin Kofler, v.2.71.F3l */
  956. AddrDiffs=SrcAddrDiffs;
  957. EmitAddrDiffs(templong, 1);
  958. SrcAddrDiffs=0;
  959. }
  960. }
  961. if (nD!=0) { /* Emit address diffs even when DestOp is absolute.
  962. -- Kevin Kofler, v.2.71.F3l */
  963. /* if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) {*/ /* DestOp is relocatable. */
  964. /* In global XREF mode, we need to handle ABSHUNK with NODEF properly.
  965. -- Kevin Kofler, v.2.71.F3t */
  966. if (GlobalXREF && Dest.Defn == NODEF && Dest.Hunk == ABSHUNK && ReadSymTab (DestOp))
  967. Dest.Hunk = Sym->Hunk;
  968. if ((Dest.Mode == AbsL)
  969. || (Dest.Mode == AbsW)
  970. || (Dest.Mode == ARDisp)
  971. || (Dest.Mode == PCDisp)
  972. || (Dest.Mode == Imm)) {
  973. templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */
  974. /* Destinations are not optimizable. -- Kevin Kofler, v.2.71.F3s */
  975. templong |= UNOPTIMIZABLE;
  976. if (Dest.Hunk!=ABSHUNK) /* added by Kevin Kofler in v.2.71.F3l */
  977. PutRel (templong, Dest.Hunk, nD, Src.Mode == PCDisp);
  978. /* Emit destination address diffs -- Kevin Kofler, v.2.71.F3l */
  979. AddrDiffs=DestAddrDiffs;
  980. EmitAddrDiffs(templong, nD);
  981. DestAddrDiffs=0;
  982. }
  983. if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) {
  984. templong = AddrCnt+nO+nS+1; /* 8-bit relocatable */
  985. /* Destinations are not optimizable. -- Kevin Kofler, v.2.71.F3s */
  986. templong |= UNOPTIMIZABLE;
  987. if (Dest.Hunk!=ABSHUNK) /* added by Kevin Kofler in v.2.71.F3l */
  988. PutRel (templong, Dest.Hunk, 1, Src.Mode == PCDisX);
  989. /* Emit destination address diffs -- Kevin Kofler, v.2.71.F3l */
  990. AddrDiffs=DestAddrDiffs;
  991. EmitAddrDiffs(templong, 1);
  992. DestAddrDiffs=0;
  993. }
  994. }
  995. }
  996. AddrAdv = InstSize;
  997. /* Get rid of leftover AddrDiffs lists -- Kevin Kofler, v.2.71.F3l */
  998. while (SrcAddrDiffs) {
  999. struct AddrDiff *next=SrcAddrDiffs->Link;
  1000. free(SrcAddrDiffs);
  1001. SrcAddrDiffs=next;
  1002. }
  1003. while (DestAddrDiffs) {
  1004. struct AddrDiff *next=DestAddrDiffs->Link;
  1005. free(DestAddrDiffs);
  1006. DestAddrDiffs=next;
  1007. }
  1008. }
  1009. void PackFwdBranch (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  1010. /* Drops expired entries (more than 128 bytes old)
  1011. from the forward branch optimization candidate table
  1012. and the label fixup table. */
  1013. {
  1014. register struct FwdBr *fp1, *fp2;
  1015. register struct SymTab **fsp, **fsp2, **fsp3;
  1016. fp2 = FwdBranch;
  1017. while ((fp2 < FwdLim1) && (fp2->Loc < (AddrCnt - 128)))
  1018. fp2++; /* Find the first unexpired entry. */
  1019. if (fp2 > FwdBranch) { /* If we can drop anything, */
  1020. fp1 = FwdBranch; /* shift active entries */
  1021. while (fp2 < FwdLim1) { /* over expired ones. */
  1022. fp1->Loc = fp2->Loc;
  1023. fp1->FwdSym = fp2->FwdSym;
  1024. fp1->Line = fp2->Line;
  1025. fp1++;
  1026. fp2++;
  1027. }
  1028. FwdLim1 = fp1; /* The table now ends here. */
  1029. }
  1030. if (FwdLim1 <= FwdBranch)
  1031. FwdFixLimit = FwdBranchFix; /* No outstanding branches */
  1032. for (fsp = FwdBranchFix; fsp < FwdFixLimit; fsp++) {
  1033. if ((*fsp)->Val < (AddrCnt - 128)) {
  1034. fsp2 = fsp3 = fsp; /* Now drop expired label entries. */
  1035. fsp3++;
  1036. while (fsp3 < FwdFixLimit)
  1037. *fsp2++ = *fsp3++;
  1038. FwdFixLimit--;
  1039. }
  1040. }
  1041. }