void SourceAssembler::bind_rom_linkable(const char *name, bool generate_fixed) { char fixed_name[256]; jvm_sprintf(fixed_name, "fixed_%s", name); Label L(name); Label L_fixed(fixed_name); if (generate_fixed) { bind_global(L_fixed); nop(); } bind_global(L); }
void InterpreterStubs::generate_interpreter_throw_exceptions() { Segment seg(this, code_segment, "Interpreter exception throwers"); bind_global("interpreter_throw_ArrayIndexOutOfBoundsException"); interpreter_call_vm("array_index_out_of_bounds_exception", T_ILLEGAL); bind_global("interpreter_throw_NullPointerException_tos_cached"); push(tos); bind_global("interpreter_throw_NullPointerException"); interpreter_call_vm("null_pointer_exception", T_ILLEGAL); bind_global("interpreter_throw_IncompatibleClassChangeError"); interpreter_call_vm("incompatible_class_change_error", T_ILLEGAL); }
void InterpreterStubs::generate_current_thread_to_primordial() { Segment seg(this, code_segment, "Current thread to primordial"); bind_global("current_thread_to_primordial"); comment("Set up global pointer, as we can be called from C code"); ldr_gp_base(gp); bind_global("current_thread_to_primordial_fast"); // We're never going to return to this thread, so it doesn't matter if // it doesn't look like a stopped Java thread anymore. get_primordial_sp(sp); comment("restore permanent registers (including return address)"); ldr(lr, imm_index(sp, BytesPerWord, post_indexed)); ldmfd(sp, range(r3, r11), writeback); jmpx(lr); if (GenerateDebugAssembly) { bind_local("interpreter_bkpt"); get_gp_bytecode_counter(tmp3); add(tmp3, tmp3, imm(1)); set_gp_bytecode_counter(tmp3); mov(pc, reg(tmp0)); } #if ENABLE_XSCALE_WMMX_TIMER_TICK && !ENABLE_TIMER_THREAD // set timer_tick from WMMX wCASF register comment("wmmx_set_timer_tick to set timer_tick from WMMX register"); bind_global("wmmx_set_timer_tick"); // tmrc(r2, wCASF); define_long(0xEE132110); mvn(r3, imm(4) ); andr(r2, r2, reg(r3) ); // tmcr(wCASF, r2); define_long(0xEE032110); jmpx(lr); // clear timer_tick from WMMX wCASF register comment("wmmx_set_timer_tick to clear timer_tick from WMMX register"); bind_global("wmmx_clear_timer_tick"); define_long(0xEE100060); // wcmpgtub(wR0, wR0, wR0); jmpx(lr); #endif // ENABLE_XSCALE_WMMX_TIMER_TICK && !ENABLE_TIMER_THREAD }
void InterpreterStubs::generate_primordial_to_current_thread() { Segment seg(this, code_segment, "Primordial to current thread"); bind_global("primordial_to_current_thread"); comment("save permanent registers (including return address)"); stmfd(sp, range(r3, r11), writeback); str(lr, imm_index(sp, -BytesPerWord, pre_indexed)); comment("Set up global pointer"); ldr_gp_base(gp); comment("Get current thread"); get_thread(r1); comment("Save primordial stack pointer"); set_primordial_sp(sp); comment("Get new stack pointer"); ldr(jsp, imm_index(r1, Thread::stack_pointer_offset())); comment("Go to code"); ldr(lr, imm_index(jsp, -JavaStackDirection * BytesPerWord)); ldr(fp, imm_index(jsp, -JavaStackDirection * 2 * BytesPerWord, post_indexed)); jmpx(lr); bind_global("start_lightweight_thread_asm"); Label testing_compiler; const int SignedBytesPerWord = JavaStackDirection * BytesPerWord; comment("Set up global pointer"); ldr_gp_base(gp); // jsp => Thread::lightweight_thread_exit // jsp +- 4 => Thread::lightweight_thread_uncaught_exception // jsp +- 8 => Thread::finish // jsp +- 12 => force_terminated // jsp +- 16 => TestCompiler comment("Invoke pending entries unless the thread is being terminated"); get_thread(r0); comment("r1 = THREAD->status();"); ldr(r1, imm_index(r0, Thread::status_offset())); mov(r2, zero); comment("if ((r1 & THREAD_TERMINATING) != 0) {"); tst(r1, imm(THREAD_TERMINATING)); comment(" THREAD->pending_entries = NULL;"); str(r2, imm_index(r0, Thread::pending_entries_offset()), ne); comment("} else {"); comment(" invoke_pending_entries(THREAD)"); bl("invoke_pending_entries", eq); comment("}"); comment("if (!TestCompiler) {"); ldr(r0, imm_index(jsp, -4 * SignedBytesPerWord)); get_current_pending_exception(r1); cmp(r0, zero); b(testing_compiler, ne); comment(" if (Thread::current_has_pending_exception()) {"); comment(" call_on_primordial_stack(lightweight_thread_uncaught_exception);"); comment(" }"); cmp(r1, zero); ldr(r0, imm_index(jsp, -1 * SignedBytesPerWord), ne); bl("call_on_primordial_stack", ne); comment(" call_on_primordial_stack(finish);"); ldr(r0, imm_index(jsp, -2 * SignedBytesPerWord)); bl("call_on_primordial_stack"); comment(" invoke_pending_entries(THREAD);"); get_thread(r0); bl("invoke_pending_entries"); comment(" force_terminated()"); ldr(r0, imm_index(jsp, -3 * SignedBytesPerWord)); bl("call_on_primordial_stack"); comment("}"); #if ENABLE_ISOLATES comment("Terminate the task if no other threads on it"); ldr_label(r0, "thread_task_cleanup"); bl("call_on_primordial_stack"); comment(" invoke_pending_entries(THREAD);"); get_thread(r0); bl("invoke_pending_entries"); #endif bind_global(testing_compiler); comment("call_on_primordial_stack(lightweight_thread_exit);"); ldr(r0, imm_index(jsp)); bl("call_on_primordial_stack"); comment("GUARANTEE(Scheduler::_next_runnable_thread == NULL"); ldr_label(r0, "_next_runnable_thread"); ldr(r0, imm_index(r0)); cmp(r0, zero); breakpoint(ne); comment("current_thread_to_primordial();"); bl("current_thread_to_primordial_fast"); breakpoint(); }