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 amd64 code
28  */
29 #include "amd64_emit_gas.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <ctype.h>
35 #include "scope.h"
36 #include "type.h"
37 #include "decl.h"
38 #include "icode.h"
39 #include "subexpr.h"
40 #include "token.h"
41 #include "functions.h"
42 #include "symlist.h"
43 #include "dwarf.h"
44 #include "cc1_main.h"
45 #include "x86_gen.h"
46 #include "typemap.h"
47 #include "expr.h"
48 #include "x86_emit_gas.h"
49 #include "inlineasm.h"
50 #include "error.h"
51 #include "n_libc.h"
52 
53 static FILE	*out;
54 
55 static int
init(FILE * fd,struct scope * s)56 init(FILE *fd, struct scope *s) {
57 	(void) s;
58 	out = fd;
59 	return 0;
60 }
61 
62 static void
63 print_mem_operand(struct vreg *vr, struct token *constant);
64 
65 /*
66  * 04/11/08: Export print_mem_operand() for x86 emitter functions
67  * which are shared between x86 and AMD64 and need this
68  */
69 void
amd64_print_mem_operand_gas(struct vreg * vr,struct token * constant)70 amd64_print_mem_operand_gas(struct vreg *vr, struct token *constant) {
71 	print_mem_operand(vr, constant);
72 }
73 
74 extern int	size_to_gaspostfix(size_t size, struct type *type);
75 
76 static void
emit_extern_decls(void)77 emit_extern_decls(void) {
78 	if (x86_emit_gas.extern_decls != NULL) {
79 		x86_emit_gas.extern_decls();
80 	}
81 }
82 
83 static void
emit_global_extern_decls(struct decl ** d,int ndecls)84 emit_global_extern_decls(struct decl **d, int ndecls) {
85 	x86_emit_gas.global_extern_decls(d, ndecls);
86 }
87 
88 static void
emit_global_static_decls(struct decl ** d,int ndecls)89 emit_global_static_decls(struct decl **d, int ndecls) {
90 	x86_emit_gas.global_static_decls(d, ndecls);
91 }
92 
93 static void
emit_static_init_vars(struct decl * list)94 emit_static_init_vars(struct decl *list) {
95 	x86_emit_gas.static_init_vars(list);
96 }
97 
98 static void
emit_static_uninit_vars(struct decl * list)99 emit_static_uninit_vars(struct decl *list) {
100 	x86_emit_gas.static_uninit_vars(list);
101 }
102 
103 static void
emit_static_init_thread_vars(struct decl * list)104 emit_static_init_thread_vars(struct decl *list) {
105 	x86_emit_gas.static_init_thread_vars(list);
106 }
107 
108 static void
emit_static_uninit_thread_vars(struct decl * list)109 emit_static_uninit_thread_vars(struct decl *list) {
110 	x86_emit_gas.static_uninit_thread_vars(list);
111 }
112 
113 #if 0
114 static void
115 emit_static_decls(void) {
116 	x86_emit_gas.static_decls();
117 }
118 #endif
119 
120 static void
emit_struct_inits(struct init_with_name * list)121 emit_struct_inits(struct init_with_name *list) {
122 	x86_emit_gas.struct_inits(list);
123 }
124 
125 static void
emit_strings(struct ty_string * list)126 emit_strings(struct ty_string *list) {
127 	x86_emit_gas.strings(list);
128 }
129 
130 static void
emit_fp_constants(struct ty_float * list)131 emit_fp_constants(struct ty_float *list) {
132 	x86_emit_gas.fp_constants(list);
133 }
134 
135 static void
emit_support_buffers(void)136 emit_support_buffers(void) {
137 #if 0 /* 02/21/09: This is now done by the x86 emitter */
138 	if (amd64_need_negmask) {
139 		x86_emit_gas.setsection(SECTION_INIT);
140 		if (sysflag == OS_OSX) {
141 			x_fprintf(out, "\t.align 8\n");
142 		} else {
143 			x_fprintf(out, "\t.align 16\n");
144 		}
145 		if (amd64_need_negmask & 1) {
146 			x_fprintf(out, "_SSE_Negmask:\n");
147 			x_fprintf(out, "\t.long 0x80000000\n");
148 			if (sysflag == OS_OSX) {
149 				x_fprintf(out, "\t.align 8\n");
150 			} else {
151 				x_fprintf(out, "\t.align 16\n");
152 			}
153 		}
154 		if (amd64_need_negmask & 2) {
155 			x_fprintf(out, "_SSE_Negmask_double:\n");
156 			x_fprintf(out, "\t.long 0x00000000\n");
157 			x_fprintf(out, "\t.long 0x80000000\n");
158 		}
159 	}
160 	if (amd64_need_ulong_float_mask) {
161 		x86_emit_gas.setsection(SECTION_INIT);
162 		x_fprintf(out, "\t.align 4\n");
163 
164 		x_fprintf(out, "_Ulong_float_mask:\n");
165 		x_fprintf(out, "\t.long 1602224128\n");
166 	}
167 #endif
168 	x86_emit_gas.support_buffers();
169 }
170 
171 static void
emit_comment(const char * fmt,...)172 emit_comment(const char *fmt, ...) {
173 	int		rc;
174 	va_list	va;
175 
176 	va_start(va, fmt);
177 	x_fprintf(out, "# ");
178 	rc = vfprintf(out, fmt, va);
179 	va_end(va);
180 	x_fputc('\n', out);
181 
182 	if (rc == EOF || fflush(out) == EOF) {
183 		perror("vfprintf");
184 		exit(EXIT_FAILURE);
185 	}
186 }
187 
188 static void
emit_dwarf2_line(struct token * tok)189 emit_dwarf2_line(struct token *tok) {
190 	(void) tok;
191 	unimpl();
192 #if 0
193 	x_fprintf(out, "\t[loc %d %d 0]\n",
194 		tok->fileid, tok->line);
195 #endif
196 }
197 
198 static void
emit_dwarf2_files(void)199 emit_dwarf2_files(void) {
200 	struct dwarf_in_file	*inf;
201 
202 	x_fprintf(out, "[file \"%s\"]\n",
203 		input_file);
204 
205 	for (inf = dwarf_files; inf != NULL; inf = inf->next) {
206 		x_fprintf(out, "[file %d \"%s\"]\n",
207 			inf->id, inf->name);
208 	}
209 }
210 
211 static void
emit_inlineasm(struct inline_asm_stmt * stmt)212 emit_inlineasm(struct inline_asm_stmt *stmt) {
213 	x_fprintf(out, "#APP\n");
214 	/*
215 	 * There may be an empty body for statements where only the side
216 	 * effect is desired;
217 	 * __asm__("" ::: "memory");
218 	 */
219 	if (stmt->code != NULL) {
220 		inline_instr_to_gas(out, stmt->code);
221 	}
222 	x_fprintf(out, "#NO_APP\n");
223 }
224 
225 static void
emit_unimpl(void)226 emit_unimpl(void) {
227 	unimpl();
228 }
229 
230 static void
emit_empty(void)231 emit_empty(void) {
232 	x_fputc('\n', out);
233 }
234 
235 static void
emit_label(const char * name,int is_func)236 emit_label(const char *name, int is_func) {
237 	if (is_func) {
238 		if (sysflag == OS_OSX) {
239 			x_fprintf(out, "_%s:\n", name);
240 		} else {
241 			x_fprintf(out, "%s:\n", name);
242 		}
243 	} else {
244 		x_fprintf(out, ".%s:\n", name);
245 	}
246 }
247 
248 static void
emit_call(const char * name)249 emit_call(const char *name) {
250 	x86_emit_gas.call(name);
251 }
252 
253 static void
emit_callindir(struct reg * r)254 emit_callindir(struct reg *r) {
255 	x_fprintf(out, "\tcall *%%%s\n", r->name);
256 }
257 
258 static void
emit_func_header(struct function * f)259 emit_func_header(struct function *f) {
260 	if (sysflag != OS_OSX) {
261 		x_fprintf(out, "\t.type %s, @function\n", f->proto->dtype->name);
262 	}
263 }
264 
265 static void
emit_func_intro(struct function * f)266 emit_func_intro(struct function *f) {
267 	(void) f;
268 	x_fprintf(out, "\tpush %%rbp\n"); /* XXX */
269 	x_fprintf(out, "\tmov %%rsp, %%rbp\n");
270 }
271 
272 static void
emit_func_outro(struct function * f)273 emit_func_outro(struct function *f) {
274 	char	*name = f->proto->dtype->name;
275 
276 	if (sysflag != OS_OSX) {
277 		x_fprintf(out, "\t.size %s, .-%s\n", name, name);
278 	}
279 	/*x_fprintf(out, "\tret\n");*/
280 }
281 
282 
283 static void
emit_define(const char * name,const char * fmt,...)284 emit_define(const char *name, const char *fmt, ...) {
285 	x86_emit_gas.define(name, fmt);
286 }
287 
288 static void
emit_push(struct function * f,struct icode_instr * ii)289 emit_push(struct function *f, struct icode_instr *ii) {
290 	struct vreg	*vr = ii->src_vreg;
291 	struct reg	*r = ii->src_pregs?
292 				(void *)ii->src_pregs[0]: (void *)NULL;
293 	int		ch;
294 
295 	if (IS_VLA(vr->type->flags)) {
296 		ch = 'q';
297 	} else {
298 		if (backend->get_sizeof_type(vr->type, NULL) == 8) {
299 			ch = 'q';
300 		} else {
301 			ch = 'l';
302 		}
303 	}
304 
305 	if (ii->src_pregs) {
306 		x_fprintf(out, "\tpush %%%s\n", r->name);
307 	} else if (vr->var_backed) {
308 		struct decl	*d = vr->var_backed;
309 
310 		if (vr->parent != NULL) {
311 			/* Structure or union member */
312 			struct decl	*d2/* = d*/;
313 			struct vreg	*vr2;
314 
315 			vr2 = get_parent_struct(vr);
316 			d2 = vr2->var_backed;
317 			if (vr2->from_ptr) {
318 				if (vr->parent->type->code == TY_STRUCT) {
319 					x_fprintf(out, "\tpush%c %lu(%%%s)\n",
320 						ch,
321 						calc_offsets(vr2),
322 						vr2->from_ptr->pregs[0]->name);
323 				} else {
324 					x_fprintf(out, "\tpush%c (%%%s)\n",
325 						ch,
326 						vr2->from_ptr->pregs[0]->name);
327 				}
328 			} else if (d2 && d2->stack_addr != NULL) {
329 				long	soff = 0;
330 
331 				if (vr->parent->type->code == TY_STRUCT) {
332 					soff = calc_offsets(vr2);
333 				}
334 				x_fprintf(out, "\tpush%c %ld(%%rbp)\n",
335 					ch,
336 					-d2->stack_addr->offset+soff);
337 			} else if (d2 != NULL) {
338 				/* Must be static */
339 				x_fprintf(out, "\tpush%c %s",
340 					ch,
341 					d2->dtype->name);
342 				if (vr->parent->type->code == TY_STRUCT) {
343 					x_fprintf(out, "+%lu",
344 						calc_offsets(vr2));
345 				}
346 				x_fputc('\n', out);
347 			} else {
348 				unimpl();
349 			}
350 		} else {
351 			if (d->stack_addr != NULL) {
352 				/* Stack */
353 				x_fprintf(out, "\tpush%c -%ld(%%rbp)\n",
354 					ch,
355 					d->stack_addr->offset);
356 			} else {
357 				/* Static or register variable */
358 				if (d->dtype->storage == TOK_KEY_REGISTER) {
359 					unimpl();
360 				} else {
361 					x_fprintf(out, "\tpush%c %s\n",
362 						ch, d->dtype->name);
363 				}
364 			}
365 		}
366 	} else if (vr->from_const) {
367 		struct token	*t = vr->from_const;
368 
369 		if (t->type == TOK_STRING_LITERAL) {
370 			struct ty_string	*s = t->data;
371 			x_fprintf(out, "\tpushq $._Str%lu\n", s->count);
372 		} else if (IS_INT(t->type)) {
373 			/*
374 			 * There are only forms of ``int'' and ``long''
375 			 * constants
376 			 */
377 #if 0
378 			if (t->type == TY_INT) {
379 				x_fprintf(out, "\tpushl $%d\n",
380 					*(int *) t->data);
381 			} else {
382 				/* UINT */
383 				x_fprintf(out, "\tpushl $%u\n",
384 					*(unsigned *) t->data);
385 			}
386 #endif
387 			x_fprintf(out, "\tpushl $");
388 			cross_print_value_by_type(out, t->data, t->type, 0);
389 		} else if (IS_LONG(t->type) || IS_LLONG(t->type)) {
390 #if 0
391 			if (t->type == TY_LONG || t->type == TY_LLONG) {
392 				x_fprintf(out, "\tpushq $%ld\n",
393 					*(long *) t->data);
394 			} else {
395 				/* unsigned */
396 				x_fprintf(out, "\tpushq $%lu\n",
397 					*(unsigned long *) t->data);
398 			}
399 #endif
400 			x_fprintf(out, "\tpushq $");
401 			cross_print_value_by_type(out, t->data, t->type, 0);
402 		} else {
403 			puts("BUG in NASM emit_push()");
404 			exit(EXIT_FAILURE);
405 		}
406 	} else if (vr->from_ptr) {
407 		x_fprintf(out, "\tpush%c (%%%s)\n", /*ascii_type,*/
408 				ch,
409 				vr->from_ptr->pregs[0]->name);
410 	} else {
411 		unimpl();
412 	}
413 
414 	f->total_allocated += 4;
415 }
416 
417 static void
emit_allocstack(struct function * f,size_t nbytes)418 emit_allocstack(struct function *f, size_t nbytes) {
419 	(void) f;
420 	x_fprintf(out, "\tsub $%lu, %%rsp\n", (unsigned long)nbytes);
421 }
422 
423 
424 static void
emit_freestack(struct function * f,size_t * nbytes)425 emit_freestack(struct function *f, size_t *nbytes) {
426 	if (nbytes == NULL) {
427 		/* Procedure outro */
428 		if (f->total_allocated != 0) {
429 			x_fprintf(out, "\tadd $%lu, %%rsp\n",
430 				(unsigned long)f->total_allocated);
431 		}
432 		x_fprintf(out, "\tpop %%rbp\n");
433 	} else {
434 		if (*nbytes != 0) {
435 			x_fprintf(out, "\tadd $%lu, %%rsp\n",
436 				(unsigned long)*nbytes);
437 			f->total_allocated -= *nbytes;
438 		}
439 	}
440 }
441 
442 static void
emit_adj_allocated(struct function * f,int * nbytes)443 emit_adj_allocated(struct function *f, int *nbytes) {
444 	f->total_allocated += *nbytes;
445 }
446 
447 
448 #if 0
449 static void
450 emit_struct_defs(void) {
451 	if (x86_emit_gas.struct_defs) {
452 		x86_emit_gas.struct_defs();
453 	}
454 }
455 #endif
456 
457 
458 static void
emit_setsection(int value)459 emit_setsection(int value) {
460 	static int	init;
461 
462 	x86_emit_gas.setsection(value);
463 	if (value == SECTION_INIT) {
464 		if ((init & 1) == 0) {
465 			x_fprintf(out, "\t.align 16\n");
466 			init |= 1;
467 		}
468 	} else if (value == SECTION_UNINIT) {
469 		if ((init & 2) == 0) {
470 			x_fprintf(out, "\t.align 16\n");
471 			init |= 2;
472 		}
473 	}
474 }
475 
476 static void
emit_alloc(size_t nbytes)477 emit_alloc(size_t nbytes) {
478 	unimpl();
479 	(void) nbytes;
480 }
481 
482 
483 static void
print_mem_or_reg(struct reg * r,struct vreg * vr)484 print_mem_or_reg(struct reg *r, struct vreg *vr) {
485 	if (vr->on_var) {
486 		struct decl	*d = vr->var_backed;
487 
488 		if (d->stack_addr) {
489 			x_fprintf(out, "-%ld(%%rbp)",
490 				d->stack_addr->offset);
491 		} else {
492 			x_fprintf(out, "%s", d->dtype->name);
493 		}
494 	} else {
495 		x_fprintf(out, "%%%s", r->name);
496 	}
497 }
498 
499 
500 
501 static void
emit_inc(struct icode_instr * ii)502 emit_inc(struct icode_instr *ii) {
503 	x86_emit_gas.inc(ii);
504 }
505 
506 static void
emit_dec(struct icode_instr * ii)507 emit_dec(struct icode_instr *ii) {
508 	x86_emit_gas.dec(ii);
509 }
510 
511 static void
emit_load(struct reg * r,struct vreg * vr)512 emit_load(struct reg *r, struct vreg *vr) {
513 	char		*p;
514 
515 	if (r->type == REG_FPR) {
516 		if (STUPID_X87(r)) {
517 			if (!IS_FLOATING(vr->type->code)) {
518 #if ! REMOVE_FLOATBUF
519 				p = "fild";
520 
521 				/*
522 				 * 04/06/08: Don't use size postfix for fild - fildt
523 				 * isn't allowed. Why did this issue not come up
524 				 * earlier?
525 				 */
526 				if (vr->size >= 10) {
527 					x_fprintf(out, "\t%s ", p);
528 				} else {
529 					x_fprintf(out, "\t%s%c ",
530 						p, size_to_gaspostfix(vr->size, vr->type));
531 				}
532 #else
533 				buggypath();
534 #endif
535 			} else {
536 				p = "fld";
537 				x_fprintf(out, "\t%s%c ",
538 					p, size_to_gaspostfix(vr->size, vr->type));
539 			}
540 		} else {
541 			/* SSE */
542 			if (!IS_FLOATING(vr->type->code)) {
543 				p = "cvtsi2ss";
544 			} else {
545 				if (vr->type->code == TY_FLOAT) {
546 					p = "movss";
547 				} else {
548 					/* Must be double */
549 					p = "movsd";
550 				}
551 			}
552 			x_fprintf(out, "\t%s ", p);
553 		}
554 	} else {
555 		if (vr->stack_addr != NULL) {
556 			p = "mov";
557 		} else if (vr->type
558 			&& vr->type->tlist != NULL
559 			&& (vr->type->tlist->type == TN_ARRAY_OF
560 				|| vr->type->tlist->type == TN_VARARRAY_OF)) {
561 			if (vr->from_const == NULL) {
562 				p = "lea";
563 			} else {
564 				p = "mov";
565 			}
566 		} else {
567 			if (r->size == vr->size
568 				|| vr->size == 8) {
569 				/* == 8 for long long, SA for anonymous */
570 				p = "mov";
571 			} else {
572 				if (vr->type == NULL
573 					|| vr->type->sign == TOK_KEY_UNSIGNED) {
574 					/* XXX 32->64bit? ... */
575 					p = "movzx";
576 				} else {
577 					if (r->size == 8 && vr->size == 4) {
578 						if (vr->from_const) {
579 							p = "mov";
580 						} else {
581 							p = "movslq";
582 						}
583 					} else {
584 						p = "movsx";
585 					}
586 				}
587 			}
588 		}
589 		x_fprintf(out, "\t%s ", p);
590 	}
591 
592 	print_mem_operand(vr, NULL);
593 	if (r->type != REG_FPR || !STUPID_X87(r)) {
594 		x_fprintf(out, ", %%%s\n", r->name);
595 	}
596 	x_fputc('\n', out);
597 }
598 
599 static void
emit_load_addrlabel(struct reg * r,struct icode_instr * ii)600 emit_load_addrlabel(struct reg *r, struct icode_instr *ii) {
601 	x_fprintf(out, "\tlea .%s(%%rip), %%%s\n", ii->dat, r->name);
602 }
603 
604 static void
emit_comp_goto(struct reg * r)605 emit_comp_goto(struct reg *r) {
606 	x_fprintf(out, "\tjmp *%%%s\n", r->name);
607 }
608 
609 /*
610  * Takes vreg source arg - not preg - so that it can be either a preg
611  * or immediate (where that makes sense!)
612  */
613 static void
emit_store(struct vreg * dest,struct vreg * src)614 emit_store(struct vreg *dest, struct vreg *src) {
615 	char		*p = NULL;
616 	int		floating = 0;
617 	int		post = 0;
618 	int		is_movsx = 0;
619 
620 	if (dest->size) {
621 		post = size_to_gaspostfix(dest->size, dest->type);
622 	}
623 #if ! REMOVE_FLOATBUF
624 	if (dest == &floatbuf) {
625 		/*
626 		 * XXX this is a botch to ignore the problem of the messed
627 		 * up floatbuf typing for now. This makes code compile, but
628 		 * not necessarily work right :-)
629 		 */
630 		if (src->pregs[0]->size == 4 && post == 'q') {
631 			post = 'l';
632 		}
633 	}
634 #endif
635 
636 	if (src->pregs[0] && src->pregs[0]->type == REG_FPR) {
637 		if (STUPID_X87(src->pregs[0])) {
638 			if (!IS_FLOATING(dest->type->code)) {
639 #if ! REMOVE_FLOATBUF
640 				if (dest->size >= 10) {
641 					/*
642 					 * 04/06/08: Use fisttp instead of fistpt
643 					 * (postfix). Why was this not encountered
644 					 * earlier?
645 					 *
646 					 *
647 					 */
648 					p = "fisttp";
649 					post = 0;
650 				} else {
651 					p = "fistp";
652 				}
653 #else
654 				buggypath();
655 #endif
656 			} else {
657 				p = "fstp";
658 			}
659 			floating = 1;
660 		} else {
661 			if (!IS_FLOATING(dest->type->code)) {
662 				unimpl();
663 			} else {
664 				if (dest->type->code == TY_FLOAT) {
665 					p = "movss";
666 				} else {
667 					p = "movsd";
668 				}
669 			}
670 			post = 0;
671 			floating = 0; /* because SSE is non-x87-like */
672 		}
673 	} else {
674 		if (dest->stack_addr != NULL || dest->from_const != NULL) {
675 			p = "mov";
676 		} else {
677 			if (src->pregs[0] && dest->size < src->pregs[0]->size) {
678 				if (src->type == NULL
679 					|| src->type->sign
680 						== TOK_KEY_UNSIGNED) {
681 				/* XXX wow this should never be executed? */
682 					x_fprintf(out, "\tmov%c ", post?post:' ');
683 					x_fprintf(out, "$0, ");
684 					print_mem_operand(dest, NULL);
685 					p = "mov";
686 				} else {
687 					if (dest->from_ptr
688 						&& src->pregs[0]->size == 4) {
689 						/*
690 						 * ``movslq %eax, (%r9)''
691 						 * doesn't work  :S
692 						 */
693 						src->pregs[0] =
694 							find_top_reg(
695 								src->pregs[0]);
696 						x_fprintf(out,
697 							 "\tmovslq %%%s, %%%s\n",
698 					src->pregs[0]->composed_of[0]->name,
699 							src->pregs[0]->name);
700 						p = "mov";
701 					} else {
702 						if (src->pregs[0]->size == 4) {
703 							p = "movslq";
704 						} else {
705 							p = "movsx";
706 							is_movsx = 1;
707 						}
708 					}
709 				}
710 			} else {
711 				p = "mov";
712 			}
713 		}
714 	}
715 	if (post) {
716 		if (post == 'l' && is_movsx) {
717 			/* 04/06/08: Kludge to handle long double conversion
718 			 * nonsense code.. we must get rid of floatbuf. really
719 			 */
720 #if ! REMOVE_FLOATBUF
721 			x_fprintf(out, "\tmov ");
722 #else
723 			buggypath();
724 #endif
725 		} else {
726 			x_fprintf(out, "\t%s%c ", p, post);
727 		}
728 	} else {
729 		x_fprintf(out, "\t%s ", p);
730 	}
731 	if (floating) {
732 		/* Already done - floating stores only ever come from st0 */
733 		print_mem_operand(dest, NULL);
734 		x_fputc('\n', out);
735 		return;
736 	}
737 	if (src->from_const) {
738 		print_mem_operand(src, NULL);
739 	} else {
740 		/* Must be register */
741 		x_fprintf(out, "%%%s, ", src->pregs[0]->name);
742 	}
743 	print_mem_operand(dest, NULL);
744 	x_fputc('\n', out);
745 }
746 
747 
748 static void
emit_neg(struct reg ** dest,struct icode_instr * src)749 emit_neg(struct reg **dest, struct icode_instr *src) {
750 	x86_emit_gas.neg(dest, src);
751 }
752 
753 
754 /* XXX 64bit */
755 static void
emit_sub(struct reg ** dest,struct icode_instr * src)756 emit_sub(struct reg **dest, struct icode_instr *src) {
757 	if (dest[0]->type == REG_FPR) {
758 		if (STUPID_X87(dest[0])) {
759 			/* 05/27/08: fsubrp instead of fsubp.. See x86 */
760 			x_fprintf(out, "\tfsubrp ");
761 		} else {
762 			x_fprintf(out, "\tsubs%c ",
763 			src->src_vreg->type->code == TY_FLOAT? 's': 'd');
764 		}
765 	} else {
766 		if (src->dest_vreg->type->tlist) {
767 			/* ptr arit ... sub rax, edx doesn't work */
768 			if (src->src_vreg->size == 4) {
769 				/* XXX frontend stuff?! */
770 				struct reg	*r;
771 
772 				r = find_top_reg(src->src_pregs[0]);
773 				if (src->src_vreg->type->sign
774 					!= TOK_KEY_UNSIGNED) {
775 					x_fprintf(out, "\tmovslq %%%s, %%%s\n",
776 						src->src_pregs[0]->name,
777 						r->name);
778 				}
779 				x_fprintf(out, "\tsub %%%s, %%%s\n",
780 					r->name,
781 					dest[0]->name);
782 				return;
783 			}
784 		}
785 		x_fprintf(out, "\tsub ");
786 	}
787 	print_mem_or_reg(src->src_pregs[0], src->src_vreg);
788 	x_fprintf(out, ", %%%s\n", dest[0]->name);
789 }
790 
791 /* XXX 64bit */
792 static void
emit_add(struct reg ** dest,struct icode_instr * src)793 emit_add(struct reg **dest, struct icode_instr *src) {
794 	if (dest[0]->type == REG_FPR) {
795 		if (STUPID_X87(dest[0])) {
796 			x_fprintf(out, "\tfaddp ");
797 		} else {
798 			x_fprintf(out, "\tadds%c ",
799 				src->src_vreg->type->code == TY_FLOAT? 's': 'd');
800 		}
801 	} else {
802 		if (src->dest_vreg->type->tlist) {
803 			/* ptr arit ... add rax, edx doesn't work */
804 			if (src->src_vreg->size == 4) {
805 				/* XXX frontend stuff?! */
806 				struct reg	*r;
807 
808 				r = find_top_reg(src->src_pregs[0]);
809 				if (src->src_vreg->type->sign !=
810 					TOK_KEY_UNSIGNED) {
811 					x_fprintf(out, "\tmovslq %%%s, %%%s\n",
812 						 src->src_pregs[0]->name,
813 						r->name);
814 				}
815 				x_fprintf(out, "\tadd %%%s, %%%s\n",
816 					r->name,
817 					dest[0]->name);
818 				return;
819 			}
820 		}
821 		x_fprintf(out, "\tadd ");
822 	}
823 	print_mem_or_reg(src->src_pregs[0], src->src_vreg);
824 	x_fprintf(out, ", %%%s\n", dest[0]->name);
825 }
826 
827 /* XXX 64bit */
828 static void
emit_div(struct reg ** dest,struct icode_instr * src,int formod)829 emit_div(struct reg **dest, struct icode_instr *src, int formod) {
830 	struct type	*ty = src->src_vreg->type;
831 	int		is_x87 = 0;
832 
833 	(void) dest; (void) formod;
834 	if (!IS_FLOATING(ty->code)) {
835 		int	is_64bit = IS_LONG(ty->code) || IS_LLONG(ty->code);
836 
837 		if (ty->sign != TOK_KEY_UNSIGNED) {
838 			if (is_64bit) {
839 				/*
840 				 * 07/25/08: This was doing zero-extension
841 				 * instead of sign-extension!
842 				 */
843 				x_fprintf(out, "\tcqto\n");
844 		/*		x_fprintf(out, "\txor %%rdx, %%rdx\n");*/
845 			} else {
846 				/* sign-extend eax to edx:eax */
847 				x_fprintf(out, "\tcltd\n");
848 			}
849 			x_fprintf(out, "\tidiv ");
850 		} else {
851 			if (is_64bit) {
852 				x_fprintf(out, "\txor %%rdx, %%rdx\n");
853 			} else {
854 				x_fprintf(out, "\txor %%edx, %%edx\n");
855 			}
856 			x_fprintf(out, "\tdiv ");
857 		}
858 	} else {
859 		if (STUPID_X87(src->src_pregs[0])) {
860 			/* XXX why is the fxch needed???? */
861 			x_fprintf(out, "\tfxch %%st(1)\n");
862 			x_fprintf(out, "\tfdivp ");
863 			is_x87 = 1;
864 		} else {
865 			x_fprintf(out, "\tdivs%c %%%s, %%%s\n",
866 				ty->code == TY_FLOAT? 's': 'd',
867 				src->src_pregs[0]->name,
868 				dest[0]->name);
869 			return;
870 		}
871 	}
872 	if (is_x87) {
873 		print_mem_or_reg(src->dest_pregs[0], src->dest_vreg);
874 	} else {
875 		print_mem_or_reg(src->src_pregs[0], src->src_vreg);
876 	}
877 	x_fputc('\n', out);
878 }
879 
880 
881 /* XXX 64bit ... */
882 static void
emit_mod(struct reg ** dest,struct icode_instr * src)883 emit_mod(struct reg **dest, struct icode_instr *src) {
884 	emit_div(dest, src, 1);
885 	if (!IS_LLONG(src->dest_vreg->type->code)
886 		&& !IS_LONG(src->dest_vreg->type->code)) {
887 		x_fprintf(out, "\tmov %%edx, %%%s\n", dest[0]->name);
888 	} else {
889 		x_fprintf(out, "\tmov %%rdx, %%%s\n", dest[0]->name);
890 	}
891 }
892 
893 
894 /* XXX ouch..how does it work with 64bit? */
895 static void
emit_mul(struct reg ** dest,struct icode_instr * src)896 emit_mul(struct reg **dest, struct icode_instr *src) {
897 	struct type	*ty = src->src_vreg->type;
898 
899 	(void) dest;
900 
901 	if (IS_FLOATING(ty->code)) {
902 		if (STUPID_X87(dest[0])) {
903 			x_fprintf(out, "\tfmulp ");
904 		} else {
905 			x_fprintf(out, "\tmuls%c ",
906 				ty->code == TY_FLOAT? 's': 'd');
907 		}
908 	} else if (ty->sign == TOK_KEY_UNSIGNED) {
909 		x_fprintf(out, "\tmul ");
910 	} else {
911 		/* signed integer multiplication */
912 		/* XXX should use mul for pointer arithmetic :( */
913 		x_fprintf(out, "\timul %%%s, %%%s\n",
914 			src->src_pregs[0]->name,
915 			src->src_pregs[0]->size == 4? "eax": "rax");
916 		return;
917 	}
918 	print_mem_or_reg(src->src_pregs[0], src->src_vreg);
919 	if (IS_FLOATING(ty->code)) {
920 		x_fprintf(out, ", %%%s", src->dest_pregs[0]->name);
921 	}
922 	x_fputc('\n', out);
923 }
924 
925 /* XXX sal for signed values!!!!! */
926 static void
emit_shl(struct reg ** dest,struct icode_instr * src)927 emit_shl(struct reg **dest, struct icode_instr *src) {
928 	x86_emit_gas.shl(dest, src);
929 }
930 
931 
932 /* XXX sar for signed values !!!!!!!! */
933 static void
emit_shr(struct reg ** dest,struct icode_instr * src)934 emit_shr(struct reg **dest, struct icode_instr *src) {
935 	x86_emit_gas.shr(dest, src);
936 }
937 
938 static void
emit_or(struct reg ** dest,struct icode_instr * src)939 emit_or(struct reg **dest, struct icode_instr *src) {
940 	x86_emit_gas.or(dest, src);
941 }
942 
943 static void
emit_and(struct reg ** dest,struct icode_instr * src)944 emit_and(struct reg **dest, struct icode_instr *src) {
945 	x86_emit_gas.and(dest, src);
946 }
947 
948 static void
emit_xor(struct reg ** dest,struct icode_instr * src)949 emit_xor(struct reg **dest, struct icode_instr *src) {
950 	x86_emit_gas.xor(dest, src);
951 }
952 
953 static void
emit_not(struct reg ** dest,struct icode_instr * src)954 emit_not(struct reg **dest, struct icode_instr *src) {
955 	x86_emit_gas.not(dest, src);
956 }
957 
958 static void
emit_ret(struct icode_instr * ii)959 emit_ret(struct icode_instr *ii) {
960 	(void) ii;
961 
962 	x_fprintf(out, "\tret\n"); /* XXX */
963 }
964 
965 extern struct icode_instr	*last_x87_cmp;
966 extern struct icode_instr	*last_sse_cmp;
967 
968 /*
969  * XXX compltee bogus code for token.c ...
970  * call n_xmalloc
971  * movl %rax, -40(rbp)
972  * mov $0, %eax
973  * cmp $0, %eax
974  */
975 static void
emit_cmp(struct reg ** dest,struct icode_instr * src)976 emit_cmp(struct reg **dest, struct icode_instr *src) {
977 	if (dest[0]->size == 8
978 		&& src->src_pregs
979 		&& src->src_pregs[0]->size == 4) {
980 		src->src_pregs[0] = find_top_reg(src->src_pregs[0]);
981 	} else if (src->src_pregs && src->src_pregs[0]->size == 8
982 		&& dest[0]->size == 4) {
983 		dest[0] = find_top_reg(dest[0]);
984 	}
985 
986 	if (dest[0]->type == REG_FPR) {
987 		if (STUPID_X87(dest[0])) {
988 			last_x87_cmp = src;
989 		} else {
990 			last_sse_cmp = src;
991 		}
992 		return;
993 	} else {
994 		fprintf(out, "\tcmp ");
995 	}
996 	if (src->src_pregs == NULL || src->src_vreg == NULL) {
997 		x_fprintf(out, "$0");
998 	} else {
999 		print_mem_or_reg(src->src_pregs[0], src->src_vreg);
1000 	}
1001 	x_fprintf(out, ", %%%s\n", dest[0]->name);
1002 }
1003 
1004 static void
emit_branch(struct icode_instr * ii)1005 emit_branch(struct icode_instr *ii) {
1006 	x86_emit_gas.branch(ii);
1007 }
1008 
1009 static void
emit_mov(struct copyreg * cr)1010 emit_mov(struct copyreg *cr) {
1011 	x86_emit_gas.mov(cr);
1012 }
1013 
1014 
1015 static void
emit_setreg(struct reg * dest,int * value)1016 emit_setreg(struct reg *dest, int *value) {
1017 	x86_emit_gas.setreg(dest, value);
1018 }
1019 
1020 static void
emit_xchg(struct reg * r1,struct reg * r2)1021 emit_xchg(struct reg *r1, struct reg *r2) {
1022 	x86_emit_gas.xchg(r1, r2);
1023 }
1024 
1025 
1026 static void
emit_addrof(struct reg * dest,struct vreg * src,struct vreg * structtop)1027 emit_addrof(struct reg *dest, struct vreg *src, struct vreg *structtop) {
1028 	x86_emit_gas.addrof(dest, src, structtop);
1029 }
1030 
1031 
1032 static char *
get_local_sym_representation(const char * name)1033 get_local_sym_representation(const char *name) {
1034 	static char	buf[1024];
1035 	if (picflag) {
1036 		sprintf(buf, ".%s@GOTPCREL(%%rip)", name);
1037 	} else {
1038 		sprintf(buf, "$.%s", name);
1039 	}
1040 	return buf;
1041 }
1042 
1043 static char *
get_function_sym_representation(const char * name)1044 get_function_sym_representation(const char *name) {
1045 	static char	buf[1024];
1046 	if (picflag) {
1047 		sprintf(buf, "%s@PLT", name);
1048 	} else {
1049 		sprintf(buf, "%s", name);
1050 	}
1051 	return buf;
1052 }
1053 
1054 
1055 /*
1056  * Copy initializer to automatic variable of aggregate type
1057  */
1058 static void
emit_copyinit(struct decl * d)1059 emit_copyinit(struct decl *d) {
1060 	x_fprintf(out, "\tmov $%lu, %%rdx\n",
1061 		(unsigned long)backend->get_sizeof_type(d->dtype, 0));
1062 	if (sysflag == OS_OSX) {
1063 		x_fprintf(out, "\tlea .%s(%%rip), %%rsi\n", d->init_name->name); /* XXX */
1064 	} else {
1065 		x_fprintf(out, "\tmov %s, %%rsi\n", get_local_sym_representation(d->init_name->name)); /* XXX */
1066 	}
1067 	x_fprintf(out, "\tlea -%lu(%%rbp), %%rdi\n", d->stack_addr->offset);
1068 	if (sysflag == OS_OSX) {
1069 		x_fprintf(out, "\tcall _memcpy\n");
1070 	} else {
1071 		x_fprintf(out, "\tcall %s\n", get_function_sym_representation("memcpy"));
1072 	}
1073 }
1074 
1075 
1076 /*
1077  * Assign one struct to another (may be any of automatic or static or
1078  * addressed thru pointer)
1079  *
1080  * This stuff now copies intrinsically - i.e. doesn't use memcpy() -
1081  * because that way we can guarantee that no registers are trashed.
1082  * This simplifies things like passing structs to functions on the
1083  * stack, but is currently very simplistic and thus not very fast
1084  * for big structs
1085  *
1086  * (Note that the frontend cannot assume that all registers remain
1087  * intact because other backends do still call memcpy())
1088  */
1089 static void
emit_copystruct(struct copystruct * cs)1090 emit_copystruct(struct copystruct *cs) {
1091 	struct vreg		*stop;
1092 	static unsigned long	lcount;
1093 
1094 	x_fprintf(out, "\tpush %%rdx\n");
1095 	x_fprintf(out, "\tpush %%rdi\n");
1096 	x_fprintf(out, "\tpush %%rsi\n");
1097 	x_fprintf(out, "\tpush %%rax\n");
1098 	x_fprintf(out, "\tpush %%rcx\n");
1099 
1100 	/*
1101 	 * 07/26/12: XXX ugly kludge to ensure that the register saving above
1102 	 * does not corrupt sp-relative addressing of structs for function
1103 	 * call arguments
1104 	 */
1105 	x_fprintf(out, "\tadd $40, %%rsp\n");
1106 
1107 	/* arg 3 = rdx */
1108 #if 0
1109 	x_fprintf(out, "\tmov rdx, %lu\n", (unsigned long)cs->src_vreg->size);
1110 #endif
1111 	x_fprintf(out, "\tmov $%lu, %%rcx\n", (unsigned long)cs->src_vreg->size);
1112 	if (cs->src_from_ptr == NULL) {
1113 		if (cs->src_vreg->parent) {
1114 			stop = get_parent_struct(cs->src_vreg);
1115 		} else {
1116 			stop = NULL;
1117 		}
1118 		/* arg 2 = rsi */
1119 		emit_addrof(&amd64_x86_gprs[4], cs->src_vreg, stop);
1120 	} else {
1121 		if (cs->src_vreg->parent) {
1122 			x_fprintf(out, "\tadd $%lu, %%%s\n",
1123 				calc_offsets(cs->src_vreg),
1124 				/*cs->src_vreg->memberdecl->offset,*/
1125 				cs->src_from_ptr->name);
1126 		}
1127 		/* arg 2 = rsi */
1128 		x_fprintf(out, "\tmov %%%s, %%rsi\n", cs->src_from_ptr->name);
1129 	}
1130 
1131 	if (cs->dest_vreg == NULL) {
1132 		/* copy to hidden pointer */
1133 		emit_load(&amd64_x86_gprs[5], curfunc->hidden_pointer);
1134 	} else if (cs->dest_from_ptr == NULL) {
1135 		if (cs->dest_vreg->parent) {
1136 			stop = get_parent_struct(cs->dest_vreg);
1137 		} else {
1138 			stop = NULL;
1139 		}
1140 		/* arg 3 = rdi */
1141 		emit_addrof(&amd64_x86_gprs[5], cs->dest_vreg, stop);
1142 	} else {
1143 		if (cs->dest_vreg->parent) {
1144 			x_fprintf(out, "\tadd $%lu, %%%s\n",
1145 				calc_offsets(cs->dest_vreg),
1146 				/*cs->dest_vreg->memberdecl->offset,*/
1147 				cs->dest_from_ptr->name);
1148 		}
1149 		/* arg 3 = rdi */
1150 		x_fprintf(out, "\tmov %%%s, %%rdi\n", cs->dest_from_ptr->name);
1151 	}
1152 #if 0
1153 	x_fprintf(out, "\tcall memcpy\n");
1154 #endif
1155 	x_fprintf(out, "\t.copystruct%lu:\n", lcount);
1156 	x_fprintf(out, "\tmov (%%rsi), %%al\n");
1157 	x_fprintf(out, "\tmov %%al, (%%rdi)\n");
1158 	x_fprintf(out, "\tinc %%rdi\n");
1159 	x_fprintf(out, "\tinc %%rsi\n");
1160 	x_fprintf(out, "\tloop .copystruct%lu\n", lcount++);
1161 
1162 	x_fprintf(out, "\tsub $40, %%rsp\n"); /* XXX reverte addressing kludge */
1163 
1164 	/* 04/06/08: This was missing! */
1165 	x_fprintf(out, "\tpop %%rcx\n");
1166 	x_fprintf(out, "\tpop %%rax\n");
1167 	x_fprintf(out, "\tpop %%rsi\n");
1168 	x_fprintf(out, "\tpop %%rdi\n");
1169 	x_fprintf(out, "\tpop %%rdx\n");
1170 }
1171 
1172 static void
emit_intrinsic_memcpy(struct int_memcpy_data * data)1173 emit_intrinsic_memcpy(struct int_memcpy_data *data) {
1174 	x86_emit_gas.intrinsic_memcpy(data);
1175 }
1176 
1177 static void
emit_zerostack(struct stack_block * sb,size_t nbytes)1178 emit_zerostack(struct stack_block *sb, size_t nbytes) {
1179 	x_fprintf(out, "\tmov $%lu, %%rdx\n",
1180 		(unsigned long)nbytes);
1181 	x_fprintf(out, "\tmov $0, %%rsi\n");
1182 	x_fprintf(out, "\tlea -%lu(%%rbp), %%rdi\n",
1183 		(unsigned long)sb->offset);
1184 	if (sysflag == OS_OSX) {
1185 		x_fprintf(out, "\tcall _memset\n");
1186 	} else {
1187 		x_fprintf(out, "\tcall memset\n");
1188 	}
1189 }
1190 
1191 static void
emit_alloca(struct allocadata * ad)1192 emit_alloca(struct allocadata *ad) {
1193 	x_fprintf(out, "\tmov %%%s, %%%s\n", ad->size_reg->name,
1194 		ad->size_reg->size == 4? "edi": "rdi");
1195 	if (sysflag == OS_OSX) {
1196 		x_fprintf(out, "\tcall _malloc\n");
1197 	} else {
1198 		x_fprintf(out, "\tcall malloc\n");
1199 	}
1200 	if (ad->result_reg != &amd64_x86_gprs[0]) {
1201 		x_fprintf(out, "\tmov %%rax, %%%s\n",
1202 			ad->result_reg->name);
1203 	}
1204 }
1205 
1206 static void
emit_dealloca(struct stack_block * sb,struct reg * r)1207 emit_dealloca(struct stack_block *sb, struct reg *r) {
1208 	char	*regname = r? r->name: "rdi";
1209 	x_fprintf(out, "\tmovq -%lu(%%rbp), %%%s\n",
1210 		(unsigned long)sb->offset, regname);
1211 	if (sysflag == OS_OSX) {
1212 		x_fprintf(out, "\tcall _free\n");
1213 	} else {
1214 		x_fprintf(out, "\tcall free\n");
1215 	}
1216 }
1217 
1218 static void
emit_alloc_vla(struct stack_block * sb)1219 emit_alloc_vla(struct stack_block *sb) {
1220 	x_fprintf(out, "\tmov -%lu(%%rbp), %%rdi\n",
1221 		(unsigned long)sb->offset - backend->get_ptr_size());
1222 	if (sysflag == OS_OSX) {
1223 		x_fprintf(out, "\tcall _malloc\n");
1224 	} else {
1225 		x_fprintf(out, "\tcall malloc\n");
1226 	}
1227 	x_fprintf(out, "\tmov %%rax, -%lu(%%rbp)\n",
1228 		(unsigned long)sb->offset);
1229 }
1230 
1231 static void
emit_dealloc_vla(struct stack_block * sb,struct reg * r)1232 emit_dealloc_vla(struct stack_block *sb, struct reg *r) {
1233 	char	*regname = r? r->name: "rdi";
1234 	x_fprintf(out, "\tmovq -%lu(%%rbp), %%%s\n",
1235 		(unsigned long)sb->offset, regname);
1236 	if (sysflag == OS_OSX) {
1237 		x_fprintf(out, "\tcall _free\n");
1238 	} else {
1239 		x_fprintf(out, "\tcall free\n");
1240 	}
1241 }
1242 
1243 static void
emit_put_vla_size(struct vlasizedata * data)1244 emit_put_vla_size(struct vlasizedata *data) {
1245 	x_fprintf(out, "\tmovq %%%s, -%lu(%%rbp)\n",
1246 		data->size->name,
1247 		(unsigned long)data->blockaddr->offset - data->offset);
1248 }
1249 
1250 static void
emit_retr_vla_size(struct vlasizedata * data)1251 emit_retr_vla_size(struct vlasizedata *data) {
1252 	x_fprintf(out, "\tmovq -%lu(%%rbp), %%%s\n",
1253 		(unsigned long)data->blockaddr->offset - data->offset,
1254 		data->size->name);
1255 }
1256 
1257 static void
emit_load_vla(struct reg * r,struct stack_block * sb)1258 emit_load_vla(struct reg *r, struct stack_block *sb) {
1259 	x_fprintf(out, "\tmovq -%lu(%%rbp), %%%s\n",
1260 		(unsigned long)sb->offset, r->name);
1261 }
1262 
1263 static void
emit_frame_address(struct builtinframeaddressdata * dat)1264 emit_frame_address(struct builtinframeaddressdata *dat) {
1265 	x_fprintf(out, "\tmovq %%rbp, %%%s\n",
1266 		dat->result_reg->name);
1267 }
1268 
1269 
1270 
1271 static void
emit_save_ret_addr(struct function * f,struct stack_block * sb)1272 emit_save_ret_addr(struct function *f, struct stack_block *sb) {
1273 	(void) f;
1274 
1275 	x_fprintf(out, "\tmov 8(%%rbp), %%rax\n");
1276 	x_fprintf(out, "\tmov %%rax, -%lu(%%rbp)\n", sb->offset);
1277 }
1278 
1279 static void
emit_check_ret_addr(struct function * f,struct stack_block * saved)1280 emit_check_ret_addr(struct function *f, struct stack_block *saved) {
1281 	static unsigned long	labval = 0;
1282 
1283 	(void) f;
1284 
1285 	x_fprintf(out, "\tmovq -%lu(%%rbp), %%rcx\n", saved->offset);
1286 	x_fprintf(out, "\tcmpq 8(%%rbp), %%rcx\n");
1287 	x_fprintf(out, "\tje .doret%lu\n", labval);
1288 	x_fprintf(out, "\tcall __nwcc_stack_corrupt\n");
1289 	x_fprintf(out, ".doret%lu:\n", labval++);
1290 }
1291 
1292 static void
do_stack(FILE * out,struct decl * d)1293 do_stack(FILE *out, struct decl *d) {
1294 	char	*sign;
1295 
1296 	if (d->stack_addr->is_func_arg) {
1297 		sign = "";
1298 	} else {
1299 		sign = "-";
1300 	}
1301 	x_fprintf(out, "%s%lu(%%rbp", sign, d->stack_addr->offset);
1302 }
1303 
1304 static void
print_mem_operand(struct vreg * vr,struct token * constant)1305 print_mem_operand(struct vreg *vr, struct token *constant) {
1306 	int		needbracket = 1;
1307 
1308 	if (vr && vr->from_const != NULL) {
1309 		constant = vr->from_const;
1310 	}
1311 	if (constant != NULL) {
1312 		struct token	*t = vr->from_const;
1313 
1314 		if (!IS_FLOATING(t->type)) {
1315 			/*
1316 			 * XXX hmm sometimes we use $.Str and sometimes
1317 			 * .Str??
1318 			 */
1319 			x_fputc('$', out);
1320 		}
1321 		/* if (t->type == TY_INT) {
1322 			x_fprintf(out, "%d",
1323 				*(int *)t->data);
1324 		} else if (t->type == TY_UINT) {
1325 			x_fprintf(out, "%u",
1326 				*(unsigned *)t->data);
1327 		} else if (t->type == TY_LONG
1328 			|| t->type == TY_LLONG) {
1329 			x_fprintf(out, "%ld",
1330 				*(long *)t->data);
1331 		} else if (t->type == TY_ULONG
1332 			|| t->type == TY_ULLONG) {
1333 			x_fprintf(out, "%lu",
1334 				*(unsigned long *)t->data);
1335 		}*/
1336 		if (IS_INT(t->type) || IS_LONG(t->type) || IS_LLONG(t->type)) {
1337 			cross_print_value_by_type(out, t->data, t->type, 0);
1338 #if ALLOW_CHAR_SHORT_CONSTANTS
1339 		} else if (IS_CHAR(t->type) || IS_SHORT(t->type)) {
1340 			cross_print_value_by_type(out, t->data, t->type, 0);
1341 #endif
1342 		} else if (t->type == TOK_STRING_LITERAL) {
1343 			struct ty_string	*ts = t->data;
1344 			x_fprintf(out, "._Str%ld",
1345 				ts->count);
1346 		} else if (t->type == TY_FLOAT
1347 			|| t->type == TY_DOUBLE
1348 			|| t->type == TY_LDOUBLE) {
1349 			struct ty_float	*tf = t->data;
1350 
1351 			x_fprintf(out, "(_Float%lu)",
1352 				tf->count);
1353 		} else {
1354 			printf("loadimm: Bad data type %d\n", t->type);
1355 			exit(EXIT_FAILURE);
1356 		}
1357 	} else if (vr->parent != NULL) {
1358 		struct vreg	*vr2;
1359 		struct decl	*d2;
1360 
1361 		vr2 = get_parent_struct(vr);
1362 		if ((d2 = vr2->var_backed) != NULL) {
1363 			unsigned long	off = calc_offsets(vr);
1364 #if 0
1365 			hm continue here, upwards
1366 #endif
1367 			if (d2->stack_addr) {
1368 				/* XXX wow this sux */
1369 				if (vr2->var_backed->stack_addr->is_func_arg) {
1370 					vr2->var_backed->stack_addr->offset +=
1371 						/*vr->memberdecl->offset*/ off;
1372 				} else {
1373 					vr2->var_backed->stack_addr->offset -=
1374 						/*vr->memberdecl->offset*/ off;
1375 				}
1376 				do_stack(out, vr2->var_backed);
1377 				if (vr2->var_backed->stack_addr->is_func_arg) {
1378 					vr2->var_backed->stack_addr->offset -=
1379 						/*vr->memberdecl->offset*/ off;
1380 				} else {
1381 					vr2->var_backed->stack_addr->offset +=
1382 						/*vr->memberdecl->offset*/ off;
1383 				}
1384 			} else {
1385 				/* static */
1386 				x_fprintf(out, "%s+%lu",
1387 					d2->dtype->name, calc_offsets(vr));
1388 				needbracket = 0;
1389 			}
1390 		} else if (vr2->from_ptr) {
1391 			/* Struct comes from pointer */
1392 			x_fprintf(out, "%lu(%%%s",
1393 				calc_offsets(vr)	,
1394 				vr2->from_ptr->pregs[0]->name);
1395 		} else {
1396 			printf("BUG: Bad load for %s\n",
1397 				vr->type->name? vr->type->name: "structure");
1398 			abort();
1399 		}
1400 	} else if (vr->var_backed) {
1401 		struct decl	*d = vr->var_backed;
1402 
1403 		if (d->stack_addr != NULL) {
1404 			do_stack(out, d);
1405 		} else {
1406 			/*
1407 			 * Static or register variable
1408 			 */
1409 			if (d->dtype->storage == TOK_KEY_REGISTER) {
1410 				unimpl();
1411 			} else {
1412 				if (d->dtype->tlist != NULL
1413 					&& d->dtype->tlist->type
1414 					== TN_FUNCTION) {
1415 					needbracket = 0;
1416 					x_fprintf(out, "$%s", d->dtype->name);
1417 				} else {
1418 					x_fprintf(out, "%s(%%rip)", d->dtype->name);
1419 				}
1420 				needbracket = 0;
1421 			}
1422 		}
1423 	} else if (vr->stack_addr) {
1424 		/*
1425 		 * 07/26/12: This was missing support for writing through
1426 		 * the stack rather than frame pointer
1427 		 */
1428 		if (vr->stack_addr->use_frame_pointer) {
1429 			x_fprintf(out, "-%lu(%%rbp", vr->stack_addr->offset);
1430 		} else {
1431 			x_fprintf(out, "%lu(%%rsp", vr->stack_addr->offset);
1432 		}
1433 	} else if (vr->from_ptr) {
1434 		x_fprintf(out, "(%%%s", vr->from_ptr->pregs[0]->name);
1435 	} else {
1436 		abort();
1437 	}
1438 	if (constant == NULL) {
1439 		if (needbracket) {
1440 			x_fputc(')', out);
1441 		}
1442 	}
1443 }
1444 
1445 static void
emit_finish_program(void)1446 emit_finish_program(void) {
1447 /*	x86_emit_gas.finish_program();*/
1448 }
1449 
1450 
1451 /* Mem to FPR */
1452 static void
emit_amd64_cvtsi2sd(struct icode_instr * ip)1453 emit_amd64_cvtsi2sd(struct icode_instr *ip) {
1454 	x_fprintf(out, "\tcvtsi2sd ");
1455 	print_mem_or_reg(ip->src_pregs[0], ip->src_vreg);
1456 	x_fprintf(out, ", %%%s\n", ip->dest_pregs[0]->name);
1457 }
1458 
1459 /* Mem to FPR */
1460 static void
emit_amd64_cvtsi2ss(struct icode_instr * ip)1461 emit_amd64_cvtsi2ss(struct icode_instr *ip) {
1462 	x_fprintf(out, "\tcvtsi2ss ");
1463 	print_mem_or_reg(ip->src_pregs[0], ip->src_vreg);
1464 	x_fprintf(out, ", %%%s\n", ip->dest_pregs[0]->name);
1465 }
1466 
1467 /* Mem to FPR */
1468 static void
emit_amd64_cvtsi2sdq(struct icode_instr * ip)1469 emit_amd64_cvtsi2sdq(struct icode_instr *ip) {
1470 	x_fprintf(out, "\tcvtsi2sdq ");
1471 	print_mem_or_reg(ip->src_pregs[0], ip->src_vreg);
1472 	x_fprintf(out, ", %%%s\n", ip->dest_pregs[0]->name);
1473 }
1474 
1475 /* Mem to FPR */
1476 static void
emit_amd64_cvtsi2ssq(struct icode_instr * ip)1477 emit_amd64_cvtsi2ssq(struct icode_instr *ip) {
1478 	x_fprintf(out, "\tcvtsi2ssq ");
1479 	print_mem_or_reg(ip->src_pregs[0], ip->src_vreg);
1480 	x_fprintf(out, ", %%%s\n", ip->dest_pregs[0]->name);
1481 }
1482 
1483 /* FPR to GPR */
1484 static void
emit_amd64_cvttsd2si(struct icode_instr * ip)1485 emit_amd64_cvttsd2si(struct icode_instr *ip) {
1486 	x_fprintf(out, "\tcvttsd2si %%%s, %%%s\n",
1487 		 ip->src_pregs[0]->name, ip->dest_pregs[0]->name);
1488 }
1489 
1490 /* FPR to GPR */
1491 /* 08/01/08: For quad-word target */
1492 static void
emit_amd64_cvttsd2siq(struct icode_instr * ip)1493 emit_amd64_cvttsd2siq(struct icode_instr *ip) {
1494 	x_fprintf(out, "\tcvttsd2siq %%%s, %%%s\n",
1495 		 ip->src_pregs[0]->name, ip->dest_pregs[0]->name);
1496 }
1497 
1498 /* FPR to GPR */
1499 static void
emit_amd64_cvttss2si(struct icode_instr * ip)1500 emit_amd64_cvttss2si(struct icode_instr *ip) {
1501 	x_fprintf(out, "\tcvttss2si %%%s, %%%s\n",
1502 		 ip->src_pregs[0]->name, ip->dest_pregs[0]->name);
1503 }
1504 
1505 /* FPR to GPR */
1506 /* 08/01/08: For quad-word target */
1507 static void
emit_amd64_cvttss2siq(struct icode_instr * ip)1508 emit_amd64_cvttss2siq(struct icode_instr *ip) {
1509 	x_fprintf(out, "\tcvttss2siq %%%s, %%%s\n",
1510 		 ip->src_pregs[0]->name, ip->dest_pregs[0]->name);
1511 }
1512 
1513 static void
emit_amd64_cvtsd2ss(struct icode_instr * ii)1514 emit_amd64_cvtsd2ss(struct icode_instr *ii) {
1515 	struct reg	*r = ii->dat;
1516 
1517 	x_fprintf(out, "\tcvtsd2ss %%%s, %%%s\n", r->name, r->name);
1518 }
1519 
1520 static void
emit_amd64_cvtss2sd(struct icode_instr * ii)1521 emit_amd64_cvtss2sd(struct icode_instr *ii) {
1522 	struct reg	*r = ii->dat;
1523 
1524 	x_fprintf(out, "\tcvtss2sd %%%s, %%%s\n", r->name, r->name);
1525 }
1526 
1527 static void
emit_amd64_load_negmask(struct icode_instr * ii)1528 emit_amd64_load_negmask(struct icode_instr *ii) {
1529 /*	struct reg	*r = ii->dat;*/
1530 	struct amd64_negmask_data	*dat = ii->dat;
1531 	struct reg			*target_fpr = dat->target_fpr;
1532 	struct reg			*support_gpr = dat->support_gpr;
1533 	int				for_double;
1534 
1535 	if (ii->src_vreg != NULL) {
1536 		for_double = 1;
1537 	} else {
1538 		for_double = 0;
1539 	}
1540 
1541 	if (sysflag == OS_OSX && backend->arch == ARCH_AMD64) {
1542 		x_fprintf(out, "\tmovs%c _SSE_Negmask%s(%%rip), %%%s\n",
1543 				for_double? 'd': 's',
1544 				for_double? "_double": "",
1545 				target_fpr->name);
1546 	} else {
1547 		if (picflag) {
1548 			x_fprintf(out, "\tmov _SSE_Negmask%s@GOTPCREL(%%rip), %%%s\n",
1549 				for_double? "_double": "",
1550 				support_gpr->name);
1551 			x_fprintf(out, "\tmovs%c (%%%s), %%%s\n",
1552 				for_double? 'd': 's',
1553 				support_gpr->name,
1554 				target_fpr->name);
1555 		} else {
1556 			x_fprintf(out, "\tmovs%c (_SSE_Negmask%s), %%%s\n",
1557 					for_double? 'd': 's',
1558 					for_double? "_double": "",
1559 					target_fpr->name);
1560 		}
1561 	}
1562 }
1563 
1564 static void
emit_amd64_xorps(struct icode_instr * ii)1565 emit_amd64_xorps(struct icode_instr *ii) {
1566 	struct reg	*r = ii->dat;
1567 
1568 	x_fprintf(out, "\txorps %%%s, %%%s\n",
1569 		r->name, ii->dest_vreg->pregs[0]->name);
1570 }
1571 
1572 static void
emit_amd64_xorpd(struct icode_instr * ii)1573 emit_amd64_xorpd(struct icode_instr *ii) {
1574 	struct reg	*r = ii->dat;
1575 
1576 	x_fprintf(out, "\txorpd %%%s, %%%s\n",
1577 		r->name, ii->dest_vreg->pregs[0]->name);
1578 }
1579 
1580 static void
emit_amd64_ulong_to_float(struct icode_instr * ii)1581 emit_amd64_ulong_to_float(struct icode_instr *ii) {
1582 	struct amd64_ulong_to_float	*data = ii->dat;
1583 	static unsigned long		count;
1584 
1585 	if (data->code == TY_LDOUBLE) {
1586 		x_fprintf(out, "\ttestq %%%s, %%%s\n", data->src_gpr->name, data->src_gpr->name);
1587 		x_fprintf(out, "\tjs ._Ulong_float%lu\n", count);
1588 		x_fprintf(out, "\tjmp ._Ulong_float%lu\n", count+1);
1589 		x_fprintf(out, "._Ulong_float%lu:\n", count);
1590 		x_fprintf(out, "\tfadds _Ulong_float_mask(%%rip)\n");
1591 		x_fprintf(out, "._Ulong_float%lu:\n", count+1);
1592 		count += 2;
1593 	} else {
1594 		x_fprintf(out, "\ttestq %%%s, %%%s\n", data->src_gpr->name, data->src_gpr->name);
1595 		x_fprintf(out, "\tjs ._Ulong_float%lu\n", count);
1596 		x_fprintf(out, "\tcvtsi2%sq %%%s, %%%s\n",
1597 			data->code == TY_DOUBLE? "sd": "ss", data->src_gpr->name, data->dest_sse_reg->name);
1598 		x_fprintf(out, "\tjmp ._Ulong_float%lu\n", count+1);
1599 		x_fprintf(out, "._Ulong_float%lu:\n", count);
1600 		x_fprintf(out, "\tmovq %%%s, %%%s\n", data->src_gpr->name, data->temp_gpr->name);
1601 		x_fprintf(out, "\tandl $1, %%%s\n", data->src_gpr->composed_of[0]->name);
1602 		x_fprintf(out, "\tshrq %%%s\n", data->temp_gpr->name);
1603 		x_fprintf(out, "\torq %%%s, %%%s\n", data->src_gpr->name, data->temp_gpr->name);
1604 		x_fprintf(out, "\tcvtsi2%sq %%%s, %%%s\n",
1605 			data->code == TY_DOUBLE? "sd": "ss", data->temp_gpr->name, data->dest_sse_reg->name);
1606 		x_fprintf(out, "\tadd%s %%%s, %%%s\n",
1607 			data->code == TY_DOUBLE? "sd": "ss", data->dest_sse_reg->name, data->dest_sse_reg->name);
1608 		x_fprintf(out, "._Ulong_float%lu:\n", count+1);
1609 		count += 2;
1610 	}
1611 }
1612 
1613 struct emitter amd64_emit_gas = {
1614 	0, /* need_explicit_extern_decls */
1615 	init,
1616 	emit_strings,
1617 	emit_fp_constants,
1618 	NULL, /* llong_constants */
1619 	emit_support_buffers,
1620 	NULL, /* pic_support */
1621 
1622 	NULL, /* support_decls */
1623 	emit_extern_decls,
1624 	emit_global_extern_decls,
1625 	emit_global_static_decls,
1626 #if 0
1627 	emit_global_decls,
1628 	emit_static_decls,
1629 #endif
1630 	emit_static_init_vars,
1631 	emit_static_uninit_vars,
1632 	emit_static_init_thread_vars,
1633 	emit_static_uninit_thread_vars,
1634 	NULL,  /*emit_struct_defs,*/
1635 	emit_comment,
1636 	emit_dwarf2_line,
1637 	emit_dwarf2_files,
1638 	emit_inlineasm,
1639 	emit_unimpl,
1640 	emit_empty,
1641 	emit_label,
1642 	emit_call,
1643 	emit_callindir,
1644 	emit_func_header,
1645 	emit_func_intro,
1646 	emit_func_outro,
1647 	emit_define,
1648 	emit_push,
1649 	emit_allocstack,
1650 	emit_freestack,
1651 	emit_adj_allocated,
1652 	emit_inc,
1653 	emit_dec,
1654 	emit_load,
1655 	emit_load_addrlabel,
1656 	emit_comp_goto,
1657 	emit_store,
1658 	emit_setsection,
1659 	emit_alloc,
1660 	emit_neg,
1661 	emit_sub,
1662 	emit_add,
1663 	emit_div,
1664 	emit_mod,
1665 	emit_mul,
1666 	emit_shl,
1667 	emit_shr,
1668 	emit_or,
1669 	NULL, /* emit_preg_or */
1670 	emit_and,
1671 	emit_xor,
1672 	emit_not,
1673 	emit_ret,
1674 	emit_cmp,
1675 	NULL, /* extend_sign */
1676 	NULL, /* conv_fp */
1677 	NULL, /* from_ldouble */
1678 	NULL, /* to_ldouble */
1679 	emit_branch,
1680 	emit_mov,
1681 	emit_setreg,
1682 	emit_xchg,
1683 	emit_addrof,
1684 	NULL, /* initialize_pic */
1685 	emit_copyinit,
1686 	NULL, /* putstructregs */
1687 	emit_copystruct,
1688 	emit_intrinsic_memcpy,
1689 	emit_zerostack,
1690 	emit_alloca,
1691 	emit_dealloca,
1692 	emit_alloc_vla,
1693 	emit_dealloc_vla,
1694 	emit_put_vla_size,
1695 	emit_retr_vla_size,
1696 	emit_load_vla,
1697 	emit_frame_address,
1698 	emit_struct_inits,
1699 	emit_save_ret_addr,
1700 	emit_check_ret_addr,
1701 	print_mem_operand,
1702 	emit_finish_program,
1703 	NULL, /* stupidtrace */
1704 	NULL, /* finish_stupidtrace */
1705 };
1706 
1707 struct emitter_amd64	emit_amd64_gas = {
1708 	emit_amd64_cvtsi2sd,
1709 	emit_amd64_cvtsi2ss,
1710 	emit_amd64_cvtsi2sdq,
1711 	emit_amd64_cvtsi2ssq,
1712 	emit_amd64_cvttsd2si,
1713 	emit_amd64_cvttsd2siq,
1714 	emit_amd64_cvttss2si,
1715 	emit_amd64_cvttss2siq,
1716 	emit_amd64_cvtsd2ss,
1717 	emit_amd64_cvtss2sd,
1718 	emit_amd64_load_negmask,
1719 	emit_amd64_xorps,
1720 	emit_amd64_xorpd,
1721 	emit_amd64_ulong_to_float
1722 };
1723 
1724