- MonoJitInfo *codeJi,
- *addrJi;
-
- addr = mono_compile_method(method);
- g_assert(addr);
-
- if (code) {
-
- codeJi = mono_jit_info_table_find (mono_domain_get(), code);
- addrJi = mono_jit_info_table_find (mono_domain_get(), addr);
- if (mono_method_same_domain (codeJi, addrJi)) {
-
- opcode = *((unsigned short *) (code - 6));
- if (opcode == 0xc0e5) {
- /* This is the 'brasl' instruction */
- code -= 4;
- displace = ((gint64) addr - (gint64) (code - 2)) / 2;
- if (mono_method_same_domain (codeJi, addrJi)) {
- s390_patch_rel (code, displace);
- mono_arch_flush_icache (code, 4);
- }
- } else {
- /*-----------------------------------*/
- /* This is a bras r14,Rz instruction */
- /* If it's preceded by a LG Rx,d(Ry) */
- /* If Rz == 1 then we check if unbox-*/
- /* is required. We patch the address */
- /* by determining the location desc- */
- /* cribed by *Ry+d. */
- /*-----------------------------------*/
- code -= 6;
-
- /*-----------------------------------*/
- /* If call is preceded by LGR then */
- /* there's nothing to patch */
- /*-----------------------------------*/
- if ((code[0] == 0xb9) &&
- (code[1] == 0x04))
- return addr;
-
- /*-----------------------------------*/
- /* We back up until we're pointing at*/
- /* the base/displacement portion of */
- /* the LG instruction */
- /*-----------------------------------*/
- lkReg = code[5] & 0x0f;
-
- /*-----------------------------------*/
- /* The LG instruction has format: */
- /* E3x0ylllhh04 - where: */
- /* x = Rx; y = Ry; */
- /* lll = low 12 bits of displacement */
- /* hh = high 8 bits of displacement */
- /*-----------------------------------*/
- reg = code[0] >> 4;
- displace = (code[2] << 12) +
- ((code[0] & 0x0f) << 8) +
- code[1];
-
- if (reg > 5)
- base = *((guchar **) (sp + S390_REG_SAVE_OFFSET +
- sizeof(long)*(reg-6)));
- else
- base = *((guchar **) ((sp - CREATE_STACK_SIZE) +
- CREATE_GR_OFFSET +
- sizeof(long)*(reg-2)));
-
- /* Calls that need unboxing use R1 */
- if (lkReg == 1) {
- if ((method->klass->valuetype) &&
- (!mono_aot_is_got_entry(code, base)))
- addr = get_unbox_trampoline(method, addr);
-
- code = base + displace;
- if (mono_domain_owns_vtable_slot(mono_domain_get(),
- code))
- s390_patch_addr(code, addr);
- } else {
- code = base + displace;
- s390_patch_addr(code, addr);
- }
- }
- }
+
+ opcode = *((unsigned short *) (orig_code - 6));
+ if (opcode == 0xc0e5) {
+ /* This is the 'brasl' instruction */
+ orig_code -= 4;
+ displace = ((gssize) addr - (gssize) (orig_code - 2)) / 2;
+ s390_patch_rel (orig_code, displace);
+ mono_arch_flush_icache (orig_code, 4);
+ } else {
+ /* This should be a 'lg %r14,4(%r13)' then a 'basr r14, r14' instruction */
+ g_assert (orig_code [-8] == 0xe3);
+ g_assert (orig_code [-7] == 0xe0);
+ g_assert (orig_code [-6] == 0xd0);
+ g_assert (orig_code [-5] == 0x04);
+ g_assert (orig_code [-4] == 0x00);
+ g_assert (orig_code [-3] == 0x04);
+ opcode = *((unsigned short*) (orig_code - 2));
+ g_assert (opcode == 0x0dee);
+
+ /* The call address is stored in the 8 bytes preceeding the basr instruction */
+ s390_patch_addr(orig_code - 16, (gssize)addr);
+ mono_arch_flush_icache (orig_code - 16, 8);