1 /* parse_ack.c - parse GNU assembly Author: R.S. Veldema
14 #include "languages.h"
16 typedef struct mnemonic
{ /* GNU as86 mnemonics translation table. */
22 static mnemonic_t mnemtab
[] = { /* This array is sorted. */
23 { ".align", DOT_ALIGN
, PSEUDO
},
24 { ".ascii", DOT_ASCII
, PSEUDO
},
25 { ".asciz", DOT_ASCIZ
, PSEUDO
},
26 { ".assert", DOT_ASSERT
, PSEUDO
},
27 { ".base", DOT_BASE
, PSEUDO
},
28 { ".bss", DOT_BSS
, PSEUDO
},
29 { ".byte", DOT_DATA1
, PSEUDO
},
30 { ".comm", DOT_COMM
, PSEUDO
},
31 { ".data", DOT_DATA
, PSEUDO
},
32 { ".data1", DOT_DATA1
, PSEUDO
},
33 { ".data2", DOT_DATA2
, PSEUDO
},
34 { ".data4", DOT_DATA4
, PSEUDO
},
35 { ".end", DOT_END
, PSEUDO
},
36 { ".extern", DOT_EXTERN
, PSEUDO
},
37 { ".file", DOT_FILE
, PSEUDO
},
38 { ".globl", DOT_DEFINE
, PSEUDO
},
39 { ".lcomm", DOT_LCOMM
, PSEUDO
},
40 { ".line", DOT_LINE
, PSEUDO
},
41 { ".list", DOT_LIST
, PSEUDO
},
42 { ".long", DOT_DATA4
, PSEUDO
},
43 { ".nolist", DOT_NOLIST
, PSEUDO
},
44 { ".rom", DOT_ROM
, PSEUDO
},
45 { ".space", DOT_SPACE
, PSEUDO
},
46 { ".symb", DOT_SYMB
, PSEUDO
},
47 { ".text", DOT_TEXT
, PSEUDO
},
48 { ".word", DOT_DATA2
, PSEUDO
},
53 { "adcb", ADC
, BYTE
},
54 { "adcl", ADC
, WORD
},
55 { "adcw", ADC
, OWORD
},
56 { "addb", ADD
, BYTE
},
57 { "addl", ADD
, WORD
},
58 { "addw", ADD
, OWORD
},
59 { "andb", AND
, BYTE
},
60 { "andl", AND
, WORD
},
61 { "andw", AND
, OWORD
},
62 { "arpl", ARPL
, WORD
},
63 { "bound", BOUND
, WORD
},
66 { "bswap", BSWAP
, WORD
},
72 { "call", CALL
, JUMP
},
73 { "callf", CALLF
, JUMP
},
74 { "cbtw", CBW
, OWORD
},
80 { "cltd", CWD
, WORD
},
81 { "clts", CLTS
, WORD
},
83 { "cmpb", CMP
, BYTE
},
84 { "cmpl", CMP
, WORD
},
85 { "cmps", CMPS
, WORD
},
86 { "cmpsb", CMPS
, BYTE
},
87 { "cmpw", CMP
, OWORD
},
88 { "cmpxchg", CMPXCHG
, WORD
},
90 { "cwde", CBW
, WORD
},
91 { "cwtd", CWD
, OWORD
},
92 { "cwtl", CBW
, WORD
},
95 { "decb", DEC
, BYTE
},
96 { "decl", DEC
, WORD
},
97 { "decw", DEC
, OWORD
},
98 { "divb", DIV
, BYTE
},
99 { "divl", DIV
, WORD
},
100 { "divw", DIV
, OWORD
},
101 { "enter", ENTER
, WORD
},
102 { "f2xm1", F2XM1
, WORD
},
103 { "fabs", FABS
, WORD
},
104 { "fadd", FADD
, WORD
},
105 { "faddd", FADDD
, WORD
},
106 { "faddp", FADDP
, WORD
},
107 { "fadds", FADDS
, WORD
},
108 { "fbld", FBLD
, WORD
},
109 { "fbstp", FBSTP
, WORD
},
110 { "fchs", FCHS
, WORD
},
111 { "fcomd", FCOMD
, WORD
},
112 { "fcompd", FCOMPD
, WORD
},
113 { "fcompp", FCOMPP
, WORD
},
114 { "fcomps", FCOMPS
, WORD
},
115 { "fcoms", FCOMS
, WORD
},
116 { "fcos", FCOS
, WORD
},
117 { "fdecstp", FDECSTP
, WORD
},
118 { "fdivd", FDIVD
, WORD
},
119 { "fdivp", FDIVP
, WORD
},
120 { "fdivrd", FDIVRD
, WORD
},
121 { "fdivrp", FDIVRP
, WORD
},
122 { "fdivrs", FDIVRS
, WORD
},
123 { "fdivs", FDIVS
, WORD
},
124 { "ffree", FFREE
, WORD
},
125 { "fiaddl", FIADDL
, WORD
},
126 { "fiadds", FIADDS
, WORD
},
127 { "ficom", FICOM
, WORD
},
128 { "ficomp", FICOMP
, WORD
},
129 { "fidivl", FIDIVL
, WORD
},
130 { "fidivrl", FIDIVRL
, WORD
},
131 { "fidivrs", FIDIVRS
, WORD
},
132 { "fidivs", FIDIVS
, WORD
},
133 { "fildl", FILDL
, WORD
},
134 { "fildq", FILDQ
, WORD
},
135 { "filds", FILDS
, WORD
},
136 { "fimull", FIMULL
, WORD
},
137 { "fimuls", FIMULS
, WORD
},
138 { "fincstp", FINCSTP
, WORD
},
139 { "fistl", FISTL
, WORD
},
140 { "fistp", FISTP
, WORD
},
141 { "fists", FISTS
, WORD
},
142 { "fisubl", FISUBL
, WORD
},
143 { "fisubrl", FISUBRL
, WORD
},
144 { "fisubrs", FISUBRS
, WORD
},
145 { "fisubs", FISUBS
, WORD
},
146 { "fld1", FLD1
, WORD
},
147 { "fldcw", FLDCW
, WORD
},
148 { "fldd", FLDD
, WORD
},
149 { "fldenv", FLDENV
, WORD
},
150 { "fldl2e", FLDL2E
, WORD
},
151 { "fldl2t", FLDL2T
, WORD
},
152 { "fldlg2", FLDLG2
, WORD
},
153 { "fldln2", FLDLN2
, WORD
},
154 { "fldpi", FLDPI
, WORD
},
155 { "flds", FLDS
, WORD
},
156 { "fldx", FLDX
, WORD
},
157 { "fldz", FLDZ
, WORD
},
158 { "fmuld", FMULD
, WORD
},
159 { "fmulp", FMULP
, WORD
},
160 { "fmuls", FMULS
, WORD
},
161 { "fnclex", FCLEX
, WORD
},
162 { "fninit", FINIT
, WORD
},
163 { "fnop", FNOP
, WORD
},
164 { "fnsave", FSAVE
, WORD
},
165 { "fnstcw", FSTCW
, WORD
},
166 { "fnstenv", FSTENV
, WORD
},
167 { "fpatan", FPATAN
, WORD
},
168 { "fprem", FPREM
, WORD
},
169 { "fprem1", FPREM1
, WORD
},
170 { "fptan", FPTAN
, WORD
},
171 { "frndint", FRNDINT
, WORD
},
172 { "frstor", FRSTOR
, WORD
},
173 { "fscale", FSCALE
, WORD
},
174 { "fsin", FSIN
, WORD
},
175 { "fsincos", FSINCOS
, WORD
},
176 { "fsqrt", FSQRT
, WORD
},
177 { "fstd", FSTD
, WORD
},
178 { "fstpd", FSTPD
, WORD
},
179 { "fstps", FSTPS
, WORD
},
180 { "fstpx", FSTPX
, WORD
},
181 { "fsts", FSTS
, WORD
},
182 { "fstsw", FSTSW
, WORD
},
183 { "fsubd", FSUBD
, WORD
},
184 { "fsubp", FSUBP
, WORD
},
185 { "fsubpr", FSUBPR
, WORD
},
186 { "fsubrd", FSUBRD
, WORD
},
187 { "fsubrs", FSUBRS
, WORD
},
188 { "fsubs", FSUBS
, WORD
},
189 { "ftst", FTST
, WORD
},
190 { "fucom", FUCOM
, WORD
},
191 { "fucomp", FUCOMP
, WORD
},
192 { "fucompp", FUCOMPP
, WORD
},
193 { "fxam", FXAM
, WORD
},
194 { "fxch", FXCH
, WORD
},
195 { "fxtract", FXTRACT
, WORD
},
196 { "fyl2x", FYL2X
, WORD
},
197 { "fyl2xp1", FYL2XP1
, WORD
},
198 { "hlt", HLT
, WORD
},
199 { "idivb", IDIV
, BYTE
},
200 { "idivl", IDIV
, WORD
},
201 { "idivw", IDIV
, OWORD
},
202 { "imulb", IMUL
, BYTE
},
203 { "imull", IMUL
, WORD
},
204 { "imulw", IMUL
, OWORD
},
206 { "incb", INC
, BYTE
},
207 { "incl", INC
, WORD
},
208 { "incw", INC
, OWORD
},
210 { "insb", INS
, BYTE
},
211 { "insl", INS
, WORD
},
212 { "insw", INS
, OWORD
},
213 { "int", INT
, WORD
},
214 { "into", INTO
, JUMP
},
215 { "invd", INVD
, WORD
},
216 { "invlpg", INVLPG
, WORD
},
217 { "inw", IN
, OWORD
},
218 { "iret", IRET
, JUMP
},
219 { "iretd", IRETD
, JUMP
},
221 { "jae", JAE
, JUMP
},
223 { "jbe", JBE
, JUMP
},
225 { "jcxz", JCXZ
, JUMP
},
227 { "jecxz", JCXZ
, JUMP
},
229 { "jge", JGE
, JUMP
},
231 { "jle", JLE
, JUMP
},
232 { "jmp", JMP
, JUMP
},
233 { "jmpf", JMPF
, JUMP
},
234 { "jna", JBE
, JUMP
},
235 { "jnae", JB
, JUMP
},
236 { "jnb", JAE
, JUMP
},
237 { "jnbe", JA
, JUMP
},
238 { "jnc", JAE
, JUMP
},
239 { "jne", JNE
, JUMP
},
240 { "jng", JLE
, JUMP
},
241 { "jnge", JL
, JUMP
},
242 { "jnl", JGE
, JUMP
},
243 { "jnle", JG
, JUMP
},
244 { "jno", JNO
, JUMP
},
245 { "jnp", JNP
, JUMP
},
246 { "jns", JNS
, JUMP
},
247 { "jnz", JNE
, JUMP
},
252 { "lahf", LAHF
, WORD
},
253 { "lar", LAR
, WORD
},
254 { "lds", LDS
, WORD
},
255 { "leal", LEA
, WORD
},
256 { "leave", LEAVE
, WORD
},
257 { "leaw", LEA
, OWORD
},
258 { "les", LES
, WORD
},
259 { "lfs", LFS
, WORD
},
260 { "lgdt", LGDT
, WORD
},
261 { "lgs", LGS
, WORD
},
262 { "lidt", LIDT
, WORD
},
263 { "lldt", LLDT
, WORD
},
264 { "lmsw", LMSW
, WORD
},
265 { "lock", LOCK
, WORD
},
266 { "lods", LODS
, WORD
},
267 { "lodsb", LODS
, BYTE
},
268 { "loop", LOOP
, JUMP
},
269 { "loope", LOOPE
, JUMP
},
270 { "loopne", LOOPNE
, JUMP
},
271 { "loopnz", LOOPNE
, JUMP
},
272 { "loopz", LOOPE
, JUMP
},
273 { "lsl", LSL
, WORD
},
274 { "lss", LSS
, WORD
},
275 { "ltr", LTR
, WORD
},
276 { "movb", MOV
, BYTE
},
277 { "movl", MOV
, WORD
},
278 { "movsb", MOVS
, BYTE
},
279 { "movsbl", MOVSXB
, WORD
},
280 { "movsbw", MOVSXB
, OWORD
},
281 { "movsl", MOVS
, WORD
},
282 { "movsw", MOVS
, OWORD
},
283 { "movswl", MOVSX
, WORD
},
284 { "movw", MOV
, OWORD
},
285 { "movzbl", MOVZXB
, WORD
},
286 { "movzbw", MOVZXB
, OWORD
},
287 { "movzwl", MOVZX
, WORD
},
288 { "mulb", MUL
, BYTE
},
289 { "mull", MUL
, WORD
},
290 { "mulw", MUL
, OWORD
},
291 { "negb", NEG
, BYTE
},
292 { "negl", NEG
, WORD
},
293 { "negw", NEG
, OWORD
},
294 { "nop", NOP
, WORD
},
295 { "notb", NOT
, BYTE
},
296 { "notl", NOT
, WORD
},
297 { "notw", NOT
, OWORD
},
300 { "orw", OR
, OWORD
},
301 { "outb", OUT
, BYTE
},
302 { "outl", OUT
, WORD
},
303 { "outsb", OUTS
, BYTE
},
304 { "outsl", OUTS
, WORD
},
305 { "outsw", OUTS
, OWORD
},
306 { "outw", OUT
, OWORD
},
307 { "pop", POP
, WORD
},
308 { "popa", POPA
, WORD
},
309 { "popad", POPA
, WORD
},
310 { "popf", POPF
, WORD
},
311 { "popl", POP
, WORD
},
312 { "push", PUSH
, WORD
},
313 { "pusha", PUSHA
, WORD
},
314 { "pushad", PUSHA
, WORD
},
315 { "pushf", PUSHF
, WORD
},
316 { "pushl", PUSH
, WORD
},
317 { "rclb", RCL
, BYTE
},
318 { "rcll", RCL
, WORD
},
319 { "rclw", RCL
, OWORD
},
320 { "rcrb", RCR
, BYTE
},
321 { "rcrl", RCR
, WORD
},
322 { "rcrw", RCR
, OWORD
},
323 { "ret", RET
, JUMP
},
324 { "retf", RETF
, JUMP
},
325 { "rolb", ROL
, BYTE
},
326 { "roll", ROL
, WORD
},
327 { "rolw", ROL
, OWORD
},
328 { "rorb", ROR
, BYTE
},
329 { "rorl", ROR
, WORD
},
330 { "rorw", ROR
, OWORD
},
331 { "sahf", SAHF
, WORD
},
332 { "salb", SAL
, BYTE
},
333 { "sall", SAL
, WORD
},
334 { "salw", SAL
, OWORD
},
335 { "sarb", SAR
, BYTE
},
336 { "sarl", SAR
, WORD
},
337 { "sarw", SAR
, OWORD
},
338 { "sbbb", SBB
, BYTE
},
339 { "sbbl", SBB
, WORD
},
340 { "sbbw", SBB
, OWORD
},
341 { "scasb", SCAS
, BYTE
},
342 { "scasl", SCAS
, WORD
},
343 { "scasw", SCAS
, OWORD
},
344 { "seta", SETA
, BYTE
},
345 { "setae", SETAE
, BYTE
},
346 { "setb", SETB
, BYTE
},
347 { "setbe", SETBE
, BYTE
},
348 { "sete", SETE
, BYTE
},
349 { "setg", SETG
, BYTE
},
350 { "setge", SETGE
, BYTE
},
351 { "setl", SETL
, BYTE
},
352 { "setna", SETBE
, BYTE
},
353 { "setnae", SETB
, BYTE
},
354 { "setnb", SETAE
, BYTE
},
355 { "setnbe", SETA
, BYTE
},
356 { "setne", SETNE
, BYTE
},
357 { "setng", SETLE
, BYTE
},
358 { "setnge", SETL
, BYTE
},
359 { "setnl", SETGE
, BYTE
},
360 { "setnle", SETG
, BYTE
},
361 { "setno", SETNO
, BYTE
},
362 { "setnp", SETNP
, BYTE
},
363 { "setns", SETNS
, BYTE
},
364 { "seto", SETO
, BYTE
},
365 { "setp", SETP
, BYTE
},
366 { "sets", SETS
, BYTE
},
367 { "setz", SETE
, BYTE
},
368 { "sgdt", SGDT
, WORD
},
369 { "shlb", SHL
, BYTE
},
370 { "shldl", SHLD
, WORD
},
371 { "shll", SHL
, WORD
},
372 { "shlw", SHL
, OWORD
},
373 { "shrb", SHR
, BYTE
},
374 { "shrdl", SHRD
, WORD
},
375 { "shrl", SHR
, WORD
},
376 { "shrw", SHR
, OWORD
},
377 { "sidt", SIDT
, WORD
},
378 { "sldt", SLDT
, WORD
},
379 { "smsw", SMSW
, WORD
},
380 { "stc", STC
, WORD
},
381 { "std", STD
, WORD
},
382 { "sti", STI
, WORD
},
383 { "stosb", STOS
, BYTE
},
384 { "stosl", STOS
, WORD
},
385 { "stosw", STOS
, OWORD
},
386 { "str", STR
, WORD
},
387 { "subb", SUB
, BYTE
},
388 { "subl", SUB
, WORD
},
389 { "subw", SUB
, OWORD
},
390 { "testb", TEST
, BYTE
},
391 { "testl", TEST
, WORD
},
392 { "testw", TEST
, OWORD
},
393 { "verr", VERR
, WORD
},
394 { "verw", VERW
, WORD
},
395 { "wait", WAIT
, WORD
},
396 { "wbinvd", WBINVD
, WORD
},
397 { "xadd", XADD
, WORD
},
398 { "xchgb", XCHG
, BYTE
},
399 { "xchgl", XCHG
, WORD
},
400 { "xchgw", XCHG
, OWORD
},
401 { "xlat", XLAT
, WORD
},
402 { "xorb", XOR
, BYTE
},
403 { "xorl", XOR
, WORD
},
404 { "xorw", XOR
, OWORD
},
407 void gnu_parse_init(char *file
)
408 /* Prepare parsing of an GNU assembly file. */
413 static void zap(void)
414 /* An error, zap the rest of the line. */
418 while ((t
= get_token(0))->type
!= T_EOF
&& t
->symbol
!= ';')
422 static mnemonic_t
*search_mnem(char *name
)
423 /* Binary search for a mnemonic. (That's why the table is sorted.) */
430 high
= arraysize(mnemtab
)-1;
431 while (low
<= high
) {
432 mid
= (low
+ high
) / 2;
435 if ((cmp
= strcmp(name
, m
->name
)) == 0) return m
;
437 if (cmp
< 0) high
= mid
-1; else low
= mid
+1;
442 static expression_t
*gnu_get_C_expression(int *pn
)
443 /* Read a "C-like" expression. Note that we don't worry about precedence,
444 * the expression is printed later like it is read. If the target language
445 * does not have all the operators (like ~) then this has to be repaired by
446 * changing the source file. (No problem, you still have one source file
447 * to maintain, not two.)
450 expression_t
*e
, *a1
, *a2
;
453 if ((t
= get_token(*pn
))->symbol
== '(') {
454 /* ( expr ): grouping. */
456 if ((a1
= gnu_get_C_expression(pn
)) == nil
) return nil
;
457 if (get_token(*pn
)->symbol
!= ')') {
458 parse_err(1, t
, "missing )\n");
467 if (t
->type
== T_WORD
|| t
->type
== T_STRING
) {
468 /* Label, number, or string. */
470 e
->operator= t
->type
== T_WORD
? 'W' : 'S';
471 e
->name
= allocate(nil
, (t
->len
+1) * sizeof(e
->name
[0]));
472 memcpy(e
->name
, t
->name
, t
->len
+1);
476 if (t
->symbol
== '+' || t
->symbol
== '-' || t
->symbol
== '~') {
477 /* Unary operator. */
479 if ((a1
= gnu_get_C_expression(pn
)) == nil
) return nil
;
481 e
->operator= t
->symbol
;
484 parse_err(1, t
, "expression syntax error\n");
488 switch ((t
= get_token(*pn
))->symbol
) {
501 if ((a2
= gnu_get_C_expression(pn
)) == nil
) {
506 e
->operator= t
->symbol
;
513 static expression_t
*gnu_get_operand(int *pn
, int deref
)
514 /* Get something like: $immed, memory, offset(%base,%index,scale), or simpler. */
516 expression_t
*e
, *offset
, *base
, *index
;
520 if (get_token(*pn
)->symbol
== '$') {
521 /* An immediate value. */
523 return gnu_get_C_expression(pn
);
526 if (get_token(*pn
)->symbol
== '*') {
529 if ((offset
= gnu_get_operand(pn
, deref
)) == nil
) return nil
;
536 if ((get_token(*pn
)->symbol
== '%')
537 && (t
= get_token(*pn
+ 1))->type
== T_WORD
538 && isregister(t
->name
)
540 /* A register operand. */
544 e
->name
= copystr(t
->name
);
549 if (get_token(*pn
)->symbol
!= '('
550 || get_token(*pn
+ 1)->symbol
!= '%') {
551 /* There is an offset. */
552 if ((offset
= gnu_get_C_expression(pn
)) == nil
) return nil
;
558 /* (%base,%index,scale) ? */
560 if (get_token(*pn
)->symbol
== '(') {
564 if (get_token(*pn
)->symbol
== '%'
565 && (t
= get_token(*pn
+ 1))->type
== T_WORD
566 && isregister(t
->name
)
568 /* A base register expression. */
571 base
->name
= copystr(t
->name
);
575 if (get_token(*pn
)->symbol
== ',') (*pn
)++;
578 if (get_token(*pn
)->symbol
== '%'
579 && (t
= get_token(*pn
+ 1))->type
== T_WORD
580 && isregister(t
->name
)
582 /* A index register expression. */
584 index
->operator= '1'; /* for now */
585 index
->name
= copystr(t
->name
);
589 if (get_token(*pn
)->symbol
== ',') (*pn
)++;
592 if ((base
!= nil
|| index
!= nil
)
593 && (t
= get_token(*pn
))->type
== T_WORD
594 && strchr("1248", t
->name
[0]) != nil
598 /* Base is really an index register. */
602 index
->operator= t
->name
[0];
606 if (get_token(*pn
)->symbol
== ')') {
611 parse_err(1, t
, "operand syntax error\n");
619 if (base
== nil
&& index
== nil
) {
621 /* Return a lone offset as (offset). */
626 /* Return a lone offset as is. */
640 static expression_t
*gnu_get_oplist(int *pn
, int deref
)
641 /* Get a comma (or colon for jmpf and callf) separated list of instruction
645 expression_t
*e
, *o1
, *o2
;
648 if ((e
= gnu_get_operand(pn
, deref
)) == nil
) return nil
;
650 if ((t
= get_token(*pn
))->symbol
== ',' || t
->symbol
== ':') {
653 if ((o2
= gnu_get_oplist(pn
, deref
)) == nil
) {
666 static asm86_t
*gnu_get_statement(void)
667 /* Get a pseudo op or machine instruction with arguments. */
669 token_t
*t
= get_token(0);
676 assert(t
->type
== T_WORD
);
680 /* Process instruction prefixes. */
681 for (prefix_seen
= 0;; prefix_seen
= 1) {
682 if (strcmp(t
->name
, "rep") == 0
683 || strcmp(t
->name
, "repe") == 0
684 || strcmp(t
->name
, "repne") == 0
685 || strcmp(t
->name
, "repz") == 0
686 || strcmp(t
->name
, "repnz") == 0
688 if (a
->rep
!= ONCE
) {
690 "can't have more than one rep\n");
692 switch (t
->name
[3]) {
693 case 0: a
->rep
= REP
; break;
695 case 'z': a
->rep
= REPE
; break;
696 case 'n': a
->rep
= REPNE
; break;
700 /* No prefix here, get out! */
703 /* No more prefixes, next must be an instruction. */
704 if (t
->type
!= T_WORD
705 || (m
= search_mnem(t
->name
)) == nil
706 || m
->optype
== PSEUDO
709 "machine instruction expected after instruction prefix\n");
716 /* Skip the prefix and extra newlines. */
719 } while ((t
= get_token(0))->symbol
== ';');
722 /* All the readahead being done upsets the line counter. */
725 /* Read a machine instruction or pseudo op. */
726 if ((m
= search_mnem(t
->name
)) == nil
) {
727 parse_err(1, t
, "unknown instruction '%s'\n", t
->name
);
731 a
->opcode
= m
->opcode
;
732 a
->optype
= m
->optype
;
734 if (a
->optype
== OWORD
) {
746 deref
= (a
->optype
>= BYTE
);
749 if (get_token(1)->symbol
!= ';'
750 && (a
->args
= gnu_get_oplist(&n
, deref
)) == nil
) {
754 if (get_token(n
)->symbol
!= ';') {
755 parse_err(1, t
, "garbage at end of instruction\n");
759 if (!is_pseudo(a
->opcode
)) {
760 /* GNU operand order is the other way around. */
764 while (e
!= nil
&& e
->operator == ',') {
765 t
= e
->right
; e
->right
= e
->left
; e
->left
= t
;
771 /* Delete two argument .align, because ACK can't do it.
772 * Raise 2 to the power of .align's argument.
774 if (a
->args
== nil
|| a
->args
->operator != 'W') {
778 if (a
->args
!= nil
&& a
->args
->operator == 'W'
779 && isanumber(a
->args
->name
)
782 char num
[sizeof(int) * CHAR_BIT
/ 3 + 1];
784 n
= 1 << strtoul(a
->args
->name
, nil
, 0);
785 sprintf(num
, "%u", n
);
786 deallocate(a
->args
->name
);
787 a
->args
->name
= copystr(num
);
803 asm86_t
*gnu_get_instruction(void)
809 while ((t
= get_token(0))->symbol
== ';' || t
->symbol
== '/') {
810 zap(); /* if a comment started by a '/' */
814 if (t
->type
== T_EOF
) return nil
;
816 if (t
->symbol
== '#') {
817 /* Preprocessor line and file change. */
819 if ((t
= get_token(1))->type
!= T_WORD
|| !isanumber(t
->name
)
820 || get_token(2)->type
!= T_STRING
822 parse_err(1, t
, "file not preprocessed?\n");
825 set_file(get_token(2)->name
,
826 strtol(get_token(1)->name
, nil
, 0) - 1);
828 /* GNU CPP adds extra cruft, simply zap the line. */
831 a
= gnu_get_instruction();
833 if (t
->type
== T_WORD
&& get_token(1)->symbol
== ':') {
834 /* A label definition. */
838 a
->opcode
= DOT_LABEL
;
840 a
->args
= e
= new_expr();
842 e
->name
= copystr(t
->name
);
845 if (t
->type
== T_WORD
&& get_token(1)->symbol
== '=') {
848 if ((e
= gnu_get_C_expression(&n
)) == nil
) {
850 a
= gnu_get_instruction();
852 if (get_token(n
)->symbol
!= ';') {
853 parse_err(1, t
, "garbage after assignment\n");
855 a
= gnu_get_instruction();
862 a
->args
->operator= '=';
863 a
->args
->name
= copystr(t
->name
);
868 if (t
->type
== T_WORD
) {
869 if ((a
= gnu_get_statement()) == nil
) {
871 a
= gnu_get_instruction();
874 parse_err(1, t
, "syntax error\n");
876 a
= gnu_get_instruction();