Pristine Ack-5.5
[Ack-5.5.git] / mach / ns / as / mach5.c
1 /*
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".
4  */
5 #define RCSID5 "$Id: mach5.c,v 0.3 1994/06/24 13:09:58 ceriel Exp $"
6
7 /*
8  * NS 16032 special routines
9  */
10
11 clrmode() {     /* clear the current mode */
12         mode_ptr->m_ndisp   = 0 ;
13 }
14
15 int ind_mode(type) {
16         switch ( type ) {
17         case 'b' :      return 0x1C ;
18         case 'w' :      return 0x1D ;
19         case 'd' :      return 0x1E ;
20         case 'q' :      return 0x1F ;
21         default :
22                         serror("illegal size indicator") ;
23                         return 0x1F ;
24         }
25 }
26
27 badsyntax() {
28
29         serror("bad operands");
30 }
31
32 ill_imm() {
33         serror("immediate operand not allowed") ;
34 }
35 /* Create  the output formats */
36 form2(id,sval) {
37         assert ( id_t1(id)==T_INT ) ;
38         emit1( id_g1(id) | 0xC | (id_op(id)<<4) | ((sval&1)<<7 ) ) ;
39         emit1( (sval>>1) | (mode1.m_mode<<3) ) ;
40 }
41
42 form3(id) {
43         assert ( id_t1(id)==T_INT ) ;
44         emit1( id_g1(id) | 0x7C | ((id_op(id)&1)<<7) ) ;
45         emit1( (id_op(id)>>1) | (mode1.m_mode<<3) ) ;
46 }
47
48 form4(id) {
49         assert ( id_t1(id)==T_INT && id_t2(id)==T_INT );
50         emit1( id_g2(id) | (id_op(id)<<2) | ((mode2.m_mode&3)<<6) ) ;
51         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
52 }
53
54 form5(id,sval) {
55         assert ( id_t1(id)==T_INT ) ;
56         emit1(0xE) ;
57         emit1( id_g1(id) | (id_op(id)<<2) | ((sval&1)<<7 ) ) ;
58         emit1( (sval>>1) ) ;
59 }
60
61 form7x(id,i_type) {
62         assert ( id_t1(id)==T_INT && id_t2(id)==T_INT );
63         emit1(0xCE) ;
64         emit1( i_type | (id_op(id)<<2) | ((mode2.m_mode&3)<<6) ) ;
65         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
66 }
67
68 form8(id,reg) {
69         assert ( id_t1(id)==T_INT ) ;
70         emit1( 0x2E | ((id_op(id)&3)<<6) ) ;
71         emit1( id_g1(id) | (id_op(id)&04) | (reg<<3) | ((mode2.m_mode&03)<<6) ) ;
72         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
73 }
74
75 form9(id,i_type,f_type) {
76         emit1(0x3E) ;
77         emit1( i_type | (f_type<<2) | (id_op(id)<<3) | ((mode2.m_mode&03)<<6) ) ;
78         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
79 }
80
81 form11(id) {
82         assert ( id_t1(id)==T_FL && id_t2(id)==T_FL && id_g1(id)==id_g2(id) );
83         emit1(0xBE) ;
84         emit1( id_g1(id) | (id_op(id)<<2) | ((mode2.m_mode&3)<<6) ) ;
85         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
86 }
87
88 form14(id,reg) {
89         assert ( id_t1(id)==T_INT ) ;
90         emit1(0x1E) ;
91         emit1( id_g1(id) | (id_op(id)<<2) | ((reg&1)<<7 ) ) ;
92         emit1( (reg>>1) | (mode1.m_mode<<3) ) ;
93 }
94
95 frm15_0(id,reg) {
96         assert ( id_t1(id)==T_INT ) ;
97         emit1(0x16 /* + slave<<5 */ ) ;
98         emit1( id_g1(id) | (id_op(id)<<2) | ((reg&1)<<7 ) ) ;
99         emit1( (reg>>1) | (mode1.m_mode<<3) ) ;
100 }
101
102 frm15_1(id,i_type,s_type) {
103         emit1(0x16 /* + slave<<5 */ ) ;
104         emit1( i_type | (s_type<<2) | (id_op(id)<<3) | ((mode2.m_mode&03)<<6) ) ;
105         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
106 }
107
108 frm15_5(id) {
109         assert(id_t1(id)==T_SLAVE&& id_t2(id)==T_SLAVE&& id_g1(id)==id_g2(id) );
110         emit1(0x16 /* + slave<<5 */ ) ;
111         emit1( id_g1(id) | (id_op(id)<<2) | ((mode2.m_mode&3)<<6) ) ;
112         emit1( (mode2.m_mode>>2) | (mode1.m_mode<<3) ) ;
113 }
114
115 gen1(id) {
116         if ( (mode1.m_mode&0x1C)==0x1C ) {
117                 emit1(mode1.m_index) ;
118         }
119         if ( mode1.m_mode==0x14 ) { /* Immediate */
120                 RELOMOVE(relonami, mode1.m_rel1);
121                 imm(id_g1(id),&mode1.m_expr1) ;
122         } else
123         if ( mode1.m_ndisp >0 ) {
124                 RELOMOVE(relonami, mode1.m_rel1);
125                 disp(&mode1.m_expr1, mode1.m_mode == 0x1B ? RELPC : 0) ;
126                 if ( mode1.m_ndisp >1 ) {
127                         RELOMOVE(relonami, mode1.m_rel2);
128                         disp(&mode1.m_expr2, 0) ;
129                 }
130         }
131 }
132
133 gengen(id) {
134         if ( (mode1.m_mode&0x1C)==0x1C ) {
135                 emit1(mode1.m_index) ;
136         }
137         if ( (mode2.m_mode&0x1C)==0x1C ) {
138                 emit1(mode2.m_index) ;
139         }
140         if ( mode1.m_mode==0x14 ) { /* Immediate */
141                 RELOMOVE(relonami, mode1.m_rel1);
142                 imm(id_g1(id),&mode1.m_expr1) ;
143         } else
144         if ( mode1.m_ndisp >0 ) {
145                 RELOMOVE(relonami, mode1.m_rel1);
146                 disp(&mode1.m_expr1, mode1.m_mode == 0x1B ? RELPC : 0) ;
147                 if ( mode1.m_ndisp >1 ) {
148                         RELOMOVE(relonami, mode1.m_rel2);
149                         disp(&mode1.m_expr2, 0) ;
150                 }
151         }
152         if ( mode2.m_mode==0x14 ) { /* Immediate */
153                 RELOMOVE(relonami, mode2.m_rel1);
154                 imm(id_g2(id),&mode2.m_expr1) ;
155         } else
156         if ( mode2.m_ndisp >0 ) {
157                 RELOMOVE(relonami, mode2.m_rel1);
158                 disp(&mode2.m_expr1, mode2.m_mode == 0x1B ? RELPC : 0) ;
159                 if ( mode2.m_ndisp >1 ) {
160                         RELOMOVE(relonami, mode2.m_rel2);
161                         disp(&mode2.m_expr2, 0) ;
162                 }
163         }
164 }
165
166 disp(expr, relpc) register expr_t *expr ; {
167         register sm1, sm2 ;
168
169         sm1=0 ; sm2=0 ;
170         if (DOTTYP >= 0x2 && DOTTYP<=0x7F &&
171 #ifdef ASLD
172             (pass==PASS_1 ? expr->typ==S_ABS : expr->typ!=S_VAR ) ) {
173 #else
174            expr->typ == S_ABS) {
175 #endif
176                 /* All non-text displacements are quad-sized.
177                    The algorithm currently used for minimizing the size
178                    (See CACM article) might generate assertion failures if
179                    any displacement it is trying to minimize increases during
180                    the assembly process. The only way to avoid increases
181                    like that is to fix the sizes of all displacements in
182                    non-text segments.
183                    If the framework included enough information one
184                    might detect in the first pass (0) whether the value
185                    of the expression depends on any symbols whose value
186                    might alter later on in the assembly process. In that case
187                    one could determine the right size in the first pass in
188                    most cases.
189                 */
190                 if ( fitd_b(expr->val) ) {
191                         sm1=1 ; sm2= 1 ;
192                 } else {
193                         if ( fitd_w(expr->val) ) sm2=1 ;
194                 }
195         }
196         sm1=small(sm1,1) ; sm2=small(sm2,2) ;
197 #ifdef RELOCATION
198         newrelo(expr->typ, RELO4|RELBR|RELWR|relpc);
199 #endif
200         if ( sm1 )      putdisp(expr->val,1) ;
201         else if ( sm2 ) putdisp(expr->val,2) ;
202         else            putdisp(expr->val,4) ;
203 }
204
205 putdisp(val,size) valu_t val ; {
206         switch ( size ) {
207         case 1 :
208                 emit1( ((int)val)&0x7F ) ;
209                 break ;
210         case 2 :
211                 emit1( ( (((int)val)>>8)&0x3F ) | 0x80 ) ;
212                 emit1( ((int)val)&0xFF ) ;
213                 break ;
214         case 4 :
215                 emit1( (((int)(val>>24)) | 0xC0) & 0xFF ) ;
216                 emit1( ((int)(val>>16)) & 0xFF ) ;
217                 emit1( (((int)val)>>8) & 0xFF ) ;
218                 emit1( ((int)val)&0xFF ) ;
219                 break ;
220         }
221 }
222
223 dot_adjust(expr) register expr_t *expr ; {
224         expr->val -= DOTVAL ;
225         if ( pass==PASS_2 ) {
226                 if ( (expr->typ&S_DOT) == 0 && expr->val>0 ) {
227                         expr->val -= DOTGAIN;
228                 }
229         }
230         if ( (expr->typ & ~S_DOT) == DOTTYP ) {
231                 expr->typ=S_ABS ;
232         } else {
233                 expr->typ=S_VAR ;
234         }
235 }
236
237 /* The idea of the following is:
238  * Give the assembler programmer a warning if he tries to store
239  * an immediate value in a field which is too small to fit in.
240  */
241
242 testsize(type,val) {
243 /* check if value fits in type */
244         switch( type ) {
245         case I_DOUBLE : return fit32(val);
246         case I_WORD   : return fit16(val);
247         case I_BYTE   : return fit8(val);
248         }
249 }
250
251 imm(i_type,expr) register expr_t *expr ; {
252 /* emit value of immediate expression , after check on FIT */
253         if (!testsize(i_type,(int)expr->val))
254                 warning("immediate operand too large");
255         switch( i_type ) {
256         case I_DOUBLE : 
257 #ifdef RELOCATION
258                         newrelo(expr->typ, RELO4|RELBR|RELWR);
259 #endif
260                         emit1( ((int)(expr->val>>24)) & 0xFF ) ;
261                         emit1( ((int)(expr->val>>16)) & 0xFF ) ;
262                         emit1( (((int)expr->val)>>8)  & 0xFF ) ;
263                         emit1(  ((int)expr->val)      & 0xFF ) ;
264                         break;
265         case I_WORD:
266 #ifdef RELOCATION
267                         newrelo(expr->typ, RELO2|RELBR);
268 #endif
269                         emit1( (((int)expr->val)>>8)  & 0xFF ) ;
270                         emit1(  ((int)expr->val)      & 0xFF ) ;
271                         break;
272         case I_BYTE:    
273 #ifdef RELOCATION
274                         newrelo(expr->typ, RELO1);
275 #endif
276                         emit1(  ((int)expr->val)      & 0xFF ) ;
277         }
278 }
279
280
281 reg_list(list,reverse) {
282         register rev_list, i ;
283         if ( !reverse ) {
284                 return list ;
285         }
286         rev_list= 0 ;
287         for ( i=0 ; i<8 ; i++ ) {
288                 if ( list & (1<<i) ) {
289                         rev_list |= 1<<(7-i) ;
290                 }
291         }
292         return rev_list ;
293 }
294 cpu_opt(indic) {
295         switch( indic ) {
296         case 'i' : return 1 ;
297         case 'f' : return 2 ;
298         case 'm' : return 4 ;
299         case 'c' : return 8 ;
300         default :
301                 serror("illegal cpu option %c",indic) ;
302                 return 0 ;
303         }
304 }
305
306 string_opt(indic) {
307         switch( indic ) {
308         case 'b' : return SO_BACKW ;
309         case 'u' : return SO_UNTIL ;
310         case 'w' : return SO_WHILE ;
311         default :
312                 serror("illegal string option %c",indic) ;
313                 return 0 ;
314         }
315 }