x86_64: Add support for complex types

This commit is contained in:
Richard Henderson
2014-10-28 11:21:50 -07:00
parent 32c5683163
commit 610c90bf71
3 changed files with 121 additions and 43 deletions

View File

@@ -171,6 +171,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
case FFI_TYPE_UINT64: case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64: case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER: case FFI_TYPE_POINTER:
do_integer:
{ {
size_t size = byte_offset + type->size; size_t size = byte_offset + type->size;
@@ -301,11 +302,42 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
} }
return words; return words;
} }
case FFI_TYPE_COMPLEX:
{
ffi_type *inner = type->elements[0];
switch (inner->type)
{
case FFI_TYPE_INT:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
goto do_integer;
default: case FFI_TYPE_FLOAT:
FFI_ASSERT(0); classes[0] = X86_64_SSE_CLASS;
if (byte_offset % 8)
{
classes[1] = X86_64_SSESF_CLASS;
return 2;
}
return 1;
case FFI_TYPE_DOUBLE:
classes[0] = classes[1] = X86_64_SSEDF_CLASS;
return 2;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
classes[0] = X86_64_COMPLEX_X87_CLASS;
return 1;
#endif
}
}
} }
return 0; /* Never reached. */ abort();
} }
/* Examine the argument and return set number of register required in each /* Examine the argument and return set number of register required in each
@@ -360,7 +392,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
{ {
int gprcount, ssecount, i, avn, ngpr, nsse, flags; int gprcount, ssecount, i, avn, ngpr, nsse, flags;
enum x86_64_reg_class classes[MAX_CLASSES]; enum x86_64_reg_class classes[MAX_CLASSES];
size_t bytes, n; size_t bytes, n, rtype_size;
ffi_type *rtype; ffi_type *rtype;
if (cif->abi != FFI_UNIX64) if (cif->abi != FFI_UNIX64)
@@ -369,6 +401,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
gprcount = ssecount = 0; gprcount = ssecount = 0;
rtype = cif->rtype; rtype = cif->rtype;
rtype_size = rtype->size;
switch (rtype->type) switch (rtype->type)
{ {
case FFI_TYPE_VOID: case FFI_TYPE_VOID:
@@ -421,16 +454,54 @@ ffi_prep_cif_machdep (ffi_cif *cif)
} }
else else
{ {
/* Mark which registers the result appears in. */
_Bool sse0 = SSE_CLASS_P (classes[0]); _Bool sse0 = SSE_CLASS_P (classes[0]);
_Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
if (sse0)
flags = (sse1 ? UNIX64_RET_ST_XMM0_XMM1 : UNIX64_RET_ST_XMM0_RAX);
else
flags = (sse1 ? UNIX64_RET_ST_RAX_XMM0 : UNIX64_RET_ST_RAX_RDX);
/* Mark the true size of the structure. */ if (rtype_size == 4 && sse0)
flags |= rtype->size << UNIX64_SIZE_SHIFT; flags = UNIX64_RET_XMM32;
else if (rtype_size == 8)
flags = sse0 ? UNIX64_RET_XMM64 : UNIX64_RET_INT64;
else
{
_Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
if (sse0 && sse1)
flags = UNIX64_RET_ST_XMM0_XMM1;
else if (sse0)
flags = UNIX64_RET_ST_XMM0_RAX;
else if (sse1)
flags = UNIX64_RET_ST_RAX_XMM0;
else
flags = UNIX64_RET_ST_RAX_RDX;
flags |= rtype_size << UNIX64_SIZE_SHIFT;
}
}
break;
case FFI_TYPE_COMPLEX:
switch (rtype->elements[0]->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
flags = UNIX64_RET_ST_RAX_RDX | (rtype_size << UNIX64_SIZE_SHIFT);
break;
case FFI_TYPE_FLOAT:
flags = UNIX64_RET_XMM64;
break;
case FFI_TYPE_DOUBLE:
flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT);
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
flags = UNIX64_RET_X87_2;
break;
#endif
default:
return FFI_BAD_TYPEDEF;
} }
break; break;
default: default:

View File

@@ -9,11 +9,13 @@
#define UNIX64_RET_XMM32 8 #define UNIX64_RET_XMM32 8
#define UNIX64_RET_XMM64 9 #define UNIX64_RET_XMM64 9
#define UNIX64_RET_X87 10 #define UNIX64_RET_X87 10
#define UNIX64_RET_ST_RAX_RDX 11 #define UNIX64_RET_X87_2 11
#define UNIX64_RET_ST_XMM0_RAX 12 #define UNIX64_RET_ST_XMM0_RAX 12
#define UNIX64_RET_ST_RAX_XMM0 13 #define UNIX64_RET_ST_RAX_XMM0 13
#define UNIX64_RET_ST_XMM0_XMM1 14 #define UNIX64_RET_ST_XMM0_XMM1 14
#define UNIX64_RET_LAST 14 #define UNIX64_RET_ST_RAX_RDX 15
#define UNIX64_RET_LAST 15
#define UNIX64_FLAG_RET_IN_MEM (1 << 10) #define UNIX64_FLAG_RET_IN_MEM (1 << 10)
#define UNIX64_FLAG_XMM_ARGS (1 << 11) #define UNIX64_FLAG_XMM_ARGS (1 << 11)

View File

@@ -156,9 +156,10 @@ E UNIX64_RET_XMM64
E UNIX64_RET_X87 E UNIX64_RET_X87
fstpt (%rdi) fstpt (%rdi)
ret ret
E UNIX64_RET_ST_RAX_RDX E UNIX64_RET_X87_2
movq %rdx, 8(%rsi) fstpt (%rdi)
jmp 2f fstpt 16(%rdi)
ret
E UNIX64_RET_ST_XMM0_RAX E UNIX64_RET_ST_XMM0_RAX
movq %rax, 8(%rsi) movq %rax, 8(%rsi)
jmp 3f jmp 3f
@@ -167,14 +168,15 @@ E UNIX64_RET_ST_RAX_XMM0
jmp 2f jmp 2f
E UNIX64_RET_ST_XMM0_XMM1 E UNIX64_RET_ST_XMM0_XMM1
movq %xmm1, 8(%rsi) movq %xmm1, 8(%rsi)
jmp 3f
.align 8 E UNIX64_RET_ST_RAX_RDX
3: movq %xmm0, (%rsi) movq %rdx, 8(%rsi)
2: movq %rax, (%rsi)
shrl $UNIX64_SIZE_SHIFT, %ecx shrl $UNIX64_SIZE_SHIFT, %ecx
rep movsb rep movsb
ret ret
.align 8 .align 8
2: movq %rax, (%rsi) 3: movq %xmm0, (%rsi)
shrl $UNIX64_SIZE_SHIFT, %ecx shrl $UNIX64_SIZE_SHIFT, %ecx
rep movsb rep movsb
ret ret
@@ -201,11 +203,11 @@ E UNIX64_RET_ST_XMM0_XMM1
.size ffi_call_unix64,.-ffi_call_unix64 .size ffi_call_unix64,.-ffi_call_unix64
/* 6 general registers, 8 vector registers, /* 6 general registers, 8 vector registers,
16 bytes of rvalue, 8 bytes of alignment. */ 32 bytes of rvalue, 8 bytes of alignment. */
#define ffi_closure_OFS_G 0 #define ffi_closure_OFS_G 0
#define ffi_closure_OFS_V (6*8) #define ffi_closure_OFS_V (6*8)
#define ffi_closure_OFS_RVALUE (ffi_closure_OFS_V + 8*16) #define ffi_closure_OFS_RVALUE (ffi_closure_OFS_V + 8*16)
#define ffi_closure_FS (ffi_closure_OFS_RVALUE + 16 + 8) #define ffi_closure_FS (ffi_closure_OFS_RVALUE + 32 + 8)
/* The location of rvalue within the red zone after deallocating the frame. */ /* The location of rvalue within the red zone after deallocating the frame. */
#define ffi_closure_RED_RVALUE (ffi_closure_OFS_RVALUE - ffi_closure_FS) #define ffi_closure_RED_RVALUE (ffi_closure_OFS_RVALUE - ffi_closure_FS)
@@ -275,6 +277,7 @@ ffi_closure_unix64:
leaq 0f(%rip), %r11 leaq 0f(%rip), %r11
ja 9f ja 9f
leaq (%r11, %r10, 8), %r10 leaq (%r11, %r10, 8), %r10
leaq ffi_closure_RED_RVALUE(%rsp), %rsi
jmp *%r10 jmp *%r10
.align 8 .align 8
@@ -282,52 +285,54 @@ ffi_closure_unix64:
E UNIX64_RET_VOID E UNIX64_RET_VOID
ret ret
E UNIX64_RET_UINT8 E UNIX64_RET_UINT8
movzbl ffi_closure_RED_RVALUE(%rsp), %eax movzbl (%rsi), %eax
ret ret
E UNIX64_RET_UINT16 E UNIX64_RET_UINT16
movzwl ffi_closure_RED_RVALUE(%rsp), %eax movzwl (%rsi), %eax
ret ret
E UNIX64_RET_UINT32 E UNIX64_RET_UINT32
movl ffi_closure_RED_RVALUE(%rsp), %eax movl (%rsi), %eax
ret ret
E UNIX64_RET_SINT8 E UNIX64_RET_SINT8
movsbl ffi_closure_RED_RVALUE(%rsp), %eax movsbl (%rsi), %eax
ret ret
E UNIX64_RET_SINT16 E UNIX64_RET_SINT16
movswl ffi_closure_RED_RVALUE(%rsp), %eax movswl (%rsi), %eax
ret ret
E UNIX64_RET_SINT32 E UNIX64_RET_SINT32
movl ffi_closure_RED_RVALUE(%rsp), %eax movl (%rsi), %eax
ret ret
E UNIX64_RET_INT64 E UNIX64_RET_INT64
movq ffi_closure_RED_RVALUE(%rsp), %rax movq (%rsi), %rax
ret ret
E UNIX64_RET_XMM32 E UNIX64_RET_XMM32
movd ffi_closure_RED_RVALUE(%rsp), %xmm0 movd (%rsi), %xmm0
ret ret
E UNIX64_RET_XMM64 E UNIX64_RET_XMM64
movq ffi_closure_RED_RVALUE(%rsp), %xmm0 movq (%rsi), %xmm0
ret ret
E UNIX64_RET_X87 E UNIX64_RET_X87
fldt ffi_closure_RED_RVALUE(%rsp) fldt (%rsi)
ret
E UNIX64_RET_X87_2
fldt 16(%rsi)
fldt (%rsi)
ret ret
E UNIX64_RET_ST_RAX_RDX
movq ffi_closure_RED_RVALUE+8(%rsp), %rdx
jmp 2f
E UNIX64_RET_ST_XMM0_RAX E UNIX64_RET_ST_XMM0_RAX
movq ffi_closure_RED_RVALUE+8(%rsp), %rax movq 8(%rsi), %rax
jmp 3f jmp 3f
E UNIX64_RET_ST_RAX_XMM0 E UNIX64_RET_ST_RAX_XMM0
movq ffi_closure_RED_RVALUE+8(%rsp), %xmm0 movq 8(%rsi), %xmm0
jmp 2f jmp 2f
E UNIX64_RET_ST_XMM0_XMM1 E UNIX64_RET_ST_XMM0_XMM1
movq ffi_closure_RED_RVALUE+8(%rsp), %xmm1 movq 8(%rsi), %xmm1
jmp 3f
.align 8 E UNIX64_RET_ST_RAX_RDX
3: movq ffi_closure_RED_RVALUE(%rsp), %xmm0 movq 8(%rsi), %rdx
2: movq (%rsi), %rax
ret ret
.align 8 .align 8
2: movq ffi_closure_RED_RVALUE(%rsp), %rax 3: movq (%rsi), %xmm0
ret ret
9: call abort@PLT 9: call abort@PLT