view src/cpu/zero/vm/cppInterpreter_arm.S @ 3856:9747f83d7a38

Replace literal offsets for METHOD_SIZEOFPARAMETERS and ISTATE_NEXT_FRAME with correct symbolic names. Fix trace code not to dereference null pointers. Correct Helper_aputfield and helper_aastore not to use static _byte_map_base. Comment-out calls to TRACE. Make sure that ISTATE_METHOD and ISTATE_SELF_LINK are set even when JITting fails.
author aph
date Fri, 21 Mar 2014 20:57:28 +0000
parents 920cd25ec34c
children
line wrap: on
line source

#ifdef __arm__

@ Copyright 2009, 2010 Edward Nevill
@ Copyright 2012, Red Hat
@ 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.

#undef T2JIT
#if !defined(DISABLE_THUMB2) && defined(HOTSPOT_ASM) && !defined(SHARK)
#define T2JIT
#endif

#ifdef HOTSPOT_ASM

#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
#define ARMv4
#endif

#if defined(SHARK) || defined(T2JIT)

#define USE_COMPILER

#endif

#ifdef USE_COMPILER

#ifdef SHARK
#define MP_COMPILE_THRESHOLD    0x10000         // 65536 - must be a single MOV constant
#define UP_COMPILE_THRESHOLD    0x30000         // 196608 - must be a single MOV constant
#else
#define MP_COMPILE_THRESHOLD    0x1380		// ~ 5000 - must be a single MOV constant
#define UP_COMPILE_THRESHOLD    0x1380		// ~ 5000 - must be a single MOV constant
#endif

#define MAX_FG_METHOD_SIZE      500

#ifndef DISABLE_ON_STACK_REPLACEMENT
#define ON_STACK_REPLACEMENT
#endif
#ifndef ENABLE_BG_COMP_ON_NON_MP
#define DISABLE_BG_COMP_ON_NON_MP
#endif

#ifdef T2JIT
#define FREQ_COUNT_OVERFLOW Thumb2_Compile
#else
#define FREQ_COUNT_OVERFLOW _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh
#endif

#endif // USE_COMPILER

#ifndef DISABLE_NOTICE_SAFEPOINTS
#define NOTICE_SAFEPOINTS
#endif
#ifndef DISABLE_HW_NULL_PTR_CHECK
#define HW_NULL_PTR_CHECK
#endif
#ifndef DISABLE_FAST_BYTECODES
#define FAST_BYTECODES
#endif
#ifndef DISABLE_HW_FP
#define HW_FP
#endif

#define LEAF_STACK_SIZE	200
#define STACK_SPARE	40

#define TBIT 1
	
#define stack		r4
#define	jpc		r5
#define dispatch	r6
#define locals		r7
#define istate		r8
#define constpool	r9
#define thread		r10
#define arm_sp		r13

#define tmp_xxx		r7
#define tmp_yyy		r5
#define tmp_vvv		r9

#define tmp1		r11

#define regset		r4,r5,r6,r7,r9,r10,r11
#define fast_regset	r8

#define Rframe	r7

#define FRAME_METHOD		(ISTATE_METHOD-ISTATE_NEXT_FRAME)
#define FRAME_CONSTANTS		(ISTATE_CONSTANTS-ISTATE_NEXT_FRAME)
#define FRAME_BCP		(ISTATE_BCP-ISTATE_NEXT_FRAME)
#define FRAME_STACK_LIMIT	(ISTATE_STACK_LIMIT-ISTATE_NEXT_FRAME)
#define FRAME_LOCALS		(ISTATE_LOCALS-ISTATE_NEXT_FRAME)
#define FRAME_STACK		(ISTATE_STACK-ISTATE_NEXT_FRAME)

#include "offsets_arm.s"

#define last_implemented_bytecode 201

	.macro	ALIGN_CODE
	.align	6
	.endm

	.macro	ALIGN_DATA
	.align	6
	.endm

	.macro	ALIGN_OPCODE
	.align	6
	.endm

	.macro	ALIGN_WORD
	.align	2
	.endm

#define SLOW_ENTRY_OFFSET 24
#define FAST_ENTRY_OFFSET 40

	.macro	SLOW_ENTRY
	ALIGN_CODE
	.word	0, 0, 0, 0, 0, 0
	.endm

	.macro	FAST_ENTRY
	ALIGN_CODE
	.endm

@------------------------------------------------
@ Software NULL Pointer check macro.
@ Usage:
@	SW_NPC	cmp	obj, #0
@	SW_NPC	beq	null_ptr_exception
@------------------------------------------------
	.macro	SW_NPC	p1, p2, p3, p4
#ifndef HW_NULL_PTR_CHECK
  .ifnes "\p4", ""
	\p1 \p2, \p3, \p4
  .else
    .ifnes "\p3", ""
	\p1 \p2, \p3
    .else
	\p1 \p2
    .endif
  .endif
#endif // HW_NULL_PTR_CHECK
	.endm

	.macro	HW_NPC	p1, p2, p3, p4
#ifdef HW_NULL_PTR_CHECK
  .ifnes "\p4", ""
	\p1 \p2, \p3, \p4
  .else
    .ifnes "\p3", ""
	\p1 \p2, \p3
    .else
	\p1 \p2
    .endif
  .endif
#endif // HW_NULL_PTR_CHECK
	.endm

@------------------------------------------------
@ Fast Bytecode Macros FBC and NFBC
@ Use to conditionalise code using fast bytecodes
@ EG:
@	FBC	mov	r0, #opc_invokeresolved
@	FBC	b	rewrite_bytecode
@	NFBC	code to handle slow case
@	NFBC	...
@------------------------------------------------
	.macro	FBC	p1, p2, p3, p4, p5
#ifdef FAST_BYTECODES
  .ifnes "\p5", ""
	  \p1 \p2, \p3, \p4, \p5
  .else
    .ifnes "\p4", ""
	  \p1 \p2, \p3, \p4
    .else
      .ifnes "\p3", ""
	  \p1 \p2, \p3
      .else
	  \p1 \p2
      .endif
    .endif
  .endif
#endif
	.endm

	.macro	NFBC	p1, p2, p3, p4
#ifndef FAST_BYTECODES
  .ifnes "\p4", ""
	\p1 \p2, \p3, \p4
  .else
    .ifnes "\p3", ""
	\p1 \p2, \p3
    .else
	\p1 \p2
    .endif
  .endif
#endif
	.endm

@------------------------------------------------
@ Notice Safepoints macro
@ Usage:
@	NSP	<notice safepoint specific code>
@------------------------------------------------
	.macro	NSP	p1, p2, p3, p4, p5
#ifdef NOTICE_SAFEPOINTS
  .ifnes "\p5", ""
	  \p1 \p2, \p3, \p4, \p5
  .else
    .ifnes "\p4", ""
	  \p1 \p2, \p3, \p4
    .else
      .ifnes "\p3", ""
	  \p1 \p2, \p3
      .else
	  \p1 \p2
      .endif
    .endif
  .endif
#endif
	.endm

@------------------------------------------------
@ Use Compiler macro
@ Usage:
@	USEC	<compiler specific code>
@------------------------------------------------
	.macro	USEC	p1, p2, p3, p4
#ifdef USE_COMPILER
  .ifnes "\p4", ""
	\p1 \p2, \p3, \p4
  .else
    .ifnes "\p3", ""
	\p1 \p2, \p3
    .else
	\p1 \p2
    .endif
  .endif
#endif
	.endm

@------------------------------------------------
@ On stack replacement macro
@ Usage:
@       OSR     <compiler specific code>
@------------------------------------------------
        .macro  OSR     p1, p2, p3, p4
#ifdef ON_STACK_REPLACEMENT
  .ifnes "\p4", ""
        \p1 \p2, \p3, \p4
  .else
    .ifnes "\p3", ""
        \p1 \p2, \p3
    .else
        \p1 \p2
    .endif
  .endif
#endif
        .endm
@------------------------------------------------
@ THUMB2 specific code macro
@ Usage:
@	T2	<thumb2 specific code>
@------------------------------------------------
	.macro	T2	p1, p2, p3, p4
#ifdef T2JIT
  .ifnes "\p4", ""
        \p1 \p2, \p3, \p4
  .else
    .ifnes "\p3", ""
        \p1 \p2, \p3
    .else
        \p1 \p2
    .endif
  .endif
#endif
        .endm

@------------------------------------------------
@ Rewrite pairs of bytecodes
@
@ The fast bytecodes that replace pairs of codes improve performance,
@ but they cause races between threads and incorrect operation in some
@ other cases too.  REWRITE_PAIRS disables rewriting bytecode pairs.
@	
@ Usage:
@	REWRITE_PAIRS	<instruction>
@------------------------------------------------
	.macro	REWRITE_PAIRS	p1, p2, p3, p4
        .endm

	.macro	Opcode	label
	ALIGN_OPCODE
do_\label:
	.endm

	.macro	GET_STACK	offset, reg
	ldr	\reg, [stack, #(\offset+1) * 4]
	.endm

	.macro	PUT_STACK	offset, reg
	str	\reg, [stack, #(\offset+1) * 4]
	.endm

#define PUSH	java_push
	.macro	PUSH	reg1, reg2, reg3, reg4
  .ifnes "\reg4", ""
	stmda	stack!, {\reg1, \reg2, \reg3, \reg4}
  .else
    .ifnes "\reg3", ""
	stmda	stack!, {\reg1, \reg2, \reg3}
    .else
      .ifnes "\reg2", ""
	stmda	stack!, {\reg1, \reg2}
      .else
	str	\reg1, [stack], #-4
      .endif
    .endif
  .endif
	.endm

#define POP	java_pop
	.macro	POP	reg1, reg2, reg3, reg4
  .ifnes "\reg4", ""
	ldmib	stack!, {\reg1, \reg2, \reg3, \reg4}
  .else
    .ifnes "\reg3", ""
	ldmib	stack!, {\reg1, \reg2, \reg3}
    .else
      .ifnes "\reg2", ""
	ldmib	stack!, {\reg1, \reg2}
      .else
	ldr	\reg1, [stack, #4]!
      .endif
    .endif
  .endif
	.endm

	.macro POPF0
#ifdef __ARM_PCS_VFP
	flds s0, [stack, #4]
	add stack, #4
#else
	POP r0
#endif
	.endm
	
	.macro POPF1
#ifdef __ARM_PCS_VFP
	flds s1, [stack, #4]
	add stack, #4
#else
	POP r1
#endif
	.endm
	
	.macro POPD0
#ifdef __ARM_PCS_VFP
	flds s0, [stack, #4]
	flds s1, [stack, #8]
	add stack, #8
#else
	POP r0, r1
#endif
	.endm
	
	.macro POPD1
#ifdef __ARM_PCS_VFP
	flds s2, [stack, #4]
	flds s3, [stack, #8]
	add stack, #8
#else
	POP r2, r3
#endif
	.endm
	
	.macro PUSHF0
#ifdef __ARM_PCS_VFP
	add stack, #-4
	fsts s0, [stack, #4]
#else
	PUSH r0
#endif
	.endm
	
	.macro PUSHD0
#ifdef __ARM_PCS_VFP
	add stack, #-8
	fsts s0, [stack, #4]
	fsts s1, [stack, #8]
#else
	PUSH r0, r1
#endif
	.endm
	
	.macro	LOAD_ISTATE
	ldr	istate, [thread, #THREAD_TOP_ZERO_FRAME]
	sub	istate, istate, #ISTATE_NEXT_FRAME
	.endm

	.macro	CACHE_JPC
	ldr	jpc, [istate, #ISTATE_BCP]
	.endm

	.macro	CACHE_LOCALS
	ldr	locals, [istate, #ISTATE_LOCALS]
	.endm

	.macro	CACHE_STACK
	ldr	stack, [istate, #ISTATE_STACK]
	.endm

	.macro	CACHE_CP
	ldr	constpool, [istate, #ISTATE_CONSTANTS]
	.endm

	.macro	DECACHE_STACK_USING_FRAME
	str	stack, [Rframe, #FRAME_STACK]
	.endm

	.macro	DECACHE_STACK
	str	stack, [istate, #ISTATE_STACK]
	.endm

	.macro	DECACHE_JPC_USING_FRAME
	str	jpc, [Rframe, #FRAME_BCP]
	.endm

	.macro	DECACHE_JPC
	str	jpc, [istate, #ISTATE_BCP]
	.endm

	.macro	BREAK_DISPATCH
	ldr	r1, [dispatch, #DispatchBreakPoint-XXX]
	cmp	r1, jpc
	bleq	do_dispatch_break
	.endm

	.set	dispatch_state, 0

	.macro	DISPATCH_STATE	state
	.set	dispatch_state, \state
	.endm

	.macro	DISPATCH_START	step=0
	.set	dispatch_state, 1
	ldrb	r0, [jpc, #\step]!
	.endm

	.macro	DISPATCH_START_REG	reg
	.set	dispatch_state, 1
	ldrb	r0, [jpc, \reg]!
	.endm

	.macro	DISPATCH_START_R2_R0
	.set	dispatch_state, 1
	mov	r0, r2
	.endm

	.macro	DISPATCH_START_R2_JPC
	.set	dispatch_state, 1
	add	jpc, jpc, #1
	.endm

	.macro	DISPATCH_START_R2
	.set	dispatch_state, 1
	add	jpc, jpc, #1
	mov	r0, r2
	.endm

	.macro	DISPATCH_1
@        ldrb    r1, [jpc, #2]
	.endm

	.macro	DISPATCH_2
        ldr     ip, [dispatch, r0, lsl #2]
	.endm

	.macro	DISPATCH_3
        ldrb    r2, [jpc, #1]
	.endm

	.macro	DISPATCH_4
        ands    lr, ip, #7
	.endm

	.macro	DISPATCH_NEXT
    .if dispatch_state == 0
	.error	"DISPATCH_FINISH without a DISPATCH_START or DISPATCH_STATE"
    .elseif dispatch_state == 1
	DISPATCH_1
    .elseif dispatch_state == 2
	DISPATCH_2
    .elseif dispatch_state == 3
	DISPATCH_3
    .elseif dispatch_state == 4
	DISPATCH_4
    .else
	.error "Too many DISPATCH_NEXTs"
    .endif
	.set	dispatch_state, dispatch_state + 1
	.endm

	@ This macro calls a user-supplied my_trace routine.  It
	@ passes the current JPC as argument zero.  It can be safely
	@ inserted at any point in the interpreter.
 	.macro TRACE
	stmfd	sp!, {r0, r1, r2, r3, r4, lr, ip}
	mrs	r4, cpsr
	mov	r0, jpc
	ldr	r1, [thread, #THREAD_TOP_ZERO_FRAME]
        cmp        r1, #0
	sub	r1, r1, #ISTATE_NEXT_FRAME
        beq        0f
        DECACHE_JPC
	ldr	r2, =my_trace
	blx	r2
0:        msr        cpsr, r4
	ldmfd	sp!, {r0, r1, r2, r3, r4, lr, ip}	
	.endm
	
	.macro	DISPATCH_FINISH
    .if dispatch_state == 0
	.error	"DISPATCH_FINISH without a DISPATCH_START or DISPATCH_STATE"
    .elseif dispatch_state == 1
	DISPATCH_1
	DISPATCH_2
	DISPATCH_3
	DISPATCH_4
    .elseif dispatch_state == 2
	DISPATCH_2
	DISPATCH_3
	DISPATCH_4
    .elseif dispatch_state == 3
	DISPATCH_3
	DISPATCH_4
    .elseif dispatch_state == 4
	DISPATCH_4
    .endif
        moveq   pc, ip
	ldrb	r1, [jpc, lr]
        bic     ip, ip, #7
        ldr     pc, [ip, r1, lsl #2]
	.set	dispatch_state, 0
	.ltorg
	.endm

	.macro	DISPATCH_BYTECODE
@        ldrb    r1, [jpc, #2]
        ldr     ip, [dispatch, r0, lsl #2]
        ldrb    r2, [jpc, #1]
        ands    lr, ip, #7
        moveq   pc, ip
	ldrb	r1, [jpc, lr]
        bic     ip, ip, #7
        ldr     pc, [ip, r1, lsl #2]
	.endm

	.macro	DISPATCH step=0
	ldrb	r0, [jpc, #\step]!
@        ldrb    r1, [jpc, #2]
        ldr     ip, [dispatch, r0, lsl #2]
        ldrb    r2, [jpc, #1]
        ands    lr, ip, #7
        moveq   pc, ip
	ldrb	r1, [jpc, lr]
        bic     ip, ip, #7
        ldr     pc, [ip, r1, lsl #2]
	.ltorg
	.endm

#define FFI_TYPE_VOID		0
#define FFI_TYPE_FLOAT		2
#define	FFI_TYPE_DOUBLE		3
#define FFI_TYPE_BOOL		5
#define	FFI_TYPE_SINT8		6
#define FFI_TYPE_UINT16		7
#define FFI_TYPE_SINT16		8
#define FFI_TYPE_SINT32		10
#define FFI_TYPE_SINT64		12
#define FFI_TYPE_POINTER	14

	.macro	_BLX	reg
	mov	lr, pc
	mov	pc, \reg
	.endm

	.macro	_BX	reg
	mov	pc, \reg
	.endm

	.macro	_BXEQ	reg
	moveq	pc, \reg
	.endm

	.macro	_BXNE	reg
	movne	pc, \reg
	.endm

#ifdef ARMv4

#define blx _BLX
#define bx _BX
#define bxeq _BXEQ
#define bxne _BXNE
	.arch armv4

#else
	.arch armv7-a
#endif

#ifdef HW_FP

#ifdef __ARM_PCS_VFP
 	.fpu vfpv3-d16
	.eabi_attribute Tag_ABI_HardFP_use, 3
	.eabi_attribute Tag_ABI_VFP_args, 1
#else // __ARM_PCS_VFP
	.fpu vfp
#endif // __ARM_PCS_VFP

#else // HW_FP
	.fpu softvfp
#endif // HW_FP

#ifndef	__ARM_ARCH_7A__
#	define dmb VOLATILE_BARRIER
#	define dmb_st VOLATILE_BARRIER
#else
#	define	dmb_st .inst   0xf57ff05e
#endif

#define StoreStoreBarrier dmb_st
#define StoreLoadBarrier dmb
#define FullBarrier dmb
	
	.macro	VOLATILE_BARRIER arg
	stmfd	sp!, {r2, lr}
	ldr	r2, =0xffff0fa0 @ kernel_dmb
	blx	r2
	ldmfd	sp!, {r2, lr}
	.endm
	
	.macro	GO_IF_VOLATILE reg, cp_cache, label
	ldr	\reg, [\cp_cache, #CP_OFFSET+CP_CACHE_FLAGS]
	tst	\reg, #(1<<CP_CACHE_VOLATILE_FIELD_FLAG_BIT)
	bne	\label
	.set	dispatch_saved, dispatch_state
	.endm

	@ We have to save and restore the dispatch_state because
	@ dispatching is done twice, once each for volatile and
	@ non-volatile versions.  It's essential that dispatch_state
	@ be correct at the entry to the volatile version of the
	@ handler.

	.macro VOLATILE_VERSION
	.if dispatch_state == 0
	.set	dispatch_state, dispatch_saved
	.else
	.error "VOLATILE_VERSION macro used before non-volatile DISPATCH_FINISH."
	.endif
	.endm
	
	.eabi_attribute 20, 1 @ Tag_ABI_FP_denormal
	.eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions
	.eabi_attribute 23, 3 @ Tag_ABI_FP_number_model
	.eabi_attribute 24, 1 @ Tag_ABI_align8_needed
	.eabi_attribute 25, 1 @ Tag_ABI_align8_preserved
	.eabi_attribute 26, 2 @ Tag_ABI_enum_size
	.eabi_attribute 30, 2 @ Tag_ABI_optimization_goals
	.eabi_attribute 18, 4 @ Tag_ABI_PCS_wchar_t

	.text

	.global	cmpxchg_ptr
	.type cmpxchg_ptr, %function
cmpxchg_ptr:
	stmfd	sp!, {r4, r5, r6, r7, r8, lr}
	mov	r6, #0xffffffc0
	mov	r4, r2
	mov	r7, r0
	mov	r5, r1
	bic	r6, r6, #0xf000
	mov	r8, r2
1:
	ldr	r3, [r5, #0]
	mov	r0, r4
	mov	r1, r7
	mov	r2, r5
	cmp	r4, r3
	bne	2f
	blx	r6
	cmp	r0, #0
	bne	1b
	mov	r0, r8
	ldmfd	sp!, {r4, r5, r6, r7, r8, pc}
2:
	mov	r8, r3
	mov	r0, r8
	ldmfd	sp!, {r4, r5, r6, r7, r8, pc}

build_frame:
	mov	r3, r0
	ldr	r0, [r1, #METHOD_ACCESSFLAGS]
	stmfd	arm_sp!, {r4, r5, r6, r7, r8}
	ands	r7, r0, #JVM_ACC_SYNCHRONIZED
	movne	r7, #2
	tst	r0, #JVM_ACC_NATIVE
	mov	r4, #0
	movne	r5, #0
	ldreqh	r6, [r1, #METHOD_MAXLOCALS]
	ldrneh	r6, [r1, #METHOD_SIZEOFPARAMETERS]
	ldreq	r0, [r3, #8]
	subeq	r6, r6, #1
	ldrne	r0, [r3, #8]
	subne	r6, r6, #1
	ldreqh	r5, [r1, #METHOD_MAXSTACK]
	addeq	r6, r0, r6, asl #2
	addne	r6, r0, r6, asl #2
	sub	ip, r0, #4
	str	ip, [r3, #8]
	mov     ip, #INTERPRETER_FRAME
	str	r4, [r0, #-4]
	ldr	r0, [r3, #8]
	sub	r8, r0, #4
	str	r8, [r3, #8]
	str	ip, [r0, #-4]
	ldr	r8, [r3, #8]
	sub	ip, r8, #68
	str	ip, [r3, #8]
	str	r2, [r8, #-68]
	mov	r8, #0
	str	r4, [ip, #44]
	str	r6, [ip, #8]
	str	r1, [ip, #16]
	str	ip, [ip, #64]
	ldr	r2, [r1, #METHOD_ACCESSFLAGS]
	tst	r2, #JVM_ACC_NATIVE
	mov	r2, #0
	ldreq	r4, [r1, #METHOD_CONSTMETHOD]
	addeq	r4, r4, #CONSTMETHOD_CODEOFFSET
	str	r4, [ip, #4]
	ldr	r4, [r1, #METHOD_CONSTANTS]
	ldr	r4, [r4, #CONSTANTPOOL_CACHE]
	str	r8, [ip, #28]
	str	r2, [ip, #32]
	str	r4, [ip, #12]
	str	r2, [ip, #48]
	str	r2, [ip, #20]
	ldr	r2, [r3, #8]
	str	r2, [ip, #60]
	ldr	r2, [r1, #METHOD_ACCESSFLAGS]
	tst	r2, #JVM_ACC_SYNCHRONIZED
	beq	.L10
	ldr	r2, [r3, #8]
	sub	r7, r2, r7, asl #2
	str	r7, [r3, #8]
	ldr	r2, [r1, #METHOD_ACCESSFLAGS]
	tst	r2, #JVM_ACC_STATIC
	ldrne	r2, [r1, #METHOD_CONSTANTS]
	ldreq	r2, [r6, #0]
	ldrne	r2, [r2, #CONSTANTPOOL_POOL_HOLDER]
	ldrne	r2, [r2, #KLASS_PART + KLASS_JAVA_MIRROR]
	str	r2, [r7, #4]
.L10:
	ldr	r2, [r3, #8]
	cmp	r5, #0
	str	r2, [ip, #52]
	ldr	r2, [r3, #8]
	sub	r2, r2, #4
	str	r2, [ip, #24]
	ldrne	r2, [r3, #8]
	ldreq	r5, [r3, #8]
	subne	r5, r2, r5, asl #2
	strne	r5, [r3, #8]
	sub	r5, r5, #4
	str	r5, [ip, #56]
	ldmfd	arm_sp!, {r4, r5, r6, r7, r8}
	bx	lr

	ALIGN_CODE
	.global	asm_generate_method_entry
	.type asm_generate_method_entry, %function
asm_generate_method_entry:
	mov	r3, r0
	mov	r0, #0
#ifdef PRODUCT
	// These entry points can not be used when PRODUCT is
	// undefined because the BytecodeInterpreter class is virtual
	// so it has an extra word (the vtable pointer) at its
	// beginning.
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r1, r2}
	add	r1, r1, ip
	add	r1, r1, r2		@ r1->dispatch

	ldr	r2, [r1, #can_post_interpreter_events-XXX]
	ldrb	r2, [r2]
	cmp	r2, #0
	bne	1f

	ldr	r2, [r1, #PrintCommandLineFlags_Address-XXX]
	ldrb	r2, [r2]
	cmp	r2, #0
	bne	1f

	cmp	r3, #((3f-2f)/4) // i.e. sizeof asm_method_table
	adrcc	ip, asm_method_table
	ldrcc	r0, [ip, r3, lsl #2]
#endif // PRODUCT
1:
	bx	lr

// This table must be kept in sync with
// AbstractInterpreter::MethodKind.  Note that every entry must have a
// corresponding fast entry point at addr + CODE_ALIGN_SIZE.
asm_method_table:
2:
        .word   normal_entry                    // method needs locals initialization
        .word   normal_entry_synchronized       // method needs locals initialization & is synchronized
        .word   native_entry                    // native method
        .word   native_entry_synchronized       // native method & is synchronized
        .word   empty_entry                     // empty method (code: _return)
        .word   accessor_entry                  // accessor method (code: _aload_0, _getfield, _(a|i)return)
        .word   normal_entry                    // abstract method (throws an AbstractMethodException)
        .word   method_handle_entry             // java.lang.invoke.MethodHandles::invoke
        .word   normal_entry                    // implementation of java.lang.Math.sin   (x)
        .word   normal_entry                    // implementation of java.lang.Math.cos   (x)
        .word   normal_entry                    // implementation of java.lang.Math.tan   (x)
        .word   normal_entry                    // implementation of java.lang.Math.abs   (x)
        .word   normal_entry                    // implementation of java.lang.Math.sqrt  (x)
        .word   normal_entry                    // implementation of java.lang.Math.log   (x)
        .word   normal_entry                    // implementation of java.lang.Math.log10 (x)
        .word   accessor_entry                  // implementation of java.lang.ref.Reference.get()
3:
	
	SLOW_ENTRY
native_entry_synchronized:
	mov	r2, thread
	b	_ZN14CppInterpreter12native_entryEP13methodOopDesciP6Thread

	FAST_ENTRY
fast_native_entry_synchronized:
	mov	r2, thread
	b	_ZN14CppInterpreter12native_entryEP13methodOopDesciP6Thread

	SLOW_ENTRY
empty_entry:
        ldrh        r3, [r0, #METHOD_SIZEOFPARAMETERS]
	ldr	r1, [r2, #THREAD_JAVA_SP]
	add	r1, r1, r3, lsl #2
	str	r1, [r2, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	bx	lr

	FAST_ENTRY
fast_empty_entry:
        ldrh        r3, [r0, #METHOD_SIZEOFPARAMETERS]
	ldr	r1, [thread, #THREAD_JAVA_SP]
	add	r1, r1, r3, lsl #2
	str	r1, [thread, #THREAD_JAVA_SP]
	bx	lr

@ ---- START execute.s ---------------------------------------------------------------------

	.global	asm_check_null_ptr
	.type asm_check_null_ptr, %function
asm_check_null_ptr:

#ifdef HW_NULL_PTR_CHECK

#define uc_mcontext		20
#define arm_registers_offset	12
#define arm_cpsr_offset		16*4

	add	r0, r0, #uc_mcontext + arm_registers_offset
	ldr	r1, [r0, #15*4]
	adr	ip, abort_table
abort_loop:
	ldr	r2, [ip], #8
	cmp	r2, #0
	beq	2f
	cmp	r2, r1
	bne	abort_loop

	ldr	r3, [ip, #-4]
	cmp	r3, #8
	bcs	1f

	ldr	ip, [r0, #5*4]
	sub	ip, ip, r3
	str	ip, [r0, #5*4]

	adrl	r3, null_ptr_exception
1:
	str	r3, [r0, #15*4]
do_setcontext:
	mov	r0, #1
	bx	lr
#endif // HW_NULL_PTR_CHECK
2:
#ifdef T2JIT
	b	Thumb2_Check_Null
#else
	mov	r0, #0
	bx	lr
#endif

#ifdef HW_NULL_PTR_CHECK
abort_table:
			.word	.abortentry5, 1
			.word	.abortentry6, 1
			.word	.abortentry7, 1
			.word	.abortentry8, 1
			.word	.abortentry9, 1
			.word	.abortentry10, 1
			.word	.abortentry11, 1
			.word	.abortentry12, 1
			.word	.abortentry13, 1

		FBC	.word	.abortentry19, 1
		FBC	.word	.abortentry20, 1
		FBC	.word	.abortentry21, 1
		FBC	.word	.abortentry22, 1
		FBC	.word	.abortentry23, 1
		FBC	.word	.abortentry24, 1
		FBC	.word	.abortentry25, 1
		FBC	.word	.abortentry26, 1
		FBC	.word	.abortentry27, 1
		FBC	.word	.abortentry28, 1
		FBC	.word	.abortentry29, 1
		FBC	.word	.abortentry30, 1
		FBC	.word	.abortentry31, 1
		FBC	.word	.abortentry32, 1

		FBC	.word	.abortentry38, 2
		FBC	.word	.abortentry39, 3
		FBC	.word	.abortentry40, 4
		FBC	.word	.abortentry41, 3
		FBC	.word	.abortentry42, 2
		FBC	.word	.abortentry42_1, 2
		FBC	.word	.abortentry43, 0
		FBC	.word	.abortentry44, 1
		FBC	.word	.abortentry45, 3
		FBC	.word	.abortentry46, 2
		FBC	.word	.abortentry47, 0
		FBC	.word	.abortentry48, 1
		FBC	.word	.abortentry49, 0
		FBC	.word	.abortentry50, 1
		FBC	.word	.abortentry51, 0
		FBC	.word	.abortentry52, 1

		FBC	.word	.abortentry58, 2
		FBC	.word	.abortentry59, 2
		FBC	.word	.abortentry60, 2

		FBC	.word	.abortentry73, 1
		FBC	.word	.abortentry74, 1
		FBC	.word	.abortentry75, 1
		FBC	.word	.abortentry76, 1
		FBC	.word	.abortentry77, 1

	    FBC		.word	.abortentry78, 3
	    FBC		.word	.abortentry78_v, 3
	    FBC		.word	.abortentry79, 3
	    FBC		.word	.abortentry79_v, 3
	    FBC		.word	.abortentry80, 3
	    FBC		.word	.abortentry80_v, 3
	    FBC		.word	.abortentry81, 3
	    FBC		.word	.abortentry81_v, 3
	    FBC		.word	.abortentry82, 3
	    FBC		.word	.abortentry82_v, 3
	    FBC		.word	.abortentry83, 3
	    FBC		.word	.abortentry83_v, 3
	    FBC		.word	.abortentry84, 3
	    FBC		.word	.abortentry84_v, 3
	    FBC		.word	.abortentry85, 3
	    FBC		.word	.abortentry85_v, 3
	    FBC		.word	.abortentry86, 3
	    FBC		.word	.abortentry86_v, 3
	    FBC		.word	.abortentry87, 3
	    FBC		.word	.abortentry87_v, 3

	    FBC    	.word	.abortentry88, 3
	    FBC    	.word	.abortentry88_v, 3
	    FBC	   	.word	.abortentry89, 5
	    FBC	     	.word	.abortentry90, 4
	    FBC	     	.word	.abortentry91, 4
	    FBC		.word	.abortentry104, 0
		FBC	.word	.abortentry105, 1
		FBC	.word	.abortentry106, 1
		FBC	.word	.abortentry107, 1
		FBC	.word	.abortentry108, 1
		FBC	.word	.abortentry109, 1
			.word	.abortentry110, 0

		FBC	.word	.abortentry111, 3
		FBC	.word	.abortentry112, 3

		FBC	.word	.abortentry113, 0
		FBC	.word	.abortentry113_v, 0
			.word	.abortentry114, 1
		FBC	.word	.abortentry117, 0
			.word	.abortentry118, 0
			.word	.abortentry119, 1
	.word	0

#endif


	SLOW_ENTRY
native_entry:
	stmfd	arm_sp!, {regset, lr}
	mov	thread, r2
	bl	fast_native_entry	
	mov	r0, #0	@ deoptimized_frames = 0
	ldmia	sp!, {regset, pc}

	FAST_ENTRY
fast_native_entry:
	adrl	ip, dispatch_init_adcon
	mov	r11, r0
	ldm	ip, {dispatch, r7}
	stmdb	sp!, {fast_regset, lr}
	add	dispatch, dispatch, ip
	add	dispatch, dispatch, r7
	ldrh	r1, [r11, #METHOD_SIZEOFPARAMETERS]
	ldr	r4, [thread, #THREAD_JAVA_SP]
	ldr	r3, [thread, #THREAD_TOP_ZERO_FRAME]
	mov	r0, #0
	mov	ip, #INTERPRETER_FRAME
	sub	r9, r4, #FRAME_SIZE
	str	r9, [thread, #THREAD_JAVA_SP]	@ drop stack
	sub	r5, r9, #4		@ stack limit = r9 - 4
	str	r3, [r9, #ISTATE_NEXT_FRAME]
	str	ip, [r9, #ISTATE_FRAME_TYPE]
	str	r9, [r9, #ISTATE_MONITOR_BASE]
	str	r5, [r9, #ISTATE_STACK_LIMIT]
	str	r9, [r9, #ISTATE_STACK_BASE]
	str	r0, [r9, #ISTATE_OOP_TEMP]

	str	r0, [r9, #ISTATE_MSG]

	ldr	ip, [r11, #METHOD_CONSTANTS]
	sub	r7, r4, #4
	mov	r5, #0
	add	r7, r7, r1, lsl #2

	ldr	ip, [ip, #CONSTANTPOOL_CACHE]

	str	thread, [r9, #ISTATE_THREAD]
	str	r5, [r9, #ISTATE_BCP]
	str	r7, [r9, #ISTATE_LOCALS]
	str	ip, [r9, #ISTATE_CONSTANTS]
	str	r11, [r9, #ISTATE_METHOD]
	str     r9, [r9, #ISTATE_SELF_LINK]

	ldr	r1, [thread, #THREAD_STACK_SIZE]
	ldr	r3, [thread, #THREAD_STACK_BASE]
        add        r0, r9, #ISTATE_NEXT_FRAME

	rsb	r3, r1, r3
	rsb	r3, r3, arm_sp
	cmp	r3, #4096
	str	r0, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r5, [r11, #METHOD_SIGNATUREHANDLER]
	blt	.fast_native_entry_throw_stack_overflow
	cmp	r5, #0
	bne	.fast_native_entry_got_handleraddr
	str	r5, [thread, #THREAD_LAST_JAVA_SP] @ r5 is zero at this point
	str	r0, [thread, #THREAD_LAST_JAVA_FP]
	ldr	r0, [thread, #THREAD_JAVA_SP]
	str	r0, [thread, #THREAD_LAST_JAVA_SP]
	mov	r0, thread
	mov	r1, r11
	bl	_ZN18InterpreterRuntime19prepare_native_callEP10JavaThreadP13methodOopDesc
	ldr	r11, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r1, [thread, #THREAD_PENDING_EXC]
	str	r5, [thread, #THREAD_LAST_JAVA_SP]  @ r5 is zero at this point
	str	r5, [thread, #THREAD_LAST_JAVA_FP]
	ldr	r5, [thread, #THREAD_JAVA_SP]
	str	r5, [thread, #THREAD_LAST_JAVA_SP]
        ldr        r11, [r11, #-ISTATE_NEXT_FRAME + ISTATE_METHOD]
	cmp	r1, #0
	bne	.fast_native_entry_exception
	ldr	r5, [r11, #METHOD_SIGNATUREHANDLER]
.fast_native_entry_got_handleraddr:
	ldr	r2, [dispatch, #InterpreterRuntime_slow_signature_handler_Address-XXX]
	cmp	r5, r2
	bne	.fast_native_entry_get_handler
	ldr	r3, [thread, #THREAD_TOP_ZERO_FRAME]
	stmfd	sp!, {r2}
	mov	r2, #0
        str     r2, [thread, #THREAD_LAST_JAVA_SP]
	ldmfd	sp!, {r2}
	mov	r0, thread
	str	r3, [thread, #THREAD_LAST_JAVA_FP]
	ldr	r3, [thread, #THREAD_JAVA_SP]
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
	mov	r3, r2
	mov	r1, r11
	bl	_ZN18InterpreterRuntime22slow_signature_handlerEP10JavaThreadP13methodOopDescPiS4_
	ldr	r11, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r1, [thread, #THREAD_PENDING_EXC]
	mov	r3, #0
        ldr        r11, [r11, #-ISTATE_NEXT_FRAME + ISTATE_METHOD]
	cmp	r1, #0
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
	str	r3, [thread, #THREAD_LAST_JAVA_FP]
	mov	r5, r0
	bne	.fast_native_entry_exception
.fast_native_entry_get_handler:

	sub	ip, r7, r4
	add	r3, r4, #ISTATE_OOP_TEMP-76

	mov	ip, ip, asr #2
	mov	r4, arm_sp

	add	lr, ip, #4
	sub	arm_sp, arm_sp, #16

	bic	lr, lr, #1
	add	r1, r5, #SIZEOF_FFI_CIF

	sub	arm_sp, arm_sp, lr, lsl #2
	add	r2, thread, #THREAD_JNI_ENVIRONMENT

	mov	lr, arm_sp
	str	r2, [lr], #4

#ifdef __ARM_PCS_VFP
	mov	thread, #0xff	@ bitmap for floating-point register set
	orr	thread, #0xff00
#endif	
	ldr	r2, [r11, #METHOD_ACCESSFLAGS]
	add	r1, r1, #4
	tst	r2, #JVM_ACC_STATIC
	beq	.do_fast_copy_args

	ldr	r2, [r11, #METHOD_CONSTANTS]
	ldr	r2, [r2, #CONSTANTPOOL_POOL_HOLDER]
	str	r3, [lr], #4
	ldr	r2, [r2, #KLASS_PART + KLASS_JAVA_MIRROR]
	add	r1, r1, #4
	str	r2, [r3]

.do_fast_copy_args:
	cmp	ip, #0
	blt	.fast_no_args

.fast_copy_args:
	ldr	r0, [r1], #4
	ldrh	r3, [r0, #6]
	cmp	r3, #FFI_TYPE_DOUBLE
	beq	.fast_copy_double
	cmp	r3, #FFI_TYPE_FLOAT
	beq	.fast_copy_float
	ldr	r2, [r7], #-4
	cmp	r3, #FFI_TYPE_SINT64
	beq	.fast_copy_long

	cmp	r3, #FFI_TYPE_POINTER
	beq	.fast_copy_ptr

	subs	ip, ip, #1
	str	r2, [lr], #4
	bge	.fast_copy_args
	b	.fast_no_args

#ifdef __ARM_PCS_VFP
	// FIXME: These macros are very inefficient
	.macro	FIND_LOWEST_BIT	rd, rs
	mov	\rd, #0
0:	tst	\rs, #1
	lsr	\rs, #1
	addeq	\rd, #1
	beq	0b
	lsl	\rs, \rd
	lsl	\rs, #1
	.endm
	
	.macro	FIND_LOWEST_BIT_PAIR rd, rs
	stmfd	sp!, {r1}
	stmfd	sp!, {\rs}
	mov	\rd, #0
0:	tst	\rs, #1
	lsr	\rs, #2
	addeq	\rd, #2
	beq	0b
	ldmfd	sp!, {\rs}
	mov	r1, #3
	lsl	r1, \rd
	bic	\rs, r1
	ldmfd	sp!, {r1}
	.endm
	
.fast_copy_double:
	orrs	thread, thread
	ldreq	r2, [r7], #-4	
	beq	vm_fatal_error
	FIND_LOWEST_BIT_PAIR r0, thread
	adrl	r2, .copy_double_table
	add	pc, r2, r0, asl#5

.fast_copy_float:
	orrs	thread, thread
	ldreq	r2, [r7], #-4	
	beq	vm_fatal_error
	FIND_LOWEST_BIT r0, thread
	adr	r2, .copy_float_table
	add	pc, r2, r0, asl#6
#else

.fast_copy_double:
	ldr	r2, [r7], #-4
	tst	lr, #4
	ldr	r3, [r7], #-4
	addne	lr, lr, #4
	str	r2, [lr, #4]
	subs	ip, ip, #2
	str	r3, [lr], #8
	bge	.fast_copy_args
	b	.fast_no_args
	
.fast_copy_float:
	ldr	r2, [r7], #-4
	subs	ip, ip, #1
	str	r2, [lr], #4
	bge	.fast_copy_args

#endif

.fast_copy_long:
	tst	lr, #4
	ldr	r3, [r7], #-4
	addne	lr, lr, #4
	str	r2, [lr, #4]
	subs	ip, ip, #2
	str	r3, [lr], #8
	bge	.fast_copy_args
	b	.fast_no_args

.fast_copy_ptr:
	cmp	r2, #0
	addne	r2, r7, #4
	subs	ip, ip, #1
	str	r2, [lr], #4
	bge	.fast_copy_args

.fast_no_args:
	ldr     thread, [r9, #ISTATE_THREAD]
	ldr	r0, [thread, #THREAD_TOP_ZERO_FRAME]
	mov	r2, #_thread_in_native

	mov	ip, #0
	str	ip, [thread, #THREAD_LAST_JAVA_SP]

	str	r0, [thread, #THREAD_LAST_JAVA_FP]
	str	r2, [thread, #THREAD_STATE]

	ldr	r2, [thread, #THREAD_JAVA_SP]
	str	r2, [thread, #THREAD_LAST_JAVA_SP]

	ldr	ip, [r11, #METHOD_NATIVEHANDLER]
	ldrh	r11, [r11, #METHOD_SIZEOFPARAMETERS]

	ldmia	arm_sp!, {r0, r1, r2, r3}
	blx	ip

	mov	ip, #_thread_in_native_trans
	mov	arm_sp, r4

	ldr	r3, [dispatch, #SafePointSynchronize_state_Address-XXX]
	str	ip, [thread, #THREAD_STATE]

	ldr	r3, [r3, #0]
	cmp	r3, #0
	ldreq	r3, [thread, #THREAD_SUSPEND_FLAGS]
	cmpeq	r3, #0
	bne	.fast_native_entry_do_special

.fast_native_entry_do_return:
	mov	r3, #_thread_in_Java
	mov	r2, #0

	str	r3, [thread, #THREAD_STATE]
	str	r2, [thread, #THREAD_LAST_JAVA_SP]
	str	r2, [thread, #THREAD_LAST_JAVA_FP]

	add	r2, r5, #SIZEOF_FFI_CIF
	ldr	r3, [r5, #4]

	ldr	r5, [thread, #THREAD_TOP_ZERO_FRAME]

	ldr	lr, [r5], #4

	add	r5, r5, r11, lsl #2

	ldr	ip, [r2, r3, asl #2]
	adr	r3, .return_type_table

	ldrh	r2, [ip, #6]
	ldr	ip, [thread, #THREAD_ACTIVE_HANDLES]

	mov	tmp1, #0
	ldr	pc, [r3, r2, lsl #2]

.return_type_table:
	.word	.fast_native_return_void	@ FFI_TYPE_VOID	== 0
	.word	0
#ifdef __ARM_PCS_VFP
	.word	.fast_native_return_float	@ FFI_TYPE_FLOAT == 2
	.word	.fast_native_return_double	@ FFI_TYPE_DOUBLE == 3
#else
	.word	.fast_native_return_w		@ FFI_TYPE_FLOAT == 2
	.word	.fast_native_return_dw		@ FFI_TYPE_DOUBLE == 3
#endif
	.word	0
	.word	.fast_native_return_bool	@ FFI_TYPE_BOOL == 5
	.word	.fast_native_return_byte	@ FFI_TYPE_SINT8 == 6
	.word	.fast_native_return_char	@ FFI_TYPE_UINT16 == 7
	.word	.fast_native_return_short	@ FFI_TYPE_SINT16 == 8
	.word	0
	.word	.fast_native_return_w		@ FFI_TYPE_SINT32 == 10
	.word	0
	.word	.fast_native_return_dw		@ FFI_TYPE_SINT64 == 12
	.word	0
	.word	.fast_native_return_obj		@ FFI_TYPE_POINTER == 14

#ifdef __ARM_PCS_VFP
.fast_native_return_double:
	fsts	s0, [r5, #-8]
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	fsts	s1, [r5, #-4]
	add	r5, #-8
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
.fast_native_return_float:
	fsts	s0, [r5, #-4]
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	add	r5, #-4
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
#endif
.fast_native_return_dw:
	str	r0, [r5, #-8]!
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	str	r1, [r5, #4]
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
.fast_native_return_byte:
	mov	r0, r0, lsl #24
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	mov	r0, r0, asr #24
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	str	r0, [r5, #-4]!
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
.fast_native_return_char:
	mov	r0, r0, lsl #16
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	mov	r0, r0, lsr #16
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	str	r0, [r5, #-4]!
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
.fast_native_return_bool:
	ands	r0, r0, #255
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	movne	r0, #1
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	str	r0, [r5, #-4]!
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
.fast_native_return_obj:
	cmp	r0, #0
	ldrne	r0, [r0]
	str	r0, [r5, #-4]!
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}
.fast_native_return_short:
	mov	r0, r0, lsl #16
	mov	r0, r0, asr #16
.fast_native_return_w:
	str	r0, [r5, #-4]!
.fast_native_return_void:
	str	lr, [thread, #THREAD_TOP_ZERO_FRAME]
	str	tmp1, [ip, #JNIHANDLEBLOCK_TOP]
.fast_native_exit:
	str	r5, [thread, #THREAD_JAVA_SP]
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}

.fast_native_entry_throw_stack_overflow:
	str	r0, [thread, #THREAD_LAST_JAVA_FP]
	mov	r0, thread
	bl	_ZN18InterpreterRuntime24throw_StackOverflowErrorEP10JavaThread
	mov	r3, #0
	ldr	r1, [thread, #THREAD_PENDING_EXC]
	str	r3, [thread, #THREAD_LAST_JAVA_FP]
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
.fast_native_entry_exception:
	ldr	r5, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r3, [r5], #4
	str	r3, [thread, #THREAD_TOP_ZERO_FRAME]

	ldrh	r3, [r11, #METHOD_SIZEOFPARAMETERS]
	add	r5, r5, r3, lsl #2
	b	.fast_native_exit

.fast_native_entry_do_special:
	stmdb	arm_sp!, {r0, r1}
	mov	r0, thread
	bl	_ZN10JavaThread40check_special_condition_for_native_transEPS_
	ldmia	arm_sp!, {r0, r1}
	b	.fast_native_entry_do_return


	
#ifdef __ARM_PCS_VFP

	.macro	COPY_FLOAT rs, rd, rcount
	.align	6
	flds	\rd, [\rs]
	add	\rs, #-4
	subs	\rcount, #1
	bge	.fast_copy_args
	b	.fast_no_args
	.endm

	.align	6
.copy_float_table:
	COPY_FLOAT r7, s0, ip
	COPY_FLOAT r7, s1, ip
	COPY_FLOAT r7, s2, ip
	COPY_FLOAT r7, s3, ip
	COPY_FLOAT r7, s4, ip
	COPY_FLOAT r7, s5, ip
	COPY_FLOAT r7, s6, ip
	COPY_FLOAT r7, s7, ip
	COPY_FLOAT r7, s8, ip
	COPY_FLOAT r7, s9, ip
	COPY_FLOAT r7, s10, ip
	COPY_FLOAT r7, s11, ip
	COPY_FLOAT r7, s12, ip
	COPY_FLOAT r7, s13, ip
	COPY_FLOAT r7, s14, ip
	COPY_FLOAT r7, s15, ip
	COPY_FLOAT r7, s16, ip
	COPY_FLOAT r7, s17, ip
	COPY_FLOAT r7, s18, ip
	COPY_FLOAT r7, s19, ip
	COPY_FLOAT r7, s20, ip
	COPY_FLOAT r7, s21, ip
	COPY_FLOAT r7, s22, ip
	COPY_FLOAT r7, s23, ip
	COPY_FLOAT r7, s24, ip
	COPY_FLOAT r7, s25, ip
	COPY_FLOAT r7, s26, ip
	COPY_FLOAT r7, s27, ip
	COPY_FLOAT r7, s28, ip
	COPY_FLOAT r7, s29, ip
	COPY_FLOAT r7, s30, ip
	COPY_FLOAT r7, s31, ip

	.macro	COPY_DOUBLE rs, rdlo, rdhi, rcount
	.align	6
	flds	\rdhi, [\rs]
	flds	\rdlo, [\rs, #-4]
	add	\rs, #-8
	subs	\rcount, #2
	bge	.fast_copy_args
	b	.fast_no_args
	.endm

	.align	6
.copy_double_table:
	COPY_DOUBLE r7, s0, s1, ip
	COPY_DOUBLE r7, s2, s3, ip
	COPY_DOUBLE r7, s4, s5, ip
	COPY_DOUBLE r7, s6, s7, ip
	COPY_DOUBLE r7, s8, s9, ip
	COPY_DOUBLE r7, s10, s11, ip
	COPY_DOUBLE r7, s12, s13, ip
	COPY_DOUBLE r7, s14, s15, ip
	COPY_DOUBLE r7, s16, s17, ip
	COPY_DOUBLE r7, s18, s19, ip
	COPY_DOUBLE r7, s20, s21, ip
	COPY_DOUBLE r7, s22, s23, ip
	COPY_DOUBLE r7, s24, s25, ip
	COPY_DOUBLE r7, s26, s27, ip
	COPY_DOUBLE r7, s28, s29, ip
	COPY_DOUBLE r7, s30, s31, ip
#endif

#include "bytecodes_arm.s"

	Opcode	idiv

	POP	r1
	POP	r0
	cmp	r1, #0
	beq	divide_by_zero_exception
	bl	__aeabi_idiv
	PUSH	r0
	DISPATCH 1

	Opcode	idiv_clz

	POP	r1
	POP	r0
	bl	int_div
idiv_clz_ret:
	PUSH	r0
	DISPATCH 1

	Opcode	irem

	POP	r1
	POP	r0
	cmp	r1, #0
	beq	divide_by_zero_exception
	bl	__aeabi_idivmod
	PUSH	r1
	DISPATCH 1

	Opcode	irem_clz

	POP	r1
	POP	r0
	bl	int_rem
irem_clz_ret:
	PUSH	r0
	DISPATCH 1

	Opcode	goto
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
branch_taken:
        orr     r2, r2, r1, lsl #8
        DISPATCH_START_REG	r2
	cmp	r2, #0
	ble	do_backedge
	DISPATCH_FINISH

branch_taken_unsafe:
	mov	r2, r2, lsl #24
	orr	r2, r1, r2, asr #16
        DISPATCH_START_REG	r2
  USEC	cmp	r2, #0
  USEC	ble	do_backedge
	DISPATCH_FINISH

branch_taken_unsafe_1:
	add	jpc, jpc, #1
	orr	r2, ip, r1, lsl #8
        DISPATCH_START_REG	r2
  USEC	cmp	r2, #0
  USEC	ble	do_backedge
	DISPATCH_FINISH

branch_taken_unsafe_2:
	add	jpc, jpc, #2
	orr	r2, ip, r1, lsl #8
        DISPATCH_START_REG	r2
  USEC	cmp	r2, #0
  USEC	ble	do_backedge
	DISPATCH_FINISH

branch_taken_unsafe_3:
	add	jpc, jpc, #3
	orr	r2, ip, r1, lsl #8
        DISPATCH_START_REG	r2
  USEC	cmp	r2, #0
  USEC	ble	do_backedge
	DISPATCH_FINISH

branch_taken_unsafe_4:
	add	jpc, jpc, #4
	orr	r2, ip, r1, lsl #8
        DISPATCH_START_REG	r2
  USEC	cmp	r2, #0
  USEC	ble	do_backedge
	DISPATCH_FINISH

do_backedge:
  USEC	ldr	tmp1, [istate, #ISTATE_METHOD]
  OSR	ldr	lr, [dispatch, #InterpreterInvocationLimit_Address-XXX]
  USEC	ldr	r1, [tmp1, #METHOD_BACKEDGECOUNTER]
  USEC	ldr	ip, [tmp1, #METHOD_INVOCATIONCOUNTER]
  USEC	add	r1, r1, #INVOCATIONCOUNTER_COUNTINCREMENT
  OSR	ldr	lr, [lr]
  USEC	add	ip, ip, #INVOCATIONCOUNTER_COUNTINCREMENT
  USEC	str	r1, [tmp1, #METHOD_BACKEDGECOUNTER]
#ifdef T2JIT
  OSR	cmp	r1, lr
#else
  OSR	cmp	r1, lr, lsl #2
#endif
  USEC	str	ip, [tmp1, #METHOD_INVOCATIONCOUNTER]
  OSR	bcs	do_osr

osr_continue:
	ldr	ip, [dispatch, #SafePointSynchronize_state_Address-XXX]
	ldr	r1, [ip]
	cmp	r1, #1
	beq	do_synchronize
	DISPATCH_STATE	1
	DISPATCH_FINISH


do_synchronize:
	DECACHE_JPC
	DECACHE_STACK
	mov	r0, thread
	bl	Helper_SafePoint
	CACHE_CP
	CACHE_JPC
	cmp	r0, #0
	bne	handle_exception
	DISPATCH	0

#ifdef ON_STACK_REPLACEMENT

#ifdef T2JIT
do_osr:
	ldr	r3, [tmp1, #METHOD_CONSTMETHOD]
	DECACHE_JPC
	DECACHE_STACK
	mov	r0, thread
	sub	r1, jpc, r3
	sub	r1, r1, #CONSTMETHOD_CODEOFFSET
	bl	FREQ_COUNT_OVERFLOW
1:
	cmp	r0, #0
	bne	call_thumb2
	CACHE_CP
	CACHE_JPC
	DISPATCH_START	0
	b	osr_continue

#else

do_osr:
	ldr	ip, [dispatch, #UseOnStackReplacement_Address-XXX]
	ldrb	ip, [ip]
	cmp	ip, #0
	beq	osr_continue

	ldr	r3, [tmp1, #METHOD_CONSTMETHOD]
	DECACHE_JPC
	ldrh	r3, [r3, #CONSTMETHOD_CODESIZE]
	DECACHE_STACK
	mov	r0, thread
	sub	r1, jpc, r2
	cmp	r3, #MAX_FG_METHOD_SIZE
	bcc	1f
	ldr	tmp1, [dispatch, #BackgroundCompilation_Address-XXX]
	mov	r3, #1
	ldr	r5, [tmp1]
	str	r3, [tmp1]
	bl	FREQ_COUNT_OVERFLOW
	str	r5, [tmp1]
	b	2f
1:
	bl	FREQ_COUNT_OVERFLOW
2:
	CACHE_CP
	ldr	r1, [thread, #THREAD_PENDING_EXC]
	CACHE_JPC
	cmp	r1, #0
	bne	handle_exception
	cmp	r0, #0
	beq	1f
	ldr	r1, [r0, #56]
	cmn	r1, #2
	bne	osr_migrate
1:
	DISPATCH_START	0
	b	osr_continue

osr_migrate:
	ldr	tmp1, [r0, #128]	@ osr_method->osr_entry()
	mov	r0, thread
	bl	_ZN13SharedRuntime19OSR_migration_beginEP10JavaThread
	mov	r1, r0
	ldr	r0, [istate, #ISTATE_METHOD]
	ldrh	lr, [r0, #METHOD_MAXLOCALS]
	ldrh	ip, [r0, #METHOD_SIZEOFPARAMETERS]
	sub	lr, lr, ip
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	add	ip, r2, #4
	ldr	r2, [r2]
	add	ip, ip, lr, lsl #2
	str	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	str	ip, [thread, #THREAD_JAVA_SP]
	mov	r2, tmp1
@ r0 = method
@ r1 = osr_buf
@ r2 = osr_entry
	mov	lr, pc
	ldr	pc, [tmp1]

	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}

#endif // T2JIT

#endif // ON_STACK_REPLACEMENT

	Opcode	ifeq
	Opcode	ifnull
        POP     r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, #0
	beq	branch_taken
	DISPATCH	3

	Opcode	ifne
	Opcode	ifnonnull
        POP     r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, #0
	bne	branch_taken
	DISPATCH	3

	Opcode	iflt
        POP     r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, #0
	blt	branch_taken
	DISPATCH	3

	Opcode	ifge
        POP     r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, #0
	bge	branch_taken
	DISPATCH	3

	Opcode	ifgt
        POP     r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, #0
	bgt	branch_taken
	DISPATCH	3

	Opcode	ifle
        POP     r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, #0
	ble	branch_taken
	DISPATCH	3

	Opcode	if_icmpeq
	Opcode	if_acmpeq
        POP    r2, r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, r2
	beq	branch_taken
	DISPATCH	3

	Opcode	if_icmpne
	Opcode	if_acmpne
        POP    r2, r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, r2
	bne	branch_taken
	DISPATCH	3

	Opcode	if_icmplt
        POP    r2, r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, r2
	blt	branch_taken
	DISPATCH	3

	Opcode	if_icmpge
        POP    r2, r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, r2
	bge	branch_taken
	DISPATCH	3

	Opcode	if_icmpgt
        POP    r2, r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, r2
	bgt	branch_taken
	DISPATCH	3

	Opcode	if_icmple
        POP    r2, r3
        ldrsb   r1, [jpc, #1]
        ldrb    r2, [jpc, #2]
        cmp     r3, r2
	ble	branch_taken
	DISPATCH	3

	Opcode	ireturn
	Opcode	freturn
	Opcode	lreturn
	Opcode	dreturn
	Opcode	areturn
	Opcode	return
	ldr	r3, [dispatch, #SafePointSynchronize_state_Address-XXX]
	ldr	r1, [r3]
	cmp	r1, #1
	bne	handle_return
	DECACHE_JPC
	DECACHE_STACK
	mov	r0, thread
	bl	Helper_SafePoint
	CACHE_JPC
	cmp	r0, #0
	beq	handle_return
	b	handle_exception

resolve_get_put:
	mov	r1, r0
	mov	tmp1, lr
	@ stmfd	arm_sp!, {lr}
	mov	r0, thread
	DECACHE_JPC
        DECACHE_STACK
       	bl      _ZN18InterpreterRuntime15resolve_get_putEP10JavaThreadN9Bytecodes4CodeE
        ldr     r3, [thread, #THREAD_PENDING_EXC]
	CACHE_JPC
	CACHE_CP
        cmp     r3, #0
	mov	lr, tmp1
	@ ldmfd	arm_sp!, {lr}
        bne     getfield_exception
@ Now restart the getfield
        ldrb    r3, [jpc, #1]
        ldrb    r2, [jpc, #2]
        orr     r3, r3, r2, lsl #8      @ r3 = index
	add	tmp1, constpool, r3, lsl #4	@ tmp1 = cache
	bx	lr

accessor_non_w:
	bcs	accessor_h
	beq	accessor_sb
	tst	r0, #2
	bne	accessor_dw
accessor_sh:
	ldrsh	r0, [r3, r1]
	str	r0, [ip, #0]
	mov	r0, #0	@ deoptimized_frames = 0
	bx	lr
accessor_h:
	ldrh	r0, [r3, r1]
	str	r0, [ip, #0]
	mov	r0, #0	@ deoptimized_frames = 0
	bx	lr
accessor_sb:
	ldrsb	r0, [r3, r1]
	str	r0, [ip, #0]
	mov	r0, #0	@ deoptimized_frames = 0
	bx	lr
accessor_dw:
	add	r0, r3, r1
	ldm	r0, {r0, r1}
	sub	ip, ip, #4
	str	ip, [thread, #THREAD_JAVA_SP]
	stmia	ip, {r0, r1}
	mov	r0, #0	@ deoptimized_frames = 0
	bx	lr

	Opcode	getfield
	ldrb	r1, [jpc, #2]
        add     tmp1, constpool, r1, lsl #12
	add	tmp1, tmp1, r2, lsl #4
	ldr	r3, [tmp1, #CP_OFFSET]
        and     r3, r3, #0x00ff0000
        cmp     r3, #opc_getfield << 16
        blne    resolve_get_put
  NFBC	POP	r3
        ldr     r2, [tmp1, #CP_OFFSET+12]
  NFBC	cmp	r3, #0
  NFBC	beq	null_ptr_exception
  NFBC	ldr	tmp1, [tmp1, #CP_OFFSET+8]
        movs    r2, r2, lsr #29
  FBC	movhi	r0, #opc_igetfield
        bls     getfield_non_w
  NFBC	ldr	tmp1, [r3, tmp1]
  NFBC	PUSH	tmp1
  NFBC	DISPATCH 3

#ifdef FAST_BYTECODES
rewrite_bytecode:
	strb	r0, [jpc]
	DISPATCH_BYTECODE
#endif

getfield_non_w:
        bcs     getfield_h              @ C = 1 => R2 = 1
        beq     getfield_sb             @ Z = 1 => R2 = 0
        tst     r2, #2
        bne     getfield_dw

#ifdef FAST_BYTECODES
getfield_sh:
	mov	r0, #opc_sgetfield
	b	rewrite_bytecode
getfield_h:
	mov	r0, #opc_cgetfield
	b	rewrite_bytecode
getfield_sb:
	mov	r0, #opc_bgetfield
	b	rewrite_bytecode
getfield_dw:
	mov	r0, #opc_lgetfield
	b	rewrite_bytecode
#else
getfield_sh:
	ldrsh	tmp1, [r3, tmp1]
	PUSH	tmp1
	DISPATCH 3
getfield_h:
	ldrh	tmp1, [r3, tmp1]
	PUSH	tmp1
	DISPATCH 3
getfield_sb:
	ldrsb	tmp1, [r3, tmp1]
	PUSH	tmp1
	DISPATCH 3
getfield_dw:
	add	r3, r3, tmp1
	ldm	r3, {r2, tmp1}
	PUSH	r2, tmp1
	DISPATCH 3
#endif

	Opcode	putfield
	ldrb	r1, [jpc, #2]
        add     tmp1, constpool, r1, lsl #12
	add	tmp1, tmp1, r2, lsl #4
	ldr	r3, [tmp1, #CP_OFFSET]
        and     r3, r3, #0xff000000
        cmp     r3, #opc_putfield << 24
        blne    resolve_get_put
        ldr     r2, [tmp1, #CP_OFFSET+12]
  NFBC	ldr	tmp1, [tmp1, #CP_OFFSET+8]
        movs    r2, r2, lsr #29
	bls	putfield_non_w
  FBC   mov	r0, #opc_iputfield
	cmp	r2, #tos_atos >> 1
  FBC	moveq	r0, #opc_aputfield
  FBC	b	rewrite_bytecode
  NFBC	beq	putfield_a
  NFBC	POP	r2, r3
  NFBC	cmp	r3, #0
  NFBC	beq	null_ptr_exception
  NFBC	str	r2, [r3, tmp1]
  NFBC	DISPATCH 3

putfield_non_w:
	bcs	putfield_h
	beq	putfield_sb
	tst	r2, #2
	bne	putfield_dw

#ifdef FAST_BYTECODES
putfield_sh:
putfield_h:
	mov	r0, #opc_cputfield
	b	rewrite_bytecode
putfield_sb:
	mov	r0, #opc_bputfield
	b	rewrite_bytecode
putfield_dw:
	mov	r0, #opc_lputfield
	b	rewrite_bytecode
#else
putfield_sh:
putfield_h:
	POP	r2, r3
	cmp	r3, #0
	beq	null_ptr_exception
	strh	r2, [r3, tmp1]
	DISPATCH 3
putfield_sb:
	POP	r2, r3
	cmp	r3, #0
	beq	null_ptr_exception
	strb	r2, [r3, tmp1]
	DISPATCH 3
putfield_dw:
	POP	r2, r3, lr
	cmp	lr, #0
	beq	null_ptr_exception
	add	tmp1, lr, tmp1
	stm	tmp1, {r2, r3}
	DISPATCH 3
putfield_a:
	POP	r2, r3
	cmp	r3, #0
	beq	null_ptr_exception
	str	r2, [r3, tmp1]
	mov	r0, r3
	bl	Helper_aputfield
	DISPATCH 3
#endif

getstatic_sh:
	DISPATCH_START	3
	ldrsh	tmp1, [r3, lr]
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH
getstatic_h:
	DISPATCH_START	3
	ldrh	tmp1, [r3, lr]
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH
getstatic_sb:
	DISPATCH_START	3
	ldrsb	tmp1, [r3, lr]
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH
getstatic_dw:
	DISPATCH_START	3
	add	r3, r3, lr
	ldm	r3, {r2, tmp1}
	DISPATCH_NEXT
	PUSH	r2, tmp1
	DISPATCH_FINISH
getstatic_w:
	DISPATCH_START	3
	ldr	tmp1, [r3, lr]
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH

putstatic_sh:
putstatic_h:
	DISPATCH_START	3
	POP	tmp1
	DISPATCH_NEXT
	strh	tmp1, [r3, r2]
	DISPATCH_FINISH
putstatic_w:
	cmp	lr, #tos_atos >> 1	@ >> 1 due to lsr #29 above
	beq	putstatic_a
	DISPATCH_START	3
	POP	tmp1
	DISPATCH_NEXT
	str	tmp1, [r3, r2]
	DISPATCH_FINISH
putstatic_sb:
	DISPATCH_START	3
	POP	tmp1
	DISPATCH_NEXT
	strb	tmp1, [r3, r2]
	DISPATCH_FINISH
putstatic_dw:
	DISPATCH_START	3
	add	r2, r2, r3
	POP	r3, tmp1
	DISPATCH_NEXT
	stm	r2, {r3, tmp1}
	DISPATCH_FINISH
putstatic_a:
	POP	tmp1
	str	tmp1, [r3, r2]
	mov	r0, r3
	bl	Helper_aputfield
	DISPATCH 3

getstatic_volatile_sh:
	DISPATCH_START	3
	ldrsh	tmp1, [r3, lr]
	FullBarrier
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH
getstatic_volatile_h:
	DISPATCH_START	3
	ldrh	tmp1, [r3, lr]
	FullBarrier
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH
getstatic_volatile_sb:
	DISPATCH_START	3
	ldrsb	tmp1, [r3, lr]
	FullBarrier
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH
getstatic_volatile_dw:
	add	r3, r3, lr
#ifndef	__ARM_ARCH_7A__
	ldm	r3, {r2, tmp1}
	FullBarrier
	PUSH	r2, tmp1
#else
	ldrexd	r0, r1, [r3]
	FullBarrier
	PUSH	r0, r1
#endif
	DISPATCH	3
getstatic_volatile_w:
	DISPATCH_START	3
	ldr	tmp1, [r3, lr]
	FullBarrier
	DISPATCH_NEXT
	PUSH	tmp1
	DISPATCH_FINISH

putstatic_volatile_sh:
putstatic_volatile_h:
	DISPATCH_START	3
	POP	tmp1
	DISPATCH_NEXT
	StoreStoreBarrier
	strh	tmp1, [r3, r2]
	StoreLoadBarrier
	DISPATCH_FINISH
putstatic_volatile_w:
	cmp	lr, #tos_atos >> 1	@ >> 1 due to lsr #29 above
	beq	putstatic_volatile_a
	DISPATCH_START	3
	POP	tmp1
	DISPATCH_NEXT
	StoreStoreBarrier
	str	tmp1, [r3, r2]
	StoreLoadBarrier
	DISPATCH_FINISH
putstatic_volatile_sb:
	DISPATCH_START	3
	POP	tmp1
	DISPATCH_NEXT
	StoreStoreBarrier
	strb	tmp1, [r3, r2]
	StoreLoadBarrier
	DISPATCH_FINISH
putstatic_volatile_dw:
	add	ip, r2, r3
	POP	r0, r1
	StoreStoreBarrier
#ifndef	__ARM_ARCH_7A__
	stm	ip, {r0, r1}
#else
	// Data in tmp1 & tmp2, address in ip, r2 & r3 scratch
0:	ldrexd	r2, r3, [ip]
	strexd	r2, r0, r1, [ip]
	teq	r2, #0
	bne	0b
#endif
	DISPATCH_START	3
	StoreLoadBarrier
	DISPATCH_FINISH
putstatic_volatile_a:
	POP	tmp1
	StoreStoreBarrier
	str	tmp1, [r3, r2]
	mov	r0, r3
	bl	Helper_aputfield
	DISPATCH 3

resolve_invokeinterface:
	mov	r1, #opc_invokeinterface
	b	resolve_invoke
resolve_invokevirtual:
	mov	r1, #opc_invokevirtual
	b	resolve_invoke
resolve_invokespecial:
	mov	r1, #opc_invokespecial
	b	resolve_invoke
resolve_invokestatic:
	mov	r1, #opc_invokestatic
resolve_invoke:
	mov	tmp1, lr
	mov	r0, thread
	DECACHE_JPC
	DECACHE_STACK
	bl	_ZN18InterpreterRuntime14resolve_invokeEP10JavaThreadN9Bytecodes4CodeE
	CACHE_JPC
	ldr	r3, [thread, #THREAD_PENDING_EXC]
	CACHE_CP
	cmp	r3, #0
        ldrb    r3, [jpc, #1]
        ldrb    r2, [jpc, #2]
	bne	resolve_exception
        orr     r3, r3, r2, lsl #8      @ r3 = index
	add	r0, constpool, r3, lsl #4	@ r1 = cache
	bx	tmp1

# r2 = [jpc, #1]
# r1 = [jpc, #2]
	Opcode	new
	ldrb	r1, [jpc, #2]
	DECACHE_JPC
	DECACHE_STACK
	orr	r1, r1, r2, lsl #8
	mov	r0, r8
	bl	Helper_new
	CACHE_JPC
	CACHE_CP
	cmp	r0, #0
	beq	handle_exception
	PUSH	r0
	DISPATCH 3

bytecode_interpreter_str:
	.ascii  __FILE__
	.byte 0
	ALIGN_WORD

	Opcode	newarray
	ldrb	r1, [jpc, #1]	@ zero_extendqisi2
	ldr	r2, [stack, #4]
	mov	r0, thread
	DECACHE_JPC
	DECACHE_STACK
	bl	_ZN18InterpreterRuntime8newarrayEP10JavaThread9BasicTypei
	ldr	ip, [thread, #THREAD_PENDING_EXC]
	CACHE_JPC
	CACHE_CP
	cmp	ip, #0
	ldr	r2, [thread, #THREAD_VM_RESULT]
	bne	handle_exception
	str	r2, [stack, #4]
	str	ip, [thread, #THREAD_VM_RESULT]
	DISPATCH	2

	Opcode	anewarray
	ldrb	r0, [jpc, #1]	@ zero_extendqisi2
	ldr	r3, [stack, #4]
	ldr	lr, [istate, #ISTATE_METHOD]
	ldrb	r2, [jpc, #2]	@ zero_extendqisi2
	orr	r2, r2, r0, asl #8
	DECACHE_JPC
	DECACHE_STACK
	ldr	r1, [lr, #METHOD_CONSTANTS]
	mov	r0, thread
	bl	_ZN18InterpreterRuntime9anewarrayEP10JavaThreadP19constantPoolOopDescii
	ldr	ip, [thread, #THREAD_PENDING_EXC]
	CACHE_JPC
	CACHE_CP
	cmp	ip, #0
	ldr	r2, [thread, #THREAD_VM_RESULT]
	bne	handle_exception
	str	r2, [stack, #4]
	str	ip, [thread, #THREAD_VM_RESULT]
	DISPATCH	3

	Opcode	arraylength
	DISPATCH_START	1
	ldr	r3, [stack, #4]
	DISPATCH_NEXT
	DISPATCH_NEXT
	SW_NPC	cmp	r3, #0
	SW_NPC	beq	null_ptr_exception_jpc_1
.abortentry114:
	ldr	r3, [r3, #8]
	DISPATCH_NEXT
	DISPATCH_NEXT
	str	r3, [stack, #4]
	DISPATCH_FINISH

	Opcode	athrow
	ldr	r1, [stack, #4]
	cmp	r1, #0
	beq	null_ptr_exception
	mov	r2, #0
	mov	r0, thread
	mov	r3, r2
	bl	_ZN12ThreadShadow21set_pending_exceptionEP7oopDescPKci
	b	handle_exception

#define secondary_super_cache_offset_in_bytes	20
#define tmp_chunk	locals
#define tmp_hwm		stack
#define	tmp_max		constpool

# r2 = [jpc, #1]
# r1 = [jpc, #2]
	Opcode	checkcast
	ldrb	r1, [jpc, #2]
	DECACHE_JPC
	DECACHE_STACK
	orr	r1, r1, r2, lsl #8
	mov	r0, r8
	GET_STACK	0, r2
	bl	Helper_checkcast
	CACHE_JPC
	CACHE_CP
	cmp	r0, #0
	bne	handle_exception
	DISPATCH 3

# r2 = [jpc, #1]
# r1 = [jpc, #2]
	Opcode	instanceof
	ldrb	r1, [jpc, #2]
	DECACHE_JPC
	DECACHE_STACK
	orr	r1, r1, r2, lsl #8
	mov	r0, r8
	POP	r2
	bl	Helper_instanceof
	CACHE_JPC
	CACHE_CP
	cmp	r0, #-1
	beq	handle_exception
	PUSH	r0
	DISPATCH 3

	Opcode	monitorenter
	mov	r0, r8
	POP	r1
 	DECACHE_JPC
 	DECACHE_STACK
	bl	Helper_monitorenter
	CACHE_JPC
	CACHE_CP
	CACHE_STACK		@ monitorenter may expand stack!!!	
	cmp	r0, #0
	bne	handle_exception
	DISPATCH 1

	Opcode	monitorexit
	mov	r0, r8
	POP	r1
	DECACHE_JPC
	DECACHE_STACK
	bl	Helper_monitorexit
	CACHE_JPC
	CACHE_CP
	cmp	r0, #0
	bne	handle_exception
	DISPATCH 1

	ALIGN_CODE
vm_fatal_error:
	adr	r0, .fatal_filename
	mov	r1, #99
	bl	_Z28report_should_not_reach_herePKci
	b	breakpoint
.fatal_filename:
	.ascii	"[Optimsed Assembler Interpreter Loop]\000"

// This extra entry point for vm_fatal_error (at vm_fatal_error +
// CODE_ALIGN_SIZE) allows vm_fatal_error to be used as an entry point
// in the asm_method_table.
	ALIGN_CODE	
	b	vm_fatal_error

	ALIGN_WORD

	Opcode	aastore
	DECACHE_JPC
	DECACHE_STACK
	mov	r0, r8
	POP	r1, r2, r3
	bl	Helper_aastore
	CACHE_JPC
	CACHE_CP
	cmp	r0, #0
	bne	handle_exception
	DISPATCH 1

	Opcode	wide
	ldrb	r2, [jpc, #1]
	ldrb	r1, [jpc, #2]	@ zero_extendqisi2
	ldrb	r3, [jpc, #3]	@ zero_extendqisi2

	sub	lr, r2, #opc_aload+1
	cmp	lr, #opc_istore - (opc_aload+1)
	bcc	wide_undef_opc_exception

	sub	lr, r2, #opc_iload
	cmp	r2, #opc_istore
	subcs	lr, lr, #opc_istore - (opc_aload+1)
	cmp	r2, #opc_astore+1

	orr	r1, r3, r1, asl #8
	adr	r3, wide_case_table
	ldrcc	pc, [r3, lr, lsl #2]
	
	cmp	r2, #opc_ret
	beq	do_wide_ret
	cmp	r2, #opc_iinc
	beq	do_wide_iinc
wide_undef_opc_exception:
	mov	r0, #VMSYMBOLS_InternalError
	adr	r1, undef_opcode_msg
	b	raise_exception_with_msg
undef_opcode_msg:
	.ascii  "undefined opcode\000"
	ALIGN_WORD

wide_case_table:
        .word	case_wide_iload
        .word	case_wide_lload
        .word	case_wide_fload
        .word	case_wide_dload
        .word	case_wide_aload
        .word	case_wide_istore
        .word	case_wide_lstore
        .word	case_wide_fstore
        .word	case_wide_dstore
        .word	case_wide_astore

case_wide_iload:
case_wide_fload:
case_wide_aload:
	ldr	r2, [locals, -r1, lsl #2]
	PUSH	r2
	DISPATCH	4
case_wide_istore:
case_wide_fstore:
case_wide_astore:
	POP	r2
	str	r2, [locals, -r1, lsl #2]
	DISPATCH	4
case_wide_dload:
case_wide_lload:
	sub	r1, locals, r1, lsl #2
	ldmda	r1, {r1, r2}
	PUSH	r1, r2
	DISPATCH	4
case_wide_dstore:
case_wide_lstore:
	POP	r2, r3
	sub	r1, locals, r1, lsl #2
	stmda	r1, {r2, r3}
	DISPATCH	4
do_wide_ret:
	ldr	r2, [istate, #ISTATE_METHOD]
	ldr	r2, [r2, #METHOD_CONSTMETHOD]
	ldr	r1, [locals, -r1, lsl #2]
	add	jpc, r2, r1
	DISPATCH	CONSTMETHOD_CODEOFFSET
do_wide_iinc:
	ldrsb	r2, [jpc, #4]
	ldrb	r3, [jpc, #5]
	orr	r2, r3, r2, lsl #8
	ldr	r3, [locals, -r1, lsl #2]
	add	r3, r3, r2
	str	r3, [locals, -r1, lsl #2]
	DISPATCH	6

	Opcode	multianewarray
	ldrb	tmp1, [jpc, #3]	@ zero_extendqisi2
	mov	r0, thread
	add	r1, stack, tmp1, lsl #2
	DECACHE_JPC
	DECACHE_STACK
	bl	_ZN18InterpreterRuntime14multianewarrayEP10JavaThreadPi
	CACHE_JPC
	ldr	r1, [thread, #THREAD_PENDING_EXC]
	CACHE_CP
	cmp	r1, #0
	ldr	r3, [thread, #THREAD_VM_RESULT]
	bne	handle_exception
	str	r3, [stack, tmp1, asl #2]!
	str	r1, [thread, #THREAD_VM_RESULT]
	sub	stack, stack, #4
	DISPATCH	4

	Opcode	jsr_w
	ldr	r3, [istate, #ISTATE_METHOD]
	ldr	r1, [r3, #METHOD_CONSTMETHOD]
	rsb	r2, r1, jpc
	sub	r2, r2, #CONSTMETHOD_CODEOFFSET - 5
	str	r2, [stack], #-4
	b	do_goto_w

	Opcode	goto_w
	add	r2, jpc, #1
	ldrb	tmp1, [jpc, #1]	@ zero_extendqisi2
	ldrb	r3, [r2, #3]	@ zero_extendqisi2
	ldrb	r0, [r2, #1]	@ zero_extendqisi2
	ldrb	ip, [r2, #2]	@ zero_extendqisi2
	orr	r3, r3, tmp1, asl #24
	orr	r3, r3, r0, asl #16
	orr	r3, r3, ip, asl #8
	cmp	r3, #0
	add	jpc, jpc, r3
	bgt	1f

	ldr	r3, [dispatch, #SafePointSynchronize_state_Address-XXX]
	ldr	r1, [r3]
	cmp	r1, #1
	bne	1f
	DECACHE_JPC
	DECACHE_STACK
	mov	r0, thread
	bl	Helper_SafePoint
	CACHE_JPC
	CACHE_CP
	cmp	r0, #0
	bne	handle_exception
1:
	DISPATCH	0

	Opcode	breakpoint
	mov	r2, jpc
	DECACHE_STACK
	DECACHE_JPC
	mov	r0, thread
	ldr	r1, [istate, #ISTATE_METHOD]
	bl	_ZN18InterpreterRuntime24get_original_bytecode_atEP10JavaThreadP13methodOopDescPh
	mov	tmp1, r0
	mov	r0, thread
	ldr	r3, [thread, #THREAD_PENDING_EXC]
	cmp	r3, #0
	bne	handle_exception
	ldr	r2, [istate, #ISTATE_BCP]
	ldr	r1, [istate, #ISTATE_METHOD]
	bl	_ZN18InterpreterRuntime11_breakpointEP10JavaThreadP13methodOopDescPh
	CACHE_JPC
	ldr	r3, [thread, #THREAD_PENDING_EXC]
	CACHE_CP
	cmp	r3, #0
	and	r0, tmp1, #255
	bne	handle_exception
	DISPATCH_BYTECODE

#ifndef FAST_BYTECODES
	Opcode	bgetfield
	Opcode	cgetfield
	Opcode	igetfield
	Opcode	lgetfield
	Opcode	sgetfield
	Opcode	aputfield
	Opcode	bputfield
	Opcode	cputfield
	Opcode	iputfield
	Opcode	lputfield
	Opcode	invokevfinal
	Opcode	invokeresolved
	Opcode	invokespecialresolved
	Opcode	invokestaticresolved
	Opcode	iaccess_0
	Opcode	iload_0_iconst_N
	Opcode	iload_iconst_N
	Opcode	iadd_istore_N
	Opcode	isub_istore_N
	Opcode	iand_istore_N
	Opcode	ior_istore_N
	Opcode	ixor_istore_N
	Opcode	iadd_u4store
	Opcode	isub_u4store
	Opcode	iand_u4store
	Opcode	ior_u4store
	Opcode	ixor_u4store
	Opcode	fast_iload_iload
	Opcode	fast_iload_iload_N
	Opcode	fast_iload_N_iload
	Opcode	fast_iload_N_iload_N
#endif
	Opcode	undefined
	// Decache to get better diagnostic info
	DECACHE_JPC
	DECACHE_STACK
	ldr	r2, [dispatch, #Bytecodes_name_Address-XXX]
	ldrb	r3, [jpc, #0]	@ zero_extendqisi2
	adrl	r0, bytecode_interpreter_str
	cmp	r3, #last_implemented_bytecode+1
	adrcs	ip, unknown_bytecode
	ldrcc	ip, [r2, r3, asl #2]
	adr	r2, unimplemented_opcode_msg
	ldr	r1, =__LINE__
	str	ip, [arm_sp, #-8]!
 	bl	Helper_report_fatal
	b	breakpoint
	.ltorg
unimplemented_opcode_msg:
	.ascii  "\011*** Unimplemented opcode: %d = %s\012\000"
unknown_bytecode:
	.ascii	"<unknown>\000"
	ALIGN_WORD

	Opcode	return_register_finalizer
	ldr	r1, [locals, #0]
	ldr	r3, [r1, #4]
	ldr	r2, [r3, #KLASS_PART+KLASS_ACCESSFLAGS]
	tst	r2, #JVM_ACC_HAS_FINALIZER
	beq	handle_return
	DECACHE_JPC
	DECACHE_STACK
	mov	r0, thread
	bl	_ZN18InterpreterRuntime18register_finalizerEP10JavaThreadP7oopDesc
	CACHE_JPC
	ldr	r3, [thread, #THREAD_PENDING_EXC]
@ CACHE_LOCALS & CACHE_CP not require for handle_retuen / handle_exception
	cmp	r3, #0
	beq	handle_return
	b	handle_exception

// This code is logically part of normal_entry_synchronized, but it's
// been moved out because there is only a FAST_ENTRY_OFFSET sized gap
// here.

.normal_entry_return_synchronized:
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {regset, pc}
	SLOW_ENTRY
normal_entry_synchronized:
	stmfd	arm_sp!, {regset, lr}
	mov	thread, r2
	ldr	r7, [thread, #THREAD_STACK_SIZE]
	ldr	r3, [thread, #THREAD_STACK_BASE]
	rsb	r3, r7, r3
	rsb	r3, r3, arm_sp
	cmp	r3, #32768
	blt	stack_overflow_no_frame
	add	lr, pc, #(.normal_entry_return_synchronized-(.fast_normal_entry1+4))
.fast_normal_entry1:

	FAST_ENTRY
fast_normal_entry_synchronized:
	stmfd	arm_sp!, {fast_regset, lr}

	mov	tmp1, r0

	ldrh	r2, [tmp1, #METHOD_MAXLOCALS]
	ldrh	r3, [tmp1, #METHOD_SIZEOFPARAMETERS]
	rsb	r8, r3, r2

	ldr	r1, [thread, #THREAD_JAVA_SP]
	ldrh	r0, [tmp1, #METHOD_MAXSTACK]
	ldr	r3, [thread, #THREAD_JAVA_STACK_BASE]

	sub	r5, r1, r8, lsl #2
	sub	r5, r5, #FRAME_SIZE+STACK_SPARE+LEAF_STACK_SIZE
	sub	r5, r5, r0, lsl #2
	cmp	r3, r5
	bcs	stack_overflow_before_frame

	cmp	r8, #0
	ble	.normal_entry_synchronized_no_locals

	mov	r2, #0
.zero_locals_synchronized:
	subs	r8, r8, #1
	str	r2, [r1, #-4]!
	bgt	.zero_locals_synchronized
	str	r1, [thread, #THREAD_JAVA_SP]

.normal_entry_synchronized_no_locals:
	mov	r2, thread
	mov	r1, tmp1
	add	r0, thread, #THREAD_JAVA_STACK_BASE
	bl	build_frame
	ldr	ip, [thread, #THREAD_TOP_ZERO_FRAME]
	sub	istate, r0, #ISTATE_NEXT_FRAME
	mov	r2, #0  @ set SP to zero before setting FP
	str	r0, [thread, #THREAD_TOP_ZERO_FRAME]
	str	r2, [thread, #THREAD_LAST_JAVA_SP]
	str	r0, [thread, #THREAD_LAST_JAVA_FP]
	ldr	r3, [thread, #THREAD_JAVA_SP]
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
	str	ip, [istate, #ISTATE_NEXT_FRAME]
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r0, r1}
	add	r0, r0, ip
	add	dispatch, r1, r0
	ldr	r0, [istate, #ISTATE_METHOD]
	ldr	r3, [r0, #METHOD_ACCESSFLAGS]
	tst	r3, #JVM_ACC_SYNCHRONIZED
	beq	1f

@ Do Synchronisation
	CACHE_STACK
	CACHE_LOCALS
	tst	r3, #JVM_ACC_STATIC
	ldrne	r3, [r0, #METHOD_CONSTANTS]
	ldreq	tmp1, [locals, #0]
	ldrne	r2, [r3, #CONSTANTPOOL_POOL_HOLDER]
	ldrne	tmp1, [r2, #KLASS_PART+KLASS_JAVA_MIRROR]
	ldr	r3, [tmp1, #0]
	orr	tmp_xxx, r3, #1
	ldr	ip, [istate, #ISTATE_MONITOR_BASE]
	str	tmp_xxx, [ip, #-8]
.normal_do_synchronisation_2:
	ldr	tmp_vvv, [tmp1, #0]
	cmp	tmp_xxx, tmp_vvv
	bne	.normal_do_synchronisation_3
	mov	r0, tmp_xxx
	ldr	r1, [istate, #ISTATE_MONITOR_BASE]
	sub	r1, r1, #8
	mov	r2, tmp1
	mov	r3, #0xffffffc0
	bic	r3, r3, #0xf000
	blx	r3
	cmp	r0, #0
	bne	.normal_do_synchronisation_2
	b	1f
.normal_do_synchronisation_3:
	mov	r0, thread
	bic	r1, tmp_xxx, #3
	bl	JavaThread_is_lock_owned
	cmp	r0, #0
	beq	.normal_do_synchronisation_4
	ldr	ip, [istate, #ISTATE_MONITOR_BASE]
	mov	r3, #0
	str	r3, [ip, #-8]
	b	1f
.normal_do_synchronisation_4:
	ldr	r1, [istate, #ISTATE_MONITOR_BASE]
	sub	r1, r1, #8
	DECACHE_STACK
	mov	r0, thread
	bl	_ZN18InterpreterRuntime12monitorenterEP10JavaThreadP15BasicObjectLock
	ldr	r3, [thread, #THREAD_PENDING_EXC]
	cmp	r3, #0
	mov	r2, r0
	bne	handle_exception_do_not_unlock
1:
  USEC ldr	r0, [istate, #ISTATE_METHOD]
  USEC	ldr	r2, [r0, #METHOD_INVOCATIONCOUNTER]
  USEC	ldr	lr, [dispatch, #InterpreterInvocationLimit_Address-XXX]
  USEC	add	r2, r2, #INVOCATIONCOUNTER_COUNTINCREMENT
  USEC	ldr	lr, [lr]
  USEC	str	r2, [r0, #METHOD_INVOCATIONCOUNTER]
  USEC	cmp	r2, lr
  USEC	bcs	sync_method_entry_freq_count_overflow
	CACHE_JPC
	CACHE_LOCALS
	CACHE_CP
	DISPATCH	0

#ifdef USE_COMPILER
sync_method_entry_freq_count_overflow:
        ldr     r3, [r0, #METHOD_CONSTMETHOD]
        ldrh    r3, [r3, #CONSTMETHOD_CODESIZE]
	mov	r1, #0
	mov	r0, thread
        cmp     r3, #MAX_FG_METHOD_SIZE
        bcc     1f
        ldr     tmp1, [dispatch, #BackgroundCompilation_Address-XXX]
        mov     r3, #1
        ldr     r5, [tmp1]
        str     r3, [tmp1]
        bl      FREQ_COUNT_OVERFLOW
        str     r5, [tmp1]
        b       2f
1:
	bl	FREQ_COUNT_OVERFLOW
2:
  T2	cmp	r0, #0
	CACHE_LOCALS
  T2	bne	call_thumb2
	CACHE_JPC
	CACHE_CP
	DISPATCH	0
#endif

# r2 = [jpc, #1]
# r1 = [jpc, #2]
	Opcode	invokeinterface
	ldrb	r1, [jpc, #2]
	DECACHE_STACK
        add     r0, constpool, r1, lsl #12
	add	r0, r0, r2, asl #4
	DECACHE_JPC
        ldr     r2, [r0, #CP_OFFSET]
        and     r2, r2, #0x00ff0000
        cmp     r2, #opc_invokeinterface << 16
        blne    resolve_invokeinterface

	ldr	r3, [r0, #CP_OFFSET+12]
	and	r2, r3, #255
	ldr	r2, [stack, r2, lsl #2]
	SW_NPC	cmp	r2, #0
	SW_NPC	beq	null_ptr_exception
.abortentry110:
	ldr	tmp1, [r2, #4]				@ rcvr->klass()
	tst	r3, #flag_methodInterface
	bne	.invokeinterface_methodInterface

	ldr	lr, [r0, #CP_OFFSET+4]			@ lr = iclass

	add	r1, tmp1, #INSTANCEKLASS_VTABLE_OFFSET
	ldr	r2, [tmp1, #KLASS_PART+INSTANCEKLASS_VTABLE_LEN]
	ldr	ip, [tmp1, #KLASS_PART+INSTANCEKLASS_ITABLE_LEN]
	add	r2, r2, #1
	bic	r2, r2, #1

	add	r1, r1, r2, lsl #2

	mov	r2, #0
1:
	cmp	r2, ip
	beq	incompatibleclass_exception
	ldr	r3, [r1], #8
	add	r2, r2, #1
	cmp	lr, r3
	bne	1b

	ldr	r3, [r0, #CP_OFFSET+8]
	ldr	r2, [r1, #-4]
	add	r3, tmp1, r3, lsl #2
	ldr	tmp1, [r3, r2]
	cmp	tmp1, #0
	beq	abstractmethod_exception
.invokeinterface_invoke:
	ldr	ip, [tmp1, #METHOD_FROM_INTERPRETED]
	mov	r1, #0
	str	r1, [thread, #THREAD_LAST_JAVA_FP]
	str	r1, [thread, #THREAD_LAST_JAVA_SP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [ip]

	mov	r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
	add	r3, r3, #FAST_ENTRY_OFFSET
#endif
	blx	r3

	adrl	ip, dispatch_init_adcon
	ldm	ip, {r0, r1}
	add	r0, r0, ip
	add	dispatch, r1, r0

	CACHE_LOCALS

	CACHE_JPC
	ldr	stack, [thread, #THREAD_JAVA_SP]
	ldr	r2, [istate, #ISTATE_STACK_LIMIT]
	sub	stack, stack, #4

	ldr	r1, [thread, #THREAD_JAVA_SP]
	stmfd	arm_sp!, {r1}
	mov	r1, #0
	str	r1, [thread, #THREAD_LAST_JAVA_SP]
	ldr	r1, [thread, #THREAD_TOP_ZERO_FRAME]
	add	r2, r2, #4
	str	r2, [thread, #THREAD_JAVA_SP]
	str	r1, [thread, #THREAD_LAST_JAVA_FP]
	ldmfd	arm_sp!, {r1}
	str	r1, [thread, #THREAD_LAST_JAVA_SP]
	DISPATCH_START	5
	ldr	r3, [thread, #THREAD_PENDING_EXC]
	DISPATCH_NEXT
	DISPATCH_NEXT
	cmp	r3, #0
	DISPATCH_NEXT
	bne	invokeinterface_exception_fix
	DISPATCH_NEXT
	CACHE_CP
	DISPATCH_FINISH

.invokeinterface_methodInterface:
	tst	r3, #flag_vfinalMethod
	ldrne	tmp1, [r0, #CP_OFFSET+8]
	bne	.invokeinterface_invoke
	ldr	r1, [r0, #CP_OFFSET+8]
	add	r3, tmp1, r1, lsl #2
	ldr	tmp1, [r3, #INSTANCEKLASS_VTABLE_OFFSET]
	b	.invokeinterface_invoke

# r2 = [jpc, #1]
	Opcode	invokedynamic
	DECACHE_STACK
	// Fetch index bytes from bytecode
	ldrb	r0, [jpc, #2]
	ldrb	r1, [jpc, #3]
	ldrb	r3, [jpc, #4]
	orr	r2, r2, r0, lsl #8
	orr	r2, r2, r1, lsl #16
	orr	r1, r2, r3, lsl #24
	// The index is inverted, so we invert it back with MVN
        mvn     r1, r1
	// The pool entry is in R0
        add     r0, constpool, r1, lsl #4

	// Save the pool entry
	stmfd	arm_sp!, {r0}

	DECACHE_JPC
	ldr     r1, [r0, #CP_OFFSET+4]  // Pointer to call site
	// Already resolved?
	cmp     r1, #0 
	bleq    resolve_invokedynamic

	// Get the offset from a call site to the corresponding target
	// method handle
	bl	Helper_target_offset_in_bytes
	mov	lr, r0

	// Restore the pool entry
	ldmfd	arm_sp!, {r0}

	ldr	r0, [r0, #CP_OFFSET+4]	// Call site
.abortentry119:
	ldr	r0, [r0, lr]		// Method handle
	mov	r1, thread

	// Call the target method
	bl	_ZN14CppInterpreter21process_method_handleEP7oopDescP6Thread

	// Load up the interpreter registers.  Probably not necessary
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r0, r1}
	add	r0, r0, ip
	add	dispatch, r1, r0

	CACHE_LOCALS

	CACHE_JPC
	ldr	stack, [thread, #THREAD_JAVA_SP]
	ldr	r2, [istate, #ISTATE_STACK_LIMIT]
	sub	stack, stack, #4

	// Fix up everything in the thread state to point to the
	// current frame
	ldr	r1, [thread, #THREAD_JAVA_SP]
	stmfd	arm_sp!, {r1}
	mov	r1, #0
	str	r1, [thread, #THREAD_LAST_JAVA_SP]
	ldr	r1, [thread, #THREAD_TOP_ZERO_FRAME]
	add	r2, r2, #4
	str	r2, [thread, #THREAD_JAVA_SP]
	str	r1, [thread, #THREAD_LAST_JAVA_FP]
	ldmfd	arm_sp!, {r1}
	str	r1, [thread, #THREAD_LAST_JAVA_SP]
	DISPATCH_START	5
	// Test for an exception
	ldr	r3, [thread, #4]
	DISPATCH_NEXT
	DISPATCH_NEXT
	cmp	r3, #0
	DISPATCH_NEXT
	bne	invokedynamic_exception_fix
	DISPATCH_NEXT
	CACHE_CP
	DISPATCH_FINISH

resolve_invokedynamic:
	stmfd	arm_sp!, {lr}
	ldr	r0, [istate, #ISTATE_THREAD]
	bl	_ZN18InterpreterRuntime21resolve_invokedynamicEP10JavaThread
	ldmfd	arm_sp!, {pc}

	// Handler for java.lang.invoke.MethodHandles::invoke
	ALIGN_CODE
method_handle_entry:
	stmfd   arm_sp!, {thread, lr}
	mov     thread, r2
	bl      fast_method_handle_entry
	ldmfd   arm_sp!, {thread, pc}
	ALIGN_CODE
fast_method_handle_entry:
	stmfd	arm_sp!, {regset, lr}
	mov	r2, thread
	bl	_ZN14CppInterpreter19method_handle_entryEP13methodOopDesciP6Thread
	ldmia	sp!, {regset, pc}

	// Common code for fast_aldc and fast_aldc_w
# r0 = constpool cache entry
	.macro	aldc	opc, seq_len
	// Save the pool entry
	stmfd	arm_sp!, {r0}

	DECACHE_JPC
	ldr     r1, [r0, #CP_OFFSET+4]  // Pointer to call site
	// Already resolved?
	cmp     r1, #0 
	mov	r0, thread
	mov	r1, #\opc
	bleq    _ZN18InterpreterRuntime11resolve_ldcEP10JavaThreadN9Bytecodes4CodeE

	// Restore the pool entry
	ldmfd	arm_sp!, {r0}

	ldr     r1, [r0, #CP_OFFSET+4]  // Pointer to MethodHandle
	PUSH	r1

	// Test for an exception
	ldr	r3, [thread, #4]
	cmp	r3, #0
	bne	handle_exception
	
	DISPATCH	\seq_len
	.endm

	// Handler for ldc MethodHandle
# r2 = [jpc, #1]
	Opcode fast_aldc
	DECACHE_STACK
        add     r0, constpool, r2, lsl #4
	aldc opc_fast_aldc, 2

	// Handler for ldc_w MethodHandle
# r2 = [jpc, #1]
# r1 = [jpc, #2]
	Opcode fast_aldc_w
	// Fetch index bytes from bytecode
	ldrb	r1, [jpc, #2]
	DECACHE_STACK
	orr	r1, r2, r1, lsl #8
        add     r0, constpool, r1, lsl #4
	aldc opc_fast_aldc_w, 3

#ifdef FAST_BYTECODES
# r2 = [jpc, #1]
# r1 = [jpc, #2]
	Opcode	invokevfinal
	ldrb	r1, [jpc, #2]
	DECACHE_STACK
	add	r0, constpool, r1, lsl #12
	DECACHE_JPC
	add	r0, r2, asl #4
	ldr	r3, [r0, #CP_OFFSET+12]
	and	r1, r3, #255
	ldr	r2, [stack, r1, asl #2]
	mov	r1, #0
	SW_NPC	cmp	r2, #0
	SW_NPC	beq	null_ptr_exception
.abortentry117:
	HW_NPC	ldr	r3, [r2]		@ Only to provoke abort

	ldr	tmp1, [r0, #CP_OFFSET+8]

	ldr	ip, [tmp1, #METHOD_FROM_INTERPRETED]
	str	r1, [thread, #THREAD_LAST_JAVA_SP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [ip, #0]
	b	normal_dispatch_and_return
#endif // FAST_BYTECODES

# r2 = [jpc, #1]
# r1 = [jpc, #2]
        Opcode  invokevirtual
	ldrb	r1, [jpc, #2]
        add     r0, constpool, r1, lsl #12
	add	r0, r0, r2, asl #4
        ldr     r2, [r0, #CP_OFFSET]
        and     r2, r2, #0xff000000
        cmp     r2, #opc_invokevirtual << 24
        blne    resolve_invokevirtual
        ldr     r3, [r0, #CP_OFFSET+12]
#ifdef FAST_BYTECODES
        mov     r0, #opc_invokeresolved
        tst     r3, #flag_vfinalMethod
        movne   r0, #opc_invokevfinal
        b       rewrite_bytecode
#else
        DECACHE_STACK
	DECACHE_JPC
        and     r1, r3, #255
        ldr     r2, [stack, r1, asl #2]
        mov     r1, #0
        cmp     r2, #0
        beq     null_ptr_exception

        ldr     tmp1, [r0, #CP_OFFSET+8]
        tst     r3, #flag_vfinalMethod
        bne     1f

        ldr     r3, [r2, #4]
        add     r3, r3, tmp1, lsl #2
        ldr     tmp1, [r3, #INSTANCEKLASS_VTABLE_OFFSET]
1:
#endif // FAST_BYTECODES

#ifdef FAST_BYTECODES
# r2 = [jpc, #1]
# r1 = [jpc, #2]
        Opcode  invokeresolved
	ldrb	r1, [jpc, #2]
        DECACHE_STACK
        add     r0, constpool, r1, lsl #12
	DECACHE_JPC
        add     r0, r0, r2, asl #4
        ldr     r3, [r0, #CP_OFFSET+12]
        and     r1, r3, #255
        ldr     r2, [stack, r1, asl #2]
        mov     r1, #0
        SW_NPC	cmp     r2, #0
        SW_NPC	beq     null_ptr_exception_jpc_0

        ldr     tmp1, [r0, #CP_OFFSET+8]
.abortentry104:
        ldr     r3, [r2, #4]
        add     r3, r3, tmp1, lsl #2
        ldr     tmp1, [r3, #INSTANCEKLASS_VTABLE_OFFSET]
#endif // FAST_BYTECODES
        ldr     ip, [tmp1, #METHOD_FROM_INTERPRETED]
        str     r1, [thread, #THREAD_LAST_JAVA_SP]

        add     stack, stack, #4
        str     stack, [thread, #THREAD_JAVA_SP]

        ldr     r3, [ip, #0]

normal_dispatch_and_return:
	mov	r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
	add	r3, r3, #FAST_ENTRY_OFFSET
#endif
	blx	r3

	adrl	ip, dispatch_init_adcon
	ldm	ip, {r0, r1}
	add	r0, r0, ip
	add	dispatch, r1, r0

	CACHE_LOCALS

	CACHE_JPC
	ldr	stack, [thread, #THREAD_JAVA_SP]
	ldr	r2, [istate, #ISTATE_STACK_LIMIT]
	sub	stack, stack, #4

	ldr	r1, [thread, #THREAD_TOP_ZERO_FRAME]
	add	r2, r2, #4
	mov	r3, #0
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
	str	r2, [thread, #THREAD_JAVA_SP]
	str	r1, [thread, #THREAD_LAST_JAVA_FP]
	str	r2, [thread, #THREAD_LAST_JAVA_SP]
	DISPATCH_START	3
	ldr	r3, [thread, #THREAD_PENDING_EXC]
	DISPATCH_NEXT
	DISPATCH_NEXT
	cmp	r3, #0
	DISPATCH_NEXT

	bne	invoke_exception_fix
	DISPATCH_NEXT
	CACHE_CP
	DISPATCH_FINISH

	Opcode	invokestatic
	ldrb	r1, [jpc, #2]
        add     r0, constpool, r1, lsl #12
	add	r0, r0, r2, asl #4
        ldr     r2, [r0, #CP_OFFSET]
	and	r2, r2, #0x00ff0000
	cmp	r2, #opc_invokestatic << 16
	blne	resolve_invokestatic
  FBC	mov	r0, #opc_invokestaticresolved
  FBC	b	rewrite_bytecode

  FBC	Opcode	invokestaticresolved
  FBC	ldrb	r1, [jpc, #2]
        DECACHE_STACK
  FBC   add     r0, constpool, r1, lsl #12
	DECACHE_JPC
  FBC	add	r0, r2, asl #4

	ldr	tmp1, [r0, #CP_OFFSET+4]
	mov	r1, #0
	ldr	r3, [tmp1, #METHOD_FROM_INTERPRETED]
	str	r1, [thread, #THREAD_LAST_JAVA_SP]
	str	r1, [thread, #THREAD_LAST_JAVA_FP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [r3, #0]
	b	normal_dispatch_and_return


	Opcode	invokespecial
     	ldrb	r1, [jpc, #2]
        add     r0, constpool, r1, lsl #12
	add	r0, r0, r2, asl #4
        ldr     r2, [r0, #CP_OFFSET]
        and     r2, r2, #0x00ff0000
        cmp     r2, #opc_invokespecial << 16
        blne     resolve_invokespecial
  FBC	mov	r0, #opc_invokespecialresolved
  FBC	b	rewrite_bytecode

  FBC	Opcode	invokespecialresolved
  FBC	ldrb	r1, [jpc, #2]
        DECACHE_STACK
  FBC   add     r0, constpool, r1, lsl #12
	DECACHE_JPC
  FBC	add	r0, r2, asl #4

	ldr	r3, [r0, #CP_OFFSET+12]
	and	r3, r3, #255
	ldr	r2, [stack, r3, asl #2]
	mov	r1, #0
	SW_NPC	cmp	r2, #0
	SW_NPC	beq	null_ptr_exception
.abortentry118:
	HW_NPC	ldr	r3, [r2]		@ Only to provoke abort

	ldr	tmp1, [r0, #CP_OFFSET+4]

	ldr	ip, [tmp1, #METHOD_FROM_INTERPRETED]
	str	r1, [thread, #THREAD_LAST_JAVA_SP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [ip, #0]
	b	normal_dispatch_and_return

// This code is logically part of normal_entry, but it's been moved
// out because there is only a FAST_ENTRY_OFFSET sized gap here.

.normal_entry_return:
	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {regset, pc}
	SLOW_ENTRY
normal_entry:
	stmfd	arm_sp!, {regset, lr}
	mov	thread, r2
	ldr	r7, [thread, #THREAD_STACK_SIZE]
	ldr	r3, [thread, #THREAD_STACK_BASE]
	rsb	r3, r7, r3
	rsb	r3, r3, arm_sp
	cmp	r3, #32768
	blt	stack_overflow_no_frame
	add	lr, pc, #(.normal_entry_return-(.normal_entry1+4))
.normal_entry1:

	FAST_ENTRY
fast_normal_entry:
	adrl	ip, dispatch_init_adcon
	mov	tmp1, r0
	ldm	ip, {r0, r1}
	add	r0, r0, ip
	ldr	stack, [thread, #THREAD_JAVA_SP]
	add	dispatch, r1, r0

	stmdb	arm_sp!, {fast_regset, lr}

	ldrh	r0, [tmp1, #METHOD_MAXLOCALS]
	mov	r1, #0
	ldrh	r3, [tmp1, #METHOD_SIZEOFPARAMETERS]
        mov     ip, #INTERPRETER_FRAME
	ldrh	r2, [tmp1, #METHOD_MAXSTACK]
        sub     r7, r0, r3

	ldr	r3, [thread, #THREAD_JAVA_STACK_BASE]
	sub	r5, stack, r7, lsl #2
	sub	r5, r5, #FRAME_SIZE+STACK_SPARE+LEAF_STACK_SIZE
	sub	r5, r5, r2, lsl #2
	cmp	r3, r5
	bcs	stack_overflow_before_frame

        subs    r5, r7, #2
        tst     r7, #1
        strne   r1, [stack, #-4]!  // stack->push(0);
        bcc     3f
1:
        str     r1, [stack, #-4]
        str     r1, [stack, #-8]!
        subs    r5, r5, #2
        bcs     1b
3:
	ldr	r3, [thread, #THREAD_TOP_ZERO_FRAME]
	mov	lr, #0
        sub     istate, stack, #FRAME_SIZE     // stack->push(INTERPRETER_FRAME);
        sub     r2, istate, r2, lsl #2
        str     lr, [istate, #ISTATE_MSG]
	str	r2, [thread, #THREAD_JAVA_SP]
        sub     r5, r2, #4                      @ stack limit = istate - stackwords - 4
	str	r3, [istate, #ISTATE_NEXT_FRAME]
	str	ip, [istate, #ISTATE_FRAME_TYPE]
	str	istate, [istate, #ISTATE_MONITOR_BASE]
	str	r5, [istate, #ISTATE_STACK_LIMIT]
	str	istate, [istate, #ISTATE_STACK_BASE]
        sub     locals, stack, #4
	str	r1, [istate, #ISTATE_OOP_TEMP]
        add     locals, locals, r0, lsl #2
        sub     stack, istate, #4
        ldr     jpc, [tmp1, #METHOD_CONSTMETHOD]
        ldr     constpool, [tmp1, #METHOD_CONSTANTS]
        add     ip, istate, #ISTATE_NEXT_FRAME
	DISPATCH_START	CONSTMETHOD_CODEOFFSET
        ldr     constpool, [constpool, #CONSTANTPOOL_CACHE]
        str     ip, [thread, #THREAD_TOP_ZERO_FRAME]
  USEC	ldr	r3, [tmp1, #METHOD_INVOCATIONCOUNTER]
	mov	r1, #0
        str     r1, [thread, #THREAD_LAST_JAVA_SP]
        str     ip, [thread, #THREAD_LAST_JAVA_FP]
	ldr	ip, [thread, #THREAD_JAVA_SP]
        str     ip, [thread, #THREAD_LAST_JAVA_SP]
	DISPATCH_NEXT
  USEC	ldr	lr, [dispatch, #InterpreterInvocationLimit_Address-XXX]
  USEC	add	r3, r3, #INVOCATIONCOUNTER_COUNTINCREMENT
        str     thread, [istate, #ISTATE_THREAD]
  USEC	ldr	lr, [lr]
  USEC	str	r3, [tmp1, #METHOD_INVOCATIONCOUNTER]
	str	locals, [istate, #ISTATE_LOCALS]
  USEC	cmp	r3, lr
	str	constpool, [istate, #ISTATE_CONSTANTS]
        str        tmp1, [istate, #ISTATE_METHOD]
        str        istate, [istate, #ISTATE_SELF_LINK]
  USEC	bcs	method_entry_freq_count_overflow
	DISPATCH_NEXT
	DISPATCH_NEXT
	DISPATCH_NEXT
@	mov	lr, #0
@        str     lr, [istate, #ISTATE_PREV_LINK]
@	str	lr, [istate, #ISTATE_CALLEE]
	DISPATCH_FINISH
#ifdef USE_COMPILER
method_entry_freq_count_overflow:
        ldr     r3, [tmp1, #METHOD_CONSTMETHOD]
	DECACHE_JPC
        ldrh    r3, [r3, #CONSTMETHOD_CODESIZE]
	str	tmp1, [istate, #ISTATE_METHOD]
	mov	r1, #0
	mov	r0, thread
        cmp     r3, #MAX_FG_METHOD_SIZE
        bcc     1f
        ldr     tmp1, [dispatch, #BackgroundCompilation_Address-XXX]
        mov     r3, #1
        ldr     r5, [tmp1]
        str     r3, [tmp1]
        bl      FREQ_COUNT_OVERFLOW
        str     r5, [tmp1]
        b       2f
1:
	bl	FREQ_COUNT_OVERFLOW
2:
 T2	cmp	r0, #0
 T2	bne	call_thumb2
	CACHE_JPC
	CACHE_CP
	DISPATCH	0

#ifdef T2JIT

#define JAZ_V1	r5
#define JAZ_V2	r6
#define JAZ_V3	r7
#define JAZ_V4	r8
#define	JAZ_V5	r9
#define	JAZ_V6	r11

#define JAZ_REGSET	JAZ_V1,JAZ_V2,JAZ_V3,JAZ_V4,JAZ_V5,JAZ_V6
#define JAZ_REGSET_LEN	6

call_thumb2:
	str	istate, [istate, #ISTATE_SELF_LINK]
	stmdb	sp!, {JAZ_REGSET}
	mov	ip, #0
3:
	ldrsh	r3, [r1], #2
	cmp	r3, #-1
	ldrne	r3, [locals, -r3, lsl #2]
	strne	r3, [sp, ip, lsl #2]
	add	ip, ip, #1
	cmp	ip, #JAZ_REGSET_LEN
	bne	3b

	ldmia	sp!, {JAZ_REGSET}
1:
	add	stack, stack, #4
	bx r0
#endif // T2JIT

#endif // USE_COMPILER
	.global	Thumb2_Install
	.type Thumb2_Install, %function
Thumb2_Install:
@	ldr	r0, [r0]
	str	r1, [r0, #METHOD_FROM_INTERPRETED]
	bx	lr

handle_return:
	ldr	r9, [istate, #ISTATE_MONITOR_BASE]	@ r9 = base

	ldr	tmp1, [istate, #ISTATE_STACK_BASE]	@ tmp1 = end

	cmp	tmp1, r9
	blcc	return_check_monitors

	mov	r3, #0
	ldrb	lr, [jpc, #0]

	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
	str	r3, [thread, #THREAD_LAST_JAVA_FP]
	ldr	r0, [istate, #ISTATE_METHOD]
	ldr	r3, [r2, #0]
	ldrh	r0, [r0, #40]
	add	r1, r2, #4
	str	r3, [thread, #THREAD_TOP_ZERO_FRAME]

	add	r1, r1, r0, lsl #2

	cmp	lr, #opc_lreturn
	cmpne	lr, #opc_dreturn
	ldreq	r0, [stack, #8]
	streq	r0, [r1, #-4]!
	cmpne	lr, #opc_ireturn
	cmpne	lr, #opc_freturn
	cmpne	lr, #opc_areturn
	ldreq	r0, [stack, #4]
	streq	r0, [r1, #-4]!

	str	r1, [thread, #THREAD_JAVA_SP]

	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}

@ ----------------------------------------------------------------------------------------
stack_overflow_no_frame:
	mov	r0, thread
	mov	ip, #0
	str	ip, [r0, #THREAD_LAST_JAVA_SP]
	ldr	ip, [r0, #THREAD_TOP_ZERO_FRAME]
	str	ip, [r0, #THREAD_LAST_JAVA_FP]
	ldr	ip, [r0, #THREAD_JAVA_SP]
	str	ip, [r0, #THREAD_LAST_JAVA_SP]
	bl	_ZN18InterpreterRuntime24throw_StackOverflowErrorEP10JavaThread
	ldmfd	arm_sp!, {regset, pc}

stack_overflow_before_frame:
	mov	r0, thread
	mov	ip, #0
	str	ip, [r0, #THREAD_LAST_JAVA_SP]
	ldr	ip, [r0, #THREAD_TOP_ZERO_FRAME]
	str	ip, [r0, #THREAD_LAST_JAVA_FP]
	ldr	ip, [r0, #THREAD_JAVA_SP]
	str	ip, [r0, #THREAD_LAST_JAVA_SP]
	bl	_ZN18InterpreterRuntime24throw_StackOverflowErrorEP10JavaThread
	ldmfd	arm_sp!, {fast_regset, pc}

handle_exception_do_not_unlock:
	mov	r3, #1
	strb	r3, [thread, #THREAD_DO_NOT_UNLOCK]
	b	handle_exception_with_bcp

abstractmethod_exception:
	mov	r0, #VMSYMBOLS_AbstractMethodError
	b	raise_exception
incompatibleclass_exception:
	mov	r0, #VMSYMBOLS_IncompatibleClassChangeError
raise_exception:
	adr	r1, null_str
raise_exception_with_msg:
	stmdb	sp!, {r0, r1}
	bl	load_dispatch
	ldmia	sp!, {r0, r1}
	DECACHE_JPC
        DECACHE_STACK
	mov	r2, r1
	ldr	r1, [dispatch, #VmSymbols_symbols_Address-XXX]
	ldr	r1, [r1, r0, lsl #2]
	mov	r0, thread
	bl	Helper_Raise
        b       handle_exception_with_bcp
null_str:
	.byte	0
	ALIGN_WORD

invokedynamic_exception_fix:
invokeinterface_exception_fix:
	sub	jpc, jpc, #2
invoke_exception_fix:
invokenative_exception:
return_exception:
	sub	jpc, jpc, #3
resolve_exception:
putfield_exception:
getfield_exception:
handle_exception:
@ jpc = Exception PC
@ stack = garbage
@ locals = garbage
@ constpool = garbage
	DECACHE_JPC
handle_exception_with_bcp:
	bl	load_dispatch
	CACHE_JPC
	ldr	stack, [istate, #ISTATE_STACK_BASE]
	sub	stack, stack, #4
	DECACHE_STACK
	cmp	jpc, #0
	beq	1f

	mov	r0, istate
	mov	r1, thread
	bl	Helper_HandleException
	cmp	r0, #0
	beq	1f

	mov	jpc, r0
	CACHE_STACK
	CACHE_LOCALS
	CACHE_CP
	DISPATCH 0
1:
	ldr	r9, [istate, #ISTATE_MONITOR_BASE]	@ r9 = base

	ldr	tmp1, [istate, #ISTATE_STACK_BASE]	@ tmp1 = end

	mov	r3, #0
	ldrb	r0, [thread, #THREAD_DO_NOT_UNLOCK]
	strb	r3, [thread, #THREAD_DO_NOT_UNLOCK]
	cmp	r0, #0
	bne	2f

	cmp	tmp1, r9
	blcc	return_check_monitors

2:
	mov	r3, #0

	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	str	r3, [thread, #THREAD_LAST_JAVA_SP]
	ldr	r0, [istate, #ISTATE_METHOD]
	ldr	r3, [r2, #0]
	ldrh	r0, [r0, #40]
	add	r1, r2, #4
	str	r3, [thread, #THREAD_TOP_ZERO_FRAME]

	add	r1, r1, r0, lsl #2

	str	r1, [thread, #THREAD_JAVA_SP]

	mov	r0, #0	@ deoptimized_frames = 0
	ldmfd	arm_sp!, {fast_regset, pc}

return_check_monitors:
	stmdb	arm_sp!, {r4, lr}

	DECACHE_JPC	// FIXME: May not be needed.
	ldr	r2, [istate, #ISTATE_METHOD]
	ldr	r4, [r2, #METHOD_ACCESSFLAGS]
	tst	r4, #1<<5
	subne	r9, r9, #8
	cmp	tmp1, r9
	bcs	2f
1:
	ldr	r3, [tmp1, #4]
	cmp	r3, #0
	bne	3f
	add	tmp1, tmp1, #8
	cmp	tmp1, r9
	bcc	1b

2:
	tst	r4, #1<<5

	ldmeqia	arm_sp!, {r4, pc}

	ldr	tmp1, [r9, #4]		@ base->obj == NULL
	cmp	tmp1, #0
	beq	4f

	ldr	r0, [r9, #0]			@ r0 = header
	mov	r3, #0
	cmp	r0, #0
	str	r3, [r9, #4]			@ base->obj = NULL

	ldmeqia	arm_sp!, {r4, pc}

	mov	r1, tmp1
	mov	r2, r9
	bl	cmpxchg_ptr
	cmp	r9, r0

	ldmeqia	arm_sp!, {r4, pc}

	str	tmp1, [r9, #4]

	mov	r1, r9
	mov	r0, thread
	bl	Helper_synchronized_exit

	ldmeqia	arm_sp!, {r4, pc}

3:
	mov	r0, thread
	bl	Helper_RaiseIllegalMonitorException
	b	2b

4:
	mov	r0, thread
	bl	Helper_RaiseIllegalMonitorException
	ldmia	arm_sp!, {r4, pc}

	SLOW_ENTRY
accessor_entry:
	stmfd	arm_sp!, {regset, lr}
	mov	thread, r2
	ldr	r7, [thread, #THREAD_STACK_SIZE]
	ldr	r3, [thread, #THREAD_STACK_BASE]
	rsb	r3, r7, r3
	rsb	r3, r3, arm_sp
	cmp	r3, #32768
	blt	stack_overflow_no_frame
	bl	fast_accessor_entry
	ldmia	sp!, {regset, pc}

	FAST_ENTRY
fast_accessor_entry:
  USEC	adrl	ip, dispatch_init_adcon
  USEC	ldr	r3, [ip]
  USEC	add	r3, r3, ip
  USEC	ldr	ip, [ip, #invocationlimit_adcon-dispatch_init_adcon]
  USEC	ldr	ip, [r3, ip]

  USEC	ldr	r3, [r0, #METHOD_INVOCATIONCOUNTER]
  USEC	ldr	ip, [ip, #0]
  USEC	add	r3, r3, #INVOCATIONCOUNTER_COUNTINCREMENT
  USEC	str	r3, [r0, #METHOD_INVOCATIONCOUNTER]
  USEC	cmp	r3, ip
  USEC	bcs	fast_normal_entry

	ldr	r1, [r0, #METHOD_CONSTMETHOD]
	ldrb	r3, [r1, #CONSTMETHOD_CODEOFFSET+2]
	ldrb	r1, [r1, #CONSTMETHOD_CODEOFFSET+3]
	ldr	ip, [r0, #METHOD_CONSTANTS]
	ldr	ip, [ip, #CONSTANTPOOL_CACHE]
	orr	r3, r3, r1, lsl #8		@ r3 = index

	add	r1, ip, #CP_OFFSET
	ldr	r3, [r1, r3, lsl #4]!		@ r1 = cache, r3 = flags
	ldr	ip, [thread, #THREAD_JAVA_SP]			@ ip == stack
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getfield << 16
	ldr	r3, [ip, #0]
	bne	fast_normal_entry

	cmp	r3, #0
	beq	fast_normal_entry

	ldr	r0, [r1, #12]
	ldr	r1, [r1, #8]
	movs	r0, r0, lsr #29
	bls	accessor_non_w

	ldr	r0, [r3, r1]
	str	r0, [ip, #0]
	mov	r0, #0
	bx	lr

div_zero_jpc_1:
	sub	jpc, jpc, #1
.lrem_0:
.ldiv_0:
divide_by_zero_exception:
	mov	r0, #VMSYMBOLS_ArithmeticException
	adr	r1, div_zero_msg
	b	raise_exception_with_msg
div_zero_msg:
	.ascii  "/ by int zero\000"
	ALIGN_WORD

array_bound_exception_jpc_4_r3:
	sub	jpc, jpc, #1
array_bound_exception_jpc_3_r3:
	sub	jpc, jpc, #1
array_bound_exception_jpc_2_r3:
	sub	jpc, jpc, #1
array_bound_exception_jpc_1_r3:
	sub	jpc, jpc, #1
array_bound_exception_jpc_0_r3:
	mov	r2, r3
	b	array_bounds_exception
array_bound_exception_jpc_1_tmp1:
	sub	jpc, jpc, #1
array_bound_exception_jpc_0_tmp1:
	mov	r2, tmp1
	b	array_bounds_exception
array_bound_exception_jpc_3:
	sub	jpc, jpc, #1
array_bound_exception_jpc_2:
	sub	jpc, jpc, #1
array_bound_exception_jpc_1:
	sub	jpc, jpc, #1
array_bound_exception_jpc_0:
array_bounds_exception:
	DECACHE_JPC
        DECACHE_STACK
	mov	r1, r2
	mov	r0, thread
	bl	Helper_RaiseArrayBoundException
        b       handle_exception_with_bcp

#ifndef HW_NULL_PTR_CHECK
null_ptr_exception_jpc_5:
	sub	jpc, jpc, #1
null_ptr_exception_jpc_4:
	sub	jpc, jpc, #1
null_ptr_exception_jpc_3:
	sub	jpc, jpc, #1
null_ptr_exception_jpc_2:
	sub	jpc, jpc, #1
null_ptr_exception_jpc_1:
	sub	jpc, jpc, #1
null_ptr_exception_jpc_0:
#endif
null_ptr_exception:
	mov	r0, #VMSYMBOLS_NullPointerException
	b	raise_exception

@ ==== SW FP ==============================================================================

	Opcode	fadd
	POP	r0, r1
        bl      __aeabi_fadd
	PUSH	r0
	DISPATCH	1

	Opcode	fsub
	POP	r1
	POP	r0
        bl      __aeabi_fsub
	PUSH	r0
	DISPATCH	1

	Opcode	fmul
	POP	r0, r1
        bl      __aeabi_fmul
	PUSH	r0
	DISPATCH	1

	Opcode	fdiv
	POP	r1
	POP	r0
        bl      __aeabi_fdiv
	PUSH	r0
	DISPATCH	1

	Opcode	ddiv
	POP	r2, r3
	POP	r0, r1
        bl      __aeabi_ddiv
	PUSH	r0, r1
	DISPATCH	1

	Opcode	fcmpl
        ldmib   stack, {r0, r1}
        bl      __aeabi_fcmpgt
        cmp     r0, #0
        movne   r3, #-1
        bne     3f
        ldmib   stack, {r0, r1}
        bl      __aeabi_fcmplt
        cmp     r0, #0
        movne   r3, #1
        bne     3f
        ldmib   stack, {r0, r1}
        bl      __aeabi_fcmpeq
        cmp     r0, #0
        movne   r3, #0
        moveq   r3, #-1
3:
	DISPATCH_START	1
	add	stack, stack, #8
	DISPATCH_NEXT
	PUSH	r3
	DISPATCH_FINISH

	Opcode	fcmpg
        ldmib   stack, {r0, r1}
        bl      __aeabi_fcmpgt
        cmp     r0, #0
        movne   r3, #-1
        bne     4f
        ldmib   stack, {r0, r1}
        bl      __aeabi_fcmplt
        cmp     r0, #0
        movne   r3, #1
        bne     4f
        ldmib   stack, {r0, r1}
        bl      __aeabi_fcmpeq
        cmp     r0, #0
        movne   r3, #0
        moveq   r3, #1
4:
	DISPATCH_START	1
	add	stack, stack, #8
	DISPATCH_NEXT
	PUSH	r3
	DISPATCH_FINISH

	Opcode	dcmpl
        ldmib   stack, {r0, r1, r2, r3}
        bl      __aeabi_dcmpgt
        cmp     r0, #0
        movne   r3, #-1
        bne     5f
        ldmib   stack, {r0, r1, r2, r3}
        bl      __aeabi_dcmplt
        cmp     r0, #0
        movne   r3, #1
        bne     5f
        ldmib   stack, {r0, r1, r2, r3}
        bl      __aeabi_dcmpeq
        cmp     r0, #0
        movne   r3, #0
        moveq   r3, #-1
5:
	DISPATCH_START	1
	add	stack, stack, #16
	DISPATCH_NEXT
	PUSH	r3
	DISPATCH_FINISH

	Opcode	dcmpg
        ldmib   stack, {r0, r1, r2, r3}
        bl      __aeabi_dcmpgt
        cmp     r0, #0
        movne   r3, #-1
        bne     6f
        ldmib   stack, {r0, r1, r2, r3}
        bl      __aeabi_dcmplt
        cmp     r0, #0
        movne   r3, #1
        bne     6f
        ldmib   stack, {r0, r1, r2, r3}
        bl      __aeabi_dcmpeq
        cmp     r0, #0
        movne   r3, #0
        moveq   r3, #1
6:
	DISPATCH_START	1
	add	stack, stack, #16
	DISPATCH_NEXT
	PUSH	r3
	DISPATCH_FINISH

@ ==== Fast SW FP emulation ===============================================================

#define al		r0
#define ah		r1
#define bl		r2
#define bh		r3
#define tmp		tmp1
#define sh		r12
#define ex_add		r14

@ TOS = TOSM1 + TOS
@ What we actually do is TOS = TOS + TOSM1
@ --- do_dadd_vtos -------------------------------------------------
	Opcode	dadd
	POP	al, ah, bl, bh
	mov	tmp, #0xff000000
	orr	tmp, tmp, #0x00e00000
        bics    ex_add, tmp, ah, LSL #1
        bicnes  ex_add, tmp, bh, LSL #1
        beq     .dadd_naninf
        teq     ah, bh
        eormi   bh, bh, #1 << 31
        bmi     ._dsub1
._dadd1:
        subs    ex_add, al, bl
        sbcs    sh, ah, bh
        bhs     .dadd_swapped
        adds    bl, bl, ex_add
        adc     bh, bh, sh
        subs    al, al, ex_add
        sbc     ah, ah, sh
.dadd_swapped:
        mov     ex_add, ah, LSR #20
        sub     sh, ex_add, bh, LSR #20
        tst     tmp, bh, LSL #1
        beq     .dadd_uncommon
        bic     ah, ah, ex_add, LSL #20
        bic     bh, bh, tmp
        orr     bh, bh, #1 << 20
.dadd_doadd:
        rsbs    tmp, sh, #32
        blo     .dadd_bigshift
.dadd_smallshift:
        adds    al, al, bl, LSR sh
        adc     ah, ah, bh, LSR sh
        adds    al, al, bh, LSL tmp
        adcs    ah, ah, #0
        cmp     ah, #1 << 20
        bhs     .dadd_carry
        add     ah, ah, ex_add, LSL #20     @ add exponent
.dadd_nocarry:
        movs    bl, bl, LSL tmp         @ round and sticky bits
	bpl	.dadd_exit
        adds    al, al, #1
        movccs  bl, bl, LSL #1          @ is sticky bit zero?
	bne	.dadd_exit
.dadd_roundeven:
        cmp     al, #0
        bicne   al, al, #1              @ RTE if carry didn't occur
        adceq   ah, ah, #0              @ increment high word if it did
.dadd_check_overflow_inx:
        mov     bh, ah, LSL #1
        cmp     bh, #0xFFE00000
	blo	.dadd_exit
        subhs   ah, ah, #3<<29          @ bias exponent
	b	.return_double_Inf
.dadd_bigshift:
        cmp     bl, #1
        adc     bl, bh, bh
        sub     sh, sh, #32             @ nonzero
        rsbs    tmp, sh, #31            @ sets C if within a word
        movlo   tmp, #0                 @ C clear if sh > 31
        addhss  al, al, bh, LSR sh
        adc     ah, ah, ex_add, LSL #20
        cmp     ex_add, ah, LSR #20
        beq     .dadd_nocarry
        sub     ah, ah, ex_add, LSL #20
.dadd_carry:
        add     ah, ah, #1 << 20
        movs    ah, ah, LSR #1
        add     ah, ah, ex_add, LSL #20
        movs    al, al, RRX
        bcc     .dadd_check_overflow_exact
        adcs    al, al, #0
        movccs  tmp, bl, LSL tmp    @EQ = round to even
        bne     .dadd_check_overflow_exact
        b       .dadd_roundeven
.dadd_rnearup_carry:
        adds    al, al, #1
        movccs  bl, bl, LSL #1          @ is sticky bit zero?
        bne     .dadd_check_overflow_inx
        b       .dadd_roundeven
.dadd_check_overflow_exact:
        mov     bh, ah, LSL #1
        cmp     bh, #0xFFE00000
	blo	.dadd_exit
        sub     ah, ah, #3<<29          @ bias exponent

.return_double_Inf:
	and	a3, ah, #0x80000000
.return_double_Inf_1:
	mov	al, #0
	mov	ah, #0x7f000000
	orr	ah, ah, #0x00f00000
	orr	ah,ah,a3
.dadd_exit:
	PUSH	al, ah
	DISPATCH	1

.dadd_uncommon:
        orrs    tmp, bl, bh, LSL #1     @ Is b zero or denormal?
        beq     .dadd_bzero
        movs    tmp, ex_add, LSL #21
        bic     ah, ah, ex_add, LSL #20
        bicne   bh, bh, #1 << 31
        subne   sh, sh, #1              @ adjust exponent to fake exp_b = 1
        bne     .dadd_doadd    
        adds    al, al, bl
        adc     ah, ah, bh
        b       .daddsub_denorm
.dadd_bzero:
        movs    tmp, ex_add, LSL #21        @ is a denormal?
	bne	.dadd_exit
        orrs    tmp, al, ah, LSL #1     @ a zero?
	beq	.dadd_exit
        b       .daddsub_denorm

.dadd_naninf:
        cmp     al, #1                  @ sets C if al!=0
        adc     ex_add, ah, ah
        cmp     bl, #1
        adc     sh, bh, bh
        cmp     ex_add, tmp                 @ HI if a is NaN
        cmpls   sh, tmp                 @ HI if either is NaN
        bhi     .return_double_NaN
        cmp     ex_add, sh
        beq     .dadd_twoinf
        cmp     ex_add, tmp                 @ EQ if a is Inf
        movne   ah, bh
        movne   al, bl
	b	.dadd_exit
.dadd_twoinf:
        teq     ah, bh
	bpl	.dadd_exit
	b	.return_double_NaN

@ --- do_dsub_itos -------------------------------------------------
	Opcode	dsub
	POP	al, ah, bl, bh
        mov     tmp, #0xff000000
        orr     tmp, tmp, #0x00e00000
        bics    ex_add, tmp, ah, LSL #1
        bicnes  ex_add, tmp, bh, LSL #1
        beq     .drsb_naninf
	teq	ah, bh
	eor	ah, ah, #1 << 31
	bmi	._dadd1
	eor	bh, bh, #1 << 31
._dsub1:
        subs    ex_add, al, bl
        sbcs    sh, ah, bh
        bhs     .dsub_swapped
.dsub_do_swap:
        eor     sh, sh, #1 << 31        @ negate a and b as a - b == -b - -a
        adds    bl, bl, ex_add
        adc     bh, bh, sh
        subs    al, al, ex_add
        sbc     ah, ah, sh
.dsub_swapped:
        mov     ex_add, ah, LSR #20
        sub     sh, ex_add, bh, LSR #20
        tst     tmp, bh, LSL #1
        beq     .dsub_uncommon
        bic     ah, ah, ex_add, LSL #20
        bic     bh, bh, tmp, ASR #1
        rsbs    bl, bl, #0
        rsc     bh, bh, tmp, ASR #1     @ 0xffe00000 >> 1 = -(1 << 20)
.dsub_dosub:
        rsbs    tmp, sh, #32
        blo     .dsub_bigshift
.dsub_smallshift:
        adds    al, al, bl, LSR sh
        adc     ah, ah, bh, ASR sh
        adds    al, al, bh, LSL tmp
        adcs    ah, ah, #0
        bmi     .dsub_borrow
.dsub_noborrow:
        add     ah, ah, ex_add, LSL #20
        movs    bl, bl, LSL tmp
.dsub_dorounding:
	bpl	.dsub_exit
        adds    al, al, #1              @ Z flag set if carry to high word
        cmpne   bl, #0x80000000         @ check we don't have to round to even
	bne	.dsub_exit
        cmp     al, #0
        addeq   ah, ah, #1
        bicne   al, al, #1
	b	.dsub_exit
.dsub_bigshift:
        cmp     bl, #1
        adc     bl, bh, bh 
        sub     sh, sh, #32
        rsbs    tmp, sh, #31
        blo     .dsub_hugeshift
        adds    al, al, bh, ASR sh
        adcs    ah, ah, #-1
        bpl     .dsub_noborrow
.dsub_borrow:
        add     tmp, tmp, #1
        movs    tmp, bl, LSL tmp
        adcs    al, al, al              @ shift al,ah left including guard bit
        adc     ah, ah, ah
        add     sh, ah, ex_add, LSL #21     @ ah = 0xFFE00000 + fraction. Adding
        movs    sh, sh, LSR #21         @ C-bit is clear if bit 20 of ah
        bls     .dsub_renormalize        @   clear, so 2 bits or more
        add     ah, ah, ex_add, LSL #20
        adds    al, al, tmp, LSR #31    @ C and Z flag are set if carry over
        cmpcc   tmp, #0x80000000        @ check that we don't have to round
	bne	.dsub_exit
        cmp     al, #0
        addeq   ah, ah, #1
        bicne   al, al, #1
	b	.dsub_exit
.dsub_renormalize:
        bcs     .dsub_ex_one
        adds    ah, ah, #1 << 21
        cmpeq   al, #0
        beq     .dsub_retzero            @ go and deal with it, if so
        mov     sh, ex_add, LSR #11
        bic     ex_add, ex_add, #1 << 11
        sub     ex_add, ex_add, #2        @ for leading bit
.dsub_renormloop:                 @ TODO: add loop for 8 bit per cycle renorm
        adds    al, al, al
        adc     ah, ah, ah
        sub     ex_add, ex_add, #1
        tst     ah, #1 << 20
        beq     .dsub_renormloop
        add     ah, ah, sh, LSL #31 
        add     ah, ah, ex_add, LSL #20
        cmp     ex_add, #0
	bgt	.dsub_exit
        add     ah, ah, #3 << 29        @ bias exponent
        @ Rounding direction indicator is zero (denormal results are exact)
	mov	ip, #0
        b       .__dunder
.dsub_hugeshift:
.dsub_return:
        add     ah, ah, ex_add, LSL #20
.dsub_return1:
.dsub_exit:
	PUSH	al, ah
	DISPATCH	1
.dsub_ex_one:    @ underflow when ex = 1 - shift back to denorm
        movs    ah, ah, ASR #1
        mov     al, al, RRX
        add     ah, ah, ex_add, LSL #20
        b       .dsub_denorm
.dsub_uncommon:
        orrs    tmp, bl, bh, LSL #12    @ is b zero or denorm?
        beq     .dsub_bzero
        movs    tmp, ex_add, LSL #21
        bic     ah, ah, ex_add, LSL #20
        beq     .dsub_both_denorm
        bic     bh, bh, #1 << 31
        sub     sh, sh, #1
        rsbs    bl, bl,#0
        rsc     bh, bh,#0
        b       .dsub_dosub    
.dsub_both_denorm:
        subs    al, al, bl
        sbc     ah, ah, bh
        b       .dsub_denorm
.dsub_bzero:
        orrs    tmp, al, ah, LSL #1
        bne     .dsub_denorm             @ return a@ but it might be denormal
.dsub_retzero:
        mov     ah, #0                  @ clear sign bit (al is already 0)
	b	.dsub_exit
.dsub_denorm:
.daddsub_denorm:
        movs    bl, ah, LSL #1          @ discard sign bit
        tsteq   al, al                  @ do we have a zero?
        beq     .dsub_retzero            @ yes@ go and ensure the right sign
	b	.dsub_exit
.drsb_naninf:
        @ Handle NaNs and infinities in reverse subtraction. We
        @ just swap the operands and go to dsub_naninf.
        eor     ah, ah, bh
        eor     al, al, bl
        eor     bh, bh, ah
        eor     bl, bl, al
        eor     ah, ah, bh
        eor     al, al, bl
.dsub_naninf:
        cmp     al, #1                  @ sets C if al!=0
        adc     ex_add, ah, ah
        cmp     bl, #1
        adc     sh, bh, bh
        cmp     ex_add, tmp                 @ HI if a is NaN
        cmpls   sh, tmp                 @ HI if either is NaN
        bhi     .return_double_NaN
        cmp     ex_add, sh
        beq     .dsub_twoinf
        cmp     ex_add, tmp                 @ EQ if a is Inf
        eorne   ah, bh, #0x80000000
        movne   al, bl
	b	.dsub_exit
.dsub_twoinf:
        teq     ah, bh
	bmi	.dsub_exit

.return_double_NaN:
	and	a3, ah, #0x80000000
	mov	al, #0
	mov	ah, #0x7f000000
	orr	ah, ah, #0x00f80000
	orr	ah,ah,a3
	b	.dsub_exit

@ === underflow handler ================================================

#define	INX_pos	30
#define INX_bit (1<<30)

#define exp	r2
#define temp	r3

.__dunder:
        tst     ah, ah
        orrmi   ip, ip, #1<<16
        mov     temp, #0x600
        mov     exp, ah, LSR #20      @ find the exponent
        add     temp, temp, #1
        bic     ah, ah, exp, LSL #20 @ remove exponent from mantissa
        bic     exp, exp, #0x800        @ lose the sign bit
        sub     exp, temp, exp
        orr     ah, ah, #1<<20      @ put on mantissa leading bit
        cmp     exp, #53
        bhi     .dunder_stickyonly
        beq     .dunder_roundbit
        cmp     exp, #21
        blo     .dunder_hiword
        subs    exp, exp, #32
        bls     .dunder_hiloword
.dunder_loloword:
        rsb     temp, exp, #32
        cmp     al, #0
        mov     al, ah, LSR exp
        mov     exp, ah, LSL temp
        orrne   exp, exp, #1
        mov     ah, #0
        b       .dunder_round
.dunder_hiloword:
        rsb     temp, exp, #0
        add     exp, exp, #32
        mov     ah, ah, LSL temp
        orr     ah, ah, al, LSR exp
        mov     exp, al, LSL temp
        mov     al, ah
        mov     ah, #0
        b       .dunder_round
.dunder_hiword:
        rsb     temp, exp, #32
        mov     tmp, al, LSL temp
        mov     temp, ah, LSL temp
        orr     al, temp, al, LSR exp
        mov     ah, ah, LSR exp
        mov     exp, tmp
        b       .dunder_round
.dunder_roundbit:
        orrs    exp, al, ah, LSL #12
        mov     al, #0
        mov     ah, #0
        mov     exp, #0x80000000
        addne   exp, exp, #1
        b       .dunder_round
.dunder_stickyonly:
        mov     exp, #1
        mov     ah, #0
        mov     al, #0
.dunder_round:
        tst     ip, #1<<16
        bic     ip, ip, #1<<16
        orrne   ah, ah, #0x80000000
        tst     exp, exp
	beq	.dsub_exit
        movs    exp, exp, LSL #1        @ round bit in C, sticky in ~Z
        bcc     .dunder_rerounded        @ if no round bit, we're done
        beq     .dunder_roundeven        @ RTE is tricky due to rerounding
.dunder_roundup:
        adds    al, al, #1          @ round up
        adc     ah, ah, #0
.dunder_rerounded:
	b	.dsub_exit
.dunder_roundeven:
        movs    exp, ip, ASR #INX_pos   @ get -1, 0, +1 from direction bits
        bmi     .dunder_roundup          @ if -1, round up unconditionally
        bne     .dunder_rerounded        @ if +1, round down unconditionally
        adds    al, al, #1          @ round up ...
        adc     ah, ah, #0
        bic     al, al, #1          @ ... and then to even
        b       .dunder_rerounded

@ === MULTIPLY Double ===================================================

#define ex_m		r14
#define uh		r12
#define ul		r4
#define rs		r4
#define th		r5
#define tl		r11

@ --- do_dmul_itos -------------------------------------------------
	Opcode	dmul
	POP	al, ah, bl, bh
	stmdb	arm_sp!, {r4, r5}
	mov	tmp, #0x7f00000
	orr	tmp, tmp, #0x00f0000
        bics    ex_m, tmp, ah, LSR #4     @ test for Infs or NaNs
        bicnes  ex_m, tmp, bh, LSR #4
        beq     .dmul_naninf
        and     ex_m, tmp, ah, LSR #4     @ get exponent of a
        eor     th, ah, bh              @ compute sign of result
        orr     ex_m, ex_m, th, LSR #31     @   and save it at bottom of ex
        ands    th, tmp, bh, LSR #4     @ get exponent of b, and test
        tstne   ah, tmp, LSL #4         @   for zeros/denorms ...
        beq     .dmul_zerodenorm         @   go and renormalise if we got any
.dmul_normalised:
        add     ex_m, ex_m, th              @ calculate exponent of result
        sub     ex_m, ex_m, #0x3FC0000      @ rebias exponent mostly
        bic     ah, ah, tmp, LSL #5     @ clear sign and all but lo bit of exp
        bic     bh, bh, tmp, LSL #5
        orr     ah, ah, #1<<20          @ set leading bit on mantissa
        orr     bh, bh, #1<<20          @ set leading bit on mantissa
.dmul_mantmul:
        umull   ul, uh, ah, bl
        umull   tl, th, al, bh
        adds    tl, tl, ul
        adcs    th, th, uh              @ carry from here is used below
        umull   ul, uh, ah, bh          @ uh:ul is top part
        adc     bh, uh, #0              @ get carry from above addition
        umull   ah, uh, al, bl          @ uh:ah is bottom part
        adds    tl, tl, uh
        adcs    th, th, ul
        adcs    bh, bh, #0
        tst     ah, ah
        orrne   tl, tl, #1              @ don't lose sticky bit
        mov     bl, #-4
        mov     uh, #32-12              @ uh will be corresponding right shift
        cmp     bh, #0x200              @ C set if it's 11 bits
        adc     uh, uh, #0
        adc     bl, bl, ex_m, ASR #16     @ increment exponent correspondingly
        rsb     ul, uh, #32             @ ul is left shift
        mov     ah, bh, LSL ul
        mov     al, th, LSL ul
        orr     ah, ah, th, LSR uh
        orr     al, al, tl, LSR uh
        add     ah, ah, bl, LSL #20 @ put exponent back on (may wrap
        eor     ah, ah, ex_m, LSL #31 @ put sign back on (with EOR so that
        movs    rs, tl, LSL ul          @ compute the round word
        beq     .dmul_exact
        movs    uh, rs, LSL #1          @ rs is already in place
        movcc   rs, #-INX_bit           @ direction indicator: rounded down
        bcc     .dmul_rounded
        orreq   bh, bh, #1<<31          @ save the round-to-even bit
        adcs    al, al, #0          @ round up if necessary
        adc     ah, ah, #0
        mov     rs, #INX_bit            @ direction indicator: rounded up
        tst     al, bh, LSR #31       @ does RTE do anything?
        bic     al, al, bh, LSR #31 @ perform RTE
        movne   rs, #-INX_bit           @ if RTE had effect, we rounded down
.dmul_exact:
.dmul_rounded:
        teq     ah, ex_m, LSL #31       @ do the signs agree?
	mov	uh, #0x70000000         @ even if so, need to test exp 0/7FF
	orr	uh, uh, #0x0ff00000
        bmi     .dmul_outflow            @ if not, UFL or OFL
        tst     ah, uh
        bicnes  uh, uh, ah            @ is exp 0 or 7FF?
        beq     .dmul_outflow
.dmul_exit:
	ldmia	arm_sp!, {r4, r5}
	PUSH	al, ah
	DISPATCH	1

.dmul_rdirect:
        movs    ul, ex_m, LSL #31         @ put sign bit in N
        tstpl   uh, #2 << 22        @ if +ve: EQ iff round up. Keeps PL
        tstmi   uh, #1 << 22         @ if -ve: EQ iff round up.
        moveq   rs, #INX_bit            @ rounded up
        movne   rs, #-INX_bit           @ rounded down
        addeqs  al, al, #1          @ may set C
        adc     ah, ah, #0
        b       .dmul_rounded

.dmul_outflow:
        cmp     ex_m, #0x400<<16          @ Which ballpark are we in?
        addle   ah, ah, #0x60000000 @ Bias up if underflow
        subge   ah, ah, #0x60000000 @ Bias down if overflow
	mov	ip, rs
	ldmia	arm_sp!, {r4, r5}
        ble     .__dunder                @ underflow
	b	.return_double_Inf

.dmul_zerodenorm:
        orrs    ul, al, ah, LSL #1      @ is a zero?
        orrnes  ul, bl, bh, LSL #1      @ or is b zero?
        beq     .dmul_zero               @ Return zero if so

        tst     th, th                  @ is b denormal?
        beq     .dmul_renorm_op2
.dmul_done_op2:
        bics    ul, ex_m, #1              @ is a denormal? (careful of sign bit)
        beq     .dmul_renorm_op1
        b       .dmul_normalised
.dmul_zero:
        mov     al, #0                  @ clear low word
        mov     ah, ex_m, LSL #31         @ get sign of result and clear hi word
	b	.dmul_exit

.dmul_renorm_op1:
        add     ex_m, ex_m, #1<<16          @ correct the exponent
        bic     ah, ah, #0x80000000       @ this will get in our way
        orrs    tl, ah, al, LSR #12    @ is highest set bit in low twelve?
        moveq   al, al, LSL #20         @ if so, move it up
        subeq   ex_m, ex_m, #20<<16       @ and adjust exponent
        tst     ah, ah                  @ is highest set bit in low word?
        moveq   ah, al, LSR #12         @ if so, move up by 20
        moveq   al, al, LSL #20
        subeq   ex_m, ex_m, #20<<16       @ and adjust exponent
        mov     ul, #0                 @ shift of top word
        movs    tl, ah, LSR #(21-16)   @ is highest set bit within 16 of top?
        moveq   ah, ah, LSL #16         @ if not, move up
        addeq   ul, ul, #16           @ and adjust exponent
        movs    tl, ah, LSR #(21-8)   @ is highest set bit within 8 of top?
        moveq   ah, ah, LSL #8         @ if not, move up
        addeq   ul, ul, #8           @ and adjust exponent
        movs    tl, ah, LSR #(21-4)   @ is highest set bit within 4 of top?
        moveq   ah, ah, LSL #4         @ if not, move up
        addeq   ul, ul, #4           @ and adjust exponent
        movs    tl, ah, LSR #(21-2)   @ is highest set bit within 2 of top?
        moveq   ah, ah, LSL #2         @ if not, move up
        addeq   ul, ul, #2           @ and adjust exponent
        movs    tl, ah, LSR #(21-1)   @ is highest set bit within 1 of top?
        moveq   ah, ah, LSL #1         @ if not, move up
        addeq   ul, ul, #1           @ and adjust exponent

        sub     ex_m, ex_m, ul, LSL #16  @ calculate final pseudo exponent
        mov     tl, al, LSL ul        @ shift low word up by same amout
        rsb     ul, ul, #32           @ compute reverse shift for al
        orr     ah, ah, al, LSR ul     @ put in high end of low word
        mov     al, tl

	mov	tmp, #0x7f00000
	orr	tmp, tmp, #0x00f0000

        b       .dmul_normalised

.dmul_renorm_op2:
        add     th, th, #1<<16          @ correct the exponent
        bic     bh, bh, #0x80000000       @ this will get in our way
        orrs    tl, bh, bl, LSR #12    @ is highest set bit in low twelve?
        moveq   bl, bl, LSL #20         @ if so, move it up
        subeq   th, th, #20<<16       @ and adjust exponent
        tst     bh, bh                  @ is highest set bit in low word?
        moveq   bh, bl, LSR #12         @ if so, move up by 20
        moveq   bl, bl, LSL #20
        subeq   th, th, #20<<16       @ and adjust exponent
        mov     ul, #0                 @ shift of top word
        movs    tl, bh, LSR #(21-16)   @ is highest set bit within 16 of top?
        moveq   bh, bh, LSL #16         @ if not, move up
        addeq   ul, ul, #16           @ and adjust exponent
        movs    tl, bh, LSR #(21-8)   @ is highest set bit within 8 of top?
        moveq   bh, bh, LSL #8         @ if not, move up
        addeq   ul, ul, #8           @ and adjust exponent
        movs    tl, bh, LSR #(21-4)   @ is highest set bit within 4 of top?
        moveq   bh, bh, LSL #4         @ if not, move up
        addeq   ul, ul, #4           @ and adjust exponent
        movs    tl, bh, LSR #(21-2)   @ is highest set bit within 2 of top?
        moveq   bh, bh, LSL #2         @ if not, move up
        addeq   ul, ul, #2           @ and adjust exponent
        movs    tl, bh, LSR #(21-1)   @ is highest set bit within 1 of top?
        moveq   bh, bh, LSL #1         @ if not, move up
        addeq   ul, ul, #1           @ and adjust exponent

        sub     th, th, ul, LSL #16  @ calculate final pseudo exponent
        mov     tl, bl, LSL ul        @ shift low word up by same amout
        rsb     ul, ul, #32           @ compute reverse shift for bl
        orr     bh, bh, bl, LSR ul     @ put in high end of low word
        mov     bl, tl

	mov	tmp, #0x7f00000
	orr	tmp, tmp, #0x00f0000

        b       .dmul_done_op2

.dmul_naninf:
        mov     uh, ah, LSL #1          @ discard sign bit on a
        mov     ul, bh, LSL #1          @ and on b
        cmp     uh, tmp, LSL #5         @ HI if ah shows a to be NaN
        cmpeq   al, #0                  @ now HI if a is NaN
        cmpls   ul, tmp, LSL #5         @ another chance to set HI ...
        cmpeq   bl, #0                  @  ... if b is NaN
        bhi     .dmul_ivo
        orrs    ul, al, ah, LSL #1      @ is a zero?
        orrnes  ul, bl, bh, LSL #1      @ or is b zero?
        beq     .dmul_ivo
        eor     ah, ah, bh
        mov     al, #0
        and     ah, ah, #0x80000000
        orr     ah, ah, tmp, LSL #4
	b	.dmul_exit

.dmul_ivo:
	ldmia	arm_sp!, {r4, r5}
	b	.return_double_NaN

#undef al
#undef ah
#undef bl
#undef bh
#undef tmp
#undef sh
#undef ex_add

#undef	INX_pos
#undef INX_bit

#undef exp
#undef temp

#undef ex_m
#undef uh
#undef ul
#undef rs
#undef th
#undef tl

@ --- ignore_safepoints ---------------------------------------------------------------------------
	.global	_ZN14CppInterpreter17ignore_safepointsEv
	.type	_ZN14CppInterpreter17ignore_safepointsEv, %function
_ZN14CppInterpreter17ignore_safepointsEv:
#ifdef NOTICE_SAFEPOINTS
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r2, r3}
	add	r2, r2, ip
	add	ip, r3, r2
	ldr	r2, [ip, #AbstractInterpreter_notice_safepoints-XXX]
	ldrb	r1, [r2, #0]	@ zero_extendqisi2
	cmp	r1, #0
	bxeq	lr
	mov	r3, #0
	strb	r3, [r2, #0]
	adrl	r3, main_dispatch_table
#ifdef HW_FP
	ldr	r0, [ip, #CPUInfo-XXX]
	tst	r0, #ARCH_VFP
	beq	2f
#endif
	mov	r2, #256
1:
	ldr	r1, [r3], #4
	str	r1, [ip], #4
	subs	r2, r2, #1
	bne	1b
	sub	ip, ip, #4 * 256
	b	4f

@ No HW FP - must update the table from a combination main_dispatch_table and
@ vfp_table. Previously this updated from main_dispatch_table first, and then
@ overwrite the updated entries with those from vfp_table. However, this creates
@ a window where the jump table has vfp entries, so in a multithreaded world we
@ can get undefined VFP instructions.
@ The code below updates from both tables simultaneously. Note: this relies on
@ the enties in vfp_table being in opcode order.
#ifdef HW_FP
2:
	stmdb	arm_sp!, {r4, lr}
	mov	r2, #0
	adrl	r0, vfp_table
	ldr	r4, [r0], #4
3:
	ldr	r1, [r3], #4
	cmp	r2, r4
	ldreq	r1, [r0], #4
	ldreq	r4, [r0], #4
	str	r1, [ip], #4
	add	r2, r2, #1
	cmp	r2, #256
	bcc	3b
	sub	ip, ip, #4 * 256
	ldmia	arm_sp!, {r4, lr}
#endif // HW_FP

4:
	ldr	r0, [ip, #CPUInfo-XXX]
	tst	r0, #ARCH_CLZ
	beq	5f

	adrl	r0, do_idiv_clz
	str	r0, [ip, #opc_idiv * 4]
	adrl	r0, do_irem_clz
	str	r0, [ip, #opc_irem * 4]

5:
#endif // NOTICE_SAFEPOINTS

	bx	lr

@ --- notice_safepoints ---------------------------------------------------------------------------
	.global	_ZN14CppInterpreter17notice_safepointsEv
	.type	_ZN14CppInterpreter17notice_safepointsEv, %function
_ZN14CppInterpreter17notice_safepointsEv:
#ifdef NOTICE_SAFEPOINTS
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r2, r3}
	add	r2, r2, ip
	add	ip, r3, r2
	ldr	r2, [ip, #AbstractInterpreter_notice_safepoints-XXX]
	ldrb	r1, [r2, #0]	@ zero_extendqisi2
	cmp	r1, #0
	bxne	lr
	mov	r3, #1
	strb	r3, [r2, #0]
	adrl	r3, safe_dispatch_table
	mov	r2, #256
1:
	ldr	r1, [r3], #4
	str	r1, [ip], #4
	subs	r2, r2, #1
	bne	1b
#endif
	bx	lr

@ --- END execute.s ----------------------------------------------------------------------------

	ALIGN_CODE
bci_init:
        stmfd   sp!, {r4, lr}

	adrl	r3, dispatch_init_adcon
	ldm	r3, {r0, r1}
	add	r0, r0, r3
        add     r4, r1, r0
	adrl	r2, adcon_init_table
        mov     r1, r4
1:
	ldr	ip, [r2], #4
	cmp	ip, #0
	ldrne	ip, [r0, ip]
	strne	ip, [r1, #-4]!
	bne	1b
	adrl	r2, main_dispatch_table
	mov	r1, #256
        mov     r3, r4
2:
	ldr	ip, [r2], #4
	str	ip, [r3], #4
	subs	r1, r1, #1
	bne	2b

	bl	hwcap
	str	r0, [r4, #CPUInfo-XXX]

#ifdef USE_COMPILER

#define NPROCESSORS_CONF        83

        mov     r0, #NPROCESSORS_CONF
        bl      sysconf
        cmp     r0, #2

#ifdef DISABLE_BG_COMP_ON_NON_MP
        movcc   r0, #0
        ldrcc   r1, [r4, #BackgroundCompilation_Address-XXX]
        strccb  r0, [r1]
#endif

        movcs   r0, #MP_COMPILE_THRESHOLD
        movcc   r0, #UP_COMPILE_THRESHOLD
        ldr     r1, [r4, #CompileThreshold_Address-XXX]
        str     r0, [r1]

#endif // USE_COMPILER

#ifdef T2JIT
	bl	Thumb2_Initialize
#endif

#ifdef HW_FP
	ldr	r0, [r4, #CPUInfo-XXX]
	tst	r0, #ARCH_VFP
	bne	4f

@ No HW FP - replace the HW FP entries with SW entries
update_vfp_table:
	adr	r0, vfp_table
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r2, r3}
	add	r2, r2, ip
	add	ip, r3, r2
.update_vfp_loop:
	ldr	r1, [r0], #4
	cmp	r1, #0
	ldrne	r2, [r0], #4
	strne	r2, [ip, r1, lsl #2]
	bne	.update_vfp_loop
4:
#endif // HW_FP

	ldr	r0, [r4, #CPUInfo-XXX]
	tst	r0, #ARCH_CLZ
	beq	5f

	adrl	r0, do_idiv_clz
	str	r0, [r4, #opc_idiv * 4]
	adrl	r0, do_irem_clz
	str	r0, [r4, #opc_irem * 4]

5:
	ldmia	sp!, {r4, pc}

#ifdef HW_FP
vfp_table:
	.word	opc_fadd,	do_fadd
	.word	opc_dadd,	do_dadd
	.word	opc_fsub,	do_fsub
	.word	opc_dsub,	do_dsub
	.word	opc_fmul,	do_fmul
	.word	opc_dmul,	do_dmul
	.word	opc_fdiv,	do_fdiv
	.word	opc_ddiv,	do_ddiv
	.word	opc_fcmpl,	do_fcmpl
	.word	opc_fcmpg,	do_fcmpg
	.word	opc_dcmpl,	do_dcmpl
	.word	opc_dcmpg,	do_dcmpg
	.word	0
#endif // HW_FP

load_dispatch:
	adrl	ip, dispatch_init_adcon
	ldm	ip, {r0, r1}
	add	r0, r0, ip
	add	dispatch, r1, r0
	mov	pc, lr

	ALIGN_DATA
dispatch_init_adcon:
	.word	_GLOBAL_OFFSET_TABLE_-dispatch_init_adcon, opclabels_data(GOTOFF)
adcon_init_table:
	.word	_ZN18InterpreterRuntime22slow_signature_handlerEP10JavaThreadP13methodOopDescPiS4_(GOT)
	.word	_ZN20SafepointSynchronize6_stateE(GOT)
	.word	_ZN9vmSymbols8_symbolsE(GOT)
	.word	always_do_update_barrier(GOT)
	.word	_ZN8Universe14_collectedHeapE(GOT)
	.word	_ZN9Bytecodes5_nameE(GOT)
	.word	_ZN19AbstractInterpreter18_notice_safepointsE(GOT)
	.word	_ZN18ThreadLocalStorage13_thread_indexE(GOT)
	.word	_ZN7oopDesc3_bsE(GOT)
	.word	PrintCommandLineFlags(GOT)
	.word	_ZN11JvmtiExport28_can_post_interpreter_eventsE(GOT)
	.word	UseCompiler(GOT)
invocationlimit_adcon:
	.word	_ZN17InvocationCounter26InterpreterInvocationLimitE(GOT)
        .word   CompileThreshold(GOT)
        .word   BackgroundCompilation(GOT)
        .word   UseOnStackReplacement(GOT)
	.word	0

	ALIGN_DATA
main_dispatch_table:
	MAIN_DISPATCH_TABLE

#ifdef NOTICE_SAFEPOINTS
safe_dispatch_table:

/*  WARNING: If you change any of these bytecodes, you must also
    change the table in bytecodes_arm.def to make it match.  */

	.word	do_nop	@ 0 0x00
	.word	do_u4const_0	@ 1 0x01
	.word	do_iconst_N	@ 2 0x02
	.word	do_iconst_N	@ 3 0x03
	.word	do_iconst_N	@ 4 0x04
	.word	do_iconst_N	@ 5 0x05
	.word	do_iconst_N	@ 6 0x06
	.word	do_iconst_N	@ 7 0x07
	.word	do_iconst_N	@ 8 0x08
	.word	do_u8const_0	@ 9 0x09
	.word	do_lconst_1	@ 10 0x0a
	.word	do_u4const_0	@ 11 0x0b
	.word	do_fconst_1	@ 12 0x0c
	.word	do_fconst_2	@ 13 0x0d
	.word	do_u8const_0	@ 14 0x0e
	.word	do_dconst_1	@ 15 0x0f
	.word	do_bipush	@ 16 0x10
	.word	do_sipush	@ 17 0x11
	.word	do_ldc	@ 18 0x12
	.word	do_ldc_w	@ 19 0x13
	.word	do_ldc2_w	@ 20 0x14
	.word	do_u4load	@ 21 0x15
	.word	do_u8load	@ 22 0x16
	.word	do_u4load	@ 23 0x17
	.word	do_u8load	@ 24 0x18
	.word	do_u4load	@ 25 0x19
	.word	do_iload_0	@ 26 0x1a
	.word	do_iload_0	@ 27 0x1b
	.word	do_iload_0	@ 28 0x1c
	.word	do_iload_0	@ 29 0x1d
	.word	do_u8load_0	@ 30 0x1e
	.word	do_u8load_1	@ 31 0x1f
	.word	do_u8load_2	@ 32 0x20
	.word	do_u8load_3	@ 33 0x21
	.word	do_fload_0	@ 34 0x22
	.word	do_fload_0	@ 35 0x23
	.word	do_fload_0	@ 36 0x24
	.word	do_fload_0	@ 37 0x25
	.word	do_u8load_0	@ 38 0x26
	.word	do_u8load_1	@ 39 0x27
	.word	do_u8load_2	@ 40 0x28
	.word	do_u8load_3	@ 41 0x29
	.word	do_aload_0	@ 42 0x2a
	.word	do_aload_0	@ 43 0x2b
	.word	do_aload_0	@ 44 0x2c
	.word	do_aload_0	@ 45 0x2d
	.word	do_u4aload	@ 46 0x2e
	.word	do_u8aload	@ 47 0x2f
	.word	do_u4aload	@ 48 0x30
	.word	do_u8aload	@ 49 0x31
	.word	do_u4aload	@ 50 0x32
	.word	do_baload	@ 51 0x33
	.word	do_caload	@ 52 0x34
	.word	do_saload	@ 53 0x35
	.word	do_u4store	@ 54 0x36
	.word	do_u8store	@ 55 0x37
	.word	do_u4store	@ 56 0x38
	.word	do_u8store	@ 57 0x39
	.word	do_u4store	@ 58 0x3a
	.word	do_u4store_0	@ 59 0x3b
	.word	do_u4store_1	@ 60 0x3c
	.word	do_u4store_2	@ 61 0x3d
	.word	do_u4store_3	@ 62 0x3e
	.word	do_u8store_0	@ 63 0x3f
	.word	do_u8store_1	@ 64 0x40
	.word	do_u8store_2	@ 65 0x41
	.word	do_u8store_3	@ 66 0x42
	.word	do_u4store_0	@ 67 0x43
	.word	do_u4store_1	@ 68 0x44
	.word	do_u4store_2	@ 69 0x45
	.word	do_u4store_3	@ 70 0x46
	.word	do_u8store_0	@ 71 0x47
	.word	do_u8store_1	@ 72 0x48
	.word	do_u8store_2	@ 73 0x49
	.word	do_u8store_3	@ 74 0x4a
	.word	do_u4store_0	@ 75 0x4b
	.word	do_u4store_1	@ 76 0x4c
	.word	do_u4store_2	@ 77 0x4d
	.word	do_u4store_3	@ 78 0x4e
	.word	do_u4astore	@ 79 0x4f
	.word	do_u8astore	@ 80 0x50
	.word	do_u4astore	@ 81 0x51
	.word	do_u8astore	@ 82 0x52
	.word	do_aastore	@ 83 0x53
	.word	do_bastore	@ 84 0x54
	.word	do_u2astore	@ 85 0x55
	.word	do_u2astore	@ 86 0x56
	.word	do_jpop	@ 87 0x57
	.word	do_jpop2	@ 88 0x58
	.word	do_dup	@ 89 0x59
	.word	do_dup_x1	@ 90 0x5a
	.word	do_dup_x2	@ 91 0x5b
	.word	do_dup2	@ 92 0x5c
	.word	do_dup2_x1	@ 93 0x5d
	.word	do_dup2_x2	@ 94 0x5e
	.word	do_swap	@ 95 0x5f
	.word	do_iadd	@ 96 0x60
	.word	do_ladd	@ 97 0x61
	.word	do_fadd	@ 98 0x62
	.word	do_dadd	@ 99 0x63
	.word	do_isub	@ 100 0x64
	.word	do_lsub	@ 101 0x65
	.word	do_fsub	@ 102 0x66
	.word	do_dsub	@ 103 0x67
	.word	do_imul	@ 104 0x68
	.word	do_lmul	@ 105 0x69
	.word	do_fmul	@ 106 0x6a
	.word	do_dmul	@ 107 0x6b
	.word	do_idiv	@ 108 0x6c
	.word	do_ldiv	@ 109 0x6d
	.word	do_fdiv	@ 110 0x6e
	.word	do_ddiv	@ 111 0x6f
	.word	do_irem	@ 112 0x70
	.word	do_lrem	@ 113 0x71
	.word	do_frem	@ 114 0x72
	.word	do_drem	@ 115 0x73
	.word	do_ineg	@ 116 0x74
	.word	do_lneg	@ 117 0x75
	.word	do_fneg	@ 118 0x76
	.word	do_dneg	@ 119 0x77
	.word	do_ishl	@ 120 0x78
	.word	do_lshl	@ 121 0x79
	.word	do_ishr	@ 122 0x7a
	.word	do_lshr	@ 123 0x7b
	.word	do_iushr	@ 124 0x7c
	.word	do_lushr	@ 125 0x7d
	.word	do_iand	@ 126 0x7e
	.word	do_land	@ 127 0x7f
	.word	do_ior	@ 128 0x80
	.word	do_lor	@ 129 0x81
	.word	do_ixor	@ 130 0x82
	.word	do_lxor	@ 131 0x83
	.word	do_iinc	@ 132 0x84
	.word	do_i2l	@ 133 0x85
	.word	do_i2f	@ 134 0x86
	.word	do_i2d	@ 135 0x87
	.word	do_l2i	@ 136 0x88
	.word	do_l2f	@ 137 0x89
	.word	do_l2d	@ 138 0x8a
	.word	do_f2i	@ 139 0x8b
	.word	do_f2l	@ 140 0x8c
	.word	do_f2d	@ 141 0x8d
	.word	do_d2i	@ 142 0x8e
	.word	do_d2l	@ 143 0x8f
	.word	do_d2f	@ 144 0x90
	.word	do_i2b	@ 145 0x91
	.word	do_i2c	@ 146 0x92
	.word	do_i2s	@ 147 0x93
	.word	do_lcmp	@ 148 0x94
	.word	do_fcmpl	@ 149 0x95
	.word	do_fcmpg	@ 150 0x96
	.word	do_dcmpl	@ 151 0x97
	.word	do_dcmpg	@ 152 0x98
	.word	do_ifeq	@ 153 0x99
	.word	do_ifne	@ 154 0x9a
	.word	do_iflt	@ 155 0x9b
	.word	do_ifge	@ 156 0x9c
	.word	do_ifgt	@ 157 0x9d
	.word	do_ifle	@ 158 0x9e
	.word	do_if_icmpeq	@ 159 0x9f
	.word	do_if_icmpne	@ 160 0xa0
	.word	do_if_icmplt	@ 161 0xa1
	.word	do_if_icmpge	@ 162 0xa2
	.word	do_if_icmpgt	@ 163 0xa3
	.word	do_if_icmple	@ 164 0xa4
	.word	do_if_icmpeq	@ 165 0xa5
	.word	do_if_icmpne	@ 166 0xa6
	.word	do_goto	@ 167 0xa7
	.word	do_jsr	@ 168 0xa8
	.word	do_ret	@ 169 0xa9
	.word	do_tableswitch	@ 170 0xaa
	.word	do_lookupswitch	@ 171 0xab
	.word	do_ireturn	@ 172 0xac
	.word	do_lreturn	@ 173 0xad
	.word	do_ireturn	@ 174 0xae
	.word	do_lreturn	@ 175 0xaf
	.word	do_ireturn	@ 176 0xb0
	.word	do_return	@ 177 0xb1
	.word	do_getstatic	@ 178 0xb2
	.word	do_putstatic	@ 179 0xb3
	.word	do_getfield	@ 180 0xb4
	.word	do_putfield	@ 181 0xb5
	.word	do_invokevirtual	@ 182 0xb6
	.word	do_invokespecial	@ 183 0xb7
	.word	do_invokestatic	@ 184 0xb8
	.word	do_invokeinterface	@ 185 0xb9
	.word	do_invokedynamic	@ 186 0xba
	.word	do_new	@ 187 0xbb
	.word	do_newarray	@ 188 0xbc
	.word	do_anewarray	@ 189 0xbd
	.word	do_arraylength	@ 190 0xbe
	.word	do_athrow	@ 191 0xbf
	.word	do_checkcast	@ 192 0xc0
	.word	do_instanceof	@ 193 0xc1
	.word	do_monitorenter	@ 194 0xc2
	.word	do_monitorexit	@ 195 0xc3
	.word	do_wide	@ 196 0xc4
	.word	do_multianewarray	@ 197 0xc5
	.word	do_ifeq	@ 198 0xc6
	.word	do_ifne	@ 199 0xc7
	.word	do_goto_w	@ 200 0xc8
	.word	do_jsr_w	@ 201 0xc9
	.word	do_breakpoint	@ 202 0xca
	.word	do_undefined	@ 203 0xcb
	.word	do_bgetfield	@ 204 0xcc
	.word	do_cgetfield	@ 205 0xcd
	.word	do_undefined	@ 206 0xce
	.word	do_undefined	@ 207 0xcf
	.word	do_igetfield	@ 208 0xd0
	.word	do_lgetfield	@ 209 0xd1
	.word	do_sgetfield	@ 210 0xd2
	.word	do_aputfield	@ 211 0xd3
	.word	do_bputfield	@ 212 0xd4
	.word	do_cputfield	@ 213 0xd5
	.word	do_undefined	@ 214 0xd6
	.word	do_undefined	@ 215 0xd7
	.word	do_iputfield	@ 216 0xd8
	.word	do_lputfield	@ 217 0xd9
	.word	do_undefined	@ 218 0xda
	.word	do_iaccess_0	@ 219 0xdb
	.word	do_iaccess_0	@ 220 0xdc
	.word	do_iaccess_0	@ 221 0xdd
	.word	do_iaccess_0	@ 222 0xde
	.word	do_invokeresolved	@ 223 0xdf
	.word	do_invokespecialresolved	@ 224 0xe0
	.word	do_invokestaticresolved	@ 225 0xe1
	.word	do_invokevfinal	@ 226 0xe2
	.word	do_fast_iload_iload	@ 227 0xe3
	.word	do_fast_iload_iload_N	@ 228 0xe4
	.word	do_fast_aldc		@ 229 0xe5
	.word	do_fast_aldc_w	@ 230 0xe6
	.word	do_return_register_finalizer	@ 231 0xe7
	.word	do_undefined	@ 232 0xe8
	.word	do_iload_0_iconst_N	@ 233 0xe9
	.word	do_iload_0_iconst_N	@ 234 0xea
	.word	do_iload_0_iconst_N	@ 235 0xeb
	.word	do_iload_0_iconst_N	@ 236 0xec
	.word	do_iload_iconst_N	@ 237 0xed
	.word	do_iadd_istore_N	@ 238 0xee
	.word	do_isub_istore_N	@ 239 0xef
	.word	do_iand_istore_N	@ 240 0xf0
	.word	do_ior_istore_N	@ 241 0xf1
	.word	do_ixor_istore_N	@ 242 0xf2
	.word	do_iadd_u4store	@ 243 0xf3
	.word	do_isub_u4store	@ 244 0xf4
	.word	do_iand_u4store	@ 245 0xf5
	.word	do_ior_u4store	@ 246 0xf6
	.word	do_ixor_u4store	@ 247 0xf7
	.word	do_fast_iload_N_iload	@ 248 0xf8
	.word	do_fast_iload_N_iload	@ 249 0xf9
	.word	do_fast_iload_N_iload	@ 250 0xfa
	.word	do_fast_iload_N_iload	@ 251 0xfb
	.word	do_fast_iload_N_iload_N	@ 252 0xfc
	.word	do_fast_iload_N_iload_N	@ 253 0xfd
	.word	do_fast_iload_N_iload_N	@ 254 0xfe
	.word	do_fast_iload_N_iload_N	@ 255 0xff
#endif

	SUB_DISPATCH_TABLES

	.arch	armv7-a

	ALIGN_CODE
	.global	Thumb2_stubs
	.type Thumb2_stubs, %function
Thumb2_stubs:
	.global	Thumb2_idiv_stub
	.type Thumb2_idiv_stub, %function
Thumb2_idiv_stub:
int_div:
	cmp     r1, #0x21
	adr	r3, 1f
	eor     r12, r0, r1
	ldrcc	pc, [r3, r1, lsl #2]
	rsblt   r1, r1, #0
	subs    r2, r1, #1
	beq     2f
	movs    r3, r0
	rsbmi   r3, r0, #0
	cmp     r3, r1
	bls     3f
	tst     r1, r2
	beq     4f
	clz     r2, r3
	clz     r0, r1
	sub     r2, r0, r2
	rsbs    r2, r2, #31
	add     r2, r2, r2, lsl #1
	mov     r0, #0
	add     pc, pc, r2, lsl #2
	mov	r0, #0
	cmp     r3, r1, lsl #31
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #31
	cmp     r3, r1, lsl #30
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #30
	cmp     r3, r1, lsl #29
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #29
	cmp     r3, r1, lsl #28
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #28
	cmp     r3, r1, lsl #27
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #27
	cmp     r3, r1, lsl #26
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #26
	cmp     r3, r1, lsl #25
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #25
	cmp     r3, r1, lsl #24
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #24
	cmp     r3, r1, lsl #23
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #23
	cmp     r3, r1, lsl #22
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #22
	cmp     r3, r1, lsl #21
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #21
	cmp     r3, r1, lsl #20
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #20
	cmp     r3, r1, lsl #19
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #19
	cmp     r3, r1, lsl #18
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #18
	cmp     r3, r1, lsl #17
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #17
	cmp     r3, r1, lsl #16
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #16
	cmp     r3, r1, lsl #15
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #15
	cmp     r3, r1, lsl #14
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #14
	cmp     r3, r1, lsl #13
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #13
	cmp     r3, r1, lsl #12
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #12
	cmp     r3, r1, lsl #11
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #11
	cmp     r3, r1, lsl #10
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #10
	cmp     r3, r1, lsl #9
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #9
	cmp     r3, r1, lsl #8
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #8
	cmp     r3, r1, lsl #7
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #7
	cmp     r3, r1, lsl #6
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #6
	cmp     r3, r1, lsl #5
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #5
	cmp     r3, r1, lsl #4
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #4
	cmp     r3, r1, lsl #3
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #3
	cmp     r3, r1, lsl #2
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #2
	cmp     r3, r1, lsl #1
	adc     r0, r0, r0
	subcs   r3, r3, r1, lsl #1
	cmp     r3, r1
	adc     r0, r0, r0
	subcs   r3, r3, r1
	cmp     r12, #0
	rsbmi   r0, r0, #0
	bx      lr
2:
	teq     r12, r0
	rsbmi   r0, r0, #0
	bx      lr
3:
	movcc   r0, #0
	asreq   r0, r12, #31
	orreq   r0, r0, #1
	bx      lr
4:
	clz     r2, r1
	rsb     r2, r2, #31
	cmp     r12, #0
	lsr     r0, r3, r2
	rsbmi   r0, r0, #0
	bx      lr
1:
	.word	Thumb2_DivZero_Handler
	.word	jdiv_1
	.word	jdiv_2
	.word	jdiv_3
	.word	jdiv_4
	.word	jdiv_5
	.word	jdiv_6
	.word	jdiv_7
	.word	jdiv_8
	.word	jdiv_9
	.word	jdiv_10
	.word	jdiv_11
	.word	jdiv_12
	.word	jdiv_13
	.word	jdiv_14
	.word	jdiv_15
	.word	jdiv_16
	.word	jdiv_17
	.word	jdiv_18
	.word	jdiv_19
	.word	jdiv_20
	.word	jdiv_21
	.word	jdiv_22
	.word	jdiv_23
	.word	jdiv_24
	.word	jdiv_25
	.word	jdiv_26
	.word	jdiv_27
	.word	jdiv_28
	.word	jdiv_29
	.word	jdiv_30
	.word	jdiv_31
	.word	jdiv_32
	ALIGN_CODE
	.global	Thumb2_irem_stub
	.type Thumb2_irem_stub, %function
Thumb2_irem_stub:
int_rem:
	cmp     r1, #0x21
	adr	r3, 1f
	ldrcc	pc, [r3, r1, lsl #2]
	rsblt   r1, r1, #0
	subs    r2, r1, #1
	beq     2f
	movs    r12, r0
	rsbmi   r0, r0, #0
	cmp     r0, r1
	bls     3f
	tst     r1, r2
	beq     4f
	clz     r2, r0
	clz     r3, r1
	sub     r2, r3, r2
	rsbs    r2, r2, #31
	add     pc, pc, r2, lsl #3
	mov	r3, #0
	cmp     r0, r1, lsl #31
	subcs   r0, r0, r1, lsl #31
	cmp     r0, r1, lsl #30
	subcs   r0, r0, r1, lsl #30
	cmp     r0, r1, lsl #29
	subcs   r0, r0, r1, lsl #29
	cmp     r0, r1, lsl #28
	subcs   r0, r0, r1, lsl #28
	cmp     r0, r1, lsl #27
	subcs   r0, r0, r1, lsl #27
	cmp     r0, r1, lsl #26
	subcs   r0, r0, r1, lsl #26
	cmp     r0, r1, lsl #25
	subcs   r0, r0, r1, lsl #25
	cmp     r0, r1, lsl #24
	subcs   r0, r0, r1, lsl #24
	cmp     r0, r1, lsl #23
	subcs   r0, r0, r1, lsl #23
	cmp     r0, r1, lsl #22
	subcs   r0, r0, r1, lsl #22
	cmp     r0, r1, lsl #21
	subcs   r0, r0, r1, lsl #21
	cmp     r0, r1, lsl #20
	subcs   r0, r0, r1, lsl #20
	cmp     r0, r1, lsl #19
	subcs   r0, r0, r1, lsl #19
	cmp     r0, r1, lsl #18
	subcs   r0, r0, r1, lsl #18
	cmp     r0, r1, lsl #17
	subcs   r0, r0, r1, lsl #17
	cmp     r0, r1, lsl #16
	subcs   r0, r0, r1, lsl #16
	cmp     r0, r1, lsl #15
	subcs   r0, r0, r1, lsl #15
	cmp     r0, r1, lsl #14
	subcs   r0, r0, r1, lsl #14
	cmp     r0, r1, lsl #13
	subcs   r0, r0, r1, lsl #13
	cmp     r0, r1, lsl #12
	subcs   r0, r0, r1, lsl #12
	cmp     r0, r1, lsl #11
	subcs   r0, r0, r1, lsl #11
	cmp     r0, r1, lsl #10
	subcs   r0, r0, r1, lsl #10
	cmp     r0, r1, lsl #9
	subcs   r0, r0, r1, lsl #9
	cmp     r0, r1, lsl #8
	subcs   r0, r0, r1, lsl #8
	cmp     r0, r1, lsl #7
	subcs   r0, r0, r1, lsl #7
	cmp     r0, r1, lsl #6
	subcs   r0, r0, r1, lsl #6
	cmp     r0, r1, lsl #5
	subcs   r0, r0, r1, lsl #5
	cmp     r0, r1, lsl #4
	subcs   r0, r0, r1, lsl #4
	cmp     r0, r1, lsl #3
	subcs   r0, r0, r1, lsl #3
	cmp     r0, r1, lsl #2
	subcs   r0, r0, r1, lsl #2
	cmp     r0, r1, lsl #1
	subcs   r0, r0, r1, lsl #1
	cmp     r0, r1
	subcs   r0, r0, r1
	cmp     r12, #0
	rsbmi   r0, r0, #0
	bx      lr
2:
	mov	r0, #0
	bx      lr
3:
	moveq	r0, #0
	cmp	r12, #0
	rsbmi	r0, r0, #0
	bx	lr
4:
	and	r0, r0, r2
	cmp	r12, #0
	rsbmi	r0, r0, #0
	bx      lr
1:
	.word	Thumb2_DivZero_Handler
	.word	jrem_1
	.word	jrem_2
	.word	jrem_3
	.word	jrem_4
	.word	jrem_5
	.word	jrem_6
	.word	jrem_7
	.word	jrem_8
	.word	jrem_9
	.word	jrem_10
	.word	jrem_11
	.word	jrem_12
	.word	jrem_13
	.word	jrem_14
	.word	jrem_15
	.word	jrem_16
	.word	jrem_17
	.word	jrem_18
	.word	jrem_19
	.word	jrem_20
	.word	jrem_21
	.word	jrem_22
	.word	jrem_23
	.word	jrem_24
	.word	jrem_25
	.word	jrem_26
	.word	jrem_27
	.word	jrem_28
	.word	jrem_29
	.word	jrem_30
	.word	jrem_31
	.word	jrem_32

#ifdef T2JIT

	.macro	LOAD_FRAME
	ldr	Rframe, [thread, #THREAD_TOP_ZERO_FRAME]
	.endm

@ R0 = BCI
@ R1 = index

	.global	Thumb2_invokeinterface_stub
	.type Thumb2_invokeinterface_stub, %function
Thumb2_invokeinterface_stub:
	LOAD_FRAME
	stmdb	sp!, {ip, lr}
	ldr	ip, [Rframe, #FRAME_METHOD]
	sub	stack, stack, #4
	ldr	r2, [Rframe, #FRAME_CONSTANTS]
	ldr	ip, [ip, #METHOD_CONSTMETHOD]
	str	stack, [Rframe, #FRAME_STACK]
	add	jpc, ip, r0
        add     r0, r2, r1, lsl #4
	str	jpc, [Rframe, #FRAME_BCP]

        ldr     r2, [r0, #CP_OFFSET]
        and     r2, r2, #0x00ff0000
        cmp     r2, #opc_invokeinterface << 16
        bne     istub_resolve
2:
	ldr	r3, [r0, #CP_OFFSET+12]
	and	r2, r3, #255
	ldr	r2, [stack, r2, lsl #2]
	cmp	r2, #0
	beq	istub_null_ptr_exception
	ldr	tmp1, [r2, #4]				@ rcvr->klass()
	tst	r3, #flag_methodInterface
	bne	istub_methodInterface

	ldr	lr, [r0, #CP_OFFSET+4]			@ lr = iclass

	add	r1, tmp1, #INSTANCEKLASS_VTABLE_OFFSET
	ldr	r2, [tmp1, #KLASS_PART+INSTANCEKLASS_VTABLE_LEN]
	ldr	ip, [tmp1, #KLASS_PART+INSTANCEKLASS_ITABLE_LEN]
	add	r2, r2, #1
	bic	r2, r2, #1

	add	r1, r1, r2, lsl #2

	mov	r2, #0
1:
	cmp	r2, ip
	beq	istub_incompatibleclass_exception
	ldr	r3, [r1], #8
	add	r2, r2, #1
	cmp	lr, r3
	bne	1b

	ldr	r3, [r0, #CP_OFFSET+8]
	ldr	r2, [r1, #-4]
	add	r3, tmp1, r3, lsl #2
	ldr	tmp1, [r3, r2]
	cmp	tmp1, #0
	beq	istub_abstractmethod_exception
istub_invoke:
	ldr	ip, [tmp1, #METHOD_FROM_INTERPRETED]
	mov	r1, #0
	str	r1, [thread, #THREAD_LAST_JAVA_FP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [ip]

	mov	r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
	add	r3, r3, #FAST_ENTRY_OFFSET
#endif
	blx	r3

	LOAD_FRAME

	ldr	stack, [thread, #THREAD_JAVA_SP]
	ldr	r2, [Rframe, #FRAME_STACK_LIMIT]

	ldr	r1, [thread, #THREAD_TOP_ZERO_FRAME]
	add	r2, r2, #4
	mov	r0, #0
	str	r0, [thread, #THREAD_LAST_JAVA_SP]
	str	r2, [thread, #THREAD_JAVA_SP]
	str	r1, [thread, #THREAD_LAST_JAVA_FP]
	str	r2, [thread, #THREAD_LAST_JAVA_SP]
	ldr	r3, [thread, #4]
	cmp	r3, #0
	bne	istub_exception
	ldmia	sp!, {ip, pc}

istub_methodInterface:
	tst	r3, #flag_vfinalMethod
	ldrne	tmp1, [r0, #CP_OFFSET+8]
	bne	istub_invoke
	ldr	r1, [r0, #CP_OFFSET+8]
	add	r3, tmp1, r1, lsl #2
	ldr	tmp1, [r3, #INSTANCEKLASS_VTABLE_OFFSET]
	b	istub_invoke

istub_resolve:
	mov	tmp1, r1
	mov	r1, #opc_invokeinterface
	mov	r0, thread
	ldr	ip, resolve_invoke_adcon
	blx	ip
	ldr	r3, [thread, #4]
	ldr	r2, [Rframe, #FRAME_CONSTANTS]
	cmp	r3, #0
	bne	istub_exception
	add	r0, r2, tmp1, lsl #4	@ r1 = cache
	b	2b

istub_exception:
	ldmia	sp!, {ip, lr}
	ldr	ip, handle_exception_adcon
	LOAD_ISTATE
	bx	ip

istub_null_ptr_exception:
	mov	r0, #VMSYMBOLS_NullPointerException
	b	3f
istub_abstractmethod_exception:
	mov	r0, #VMSYMBOLS_AbstractMethodError
	b	3f
istub_incompatibleclass_exception:
	mov	r0, #VMSYMBOLS_IncompatibleClassChangeError
3:
	ldr	jpc, [Rframe, #FRAME_BCP]
	ldmia	sp!, {ip, lr}
	ldr	ip, raise_exception_adcon
	LOAD_ISTATE
	bx	ip

resolve_invoke_adcon:
	.word	_ZN18InterpreterRuntime14resolve_invokeEP10JavaThreadN9Bytecodes4CodeE
resolve_get_put_adcon:
       	.word   _ZN18InterpreterRuntime15resolve_get_putEP10JavaThreadN9Bytecodes4CodeE
handle_exception_adcon:
	.word	handle_exception_with_bcp
raise_exception_adcon:
	.word	raise_exception
helper_aputfield_adcon:
	.word	Helper_aputfield
lr_to_bci_adcon:
	.word	Thumb2_lr_to_bci

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokevirtual_stub
	.type Thumb2_invokevirtual_stub, %function
Thumb2_invokevirtual_stub:
	LOAD_FRAME
	stmdb	sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
	str	stack, [Rframe, #FRAME_STACK]
        add     jpc, ip, r0
        add     r0, r2, r1, lsl #4
	str	jpc, [Rframe, #FRAME_BCP]

        ldr     r2, [r0, #CP_OFFSET]
        and     r2, r2, #0xff000000
        cmp     r2, #opc_invokevirtual << 24
        bne     ivstub_resolve
2:

	ldr	r3, [r0, #CP_OFFSET+12]
        and     r2, r3, #255
        ldr     r2, [stack, r2, asl #2]
        cmp     r2, #0
        beq     istub_null_ptr_exception

        ldr     tmp1, [r0, #CP_OFFSET+8]
        tst     r3, #flag_vfinalMethod
        bne     1f

        ldr     r3, [r2, #4]
        add     r3, r3, tmp1, lsl #2
        ldr     tmp1, [r3, #INSTANCEKLASS_VTABLE_OFFSET]
1:
	mov	r1, #0
        ldr     ip, [tmp1, #METHOD_FROM_INTERPRETED]
        str     r1, [thread, #THREAD_LAST_JAVA_SP]
        str     r1, [thread, #THREAD_LAST_JAVA_FP]

        add     stack, stack, #4
        str     stack, [thread, #THREAD_JAVA_SP]

        ldr     r3, [ip, #0]

	mov	r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
	add	r3, r3, #FAST_ENTRY_OFFSET
#endif
	blx	r3
	LOAD_FRAME

	ldr	stack, [thread, #THREAD_JAVA_SP]
	ldr	r2, [Rframe, #FRAME_STACK_LIMIT]

	mov	r0, #0
	str	r0, [thread, #THREAD_LAST_JAVA_SP]
	ldr	r1, [thread, #THREAD_TOP_ZERO_FRAME]
	add	r2, r2, #4
	str	r2, [thread, #THREAD_JAVA_SP]
	str	r1, [thread, #THREAD_LAST_JAVA_FP]
	str	r2, [thread, #THREAD_LAST_JAVA_SP]
	ldr	r3, [thread, #4]
	cmp	r3, #0
	bne	istub_exception
	ldmia	sp!, {ip, pc}

ivstub_resolve:
	mov	tmp1, r1
	mov	r1, #opc_invokevirtual
	mov	r0, thread
	ldr	ip, resolve_invoke_adcon
	blx	ip
	ldr	r3, [thread, #4]
	ldr	r2, [Rframe, #FRAME_CONSTANTS]
	cmp	r3, #0
	bne	istub_exception
	add	r0, r2, tmp1, lsl #4	@ r1 = cache
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokevfinalresolved_stub
Thumb2_invokevfinalresolved_stub:
	LOAD_FRAME
        stmdb   sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
        DECACHE_STACK_USING_FRAME
        add     jpc, ip, r0

        add     r0, r2, r1, lsl #4
        DECACHE_JPC_USING_FRAME
        ldr     r3, [r0, #CP_OFFSET+12]
        and     r2, r3, #255
        ldr     r2, [stack, r2, asl #2]
        cmp     r2, #0
        beq     istub_null_ptr_exception

        ldr     tmp1, [r0, #CP_OFFSET+8]
        mov     r1, #0
        ldr     ip, [tmp1, #METHOD_FROM_INTERPRETED]
        str     r1, [thread, #THREAD_LAST_JAVA_SP]

        add     stack, stack, #4
        str     stack, [thread, #THREAD_JAVA_SP]

        ldr     r3, [ip, #0]

        mov     r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
        add     r3, r3, #FAST_ENTRY_OFFSET
#endif
        blx     r3
	LOAD_FRAME

        ldr     stack, [thread, #THREAD_JAVA_SP]
        ldr     r2, [Rframe, #FRAME_STACK_LIMIT]

        add     r2, r2, #4
        str     r2, [thread, #THREAD_JAVA_SP]
        str     Rframe, [thread, #THREAD_LAST_JAVA_SP]
        ldr     r3, [thread, #4]
        cmp     r3, #0
        bne     istub_exception
        ldmia   sp!, {ip, pc}

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokevirtualresolved_stub
Thumb2_invokevirtualresolved_stub:
	LOAD_FRAME
        stmdb   sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
        DECACHE_STACK_USING_FRAME
        add     jpc, ip, r0

        add     r0, r2, r1, lsl #4
        DECACHE_JPC_USING_FRAME

        ldr     r3, [r0, #CP_OFFSET+12]
        and     r2, r3, #255
        ldr     r2, [stack, r2, asl #2]
        cmp     r2, #0
        beq     istub_null_ptr_exception

        ldr     tmp1, [r0, #CP_OFFSET+8]
        ldr     r3, [r2, #4]
        add     r3, r3, tmp1, lsl #2
        ldr     tmp1, [r3, #INSTANCEKLASS_VTABLE_OFFSET]
        mov     r1, #0
        ldr     ip, [tmp1, #METHOD_FROM_INTERPRETED]
        str     r1, [thread, #THREAD_LAST_JAVA_SP]

        add     stack, stack, #4
        str     stack, [thread, #THREAD_JAVA_SP]

        ldr     r3, [ip, #0]

        mov     r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
        add     r3, r3, #FAST_ENTRY_OFFSET
#endif
        blx     r3
	LOAD_FRAME

        ldr     stack, [thread, #THREAD_JAVA_SP]
        ldr     r2, [Rframe, #FRAME_STACK_LIMIT]

        add     r2, r2, #4
        str     r2, [thread, #THREAD_JAVA_SP]
        str     Rframe, [thread, #THREAD_LAST_JAVA_SP]
        ldr     r3, [thread, #4]
        cmp     r3, #0
        bne     istub_exception
        ldmia   sp!, {ip, pc}

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokestatic_stub
	.type Thumb2_invokestatic_stub, %function
Thumb2_invokestatic_stub:
	LOAD_FRAME
        stmdb   sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
        DECACHE_STACK_USING_FRAME
        add     jpc, ip, r0

        add     r0, r2, r1, lsl #4
        DECACHE_JPC_USING_FRAME

        ldr     r2, [r0, #CP_OFFSET]
	and	r2, r2, #0x00ff0000
	cmp	r2, #opc_invokestatic << 16
	bne	isstub_resolve
2:
	ldr	tmp1, [r0, #CP_OFFSET+4]
	mov	r1, #0
	ldr	ip, [tmp1, #METHOD_FROM_INTERPRETED]
	str	r1, [thread, #THREAD_LAST_JAVA_SP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [ip, #0]

        mov     r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
        add     r3, r3, #FAST_ENTRY_OFFSET
#endif
        blx     r3
	LOAD_FRAME

        ldr     stack, [thread, #THREAD_JAVA_SP]
        ldr     r2, [Rframe, #FRAME_STACK_LIMIT]

        ldr     r1, [thread, #THREAD_TOP_ZERO_FRAME]
        add     r2, r2, #4
	mov	r3, #0
	str	r3, [thread, #THREAD_LAST_JAVA_SP]	
        str     r1, [thread, #THREAD_LAST_JAVA_FP]
        str     r2, [thread, #THREAD_JAVA_SP]
        str     Rframe, [thread, #THREAD_LAST_JAVA_SP] // FIXME: Don't understand this
        ldr     r3, [thread, #4]
        cmp     r3, #0
        bne     istub_exception
	mov	r0, #0
        ldmia   sp!, {ip, pc}

isstub_resolve:
        mov     tmp1, r1
        mov     r1, #opc_invokestatic
        mov	r0, thread
        ldr     ip, resolve_invoke_adcon
        blx     ip
        ldr     r3, [thread, #4]
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        cmp     r3, #0
        bne     istub_exception
        add     r0, r2, tmp1, lsl #4    @ r1 = cache
        b       2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokestaticresolved_stub
Thumb2_invokestaticresolved_stub:
	LOAD_FRAME
	stmdb	sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
        DECACHE_STACK_USING_FRAME
        add     jpc, ip, r0
        add     r0, r2, r1, lsl #4
        DECACHE_JPC_USING_FRAME
        ldr     tmp1, [r0, #CP_OFFSET+4]
        mov     r1, #0
        ldr     ip, [tmp1, #METHOD_FROM_INTERPRETED]
        str     r1, [thread, #THREAD_LAST_JAVA_SP]

        add     stack, stack, #4
        str     stack, [thread, #THREAD_JAVA_SP]
        ldr     r3, [ip, #0]

        mov     r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
        add     r3, r3, #FAST_ENTRY_OFFSET
#endif
        blx     r3
	LOAD_FRAME

        ldr     stack, [thread, #THREAD_JAVA_SP]
        ldr     r2, [Rframe, #FRAME_STACK_LIMIT]

        ldr     r1, [thread, #THREAD_TOP_ZERO_FRAME]
        add     r2, r2, #4
	mov	r3, #0
	str	r3, [thread, #THREAD_LAST_JAVA_SP]	
        str     r1, [thread, #THREAD_LAST_JAVA_FP]
        str     r2, [thread, #THREAD_JAVA_SP]
        str     Rframe, [thread, #THREAD_LAST_JAVA_SP] // FIXME: Don't understand this
        ldr     r3, [thread, #4]
        cmp     r3, #0
        bne     istub_exception
	mov	r0, #0
        ldmia   sp!, {ip, pc}

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokespecial_stub
	.type Thumb2_invokespecial_stub, %function
Thumb2_invokespecial_stub:
	LOAD_FRAME
        stmdb   sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
        DECACHE_STACK_USING_FRAME
        add     jpc, ip, r0

        add     r0, r2, r1, lsl #4
        DECACHE_JPC_USING_FRAME
 
        ldr     r2, [r0, #CP_OFFSET]
 	and	r2, r2, #0x00ff0000
	cmp	r2, #opc_invokespecial << 16
	bne	ispstub_resolve
2:
        ldr     r3, [r0, #CP_OFFSET+12]
        and     r3, r3, #255
        ldr     r2, [stack, r3, asl #2]
	cmp	r2, #0
	beq	istub_null_ptr_exception

	ldr	tmp1, [r0, #CP_OFFSET+4]
	mov	r1, #0
	ldr	ip, [tmp1, #METHOD_FROM_INTERPRETED]
	str	r1, [thread, #THREAD_LAST_JAVA_SP]

	add	stack, stack, #4
	str	stack, [thread, #THREAD_JAVA_SP]

	ldr	r3, [ip, #0]

        mov     r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
        add     r3, r3, #FAST_ENTRY_OFFSET
#endif
        mov     r2, thread
        blx     r3
	LOAD_FRAME

        ldr     stack, [thread, #THREAD_JAVA_SP]
        ldr     r2, [Rframe, #FRAME_STACK_LIMIT]

        ldr     r1, [thread, #THREAD_TOP_ZERO_FRAME]
        add     r2, r2, #4
	mov	r3, #0
	str	r3, [thread, #THREAD_LAST_JAVA_SP]	
        str     r1, [thread, #THREAD_LAST_JAVA_FP]
        str     r2, [thread, #THREAD_JAVA_SP]
        str     Rframe, [thread, #THREAD_LAST_JAVA_SP] // FIXME: Don't understand this
        ldr     r3, [thread, #4]
        cmp     r3, #0
        bne     istub_exception
	mov	r0, #0
        ldmia   sp!, {ip, pc}

ispstub_resolve:
        mov     tmp1, r1
        mov     r1, #opc_invokespecial
        mov	r0, thread
        ldr     ip, resolve_invoke_adcon
        blx     ip
        ldr     r3, [thread, #4]
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        cmp     r3, #0
        bne     istub_exception
        add     r0, r2, tmp1, lsl #4    @ r1 = cache
        b       2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_invokespecialresolved_stub
Thumb2_invokespecialresolved_stub:
	LOAD_FRAME
        stmdb   sp!, {ip, lr}
        ldr     ip, [Rframe, #FRAME_METHOD]
        sub     stack, stack, #4
        ldr     r2, [Rframe, #FRAME_CONSTANTS]
        ldr     ip, [ip, #METHOD_CONSTMETHOD]
        DECACHE_STACK_USING_FRAME
        add     jpc, ip, r0

        add     r0, r2, r1, lsl #4
        DECACHE_JPC_USING_FRAME
        ldr     r3, [r0, #CP_OFFSET+12]
        and     r3, r3, #255
        ldr     r2, [stack, r3, asl #2]
        cmp     r2, #0
        beq     istub_null_ptr_exception

        ldr     tmp1, [r0, #CP_OFFSET+4]
        mov     r1, #0
        ldr     ip, [tmp1, #METHOD_FROM_INTERPRETED]
        str     r1, [thread, #THREAD_LAST_JAVA_SP]

        add     stack, stack, #4
        str     stack, [thread, #THREAD_JAVA_SP]

        ldr     r3, [ip, #0]

        mov     r0, tmp1
#ifdef SHARK
	mov	r2, thread
#else
        add     r3, r3, #FAST_ENTRY_OFFSET
#endif
        blx     r3
	LOAD_FRAME

        ldr     stack, [thread, #THREAD_JAVA_SP]
        ldr     r2, [Rframe, #FRAME_STACK_LIMIT]

        ldr     r1, [thread, #THREAD_TOP_ZERO_FRAME]
        add     r2, r2, #4
	mov	r3, #0
	str	r3, [thread, #THREAD_LAST_JAVA_SP]	
        str     r1, [thread, #THREAD_LAST_JAVA_FP]
        str     r2, [thread, #THREAD_JAVA_SP]
        str     Rframe, [thread, #THREAD_LAST_JAVA_SP] // FIXME: Don't understand this
        ldr     r3, [thread, #4]
        cmp     r3, #0
        bne     istub_exception
	mov	r0, #0
        ldmia   sp!, {ip, pc}

@ R0 = BCI
@ R1 = index
	.global	Thumb2_getfield_word_stub
	.type Thumb2_getfield_word_stub, %function
Thumb2_getfield_word_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getfield << 16
	bne	1f
2:
	ldr	r3, [stack], #4		@ POP r3
	ldr	ip, [r2, #CP_OFFSET+8]
	cmp	r3, #0
	beq	field_null_ptr_exception

	GO_IF_VOLATILE	r2, r2, 3f

	ldr	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	
	ldr	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getfield_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_getfield_sh_stub
	.type Thumb2_getfield_sh_stub, %function
Thumb2_getfield_sh_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getfield << 16
	bne	1f
2:
	ldr	r3, [stack], #4		@ POP r3
	ldr	ip, [r2, #CP_OFFSET+8]
	cmp	r3, #0
	beq	field_null_ptr_exception

	GO_IF_VOLATILE	r2, r2, 3f

	ldrsh	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldrsh	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getfield_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_getfield_h_stub
	.type Thumb2_getfield_h_stub, %function
Thumb2_getfield_h_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getfield << 16
	bne	1f
2:
	ldr	r3, [stack], #4		@ POP r3
	ldr	ip, [r2, #CP_OFFSET+8]
	cmp	r3, #0
	beq	field_null_ptr_exception

	GO_IF_VOLATILE	r2, r2, 3f

	ldrh	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldrh	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getfield_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_getfield_sb_stub
	.type Thumb2_getfield_sb_stub, %function
Thumb2_getfield_sb_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getfield << 16
	bne	1f
2:
	ldr	r3, [stack], #4		@ POP r3
	ldr	ip, [r2, #CP_OFFSET+8]
	cmp	r3, #0
	beq	field_null_ptr_exception

	GO_IF_VOLATILE	r2, r2, 3f

	ldrsb	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldrsb	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getfield_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_getfield_dw_stub
	.type Thumb2_getfield_dw_stub, %function
Thumb2_getfield_dw_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getfield << 16
	bne	1f
2:
	ldr	r3, [stack], #4		@ POP r3
	ldr	ip, [r2, #CP_OFFSET+8]
	cmp	r3, #0
	beq	field_null_ptr_exception

	GO_IF_VOLATILE	r2, r2, 3f

	ldrd	r2, r3, [r3, ip]
	stmdb	stack!, {r2, r3}	@ PUSH r2, r3
	bx	lr
3:
	ldrd	r2, r3, [r3, ip]	// FIXME: Shold be ldrexd
	FullBarrier
	stmdb	stack!, {r2, r3}	@ PUSH r2, r3
	bx	lr
1:
	mov	ip, lr
	bl	getfield_stub_unresolved
	mov	lr, ip
	b	2b
	.ltorg
	
@ R0 = BCI
@ R1 = index
putstatic_stub_unresolved:
	mov	r2, #opc_putstatic
	b	field_stub_unresolved
getstatic_stub_unresolved:
	mov	r2, #opc_getstatic
	b	field_stub_unresolved
putfield_stub_unresolved:
	mov	r2, #opc_putfield
	b	field_stub_unresolved
getfield_stub_unresolved:
	mov	r2, #opc_getfield
field_stub_unresolved:
	stmdb	sp!, {r0, r1, ip, lr}
	ldr	lr, [thread, #THREAD_TOP_ZERO_FRAME]
        ldr     ip, [lr, #FRAME_METHOD]
	sub	r3, stack, #4
	ldr	ip, [ip, #METHOD_CONSTMETHOD]
	str	r3, [lr, #FRAME_STACK]	@ DECACHE_STACK
	add	r3, ip, r0
	str	r3, [lr, #FRAME_BCP]	@ DECACHE_JPC
	ldr	ip, resolve_get_put_adcon
	mov	r1, r2
	mov	r0, thread
	blx	ip
	ldmia	sp!, {r0, r1, ip, lr}
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r3, [thread, #4]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	cmp	r3, #0
	bne	field_exception
	add	r2, r2, r1, lsl #4
	bx	lr

field_null_ptr_exception:
	stmdb	sp!, {JAZ_REGSET}
	ldr	ip, [thread, #THREAD_TOP_ZERO_FRAME]
        ldr     r1, [ip, #FRAME_METHOD]
	ldr	r3, [ip, #FRAME_LOCALS]
        ldr     ip, [r1, #METHOD_CONSTMETHOD]
        add     jpc, ip, r0
 	mov	r0, #VMSYMBOLS_NullPointerException
	bic	r0, lr, #TBIT
	mov	r2, sp

@ We already have BCI, so just call lr_to_bci to save the locals
@ The result value is ignored
	ldr	ip, lr_to_bci_adcon
	blx	ip

	add	sp, sp, #JAZ_REGSET_LEN * 4
 	ldr	ip, raise_exception_adcon
	LOAD_ISTATE
 	bx	ip
 
 field_exception:
 	ldr	ip, handle_exception_adcon
	LOAD_ISTATE
 	bx	ip

@ R0 = BCI
@ R1 = index
	.global	Thumb2_putfield_word_stub
	.type Thumb2_putfield_word_stub, %function
Thumb2_putfield_word_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putfield << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	str	r2, [r3, ip]
	bx	lr
3:	
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	StoreStoreBarrier
	str	r2, [r3, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putfield_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_putfield_h_stub
	.type Thumb2_putfield_h_stub, %function
Thumb2_putfield_h_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putfield << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	strh	r2, [r3, ip]
	bx	lr
3:
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	StoreStoreBarrier
	strh	r2, [r3, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putfield_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_putfield_b_stub
	.type Thumb2_putfield_b_stub, %function
Thumb2_putfield_b_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putfield << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	strb	r2, [r3, ip]
	bx	lr
3:
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	StoreStoreBarrier
	strb	r2, [r3, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putfield_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_putfield_a_stub
	.type Thumb2_putfield_a_stub, %function
Thumb2_putfield_a_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putfield << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	str	r2, [r3, ip]
	ldr	ip, helper_aputfield_adcon
	mov	r0, r3
	bx	ip
3:
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}	@ r2 = value, r3 = obj
	cmp	r3, #0
	beq	field_null_ptr_exception

	StoreStoreBarrier
	str	r2, [r3, ip]
	StoreLoadBarrier
	ldr	ip, helper_aputfield_adcon
	mov	r0, r3
	bx	ip
1:
	mov	ip, lr
	bl	putfield_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_putfield_dw_stub
	.type Thumb2_putfield_dw_stub, %function
Thumb2_putfield_dw_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putfield << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r1, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3, ip}	@ r2,r3 = value, ip = obj
	cmp	ip, #0
	beq	field_null_ptr_exception

	strd	r2,r3, [ip, r1]
	bx	lr
3:
	ldr	r1, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3, ip}	@ r2,r3 = value, ip = obj
	cmp	ip, #0
	beq	field_null_ptr_exception

	StoreStoreBarrier
	// FIXME: This should use strexd on an MP system
	strd	r2,r3, [ip, r1]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putfield_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_getstatic_word_stub
	.type Thumb2_getstatic_word_stub, %function
Thumb2_getstatic_word_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getstatic << 16
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldr	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldr	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getstatic_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_getstatic_h_stub
	.type Thumb2_getstatic_h_stub, %function
Thumb2_getstatic_h_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getstatic << 16
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrh	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrh	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getstatic_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_getstatic_sh_stub
	.type Thumb2_getstatic_sh_stub, %function
Thumb2_getstatic_sh_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getstatic << 16
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrsh	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrsh	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getstatic_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_getstatic_sb_stub
	.type Thumb2_getstatic_sb_stub, %function
Thumb2_getstatic_sb_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getstatic << 16
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrsb	r3, [r3, ip]
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrsb	r3, [r3, ip]
	FullBarrier
	str	r3, [stack, #-4]!	@ PUSH r3
	bx	lr
1:
	mov	ip, lr
	bl	getstatic_stub_unresolved
	mov	lr, ip
	b	2b

	.global	Thumb2_getstatic_dw_stub
	.type Thumb2_getstatic_dw_stub, %function
Thumb2_getstatic_dw_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0x00ff0000
	cmp	r3, #opc_getstatic << 16
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrd	r2, r3, [r3, ip]
	stmdb	stack!, {r2, r3}	@ PUSH r2, r3
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]

	ldrd	r2, r3, [r3, ip]
	FullBarrier
	// FIXME: This should use strexd on an MP system
	stmdb	stack!, {r2, r3}	@ PUSH r2, r3
	bx	lr
1:
	mov	ip, lr
	bl	getstatic_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_putstatic_word_stub
	.type Thumb2_putstatic_word_stub, %function
Thumb2_putstatic_word_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putstatic << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	str	r2, [r3, ip]
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	StoreStoreBarrier
	str	r2, [r3, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putstatic_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_putstatic_h_stub
	.type Thumb2_putstatic_h_stub, %function
Thumb2_putstatic_h_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putstatic << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	strh	r2, [r3, ip]
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	StoreStoreBarrier
	strh	r2, [r3, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putstatic_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_putstatic_b_stub
	.type Thumb2_putstatic_b_stub, %function
Thumb2_putstatic_b_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putstatic << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	strb	r2, [r3, ip]
	bx	lr
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	StoreStoreBarrier
	strb	r2, [r3, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putstatic_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_putstatic_dw_stub
	.type Thumb2_putstatic_dw_stub, %function
Thumb2_putstatic_dw_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putstatic << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r1, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}

	strd	r2,r3, [r1, ip]
	bx	lr
3:
	ldr	r1, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldmia	stack!, {r2, r3}

	StoreStoreBarrier
	strd	r2,r3, [r1, ip]
	StoreLoadBarrier
	bx	lr
1:
	mov	ip, lr
	bl	putstatic_stub_unresolved
	mov	lr, ip
	b	2b

@ R0 = BCI
@ R1 = index
	.global	Thumb2_putstatic_a_stub
	.type Thumb2_putstatic_a_stub, %function
Thumb2_putstatic_a_stub:
	ldr	r2, [thread, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r2, #FRAME_CONSTANTS]
	add	r2, r2, r1, lsl #4
	ldr	r3, [r2, #CP_OFFSET]
	and	r3, r3, #0xff000000
	cmp	r3, #opc_putstatic << 24
	bne	1f
2:
	GO_IF_VOLATILE	r3, r2, 3f
	
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	str	r2, [r3, ip]
	ldr	ip, helper_aputfield_adcon
	mov	r0, r3
	bx	ip
3:
	ldr	r3, [r2, #CP_OFFSET+4]
	ldr	ip, [r2, #CP_OFFSET+8]
	ldr	r2, [stack], #4		@ POP r2

	StoreStoreBarrier
	str	r2, [r3, ip]
	StoreLoadBarrier
	ldr	ip, helper_aputfield_adcon
	mov	r0, r3
	bx	ip
1:
	mov	ip, lr
	bl	putstatic_stub_unresolved
	mov	lr, ip
	b	2b

#endif // T2JIT

	.global	Thumb2_stubs_end
	.type Thumb2_stubs_end, %function
Thumb2_stubs_end:

	ALIGN_CODE
jdiv_1:
	bx	lr
jdiv_2:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
	bx	lr
jdiv_24:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_12:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_6:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_3:
	ldr	r1, dc_3
        smull	r3, r2, r0, r1
        sub	r0, r2, r0, asr #31
	bx	lr
jdiv_4:
	mov	r1, r0, asr #31
	add	r0, r0, r1, lsr #30
	mov	r0, r0, asr #2
	bx	lr
jdiv_20:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_10:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_5:
	ldr	r1, dc_5
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #1
	bx	lr
jdiv_28:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_14:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_7:
	ldr	r1, dc_7
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r0, r1, r3, asr #2
	bx	lr
jdiv_8:
	mov	r1, r0, asr #31
	add	r0, r0, r1, lsr #29
	mov	r0, r0, asr #3
	bx	lr
jdiv_18:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_9:
	ldr	r1, dc_9
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #1
	bx	lr
jdiv_22:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_11:
	ldr	r1, dc_11
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #1
	bx	lr
jdiv_26:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_13:
	ldr	r1, dc_13
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #2
	bx	lr
jdiv_30:
        add     r0, r0, r0, lsr #31
        mov     r0, r0, asr #1
jdiv_15:
	ldr	r1, dc_15
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r0, r1, r3, asr #3
	bx	lr
jdiv_16:
	mov	r1, r0, asr #31
	add	r0, r0, r1, lsr #28
	mov	r0, r0, asr #4
	bx	lr
jdiv_17:
	ldr	r1, dc_17
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #3
	bx	lr
jdiv_19:
	ldr	r1, dc_19
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #3
	bx	lr
jdiv_21:
	ldr	r1, dc_21
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #2
	bx	lr
jdiv_23:
	ldr	r1, dc_23
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r0, r1, r3, asr #4
	bx	lr
jdiv_25:
	ldr	r1, dc_25
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #3
	bx	lr
jdiv_27:
	ldr	r1, dc_27
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r0, r3, r2, asr #3
	bx	lr
jdiv_29:
	ldr	r1, dc_29
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r0, r1, r3, asr #4
	bx	lr
jdiv_31:
	ldr	r1, dc_31
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r0, r1, r3, asr #4
	bx	lr
jdiv_32:
	mov	r1, r0, asr #31
	add	r0, r0, r1, lsr #27
	mov	r0, r0, asr #5
	bx	lr
jrem_1:
	mov	r0, #0
	bx	lr
jrem_2:
	add	r3, r0, r0, lsr #31
        mov	r1, r3, asr #1
	sub	r0, r0, r1, lsl #1
	bx	lr
jrem_3:
	ldr	r1, dc_3
        smull	r3, r2, r0, r1
        sub	r1, r2, r0, asr #31
	add	r3, r1, r1, lsl #1
	sub	r0, r0, r3
	bx	lr
jrem_4:
	movs	r3, r0
        addmi	r3, r3, #3
        mov	r1, r3, asr #2
	sub	r0, r0, r1, lsl #2
	bx	lr
jrem_5:
	ldr	r1, dc_5
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #1
	add	r3, r1, r1, lsl #2
	sub	r0, r0, r3
	bx	lr
jrem_6:
	ldr	r1, dc_6
        smull	r3, r2, r0, r1
        sub	r1, r2, r0, asr #31
	add	r3, r1, r1, lsl #1
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_7:
	ldr	r1, dc_7
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #2
	rsb	r3, r1, r1, lsl #3
	sub	r0, r0, r3
	bx	lr
jrem_8:
	movs	r3, r0
        addmi	r3, r3, #7
        mov	r1, r3, asr #3
	sub	r0, r0, r1, lsl #3
	bx	lr
jrem_9:
	ldr	r1, dc_9
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #1
	add	r3, r1, r1, lsl #3
	sub	r0, r0, r3
	bx	lr
jrem_10:
	ldr	r1, dc_10
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #2
	add	r3, r1, r1, lsl #2
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_11:
	ldr	r1, dc_11
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #1
	add	r3, r1, r1, lsl #2
	add	r3, r1, r3, lsl #1
	sub	r0, r0, r3
	bx	lr
jrem_12:
	ldr	r1, dc_12
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #1
	add	r3, r1, r1, lsl #1
	sub	r0, r0, r3, lsl #2
	bx	lr
jrem_13:
	ldr	r1, dc_13
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #2
	add	r3, r1, r1, lsl #1
	add	r3, r1, r3, lsl #2
	sub	r0, r0, r3
	bx	lr
jrem_14:
	ldr	r1, dc_14
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #3
	rsb	r3, r1, r1, lsl #3
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_15:
	ldr	r1, dc_15
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #3
	rsb	r3, r1, r1, lsl #4
	sub	r0, r0, r3
	bx	lr
jrem_16:
	movs	r3, r0
        addmi	r3, r3, #15
        mov	r1, r3, asr #4
	sub	r0, r0, r1, lsl #4
	bx	lr
jrem_17:
	ldr	r1, dc_17
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #3
	add	r3, r1, r1, lsl #4
	sub	r0, r0, r3
	bx	lr
jrem_18:
	ldr	r1, dc_18
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #2
	add	r3, r1, r1, lsl #3
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_19:
	ldr	r1, dc_19
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #3
	add	r3, r1, r1, lsl #3
	add	r3, r1, r3, lsl #1
	sub	r0, r0, r3
	bx	lr
jrem_20:
	ldr	r1, dc_20
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #3
	add	r3, r1, r1, lsl #2
	sub	r0, r0, r3, lsl #2
	bx	lr
jrem_21:
	ldr	r1, dc_21
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #2
	add	r3, r1, r1, lsl #1
	rsb	r3, r3, r3, lsl #3
	sub	r0, r0, r3
	bx	lr
jrem_22:
	ldr	r1, dc_22
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #2
	add	r3, r1, r1, lsl #2
	add	r3, r1, r3, lsl #1
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_23:
	ldr	r1, dc_23
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #4
	add	r3, r1, r1, lsl #1
	rsb	r3, r1, r3, lsl #3
	sub	r0, r0, r3
	bx	lr
jrem_24:
	ldr	r1, dc_24
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #2
	add	r3, r1, r1, lsl #1
	sub	r0, r0, r3, lsl #3
	bx	lr
jrem_25:
	ldr	r1, dc_25
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #3
	add	r3, r1, r1, lsl #2
	add	r3, r3, r3, lsl #2
	sub	r0, r0, r3
	bx	lr
jrem_26:
	ldr	r1, dc_26
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #3
	add	r3, r1, r1, lsl #1
	add	r3, r1, r3, lsl #2
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_27:
	ldr	r1, dc_27
        smull	r3, r2, r0, r1
        mov	r3, r0, asr #31
        rsb	r1, r3, r2, asr #3
	add	r3, r1, r1, lsl #1
	add	r3, r3, r3, lsl #3
	sub	r0, r0, r3
	bx	lr
jrem_28:
	ldr	r1, dc_28
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #4
	rsb	r3, r1, r1, lsl #3
	sub	r0, r0, r3, lsl #2
	bx	lr
jrem_29:
	ldr	r1, dc_29
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #4
	rsb	r3, r1, r1, lsl #3
	add	r3, r1, r3, lsl #2
	sub	r0, r0, r3
	bx	lr
jrem_30:
	ldr	r1, dc_30
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #4
	rsb	r3, r1, r1, lsl #4
	sub	r0, r0, r3, lsl #1
	bx	lr
jrem_31:
	ldr	r1, dc_31
        smull	r3, r2, r0, r1
        mov	r1, r0, asr #31
        add	r3, r0, r2
        rsb	r1, r1, r3, asr #4
	rsb	r3, r1, r1, lsl #5
	sub	r0, r0, r3
	bx	lr
jrem_32:
	movs	r3, r0
        addmi	r3, r3, #31
        mov	r1, r3, asr #5
	sub	r0, r0, r1, lsl #5
	bx	lr
	ALIGN_DATA
dc_7:
dc_14:
	.word     0x92492493
dc_15:
dc_30:
	.word     0x88888889
dc_23:
	.word     0xb21642c9
dc_28:
	.word     0x92492493
dc_29:
	.word     0x8d3dcb09
dc_31:
	.word     0x84210843
dc_6:
dc_12:
dc_24:
	.word     0x2aaaaaab
dc_19:
	.word     0x6bca1af3
dc_5:
dc_10:
dc_20:
	.word     0x66666667
dc_21:
	.word     0x30c30c31
dc_11:
dc_22:
	.word     0x2e8ba2e9
dc_26:
dc_13:
	.word     0x4ec4ec4f
dc_25:
	.word     0x51eb851f
dc_27:
	.word     0x4bda12f7
dc_3:
	.word     0x55555556
dc_17:
	.word     0x78787879
dc_9:
dc_18:
	.word     0x38e38e39

	.global	Thumb2_DivZero_Handler
	.type Thumb2_DivZero_Handler, %function
Thumb2_DivZero_Handler:
#ifdef T2JIT

	adrl	r0, idiv_clz_ret
	cmp	r0, lr
	addne	r0, r0, #irem_clz_ret - idiv_clz_ret
	cmpne	r0, lr
	beq	divide_by_zero_exception
	stmdb	sp!, {JAZ_REGSET}
	LOAD_FRAME
	bic	r0, lr, #TBIT
	ldr	r1, [Rframe, #FRAME_METHOD]
        ldr     jpc, [r1, #METHOD_CONSTMETHOD]
	add	jpc, jpc, #CONSTMETHOD_CODEOFFSET
	mov	r2, sp
	ldr	r3, [Rframe, #FRAME_LOCALS]
	bl	Thumb2_lr_to_bci
	add	sp, sp, #JAZ_REGSET_LEN * 4
	cmp	r0, #-1
	moveq	jpc, #0
	addne	jpc, jpc, r0
	bl	load_dispatch
	LOAD_ISTATE
#endif // T2JIT
	b	divide_by_zero_exception

#ifdef T2JIT

	.global	Thumb2_Handle_Exception
	.type Thumb2_Handle_Exception, %function
	.global	Thumb2_Handle_Exception_NoRegs
	.type Thumb2_Handle_Exception_NoRegs, %function
	.global Thumb2_ArrayBounds_Handler
	.type Thumb2_ArrayBounds_Handler, %function
	.global Thumb2_NullPtr_Handler
	.type Thumb2_NullPtr_Handler, %function
	.global Thumb2_Stack_Overflow
	.type Thumb2_Stack_Overflow, %function
Thumb2_ArrayBounds_Handler:
	stmdb	sp!, {JAZ_REGSET}
	LOAD_FRAME
	bic	r0, lr, #TBIT
	ldr	r1, [Rframe, #FRAME_METHOD]
        ldr     jpc, [r1, #METHOD_CONSTMETHOD]
	add	jpc, jpc, #CONSTMETHOD_CODEOFFSET
	mov	r2, sp
	ldr	r3, [Rframe, #FRAME_LOCALS]
	bl	Thumb2_lr_to_bci
	add	sp, sp, #JAZ_REGSET_LEN * 4
	cmp	r0, #-1
	moveq	jpc, #0
	addne	jpc, jpc, r0
	bl	load_dispatch
	mov	r0, #VMSYMBOLS_ArrayIndexOutOfBounds
	LOAD_ISTATE
	b	raise_exception
Thumb2_Handle_Exception:
	stmdb	sp!, {JAZ_REGSET}
	LOAD_FRAME
	bic	r0, lr, #TBIT
	ldr	r1, [Rframe, #FRAME_METHOD]
        ldr     jpc, [r1, #METHOD_CONSTMETHOD]
	add	jpc, jpc, #CONSTMETHOD_CODEOFFSET
	mov	r2, sp
	ldr	r3, [Rframe, #FRAME_LOCALS]
	bl	Thumb2_lr_to_bci
	add	sp, sp, #JAZ_REGSET_LEN * 4
	cmp	r0, #-1
	moveq	jpc, #0
	addne	jpc, jpc, r0
	bl	load_dispatch
	LOAD_ISTATE
	b	handle_exception
Thumb2_Handle_Exception_NoRegs:
	LOAD_FRAME
	ldr	r0, [Rframe, #FRAME_STACK_LIMIT]
	add	r0, r0, #4
	str	r0, [thread, #THREAD_JAVA_SP]
	bic	r0, lr, #TBIT
	ldr	r1, [Rframe, #FRAME_METHOD]
        ldr     jpc, [r1, #METHOD_CONSTMETHOD]
	add	jpc, jpc, #CONSTMETHOD_CODEOFFSET
	mov	r2, #0
	bl	Thumb2_lr_to_bci
	cmp	r0, #-1
	moveq	jpc, #0
	addne	jpc, jpc, r0
	bl	load_dispatch
	LOAD_ISTATE
	b	handle_exception
Thumb2_NullPtr_Handler:
	stmdb	sp!, {JAZ_REGSET}
	LOAD_FRAME
	bic	r0, lr, #TBIT
	ldr	r1, [Rframe, #FRAME_METHOD]
        ldr     jpc, [r1, #METHOD_CONSTMETHOD]
	add	jpc, jpc, #CONSTMETHOD_CODEOFFSET
	mov	r2, sp
	ldr	r3, [Rframe, #FRAME_LOCALS]
	bl	Thumb2_lr_to_bci
	add	sp, sp, #JAZ_REGSET_LEN * 4
	cmp	r0, #-1
	moveq	jpc, #0
	addne	jpc, jpc, r0
	bl	load_dispatch
	LOAD_ISTATE
	b	null_ptr_exception

Thumb2_Stack_Overflow:
	mov	r0, thread
	mov	r2, #0
	str	r2, [r0, #THREAD_LAST_JAVA_SP]
	ldr	ip, [r0, #THREAD_TOP_ZERO_FRAME]
	ldr	r2, [r0, #THREAD_JAVA_SP]
	str	ip, [r0, #THREAD_LAST_JAVA_FP]
	str	r2, [r0, #THREAD_LAST_JAVA_SP]
	bl	_ZN18InterpreterRuntime24throw_StackOverflowErrorEP10JavaThread
	mov	r0, #0
	ldmfd	arm_sp!, {fast_regset, pc}

	.global	Thumb2_Exit_To_Interpreter
	.type Thumb2_Exit_To_Interpreter, %function
Thumb2_Exit_To_Interpreter:
	LOAD_ISTATE
	bl	load_dispatch
	sub	stack, stack, #4
	CACHE_CP
	CACHE_LOCALS
	DISPATCH	0

	.global	Thumb2_monitorenter
Thumb2_monitorenter:
	stmdb	sp!, {ip, lr}
	sub	stack, stack, #4
	mov	r0, r8
	POP	r1
	DECACHE_JPC
	DECACHE_STACK
	bl	Helper_monitorenter
	CACHE_STACK		@ monitorenter may expand stack!!!
	ldmia	sp!, {ip, lr}
	cmp	r0, #0
	bne	handle_exception
	add	stack, stack, #4
	bx	lr

	.global	Thumb2_Clear_Cache
	.type Thumb2_Clear_Cache, %function
Thumb2_Clear_Cache:
	stmdb	sp!, {r7}
	mov	r2, #0
	mov	r7, #2
	orr	r7, r7, #0xf0000
	svc	0
	ldmia	sp!, {r7}
	bx	lr

#endif // T2JIT

	.section	.init_array,"aw",%init_array
	.word	bci_init(target1)

	.data
	.global	CPUInfo
	ALIGN_DATA
        .word   0, 0, 0, 0, 0, 0, 0, 0
        .word   0, 0, 0, 0, 0
DispatchBreakPoint:					.word	0
CPUInfo:						.word	0
CodeTrace_Idx:						.word	0
UseOnStackReplacement_Address:                          .word   0
BackgroundCompilation_Address:                          .word   0
CompileThreshold_Address:                               .word   0
InterpreterInvocationLimit_Address:			.word	0
UseCompiler_Address:					.word	0
can_post_interpreter_events:				.word	0 	
PrintCommandLineFlags_Address:				.word	0
oopDesc_Address:					.word	0
ThreadLocalStorage_thread_index:			.word	0
AbstractInterpreter_notice_safepoints:			.word	0
Bytecodes_name_Address:					.word	0
Universe_collectedHeap_Address:				.word	0
always_do_update_barrier_Address:			.word	0
VmSymbols_symbols_Address:				.word	0
SafePointSynchronize_state_Address:			.word	0
InterpreterRuntime_slow_signature_handler_Address:	.word	0
XXX:
opclabels_data:
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
#endif

#endif // __arm__