void InterpreterStubs::generate_interpreter_timer_tick() { comment_section("Interpreter call timer_tick"); entry("interpreter_timer_tick"); interpreter_call_vm(Constant("timer_tick"), T_VOID); dispatch_next(); entry_end(); // interpreter_timer_tick #if ENABLE_PAGE_PROTECTION stop_code_segment(); start_data_segment(); if (GenerateGNUCode || GenerateInlineAsm) { align(PROTECTED_PAGE_SIZE); define_array_begin("unsigned char", "_protected_page"); for (int i = 0; i < PROTECTED_PAGE_SIZE; i++) { define_byte_element(Constant(0)); } define_array_end(); } else { // MASM doesn't allow 4096-byte alignment, // so surround the protected area with 4K padding. // This will certainly add 8K of static footprint, // but who cares about the size of win32_i386 binary! define_byte(Constant(0), PROTECTED_PAGE_SIZE); define_long(Constant(0), PROTECTED_PAGE_SIZE / BytesPerWord, "_protected_page"); define_byte(Constant(0), PROTECTED_PAGE_SIZE); } stop_data_segment(); start_code_segment(); #endif }
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 GPTableGenerator::generate_protected_page() { if (!GenerateGPTableOnly && ENABLE_PAGE_PROTECTION) { GUARANTEE(!ENABLE_THUMB_GP_TABLE, "Not supported"); align(PROTECTED_PAGE_SIZE); bind("_protected_page"); // Fill the page with pointers to gp_base_label to allow ldr gp, [gp, -##] Label gp_base_label("gp_base_label"); for (int i = 0; i < PROTECTED_PAGE_SIZE; i += BytesPerWord) { define_long(gp_base_label); } } }
void SourceAssembler::define_call_info() { #if ENABLE_EMBEDDED_CALLINFO CallInfo ci = CallInfo::interpreter(); define_long(ci.raw()); #endif }
// Bytecode dispatch table for ARM Interpreter/Thumb Compiler void GPTableGenerator::generate_thumb_bytecode_dispatch_table() { int i; define_long(0); // 256 or 263 define_long(0); // 255 or 262 if (ENABLE_DISPATCH_TABLE_PADDING) { SHOULD_NOT_REACH_HERE(); // This is a bit bogus -- padded dispatch tables must be ascending, // so it won't work with Thumb compiler! define_long("bytecode_dispatch_0x105"); define_long("bytecode_dispatch_0x104"); define_long("bytecode_dispatch_0x103"); define_long("bytecode_dispatch_0x102"); define_long("bytecode_dispatch_0x101"); define_long("bytecode_dispatch_0x100"); define_long("bytecode_dispatch_0x0FF"); define_long("bytecode_dispatch_0x0FE"); } for (i = 253; i > 0; i--) { Bytecodes::Code bc = (Bytecodes::Code) i; if (Bytecodes::is_defined(bc) && !GenerateGPTableOnly) { char buffer[256]; if (GenerateGNUCode) { jvm_sprintf(buffer, "bc_impl_%-30s /* 0x%x */", Bytecodes::name(bc), (int)bc); } else { jvm_sprintf(buffer, "bc_impl_%-30s ; 0x%x", Bytecodes::name(bc), \ (int)bc); } define_long(buffer); } else { define_long(0); } } bind("gp_base_label"); set_current_commented_offset(0); set_use_offset_comments(true); if (!GenerateGPTableOnly) { // Define nop at offset 0 from base_label // the rest would be at -ve offset char buffer[256]; if (GenerateGNUCode) { jvm_sprintf(buffer, "bc_impl_%-30s /* 0x%x */", Bytecodes::name((Bytecodes::Code)0), 0); } else { jvm_sprintf(buffer, "bc_impl_%-30s ; 0x%x", Bytecodes::name((Bytecodes::Code)0), 0); } define_long(buffer); } else { define_long(0); } }
// Bytecode dispatch table for ARM Interpreter/Compiler void GPTableGenerator::generate_arm_bytecode_dispatch_table() { int i; bind("gp_base_label"); set_current_commented_offset(0); set_use_offset_comments(true); for (i = 0; i <= 253; i++) { Bytecodes::Code bc = (Bytecodes::Code) i; if (Bytecodes::is_defined(bc) && !GenerateGPTableOnly) { char buffer[256]; if (GenerateGNUCode) { jvm_sprintf(buffer, "bc_impl_%-30s /* 0x%x */", Bytecodes::name(bc), (int)bc); } else { jvm_sprintf(buffer, "bc_impl_%-30s ; 0x%x", Bytecodes::name(bc), (int)bc); } define_long(buffer); } else { eol_comment("undefined bytecode 0x%x", bc); define_long(0); } } if (ENABLE_DISPATCH_TABLE_PADDING) { define_long("bytecode_dispatch_0x0FE"); define_long("bytecode_dispatch_0x0FF"); define_long("bytecode_dispatch_0x100"); define_long("bytecode_dispatch_0x101"); define_long("bytecode_dispatch_0x102"); define_long("bytecode_dispatch_0x103"); define_long("bytecode_dispatch_0x104"); define_long("bytecode_dispatch_0x105"); } define_long(0); // 255 or 262 define_long(0); // 256 or 263 }
void GPTableGenerator::generate_constants_table() { int i; bind("gp_constants"); static const GPTemplate gp_templates[] = { GP_SYMBOLS_DO(DEFINE_GP_POINTER, DEFINE_GP_VALUE) {NULL, 0, 0, 0} }; for (const GPTemplate* tmpl = gp_templates; tmpl->name; tmpl++) { if (tmpl->is_pointer) { char buff[120]; jvm_sprintf(buff, "gp_%s_ptr", tmpl->name); bind(buff); Label L(tmpl->name); if (!tmpl->is_asm) { import(L); } define_long(L); } else { if (jvm_strcmp(tmpl->name, "current_thread") == 0) { bind("jvm_fast_globals"); } char buff[120]; jvm_sprintf(buff, "_%s", tmpl->name); bind(buff); if (jvm_strcmp(tmpl->name, "bit_selector") == 0) { // IMPL_NOTE: create a common framework to define initial values define_long(0x80808080); } else { define_zeros(tmpl->size); } } } if (!GenerateGPTableOnly) { // Some constants to check we've linked with the right ROM Label L1(XSTR(_ROM_LINKCHECK_HLE)); import(L1); define_long(L1); Label L2(XSTR(_ROM_LINKCHECK_MFFD)); import(L2); define_long(L2); Label L3(XSTR(_ROM_LINKCHECK_MFFL)); import(L3); define_long(L3); } if (ENABLE_THUMB_GP_TABLE && GenerateGPTableOnly) { // These symbols are necessary to link romgen. // We define a long for each entry, since they // should be bound to different addresses. bind("jvm_ladd"); define_long(0); bind("jvm_lsub"); define_long(0); bind("jvm_land"); define_long(0); bind("jvm_lor"); define_long(0); bind("jvm_lxor"); define_long(0); bind("jvm_lcmp"); define_long(0); bind("jvm_lmin"); define_long(0); bind("jvm_lmax"); define_long(0); bind("jvm_lmul"); define_long(0); bind("jvm_lshl"); define_long(0); bind("jvm_lshr"); define_long(0); bind("jvm_lushr"); define_long(0); } bind("gp_constants_end"); }