--- old/src/cpu/s390/vm/macroAssembler_s390.cpp 2017-05-23 12:08:46.514411000 +0200 +++ new/src/cpu/s390/vm/macroAssembler_s390.cpp 2017-05-23 12:08:46.369371000 +0200 @@ -2022,18 +2022,54 @@ z_stg(fp, _z_abi(callers_sp), Z_SP); } -// Resize_frame with SP(new) = [addr]. -void MacroAssembler::resize_frame_absolute(Register addr, Register fp, bool load_fp) { - assert_different_registers(addr, fp, Z_SP); - if (load_fp) { z_lg(fp, _z_abi(callers_sp), Z_SP); } - - if (addr != Z_R0) { - // Minimize stalls by not using Z_SP immediately after update. - z_stg(fp, _z_abi(callers_sp), addr); - z_lgr(Z_SP, addr); +// Resize_frame with SP(new) = [newSP] + offset. +// This emitter is useful if we already have calculated a pointer +// into the to-be-allocated stack space, e.g. with special alignment properties, +// but need some additional space, e.g. for spilling. +// newSP is the pre-calculated pointer. It must not be modified. +// fp holds, or is filled with, the frame pointer. +// offset is the additional increment which is added to addr to form the new SP. +// Note: specify a negative value to reserve more space! +// load_fp == true only indicates that fp is not pre-filled with the frame pointer. +// It does not guarantee that fp contains the frame pointer at the end. +void MacroAssembler::resize_frame_abs_with_offset(Register newSP, Register fp, int offset, bool load_fp) { + assert_different_registers(newSP, fp, Z_SP); + + if (load_fp) { + z_lg(fp, _z_abi(callers_sp), Z_SP); + } + + if (newSP == Z_R0) { + add2reg(Z_SP, offset, newSP); + z_stg(fp, _z_abi(callers_sp), Z_SP); } else { - z_lgr(Z_SP, addr); + z_stg(fp, _z_abi(callers_sp)+offset, newSP); + add2reg(Z_SP, offset, newSP); + } +} + +// Resize_frame with SP(new) = [newSP]. +// load_fp == true only indicates that fp is not pre-filled with the frame pointer. +// It does not guarantee that fp contains the frame pointer at the end. +void MacroAssembler::resize_frame_absolute(Register newSP, Register fp, bool load_fp) { + assert_different_registers(newSP, fp, Z_SP); + + if (load_fp) { + if (newSP == Z_R0) { + z_lg(fp, _z_abi(callers_sp), Z_SP); // need to use load/store. + } else { + DEBUG_ONLY(z_lghi(fp, -1);) // safety net + z_mvc(_z_abi(callers_sp), sizeof(void*)-1, newSP, _z_abi(callers_sp), Z_SP); + } + } + + z_lgr(Z_SP, newSP); + if (newSP == Z_R0) { z_stg(fp, _z_abi(callers_sp), Z_SP); + } else { + if (!load_fp) { + z_stg(fp, _z_abi(callers_sp), newSP); + } } } --- old/src/cpu/s390/vm/macroAssembler_s390.hpp 2017-05-23 12:08:47.090436000 +0200 +++ new/src/cpu/s390/vm/macroAssembler_s390.hpp 2017-05-23 12:08:46.979411000 +0200 @@ -442,7 +442,8 @@ // Resize current frame either relatively wrt to current SP or absolute. void resize_frame_sub(Register offset, Register fp, bool load_fp=true); - void resize_frame_absolute(Register addr, Register fp, bool load_fp=true); + void resize_frame_abs_with_offset(Register newSP, Register fp, int offset, bool load_fp); + void resize_frame_absolute(Register newSP, Register fp, bool load_fp); void resize_frame(RegisterOrConstant offset, Register fp, bool load_fp=true); // Push a frame of size bytes, if copy_sp is false, old_sp must already