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