//
// Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 2 only, as
// published by the Free Software Foundation.
//
// This code is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// version 2 for more details (a copy is included in the LICENSE file that
// accompanied this code).
//
// You should have received a copy of the GNU General Public License version
// 2 along with this work; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
// or visit www.oracle.com if you need additional information or have any
// questions.
//

	.globl fixcw
	.globl sse_check
	.globl sse_unavailable
	.globl gs_load
	.globl gs_thread
        .globl _Atomic_cmpxchg_long_gcc

        // NOTE WELL!  The _Copy functions are called directly
	// from server-compiler-generated code via CallLeafNoFP,
	// which means that they *must* either not use floating
	// point or use it in the same manner as does the server
	// compiler.

        .globl _Copy_conjoint_bytes
        .globl _Copy_arrayof_conjoint_bytes
        .globl _Copy_conjoint_jshorts_atomic
	.globl _Copy_arrayof_conjoint_jshorts
        .globl _Copy_conjoint_jints_atomic
        .globl _Copy_arrayof_conjoint_jints
	.globl _Copy_conjoint_jlongs_atomic
        .globl _mmx_Copy_arrayof_conjoint_jshorts

	.section .text,"ax"

/ Support for void os::Solaris::init_thread_fpu_state() in os_solaris_i486.cpp
/ Set fpu to 53 bit precision.  This happens too early to use a stub.
	.align   16
fixcw:
	pushl    $0x27f
	fldcw    0(%esp)
	popl     %eax
	ret

       .align  16
       .globl  SafeFetch32
       .globl  SafeFetchN
       .globl  Fetch32PFI, Fetch32Resume
SafeFetch32:
SafeFetchN:
        movl    0x8(%esp), %eax
        movl    0x4(%esp), %ecx
Fetch32PFI:
        movl    (%ecx), %eax
Fetch32Resume:
        ret


        .align  16
        .globl  SpinPause
SpinPause:
        rep 
        nop
        movl    $1, %eax
        ret


/ Test SSE availability, used by os_solaris_i486.cpp
	.align   16
sse_check:
	/ Fault if SSE not available
	xorps %xmm0,%xmm0
	/ No fault
	movl $1,%eax
	ret
	/ Signal handler continues here if SSE is not available
sse_unavailable:
	xorl %eax,%eax
	ret

/ Fast thread accessors, used by threadLS_solaris_i486.cpp
	.align   16
gs_load:
	movl 4(%esp),%ecx
	movl %gs:(%ecx),%eax
	ret

	.align   16
gs_thread:
	movl %gs:0x0,%eax
	ret

        / Support for void Copy::conjoint_bytes(void* from,
        /                                       void* to,
        /                                       size_t count)
        .align   16
_Copy_conjoint_bytes:
        pushl    %esi
        movl     4+12(%esp),%ecx      / count
        pushl    %edi
        movl     8+ 4(%esp),%esi      / from
        movl     8+ 8(%esp),%edi      / to
        cmpl     %esi,%edi
        leal     -1(%esi,%ecx),%eax   / from + count - 1
        jbe      cb_CopyRight
        cmpl     %eax,%edi
        jbe      cb_CopyLeft
        / copy from low to high
cb_CopyRight:
        cmpl     $3,%ecx
        jbe      5f                   / <= 3 bytes
        / align source address at dword address boundary
        movl     %ecx,%eax            / original count
        movl     $4,%ecx
        subl     %esi,%ecx
        andl     $3,%ecx              / prefix byte count
        jz       1f                   / no prefix
        subl     %ecx,%eax            / byte count less prefix
        / copy prefix
        subl     %esi,%edi
0:      movb     (%esi),%dl
        movb     %dl,(%edi,%esi,1)
        addl     $1,%esi
        subl     $1,%ecx
        jnz      0b
        addl     %esi,%edi
1:      movl     %eax,%ecx            / byte count less prefix
        shrl     $2,%ecx              / dword count
        jz       4f                   / no dwords to move
        cmpl     $32,%ecx
        jbe      2f                   / <= 32 dwords
        / copy aligned dwords
        rep;     smovl
        jmp      4f
        / copy aligned dwords
2:      subl     %esi,%edi
        .align   16
3:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        addl     $4,%esi
        subl     $1,%ecx
        jnz      3b
        addl     %esi,%edi
4:      movl     %eax,%ecx            / byte count less prefix
5:      andl     $3,%ecx              / suffix byte count
        jz       7f                   / no suffix
        / copy suffix
        xorl     %eax,%eax
6:      movb     (%esi,%eax,1),%dl
        movb     %dl,(%edi,%eax,1)
        addl     $1,%eax
        subl     $1,%ecx
        jnz      6b
7:      popl     %edi
        popl     %esi
        ret
        / copy from high to low
cb_CopyLeft:
        std
        leal     -4(%edi,%ecx),%edi   / to + count - 4
        movl     %eax,%esi            / from + count - 1
        movl     %ecx,%eax
        subl     $3,%esi              / from + count - 4
        cmpl     $3,%ecx
        jbe      5f                   / <= 3 bytes
1:      shrl     $2,%ecx              / dword count
        jz       4f                   / no dwords to move
        cmpl     $32,%ecx
        ja       3f                   / > 32 dwords
        / copy dwords, aligned or not
        subl     %esi,%edi
        .align   16
2:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        subl     $4,%esi
        subl     $1,%ecx
        jnz      2b
        addl     %esi,%edi
        jmp      4f
        / copy dwords, aligned or not
3:      rep;     smovl
4:      movl     %eax,%ecx            / byte count
5:      andl     $3,%ecx              / suffix byte count
        jz       7f                   / no suffix
        / copy suffix
        subl     %esi,%edi
        addl     $3,%esi
6:      movb     (%esi),%dl
        movb     %dl,(%edi,%esi,1)
	subl     $1,%esi
        subl     $1,%ecx
        jnz      6b
7:      cld
        popl     %edi
        popl     %esi
        ret

        / Support for void Copy::arrayof_conjoint_bytes(void* from,
        /                                               void* to,
        /                                               size_t count)
        /
        / Same as _Copy_conjoint_bytes, except no source alignment check.
        .align   16
_Copy_arrayof_conjoint_bytes:
        pushl    %esi
        movl     4+12(%esp),%ecx      / count
        pushl    %edi
        movl     8+ 4(%esp),%esi      / from
        movl     8+ 8(%esp),%edi      / to
        cmpl     %esi,%edi
        leal     -1(%esi,%ecx),%eax   / from + count - 1
        jbe      acb_CopyRight
        cmpl     %eax,%edi
        jbe      acb_CopyLeft 
        / copy from low to high
acb_CopyRight:
        cmpl     $3,%ecx
        jbe      5f
1:      movl     %ecx,%eax
        shrl     $2,%ecx
        jz       4f
        cmpl     $32,%ecx
        ja       3f
        / copy aligned dwords
        subl     %esi,%edi
        .align   16
2:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        addl     $4,%esi
        subl     $1,%ecx
        jnz      2b
        addl     %esi,%edi
        jmp      4f
        / copy aligned dwords
3:      rep;     smovl
4:      movl     %eax,%ecx
5:      andl     $3,%ecx
        jz       7f
        / copy suffix
        xorl     %eax,%eax
6:      movb     (%esi,%eax,1),%dl
        movb     %dl,(%edi,%eax,1)
        addl     $1,%eax
        subl     $1,%ecx
        jnz      6b
7:      popl     %edi
        popl     %esi
        ret
acb_CopyLeft:
        std
        leal     -4(%edi,%ecx),%edi   / to + count - 4
        movl     %eax,%esi            / from + count - 1
        movl     %ecx,%eax
        subl     $3,%esi              / from + count - 4
        cmpl     $3,%ecx
        jbe      5f
1:      shrl     $2,%ecx
        jz       4f
        cmpl     $32,%ecx
        jbe      2f                   / <= 32 dwords
        rep;     smovl
        jmp      4f
	.=.+8
2:      subl     %esi,%edi
        .align   16
3:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        subl     $4,%esi
        subl     $1,%ecx
        jnz      3b
        addl     %esi,%edi
4:      movl     %eax,%ecx
5:      andl     $3,%ecx
        jz       7f
        subl     %esi,%edi
        addl     $3,%esi
6:      movb     (%esi),%dl
        movb     %dl,(%edi,%esi,1)
	subl     $1,%esi
        subl     $1,%ecx
        jnz      6b
7:      cld
        popl     %edi
        popl     %esi
        ret

        / Support for void Copy::conjoint_jshorts_atomic(void* from,
        /                                                void* to,
        /                                                size_t count)
        .align   16
_Copy_conjoint_jshorts_atomic:
        pushl    %esi
        movl     4+12(%esp),%ecx      / count
        pushl    %edi
        movl     8+ 4(%esp),%esi      / from
        movl     8+ 8(%esp),%edi      / to
        cmpl     %esi,%edi
        leal     -2(%esi,%ecx,2),%eax / from + count*2 - 2
        jbe      cs_CopyRight
        cmpl     %eax,%edi
        jbe      cs_CopyLeft 
        / copy from low to high
cs_CopyRight:
        / align source address at dword address boundary
        movl     %esi,%eax            / original from
        andl     $3,%eax              / either 0 or 2
        jz       1f                   / no prefix
        / copy prefix
        subl     $1,%ecx
        jl       5f                   / zero count
        movw     (%esi),%dx
        movw     %dx,(%edi)
        addl     %eax,%esi            / %eax == 2
        addl     %eax,%edi
1:      movl     %ecx,%eax            / word count less prefix
        sarl     %ecx                 / dword count
        jz       4f                   / no dwords to move
        cmpl     $32,%ecx
        jbe      2f                   / <= 32 dwords
        / copy aligned dwords
        rep;     smovl
        jmp      4f 
        / copy aligned dwords
2:      subl     %esi,%edi
        .align   16
3:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        addl     $4,%esi
        subl     $1,%ecx
        jnz      3b
        addl     %esi,%edi
4:      andl     $1,%eax              / suffix count
        jz       5f                   / no suffix
        / copy suffix
        movw     (%esi),%dx
        movw     %dx,(%edi)
5:      popl     %edi
        popl     %esi
        ret
        / copy from high to low
cs_CopyLeft:
        std
        leal     -4(%edi,%ecx,2),%edi / to + count*2 - 4
        movl     %eax,%esi            / from + count*2 - 2
        movl     %ecx,%eax
        subl     $2,%esi              / from + count*2 - 4
1:      sarl     %ecx                 / dword count
        jz       4f                   / no dwords to move
        cmpl     $32,%ecx
        ja       3f                   / > 32 dwords
        subl     %esi,%edi
        .align   16
2:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        subl     $4,%esi
        subl     $1,%ecx
        jnz      2b
        addl     %esi,%edi
        jmp      4f
3:      rep;     smovl
4:      andl     $1,%eax              / suffix count
        jz       5f                   / no suffix
        / copy suffix
        addl     $2,%esi
        addl     $2,%edi
        movw     (%esi),%dx
        movw     %dx,(%edi)
5:      cld
        popl     %edi
        popl     %esi
        ret

        / Support for void Copy::arrayof_conjoint_jshorts(void* from,
        /                                                 void* to,
        /                                                 size_t count)
        .align   16
_Copy_arrayof_conjoint_jshorts:
        pushl    %esi
        movl     4+12(%esp),%ecx      / count
        pushl    %edi
        movl     8+ 4(%esp),%esi      / from
        movl     8+ 8(%esp),%edi      / to
        cmpl     %esi,%edi
        leal     -2(%esi,%ecx,2),%eax / from + count*2 - 2
        jbe      acs_CopyRight
        cmpl     %eax,%edi
        jbe      acs_CopyLeft 
acs_CopyRight:
        movl     %ecx,%eax            / word count
        sarl     %ecx                 / dword count
        jz       4f                   / no dwords to move
        cmpl     $32,%ecx
        jbe      2f                   / <= 32 dwords
        / copy aligned dwords
        rep;     smovl 	 
        jmp      4f 
        / copy aligned dwords
        .=.+5
2:      subl     %esi,%edi 
        .align   16	
3:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        addl     $4,%esi
        subl     $1,%ecx
        jnz      3b
        addl     %esi,%edi
4:      andl     $1,%eax              / suffix count
        jz       5f                   / no suffix
        / copy suffix
        movw     (%esi),%dx
        movw     %dx,(%edi)
5:      popl     %edi
        popl     %esi
        ret
acs_CopyLeft:
        std
        leal     -4(%edi,%ecx,2),%edi / to + count*2 - 4
        movl     %eax,%esi            / from + count*2 - 2
        movl     %ecx,%eax
        subl     $2,%esi              / from + count*2 - 4
        sarl     %ecx                 / dword count
        jz       4f                   / no dwords to move
        cmpl     $32,%ecx
        ja       3f                   / > 32 dwords
        subl     %esi,%edi
        .align   16
2:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        subl     $4,%esi
        subl     $1,%ecx
        jnz      2b
        addl     %esi,%edi
        jmp      4f
3:      rep;     smovl
4:      andl     $1,%eax              / suffix count
        jz       5f                   / no suffix
        / copy suffix
        addl     $2,%esi
        addl     $2,%edi
        movw     (%esi),%dx
        movw     %dx,(%edi)
5:      cld
        popl     %edi
        popl     %esi
        ret

        / Support for void Copy::conjoint_jints_atomic(void* from,
        /                                              void* to,
        /                                              size_t count)
        / Equivalent to
        /   arrayof_conjoint_jints
        .align   16
_Copy_conjoint_jints_atomic:
_Copy_arrayof_conjoint_jints:
        pushl    %esi
        movl     4+12(%esp),%ecx      / count
        pushl    %edi
        movl     8+ 4(%esp),%esi      / from
        movl     8+ 8(%esp),%edi      / to
        cmpl     %esi,%edi
        leal     -4(%esi,%ecx,4),%eax / from + count*4 - 4
        jbe      ci_CopyRight
        cmpl     %eax,%edi
        jbe      ci_CopyLeft 
ci_CopyRight:
        cmpl     $32,%ecx
        jbe      2f                   / <= 32 dwords
        rep;     smovl 
        popl     %edi
        popl     %esi
        ret
        .=.+10
2:      subl     %esi,%edi
        jmp      4f
        .align   16
3:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        addl     $4,%esi
4:      subl     $1,%ecx
        jge      3b
        popl     %edi
        popl     %esi
        ret
ci_CopyLeft:
        std
        leal     -4(%edi,%ecx,4),%edi / to + count*4 - 4
        cmpl     $32,%ecx
        ja       4f                   / > 32 dwords
        subl     %eax,%edi            / eax == from + count*4 - 4
        jmp      3f
        .align   16
2:      movl     (%eax),%edx
        movl     %edx,(%edi,%eax,1)
        subl     $4,%eax
3:      subl     $1,%ecx
        jge      2b
        cld
        popl     %edi
        popl     %esi
        ret
4:      movl     %eax,%esi            / from + count*4 - 4
        rep;     smovl
        cld
        popl     %edi
        popl     %esi
        ret
	
        / Support for void Copy::conjoint_jlongs_atomic(jlong* from,
        /                                               jlong* to,
        /                                               size_t count)
        /
        / 32-bit
        /
        / count treated as signed
        /
        / if (from > to) {
        /   while (--count >= 0) {
        /     *to++ = *from++;
        /   }
        / } else {
        /   while (--count >= 0) {
        /     to[count] = from[count];
        /   }
        / }
        .align   16
_Copy_conjoint_jlongs_atomic:
        movl     4+8(%esp),%ecx       / count
        movl     4+0(%esp),%eax       / from
        movl     4+4(%esp),%edx       / to
        cmpl     %eax,%edx
        jae      cla_CopyLeft
cla_CopyRight:
        subl     %eax,%edx
        jmp      2f
        .align   16
1:      fildll   (%eax)
        fistpll  (%edx,%eax,1)
        addl     $8,%eax
2:      subl     $1,%ecx
        jge      1b
        ret
        .align   16
3:      fildll   (%eax,%ecx,8)
        fistpll  (%edx,%ecx,8)
cla_CopyLeft:
        subl     $1,%ecx
        jge      3b
        ret

        / Support for void Copy::arrayof_conjoint_jshorts(void* from,
        /                                                 void* to,
        /                                                 size_t count)
       .align   16
_mmx_Copy_arrayof_conjoint_jshorts:
        pushl    %esi
        movl     4+12(%esp),%ecx
        pushl    %edi
        movl     8+ 4(%esp),%esi
        movl     8+ 8(%esp),%edi
        cmpl     %esi,%edi
        leal     -2(%esi,%ecx,2),%eax
        jbe      mmx_acs_CopyRight
        cmpl     %eax,%edi
        jbe      mmx_acs_CopyLeft
mmx_acs_CopyRight:
        movl     %ecx,%eax
        sarl     %ecx
        je       5f
        cmpl     $33,%ecx
        jae      3f
1:      subl     %esi,%edi 
        .align   16
2:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        addl     $4,%esi
        subl     $1,%ecx
        jnz      2b
        addl     %esi,%edi
        jmp      5f 
3:      smovl / align to 8 bytes, we know we are 4 byte aligned to start
        subl     $1,%ecx
4:      .align   16
        movq     0(%esi),%mm0
        addl     $64,%edi
        movq     8(%esi),%mm1
        subl     $16,%ecx
        movq     16(%esi),%mm2
        movq     %mm0,-64(%edi)
        movq     24(%esi),%mm0
        movq     %mm1,-56(%edi)
        movq     32(%esi),%mm1
        movq     %mm2,-48(%edi)
        movq     40(%esi),%mm2
        movq     %mm0,-40(%edi)
        movq     48(%esi),%mm0
        movq     %mm1,-32(%edi)
        movq     56(%esi),%mm1
        movq     %mm2,-24(%edi)
        movq     %mm0,-16(%edi)
        addl     $64,%esi
        movq     %mm1,-8(%edi)
        cmpl     $16,%ecx
        jge      4b
        emms
	testl    %ecx,%ecx
	ja       1b
5:      andl     $1,%eax
        je       7f
6:      movw     (%esi),%dx
        movw     %dx,(%edi)
7:      popl     %edi
        popl     %esi
        ret
mmx_acs_CopyLeft:
        std
        leal     -4(%edi,%ecx,2),%edi
        movl     %eax,%esi
        movl     %ecx,%eax
        subl     $2,%esi
        sarl     %ecx
        je       4f
        cmpl     $32,%ecx
        ja       3f
        subl     %esi,%edi
        .align   16
2:      movl     (%esi),%edx
        movl     %edx,(%edi,%esi,1)
        subl     $4,%esi
        subl     $1,%ecx
        jnz      2b
        addl     %esi,%edi
        jmp      4f
3:      rep;     smovl
4:      andl     $1,%eax
        je       6f
        addl     $2,%esi
        addl     $2,%edi
5:      movw     (%esi),%dx
        movw     %dx,(%edi)
6:      cld
        popl     %edi
        popl     %esi
        ret


        / Support for jlong Atomic::cmpxchg(jlong exchange_value,
        /                                   volatile jlong* dest,
        /                                   jlong compare_value,
        /                                   bool is_MP)
        / Used only for Solaris/gcc builds
        .align 16
_Atomic_cmpxchg_long_gcc:
                                   /  8(%esp) : return PC
        pushl    %ebx              /  4(%esp) : old %ebx
        pushl    %edi              /  0(%esp) : old %edi
        movl     12(%esp), %ebx    / 12(%esp) : exchange_value (low)
        movl     16(%esp), %ecx    / 16(%esp) : exchange_value (high)
        movl     24(%esp), %eax    / 24(%esp) : compare_value (low)
        movl     28(%esp), %edx    / 28(%esp) : compare_value (high)
        movl     20(%esp), %edi    / 20(%esp) : dest
        cmpl     $0, 32(%esp)      / 32(%esp) : is_MP
        je       1f
        lock
1:      cmpxchg8b (%edi)
        popl     %edi
        popl     %ebx
        ret
