view hotspot/src/os_cpu/linux_mips/vm/atomic_linux_mips.inline.hpp @ 1:c1e1428eff7c

The preliminary porting to MIPS architecture. With this commit, the interpreter can pass 140/141 regression tests, 8/8 SPECjvm98 tests and 31/37 SPECjvm2008 tests. The compiler can pass 136/141 regression tests, but it can not run the benchmark of SPECjvm98 and SPECjvm2008.
author LIU Qi <liuqi82@gmail.com>
date Thu, 30 Sep 2010 13:48:16 +0800
parents
children
line wrap: on
line source

/*
 * Copyright 1999-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * Copyright 2010 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

// Implementation of class atomici

///////////implementation of Atomic::store*//////////////
inline void Atomic::store     (jbyte    store_value, jbyte*    dest) { *dest = store_value; }
inline void Atomic::store     (jshort   store_value, jshort*   dest) { *dest = store_value;}
inline void Atomic::store     (jint	    store_value, jint*     dest) { *dest = store_value; }
//no need to consider the unaligned double word load
inline void Atomic::store     (jlong    store_value, jlong*    dest) { *dest = store_value; }
inline void Atomic::store_ptr	(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
inline void Atomic::store_ptr (void*    store_value, void*	   dest) { *(void**)dest = store_value; }

inline void Atomic::store     (jbyte    store_value, volatile jbyte*    dest) { *dest = store_value; }
inline void Atomic::store     (jshort   store_value, volatile jshort*   dest) { *dest = store_value; }
inline void Atomic::store     (jint     store_value, volatile jint*     dest) { *dest = store_value; }
//no need to consider the unaligned double word load
inline void Atomic::store     (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
inline void Atomic::store_ptr (intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
inline void Atomic::store_ptr (void*    store_value, volatile void*     dest) {*(void**)dest = store_value; }


///////////implementation of Atomic::inc*/////////////////
inline void Atomic::inc	    (volatile jint*	    dest) { (void)add(1, dest); }
inline void Atomic::inc_ptr (volatile intptr_t*	dest) { (void)inc((volatile jint*)dest); }
inline void Atomic::inc_ptr (volatile void*     dest) { (void)inc((volatile jint*)dest); }

///////////implementation of Atomic::dec*/////////////////
inline void Atomic::dec	    (volatile jint*	    dest) { (void)add(-1, dest); }
inline void Atomic::dec_ptr (volatile intptr_t* dest) { (void)dec((volatile jint*)dest); }
inline void Atomic::dec_ptr (volatile void*     dest) { (void)dec((volatile jint*)dest); } 


///////////implementation of Atomic::add*/////////////////
inline jint Atomic::add	(jint add_value, volatile jint* dest) {
	jint __ret, __tmp;
	__asm__ __volatile__ (
		" .set push\n"
		" .set mips2\n"
		" .set noreorder\n"
			
		" 	sync					\n"
		"1:	ll  	%[__ret], %[__dest]		\n"
		" 	addu  %[__tmp], %[__val], %[__ret]	\n"
		" 	sc  	%[__tmp], %[__dest]		\n"
		" 	beqz  %[__tmp], 1b   			\n"
		" 	nop					\n"
		//" 	sync					\n"
		" .set pop\n"

		: [__ret] "=&r" (__ret), [__tmp] "=&r" (__tmp)
		: [__dest] "m" (*(volatile jint*)dest), [__val] "r" (add_value)
		: "memory"
	);
	
	return add_value + __ret;
}

inline intptr_t Atomic::add_ptr (intptr_t add_value, volatile intptr_t* dest) {
	return (intptr_t)add((jint)add_value, (volatile jint*)dest);
}

inline void* Atomic::add_ptr (intptr_t add_value, volatile void* dest) {
	return (void*)add((jint)add_value, (volatile jint*)dest);
}


///////////implementation of Atomic::xchg*/////////////////
inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
	jint __ret, __tmp;
	
  __asm__ __volatile__ (
		" .set push\n"
		" .set mips2\n"
		" .set noreorder\n"
		" 	sync\n"
		"1:	ll  	%[__ret], %[__dest]	\n"
		" 	move  %[__tmp], %[__val]	\n"
		" 	sc  	%[__tmp], %[__dest]	\n"
		" 	beqz  %[__tmp], 1b		\n"
		"  	nop				\n"
		//" 	sync											\n"
		" .set pop\n"

		: [__ret] "=&r" (__ret), [__tmp] "=&r" (__tmp)
		: [__dest] "m" (*(volatile jint*)dest), [__val] "r" (exchange_value)
		: "memory"
	);

	return __ret;
}

inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
	return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
}

inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
	  return (void*)xchg((jint)exchange_value, (volatile jint*)dest);
}

///////////implementation of Atomic::cmpxchg*/////////////////
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
	jint __prev, __cmp;
	
	__asm__ __volatile__ (
		"  .set push\n"						
		"  .set mips2\n"						
		"  .set noreorder\n"
		
		"  sync \n"
		"1:ll   %[__prev], %[__dest]    \n"
		"  bne  %[__prev], %[__old], 2f	\n"	
		"  move	%[__cmp], $0	\n"
		"  move	%[__cmp], %[__new]	\n"
		"  sc	%[__cmp], %[__dest]	\n"
		"  beqz	%[__cmp], 1b		\n"
		"  nop				\n"
		"2:				\n"
		
		"	.set pop"

		: [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp)	
		: [__dest] "m" (*(volatile jint*)dest), [__old] "r" (compare_value),	[__new] "r" (exchange_value)
		: "memory"
	);

	return __prev;
}

inline intptr_t Atomic::cmpxchg_ptr (intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
	return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}

inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
	  return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}

inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
	jlong __ret;
	jint __cmp, __new, __old, __prev;

	__asm__ __volatile__ (
		" .set push\n"
		" .set mips3\n"
		" .set noreorder\n"

		"   sync                          \n"
		"   ld    %[__old], %[__oa]       \n"
		"   ld    %[__new], %[__na]       \n"
		"1: lld   %[__prev], %[__dest]    \n"
		"   bne   %[__prev], %[__old], 2f \n"
		"   move  %[__cmp],  $0           \n"
		"   move  %[__cmp], %[__new]      \n"
		"   scd   %[__cmp], %[__dest]     \n"
		"   beqz  %[__cmp], 1b            \n"
		"   nop                           \n"
		//"   sync                          \n"
		"2:                               \n"
		"   sd    %[__prev], %[__ret]     \n"

		"	.set pop"
		
		: [__cmp] "=&r" (__cmp), 
			[__old] "=&r" (__old), 
			[__new] "=&r" (__new), 
			[__prev] "=&r" (__prev)
		: [__dest] "m" (*(volatile jint*)dest),
			[__oa] "m" (*(volatile jint*)&compare_value),
			[__na] "m" (*(volatile jint*)&exchange_value),
			[__ret] "m" (*(volatile jint*)&__ret)
		: "memory"
	);

	return __ret;
}