* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / linux86-0.16.17 / bcc / longop.c
blob9f8acb3cbaff2c36c0618c94d872abda167ba7c7
1 /* longop.c - software operations on longs for bcc */
3 /* Copyright (C) 1992 Bruce Evans */
5 #include "bcc.h"
6 #include "byteord.h"
7 #include "gencode.h"
8 #include "reg.h"
9 #include "scan.h"
10 #include "type.h"
12 /*-----------------------------------------------------------------------------
13 longop(operation code, source leaf, target leaf)
14 handles all binary operations on longs
15 source and target must already have been converted to long,
16 (except source is int for shifts) and not more than singly indirect
17 hence they must be direct (in an index reg paired with DREG),
18 or singly indirect (local, global, or from an index reg)
19 -----------------------------------------------------------------------------*/
21 PUBLIC void longop(op, source, target)
22 op_pt op;
23 struct symstruct *source;
24 struct symstruct *target;
26 store_pt reglist;
27 store_t regmark;
28 bool_t shiftflag;
29 scalar_t scalar;
30 offset_T spmark;
32 pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG));
33 reguse &= ~reglist;
34 spmark = sp;
35 shiftflag = FALSE;
36 scalar = target->type->scalar;
37 if ((op_t) op == SLOP || (op_t) op == SROP)
38 shiftflag = TRUE;
39 else
40 scalar |= source->type->scalar;
41 if ((source->indcount == 0 && !shiftflag) ||
42 source->type->scalar & CHAR ||
43 source->storage & (BREG | DREG | OPREG | OPWORKREG))
45 pres2(source, target);
46 push(source);
48 if (!shiftflag)
49 address(source);
50 load(target, OPREG);
51 if (source->storage == CONSTANT && shiftflag)
53 if (scalar & UNSIGNED)
54 target->type = ultype;
55 if ((op_t) op == SLOP)
56 source->offset.offv = lslconst(source->offset.offv,
57 target->storage);
58 else
59 source->offset.offv = lsrconst(source->offset.offv,
60 target->storage, scalar & UNSIGNED);
61 if (source->offset.offv == 0)
62 goto shiftdone;
64 #ifdef I8088
65 /* This is ugly! But it works. I should be able to stop it being used
66 * by removing the char demotion. */
67 if (source->type->scalar & CHAR &&
68 !(source->storage & (BREG|DREG|DATREG1B))) {
69 load(source, DATREG1B);
70 outop2str("xor\tch,ch"); outnl();
71 source->storage = DATREG1;
73 #endif
74 load(source, OPWORKREG);
75 switch ((op_t) op)
77 case ADDOP:
78 call("ladd");
79 break;
80 case ANDOP:
81 call("land");
82 break;
83 case DIVOP:
84 call("ldiv");
85 break;
86 case EOROP:
87 call("leor");
88 break;
89 case EQOP:
90 call("lcmp");
91 break;
92 case MODOP:
93 call("lmod");
94 break;
95 case MULOP:
96 call("lmul");
97 break;
98 case OROP:
99 call("lor");
100 break;
101 case SLOP:
102 call("lsl");
103 break;
104 case SROP:
105 call("lsr");
106 break;
107 case SUBOP:
108 call("lsub");
109 break;
111 if (scalar & UNSIGNED)
113 outbyte('u');
114 target->type = ultype;
116 outlongendian();
118 shiftdone:
119 if ((reguse = regmark) & OPREG && op != EQOP)
120 load(target, getindexreg());
121 if (reglist)
123 #ifdef I8088
124 if (op == EQOP)
125 changesp(spmark, FALSE);
126 else
127 #endif
128 modstk(spmark);
129 poplist(reglist);
133 /*-----------------------------------------------------------------------------
134 long1op(operation code, target leaf)
135 handles all unary operations on longs except inc/dec
136 target must be not more than singly indirect
137 hence it must be direct (in an index reg paired with DREG),
138 or singly indirect (local, global, or from an index reg)
139 -----------------------------------------------------------------------------*/
141 PUBLIC void long1op(op, target)
142 op_pt op;
143 struct symstruct *target;
145 pushlist(reguse & OPREG);
146 load(target, OPREG);
147 if (op == NOTOP)
148 call("lcom");
149 else if (op == NEGOP)
150 call("lneg");
151 else
152 call("ltst");
153 outlongendian();
154 if (reguse & OPREG)
156 if (op != EQOP)
157 load(target, getindexreg());
158 poplist(reguse & OPREG);
162 PUBLIC void outlongendian()
164 #ifdef MC6809
165 outbyte('_');
166 #endif
167 #if DYNAMIC_LONG_ORDER
168 if (long_big_endian)
169 #endif
170 #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
171 outnbyte('b');
172 #endif
173 #if DYNAMIC_LONG_ORDER
174 else
175 #endif
176 #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
177 outnbyte('l');
178 #endif