Pristine Ack-5.5
[Ack-5.5.git] / mach / vax4 / ce / as.c
1 #include <ctype.h>
2 #include "as.h"
3
4 #define DOLLAR  '$'
5 #define LEFT    '('      
6 #define RIGHT   ')'
7
8
9 /*****************************************************************************/
10
11 /* Een constraint-function */
12
13 cst( arg)
14 struct t_operand *arg;
15 {
16         return( arg->type == CONST);
17 }
18
19
20 /*****************************************************************************/
21
22
23 /*    decode_operand() recognizes the follwing assembly-argumnets:
24  
25         $cst                    : CONST
26         register                : REGISTER
27         -(register)             : AUTO_DEC
28         (register)+             : AUTO_INC
29         (register)              : REG_DEF
30         indx(register)          : IND_REG
31         label+offset            : LABEL
32         label[b|f]              : L_ILB
33  */
34
35
36 /* An assembly instruction has at most 5 arguments.
37  * This is for the time being.
38  */
39
40 char lab_buf[4][256],
41      ind_buf[4][256],
42      *match(), *lab(), *ind(), *end_arg(), *strindex();
43
44 static int n_index = -1;
45
46
47 process_label( l)
48 char *l;
49 {
50 }
51
52
53 process_mnemonic( m)
54 char *m;
55 {
56 }
57
58
59 process_operand( arg, op)
60 register char *arg;
61 register struct t_operand *op;
62 {
63         register char *einde;
64
65         if ( n_index == 3) 
66                 n_index = 0;
67         else
68                 n_index++;
69
70         if  ( arg[0] == '~' ) {
71                 op->type = CONST;
72                 op->cst = arg+1;
73         }
74         else if ( is_reg( arg, &(op->num)) ) {
75                 op->type = REGISTER;
76         }
77         else if ((arg[0]=='-') && (arg[1] == LEFT) && 
78                                 is_reg( arg+2,&(op->num))) {
79                 op->type = AUTO_DEC;
80         }
81         else if( ( arg[0] == LEFT) && is_reg( arg+1, &(op->num))) {
82                 arg = match( arg, RIGHT);
83                 if ( *(arg+1) == '+') 
84                         op->type = AUTO_INC;
85                 else
86                         op->type = REG_DEF;
87         }
88         else  { 
89                 einde = end_arg( arg);
90                 if ( (*einde == 'b' || *einde == 'f') && isdigit( *(einde-1))) {
91                         *einde = '\0';
92                         op->type = L_ILB;
93                         op->offset = "0";
94                         op->lab = arg;
95                 }
96                 else if ( *einde == RIGHT) {
97                         op->type = IND_REG;
98                         arg = ind( ind_buf[ n_index], arg);
99                         if ( is_reg( arg+1, &(op->num)))
100                                 op->indx = ind_buf[ n_index];
101                         else
102                                 fprint( STDERR, "unknown argtype %s\n", arg);
103                 }
104                 else {
105                         op->type = LABEL;
106                         arg = lab( lab_buf[ n_index], arg);
107                         op->lab = lab_buf[ n_index];
108                         if ( *arg == '\0') 
109                                 op->offset = "0";
110                         else 
111                                 op->offset = arg+1; 
112                 }
113
114         }       
115 }
116
117
118 char *ind( buf, str)
119 register char *buf, *str;
120
121 /* Reads the index in front of '(register)'.
122  */
123 {
124         while ( *str != LEFT) 
125                 *buf++ = *str++;
126         *buf = '\0';
127         return( str);
128 }
129
130
131 char *lab( buf, str)
132 register char *buf, *str;
133
134 /* Reads 'label' in front of '+offset'.
135  */
136 {
137         while ( ( *str != '+') && ( *str != '\0'))
138                 *buf++ = *str++;
139         *buf = '\0';
140         while ( isspace( *(buf-1)) ) {
141                 *(buf-1) = '\0';
142                 buf--;
143         }
144         return( str);
145 }
146         
147
148 int is_reg( str, num)
149 register char *str;
150 register int *num; 
151
152 /* Is "str" a 'registers' ?
153  */
154 {
155         if ( ( *str == 'a') && ( *(str+1) == 'p')) {
156                 *num = 12;
157                 return( TRUE);
158         }
159         else if ( ( *str == 'f') && ( *(str+1) == 'p')) {
160                 *num = 13;
161                 return( TRUE);
162         }
163         else if ( ( *str == 's') && ( *(str+1) == 'p')) {
164                 *num = 14;
165                 return( TRUE);
166         }
167         if ( *str == 'r') {
168                 if ( isdigit( *(str+1)) &&  isdigit( *(str+2))) {
169                         *num = ( *(str+1) - '0') * 10 + *(str+2) - '0';
170                         return( TRUE);
171                 }
172                 else if ( isdigit( *(str+1))) {
173                         *num = *(str+1) - '0';
174                         return( TRUE);
175                 }
176                 else 
177                      return( FALSE);
178         }       
179         return( FALSE);
180 }
181
182
183 char *end_arg( str)
184 register char *str;
185
186 /* Shift to the last character of "str".
187  */
188 {
189         while ( *str != '\0')
190                 str++;
191         return( str-1);
192 }
193
194
195 char *match( str, sym)
196 register char *str;
197 char sym;
198 {
199         while ( *str != sym)
200                 str++;
201         return( str);
202 }
203
204
205 /******************************************************************************/
206
207 char my_buf[256];
208
209 gen_operand( op)
210 register struct t_operand *op;
211
212 /* Generate object-code for a argument.
213  */
214 {
215         switch( op->type) {
216                 case CONST :
217                                 if (isdigit(op->cst[0])) {
218                                         long l, atol();
219                                         l = atol(op->cst);
220                                         if (fit_6bits(l)) {
221                                                 @text1(%$(op->cst));
222                                         }
223                                         else {
224                                                 @text1( 0x8f);
225                                                 @text4( %$(op->cst));
226                                         }
227                                 }
228                                 else {
229                                         @__as_const(%$(op->cst));
230                                 }
231                                 break;
232                 case REGISTER:  @text1( %d(0x50 | op->num));
233                                 break;
234                 case REG_DEF :  @text1( %d(0x60 | op->num));
235                                 break;
236                 case AUTO_DEC : @text1( %d(0x70 | op->num));
237                                 break;
238                 case AUTO_INC : @text1( %d(0x80 | op->num));
239                                 break;
240                 case IND_REG :
241                                 if (isdigit(op->indx[0])) {
242                                         long l, atol();
243                                         l = atol(op->indx);
244                                         if (fit_byte(l)) {
245                                                 @text1( %d(0xa0 | op->num));
246                                                 @text1( %$(op->indx));
247                                         } else if (fit_word(l)) {
248                                                 @text1( %d(0xc0 | op->num));
249                                                 @text2( %$(op->indx));
250                                         } else {
251                                                 @text1( %d(0xe0 | op->num));
252                                                 @text4( %$(op->indx));
253                                         }
254                                 }
255                                 else {
256                                         @__as_indexed(%$(op->indx) , %d(op->num));
257                                 }
258                                 break;
259                 case LABEL :    @text1( 0xef);
260                                 if ( strindex( op->lab, DOLLAR)) {
261                         @reloc4( %$(op->lab), %$(op->offset), PC_REL);
262                                 }
263                                 else if ( strindex( op->lab, LEFT)) {
264                         @reloc4( %$(op->lab), %$(op->offset), PC_REL);
265                                 }
266                                 else {
267                                         sprint( my_buf, "\"%s\"", op->lab);
268                                 @reloc4( %$(my_buf), %$(op->offset) , PC_REL);
269                                 }
270                                 break;
271                 case L_ILB :    @text1( %dist( op->lab));
272                                 break;
273                 default : fprint( STDERR, "error");
274         }
275 }