Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1528 lines
41 KiB

4 years ago
  1. /* Intermediate 68000 Assembly Language Builder Functions
  2. This file contains the functions necessary to build the intermediate 68000
  3. assembly language instructions from a 68000 instruction stream.
  4. The public function is
  5. unsigned CbBuildIasm(piasm, pc, pbInstr)
  6. This function builds an intermediate 68000 assembly language
  7. instruction from the bytes starting at pbInstr assuming that pc is the
  8. program counter.
  9. piasm pointer to the IASM structure being built
  10. pc starting virtual program counter
  11. pbInstr pointer to the instruction stream
  12. returns the number of bytes read to construct the IASM structure
  13. */
  14. #include <stdio.h>
  15. #include "iasm68.h"
  16. #include "opd.h"
  17. // This macro retrieves cbits bits from the word w starting at the position lsb
  18. #define GETBITS(w, cbits, lsb) \
  19. ((unsigned short)((w) & ~((short)0x8000 >> (15 - cbits)) << lsb) >> lsb)
  20. // Internal constants
  21. #define FALSE 0
  22. #define TRUE (!FALSE)
  23. #define iopEXTW 0
  24. #define iopEXTL 1
  25. #define iopEXTB 2
  26. #define iopSWAP 3
  27. #define iopUNLK 4
  28. #define grpopTOCCR 0
  29. #define grpopFROMCCR 1
  30. #define grpopTOSR 2
  31. #define grpopFROMSR 3
  32. #define opONEOPERBASE opJMP
  33. #define opSHROBASE opASR
  34. #define opBITBASE opBTST
  35. #define opFPBASE opFMOVE
  36. // Prototypes for internal functions
  37. unsigned short WFetch(void);
  38. void SetIasmHeader(IASM *, unsigned, unsigned, unsigned);
  39. void SetEa(OPER *, unsigned, unsigned, unsigned);
  40. void SetEaImmed(OPER *, unsigned, long);
  41. void SetEaLabel(OPER *, long);
  42. void SetEaRegPair(OPER *, unsigned, unsigned, unsigned);
  43. unsigned short WReverse(unsigned short);
  44. // Prototypes for builder functions
  45. void BuildMove(IASM *, unsigned short, unsigned short);
  46. void BuildMovea(IASM *, unsigned short, unsigned short);
  47. void BuildBranch(IASM *, unsigned short, unsigned short);
  48. void BuildDbcc(IASM *, unsigned short, unsigned short);
  49. void BuildScc(IASM *, unsigned short, unsigned short);
  50. void BuildBitOp(IASM *, unsigned short, unsigned short);
  51. void BuildMovep(IASM *, unsigned short, unsigned short);
  52. void BuildOpmode(IASM *, unsigned short, unsigned short);
  53. void BuildOpmodeA(IASM *, unsigned short, unsigned short);
  54. void BuildShroOp(IASM *, unsigned short, unsigned short);
  55. void BuildImmed(IASM *, unsigned short, unsigned short) ;
  56. void BuildMoveUSP(IASM *, unsigned short, unsigned short);
  57. void BuildReg(IASM *, unsigned short, unsigned short);
  58. void BuildExtend(IASM *, unsigned short, unsigned short);
  59. void BuildLink(IASM *, unsigned short, unsigned short);
  60. void BuildTrap(IASM *, unsigned short, unsigned short);
  61. void BuildToolbox(IASM *, unsigned short, unsigned short);
  62. void BuildSreg(IASM *, unsigned short, unsigned short);
  63. void BuildOneOper(IASM *, unsigned short, unsigned short);
  64. void BuildMovem(IASM *, unsigned short, unsigned short);
  65. void BuildChk(IASM *, unsigned short, unsigned short);
  66. void BuildOneOperS(IASM *, unsigned short, unsigned short);
  67. void BuildQuick(IASM *, unsigned short, unsigned short);
  68. void BuildMoveq(IASM *, unsigned short, unsigned short);
  69. void BuildNoOper(IASM *, unsigned short, unsigned short);
  70. void BuildWExt(IASM *, unsigned short, unsigned short);
  71. void BuildFP(IASM *, unsigned short, unsigned short);
  72. void BuildFDbcc(IASM *, unsigned short, unsigned short);
  73. void BuildFTrapcc(IASM *, unsigned short, unsigned short);
  74. void BuildFScc(IASM *, unsigned short, unsigned short);
  75. void BuildFBcc(IASM *, unsigned short, unsigned short);
  76. void BuildFNop(IASM *, unsigned short, unsigned short);
  77. void BuildFMoveFPcr(IASM *, unsigned short, unsigned short);
  78. void BuildFMovem(IASM *, unsigned short, unsigned short);
  79. void BuildLongMath(IASM *, unsigned short, unsigned short);
  80. #ifdef TRAP_NAMES
  81. int ItrpdFromTrp(unsigned short trp);
  82. #endif
  83. // Global data
  84. unsigned long pc; // Current program counter
  85. unsigned long pcInit; // Initial program counter
  86. const unsigned char *pb; // Current position in the instruction stream
  87. // Opcode descriptor table
  88. const OPD rgopd[] = { // order is important below
  89. 0xFF00, 0x0000, BuildImmed, opORI, // 0000 0000 xxxx xxxx
  90. 0xFF00, 0x0200, BuildImmed, opANDI, // 0000 0010 xxxx xxxx
  91. 0xFF00, 0x0400, BuildImmed, opSUBI, // 0000 0100 xxxx xxxx
  92. 0xFF00, 0x0600, BuildImmed, opADDI, // 0000 0110 xxxx xxxx
  93. 0xFF00, 0x0800, BuildBitOp, 0, // 0000 1000 xxxx xxxx
  94. 0xFF00, 0x0A00, BuildImmed, opEORI, // 0000 1010 xxxx xxxx
  95. 0xFF00, 0x0C00, BuildImmed, opCMPI, // 0000 1100 xxxx xxxx
  96. 0xF138, 0x0108, BuildMovep, 0, // 0000 xxx1 xx00 1xxx
  97. 0xF100, 0x0100, BuildBitOp, 0, // 0000 xxx1 xxxx xxxx
  98. 0xF000, 0x1000, BuildMove, sizeBYTE, // 0001 xxxx xxxx xxxx
  99. 0xF1C0, 0x2040, BuildMovea, sizeLONG, // 0010 xxx0 01xx xxxx
  100. 0xF000, 0x2000, BuildMove, sizeLONG, // 0010 xxxx xxxx xxxx
  101. 0xF1C0, 0x3040, BuildMovea, sizeWORD, // 0011 xxx0 01xx xxxx
  102. 0xF000, 0x3000, BuildMove, sizeWORD, // 0011 xxxx xxxx xxxx
  103. 0xFFC0, 0x40C0, BuildSreg, grpopFROMSR, // 0100 0000 11xx xxxx
  104. 0xFF00, 0x4000, BuildOneOperS, opNEGX, // 0100 0000 xxxx xxxx
  105. 0xFFC0, 0x42C0, BuildSreg, grpopFROMCCR, // 0100 0010 11xx xxxx
  106. 0xFF00, 0x4200, BuildOneOperS, opCLR, // 0100 0010 xxxx xxxx
  107. 0xFFC0, 0x44C0, BuildSreg, grpopTOCCR, // 0100 0100 11xx xxxx
  108. 0xFF00, 0x4400, BuildOneOperS, opNEG, // 0100 0100 xxxx xxxx
  109. 0xFFC0, 0x46C0, BuildSreg, grpopTOSR, // 0100 0110 11xx xxxx
  110. 0xFF00, 0x4600, BuildOneOperS, opNOT, // 0100 0110 xxxx xxxx
  111. 0xFFC0, 0x4800, BuildOneOper, opNBCD, // 0100 1000 00xx xxxx
  112. 0xFFF8, 0x4840, BuildReg, iopSWAP, // 0100 1000 0100 0xxx
  113. 0xFFC0, 0x4840, BuildOneOper, opPEA, // 0100 1000 01xx xxxx
  114. 0xFFF8, 0x4880, BuildReg, iopEXTW, // 0100 1000 1000 0xxx
  115. 0xFFF8, 0x48C0, BuildReg, iopEXTL, // 0100 1000 1100 0xxx
  116. 0xFFF8, 0x49C0, BuildReg, iopEXTB, // 0100 1001 1100 0xxx
  117. 0xFB80, 0x4880, BuildMovem, 0, // 0100 1x00 1xxx xxxx
  118. 0xFFFF, 0x4AFC, BuildNoOper, opILLEGAL, // 0100 1010 1111 1100
  119. 0xFFC0, 0x4AC0, BuildOneOper, opTAS, // 0100 1010 11xx xxxx
  120. 0xFF00, 0x4A00, BuildOneOperS, opTST, // 0100 1010 xxxx xxxx
  121. 0xFF80, 0x4C00, BuildLongMath, 0, // 0100 1100 0xxx xxxx
  122. 0xFFF0, 0x4E40, BuildTrap, 0, // 0100 1110 0100 xxxx
  123. 0xFFF8, 0x4E50, BuildLink, 0, // 0100 1110 0101 0xxx
  124. 0xFFF8, 0x4E58, BuildReg, iopUNLK, // 0100 1110 0101 1xxx
  125. 0xFFF0, 0x4E60, BuildMoveUSP, 0, // 0100 1110 0110 xxxx
  126. 0xFFFF, 0x4E70, BuildNoOper, opRESET, // 0100 1110 0111 0000
  127. 0xFFFF, 0x4E71, BuildNoOper, opNOP, // 0100 1110 0111 0001
  128. 0xFFFF, 0x4E72, BuildWExt, opSTOP, // 0100 1110 0111 0010
  129. 0xFFFF, 0x4E73, BuildNoOper, opRTE, // 0100 1110 0111 0011
  130. 0xFFFF, 0x4E74, BuildWExt, opRTD, // 0100 1110 0111 0100
  131. 0xFFFF, 0x4E75, BuildNoOper, opRTS, // 0100 1110 0111 0101
  132. 0xFFFF, 0x4E76, BuildNoOper, opTRAPV, // 0100 1110 0111 0110
  133. 0xFFFF, 0x4E77, BuildNoOper, opRTR, // 0100 1110 0111 0111
  134. 0xFFC0, 0x4E80, BuildOneOper, opJSR, // 0100 1110 10xx xxxx
  135. 0xFFC0, 0x4EC0, BuildOneOper, opJMP, // 0100 1110 11xx xxxx
  136. 0xF1C0, 0x4180, BuildChk, opCHK, // 0100 xxx1 10xx xxxx
  137. 0xF1C0, 0x41C0, BuildChk, opLEA, // 0100 xxx1 11xx xxxx
  138. 0xF0F8, 0x50C8, BuildDbcc, 0, // 0101 xxxx 1100 1xxx
  139. 0xF0C0, 0x50C0, BuildScc, 0, // 0101 xxxx 11xx xxxx
  140. 0xF100, 0x5000, BuildQuick, opADDQ, // 0101 xxx0 xxxx xxxx
  141. 0xF100, 0x5100, BuildQuick, opSUBQ, // 0101 xxx1 xxxx xxxx
  142. 0xF000, 0x6000, BuildBranch, 0, // 0110 xxxx xxxx xxxx
  143. 0xF000, 0x7000, BuildMoveq, 0, // 0111 xxxx xxxx xxxx
  144. 0xF1C0, 0x80C0, BuildChk, opDIVU, // 1000 xxx0 11xx xxxx
  145. 0xF1C0, 0x81C0, BuildChk, opDIVS, // 1000 xxx1 11xx xxxx
  146. 0xF1F0, 0x8100, BuildExtend, opSBCD, // 1000 xxx1 0000 xxxx
  147. 0xF000, 0x8000, BuildOpmode, opOR, // 1000 xxxx xxxx xxxx
  148. 0xF1F0, 0x91C0, BuildOpmodeA, opSUBA, // 1001 xxx1 1100 xxxx
  149. 0xF130, 0x9100, BuildExtend, opSUBX, // 1001 xxx1 xx00 xxxx
  150. 0xF0C0, 0x90C0, BuildOpmodeA, opSUBA, // 1001 xxxx 11xx xxxx
  151. 0xF000, 0x9000, BuildOpmode, opSUB, // 1001 xxxx xxxx xxxx
  152. 0xF000, 0xa000, BuildToolbox, 0, // 1010 xxxx xxxx xxxx
  153. /* This next OPD entry is unusual; it is designed to catch the CMPA
  154. instructions that might otherwise look like CMPM instructions. */
  155. 0xF1F8, 0xB1C8, BuildOpmodeA, opCMPA, // 1011 xxx1 1100 1xxx
  156. 0xF138, 0xB108, BuildExtend, opCMPM, // 1011 xxx1 xx00 1xxx
  157. 0xF0C0, 0xB0C0, BuildOpmodeA, opCMPA, // 1011 xxxx 11xx xxxx
  158. 0xF100, 0xB000, BuildOpmode, opCMP, // 1011 xxx0 xxxx xxxx
  159. 0xF100, 0xB100, BuildOpmode, opEOR, // 1011 xxx1 xxxx xxxx
  160. 0xF1C0, 0xC0C0, BuildChk, opMULU, // 1100 xxx0 11xx xxxx
  161. 0xF1F0, 0xC100, BuildExtend, opABCD, // 1100 xxx1 0000 xxxx
  162. 0xF1F8, 0xC140, BuildExtend, opEXG, // 1100 xxx1 0100 0xxx
  163. 0xF1F8, 0xC148, BuildExtend, opEXG, // 1100 xxx1 0100 1xxx
  164. 0xF1F8, 0xC188, BuildExtend, opEXG, // 1100 xxx1 1000 1xxx
  165. 0xF1C0, 0xC1C0, BuildChk, opMULS, // 1100 xxx1 11xx xxxx
  166. 0xF000, 0xC000, BuildOpmode, opAND, // 1100 xxxx xxxx xxxx
  167. 0xF1F0, 0xD1C0, BuildOpmodeA, opADDA, // 1101 xxx1 1100 xxxx
  168. 0xF130, 0xD100, BuildExtend, opADDX, // 1101 xxx1 xx00 xxxx
  169. 0xF0C0, 0xD0C0, BuildOpmodeA, opADDA, // 1101 xxxx 11xx xxxx
  170. 0xF000, 0xD000, BuildOpmode, opADD, // 1101 xxxx xxxx xxxx
  171. 0xF000, 0xE000, BuildShroOp, 0, // 1110 xxxx xxxx xxxx
  172. 0xFFC0, 0xF200, BuildFP, 0, // 1111 0010 00xx xxxx
  173. 0xFFF8, 0xF248, BuildFDbcc, 0, // 1111 0010 0100 1xxx
  174. 0xFFF8, 0xF278, BuildFTrapcc, 0, // 1111 0010 0111 1xxx
  175. 0xFFC0, 0xF240, BuildFScc, 0, // 1111 0010 01xx xxxx
  176. 0xFF80, 0xF280, BuildFBcc, 0, // 1111 0010 1xxx xxxx
  177. 0xFFC0, 0xF300, BuildOneOper, opFSAVE, // 1111 0011 00xx xxxx
  178. 0xFFC0, 0xF340, BuildOneOper, opFRESTORE // 1111 0011 01xx xxxx
  179. };
  180. const unsigned copd = sizeof(rgopd) / sizeof(OPD);
  181. unsigned
  182. CbBuildIasm(
  183. IASM *piasm,
  184. unsigned long pcStart,
  185. const unsigned char *pbStart)
  186. {
  187. /* This function builds an intermediate 68000 assembly language instruction
  188. from the bytes starting at pbStart assuming that pcStart is the starting
  189. program counter. The number of bytes used to construct the instruction is
  190. returned. */
  191. const OPD *popd;
  192. const OPD *popdEnd;
  193. unsigned short wInstr;
  194. /* Save the starting location and program counter in global variables so
  195. that the builder functions can access them if need be. */
  196. pcInit = pc = pcStart;
  197. pb = pbStart;
  198. /* Read the first word from memory. */
  199. wInstr = WFetch();
  200. /* Attempt to match the bit pattern in the word read to valid 68000
  201. instruction bit patterns. */
  202. for (popd = &rgopd[0], popdEnd = &rgopd[sizeof(rgopd) / sizeof(OPD)];
  203. popd != popdEnd; popd++) {
  204. /* If we have identified this instruction, call the builder function
  205. and return the number of bytes read. */
  206. if ((wInstr & popd->mask) == popd->match) {
  207. (*popd->pfn)(piasm, wInstr, popd->arg);
  208. return (unsigned)(pb - pbStart);
  209. }
  210. }
  211. /* We have been unable to identify this instruction. Mark it as a NULL
  212. instruction and return. */
  213. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  214. return 2;
  215. }
  216. unsigned short
  217. WFetch()
  218. {
  219. /* This function reads a word out of memory in big-endian format (high-byte
  220. first). */
  221. unsigned short w;
  222. w = (unsigned short)(*pb++ << 8);
  223. w |= (unsigned short)(*pb++);
  224. /* Update the virtual program counter. */
  225. pc += 2L;
  226. return w;
  227. }
  228. void
  229. SetIasmHeader(
  230. IASM *piasm,
  231. unsigned op,
  232. unsigned coper,
  233. unsigned size)
  234. {
  235. /* This function sets the header of the intermediate 68000 assembly language
  236. instruction. */
  237. piasm->op = op;
  238. piasm->coper = coper;
  239. piasm->size = size;
  240. }
  241. void
  242. SetEa(
  243. OPER *poper,
  244. unsigned mode,
  245. unsigned reg,
  246. unsigned size)
  247. {
  248. /* This functions sets the effective addressing mode of the specified
  249. operand based on the addressing mode, the register, and the size of the
  250. operation. This function will read words from the instruction stream if it
  251. is necessary to compute the effective addressing mode. */
  252. unsigned short wExt;
  253. #if 0
  254. unsigned short *pw;
  255. #endif
  256. /* If the mode is not one of the special modes, then the mode is the
  257. effective addressing mode and the register is the register we will use in
  258. calculating the operand. */
  259. if (mode != modeSPECIAL) {
  260. poper->ea = mode;
  261. poper->reg = reg;
  262. /* If the register is a valid special register to use with the special
  263. mode, then the effective addressing mode is the sum of the mode and the
  264. special register. */
  265. } else if (reg < regMAX) {
  266. poper->ea = mode + reg;
  267. /* If this is an immediate value, we must add in the size of the value.
  268. */
  269. if (reg == regIMMED) {
  270. poper->ea += size;
  271. }
  272. /* Otherwise, we do not recognize this effective addressing. */
  273. } else {
  274. poper->ea = eaNULL;
  275. }
  276. /* Initial the displacement so we can cleverly combine the effective
  277. addressing modes (see fall throughs). */
  278. poper->disp = 0L;
  279. /* Is there and extension word associated with this effective addressing? */
  280. switch (poper->ea) {
  281. case eaPCDISP:
  282. /* Save the program counter. */
  283. poper->val.pc = pcInit;
  284. poper->disp = pc - pcInit;
  285. /* Fall through */
  286. case eaDISP:
  287. /* This extenstion word is the displacement. */
  288. poper->disp += (long)(short)WFetch();
  289. poper->szLabel = (char *)NULL;
  290. break;
  291. case eaPCINDEX:
  292. /* Save the program counter. */
  293. poper->val.pc = pcInit;
  294. poper->disp = pc - pcInit;
  295. /* Fall through */
  296. case eaINDEX:
  297. /* The extension word describes the index register. */
  298. wExt = WFetch();
  299. poper->fARegIndex = GETBITS(wExt, 1, 15);
  300. poper->reg2 = GETBITS(wExt, 3, 12);
  301. poper->fLongIndex = GETBITS(wExt, 1, 11);
  302. // REVIEW: Special casing 32-bit displacment addressing. Need to have
  303. // general support for all 68020 addressing modes.
  304. if (GETBITS(wExt, 11, 0) == 0x170) {
  305. poper->ea = poper->ea == eaINDEX ? eaDISP : eaPCDISP;
  306. wExt = WFetch();
  307. poper->disp += (long)(((long)wExt << 16) | (unsigned long)WFetch());
  308. } else {
  309. poper->disp += (long)(char)GETBITS(wExt, 8, 0);
  310. }
  311. poper->szLabel = (char *)NULL;
  312. break;
  313. case eaSHORTADDR:
  314. case eaWORDIMMED:
  315. /* The extenstion word is an immediate word value. */
  316. poper->val.w = WFetch();
  317. break;
  318. case eaBYTEIMMED:
  319. /* The extenstion word is an immediate byte value. */
  320. poper->val.b = (char)GETBITS(WFetch(), 8, 0);
  321. break;
  322. case eaLONGADDR:
  323. case eaLONGIMMED:
  324. /* The extenstion words are an immediate long value. Convert them to
  325. big-endian format (high-order word first). */
  326. wExt = WFetch();
  327. poper->val.l = (long)(((long)wExt << 16) | (unsigned long)WFetch());
  328. break;
  329. #if 0
  330. case eaSINGLEIMMED:
  331. /* The extenstion words are an immediate single precision value. */
  332. pw = (unsigned short *)&poper->val.s;
  333. *pw++ = WFetch();
  334. *pw = WFetch();
  335. break;
  336. case eaDOUBLEIMMED:
  337. /* The extenstion words are an immediate double precision value. */
  338. pw = (unsigned short *)&poper->val.d;
  339. *pw++ = WFetch();
  340. *pw++ = WFetch();
  341. *pw++ = WFetch();
  342. *pw = WFetch();
  343. break;
  344. case eaEXTENDEDIMMED:
  345. /* The extenstion words are an immediate extended precision value. */
  346. pw = (unsigned short *)&poper->val.d;
  347. *pw++ = WFetch();
  348. WFetch(); // Skip the zero word in the 68k format
  349. *pw++ = WFetch();
  350. *pw++ = WFetch();
  351. *pw++ = WFetch();
  352. *pw = WFetch();
  353. break;
  354. #endif
  355. }
  356. }
  357. void
  358. SetEaImmed(
  359. OPER *poper,
  360. unsigned ea,
  361. long val)
  362. {
  363. /* This function sets the effective addressing mode of an operand when the
  364. mode is an immediate mode and the value is already known (i.e. not read from
  365. the instruction stream). */
  366. switch (poper->ea = ea) {
  367. case eaBYTEIMMED:
  368. poper->val.b = (char)val;
  369. break;
  370. case eaWORDIMMED:
  371. poper->val.w = (short)val;
  372. break;
  373. case eaLONGIMMED:
  374. poper->val.l = val;
  375. break;
  376. case eaREGLIST:
  377. poper->val.rl = val;
  378. break;
  379. }
  380. }
  381. void
  382. SetEaLabel(
  383. OPER *poper,
  384. long disp)
  385. {
  386. /* This function sets the effective addressing mode of an operand to that
  387. of a label. */
  388. poper->ea = eaLABEL;
  389. poper->val.pc = pcInit;
  390. poper->disp = disp;
  391. poper->szLabel = (char *)NULL;
  392. }
  393. void
  394. SetEaRegPair(
  395. OPER *poper,
  396. unsigned ea,
  397. unsigned reg1,
  398. unsigned reg2)
  399. {
  400. /* This function sets the effective addressing mode of an operand to that
  401. of a register pair. */
  402. poper->ea = ea;
  403. poper->reg = reg1;
  404. poper->reg2 = reg2;
  405. }
  406. unsigned short
  407. WReverse(
  408. unsigned short w)
  409. {
  410. static const unsigned short rgrev[] = {
  411. 0x0, /* 0000b => 0000b */
  412. 0x8, /* 0001b => 1000b */
  413. 0x4, /* 0010b => 0100b */
  414. 0xC, /* 0011b => 1100b */
  415. 0x2, /* 0100b => 0010b */
  416. 0xA, /* 0101b => 1010b */
  417. 0x6, /* 0110b => 0110b */
  418. 0xE, /* 0111b => 1110b */
  419. 0x1, /* 1000b => 0001b */
  420. 0x9, /* 1001b => 1001b */
  421. 0x5, /* 1010b => 0101b */
  422. 0xD, /* 1011b => 1101b */
  423. 0x3, /* 1100b => 0011b */
  424. 0xB, /* 1101b => 1011b */
  425. 0x7, /* 1110b => 0111b */
  426. 0xF /* 1111b => 1111b */
  427. };
  428. unsigned short wrev;
  429. int shift;
  430. /* Reverse the bits in the word nibble by nibble. */
  431. for (wrev = 0, shift = 12; w != 0; w >>= 4, shift -= 4) {
  432. wrev |= rgrev[w & 0x000F] << shift;
  433. }
  434. return wrev;
  435. }
  436. void
  437. BuildMove(
  438. IASM *piasm,
  439. unsigned short wInstr,
  440. unsigned short size)
  441. {
  442. /* This function build the intermediate 68000 assembly language instruction
  443. for the MOVE instruction. */
  444. SetIasmHeader(piasm, opMOVE, 2, size);
  445. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
  446. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 6), GETBITS(wInstr, 3, 9), size);
  447. }
  448. void
  449. BuildMovea(
  450. IASM *piasm,
  451. unsigned short wInstr,
  452. unsigned short size)
  453. {
  454. /* This function build the intermediate 68000 assembly language instruction
  455. for the MOVEA instruction. */
  456. SetIasmHeader(piasm, opMOVEA, 2, size);
  457. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
  458. SetEa(&piasm->oper2, modeAREG, GETBITS(wInstr, 3, 9), size);
  459. }
  460. void
  461. BuildBranch(
  462. IASM *piasm,
  463. unsigned short wInstr,
  464. unsigned short wDummy)
  465. {
  466. /* This function build the intermediate 68000 assembly language instruction
  467. for the BRA, BSR, and Bcc instructions. */
  468. unsigned size;
  469. long disp;
  470. /* Read the displacment for the branch. */
  471. switch (disp = (long)(char)GETBITS(wInstr, 8, 0)) {
  472. case 0L:
  473. size = sizeWORD;
  474. disp = (long)(short)WFetch();
  475. break;
  476. case -1L:
  477. size = sizeLONG;
  478. disp = (long)((unsigned long)WFetch() << 16) | (unsigned long)WFetch();
  479. break;
  480. default:
  481. size = sizeBYTE;
  482. break;
  483. }
  484. /* Build the intermediate instruction. */
  485. SetIasmHeader(piasm, opBcc + GETBITS(wInstr, 4, 8), 1, size);
  486. SetEaLabel(&piasm->oper1, disp + 2L);
  487. }
  488. void
  489. BuildDbcc(
  490. IASM *piasm,
  491. unsigned short wInstr,
  492. unsigned short wDummy)
  493. {
  494. /* This function build the intermediate 68000 assembly language instruction
  495. for the DBcc instructions. */
  496. SetIasmHeader(piasm, opDBcc + GETBITS(wInstr, 4, 8), 2, sizeWORD);
  497. SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 0), sizeWORD);
  498. SetEaLabel(&piasm->oper2, (long)(short)WFetch() + 2L);
  499. }
  500. void
  501. BuildScc(
  502. IASM *piasm,
  503. unsigned short wInstr,
  504. unsigned short wDummy)
  505. {
  506. /* This function build the intermediate 68000 assembly language instruction
  507. for the Scc instructions. */
  508. SetIasmHeader(piasm, opScc + GETBITS(wInstr, 4, 8), 1, sizeBYTE);
  509. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  510. sizeBYTE);
  511. }
  512. void
  513. BuildBitOp(
  514. IASM *piasm,
  515. unsigned short wInstr,
  516. unsigned short wDummy)
  517. {
  518. /* This function build the intermediate 68000 assembly language instruction
  519. for the BTST, BCHG, BSET, and BCLR instructions. */
  520. unsigned size;
  521. /* Is this a register or immediate instruction? */
  522. if (GETBITS(wInstr, 1, 8) != 0) {
  523. SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size = sizeLONG);
  524. } else {
  525. SetEa(&piasm->oper1, modeSPECIAL, regIMMED, size = sizeBYTE);
  526. }
  527. SetIasmHeader(piasm, opBITBASE + GETBITS(wInstr, 2, 6), 2, size);
  528. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
  529. }
  530. void
  531. BuildMovep(
  532. IASM *piasm,
  533. unsigned short wInstr,
  534. unsigned short wDummy)
  535. {
  536. /* This function build the intermediate 68000 assembly language instruction
  537. for the MOVEP instruction. */
  538. unsigned size;
  539. SetIasmHeader(piasm, opMOVEP, 2, size = GETBITS(wInstr, 1, 6) != 0 ?
  540. sizeLONG : sizeWORD);
  541. /* Is this a move to or from memory? */
  542. if (GETBITS(wInstr, 1, 7) != 0) {
  543. SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size);
  544. SetEa(&piasm->oper2, modeDISP, GETBITS(wInstr, 3, 0), size);
  545. } else {
  546. SetEa(&piasm->oper1, modeDISP, GETBITS(wInstr, 3, 0), size);
  547. SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 9), size);
  548. }
  549. }
  550. void
  551. BuildOpmode(
  552. IASM *piasm,
  553. unsigned short wInstr,
  554. unsigned short op)
  555. {
  556. /* This function build the intermediate 68000 assembly language instruction
  557. for the ADD, AND, CMP, EOR, OR, and SUB instructions. */
  558. unsigned size;
  559. if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
  560. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  561. } else {
  562. SetIasmHeader(piasm, op, 2, size);
  563. /* Is the destination or source operand a register? */
  564. if (GETBITS(wInstr, 1, 8) != 0) {
  565. SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size);
  566. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  567. size);
  568. } else {
  569. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  570. size);
  571. SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 9), size);
  572. }
  573. }
  574. }
  575. void
  576. BuildOpmodeA(
  577. IASM *piasm,
  578. unsigned short wInstr,
  579. unsigned short op)
  580. {
  581. /* This function build the intermediate 68000 assembly language instruction
  582. for the ADDA and SUBA instructions. */
  583. unsigned size;
  584. SetIasmHeader(piasm, op, 2, size = GETBITS(wInstr, 1, 8) != 0 ? sizeLONG :
  585. sizeWORD);
  586. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
  587. SetEa(&piasm->oper2, modeAREG, GETBITS(wInstr, 3, 9), size);
  588. }
  589. void
  590. BuildShroOp(
  591. IASM *piasm,
  592. unsigned short wInstr,
  593. unsigned short wDummy)
  594. {
  595. /* This function build the intermediate 68000 assembly language instruction
  596. for the ASL, ASR, LSL, LSR, ROL, ROR, ROXL, and ROXR instructions. */
  597. unsigned size;
  598. unsigned cbits;
  599. /* Is this instruction shifting or rotating memory on place? */
  600. if (GETBITS(wInstr, 2, 6) == 0x3) {
  601. SetIasmHeader(piasm, opSHROBASE + (GETBITS(wInstr, 2, 9) << 1) +
  602. GETBITS(wInstr, 1, 8), 1, sizeWORD);
  603. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  604. sizeWORD);
  605. /* This instuction is operating on a data register. */
  606. } else if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
  607. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  608. } else {
  609. SetIasmHeader(piasm, opSHROBASE + (GETBITS(wInstr, 2, 3) << 1) +
  610. GETBITS(wInstr, 1, 8), 2, size);
  611. SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 0), size);
  612. /* Is the count in a register? */
  613. if (GETBITS(wInstr, 1, 5) != 0) {
  614. SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 9), size);
  615. /* The count is an immediate value. */
  616. } else {
  617. cbits = GETBITS(wInstr, 3, 9);
  618. SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)(cbits == 0 ? 8 :
  619. cbits));
  620. }
  621. }
  622. }
  623. void
  624. BuildImmed(
  625. IASM *piasm,
  626. unsigned short wInstr,
  627. unsigned short op)
  628. {
  629. /* This function build the intermediate 68000 assembly language instruction
  630. for the ADDI, ANDI, CMPI, EORI, ORI, and SUBI instructions. */
  631. unsigned size;
  632. unsigned mode;
  633. unsigned reg;
  634. if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
  635. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  636. } else {
  637. SetIasmHeader(piasm, op, 2, size);
  638. SetEa(&piasm->oper1, modeSPECIAL, regIMMED, size);
  639. /* Get the effective addressing mode and register for the second
  640. operand. */
  641. mode = GETBITS(wInstr, 3, 3);
  642. reg = GETBITS(wInstr, 3, 0);
  643. /* Is this instruction operating on a special register? */
  644. if (mode == modeSPECIAL && reg == regIMMED) {
  645. mode = modeSREG;
  646. reg = size == sizeBYTE ? regCCR : regSR;
  647. }
  648. SetEa(&piasm->oper2, mode, reg, size);
  649. }
  650. }
  651. void
  652. BuildMoveUSP(
  653. IASM *piasm,
  654. unsigned short wInstr,
  655. unsigned short wDummy)
  656. {
  657. /* This function build the intermediate 68000 assembly language instruction
  658. for the MOVE USP to An and MOVE An to USP instructions. */
  659. SetIasmHeader(piasm, opMOVE, 2, sizeLONG);
  660. /* Is this instruction moving from the USP? */
  661. if (GETBITS(wInstr, 1, 3) != 0) {
  662. SetEa(&piasm->oper1, modeSREG, regUSP, sizeLONG);
  663. SetEa(&piasm->oper2, modeAREG, GETBITS(wInstr, 3, 0), sizeLONG);
  664. /* We must be moving to the USP. */
  665. } else {
  666. SetEa(&piasm->oper1, modeAREG, GETBITS(wInstr, 3, 0), sizeLONG);
  667. SetEa(&piasm->oper2, modeSREG, regUSP, sizeLONG);
  668. }
  669. }
  670. void
  671. BuildReg(
  672. IASM *piasm,
  673. unsigned short wInstr,
  674. unsigned short iop)
  675. {
  676. /* This function build the intermediate 68000 assembly language instruction
  677. for the EXT, EXTB, SWAP, and UNLK instructions. */
  678. static unsigned rgop[] = {
  679. opEXT, opEXT, opEXTB, opSWAP, opUNLK
  680. };
  681. static unsigned rgsize[] = {
  682. sizeWORD, sizeLONG, sizeLONG, sizeWORD, sizeNULL
  683. };
  684. static unsigned rgmode[] = {
  685. modeDREG, modeDREG, modeDREG, modeDREG, modeAREG
  686. };
  687. unsigned size;
  688. SetIasmHeader(piasm, rgop[iop], 1, size = rgsize[iop]);
  689. SetEa(&piasm->oper1, rgmode[iop], GETBITS(wInstr, 3, 0), size);
  690. }
  691. void
  692. BuildExtend(
  693. IASM *piasm,
  694. unsigned short wInstr,
  695. unsigned short op)
  696. {
  697. /* This function build the intermediate 68000 assembly language instruction
  698. for the ABCD, ADDX, CMPM, EXG, SBCD, and SUBX instructions. */
  699. unsigned size;
  700. unsigned reg1;
  701. unsigned reg2;
  702. /* Get the two registers used in the instruction. */
  703. reg1 = GETBITS(wInstr, 3, 9);
  704. reg2 = GETBITS(wInstr, 3, 0);
  705. /* Is this an EXG instruction? */
  706. if (op == opEXG) {
  707. /* The size is always long. */
  708. size = sizeLONG;
  709. /* Is this "EXG Dn, An"? */
  710. if (GETBITS(wInstr, 1, 7) != 0) {
  711. SetEa(&piasm->oper1, modeDREG, reg1, sizeLONG);
  712. SetEa(&piasm->oper2, modeAREG, reg2, sizeLONG);
  713. /* Is this "EXG An, An"? */
  714. } else if (GETBITS(wInstr, 1, 3) != 0) {
  715. SetEa(&piasm->oper1, modeAREG, reg1, sizeLONG);
  716. SetEa(&piasm->oper2, modeAREG, reg2, sizeLONG);
  717. /* This must be "EXG Dn, Dn"? */
  718. } else {
  719. SetEa(&piasm->oper1, modeDREG, reg1, sizeLONG);
  720. SetEa(&piasm->oper2, modeDREG, reg2, sizeLONG);
  721. }
  722. } else {
  723. /* If bit 12 is set (ADDX, CMPM, or SUBX) then bits 6-7 indicate the
  724. size. Otherwise (ABCD or SBCD), the size is a byte. */
  725. if ((size = GETBITS(wInstr, 1, 12) != 0 ? GETBITS(wInstr, 2, 6) :
  726. sizeBYTE) == sizeNULL) {
  727. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  728. } else {
  729. /* Is this instruction "CMPM (An)+, (An)+"? */
  730. if (op == opCMPM) {
  731. SetEa(&piasm->oper1, modePOSTINC, reg2, size);
  732. SetEa(&piasm->oper2, modePOSTINC, reg1, size);
  733. /* Is this instruction of the form "OP -(An), -(An)"? */
  734. } else if (GETBITS(wInstr, 1, 3) != 0) {
  735. SetEa(&piasm->oper1, modePREDEC, reg2, size);
  736. SetEa(&piasm->oper2, modePREDEC, reg1, size);
  737. /* It must be of the form "OP Dn, Dn". */
  738. } else {
  739. SetEa(&piasm->oper1, modeDREG, reg2, size);
  740. SetEa(&piasm->oper2, modeDREG, reg1, size);
  741. }
  742. }
  743. SetIasmHeader(piasm, op, 2, size);
  744. }
  745. }
  746. void
  747. BuildLink(
  748. IASM *piasm,
  749. unsigned short wInstr,
  750. unsigned short wDummy)
  751. {
  752. /* This function build the intermediate 68000 assembly language instruction
  753. for the LINK instruction. */
  754. SetIasmHeader(piasm, opLINK, 2, sizeWORD);
  755. SetEa(&piasm->oper1, modeAREG, GETBITS(wInstr, 3, 0), sizeWORD);
  756. SetEa(&piasm->oper2, modeSPECIAL, regIMMED, sizeWORD);
  757. }
  758. void
  759. BuildTrap(
  760. IASM *piasm,
  761. unsigned short wInstr,
  762. unsigned short wDummy)
  763. {
  764. /* This function build the intermediate 68000 assembly language instruction
  765. for the TRAP instruction. */
  766. SetIasmHeader(piasm, opTRAP, 1, sizeNULL);
  767. SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)GETBITS(wInstr, 4, 0));
  768. }
  769. void
  770. BuildToolbox(
  771. IASM *piasm,
  772. unsigned short wInstr,
  773. unsigned short wDummy)
  774. {
  775. /* This function build the intermediate 68000 assembly language instruction
  776. for the A-TRAP (Macintosh Toolbox) instruction. */
  777. #ifdef TRAP_NAMES
  778. SetIasmHeader(piasm, opMAX + ItrpdFromTrp(wInstr), 0, sizeNULL);
  779. #else
  780. SetIasmHeader(piasm, opTOOLBOX, 1, sizeNULL);
  781. SetEaImmed(&piasm->oper1, eaLONGIMMED, (long)GETBITS(wInstr, 12, 0));
  782. #endif
  783. }
  784. void
  785. BuildSreg(
  786. IASM *piasm,
  787. unsigned short wInstr,
  788. unsigned short grpop)
  789. {
  790. /* This function build the intermediate 68000 assembly language instruction
  791. for the MOVE to and from the CCR and SR instructions. */
  792. unsigned reg;
  793. /* Are we dealing with the SR or the CCR? */
  794. reg = GETBITS(grpop, 1, 1) != 0 ? regSR : regCCR;
  795. SetIasmHeader(piasm, opMOVE, 2, sizeWORD);
  796. /* Are we moving to the special register? */
  797. if (GETBITS(grpop, 1, 0) != 0) {
  798. SetEa(&piasm->oper1, modeSREG, reg, sizeWORD);
  799. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  800. sizeWORD);
  801. /* We must be moving from the special register. */
  802. } else {
  803. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  804. sizeWORD);
  805. SetEa(&piasm->oper2, modeSREG, reg, sizeWORD);
  806. }
  807. }
  808. void
  809. BuildOneOper(
  810. IASM *piasm,
  811. unsigned short wInstr,
  812. unsigned short op)
  813. {
  814. /* This function build the intermediate 68000 assembly language instruction
  815. for the JMP, JSR, NBCD, PEA, TAS, FRESTORE, and FSAVE instructions. */
  816. static unsigned rgsize[] = {
  817. sizeNULL, sizeNULL, sizeBYTE, sizeLONG, sizeBYTE, sizeNULL, sizeNULL
  818. };
  819. unsigned size;
  820. SetIasmHeader(piasm, op, 1, size = rgsize[op - opONEOPERBASE]);
  821. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
  822. }
  823. void
  824. BuildMovem(
  825. IASM *piasm,
  826. unsigned short wInstr,
  827. unsigned short wDummy)
  828. {
  829. /* This function build the intermediate 68000 assembly language instruction
  830. for the MOVEM instruction. */
  831. unsigned size;
  832. unsigned mode;
  833. unsigned reglist;
  834. SetIasmHeader(piasm, opMOVEM, 2, size = GETBITS(wInstr, 1, 6) != 0 ?
  835. sizeLONG : sizeWORD);
  836. /* The register list is read from the instruction stream and reversed if
  837. the addressing mode is predecrement. */
  838. mode = GETBITS(wInstr, 3, 3);
  839. reglist = mode == modePREDEC ? WReverse(WFetch()) : WFetch();
  840. /* Are we moving to the registers? */
  841. if (GETBITS(wInstr, 1, 10) != 0) {
  842. SetEa(&piasm->oper1, mode, GETBITS(wInstr, 3, 0), size);
  843. SetEaImmed(&piasm->oper2, eaREGLIST, (long)reglist);
  844. /* We must be moving from the registers. */
  845. } else {
  846. SetEaImmed(&piasm->oper1, eaREGLIST, (long)reglist);
  847. SetEa(&piasm->oper2, mode, GETBITS(wInstr, 3, 0), size);
  848. }
  849. }
  850. void
  851. BuildChk(
  852. IASM *piasm,
  853. unsigned short wInstr,
  854. unsigned short op)
  855. {
  856. /* This function build the intermediate 68000 assembly language instruction
  857. for the CHK, DIVU, DIVS, LEA, MULU, and MULS instructions. */
  858. unsigned size;
  859. SetIasmHeader(piasm, op, 2, size = op == opLEA ? sizeLONG : sizeWORD);
  860. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0), size);
  861. SetEa(&piasm->oper2, op == opLEA ? modeAREG : modeDREG, GETBITS(wInstr, 3,
  862. 9), size);
  863. }
  864. void
  865. BuildLongMath(
  866. IASM *piasm,
  867. unsigned short wInstr,
  868. unsigned short op)
  869. {
  870. /* This function build the intermediate 68000 assembly language instruction
  871. for the long MULS, MULU, DIVS, DIVU instructions. */
  872. unsigned short wExt;
  873. unsigned fSigned, fDouble;
  874. unsigned destH, destL;
  875. /* Fetch the extra instruction word */
  876. wExt = WFetch();
  877. /* get the destination registers */
  878. destH = GETBITS(wExt, 3, 0);
  879. destL = GETBITS(wExt, 3, 12);
  880. /* get some flags */
  881. fSigned = (GETBITS(wExt, 1, 11) != 0);
  882. fDouble = (GETBITS(wExt, 1, 10) != 0);
  883. /* is it a DIV ? */
  884. if (GETBITS(wInstr, 1, 6) != 0)
  885. {
  886. if ((destH != destL) && !fDouble)
  887. {
  888. op = fSigned ? opDIVSL : opDIVUL;
  889. }
  890. else
  891. {
  892. op = fSigned ? opDIVS : opDIVU;
  893. }
  894. }
  895. else
  896. {
  897. op = fSigned ? opMULS : opMULU;
  898. }
  899. SetIasmHeader(piasm, op, 2, sizeLONG);
  900. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  901. sizeLONG);
  902. if ((destH != destL) || fDouble)
  903. {
  904. SetEaRegPair(&piasm->oper2, modeDREGPAIR, destH, destL);
  905. }
  906. else
  907. {
  908. SetEa(&piasm->oper2, modeDREG, destL, sizeLONG);
  909. }
  910. }
  911. void
  912. BuildOneOperS(
  913. IASM *piasm,
  914. unsigned short wInstr,
  915. unsigned short op)
  916. {
  917. /* This function build the intermediate 68000 assembly language instruction
  918. for the CLR, NEG, NEGX, NOT, and TST instructions. */
  919. unsigned size;
  920. if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
  921. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  922. } else {
  923. SetIasmHeader(piasm, op, 1, size);
  924. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  925. size);
  926. }
  927. }
  928. void
  929. BuildQuick(
  930. IASM *piasm,
  931. unsigned short wInstr,
  932. unsigned short op)
  933. {
  934. /* This function build the intermediate 68000 assembly language instruction
  935. for the ADDQ and SUBQ instructions. */
  936. unsigned size;
  937. unsigned data;
  938. if ((size = GETBITS(wInstr, 2, 6)) == sizeNULL) {
  939. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  940. } else {
  941. SetIasmHeader(piasm, op, 2, size);
  942. data = GETBITS(wInstr, 3, 9);
  943. SetEaImmed(&piasm->oper1, eaBYTEIMMED, data == 0 ? 8 : data);
  944. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  945. size);
  946. }
  947. }
  948. void
  949. BuildMoveq(
  950. IASM *piasm,
  951. unsigned short wInstr,
  952. unsigned short wDummy)
  953. {
  954. /* This function build the intermediate 68000 assembly language instruction
  955. for the MOVEQ instruction. */
  956. SetIasmHeader(piasm, opMOVEQ, 2, sizeLONG);
  957. SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)(char)GETBITS(wInstr, 8, 0));
  958. SetEa(&piasm->oper2, modeDREG, GETBITS(wInstr, 3, 9), sizeLONG);
  959. }
  960. void
  961. BuildNoOper(
  962. IASM *piasm,
  963. unsigned short wInstr,
  964. unsigned short op)
  965. {
  966. /* This function build the intermediate 68000 assembly language instruction
  967. for the ILLEGAL, NOP, RESET, RTR, RTS, and TRAPV instructions. */
  968. SetIasmHeader(piasm, op, 0, sizeNULL);
  969. }
  970. void
  971. BuildWExt(
  972. IASM *piasm,
  973. unsigned short wInstr,
  974. unsigned short op)
  975. {
  976. /* This function build the intermediate 68000 assembly language instruction
  977. for the STOP and RTD instructions. */
  978. SetIasmHeader(piasm, op, 1, sizeNULL);
  979. SetEa(&piasm->oper1, modeSPECIAL, regIMMED, sizeWORD);
  980. }
  981. void
  982. BuildFP(
  983. IASM *piasm,
  984. unsigned short wInstr,
  985. unsigned short wDummy)
  986. {
  987. /* This function build the intermediate 68000 assembly language instruction
  988. for the majority of the floating point instructions. */
  989. static unsigned mpbitssize[] = {
  990. sizeLONG,
  991. sizeSINGLE,
  992. sizeEXTENDED,
  993. sizePACKED,
  994. sizeWORD,
  995. sizeDOUBLE,
  996. sizeBYTE,
  997. sizePACKED
  998. };
  999. unsigned short wExt = WFetch();
  1000. unsigned op;
  1001. unsigned size;
  1002. /* Is this instruction an FMOVE <ea>,FPcr instruction? */
  1003. if (GETBITS(wExt, 2, 14) == 0x02) {
  1004. BuildFMoveFPcr(piasm, wInstr, wExt);
  1005. return;
  1006. }
  1007. /* Is this instruction an FMOVEM instruction? */
  1008. if (GETBITS(wExt, 2, 14) == 0x03) {
  1009. BuildFMovem(piasm, wInstr, wExt);
  1010. return;
  1011. }
  1012. /* Is this instruction "FMOVE FPn,<ea>"? */
  1013. if (GETBITS(wExt, 3, 13) == 0x03) {
  1014. SetIasmHeader(piasm, opFMOVE, 2, size = mpbitssize[GETBITS(wExt, 3,
  1015. 10)]);
  1016. SetEa(&piasm->oper1, modeFREG, GETBITS(wExt, 3, 7), size);
  1017. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  1018. size);
  1019. return;
  1020. }
  1021. /* Is this instruction an FMOVECR instruction? */
  1022. if (GETBITS(wInstr, 6, 0) == 0x00 && GETBITS(wExt, 6, 10) == 0x27) {
  1023. SetIasmHeader(piasm, opFMOVECR, 2, sizeEXTENDED);
  1024. SetEaImmed(&piasm->oper1, eaBYTEIMMED, (long)GETBITS(wExt, 6, 0));
  1025. SetEa(&piasm->oper2, modeFREG, GETBITS(wInstr, 3, 7), sizeEXTENDED);
  1026. return;
  1027. }
  1028. /* Is this instruction an FSINCOS instruction? */
  1029. if (GETBITS(wExt, 4, 3) == 0x06) {
  1030. op = opFSINCOS;
  1031. /* Calculate the opcode for this instruction. */
  1032. } else {
  1033. switch (op = GETBITS(wExt, 6, 0)) {
  1034. case 0x38:
  1035. /* Special case the FCMP opcode. */
  1036. op = opFCMP;
  1037. break;
  1038. case 0x3A:
  1039. /* Special case the FTST opcode. */
  1040. op = opFTST;
  1041. break;
  1042. default:
  1043. /* The floating point opcodes are ordered sequencially from
  1044. opFPBASE. */
  1045. op += opFPBASE;
  1046. break;
  1047. }
  1048. }
  1049. /* Is this instruction "FOP <ea>,FPn"? */
  1050. if (GETBITS(wExt, 1, 14) != 0) {
  1051. SetIasmHeader(piasm, op, 2, size = mpbitssize[GETBITS(wExt, 3, 10)]);
  1052. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  1053. size);
  1054. /* Then, it must be "FOP FPm,FPn". */
  1055. } else {
  1056. SetIasmHeader(piasm, op, 2, size = sizeEXTENDED);
  1057. SetEa(&piasm->oper1, modeFREG, GETBITS(wInstr, 3, 10), sizeEXTENDED);
  1058. }
  1059. if (op == opFSINCOS) {
  1060. /* Set the destination FPc:FPs. */
  1061. SetEaRegPair(&piasm->oper2, eaFREGPAIR, GETBITS(wExt, 3, 0),
  1062. GETBITS(wExt, 3, 7));
  1063. } else {
  1064. /* Set the destination floating point register. */
  1065. SetEa(&piasm->oper2, modeFREG, GETBITS(wExt, 3, 7), size);
  1066. }
  1067. }
  1068. void
  1069. BuildFMoveFPcr(
  1070. IASM *piasm,
  1071. unsigned short wInstr,
  1072. unsigned short wExt)
  1073. {
  1074. /* This function build the intermediate 68000 assembly language instruction
  1075. for the "FMOVE FPcr,<ea>" and "FMOVE <ea>,FPcr" instructions. */
  1076. /* Set the header for this instruction. */
  1077. SetIasmHeader(piasm, opFMOVE, 2, sizeLONG);
  1078. /* Is this instruction "FMOVE <ea>,FPcr"? */
  1079. if (GETBITS(wExt, 1, 14) != 0) {
  1080. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  1081. sizeLONG);
  1082. SetEa(&piasm->oper2, modeSREG, GETBITS(wExt, 3, 10), sizeLONG);
  1083. /* Then, it must be "FMOVE FPcr,<ea>". */
  1084. } else {
  1085. SetEa(&piasm->oper1, modeSREG, GETBITS(wExt, 3, 10), sizeLONG);
  1086. SetEa(&piasm->oper2, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  1087. sizeLONG);
  1088. }
  1089. }
  1090. void
  1091. BuildFMovem(
  1092. IASM *piasm,
  1093. unsigned short wInstr,
  1094. unsigned short wExt)
  1095. {
  1096. /* This function build the intermediate 68000 assembly language instruction
  1097. for the FMOVEM instruction. */
  1098. unsigned size;
  1099. unsigned mode;
  1100. unsigned long reglist;
  1101. /* Determine the mode of the effective address. */
  1102. mode = GETBITS(wInstr, 3, 3);
  1103. /* Are we moving floating point control registers? */
  1104. if (GETBITS(wExt, 8, 0) == 0) {
  1105. size = sizeLONG;
  1106. reglist = (unsigned long)GETBITS(wExt, 3, 10) << 24;
  1107. /* Then we must be moving floating point registers. */
  1108. } else {
  1109. size = sizeEXTENDED;
  1110. /* The register list is read from the instruction stream and reversed if
  1111. the addressing mode is not predecrement. */
  1112. reglist = mode != modePREDEC ? WReverse(wExt) << 8 : wExt << 16;
  1113. }
  1114. /* Set the header for this instruction. */
  1115. SetIasmHeader(piasm, opFMOVEM, 2, size);
  1116. /* Are we moving from the registers? */
  1117. if (GETBITS(wInstr, 1, 13) != 0) {
  1118. SetEaImmed(&piasm->oper1, eaREGLIST, reglist);
  1119. SetEa(&piasm->oper2, mode, GETBITS(wInstr, 3, 0), sizeEXTENDED);
  1120. /* We must be moving to the registers. */
  1121. } else {
  1122. SetEa(&piasm->oper1, mode, GETBITS(wInstr, 3, 0), sizeEXTENDED);
  1123. SetEaImmed(&piasm->oper2, eaREGLIST, reglist);
  1124. }
  1125. }
  1126. void
  1127. BuildFDbcc(
  1128. IASM *piasm,
  1129. unsigned short wInstr,
  1130. unsigned short wDummy)
  1131. {
  1132. /* This function build the intermediate 68000 assembly language instruction
  1133. for the FDBcc instructions. */
  1134. unsigned short wExt = WFetch();
  1135. SetIasmHeader(piasm, opFDBcc + GETBITS(wExt, 6, 0), 2, sizeNULL);
  1136. SetEa(&piasm->oper1, modeDREG, GETBITS(wInstr, 3, 0), sizeNULL);
  1137. SetEaLabel(&piasm->oper2, (long)(short)WFetch() + 2L);
  1138. }
  1139. void
  1140. BuildFScc(
  1141. IASM *piasm,
  1142. unsigned short wInstr,
  1143. unsigned short wDummy)
  1144. {
  1145. /* This function build the intermediate 68000 assembly language instruction
  1146. for the FScc instructions. */
  1147. unsigned short wExt = WFetch();
  1148. SetIasmHeader(piasm, opFScc + GETBITS(wExt, 6, 0), 1, sizeBYTE);
  1149. SetEa(&piasm->oper1, GETBITS(wInstr, 3, 3), GETBITS(wInstr, 3, 0),
  1150. sizeBYTE);
  1151. }
  1152. void
  1153. BuildFTrapcc(
  1154. IASM *piasm,
  1155. unsigned short wInstr,
  1156. unsigned short wDummy)
  1157. {
  1158. /* This function build the intermediate 68000 assembly language instruction
  1159. for the FTRAPcc instructions. */
  1160. unsigned size;
  1161. /* Does the instruction have an argument? */
  1162. if ((size = GETBITS(wInstr, 3, 0) - 1) == sizeNULL) {
  1163. SetIasmHeader(piasm, opFScc + GETBITS(WFetch(), 6, 0), 0, sizeNULL);
  1164. } else if (size != sizeWORD && size != sizeLONG) {
  1165. SetIasmHeader(piasm, opNULL, 0, sizeNULL);
  1166. /* Determine what the argument is. */
  1167. } else {
  1168. SetIasmHeader(piasm, opFScc + GETBITS(WFetch(), 6, 0), 1, size);
  1169. SetEa(&piasm->oper1, modeSPECIAL, regIMMED, size);
  1170. }
  1171. }
  1172. void
  1173. BuildFBcc(
  1174. IASM *piasm,
  1175. unsigned short wInstr,
  1176. unsigned short wDummy)
  1177. {
  1178. /* This function build the intermediate 68000 assembly language instruction
  1179. for the FBcc instructions. */
  1180. unsigned size;
  1181. long disp;
  1182. /* Read the displacment for the branch. */
  1183. if (GETBITS(wInstr, 1, 6) != 0) {
  1184. size = sizeLONG;
  1185. disp = (long)((unsigned long)WFetch() << 16) | (unsigned long)WFetch();
  1186. } else {
  1187. size = sizeWORD;
  1188. disp = (long)(short)WFetch();
  1189. }
  1190. /* Build the intermediate instruction. */
  1191. SetIasmHeader(piasm, opFBcc + GETBITS(wInstr, 6, 0), 1, size);
  1192. SetEaLabel(&piasm->oper1, disp + 2L);
  1193. }
  1194. void
  1195. BuildFNop(
  1196. IASM *piasm,
  1197. unsigned short wInstr,
  1198. unsigned short wDummy)
  1199. {
  1200. /* This function build the intermediate 68000 assembly language instruction
  1201. for the FNOP instruction. */
  1202. unsigned short wExt = WFetch();
  1203. SetIasmHeader(piasm, opFNOP, 0, sizeNULL);
  1204. }
  1205. #ifdef TRAP_NAMES
  1206. #include "trpd.h"
  1207. extern TRPD rgtrpd[];
  1208. extern int ctrpd;
  1209. int
  1210. ItrpdFromTrp(
  1211. unsigned short trp)
  1212. {
  1213. int itrpdLower = 0;
  1214. int itrpdUpper = ctrpd - 1;
  1215. int itrpd;
  1216. // get rid of the option flags...
  1217. if(trp & 0x0800)
  1218. {
  1219. trp &= 0xf9ff; // toolbox trap
  1220. }
  1221. else
  1222. {
  1223. trp &= 0xf1ff; // os trap
  1224. }
  1225. // Conduct a binary search looking for the requested trap descriptor
  1226. while (itrpdLower <= itrpdUpper) {
  1227. itrpd = (itrpdLower + itrpdUpper) / 2;
  1228. if (trp < rgtrpd[itrpd].trp) {
  1229. itrpdUpper = itrpd - 1;
  1230. } else if (trp > rgtrpd[itrpd].trp) {
  1231. itrpdLower = itrpd + 1;
  1232. } else {
  1233. // The trap number was found; return the index.
  1234. return itrpd;
  1235. }
  1236. }
  1237. }
  1238. #endif