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