History

Most x86-64 tests now work; only on error in test1-3.

I've had to introduce the XMM1 register to get the calling convention to work properly, unfortunately this has broken a fair bit of code which assumes that only XMM0 is used.

James Lyon committed 13 years ago

Commit 0e176711 parent b961ba53 files · +129 −67Browse files

Unified · Split

3 files
  1. tccgen.c +47 −22
  2. tests/abitest.c +2 −2
  3. x86_64-gen.c +80 −43
tccgen.c+47−22
@@ -88,7 +88,7 @@ ST_INLN int is_float(int t) · 87 unmodified lines
88{88{
89 int bt;89 int bt;
90 bt = t & VT_BTYPE;90 bt = t & VT_BTYPE;
91 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;91 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT || bt == VT_QFLOAT;
92}92}
93 93
94/* we use our own 'finite' function to avoid potential problems with94/* we use our own 'finite' function to avoid potential problems with
@@ -688,9 +688,7 @@ static void gbound(void) · 593 unmodified lines
688ST_FUNC int gv(int rc)688ST_FUNC int gv(int rc)
689{689{
690 int r, bit_pos, bit_size, size, align, i;690 int r, bit_pos, bit_size, size, align, i;
691#ifndef TCC_TARGET_X86_64
692 int rc2;691 int rc2;
693#endif
694 692
695 /* NOTE: get_reg can modify vstack[] */693 /* NOTE: get_reg can modify vstack[] */
696 if (vtop->type.t & VT_BITFIELD) {694 if (vtop->type.t & VT_BITFIELD) {
@@ -765,11 +763,14 @@ ST_FUNC int gv(int rc) · 68 unmodified lines
765#endif763#endif
766 764
767 r = vtop->r & VT_VALMASK;765 r = vtop->r & VT_VALMASK;
768#ifndef TCC_TARGET_X86_64
769 rc2 = RC_INT;766 rc2 = RC_INT;
770 if (rc == RC_IRET)767 if (rc == RC_IRET)
771 rc2 = RC_LRET;768 rc2 = RC_LRET;
769#ifdef TCC_TARGET_X86_64
770 else if (rc == RC_FRET)
771 rc2 = RC_QRET;
772#endif772#endif
773
773 /* need to reload if:774 /* need to reload if:
774 - constant775 - constant
775 - lvalue (need to dereference pointer)776 - lvalue (need to dereference pointer)
@@ -777,18 +778,25 @@ ST_FUNC int gv(int rc) · 1 unmodified line
777 if (r >= VT_CONST778 if (r >= VT_CONST
778 || (vtop->r & VT_LVAL)779 || (vtop->r & VT_LVAL)
779 || !(reg_classes[r] & rc)780 || !(reg_classes[r] & rc)
780#ifndef TCC_TARGET_X86_64781#ifdef TCC_TARGET_X86_64
782 || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
783 || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
784#else
781 || ((vtop->type.t & VT_BTYPE) == VT_LLONG && !(reg_classes[vtop->r2] & rc2))785 || ((vtop->type.t & VT_BTYPE) == VT_LLONG && !(reg_classes[vtop->r2] & rc2))
782#endif786#endif
783 )787 )
784 {788 {
785 r = get_reg(rc);789 r = get_reg(rc);
786#ifndef TCC_TARGET_X86_64790#ifdef TCC_TARGET_X86_64
791 if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {
792#else
787 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {793 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
794#endif
788 int r2;795 int r2;
789 unsigned long long ll;796 unsigned long long ll;
790 /* two register type load : expand to two words797 /* two register type load : expand to two words
791 temporarily */798 temporarily */
799#ifndef TCC_TARGET_X86_64
792 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {800 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
793 /* load constant */801 /* load constant */
794 ll = vtop->c.ull;802 ll = vtop->c.ull;
@@ -796,23 +804,32 @@ ST_FUNC int gv(int rc) · 1 unmodified line
796 load(r, vtop);804 load(r, vtop);
797 vtop->r = r; /* save register value */805 vtop->r = r; /* save register value */
798 vpushi(ll >> 32); /* second word */806 vpushi(ll >> 32); /* second word */
799 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */807 } else
808#endif
809 if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
800 (vtop->r & VT_LVAL)) {810 (vtop->r & VT_LVAL)) {
811#ifdef TCC_TARGET_X86_64
812 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
813#else
814 int addr_type = VT_INT, load_size = 4, load_type = VT_INT;
815#endif
801 /* We do not want to modifier the long long816 /* We do not want to modifier the long long
802 pointer here, so the safest (and less817 pointer here, so the safest (and less
803 efficient) is to save all the other registers818 efficient) is to save all the other registers
804 in the stack. XXX: totally inefficient. */819 in the stack. XXX: totally inefficient. */
805 save_regs(1);820 save_regs(1);
806 /* load from memory */821 /* load from memory */
822 vtop->type.t = load_type;
807 load(r, vtop);823 load(r, vtop);
808 vdup();824 vdup();
809 vtop[-1].r = r; /* save register value */825 vtop[-1].r = r; /* save register value */
810 /* increment pointer to get second word */826 /* increment pointer to get second word */
811 vtop->type.t = VT_INT;827 vtop->type.t = addr_type;
812 gaddrof();828 gaddrof();
813 vpushi(4);829 vpushi(load_size);
814 gen_op('+');830 gen_op('+');
815 vtop->r |= VT_LVAL;831 vtop->r |= VT_LVAL;
832 vtop->type.t = load_type;
816 } else {833 } else {
817 /* move registers */834 /* move registers */
818 load(r, vtop);835 load(r, vtop);
@@ -827,9 +844,7 @@ ST_FUNC int gv(int rc) · 8 unmodified lines
827 vpop();844 vpop();
828 /* write second register */845 /* write second register */
829 vtop->r2 = r2;846 vtop->r2 = r2;
830 } else847 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
831#endif
832 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
833 int t1, t;848 int t1, t;
834 /* lvalue of scalar type : need to use lvalue type849 /* lvalue of scalar type : need to use lvalue type
835 because of possible cast */850 because of possible cast */
@@ -2479,6 +2494,8 @@ ST_FUNC void vstore(void) · 1643 unmodified lines
2479#ifdef TCC_TARGET_X86_642494#ifdef TCC_TARGET_X86_64
2480 if ((ft & VT_BTYPE) == VT_LDOUBLE) {2495 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
2481 rc = RC_ST0;2496 rc = RC_ST0;
2497 } else if ((ft & VT_BTYPE) == VT_QFLOAT) {
2498 rc = RC_FRET;
2482 }2499 }
2483#endif2500#endif
2484 }2501 }
@@ -2497,29 +2514,29 @@ ST_FUNC void vstore(void) · 12 unmodified lines
2497 load(t, &sv);2514 load(t, &sv);
2498 vtop[-1].r = t | VT_LVAL;2515 vtop[-1].r = t | VT_LVAL;
2499 }2516 }
2500 store(r, vtop - 1);
2501 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */2517 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */
2502#ifdef TCC_TARGET_X86_642518#ifdef TCC_TARGET_X86_64
2503 if ((ft & VT_BTYPE) == VT_QLONG) {2519 if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) {
2520 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
2504#else2521#else
2505 if ((ft & VT_BTYPE) == VT_LLONG) {2522 if ((ft & VT_BTYPE) == VT_LLONG) {
2523 int addr_type = VT_INT, load_size = 4, load_type = VT_INT;
2506#endif2524#endif
2525 vtop[-1].type.t = load_type;
2526 store(r, vtop - 1);
2507 vswap();2527 vswap();
2508 /* convert to int to increment easily */2528 /* convert to int to increment easily */
2509#ifdef TCC_TARGET_X86_642529 vtop->type.t = addr_type;
2510 vtop->type.t = VT_LLONG;
2511 gaddrof();
2512 vpushi(8);
2513#else
2514 vtop->type.t = VT_INT;
2515 gaddrof();2530 gaddrof();
2516 vpushi(4);2531 vpushi(load_size);
2517#endif
2518 gen_op('+');2532 gen_op('+');
2519 vtop->r |= VT_LVAL;2533 vtop->r |= VT_LVAL;
2520 vswap();2534 vswap();
2535 vtop[-1].type.t = load_type;
2521 /* XXX: it works because r2 is spilled last ! */2536 /* XXX: it works because r2 is spilled last ! */
2522 store(vtop->r2, vtop - 1);2537 store(vtop->r2, vtop - 1);
2538 } else {
2539 store(r, vtop - 1);
2523 }2540 }
2524 }2541 }
2525 vswap();2542 vswap();
@@ -3897,8 +3914,16 @@ ST_FUNC void unary(void) · 1371 unmodified lines
3897 /* return in register */3914 /* return in register */
3898 if (is_float(ret.type.t)) {3915 if (is_float(ret.type.t)) {
3899 ret.r = reg_fret(ret.type.t);3916 ret.r = reg_fret(ret.type.t);
3917#ifdef TCC_TARGET_X86_64
3918 if ((ret.type.t & VT_BTYPE) == VT_QFLOAT)
3919 ret.r2 = REG_QRET;
3920#endif
3900 } else {3921 } else {
3922#ifdef TCC_TARGET_X86_64
3923 if ((ret.type.t & VT_BTYPE) == VT_QLONG)
3924#else
3901 if ((ret.type.t & VT_BTYPE) == VT_LLONG)3925 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
3926#endif
3902 ret.r2 = REG_LRET;3927 ret.r2 = REG_LRET;
3903 ret.r = REG_IRET;3928 ret.r = REG_IRET;
3904 }3929 }
tests/abitest.c+2−2
@@ -88,8 +88,8 @@ static int ret_2float_test(void) { · 87 unmodified lines
88/*88/*
89 * ret_2double_test:89 * ret_2double_test:
90 * 90 *
91 * On x86-64, a struct with 2 doubles should be packed into a single91 * On x86-64, a struct with 2 doubles should be passed in two SSE
92 * SSE register (this tests VT_QFLOAT).92 * registers.
93 */93 */
94typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;94typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;
95typedef ret_2double_test_type (*ret_2double_test_function_type) (ret_2double_test_type);95typedef ret_2double_test_type (*ret_2double_test_function_type) (ret_2double_test_type);
x86_64-gen.c+80−43
@@ -23,7 +23,7 @@ · 22 unmodified lines
23#ifdef TARGET_DEFS_ONLY23#ifdef TARGET_DEFS_ONLY
24 24
25/* number of available registers */25/* number of available registers */
26#define NB_REGS 526#define NB_REGS 6
27#define NB_ASM_REGS 827#define NB_ASM_REGS 8
28 28
29/* a register can belong to several classes. The classes must be29/* a register can belong to several classes. The classes must be
@@ -39,10 +39,12 @@ · 9 unmodified lines
39#define RC_R10 0x040039#define RC_R10 0x0400
40#define RC_R11 0x080040#define RC_R11 0x0800
41#define RC_XMM0 0x002041#define RC_XMM0 0x0020
42#define RC_ST0 0x0040 /* only for long double */42#define RC_XMM1 0x0040
43#define RC_ST0 0x0080 /* only for long double */
43#define RC_IRET RC_RAX /* function return: integer register */44#define RC_IRET RC_RAX /* function return: integer register */
44#define RC_LRET RC_RDX /* function return: second integer register */45#define RC_LRET RC_RDX /* function return: second integer register */
45#define RC_FRET RC_XMM0 /* function return: float register */46#define RC_FRET RC_XMM0 /* function return: float register */
47#define RC_QRET RC_XMM1 /* function return: second float register */
46 48
47/* pretty names for the registers */49/* pretty names for the registers */
48enum {50enum {
@@ -50,7 +52,8 @@ enum { · 1 unmodified line
50 TREG_RCX = 1,52 TREG_RCX = 1,
51 TREG_RDX = 2,53 TREG_RDX = 2,
52 TREG_XMM0 = 3,54 TREG_XMM0 = 3,
53 TREG_ST0 = 4,55 TREG_XMM1 = 4,
56 TREG_ST0 = 5,
54 57
55 TREG_RSI = 6,58 TREG_RSI = 6,
56 TREG_RDI = 7,59 TREG_RDI = 7,
@@ -70,6 +73,7 @@ enum { · 13 unmodified lines
70#define REG_IRET TREG_RAX /* single word int return register */73#define REG_IRET TREG_RAX /* single word int return register */
71#define REG_LRET TREG_RDX /* second word return register (for long long) */74#define REG_LRET TREG_RDX /* second word return register (for long long) */
72#define REG_FRET TREG_XMM0 /* float return register */75#define REG_FRET TREG_XMM0 /* float return register */
76#define REG_QRET TREG_XMM1 /* second float return register */
73 77
74/* defined if function parameters must be evaluated in reverse order */78/* defined if function parameters must be evaluated in reverse order */
75#define INVERT_FUNC_PARAMS79#define INVERT_FUNC_PARAMS
@@ -108,6 +112,7 @@ ST_DATA const int reg_classes[NB_REGS+7] = { · 32 unmodified lines
108 /* ecx */ RC_INT | RC_RCX,112 /* ecx */ RC_INT | RC_RCX,
109 /* edx */ RC_INT | RC_RDX,113 /* edx */ RC_INT | RC_RDX,
110 /* xmm0 */ RC_FLOAT | RC_XMM0,114 /* xmm0 */ RC_FLOAT | RC_XMM0,
115 /* xmm1 */ RC_FLOAT | RC_XMM1,
111 /* st0 */ RC_ST0,116 /* st0 */ RC_ST0,
112 0,117 0,
113 0,118 0,
@@ -375,7 +380,8 @@ void load(int r, SValue *sv) · 261 unmodified lines
375 if ((ft & VT_BTYPE) == VT_FLOAT) {380 if ((ft & VT_BTYPE) == VT_FLOAT) {
376 b = 0x6e0f66, r = 0; /* movd */381 b = 0x6e0f66, r = 0; /* movd */
377 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {382 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
378 b = 0x7e0ff3, r = 0; /* movq */383 b = 0x7e0ff3; /* movq */
384 r -= TREG_XMM0;
379 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {385 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
380 b = 0xdb, r = 5; /* fldt */386 b = 0xdb, r = 5; /* fldt */
381 } else if ((ft & VT_TYPE) == VT_BYTE) {387 } else if ((ft & VT_TYPE) == VT_BYTE) {
@@ -387,6 +393,9 @@ void load(int r, SValue *sv) · 5 unmodified lines
387 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {393 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
388 b = 0xb70f; /* movzwl */394 b = 0xb70f; /* movzwl */
389 } else {395 } else {
396 assert(((ft & VT_BTYPE) == VT_INT) || ((ft & VT_BTYPE) == VT_LLONG)
397 || ((ft & VT_BTYPE) == VT_PTR) || ((ft & VT_BTYPE) == VT_ENUM)
398 || ((ft & VT_BTYPE) == VT_FUNC));
390 ll = is64_type(ft);399 ll = is64_type(ft);
391 b = 0x8b;400 b = 0x8b;
392 }401 }
@@ -450,18 +459,30 @@ void load(int r, SValue *sv) · 57 unmodified lines
450 orex(0,r,0,0);459 orex(0,r,0,0);
451 oad(0xb8 + REG_VALUE(r), t ^ 1); /* mov $0, r */460 oad(0xb8 + REG_VALUE(r), t ^ 1); /* mov $0, r */
452 } else if (v != r) {461 } else if (v != r) {
453 if (r == TREG_XMM0) {462 if ((r == TREG_XMM0) || (r == TREG_XMM1)) {
454 assert(v == TREG_ST0);463 if (v == TREG_ST0) {
455 /* gen_cvt_ftof(VT_DOUBLE); */464 /* gen_cvt_ftof(VT_DOUBLE); */
456 o(0xf0245cdd); /* fstpl -0x10(%rsp) */465 o(0xf0245cdd); /* fstpl -0x10(%rsp) */
457 /* movsd -0x10(%rsp),%xmm0 */466 /* movsd -0x10(%rsp),%xmmN */
458 o(0x44100ff2);467 o(0x100ff2);
459 o(0xf024);468 o(0x44 + ((r - TREG_XMM0) << 3)); /* %xmmN */
469 o(0xf024);
470 } else {
471 assert((v == TREG_XMM0) || (v == TREG_XMM1));
472 if ((ft & VT_BTYPE) == VT_FLOAT) {
473 o(0x100ff3);
474 } else {
475 assert((ft & VT_BTYPE) == VT_DOUBLE);
476 o(0x100ff2);
477 }
478 o(0xc0 + (v - TREG_XMM0) + ((r - TREG_XMM0) << 3));
479 }
460 } else if (r == TREG_ST0) {480 } else if (r == TREG_ST0) {
461 assert(v == TREG_XMM0);481 assert((v == TREG_XMM0) || (v == TREG_XMM1));
462 /* gen_cvt_ftof(VT_LDOUBLE); */482 /* gen_cvt_ftof(VT_LDOUBLE); */
463 /* movsd %xmm0,-0x10(%rsp) */483 /* movsd %xmm0,-0x10(%rsp) */
464 o(0x44110ff2);484 o(0x110ff2);
485 o(0x44 + ((r - TREG_XMM0) << 3)); /* %xmmN */
465 o(0xf024);486 o(0xf024);
466 o(0xf02444dd); /* fldl -0x10(%rsp) */487 o(0xf02444dd); /* fldl -0x10(%rsp) */
467 } else {488 } else {
@@ -510,7 +531,7 @@ void store(int r, SValue *v) · 42 unmodified lines
510 o(0x66);531 o(0x66);
511 o(pic);532 o(pic);
512 o(0xd60f); /* movq */533 o(0xd60f); /* movq */
513 r = 0;534 r -= TREG_XMM0;
514 } else if (bt == VT_LDOUBLE) {535 } else if (bt == VT_LDOUBLE) {
515 o(0xc0d9); /* fld %st(0) */536 o(0xc0d9); /* fld %st(0) */
516 o(pic);537 o(pic);
@@ -679,7 +700,7 @@ void gfunc_call(int nb_args) · 162 unmodified lines
679 struct_size += size;700 struct_size += size;
680 701
681 } else if (is_sse_float(vtop->type.t)) {702 } else if (is_sse_float(vtop->type.t)) {
682 gv(RC_FLOAT); /* only one float register */703 gv(RC_XMM0); /* only one float register */
683 j = --gen_reg;704 j = --gen_reg;
684 if (j >= REGN) {705 if (j >= REGN) {
685 /* movq %xmm0, j*8(%rsp) */706 /* movq %xmm0, j*8(%rsp) */
@@ -861,6 +882,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { · 175 unmodified lines
861 case VT_LLONG:882 case VT_LLONG:
862 case VT_BOOL:883 case VT_BOOL:
863 case VT_PTR:884 case VT_PTR:
885 case VT_FUNC:
864 case VT_ENUM: return x86_64_mode_integer;886 case VT_ENUM: return x86_64_mode_integer;
865 887
866 case VT_FLOAT:888 case VT_FLOAT:
@@ -881,6 +903,8 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { · 14 unmodified lines
881 903
882 return mode;904 return mode;
883 }905 }
906
907 assert(0);
884}908}
885 909
886static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *reg_count) {910static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *reg_count) {
@@ -963,6 +987,14 @@ static const uint8_t arg_regs[REGN] = { · 76 unmodified lines
963 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9987 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
964};988};
965 989
990static int arg_prepare_reg(int idx) {
991 if (idx == 2 || idx == 3)
992 /* idx=2: r10, idx=3: r11 */
993 return idx + 8;
994 else
995 return arg_regs[idx];
996}
997
966/* Generate function call. The function address is pushed first, then998/* Generate function call. The function address is pushed first, then
967 all the parameters in call order. This functions pops all the999 all the parameters in call order. This functions pops all the
968 parameters and the function address. */1000 parameters and the function address. */
@@ -1051,7 +1083,7 @@ void gfunc_call(int nb_args) · 82 unmodified lines
1051 1083
1052 case x86_64_mode_sse:1084 case x86_64_mode_sse:
1053 if (sse_reg > 8) {1085 if (sse_reg > 8) {
1054 gv(RC_FLOAT);1086 gv(RC_XMM0);
1055 o(0x50); /* push $rax */1087 o(0x50); /* push $rax */
1056 /* movq %xmm0, (%rsp) */1088 /* movq %xmm0, (%rsp) */
1057 o(0x04d60f66);1089 o(0x04d60f66);
@@ -1097,15 +1129,18 @@ void gfunc_call(int nb_args) · 39 unmodified lines
1097 break;1129 break;
1098 1130
1099 case x86_64_mode_sse:1131 case x86_64_mode_sse:
1100 if (sse_reg > 8) {1132 sse_reg -= reg_count;
1101 sse_reg -= reg_count;1133 if (sse_reg + reg_count <= 8) {
1102 } else {1134 gv(RC_XMM0); /* only one float register */
1103 for (j = 0; j < reg_count; ++j) {1135 if (sse_reg) { /* avoid redundant movaps %xmm0, %xmm0 */
1104 --sse_reg;
1105 gv(RC_FLOAT); /* only one float register */
1106 /* movaps %xmm0, %xmmN */1136 /* movaps %xmm0, %xmmN */
1107 o(0x280f);1137 o(0x280f);
1108 o(0xc0 + (sse_reg << 3));1138 o(0xc0 + (sse_reg << 3));
1139 if (reg_count == 2) {
1140 /* movaps %xmm1, %xmmN */
1141 o(0x280f);
1142 o(0xc1 + ((sse_reg+1) << 3));
1143 }
1109 }1144 }
1110 }1145 }
1111 break;1146 break;
@@ -1113,16 +1148,17 @@ void gfunc_call(int nb_args) · 1 unmodified line
1113 case x86_64_mode_integer:1148 case x86_64_mode_integer:
1114 /* simple type */1149 /* simple type */
1115 /* XXX: implicit cast ? */1150 /* XXX: implicit cast ? */
1116 if (gen_reg > 8) {1151 gen_reg -= reg_count;
1117 gen_reg -= reg_count;1152 if (gen_reg + reg_count <= REGN) {
1118 } else {1153 r = gv((reg_count == 1) ? RC_INT : RC_IRET);
1119 for (j = 0; j < reg_count; ++j) {1154 int d = arg_prepare_reg(gen_reg);
1120 --gen_reg;1155 orex(1,d,r,0x89); /* mov */
1121 int d = arg_regs[gen_reg];1156 o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
1122 r = gv(RC_INT);1157 if (reg_count == 2) {
1123 if (gen_reg == 2 || gen_reg == 3)1158 /* Second word of two-word value should always be in rdx
1124 /* gen_reg=2: r10, gen_reg=3: r11 */1159 this case is handled via RC_IRET */
1125 d = gen_reg + 8;1160 r = TREG_RDX;
1161 d = arg_prepare_reg(gen_reg+1);
1126 orex(1,d,r,0x89); /* mov */1162 orex(1,d,r,0x89); /* mov */
1127 o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));1163 o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
1128 }1164 }
@@ -1263,13 +1299,13 @@ void gfunc_prolog(CType *func_type) · 134 unmodified lines
1263 case x86_64_mode_sse:1299 case x86_64_mode_sse:
1264 if (sse_param_index + reg_count <= 8) {1300 if (sse_param_index + reg_count <= 8) {
1265 /* save arguments passed by register */1301 /* save arguments passed by register */
1302 loc -= reg_count * 8;
1303 param_addr = loc;
1266 for (i = 0; i < reg_count; ++i) {1304 for (i = 0; i < reg_count; ++i) {
1267 loc -= 8;
1268 o(0xd60f66); /* movq */1305 o(0xd60f66); /* movq */
1269 gen_modrm(sse_param_index, VT_LOCAL, NULL, loc);1306 gen_modrm(sse_param_index, VT_LOCAL, NULL, param_addr + i*8);
1270 ++sse_param_index;1307 ++sse_param_index;
1271 }1308 }
1272 param_addr = loc;
1273 } else {1309 } else {
1274 param_addr = addr;1310 param_addr = addr;
1275 addr += size;1311 addr += size;
@@ -1286,11 +1322,12 @@ void gfunc_prolog(CType *func_type) · 10 unmodified lines
1286 case x86_64_mode_integer: {1322 case x86_64_mode_integer: {
1287 if (reg_param_index + reg_count <= REGN) {1323 if (reg_param_index + reg_count <= REGN) {
1288 /* save arguments passed by register */1324 /* save arguments passed by register */
1325 loc -= reg_count * 8;
1326 param_addr = loc;
1289 for (i = 0; i < reg_count; ++i) {1327 for (i = 0; i < reg_count; ++i) {
1290 push_arg_reg(reg_param_index);1328 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, param_addr + i*8);
1291 ++reg_param_index;1329 ++reg_param_index;
1292 }1330 }
1293 param_addr = loc;
1294 } else {1331 } else {
1295 param_addr = addr;1332 param_addr = addr;
1296 addr += size;1333 addr += size;
@@ -1547,12 +1584,12 @@ void gen_opl(int op) · 250 unmodified lines
1547 1584
1548/* generate a floating point operation 'v = t1 op t2' instruction. The1585/* generate a floating point operation 'v = t1 op t2' instruction. The
1549 two operands are guaranted to have the same floating point type */1586 two operands are guaranted to have the same floating point type */
1550/* XXX: need to use ST1 too */1587/* XXX: need to use ST1 and XMM1 too */
1551void gen_opf(int op)1588void gen_opf(int op)
1552{1589{
1553 int a, ft, fc, swapped, r;1590 int a, ft, fc, swapped, r;
1554 int float_type =1591 int float_type =
1555 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE ? RC_ST0 : RC_FLOAT;1592 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE ? RC_ST0 : RC_XMM0; /* to avoid xmm1 handling for now */
1556 1593
1557 /* convert constants to memory references */1594 /* convert constants to memory references */
1558 if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {1595 if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
@@ -1803,9 +1840,9 @@ void gen_cvt_ftof(int t) · 244 unmodified lines
1803 ft = vtop->type.t;1840 ft = vtop->type.t;
1804 bt = ft & VT_BTYPE;1841 bt = ft & VT_BTYPE;
1805 tbt = t & VT_BTYPE;1842 tbt = t & VT_BTYPE;
1806 1843
1807 if (bt == VT_FLOAT) {1844 if (bt == VT_FLOAT) {
1808 gv(RC_FLOAT);1845 gv(RC_XMM0); /* to avoid rewriting to handle xmm1 for now */
1809 if (tbt == VT_DOUBLE) {1846 if (tbt == VT_DOUBLE) {
1810 o(0xc0140f); /* unpcklps */1847 o(0xc0140f); /* unpcklps */
1811 o(0xc05a0f); /* cvtps2pd */1848 o(0xc05a0f); /* cvtps2pd */
@@ -1817,7 +1854,7 @@ void gen_cvt_ftof(int t) · 5 unmodified lines
1817 vtop->r = TREG_ST0;1854 vtop->r = TREG_ST0;
1818 }1855 }
1819 } else if (bt == VT_DOUBLE) {1856 } else if (bt == VT_DOUBLE) {
1820 gv(RC_FLOAT);1857 gv(RC_XMM0); /* to avoid rewriting to handle xmm1 for now */
1821 if (tbt == VT_FLOAT) {1858 if (tbt == VT_FLOAT) {
1822 o(0xc0140f66); /* unpcklpd */1859 o(0xc0140f66); /* unpcklpd */
1823 o(0xc05a0f66); /* cvtpd2ps */1860 o(0xc05a0f66); /* cvtpd2ps */
@@ -1857,7 +1894,7 @@ void gen_cvt_ftoi(int t) · 33 unmodified lines
1857 bt = VT_DOUBLE;1894 bt = VT_DOUBLE;
1858 }1895 }
1859 1896
1860 gv(RC_FLOAT);1897 gv(RC_XMM0);
1861 if (t != VT_INT)1898 if (t != VT_INT)
1862 size = 8;1899 size = 8;
1863 else1900 else