1 /*
2 * Copyright (c) 2005 - 2010, Nils R. Weller
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Emit NASM code from intermediate x86 code
28 */
29 #include "x86_emit_nasm.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <assert.h>
35 #include <ctype.h>
36 #include "scope.h"
37 #include "type.h"
38 #include "decl.h"
39 #include "icode.h"
40 #include "subexpr.h"
41 #include "token.h"
42 #include "functions.h"
43 #include "typemap.h"
44 #include "symlist.h"
45 #include "dwarf.h"
46 #include "cc1_main.h"
47 #include "x86_gen.h"
48 #include "amd64_gen.h"
49 #include "amd64_emit_yasm.h"
50 #include "expr.h"
51 #include "inlineasm.h"
52 #include "error.h"
53 #include "n_libc.h"
54
55 static FILE *out;
56 static size_t data_segment_offset;
57 static size_t bss_segment_offset;
58 static size_t thread_data_segment_offset;
59 static size_t thread_bss_segment_offset;
60
61 static int
init(FILE * fd,struct scope * s)62 init(FILE *fd, struct scope *s) {
63 (void) s;
64 out = fd;
65 return 0;
66 }
67
68 static void
69 print_mem_operand(struct vreg *vr, struct token *constant);
70 struct reg *
71 get_smaller_reg(struct reg *r, size_t size);
72
73 /*
74 * Turns either a byte size into an assembler type string. If a type
75 * argument is supplied (non-null), it will ensure that ``long long''
76 * is mapped to ``dword'', as that type is really dealt with as two
77 * dwords rather than a qword.
78 */
79 static char *
size_to_asmtype(size_t size,struct type * type)80 size_to_asmtype(size_t size, struct type *type) {
81 if (type != NULL) {
82 if (type->tlist == NULL) {
83 if (IS_LLONG(type->code)) {
84 size = 4;
85 }
86 }
87 }
88 /* XXXXXXX long double :( */
89 if (size == /*10*/ 12 || size == 10) return "tword"; /* long double */
90 else if (size == 8) return "qword"; /* double */
91 else if (size == 4) return "dword";
92 else if (size == 2) return "word";
93 else if (size == 1) return "byte";
94 else {
95 printf("bad size for size_to_type(): %lu\n",
96 (unsigned long)size);
97 abort();
98 }
99 return NULL;
100 }
101
102 void
print_nasm_offsets(struct vreg * vr)103 print_nasm_offsets(struct vreg *vr) {
104 /*
105 * XXX this should probably be selectable as command line
106 * flag, -verboseoffsets or somesuch
107 */
108 x_fprintf(out, "+ %lu", calc_offsets(vr));
109 #if 0
110 do {
111 char *tag;
112
113 if (vr->parent->type->code == TY_STRUCT) {
114 tag = vr->parent->type->tstruc->tag;
115 x_fprintf(out, "+ %s%s.%s",
116 vr->parent->type->tstruc->unnamed? "":
117 "_Struct_",
118 tag, vr->type->name);
119 }
120 if (vr->from_ptr) {
121 break;
122 }
123 vr = vr->parent;
124 } while (vr->parent != NULL);
125 #endif
126 }
127
128 #if 0
129 static void
130 emit_section(const char *name) {
131 x_fprintf(out, "section .%s\n", name);
132 }
133 #endif
134
135 static int cursect = 0;
136
137 static void
emit_setsection(int value)138 emit_setsection(int value) {
139 char *p = NULL;
140
141 if (cursect == value) {
142 /* We're already in that section */
143 return;
144 }
145 p = generic_elf_section_name(value);
146
147 if (p != NULL) {
148 x_fprintf(out, "section .%s\n", p);
149 }
150 cursect = value;
151 }
152
153 static void
154 print_init_list(struct decl *dec, struct initializer *init);
155 void print_nasm_string_init(size_t howmany, struct ty_string *str);
156 static void
157 print_reg_assign(struct reg *dest,
158 struct reg *srcreg, size_t src_size, struct type *src_type);
159
160 static void
print_init_expr(struct type * dt,struct expr * ex)161 print_init_expr(struct type *dt, struct expr *ex) {
162 int is_addr_as_int = 0;
163 struct tyval *cv;
164
165 cv = ex->const_value;
166
167 if (cv && (cv->str || cv->address)) {
168 if (dt->tlist == NULL) {
169 /*
170 * This must be a stupid construct like
171 * static size_t foo = (size_t)&const_addr;
172 * because otherwise the address/string would
173 * have a pointer or array type node
174 */
175 is_addr_as_int = 1;
176 }
177 }
178
179 x_fprintf(out, "\t");
180 if (dt->tlist == NULL && !is_addr_as_int) {
181 switch (dt->code) {
182 case TY_CHAR:
183 case TY_SCHAR:
184 case TY_UCHAR:
185 case TY_BOOL:
186 x_fprintf(out, "db ");
187 cross_print_value_by_type(out, ex->const_value->value,
188 TY_UCHAR, 'd');
189 break;
190 case TY_SHORT:
191 x_fprintf(out, "dw ");
192 cross_print_value_by_type(out, ex->const_value->value,
193 TY_SHORT, 'd');
194 break;
195 case TY_USHORT:
196 x_fprintf(out, "dw ");
197 cross_print_value_by_type(out, ex->const_value->value,
198 TY_USHORT, 'd');
199 break;
200 case TY_INT:
201 case TY_ENUM:
202 x_fprintf(out, "dd ");
203 cross_print_value_by_type(out, ex->const_value->value,
204 TY_INT, 'd');
205 break;
206 case TY_UINT:
207 x_fprintf(out, "dd ");
208 cross_print_value_by_type(out, ex->const_value->value,
209 TY_UINT, 'd');
210 break;
211
212 case TY_LONG:
213 case TY_LLONG:
214 if (backend->arch != ARCH_AMD64
215 && dt->code == TY_LLONG) {
216 x_fprintf(out, "dd ");
217 cross_print_value_chunk(out,
218 ex->const_value->value,
219 TY_LLONG, TY_UINT, 0, 0);
220 x_fputc('\n', out);
221 x_fprintf(out, "\tdd ");
222 cross_print_value_chunk(out,
223 ex->const_value->value,
224 TY_LLONG, TY_UINT, 0, 1);
225 } else if (backend->arch == ARCH_AMD64) {
226 x_fprintf(out, "dq ");
227 cross_print_value_by_type(out,
228 ex->const_value->value,
229 TY_LONG, 'd');
230 } else {
231 x_fprintf(out, "dd ");
232 cross_print_value_by_type(out,
233 ex->const_value->value,
234 TY_LONG, 'd');
235 }
236 break;
237 case TY_ULONG:
238 case TY_ULLONG:
239 if (backend->arch != ARCH_AMD64
240 && dt->code == TY_ULLONG) {
241 x_fprintf(out, "dd ");
242 cross_print_value_chunk(out,
243 ex->const_value->value,
244 TY_ULLONG, TY_UINT, 0, 0);
245 x_fputc('\n', out);
246 x_fprintf(out, "\tdd ");
247 cross_print_value_chunk(out,
248 ex->const_value->value,
249 TY_ULLONG, TY_UINT, 0, 1);
250 } else if (backend->arch == ARCH_AMD64) {
251 x_fprintf(out, "dq ");
252 cross_print_value_by_type(out,
253 ex->const_value->value,
254 TY_ULONG, 'd');
255 } else {
256 x_fprintf(out, "dd ");
257 cross_print_value_by_type(out,
258 ex->const_value->value,
259 TY_ULONG, 'd');
260 }
261 break;
262 case TY_FLOAT:
263 x_fprintf(out, "dd ");
264 cross_print_value_by_type(out,
265 ex->const_value->value,
266 TY_UINT, 'd');
267 break;
268 case TY_DOUBLE:
269 x_fprintf(out, "dd ");
270 cross_print_value_chunk(out,
271 ex->const_value->value,
272 TY_DOUBLE, TY_UINT, 0, 0);
273 x_fputc('\n', out);
274 x_fprintf(out, "\tdd ");
275 cross_print_value_chunk(out,
276 ex->const_value->value,
277 TY_DOUBLE, TY_UINT, 0, 1);
278 break;
279 case TY_LDOUBLE:
280 x_fprintf(out, "dd ");
281 cross_print_value_chunk(out,
282 ex->const_value->value,
283 TY_LDOUBLE, TY_UINT, 0, 0);
284 x_fputc('\n', out);
285 x_fprintf(out, "\tdd ");
286 cross_print_value_chunk(out,
287 ex->const_value->value,
288 TY_LDOUBLE, TY_UINT, 0, 1);
289 x_fputc('\n', out);
290 x_fprintf(out, "dw ");
291 cross_print_value_chunk(out,
292 ex->const_value->value,
293 TY_LDOUBLE, TY_UINT, TY_USHORT, 2);
294 /* 02/23/09: Pad to 12 */
295 if (sysflag == OS_OSX || backend->arch == ARCH_AMD64) {
296 x_fprintf(out, "\n\ttimes 6 db 0\n");
297 } else {
298 x_fprintf(out, "\n\tdw 0\n");
299 }
300 break;
301 default:
302 printf("print_init_expr: "
303 "unsupported datatype %d\n",
304 dt->code);
305 unimpl();
306 }
307 } else {
308 if (is_addr_as_int || dt->tlist->type == TN_POINTER_TO) {
309 if (backend->arch == ARCH_AMD64) {
310 x_fprintf(out, "dq ");
311 } else {
312 x_fprintf(out, "dd ");
313 }
314 if (cv->is_nullptr_const) {
315 x_fprintf(out, "0");
316 } else if (cv->str) {
317 x_fprintf(out, "_Str%lu", cv->str->count);
318 } else if (cv->value) {
319 #if 0
320 x_fprintf(out, "%lu",
321 *(unsigned long *)cv->value);
322 #endif
323 /* XXX hmm... realy use unsigned long?? */
324 cross_print_value_by_type(out,
325 ex->const_value->value,
326 TY_LONG, 'd');
327 } else if (cv->address) {
328 /* XXX */
329 char *sign;
330
331 if (cv->address->diff < 0) {
332 /*
333 * 08/02/09: The address diff value
334 * is already negative, so we used
335 * to get var - - val
336 */
337 sign = "";
338 } else {
339 sign = "+";
340 }
341 if (cv->address->dec != NULL) {
342 /* Static variable */
343 x_fprintf(out, "%s %s %ld",
344 cv->address->dec->dtype->name,
345 sign, cv->address->diff);
346 } else {
347 /* Label */
348 x_fprintf(out, "%s.%s %s %ld",
349 cv->address->funcname,
350 cv->address->labelname,
351 sign,
352 cv->address->diff);
353 }
354 }
355 } else if (dt->tlist->type == TN_ARRAY_OF) {
356 size_t arrsize;
357 struct tyval *cv;
358
359 /*
360 * This has to be a string because only in
361 * char buf[] = "hello"; will an aggregate
362 * initializer ever be stored as INIT_EXPR
363 */
364
365 cv = ex->const_value;
366 arrsize = dt->tlist->arrarg_const;
367 print_nasm_string_init(arrsize, cv->str);
368
369 if (arrsize >= cv->str->size) {
370 if (arrsize > cv->str->size) {
371 /* XXX not totally host-independent */
372 x_fprintf(out, "\n\ttimes %lu db 0\n",
373 arrsize - cv->str->size);
374 }
375 } else {
376 /* Do not null-terminate */
377 ;
378 }
379 }
380 }
381 x_fputc('\n', out);
382 }
383
384 /* XXX may be adaptable for different platforms */
385 /* XXX duplicates gas print_init_list() :-( */
386 static void
print_init_list(struct decl * dec,struct initializer * init)387 print_init_list(struct decl *dec, struct initializer *init) {
388 struct sym_entry *se = NULL;
389 struct sym_entry *startse = NULL;
390
391 if (dec
392 && dec->dtype->code == TY_STRUCT
393 && dec->dtype->tlist == NULL) {
394 se = dec->dtype->tstruc->scope->slist;
395 }
396 for (; init != NULL; init = init->next) {
397 if (init->type == INIT_NESTED) {
398 struct decl *nested_dec = NULL;
399 struct decl *storage_unit = NULL;
400 struct type_node *saved_tlist = NULL;
401
402 if (se == NULL) {
403 /*
404 * May be an array of structs, in
405 * which case the struct declaration
406 * is needed for alignment
407 */
408 if (dec
409 && dec->dtype->code == TY_STRUCT) {
410 nested_dec = alloc_decl();
411 nested_dec->dtype = dec->dtype;
412 saved_tlist = dec->dtype->tlist;
413 dec->dtype->tlist = NULL;
414 }
415 } else {
416 nested_dec = se->dec;
417 }
418
419 print_init_list(nested_dec, init->data);
420
421 if (saved_tlist != NULL) {
422 dec->dtype->tlist = saved_tlist;
423 free(nested_dec);
424 }
425
426 /*
427 * 10/08/08: If this is a bitfield initializer, match
428 * (skip) all affected bitfield declarations in this
429 * struct. This is important for alignment
430 *
431 * XXX This is degenerating into copy&paste coding! Should
432 * share with gas!!!!!!!!!!!!!!!!!!!
433 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
434 */
435 if (se != NULL && se->dec->dtype->tbit != NULL) {
436 storage_unit = se->dec->dtype->tbit->bitfield_storage_unit;
437 /*
438 * Skip all but last initialized bitfield, which is needed
439 * for alignment below
440 */
441 if (se->next == NULL) {
442 /*
443 * This is already the last struct member, which
444 * also happens to be a bitfield
445 */
446 ;
447 } else {
448 do {
449 se = se->next;
450 } while (se != NULL
451 && se->next != NULL
452 && se->dec->dtype->tbit != NULL
453 && se->dec->dtype->tbit->bitfield_storage_unit == storage_unit);
454
455 if (se != NULL
456 && (se->dec->dtype->tbit == NULL
457 || se->dec->dtype->tbit->bitfield_storage_unit != storage_unit)) {
458 /* Move back to last BF member - so we can align for next member */
459 se = se->prev;
460 }
461 }
462 }
463 } else if (init->type == INIT_EXPR) {
464 struct expr *ex;
465
466 ex = init->data;
467 print_init_expr(ex->const_value->type, ex);
468 if (se != NULL && se->dec->dtype->tbit != NULL) {
469 /*
470 * Skip alignment stuff below, UNLESS
471 * we are dealing with the last member
472 * of the struct, in which case we may
473 * have to pad to align for the start
474 * of the struct
475 */
476 if (se->next != NULL) {
477 continue;
478 }
479 }
480 } else if (init->type == INIT_NULL) {
481 if (init->varinit != NULL && init->left_type->tbit != NULL) {
482 continue;
483 } else {
484 x_fprintf(out, "\ttimes %lu db 0\n",
485 (unsigned long)*(size_t *)init->data);
486 /*
487 * If this is for a struct, skip all members covered
488 * by this initializer (but keep the last one so the
489 * code below pad the struct for alignment)
490 */
491 startse = se;
492
493 /*
494 * 03/01/10: Don't do this for variable
495 * initializers. See x86_emit_gas.c
496 */
497 if (init->varinit == NULL) {
498 for (; se != NULL && se->next != NULL; se = se->next) {
499 ;
500 }
501 }
502 }
503 }
504 if (se != NULL) {
505 /* May need alignment */
506 struct decl *d = NULL;
507 struct type *ty = NULL;
508 size_t nbytes;
509
510 if (se->next != NULL) {
511 /* We may have to align for the next member */
512 if (se->next->dec->dtype->tbit != NULL) {
513 /* Don't align bitfields! */
514 ;
515 } else {
516 d = se->next->dec;
517 ty = d->dtype;
518 }
519 } else if (dec->dtype->tstruc->scope->slist->next) {
520 /*
521 * We've reached the end of the struct and
522 * may have to pad the struct, such that if
523 * we have an array of structs, every element
524 * is properly aligned
525 *
526 * Note that we have to use the whole struct
527 * alignment, not just first member alignment
528 */
529 ty = dec->dtype;
530 if (init->type == INIT_NULL) {
531 /*
532 * 08/08/07: Now the alignment is
533 * hopefully done correctly for zero
534 * initializers. Previously we called
535 * calc_align_bytes() for the last
536 * member of a zero initializer, which
537 * was wrong
538 */
539 size_t curoff = startse->dec->offset +
540 *(size_t *)init->data;
541 size_t alignto = backend->get_align_type(ty);
542 size_t tmp = 0;
543
544 while ((curoff + tmp) % alignto) {
545 ++tmp;
546 }
547 if (tmp > 0) {
548 x_fprintf(out, "\ttimes %lu db 0\n",
549 (unsigned long)tmp);
550 }
551 } else {
552 d = dec->dtype->tstruc->scope->slist->dec;
553 }
554 }
555
556
557 if (d != NULL) {
558 unsigned long offset;
559
560
561 /*
562 * 10/08/08: Handle bitfields
563 */
564 if (se->dec->dtype->tbit != NULL) {
565 /*
566 * Align for next member. We are at
567 *
568 * address_of_storage_unit + size_of_storage_unit
569 *
570 * We only get here if the last bitfield in the
571 * current unit is processed, so we have to account
572 * for the entire partial storage unit.
573 *
574 * Note that we're setting the offset AFTER the current
575 * item because calc_align_bytes() doesn't do this for
576 * us
577 */
578 offset = se->dec->dtype->tbit->bitfield_storage_unit->offset
579 + backend->get_sizeof_type(se->dec->dtype->tbit->
580 bitfield_storage_unit->dtype, NULL);
581 } else {
582 offset = se->dec->offset;
583 }
584
585 nbytes = calc_align_bytes(/*se->dec->*/offset,
586 se->dec->dtype, ty, 1);
587 if (nbytes) {
588 x_fprintf(out, "\ttimes %lu db 0\n",
589 (unsigned long)nbytes);
590 }
591 }
592 se = se->next;
593 }
594 }
595 }
596
597
598 static void
emit_support_decls(void)599 emit_support_decls(void) {
600 if (1) {
601 /* need memcpy() */
602 x_fprintf(out, "extern memcpy\n");
603 }
604 if (/*curfunc->alloca_head != NULL*/ 1) {
605 x_fprintf(out, "extern malloc\n");
606 x_fprintf(out, "extern free\n");
607 x_fprintf(out, "extern memset\n");
608 }
609 if (picflag) {
610 x_fprintf(out, "extern _GLOBAL_OFFSET_TABLE_\n");
611 }
612 }
613
614
615 static void
emit_extern_decls(void)616 emit_extern_decls(void) {
617
618 #if 0
619 /* Generate external references */
620 if (global_scope.extern_decls.ndecls > 0) {
621 d = global_scope.extern_decls.data;
622 for (i = 0; i < global_scope.extern_decls.ndecls; ++i) {
623 if (d[i]->references == 0
624 && (!d[i]->dtype->is_func
625 || !d[i]->dtype->is_def)) {
626 /* Unneeded declaration */
627 continue;
628 }
629
630 if (d[i]->has_def) {
631 /*
632 * extern declaration overriden by later
633 * definition
634 */
635 continue;
636 }
637
638 if (d[i]->dtype->is_func
639 && d[i]->dtype->is_def) {
640 d[i]->has_symbol = 1;
641 /* XXX hm what about extern/static inline? */
642 if (!IS_INLINE(d[i]->dtype->flags)) {
643 x_fprintf(out, "global $%s\n",
644 d[i]->dtype->name,
645 d[i]);
646 }
647 }
648 }
649 }
650 #endif
651 {
652 struct sym_entry *se;
653
654 for (se = extern_vars; se != NULL; se = se->next) {
655 if (se->dec->invalid) {
656 continue;
657 }
658 if (se->dec->has_symbol
659 || se->dec->dtype->is_def
660 || se->dec->has_def) {
661 continue;
662 }
663 if (se->dec->references == 0
664 && (!se->dec->dtype->is_func
665 || !se->dec->dtype->is_def)) {
666 /* Unneeded declaration */
667 continue;
668 }
669 x_fprintf(out, "extern $%s\n",
670 se->dec->dtype->name);
671 x_fputc('\n', out);
672 se->dec->has_symbol = 1;
673 }
674 }
675 }
676
677 static void
emit_global_extern_decls(struct decl ** d,int ndecls)678 emit_global_extern_decls(struct decl **d, int ndecls) {
679 int i;
680
681 /* Generate external references */
682 if (ndecls > 0) {
683 for (i = 0; i < ndecls; ++i) {
684 if (d[i]->references == 0
685 && (!d[i]->dtype->is_func
686 || !d[i]->dtype->is_def)) {
687 /* Unneeded declaration */
688 continue;
689 }
690
691 if (d[i]->has_def) {
692 /*
693 * extern declaration overriden by later
694 * definition
695 */
696 continue;
697 }
698 if (d[i]->invalid) {
699 continue;
700 }
701
702 if (d[i]->dtype->is_func
703 && d[i]->dtype->is_def) {
704 d[i]->has_symbol = 1;
705 /* XXX hm what about extern/static inline? */
706 if (!IS_INLINE(d[i]->dtype->flags)) {
707 x_fprintf(out, "global $%s\n",
708 d[i]->dtype->name,
709 d[i]);
710 }
711 }
712 }
713 }
714 }
715
716 static void
emit_global_static_decls(struct decl ** dv,int ndecls)717 emit_global_static_decls(struct decl **dv, int ndecls) {
718 int i;
719
720 for (i = 0; i < ndecls; ++i) {
721 if (dv[i]->dtype->storage != TOK_KEY_STATIC) {
722 struct type_node *tn = NULL;
723
724 if (dv[i]->invalid) {
725 continue;
726 }
727 if (dv[i]->dtype->is_func) {
728 for (tn = dv[i]->dtype->tlist;
729 tn != NULL;
730 tn = tn->next) {
731 if (tn->type == TN_FUNCTION) {
732 if (tn->ptrarg) {
733 continue;
734 } else {
735 break;
736 }
737 }
738 }
739 }
740
741 if (tn != NULL) {
742 tn->ptrarg = 1;
743 }
744 if (dv[i]->has_symbol) continue;
745 x_fprintf(out, "global $%s\n",
746 dv[i]->dtype->name, dv[i]);
747 dv[i]->has_symbol = 1;
748 }
749 }
750 }
751
752 static void
emit_static_init_vars(struct decl * list)753 emit_static_init_vars(struct decl *list) {
754 struct decl *d;
755 size_t size;
756
757 if (list) emit_setsection(SECTION_INIT);
758 for (d = list; d != NULL; d = d->next) {
759 struct type *dt = d->dtype;
760
761 if (d->dtype->storage == TOK_KEY_STATIC
762 && d->references == 0) {
763 continue;
764 }
765 if (d->invalid) {
766 continue;
767 }
768
769 size = backend->get_sizeof_decl(d, NULL);
770
771 /* Constant initializer expression */
772 if (picflag) {
773 x_fprintf(out, "\ttype %s object\n",
774 dt->name);
775 x_fprintf(out, "\tsize %s %lu\n", dt->name, size);
776 }
777 x_fprintf(out, "\t$%s:\n", dt->name);
778 print_init_list(d, d->init);
779 if (d->next != NULL) {
780 unsigned long align;
781
782 align = calc_align_bytes(data_segment_offset,
783 d->dtype, d->next->dtype, 0);
784 if (align) {
785 x_fprintf(out, "\ttimes %lu db 0\n", align);
786 data_segment_offset += align;
787 }
788 }
789 data_segment_offset += size;
790 }
791 }
792
793 static void
emit_static_uninit_vars(struct decl * list)794 emit_static_uninit_vars(struct decl *list) {
795 struct decl *d;
796 size_t size;
797
798 if (list != NULL) {
799 emit_setsection(SECTION_UNINIT);
800 for (d = list; d != NULL; d = d->next) {
801 if (d->dtype->storage == TOK_KEY_STATIC
802 && d->references == 0) {
803 continue;
804 }
805 if (d->invalid) {
806 continue;
807 }
808
809 size = backend->get_sizeof_decl(d, NULL);
810
811 if (picflag) {
812 x_fprintf(out, "\ttype %s object\n",
813 d->dtype->name);
814 x_fprintf(out, "\tsize %s %lu\n",
815 d->dtype->name, size);
816 }
817
818 x_fprintf(out, "\t$%s resb %lu\n",
819 d->dtype->name, size);
820 if (d->next != NULL) {
821 unsigned long align;
822
823 align = calc_align_bytes(bss_segment_offset,
824 d->dtype, d->next->dtype, 0);
825 if (align) {
826 x_fprintf(out, "\tresb %lu\n", align);
827 bss_segment_offset += align;
828 }
829 }
830 bss_segment_offset += size;
831 }
832 }
833 }
834
835 static void
emit_static_init_thread_vars(struct decl * list)836 emit_static_init_thread_vars(struct decl *list) {
837 struct decl *d;
838 size_t size;
839
840 if (list != NULL) {
841 emit_setsection(SECTION_INIT_THREAD);
842 thread_data_segment_offset = 0;
843 for (d = list; d != NULL; d = d->next) {
844 struct type *dt = d->dtype;
845
846 if (d->dtype->storage == TOK_KEY_STATIC
847 && d->references == 0) {
848 continue;
849 }
850 if (d->invalid) {
851 continue;
852 }
853
854 size = backend->get_sizeof_decl(d, NULL);
855
856 /* Constant initializer expression */
857 if (picflag) {
858 x_fprintf(out, "\ttype %s object\n",
859 dt->name);
860 x_fprintf(out, "\tsize %s %lu\n", size);
861 }
862 x_fprintf(out, "\t$%s:\n", dt->name);
863 print_init_list(d, d->init);
864 if (d->next != NULL) {
865 unsigned long align;
866
867 align = calc_align_bytes(thread_data_segment_offset,
868 d->dtype, d->next->dtype, 0);
869 if (align) {
870 x_fprintf(out, "\ttimes %lu db 0\n", align);
871 thread_data_segment_offset += align;
872 }
873 }
874 thread_data_segment_offset += size;
875 }
876 }
877 }
878
879 static void
emit_static_uninit_thread_vars(struct decl * list)880 emit_static_uninit_thread_vars(struct decl *list) {
881 struct decl *d;
882 size_t size;
883
884 if (list != NULL) {
885 thread_bss_segment_offset = 0;
886 emit_setsection(SECTION_UNINIT_THREAD);
887 for (d = list; d != NULL; d = d->next) {
888 if (d->dtype->storage == TOK_KEY_STATIC
889 && d->references == 0) {
890 continue;
891 }
892 if (d->invalid) {
893 continue;
894 }
895
896 size = backend->get_sizeof_decl(d, NULL);
897
898 if (picflag) {
899 x_fprintf(out, "\ttype %s object\n",
900 d->dtype->name);
901 x_fprintf(out, "\tsize %s %lu\n", size);
902 }
903
904 x_fprintf(out, "\t$%s resb %lu\n",
905 d->dtype->name, size);
906 if (d->next != NULL) {
907 unsigned long align;
908
909 align = calc_align_bytes(thread_bss_segment_offset,
910 d->dtype, d->next->dtype, 0);
911 if (align) {
912 x_fprintf(out, "\tresb %lu\n", align);
913 thread_bss_segment_offset += align;
914 }
915 }
916 thread_bss_segment_offset += size;
917 }
918 }
919 }
920
921 #if 0
922 static void
923 emit_static_decls(void) {
924 struct decl *d;
925 struct decl **dv;
926 size_t size;
927 int i;
928
929 bss_segment_offset = 0;
930 if (static_uninit_vars != NULL) {
931 x_fprintf(out, "section .bss\n");
932 for (d = static_uninit_vars; d != NULL; d = d->next) {
933 if (d->dtype->storage == TOK_KEY_STATIC
934 && d->references == 0) {
935 continue;
936 }
937
938 size = backend->get_sizeof_decl(d, NULL);
939
940 if (picflag) {
941 x_fprintf(out, "\ttype %s object\n",
942 d->dtype->name);
943 x_fprintf(out, "\tsize %s %lu\n",
944 d->dtype->name, size);
945 }
946
947 x_fprintf(out, "\t$%s resb %lu\n",
948 d->dtype->name, size);
949 if (d->next != NULL) {
950 unsigned long align;
951
952 align = calc_align_bytes(bss_segment_offset,
953 d->dtype, d->next->dtype);
954 if (align) {
955 x_fprintf(out, "\tresb %lu\n", align);
956 bss_segment_offset += align;
957 }
958 }
959 bss_segment_offset += size;
960 }
961 }
962
963 if (static_init_vars) x_fprintf(out, "section .data\n");
964 data_segment_offset = 0;
965 for (d = static_init_vars; d != NULL; d = d->next) {
966 struct type *dt = d->dtype;
967
968 if (d->dtype->storage == TOK_KEY_STATIC
969 && d->references == 0) {
970 continue;
971 }
972
973 size = backend->get_sizeof_decl(d, NULL);
974
975 /* Constant initializer expression */
976 if (picflag) {
977 x_fprintf(out, "\ttype %s object\n",
978 dt->name);
979 x_fprintf(out, "\tsize %s %lu\n", dt->name, size);
980 }
981 x_fprintf(out, "\t$%s:\n", dt->name);
982 print_init_list(d, d->init);
983 if (d->next != NULL) {
984 unsigned long align;
985
986 align = calc_align_bytes(data_segment_offset,
987 d->dtype, d->next->dtype);
988 if (align) {
989 x_fprintf(out, "\ttimes %lu db 0\n", align);
990 data_segment_offset += align;
991 }
992 }
993 data_segment_offset += size;
994 }
995
996 if (static_uninit_thread_vars != NULL) {
997 thread_bss_segment_offset = 0;
998 x_fprintf(out, "section .tbss\n");
999 for (d = static_uninit_thread_vars; d != NULL; d = d->next) {
1000 if (d->dtype->storage == TOK_KEY_STATIC
1001 && d->references == 0) {
1002 continue;
1003 }
1004
1005 size = backend->get_sizeof_decl(d, NULL);
1006
1007 if (picflag) {
1008 x_fprintf(out, "\ttype %s object\n",
1009 d->dtype->name);
1010 x_fprintf(out, "\tsize %s %lu\n", size);
1011 }
1012
1013 x_fprintf(out, "\t$%s resb %lu\n",
1014 d->dtype->name, size);
1015 if (d->next != NULL) {
1016 unsigned long align;
1017
1018 align = calc_align_bytes(thread_bss_segment_offset,
1019 d->dtype, d->next->dtype);
1020 if (align) {
1021 x_fprintf(out, "\tresb %lu\n", align);
1022 thread_bss_segment_offset += align;
1023 }
1024 }
1025 thread_bss_segment_offset += size;
1026 }
1027 }
1028
1029 if (static_init_thread_vars != NULL) {
1030 x_fprintf(out, "section .tdata\n");
1031 thread_data_segment_offset = 0;
1032 for (d = static_init_thread_vars; d != NULL; d = d->next) {
1033 struct type *dt = d->dtype;
1034
1035 if (d->dtype->storage == TOK_KEY_STATIC
1036 && d->references == 0) {
1037 continue;
1038 }
1039
1040 size = backend->get_sizeof_decl(d, NULL);
1041
1042 /* Constant initializer expression */
1043 if (picflag) {
1044 x_fprintf(out, "\ttype %s object\n",
1045 dt->name);
1046 x_fprintf(out, "\tsize %s %lu\n", size);
1047 }
1048 x_fprintf(out, "\t$%s:\n", dt->name);
1049 print_init_list(d, d->init);
1050 if (d->next != NULL) {
1051 unsigned long align;
1052
1053 align = calc_align_bytes(thread_data_segment_offset,
1054 d->dtype, d->next->dtype);
1055 if (align) {
1056 x_fprintf(out, "\ttimes %lu db 0\n", align);
1057 thread_data_segment_offset += align;
1058 }
1059 }
1060 thread_data_segment_offset += size;
1061 }
1062 }
1063 }
1064 #endif
1065
1066
1067 static void
emit_struct_inits(struct init_with_name * list)1068 emit_struct_inits(struct init_with_name *list) {
1069 struct init_with_name *in;
1070
1071 if (list) emit_setsection(SECTION_INIT);
1072 for (in = list; in != NULL; in = in->next) {
1073 x_fprintf(out, "%s:\n", in->name);
1074 print_init_list(in->dec, in->init);
1075 }
1076 }
1077
1078 void
print_nasm_string_init(size_t howmany,struct ty_string * str)1079 print_nasm_string_init(size_t howmany, struct ty_string *str) {
1080 char *p;
1081 int wasprint = 0;
1082 size_t i;
1083
1084 if (str->is_wide_char) {
1085 (void) fprintf(out, "dd ");
1086 } else {
1087 (void) fprintf(out, "db ");
1088 }
1089
1090 for (i = 0, p = str->str; i < str->size-1; ++p, ++i) {
1091 if (str->is_wide_char) {
1092 x_fprintf(out, "0x%x", (unsigned char)*p);
1093 if (/*p[1] != 0*/i+1 < str->size-1) {
1094 (void) fprintf(out, ", ");
1095 }
1096 } else if (isprint((unsigned char)*p)) {
1097 if (!wasprint) {
1098 if (*p == '\'') {
1099 goto printval;
1100 } else {
1101 (void) fprintf(out, "'%c", *p);
1102 }
1103 wasprint = 1;
1104 } else {
1105 if (*p == '\'') {
1106 goto printval;
1107 } else {
1108 (void) fputc(*p, out);
1109 }
1110 }
1111 } else {
1112 printval:
1113 if (wasprint) {
1114 (void) fputc('\'', out);
1115 (void) fputc(',', out);
1116 wasprint = 0;
1117 }
1118 (void) fprintf(out, " %d", *p);
1119 if (/*p[1] != 0*/i+1 < str->size-1) {
1120 (void) fprintf(out, ", ");
1121 }
1122 }
1123 }
1124
1125 if (wasprint) {
1126 (void) fprintf(out, "'");
1127 }
1128
1129 if (howmany >= str->size) {
1130 if (str->size > 1) {
1131 (void) fprintf(out, ", ");
1132 }
1133 (void) fprintf(out, "0\n");
1134 }
1135 }
1136
1137 static void
emit_fp_constants(struct ty_float * list)1138 emit_fp_constants(struct ty_float *list) {
1139 if (list != NULL) {
1140 struct ty_float *tf;
1141
1142 emit_setsection(SECTION_INIT);
1143 for (tf = list; tf != NULL; tf = tf->next) {
1144 x_fprintf(out, "\t_Float%lu ", tf->count);
1145 switch (tf->num->type) {
1146 case TY_FLOAT:
1147 x_fprintf(out, "dd ");
1148 cross_print_value_by_type(out,
1149 tf->num->value,
1150 TY_FLOAT, 0);
1151 break;
1152 case TY_DOUBLE:
1153 x_fprintf(out, "dq ");
1154 cross_print_value_by_type(out,
1155 tf->num->value,
1156 TY_DOUBLE, 0);
1157 break;
1158 case TY_LDOUBLE:
1159 x_fprintf(out, "dt ");
1160 cross_print_value_by_type(out,
1161 tf->num->value,
1162 TY_LDOUBLE, 0);
1163 break;
1164 default:
1165 printf("bad floating point constant - "
1166 "code %d\n", tf->num->type);
1167 abort();
1168 }
1169 x_fputc('\n', out);
1170 }
1171 }
1172 }
1173
1174 static void
emit_support_buffers(void)1175 emit_support_buffers(void) {
1176 static int have_floatbuf, have_x87cw;
1177
1178
1179 if (/*float_const != NULL
1180 ||*/ x87cw_old.var_backed != NULL
1181 #if ! REMOVE_FLOATBUF
1182 || floatbuf.var_backed != NULL
1183 #endif
1184 ) {
1185
1186 if (have_floatbuf && have_x87cw) {
1187 return;
1188 }
1189 emit_setsection(SECTION_INIT);
1190 #if ! REMOVE_FLOATBUF
1191 if (floatbuf.var_backed != NULL && !have_floatbuf) {
1192 x_fprintf(out, "\t%s dq 0.0\n",
1193 floatbuf.type->name);
1194 have_floatbuf = 1;
1195 }
1196 #endif
1197
1198 if (x87cw_old.var_backed != NULL && !have_x87cw) {
1199 x_fprintf(out, "\t%s dw 0\n",
1200 x87cw_old.type->name);
1201 x_fprintf(out, "\t%s dw 0\n",
1202 x87cw_new.type->name);
1203 have_x87cw = 1;
1204 }
1205 }
1206
1207 if (amd64_need_ulong_float_mask) {
1208 x86_emit_nasm.setsection(SECTION_INIT);
1209 x_fprintf(out, "_Ulong_float_mask:\n");
1210 x_fprintf(out, "\tdd 1602224128\n");
1211 }
1212 }
1213
1214 /*
1215 * XXX Misleading name ;o
1216 */
1217 static void
emit_strings(struct ty_string * list)1218 emit_strings(struct ty_string *list) {
1219 if (list != NULL) {
1220 struct ty_string *str;
1221
1222 emit_setsection(SECTION_RODATA);
1223 for (str = list; str != NULL; str = str->next) {
1224 x_fprintf(out, "\t_Str%lu ", str->count);
1225 print_nasm_string_init(str->size, str);
1226 }
1227 }
1228
1229 #if 0
1230 if (unimpl_instr) {
1231 x_fprintf(out,"\t_Unimpl_msg db 'ERROR: Use of unimplemented'\n"
1232 "\t db 'compiler feature (probably)'\n"
1233 "\t db 'floating point - check %d\n'\n");
1234 }
1235 #endif
1236 }
1237
1238 static void
emit_comment(const char * fmt,...)1239 emit_comment(const char *fmt, ...) {
1240 int rc;
1241 va_list va;
1242
1243 va_start(va, fmt);
1244 x_fprintf(out, "; ");
1245 rc = vfprintf(out, fmt, va);
1246 va_end(va);
1247 x_fputc('\n', out);
1248
1249 if (rc == EOF || fflush(out) == EOF) {
1250 perror("vfprintf");
1251 exit(EXIT_FAILURE);
1252 }
1253 }
1254
1255 static void
emit_dwarf2_line(struct token * tok)1256 emit_dwarf2_line(struct token *tok) {
1257 (void) tok;
1258 unimpl();
1259 #if 0
1260 x_fprintf(out, "\t[loc %d %d 0]\n",
1261 tok->fileid, tok->line);
1262 #endif
1263 }
1264
1265 static void
emit_dwarf2_files(void)1266 emit_dwarf2_files(void) {
1267 struct dwarf_in_file *inf;
1268
1269 x_fprintf(out, "[file \"%s\"]\n",
1270 input_file);
1271
1272 for (inf = dwarf_files; inf != NULL; inf = inf->next) {
1273 x_fprintf(out, "[file %d \"%s\"]\n",
1274 inf->id, inf->name);
1275 }
1276 }
1277
1278 static void
emit_inlineasm(struct inline_asm_stmt * stmt)1279 emit_inlineasm(struct inline_asm_stmt *stmt) {
1280 x_fprintf(out, "; inline start\n");
1281 /*
1282 * There may be an empty body for statements where only the side
1283 * effect is desired;
1284 * __asm__("" ::: "memory");
1285 */
1286 if (stmt->code != NULL) {
1287 inline_instr_to_nasm(out, stmt->code);
1288 }
1289 x_fprintf(out, "; inline end\n");
1290 }
1291
1292 static void
emit_unimpl(void)1293 emit_unimpl(void) {
1294 static int n;
1295
1296 x_fprintf(out, "\tpush dword _Unimpl_msg\n");
1297 x_fprintf(out, "\tpush dword %d\n", n++);
1298 x_fprintf(out, "\tcall printf\n");
1299 x_fprintf(out, "\tadd esp, 8\n");
1300 x_fprintf(out, "\tpush dword 1\n");
1301 x_fprintf(out, "\tcall exit\n");
1302 }
1303
1304 static void
emit_empty(void)1305 emit_empty(void) {
1306 x_fputc('\n', out);
1307 }
1308
1309 static void
emit_label(const char * name,int is_func)1310 emit_label(const char *name, int is_func) {
1311 if (is_func) {
1312 x_fprintf(out, "$%s:\n", name);
1313 } else {
1314 x_fprintf(out, ".%s:\n", name);
1315 }
1316 }
1317
1318 static void
emit_call(const char * name)1319 emit_call(const char *name) {
1320 if (picflag) {
1321 x_fprintf(out, "\tcall $%s@PLT\n", name);
1322 } else {
1323 x_fprintf(out, "\tcall $%s\n", name);
1324 }
1325 }
1326
1327 static void
emit_callindir(struct reg * r)1328 emit_callindir(struct reg *r) {
1329 x_fprintf(out, "\tcall %s\n", r->name);
1330 }
1331
1332 static void
emit_func_header(struct function * f)1333 emit_func_header(struct function *f) {
1334 if (picflag) {
1335 x_fprintf(out, "\ttype %s function\n", f->proto->dtype->name);
1336 }
1337 }
1338
1339 static void
emit_func_intro(struct function * f)1340 emit_func_intro(struct function *f) {
1341 (void) f;
1342 x_fprintf(out, "\tpush dword ebp\n"); /* XXX */
1343 x_fprintf(out, "\tmov ebp, esp\n");
1344 }
1345
1346 static void
emit_func_outro(struct function * f)1347 emit_func_outro(struct function *f) {
1348 if (picflag) {
1349 x_fprintf(out, "._End_%s:\n", f->proto->dtype->name);
1350 x_fprintf(out, "\tsize %s %s._End_%s-%s\n",
1351 f->proto->dtype->name,
1352 f->proto->dtype->name,
1353 f->proto->dtype->name);
1354 }
1355 }
1356
1357
1358 static void
emit_define(const char * name,const char * fmt,...)1359 emit_define(const char *name, const char *fmt, ...) {
1360 va_list va;
1361 const char *p;
1362
1363 va_start(va, fmt);
1364 x_fprintf(out, "%%define %s ", name);
1365 for (p = fmt; *p != 0; ++p) {
1366 switch (*p) {
1367 case '%':
1368 switch (*++p) {
1369 case 0:
1370 case '%':
1371 x_fputc('%', out);
1372 break;
1373 case 's': {
1374 char *p = va_arg(va, char *);
1375 x_fprintf(out, "%s", p);
1376 }
1377 break;
1378 case 'l':
1379 if (*++p == 'd') {
1380 long l;
1381 l = va_arg(va, long);
1382 x_fprintf(out, "%ld", l);
1383 }
1384 break;
1385 }
1386 break;
1387 default:
1388 x_fputc(*p, out);
1389 }
1390 }
1391 va_end(va);
1392 }
1393
1394 static void
emit_push(struct function * f,struct icode_instr * ii)1395 emit_push(struct function *f, struct icode_instr *ii) {
1396 struct vreg *vr = ii->src_vreg;
1397 struct reg *r = ii->src_pregs?
1398 (void *)ii->src_pregs[0]: (void *)NULL;
1399
1400 (void) f;
1401
1402 /*
1403 * XXX 07/26/07: Hmmm ascii_type not used anymore??
1404 */
1405 if (ii->src_vreg->type
1406 && ii->src_vreg->type->tlist
1407 && ii->src_vreg->type->tlist->type == TN_ARRAY_OF) {
1408 } else {
1409 #if 0
1410 if (ii->src_vreg->type && ii->src_vreg->type->is_vla) {
1411 #endif
1412 }
1413
1414 if (ii->src_pregs) {
1415 if (ii->src_vreg->is_multi_reg_obj) {
1416 x_fprintf(out, "\tpush dword %s\n",
1417 ii->src_pregs[1]->name);
1418 f->total_allocated += 4;
1419 }
1420 x_fprintf(out, "\tpush dword %s\n", /*ascii_type*/ r->name);
1421 } else if (vr->var_backed) {
1422 struct decl *d = vr->var_backed;
1423
1424 if (vr->parent != NULL) {
1425 /* Structure or union member */
1426 struct decl *d2/* = d*/;
1427 struct vreg *vr2;
1428
1429 vr2 = get_parent_struct(vr);
1430 d2 = vr2->var_backed;
1431 if (vr2->from_ptr) {
1432 x_fprintf(out, "\tpush dword [%s",
1433 vr2->from_ptr->pregs[0]->name);
1434 if (vr->parent->type->code == TY_STRUCT) {
1435 x_fprintf(out, " + %s.%s",
1436 vr2->from_ptr->type->tstruc->tag,
1437 d2->dtype->name);
1438 }
1439 x_fprintf(out, "]\n");
1440 } else if (d2 && d2->stack_addr != NULL) {
1441 x_fprintf(out, "\tpush dword [ebp - %ld",
1442 d2->stack_addr->offset);
1443 if (vr->parent->type->code == TY_STRUCT) {
1444 x_fputc(' ', out);
1445 print_nasm_offsets(/*d*/vr2);
1446 }
1447 x_fprintf(out, "]\n");
1448 } else if (d2 != NULL) {
1449 /* Must be static */
1450 x_fprintf(out, "\tpush dword [$%s",
1451 d2->dtype->name);
1452 if (vr->parent->type->code == TY_STRUCT) {
1453 x_fprintf(out, " + ");
1454 print_nasm_offsets(/*d*/vr2);
1455 }
1456 x_fprintf(out, "]\n");
1457 } else {
1458 unimpl();
1459 }
1460 } else {
1461 if (d->stack_addr != NULL) {
1462 /* Stack */
1463 x_fprintf(out, "\tpush dword [ebp - %ld]\n",
1464 /*ascii_type*/ d->stack_addr->offset);
1465 } else {
1466 /* Static or register variable */
1467 if (d->dtype->storage == TOK_KEY_REGISTER) {
1468 unimpl();
1469 } else {
1470 x_fprintf(out, "\tpush dword [$%s]\n",
1471 /*ascii_type*/ d->dtype->name);
1472 }
1473 }
1474 }
1475 } else if (vr->from_const) {
1476 struct token *t = vr->from_const;
1477
1478 if (t->type == TOK_STRING_LITERAL) {
1479 struct ty_string *s = t->data;
1480 x_fprintf(out, "\tpush dword _Str%lu\n", s->count);
1481 } else if (IS_INT(t->type) || IS_LONG(t->type)) {
1482 /*
1483 * There are only forms of ``int'' and ``long''
1484 * constants
1485 */
1486 #if 0
1487 if (t->type == TY_INT || t->type == TY_LONG) {
1488 x_fprintf(out, "\tpush dword %d\n",
1489 *(int *) t->data);
1490 } else {
1491 /* UINT/ULONG */
1492 x_fprintf(out, "\tpush dword %u\n",
1493 *(unsigned *) t->data);
1494 }
1495 #endif
1496 x_fprintf(out, "\tpush dword ");
1497 cross_print_value_by_type(out,
1498 t->data,
1499 t->type, 0);
1500 x_fputc('\n', out);
1501 } else if (IS_LLONG(t->type)) {
1502 unimpl();
1503 } else {
1504 puts("BUG in NASM emit_push()");
1505 exit(EXIT_FAILURE);
1506 }
1507 } else if (vr->from_ptr) {
1508 x_fprintf(out, "\tpush dword [%s]\n", /*ascii_type,*/
1509 vr->from_ptr->pregs[0]->name);
1510 } else {
1511 unimpl();
1512 }
1513
1514 f->total_allocated += 4;
1515 }
1516
1517 static void
1518 emit_allocstack(struct function *f, size_t nbytes) {
1519 (void) f;
1520 x_fprintf(out, "\tsub esp, %lu\n", (unsigned long)nbytes);
1521 }
1522
1523
1524 static void
1525 emit_freestack(struct function *f, size_t *nbytes) {
1526 if (nbytes == NULL) {
1527 /* Procedure outro */
1528 if (f->total_allocated != 0) {
1529 x_fprintf(out, "\tadd esp, %lu\n",
1530 (unsigned long)f->total_allocated);
1531 }
1532 x_fprintf(out, "\tpop ebp\n");
1533 } else {
1534 if (*nbytes != 0) {
1535 x_fprintf(out, "\tadd esp, %lu\n",
1536 (unsigned long)*nbytes);
1537 f->total_allocated -= *nbytes;
1538 }
1539 }
1540 }
1541
1542 static void
1543 emit_adj_allocated(struct function *f, int *nbytes) {
1544 f->total_allocated += *nbytes;
1545 }
1546
1547 static void emit_struct_defs(void) { return; }
1548
1549
1550 static void
1551 emit_alloc(size_t nbytes) {
1552 unimpl();
1553 (void) nbytes;
1554 if (cursect == SECTION_INIT) {
1555 } else if (cursect == SECTION_UNINIT) {
1556 } else if (cursect == SECTION_STACK) {
1557 } else if (cursect == SECTION_TEXT) {
1558 }
1559 }
1560
1561
1562 static void
1563 print_mem_or_reg(struct reg *r, struct vreg *vr) {
1564 if (vr->on_var) {
1565 struct decl *d = vr->var_backed;
1566 char *p = size_to_asmtype(
1567 backend->get_sizeof_decl(d, NULL),
1568 d->dtype);
1569
1570 if (d->stack_addr) {
1571 x_fprintf(out, "%s [ebp - %ld]",
1572 p, d->stack_addr->offset);
1573 } else {
1574 x_fprintf(out, "%s %s", p, d->dtype->name);
1575 }
1576 } else if (r != NULL) {
1577 /*
1578 * 04/13/08: Note: If a register is available, use that one.
1579 * Because even if it's a constant, a register is more likely
1580 * to be correct if there's no immediate instruction
1581 */
1582 x_fprintf(out, "%s", r->name);
1583 } else if (vr->from_const) {
1584 if (backend->arch == ARCH_AMD64) {
1585 amd64_print_mem_operand_yasm(vr, NULL);
1586 } else {
1587 print_mem_operand(vr, NULL);
1588 }
1589 } else {
1590 unimpl();
1591 }
1592 }
1593
1594
1595
1596 static void
1597 emit_inc(struct icode_instr *ii) {
1598 x_fprintf(out, "\tinc ");
1599 print_mem_or_reg(ii->src_pregs[0], ii->src_vreg);
1600 x_fputc('\n', out);
1601 }
1602
1603 static void
1604 emit_dec(struct icode_instr *ii) {
1605 x_fprintf(out, "\tdec ");
1606 print_mem_or_reg(ii->src_pregs[0], ii->src_vreg);
1607 x_fputc('\n', out);
1608 }
1609
1610 static void
1611 emit_load(struct reg *r, struct vreg *vr) {
1612 char *p;
1613 int needsize = 1;
1614
1615 if (r->type == REG_FPR) {
1616 if (!IS_FLOATING(vr->type->code)) {
1617 #if ! REMOVE_FLOATBUF
1618 p = "fild";
1619 #else
1620 buggypath();
1621 #endif
1622 } else {
1623 p = "fld";
1624 }
1625 x_fprintf(out, "\t%s ", p);
1626 } else {
1627 if (vr->stack_addr != NULL) {
1628 p = "mov";
1629 } else if (vr->type
1630 && vr->type->tlist != NULL
1631 && (vr->type->tlist->type == TN_ARRAY_OF
1632 || vr->type->tlist->type == TN_VARARRAY_OF)) {
1633 if (vr->from_const == NULL) {
1634 p = "lea";
1635 } else {
1636 p = "mov";
1637 }
1638 needsize = 0;
1639 } else {
1640 if (r->size == vr->size
1641 || vr->size == 8) {
1642 /* == 8 for long long, SA for anonymous */
1643 p = "mov";
1644 } else {
1645 if (vr->type == NULL
1646 || vr->type->sign == TOK_KEY_UNSIGNED) {
1647 p = "movzx";
1648 } else {
1649 p = "movsx";
1650 }
1651 }
1652 }
1653 x_fprintf(out, "\t%s %s, ", p, r->name);
1654 }
1655
1656 if (vr->from_const != NULL && vr->size == 0) {
1657 needsize = 0;
1658 }
1659
1660 if (needsize) {
1661 struct type *ty = vr->type;
1662 size_t size = vr->size;
1663
1664 if (vr->stack_addr != NULL && r->type != REG_FPR) {
1665 size = r->size;
1666 ty = NULL;
1667 }
1668 x_fprintf(out, "%s ",
1669 size_to_asmtype(size, ty));
1670 }
1671 print_mem_operand(vr, NULL);
1672 x_fputc('\n', out);
1673 }
1674
1675 static void
1676 emit_load_addrlabel(struct reg *r, struct icode_instr *ii) {
1677 (void) r;
1678 x_fprintf(out, "\tmov %s, .%s\n", r->name, ii->dat);
1679 }
1680
1681 static void
1682 emit_comp_goto(struct reg *r) {
1683 x_fprintf(out, "\tjmp %s\n", r->name);
1684 }
1685
1686
1687 /*
1688 * Takes vreg source arg - not preg - so that it can be either a preg
1689 * or immediate (where that makes sense!)
1690 */
1691 static void
1692 emit_store(struct vreg *dest, struct vreg *src) {
1693 char *p = NULL;
1694 int floating = 0;
1695 static int was_llong;
1696
1697 if (src->pregs[0] && src->pregs[0]->type == REG_FPR) {
1698 if (!IS_FLOATING(dest->type->code)) {
1699 #if ! REMOVE_FLOATBUF
1700 p = "fistp";
1701 #else
1702 buggypath();
1703 #endif
1704 } else {
1705 p = "fstp";
1706 }
1707 floating = 1;
1708 } else {
1709 if (dest->stack_addr != NULL || dest->from_const != NULL) {
1710 p = "mov";
1711 } else {
1712 if (dest->size == 0) puts("?WHAT???"), unimpl();
1713 p = "mov";
1714 }
1715 }
1716 x_fprintf(out, "\t%s ", p);
1717 if (floating) {
1718 x_fprintf(out, "%s ", size_to_asmtype(dest->size, dest->type));
1719 }
1720 print_mem_operand(dest, NULL);
1721 if (floating) {
1722 /* Already done - floating stores only ever come from st0 */
1723 x_fputc('\n', out);
1724 return;
1725 }
1726 if (src->from_const) {
1727 print_mem_operand(src, NULL);
1728 } else {
1729 /* Must be register */
1730 if (was_llong) {
1731 x_fprintf(out, ", %s\n", src->pregs[1]->name);
1732 was_llong = 0;
1733 } else {
1734 x_fprintf(out, ", %s\n", src->pregs[0]->name);
1735 if (src->is_multi_reg_obj) {
1736 was_llong = 1;
1737 }
1738 }
1739 }
1740 }
1741
1742
1743 static void
1744 emit_neg(struct reg **dest, struct icode_instr *src) {
1745 (void) src;
1746 if (dest[0]->type == REG_FPR) {
1747 /* fchs only works with TOS! */
1748 x_fprintf(out, "\tfchs\n");
1749 } else {
1750 x_fprintf(out, "\tneg %s\n", dest[0]->name);
1751 if (src->src_vreg->is_multi_reg_obj) {
1752 x_fprintf(out, "\tadc %s, 0\n", dest[1]->name);
1753 x_fprintf(out, "\tneg %s\n", dest[1]->name);
1754 }
1755 }
1756 }
1757
1758
1759 static void
1760 emit_sub(struct reg **dest, struct icode_instr *src) {
1761 if (dest[0]->type == REG_FPR) {
1762 /*
1763 * 05/27/08: Use fsubrp instead of fsubp.. THAT'S WHAT
1764 * nasm had been generating anyway!!! (XXX why?)
1765 */
1766 x_fprintf(out, "\tfsubrp %s, ", dest[0]->name);
1767 } else {
1768 x_fprintf(out, "\tsub %s, ", dest[0]->name);
1769 }
1770 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
1771 if (src->src_vreg->is_multi_reg_obj
1772 && src->dest_vreg->is_multi_reg_obj) { /* for ptr arit */
1773 /* long long */
1774 x_fprintf(out, "\n\tsbb %s, %s\n",
1775 dest[1]->name, src->src_pregs[1]->name);
1776 }
1777 x_fputc('\n', out);
1778 }
1779
1780 static void
1781 emit_add(struct reg **dest, struct icode_instr *src) {
1782 if (dest[0]->type == REG_FPR) {
1783 x_fprintf(out, "\tfaddp %s, ", dest[0]->name);
1784 } else {
1785 x_fprintf(out, "\tadd %s, ", dest[0]->name);
1786 }
1787 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
1788 if (src->src_vreg->is_multi_reg_obj
1789 && src->dest_vreg->is_multi_reg_obj) { /* for ptr arit */
1790 /* long long */
1791 x_fprintf(out, "\n\tadc %s, %s\n",
1792 dest[1]->name, src->src_pregs[1]->name);
1793 }
1794 x_fputc('\n', out);
1795 }
1796
1797 static void
1798 make_divmul_call(struct icode_instr *src,
1799 const char *func,
1800 int want_remainder) {
1801
1802 int extra_pushed = 4;
1803 struct decl *d;
1804
1805 x_fprintf(out, "\tsub esp, 4\n");
1806 x_fprintf(out, "\tmov [esp], %s\n", src->dest_pregs[1]->name);
1807 x_fprintf(out, "\tsub esp, 4\n");
1808 x_fprintf(out, "\tmov [esp], %s\n", src->dest_pregs[0]->name);
1809 x_fprintf(out, "\tsub esp, 4\n");
1810 x_fprintf(out, "\tmov [esp], %s\n", src->src_pregs[1]->name);
1811 x_fprintf(out, "\tsub esp, 4\n");
1812 x_fprintf(out, "\tmov [esp], %s\n", src->src_pregs[0]->name);
1813 x_fprintf(out, "\tlea eax, [esp + 8]\n");
1814 x_fprintf(out, "\tlea ecx, [esp]\n");
1815
1816 /* Push data size */
1817 x_fprintf(out, "\tpush dword 64\n");
1818
1819 if (want_remainder != -1) {
1820 x_fprintf(out, "\tpush dword %d\n", want_remainder);
1821 extra_pushed += 4;
1822 }
1823 /* Push src address */
1824 x_fprintf(out, "\tpush dword ecx\n");
1825 /* Push dest address */
1826 x_fprintf(out, "\tpush dword eax\n");
1827
1828 /*
1829 * The lookup below ensures that __nwcc_ullmul, etc,
1830 * is not redeclared incompatibly in libnwcc.c, which
1831 * defines these functions and declares them ``global''.
1832 * This stuff is not necessary for gas!
1833 */
1834 if ((d = lookup_symbol(&global_scope, func, 0)) == NULL
1835 || !d->has_symbol) {
1836 x_fprintf(out, "\textern $%s\n", func);
1837 if (d != NULL) {
1838 d->has_symbol = 1;
1839 }
1840 }
1841 /*x_fprintf(out, "\tcall %s\n", func);*/
1842 emit_call(func);
1843
1844 /*
1845 * Result is saved in destination stack buffer - let's move it
1846 * to eax:edx
1847 */
1848 x_fprintf(out, "\tmov eax, [esp + %d]\n", 16+extra_pushed);
1849 x_fprintf(out, "\tmov edx, [esp + %d]\n", 20+extra_pushed);
1850 x_fprintf(out, "\tadd esp, %d\n", 24+extra_pushed);
1851 }
1852
1853 static void
1854 emit_div(struct reg **dest, struct icode_instr *src, int formod) {
1855 struct type *ty = src->src_vreg->type;
1856
1857 (void) dest;
1858 if (IS_LLONG(ty->code)) {
1859 char *func;
1860
1861 if (ty->code == TY_ULLONG) {
1862 func = "__nwcc_ulldiv";
1863 } else {
1864 func = "__nwcc_lldiv";
1865 }
1866 make_divmul_call(src, func, formod);
1867 return;
1868 } else if (!IS_FLOATING(ty->code)) {
1869 if (ty->sign != TOK_KEY_UNSIGNED) {
1870 /* sign-extend eax to edx:eax */
1871 x_fprintf(out, "\tcdq\n");
1872 } else {
1873 x_fprintf(out, "\txor edx, edx\n");
1874 }
1875 }
1876
1877 if (IS_FLOATING(ty->code)) {
1878 x_fprintf(out, "\tfdivp ");
1879 } else if (ty->sign == TOK_KEY_UNSIGNED) {
1880 x_fprintf(out, "\tdiv ");
1881 } else {
1882 /* signed integer division */
1883 x_fprintf(out, "\tidiv ");
1884 }
1885 if (IS_FLOATING(ty->code)) {
1886 print_mem_or_reg(src->dest_pregs[0], src->dest_vreg);
1887 } else {
1888 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
1889 }
1890 x_fputc('\n', out);
1891 }
1892
1893
1894 static void
1895 emit_mod(struct reg **dest, struct icode_instr *src) {
1896 emit_div(dest, src, 1);
1897 if (!IS_LLONG(src->dest_vreg->type->code)) {
1898 x_fprintf(out, "\tmov %s, edx\n", dest[0]->name);
1899 }
1900 }
1901
1902
1903 static void
1904 emit_mul(struct reg **dest, struct icode_instr *src) {
1905 struct type *ty = src->src_vreg->type;
1906
1907 (void) dest;
1908
1909 if (IS_LLONG(ty->code)) {
1910 char *func;
1911
1912 if (ty->code == TY_ULLONG) {
1913 func = "__nwcc_ullmul";
1914 } else {
1915 func = "__nwcc_llmul";
1916 }
1917 make_divmul_call(src, func, -1);
1918 return;
1919 } else if (IS_FLOATING(ty->code)) {
1920 x_fprintf(out, "\tfmulp ");
1921 } else if (ty->sign == TOK_KEY_UNSIGNED) {
1922 x_fprintf(out, "\tmul ");
1923 } else {
1924 /* signed integer multiplication */
1925 /* XXX should use mul for pointer arithmetic :( */
1926 x_fprintf(out, "\timul eax, ");
1927 }
1928 if (IS_FLOATING(ty->code)) {
1929 print_mem_or_reg(src->dest_pregs[0], src->dest_vreg);
1930 } else {
1931 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
1932 }
1933 x_fputc('\n', out);
1934 }
1935
1936 static unsigned long shift_idx;
1937
1938 /* XXX sal for signed values!!!!! */
1939 static void
1940 emit_shl(struct reg **dest, struct icode_instr *src) {
1941 int is_signed = src->dest_vreg->type->sign != TOK_KEY_UNSIGNED;
1942
1943 if (src->dest_vreg->is_multi_reg_obj) {
1944 if (src->src_vreg->from_const) {
1945 /* XXX lazy way */
1946 x_fprintf(out, "\tpush ecx\n");
1947 x_fprintf(out, "\tmov ecx, ");
1948 cross_print_value_by_type(out,
1949 src->src_vreg->from_const->data,
1950 TY_INT, 0);
1951 x_fputc('\n', out);
1952 }
1953 x_fprintf(out, "\tshld %s, %s, cl\n",
1954 dest[1]->name, dest[0]->name);
1955 x_fprintf(out, "\t%s %s, cl\n",
1956 is_signed? "sal": "shl", dest[0]->name);
1957 /* if (!is_signed) {*/
1958 x_fprintf(out, "\ttest cl, 32\n");
1959 x_fprintf(out, "\tje .shftdone%lu\n", shift_idx);
1960 x_fprintf(out, "\tmov %s, %s\n",
1961 dest[1]->name, dest[0]->name);
1962 x_fprintf(out, "\txor %s, %s\n", dest[0]->name, dest[0]->name);
1963 x_fprintf(out, ".shftdone%lu:\n", shift_idx++);
1964 /* } */
1965 if (src->src_vreg->from_const) {
1966 x_fprintf(out, "\tpop ecx\n");
1967 }
1968 } else {
1969 if (src->src_vreg->from_const) {
1970 x_fprintf(out, "\t%s %s, ",
1971 is_signed? "sal": "shl", dest[0]->name);
1972 cross_print_value_by_type(out,
1973 src->src_vreg->from_const->data,
1974 TY_INT, 0);
1975 x_fputc('\n', out);
1976 } else {
1977 x_fprintf(out, "\t%s %s, cl\n",
1978 is_signed? "sal": "shl", dest[0]->name);
1979 }
1980 }
1981 }
1982
1983
1984 /* XXX sar for signed values !!!!!!!! */
1985 static void
1986 emit_shr(struct reg **dest, struct icode_instr *src) {
1987 int is_signed = src->dest_vreg->type->sign != TOK_KEY_UNSIGNED;
1988
1989 if (src->dest_vreg->is_multi_reg_obj) {
1990 x_fprintf(out, "\tshrd %s, %s, cl\n",
1991 dest[0]->name, dest[1]->name);
1992 x_fprintf(out, "\t%s %s, cl\n",
1993 is_signed? "sar": "shr", dest[1]->name);
1994 /* if (!is_signed) {*/
1995 x_fprintf(out, "\tand ecx, 32\n");
1996 x_fprintf(out, "\tje .shftdone%lu\n", shift_idx);
1997 x_fprintf(out, "\tmov %s, %s\n",
1998 dest[0]->name, dest[1]->name);
1999
2000 /*
2001 * 06/21/08: This was always sign-extending! Zero-
2002 * extend for unsigned values
2003 */
2004 if (is_signed) {
2005 x_fprintf(out, "\t%s %s, 31\n",
2006 is_signed? "sar": "shr", dest[1]->name);
2007 } else {
2008 x_fprintf(out, "\tmov %s, 0\n", dest[1]->name);
2009 }
2010
2011 x_fprintf(out, ".shftdone%lu:\n", shift_idx++);
2012 /* } */
2013 } else {
2014 if (src->src_vreg->from_const) {
2015 x_fprintf(out, "\t%s %s, ",
2016 is_signed? "sar": "shr", dest[0]->name);
2017 cross_print_value_by_type(out,
2018 src->src_vreg->from_const->data,
2019 TY_INT, 0);
2020 x_fputc('\n', out);
2021 } else {
2022 x_fprintf(out, "\t%s %s, cl\n",
2023 is_signed? "sar": "shr", dest[0]->name);
2024 }
2025 }
2026 }
2027
2028 static void
2029 emit_or(struct reg **dest, struct icode_instr *src) {
2030 x_fprintf(out, "\tor %s, ", dest[0]->name);
2031 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
2032 x_fputc('\n', out);
2033 if (src->src_vreg->is_multi_reg_obj) {
2034 x_fprintf(out, "\tor %s, %s\n",
2035 dest[1]->name, src->src_pregs[1]->name);
2036 }
2037 }
2038
2039 static void
2040 emit_and(struct reg **dest, struct icode_instr *src) {
2041 x_fprintf(out, "\tand %s, ", dest[0]->name);
2042 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
2043 x_fputc('\n', out);
2044 if (src->src_vreg->is_multi_reg_obj) {
2045 x_fprintf(out, "\tand %s, %s\n",
2046 dest[1]->name, src->src_pregs[1]->name);
2047 }
2048 }
2049
2050 static void
2051 emit_xor(struct reg **dest, struct icode_instr *src) {
2052 x_fprintf(out, "\txor %s, ", dest[0]->name);
2053 if (src->src_vreg == NULL) {
2054 x_fprintf(out, "%s\n", dest[0]->name);
2055 if (src->src_vreg->is_multi_reg_obj) {
2056 x_fprintf(out, "\txor %s, %s\n",
2057 dest[1]->name, dest[1]->name);
2058 }
2059 } else {
2060 print_mem_or_reg(src->src_pregs[0], src->src_vreg);
2061 x_fputc('\n', out);
2062 if (src->src_vreg->is_multi_reg_obj) {
2063 x_fprintf(out, "\txor %s, %s\n",
2064 dest[1]->name, src->src_pregs[1]->name);
2065 }
2066 }
2067 }
2068
2069 static void
2070 emit_not(struct reg **dest, struct icode_instr *src) {
2071 (void) src;
2072 x_fprintf(out, "\tnot %s\n", dest[0]->name);
2073 if (src->src_vreg->is_multi_reg_obj) {
2074 x_fprintf(out, "\tnot %s\n", dest[1]->name);
2075 }
2076 }
2077
2078 static void
2079 emit_ret(struct icode_instr *ii) {
2080 (void) ii;
2081
2082 if (curfunc->proto->dtype->tlist->next == NULL
2083 && (curfunc->proto->dtype->code == TY_STRUCT
2084 || curfunc->proto->dtype->code == TY_UNION)) {
2085 /*
2086 * The hidden pointer used for structure returns
2087 * is cleaned up by the callee. This NONSENSE has
2088 * cost me a long time to track down ...
2089 */
2090 x_fprintf(out, "\tret 4\n");
2091 } else {
2092 x_fprintf(out, "\tret\n"); /* XXX */
2093 }
2094 }
2095
2096 struct icode_instr *last_x87_cmp;
2097 struct icode_instr *last_sse_cmp;
2098
2099 static void
2100 emit_cmp(struct reg **dest, struct icode_instr *src) {
2101 static int was_llong;
2102 int reg_idx = 0;
2103 int need_ffree = 0;
2104
2105 if (dest[0]->type == REG_FPR) {
2106 if (is_x87_trash(src->dest_vreg)) {
2107 last_x87_cmp = src;
2108 } else {
2109 /* Must be SSE */
2110 last_sse_cmp = src;
2111 }
2112 return;
2113 } else {
2114 if (was_llong) {
2115 reg_idx = 0;
2116 was_llong = 0;
2117 } else {
2118 if (src->dest_vreg->is_multi_reg_obj) {
2119 if (!(src->hints &
2120 HINT_INSTR_NEXT_NOT_SECOND_LLONG_WORD)) {
2121 /*
2122 * 06/02/08: Conditional for repeated
2123 * cmps on same dword!
2124 */
2125 was_llong = 1;
2126 }
2127 reg_idx = 1;
2128 } else {
2129 reg_idx = 0;
2130 }
2131 }
2132 fprintf(out, "\tcmp %s, ", dest[reg_idx]->name);
2133 }
2134 if (src->src_pregs == NULL || src->src_vreg == NULL) {
2135 fputc('0', out);
2136 } else {
2137 print_mem_or_reg(src->src_pregs[/*0*/reg_idx], src->src_vreg);
2138 }
2139 x_fputc('\n', out);
2140 if (need_ffree) {
2141 x_fprintf(out, "\tffree st0\n");
2142 }
2143 }
2144
2145 static void
2146 emit_branch(struct icode_instr *ii) {
2147 char *lname;
2148 char *opcode = NULL;
2149 int i;
2150 int is_signed;
2151 static const struct {
2152 int type;
2153 char *for_signed;
2154 char *for_unsigned;
2155 } instructions[] = {
2156 { INSTR_BR_EQUAL, "je", "je" },
2157 { INSTR_BR_SMALLER, "jl", "jb" }, /* less/below */
2158 { INSTR_BR_SMALLEREQ, "jle", "jbe" }, /* less/below or equal */
2159 { INSTR_BR_GREATER, "jg", "ja" }, /* greater/above */
2160 { INSTR_BR_GREATEREQ, "jge", "jae" }, /* greater/above or eq */
2161 { INSTR_BR_NEQUAL, "jne", "jne" },
2162 { INSTR_JUMP, "jmp", "jmp" },
2163 { -1, NULL, NULL }
2164 };
2165
2166 lname = ((struct icode_instr *)ii->dat)->dat;
2167 if (ii->dest_vreg
2168 && is_floating_type(ii->dest_vreg->type)) {
2169 int cmp_with = 0;
2170 int branch_if_equals = 0;
2171 int is_sse = 0;
2172
2173 if (is_x87_trash(ii->dest_vreg)) {
2174 fprintf(out, "\tfucomip st1\n");
2175 } else {
2176 /*
2177 * Since this is fp but not x87, it must be SSE.
2178 * This means we have to generate a ucomisd/ucomiss
2179 */
2180 is_sse = 1;
2181
2182 if (last_sse_cmp->dest_vreg->type->code == TY_FLOAT) {
2183 x_fprintf(out, "\tucomiss %s, %s\n",
2184 last_sse_cmp->src_pregs[0]->name,
2185 last_sse_cmp->dest_pregs[0]->name);
2186 } else {
2187 /* double */
2188 x_fprintf(out, "\tucomisd %s, %s\n",
2189 last_sse_cmp->src_pregs[0]->name,
2190 last_sse_cmp->dest_pregs[0]->name);
2191 }
2192 }
2193
2194 /*
2195 * Now we kludge our way around the x87/SSE way of
2196 * signaling (in-)equality (both set eflags in the
2197 * same way)...
2198 * The flags register has the following meaningful flags:
2199 *
2200 * ZF=0, PF=0, CF=0 means st(0) > st(1)
2201 * ZF=0, PF=0, CF=1 means st(0) < st(1)
2202 * ZF=1, PF=0, CF=0 means st(0) = st(1)
2203 *
2204 * CF = bit 0 (lowest)
2205 * PF = bit 2
2206 * ZF = bit 6
2207 *
2208 * On x86 we can use the lahf instruction to get that
2209 * flag register byte, however this is not available on
2210 * AMD64, so we have to set* and or those flags together.
2211 */
2212 #define FP_EQU_MASK (1 /*CF*/ | (1 << 2) /*PF*/ | (1 << 6) /*ZF*/)
2213 #define ST1_SMALLER (0)
2214 #define ST1_GREATER (1)
2215 #define ST1_EQUAL (1 << 6)
2216 if (backend->arch == ARCH_AMD64) {
2217 x_fprintf(out, "\tpush rax\n"); /* save ah/al */
2218 x_fprintf(out, "\tpush rbx\n"); /* save bl */
2219
2220 /*
2221 * Now painfully construct flags in ah like
2222 * lahf plus masking does on x86. It is VERY
2223 * important to do the set stuff before or'ing
2224 * because or also sets flags! (sadly I got
2225 * this wrong first, which cost me a good hour
2226 * :-()
2227 */
2228 x_fprintf(out, "\tsetc ah\n");
2229 x_fprintf(out, "\tsetp al\n");
2230 x_fprintf(out, "\tsetz bl\n");
2231 x_fprintf(out, "\tshl al, 2\n");
2232 x_fprintf(out, "\tshl bl, 6\n");
2233 x_fprintf(out, "\tor ah, al\n");
2234 x_fprintf(out, "\tor ah, bl\n");
2235 } else {
2236 x_fprintf(out, "\tpush eax\n"); /* save ah */
2237 x_fprintf(out, "\tlahf\n"); /* get flags */
2238
2239 /* Mask off unused flags */
2240 x_fprintf(out, "\tand ah, %d\n", FP_EQU_MASK);
2241 }
2242
2243 switch (ii->type) {
2244 case INSTR_BR_EQUAL:
2245 cmp_with = ST1_EQUAL;
2246 branch_if_equals = 1;
2247 break;
2248 case INSTR_BR_SMALLER:
2249 cmp_with = ST1_SMALLER;
2250 branch_if_equals = 1;
2251 break;
2252 case INSTR_BR_SMALLEREQ:
2253 cmp_with = ST1_GREATER;
2254 branch_if_equals = 0;
2255 break;
2256 case INSTR_BR_GREATER:
2257 cmp_with = ST1_GREATER;
2258 branch_if_equals = 1;
2259 break;
2260 case INSTR_BR_GREATEREQ:
2261 cmp_with = ST1_SMALLER;
2262 branch_if_equals = 0;
2263 break;
2264 case INSTR_BR_NEQUAL:
2265 cmp_with = ST1_EQUAL;
2266 branch_if_equals = 0;
2267 break;
2268 default:
2269 unimpl();
2270 }
2271 x_fprintf(out, "\tcmp ah, %d\n", cmp_with);
2272
2273 if (backend->arch == ARCH_AMD64) {
2274 x_fprintf(out, "\tpop rbx\n"); /* restore bl */
2275 x_fprintf(out, "\tpop rax\n"); /* restore ah/al */
2276 } else {
2277 x_fprintf(out, "\tpop eax\n"); /* restore ah */
2278 }
2279
2280 if (!is_sse) {
2281 /* Now free second used fp reg */
2282 x_fprintf(out, "\tffree st0\n");
2283 }
2284
2285 /* Finally branch! */
2286 x_fprintf(out, "\t%s near .%s\n",
2287 branch_if_equals? "je": "jne", lname);
2288
2289 return;
2290 }
2291
2292
2293 if (ii->dest_vreg == NULL) {
2294 /* Signedness doesn't matter */
2295 is_signed = 1;
2296 } else {
2297 /*
2298 * 06/29/08: This was missing the check whether we
2299 * are comparing pointers, and thus need unsigned
2300 * comparison
2301 */
2302 if (ii->dest_vreg->type->sign == TOK_KEY_UNSIGNED
2303 || ii->dest_vreg->type->tlist != NULL) {
2304 is_signed = 0;
2305 } else {
2306 is_signed = 1;
2307 }
2308 }
2309
2310 for (i = 0; instructions[i].type != -1; ++i) {
2311 if (instructions[i].type == ii->type) {
2312 if (is_signed) {
2313 opcode = instructions[i].for_signed;
2314 } else {
2315 opcode = instructions[i].for_unsigned;
2316 }
2317 break;
2318 }
2319 }
2320 if (instructions[i].type == -1) {
2321 printf("BUG: bad branch instruction - %d\n",
2322 ii->type);
2323 abort();
2324 }
2325
2326 /* XXX the near part may not always be necessary */
2327 x_fprintf(out, "\t%s near .%s\n", opcode, lname);
2328 }
2329
2330 struct reg *
2331 get_smaller_reg(struct reg *r, size_t size) {
2332 if (r->size == 8 && r->composed_of) {
2333 return get_smaller_reg(r->composed_of[0], size);
2334 }
2335 if (r->size == size) return r;
2336 if (r->size == 4) {
2337 if (size == 2) {
2338 return r->composed_of[0];
2339 } else { /* 1 */
2340 if (r->composed_of[0]->composed_of[1]) {
2341 return r->composed_of[0]->composed_of[1];
2342 } else {
2343 /* amd64 gpr */
2344 return r->composed_of[0]->composed_of[0];
2345 }
2346 }
2347 } else {
2348 /* 2 */
2349 return r->composed_of[1];
2350 }
2351 }
2352
2353 static void
2354 print_reg_assign(
2355 struct reg *dest,
2356 struct reg *srcreg,
2357 size_t src_size,
2358 struct type *src_type) {
2359
2360 if (dest->type == REG_FPR) {
2361 if (!IS_FLOATING(src_type->code)) {
2362 x_fprintf(out, "\tfild ");
2363 } else {
2364 x_fprintf(out, "\tfld ");
2365 }
2366 return;
2367 }
2368
2369 if (src_type->tlist != NULL
2370 && (src_type->tlist->type == TN_ARRAY_OF
2371 || src_type->tlist->type == TN_VARARRAY_OF)) {
2372 x_fprintf(out, "\tlea %s, ", dest->name);
2373 return;
2374 }
2375
2376 if (dest->size == src_size || src_size == 8) {
2377 /* == 8 for long long on x86 */
2378 x_fprintf(out, "\tmov %s, ", dest->name);
2379 } else {
2380 /* dest > src */
2381 if (src_type->sign == TOK_KEY_UNSIGNED) {
2382 if (backend->arch == ARCH_AMD64
2383 && dest->size == 8
2384 && src_size == 4) {
2385 if (!isdigit(dest->name[1])) {
2386 /*
2387 * e.g. mov eax, edx zero extends
2388 * upper 32bits of rax
2389 */
2390 x_fprintf(out, "\tmov %s, ",
2391 dest->composed_of[0]->name);
2392 } else {
2393 /* XXX there must be a better way :( */
2394 x_fprintf(out, "\tpush rax\n");
2395 x_fprintf(out, "\tmov eax, %s\n",
2396 srcreg->name);
2397 x_fprintf(out, "\tmov %s, rax\n",
2398 dest->name);
2399 x_fprintf(out, "\tpop rax\n");
2400 return;
2401 }
2402 } else {
2403 x_fprintf(out, "\tmovzx %s, ", dest->name);
2404 }
2405 } else {
2406 if (backend->arch == ARCH_AMD64
2407 && dest->size == 8
2408 && src_size == 4) {
2409 x_fprintf(out, "\tmovsxd %s, ", dest->name);
2410 } else {
2411 x_fprintf(out, "\tmovsx %s, ", dest->name);
2412 }
2413 }
2414 }
2415
2416 if (srcreg != NULL) {
2417 x_fprintf(out, "%s\n", srcreg->name);
2418 }
2419 }
2420
2421
2422 static void
2423 emit_mov(struct copyreg *cr) {
2424 struct reg *dest = cr->dest_preg;
2425 struct reg *src = cr->src_preg;
2426 struct type *src_type = cr->src_type;
2427
2428 if (src == NULL) {
2429 /* Move null to register (XXX fp?) */
2430 x_fprintf(out, "\tmov %s, 0\n",
2431 dest->name /*, size_to_asmtype(dest->size, NULL)*/);
2432 } else if (dest->type == REG_FPR) {
2433 /* XXX ... */
2434 if (STUPID_X87(dest)) {
2435 x_fprintf(out, "\tfxch %s, %s\n",
2436 dest->name, src->name);
2437 } else {
2438 x_fprintf(out, "\tmovs%c %s, %s\n",
2439 src_type->code == TY_FLOAT? 's': 'd',
2440 dest->name, src->name);
2441 }
2442 } else if (dest->size == src->size) {
2443 x_fprintf(out, "\tmov %s, %s\n", dest->name, src->name);
2444 } else if (dest->size > src->size) {
2445 print_reg_assign(dest, src, src->size, src_type);
2446 /*x_fprintf(out, "%s\n", src->name);*/
2447 } else {
2448 /* source larger than dest */
2449 src = get_smaller_reg(src, dest->size);
2450 x_fprintf(out, "\tmov %s, %s\n", dest->name, src->name);
2451 }
2452 }
2453
2454
2455 static void
2456 emit_setreg(struct reg *dest, int *value) {
2457 x_fprintf(out, "\tmov %s, %d\n", dest->name, *(int *)value);
2458 }
2459
2460 static void
2461 emit_xchg(struct reg *r1, struct reg *r2) {
2462 x_fprintf(out, "\txchg %s, %s\n", r1->name, r2->name);
2463 }
2464
2465 static void
2466 emit_initialize_pic(struct function *f) {
2467 char buf[128];
2468 static unsigned long count;
2469
2470 (void) f;
2471 sprintf(buf, ".Piclab%lu", count++);
2472 x_fprintf(out, "\tcall %s\n", buf);
2473 x_fprintf(out, "%s:\n", buf);
2474 x_fprintf(out, "\tpop ebx\n");
2475 x_fprintf(out, "\tadd ebx, _GLOBAL_OFFSET_TABLE_+$$-%s wrt ..gotpc\n",
2476 buf);
2477 }
2478
2479 static void
2480 emit_addrof(struct reg *dest, struct vreg *src, struct vreg *structtop) {
2481 struct decl *d;
2482 long offset = 0;
2483 char *sign = NULL;
2484 char *base_pointer;
2485
2486 if (backend->arch == ARCH_AMD64) {
2487 base_pointer = "rbp";
2488 } else {
2489 base_pointer = "ebp";
2490 }
2491
2492 if (src == NULL) {
2493 d = curfunc->proto->dtype->tlist->tfunc->lastarg;
2494 } else {
2495 d = src->var_backed;
2496 }
2497
2498 if (structtop != NULL) {
2499 d = structtop->var_backed;
2500 }
2501
2502 if (d != NULL) {
2503 if (d->stack_addr != NULL) {
2504 if (d->stack_addr->is_func_arg) {
2505 sign = "+";
2506 } else {
2507 sign = "-";
2508 }
2509 offset = d->stack_addr->offset;
2510 } else if (IS_THREAD(d->dtype->flags)) {
2511 x_fprintf(out, "\tmov %s, gs\n", dest->name);
2512 x_fprintf(out, "\tmov %s, [%s + %s wrt ..tpoff]\n",
2513 dest->name, dest->name, d->dtype->name);
2514 return;
2515 } else if (picflag) {
2516 if (d->dtype->is_func && d->dtype->tlist->type ==
2517 TN_FUNCTION) {
2518 x_fprintf(out, "\tlea %s, [ebx+%s "
2519 "wrt ..got]\n",
2520 dest->name, d->dtype->name);
2521 } else if (d->dtype->storage == TOK_KEY_STATIC
2522 || d->dtype->storage == TOK_KEY_EXTERN) {
2523 if (backend->arch == ARCH_AMD64) {
2524 x_fprintf(out, "\tmov %s, [rel %s wrt ..gotpcrel]\n",
2525 dest->name, d->dtype->name);
2526 } else {
2527 x_fprintf(out, "\tmov %s, [ebx+%s "
2528 "wrt ..got]\n",
2529 dest->name, d->dtype->name);
2530 }
2531 if (src->parent != NULL) {
2532 x_fprintf(out, "\tadd %s, %ld\n",
2533 dest->name, calc_offsets(src));
2534 }
2535 }
2536 return;
2537 }
2538 } else if (picflag && src->from_const != NULL) {
2539 /*
2540 * Not variable, but may be constant that needs a PIC
2541 * relocation too. Most likely a string constant, but may
2542 * also be an FP constant
2543 */
2544 char *name = NULL;
2545 char buf[128];
2546
2547 if (src->from_const->type == TOK_STRING_LITERAL) {
2548 struct ty_string *ts = src->from_const->data;
2549 sprintf(buf, "_Str%lu", ts->count);
2550 name = buf;
2551 } else if (IS_FLOATING(src->from_const->type)) {
2552 struct ty_float *tf = src->from_const->data;
2553 sprintf(buf, "_Float%lu", tf->count); /* XXX preceding . ? */
2554 name = buf;
2555 }
2556 if (name != NULL) {
2557 if (backend->arch == ARCH_AMD64) {
2558 x_fprintf(out, "\tmov %s, [rel %s wrt ..gotpcrel]\n",
2559 dest->name, name);
2560 } else {
2561 x_fprintf(out, "\tmov %s, [ebx + %s wrt ..got]\n",
2562 dest->name, name);
2563 }
2564 return;
2565 }
2566 }
2567
2568 if (src && src->parent != NULL) {
2569 /* Structure or union type */
2570 if (d != NULL) {
2571 if (d->stack_addr != NULL) {
2572 x_fprintf(out, "\tlea %s, [%s %s %ld",
2573 dest->name, base_pointer,
2574 sign, offset);
2575 } else {
2576 /* Static */
2577 x_fprintf(out, "\tlea %s, [$%s",
2578 dest->name, d->dtype->name);
2579 }
2580 } else if (structtop->from_ptr) {
2581 x_fprintf(out, "\tlea %s, [%s",
2582 dest->name,
2583 structtop->from_ptr->pregs[0]->name);
2584 } else {
2585 printf("hm attempt to take address of %s\n",
2586 src->type->name);
2587 unimpl();
2588 }
2589 x_fputc(' ', out);
2590 print_nasm_offsets(src);
2591 x_fprintf(out, "]\n");
2592 } else if (src && src->from_ptr) {
2593 x_fprintf(out, "\tmov %s, %s\n",
2594 dest->name, src->from_ptr->pregs[0]->name);
2595 } else if (src && src->from_const && src->from_const->type == TOK_STRING_LITERAL) {
2596 /* 08/21/08: This was missing */
2597 emit_load(dest, src);
2598 } else {
2599 if (d && d->stack_addr) {
2600 if (src == NULL) {
2601 /* Move past object */
2602 offset += d->stack_addr->nbytes;
2603 }
2604
2605 x_fprintf(out, "\tlea %s, [%s %s %ld]\n",
2606 dest->name, base_pointer, sign, offset);
2607 } else if (d) {
2608 /*
2609 * Must be static variable - symbol itself is
2610 * address
2611 */
2612 x_fprintf(out, "\tmov %s, $%s\n",
2613 dest->name, d->dtype->name);
2614 } else {
2615 printf("BUG: Cannot take address of item! preg=%p\n",
2616 src->pregs[0]);
2617 abort();
2618 }
2619 }
2620 }
2621
2622
2623 static void
2624 emit_fxch(struct reg *r, struct reg *r2) {
2625 x_fprintf(out, "\tfxch %s, %s\n", r->name, r2->name);
2626 }
2627
2628 static void
2629 emit_ffree(struct reg *r) {
2630 x_fprintf(out, "\tffree %s\n", r->name);
2631 }
2632
2633
2634 static void
2635 emit_fnstcw(struct vreg *vr) {
2636 x_fprintf(out, "\tfnstcw [$%s]\n", vr->type->name);
2637 }
2638
2639 static void
2640 emit_fldcw(struct vreg *vr) {
2641 x_fprintf(out, "\tfldcw [$%s]\n", vr->type->name);
2642 }
2643
2644 /*
2645 * Copy initializer to automatic variable of aggregate type
2646 */
2647 static void
2648 emit_copyinit(struct decl *d) {
2649 x_fprintf(out, "\tpush dword %lu\n",
2650 (unsigned long)backend->get_sizeof_type(d->dtype, NULL) /*d->vreg->size*/);
2651 x_fprintf(out, "\tpush dword %s\n", d->init_name->name);
2652 x_fprintf(out, "\tlea eax, [ebp - %lu]\n", d->stack_addr->offset);
2653 x_fprintf(out, "\tpush dword eax\n");
2654 x_fprintf(out, "\tcall memcpy\n");
2655 x_fprintf(out, "\tadd esp, 12\n");
2656 }
2657
2658
2659 /*
2660 * Assign one struct to another (may be any of automatic or static or
2661 * addressed thru pointer)
2662 */
2663 static void
2664 emit_copystruct(struct copystruct *cs) {
2665 struct vreg *stop;
2666 struct reg *tmpreg = NULL;
2667 int i;
2668
2669 /* Get temporary register not used by our pointer(s), if any */
2670 for (i = 0; i < 4; ++i) {
2671 if (i == 1) {
2672 /* Don't use ebx as it's callee-saved */
2673 continue;
2674 }
2675
2676 if (&x86_gprs[i] != cs->dest_from_ptr
2677 && &x86_gprs[i] != cs->src_from_ptr
2678 && &x86_gprs[i] != cs->dest_from_ptr_struct
2679 && &x86_gprs[i] != cs->src_from_ptr_struct) {
2680 tmpreg = &x86_gprs[i];
2681 break;
2682 }
2683 }
2684
2685 x_fprintf(out, "\tpush dword %lu\n", (unsigned long)cs->src_vreg->size);
2686 if (cs->src_from_ptr == NULL) {
2687 if (cs->src_vreg->parent) {
2688 stop = get_parent_struct(cs->src_vreg);
2689 } else {
2690 stop = NULL;
2691 }
2692 emit_addrof(tmpreg, cs->src_vreg, stop);
2693 x_fprintf(out, "\tpush dword %s\n", tmpreg->name);
2694 } else {
2695 if (cs->src_vreg->parent) {
2696 x_fprintf(out, "\tadd %s, %lu\n",
2697 cs->src_from_ptr->name,
2698 calc_offsets(cs->src_vreg));
2699 /* cs->src_vreg->memberdecl->offset); */
2700 }
2701 x_fprintf(out, "\tpush dword %s\n", cs->src_from_ptr->name);
2702 }
2703
2704 if (cs->dest_from_ptr == NULL) {
2705 if (cs->dest_vreg->parent) {
2706 stop = get_parent_struct(cs->dest_vreg);
2707 } else {
2708 stop = NULL;
2709 }
2710 emit_addrof(tmpreg, cs->dest_vreg, stop);
2711 x_fprintf(out, "\tpush dword %s\n", tmpreg->name);
2712 } else {
2713 if (cs->dest_vreg->parent) {
2714 x_fprintf(out, "\tadd %s, %lu\n",
2715 cs->dest_from_ptr->name,
2716 calc_offsets(cs->dest_vreg));
2717 /* cs->dest_vreg->memberdecl->offset); */
2718 }
2719 x_fprintf(out, "\tpush dword %s\n", cs->dest_from_ptr->name);
2720 }
2721 x_fprintf(out, "\tcall memcpy\n");
2722 x_fprintf(out, "\tadd esp, 12\n");
2723 }
2724
2725 static void
2726 emit_intrinsic_memcpy(struct int_memcpy_data *data) {
2727 struct reg *dest = data->dest_addr;
2728 struct reg *src = data->src_addr;
2729 struct reg *nbytes = data->nbytes;
2730 struct reg *temp = data->temp_reg;
2731 static int labelcount;
2732
2733 if (data->type == BUILTIN_MEMSET && src != temp) {
2734 x_fprintf(out, "\tmov %s, %s\n", temp->name, src->name);
2735 }
2736 x_fprintf(out, "\tcmp %s, 0\n", nbytes->name);
2737 x_fprintf(out, "\tje .Memcpy_done%d\n", labelcount);
2738 x_fprintf(out, ".Memcpy_start%d:\n", labelcount);
2739 if (data->type == BUILTIN_MEMCPY) {
2740 x_fprintf(out, "\tmov %s, [%s]\n", temp->name, src->name);
2741 }
2742 x_fprintf(out, "\tmov [%s], %s\n", dest->name, temp->name);
2743 x_fprintf(out, "\tinc %s\n", dest->name);
2744 if (data->type == BUILTIN_MEMCPY) {
2745 x_fprintf(out, "\tinc %s\n", src->name);
2746 }
2747 x_fprintf(out, "\tdec %s\n", nbytes->name);
2748 x_fprintf(out, "\tcmp %s, 0\n", nbytes->name);
2749 x_fprintf(out, "\tjne .Memcpy_start%d\n", labelcount);
2750 x_fprintf(out, ".Memcpy_done%d:\n", labelcount);
2751 ++labelcount;
2752 }
2753
2754 static void
2755 emit_zerostack(struct stack_block *sb, size_t nbytes) {
2756 x_fprintf(out, "\tpush dword %lu\n", (unsigned long)nbytes);
2757 x_fprintf(out, "\tpush dword 0\n");
2758 x_fprintf(out, "\tlea ecx, [ebp - %lu]\n",
2759 (unsigned long)sb->offset);
2760 x_fprintf(out, "\tpush dword ecx\n");
2761 x_fprintf(out, "\tcall memset\n");
2762 x_fprintf(out, "\tadd esp, 12\n");
2763 }
2764
2765 static void
2766 emit_alloca(struct allocadata *ad) {
2767 x_fprintf(out, "\tpush dword %s\n", ad->size_reg->name);
2768 x_fprintf(out, "\tcall malloc\n");
2769 x_fprintf(out, "\tadd esp, 4\n");
2770 if (ad->result_reg != &x86_gprs[0]) {
2771 x_fprintf(out, "\tmov %s, eax\n",
2772 ad->result_reg->name);
2773 }
2774 }
2775
2776
2777 static void
2778 emit_dealloca(struct stack_block *sb, struct reg *r) {
2779 char *regname = r? r->name: "ecx";
2780
2781 x_fprintf(out, "\tmov %s, [ebp - %lu]\n",
2782 regname,
2783 (unsigned long)sb->offset);
2784 x_fprintf(out, "\tpush dword %s\n", regname);
2785 x_fprintf(out, "\tcall free\n");
2786 x_fprintf(out, "\tadd esp, 4\n");
2787 }
2788
2789 static void
2790 emit_alloc_vla(struct stack_block *sb) {
2791 x_fprintf(out, "\tmov ecx, [ebp - %lu]\n",
2792 (unsigned long)sb->offset - backend->get_ptr_size());
2793 x_fprintf(out, "\tpush dword ecx\n");
2794 x_fprintf(out, "\tcall malloc\n");
2795 x_fprintf(out, "\tadd esp, 4\n");
2796 x_fprintf(out, "\tmov [ebp - %lu], eax\n",
2797 (unsigned long)sb->offset);
2798 }
2799
2800
2801 static void
2802 emit_dealloc_vla(struct stack_block *sb, struct reg *r) {
2803 char *regname = r? r->name: "ecx";
2804
2805 x_fprintf(out, "\tmov %s, [ebp - %lu]\n",
2806 regname,
2807 (unsigned long)sb->offset);
2808 x_fprintf(out, "\tpush dword %s\n", regname);
2809 x_fprintf(out, "\tcall free\n");
2810 x_fprintf(out, "\tadd esp, 4\n");
2811 }
2812
2813 static void
2814 emit_put_vla_size(struct vlasizedata *data) {
2815 x_fprintf(out, "\tmov [ebp - %lu], %s\n",
2816 (unsigned long)data->blockaddr->offset - data->offset,
2817 data->size->name);
2818 }
2819
2820 static void
2821 emit_retr_vla_size(struct vlasizedata *data) {
2822 x_fprintf(out, "\tmov %s, [ebp - %lu]\n",
2823 data->size->name,
2824 (unsigned long)data->blockaddr->offset - data->offset);
2825 }
2826
2827 static void
2828 emit_load_vla(struct reg *r, struct stack_block *sb) {
2829 x_fprintf(out, "\tmov %s, [ebp - %lu]\n",
2830 r->name,
2831 (unsigned long)sb->offset);
2832 }
2833
2834 static void
2835 emit_frame_address(struct builtinframeaddressdata *dat) {
2836 x_fprintf(out, "\tmov %s, ebp\n", dat->result_reg->name);
2837 }
2838
2839
2840 static void
2841 emit_cdq(void) {
2842 x_fprintf(out, "\tcdq\n");
2843 }
2844
2845 static void
2846 emit_fist(struct fistdata *dat) {
2847 int size = backend->get_sizeof_type(dat->target_type, NULL);
2848
2849 x_fprintf(out, "\tfistp %s ",
2850 /*dat->vr->*/size == 4? "dword": "qword");
2851 if (backend->arch == ARCH_AMD64) {
2852 amd64_print_mem_operand_yasm(dat->vr, NULL);
2853 } else {
2854 print_mem_operand(dat->vr, NULL);
2855 print_mem_operand(NULL, NULL);
2856 }
2857 x_fputc('\n', out);
2858 }
2859
2860 static void
2861 emit_fild(struct filddata *dat) {
2862 x_fprintf(out, "\tfild %s ",
2863 dat->vr->size == 4? "dword": "qword");
2864 if (backend->arch == ARCH_AMD64) {
2865 amd64_print_mem_operand_yasm(dat->vr, NULL);
2866 } else {
2867 print_mem_operand(dat->vr, NULL);
2868 print_mem_operand(NULL, NULL);
2869 }
2870 x_fputc('\n', out);
2871 }
2872
2873 static void
2874 emit_x86_ulong_to_float(struct icode_instr *ii) {
2875 struct amd64_ulong_to_float *data = ii->dat;
2876 static unsigned long count;
2877
2878 x_fprintf(out, "\ttest %s, %s\n", data->src_gpr->name, data->src_gpr->name);
2879 x_fprintf(out, "\tjs ._Ulong_float%lu\n", count);
2880 x_fprintf(out, "\tjmp ._Ulong_float%lu\n", count+1);
2881 x_fprintf(out, "._Ulong_float%lu:\n", count);
2882 x_fprintf(out, "\tfadd dword [_Ulong_float_mask]\n");
2883 x_fprintf(out, "._Ulong_float%lu:\n", count+1);
2884 count += 2;
2885 }
2886
2887 static void
2888 emit_save_ret_addr(struct function *f, struct stack_block *sb) {
2889 (void) f;
2890
2891 x_fprintf(out, "\tmov eax, [ebp + 4]\n");
2892 x_fprintf(out, "\tmov [ebp - %lu], eax\n", sb->offset);
2893 }
2894
2895 static void
2896 emit_check_ret_addr(struct function *f, struct stack_block *saved) {
2897 static unsigned long labval = 0;
2898
2899 (void) f;
2900
2901 x_fprintf(out, "\tmov ecx, [ebp - %lu]\n", saved->offset);
2902 x_fprintf(out, "\tcmp ecx, dword [ebp + 4]\n");
2903 x_fprintf(out, "\tje .doret%lu\n", labval);
2904 x_fprintf(out, "\textern __nwcc_stack_corrupt\n");
2905 /* x_fprintf(out, "\tcall __nwcc_stack_corrupt\n");*/
2906 emit_call("__nwcc_stack_corrupt");
2907 x_fprintf(out, ".doret%lu:\n", labval++);
2908 }
2909
2910 static void
2911 do_stack(FILE *out, struct decl *d) {
2912 char *sign;
2913
2914 if (d->stack_addr->is_func_arg) {
2915 sign = "+";
2916 } else {
2917 sign = "-";
2918 }
2919 x_fprintf(out, "[ebp %s %lu", sign, d->stack_addr->offset);
2920 }
2921
2922 static void
2923 print_mem_operand(struct vreg *vr, struct token *constant) {
2924 static int was_llong;
2925 int needbracket = 1;
2926
2927 if (vr == NULL && constant == NULL) {
2928 /*
2929 * 06/12/08: Reset long long flag! The problem was
2930 * storing an fp value to a long long buffer, using
2931 * fistpq. This is the single place where we don't
2932 * need two store operations, so we can reset the
2933 * llong flag here
2934 */
2935 was_llong = 0;
2936 return;
2937 }
2938
2939 /* 04/11/08: See comment in nasm print_mem_operand() */
2940 assert(backend->arch == ARCH_X86);
2941
2942 if (vr && vr->from_const != NULL) {
2943 constant = vr->from_const;
2944 }
2945 if (constant != NULL) {
2946 struct token *t = vr->from_const;
2947
2948
2949 if (IS_INT(t->type) || IS_LONG(t->type)) {
2950 cross_print_value_by_type(out,
2951 t->data,
2952 t->type, 'd');
2953 #if ALLOW_CHAR_SHORT_CONSTANTS
2954 } else if (IS_CHAR(t->type) || IS_SHORT(t->type)) {
2955 cross_print_value_by_type(out,
2956 t->data,
2957 t->type, 'd');
2958 #endif
2959 } else if (IS_LLONG(t->type)) {
2960 static int was_llong = 0;
2961 void *p;
2962
2963 if (was_llong) {
2964 /* Loading second part of long long */
2965 p = (char *)t->data + 4;
2966 was_llong = 0;
2967 } else {
2968 p = t->data;
2969 was_llong = 1;
2970 }
2971 if (t->type == TY_LLONG) {
2972 x_fprintf(out, "%u",
2973 *(unsigned int *)p);
2974 } else {
2975 /* ULLONG */
2976 x_fprintf(out, "%u",
2977 *(unsigned int *)p);
2978 }
2979 } else if (t->type == TOK_STRING_LITERAL) {
2980 struct ty_string *ts = t->data;
2981 x_fprintf(out, "_Str%ld",
2982 ts->count);
2983 } else if (t->type == TY_FLOAT
2984 || t->type == TY_DOUBLE
2985 || t->type == TY_LDOUBLE) {
2986 struct ty_float *tf = t->data;
2987
2988 x_fprintf(out, "[_Float%lu]",
2989 tf->count);
2990 } else {
2991 printf("loadimm: Bad data type %d\n", t->type);
2992 abort();
2993 }
2994 } else if (vr->parent != NULL) {
2995 struct vreg *vr2;
2996 struct decl *d2;
2997
2998 vr2 = get_parent_struct(vr);
2999 if ((d2 = vr2->var_backed) != NULL) {
3000 if (d2->stack_addr) {
3001 do_stack(out, vr2->var_backed);
3002 } else {
3003 /* static */
3004 x_fprintf(out, "[$%s", d2->dtype->name);
3005 }
3006 } else if (vr2->from_ptr) {
3007 /* Struct comes from pointer */
3008 x_fprintf(out, "[%s",
3009 vr2->from_ptr->pregs[0]->name);
3010 } else {
3011 printf("BUG: Bad load for %s\n",
3012 vr->type->name? vr->type->name: "structure");
3013 abort();
3014 }
3015 x_fputc(' ', out);
3016 print_nasm_offsets(vr);
3017 } else if (vr->var_backed) {
3018 struct decl *d = vr->var_backed;
3019
3020 if (d->stack_addr != NULL) {
3021 do_stack(out, d);
3022 } else {
3023 /*
3024 * Static or register variable
3025 */
3026 if (d->dtype->storage == TOK_KEY_REGISTER) {
3027 unimpl();
3028 } else {
3029 if (d->dtype->tlist != NULL
3030 && d->dtype->tlist->type
3031 == TN_FUNCTION) {
3032 needbracket = 0;
3033 } else {
3034 x_fputc('[', out);
3035 }
3036 x_fprintf(out, "$%s", d->dtype->name);
3037 }
3038 }
3039 } else if (vr->stack_addr) {
3040 x_fprintf(out, "[ebp - %lu", vr->stack_addr->offset);
3041 } else if (vr->from_ptr) {
3042 x_fprintf(out, "[%s", vr->from_ptr->pregs[0]->name);
3043 } else {
3044 abort();
3045 }
3046 if (constant == NULL) {
3047 if (was_llong) {
3048 x_fprintf(out, " + 4 ");
3049 was_llong = 0;
3050 } else if (vr->is_multi_reg_obj) {
3051 was_llong = 1;
3052 }
3053 if (needbracket) {
3054 x_fputc(']', out);
3055 }
3056 }
3057 }
3058
3059
3060 /*
3061 * Print inline asm instruction operand
3062 */
3063 void
3064 print_item_nasm(FILE *out, void *item, int item_type, int postfix) {
3065 print_asmitem_x86(out, item, item_type, postfix, TO_NASM);
3066 }
3067
3068 struct emitter x86_emit_nasm = {
3069 1, /* need_explicit_extern_decls */
3070 init,
3071 emit_strings,
3072 emit_fp_constants,
3073 NULL, /* llong_constants */
3074 emit_support_buffers,
3075 NULL, /* pic_support */
3076
3077 emit_support_decls,
3078 emit_extern_decls,
3079 emit_global_extern_decls,
3080 emit_global_static_decls,
3081 #if 0
3082 emit_global_decls,
3083 emit_static_decls,
3084 #endif
3085 emit_static_init_vars,
3086 emit_static_uninit_vars,
3087 emit_static_init_thread_vars,
3088 emit_static_uninit_thread_vars,
3089 emit_struct_defs,
3090 emit_comment,
3091 emit_dwarf2_line,
3092 emit_dwarf2_files,
3093 emit_inlineasm,
3094 emit_unimpl,
3095 emit_empty,
3096 emit_label,
3097 emit_call,
3098 emit_callindir,
3099 emit_func_header,
3100 emit_func_intro,
3101 emit_func_outro,
3102 emit_define,
3103 emit_push,
3104 emit_allocstack,
3105 emit_freestack,
3106 emit_adj_allocated,
3107 emit_inc,
3108 emit_dec,
3109 emit_load,
3110 emit_load_addrlabel,
3111 emit_comp_goto,
3112 emit_store,
3113 emit_setsection,
3114 emit_alloc,
3115 emit_neg,
3116 emit_sub,
3117 emit_add,
3118 emit_div,
3119 emit_mod,
3120 emit_mul,
3121 emit_shl,
3122 emit_shr,
3123 emit_or,
3124 NULL, /* emit_preg_or */
3125 emit_and,
3126 emit_xor,
3127 emit_not,
3128 emit_ret,
3129 emit_cmp,
3130 NULL, /* extend_sign */
3131 NULL, /* conv_fp */
3132 NULL, /* from_ldouble */
3133 NULL, /* to_ldouble */
3134 emit_branch,
3135 emit_mov,
3136 emit_setreg,
3137 emit_xchg,
3138 emit_addrof,
3139 emit_initialize_pic,
3140 emit_copyinit,
3141 NULL, /* putstructregs */
3142 emit_copystruct,
3143 emit_intrinsic_memcpy,
3144 emit_zerostack,
3145 emit_alloca,
3146 emit_dealloca,
3147 emit_alloc_vla,
3148 emit_dealloc_vla,
3149 emit_put_vla_size,
3150 emit_retr_vla_size,
3151 emit_load_vla,
3152 emit_frame_address,
3153 emit_struct_inits,
3154 emit_save_ret_addr,
3155 emit_check_ret_addr,
3156 print_mem_operand,
3157 NULL, /* finish_program */
3158 NULL, /* stupidtrace */
3159 NULL /* finish_stupidtrace */
3160 };
3161
3162
3163 struct emitter_x86 x86_emit_x86_nasm = {
3164 emit_fxch,
3165 emit_ffree,
3166 emit_fnstcw,
3167 emit_fldcw,
3168 emit_cdq,
3169 emit_fist,
3170 emit_fild,
3171 emit_x86_ulong_to_float
3172 };
3173
3174
3175