mach5.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. #define RCSID5 "$Id$"
  6. /*
  7. * VAX-11 Machine dependent C declarations
  8. */
  9. /* Opcode of branch on reversed condition. */
  10. #define rev_cond_branch(opc) ((opc) ^ 1)
  11. /* Process one operand. */
  12. static
  13. oprnd(p)
  14. register struct operand *p;
  15. {
  16. int sm;
  17. if (p->index_reg >= 0 && p->mode != DISPL) {
  18. /* Indexed mode; emit */
  19. emit1((INDEX_MODE << 4) | p->index_reg);
  20. }
  21. switch(p->mode) {
  22. case REG_MODE:
  23. if (p->size == -2 && p->index_reg < 0) {
  24. serror("register mode not allowed here");
  25. }
  26. emit1((REG_MODE << 4) | p->reg);
  27. break;
  28. case REGDEF_MODE:
  29. emit1((REGDEF_MODE << 4) | p->reg);
  30. break;
  31. case AI_MODE:
  32. emit1((AI_MODE << 4) | p->reg);
  33. break;
  34. case AI_DEF_MODE:
  35. emit1((AI_DEF_MODE << 4) | p->reg);
  36. break;
  37. case AD_MODE:
  38. emit1((AD_MODE << 4) | p->reg);
  39. break;
  40. case DISPLL_MODE:
  41. case DISPLL_DEF_MODE:
  42. /* Three possible sizes: 1, 2, and 4 (and 0, but this is
  43. not implemented). Therefore, we need two bits in the
  44. optimize table.
  45. */
  46. if (small(p->exp.typ == S_ABS && fitw(p->exp.val), 2)) {
  47. /* We gained two bytes; see if we can gain another. */
  48. if (small(fitb(p->exp.val), 1)) {
  49. /* DISPLB_MODE or DISPLB_DEF_MODE */
  50. emit1(((p->mode-4)<<4) | p->reg);
  51. emit1((int)(p->exp.val));
  52. }
  53. else {
  54. /* DISPLW_MODE or DISPLW_DEF_MODE */
  55. emit1(((p->mode-2)<<4) | p->reg);
  56. emit2((int)(p->exp.val));
  57. }
  58. }
  59. else { /* We need 4 bytes here. */
  60. small(0, 1); /* dummy call too keep bits in sync */
  61. emit1((p->mode<<4) | p->reg);
  62. #ifdef RELOCATION
  63. RELOMOVE(relonami, p->relo);
  64. newrelo(p->exp.typ, RELO4);
  65. #endif
  66. emit4((long) p->exp.val);
  67. }
  68. break;
  69. case DISPL:
  70. /* A displacement. The p->size field contains the size. */
  71. p->exp.val -= (DOTVAL + p->size);
  72. if ((pass == PASS_2) &&
  73. (p->exp.val > 0) &&
  74. ((p->exp.typ & S_DOT) == 0)
  75. ) {
  76. p->exp.val -= DOTGAIN;
  77. }
  78. if (p->size == 1) sm = fitb(p->exp.val);
  79. else if (p->size == 2) sm = fitw(p->exp.val);
  80. else sm = 1;
  81. if (pass >= PASS_2 &&
  82. ((p->exp.typ & ~S_DOT) != DOTTYP || !sm)) {
  83. serror("label too far");
  84. }
  85. if (p->size == 1) emit1((int)(p->exp.val));
  86. else if (p->size == 2) emit2((int)(p->exp.val));
  87. else {
  88. #ifdef RELOCATION
  89. RELOMOVE(relonami, p->relo);
  90. newrelo(p->exp.typ, RELO4|RELPC);
  91. #endif
  92. emit4(p->exp.val);
  93. }
  94. break;
  95. case IMM:
  96. /* Immediate mode; either literal mode or auto-increment
  97. of program counter.
  98. */
  99. if (p->size < 0) {
  100. serror("immediate mode not allowed here");
  101. p->size = 4;
  102. }
  103. else if (p->size == 0) {
  104. serror("this immediate mode is not implemented");
  105. p->size = 4;
  106. }
  107. if (small(p->exp.typ == S_ABS && literal(p->exp.val), p->size)){
  108. emit1((int)(p->exp.val));
  109. }
  110. else {
  111. emit1((AI_MODE << 4) | PC);
  112. RELOMOVE(relonami, p->relo);
  113. switch(p->size) {
  114. case 1:
  115. #ifdef RELOCATION
  116. newrelo(p->exp.typ, RELO1);
  117. #endif
  118. emit1((int)(p->exp.val));
  119. break;
  120. case 2:
  121. #ifdef RELOCATION
  122. newrelo(p->exp.typ, RELO2);
  123. #endif
  124. emit2((int)(p->exp.val));
  125. break;
  126. case 4:
  127. #ifdef RELOCATION
  128. newrelo(p->exp.typ, RELO4);
  129. #endif
  130. emit4(p->exp.val);
  131. break;
  132. default:
  133. assert(0);
  134. }
  135. }
  136. break;
  137. case ABS:
  138. /* Absolute mode (is auto-increment deferred with respect
  139. to the program counter).
  140. */
  141. emit1((AI_DEF_MODE << 4) | PC);
  142. #ifdef RELOCATION
  143. RELOMOVE(relonami, p->relo);
  144. newrelo(p->exp.typ, RELO4);
  145. #endif
  146. emit4(p->exp.val);
  147. break;
  148. case REL:
  149. case REL_DEF:
  150. /* Relative or relative deferred is actually displacement
  151. or displacement deferred, but relative to program counter.
  152. */
  153. if (p->mode == REL) p->mode = DISPLL_MODE;
  154. else p->mode = DISPLL_DEF_MODE;
  155. p->reg = PC;
  156. p->exp.val -= (DOTVAL + 2);
  157. if ((pass == PASS_2)
  158. &&
  159. (p->exp.val > 0)
  160. &&
  161. ((p->exp.typ & S_DOT) == 0)
  162. ) {
  163. p->exp.val -= DOTGAIN;
  164. }
  165. /* Why test for exp.val - 1? Well, if we need a word for
  166. the offset, we actually generate one byte more, and this
  167. is reflected in the value of the program counter.
  168. */
  169. sm = fitw(p->exp.val - 1);
  170. if ((p->exp.typ & ~S_DOT) != DOTTYP) sm = 0;
  171. if (small(sm, 2)) {
  172. if (small(fitb(p->exp.val), 1)) {
  173. /* DISPLB_MODE or DISPLB_DEF_MODE */
  174. emit1(((p->mode-4)<<4) | p->reg);
  175. emit1((int)(p->exp.val));
  176. }
  177. else {
  178. /* DISPLW_MODE or DISPLW_DEF_MODE */
  179. emit1(((p->mode-2)<<4) | p->reg);
  180. /* exp.val - 1: see comment above */
  181. emit2((int)(p->exp.val - 1));
  182. }
  183. }
  184. else {
  185. small(0, 1); /* dummy call */
  186. emit1((p->mode<<4) | p->reg);
  187. #ifdef RELOCATION
  188. RELOMOVE(relonami, p->relo);
  189. newrelo(p->exp.typ, RELO4|RELPC);
  190. #endif
  191. /* exp.val - 3: see comment above */
  192. emit4((long) p->exp.val - 3);
  193. }
  194. break;
  195. default:
  196. assert(0);
  197. }
  198. }
  199. /* Give an upper bound on the size of the operands */
  200. static int
  201. size_ops()
  202. {
  203. register struct operand *p = &opnd[0];
  204. register int i;
  205. register int sz = 0;
  206. for (i = op_ind; i > 0; i--) {
  207. if (p->index_reg >= 0 && p->mode != DISPL) {
  208. sz++;
  209. }
  210. switch(p->mode) {
  211. case REG_MODE:
  212. case REGDEF_MODE:
  213. case AI_MODE:
  214. case AI_DEF_MODE:
  215. case AD_MODE:
  216. sz++;
  217. break;
  218. case DISPLL_MODE:
  219. case DISPLL_DEF_MODE:
  220. case REL:
  221. case REL_DEF:
  222. case IMM:
  223. sz += 5;
  224. break;
  225. case DISPL:
  226. sz += p->size;
  227. break;
  228. default:
  229. assert(0);
  230. }
  231. p++;
  232. }
  233. return sz;
  234. }
  235. /* Branch with byte or word offset */
  236. branch(opc, exp)
  237. expr_t exp;
  238. {
  239. exp.val -= (DOTVAL + 2);
  240. if ((pass == PASS_2) &&
  241. (exp.val > 0) &&
  242. ((exp.typ & S_DOT) == 0)
  243. ) {
  244. exp.val -= DOTGAIN;
  245. }
  246. /* For the reason of exp.val-1, see the comment at the generation
  247. of the RELative addressing mode.
  248. */
  249. if (pass >= PASS_2 &&
  250. ((exp.typ & ~S_DOT) != DOTTYP || ! fitw(exp.val - 1))) {
  251. serror("label too far");
  252. }
  253. if (small(fitb(exp.val) && ((exp.typ & ~S_DOT) == DOTTYP), 1)) {
  254. emit1(opc);
  255. emit1((int) exp.val);
  256. }
  257. else {
  258. emit1(opc|0x20);
  259. emit2((int) (exp.val - 1));
  260. }
  261. }
  262. /* Extended conditional branch instructions: if offset is too far,
  263. they are replaced by a reversed conditional branch over a word-branch or
  264. jump.
  265. */
  266. ext_branch(opc, exp)
  267. expr_t exp;
  268. {
  269. int sm;
  270. int gain = opc == BRB ? 1 : 3;
  271. valu_t val, d2 = DOTVAL + 2;
  272. exp.val -= d2;
  273. if ((pass == PASS_2) &&
  274. (exp.val > 0) &&
  275. ((exp.typ & S_DOT) == 0)
  276. ) {
  277. exp.val -= DOTGAIN;
  278. }
  279. /* We have not generated the operands yet and cannot do so
  280. because we don't know the opcode yet and have to generate that
  281. first. Therefore, we make a conservative guess of the size
  282. of the operands in case the branch is backwards. If it is
  283. forwards, the (sizes of the) operands do not matter.
  284. */
  285. if (exp.val < 0) val = exp.val - size_ops();
  286. else val = exp.val;
  287. sm = fitw(val);
  288. if ((exp.typ & ~S_DOT) != DOTTYP) sm = 0;
  289. /* We gain three bytes if the offset fits in a word; for a
  290. jump we also need an addressing mode byte.
  291. */
  292. if (small(sm, 3)) {
  293. /* Here we can gain 3 bytes if the extended branch is
  294. conditional and the offset fits in a byte. Otherwise,
  295. if the offset fits in a byte we gain 1 byte.
  296. */
  297. if (small(fitb(val), gain)) {
  298. emit1(opc);
  299. operands();
  300. /* Adjust exp.val for operand sizes. Keep into account
  301. that we already generated the opcode(!). This
  302. accounts for the "+ 1" instead of "+ 2".
  303. */
  304. emit1((int) (exp.val - (DOTVAL + 1 - d2)));
  305. }
  306. else {
  307. if (opc != BRB) {
  308. emit1(rev_cond_branch(opc));
  309. operands();
  310. emit1(3);
  311. }
  312. emit1(BRW);
  313. emit2((int) (exp.val - (DOTVAL + 2 - d2)));
  314. }
  315. }
  316. else {
  317. small(0, gain); /* dummy call to keep bittab in sync */
  318. if (opc != BRB) {
  319. emit1(rev_cond_branch(opc));
  320. operands();
  321. emit1(6);
  322. }
  323. emit1(JMP);
  324. emit1((DISPLL_MODE << 4) | PC);
  325. #ifdef RELOCATION
  326. newrelo(exp.typ, RELO4|RELPC);
  327. #endif
  328. emit4(exp.val - (DOTVAL + 4 - d2));
  329. }
  330. }
  331. /* Generate code for the operands */
  332. operands()
  333. {
  334. register int i;
  335. for (i = 0; i < op_ind; i++) {
  336. oprnd(&opnd[i]);
  337. }
  338. }