2 * (c) copyright 1987 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.8 1994/06/24 07:25:30 ceriel Exp $"
8 * INTEL 80386 special routines
14 if ((reg_1 & 070) || (param & ~070)) {
15 serror("bad operand");
20 if (reg_1 == 6 || (reg_1 & 040)) {
22 RELOMOVE(relonami, rel_1);
23 newrelo(exp_1.typ, RELO2);
33 RELOMOVE(relonami, rel_1);
34 newrelo(exp_1.typ, RELO2);
47 serror("bad operand");
51 emit1(0300 | param | (reg_1&07));
55 /* sib field use here */
56 emit1(mod_1 << 6 | param | 04);
59 else emit1(mod_1<<6 | param | (reg_1&07));
60 if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
61 /* ??? should this be protected by a call to "small" ??? */
63 RELOMOVE(relonami, rel_1);
64 newrelo(exp_1.typ, RELO4);
66 emit4((long)(exp_1.val));
68 else if (mod_1 == 1) {
69 emit1((int)(exp_1.val));
76 RELOMOVE(rel_1, rel_2);
87 serror("scaling not allowed in 16-bit mode");
112 rel_1 = rel_2; rel_2 = r;
114 op = op_1; op_1 = op_2; op_2 = op;
119 serror("bad operands");
127 bit = (sz&1) ? 0 : IS_R8;
128 if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
129 (is_reg(reg_2) && (reg_2 & IS_R8) != bit))
130 serror("register error");
131 if (! address_long) {
141 serror("register error");
142 if (rm_2 == 0 && reg_2 == 4) {
143 /* base register sp, no index register; use
144 indexed mode without index register
153 if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
154 if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
158 else if (small(0, 1)) {
164 serror("register error");
165 if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
166 if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
170 else if (small(0, 1)) {
180 /* Conditional branching; Full displacements are available
181 on the 80386, so the welknown trick with the reverse branch
182 over a jump is not needed here.
183 The only complication here is with the address size, which
184 can be set with a prefix. In this case, the user gets what
189 int saving = address_long ? 4 : 2;
191 if (opc == 0353) saving--;
192 dist = exp.val - (DOTVAL + 2);
193 if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
195 sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
196 if ((exp.typ & ~S_DOT) != DOTTYP)
198 if ((sm = small(sm,saving)) == 0) {
208 adsize_exp(exp, RELPC);
225 /* LOOP, JCXZ, etc. branch instructions.
226 Here, the offset just must fit in a byte.
230 dist = exp.val - (DOTVAL + 2);
231 if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
233 fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
243 if (is_segreg(reg_1)) {
244 /* segment register */
245 if ((reg_1 & 07) <= 3)
246 emit1(6 | opc | (reg_1&7)<<3);
249 emit1(0200 | opc | ((reg_1&7)<<3));
251 } else if (is_reg(reg_1)) {
252 /* normal register */
253 emit1(0120 | opc<<3 | (reg_1&7));
254 } else if (opc == 0) {
255 if (is_expr(reg_1)) {
256 if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
257 operand_long ? 3 : 1)) {
259 emit1((int)(exp_1.val));
263 RELOMOVE(relonami, rel_1);
264 opsize_exp(exp_1, 1);
268 emit1(0377); ea_1(6<<3);
271 emit1(0217); ea_1(0<<3);
275 opsize_exp(exp, nobyte)
280 newrelo(exp.typ, RELO1);
282 emit1((int)(exp.val));
284 else if (operand_long) {
286 newrelo(exp.typ, RELO4);
288 emit4((long)(exp.val));
292 newrelo(exp.typ, RELO2);
294 emit2((int)(exp.val));
298 adsize_exp(exp, relpc)
303 newrelo(exp.typ, RELO4 | relpc);
305 emit4((long)(exp.val));
309 newrelo(exp.typ, RELO2 | relpc);
311 emit2((int)(exp.val));
321 /* Add register to register or memory */
322 emit1(opc); ea_1((reg_2&7)<<3);
323 } else if (is_acc(reg_1) && is_expr(reg_2)) {
324 /* Add immediate to accumulator */
326 RELOMOVE(relonami, rel_2);
327 opsize_exp(exp_2, (opc&1));
328 } else if (is_expr(reg_2)) {
329 /* Add immediate to register or memory */
332 } else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
333 operand_long ? 3 : 1)) {
336 emit1(0203); opc &= ~1;
339 RELOMOVE(relonami, rel_2);
340 opsize_exp(exp_2, (opc&1));
341 } else if (is_reg(reg_1)) {
342 /* Add register or memory to register */
357 if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
359 emit1(0322 | (opc&1)); ea_1(opc&070);
360 } else if (is_expr(oreg)) {
361 if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
363 emit1(0320 | (opc&1)); ea_1(opc&070);
365 /* shift by byte count */
366 emit1(0300 | (opc & 1));
369 RELOMOVE(relonami, rel_2);
370 newrelo(exp_2.typ, RELO1);
372 emit1((int)(exp_2.val));
384 if ((opc&1) && is_reg(reg_1)) {
386 emit1(0100 | (opc&010) | (reg_1&7));
388 emit1(0376 | (opc&1));
398 if (is_expr(reg_1)) {
399 if (opc == (040+(0351<<8))) {
400 RELOMOVE(relonami, rel_1);
403 exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
405 RELOMOVE(relonami, rel_1);
406 adsize_exp(exp_1, RELPC);
409 emit1(0377); ea_1(opc&070);
418 if (! is_reg(reg_1) || is_acc(reg_2)) {
421 if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
422 emit1(0220 | (reg_2&7));
423 } else if (is_reg(reg_1)) {
424 emit1(0206 | opc); ea_2((reg_1&7)<<3);
434 if (is_reg(reg_2) || is_expr(reg_1))
436 if (is_expr(reg_2)) {
439 RELOMOVE(relonami, rel_2);
440 opsize_exp(exp_2, (opc&1));
445 RELOMOVE(relonami, rel_2);
446 opsize_exp(exp_2, (opc&1));
448 } else if (is_reg(reg_1)) {
449 emit1(0204 | opc); ea_2((reg_1&7)<<3);
459 if (is_segreg(reg_1)) {
460 /* to segment register */
461 emit1(0216); ea_2((reg_1&07)<<3);
462 } else if (is_segreg(reg_2)) {
463 /* from segment register */
464 emit1(0214); ea_1((reg_2&07)<<3);
465 } else if (is_expr(reg_2)) {
469 emit1(0260 | opc<<3 | (reg_1&7));
472 emit1(0306 | opc); ea_1(0<<3);
474 RELOMOVE(relonami, rel_2);
475 opsize_exp(exp_2, (opc&1));
476 } else if (rm_1 == 05 && is_acc(reg_2)) {
477 /* from accumulator to memory (displacement) */
479 RELOMOVE(relonami, rel_1);
480 adsize_exp(exp_1, 0);
481 } else if (rm_2 == 05 && is_acc(reg_1)) {
482 /* from memory (displacement) to accumulator */
484 RELOMOVE(relonami, rel_2);
485 adsize_exp(exp_2, 0);
486 } else if (is_reg(reg_2)) {
487 /* from register to memory or register */
488 emit1(0210 | opc); ea_1((reg_2&07)<<3);
489 } else if (is_reg(reg_1)) {
490 /* from memory or register to register */
491 emit1(0212 | opc); ea_2((reg_1&07)<<3);
505 if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
510 else if (is_expr(oreg2)) {
514 RELOMOVE(relonami, rel_2);
515 newrelo(exp_2.typ, RELO1);
517 emit1((int)(exp_2.val));
527 if (is_expr(reg_2)) {
531 RELOMOVE(relonami, rel_2);
532 newrelo(exp_2.typ, RELO1);
534 emit1((int)(exp_2.val));
536 else if (is_reg(reg_2)) {
537 emit1(0203 | (opc<<3));
546 /* This instruction is more elaborate on the 80386. Its most
548 imul reg, reg_or_mem, immediate.
549 This is the form processed here.
552 if (is_expr(reg_1)) {
554 imul reg, immediate, reg_or_mem
558 if (is_expr(reg_2)) {
559 /* The immediate form; two cases: */
560 if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
561 operand_long ? 3 : 1)) {
562 /* case 1: 1 byte encoding of immediate */
564 ea_1((reg & 07) << 3);
565 emit1((int)(exp_2.val));
568 /* case 2: WORD or DWORD encoding of immediate */
570 ea_1((reg & 07) << 3);
571 RELOMOVE(relonami, rel_2);
572 opsize_exp(exp_2, 1);
575 else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
576 /* the "reg" field and the "reg_or_mem" field are the same,
577 and the 3rd operand is not an immediate ...
580 /* how lucky we are, the target is the ax register */
581 /* However, we cannot make an optimization for f.i.
583 because the latter does not affect edx, whereas
585 does! Therefore, "reg" is or-ed with 0x10 in the
586 former case, so that the test above fails.
592 /* another register ... */
595 ea_2((reg & 07) << 3);