Pristine Ack-5.5
[Ack-5.5.git] / mach / sun3 / ce / as.c
1 #include <string.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include "as.h"
5 #include "arg_type.h"
6
7
8 process_label() {}
9
10
11 process_mnemonic( m)
12 char *m;
13 {
14         for ( ; *m != '\0'; m++)
15                 if ( *m == '.')
16                         *m = '_';
17 }
18
19
20 process_operand( str, op)
21 register char *str;
22 register struct t_operand *op;
23 {
24         char *glob_lbl(), *strindex();
25
26         op->type = 0;
27
28         switch ( *str) {
29           case '#' : op->type = IS_IMMEDIATE;
30                      op->expr = str+1;
31
32                      if ( *(op->expr) != '$') {                 /*  #1  */
33                         op->val = atoi( str+1);
34                         if ( 1 <= op->val  &&  op->val <= 8 ) {
35                                 op->type = IS_QUICK;
36                                 op->lbl = NULL;
37                         }
38                      }
39                      else 
40                         if ( arg_type( str+1) == STRING) {      /*  #$1+$2  */
41                                 op->lbl = op->expr;
42                                 *(op->lbl+2) = '\0';
43                                 op->expr = op->lbl+3;
44                         }
45                         else                                    /*  #$1  */
46                                 op->lbl = NULL;
47                      break;
48
49           case '(' : if ( strindex( str+1, ',') == NULL)
50                         if ( is_reg( str+1)) {
51                                 op->reg = reg_val( str+1);
52
53                                 if ( *(str+4) == '+')           /*  (sp)+  */
54                                         op->type = IS_INCR;
55                                 else                            /*  (a0)  */
56                                         op->type = IS_IND_REG;
57                         }
58                         else {
59                                 op->type = IS_IND_MEM;
60                                 op->expr = str+1;
61                                 for ( str++; *++str != ')';)
62                                         ;
63                                 *str = '\0';
64
65                                 if ( *(op->expr) == '$')
66                                         if ( arg_type( op->expr) == STRING) {
67                                                                 /*  ($1+$2)  */
68                                                 op->lbl = op->expr;
69                                                 if ( strlen( op->lbl) == 2) 
70                                                         op->expr = "0";
71                                                 else {
72                                                         *(op->lbl+2) = '\0';
73                                                         op->expr = op->lbl+3;
74                                                 }
75                                         }
76                                         else                    /*  ($1)  */
77                                                 op->lbl = NULL;
78                                 else if ( isdigit( *(op->expr))) /*  (1)  */
79                                         op->lbl = NULL;
80                                 else {                          /*  (.trppc) */
81                                         op->lbl = glob_lbl( op->expr);
82                                         op->expr = "0";
83                                 }
84                         }
85                      else
86                         if ( *(str+1) == '[') {
87                                 op->type = IS_IND_IND;
88                                 op->expr = str+2;
89                                 for ( str += 2; *++str != ',';)
90                                         ;
91                                 *str++ = '\0';
92                                 for ( ; *str == ' '; str++)
93                                         ;
94                                 op->reg = reg_val( str);
95
96                                 for ( ; *str++ != ']';)
97                                         ;
98                                 if ( *str == ')')       /*  ([$1, a6])  */
99                                         op->expr2 = 0;
100                                 else {                  /*  ([8,a6],8)  */
101                                         for ( ; *str++ != ',';)
102                                                 ;
103                                         for ( ; *str == ' '; str++)
104                                                 ;
105                                         op->expr2 = atoi( str);
106                                 }
107                         }
108                         else {
109                                 op->expr = str+1;
110                                 for ( str++; *++str != ',';)
111                                         ;
112                                 *str++ = '\0';
113                                 for ( ; *str == ' '; str++)
114                                         ;
115                                 op->reg = reg_val( str);
116                                 if ( *(str+2) == ')')           /*  (4, a0)  */
117                                         op->type = IS_IND_REG_DISPL;
118                                 else {                   /*  (0, sp, d0.l*1)  */
119                                         op->type = IS_3_OPS;
120                                         for ( str++; *++str != ',';)
121                                                 ;
122                                         for ( ; *str == ' '; str++)
123                                                 ;
124                                         op->reg2 = reg_val( str);
125
126                                         for ( ; *str++ != '*';)
127                                                 ;
128                                         op->scale = atoi( str);
129                                 }
130                         }
131                      break;
132
133           case '-' : op->type = IS_DECR;                        /*  -(sp)  */
134                      op->reg = reg_val( str+2);
135                      break;
136
137           case '$' : op->type = IS_GLOB_LBL;                    /*  $1  */
138                      op->lbl = str;
139                      op->expr ="0";
140                      break;
141
142           default  : if ( is_reg( str)) {
143                         op->reg = reg_val( str);
144                         if ( *(str+2) == ':') {                 /*  d2:d1  */
145                                 op->type = IS_REG_PAIR;
146                                 op->reg2 = reg_val( str+3);
147                         }
148                         else                                    /*  a6  */
149                                 op->type = ( *str == 'd' ? IS_D_REG : IS_A_REG);
150                      }
151                      else if ( isdigit( *str)) {                /*  1f  */
152                         op->type = IS_LOC_LBL;
153                         op->lbl = str;
154                         op->expr = "0";
155                         *(str+1) ='\0';
156                      }
157                      else {                                     /*  .strhp  */
158                         op->type = IS_GLOB_LBL;
159                         op->lbl = glob_lbl( str);
160                         *(str+1) ='\0';
161                         op->expr = "0";
162                      }
163         }
164 }
165
166
167 int reg_val( reg)
168 char *reg;
169 {
170         return( *reg == 's' ? 7 : atoi( reg+1));
171 }
172
173 int is_reg( str)
174 register char *str;
175 {
176         switch ( *str) {
177           case 'a' :
178           case 'd' : return( isdigit( *(str+1)));
179
180           case 's' : return( *(str+1) == 'p');
181
182           default  : return( 0);
183         }
184 }
185
186
187 char *glob_lbl( lbl)
188 char *lbl;
189 {
190         char *gl, *Malloc();
191
192         gl = Malloc( strlen( lbl) + 3);
193         sprintf( gl, "\"%s\"", lbl);
194         return( gl);
195 }
196
197
198 /******************************************************************************/
199
200
201 int mode_reg( eaddr)
202 register struct t_operand *eaddr;
203 {
204         switch ( eaddr->type) {
205           case IS_A_REG         : return( 0x08 | eaddr->reg);
206
207           case IS_D_REG         : return( 0x00 | eaddr->reg);
208
209           case IS_IND_REG       : return( 0x10 | eaddr->reg);
210
211           case IS_INCR          : return( 0x18 | eaddr->reg);
212
213           case IS_DECR          : return( 0x20 | eaddr->reg);
214
215           case IS_IND_MEM       : return( 0x39);
216
217           case IS_IND_IND       : return( 0x30 | eaddr->reg);
218
219           case IS_IND_REG_DISPL : return( 0x28 | eaddr->reg);
220
221           case IS_GLOB_LBL      : return( 0x39);
222
223           case IS_3_OPS         : if ( isdigit( *(eaddr->expr)) &&
224                                                     atoi( eaddr->expr) < 128)
225                                         return( 0x30 | eaddr->reg);
226                                   else
227                                         fprintf( stderr, "FOUT in IS_3_OPS\n");
228                                   break;
229
230           case IS_QUICK         :
231           case IS_IMMEDIATE     : return( 0x3c);
232
233           default               : fprintf( stderr,
234                                            "mode_reg(), verkeerde operand %d\n",
235                                            eaddr->type);
236                                   abort();
237                                   break;
238         }
239 }
240
241
242 code_extension( eaddr)
243 register struct t_operand *eaddr;
244 {
245
246         switch ( eaddr->type) {
247           case IS_IND_MEM       : if ( eaddr->lbl == NULL) 
248                                         @text4( %$( eaddr->expr));
249                                   else
250                                         @reloc4( %$( eaddr->lbl),
251                                                  %$( eaddr->expr),
252                                                  ABSOLUTE);
253                                   break;
254
255           case IS_IND_IND       : if ( eaddr->expr2 == 0) {
256                                         @text2( 0x161);
257                                         @text2( %$(eaddr->expr));
258                                   }
259                                   else {
260                                         @text2( 0x162);
261                                         @text2( %$(eaddr->expr));
262                                         @text2( %d(eaddr->expr2));
263                                   }
264                                   break;
265
266           case IS_IND_REG_DISPL : @text2( %$( eaddr->expr));
267                                   break;
268
269           case IS_GLOB_LBL      : @reloc4( %$(eaddr->lbl),
270                                            %$(eaddr->expr),
271                                            ABSOLUTE);
272                                   break;
273
274           case IS_3_OPS         : if ( isdigit( *(eaddr->expr)) &&
275                                                     atoi( eaddr->expr) < 128) {
276
277                                         @text2( %d( 0x0800 |
278                                                   ( eaddr->reg2 << 12) |
279                                                   ( two_log( eaddr->scale)<<9) |
280                                                   atoi( eaddr->expr)));
281                                   }
282                                   else
283                                         fprintf( stderr, "FOUT in IS_3_OPS\n");
284                                   break;
285
286           case IS_QUICK         :
287           case IS_IMMEDIATE     : if ( eaddr->lbl != NULL)
288                                         @reloc4( %$(eaddr->lbl),
289                                                  %$(eaddr->expr),
290                                                  ABSOLUTE);
291                                   else
292                                         @text4( %$(eaddr->expr));
293         }
294 }
295
296
297 int reg_mode( eaddr)
298 struct t_operand *eaddr;
299 {
300         int mr;
301
302         mr = mode_reg( eaddr);
303         return( ((mr & 0x7) << 3) | ((mr & 0x38) >> 3));
304 }
305
306
307 code_opcode( opcode, field1, field2, eaddr)
308 int opcode, field1, field2;
309 struct t_operand *eaddr;
310 {
311         @text2( %d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) |
312                    ((field2 & 0x7) << 6) | (mode_reg(eaddr) & 0x3f)));
313 }
314
315
316 code_instr( opcode, field1, field2, eaddr)
317 int opcode, field1, field2;
318 struct t_operand *eaddr;
319 {
320         if (eaddr->type == IS_IND_REG_DISPL) {
321                 @__instr_code(%d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) |
322                                 ((field2 & 0x7) << 6)),
323                               %d(eaddr->reg), %$(eaddr->expr));
324         }
325         else {
326                 code_opcode( opcode, field1, field2, eaddr);
327                 code_extension( eaddr);
328         }
329 }
330
331
332 code_move( size, src, dst)
333 int size;
334 struct t_operand *src, *dst;
335 {
336         if (src->type == IS_IND_REG_DISPL) {
337                 if (dst->type == IS_IND_REG_DISPL) {
338                         @__moveXX(%d( ((size & 0x3) << 12)),
339                                  %d(dst->reg), %$(dst->expr),
340                                  %d(src->reg), %$(src->expr));
341                 }
342                 else {
343                         @__instr_code(%d( ((size & 0x3) << 12)|((reg_mode( dst) & 0x3f) << 6)),
344                                  %d(src->reg), %$(src->expr));
345                 }
346         }
347         else if (dst->type == IS_IND_REG_DISPL) {
348                 @__move_X(%d( ((size & 0x3) << 12) | (mode_reg( src) & 0x3f)),
349                          %d(dst->reg), %$(dst->expr));
350         }
351         else {
352                 @text2( %d( ((size & 0x3) << 12) | ((reg_mode( dst) & 0x3f) << 6) |
353                                            (mode_reg( src) & 0x3f)));
354                 code_extension( src);
355                 code_extension( dst);
356         }
357 }
358
359
360 code_dist4( dst)
361 struct t_operand *dst;
362 {
363         @reloc4( %$(dst->lbl), %$(dst->expr) + 4, PC_REL);
364 }
365
366
367 int two_log( nr)
368 register int nr;
369 {
370         register int log;
371
372         for ( log = 0; nr >= 2; nr >>= 1)
373                 log++;
374
375         return( log);
376 }