History

pe32+ target: adjust x86_64-gen.c

- calling conventions are different: * only 4 registers * stack "scratch area" is always reserved * doubles are mirrored in normal registers - no GOT or PIC there

grischka committed 17 years ago

Commit 45987571 parent 3ba15321 file · +115 −25Browse files

Unified · Split

x86_64-gen.c+115−25
@@ -210,12 +210,21 @@ static void gen_addrpc32(int r, Sym *sym, int c) · 209 unmodified lines
210210 /* output got address with relocation */
211211 static void gen_gotpcrel(int r, Sym *sym, int c)
212212 {
213+#ifndef TCC_TARGET_PE
213214 Section *sr;
214215 ElfW(Rela) *rel;
215216 greloc(cur_text_section, sym, ind, R_X86_64_GOTPCREL);
216217 sr = cur_text_section->reloc;
217218 rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela)));
218219 rel->r_addend = -4;
220+#else
221+ printf("picpic: %s %x %x | %02x %02x %02x\n", get_tok_str(sym->v, NULL), c, r,
222+ cur_text_section->data[ind-3],
223+ cur_text_section->data[ind-2],
224+ cur_text_section->data[ind-1]
225+ );
226+ greloc(cur_text_section, sym, ind, R_X86_64_PC32);
227+#endif
219228 gen_le32(0);
220229
221230 if (c) {
@@ -293,6 +302,7 @@ void load(int r, SValue *sv) · 71 unmodified lines
293302 ft = sv->type.t;
294303 fc = sv->c.ul;
295304
305+#ifndef TCC_TARGET_PE
296306 /* we use indirect access via got */
297307 if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
298308 (fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) {
@@ -307,6 +317,7 @@ void load(int r, SValue *sv) · 8 unmodified lines
307317 /* load from the temporal register */
308318 fr = tr | VT_LVAL;
309319 }
320+#endif
310321
311322 v = fr & VT_VALMASK;
312323 if (fr & VT_LVAL) {
@@ -350,15 +361,19 @@ void load(int r, SValue *sv) · 37 unmodified lines
350361 gen_addr64(fr, sv->sym, sv->c.ull);
351362 } else {
352363 if (fr & VT_SYM) {
364+#ifndef TCC_TARGET_PE
353365 if (sv->sym->type.t & VT_STATIC) {
366+#endif
354367 o(0x8d48);
355368 o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */
356369 gen_addrpc32(fr, sv->sym, fc);
370+#ifndef TCC_TARGET_PE
357371 } else {
358372 o(0x8b48);
359373 o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */
360374 gen_gotpcrel(r, sv->sym, fc);
361375 }
376+#endif
362377 } else {
363378 o(0xb8 + REG_VALUE(r)); /* mov $xx, r */
364379 gen_le32(fc);
@@ -416,6 +431,7 @@ void store(int r, SValue *v) · 51 unmodified lines
416431 fr = v->r & VT_VALMASK;
417432 bt = ft & VT_BTYPE;
418433
434+#ifndef TCC_TARGET_PE
419435 /* we need to access the variable via got */
420436 if (fr == VT_CONST && (v->r & VT_SYM)) {
421437 /* mov xx(%rip), %r11 */
@@ -423,6 +439,7 @@ void store(int r, SValue *v) · 1 unmodified line
423439 gen_gotpcrel(TREG_R11, v->sym, v->c.ul);
424440 pic = is64_type(bt) ? 0x49 : 0x41;
425441 }
442+#endif
426443
427444 /* XXX: incorrect if float reg to reg */
428445 if (bt == VT_FLOAT) {
@@ -515,16 +532,24 @@ static void gcall_or_jmp(int is_jmp) · 86 unmodified lines
515532 }
516533 }
517534
518−static uint8_t arg_regs[6] = {
535+#ifdef TCC_TARGET_PE
536+#define REGN 4
537+static uint8_t arg_regs[] = {
538+ TREG_RCX, TREG_RDX, TREG_R8, TREG_R9
539+};
540+#else
541+#define REGN 6
542+static uint8_t arg_regs[REGN] = {
519543 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
520544 };
545+#endif
546+
521547 /* Generate function call. The function address is pushed first, then
522548 all the parameters in call order. This functions pops all the
523549 parameters and the function address. */
524550 void gfunc_call(int nb_args)
525551 {
526− int size, align, r, args_size, i, func_call;
527− Sym *func_sym;
552+ int size, align, r, args_size, i;
528553 SValue *orig_vtop;
529554 int nb_reg_args = 0;
530555 int nb_sse_args = 0;
@@ -537,12 +562,14 @@ void gfunc_call(int nb_args) · 6 unmodified lines
537562 args_size += type_size(&vtop->type, &align);
538563 } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) {
539564 args_size += 16;
565+#ifndef TCC_TARGET_PE
540566 } else if (is_sse_float(vtop[-i].type.t)) {
541567 nb_sse_args++;
542568 if (nb_sse_args > 8) args_size += 8;
569+#endif
543570 } else {
544571 nb_reg_args++;
545− if (nb_reg_args > 6) args_size += 8;
572+ if (nb_reg_args > REGN) args_size += 8;
546573 }
547574 }
548575
@@ -552,6 +579,11 @@ void gfunc_call(int nb_args) · 3 unmodified lines
552579 orig_vtop = vtop;
553580 gen_reg = nb_reg_args;
554581 sse_reg = nb_sse_args;
582+
583+#ifdef TCC_TARGET_PE
584+ save_regs(0); /* save used temporary registers */
585+#endif
586+
555587 /* adjust stack to align SSE boundary */
556588 if (args_size &= 8) {
557589 o(0x50); /* push $rax */
@@ -587,8 +619,13 @@ void gfunc_call(int nb_args) · 29 unmodified lines
587619 g(0x00);
588620 args_size += size;
589621 } else if (is_sse_float(vtop->type.t)) {
622+#ifdef TCC_TARGET_PE
623+ int j = --gen_reg;
624+ if (j >= REGN) {
625+#else
590626 int j = --sse_reg;
591627 if (j >= 8) {
628+#endif
592629 gv(RC_FLOAT);
593630 o(0x50); /* push $rax */
594631 /* movq %xmm0, (%rsp) */
@@ -600,7 +637,7 @@ void gfunc_call(int nb_args) · 5 unmodified lines
600637 int j = --gen_reg;
601638 /* simple type */
602639 /* XXX: implicit cast ? */
603− if (j >= 6) {
640+ if (j >= REGN) {
604641 r = gv(RC_INT);
605642 o(0x50 + r); /* push r */
606643 args_size += 8;
@@ -620,6 +657,42 @@ void gfunc_call(int nb_args) · 13 unmodified lines
620657 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT ||
621658 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
622659 } else if (is_sse_float(vtop->type.t)) {
660+#ifdef TCC_TARGET_PE
661+ int j = --gen_reg;
662+ if (j < REGN) {
663+ int d = arg_regs[j];
664+ gv(RC_FLOAT); /* only one float register */
665+ /* movaps %xmm0, %xmmN */
666+ o(0x280f);
667+ o(0xc0 + (j << 3));
668+ o(0x50);
669+ o(0xd60f66); /* movq %xmm0, (%rsp) */
670+ o(0x2404 + (j << 3));
671+ if (d < 8) {
672+ o(0x58 + d); /* pop d */
673+ } else {
674+ o(0x58);
675+ o(0xc08949 + d - 8);
676+ }
677+ }
678+ } else {
679+ int j = --gen_reg;
680+ /* simple type */
681+ /* XXX: implicit cast ? */
682+ if (j < REGN) {
683+ int d = arg_regs[j];
684+ r = gv(RC_INT);
685+ if (d != r) {
686+ if (d < 8) {
687+ o(0x8948); /* mov */
688+ o(0xc0 + r * 8 + d);
689+ } else {
690+ o(0x8949); /* mov */
691+ o(0xc0 + r * 8 + d - 8);
692+ }
693+ }
694+ }
695+#else
623696 int j = --sse_reg;
624697 if (j < 8) {
625698 gv(RC_FLOAT); /* only one float register */
@@ -631,7 +704,7 @@ void gfunc_call(int nb_args) · 5 unmodified lines
631704 int j = --gen_reg;
632705 /* simple type */
633706 /* XXX: implicit cast ? */
634− if (j < 6) {
707+ if (j < REGN) {
635708 r = gv(RC_INT);
636709 if (j < 2) {
637710 o(0x8948); /* mov */
@@ -646,10 +719,16 @@ void gfunc_call(int nb_args) · 8 unmodified lines
646719 o(0xc0 + r * 8 + j - 4);
647720 }
648721 }
722+#endif
649723 }
650724 vtop--;
651725 }
652726
727+#ifdef TCC_TARGET_PE
728+ /* allocate scratch space */
729+ gadd_sp(-8*REGN);
730+ args_size += 8*REGN;
731+#else
653732 save_regs(0); /* save used temporary registers */
654733
655734 /* Copy R10 and R11 into RDX and RCX, respectively */
@@ -660,22 +739,15 @@ void gfunc_call(int nb_args) · 4 unmodified lines
660739 }
661740 }
662741
663− func_sym = vtop->type.ref;
664− func_call = FUNC_CALL(func_sym->r);
665742 oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */
743+#endif
666744 gcall_or_jmp(0);
667745 if (args_size)
668746 gadd_sp(args_size);
669747 vtop--;
670748 }
671749
672−#ifdef TCC_TARGET_PE
673−/* XXX: support PE? */
674−#warning "PE isn't tested at all"
675−#define FUNC_PROLOG_SIZE 12
676−#else
677750 #define FUNC_PROLOG_SIZE 11
678−#endif
679751
680752 static void push_arg_reg(int i) {
681753 loc -= 8;
@@ -685,7 +757,7 @@ static void push_arg_reg(int i) { · 3 unmodified lines
685757 /* generate function prolog of type 't' */
686758 void gfunc_prolog(CType *func_type)
687759 {
688− int i, addr, align, size, func_call;
760+ int i, addr, align, size;
689761 int param_index, param_addr, reg_param_index, sse_param_index;
690762 Sym *sym;
691763 CType *type;
@@ -693,12 +765,12 @@ void gfunc_prolog(CType *func_type) · 1 unmodified line
693765 func_ret_sub = 0;
694766
695767 sym = func_type->ref;
696− func_call = FUNC_CALL(sym->r);
697768 addr = PTR_SIZE * 2;
698769 loc = 0;
699770 ind += FUNC_PROLOG_SIZE;
700771 func_sub_sp_offset = ind;
701772
773+#ifndef TCC_TARGET_PE
702774 if (func_type->ref->c == FUNC_ELLIPSIS) {
703775 int seen_reg_num, seen_sse_num, seen_stack_size;
704776 seen_reg_num = seen_sse_num = 0;
@@ -721,7 +793,7 @@ void gfunc_prolog(CType *func_type) · 16 unmodified lines
721793 } else if ((type->t & VT_BTYPE) == VT_LDOUBLE) {
722794 seen_stack_size += LDOUBLE_SIZE;
723795 } else {
724− if (seen_reg_num < 6) {
796+ if (seen_reg_num < REGN) {
725797 seen_reg_num++;
726798 } else {
727799 seen_stack_size += 8;
@@ -750,10 +822,11 @@ void gfunc_prolog(CType *func_type) · 22 unmodified lines
750822 gen_le32(loc + 8);
751823 gen_le32(0);
752824 }
753− for (i = 0; i < 6; i++) {
754− push_arg_reg(5 - i);
825+ for (i = 0; i < REGN; i++) {
826+ push_arg_reg(REGN-1-i);
755827 }
756828 }
829+#endif
757830
758831 sym = func_type->ref;
759832 param_index = 0;
@@ -776,6 +849,7 @@ void gfunc_prolog(CType *func_type) · 16 unmodified lines
776849 type = &sym->type;
777850 size = type_size(type, &align);
778851 size = (size + 3) & ~3;
852+#ifndef TCC_TARGET_PE
779853 if (is_sse_float(type->t)) {
780854 if (sse_param_index < 8) {
781855 /* save arguments passed by register */
@@ -788,12 +862,22 @@ void gfunc_prolog(CType *func_type) · 6 unmodified lines
788862 addr += size;
789863 }
790864 sse_param_index++;
791− } else if ((type->t & VT_BTYPE) == VT_STRUCT ||
865+ } else
866+#endif
867+ if ((type->t & VT_BTYPE) == VT_STRUCT ||
792868 (type->t & VT_BTYPE) == VT_LDOUBLE) {
793869 param_addr = addr;
794870 addr += size;
795871 } else {
796− if (reg_param_index < 6) {
872+#ifdef TCC_TARGET_PE
873+ if (reg_param_index < REGN) {
874+ /* save arguments passed by register */
875+ gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
876+ }
877+ param_addr = addr;
878+ addr += 8;
879+#else
880+ if (reg_param_index < REGN) {
797881 /* save arguments passed by register */
798882 push_arg_reg(reg_param_index);
799883 param_addr = loc;
@@ -801,12 +885,21 @@ void gfunc_prolog(CType *func_type) · 1 unmodified line
801885 param_addr = addr;
802886 addr += 8;
803887 }
888+#endif
804889 reg_param_index++;
805890 }
806891 sym_push(sym->v & ~SYM_FIELD, type,
807892 VT_LOCAL | VT_LVAL, param_addr);
808893 param_index++;
809894 }
895+#ifdef TCC_TARGET_PE
896+ if (func_type->ref->c == FUNC_ELLIPSIS) {
897+ for (i = reg_param_index; i < REGN; ++i) {
898+ gen_modrm64(0x89, arg_regs[i], VT_LOCAL, NULL, addr);
899+ addr += 8;
900+ }
901+ }
902+#endif
810903 }
811904
812905 /* generate function epilog */
@@ -826,7 +919,7 @@ void gfunc_epilog(void) · 13 unmodified lines
826919 v = (-loc + 15) & -16;
827920 saved_ind = ind;
828921 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
829−#ifdef TCC_TARGET_PE
922+#if 0 // def TCC_TARGET_PE - don't have __chkstk yet, because assembler does not work
830923 if (v >= 4096) {
831924 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
832925 oad(0xb8, v); /* mov stacksize, %eax */
@@ -838,9 +931,6 @@ void gfunc_epilog(void) · 5 unmodified lines
838931 o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
839932 o(0xec8148); /* sub rsp, stacksize */
840933 gen_le32(v);
841−#if FUNC_PROLOG_SIZE == 12
842− o(0x90); /* adjust to FUNC_PROLOG_SIZE */
843−#endif
844934 }
845935 ind = saved_ind;
846936 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t