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".
5 #define RCSID5 "$Id: mach5.c,v 1.4 1994/06/24 13:41:21 ceriel Exp $"
8 * VAX-11 Machine dependent C declarations
11 /* Opcode of branch on reversed condition. */
12 #define rev_cond_branch(opc) ((opc) ^ 1)
14 /* Process one operand. */
17 register struct operand *p;
21 if (p->index_reg >= 0 && p->mode != DISPL) {
22 /* Indexed mode; emit */
23 emit1((INDEX_MODE << 4) | p->index_reg);
28 if (p->size == -2 && p->index_reg < 0) {
29 serror("register mode not allowed here");
31 emit1((REG_MODE << 4) | p->reg);
34 emit1((REGDEF_MODE << 4) | p->reg);
37 emit1((AI_MODE << 4) | p->reg);
40 emit1((AI_DEF_MODE << 4) | p->reg);
43 emit1((AD_MODE << 4) | p->reg);
47 /* Three possible sizes: 1, 2, and 4 (and 0, but this is
48 not implemented). Therefore, we need two bits in the
51 if (small(p->exp.typ == S_ABS && fitw(p->exp.val), 2)) {
52 /* We gained two bytes; see if we can gain another. */
53 if (small(fitb(p->exp.val), 1)) {
54 /* DISPLB_MODE or DISPLB_DEF_MODE */
55 emit1(((p->mode-4)<<4) | p->reg);
56 emit1((int)(p->exp.val));
59 /* DISPLW_MODE or DISPLW_DEF_MODE */
60 emit1(((p->mode-2)<<4) | p->reg);
61 emit2((int)(p->exp.val));
64 else { /* We need 4 bytes here. */
65 small(0, 1); /* dummy call too keep bits in sync */
66 emit1((p->mode<<4) | p->reg);
68 RELOMOVE(relonami, p->relo);
69 newrelo(p->exp.typ, RELO4);
71 emit4((long) p->exp.val);
75 /* A displacement. The p->size field contains the size. */
76 p->exp.val -= (DOTVAL + p->size);
77 if ((pass == PASS_2) &&
79 ((p->exp.typ & S_DOT) == 0)
81 p->exp.val -= DOTGAIN;
83 if (p->size == 1) sm = fitb(p->exp.val);
84 else if (p->size == 2) sm = fitw(p->exp.val);
87 ((p->exp.typ & ~S_DOT) != DOTTYP || !sm)) {
88 serror("label too far");
90 if (p->size == 1) emit1((int)(p->exp.val));
91 else if (p->size == 2) emit2((int)(p->exp.val));
94 RELOMOVE(relonami, p->relo);
95 newrelo(p->exp.typ, RELO4|RELPC);
101 /* Immediate mode; either literal mode or auto-increment
105 serror("immediate mode not allowed here");
108 else if (p->size == 0) {
109 serror("this immediate mode is not implemented");
112 if (small(p->exp.typ == S_ABS && literal(p->exp.val), p->size)){
113 emit1((int)(p->exp.val));
116 emit1((AI_MODE << 4) | PC);
117 RELOMOVE(relonami, p->relo);
121 newrelo(p->exp.typ, RELO1);
123 emit1((int)(p->exp.val));
127 newrelo(p->exp.typ, RELO2);
129 emit2((int)(p->exp.val));
133 newrelo(p->exp.typ, RELO4);
143 /* Absolute mode (is auto-increment deferred with respect
144 to the program counter).
146 emit1((AI_DEF_MODE << 4) | PC);
148 RELOMOVE(relonami, p->relo);
149 newrelo(p->exp.typ, RELO4);
155 /* Relative or relative deferred is actually displacement
156 or displacement deferred, but relative to program counter.
158 if (p->mode == REL) p->mode = DISPLL_MODE;
159 else p->mode = DISPLL_DEF_MODE;
161 p->exp.val -= (DOTVAL + 2);
166 ((p->exp.typ & S_DOT) == 0)
168 p->exp.val -= DOTGAIN;
170 /* Why test for exp.val - 1? Well, if we need a word for
171 the offset, we actually generate one byte more, and this
172 is reflected in the value of the program counter.
174 sm = fitw(p->exp.val - 1);
175 if ((p->exp.typ & ~S_DOT) != DOTTYP) sm = 0;
177 if (small(fitb(p->exp.val), 1)) {
178 /* DISPLB_MODE or DISPLB_DEF_MODE */
179 emit1(((p->mode-4)<<4) | p->reg);
180 emit1((int)(p->exp.val));
183 /* DISPLW_MODE or DISPLW_DEF_MODE */
184 emit1(((p->mode-2)<<4) | p->reg);
185 /* exp.val - 1: see comment above */
186 emit2((int)(p->exp.val - 1));
190 small(0, 1); /* dummy call */
191 emit1((p->mode<<4) | p->reg);
193 RELOMOVE(relonami, p->relo);
194 newrelo(p->exp.typ, RELO4|RELPC);
196 /* exp.val - 3: see comment above */
197 emit4((long) p->exp.val - 3);
205 /* Give an upper bound on the size of the operands */
209 register struct operand *p = &opnd[0];
213 for (i = op_ind; i > 0; i--) {
214 if (p->index_reg >= 0 && p->mode != DISPL) {
226 case DISPLL_DEF_MODE:
243 /* Branch with byte or word offset */
247 exp.val -= (DOTVAL + 2);
248 if ((pass == PASS_2) &&
250 ((exp.typ & S_DOT) == 0)
254 /* For the reason of exp.val-1, see the comment at the generation
255 of the RELative addressing mode.
257 if (pass >= PASS_2 &&
258 ((exp.typ & ~S_DOT) != DOTTYP || ! fitw(exp.val - 1))) {
259 serror("label too far");
261 if (small(fitb(exp.val) && ((exp.typ & ~S_DOT) == DOTTYP), 1)) {
263 emit1((int) exp.val);
267 emit2((int) (exp.val - 1));
271 /* Extended conditional branch instructions: if offset is too far,
272 they are replaced by a reversed conditional branch over a word-branch or
279 int gain = opc == BRB ? 1 : 3;
280 valu_t val, d2 = DOTVAL + 2;
283 if ((pass == PASS_2) &&
285 ((exp.typ & S_DOT) == 0)
289 /* We have not generated the operands yet and cannot do so
290 because we don't know the opcode yet and have to generate that
291 first. Therefore, we make a conservative guess of the size
292 of the operands in case the branch is backwards. If it is
293 forwards, the (sizes of the) operands do not matter.
295 if (exp.val < 0) val = exp.val - size_ops();
298 if ((exp.typ & ~S_DOT) != DOTTYP) sm = 0;
299 /* We gain three bytes if the offset fits in a word; for a
300 jump we also need an addressing mode byte.
303 /* Here we can gain 3 bytes if the extended branch is
304 conditional and the offset fits in a byte. Otherwise,
305 if the offset fits in a byte we gain 1 byte.
307 if (small(fitb(val), gain)) {
310 /* Adjust exp.val for operand sizes. Keep into account
311 that we already generated the opcode(!). This
312 accounts for the "+ 1" instead of "+ 2".
314 emit1((int) (exp.val - (DOTVAL + 1 - d2)));
318 emit1(rev_cond_branch(opc));
323 emit2((int) (exp.val - (DOTVAL + 2 - d2)));
327 small(0, gain); /* dummy call to keep bittab in sync */
329 emit1(rev_cond_branch(opc));
334 emit1((DISPLL_MODE << 4) | PC);
336 newrelo(exp.typ, RELO4|RELPC);
338 emit4(exp.val - (DOTVAL + 4 - d2));
342 /* Generate code for the operands */
347 for (i = 0; i < op_ind; i++) {