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