blob: 0038ae58beff020c6717532b7152fac57aade601 [file] [log] [blame]
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* 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.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
#include "memory/resourceArea.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/macros.hpp"
// Convention: Use Z_R0 and Z_R1 instead of Z_scratch_* in all
// assembler_s390.* files.
// Convert the raw encoding form into the form expected by the
// constructor for Address. This is called by adlc generated code.
Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) {
assert(scale == 0, "Scale should not be used on z/Architecture. The call to make_raw is "
"generated by adlc and this must mirror all features of Operands from machnode.hpp.");
assert(disp_reloc == relocInfo::none, "not implemented on z/Architecture.");
Address madr(as_Register(base), as_Register(index), in_ByteSize(disp));
return madr;
}
int AbstractAssembler::code_fill_byte() {
return 0x00; // Illegal instruction 0x00000000.
}
// Condition code masks. Details see enum branch_condition.
// Although this method is meant for INT CCs, the Overflow/Ordered
// bit in the masks has to be considered. The CC might have been set
// by a float operation, but is evaluated while calculating an integer
// result. See elementary test TestFloat.isNotEqual(FF)Z for example.
Assembler::branch_condition Assembler::inverse_condition(Assembler::branch_condition cc) {
Assembler::branch_condition unordered_bit = (Assembler::branch_condition)(cc & bcondNotOrdered);
Assembler::branch_condition inverse_cc;
// Some are commented out to avoid duplicate labels.
switch (cc) {
case bcondNever : inverse_cc = bcondAlways; break; // 0 -> 15
case bcondAlways : inverse_cc = bcondNever; break; // 15 -> 0
case bcondOverflow : inverse_cc = bcondNotOverflow; break; // 1 -> 14
case bcondNotOverflow : inverse_cc = bcondOverflow; break; // 14 -> 1
default :
switch ((Assembler::branch_condition)(cc & bcondOrdered)) {
case bcondEqual : inverse_cc = bcondNotEqual; break; // 8 -> 6
// case bcondZero :
// case bcondAllZero :
case bcondNotEqual : inverse_cc = bcondEqual; break; // 6 -> 8
// case bcondNotZero :
// case bcondMixed :
case bcondLow : inverse_cc = bcondNotLow; break; // 4 -> 10
// case bcondNegative :
case bcondNotLow : inverse_cc = bcondLow; break; // 10 -> 4
// case bcondNotNegative :
case bcondHigh : inverse_cc = bcondNotHigh; break; // 2 -> 12
// case bcondPositive :
case bcondNotHigh : inverse_cc = bcondHigh; break; // 12 -> 2
// case bcondNotPositive :
default :
fprintf(stderr, "inverse_condition(%d)\n", (int)cc);
fflush(stderr);
ShouldNotReachHere();
return bcondNever;
}
// If cc is even, inverse_cc must be odd.
if (!unordered_bit) {
inverse_cc = (Assembler::branch_condition)(inverse_cc | bcondNotOrdered);
}
break;
}
return inverse_cc;
}
Assembler::branch_condition Assembler::inverse_float_condition(Assembler::branch_condition cc) {
Assembler::branch_condition inverse_cc;
switch (cc) {
case bcondNever : inverse_cc = bcondAlways; break; // 0
case bcondAlways : inverse_cc = bcondNever; break; // 15
case bcondNotOrdered : inverse_cc = bcondOrdered; break; // 14
case bcondOrdered : inverse_cc = bcondNotOrdered; break; // 1
case bcondEqual : inverse_cc = (branch_condition)(bcondNotEqual + bcondNotOrdered); break; // 8
case bcondNotEqual + bcondNotOrdered : inverse_cc = bcondEqual; break; // 7
case bcondLow + bcondNotOrdered : inverse_cc = (branch_condition)(bcondHigh + bcondEqual); break; // 5
case bcondNotLow : inverse_cc = (branch_condition)(bcondLow + bcondNotOrdered); break; // 10
case bcondHigh : inverse_cc = (branch_condition)(bcondLow + bcondNotOrdered + bcondEqual); break; // 2
case bcondNotHigh + bcondNotOrdered : inverse_cc = bcondHigh; break; // 13
default :
fprintf(stderr, "inverse_float_condition(%d)\n", (int)cc);
fflush(stderr);
ShouldNotReachHere();
return bcondNever;
}
return inverse_cc;
}
#ifdef ASSERT
void Assembler::print_dbg_msg(outputStream* out, unsigned long inst, const char* msg, int ilen) {
out->flush();
switch (ilen) {
case 2: out->print_cr("inst = %4.4x, %s", (unsigned short)inst, msg); break;
case 4: out->print_cr("inst = %8.8x, %s\n", (unsigned int)inst, msg); break;
case 6: out->print_cr("inst = %12.12lx, %s\n", inst, msg); break;
default: out->print_cr("inst = %16.16lx, %s\n", inst, msg); break;
}
out->flush();
}
void Assembler::dump_code_range(outputStream* out, address pc, const unsigned int range, const char* msg) {
out->cr();
out->print_cr("-------------------------------");
out->print_cr("-- %s", msg);
out->print_cr("-------------------------------");
out->print_cr("Hex dump of +/-%d bytes around %p, interval [%p,%p)", range, pc, pc-range, pc+range);
os::print_hex_dump(out, pc-range, pc+range, 2);
out->cr();
out->print_cr("Disassembly of +/-%d bytes around %p, interval [%p,%p)", range, pc, pc-range, pc+range);
Disassembler::decode(pc, pc + range, out);
}
#endif