Pristine Ack-5.5
[Ack-5.5.git] / mach / i86 / ce / as.c
1 #include "arg_type.h"
2 #include "as.h"
3
4 static struct t_operand dummy = { IS_REG, AX, 0, 0, 0};
5 struct t_operand saved_op, *AX_oper = &dummy; 
6
7 save_op( op)
8 struct t_operand *op;
9 {
10         saved_op.type = op->type;
11         saved_op.reg = op->reg;
12         saved_op.expr = op->expr;
13         saved_op.lab = op->lab;
14         saved_op.off = op->off;
15 }
16
17 #define last( s)        ( s + strlen( s) - 1)
18 #define LEFT    '('
19 #define RIGHT   ')'
20 #define DOLLAR  '$'
21
22 block_assemble( instr, nr, first, Last)
23 char **instr;
24 int nr, first, Last;
25 {
26         int i;
27
28         if ( first) {
29                 if( strncmp( instr[0], "pop", 3) == 0) {
30                         *instr[0] = 'P';
31                         *( instr[0]+1) = 'O';
32                         *( instr[0]+2) = 'P';
33                 }
34                 else
35                         @clean_push_buf();
36         }
37         if ( Last && strncmp( instr[nr-1], "push", 4) == 0) {
38                         *instr[nr-1] = 'P';
39                         *( instr[nr-1]+1) = 'U';
40                         *( instr[nr-1]+2) = 'S';
41                         *( instr[nr-1]+3) = 'H';
42         }
43
44         for( i=0; i<nr; i++)
45                 assemble( instr[i]);
46 }
47                 
48
49 process_label( l)
50 char *l;
51 {
52 }
53
54
55 process_mnemonic( m)
56 char *m;
57 {
58 }
59
60
61 process_operand( str, op)
62 char *str;
63 struct t_operand *op;
64
65 /*      expr            ->      IS_DATA en IS_LABEL
66  *      reg             ->      IS_REG en IS_ACCU
67  *      (expr)          ->      IS_ADDR
68  *      expr(reg)       ->      IS_MEM
69  */
70 {
71         char *ptr, *strindex();
72
73         op->type = UNKNOWN;
74         if ( *last( str) == RIGHT) {
75                 ptr = strindex( str, LEFT);
76                 *last( str) = '\0';
77                 *ptr = '\0';
78                 if ( is_reg( ptr+1, op)) {
79                         op->type = IS_MEM;
80                         op->expr = ( *str == '\0' ? "0" : str);
81                 }
82                 else {
83                         set_label( ptr+1, op);
84                         op->type = IS_ADDR;
85                 }
86         }
87         else
88                 if ( is_reg( str, op))
89                         op->type = IS_REG;
90                 else {
91                         if ( contains_label( str))
92                                 set_label( str, op);
93                         else {
94                                 op->type = IS_DATA;
95                                 op->expr = str;
96                         }
97                 }
98 }
99
100 int is_reg( str, op)
101 char *str;
102 struct t_operand *op;
103 {
104         if ( strlen( str) != 2)
105                 return( 0);
106
107         switch ( *(str+1)) {
108           case 'x' :
109           case 'l' : switch( *str) {
110                        case 'a' : op->reg = 0;
111                                   return( TRUE);
112
113                        case 'c' : op->reg = 1;
114                                   return( TRUE);
115
116                        case 'd' : op->reg = 2;
117                                   return( TRUE);
118
119                        case 'b' : op->reg = 3;
120                                   return( TRUE);
121
122                        default  : return( FALSE);
123                      }
124
125           case 'h' : switch( *str) {
126                        case 'a' : op->reg = 4;
127                                   return( TRUE);
128
129                        case 'c' : op->reg = 5;
130                                   return( TRUE);
131
132                        case 'd' : op->reg = 6;
133                                   return( TRUE);
134
135                        case 'b' : op->reg = 7;
136                                   return( TRUE);
137
138                        default  : return( FALSE);
139                      }
140
141           case 'p' : switch ( *str) {
142                        case 's' : op->reg = 4;
143                                   return( TRUE);
144
145                        case 'b' : op->reg = 5;
146                                   return( TRUE);
147
148                        default  : return( FALSE);
149                      }
150
151           case 'i' : switch ( *str) {
152                        case 's' : op->reg = 6;
153                                   return( TRUE);
154
155                        case 'd' : op->reg = 7;
156                                   return( TRUE);
157
158                        default  : return( FALSE);
159                      }
160
161           default  : return( FALSE);
162         }
163 }
164
165 #include <ctype.h>
166 #define  isletter( c)   ( isalpha( c) || c == '_')
167
168 int contains_label( str)
169 char *str;
170 {
171         while( !isletter( *str) && *str != '\0')
172                 if ( *str == '$')
173                         if ( arg_type( str) == STRING)
174                                 return( TRUE);
175                         else
176                                 str += 2;
177                 else
178                         str++;
179
180         return( isletter( *str));
181 }
182
183 set_label( str, op)
184 char *str;
185 struct t_operand *op;
186 {
187         char *ptr, *strindex(), *sprint();
188         static char buf[256];
189
190         ptr = strindex( str, '+');
191
192         if ( ptr == 0)
193                 op->off = "0";
194         else {
195                 *ptr = '\0';
196                 op->off = ptr + 1;
197         }
198
199         if ( isdigit( *str) && ( *(str+1) == 'b' || *(str+1) == 'f') &&
200              *(str+2) == '\0') {
201                 *(str+1) = '\0';        /* b of f verwijderen! */
202                 op->lab = str;
203                 op->type = IS_ILB;
204         }
205         else {
206                 op->type = IS_LABEL;
207                 if ( strindex( str, DOLLAR) != 0)
208                         op->lab = str;
209                 else 
210                         /* nood oplossing */
211                         op->lab = sprint( buf, "\"%s\"", str);
212         }
213 }
214
215
216 /******************************************************************************/
217
218
219
220 mod_RM( reg, op)
221 int reg;
222 struct t_operand *op;
223 {
224         if ( REG( op))
225                 R233( 0x3, reg, op->reg);
226         else if ( ADDR( op)) {
227                 R233( 0x0, reg, 0x6);
228                 @reloc2( %$(op->lab), %$(op->off), ABSOLUTE);
229         }
230         else if ( strcmp( op->expr, "0") == 0)
231                 switch( op->reg) {
232                   case SI : R233( 0x0, reg, 0x4);
233                             break;
234
235                   case DI : R233( 0x0, reg, 0x5);
236                             break;
237
238                   case BP : R233( 0x1, reg, 0x6);       /* Uitzondering! */
239                             @text1( 0);
240                             break;
241
242                   case BX : R233( 0x0, reg, 0x7);
243                             break;
244
245                   default : fprint( STDERR, "Wrong index register %d\n",
246                                     op->reg);
247                 }
248         else {
249                 @if ( fit_byte( %$(op->expr)))
250                         switch( op->reg) {
251                           case SI : R233( 0x1, reg, 0x4);
252                                     break;
253         
254                           case DI : R233( 0x1, reg, 0x5);
255                                     break;
256         
257                           case BP : R233( 0x1, reg, 0x6);
258                                     break;
259         
260                           case BX : R233( 0x1, reg, 0x7);
261                                     break;
262         
263                           default : fprint( STDERR, "Wrong index register %d\n",
264                                             op->reg);
265                         }
266                         @text1( %$(op->expr));
267                 @else
268                         switch( op->reg) {
269                           case SI : R233( 0x2, reg, 0x4);
270                                     break;
271         
272                           case DI : R233( 0x2, reg, 0x5);
273                                     break;
274         
275                           case BP : R233( 0x2, reg, 0x6);
276                                     break;
277         
278                           case BX : R233( 0x2, reg, 0x7);
279                                     break;
280         
281                           default : fprint( STDERR, "Wrong index register %d\n",
282                                             op->reg);
283                         }
284                         @text2( %$(op->expr));
285                 @fi
286         }
287 }
288
289 mov_REG_EADDR( dst, src)
290 struct t_operand *dst, *src;
291 {
292         if ( REG(src) && dst->reg == src->reg)
293                 ; /* Nothing!! result of push/pop optimization */
294         else {
295                 @text1( 0x8b);
296                 mod_RM( dst->reg, src);
297         }
298 }
299
300
301 R233( a, b, c)
302 int a,b,c;
303 {
304         @text1( %d( (a << 6) | ( b << 3) | c));
305 }
306
307
308 R53( a, b)
309 int a,b;
310 {
311         @text1( %d( (a << 3) | b));
312 }