2
// Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
3
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
// This code is free software; you can redistribute it and/or modify it
6
// under the terms of the GNU General Public License version 2 only, as
7
// published by the Free Software Foundation.
9
// This code is distributed in the hope that it will be useful, but WITHOUT
10
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
// version 2 for more details (a copy is included in the LICENSE file that
13
// accompanied this code).
15
// You should have received a copy of the GNU General Public License version
16
// 2 along with this work; if not, write to the Free Software Foundation,
17
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
// or visit www.oracle.com if you need additional information or have any
24
// ARM Architecture Description File
26
//----------DEFINITION BLOCK---------------------------------------------------
27
// Define name --> value mappings to inform the ADLC of an integer valued name
28
// Current support includes integer values in the range [0, 0x7FFFFFFF]
30
// int_def <name> ( <int_value>, <expression>);
31
// Generated Code in ad_<arch>.hpp
32
// #define <name> (<expression>)
33
// // value == <int_value>
34
// Generated code in ad_<arch>.cpp adlc_verification()
35
// assert( <name> == <int_value>, "Expect (<expression>) to equal <int_value>");
38
// The default cost (of an ALU instruction).
39
int_def DEFAULT_COST ( 100, 100);
40
int_def HUGE_COST (1000000, 1000000);
42
// Memory refs are twice as expensive as run-of-the-mill.
43
int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2);
45
// Branches are even more expensive.
46
int_def BRANCH_COST ( 300, DEFAULT_COST * 3);
47
int_def CALL_COST ( 300, DEFAULT_COST * 3);
51
//----------SOURCE BLOCK-------------------------------------------------------
52
// This is a block of C++ code which provides values, functions, and
53
// definitions necessary in the rest of the architecture description
55
// Header information of the source block.
56
// Method declarations/definitions which are used outside
57
// the ad-scope can conveniently be defined here.
59
// To keep related declarations/definitions/uses close together,
60
// we switch between source %{ }% and source_hpp %{ }% freely as needed.
62
#include "asm/macroAssembler.hpp"
63
#include "gc/shared/barrierSetAssembler.hpp"
65
// Does destination need to be loaded in a register then passed to a
67
extern bool maybe_far_call(const CallNode *n);
68
extern bool maybe_far_call(const MachCallNode *n);
69
static inline bool cache_reachable() {
70
return MacroAssembler::_cache_fully_reachable();
78
extern bool PrintOptoAssembly;
83
static OptoRegPair return_value(int ideal_reg);
88
//--------------------------------------------------------------
89
//---< Used for optimization in Compile::Shorten_branches >---
90
//--------------------------------------------------------------
93
// Size of call trampoline stub.
94
static uint size_call_trampoline() {
95
return 0; // no call trampolines on this platform
98
// number of relocations needed by a call trampoline stub
99
static uint reloc_call_trampoline() {
100
return 0; // no call trampolines on this platform
108
static int emit_exception_handler(C2_MacroAssembler *masm);
109
static int emit_deopt_handler(C2_MacroAssembler* masm);
111
static uint size_exception_handler() {
116
static uint size_deopt_handler() {
125
_last_flag = Node::_last_flag
129
// Assert that the given node is not a var shift.
130
bool assert_not_var_shift(const Node *n);
135
// Assert that the given node is not a var shift.
136
bool assert_not_var_shift(const Node *n) {
137
assert(!n->as_ShiftV()->is_var_shift(), "illegal var shift");
143
static FloatRegister reg_to_FloatRegister_object(int register_encoding);
144
static Register reg_to_register_object(int register_encoding);
146
void PhaseOutput::pd_perform_mach_node_analysis() {
149
int MachNode::pd_alignment_required() const {
153
int MachNode::compute_padding(int current_offset) const {
157
// ****************************************************************************
159
// REQUIRED FUNCTIONALITY
161
// emit an interrupt that is caught by the debugger (for debugging compiler)
162
void emit_break(C2_MacroAssembler *masm) {
167
void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const {
172
void MachBreakpointNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
176
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
177
return MachNode::size(ra_);
181
void emit_nop(C2_MacroAssembler *masm) {
186
void emit_call_reloc(C2_MacroAssembler *masm, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) {
187
int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset();
188
int call_site_offset = __ code()->insts()->mark_off();
189
__ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call
190
address target = (address)m->method();
191
assert(n->as_MachCall()->entry_point() == target, "sanity");
192
assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity");
193
assert(cache_reachable() == __ cache_fully_reachable(), "sanity");
195
assert(target != nullptr, "need real address");
197
int ret_addr_offset = -1;
198
if (rspec.type() == relocInfo::runtime_call_type) {
199
__ call(target, rspec);
200
ret_addr_offset = __ offset();
203
ret_addr_offset = __ patchable_call(target, rspec, true);
205
assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()");
208
//=============================================================================
209
// REQUIRED FUNCTIONALITY for encoding
210
void emit_lo(C2_MacroAssembler *masm, int val) { }
211
void emit_hi(C2_MacroAssembler *masm, int val) { }
214
//=============================================================================
215
const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
217
int ConstantTable::calculate_table_base_offset() const {
218
int offset = -(size() / 2);
219
// flds, fldd: 8-bit offset multiplied by 4: +/- 1024
220
// ldr, ldrb : 12-bit offset: +/- 4096
221
if (!Assembler::is_simm10(offset)) {
222
offset = Assembler::min_simm10;
227
bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
228
void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
229
ShouldNotReachHere();
232
void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const {
234
ConstantTable& constant_table = C->output()->constant_table();
236
Register r = as_Register(ra_->get_encode(this));
237
CodeSection* consts_section = __ code()->consts();
238
CodeSection* insts_section = __ code()->insts();
239
// constants section size is aligned according to the align_at_start settings of the next section
240
int consts_size = insts_section->align_at_start(consts_section->size());
241
assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size);
243
// Materialize the constant table base.
244
address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
245
RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
246
__ mov_address(r, baseaddr, rspec);
249
uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
254
void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
256
ra_->dump_register(this, reg, sizeof(reg));
257
st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg);
262
void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
265
for (int i = 0; i < OptoPrologueNops; i++) {
266
st->print_cr("NOP"); st->print("\t");
269
size_t framesize = C->output()->frame_size_in_bytes();
270
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
271
int bangsize = C->output()->bang_size_in_bytes();
272
// Remove two words for return addr and rbp,
273
framesize -= 2*wordSize;
274
bangsize -= 2*wordSize;
276
// Calls to C2R adapters often do not accept exceptional returns.
277
// We require that their callers must bang for them. But be careful, because
278
// some VM calls (such as call site linkage) can use several kilobytes of
279
// stack. But the stack safety zone should account for that.
280
// See bugs 4446381, 4468289, 4497237.
281
if (C->output()->need_stack_bang(bangsize)) {
282
st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
284
st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t");
285
if (framesize != 0) {
286
st->print ("SUB R_SP, R_SP, " SIZE_FORMAT,framesize);
289
if (C->stub_function() == nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
290
st->print("ldr t0, [guard]\n\t");
291
st->print("ldr t1, [Rthread, #thread_disarmed_guard_value_offset]\n\t");
292
st->print("cmp t0, t1\n\t");
293
st->print("beq skip\n\t");
294
st->print("blr #nmethod_entry_barrier_stub\n\t");
295
st->print("b skip\n\t");
296
st->print("guard: int\n\t");
297
st->print("skip:\n\t");
302
void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
305
for (int i = 0; i < OptoPrologueNops; i++) {
309
size_t framesize = C->output()->frame_size_in_bytes();
310
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
311
int bangsize = C->output()->bang_size_in_bytes();
312
// Remove two words for return addr and fp,
313
framesize -= 2*wordSize;
314
bangsize -= 2*wordSize;
316
// Calls to C2R adapters often do not accept exceptional returns.
317
// We require that their callers must bang for them. But be careful, because
318
// some VM calls (such as call site linkage) can use several kilobytes of
319
// stack. But the stack safety zone should account for that.
320
// See bugs 4446381, 4468289, 4497237.
321
if (C->output()->need_stack_bang(bangsize)) {
322
__ arm_stack_overflow_check(bangsize, Rtemp);
326
if (framesize != 0) {
327
__ sub_slow(SP, SP, framesize);
330
if (C->stub_function() == nullptr) {
331
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
332
bs->nmethod_entry_barrier(masm);
335
// offset from scratch buffer is not valid
336
if (strcmp(__ code()->name(), "Compile::Fill_buffer") == 0) {
337
C->output()->set_frame_complete( __ offset() );
340
if (C->has_mach_constant_base_node()) {
341
// NOTE: We set the table base offset here because users might be
342
// emitted before MachConstantBaseNode.
343
ConstantTable& constant_table = C->output()->constant_table();
344
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
348
uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
349
return MachNode::size(ra_);
352
int MachPrologNode::reloc() const {
353
return 10; // a large enough number
356
//=============================================================================
358
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
361
size_t framesize = C->output()->frame_size_in_bytes();
362
framesize -= 2*wordSize;
364
if (framesize != 0) {
365
st->print("ADD R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize);
367
st->print("POP R_FP|R_LR_LR");
369
if (do_polling() && ra_->C->is_method_compilation()) {
371
st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t");
372
st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing");
377
void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
380
size_t framesize = C->output()->frame_size_in_bytes();
381
framesize -= 2*wordSize;
382
if (framesize != 0) {
383
__ add_slow(SP, SP, framesize);
387
// If this does safepoint polling, then do it here
388
if (do_polling() && ra_->C->is_method_compilation()) {
389
__ read_polling_page(Rtemp, relocInfo::poll_return_type);
393
uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
394
return MachNode::size(ra_);
397
int MachEpilogNode::reloc() const {
398
return 16; // a large enough number
401
const Pipeline * MachEpilogNode::pipeline() const {
402
return MachNode::pipeline_class();
405
//=============================================================================
407
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
408
enum RC { rc_bad, rc_int, rc_float, rc_stack };
409
static enum RC rc_class( OptoReg::Name reg ) {
410
if (!OptoReg::is_valid(reg)) return rc_bad;
411
if (OptoReg::is_stack(reg)) return rc_stack;
412
VMReg r = OptoReg::as_VMReg(reg);
413
if (r->is_Register()) return rc_int;
414
assert(r->is_FloatRegister(), "must be");
418
static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) {
419
int rlo = Matcher::_regEncode[src_first];
420
int rhi = Matcher::_regEncode[src_second];
421
if (!((rlo&1)==0 && (rlo+1 == rhi))) {
422
tty->print_cr("CAUGHT BAD LDRD/STRD");
424
return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset);
427
uint MachSpillCopyNode::implementation( C2_MacroAssembler *masm,
430
outputStream* st ) const {
431
// Get registers to move
432
OptoReg::Name src_second = ra_->get_reg_second(in(1));
433
OptoReg::Name src_first = ra_->get_reg_first(in(1));
434
OptoReg::Name dst_second = ra_->get_reg_second(this );
435
OptoReg::Name dst_first = ra_->get_reg_first(this );
437
enum RC src_second_rc = rc_class(src_second);
438
enum RC src_first_rc = rc_class(src_first);
439
enum RC dst_second_rc = rc_class(dst_second);
440
enum RC dst_first_rc = rc_class(dst_first);
442
assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
444
// Generate spill code!
447
if (src_first == dst_first && src_second == dst_second)
448
return size; // Self copy, no move
451
if (bottom_type()->isa_vect() != nullptr) {
455
// Shared code does not expect instruction set capability based bailouts here.
456
// Handle offset unreachable bailout with minimal change in shared code.
457
// Bailout only for real instruction emit.
458
// This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
460
// --------------------------------------
461
// Check for mem-mem move. Load into unused float registers and fall into
462
// the float-store case.
463
if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
464
int offset = ra_->reg2offset(src_first);
465
if (masm && !is_memoryfp(offset)) {
466
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
469
if (src_second_rc != rc_bad) {
470
assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
471
src_first = OptoReg::Name(R_mem_copy_lo_num);
472
src_second = OptoReg::Name(R_mem_copy_hi_num);
473
src_first_rc = rc_float;
474
src_second_rc = rc_float;
476
__ ldr_double(Rmemcopy, Address(SP, offset));
477
} else if (!do_size) {
478
st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
481
src_first = OptoReg::Name(R_mem_copy_lo_num);
482
src_first_rc = rc_float;
484
__ ldr_float(Rmemcopy, Address(SP, offset));
485
} else if (!do_size) {
486
st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
493
if (src_second_rc == rc_stack && dst_second_rc == rc_stack) {
497
// --------------------------------------
498
// Check for integer reg-reg copy
499
if (src_first_rc == rc_int && dst_first_rc == rc_int) {
500
// Else normal reg-reg copy
501
assert( src_second != dst_first, "smashed second before evacuating it" );
503
__ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
505
} else if (!do_size) {
506
st->print("MOV R_%s, R_%s\t# spill",
507
Matcher::regName[dst_first],
508
Matcher::regName[src_first]);
514
// Check for integer store
515
if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
516
int offset = ra_->reg2offset(dst_first);
517
if (masm && !is_memoryI(offset)) {
518
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
521
if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) {
522
assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
524
__ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
526
} else if (!do_size) {
527
if (size != 0) st->print("\n\t");
528
st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
534
__ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
536
} else if (!do_size) {
537
if (size != 0) st->print("\n\t");
538
st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
546
// Check for integer load
547
if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
548
int offset = ra_->reg2offset(src_first);
549
if (masm && !is_memoryI(offset)) {
550
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
553
if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) {
554
assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
556
__ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
558
} else if (!do_size) {
559
if (size != 0) st->print("\n\t");
560
st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
566
__ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
568
} else if (!do_size) {
569
if (size != 0) st->print("\n\t");
570
st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
578
// Check for float reg-reg copy
579
if (src_first_rc == rc_float && dst_first_rc == rc_float) {
580
if (src_second_rc != rc_bad) {
581
assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
583
__ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
585
} else if (!do_size) {
586
st->print(MOV_DOUBLE " R_%s, R_%s\t# spill",
587
Matcher::regName[dst_first],
588
Matcher::regName[src_first]);
594
__ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
596
} else if (!do_size) {
597
st->print(MOV_FLOAT " R_%s, R_%s\t# spill",
598
Matcher::regName[dst_first],
599
Matcher::regName[src_first]);
605
// Check for float store
606
if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
607
int offset = ra_->reg2offset(dst_first);
608
if (masm && !is_memoryfp(offset)) {
609
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
612
// Further check for aligned-adjacent pair, so we can use a double store
613
if (src_second_rc != rc_bad) {
614
assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers and stack slots must be aligned/contiguous");
616
__ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
618
} else if (!do_size) {
619
if (size != 0) st->print("\n\t");
620
st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
626
__ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
628
} else if (!do_size) {
629
if (size != 0) st->print("\n\t");
630
st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
638
// Check for float load
639
if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
640
int offset = ra_->reg2offset(src_first);
641
if (masm && !is_memoryfp(offset)) {
642
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
645
// Further check for aligned-adjacent pair, so we can use a double store
646
if (src_second_rc != rc_bad) {
647
assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers and stack slots must be aligned/contiguous");
649
__ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
651
} else if (!do_size) {
652
if (size != 0) st->print("\n\t");
653
st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
659
__ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
661
} else if (!do_size) {
662
if (size != 0) st->print("\n\t");
663
st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
671
// check for int reg -> float reg move
672
if (src_first_rc == rc_int && dst_first_rc == rc_float) {
673
// Further check for aligned-adjacent pair, so we can use a single instruction
674
if (src_second_rc != rc_bad) {
675
assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
676
assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
677
assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported");
679
__ fmdrr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]), reg_to_register_object(Matcher::_regEncode[src_second]));
681
} else if (!do_size) {
682
if (size != 0) st->print("\n\t");
683
st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second));
689
__ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
691
} else if (!do_size) {
692
if (size != 0) st->print("\n\t");
693
st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
700
// check for float reg -> int reg move
701
if (src_first_rc == rc_float && dst_first_rc == rc_int) {
702
// Further check for aligned-adjacent pair, so we can use a single instruction
703
if (src_second_rc != rc_bad) {
704
assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
705
assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
706
assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported");
708
__ fmrrd(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
710
} else if (!do_size) {
711
if (size != 0) st->print("\n\t");
712
st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first));
718
__ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
720
} else if (!do_size) {
721
if (size != 0) st->print("\n\t");
722
st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
729
// --------------------------------------------------------------------
730
// Check for hi bits still needing moving. Only happens for misaligned
731
// arguments to native calls.
732
if (src_second == dst_second)
733
return size; // Self copy; no move
734
assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
736
// Check for integer reg-reg copy. Hi bits are stuck up in the top
737
// 32-bits of a 64-bit register, but are needed in low bits of another
738
// register (else it's a hi-bits-to-hi-bits copy which should have
739
// happened already as part of a 64-bit move)
740
if (src_second_rc == rc_int && dst_second_rc == rc_int) {
742
__ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second]));
744
} else if (!do_size) {
745
if (size != 0) st->print("\n\t");
746
st->print("MOV R_%s, R_%s\t# spill high",
747
Matcher::regName[dst_second],
748
Matcher::regName[src_second]);
754
// Check for high word integer store
755
if (src_second_rc == rc_int && dst_second_rc == rc_stack) {
756
int offset = ra_->reg2offset(dst_second);
758
if (masm && !is_memoryP(offset)) {
759
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
763
__ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset));
765
} else if (!do_size) {
766
if (size != 0) st->print("\n\t");
767
st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset);
774
// Check for high word integer load
775
if (dst_second_rc == rc_int && src_second_rc == rc_stack) {
776
int offset = ra_->reg2offset(src_second);
777
if (masm && !is_memoryP(offset)) {
778
ra_->C->record_method_not_compilable("unable to handle large constant offsets");
782
__ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset));
784
} else if (!do_size) {
785
if (size != 0) st->print("\n\t");
786
st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset);
794
return 0; // Mute compiler
798
void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
799
implementation( nullptr, ra_, false, st );
803
void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
804
implementation( masm, ra_, false, nullptr );
807
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
808
return implementation( nullptr, ra_, true, nullptr );
811
//=============================================================================
813
void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
814
st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
818
void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc * ) const {
819
for(int i = 0; i < _count; i += 1) {
824
uint MachNopNode::size(PhaseRegAlloc *ra_) const {
829
//=============================================================================
831
void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
832
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
833
int reg = ra_->get_reg_first(this);
834
st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset);
838
void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
839
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
840
int reg = ra_->get_encode(this);
841
Register dst = reg_to_register_object(reg);
843
if (is_aimm(offset)) {
844
__ add(dst, SP, offset);
846
__ mov_slow(dst, offset);
847
__ add(dst, SP, dst);
851
uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
852
// BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
853
assert(ra_ == ra_->C->regalloc(), "sanity");
854
return ra_->C->output()->scratch_emit_size(this);
857
//=============================================================================
859
#define R_RTEMP "R_R12"
860
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
861
st->print_cr("\nUEP:");
862
st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
863
st->print_cr("\tCMP " R_RTEMP ",R_R8" );
864
st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub");
868
void MachUEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
869
__ ic_check(InteriorEntryAlignment);
872
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
873
return MachNode::size(ra_);
877
//=============================================================================
879
// Emit exception handler code.
880
int HandlerImpl::emit_exception_handler(C2_MacroAssembler* masm) {
881
address base = __ start_a_stub(size_exception_handler());
882
if (base == nullptr) {
883
ciEnv::current()->record_failure("CodeCache is full");
884
return 0; // CodeBuffer::expand failed
887
int offset = __ offset();
889
// OK to trash LR, because exception blob will kill it
890
__ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp);
892
assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
899
int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) {
900
// Can't use any of the current frame's registers as we may have deopted
901
// at a poll and everything can be live.
902
address base = __ start_a_stub(size_deopt_handler());
903
if (base == nullptr) {
904
ciEnv::current()->record_failure("CodeCache is full");
905
return 0; // CodeBuffer::expand failed
908
int offset = __ offset();
909
address deopt_pc = __ pc();
911
__ sub(SP, SP, wordSize); // make room for saved PC
912
__ push(LR); // save LR that may be live when we get here
913
__ mov_relative_address(LR, deopt_pc);
914
__ str(LR, Address(SP, wordSize)); // save deopt PC
915
__ pop(LR); // restore LR
916
__ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);
918
assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
924
bool Matcher::match_rule_supported(int opcode) {
925
if (!has_match_rule(opcode))
931
if (!UsePopCountInstruction)
961
return VM_Version::has_simd();
967
return VM_Version::has_vfp() || VM_Version::has_simd();
973
return VM_Version::has_vfp();
976
return true; // Per default match rules are supported.
979
bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
980
return match_rule_supported_vector(opcode, vlen, bt);
983
bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
986
// identify extra cases that we might want to provide match rules for
987
// e.g. Op_ vector nodes and other intrinsics while guarding with vlen
988
bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen);
991
return ret_value; // Per default match rules are supported.
994
bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) {
998
bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
1002
const RegMask* Matcher::predicate_reg_mask(void) {
1006
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
1010
// Vector calling convention not yet implemented.
1011
bool Matcher::supports_vector_calling_convention(void) {
1015
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1017
return OptoRegPair(0, 0);
1020
// Vector width in bytes
1021
int Matcher::vector_width_in_bytes(BasicType bt) {
1022
return MaxVectorSize;
1025
int Matcher::scalable_vector_reg_size(const BasicType bt) {
1029
// Vector ideal reg corresponding to specified size in bytes
1030
uint Matcher::vector_ideal_reg(int size) {
1031
assert(MaxVectorSize >= size, "");
1033
case 8: return Op_VecD;
1034
case 16: return Op_VecX;
1036
ShouldNotReachHere();
1040
// Limits on vector size (number of elements) loaded into vector.
1041
int Matcher::max_vector_size(const BasicType bt) {
1042
assert(is_java_primitive(bt), "only primitive type vectors");
1043
return vector_width_in_bytes(bt)/type2aelembytes(bt);
1046
int Matcher::min_vector_size(const BasicType bt) {
1047
assert(is_java_primitive(bt), "only primitive type vectors");
1048
return 8/type2aelembytes(bt);
1051
int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
1052
return Matcher::max_vector_size(bt);
1055
// Is this branch offset short enough that a short branch can be used?
1057
// NOTE: If the platform does not provide any short branch variants, then
1058
// this method should return false for offset 0.
1059
bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1060
// The passed offset is relative to address of the branch.
1061
// On ARM a branch displacement is calculated relative to address
1062
// of the branch + 8.
1065
// return (Assembler::is_simm24(offset));
1069
MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
1070
ShouldNotReachHere(); // generic vector operands not supported
1074
bool Matcher::is_reg2reg_move(MachNode* m) {
1075
ShouldNotReachHere(); // generic vector operands not supported
1079
bool Matcher::is_generic_vector(MachOper* opnd) {
1080
ShouldNotReachHere(); // generic vector operands not supported
1084
// Should the matcher clone input 'm' of node 'n'?
1085
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
1086
if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
1087
mstack.push(m, Visit); // m = ShiftCntV
1093
// Should the Matcher clone shifts on addressing modes, expecting them
1094
// to be subsumed into complex addressing expressions or compute them
1096
bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
1097
return clone_base_plus_offset_address(m, mstack, address_visited);
1100
// Return whether or not this register is ever used as an argument. This
1101
// function is used on startup to build the trampoline stubs in generateOptoStub.
1102
// Registers not mentioned will be killed by the VM call in the trampoline, and
1103
// arguments in those registers not be available to the callee.
1104
bool Matcher::can_be_java_arg( int reg ) {
1105
if (reg == R_R0_num ||
1108
reg == R_R3_num) return true;
1110
if (reg >= R_S0_num &&
1111
reg <= R_S13_num) return true;
1115
bool Matcher::is_spillable_arg( int reg ) {
1116
return can_be_java_arg(reg);
1119
uint Matcher::int_pressure_limit()
1121
return (INTPRESSURE == -1) ? 12 : INTPRESSURE;
1124
uint Matcher::float_pressure_limit()
1126
return (FLOATPRESSURE == -1) ? 30 : FLOATPRESSURE;
1129
bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
1133
// Register for DIVI projection of divmodI
1134
RegMask Matcher::divI_proj_mask() {
1135
ShouldNotReachHere();
1139
// Register for MODI projection of divmodI
1140
RegMask Matcher::modI_proj_mask() {
1141
ShouldNotReachHere();
1145
// Register for DIVL projection of divmodL
1146
RegMask Matcher::divL_proj_mask() {
1147
ShouldNotReachHere();
1151
// Register for MODL projection of divmodL
1152
RegMask Matcher::modL_proj_mask() {
1153
ShouldNotReachHere();
1157
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
1158
return FP_REGP_mask();
1161
bool maybe_far_call(const CallNode *n) {
1162
return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
1165
bool maybe_far_call(const MachCallNode *n) {
1166
return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
1171
//----------ENCODING BLOCK-----------------------------------------------------
1172
// This block specifies the encoding classes used by the compiler to output
1173
// byte streams. Encoding classes are parameterized macros used by
1174
// Machine Instruction Nodes in order to generate the bit encoding of the
1175
// instruction. Operands specify their base encoding interface with the
1176
// interface keyword. There are currently supported four interfaces,
1177
// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
1178
// operand to generate a function which returns its register number when
1179
// queried. CONST_INTER causes an operand to generate a function which
1180
// returns the value of the constant when queried. MEMORY_INTER causes an
1181
// operand to generate four functions which return the Base Register, the
1182
// Index Register, the Scale Value, and the Offset Value of the operand when
1183
// queried. COND_INTER causes an operand to generate six functions which
1184
// return the encoding code (ie - encoding bits for the instruction)
1185
// associated with each basic boolean condition for a conditional instruction.
1187
// Instructions specify two basic values for encoding. Again, a function
1188
// is available to check if the constant displacement is an oop. They use the
1189
// ins_encode keyword to specify their encoding classes (which must be
1190
// a sequence of enc_class names, and their parameters, specified in
1191
// the encoding block), and they use the
1192
// opcode keyword to specify, in order, their primary, secondary, and
1193
// tertiary opcode. Only the opcode sections which a particular instruction
1194
// needs for encoding need to be specified.
1196
// Set instruction mark in MacroAssembler. This is used only in
1197
// instructions that emit bytes directly to the CodeBuffer wraped
1198
// in the MacroAssembler. Should go away once all "instruct" are
1199
// patched to emit bytes only using methods in MacroAssembler.
1200
enc_class SetInstMark %{
1204
enc_class ClearInstMark %{
1205
__ clear_inst_mark();
1208
enc_class call_epilog %{
1212
enc_class Java_To_Runtime (method meth) %{
1213
// CALL directly to the runtime
1214
emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1217
enc_class Java_Static_Call (method meth) %{
1218
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
1219
// who we intended to call.
1222
emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1224
int method_index = resolved_method_index(masm);
1225
RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1226
: static_call_Relocation::spec(method_index);
1227
emit_call_reloc(masm, as_MachCall(), $meth, rspec);
1229
// Emit stubs for static call.
1230
address stub = CompiledDirectCall::emit_to_interp_stub(masm);
1231
if (stub == nullptr) {
1232
ciEnv::current()->record_failure("CodeCache is full");
1238
enc_class save_last_PC %{
1240
address mark = __ inst_mark();
1241
debug_only(int off0 = __ offset());
1242
int ret_addr_offset = as_MachCall()->ret_addr_offset();
1243
__ adr(LR, mark + ret_addr_offset);
1244
__ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
1245
debug_only(int off1 = __ offset());
1246
assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
1248
__ set_inst_mark(mark);
1251
enc_class preserve_SP %{
1253
address mark = __ inst_mark();
1254
debug_only(int off0 = __ offset());
1255
// FP is preserved across all calls, even compiled calls.
1256
// Use it to preserve SP in places where the callee might change the SP.
1257
__ mov(Rmh_SP_save, SP);
1258
debug_only(int off1 = __ offset());
1259
assert(off1 - off0 == 4, "correct size prediction");
1261
__ set_inst_mark(mark);
1264
enc_class restore_SP %{
1265
__ mov(SP, Rmh_SP_save);
1268
enc_class Java_Dynamic_Call (method meth) %{
1269
Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
1270
assert(R8_ic_reg == Ricklass, "should be");
1272
__ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff);
1273
__ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16);
1274
address virtual_call_oop_addr = __ inst_mark();
1275
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
1276
// who we intended to call.
1277
int method_index = resolved_method_index(masm);
1278
__ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
1279
emit_call_reloc(masm, as_MachCall(), $meth, RelocationHolder::none);
1282
enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{
1283
// FIXME: load from constant table?
1284
// Load a constant replicated "count" times with width "width"
1285
int count = $cnt$$constant;
1286
int width = $wth$$constant;
1287
assert(count*width == 4, "sanity");
1288
int val = $src$$constant;
1290
int bit_width = width * 8;
1291
val &= (((int)1) << bit_width) - 1; // mask off sign bits
1292
for (int i = 0; i < count - 1; i++) {
1293
val |= (val << bit_width);
1298
__ mvn($tmp$$Register, 0);
1299
} else if (val == 0) {
1300
__ mov($tmp$$Register, 0);
1302
__ movw($tmp$$Register, val & 0xffff);
1303
__ movt($tmp$$Register, (unsigned int)val >> 16);
1305
__ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1308
enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{
1309
// Replicate float con 2 times and pack into vector (8 bytes) in regD.
1310
float fval = $src$$constant;
1311
int val = *((int*)&fval);
1314
__ mvn($tmp$$Register, 0);
1315
} else if (val == 0) {
1316
__ mov($tmp$$Register, 0);
1318
__ movw($tmp$$Register, val & 0xffff);
1319
__ movt($tmp$$Register, (unsigned int)val >> 16);
1321
__ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1324
enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
1327
Register str1_reg = $str1$$Register;
1328
Register str2_reg = $str2$$Register;
1329
Register cnt1_reg = $cnt1$$Register; // int
1330
Register cnt2_reg = $cnt2$$Register; // int
1331
Register tmp1_reg = $tmp1$$Register;
1332
Register tmp2_reg = $tmp2$$Register;
1333
Register result_reg = $result$$Register;
1335
assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg);
1337
// Compute the minimum of the string lengths(str1_reg) and the
1338
// difference of the string lengths (stack)
1340
// See if the lengths are different, and calculate min in str1_reg.
1341
// Stash diff in tmp2 in case we need it for a tie-breaker.
1342
__ subs_32(tmp2_reg, cnt1_reg, cnt2_reg);
1343
__ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit
1344
__ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit
1346
// reallocate cnt1_reg, cnt2_reg, result_reg
1347
// Note: limit_reg holds the string length pre-scaled by 2
1348
Register limit_reg = cnt1_reg;
1349
Register chr2_reg = cnt2_reg;
1350
Register chr1_reg = tmp1_reg;
1351
// str{12} are the base pointers
1353
// Is the minimum length zero?
1354
__ cmp_32(limit_reg, 0);
1355
if (result_reg != tmp2_reg) {
1356
__ mov(result_reg, tmp2_reg, eq);
1360
// Load first characters
1361
__ ldrh(chr1_reg, Address(str1_reg, 0));
1362
__ ldrh(chr2_reg, Address(str2_reg, 0));
1364
// Compare first characters
1365
__ subs(chr1_reg, chr1_reg, chr2_reg);
1366
if (result_reg != chr1_reg) {
1367
__ mov(result_reg, chr1_reg, ne);
1372
// Check after comparing first character to see if strings are equivalent
1373
// Check if the strings start at same location
1374
__ cmp(str1_reg, str2_reg);
1375
// Check if the length difference is zero
1376
__ cond_cmp(tmp2_reg, 0, eq);
1377
__ mov(result_reg, 0, eq); // result is zero
1379
// Strings might not be equal
1382
__ subs(chr1_reg, limit_reg, 1 * sizeof(jchar));
1383
if (result_reg != tmp2_reg) {
1384
__ mov(result_reg, tmp2_reg, eq);
1388
// Shift str1_reg and str2_reg to the end of the arrays, negate limit
1389
__ add(str1_reg, str1_reg, limit_reg);
1390
__ add(str2_reg, str2_reg, limit_reg);
1391
__ neg(limit_reg, chr1_reg); // limit = -(limit-2)
1393
// Compare the rest of the characters
1395
__ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1396
__ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1397
__ subs(chr1_reg, chr1_reg, chr2_reg);
1398
if (result_reg != chr1_reg) {
1399
__ mov(result_reg, chr1_reg, ne);
1403
__ adds(limit_reg, limit_reg, sizeof(jchar));
1406
// If strings are equal up to min length, return the length difference.
1407
if (result_reg != tmp2_reg) {
1408
__ mov(result_reg, tmp2_reg);
1411
// Otherwise, return the difference between the first mismatched chars.
1415
enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
1416
Label Lchar, Lchar_loop, Ldone, Lequal;
1418
Register str1_reg = $str1$$Register;
1419
Register str2_reg = $str2$$Register;
1420
Register cnt_reg = $cnt$$Register; // int
1421
Register tmp1_reg = $tmp1$$Register;
1422
Register tmp2_reg = $tmp2$$Register;
1423
Register result_reg = $result$$Register;
1425
assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg);
1427
__ cmp(str1_reg, str2_reg); //same char[] ?
1430
__ cbz_32(cnt_reg, Lequal); // count == 0
1433
Register limit_reg = cnt_reg;
1434
Register chr1_reg = tmp1_reg;
1435
Register chr2_reg = tmp2_reg;
1437
__ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1439
//check for alignment and position the pointers to the ends
1440
__ orr(chr1_reg, str1_reg, str2_reg);
1441
__ tst(chr1_reg, 0x3);
1443
// notZero means at least one not 4-byte aligned.
1444
// We could optimize the case when both arrays are not aligned
1445
// but it is not frequent case and it requires additional checks.
1448
// Compare char[] arrays aligned to 4 bytes.
1449
__ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
1450
chr1_reg, chr2_reg, Ldone);
1452
__ b(Lequal); // equal
1454
// char by char compare
1456
__ mov(result_reg, 0);
1457
__ add(str1_reg, limit_reg, str1_reg);
1458
__ add(str2_reg, limit_reg, str2_reg);
1459
__ neg(limit_reg, limit_reg); //negate count
1462
__ bind(Lchar_loop);
1463
__ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1464
__ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1465
__ cmp(chr1_reg, chr2_reg);
1467
__ adds(limit_reg, limit_reg, sizeof(jchar));
1468
__ b(Lchar_loop, ne);
1471
__ mov(result_reg, 1); //equal
1476
enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
1477
Label Ldone, Lloop, Lequal;
1479
Register ary1_reg = $ary1$$Register;
1480
Register ary2_reg = $ary2$$Register;
1481
Register tmp1_reg = $tmp1$$Register;
1482
Register tmp2_reg = $tmp2$$Register;
1483
Register tmp3_reg = $tmp3$$Register;
1484
Register result_reg = $result$$Register;
1486
assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg);
1488
int length_offset = arrayOopDesc::length_offset_in_bytes();
1489
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
1491
// return true if the same array
1492
__ teq(ary1_reg, ary2_reg);
1493
__ mov(result_reg, 1, eq);
1494
__ b(Ldone, eq); // equal
1496
__ tst(ary1_reg, ary1_reg);
1497
__ mov(result_reg, 0, eq);
1498
__ b(Ldone, eq); // not equal
1500
__ tst(ary2_reg, ary2_reg);
1501
__ mov(result_reg, 0, eq);
1502
__ b(Ldone, eq); // not equal
1504
//load the lengths of arrays
1505
__ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int
1506
__ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int
1508
// return false if the two arrays are not equal length
1509
__ teq_32(tmp1_reg, tmp2_reg);
1510
__ mov(result_reg, 0, ne);
1511
__ b(Ldone, ne); // not equal
1513
__ tst(tmp1_reg, tmp1_reg);
1514
__ mov(result_reg, 1, eq);
1515
__ b(Ldone, eq); // zero-length arrays are equal
1517
// load array addresses
1518
__ add(ary1_reg, ary1_reg, base_offset);
1519
__ add(ary2_reg, ary2_reg, base_offset);
1521
// renaming registers
1522
Register chr1_reg = tmp3_reg; // for characters in ary1
1523
Register chr2_reg = tmp2_reg; // for characters in ary2
1524
Register limit_reg = tmp1_reg; // length
1527
__ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1529
// Compare char[] arrays aligned to 4 bytes.
1530
__ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
1531
chr1_reg, chr2_reg, Ldone);
1533
__ mov(result_reg, 1); //equal
1539
//----------FRAME--------------------------------------------------------------
1540
// Definition of frame structure and management information.
1542
// S T A C K L A Y O U T Allocators stack-slot number
1543
// | (to get allocators register number
1544
// G Owned by | | v add VMRegImpl::stack0)
1546
// o | +--------+ pad to even-align allocators stack-slot
1547
// w V | pad0 | numbers; owned by CALLER
1548
// t -----------+--------+----> Matcher::_in_arg_limit, unaligned
1550
// | | args | 4 Holes in incoming args owned by SELF
1553
// V | | old out| Empty on Intel, window on Sparc
1554
// | old |preserve| Must be even aligned.
1555
// | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned
1556
// | | in | 3 area for Intel ret address
1557
// Owned by |preserve| Empty on Sparc.
1559
// | | pad2 | 2 pad to align old SP
1562
// | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned
1563
// | | pad1 | 11 pad to align new SP
1566
// | | spills | 9 spills
1567
// V | | 8 (pad0 slot for callee)
1568
// -----------+--------+----> Matcher::_out_arg_limit, unaligned
1570
// | | args | 6 Holes in outgoing args owned by CALLEE
1571
// Owned by +--------+
1572
// CALLEE | new out| 6 Empty on Intel, window on Sparc
1573
// | new |preserve| Must be even-aligned.
1574
// | SP-+--------+----> Matcher::_new_SP, even aligned
1577
// Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
1578
// known from SELF's arguments and the Java calling convention.
1579
// Region 6-7 is determined per call site.
1580
// Note 2: If the calling convention leaves holes in the incoming argument
1581
// area, those holes are owned by SELF. Holes in the outgoing area
1582
// are owned by the CALLEE. Holes should not be necessary in the
1583
// incoming area, as the Java calling convention is completely under
1584
// the control of the AD file. Doubles can be sorted and packed to
1585
// avoid holes. Holes in the outgoing arguments may be necessary for
1586
// varargs C calling conventions.
1587
// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
1588
// even aligned with pad0 as needed.
1589
// Region 6 is even aligned. Region 6-7 is NOT even aligned;
1590
// region 6-11 is even aligned; it may be padded out more so that
1591
// the region from SP to FP meets the minimum stack alignment.
1594
// These two registers define part of the calling convention
1595
// between compiled code and the interpreter.
1596
inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C
1598
// Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
1599
cisc_spilling_operand_name(indOffset);
1601
// Number of stack slots consumed by a Monitor enter
1602
sync_stack_slots(1 * VMRegImpl::slots_per_word);
1604
// Compiled code's Frame Pointer
1605
frame_pointer(R_R13);
1607
// Stack alignment requirement
1608
stack_alignment(StackAlignmentInBytes);
1609
// LP64: Alignment size in bytes (128-bit -> 16 bytes)
1610
// !LP64: Alignment size in bytes (64-bit -> 8 bytes)
1612
// Number of outgoing stack slots killed above the out_preserve_stack_slots
1613
// for calls to C. Supports the var-args backing area for register parms.
1614
// ADLC doesn't support parsing expressions, so I folded the math by hand.
1615
varargs_C_out_slots_killed( 0);
1617
// The after-PROLOG location of the return address. Location of
1618
// return address specifies a type (REG or STACK) and a number
1619
// representing the register number (i.e. - use a register name) or
1621
// Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1622
// Otherwise, it is above the locks and verification slot and alignment word
1623
return_addr(STACK - 1*VMRegImpl::slots_per_word +
1624
align_up((Compile::current()->in_preserve_stack_slots() +
1625
Compile::current()->fixed_slots()),
1626
stack_alignment_in_slots()));
1628
// Location of compiled Java return values. Same as C
1630
return c2::return_value(ideal_reg);
1635
//----------ATTRIBUTES---------------------------------------------------------
1636
//----------Instruction Attributes---------------------------------------------
1637
ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
1638
ins_attrib ins_size(32); // Required size attribute (in bits)
1639
ins_attrib ins_short_branch(0); // Required flag: is this instruction a
1640
// non-matching short branch variant of some
1643
//----------OPERANDS-----------------------------------------------------------
1644
// Operand definitions must precede instruction definitions for correct parsing
1645
// in the ADLC because operands constitute user defined types which are used in
1646
// instruction definitions.
1648
//----------Simple Operands----------------------------------------------------
1649
// Immediate Operands
1650
// Integer Immediate: 32-bit
1655
// formats are generated automatically for constants and base registers
1657
interface(CONST_INTER);
1660
// Integer Immediate: 8-bit unsigned - for VMOV
1662
predicate(0 <= n->get_int() && (n->get_int() <= 255));
1667
interface(CONST_INTER);
1670
// Integer Immediate: 16-bit
1672
predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw());
1677
interface(CONST_INTER);
1680
// Integer Immediate: offset for half and double word loads and stores
1682
predicate(is_memoryHD(n->get_int()));
1686
interface(CONST_INTER);
1689
// Integer Immediate: offset for fp loads and stores
1691
predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0));
1696
interface(CONST_INTER);
1699
// Valid scale values for addressing modes and shifts
1701
predicate(0 <= n->get_int() && (n->get_int() <= 31));
1706
interface(CONST_INTER);
1709
// Integer Immediate: 6-bit
1710
operand immU6Big() %{
1711
predicate(n->get_int() >= 32 && n->get_int() <= 63);
1715
interface(CONST_INTER);
1718
// Integer Immediate: 0-bit
1720
predicate(n->get_int() == 0);
1725
interface(CONST_INTER);
1728
// Int Immediate non-negative
1731
predicate(n->get_int() >= 0);
1736
interface(CONST_INTER);
1739
// Integer Immediate: the values 32-63
1740
operand immI_32_63() %{
1741
predicate(n->get_int() >= 32 && n->get_int() <= 63);
1746
interface(CONST_INTER);
1749
// Immediates for special shifts (sign extend)
1751
// Integer Immediate: the value 16
1753
predicate(n->get_int() == 16);
1758
interface(CONST_INTER);
1761
// Integer Immediate: the value 24
1763
predicate(n->get_int() == 24);
1768
interface(CONST_INTER);
1771
// Integer Immediate: the value 255
1772
operand immI_255() %{
1773
predicate( n->get_int() == 255 );
1778
interface(CONST_INTER);
1781
// Integer Immediate: the value 65535
1782
operand immI_65535() %{
1783
predicate(n->get_int() == 65535);
1788
interface(CONST_INTER);
1791
// Integer Immediates for arithmetic instructions
1794
predicate(is_aimm(n->get_int()));
1799
interface(CONST_INTER);
1802
operand aimmIneg() %{
1803
predicate(is_aimm(-n->get_int()));
1808
interface(CONST_INTER);
1812
predicate((0 <= n->get_int()) && is_aimm(n->get_int()));
1817
interface(CONST_INTER);
1820
// Integer Immediates for logical instructions
1823
predicate(is_limmI(n->get_int()));
1828
interface(CONST_INTER);
1831
operand limmIlow8() %{
1832
predicate(is_limmI_low(n->get_int(), 8));
1837
interface(CONST_INTER);
1841
predicate(0 <= n->get_int() && is_limmI(n->get_int()));
1846
interface(CONST_INTER);
1850
predicate(is_limmI(~n->get_int()));
1855
interface(CONST_INTER);
1858
// Pointer Immediate: 32 or 64-bit
1863
// formats are generated automatically for constants and base registers
1865
interface(CONST_INTER);
1869
predicate(n->get_ptr() == 0);
1874
interface(CONST_INTER);
1880
// formats are generated automatically for constants and base registers
1882
interface(CONST_INTER);
1886
predicate(n->get_long() == 0L);
1889
// formats are generated automatically for constants and base registers
1891
interface(CONST_INTER);
1894
// Long Immediate: 16-bit
1896
predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw());
1901
interface(CONST_INTER);
1904
// Long Immediate: low 32-bit mask
1905
operand immL_32bits() %{
1906
predicate(n->get_long() == 0xFFFFFFFFL);
1911
interface(CONST_INTER);
1920
interface(CONST_INTER);
1923
// Double Immediate: +0.0d.
1925
predicate(jlong_cast(n->getd()) == 0);
1930
interface(CONST_INTER);
1934
predicate(Assembler::double_num(n->getd()).can_be_imm8());
1939
interface(CONST_INTER);
1948
interface(CONST_INTER);
1951
// Float Immediate: +0.0f
1953
predicate(jint_cast(n->getf()) == 0);
1958
interface(CONST_INTER);
1961
// Float Immediate: encoded as 8 bits
1963
predicate(Assembler::float_num(n->getf()).can_be_imm8());
1968
interface(CONST_INTER);
1971
// Integer Register Operands
1974
constraint(ALLOC_IN_RC(int_reg));
1983
interface(REG_INTER);
1988
constraint(ALLOC_IN_RC(ptr_reg));
1993
match(RExceptionRegP);
1996
match(RthreadRegP); // FIXME: move to sp_ptr_RegP?
2001
match(store_ptr_RegP);
2004
interface(REG_INTER);
2007
// GPRs + Rthread + SP
2008
operand sp_ptr_RegP() %{
2009
constraint(ALLOC_IN_RC(sp_ptr_reg));
2012
match(SPRegP); // FIXME: check cost
2015
interface(REG_INTER);
2020
constraint(ALLOC_IN_RC(R0_regP));
2024
interface(REG_INTER);
2028
constraint(ALLOC_IN_RC(R1_regP));
2032
interface(REG_INTER);
2036
constraint(ALLOC_IN_RC(R8_regP));
2040
interface(REG_INTER);
2044
constraint(ALLOC_IN_RC(R9_regP));
2048
interface(REG_INTER);
2052
constraint(ALLOC_IN_RC(R12_regP));
2056
interface(REG_INTER);
2060
constraint(ALLOC_IN_RC(R2_regP));
2064
interface(REG_INTER);
2067
operand RExceptionRegP() %{
2068
constraint(ALLOC_IN_RC(Rexception_regP));
2072
interface(REG_INTER);
2075
operand RthreadRegP() %{
2076
constraint(ALLOC_IN_RC(Rthread_regP));
2080
interface(REG_INTER);
2084
constraint(ALLOC_IN_RC(IP_regP));
2088
interface(REG_INTER);
2092
constraint(ALLOC_IN_RC(SP_regP));
2096
interface(REG_INTER);
2100
constraint(ALLOC_IN_RC(LR_regP));
2104
interface(REG_INTER);
2108
constraint(ALLOC_IN_RC(R0_regI));
2112
interface(REG_INTER);
2116
constraint(ALLOC_IN_RC(R1_regI));
2120
interface(REG_INTER);
2124
constraint(ALLOC_IN_RC(R2_regI));
2128
interface(REG_INTER);
2132
constraint(ALLOC_IN_RC(R3_regI));
2136
interface(REG_INTER);
2140
constraint(ALLOC_IN_RC(R12_regI));
2144
interface(REG_INTER);
2149
constraint(ALLOC_IN_RC(long_reg));
2156
interface(REG_INTER);
2160
constraint(ALLOC_IN_RC(long_reg_align));
2161
match(iRegL); // FIXME: allows unaligned R11/R12?
2164
interface(REG_INTER);
2167
// first long arg, or return value
2168
operand R0R1RegL() %{
2169
constraint(ALLOC_IN_RC(R0R1_regL));
2173
interface(REG_INTER);
2176
operand R2R3RegL() %{
2177
constraint(ALLOC_IN_RC(R2R3_regL));
2181
interface(REG_INTER);
2184
// Condition Code Flag Register
2185
operand flagsReg() %{
2186
constraint(ALLOC_IN_RC(int_flags));
2190
interface(REG_INTER);
2193
// Result of compare to 0 (TST)
2194
operand flagsReg_EQNELTGE() %{
2195
constraint(ALLOC_IN_RC(int_flags));
2198
format %{ "apsr_EQNELTGE" %}
2199
interface(REG_INTER);
2202
// Condition Code Register, unsigned comparisons.
2203
operand flagsRegU() %{
2204
constraint(ALLOC_IN_RC(int_flags));
2210
format %{ "apsr_U" %}
2211
interface(REG_INTER);
2214
// Condition Code Register, pointer comparisons.
2215
operand flagsRegP() %{
2216
constraint(ALLOC_IN_RC(int_flags));
2219
format %{ "apsr_P" %}
2220
interface(REG_INTER);
2223
// Condition Code Register, long comparisons.
2224
operand flagsRegL_LTGE() %{
2225
constraint(ALLOC_IN_RC(int_flags));
2228
format %{ "apsr_L_LTGE" %}
2229
interface(REG_INTER);
2232
operand flagsRegL_EQNE() %{
2233
constraint(ALLOC_IN_RC(int_flags));
2236
format %{ "apsr_L_EQNE" %}
2237
interface(REG_INTER);
2240
operand flagsRegL_LEGT() %{
2241
constraint(ALLOC_IN_RC(int_flags));
2244
format %{ "apsr_L_LEGT" %}
2245
interface(REG_INTER);
2248
operand flagsRegUL_LTGE() %{
2249
constraint(ALLOC_IN_RC(int_flags));
2252
format %{ "apsr_UL_LTGE" %}
2253
interface(REG_INTER);
2256
operand flagsRegUL_EQNE() %{
2257
constraint(ALLOC_IN_RC(int_flags));
2260
format %{ "apsr_UL_EQNE" %}
2261
interface(REG_INTER);
2264
operand flagsRegUL_LEGT() %{
2265
constraint(ALLOC_IN_RC(int_flags));
2268
format %{ "apsr_UL_LEGT" %}
2269
interface(REG_INTER);
2272
// Condition Code Register, floating comparisons, unordered same as "less".
2273
operand flagsRegF() %{
2274
constraint(ALLOC_IN_RC(float_flags));
2277
format %{ "fpscr_F" %}
2278
interface(REG_INTER);
2283
constraint(ALLOC_IN_RC(actual_dflt_reg));
2287
interface(REG_INTER);
2291
constraint(ALLOC_IN_RC(vectorx_reg));
2295
interface(REG_INTER);
2299
constraint(ALLOC_IN_RC(actual_dflt_reg));
2304
interface(REG_INTER);
2308
constraint(ALLOC_IN_RC(sflt_reg));
2312
interface(REG_INTER);
2315
operand regD_low() %{
2316
constraint(ALLOC_IN_RC(dflt_low_reg));
2320
interface(REG_INTER);
2326
operand inline_cache_regP(iRegP reg) %{
2327
constraint(ALLOC_IN_RC(Ricklass_regP));
2330
interface(REG_INTER);
2333
//----------Complex Operands---------------------------------------------------
2334
// Indirect Memory Reference
2335
operand indirect(sp_ptr_RegP reg) %{
2336
constraint(ALLOC_IN_RC(sp_ptr_reg));
2340
format %{ "[$reg]" %}
2341
interface(MEMORY_INTER) %{
2343
index(0xf); // PC => no index
2350
// Indirect with Offset in ]-4096, 4096[
2351
operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{
2352
constraint(ALLOC_IN_RC(sp_ptr_reg));
2353
match(AddP reg offset);
2356
format %{ "[$reg + $offset]" %}
2357
interface(MEMORY_INTER) %{
2359
index(0xf); // PC => no index
2365
// Indirect with offset for float load/store
2366
operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{
2367
constraint(ALLOC_IN_RC(sp_ptr_reg));
2368
match(AddP reg offset);
2371
format %{ "[$reg + $offset]" %}
2372
interface(MEMORY_INTER) %{
2374
index(0xf); // PC => no index
2380
// Indirect with Offset for half and double words
2381
operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{
2382
constraint(ALLOC_IN_RC(sp_ptr_reg));
2383
match(AddP reg offset);
2386
format %{ "[$reg + $offset]" %}
2387
interface(MEMORY_INTER) %{
2389
index(0xf); // PC => no index
2395
// Indirect with Offset and Offset+4 in ]-1024, 1024[
2396
operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{
2397
constraint(ALLOC_IN_RC(sp_ptr_reg));
2398
match(AddP reg offset);
2401
format %{ "[$reg + $offset]" %}
2402
interface(MEMORY_INTER) %{
2404
index(0xf); // PC => no index
2410
// Indirect with Offset and Offset+4 in ]-4096, 4096[
2411
operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{
2412
constraint(ALLOC_IN_RC(sp_ptr_reg));
2413
match(AddP reg offset);
2416
format %{ "[$reg + $offset]" %}
2417
interface(MEMORY_INTER) %{
2419
index(0xf); // PC => no index
2425
// Indirect with Register Index
2426
operand indIndex(iRegP addr, iRegX index) %{
2427
constraint(ALLOC_IN_RC(ptr_reg));
2428
match(AddP addr index);
2431
format %{ "[$addr + $index]" %}
2432
interface(MEMORY_INTER) %{
2440
// Indirect Memory Times Scale Plus Index Register
2441
operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{
2442
constraint(ALLOC_IN_RC(ptr_reg));
2443
match(AddP addr (LShiftX index scale));
2446
format %{"[$addr + $index << $scale]" %}
2447
interface(MEMORY_INTER) %{
2455
// Operands for expressing Control Flow
2456
// NOTE: Label is a predefined operand which should not be redefined in
2457
// the AD file. It is generically handled within the ADLC.
2459
//----------Conditional Branch Operands----------------------------------------
2460
// Comparison Op - This is the operation of the comparison, and is limited to
2461
// the following set of codes:
2462
// L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
2464
// Other attributes of the comparison, such as unsignedness, are specified
2465
// by the comparison instruction that sets a condition code flags register.
2466
// That result is represented by a flags operand whose subtype is appropriate
2467
// to the unsignedness (etc.) of the comparison.
2469
// Later, the instruction which matches both the Comparison Op (a Bool) and
2470
// the flags (produced by the Cmp) specifies the coding of the comparison op
2471
// by matching a specific subtype of Bool operand below, such as cmpOpU.
2477
interface(COND_INTER) %{
2484
overflow(0x0); // unsupported/unimplemented
2485
no_overflow(0x0); // unsupported/unimplemented
2489
// integer comparison with 0, signed
2494
interface(COND_INTER) %{
2499
less_equal(0xd); // unsupported
2500
greater(0xc); // unsupported
2501
overflow(0x0); // unsupported/unimplemented
2502
no_overflow(0x0); // unsupported/unimplemented
2506
// Comparison Op, unsigned
2511
interface(COND_INTER) %{
2518
overflow(0x0); // unsupported/unimplemented
2519
no_overflow(0x0); // unsupported/unimplemented
2523
// Comparison Op, pointer (same as unsigned)
2528
interface(COND_INTER) %{
2535
overflow(0x0); // unsupported/unimplemented
2536
no_overflow(0x0); // unsupported/unimplemented
2544
interface(COND_INTER) %{
2551
overflow(0x0); // unsupported/unimplemented
2552
no_overflow(0x0); // unsupported/unimplemented
2556
operand cmpOpL_commute() %{
2560
interface(COND_INTER) %{
2567
overflow(0x0); // unsupported/unimplemented
2568
no_overflow(0x0); // unsupported/unimplemented
2576
interface(COND_INTER) %{
2583
overflow(0x0); // unsupported/unimplemented
2584
no_overflow(0x0); // unsupported/unimplemented
2588
operand cmpOpUL_commute() %{
2592
interface(COND_INTER) %{
2599
overflow(0x0); // unsupported/unimplemented
2600
no_overflow(0x0); // unsupported/unimplemented
2605
//----------OPERAND CLASSES----------------------------------------------------
2606
// Operand Classes are groups of operands that are used to simplify
2607
// instruction definitions by not requiring the AD writer to specify separate
2608
// instructions for every form of operand when the instruction accepts
2609
// multiple operand types with the same basic encoding and format. The classic
2610
// case of this is memory operands.
2612
opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale );
2613
opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale );
2614
opclass memoryF ( indirect, indOffsetFP );
2615
opclass memoryF2 ( indirect, indOffsetFPx2 );
2616
opclass memoryD ( indirect, indOffsetFP );
2617
opclass memoryfp( indirect, indOffsetFP );
2618
opclass memoryB ( indirect, indIndex, indOffsetHD );
2619
opclass memoryS ( indirect, indIndex, indOffsetHD );
2620
opclass memoryL ( indirect, indIndex, indOffsetHD );
2622
opclass memoryScaledI(indIndexScale);
2623
opclass memoryScaledP(indIndexScale);
2625
// when ldrex/strex is used:
2626
opclass memoryex ( indirect );
2627
opclass indIndexMemory( indIndex );
2628
opclass memorylong ( indirect, indOffset12x2 );
2629
opclass memoryvld ( indirect /* , write back mode not implemented */ );
2631
//----------PIPELINE-----------------------------------------------------------
2634
//----------ATTRIBUTES---------------------------------------------------------
2636
fixed_size_instructions; // Fixed size instructions
2637
max_instructions_per_bundle = 4; // Up to 4 instructions per bundle
2638
instruction_unit_size = 4; // An instruction is 4 bytes long
2639
instruction_fetch_unit_size = 16; // The processor fetches one line
2640
instruction_fetch_units = 1; // of 16 bytes
2642
// List of nop instructions
2643
nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR );
2646
//----------RESOURCES----------------------------------------------------------
2647
// Resources are the functional units available to the machine
2648
resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1);
2650
//----------PIPELINE DESCRIPTION-----------------------------------------------
2651
// Pipeline Description specifies the stages in the machine's pipeline
2653
pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D);
2655
//----------PIPELINE CLASSES---------------------------------------------------
2656
// Pipeline Classes describe the stages in which input and output are
2657
// referenced by the hardware pipeline.
2659
// Integer ALU reg-reg operation
2660
pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2668
// Integer ALU reg-reg long operation
2669
pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{
2670
instruction_count(2);
2678
// Integer ALU reg-reg long dependent operation
2679
pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{
2680
instruction_count(1); multiple_bundles;
2688
// Integer ALU reg-imm operation
2689
pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{
2696
// Integer ALU reg-reg operation with condition code
2697
pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{
2706
// Integer ALU zero-reg operation
2707
pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{
2714
// Integer ALU zero-reg operation with condition code only
2715
pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{
2722
// Integer ALU reg-reg operation with condition code only
2723
pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2731
// Integer ALU reg-imm operation with condition code only
2732
pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{
2739
// Integer ALU reg-reg-zero operation with condition code only
2740
pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{
2748
// Integer ALU reg-imm-zero operation with condition code only
2749
pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{
2756
// Integer ALU reg-reg operation with condition code, src1 modified
2757
pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2766
pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{
2776
// Integer ALU operation
2777
pipe_class ialu_none(iRegI dst) %{
2783
// Integer ALU reg operation
2784
pipe_class ialu_reg(iRegI dst, iRegI src) %{
2785
single_instruction; may_have_no_code;
2791
// Integer ALU reg conditional operation
2792
// This instruction has a 1 cycle stall, and cannot execute
2793
// in the same cycle as the instruction setting the condition
2794
// code. We kludge this by pretending to read the condition code
2795
// 1 cycle earlier, and by marking the functional units as busy
2796
// for 2 cycles with the result available 1 cycle later than
2797
// is really the case.
2798
pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{
2802
cr : R(read); // This is really E, with a 1 cycle stall
2807
// Integer ALU reg operation
2808
pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{
2809
single_instruction; may_have_no_code;
2814
pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{
2815
single_instruction; may_have_no_code;
2821
// Two integer ALU reg operations
2822
pipe_class ialu_reg_2(iRegL dst, iRegL src) %{
2823
instruction_count(2);
2830
// Two integer ALU reg operations
2831
pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{
2832
instruction_count(2); may_have_no_code;
2839
// Integer ALU imm operation
2840
pipe_class ialu_imm(iRegI dst) %{
2846
pipe_class ialu_imm_n(iRegI dst) %{
2852
// Integer ALU reg-reg with carry operation
2853
pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{
2861
// Integer ALU cc operation
2862
pipe_class ialu_cc(iRegI dst, flagsReg cc) %{
2869
// Integer ALU cc / second IALU operation
2870
pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{
2871
instruction_count(1); multiple_bundles;
2877
// Integer ALU cc / second IALU operation
2878
pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{
2879
instruction_count(1); multiple_bundles;
2886
// Integer ALU hi-lo-reg operation
2887
pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{
2888
instruction_count(1); multiple_bundles;
2894
pipe_class loadConL( iRegL dst, immL src ) %{
2895
instruction_count(2); multiple_bundles;
2902
pipe_class loadConP( iRegP dst, immP src ) %{
2903
instruction_count(0); multiple_bundles;
2907
// Long Constant small
2908
pipe_class loadConLlo( iRegL dst, immL src ) %{
2909
instruction_count(2);
2915
// [PHH] This is wrong for 64-bit. See LdImmF/D.
2916
pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{
2917
instruction_count(1); multiple_bundles;
2924
// Integer ALU nop operation
2925
pipe_class ialu_nop() %{
2930
// Integer ALU nop operation
2931
pipe_class ialu_nop_A0() %{
2936
// Integer ALU nop operation
2937
pipe_class ialu_nop_A1() %{
2942
// Integer Multiply reg-reg operation
2943
pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2951
pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2959
// Integer Divide reg-reg
2960
pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{
2961
instruction_count(1); multiple_bundles;
2971
pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2978
// Floating Point Add Float
2979
pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{
2987
// Floating Point Add Double
2988
pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{
2996
// Floating Point Conditional Move based on integer flags
2997
pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{
3006
// Floating Point Conditional Move based on integer flags
3007
pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{
3016
// Floating Point Multiply Float
3017
pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{
3025
// Floating Point Multiply Double
3026
pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{
3034
// Floating Point Divide Float
3035
pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{
3044
// Floating Point Divide Double
3045
pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{
3054
// Floating Point Move/Negate/Abs Float
3055
pipe_class faddF_reg(regF dst, regF src) %{
3062
// Floating Point Move/Negate/Abs Double
3063
pipe_class faddD_reg(regD dst, regD src) %{
3070
// Floating Point Convert F->D
3071
pipe_class fcvtF2D(regD dst, regF src) %{
3078
// Floating Point Convert I->D
3079
pipe_class fcvtI2D(regD dst, regF src) %{
3086
// Floating Point Convert LHi->D
3087
pipe_class fcvtLHi2D(regD dst, regD src) %{
3094
// Floating Point Convert L->D
3095
pipe_class fcvtL2D(regD dst, iRegL src) %{
3102
// Floating Point Convert L->F
3103
pipe_class fcvtL2F(regF dst, iRegL src) %{
3110
// Floating Point Convert D->F
3111
pipe_class fcvtD2F(regD dst, regF src) %{
3118
// Floating Point Convert I->L
3119
pipe_class fcvtI2L(regD dst, regF src) %{
3126
// Floating Point Convert D->F
3127
pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{
3128
instruction_count(1); multiple_bundles;
3134
// Floating Point Convert D->L
3135
pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{
3136
instruction_count(1); multiple_bundles;
3142
// Floating Point Convert F->I
3143
pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{
3144
instruction_count(1); multiple_bundles;
3150
// Floating Point Convert F->L
3151
pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{
3152
instruction_count(1); multiple_bundles;
3158
// Floating Point Convert I->F
3159
pipe_class fcvtI2F(regF dst, regF src) %{
3166
// Floating Point Compare
3167
pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{
3175
// Floating Point Compare
3176
pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{
3185
pipe_class fadd_nop() %{
3190
// Integer Store to Memory
3191
pipe_class istore_mem_reg(memoryI mem, iRegI src) %{
3198
// Integer Store to Memory
3199
pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{
3207
pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{
3215
pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{
3222
pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{
3223
instruction_count(1);
3230
pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{
3236
// Integer Load (when sign bit propagation not needed)
3237
pipe_class iload_mem(iRegI dst, memoryI mem) %{
3244
// Integer Load (when sign bit propagation or masking is needed)
3245
pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{
3253
pipe_class floadF_mem(regF dst, memoryF mem) %{
3261
pipe_class floadD_mem(regD dst, memoryD mem) %{
3262
instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case
3269
pipe_class mem_nop() %{
3274
pipe_class sethi(iRegP dst, immI src) %{
3280
pipe_class loadPollP(iRegP poll) %{
3286
pipe_class br(Universe br, label labl) %{
3287
single_instruction_with_delay_slot;
3291
pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
3292
single_instruction_with_delay_slot;
3297
pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
3298
single_instruction_with_delay_slot;
3304
pipe_class br_nop() %{
3309
pipe_class simple_call(method meth) %{
3310
instruction_count(2); multiple_bundles; force_serialization;
3317
pipe_class compiled_call(method meth) %{
3318
instruction_count(1); multiple_bundles; force_serialization;
3323
pipe_class call(method meth) %{
3324
instruction_count(0); multiple_bundles; force_serialization;
3328
pipe_class tail_call(Universe ignore, label labl) %{
3329
single_instruction; has_delay_slot;
3335
pipe_class ret(Universe ignore) %{
3336
single_instruction; has_delay_slot;
3341
// The real do-nothing guy
3342
pipe_class empty( ) %{
3343
instruction_count(0);
3346
pipe_class long_memory_op() %{
3347
instruction_count(0); multiple_bundles; force_serialization;
3353
pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{
3361
// Convert FPU flags into +1,0,-1
3362
pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{
3371
// Compare for p < q, and conditionally add y
3372
pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
3379
// Perform a compare, then move conditionally in a branch delay slot.
3380
pipe_class min_max( iRegI src2, iRegI srcdst ) %{
3387
// Define the class for the Nop node
3394
//----------INSTRUCTIONS-------------------------------------------------------
3396
//------------Special Nop instructions for bundling - no match rules-----------
3397
// Nop using the A0 functional unit
3399
ins_pipe(ialu_nop_A0);
3402
// Nop using the A1 functional unit
3403
instruct Nop_A1( ) %{
3404
ins_pipe(ialu_nop_A1);
3407
// Nop using the memory functional unit
3408
instruct Nop_MS( ) %{
3412
// Nop using the floating add functional unit
3413
instruct Nop_FA( ) %{
3417
// Nop using the branch functional unit
3418
instruct Nop_BR( ) %{
3422
//----------Load/Store/Move Instructions---------------------------------------
3423
//----------Load Instructions--------------------------------------------------
3424
// Load Byte (8bit signed)
3425
instruct loadB(iRegI dst, memoryB mem) %{
3426
match(Set dst (LoadB mem));
3427
ins_cost(MEMORY_REF_COST);
3430
format %{ "LDRSB $dst,$mem\t! byte -> int" %}
3432
__ ldrsb($dst$$Register, $mem$$Address);
3434
ins_pipe(iload_mask_mem);
3437
// Load Byte (8bit signed) into a Long Register
3438
instruct loadB2L(iRegL dst, memoryB mem) %{
3439
match(Set dst (ConvI2L (LoadB mem)));
3440
ins_cost(MEMORY_REF_COST);
3443
format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t"
3444
"ASR $dst.hi,$dst.lo,31" %}
3446
__ ldrsb($dst$$Register, $mem$$Address);
3447
__ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3449
ins_pipe(iload_mask_mem);
3452
// Load Unsigned Byte (8bit UNsigned) into an int reg
3453
instruct loadUB(iRegI dst, memoryB mem) %{
3454
match(Set dst (LoadUB mem));
3455
ins_cost(MEMORY_REF_COST);
3458
format %{ "LDRB $dst,$mem\t! ubyte -> int" %}
3460
__ ldrb($dst$$Register, $mem$$Address);
3462
ins_pipe(iload_mem);
3465
// Load Unsigned Byte (8bit UNsigned) into a Long Register
3466
instruct loadUB2L(iRegL dst, memoryB mem) %{
3467
match(Set dst (ConvI2L (LoadUB mem)));
3468
ins_cost(MEMORY_REF_COST);
3471
format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t"
3474
__ ldrb($dst$$Register, $mem$$Address);
3475
__ mov($dst$$Register->successor(), 0);
3477
ins_pipe(iload_mem);
3480
// Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register
3481
instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{
3482
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
3484
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3486
format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t"
3488
"AND $dst.lo,$dst.lo,$mask" %}
3490
__ ldrb($dst$$Register, $mem$$Address);
3491
__ mov($dst$$Register->successor(), 0);
3492
__ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
3494
ins_pipe(iload_mem);
3497
// Load Short (16bit signed)
3499
instruct loadS(iRegI dst, memoryS mem) %{
3500
match(Set dst (LoadS mem));
3501
ins_cost(MEMORY_REF_COST);
3504
format %{ "LDRSH $dst,$mem\t! short" %}
3506
__ ldrsh($dst$$Register, $mem$$Address);
3508
ins_pipe(iload_mask_mem);
3511
// Load Short (16 bit signed) to Byte (8 bit signed)
3512
instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3513
match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
3514
ins_cost(MEMORY_REF_COST);
3518
format %{ "LDRSB $dst,$mem\t! short -> byte" %}
3520
__ ldrsb($dst$$Register, $mem$$Address);
3522
ins_pipe(iload_mask_mem);
3525
// Load Short (16bit signed) into a Long Register
3526
instruct loadS2L(iRegL dst, memoryS mem) %{
3527
match(Set dst (ConvI2L (LoadS mem)));
3528
ins_cost(MEMORY_REF_COST);
3531
format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t"
3532
"ASR $dst.hi,$dst.lo,31" %}
3534
__ ldrsh($dst$$Register, $mem$$Address);
3535
__ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3537
ins_pipe(iload_mask_mem);
3540
// Load Unsigned Short/Char (16bit UNsigned)
3543
instruct loadUS(iRegI dst, memoryS mem) %{
3544
match(Set dst (LoadUS mem));
3545
ins_cost(MEMORY_REF_COST);
3548
format %{ "LDRH $dst,$mem\t! ushort/char" %}
3550
__ ldrh($dst$$Register, $mem$$Address);
3552
ins_pipe(iload_mem);
3555
// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
3556
instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{
3557
match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
3558
ins_cost(MEMORY_REF_COST);
3561
format %{ "LDRSB $dst,$mem\t! ushort -> byte" %}
3563
__ ldrsb($dst$$Register, $mem$$Address);
3565
ins_pipe(iload_mask_mem);
3568
// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
3569
instruct loadUS2L(iRegL dst, memoryS mem) %{
3570
match(Set dst (ConvI2L (LoadUS mem)));
3571
ins_cost(MEMORY_REF_COST);
3574
format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t"
3577
__ ldrh($dst$$Register, $mem$$Address);
3578
__ mov($dst$$Register->successor(), 0);
3580
ins_pipe(iload_mem);
3583
// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register
3584
instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3585
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3586
ins_cost(MEMORY_REF_COST);
3589
format %{ "LDRB $dst.lo,$mem\t! \n\t"
3592
__ ldrb($dst$$Register, $mem$$Address);
3593
__ mov($dst$$Register->successor(), 0);
3595
ins_pipe(iload_mem);
3598
// Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register
3599
instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{
3600
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3601
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3604
format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t"
3605
"MOV $dst.hi, 0\n\t"
3606
"AND $dst,$dst,$mask" %}
3608
__ ldrh($dst$$Register, $mem$$Address);
3609
__ mov($dst$$Register->successor(), 0);
3610
__ andr($dst$$Register, $dst$$Register, $mask$$constant);
3612
ins_pipe(iload_mem);
3618
instruct loadI(iRegI dst, memoryI mem) %{
3619
match(Set dst (LoadI mem));
3620
ins_cost(MEMORY_REF_COST);
3623
format %{ "ldr_s32 $dst,$mem\t! int" %}
3625
__ ldr_s32($dst$$Register, $mem$$Address);
3627
ins_pipe(iload_mem);
3630
// Load Integer to Byte (8 bit signed)
3631
instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3632
match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
3633
ins_cost(MEMORY_REF_COST);
3637
format %{ "LDRSB $dst,$mem\t! int -> byte" %}
3639
__ ldrsb($dst$$Register, $mem$$Address);
3641
ins_pipe(iload_mask_mem);
3644
// Load Integer to Unsigned Byte (8 bit UNsigned)
3645
instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{
3646
match(Set dst (AndI (LoadI mem) mask));
3647
ins_cost(MEMORY_REF_COST);
3651
format %{ "LDRB $dst,$mem\t! int -> ubyte" %}
3653
__ ldrb($dst$$Register, $mem$$Address);
3655
ins_pipe(iload_mask_mem);
3658
// Load Integer to Short (16 bit signed)
3659
instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{
3660
match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
3661
ins_cost(MEMORY_REF_COST);
3664
format %{ "LDRSH $dst,$mem\t! int -> short" %}
3666
__ ldrsh($dst$$Register, $mem$$Address);
3668
ins_pipe(iload_mask_mem);
3671
// Load Integer to Unsigned Short (16 bit UNsigned)
3672
instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{
3673
match(Set dst (AndI (LoadI mem) mask));
3674
ins_cost(MEMORY_REF_COST);
3677
format %{ "LDRH $dst,$mem\t! int -> ushort/char" %}
3679
__ ldrh($dst$$Register, $mem$$Address);
3681
ins_pipe(iload_mask_mem);
3684
// Load Integer into a Long Register
3685
instruct loadI2L(iRegL dst, memoryI mem) %{
3686
match(Set dst (ConvI2L (LoadI mem)));
3687
ins_cost(MEMORY_REF_COST);
3690
format %{ "LDR $dst.lo,$mem\t! int -> long\n\t"
3691
"ASR $dst.hi,$dst.lo,31\t! int->long" %}
3693
__ ldr($dst$$Register, $mem$$Address);
3694
__ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3696
ins_pipe(iload_mask_mem);
3699
// Load Integer with mask 0xFF into a Long Register
3700
instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3701
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3702
ins_cost(MEMORY_REF_COST);
3705
format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t"
3708
__ ldrb($dst$$Register, $mem$$Address);
3709
__ mov($dst$$Register->successor(), 0);
3711
ins_pipe(iload_mem);
3714
// Load Integer with mask 0xFFFF into a Long Register
3715
instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{
3716
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3717
ins_cost(MEMORY_REF_COST);
3720
format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t"
3723
__ ldrh($dst$$Register, $mem$$Address);
3724
__ mov($dst$$Register->successor(), 0);
3726
ins_pipe(iload_mask_mem);
3729
// Load Integer with a 31-bit immediate mask into a Long Register
3730
instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{
3731
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3732
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3735
format %{ "LDR $dst.lo,$mem\t! int -> long\n\t"
3736
"MOV $dst.hi, 0\n\t"
3737
"AND $dst,$dst,$mask" %}
3740
__ ldr($dst$$Register, $mem$$Address);
3741
__ mov($dst$$Register->successor(), 0);
3742
__ andr($dst$$Register, $dst$$Register, $mask$$constant);
3744
ins_pipe(iload_mem);
3747
// Load Integer with a 31-bit mask into a Long Register
3748
// FIXME: use iRegI mask, remove tmp?
3749
instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{
3750
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3751
effect(TEMP dst, TEMP tmp);
3753
ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST);
3755
format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t"
3756
"MOV $dst.hi, 0\n\t"
3757
"MOV_SLOW $tmp,$mask\n\t"
3758
"AND $dst,$tmp,$dst" %}
3760
__ ldr($dst$$Register, $mem$$Address);
3761
__ mov($dst$$Register->successor(), 0);
3762
__ mov_slow($tmp$$Register, $mask$$constant);
3763
__ andr($dst$$Register, $dst$$Register, $tmp$$Register);
3765
ins_pipe(iload_mem);
3768
// Load Unsigned Integer into a Long Register
3769
instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{
3770
match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
3771
ins_cost(MEMORY_REF_COST);
3774
format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t"
3777
__ ldr($dst$$Register, $mem$$Address);
3778
__ mov($dst$$Register->successor(), 0);
3780
ins_pipe(iload_mem);
3786
instruct loadL(iRegLd dst, memoryL mem ) %{
3787
predicate(!((LoadLNode*)n)->require_atomic_access());
3788
match(Set dst (LoadL mem));
3790
ins_cost(MEMORY_REF_COST);
3793
format %{ "ldr_64 $dst,$mem\t! long" %}
3795
__ ldr_64($dst$$Register, $mem$$Address);
3797
ins_pipe(iload_mem);
3800
instruct loadL_2instr(iRegL dst, memorylong mem ) %{
3801
predicate(!((LoadLNode*)n)->require_atomic_access());
3802
match(Set dst (LoadL mem));
3803
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
3806
format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3807
"LDR $dst.hi,$mem+4 or $mem" %}
3809
Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3810
Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3812
if ($dst$$Register == reg_to_register_object($mem$$base)) {
3813
__ ldr($dst$$Register->successor(), Amemhi);
3814
__ ldr($dst$$Register, Amemlo);
3816
__ ldr($dst$$Register, Amemlo);
3817
__ ldr($dst$$Register->successor(), Amemhi);
3820
ins_pipe(iload_mem);
3823
instruct loadL_volatile(iRegL dst, indirect mem ) %{
3824
predicate(((LoadLNode*)n)->require_atomic_access());
3825
match(Set dst (LoadL mem));
3826
ins_cost(MEMORY_REF_COST);
3829
format %{ "LDMIA $dst,$mem\t! long" %}
3831
// FIXME: why is ldmia considered atomic? Should be ldrexd
3832
RegisterSet set($dst$$Register);
3833
set = set | reg_to_register_object($dst$$reg + 1);
3834
__ ldmia(reg_to_register_object($mem$$base), set);
3836
ins_pipe(iload_mem);
3839
instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{
3840
predicate(((LoadLNode*)n)->require_atomic_access());
3841
match(Set dst (LoadL mem));
3842
ins_cost(MEMORY_REF_COST);
3845
format %{ "FLDD S14, $mem"
3846
"FMRRD $dst, S14\t! long \n't" %}
3848
__ fldd(S14, $mem$$Address);
3849
__ fmrrd($dst$$Register, $dst$$Register->successor(), S14);
3851
ins_pipe(iload_mem);
3854
instruct loadL_unaligned(iRegL dst, memorylong mem ) %{
3855
match(Set dst (LoadL_unaligned mem));
3856
ins_cost(MEMORY_REF_COST);
3859
format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3860
"LDR $dst.hi,$mem+4" %}
3862
Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3863
Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3865
if ($dst$$Register == reg_to_register_object($mem$$base)) {
3866
__ ldr($dst$$Register->successor(), Amemhi);
3867
__ ldr($dst$$Register, Amemlo);
3869
__ ldr($dst$$Register, Amemlo);
3870
__ ldr($dst$$Register->successor(), Amemhi);
3873
ins_pipe(iload_mem);
3877
instruct loadRange(iRegI dst, memoryI mem) %{
3878
match(Set dst (LoadRange mem));
3879
ins_cost(MEMORY_REF_COST);
3882
format %{ "LDR_u32 $dst,$mem\t! range" %}
3884
__ ldr_u32($dst$$Register, $mem$$Address);
3886
ins_pipe(iload_mem);
3892
instruct loadP(iRegP dst, memoryP mem) %{
3893
match(Set dst (LoadP mem));
3894
ins_cost(MEMORY_REF_COST);
3897
format %{ "LDR $dst,$mem\t! ptr" %}
3899
__ ldr($dst$$Register, $mem$$Address);
3901
ins_pipe(iload_mem);
3906
//instruct loadSP(iRegP dst, memoryP mem) %{
3907
instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{
3908
match(Set dst (LoadP mem));
3910
ins_cost(MEMORY_REF_COST+1);
3913
format %{ "LDR $tmp,$mem\t! ptr\n\t"
3914
"MOV $dst,$tmp\t! ptr" %}
3916
__ ldr($tmp$$Register, $mem$$Address);
3917
__ mov($dst$$Register, $tmp$$Register);
3919
ins_pipe(iload_mem);
3924
// Load Compressed Pointer
3926
// XXX This variant shouldn't be necessary if 6217251 is implemented
3927
instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
3928
match(Set dst (LoadN (AddP mem off)));
3929
ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
3933
format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %}
3935
Register base = reg_to_register_object($mem$$base);
3936
__ add($tmp$$Register, base, $off$$constant);
3937
Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3938
__ ldr_u32($dst$$Register, nmem);
3940
ins_pipe(iload_mem);
3943
instruct loadN(iRegN dst, memoryI mem) %{
3944
match(Set dst (LoadN mem));
3945
ins_cost(MEMORY_REF_COST);
3948
format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %}
3950
__ ldr_u32($dst$$Register, $mem$$Address);
3952
ins_pipe(iload_mem);
3956
// Load Klass Pointer
3957
instruct loadKlass(iRegP dst, memoryI mem) %{
3958
match(Set dst (LoadKlass mem));
3959
ins_cost(MEMORY_REF_COST);
3962
format %{ "LDR $dst,$mem\t! klass ptr" %}
3964
__ ldr($dst$$Register, $mem$$Address);
3966
ins_pipe(iload_mem);
3970
// Load narrow Klass Pointer
3971
instruct loadNKlass(iRegN dst, memoryI mem) %{
3972
match(Set dst (LoadNKlass mem));
3973
ins_cost(MEMORY_REF_COST);
3976
format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %}
3978
__ ldr_u32($dst$$Register, $mem$$Address);
3980
ins_pipe(iload_mem);
3985
instruct loadD(regD dst, memoryD mem) %{
3986
match(Set dst (LoadD mem));
3987
ins_cost(MEMORY_REF_COST);
3990
// FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees
3991
// only LDREXD and STREXD are 64-bit single-copy atomic
3992
format %{ "FLDD $dst,$mem" %}
3994
__ ldr_double($dst$$FloatRegister, $mem$$Address);
3996
ins_pipe(floadD_mem);
3999
// Load Double - UNaligned
4000
instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{
4001
match(Set dst (LoadD_unaligned mem));
4002
ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
4004
format %{ "FLDS $dst.lo,$mem\t! misaligned double\n"
4005
"\tFLDS $dst.hi,$mem+4\t!" %}
4007
Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4008
Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4009
__ flds($dst$$FloatRegister, Amemlo);
4010
__ flds($dst$$FloatRegister->successor(), Amemhi);
4012
ins_pipe(iload_mem);
4016
instruct loadF(regF dst, memoryF mem) %{
4017
match(Set dst (LoadF mem));
4019
ins_cost(MEMORY_REF_COST);
4021
format %{ "FLDS $dst,$mem" %}
4023
__ ldr_float($dst$$FloatRegister, $mem$$Address);
4025
ins_pipe(floadF_mem);
4030
instruct loadConI( iRegI dst, immI src ) %{
4032
ins_cost(DEFAULT_COST * 3/2);
4033
format %{ "MOV_SLOW $dst, $src" %}
4035
__ mov_slow($dst$$Register, $src$$constant);
4037
ins_pipe(ialu_hi_lo_reg);
4040
instruct loadConIMov( iRegI dst, immIMov src ) %{
4043
format %{ "MOV $dst, $src" %}
4045
__ mov($dst$$Register, $src$$constant);
4050
instruct loadConIMovn( iRegI dst, immIRotn src ) %{
4053
format %{ "MVN $dst, ~$src" %}
4055
__ mvn($dst$$Register, ~$src$$constant);
4057
ins_pipe(ialu_imm_n);
4060
instruct loadConI16( iRegI dst, immI16 src ) %{
4063
format %{ "MOVW $dst, $src" %}
4065
__ movw($dst$$Register, $src$$constant);
4067
ins_pipe(ialu_imm_n);
4070
instruct loadConP(iRegP dst, immP src) %{
4072
ins_cost(DEFAULT_COST * 3/2);
4073
format %{ "MOV_SLOW $dst,$src\t!ptr" %}
4075
relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc();
4076
intptr_t val = $src$$constant;
4077
if (constant_reloc == relocInfo::oop_type) {
4078
__ mov_oop($dst$$Register, (jobject)val);
4079
} else if (constant_reloc == relocInfo::metadata_type) {
4080
__ mov_metadata($dst$$Register, (Metadata*)val);
4082
__ mov_slow($dst$$Register, val);
4089
instruct loadConL(iRegL dst, immL src) %{
4091
ins_cost(DEFAULT_COST * 4);
4092
format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t"
4093
"MOV_SLOW $dst.hi, $src >> 32" %}
4095
__ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL);
4096
__ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32);
4101
instruct loadConL16( iRegL dst, immL16 src ) %{
4103
ins_cost(DEFAULT_COST * 2);
4106
format %{ "MOVW $dst.lo, $src \n\t"
4107
"MOVW $dst.hi, 0 \n\t" %}
4109
__ movw($dst$$Register, $src$$constant);
4110
__ movw($dst$$Register->successor(), 0);
4115
instruct loadConF_imm8(regF dst, imm8F src) %{
4117
ins_cost(DEFAULT_COST);
4120
format %{ "FCONSTS $dst, $src"%}
4123
__ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8());
4125
ins_pipe(loadConFD); // FIXME
4129
instruct loadConF(regF dst, immF src, iRegI tmp) %{
4131
ins_cost(DEFAULT_COST * 2);
4135
format %{ "MOV_SLOW $tmp, $src\n\t"
4139
// FIXME revisit once 6961697 is in
4144
v.f = $src$$constant;
4145
__ mov_slow($tmp$$Register, v.i);
4146
__ fmsr($dst$$FloatRegister, $tmp$$Register);
4148
ins_pipe(loadConFD); // FIXME
4151
instruct loadConD_imm8(regD dst, imm8D src) %{
4153
ins_cost(DEFAULT_COST);
4156
format %{ "FCONSTD $dst, $src"%}
4159
__ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8());
4161
ins_pipe(loadConFD); // FIXME
4164
instruct loadConD(regD dst, immD src, iRegP tmp) %{
4167
ins_cost(MEMORY_REF_COST);
4168
format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %}
4171
Register r = $constanttablebase;
4172
int offset = $constantoffset($src);
4173
if (!is_memoryD(offset)) { // can't use a predicate
4174
// in load constant instructs
4175
__ add_slow($tmp$$Register, r, offset);
4179
__ ldr_double($dst$$FloatRegister, Address(r, offset));
4181
ins_pipe(loadConFD);
4184
// Prefetch instructions.
4185
// Must be safe to execute with invalid address (cannot fault).
4187
instruct prefetchAlloc_mp( memoryP mem ) %{
4188
predicate(VM_Version::has_multiprocessing_extensions());
4189
match( PrefetchAllocation mem );
4190
ins_cost(MEMORY_REF_COST);
4193
format %{ "PLDW $mem\t! Prefetch allocation" %}
4195
__ pldw($mem$$Address);
4197
ins_pipe(iload_mem);
4200
instruct prefetchAlloc_sp( memoryP mem ) %{
4201
predicate(!VM_Version::has_multiprocessing_extensions());
4202
match( PrefetchAllocation mem );
4203
ins_cost(MEMORY_REF_COST);
4206
format %{ "PLD $mem\t! Prefetch allocation" %}
4208
__ pld($mem$$Address);
4210
ins_pipe(iload_mem);
4214
//----------Store Instructions-------------------------------------------------
4216
instruct storeB(memoryB mem, store_RegI src) %{
4217
match(Set mem (StoreB mem src));
4218
ins_cost(MEMORY_REF_COST);
4221
format %{ "STRB $src,$mem\t! byte" %}
4223
__ strb($src$$Register, $mem$$Address);
4225
ins_pipe(istore_mem_reg);
4228
instruct storeCM(memoryB mem, store_RegI src) %{
4229
match(Set mem (StoreCM mem src));
4230
ins_cost(MEMORY_REF_COST);
4233
format %{ "STRB $src,$mem\t! CMS card-mark byte" %}
4235
__ strb($src$$Register, $mem$$Address);
4237
ins_pipe(istore_mem_reg);
4243
instruct storeC(memoryS mem, store_RegI src) %{
4244
match(Set mem (StoreC mem src));
4245
ins_cost(MEMORY_REF_COST);
4248
format %{ "STRH $src,$mem\t! short" %}
4250
__ strh($src$$Register, $mem$$Address);
4252
ins_pipe(istore_mem_reg);
4258
instruct storeI(memoryI mem, store_RegI src) %{
4259
match(Set mem (StoreI mem src));
4260
ins_cost(MEMORY_REF_COST);
4263
format %{ "str_32 $src,$mem" %}
4265
__ str_32($src$$Register, $mem$$Address);
4267
ins_pipe(istore_mem_reg);
4273
instruct storeL(memoryL mem, store_RegLd src) %{
4274
predicate(!((StoreLNode*)n)->require_atomic_access());
4275
match(Set mem (StoreL mem src));
4276
ins_cost(MEMORY_REF_COST);
4279
format %{ "str_64 $src,$mem\t! long\n\t" %}
4282
__ str_64($src$$Register, $mem$$Address);
4284
ins_pipe(istore_mem_reg);
4287
instruct storeL_2instr(memorylong mem, iRegL src) %{
4288
predicate(!((StoreLNode*)n)->require_atomic_access());
4289
match(Set mem (StoreL mem src));
4290
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4293
format %{ "STR $src.lo,$mem\t! long\n\t"
4294
"STR $src.hi,$mem+4" %}
4297
Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4298
Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4299
__ str($src$$Register, Amemlo);
4300
__ str($src$$Register->successor(), Amemhi);
4302
ins_pipe(istore_mem_reg);
4305
instruct storeL_volatile(indirect mem, iRegL src) %{
4306
predicate(((StoreLNode*)n)->require_atomic_access());
4307
match(Set mem (StoreL mem src));
4308
ins_cost(MEMORY_REF_COST);
4310
format %{ "STMIA $src,$mem\t! long" %}
4312
// FIXME: why is stmia considered atomic? Should be strexd
4313
RegisterSet set($src$$Register);
4314
set = set | reg_to_register_object($src$$reg + 1);
4315
__ stmia(reg_to_register_object($mem$$base), set);
4317
ins_pipe(istore_mem_reg);
4320
instruct storeL_volatile_fp(memoryD mem, iRegL src) %{
4321
predicate(((StoreLNode*)n)->require_atomic_access());
4322
match(Set mem (StoreL mem src));
4323
ins_cost(MEMORY_REF_COST);
4325
format %{ "FMDRR S14, $src\t! long \n\t"
4328
__ fmdrr(S14, $src$$Register, $src$$Register->successor());
4329
__ fstd(S14, $mem$$Address);
4331
ins_pipe(istore_mem_reg);
4336
//instruct movSP(sp_ptr_RegP dst, SPRegP src) %{
4337
//instruct movSP(iRegP dst, SPRegP src) %{
4338
instruct movSP(store_ptr_RegP dst, SPRegP src) %{
4340
//predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
4341
ins_cost(MEMORY_REF_COST);
4344
format %{ "MOV $dst,$src\t! SP ptr\n\t" %}
4346
assert(false, "XXX1 got here");
4347
__ mov($dst$$Register, SP);
4348
__ mov($dst$$Register, $src$$Register);
4358
instruct storeP(memoryP mem, store_ptr_RegP src) %{
4359
match(Set mem (StoreP mem src));
4360
ins_cost(MEMORY_REF_COST);
4363
format %{ "STR $src,$mem\t! ptr" %}
4365
__ str($src$$Register, $mem$$Address);
4367
ins_pipe(istore_mem_spORreg);
4372
// Store Compressed Pointer
4375
instruct storeN(memoryI mem, store_RegN src) %{
4376
match(Set mem (StoreN mem src));
4377
ins_cost(MEMORY_REF_COST);
4380
format %{ "str_32 $src,$mem\t! compressed ptr" %}
4382
__ str_32($src$$Register, $mem$$Address);
4384
ins_pipe(istore_mem_reg);
4388
// Store Compressed Klass Pointer
4389
instruct storeNKlass(memoryI mem, store_RegN src) %{
4390
match(Set mem (StoreNKlass mem src));
4391
ins_cost(MEMORY_REF_COST);
4394
format %{ "str_32 $src,$mem\t! compressed klass ptr" %}
4396
__ str_32($src$$Register, $mem$$Address);
4398
ins_pipe(istore_mem_reg);
4405
instruct storeD(memoryD mem, regD src) %{
4406
match(Set mem (StoreD mem src));
4407
ins_cost(MEMORY_REF_COST);
4410
// FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees
4411
// only LDREXD and STREXD are 64-bit single-copy atomic
4412
format %{ "FSTD $src,$mem" %}
4414
__ str_double($src$$FloatRegister, $mem$$Address);
4416
ins_pipe(fstoreD_mem_reg);
4423
instruct storeF( memoryF mem, regF src) %{
4424
match(Set mem (StoreF mem src));
4425
ins_cost(MEMORY_REF_COST);
4428
format %{ "FSTS $src,$mem" %}
4430
__ str_float($src$$FloatRegister, $mem$$Address);
4432
ins_pipe(fstoreF_mem_reg);
4436
//----------MemBar Instructions-----------------------------------------------
4437
// Memory barrier flavors
4439
// pattern-match out unnecessary membars
4440
instruct membar_storestore() %{
4441
match(MemBarStoreStore);
4442
match(StoreStoreFence);
4443
ins_cost(4*MEMORY_REF_COST);
4446
format %{ "MEMBAR-storestore" %}
4448
__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
4450
ins_pipe(long_memory_op);
4453
instruct membar_acquire() %{
4454
match(MemBarAcquire);
4456
ins_cost(4*MEMORY_REF_COST);
4459
format %{ "MEMBAR-acquire" %}
4461
__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg);
4463
ins_pipe(long_memory_op);
4466
instruct membar_acquire_lock() %{
4467
match(MemBarAcquireLock);
4471
format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %}
4476
instruct membar_release() %{
4477
match(MemBarRelease);
4479
ins_cost(4*MEMORY_REF_COST);
4482
format %{ "MEMBAR-release" %}
4484
__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg);
4486
ins_pipe(long_memory_op);
4489
instruct membar_release_lock() %{
4490
match(MemBarReleaseLock);
4494
format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %}
4499
instruct membar_volatile() %{
4500
match(MemBarVolatile);
4501
ins_cost(4*MEMORY_REF_COST);
4504
format %{ "MEMBAR-volatile" %}
4506
__ membar(MacroAssembler::StoreLoad, noreg);
4508
ins_pipe(long_memory_op);
4511
instruct unnecessary_membar_volatile() %{
4512
match(MemBarVolatile);
4513
predicate(Matcher::post_store_load_barrier(n));
4517
format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %}
4522
//----------Register Move Instructions-----------------------------------------
4523
// instruct roundDouble_nop(regD dst) %{
4524
// match(Set dst (RoundDouble dst));
4529
// instruct roundFloat_nop(regF dst) %{
4530
// match(Set dst (RoundFloat dst));
4536
// Cast Index to Pointer for unsafe natives
4537
instruct castX2P(iRegX src, iRegP dst) %{
4538
match(Set dst (CastX2P src));
4540
format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %}
4542
if ($dst$$Register != $src$$Register) {
4543
__ mov($dst$$Register, $src$$Register);
4549
// Cast Pointer to Index for unsafe natives
4550
instruct castP2X(iRegP src, iRegX dst) %{
4551
match(Set dst (CastP2X src));
4553
format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %}
4555
if ($dst$$Register != $src$$Register) {
4556
__ mov($dst$$Register, $src$$Register);
4562
//----------Conditional Move---------------------------------------------------
4564
instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{
4565
match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4568
format %{ "MOV$cmp $dst,$src\t! int" %}
4570
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4576
instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{
4577
match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4580
format %{ "MOV$cmp $dst,$src" %}
4582
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4587
instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{
4588
match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4591
format %{ "MOVw$cmp $dst,$src" %}
4593
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4598
instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{
4599
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4602
format %{ "MOV$cmp $dst,$src" %}
4604
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4610
instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{
4611
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4614
format %{ "MOV$cmp $dst,$src" %}
4616
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4621
instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{
4622
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4625
format %{ "MOVw$cmp $dst,$src" %}
4627
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4632
instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{
4633
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4634
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4635
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4636
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4637
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4640
format %{ "MOV$cmp $dst,$src" %}
4642
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4647
instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{
4648
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4649
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4650
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4651
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4652
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4655
format %{ "MOV$cmp $dst,$src" %}
4657
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4662
instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{
4663
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4664
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4665
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4666
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4667
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4670
format %{ "MOVW$cmp $dst,$src" %}
4672
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4677
instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
4678
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4681
format %{ "MOV$cmp $dst,$src" %}
4683
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4688
instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{
4689
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4692
format %{ "MOV$cmp $dst,$src" %}
4694
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4699
instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{
4700
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4703
format %{ "MOVW$cmp $dst,$src" %}
4705
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4711
instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
4712
match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4715
format %{ "MOV$cmp $dst,$src" %}
4717
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4722
instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{
4723
match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4726
format %{ "MOV$cmp $dst,$src" %}
4728
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4733
// This instruction also works with CmpN so we don't need cmovPN_reg.
4734
instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
4735
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4739
format %{ "MOV$cmp $dst,$src\t! ptr" %}
4741
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4746
instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{
4747
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4748
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4749
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4750
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4751
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4755
format %{ "MOV$cmp $dst,$src\t! ptr" %}
4757
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4762
instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
4763
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4767
format %{ "MOV$cmp $dst,$src\t! ptr" %}
4769
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4774
instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
4775
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4779
format %{ "MOV$cmp $dst,$src\t! ptr" %}
4781
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4786
instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{
4787
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4788
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4789
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4790
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4791
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4795
format %{ "MOV$cmp $dst,$src\t! ptr" %}
4797
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4802
instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
4803
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4807
format %{ "MOV$cmp $dst,$src\t! ptr" %}
4809
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4816
instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{
4817
match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src)));
4820
format %{ "FCPYS$cmp $dst,$src" %}
4822
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4824
ins_pipe(int_conditional_float_move);
4827
instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
4828
match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4832
format %{ "FCPYS$cmp $dst,$src" %}
4834
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4836
ins_pipe(int_conditional_float_move);
4839
instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{
4840
match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4841
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4842
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4843
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4844
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4848
format %{ "FCPYS$cmp $dst,$src" %}
4850
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4852
ins_pipe(int_conditional_float_move);
4855
instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
4856
match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4860
format %{ "FCPYS$cmp $dst,$src" %}
4862
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4864
ins_pipe(int_conditional_float_move);
4868
instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{
4869
match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src)));
4872
format %{ "FCPYD$cmp $dst,$src" %}
4874
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4876
ins_pipe(int_conditional_double_move);
4879
instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
4880
match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4884
format %{ "FCPYD$cmp $dst,$src" %}
4886
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4888
ins_pipe(int_conditional_double_move);
4891
instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{
4892
match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4893
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4897
format %{ "FCPYD$cmp $dst,$src" %}
4899
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4901
ins_pipe(int_conditional_double_move);
4904
instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
4905
match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4909
format %{ "FCPYD$cmp $dst,$src" %}
4911
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4913
ins_pipe(int_conditional_double_move);
4917
instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{
4918
match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4922
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4923
"MOV$cmp $dst.hi,$src.hi" %}
4925
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4926
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4931
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
4932
// (hi($con$$constant), lo($con$$constant)) becomes
4933
instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{
4934
match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4938
format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4939
"MOV$cmp $dst.hi,0" %}
4941
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4942
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4947
instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{
4948
match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4952
format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4953
"MOV$cmp $dst.hi,0" %}
4955
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4956
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4961
instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
4962
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4966
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4967
"MOV$cmp $dst.hi,$src.hi" %}
4969
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4970
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4975
instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{
4976
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4977
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4978
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4979
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4980
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4984
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4985
"MOV$cmp $dst.hi,$src.hi" %}
4987
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4988
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4993
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
4994
// (hi($con$$constant), lo($con$$constant)) becomes
4995
instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{
4996
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5000
format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
5001
"MOV$cmp $dst.hi,0" %}
5003
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5004
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5009
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5010
// (hi($con$$constant), lo($con$$constant)) becomes
5011
instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{
5012
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5013
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5014
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5015
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5016
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5020
format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
5021
"MOV$cmp $dst.hi,0" %}
5023
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5024
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5029
instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{
5030
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5034
format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
5035
"MOV$cmp $dst.hi,0" %}
5037
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5038
__ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5043
instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{
5044
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5045
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5046
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5047
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5048
_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5052
format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
5053
"MOV$cmp $dst.hi,0" %}
5055
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5056
__ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5061
instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
5062
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5066
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
5067
"MOV$cmp $dst.hi,$src.hi" %}
5069
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5070
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5076
//----------OS and Locking Instructions----------------------------------------
5078
// This name is KNOWN by the ADLC and cannot be changed.
5079
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
5081
instruct tlsLoadP(RthreadRegP dst) %{
5082
match(Set dst (ThreadLocal));
5086
format %{ "! TLS is in $dst" %}
5087
ins_encode( /*empty encoding*/ );
5088
ins_pipe(ialu_none);
5091
instruct checkCastPP( iRegP dst ) %{
5092
match(Set dst (CheckCastPP dst));
5095
format %{ "! checkcastPP of $dst" %}
5096
ins_encode( /*empty encoding*/ );
5101
instruct castPP( iRegP dst ) %{
5102
match(Set dst (CastPP dst));
5103
format %{ "! castPP of $dst" %}
5104
ins_encode( /*empty encoding*/ );
5108
instruct castII( iRegI dst ) %{
5109
match(Set dst (CastII dst));
5110
format %{ "! castII of $dst" %}
5111
ins_encode( /*empty encoding*/ );
5116
instruct castLL( iRegL dst ) %{
5117
match(Set dst (CastLL dst));
5118
format %{ "! castLL of $dst" %}
5119
ins_encode( /*empty encoding*/ );
5124
instruct castFF( regF dst ) %{
5125
match(Set dst (CastFF dst));
5126
format %{ "! castFF of $dst" %}
5127
ins_encode( /*empty encoding*/ );
5132
instruct castDD( regD dst ) %{
5133
match(Set dst (CastDD dst));
5134
format %{ "! castDD of $dst" %}
5135
ins_encode( /*empty encoding*/ );
5140
instruct castVVD( vecD dst ) %{
5141
match(Set dst (CastVV dst));
5142
format %{ "! castVV of $dst" %}
5143
ins_encode( /*empty encoding*/ );
5148
instruct castVVX( vecX dst ) %{
5149
match(Set dst (CastVV dst));
5150
format %{ "! castVV of $dst" %}
5151
ins_encode( /*empty encoding*/ );
5157
//----------Arithmetic Instructions--------------------------------------------
5158
// Addition Instructions
5160
instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5161
match(Set dst (AddI src1 src2));
5164
format %{ "add_32 $dst,$src1,$src2\t! int" %}
5166
__ add_32($dst$$Register, $src1$$Register, $src2$$Register);
5168
ins_pipe(ialu_reg_reg);
5171
instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5172
match(Set dst (AddI (LShiftI src1 src2) src3));
5175
format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5177
__ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5179
ins_pipe(ialu_reg_reg);
5183
instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5184
match(Set dst (AddI (LShiftI src1 src2) src3));
5187
format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5189
__ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5191
ins_pipe(ialu_reg_reg);
5194
instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5195
match(Set dst (AddI (RShiftI src1 src2) src3));
5198
format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5200
__ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5202
ins_pipe(ialu_reg_reg);
5205
instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5206
match(Set dst (AddI (RShiftI src1 src2) src3));
5209
format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5211
__ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5213
ins_pipe(ialu_reg_reg);
5216
instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5217
match(Set dst (AddI (URShiftI src1 src2) src3));
5220
format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5222
__ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5224
ins_pipe(ialu_reg_reg);
5227
instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5228
match(Set dst (AddI (URShiftI src1 src2) src3));
5231
format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5233
__ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5235
ins_pipe(ialu_reg_reg);
5238
// Immediate Addition
5239
instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5240
match(Set dst (AddI src1 src2));
5243
format %{ "add_32 $dst,$src1,$src2\t! int" %}
5245
__ add_32($dst$$Register, $src1$$Register, $src2$$constant);
5247
ins_pipe(ialu_reg_imm);
5250
// Pointer Register Addition
5251
instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{
5252
match(Set dst (AddP src1 src2));
5255
format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5257
__ add($dst$$Register, $src1$$Register, $src2$$Register);
5259
ins_pipe(ialu_reg_reg);
5263
// shifted iRegX operand
5264
operand shiftedX(iRegX src2, shimmX src3) %{
5265
//constraint(ALLOC_IN_RC(sp_ptr_reg));
5266
match(LShiftX src2 src3);
5269
format %{ "$src2 << $src3" %}
5270
interface(MEMORY_INTER) %{
5278
instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{
5279
match(Set dst (AddP src1 src2));
5281
ins_cost(DEFAULT_COST * 3/2);
5283
format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5285
Register base = reg_to_register_object($src2$$base);
5286
__ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale));
5288
ins_pipe(ialu_reg_reg);
5291
// Pointer Immediate Addition
5292
instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{
5293
match(Set dst (AddP src1 src2));
5296
format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5298
__ add($dst$$Register, $src1$$Register, $src2$$constant);
5300
ins_pipe(ialu_reg_imm);
5304
instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{
5305
match(Set dst (AddL src1 src2));
5308
format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5309
"ADC $dst.hi,$src1.hi,$src2.hi" %}
5311
__ adds($dst$$Register, $src1$$Register, $src2$$Register);
5312
__ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5314
ins_pipe(ialu_reg_reg);
5319
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5320
// (hi($con$$constant), lo($con$$constant)) becomes
5321
instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
5322
match(Set dst (AddL src1 con));
5325
format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t"
5326
"ADC $dst.hi,$src1.hi,0" %}
5328
__ adds($dst$$Register, $src1$$Register, $con$$constant);
5329
__ adc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5331
ins_pipe(ialu_reg_imm);
5334
// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
5336
instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
5337
match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5338
effect( KILL ccr, TEMP tmp);
5340
format %{ "loop: \n\t"
5341
"LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5342
"CMP $tmp.lo, $oldval.lo\n\t"
5343
"CMP.eq $tmp.hi, $oldval.hi\n\t"
5344
"STREXD.eq $tmp, $newval, $mem\n\t"
5345
"MOV.ne $tmp, 0 \n\t"
5346
"XORS.eq $tmp,$tmp, 1 \n\t"
5352
__ ldrexd($tmp$$Register, $mem$$Address);
5353
__ cmp($tmp$$Register, $oldval$$Register);
5354
__ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq);
5355
__ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5356
__ mov($tmp$$Register, 0, ne);
5357
__ eors($tmp$$Register, $tmp$$Register, 1, eq);
5359
__ mov($res$$Register, $tmp$$Register);
5361
ins_pipe( long_memory_op );
5365
instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5366
match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5367
effect( KILL ccr, TEMP tmp);
5369
format %{ "loop: \n\t"
5370
"LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5371
"CMP $tmp, $oldval\n\t"
5372
"STREX.eq $tmp, $newval, $mem\n\t"
5373
"MOV.ne $tmp, 0 \n\t"
5374
"XORS.eq $tmp,$tmp, 1 \n\t"
5381
__ ldrex($tmp$$Register,$mem$$Address);
5382
__ cmp($tmp$$Register, $oldval$$Register);
5383
__ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5384
__ mov($tmp$$Register, 0, ne);
5385
__ eors($tmp$$Register, $tmp$$Register, 1, eq);
5387
__ mov($res$$Register, $tmp$$Register);
5389
ins_pipe( long_memory_op );
5392
instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5393
match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5394
effect( KILL ccr, TEMP tmp);
5396
format %{ "loop: \n\t"
5397
"LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5398
"CMP $tmp, $oldval\n\t"
5399
"STREX.eq $tmp, $newval, $mem\n\t"
5400
"MOV.ne $tmp, 0 \n\t"
5401
"EORS.eq $tmp,$tmp, 1 \n\t"
5408
__ ldrex($tmp$$Register,$mem$$Address);
5409
__ cmp($tmp$$Register, $oldval$$Register);
5410
__ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5411
__ mov($tmp$$Register, 0, ne);
5412
__ eors($tmp$$Register, $tmp$$Register, 1, eq);
5414
__ mov($res$$Register, $tmp$$Register);
5416
ins_pipe( long_memory_op );
5419
instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5420
predicate(n->as_LoadStore()->result_not_used());
5421
match(Set dummy (GetAndAddI mem add));
5422
effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5424
format %{ "loop: \n\t"
5425
"LDREX $tmp1, $mem\n\t"
5426
"ADD $tmp1, $tmp1, $add\n\t"
5427
"STREX $tmp2, $tmp1, $mem\n\t"
5434
__ ldrex($tmp1$$Register,$mem$$Address);
5435
__ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
5436
__ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5437
__ cmp($tmp2$$Register, 0);
5440
ins_pipe( long_memory_op );
5443
instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5444
predicate(n->as_LoadStore()->result_not_used());
5445
match(Set dummy (GetAndAddI mem add));
5446
effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5448
format %{ "loop: \n\t"
5449
"LDREX $tmp1, $mem\n\t"
5450
"ADD $tmp1, $tmp1, $add\n\t"
5451
"STREX $tmp2, $tmp1, $mem\n\t"
5458
__ ldrex($tmp1$$Register,$mem$$Address);
5459
__ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
5460
__ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5461
__ cmp($tmp2$$Register, 0);
5464
ins_pipe( long_memory_op );
5467
instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5468
match(Set res (GetAndAddI mem add));
5469
effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5471
format %{ "loop: \n\t"
5472
"LDREX $res, $mem\n\t"
5473
"ADD $tmp1, $res, $add\n\t"
5474
"STREX $tmp2, $tmp1, $mem\n\t"
5481
__ ldrex($res$$Register,$mem$$Address);
5482
__ add($tmp1$$Register, $res$$Register, $add$$constant);
5483
__ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5484
__ cmp($tmp2$$Register, 0);
5487
ins_pipe( long_memory_op );
5490
instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5491
match(Set res (GetAndAddI mem add));
5492
effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5494
format %{ "loop: \n\t"
5495
"LDREX $res, $mem\n\t"
5496
"ADD $tmp1, $res, $add\n\t"
5497
"STREX $tmp2, $tmp1, $mem\n\t"
5504
__ ldrex($res$$Register,$mem$$Address);
5505
__ add($tmp1$$Register, $res$$Register, $add$$Register);
5506
__ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5507
__ cmp($tmp2$$Register, 0);
5510
ins_pipe( long_memory_op );
5513
instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5514
predicate(n->as_LoadStore()->result_not_used());
5515
match(Set dummy (GetAndAddL mem add));
5516
effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5518
format %{ "loop: \n\t"
5519
"LDREXD $tmp1, $mem\n\t"
5520
"ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t"
5521
"ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t"
5522
"STREXD $tmp2, $tmp1, $mem\n\t"
5529
__ ldrexd($tmp1$$Register, $mem$$Address);
5530
__ adds($tmp1$$Register, $tmp1$$Register, $add$$Register);
5531
__ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor());
5532
__ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5533
__ cmp($tmp2$$Register, 0);
5536
ins_pipe( long_memory_op );
5539
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5540
// (hi($con$$constant), lo($con$$constant)) becomes
5541
instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5542
predicate(n->as_LoadStore()->result_not_used());
5543
match(Set dummy (GetAndAddL mem add));
5544
effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5546
format %{ "loop: \n\t"
5547
"LDREXD $tmp1, $mem\n\t"
5548
"ADDS $tmp1.lo, $tmp1.lo, $add\n\t"
5549
"ADC $tmp1.hi, $tmp1.hi, 0\n\t"
5550
"STREXD $tmp2, $tmp1, $mem\n\t"
5557
__ ldrexd($tmp1$$Register, $mem$$Address);
5558
__ adds($tmp1$$Register, $tmp1$$Register, $add$$constant);
5559
__ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0);
5560
__ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5561
__ cmp($tmp2$$Register, 0);
5564
ins_pipe( long_memory_op );
5567
instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5568
match(Set res (GetAndAddL mem add));
5569
effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5571
format %{ "loop: \n\t"
5572
"LDREXD $res, $mem\n\t"
5573
"ADDS $tmp1.lo, $res.lo, $add.lo\n\t"
5574
"ADC $tmp1.hi, $res.hi, $add.hi\n\t"
5575
"STREXD $tmp2, $tmp1, $mem\n\t"
5582
__ ldrexd($res$$Register, $mem$$Address);
5583
__ adds($tmp1$$Register, $res$$Register, $add$$Register);
5584
__ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor());
5585
__ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5586
__ cmp($tmp2$$Register, 0);
5589
ins_pipe( long_memory_op );
5592
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5593
// (hi($con$$constant), lo($con$$constant)) becomes
5594
instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5595
match(Set res (GetAndAddL mem add));
5596
effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5598
format %{ "loop: \n\t"
5599
"LDREXD $res, $mem\n\t"
5600
"ADDS $tmp1.lo, $res.lo, $add\n\t"
5601
"ADC $tmp1.hi, $res.hi, 0\n\t"
5602
"STREXD $tmp2, $tmp1, $mem\n\t"
5609
__ ldrexd($res$$Register, $mem$$Address);
5610
__ adds($tmp1$$Register, $res$$Register, $add$$constant);
5611
__ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0);
5612
__ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5613
__ cmp($tmp2$$Register, 0);
5616
ins_pipe( long_memory_op );
5619
instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
5620
match(Set res (GetAndSetI mem newval));
5621
effect(KILL ccr, TEMP tmp, TEMP res);
5623
format %{ "loop: \n\t"
5624
"LDREX $res, $mem\n\t"
5625
"STREX $tmp, $newval, $mem\n\t"
5632
__ ldrex($res$$Register,$mem$$Address);
5633
__ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5634
__ cmp($tmp$$Register, 0);
5637
ins_pipe( long_memory_op );
5640
instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{
5641
match(Set res (GetAndSetL mem newval));
5642
effect( KILL ccr, TEMP tmp, TEMP res);
5644
format %{ "loop: \n\t"
5645
"LDREXD $res, $mem\n\t"
5646
"STREXD $tmp, $newval, $mem\n\t"
5653
__ ldrexd($res$$Register, $mem$$Address);
5654
__ strexd($tmp$$Register, $newval$$Register, $mem$$Address);
5655
__ cmp($tmp$$Register, 0);
5658
ins_pipe( long_memory_op );
5661
instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{
5662
match(Set res (GetAndSetP mem newval));
5663
effect(KILL ccr, TEMP tmp, TEMP res);
5665
format %{ "loop: \n\t"
5666
"LDREX $res, $mem\n\t"
5667
"STREX $tmp, $newval, $mem\n\t"
5674
__ ldrex($res$$Register,$mem$$Address);
5675
__ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5676
__ cmp($tmp$$Register, 0);
5679
ins_pipe( long_memory_op );
5682
//---------------------
5683
// Subtraction Instructions
5684
// Register Subtraction
5685
instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5686
match(Set dst (SubI src1 src2));
5689
format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5691
__ sub_32($dst$$Register, $src1$$Register, $src2$$Register);
5693
ins_pipe(ialu_reg_reg);
5696
instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5697
match(Set dst (SubI src1 (LShiftI src2 src3)));
5700
format %{ "SUB $dst,$src1,$src2<<$src3" %}
5702
__ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
5704
ins_pipe(ialu_reg_reg);
5707
instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5708
match(Set dst (SubI src1 (LShiftI src2 src3)));
5711
format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %}
5713
__ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
5715
ins_pipe(ialu_reg_reg);
5718
instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5719
match(Set dst (SubI src1 (RShiftI src2 src3)));
5722
format %{ "SUB $dst,$src1,$src2>>$src3" %}
5724
__ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
5726
ins_pipe(ialu_reg_reg);
5729
instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5730
match(Set dst (SubI src1 (RShiftI src2 src3)));
5733
format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %}
5735
__ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
5737
ins_pipe(ialu_reg_reg);
5740
instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5741
match(Set dst (SubI src1 (URShiftI src2 src3)));
5744
format %{ "SUB $dst,$src1,$src2>>>$src3" %}
5746
__ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
5748
ins_pipe(ialu_reg_reg);
5751
instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5752
match(Set dst (SubI src1 (URShiftI src2 src3)));
5755
format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %}
5757
__ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
5759
ins_pipe(ialu_reg_reg);
5762
instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5763
match(Set dst (SubI (LShiftI src1 src2) src3));
5766
format %{ "RSB $dst,$src3,$src1<<$src2" %}
5768
__ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5770
ins_pipe(ialu_reg_reg);
5773
instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5774
match(Set dst (SubI (LShiftI src1 src2) src3));
5777
format %{ "RSB $dst,$src3,$src1<<$src2" %}
5779
__ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5781
ins_pipe(ialu_reg_reg);
5784
instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5785
match(Set dst (SubI (RShiftI src1 src2) src3));
5788
format %{ "RSB $dst,$src3,$src1>>$src2" %}
5790
__ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5792
ins_pipe(ialu_reg_reg);
5795
instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5796
match(Set dst (SubI (RShiftI src1 src2) src3));
5799
format %{ "RSB $dst,$src3,$src1>>$src2" %}
5801
__ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5803
ins_pipe(ialu_reg_reg);
5806
instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5807
match(Set dst (SubI (URShiftI src1 src2) src3));
5810
format %{ "RSB $dst,$src3,$src1>>>$src2" %}
5812
__ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5814
ins_pipe(ialu_reg_reg);
5817
instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5818
match(Set dst (SubI (URShiftI src1 src2) src3));
5821
format %{ "RSB $dst,$src3,$src1>>>$src2" %}
5823
__ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5825
ins_pipe(ialu_reg_reg);
5828
// Immediate Subtraction
5829
instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5830
match(Set dst (SubI src1 src2));
5833
format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5835
__ sub_32($dst$$Register, $src1$$Register, $src2$$constant);
5837
ins_pipe(ialu_reg_imm);
5840
instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{
5841
match(Set dst (AddI src1 src2));
5844
format %{ "sub_32 $dst,$src1,-($src2)\t! int" %}
5846
__ sub_32($dst$$Register, $src1$$Register, -$src2$$constant);
5848
ins_pipe(ialu_reg_imm);
5851
instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{
5852
match(Set dst (SubI src1 src2));
5855
format %{ "RSB $dst,$src2,src1" %}
5857
__ rsb($dst$$Register, $src2$$Register, $src1$$constant);
5859
ins_pipe(ialu_zero_reg);
5862
// Register Subtraction
5863
instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{
5864
match(Set dst (SubL src1 src2));
5868
format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5869
"SBC $dst.hi,$src1.hi,$src2.hi" %}
5871
__ subs($dst$$Register, $src1$$Register, $src2$$Register);
5872
__ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5874
ins_pipe(ialu_reg_reg);
5879
// Immediate Subtraction
5880
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5881
// (hi($con$$constant), lo($con$$constant)) becomes
5882
instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{
5883
match(Set dst (SubL src1 con));
5887
format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t"
5888
"SBC $dst.hi,$src1.hi,0" %}
5890
__ subs($dst$$Register, $src1$$Register, $con$$constant);
5891
__ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5893
ins_pipe(ialu_reg_imm);
5897
instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{
5898
match(Set dst (SubL zero src2));
5902
format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t"
5903
"RSC $dst.hi,$src2.hi,0" %}
5905
__ rsbs($dst$$Register, $src2$$Register, 0);
5906
__ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0);
5908
ins_pipe(ialu_zero_reg);
5911
// Multiplication Instructions
5912
// Integer Multiplication
5913
// Register Multiplication
5914
instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5915
match(Set dst (MulI src1 src2));
5918
format %{ "mul_32 $dst,$src1,$src2" %}
5920
__ mul_32($dst$$Register, $src1$$Register, $src2$$Register);
5922
ins_pipe(imul_reg_reg);
5925
instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{
5926
effect(DEF dst, USE src1, USE src2);
5928
format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %}
5930
__ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor());
5932
ins_pipe(imul_reg_reg);
5935
instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5936
effect(USE_DEF dst, USE src1, USE src2);
5938
format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t"
5941
__ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor());
5942
__ mov($dst$$Register, 0);
5944
ins_pipe(imul_reg_reg);
5947
instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5948
effect(USE_DEF dst, USE src1, USE src2);
5950
format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %}
5952
__ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register);
5954
ins_pipe(imul_reg_reg);
5957
instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
5958
match(Set dst (MulL src1 src2));
5961
mulL_lo1_hi2(dst, src1, src2);
5962
mulL_hi1_lo2(dst, src1, src2);
5963
mulL_lo1_lo2(dst, src1, src2);
5969
instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{
5970
match(Set dst (DivI src1 src2));
5971
effect( KILL ccr, KILL src1, KILL src2, KILL lr);
5972
ins_cost((2+71)*DEFAULT_COST);
5974
format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %}
5976
__ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
5978
ins_pipe(sdiv_reg_reg);
5981
// Register Long Division
5982
instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
5983
match(Set dst (DivL src1 src2));
5985
ins_cost(DEFAULT_COST*71);
5986
format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %}
5988
address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv);
5989
__ call(target, relocInfo::runtime_call_type);
5991
ins_pipe(divL_reg_reg);
5995
// Register Remainder
5996
instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{
5997
match(Set dst (ModI src1 src2));
5998
effect( KILL ccr, KILL temp, KILL src2, KILL lr);
6000
format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %}
6002
__ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
6004
ins_pipe(sdiv_reg_reg);
6007
// Register Long Remainder
6008
instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
6009
match(Set dst (ModL src1 src2));
6011
ins_cost(MEMORY_REF_COST); // FIXME
6012
format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %}
6014
address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
6015
__ call(target, relocInfo::runtime_call_type);
6017
ins_pipe(divL_reg_reg);
6020
// Integer Shift Instructions
6022
// Register Shift Left
6023
instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6024
match(Set dst (LShiftI src1 src2));
6027
format %{ "LSL $dst,$src1,$src2 \n\t" %}
6029
__ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6031
ins_pipe(ialu_reg_reg);
6034
// Register Shift Left Immediate
6035
instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6036
match(Set dst (LShiftI src1 src2));
6039
format %{ "LSL $dst,$src1,$src2\t! int" %}
6041
__ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
6043
ins_pipe(ialu_reg_imm);
6046
instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6047
effect(USE_DEF dst, USE src1, USE src2);
6049
format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %}
6051
__ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register));
6053
ins_pipe(ialu_reg_reg);
6056
instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6057
effect(USE_DEF dst, USE src1, USE src2);
6059
format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %}
6061
__ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6063
ins_pipe(ialu_reg_reg);
6066
instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6067
effect(DEF dst, USE src1, USE src2, KILL ccr);
6069
format %{ "SUBS $dst.hi,$src2,32 \n\t"
6070
"LSLpl $dst.hi,$src1.lo,$dst.hi \n\t"
6071
"RSBmi $dst.hi,$dst.hi,0 \n\t"
6072
"LSRmi $dst.hi,$src1.lo,$dst.hi" %}
6075
// $src1$$Register and $dst$$Register->successor() can't be the same
6076
__ subs($dst$$Register->successor(), $src2$$Register, 32);
6077
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl);
6078
__ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi);
6079
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi);
6081
ins_pipe(ialu_reg_reg);
6084
instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6085
match(Set dst (LShiftL src1 src2));
6089
shlL_reg_reg_overlap(dst, src1, src2, ccr);
6090
shlL_reg_reg_merge_hi(dst, src1, src2);
6091
shlL_reg_reg_merge_lo(dst, src1, src2);
6095
// Register Shift Left Immediate
6096
instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6097
match(Set dst (LShiftL src1 src2));
6100
format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t"
6103
if ($src2$$constant == 32) {
6104
__ mov($dst$$Register->successor(), $src1$$Register);
6106
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32));
6108
__ mov($dst$$Register, 0);
6110
ins_pipe(ialu_reg_imm);
6113
instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6114
match(Set dst (LShiftL src1 src2));
6117
format %{ "LSL $dst.hi,$src1.lo,$src2\n\t"
6118
"OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t"
6119
"LSL $dst.lo,$src1.lo,$src2" %}
6121
// The order of the following 3 instructions matters: src1.lo and
6122
// dst.hi can't overlap but src.hi and dst.hi can.
6123
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant));
6124
__ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant));
6125
__ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6127
ins_pipe(ialu_reg_imm);
6130
// Register Arithmetic Shift Right
6131
instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6132
match(Set dst (RShiftI src1 src2));
6134
format %{ "ASR $dst,$src1,$src2\t! int" %}
6136
__ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
6138
ins_pipe(ialu_reg_reg);
6141
// Register Arithmetic Shift Right Immediate
6142
instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6143
match(Set dst (RShiftI src1 src2));
6146
format %{ "ASR $dst,$src1,$src2" %}
6148
__ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
6150
ins_pipe(ialu_reg_imm);
6153
// Register Shift Right Arithmetic Long
6154
instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6155
effect(USE_DEF dst, USE src1, USE src2);
6157
format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %}
6159
__ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6161
ins_pipe(ialu_reg_reg);
6164
instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6165
effect(USE_DEF dst, USE src1, USE src2);
6167
format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %}
6169
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register));
6171
ins_pipe(ialu_reg_reg);
6174
instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6175
effect(DEF dst, USE src1, USE src2, KILL ccr);
6177
format %{ "SUBS $dst.lo,$src2,32 \n\t"
6178
"ASRpl $dst.lo,$src1.hi,$dst.lo \n\t"
6179
"RSBmi $dst.lo,$dst.lo,0 \n\t"
6180
"LSLmi $dst.lo,$src1.hi,$dst.lo" %}
6183
// $src1$$Register->successor() and $dst$$Register can't be the same
6184
__ subs($dst$$Register, $src2$$Register, 32);
6185
__ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl);
6186
__ rsb($dst$$Register, $dst$$Register, 0, mi);
6187
__ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6189
ins_pipe(ialu_reg_reg);
6192
instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6193
match(Set dst (RShiftL src1 src2));
6197
sarL_reg_reg_overlap(dst, src1, src2, ccr);
6198
sarL_reg_reg_merge_lo(dst, src1, src2);
6199
sarL_reg_reg_merge_hi(dst, src1, src2);
6203
// Register Shift Left Immediate
6204
instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6205
match(Set dst (RShiftL src1 src2));
6208
format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6209
"ASR $dst.hi,$src1.hi, $src2" %}
6211
if ($src2$$constant == 32) {
6212
__ mov($dst$$Register, $src1$$Register->successor());
6214
__ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32));
6216
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0));
6219
ins_pipe(ialu_reg_imm);
6222
instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6223
match(Set dst (RShiftL src1 src2));
6225
format %{ "LSR $dst.lo,$src1.lo,$src2\n\t"
6226
"OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6227
"ASR $dst.hi,$src1.hi,$src2" %}
6229
// The order of the following 3 instructions matters: src1.lo and
6230
// dst.hi can't overlap but src.hi and dst.hi can.
6231
__ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6232
__ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6233
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant));
6235
ins_pipe(ialu_reg_imm);
6238
// Register Shift Right
6239
instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6240
match(Set dst (URShiftI src1 src2));
6242
format %{ "LSR $dst,$src1,$src2\t! int" %}
6244
__ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6246
ins_pipe(ialu_reg_reg);
6249
// Register Shift Right Immediate
6250
instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6251
match(Set dst (URShiftI src1 src2));
6254
format %{ "LSR $dst,$src1,$src2" %}
6256
__ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6258
ins_pipe(ialu_reg_imm);
6261
// Register Shift Right
6262
instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6263
effect(USE_DEF dst, USE src1, USE src2);
6265
format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %}
6267
__ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6269
ins_pipe(ialu_reg_reg);
6272
instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6273
effect(USE_DEF dst, USE src1, USE src2);
6275
format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %}
6277
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register));
6279
ins_pipe(ialu_reg_reg);
6282
instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6283
effect(DEF dst, USE src1, USE src2, KILL ccr);
6285
format %{ "SUBS $dst,$src2,32 \n\t"
6286
"LSRpl $dst,$src1.hi,$dst \n\t"
6287
"RSBmi $dst,$dst,0 \n\t"
6288
"LSLmi $dst,$src1.hi,$dst" %}
6291
// $src1$$Register->successor() and $dst$$Register can't be the same
6292
__ subs($dst$$Register, $src2$$Register, 32);
6293
__ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl);
6294
__ rsb($dst$$Register, $dst$$Register, 0, mi);
6295
__ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6297
ins_pipe(ialu_reg_reg);
6300
instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6301
match(Set dst (URShiftL src1 src2));
6305
shrL_reg_reg_overlap(dst, src1, src2, ccr);
6306
shrL_reg_reg_merge_lo(dst, src1, src2);
6307
shrL_reg_reg_merge_hi(dst, src1, src2);
6311
// Register Shift Right Immediate
6312
instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6313
match(Set dst (URShiftL src1 src2));
6316
format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6319
if ($src2$$constant == 32) {
6320
__ mov($dst$$Register, $src1$$Register->successor());
6322
__ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32));
6324
__ mov($dst$$Register->successor(), 0);
6327
ins_pipe(ialu_reg_imm);
6330
instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6331
match(Set dst (URShiftL src1 src2));
6334
format %{ "LSR $dst.lo,$src1.lo,$src2\n\t"
6335
"OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6336
"LSR $dst.hi,$src1.hi,$src2" %}
6338
// The order of the following 3 instructions matters: src1.lo and
6339
// dst.hi can't overlap but src.hi and dst.hi can.
6340
__ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6341
__ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6342
__ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant));
6344
ins_pipe(ialu_reg_imm);
6348
instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{
6349
match(Set dst (URShiftI (CastP2X src1) src2));
6351
format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %}
6353
__ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant);
6355
ins_pipe(ialu_reg_imm);
6358
//----------Floating Point Arithmetic Instructions-----------------------------
6360
// Add float single precision
6361
instruct addF_reg_reg(regF dst, regF src1, regF src2) %{
6362
match(Set dst (AddF src1 src2));
6365
format %{ "FADDS $dst,$src1,$src2" %}
6367
__ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6370
ins_pipe(faddF_reg_reg);
6373
// Add float double precision
6374
instruct addD_reg_reg(regD dst, regD src1, regD src2) %{
6375
match(Set dst (AddD src1 src2));
6378
format %{ "FADDD $dst,$src1,$src2" %}
6380
__ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6383
ins_pipe(faddD_reg_reg);
6386
// Sub float single precision
6387
instruct subF_reg_reg(regF dst, regF src1, regF src2) %{
6388
match(Set dst (SubF src1 src2));
6391
format %{ "FSUBS $dst,$src1,$src2" %}
6393
__ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6395
ins_pipe(faddF_reg_reg);
6398
// Sub float double precision
6399
instruct subD_reg_reg(regD dst, regD src1, regD src2) %{
6400
match(Set dst (SubD src1 src2));
6403
format %{ "FSUBD $dst,$src1,$src2" %}
6405
__ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6407
ins_pipe(faddD_reg_reg);
6410
// Mul float single precision
6411
instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{
6412
match(Set dst (MulF src1 src2));
6415
format %{ "FMULS $dst,$src1,$src2" %}
6417
__ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6420
ins_pipe(fmulF_reg_reg);
6423
// Mul float double precision
6424
instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{
6425
match(Set dst (MulD src1 src2));
6428
format %{ "FMULD $dst,$src1,$src2" %}
6430
__ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6433
ins_pipe(fmulD_reg_reg);
6436
// Div float single precision
6437
instruct divF_reg_reg(regF dst, regF src1, regF src2) %{
6438
match(Set dst (DivF src1 src2));
6441
format %{ "FDIVS $dst,$src1,$src2" %}
6443
__ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6446
ins_pipe(fdivF_reg_reg);
6449
// Div float double precision
6450
instruct divD_reg_reg(regD dst, regD src1, regD src2) %{
6451
match(Set dst (DivD src1 src2));
6454
format %{ "FDIVD $dst,$src1,$src2" %}
6456
__ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6459
ins_pipe(fdivD_reg_reg);
6462
// Absolute float double precision
6463
instruct absD_reg(regD dst, regD src) %{
6464
match(Set dst (AbsD src));
6467
format %{ "FABSd $dst,$src" %}
6469
__ abs_double($dst$$FloatRegister, $src$$FloatRegister);
6471
ins_pipe(faddD_reg);
6474
// Absolute float single precision
6475
instruct absF_reg(regF dst, regF src) %{
6476
match(Set dst (AbsF src));
6477
format %{ "FABSs $dst,$src" %}
6479
__ abs_float($dst$$FloatRegister, $src$$FloatRegister);
6481
ins_pipe(faddF_reg);
6484
instruct negF_reg(regF dst, regF src) %{
6485
match(Set dst (NegF src));
6488
format %{ "FNEGs $dst,$src" %}
6490
__ neg_float($dst$$FloatRegister, $src$$FloatRegister);
6492
ins_pipe(faddF_reg);
6495
instruct negD_reg(regD dst, regD src) %{
6496
match(Set dst (NegD src));
6498
format %{ "FNEGd $dst,$src" %}
6500
__ neg_double($dst$$FloatRegister, $src$$FloatRegister);
6502
ins_pipe(faddD_reg);
6505
// Sqrt float double precision
6506
instruct sqrtF_reg_reg(regF dst, regF src) %{
6507
match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
6510
format %{ "FSQRTS $dst,$src" %}
6512
__ sqrt_float($dst$$FloatRegister, $src$$FloatRegister);
6514
ins_pipe(fdivF_reg_reg);
6517
// Sqrt float double precision
6518
instruct sqrtD_reg_reg(regD dst, regD src) %{
6519
match(Set dst (SqrtD src));
6522
format %{ "FSQRTD $dst,$src" %}
6524
__ sqrt_double($dst$$FloatRegister, $src$$FloatRegister);
6526
ins_pipe(fdivD_reg_reg);
6529
//----------Logical Instructions-----------------------------------------------
6532
instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6533
match(Set dst (AndI src1 src2));
6536
format %{ "and_32 $dst,$src1,$src2" %}
6538
__ and_32($dst$$Register, $src1$$Register, $src2$$Register);
6540
ins_pipe(ialu_reg_reg);
6543
instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6544
match(Set dst (AndI src1 (LShiftI src2 src3)));
6547
format %{ "AND $dst,$src1,$src2<<$src3" %}
6549
__ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6551
ins_pipe(ialu_reg_reg);
6554
instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6555
match(Set dst (AndI src1 (LShiftI src2 src3)));
6558
format %{ "and_32 $dst,$src1,$src2<<$src3" %}
6560
__ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6562
ins_pipe(ialu_reg_reg);
6565
instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6566
match(Set dst (AndI src1 (RShiftI src2 src3)));
6569
format %{ "AND $dst,$src1,$src2>>$src3" %}
6571
__ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6573
ins_pipe(ialu_reg_reg);
6576
instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6577
match(Set dst (AndI src1 (RShiftI src2 src3)));
6580
format %{ "and_32 $dst,$src1,$src2>>$src3" %}
6582
__ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6584
ins_pipe(ialu_reg_reg);
6587
instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6588
match(Set dst (AndI src1 (URShiftI src2 src3)));
6591
format %{ "AND $dst,$src1,$src2>>>$src3" %}
6593
__ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6595
ins_pipe(ialu_reg_reg);
6598
instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6599
match(Set dst (AndI src1 (URShiftI src2 src3)));
6602
format %{ "and_32 $dst,$src1,$src2>>>$src3" %}
6604
__ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6606
ins_pipe(ialu_reg_reg);
6610
instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6611
match(Set dst (AndI src1 src2));
6614
format %{ "and_32 $dst,$src1,$src2\t! int" %}
6616
__ and_32($dst$$Register, $src1$$Register, $src2$$constant);
6618
ins_pipe(ialu_reg_imm);
6621
instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{
6622
match(Set dst (AndI src1 src2));
6625
format %{ "bic $dst,$src1,~$src2\t! int" %}
6627
__ bic($dst$$Register, $src1$$Register, ~$src2$$constant);
6629
ins_pipe(ialu_reg_imm);
6633
instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6634
match(Set dst (AndL src1 src2));
6636
ins_cost(DEFAULT_COST);
6638
format %{ "AND $dst,$src1,$src2\t! long" %}
6640
__ andr($dst$$Register, $src1$$Register, $src2$$Register);
6641
__ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6643
ins_pipe(ialu_reg_reg);
6646
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6647
// (hi($con$$constant), lo($con$$constant)) becomes
6648
instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6649
match(Set dst (AndL src1 con));
6650
ins_cost(DEFAULT_COST);
6652
format %{ "AND $dst,$src1,$con\t! long" %}
6654
__ andr($dst$$Register, $src1$$Register, $con$$constant);
6655
__ andr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6657
ins_pipe(ialu_reg_imm);
6662
instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6663
match(Set dst (OrI src1 src2));
6666
format %{ "orr_32 $dst,$src1,$src2\t! int" %}
6668
__ orr_32($dst$$Register, $src1$$Register, $src2$$Register);
6670
ins_pipe(ialu_reg_reg);
6673
instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6674
match(Set dst (OrI src1 (LShiftI src2 src3)));
6677
format %{ "OR $dst,$src1,$src2<<$src3" %}
6679
__ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6681
ins_pipe(ialu_reg_reg);
6684
instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6685
match(Set dst (OrI src1 (LShiftI src2 src3)));
6688
format %{ "orr_32 $dst,$src1,$src2<<$src3" %}
6690
__ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6692
ins_pipe(ialu_reg_reg);
6695
instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6696
match(Set dst (OrI src1 (RShiftI src2 src3)));
6699
format %{ "OR $dst,$src1,$src2>>$src3" %}
6701
__ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6703
ins_pipe(ialu_reg_reg);
6706
instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6707
match(Set dst (OrI src1 (RShiftI src2 src3)));
6710
format %{ "orr_32 $dst,$src1,$src2>>$src3" %}
6712
__ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6714
ins_pipe(ialu_reg_reg);
6717
instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6718
match(Set dst (OrI src1 (URShiftI src2 src3)));
6721
format %{ "OR $dst,$src1,$src2>>>$src3" %}
6723
__ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6725
ins_pipe(ialu_reg_reg);
6728
instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6729
match(Set dst (OrI src1 (URShiftI src2 src3)));
6732
format %{ "orr_32 $dst,$src1,$src2>>>$src3" %}
6734
__ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6736
ins_pipe(ialu_reg_reg);
6740
instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6741
match(Set dst (OrI src1 src2));
6744
format %{ "orr_32 $dst,$src1,$src2" %}
6746
__ orr_32($dst$$Register, $src1$$Register, $src2$$constant);
6748
ins_pipe(ialu_reg_imm);
6750
// TODO: orn_32 with limmIn
6753
instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6754
match(Set dst (OrL src1 src2));
6756
ins_cost(DEFAULT_COST);
6758
format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
6759
"OR $dst.hi,$src1.hi,$src2.hi" %}
6761
__ orr($dst$$Register, $src1$$Register, $src2$$Register);
6762
__ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6764
ins_pipe(ialu_reg_reg);
6767
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6768
// (hi($con$$constant), lo($con$$constant)) becomes
6769
instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6770
match(Set dst (OrL src1 con));
6771
ins_cost(DEFAULT_COST);
6773
format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t"
6774
"OR $dst.hi,$src1.hi,$con" %}
6776
__ orr($dst$$Register, $src1$$Register, $con$$constant);
6777
__ orr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6779
ins_pipe(ialu_reg_imm);
6783
// Use SPRegP to match Rthread (TLS register) without spilling.
6784
// Use store_ptr_RegP to match Rthread (TLS register) without spilling.
6785
// Use sp_ptr_RegP to match Rthread (TLS register) without spilling.
6786
instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{
6787
match(Set dst (OrI src1 (CastP2X src2)));
6789
format %{ "OR $dst,$src1,$src2" %}
6791
__ orr($dst$$Register, $src1$$Register, $src2$$Register);
6793
ins_pipe(ialu_reg_reg);
6799
instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6800
match(Set dst (XorI src1 src2));
6803
format %{ "eor_32 $dst,$src1,$src2" %}
6805
__ eor_32($dst$$Register, $src1$$Register, $src2$$Register);
6807
ins_pipe(ialu_reg_reg);
6810
instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6811
match(Set dst (XorI src1 (LShiftI src2 src3)));
6814
format %{ "XOR $dst,$src1,$src2<<$src3" %}
6816
__ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6818
ins_pipe(ialu_reg_reg);
6821
instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6822
match(Set dst (XorI src1 (LShiftI src2 src3)));
6825
format %{ "eor_32 $dst,$src1,$src2<<$src3" %}
6827
__ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6829
ins_pipe(ialu_reg_reg);
6832
instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6833
match(Set dst (XorI src1 (RShiftI src2 src3)));
6836
format %{ "XOR $dst,$src1,$src2>>$src3" %}
6838
__ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6840
ins_pipe(ialu_reg_reg);
6843
instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6844
match(Set dst (XorI src1 (RShiftI src2 src3)));
6847
format %{ "eor_32 $dst,$src1,$src2>>$src3" %}
6849
__ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6851
ins_pipe(ialu_reg_reg);
6854
instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6855
match(Set dst (XorI src1 (URShiftI src2 src3)));
6858
format %{ "XOR $dst,$src1,$src2>>>$src3" %}
6860
__ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6862
ins_pipe(ialu_reg_reg);
6865
instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6866
match(Set dst (XorI src1 (URShiftI src2 src3)));
6869
format %{ "eor_32 $dst,$src1,$src2>>>$src3" %}
6871
__ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6873
ins_pipe(ialu_reg_reg);
6877
instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{
6878
match(Set dst (XorI src1 src2));
6881
format %{ "eor_32 $dst,$src1,$src2" %}
6883
__ eor_32($dst$$Register, $src1$$Register, $src2$$constant);
6885
ins_pipe(ialu_reg_imm);
6889
instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6890
match(Set dst (XorL src1 src2));
6891
ins_cost(DEFAULT_COST);
6893
format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t"
6894
"XOR $dst.lo,$src1.lo,$src2.lo\t! long" %}
6896
__ eor($dst$$Register, $src1$$Register, $src2$$Register);
6897
__ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6899
ins_pipe(ialu_reg_reg);
6902
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6903
// (hi($con$$constant), lo($con$$constant)) becomes
6904
instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6905
match(Set dst (XorL src1 con));
6906
ins_cost(DEFAULT_COST);
6908
format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t"
6909
"XOR $dst.lo,$src1.lo,0\t! long" %}
6911
__ eor($dst$$Register, $src1$$Register, $con$$constant);
6912
__ eor($dst$$Register->successor(), $src1$$Register->successor(), 0);
6914
ins_pipe(ialu_reg_imm);
6917
instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
6918
match(Set dst (CmpLTMask p q));
6920
ins_cost(DEFAULT_COST*3);
6921
format %{ "CMP $p,$q\n\t"
6923
"MOV.lt $dst, #-1" %}
6925
__ cmp($p$$Register, $q$$Register);
6926
__ mov($dst$$Register, 0);
6927
__ mvn($dst$$Register, 0, lt);
6929
ins_pipe(ialu_reg_reg_ialu);
6932
instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{
6933
match(Set dst (CmpLTMask p q));
6935
ins_cost(DEFAULT_COST*3);
6936
format %{ "CMP $p,$q\n\t"
6938
"MOV.lt $dst, #-1" %}
6940
__ cmp($p$$Register, $q$$constant);
6941
__ mov($dst$$Register, 0);
6942
__ mvn($dst$$Register, 0, lt);
6944
ins_pipe(ialu_reg_reg_ialu);
6947
instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{
6948
match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6950
ins_cost(DEFAULT_COST*2);
6951
format %{ "CMP $p,$q\n\t"
6952
"ADD.lt $z,$y,$z" %}
6954
__ cmp($p$$Register, $q$$Register);
6955
__ add($z$$Register, $y$$Register, $z$$Register, lt);
6957
ins_pipe( cadd_cmpltmask );
6960
// FIXME: remove unused "dst"
6961
instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{
6962
match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6964
ins_cost(DEFAULT_COST*2);
6965
format %{ "CMP $p,$q\n\t"
6966
"ADD.lt $z,$y,$z" %}
6968
__ cmp($p$$Register, $q$$constant);
6969
__ add($z$$Register, $y$$Register, $z$$Register, lt);
6971
ins_pipe( cadd_cmpltmask );
6974
instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
6975
match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
6977
ins_cost(DEFAULT_COST*2);
6978
format %{ "SUBS $p,$p,$q\n\t"
6979
"ADD.lt $p,$y,$p" %}
6981
__ subs($p$$Register, $p$$Register, $q$$Register);
6982
__ add($p$$Register, $y$$Register, $p$$Register, lt);
6984
ins_pipe( cadd_cmpltmask );
6987
//----------Arithmetic Conversion Instructions---------------------------------
6988
// The conversions operations are all Alpha sorted. Please keep it that way!
6990
instruct convD2F_reg(regF dst, regD src) %{
6991
match(Set dst (ConvD2F src));
6993
format %{ "FCVTSD $dst,$src" %}
6995
__ convert_d2f($dst$$FloatRegister, $src$$FloatRegister);
7000
// Convert a double to an int in a float register.
7001
// If the double is a NAN, stuff a zero in instead.
7003
instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{
7004
match(Set dst (ConvD2I src));
7006
ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7007
format %{ "FTOSIZD $tmp,$src\n\t"
7008
"FMRS $dst, $tmp" %}
7010
__ ftosizd($tmp$$FloatRegister, $src$$FloatRegister);
7011
__ fmrs($dst$$Register, $tmp$$FloatRegister);
7016
// Convert a double to a long in a double register.
7017
// If the double is a NAN, stuff a zero in instead.
7019
// Double to Long conversion
7020
instruct convD2L_reg(R0R1RegL dst, regD src) %{
7021
match(Set dst (ConvD2L src));
7023
ins_cost(MEMORY_REF_COST); // FIXME
7024
format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %}
7027
__ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7029
if ($src$$FloatRegister != D0) {
7030
__ mov_double(D0, $src$$FloatRegister);
7033
address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
7034
__ call(target, relocInfo::runtime_call_type);
7039
instruct convF2D_reg(regD dst, regF src) %{
7040
match(Set dst (ConvF2D src));
7042
format %{ "FCVTDS $dst,$src" %}
7044
__ convert_f2d($dst$$FloatRegister, $src$$FloatRegister);
7049
instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{
7050
match(Set dst (ConvF2I src));
7052
ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7054
format %{ "FTOSIZS $tmp,$src\n\t"
7055
"FMRS $dst, $tmp" %}
7057
__ ftosizs($tmp$$FloatRegister, $src$$FloatRegister);
7058
__ fmrs($dst$$Register, $tmp$$FloatRegister);
7063
// Float to Long conversion
7064
instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{
7065
match(Set dst (ConvF2L src));
7066
ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7068
format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %}
7071
__ fmrs($arg1$$Register, $src$$FloatRegister);
7073
if($src$$FloatRegister != S0) {
7074
__ mov_float(S0, $src$$FloatRegister);
7077
address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
7078
__ call(target, relocInfo::runtime_call_type);
7083
instruct convI2D_reg_reg(iRegI src, regD_low dst) %{
7084
match(Set dst (ConvI2D src));
7085
ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7087
format %{ "FMSR $dst,$src \n\t"
7088
"FSITOD $dst $dst"%}
7090
__ fmsr($dst$$FloatRegister, $src$$Register);
7091
__ fsitod($dst$$FloatRegister, $dst$$FloatRegister);
7096
instruct convI2F_reg_reg( regF dst, iRegI src ) %{
7097
match(Set dst (ConvI2F src));
7098
ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7100
format %{ "FMSR $dst,$src \n\t"
7101
"FSITOS $dst, $dst"%}
7103
__ fmsr($dst$$FloatRegister, $src$$Register);
7104
__ fsitos($dst$$FloatRegister, $dst$$FloatRegister);
7109
instruct convI2L_reg(iRegL dst, iRegI src) %{
7110
match(Set dst (ConvI2L src));
7112
format %{ "MOV $dst.lo, $src \n\t"
7113
"ASR $dst.hi,$src,31\t! int->long" %}
7115
__ mov($dst$$Register, $src$$Register);
7116
__ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31));
7118
ins_pipe(ialu_reg_reg);
7121
// Zero-extend convert int to long
7122
instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{
7123
match(Set dst (AndL (ConvI2L src) mask) );
7125
format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t"
7128
__ mov($dst$$Register, $src$$Register);
7129
__ mov($dst$$Register->successor(), 0);
7131
ins_pipe(ialu_reg_reg);
7135
instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
7136
match(Set dst (AndL src mask) );
7138
format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t"
7141
__ mov($dst$$Register, $src$$Register);
7142
__ mov($dst$$Register->successor(), 0);
7144
ins_pipe(ialu_reg_reg);
7147
instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
7148
match(Set dst (MoveF2I src));
7149
effect(DEF dst, USE src);
7150
ins_cost(MEMORY_REF_COST); // FIXME
7153
format %{ "FMRS $dst,$src\t! MoveF2I" %}
7155
__ fmrs($dst$$Register, $src$$FloatRegister);
7157
ins_pipe(iload_mem); // FIXME
7160
instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
7161
match(Set dst (MoveI2F src));
7162
ins_cost(MEMORY_REF_COST); // FIXME
7165
format %{ "FMSR $dst,$src\t! MoveI2F" %}
7167
__ fmsr($dst$$FloatRegister, $src$$Register);
7169
ins_pipe(iload_mem); // FIXME
7172
instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
7173
match(Set dst (MoveD2L src));
7174
effect(DEF dst, USE src);
7175
ins_cost(MEMORY_REF_COST); // FIXME
7178
format %{ "FMRRD $dst,$src\t! MoveD2L" %}
7180
__ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7182
ins_pipe(iload_mem); // FIXME
7185
instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
7186
match(Set dst (MoveL2D src));
7187
effect(DEF dst, USE src);
7188
ins_cost(MEMORY_REF_COST); // FIXME
7191
format %{ "FMDRR $dst,$src\t! MoveL2D" %}
7193
__ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7195
ins_pipe(ialu_reg_reg); // FIXME
7199
// Long to Double conversion
7201
// Magic constant, 0x43300000
7202
instruct loadConI_x43300000(iRegI dst) %{
7205
format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %}
7207
__ mov_slow($dst$$Register, 0x43300000);
7209
ins_pipe(ialu_none);
7212
// Magic constant, 0x41f00000
7213
instruct loadConI_x41f00000(iRegI dst) %{
7216
format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %}
7218
__ mov_slow($dst$$Register, 0x41f00000);
7220
ins_pipe(ialu_none);
7223
instruct loadConI_x0(iRegI dst) %{
7226
format %{ "MOV $dst, 0x0\t! 0" %}
7228
__ mov($dst$$Register, 0);
7230
ins_pipe(ialu_none);
7233
// Construct a double from two float halves
7234
instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{
7235
effect(DEF dst, USE src1, USE src2);
7237
format %{ "FCPYS $dst.hi,$src1.hi\n\t"
7238
"FCPYS $dst.lo,$src2.lo" %}
7240
__ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor());
7241
__ fcpys($dst$$FloatRegister, $src2$$FloatRegister);
7243
ins_pipe(faddD_reg_reg);
7246
// Convert integer in high half of a double register (in the lower half of
7247
// the double register file) to double
7248
instruct convI2D_regDHi_regD(regD dst, regD_low src) %{
7249
effect(DEF dst, USE src);
7251
format %{ "FSITOD $dst,$src" %}
7253
__ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor());
7255
ins_pipe(fcvtLHi2D);
7258
// Add float double precision
7259
instruct addD_regD_regD(regD dst, regD src1, regD src2) %{
7260
effect(DEF dst, USE src1, USE src2);
7262
format %{ "FADDD $dst,$src1,$src2" %}
7264
__ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7266
ins_pipe(faddD_reg_reg);
7269
// Sub float double precision
7270
instruct subD_regD_regD(regD dst, regD src1, regD src2) %{
7271
effect(DEF dst, USE src1, USE src2);
7273
format %{ "FSUBD $dst,$src1,$src2" %}
7275
__ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7277
ins_pipe(faddD_reg_reg);
7280
// Mul float double precision
7281
instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{
7282
effect(DEF dst, USE src1, USE src2);
7284
format %{ "FMULD $dst,$src1,$src2" %}
7286
__ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7288
ins_pipe(fmulD_reg_reg);
7291
instruct regL_to_regD(regD dst, iRegL src) %{
7292
// No match rule to avoid chain rule match.
7293
effect(DEF dst, USE src);
7294
ins_cost(MEMORY_REF_COST);
7296
format %{ "FMDRR $dst,$src\t! regL to regD" %}
7298
__ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7300
ins_pipe(ialu_reg_reg); // FIXME
7303
instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{
7304
// No match rule to avoid chain rule match.
7305
effect(DEF dst, USE src1, USE src2);
7306
ins_cost(MEMORY_REF_COST);
7308
format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %}
7310
__ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register);
7312
ins_pipe(ialu_reg_reg); // FIXME
7315
instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{
7316
match(Set dst (ConvL2D src));
7317
ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME
7324
regD_low dx43300000;
7331
regL_to_regD(tmpsrc, src);
7333
loadConI_x43300000(ix43300000);
7334
loadConI_x41f00000(ix41f00000);
7337
regI_regI_to_regD(dx43300000, ix0, ix43300000);
7338
regI_regI_to_regD(dx41f00000, ix0, ix41f00000);
7340
convI2D_regDHi_regD(tmp1, tmpsrc);
7341
regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc);
7342
subD_regD_regD(tmp3, tmp2, dx43300000);
7343
mulD_regD_regD(tmp4, tmp1, dx41f00000);
7344
addD_regD_regD(dst, tmp3, tmp4);
7348
instruct convL2I_reg(iRegI dst, iRegL src) %{
7349
match(Set dst (ConvL2I src));
7351
format %{ "MOV $dst,$src.lo\t! long->int" %}
7353
__ mov($dst$$Register, $src$$Register);
7355
ins_pipe(ialu_move_reg_I_to_L);
7358
// Register Shift Right Immediate
7359
instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{
7360
match(Set dst (ConvL2I (RShiftL src cnt)));
7362
format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %}
7364
if ($cnt$$constant == 32) {
7365
__ mov($dst$$Register, $src$$Register->successor());
7367
__ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32));
7370
ins_pipe(ialu_reg_imm);
7374
//----------Control Flow Instructions------------------------------------------
7375
// Compare Instructions
7377
instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{
7378
match(Set icc (CmpI op1 op2));
7379
effect( DEF icc, USE op1, USE op2 );
7382
format %{ "cmp_32 $op1,$op2\t! int" %}
7384
__ cmp_32($op1$$Register, $op2$$Register);
7386
ins_pipe(ialu_cconly_reg_reg);
7390
// Compare compressed pointers
7391
instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{
7392
match(Set icc (CmpN op1 op2));
7393
effect( DEF icc, USE op1, USE op2 );
7396
format %{ "cmp_32 $op1,$op2\t! int" %}
7398
__ cmp_32($op1$$Register, $op2$$Register);
7400
ins_pipe(ialu_cconly_reg_reg);
7404
instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
7405
match(Set icc (CmpU op1 op2));
7408
format %{ "cmp_32 $op1,$op2\t! unsigned int" %}
7410
__ cmp_32($op1$$Register, $op2$$Register);
7412
ins_pipe(ialu_cconly_reg_reg);
7415
instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{
7416
match(Set icc (CmpI op1 op2));
7417
effect( DEF icc, USE op1 );
7420
format %{ "cmn_32 $op1,-$op2\t! int" %}
7422
__ cmn_32($op1$$Register, -$op2$$constant);
7424
ins_pipe(ialu_cconly_reg_imm);
7427
instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{
7428
match(Set icc (CmpI op1 op2));
7429
effect( DEF icc, USE op1 );
7432
format %{ "cmp_32 $op1,$op2\t! int" %}
7434
__ cmp_32($op1$$Register, $op2$$constant);
7436
ins_pipe(ialu_cconly_reg_imm);
7439
instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{
7440
match(Set icc (CmpI (AndI op1 op2) zero));
7442
format %{ "tst_32 $op2,$op1" %}
7445
__ tst_32($op1$$Register, $op2$$Register);
7447
ins_pipe(ialu_cconly_reg_reg_zero);
7450
instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7451
match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7453
format %{ "TST $op2,$op1<<$op3" %}
7456
__ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register));
7458
ins_pipe(ialu_cconly_reg_reg_zero);
7461
instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7462
match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7464
format %{ "tst_32 $op2,$op1<<$op3" %}
7467
__ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant));
7469
ins_pipe(ialu_cconly_reg_reg_zero);
7472
instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7473
match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7475
format %{ "TST $op2,$op1<<$op3" %}
7478
__ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register));
7480
ins_pipe(ialu_cconly_reg_reg_zero);
7483
instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7484
match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7486
format %{ "tst_32 $op2,$op1<<$op3" %}
7489
__ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant));
7491
ins_pipe(ialu_cconly_reg_reg_zero);
7494
instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7495
match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7497
format %{ "TST $op2,$op1<<$op3" %}
7500
__ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register));
7502
ins_pipe(ialu_cconly_reg_reg_zero);
7505
instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7506
match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7508
format %{ "tst_32 $op2,$op1<<$op3" %}
7511
__ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant));
7513
ins_pipe(ialu_cconly_reg_reg_zero);
7516
instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{
7517
match(Set icc (CmpI (AndI op1 op2) zero));
7519
format %{ "tst_32 $op2,$op1" %}
7522
__ tst_32($op1$$Register, $op2$$constant);
7524
ins_pipe(ialu_cconly_reg_imm_zero);
7527
instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7528
match(Set xcc (CmpL op1 op2));
7529
effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7532
format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t"
7533
"SBCS $tmp,$op1.hi,$op2.hi" %}
7535
__ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7536
__ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7538
ins_pipe(ialu_cconly_reg_reg);
7541
instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7542
match(Set xcc (CmpUL op1 op2));
7543
effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7546
format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
7547
"SBCS $tmp,$op1.hi,$op2.hi" %}
7549
__ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7550
__ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7552
ins_pipe(ialu_cconly_reg_reg);
7555
instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
7556
match(Set xcc (CmpL op1 op2));
7557
effect( DEF xcc, USE op1, USE op2 );
7560
format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t"
7561
"TEQ.eq $op1.lo,$op2.lo" %}
7563
__ teq($op1$$Register->successor(), $op2$$Register->successor());
7564
__ teq($op1$$Register, $op2$$Register, eq);
7566
ins_pipe(ialu_cconly_reg_reg);
7569
instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7570
match(Set xcc (CmpL op1 op2));
7571
effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7574
format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t"
7575
"SBCS $tmp,$op2.hi,$op1.hi" %}
7577
__ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7578
__ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7580
ins_pipe(ialu_cconly_reg_reg);
7583
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7584
// (hi($con$$constant), lo($con$$constant)) becomes
7585
instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7586
match(Set xcc (CmpL op1 con));
7587
effect( DEF xcc, USE op1, USE con, TEMP tmp );
7590
format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t"
7591
"SBCS $tmp,$op1.hi,0" %}
7593
__ subs($tmp$$Register, $op1$$Register, $con$$constant);
7594
__ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7597
ins_pipe(ialu_cconly_reg_reg);
7600
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7601
// (hi($con$$constant), lo($con$$constant)) becomes
7602
instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{
7603
match(Set xcc (CmpL op1 con));
7604
effect( DEF xcc, USE op1, USE con );
7607
format %{ "TEQ $op1.hi,0\t\t! long\n\t"
7608
"TEQ.eq $op1.lo,$con" %}
7610
__ teq($op1$$Register->successor(), 0);
7611
__ teq($op1$$Register, $con$$constant, eq);
7614
ins_pipe(ialu_cconly_reg_reg);
7617
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7618
// (hi($con$$constant), lo($con$$constant)) becomes
7619
instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7620
match(Set xcc (CmpL op1 con));
7621
effect( DEF xcc, USE op1, USE con, TEMP tmp );
7624
format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t"
7625
"RSCS $tmp,$op1.hi,0" %}
7627
__ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7628
__ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7631
ins_pipe(ialu_cconly_reg_reg);
7634
instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
7635
match(Set xcc (CmpUL op1 op2));
7636
effect(DEF xcc, USE op1, USE op2);
7639
format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t"
7640
"TEQ.eq $op1.lo,$op2.lo" %}
7642
__ teq($op1$$Register->successor(), $op2$$Register->successor());
7643
__ teq($op1$$Register, $op2$$Register, eq);
7645
ins_pipe(ialu_cconly_reg_reg);
7648
instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7649
match(Set xcc (CmpUL op1 op2));
7650
effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7653
format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
7654
"SBCS $tmp,$op2.hi,$op1.hi" %}
7656
__ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7657
__ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7659
ins_pipe(ialu_cconly_reg_reg);
7662
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7663
// (hi($con$$constant), lo($con$$constant)) becomes
7664
instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7665
match(Set xcc (CmpUL op1 con));
7666
effect(DEF xcc, USE op1, USE con, TEMP tmp);
7669
format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7670
"SBCS $tmp,$op1.hi,0" %}
7672
__ subs($tmp$$Register, $op1$$Register, $con$$constant);
7673
__ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7676
ins_pipe(ialu_cconly_reg_reg);
7679
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7680
// (hi($con$$constant), lo($con$$constant)) becomes
7681
instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
7682
match(Set xcc (CmpUL op1 con));
7683
effect(DEF xcc, USE op1, USE con);
7686
format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t"
7687
"TEQ.eq $op1.lo,$con" %}
7689
__ teq($op1$$Register->successor(), 0);
7690
__ teq($op1$$Register, $con$$constant, eq);
7693
ins_pipe(ialu_cconly_reg_reg);
7696
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7697
// (hi($con$$constant), lo($con$$constant)) becomes
7698
instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7699
match(Set xcc (CmpUL op1 con));
7700
effect(DEF xcc, USE op1, USE con, TEMP tmp);
7703
format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7704
"RSCS $tmp,$op1.hi,0" %}
7706
__ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7707
__ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7710
ins_pipe(ialu_cconly_reg_reg);
7713
/* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
7714
/* match(Set xcc (CmpL (AndL op1 op2) zero)); */
7716
/* __ stop("testL_reg_reg unimplemented"); */
7718
/* ins_pipe(ialu_cconly_reg_reg); */
7721
/* // useful for checking the alignment of a pointer: */
7722
/* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */
7723
/* match(Set xcc (CmpL (AndL op1 con) zero)); */
7725
/* __ stop("testL_reg_con unimplemented"); */
7727
/* ins_pipe(ialu_cconly_reg_reg); */
7730
instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{
7731
match(Set icc (CmpU op1 op2));
7734
format %{ "cmp_32 $op1,$op2\t! unsigned" %}
7736
__ cmp_32($op1$$Register, $op2$$constant);
7738
ins_pipe(ialu_cconly_reg_imm);
7742
instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
7743
match(Set pcc (CmpP op1 op2));
7746
format %{ "CMP $op1,$op2\t! ptr" %}
7748
__ cmp($op1$$Register, $op2$$Register);
7750
ins_pipe(ialu_cconly_reg_reg);
7753
instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{
7754
match(Set pcc (CmpP op1 op2));
7757
format %{ "CMP $op1,$op2\t! ptr" %}
7759
assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?");
7760
__ cmp($op1$$Register, $op2$$constant);
7762
ins_pipe(ialu_cconly_reg_imm);
7765
//----------Max and Min--------------------------------------------------------
7767
// Conditional move for min
7768
instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{
7769
effect( USE_DEF op2, USE op1, USE icc );
7772
format %{ "MOV.lt $op2,$op1\t! min" %}
7774
__ mov($op2$$Register, $op1$$Register, lt);
7776
ins_pipe(ialu_reg_flags);
7779
// Min Register with Register.
7780
instruct minI_eReg(iRegI op1, iRegI op2) %{
7781
match(Set op2 (MinI op1 op2));
7782
ins_cost(DEFAULT_COST*2);
7785
compI_iReg(icc,op1,op2);
7786
cmovI_reg_lt(op2,op1,icc);
7791
// Conditional move for max
7792
instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{
7793
effect( USE_DEF op2, USE op1, USE icc );
7794
format %{ "MOV.gt $op2,$op1\t! max" %}
7796
__ mov($op2$$Register, $op1$$Register, gt);
7798
ins_pipe(ialu_reg_flags);
7801
// Max Register with Register
7802
instruct maxI_eReg(iRegI op1, iRegI op2) %{
7803
match(Set op2 (MaxI op1 op2));
7804
ins_cost(DEFAULT_COST*2);
7807
compI_iReg(icc,op1,op2);
7808
cmovI_reg_gt(op2,op1,icc);
7813
//----------Float Compares----------------------------------------------------
7814
// Compare floating, generate condition code
7815
instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{
7816
match(Set icc (CmpF src1 src2));
7820
format %{ "FCMPs $src1,$src2\n\t"
7823
__ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7826
ins_pipe(faddF_fcc_reg_reg_zero);
7829
instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{
7830
match(Set icc (CmpF src1 src2));
7834
format %{ "FCMPs $src1,$src2\n\t"
7837
__ fcmpzs($src1$$FloatRegister);
7840
ins_pipe(faddF_fcc_reg_reg_zero);
7843
instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{
7844
match(Set icc (CmpD src1 src2));
7848
format %{ "FCMPd $src1,$src2 \n\t"
7851
__ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7854
ins_pipe(faddD_fcc_reg_reg_zero);
7857
instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{
7858
match(Set icc (CmpD src1 src2));
7862
format %{ "FCMPZd $src1,$src2 \n\t"
7865
__ fcmpzd($src1$$FloatRegister);
7868
ins_pipe(faddD_fcc_reg_reg_zero);
7871
// Compare floating, generate -1,0,1
7872
instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{
7873
match(Set dst (CmpF3 src1 src2));
7875
ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7877
// same number of instructions as code using conditional moves but
7878
// doesn't kill integer condition register
7879
format %{ "FCMPs $dst,$src1,$src2 \n\t"
7880
"VMRS $dst, FPSCR \n\t"
7881
"OR $dst, $dst, 0x08000000 \n\t"
7882
"EOR $dst, $dst, $dst << 3 \n\t"
7883
"MOV $dst, $dst >> 30" %}
7885
__ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7886
__ floating_cmp($dst$$Register);
7888
ins_pipe( floating_cmp );
7891
instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{
7892
match(Set dst (CmpF3 src1 src2));
7894
ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7896
// same number of instructions as code using conditional moves but
7897
// doesn't kill integer condition register
7898
format %{ "FCMPZs $dst,$src1,$src2 \n\t"
7899
"VMRS $dst, FPSCR \n\t"
7900
"OR $dst, $dst, 0x08000000 \n\t"
7901
"EOR $dst, $dst, $dst << 3 \n\t"
7902
"MOV $dst, $dst >> 30" %}
7904
__ fcmpzs($src1$$FloatRegister);
7905
__ floating_cmp($dst$$Register);
7907
ins_pipe( floating_cmp );
7910
instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{
7911
match(Set dst (CmpD3 src1 src2));
7913
ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7915
// same number of instructions as code using conditional moves but
7916
// doesn't kill integer condition register
7917
format %{ "FCMPd $dst,$src1,$src2 \n\t"
7918
"VMRS $dst, FPSCR \n\t"
7919
"OR $dst, $dst, 0x08000000 \n\t"
7920
"EOR $dst, $dst, $dst << 3 \n\t"
7921
"MOV $dst, $dst >> 30" %}
7923
__ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7924
__ floating_cmp($dst$$Register);
7926
ins_pipe( floating_cmp );
7929
instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{
7930
match(Set dst (CmpD3 src1 src2));
7932
ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7934
// same number of instructions as code using conditional moves but
7935
// doesn't kill integer condition register
7936
format %{ "FCMPZd $dst,$src1,$src2 \n\t"
7937
"VMRS $dst, FPSCR \n\t"
7938
"OR $dst, $dst, 0x08000000 \n\t"
7939
"EOR $dst, $dst, $dst << 3 \n\t"
7940
"MOV $dst, $dst >> 30" %}
7942
__ fcmpzd($src1$$FloatRegister);
7943
__ floating_cmp($dst$$Register);
7945
ins_pipe( floating_cmp );
7948
//----------Branches---------------------------------------------------------
7950
// (compare 'operand indIndex' and 'instruct addP_reg_reg' above)
7952
instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{
7953
match(Jump switch_val);
7956
format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t"
7957
"LDR $tmp,[$tmp + $constantoffset]\n\t"
7962
Register label_reg = $tmp$$Register;
7963
if (constant_offset() == 0) {
7964
table_reg = $constanttablebase;
7965
__ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7967
table_reg = $tmp$$Register;
7968
int offset = $constantoffset;
7969
if (is_memoryP(offset)) {
7970
__ add(table_reg, $constanttablebase, $switch_val$$Register);
7971
__ ldr(label_reg, Address(table_reg, offset));
7973
__ mov_slow(table_reg, $constantoffset);
7974
__ add(table_reg, $constanttablebase, table_reg);
7975
__ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7978
__ jump(label_reg); // ldr + b better than ldr to PC for branch predictor?
7979
// __ ldr(PC, Address($table$$Register, $switch_val$$Register));
7981
ins_pipe(ialu_reg_reg);
7985
instruct branch(label labl) %{
7990
ins_cost(BRANCH_COST);
7991
format %{ "B $labl" %}
7993
__ b(*($labl$$label));
7998
// Conditional Direct Branch
7999
instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
8004
ins_cost(BRANCH_COST);
8005
format %{ "B$cmp $icc,$labl" %}
8007
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8013
instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{
8016
predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8019
ins_cost(BRANCH_COST);
8020
format %{ "B$cmp $icc,$labl" %}
8022
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8029
instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
8034
ins_cost(BRANCH_COST);
8035
format %{ "B$cmp $icc,$labl" %}
8037
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8042
instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{
8047
ins_cost(BRANCH_COST);
8048
format %{ "B$cmp $pcc,$labl" %}
8050
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8055
instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{
8058
predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8061
ins_cost(BRANCH_COST);
8062
format %{ "B$cmp $xcc,$labl" %}
8064
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8069
instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{
8072
predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8075
ins_cost(BRANCH_COST);
8076
format %{ "B$cmp $xcc,$labl" %}
8078
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8083
instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
8086
predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
8089
ins_cost(BRANCH_COST);
8090
format %{ "B$cmp $xcc,$labl" %}
8092
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8097
instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
8100
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8103
ins_cost(BRANCH_COST);
8104
format %{ "B$cmp $xcc,$labl" %}
8106
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8111
instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
8114
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8117
ins_cost(BRANCH_COST);
8118
format %{ "B$cmp $xcc,$labl" %}
8120
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8125
instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
8128
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
8131
ins_cost(BRANCH_COST);
8132
format %{ "B$cmp $xcc,$labl" %}
8134
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8139
instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
8140
match(CountedLoopEnd cmp icc);
8144
ins_cost(BRANCH_COST);
8145
format %{ "B$cmp $icc,$labl\t! Loop end" %}
8147
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8152
// instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{
8153
// match(CountedLoopEnd cmp icc);
8157
// ============================================================================
8160
// Currently we hold longs in 2 registers. Comparing such values efficiently
8161
// is tricky. The flavor of compare used depends on whether we are testing
8162
// for LT, LE, or EQ. For a simple LT test we can check just the sign bit.
8163
// The GE test is the negated LT test. The LE test can be had by commuting
8164
// the operands (yielding a GE test) and then negating; negate again for the
8165
// GT test. The EQ test is done by ORcc'ing the high and low halves, and the
8166
// NE test is negated from that.
8168
// Due to a shortcoming in the ADLC, it mixes up expressions like:
8169
// (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the
8170
// difference between 'Y' and '0L'. The tree-matches for the CmpI sections
8171
// are collapsed internally in the ADLC's dfa-gen code. The match for
8172
// (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
8173
// foo match ends up with the wrong leaf. One fix is to not match both
8174
// reg-reg and reg-zero forms of long-compare. This is unfortunate because
8175
// both forms beat the trinary form of long-compare and both are very useful
8176
// on Intel which has so few registers.
8178
// instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
8179
// match(If cmp xcc);
8183
// Manifest a CmpL3 result in an integer register. Very painful.
8184
// This is the test to avoid.
8185
instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
8186
match(Set dst (CmpL3 src1 src2) );
8188
ins_cost(6*DEFAULT_COST); // FIXME
8191
"CMP $src1.hi, $src2.hi\t\t! long\n"
8192
"\tMOV.gt $dst, 1\n"
8193
"\tmvn.lt $dst, 0\n"
8195
"\tSUBS $dst, $src1.lo, $src2.lo\n"
8196
"\tMOV.hi $dst, 1\n"
8197
"\tmvn.lo $dst, 0\n"
8201
__ cmp($src1$$Register->successor(), $src2$$Register->successor());
8202
__ mov($dst$$Register, 1, gt);
8203
__ mvn($dst$$Register, 0, lt);
8205
__ subs($dst$$Register, $src1$$Register, $src2$$Register);
8206
__ mov($dst$$Register, 1, hi);
8207
__ mvn($dst$$Register, 0, lo);
8214
instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{
8215
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8216
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8220
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8221
"MOV$cmp $dst,$src.hi" %}
8223
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8224
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8229
instruct cmovLL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{
8230
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8231
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8235
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8236
"MOV$cmp $dst,$src.hi" %}
8238
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8239
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8244
instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{
8245
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8246
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8250
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8251
"MOV$cmp $dst,$src.hi" %}
8253
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8254
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8259
instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{
8260
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8261
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8265
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8266
"MOV$cmp $dst,$src.hi" %}
8268
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8269
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8274
instruct cmovLL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{
8275
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8276
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8280
format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8281
"MOV$cmp $dst,$src.hi" %}
8283
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8284
__ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8289
instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{
8290
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8291
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8294
format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8297
__ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8298
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8303
instruct cmovLL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{
8304
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8305
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8308
format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8311
__ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8312
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8317
instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{
8318
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8319
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8322
format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8325
__ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8326
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8331
instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{
8332
match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8333
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8336
format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8339
__ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8340
__ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8345
instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{
8346
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8347
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8351
format %{ "MOV$cmp $dst,$src" %}
8353
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8358
instruct cmovIL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, iRegI src) %{
8359
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8360
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8364
format %{ "MOV$cmp $dst,$src" %}
8366
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8371
instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{
8372
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8373
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8377
format %{ "MOV$cmp $dst,$src" %}
8379
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8384
instruct cmovIL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, iRegI src) %{
8385
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8386
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8390
format %{ "MOV$cmp $dst,$src" %}
8392
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8397
instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{
8398
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8399
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8403
format %{ "MOV$cmp $dst,$src" %}
8405
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8410
instruct cmovIL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, iRegI src) %{
8411
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8412
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8416
format %{ "MOV$cmp $dst,$src" %}
8418
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8423
instruct cmovIL_imm16_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{
8424
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8425
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8429
format %{ "MOVW$cmp $dst,$src" %}
8431
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8436
instruct cmovIL_imm16_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immI16 src) %{
8437
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8438
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8442
format %{ "MOVW$cmp $dst,$src" %}
8444
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8449
instruct cmovIL_imm16_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{
8450
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8451
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8455
format %{ "MOVW$cmp $dst,$src" %}
8457
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8462
instruct cmovIL_imm16_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immI16 src) %{
8463
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8464
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8468
format %{ "MOVW$cmp $dst,$src" %}
8470
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8475
instruct cmovIL_imm16_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{
8476
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8477
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8481
format %{ "MOVW$cmp $dst,$src" %}
8483
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8488
instruct cmovIL_imm16_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immI16 src) %{
8489
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8490
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8494
format %{ "MOVW$cmp $dst,$src" %}
8496
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8501
instruct cmovIL_immMov_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immIMov src) %{
8502
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8503
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8507
format %{ "MOV$cmp $dst,$src" %}
8509
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8514
instruct cmovIL_immMov_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immIMov src) %{
8515
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8516
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8520
format %{ "MOV$cmp $dst,$src" %}
8522
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8527
instruct cmovIL_immMov_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immIMov src) %{
8528
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8529
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8533
format %{ "MOV$cmp $dst,$src" %}
8535
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8540
instruct cmovIL_immMov_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immIMov src) %{
8541
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8542
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8546
format %{ "MOV$cmp $dst,$src" %}
8548
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8553
instruct cmovIL_immMov_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immIMov src) %{
8554
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8555
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8559
format %{ "MOV$cmp $dst,$src" %}
8561
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8566
instruct cmovIL_immMov_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immIMov src) %{
8567
match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8568
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8572
format %{ "MOV$cmp $dst,$src" %}
8574
__ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8579
instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{
8580
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8581
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8585
format %{ "MOV$cmp $dst,$src" %}
8587
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8592
instruct cmovPL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, iRegP src) %{
8593
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8594
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8598
format %{ "MOV$cmp $dst,$src" %}
8600
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8605
instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{
8606
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8607
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8611
format %{ "MOV$cmp $dst,$src" %}
8613
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8618
instruct cmovPL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, iRegP src) %{
8619
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8620
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8624
format %{ "MOV$cmp $dst,$src" %}
8626
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8631
instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{
8632
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8633
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8637
format %{ "MOV$cmp $dst,$src" %}
8639
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8644
instruct cmovPL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, iRegP src) %{
8645
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8646
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8650
format %{ "MOV$cmp $dst,$src" %}
8652
__ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8657
instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{
8658
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8659
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8663
format %{ "MOVW$cmp $dst,$src" %}
8665
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8670
instruct cmovPL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, immP0 src) %{
8671
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8672
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8676
format %{ "MOVW$cmp $dst,$src" %}
8678
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8683
instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{
8684
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8685
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8689
format %{ "MOVW$cmp $dst,$src" %}
8691
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8696
instruct cmovPL_imm_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, immP0 src) %{
8697
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8698
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8702
format %{ "MOVW$cmp $dst,$src" %}
8704
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8709
instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{
8710
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8711
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8715
format %{ "MOVW$cmp $dst,$src" %}
8717
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8722
instruct cmovPL_imm_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, immP0 src) %{
8723
match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8724
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8728
format %{ "MOVW$cmp $dst,$src" %}
8730
__ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8735
instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{
8736
match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8737
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8740
format %{ "FCPYS$cmp $dst,$src" %}
8742
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8744
ins_pipe(int_conditional_float_move);
8747
instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{
8748
match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8749
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8752
format %{ "FCPYS$cmp $dst,$src" %}
8754
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8756
ins_pipe(int_conditional_float_move);
8759
instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{
8760
match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8761
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8764
format %{ "FCPYS$cmp $dst,$src" %}
8766
__ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8768
ins_pipe(int_conditional_float_move);
8771
instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{
8772
match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8773
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8777
format %{ "FCPYD$cmp $dst,$src" %}
8779
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8781
ins_pipe(int_conditional_float_move);
8784
instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{
8785
match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8786
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8790
format %{ "FCPYD$cmp $dst,$src" %}
8792
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8794
ins_pipe(int_conditional_float_move);
8797
instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{
8798
match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8799
predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8803
format %{ "FCPYD$cmp $dst,$src" %}
8805
__ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8807
ins_pipe(int_conditional_float_move);
8810
// ============================================================================
8811
// Safepoint Instruction
8812
// rather than KILL R12, it would be better to use any reg as
8813
// TEMP. Can't do that at this point because it crashes the compiler
8814
instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
8815
match(SafePoint poll);
8816
effect(USE poll, KILL tmp, KILL icc);
8819
format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %}
8821
__ relocate(relocInfo::poll_type);
8822
__ ldr($tmp$$Register, Address($poll$$Register));
8824
ins_pipe(loadPollP);
8828
// ============================================================================
8830
// Call Java Static Instruction
8831
instruct CallStaticJavaDirect( method meth ) %{
8832
match(CallStaticJava);
8833
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
8836
ins_cost(CALL_COST);
8837
format %{ "CALL,static ==> " %}
8838
ins_encode( SetInstMark, Java_Static_Call( meth ), call_epilog, ClearInstMark );
8839
ins_pipe(simple_call);
8842
// Call Java Static Instruction (method handle version)
8843
instruct CallStaticJavaHandle( method meth ) %{
8844
match(CallStaticJava);
8845
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
8847
// FP is saved by all callees (for interpreter stack correction).
8848
// We use it here for a similar purpose, in {preserve,restore}_FP.
8850
ins_cost(CALL_COST);
8851
format %{ "CALL,static/MethodHandle ==> " %}
8852
ins_encode( SetInstMark, preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog, ClearInstMark );
8853
ins_pipe(simple_call);
8856
// Call Java Dynamic Instruction
8857
instruct CallDynamicJavaDirect( method meth ) %{
8858
match(CallDynamicJava);
8861
ins_cost(CALL_COST);
8862
format %{ "MOV_OOP (empty),R_R8\n\t"
8863
"CALL,dynamic ; NOP ==> " %}
8864
ins_encode( SetInstMark, Java_Dynamic_Call( meth ), call_epilog, ClearInstMark );
8868
// Call Runtime Instruction
8869
instruct CallRuntimeDirect(method meth) %{
8872
ins_cost(CALL_COST);
8873
format %{ "CALL,runtime" %}
8874
ins_encode( SetInstMark, Java_To_Runtime( meth ),
8875
call_epilog, ClearInstMark );
8876
ins_pipe(simple_call);
8879
// Call runtime without safepoint - same as CallRuntime
8880
instruct CallLeafDirect(method meth) %{
8883
ins_cost(CALL_COST);
8884
format %{ "CALL,runtime leaf" %}
8885
// TODO: need save_last_PC here?
8886
ins_encode( SetInstMark, Java_To_Runtime( meth ),
8887
call_epilog, ClearInstMark );
8888
ins_pipe(simple_call);
8891
// Call runtime without safepoint - same as CallLeaf
8892
instruct CallLeafNoFPDirect(method meth) %{
8893
match(CallLeafNoFP);
8895
ins_cost(CALL_COST);
8896
format %{ "CALL,runtime leaf nofp" %}
8897
// TODO: need save_last_PC here?
8898
ins_encode( SetInstMark, Java_To_Runtime( meth ),
8899
call_epilog, ClearInstMark );
8900
ins_pipe(simple_call);
8903
// Tail Call; Jump from runtime stub to Java code.
8904
// Also known as an 'interprocedural jump'.
8905
// Target of jump will eventually return to caller.
8906
// TailJump below removes the return address.
8907
instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{
8908
match(TailCall jump_target method_ptr);
8910
ins_cost(CALL_COST);
8911
format %{ "MOV Rexception_pc, LR\n\t"
8912
"jump $jump_target \t! $method_ptr holds method" %}
8914
__ mov(Rexception_pc, LR); // this is used only to call
8915
// StubRoutines::forward_exception_entry()
8916
// which expects PC of exception in
8918
__ jump($jump_target$$Register);
8920
ins_pipe(tail_call);
8924
// Return Instruction
8928
format %{ "ret LR" %}
8938
// Tail Jump; remove the return address; jump to target.
8939
// TailCall above leaves the return address around.
8940
// TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2).
8941
// ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a
8942
// "restore" before this instruction (in Epilogue), we need to materialize it
8944
instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{
8945
match( TailJump jump_target ex_oop );
8946
ins_cost(CALL_COST);
8947
format %{ "MOV Rexception_pc, LR\n\t"
8948
"jump $jump_target \t! $ex_oop holds exc. oop" %}
8950
__ mov(Rexception_pc, LR);
8951
__ jump($jump_target$$Register);
8953
ins_pipe(tail_call);
8956
// Create exception oop: created by stack-crawling runtime code.
8957
// Created exception is now available to this handler, and is setup
8958
// just prior to jumping to this handler. No code emitted.
8959
instruct CreateException( RExceptionRegP ex_oop )
8961
match(Set ex_oop (CreateEx));
8965
// use the following format syntax
8966
format %{ "! exception oop is in Rexception_obj; no code emitted" %}
8972
// Rethrow exception:
8973
// The exception oop will come in the first argument position.
8974
// Then JUMP (not call) to the rethrow stub code.
8975
instruct RethrowException()
8978
ins_cost(CALL_COST);
8980
// use the following format syntax
8981
format %{ "b rethrow_stub" %}
8983
Register scratch = R1_tmp;
8984
assert_different_registers(scratch, c_rarg0, LR);
8985
__ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch);
8987
ins_pipe(tail_call);
8992
instruct ShouldNotReachHere( )
8995
ins_cost(CALL_COST);
8997
// Use the following format syntax
8998
format %{ "ShouldNotReachHere" %}
9000
if (is_reachable()) {
9001
__ stop(_halt_reason);
9004
ins_pipe(tail_call);
9007
// ============================================================================
9008
// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass
9009
// array for an instance of the superklass. Set a hidden internal cache on a
9010
// hit (cache is checked with exposed code in gen_subtype_check()). Return
9011
// not zero for a miss or zero for a hit. The encoding ALSO sets flags.
9012
instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{
9013
match(Set index (PartialSubtypeCheck sub super));
9014
effect( KILL pcc, KILL lr );
9015
ins_cost(DEFAULT_COST*10);
9016
format %{ "CALL PartialSubtypeCheck" %}
9018
__ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type);
9020
ins_pipe(partial_subtype_check_pipe);
9023
/* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */
9024
/* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */
9025
/* ins_pipe(partial_subtype_check_pipe); */
9029
// ============================================================================
9030
// inlined locking and unlocking
9032
instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch )
9034
match(Set pcc (FastLock object box));
9036
effect(TEMP scratch, TEMP scratch2);
9037
ins_cost(DEFAULT_COST*3);
9039
format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %}
9041
__ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
9043
ins_pipe(long_memory_op);
9046
instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{
9047
match(Set pcc (FastUnlock object box));
9048
effect(TEMP scratch, TEMP scratch2);
9051
format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %}
9053
__ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
9055
ins_pipe(long_memory_op);
9058
// Count and Base registers are fixed because the allocator cannot
9059
// kill unknown registers. The encodings are generic.
9060
instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{
9061
match(Set dummy (ClearArray cnt base));
9062
effect(TEMP temp, TEMP zero, KILL cpsr);
9064
format %{ "MOV $zero,0\n"
9066
"loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n"
9067
" STR.ge $zero,[$base+$temp]\t! delay slot"
9068
" B.gt loop\t\t! Clearing loop\n" %}
9070
__ mov($zero$$Register, 0);
9071
__ mov($temp$$Register, $cnt$$Register);
9074
__ subs($temp$$Register, $temp$$Register, 4);
9075
__ str($zero$$Register, Address($base$$Register, $temp$$Register), ge);
9078
ins_pipe(long_memory_op);
9082
// FIXME: Why R0/R1/R2/R3?
9083
instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result,
9084
iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
9085
predicate(!CompactStrings);
9086
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
9087
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2);
9089
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %}
9090
ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) );
9092
ins_pipe(long_memory_op);
9095
// FIXME: Why R0/R1/R2?
9096
instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2,
9098
predicate(!CompactStrings);
9099
match(Set result (StrEquals (Binary str1 str2) cnt));
9100
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr);
9103
format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %}
9104
ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) );
9105
ins_pipe(long_memory_op);
9109
instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result,
9111
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
9112
match(Set result (AryEq ary1 ary2));
9113
effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr);
9116
format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %}
9117
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result));
9118
ins_pipe(long_memory_op);
9122
//---------- Zeros Count Instructions ------------------------------------------
9124
instruct countLeadingZerosI(iRegI dst, iRegI src) %{
9125
match(Set dst (CountLeadingZerosI src));
9127
format %{ "CLZ_32 $dst,$src" %}
9129
__ clz_32($dst$$Register, $src$$Register);
9134
instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9135
match(Set dst (CountLeadingZerosL src));
9136
effect(TEMP tmp, TEMP dst, KILL ccr);
9138
format %{ "CLZ $dst,$src.hi\n\t"
9140
"CLZ.eq $tmp,$src.lo\n\t"
9141
"ADD.eq $dst, $dst, $tmp\n\t" %}
9143
__ clz($dst$$Register, $src$$Register->successor());
9144
__ teq($dst$$Register, 32);
9145
__ clz($tmp$$Register, $src$$Register, eq);
9146
__ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9151
instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{
9152
match(Set dst (CountTrailingZerosI src));
9155
format %{ "RBIT_32 $tmp, $src\n\t"
9156
"CLZ_32 $dst,$tmp" %}
9158
__ rbit_32($tmp$$Register, $src$$Register);
9159
__ clz_32($dst$$Register, $tmp$$Register);
9164
instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9165
match(Set dst (CountTrailingZerosL src));
9166
effect(TEMP tmp, TEMP dst, KILL ccr);
9168
format %{ "RBIT $tmp,$src.lo\n\t"
9171
"RBIT $tmp,$src.hi\n\t"
9172
"CLZ.eq $tmp,$tmp\n\t"
9173
"ADD.eq $dst,$dst,$tmp\n\t" %}
9175
__ rbit($tmp$$Register, $src$$Register);
9176
__ clz($dst$$Register, $tmp$$Register);
9177
__ teq($dst$$Register, 32);
9178
__ rbit($tmp$$Register, $src$$Register->successor());
9179
__ clz($tmp$$Register, $tmp$$Register, eq);
9180
__ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9186
//---------- Population Count Instructions -------------------------------------
9188
instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
9189
predicate(UsePopCountInstruction);
9190
match(Set dst (PopCountI src));
9193
format %{ "FMSR $tmp,$src\n\t"
9194
"VCNT.8 $tmp,$tmp\n\t"
9195
"VPADDL.U8 $tmp,$tmp\n\t"
9196
"VPADDL.U16 $tmp,$tmp\n\t"
9201
__ fmsr($tmp$$FloatRegister, $src$$Register);
9202
__ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9203
__ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9204
__ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9205
__ fmrs($dst$$Register, $tmp$$FloatRegister);
9207
ins_pipe(ialu_reg); // FIXME
9210
// Note: Long.bitCount(long) returns an int.
9211
instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{
9212
predicate(UsePopCountInstruction);
9213
match(Set dst (PopCountL src));
9216
format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t"
9217
"VCNT.8 $tmp,$tmp\n\t"
9218
"VPADDL.U8 $tmp,$tmp\n\t"
9219
"VPADDL.U16 $tmp,$tmp\n\t"
9220
"VPADDL.U32 $tmp,$tmp\n\t"
9226
__ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor());
9227
__ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9228
__ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9229
__ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9230
__ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0);
9231
__ fmrs($dst$$Register, $tmp$$FloatRegister);
9237
// ============================================================================
9238
//------------Bytes reverse--------------------------------------------------
9240
instruct bytes_reverse_int(iRegI dst, iRegI src) %{
9241
match(Set dst (ReverseBytesI src));
9244
format %{ "REV32 $dst,$src" %}
9246
__ rev($dst$$Register, $src$$Register);
9248
ins_pipe( iload_mem ); // FIXME
9251
instruct bytes_reverse_long(iRegL dst, iRegL src) %{
9252
match(Set dst (ReverseBytesL src));
9255
format %{ "REV $dst.lo,$src.lo\n\t"
9256
"REV $dst.hi,$src.hi" %}
9258
__ rev($dst$$Register, $src$$Register->successor());
9259
__ rev($dst$$Register->successor(), $src$$Register);
9261
ins_pipe( iload_mem ); // FIXME
9264
instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
9265
match(Set dst (ReverseBytesUS src));
9267
format %{ "REV16 $dst,$src" %}
9269
__ rev16($dst$$Register, $src$$Register);
9271
ins_pipe( iload_mem ); // FIXME
9274
instruct bytes_reverse_short(iRegI dst, iRegI src) %{
9275
match(Set dst (ReverseBytesS src));
9277
format %{ "REVSH $dst,$src" %}
9279
__ revsh($dst$$Register, $src$$Register);
9281
ins_pipe( iload_mem ); // FIXME
9285
// ====================VECTOR INSTRUCTIONS=====================================
9287
// Load Aligned Packed values into a Double Register
9288
instruct loadV8(vecD dst, memoryD mem) %{
9289
predicate(n->as_LoadVector()->memory_size() == 8);
9290
match(Set dst (LoadVector mem));
9291
ins_cost(MEMORY_REF_COST);
9293
format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %}
9295
__ ldr_double($dst$$FloatRegister, $mem$$Address);
9297
ins_pipe(floadD_mem);
9300
// Load Aligned Packed values into a Double Register Pair
9301
instruct loadV16(vecX dst, memoryvld mem) %{
9302
predicate(n->as_LoadVector()->memory_size() == 16);
9303
match(Set dst (LoadVector mem));
9304
ins_cost(MEMORY_REF_COST);
9306
format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %}
9308
__ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9310
ins_pipe(floadD_mem); // FIXME
9313
// Store Vector in Double register to memory
9314
instruct storeV8(memoryD mem, vecD src) %{
9315
predicate(n->as_StoreVector()->memory_size() == 8);
9316
match(Set mem (StoreVector mem src));
9317
ins_cost(MEMORY_REF_COST);
9319
format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %}
9321
__ str_double($src$$FloatRegister, $mem$$Address);
9323
ins_pipe(fstoreD_mem_reg);
9326
// Store Vector in Double Register Pair to memory
9327
instruct storeV16(memoryvld mem, vecX src) %{
9328
predicate(n->as_StoreVector()->memory_size() == 16);
9329
match(Set mem (StoreVector mem src));
9330
ins_cost(MEMORY_REF_COST);
9332
format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %}
9334
__ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9336
ins_pipe(fstoreD_mem_reg); // FIXME
9339
// Replicate scalar to packed byte values in Double register
9340
instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{
9341
predicate(n->as_Vector()->length() == 8 &&
9342
Matcher::vector_element_basic_type(n) == T_BYTE);
9343
match(Set dst (Replicate src));
9344
ins_cost(DEFAULT_COST*4);
9348
// FIXME: could use PKH instruction instead?
9349
format %{ "LSL $tmp, $src, 24 \n\t"
9350
"OR $tmp, $tmp, ($tmp >> 8) \n\t"
9351
"OR $tmp, $tmp, ($tmp >> 16) \n\t"
9352
"FMDRR $dst,$tmp,$tmp\t" %}
9354
__ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24));
9355
__ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8));
9356
__ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9357
__ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9359
ins_pipe(ialu_reg); // FIXME
9362
// Replicate scalar to packed byte values in Double register
9363
instruct Repl8B_reg_simd(vecD dst, iRegI src) %{
9364
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9365
Matcher::vector_element_basic_type(n) == T_BYTE);
9366
match(Set dst (Replicate src));
9369
format %{ "VDUP.8 $dst,$src\t" %}
9372
__ vdupI($dst$$FloatRegister, $src$$Register,
9373
MacroAssembler::VELEM_SIZE_8, quad);
9375
ins_pipe(ialu_reg); // FIXME
9378
// Replicate scalar to packed byte values in Double register pair
9379
instruct Repl16B_reg(vecX dst, iRegI src) %{
9380
predicate(n->as_Vector()->length_in_bytes() == 16 &&
9381
Matcher::vector_element_basic_type(n) == T_BYTE);
9382
match(Set dst (Replicate src));
9385
format %{ "VDUP.8 $dst.Q,$src\t" %}
9388
__ vdupI($dst$$FloatRegister, $src$$Register,
9389
MacroAssembler::VELEM_SIZE_8, quad);
9391
ins_pipe(ialu_reg); // FIXME
9394
// Replicate scalar constant to packed byte values in Double register
9395
instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{
9396
predicate(n->as_Vector()->length() == 8 &&
9397
Matcher::vector_element_basic_type(n) == T_BYTE);
9398
match(Set dst (Replicate src));
9399
ins_cost(DEFAULT_COST*2);
9403
format %{ "MOV $tmp, Repl4($src))\n\t"
9404
"FMDRR $dst,$tmp,$tmp\t" %}
9405
ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) );
9406
ins_pipe(loadConFD); // FIXME
9409
// Replicate scalar constant to packed byte values in Double register
9410
// TODO: support negative constants with MVNI?
9411
instruct Repl8B_immU8(vecD dst, immU8 src) %{
9412
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9413
Matcher::vector_element_basic_type(n) == T_BYTE);
9414
match(Set dst (Replicate src));
9417
format %{ "VMOV.U8 $dst,$src" %}
9420
__ vmovI($dst$$FloatRegister, $src$$constant,
9421
MacroAssembler::VELEM_SIZE_8, quad);
9423
ins_pipe(loadConFD); // FIXME
9426
// Replicate scalar constant to packed byte values in Double register pair
9427
instruct Repl16B_immU8(vecX dst, immU8 src) %{
9428
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9429
Matcher::vector_element_basic_type(n) == T_BYTE);
9430
match(Set dst (Replicate src));
9433
format %{ "VMOV.U8 $dst.Q,$src" %}
9436
__ vmovI($dst$$FloatRegister, $src$$constant,
9437
MacroAssembler::VELEM_SIZE_8, quad);
9439
ins_pipe(loadConFD); // FIXME
9442
// Replicate scalar to packed short/char values into Double register
9443
instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{
9444
predicate(n->as_Vector()->length() == 4 &&
9445
Matcher::vector_element_basic_type(n) == T_SHORT);
9446
match(Set dst (Replicate src));
9447
ins_cost(DEFAULT_COST*3);
9451
// FIXME: could use PKH instruction instead?
9452
format %{ "LSL $tmp, $src, 16 \n\t"
9453
"OR $tmp, $tmp, ($tmp >> 16) \n\t"
9454
"FMDRR $dst,$tmp,$tmp\t" %}
9456
__ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16));
9457
__ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9458
__ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9460
ins_pipe(ialu_reg); // FIXME
9463
// Replicate scalar to packed byte values in Double register
9464
instruct Repl4S_reg_simd(vecD dst, iRegI src) %{
9465
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9466
Matcher::vector_element_basic_type(n) == T_SHORT);
9467
match(Set dst (Replicate src));
9470
format %{ "VDUP.16 $dst,$src\t" %}
9473
__ vdupI($dst$$FloatRegister, $src$$Register,
9474
MacroAssembler::VELEM_SIZE_16, quad);
9476
ins_pipe(ialu_reg); // FIXME
9479
// Replicate scalar to packed byte values in Double register pair
9480
instruct Repl8S_reg(vecX dst, iRegI src) %{
9481
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9482
Matcher::vector_element_basic_type(n) == T_SHORT);
9483
match(Set dst (Replicate src));
9486
format %{ "VDUP.16 $dst.Q,$src\t" %}
9489
__ vdupI($dst$$FloatRegister, $src$$Register,
9490
MacroAssembler::VELEM_SIZE_16, quad);
9492
ins_pipe(ialu_reg); // FIXME
9496
// Replicate scalar constant to packed short/char values in Double register
9497
instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{
9498
predicate(n->as_Vector()->length() == 4 &&
9499
Matcher::vector_element_basic_type(n) == T_SHORT);
9500
match(Set dst (Replicate src));
9503
ins_cost(DEFAULT_COST*4); // FIXME
9505
format %{ "MOV $tmp, Repl2($src))\n\t"
9506
"FMDRR $dst,$tmp,$tmp\t" %}
9507
ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) );
9508
ins_pipe(loadConFD); // FIXME
9511
// Replicate scalar constant to packed byte values in Double register
9512
instruct Repl4S_immU8(vecD dst, immU8 src) %{
9513
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9514
Matcher::vector_element_basic_type(n) == T_SHORT);
9515
match(Set dst (Replicate src));
9518
format %{ "VMOV.U16 $dst,$src" %}
9521
__ vmovI($dst$$FloatRegister, $src$$constant,
9522
MacroAssembler::VELEM_SIZE_16, quad);
9524
ins_pipe(loadConFD); // FIXME
9527
// Replicate scalar constant to packed byte values in Double register pair
9528
instruct Repl8S_immU8(vecX dst, immU8 src) %{
9529
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9530
Matcher::vector_element_basic_type(n) == T_SHORT);
9531
match(Set dst (Replicate src));
9534
format %{ "VMOV.U16 $dst.Q,$src" %}
9537
__ vmovI($dst$$FloatRegister, $src$$constant,
9538
MacroAssembler::VELEM_SIZE_16, quad);
9540
ins_pipe(loadConFD); // FIXME
9543
// Replicate scalar to packed int values in Double register
9544
instruct Repl2I_reg(vecD dst, iRegI src) %{
9545
predicate(n->as_Vector()->length() == 2 &&
9546
Matcher::vector_element_basic_type(n) == T_INT);
9547
match(Set dst (Replicate src));
9550
format %{ "FMDRR $dst,$src,$src\t" %}
9552
__ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9554
ins_pipe(ialu_reg); // FIXME
9557
// Replicate scalar to packed int values in Double register pair
9558
instruct Repl4I_reg(vecX dst, iRegI src) %{
9559
predicate(n->as_Vector()->length() == 4 &&
9560
Matcher::vector_element_basic_type(n) == T_INT);
9561
match(Set dst (Replicate src));
9562
ins_cost(DEFAULT_COST*2);
9565
format %{ "FMDRR $dst.lo,$src,$src\n\t"
9566
"FMDRR $dst.hi,$src,$src" %}
9569
__ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9570
__ fmdrr($dst$$FloatRegister->successor()->successor(),
9571
$src$$Register, $src$$Register);
9573
ins_pipe(ialu_reg); // FIXME
9576
// Replicate scalar to packed int values in Double register
9577
instruct Repl2I_reg_simd(vecD dst, iRegI src) %{
9578
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9579
Matcher::vector_element_basic_type(n) == T_INT);
9580
match(Set dst (Replicate src));
9583
format %{ "VDUP.32 $dst.D,$src\t" %}
9586
__ vdupI($dst$$FloatRegister, $src$$Register,
9587
MacroAssembler::VELEM_SIZE_32, quad);
9589
ins_pipe(ialu_reg); // FIXME
9592
// Replicate scalar to packed int values in Double register pair
9593
instruct Repl4I_reg_simd(vecX dst, iRegI src) %{
9594
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9595
Matcher::vector_element_basic_type(n) == T_INT);
9596
match(Set dst (Replicate src));
9599
format %{ "VDUP.32 $dst.Q,$src\t" %}
9602
__ vdupI($dst$$FloatRegister, $src$$Register,
9603
MacroAssembler::VELEM_SIZE_32, quad);
9605
ins_pipe(ialu_reg); // FIXME
9609
// Replicate scalar zero constant to packed int values in Double register
9610
instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{
9611
predicate(n->as_Vector()->length() == 2 &&
9612
Matcher::vector_element_basic_type(n) == T_INT);
9613
match(Set dst (Replicate src));
9616
ins_cost(DEFAULT_COST*4); // FIXME
9618
format %{ "MOV $tmp, Repl1($src))\n\t"
9619
"FMDRR $dst,$tmp,$tmp\t" %}
9620
ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) );
9621
ins_pipe(loadConFD); // FIXME
9624
// Replicate scalar constant to packed byte values in Double register
9625
instruct Repl2I_immU8(vecD dst, immU8 src) %{
9626
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9627
Matcher::vector_element_basic_type(n) == T_INT);
9628
match(Set dst (Replicate src));
9631
format %{ "VMOV.I32 $dst.D,$src" %}
9634
__ vmovI($dst$$FloatRegister, $src$$constant,
9635
MacroAssembler::VELEM_SIZE_32, quad);
9637
ins_pipe(loadConFD); // FIXME
9640
// Replicate scalar constant to packed byte values in Double register pair
9641
instruct Repl4I_immU8(vecX dst, immU8 src) %{
9642
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9643
Matcher::vector_element_basic_type(n) == T_INT);
9644
match(Set dst (Replicate src));
9647
format %{ "VMOV.I32 $dst.Q,$src" %}
9650
__ vmovI($dst$$FloatRegister, $src$$constant,
9651
MacroAssembler::VELEM_SIZE_32, quad);
9653
ins_pipe(loadConFD); // FIXME
9656
// Replicate scalar to packed byte values in Double register pair
9657
instruct Repl2L_reg(vecX dst, iRegL src) %{
9658
predicate(n->as_Vector()->length() == 2 &&
9659
Matcher::vector_element_basic_type(n) == T_LONG);
9660
match(Set dst (Replicate src));
9662
ins_cost(DEFAULT_COST*2); // FIXME
9664
format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n"
9665
"FMDRR $dst.D.next,$src.lo,$src.hi" %}
9667
__ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
9668
__ fmdrr($dst$$FloatRegister->successor()->successor(),
9669
$src$$Register, $src$$Register->successor());
9671
ins_pipe(ialu_reg); // FIXME
9675
// Replicate scalar to packed float values in Double register
9676
instruct Repl2F_regI(vecD dst, iRegI src) %{
9677
predicate(n->as_Vector()->length() == 2 &&
9678
Matcher::vector_element_basic_type(n) == T_FLOAT);
9679
match(Set dst (Replicate src));
9682
format %{ "FMDRR $dst.D,$src,$src\t" %}
9684
__ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9686
ins_pipe(ialu_reg); // FIXME
9689
// Replicate scalar to packed float values in Double register
9690
instruct Repl2F_reg_vfp(vecD dst, regF src) %{
9691
predicate(n->as_Vector()->length() == 2 &&
9692
Matcher::vector_element_basic_type(n) == T_FLOAT);
9693
match(Set dst (Replicate src));
9695
ins_cost(DEFAULT_COST*2); // FIXME
9699
MoveF2I_reg_reg(tmp, src);
9700
Repl2F_regI(dst,tmp);
9704
// Replicate scalar to packed float values in Double register
9705
instruct Repl2F_reg_simd(vecD dst, regF src) %{
9706
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9707
Matcher::vector_element_basic_type(n) == T_FLOAT);
9708
match(Set dst (Replicate src));
9710
ins_cost(DEFAULT_COST); // FIXME
9712
format %{ "VDUP.32 $dst.D,$src.D\t" %}
9715
__ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9717
ins_pipe(ialu_reg); // FIXME
9720
// Replicate scalar to packed float values in Double register pair
9721
instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{
9722
predicate(n->as_Vector()->length() == 4 &&
9723
Matcher::vector_element_basic_type(n) == T_FLOAT);
9724
match(Set dst (Replicate src));
9727
ins_cost(DEFAULT_COST*3); // FIXME
9729
format %{ "FMRS $tmp,$src\n\t"
9730
"FMDRR $dst.D,$tmp,$tmp\n\t"
9731
"FMDRR $dst.D.next,$tmp,$tmp\t" %}
9733
__ fmrs($tmp$$Register, $src$$FloatRegister);
9734
__ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9735
__ fmdrr($dst$$FloatRegister->successor()->successor(),
9736
$tmp$$Register, $tmp$$Register);
9738
ins_pipe(ialu_reg); // FIXME
9741
// Replicate scalar to packed float values in Double register pair
9742
instruct Repl4F_reg_simd(vecX dst, regF src) %{
9743
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9744
Matcher::vector_element_basic_type(n) == T_FLOAT);
9745
match(Set dst (Replicate src));
9747
ins_cost(DEFAULT_COST); // FIXME
9749
format %{ "VDUP.32 $dst.Q,$src.D\t" %}
9752
__ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9754
ins_pipe(ialu_reg); // FIXME
9757
// Replicate scalar zero constant to packed float values in Double register
9758
instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{
9759
predicate(n->as_Vector()->length() == 2 &&
9760
Matcher::vector_element_basic_type(n) == T_FLOAT);
9761
match(Set dst (Replicate src));
9764
ins_cost(DEFAULT_COST*4); // FIXME
9766
format %{ "MOV $tmp, Repl1($src))\n\t"
9767
"FMDRR $dst,$tmp,$tmp\t" %}
9768
ins_encode( LdReplImmF(src, dst, tmp) );
9769
ins_pipe(loadConFD); // FIXME
9772
// Replicate scalar to packed double float values in Double register pair
9773
instruct Repl2D_reg(vecX dst, regD src) %{
9774
predicate(n->as_Vector()->length() == 2 &&
9775
Matcher::vector_element_basic_type(n) == T_DOUBLE);
9776
match(Set dst (Replicate src));
9778
ins_cost(DEFAULT_COST*2); // FIXME
9780
format %{ "FCPYD $dst.D.a,$src\n\t"
9781
"FCPYD $dst.D.b,$src\t" %}
9783
FloatRegister dsta = $dst$$FloatRegister;
9784
FloatRegister src = $src$$FloatRegister;
9785
__ fcpyd(dsta, src);
9786
FloatRegister dstb = dsta->successor()->successor();
9787
__ fcpyd(dstb, src);
9789
ins_pipe(ialu_reg); // FIXME
9792
// ====================VECTOR ARITHMETIC=======================================
9794
// --------------------------------- ADD --------------------------------------
9797
instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{
9798
predicate(n->as_Vector()->length() == 8);
9799
match(Set dst (AddVB src1 src2));
9800
format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %}
9804
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9805
MacroAssembler::VELEM_SIZE_8, quad);
9807
ins_pipe( ialu_reg_reg ); // FIXME
9810
instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
9811
predicate(n->as_Vector()->length() == 16);
9812
match(Set dst (AddVB src1 src2));
9814
format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %}
9817
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9818
MacroAssembler::VELEM_SIZE_8, quad);
9820
ins_pipe( ialu_reg_reg ); // FIXME
9823
// Shorts/Chars vector add
9824
instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{
9825
predicate(n->as_Vector()->length() == 4);
9826
match(Set dst (AddVS src1 src2));
9828
format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %}
9831
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9832
MacroAssembler::VELEM_SIZE_16, quad);
9834
ins_pipe( ialu_reg_reg ); // FIXME
9837
instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
9838
predicate(n->as_Vector()->length() == 8);
9839
match(Set dst (AddVS src1 src2));
9841
format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %}
9844
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9845
MacroAssembler::VELEM_SIZE_16, quad);
9847
ins_pipe( ialu_reg_reg ); // FIXME
9850
// Integers vector add
9851
instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{
9852
predicate(n->as_Vector()->length() == 2);
9853
match(Set dst (AddVI src1 src2));
9855
format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %}
9858
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9859
MacroAssembler::VELEM_SIZE_32, quad);
9861
ins_pipe( ialu_reg_reg ); // FIXME
9864
instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
9865
predicate(n->as_Vector()->length() == 4);
9866
match(Set dst (AddVI src1 src2));
9868
format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %}
9871
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9872
MacroAssembler::VELEM_SIZE_32, quad);
9874
ins_pipe( ialu_reg_reg ); // FIXME
9878
instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
9879
predicate(n->as_Vector()->length() == 2);
9880
match(Set dst (AddVL src1 src2));
9882
format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %}
9885
__ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9886
MacroAssembler::VELEM_SIZE_64, quad);
9888
ins_pipe( ialu_reg_reg ); // FIXME
9892
instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{
9893
predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
9894
match(Set dst (AddVF src1 src2));
9896
format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %}
9899
__ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9900
MacroAssembler::VFA_SIZE_F32, quad);
9902
ins_pipe( faddD_reg_reg ); // FIXME
9905
instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
9906
predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
9907
match(Set dst (AddVF src1 src2));
9908
ins_cost(DEFAULT_COST*2); // FIXME
9911
format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t"
9912
"FADDS $dst.b,$src1.b,$src2.b" %}
9914
__ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9915
__ add_float($dst$$FloatRegister->successor(),
9916
$src1$$FloatRegister->successor(),
9917
$src2$$FloatRegister->successor());
9920
ins_pipe(faddF_reg_reg); // FIXME
9923
instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{
9924
predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
9925
match(Set dst (AddVF src1 src2));
9927
format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %}
9930
__ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9931
MacroAssembler::VFA_SIZE_F32, quad);
9933
ins_pipe( faddD_reg_reg ); // FIXME
9936
instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9937
predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
9938
match(Set dst (AddVF src1 src2));
9940
ins_cost(DEFAULT_COST*4); // FIXME
9942
format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t"
9943
"FADDS $dst.b,$src1.b,$src2.b\n\t"
9944
"FADDS $dst.c,$src1.c,$src2.c\n\t"
9945
"FADDS $dst.d,$src1.d,$src2.d" %}
9948
FloatRegister dsta = $dst$$FloatRegister;
9949
FloatRegister src1a = $src1$$FloatRegister;
9950
FloatRegister src2a = $src2$$FloatRegister;
9951
__ add_float(dsta, src1a, src2a);
9952
FloatRegister dstb = dsta->successor();
9953
FloatRegister src1b = src1a->successor();
9954
FloatRegister src2b = src2a->successor();
9955
__ add_float(dstb, src1b, src2b);
9956
FloatRegister dstc = dstb->successor();
9957
FloatRegister src1c = src1b->successor();
9958
FloatRegister src2c = src2b->successor();
9959
__ add_float(dstc, src1c, src2c);
9960
FloatRegister dstd = dstc->successor();
9961
FloatRegister src1d = src1c->successor();
9962
FloatRegister src2d = src2c->successor();
9963
__ add_float(dstd, src1d, src2d);
9966
ins_pipe(faddF_reg_reg); // FIXME
9969
instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9970
predicate(n->as_Vector()->length() == 2);
9971
match(Set dst (AddVD src1 src2));
9973
ins_cost(DEFAULT_COST*2); // FIXME
9975
format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t"
9976
"FADDD $dst.b,$src1.b,$src2.b" %}
9979
FloatRegister dsta = $dst$$FloatRegister;
9980
FloatRegister src1a = $src1$$FloatRegister;
9981
FloatRegister src2a = $src2$$FloatRegister;
9982
__ add_double(dsta, src1a, src2a);
9983
FloatRegister dstb = dsta->successor()->successor();
9984
FloatRegister src1b = src1a->successor()->successor();
9985
FloatRegister src2b = src2a->successor()->successor();
9986
__ add_double(dstb, src1b, src2b);
9989
ins_pipe(faddF_reg_reg); // FIXME
9994
instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{
9995
predicate(n->as_Vector()->length() == 8);
9996
match(Set dst (SubVB src1 src2));
9998
format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %}
10001
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10002
MacroAssembler::VELEM_SIZE_8, quad);
10004
ins_pipe( ialu_reg_reg ); // FIXME
10007
instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
10008
predicate(n->as_Vector()->length() == 16);
10009
match(Set dst (SubVB src1 src2));
10011
format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %}
10014
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10015
MacroAssembler::VELEM_SIZE_8, quad);
10017
ins_pipe( ialu_reg_reg ); // FIXME
10020
// Shorts/Chars vector sub
10021
instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{
10022
predicate(n->as_Vector()->length() == 4);
10023
match(Set dst (SubVS src1 src2));
10025
format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %}
10028
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10029
MacroAssembler::VELEM_SIZE_16, quad);
10031
ins_pipe( ialu_reg_reg ); // FIXME
10034
instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{
10035
predicate(n->as_Vector()->length() == 8);
10036
match(Set dst (SubVS src1 src2));
10038
format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %}
10041
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10042
MacroAssembler::VELEM_SIZE_16, quad);
10044
ins_pipe( ialu_reg_reg ); // FIXME
10047
// Integers vector sub
10048
instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{
10049
predicate(n->as_Vector()->length() == 2);
10050
match(Set dst (SubVI src1 src2));
10052
format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %}
10055
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10056
MacroAssembler::VELEM_SIZE_32, quad);
10058
ins_pipe( ialu_reg_reg ); // FIXME
10061
instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
10062
predicate(n->as_Vector()->length() == 4);
10063
match(Set dst (SubVI src1 src2));
10065
format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %}
10068
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10069
MacroAssembler::VELEM_SIZE_32, quad);
10071
ins_pipe( ialu_reg_reg ); // FIXME
10075
instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
10076
predicate(n->as_Vector()->length() == 2);
10077
match(Set dst (SubVL src1 src2));
10079
format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %}
10082
__ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10083
MacroAssembler::VELEM_SIZE_64, quad);
10085
ins_pipe( ialu_reg_reg ); // FIXME
10088
// Floats vector sub
10089
instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{
10090
predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10091
match(Set dst (SubVF src1 src2));
10093
format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %}
10096
__ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10097
MacroAssembler::VFA_SIZE_F32, quad);
10099
ins_pipe( faddF_reg_reg ); // FIXME
10102
instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10103
predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10104
match(Set dst (SubVF src1 src2));
10106
ins_cost(DEFAULT_COST*2); // FIXME
10108
format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t"
10109
"FSUBS $dst.b,$src1.b,$src2.b" %}
10112
FloatRegister dsta = $dst$$FloatRegister;
10113
FloatRegister src1a = $src1$$FloatRegister;
10114
FloatRegister src2a = $src2$$FloatRegister;
10115
__ sub_float(dsta, src1a, src2a);
10116
FloatRegister dstb = dsta->successor();
10117
FloatRegister src1b = src1a->successor();
10118
FloatRegister src2b = src2a->successor();
10119
__ sub_float(dstb, src1b, src2b);
10122
ins_pipe(faddF_reg_reg); // FIXME
10126
instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
10127
predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10128
match(Set dst (SubVF src1 src2));
10130
format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %}
10133
__ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10134
MacroAssembler::VFA_SIZE_F32, quad);
10136
ins_pipe( faddF_reg_reg ); // FIXME
10139
instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10140
predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10141
match(Set dst (SubVF src1 src2));
10143
ins_cost(DEFAULT_COST*4); // FIXME
10145
format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t"
10146
"FSUBS $dst.b,$src1.b,$src2.b\n\t"
10147
"FSUBS $dst.c,$src1.c,$src2.c\n\t"
10148
"FSUBS $dst.d,$src1.d,$src2.d" %}
10151
FloatRegister dsta = $dst$$FloatRegister;
10152
FloatRegister src1a = $src1$$FloatRegister;
10153
FloatRegister src2a = $src2$$FloatRegister;
10154
__ sub_float(dsta, src1a, src2a);
10155
FloatRegister dstb = dsta->successor();
10156
FloatRegister src1b = src1a->successor();
10157
FloatRegister src2b = src2a->successor();
10158
__ sub_float(dstb, src1b, src2b);
10159
FloatRegister dstc = dstb->successor();
10160
FloatRegister src1c = src1b->successor();
10161
FloatRegister src2c = src2b->successor();
10162
__ sub_float(dstc, src1c, src2c);
10163
FloatRegister dstd = dstc->successor();
10164
FloatRegister src1d = src1c->successor();
10165
FloatRegister src2d = src2c->successor();
10166
__ sub_float(dstd, src1d, src2d);
10169
ins_pipe(faddF_reg_reg); // FIXME
10172
instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10173
predicate(n->as_Vector()->length() == 2);
10174
match(Set dst (SubVD src1 src2));
10176
ins_cost(DEFAULT_COST*2); // FIXME
10178
format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t"
10179
"FSUBD $dst.b,$src1.b,$src2.b" %}
10182
FloatRegister dsta = $dst$$FloatRegister;
10183
FloatRegister src1a = $src1$$FloatRegister;
10184
FloatRegister src2a = $src2$$FloatRegister;
10185
__ sub_double(dsta, src1a, src2a);
10186
FloatRegister dstb = dsta->successor()->successor();
10187
FloatRegister src1b = src1a->successor()->successor();
10188
FloatRegister src2b = src2a->successor()->successor();
10189
__ sub_double(dstb, src1b, src2b);
10192
ins_pipe(faddF_reg_reg); // FIXME
10195
// Shorts/Chars vector mul
10196
instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{
10197
predicate(n->as_Vector()->length() == 4);
10198
match(Set dst (MulVS src1 src2));
10200
format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %}
10202
__ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10203
MacroAssembler::VELEM_SIZE_16, 0);
10205
ins_pipe( ialu_reg_reg ); // FIXME
10208
instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{
10209
predicate(n->as_Vector()->length() == 8);
10210
match(Set dst (MulVS src1 src2));
10212
format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %}
10214
__ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10215
MacroAssembler::VELEM_SIZE_16, 1);
10217
ins_pipe( ialu_reg_reg ); // FIXME
10220
// Integers vector mul
10221
instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{
10222
predicate(n->as_Vector()->length() == 2);
10223
match(Set dst (MulVI src1 src2));
10225
format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %}
10227
__ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10228
MacroAssembler::VELEM_SIZE_32, 0);
10230
ins_pipe( ialu_reg_reg ); // FIXME
10233
instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
10234
predicate(n->as_Vector()->length() == 4);
10235
match(Set dst (MulVI src1 src2));
10237
format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %}
10239
__ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10240
MacroAssembler::VELEM_SIZE_32, 1);
10242
ins_pipe( ialu_reg_reg ); // FIXME
10245
// Floats vector mul
10246
instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{
10247
predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10248
match(Set dst (MulVF src1 src2));
10250
format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %}
10252
__ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10253
MacroAssembler::VFA_SIZE_F32, 0);
10255
ins_pipe( fmulF_reg_reg ); // FIXME
10258
instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10259
predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10260
match(Set dst (MulVF src1 src2));
10262
ins_cost(DEFAULT_COST*2); // FIXME
10264
format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t"
10265
"FMULS $dst.b,$src1.b,$src2.b" %}
10267
__ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10268
__ mul_float($dst$$FloatRegister->successor(),
10269
$src1$$FloatRegister->successor(),
10270
$src2$$FloatRegister->successor());
10273
ins_pipe(fmulF_reg_reg); // FIXME
10276
instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
10277
predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10278
match(Set dst (MulVF src1 src2));
10280
format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %}
10282
__ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10283
MacroAssembler::VFA_SIZE_F32, 1);
10285
ins_pipe( fmulF_reg_reg ); // FIXME
10288
instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10289
predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10290
match(Set dst (MulVF src1 src2));
10292
ins_cost(DEFAULT_COST*4); // FIXME
10294
format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t"
10295
"FMULS $dst.b,$src1.b,$src2.b\n\t"
10296
"FMULS $dst.c,$src1.c,$src2.c\n\t"
10297
"FMULS $dst.d,$src1.d,$src2.d" %}
10300
FloatRegister dsta = $dst$$FloatRegister;
10301
FloatRegister src1a = $src1$$FloatRegister;
10302
FloatRegister src2a = $src2$$FloatRegister;
10303
__ mul_float(dsta, src1a, src2a);
10304
FloatRegister dstb = dsta->successor();
10305
FloatRegister src1b = src1a->successor();
10306
FloatRegister src2b = src2a->successor();
10307
__ mul_float(dstb, src1b, src2b);
10308
FloatRegister dstc = dstb->successor();
10309
FloatRegister src1c = src1b->successor();
10310
FloatRegister src2c = src2b->successor();
10311
__ mul_float(dstc, src1c, src2c);
10312
FloatRegister dstd = dstc->successor();
10313
FloatRegister src1d = src1c->successor();
10314
FloatRegister src2d = src2c->successor();
10315
__ mul_float(dstd, src1d, src2d);
10318
ins_pipe(fmulF_reg_reg); // FIXME
10321
instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10322
predicate(n->as_Vector()->length() == 2);
10323
match(Set dst (MulVD src1 src2));
10325
ins_cost(DEFAULT_COST*2); // FIXME
10327
format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10328
"FMULD $dst.D.b,$src1.D.b,$src2.D.b" %}
10330
FloatRegister dsta = $dst$$FloatRegister;
10331
FloatRegister src1a = $src1$$FloatRegister;
10332
FloatRegister src2a = $src2$$FloatRegister;
10333
__ mul_double(dsta, src1a, src2a);
10334
FloatRegister dstb = dsta->successor()->successor();
10335
FloatRegister src1b = src1a->successor()->successor();
10336
FloatRegister src2b = src2a->successor()->successor();
10337
__ mul_double(dstb, src1b, src2b);
10340
ins_pipe(fmulD_reg_reg); // FIXME
10344
// Floats vector div
10345
instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10346
predicate(n->as_Vector()->length() == 2);
10347
match(Set dst (DivVF src1 src2));
10349
ins_cost(DEFAULT_COST*2); // FIXME
10351
format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t"
10352
"FDIVS $dst.b,$src1.b,$src2.b" %}
10354
__ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10355
__ div_float($dst$$FloatRegister->successor(),
10356
$src1$$FloatRegister->successor(),
10357
$src2$$FloatRegister->successor());
10360
ins_pipe(fdivF_reg_reg); // FIXME
10363
instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10364
predicate(n->as_Vector()->length() == 4);
10365
match(Set dst (DivVF src1 src2));
10367
ins_cost(DEFAULT_COST*4); // FIXME
10369
format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t"
10370
"FDIVS $dst.b,$src1.b,$src2.b\n\t"
10371
"FDIVS $dst.c,$src1.c,$src2.c\n\t"
10372
"FDIVS $dst.d,$src1.d,$src2.d" %}
10375
FloatRegister dsta = $dst$$FloatRegister;
10376
FloatRegister src1a = $src1$$FloatRegister;
10377
FloatRegister src2a = $src2$$FloatRegister;
10378
__ div_float(dsta, src1a, src2a);
10379
FloatRegister dstb = dsta->successor();
10380
FloatRegister src1b = src1a->successor();
10381
FloatRegister src2b = src2a->successor();
10382
__ div_float(dstb, src1b, src2b);
10383
FloatRegister dstc = dstb->successor();
10384
FloatRegister src1c = src1b->successor();
10385
FloatRegister src2c = src2b->successor();
10386
__ div_float(dstc, src1c, src2c);
10387
FloatRegister dstd = dstc->successor();
10388
FloatRegister src1d = src1c->successor();
10389
FloatRegister src2d = src2c->successor();
10390
__ div_float(dstd, src1d, src2d);
10393
ins_pipe(fdivF_reg_reg); // FIXME
10396
instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10397
predicate(n->as_Vector()->length() == 2);
10398
match(Set dst (DivVD src1 src2));
10400
ins_cost(DEFAULT_COST*2); // FIXME
10402
format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10403
"FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %}
10405
FloatRegister dsta = $dst$$FloatRegister;
10406
FloatRegister src1a = $src1$$FloatRegister;
10407
FloatRegister src2a = $src2$$FloatRegister;
10408
__ div_double(dsta, src1a, src2a);
10409
FloatRegister dstb = dsta->successor()->successor();
10410
FloatRegister src1b = src1a->successor()->successor();
10411
FloatRegister src2b = src2a->successor()->successor();
10412
__ div_double(dstb, src1b, src2b);
10415
ins_pipe(fdivD_reg_reg); // FIXME
10418
// --------------------------------- NEG --------------------------------------
10420
instruct vneg8B_reg(vecD dst, vecD src) %{
10421
predicate(n->as_Vector()->length_in_bytes() == 8);
10422
effect(DEF dst, USE src);
10424
ins_cost(DEFAULT_COST); // FIXME
10425
format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %}
10428
__ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10429
MacroAssembler::VELEM_SIZE_8, quad);
10431
ins_pipe( ialu_reg_reg ); // FIXME
10434
instruct vneg16B_reg(vecX dst, vecX src) %{
10435
predicate(n->as_Vector()->length_in_bytes() == 16);
10436
effect(DEF dst, USE src);
10438
ins_cost(DEFAULT_COST); // FIXME
10439
format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %}
10441
bool _float = false;
10443
__ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10444
MacroAssembler::VELEM_SIZE_8, quad);
10446
ins_pipe( ialu_reg_reg ); // FIXME
10449
// ------------------------------ ShiftCount ----------------------------------
10451
instruct vslcntD(vecD dst, iRegI cnt) %{
10452
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10453
match(Set dst (LShiftCntV cnt));
10455
ins_cost(DEFAULT_COST); // FIXME
10457
Repl8B_reg_simd(dst, cnt);
10461
instruct vslcntX(vecX dst, iRegI cnt) %{
10462
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10463
match(Set dst (LShiftCntV cnt));
10465
ins_cost(DEFAULT_COST); // FIXME
10467
Repl16B_reg(dst, cnt);
10471
// Low bits of vector "shift" elements are used, so it
10472
// doesn't matter if we treat it as ints or bytes here.
10473
instruct vsrcntD(vecD dst, iRegI cnt) %{
10474
predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10475
match(Set dst (RShiftCntV cnt));
10477
ins_cost(DEFAULT_COST*2); // FIXME
10479
format %{ "VDUP.8 $dst.D,$cnt\n\t"
10480
"VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %}
10483
__ vdupI($dst$$FloatRegister, $cnt$$Register,
10484
MacroAssembler::VELEM_SIZE_8, quad);
10485
__ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10486
MacroAssembler::VELEM_SIZE_8, quad);
10488
ins_pipe( ialu_reg_reg ); // FIXME
10491
instruct vsrcntX(vecX dst, iRegI cnt) %{
10492
predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10493
match(Set dst (RShiftCntV cnt));
10495
ins_cost(DEFAULT_COST*2); // FIXME
10496
format %{ "VDUP.8 $dst.Q,$cnt\n\t"
10497
"VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %}
10500
__ vdupI($dst$$FloatRegister, $cnt$$Register,
10501
MacroAssembler::VELEM_SIZE_8, quad);
10502
__ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10503
MacroAssembler::VELEM_SIZE_8, quad);
10505
ins_pipe( ialu_reg_reg ); // FIXME
10508
// ------------------------------ LogicalShift --------------------------------
10510
// Byte vector logical left/right shift based on sign
10511
instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{
10512
predicate(n->as_Vector()->length() == 8);
10513
effect(DEF dst, USE src, USE shift);
10515
ins_cost(DEFAULT_COST); // FIXME
10517
"VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B"
10521
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10522
MacroAssembler::VELEM_SIZE_8, quad);
10524
ins_pipe( ialu_reg_reg ); // FIXME
10527
instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{
10528
predicate(n->as_Vector()->length() == 16);
10529
effect(DEF dst, USE src, USE shift);
10531
ins_cost(DEFAULT_COST); // FIXME
10533
"VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B"
10537
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10538
MacroAssembler::VELEM_SIZE_8, quad);
10540
ins_pipe( ialu_reg_reg ); // FIXME
10543
// Shorts/Char vector logical left/right shift based on sign
10544
instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{
10545
predicate(n->as_Vector()->length() == 4);
10546
effect(DEF dst, USE src, USE shift);
10548
ins_cost(DEFAULT_COST); // FIXME
10550
"VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S"
10554
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10555
MacroAssembler::VELEM_SIZE_16, quad);
10557
ins_pipe( ialu_reg_reg ); // FIXME
10560
instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{
10561
predicate(n->as_Vector()->length() == 8);
10562
effect(DEF dst, USE src, USE shift);
10564
ins_cost(DEFAULT_COST); // FIXME
10566
"VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S"
10570
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10571
MacroAssembler::VELEM_SIZE_16, quad);
10573
ins_pipe( ialu_reg_reg ); // FIXME
10576
// Integers vector logical left/right shift based on sign
10577
instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{
10578
predicate(n->as_Vector()->length() == 2);
10579
effect(DEF dst, USE src, USE shift);
10581
ins_cost(DEFAULT_COST); // FIXME
10583
"VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I"
10587
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10588
MacroAssembler::VELEM_SIZE_32, quad);
10590
ins_pipe( ialu_reg_reg ); // FIXME
10593
instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{
10594
predicate(n->as_Vector()->length() == 4);
10595
effect(DEF dst, USE src, USE shift);
10597
ins_cost(DEFAULT_COST); // FIXME
10599
"VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I"
10603
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10604
MacroAssembler::VELEM_SIZE_32, quad);
10606
ins_pipe( ialu_reg_reg ); // FIXME
10609
// Longs vector logical left/right shift based on sign
10610
instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{
10611
predicate(n->as_Vector()->length() == 2);
10612
effect(DEF dst, USE src, USE shift);
10614
ins_cost(DEFAULT_COST); // FIXME
10616
"VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L"
10620
__ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10621
MacroAssembler::VELEM_SIZE_64, quad);
10623
ins_pipe( ialu_reg_reg ); // FIXME
10626
// ------------------------------ LogicalLeftShift ----------------------------
10628
// Byte vector logical left shift
10629
instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{
10630
predicate(n->as_Vector()->length() == 8);
10631
match(Set dst (LShiftVB src shift));
10633
ins_cost(DEFAULT_COST*1); // FIXME
10635
vsh8B_reg(dst, src, shift);
10639
instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{
10640
predicate(n->as_Vector()->length() == 16);
10641
match(Set dst (LShiftVB src shift));
10643
ins_cost(DEFAULT_COST*1); // FIXME
10645
vsh16B_reg(dst, src, shift);
10649
instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{
10650
predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10651
match(Set dst (LShiftVB src (LShiftCntV shift)));
10653
ins_cost(DEFAULT_COST); // FIXME
10655
"VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B"
10659
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10662
ins_pipe( ialu_reg_reg ); // FIXME
10665
instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{
10666
predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
10667
match(Set dst (LShiftVB src (LShiftCntV shift)));
10669
ins_cost(DEFAULT_COST); // FIXME
10671
"VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B"
10675
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10678
ins_pipe( ialu_reg_reg ); // FIXME
10681
// Shorts/Chars vector logical left shift
10682
instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{
10683
predicate(n->as_Vector()->length() == 4);
10684
match(Set dst (LShiftVS src shift));
10686
ins_cost(DEFAULT_COST*1); // FIXME
10688
vsh4S_reg(dst, src, shift);
10692
instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{
10693
predicate(n->as_Vector()->length() == 8);
10694
match(Set dst (LShiftVS src shift));
10696
ins_cost(DEFAULT_COST*1); // FIXME
10698
vsh8S_reg(dst, src, shift);
10702
instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{
10703
predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10704
match(Set dst (LShiftVS src (LShiftCntV shift)));
10706
ins_cost(DEFAULT_COST); // FIXME
10708
"VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S"
10712
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10715
ins_pipe( ialu_reg_reg ); // FIXME
10718
instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{
10719
predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10720
match(Set dst (LShiftVS src shift));
10722
ins_cost(DEFAULT_COST); // FIXME
10724
"VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S"
10728
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10731
ins_pipe( ialu_reg_reg ); // FIXME
10734
// Integers vector logical left shift
10735
instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{
10736
predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10737
match(Set dst (LShiftVI src shift));
10739
ins_cost(DEFAULT_COST*1); // FIXME
10741
vsh2I_reg(dst, src, shift);
10745
instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{
10746
predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10747
match(Set dst (LShiftVI src shift));
10749
ins_cost(DEFAULT_COST*1); // FIXME
10751
vsh4I_reg(dst, src, shift);
10755
instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{
10756
predicate(n->as_Vector()->length() == 2 &&
10757
VM_Version::has_simd() &&
10758
assert_not_var_shift(n));
10759
match(Set dst (LShiftVI src (LShiftCntV shift)));
10761
ins_cost(DEFAULT_COST); // FIXME
10763
"VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I"
10767
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10770
ins_pipe( ialu_reg_reg ); // FIXME
10773
instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{
10774
predicate(n->as_Vector()->length() == 4 &&
10775
VM_Version::has_simd() &&
10776
assert_not_var_shift(n));
10777
match(Set dst (LShiftVI src (LShiftCntV shift)));
10779
ins_cost(DEFAULT_COST); // FIXME
10781
"VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I"
10785
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10788
ins_pipe( ialu_reg_reg ); // FIXME
10791
// Longs vector logical left shift
10792
instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{
10793
predicate(n->as_Vector()->length() == 2);
10794
match(Set dst (LShiftVL src shift));
10796
ins_cost(DEFAULT_COST*1); // FIXME
10798
vsh2L_reg(dst, src, shift);
10802
instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{
10803
predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
10804
match(Set dst (LShiftVL src (LShiftCntV shift)));
10806
ins_cost(DEFAULT_COST); // FIXME
10808
"VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L"
10812
__ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
10815
ins_pipe( ialu_reg_reg ); // FIXME
10818
// ----------------------- LogicalRightShift -----------------------------------
10820
// Bytes/Shorts vector logical right shift produces incorrect Java result
10821
// for negative data because java code convert short value into int with
10822
// sign extension before a shift.
10824
// Right shift with vector shift count on aarch32 SIMD is implemented as left
10825
// shift by negative shift count value.
10827
// Method is_var_shift() denotes that vector shift count is a variable shift:
10828
// 1) for this case, vector shift count should be negated before conducting
10829
// right shifts. E.g., vsrl4S_reg_var rule.
10830
// 2) for the opposite case, vector shift count is generated via RShiftCntV
10831
// rules and is already negated there. Hence, no negation is needed.
10832
// E.g., vsrl4S_reg rule.
10834
// Chars vector logical right shift
10835
instruct vsrl4S_reg(vecD dst, vecD src, vecD shift) %{
10836
predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
10837
match(Set dst (URShiftVS src shift));
10839
ins_cost(DEFAULT_COST);
10841
vsh4S_reg(dst, src, shift);
10845
instruct vsrl4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10846
predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
10847
match(Set dst (URShiftVS src shift));
10850
ins_cost(DEFAULT_COST*2);
10852
"VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10853
"VSHL.U16 $dst.D,$src.D,$tmp.D\t! logical right shift packed4S"
10857
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10858
MacroAssembler::VELEM_SIZE_8, quad);
10859
__ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10860
MacroAssembler::VELEM_SIZE_16, quad);
10862
ins_pipe(ialu_reg_reg);
10865
instruct vsrl8S_reg(vecX dst, vecX src, vecX shift) %{
10866
predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
10867
match(Set dst (URShiftVS src shift));
10869
ins_cost(DEFAULT_COST);
10871
vsh8S_reg(dst, src, shift);
10875
instruct vsrl8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10876
predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
10877
match(Set dst (URShiftVS src shift));
10880
ins_cost(DEFAULT_COST*2);
10882
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10883
"VSHL.U16 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed8S"
10887
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10888
MacroAssembler::VELEM_SIZE_8, quad);
10889
__ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10890
MacroAssembler::VELEM_SIZE_16, quad);
10892
ins_pipe(ialu_reg_reg);
10895
instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{
10896
predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10897
match(Set dst (URShiftVS src (RShiftCntV shift)));
10899
ins_cost(DEFAULT_COST); // FIXME
10901
"VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
10905
__ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10908
ins_pipe( ialu_reg_reg ); // FIXME
10911
instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{
10912
predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10913
match(Set dst (URShiftVS src (RShiftCntV shift)));
10915
ins_cost(DEFAULT_COST); // FIXME
10917
"VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
10921
__ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10924
ins_pipe( ialu_reg_reg ); // FIXME
10927
// Integers vector logical right shift
10928
instruct vsrl2I_reg(vecD dst, vecD src, vecD shift) %{
10929
predicate(n->as_Vector()->length() == 2 &&
10930
VM_Version::has_simd() &&
10931
!n->as_ShiftV()->is_var_shift());
10932
match(Set dst (URShiftVI src shift));
10934
ins_cost(DEFAULT_COST);
10936
vsh2I_reg(dst, src, shift);
10940
instruct vsrl2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10941
predicate(n->as_Vector()->length() == 2 &&
10942
VM_Version::has_simd() &&
10943
n->as_ShiftV()->is_var_shift());
10944
match(Set dst (URShiftVI src shift));
10947
ins_cost(DEFAULT_COST*2);
10949
"VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10950
"VSHL.U32 $dst.D,$src.D,$tmp.D\t! logical right shift packed2I"
10954
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10955
MacroAssembler::VELEM_SIZE_8, quad);
10956
__ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10957
MacroAssembler::VELEM_SIZE_32, quad);
10959
ins_pipe(ialu_reg_reg);
10962
instruct vsrl4I_reg(vecX dst, vecX src, vecX shift) %{
10963
predicate(n->as_Vector()->length() == 4 &&
10964
VM_Version::has_simd() &&
10965
!n->as_ShiftV()->is_var_shift());
10966
match(Set dst (URShiftVI src shift));
10968
ins_cost(DEFAULT_COST);
10970
vsh4I_reg(dst, src, shift);
10974
instruct vsrl4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10975
predicate(n->as_Vector()->length() == 4 &&
10976
VM_Version::has_simd() &&
10977
n->as_ShiftV()->is_var_shift());
10978
match(Set dst (URShiftVI src shift));
10981
ins_cost(DEFAULT_COST*2);
10983
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10984
"VSHL.U32 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed4I"
10988
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10989
MacroAssembler::VELEM_SIZE_8, quad);
10990
__ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10991
MacroAssembler::VELEM_SIZE_32, quad);
10993
ins_pipe(ialu_reg_reg);
10996
instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{
10997
predicate(n->as_Vector()->length() == 2 &&
10998
VM_Version::has_simd() &&
10999
assert_not_var_shift(n));
11000
match(Set dst (URShiftVI src (RShiftCntV shift)));
11002
ins_cost(DEFAULT_COST); // FIXME
11004
"VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
11008
__ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11011
ins_pipe( ialu_reg_reg ); // FIXME
11014
instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{
11015
predicate(n->as_Vector()->length() == 4 &&
11016
VM_Version::has_simd() &&
11017
assert_not_var_shift(n));
11018
match(Set dst (URShiftVI src (RShiftCntV shift)));
11020
ins_cost(DEFAULT_COST); // FIXME
11022
"VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
11026
__ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11029
ins_pipe( ialu_reg_reg ); // FIXME
11032
// Longs vector logical right shift
11033
instruct vsrl2L_reg(vecX dst, vecX src, vecX shift) %{
11034
predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11035
match(Set dst (URShiftVL src shift));
11037
ins_cost(DEFAULT_COST);
11039
vsh2L_reg(dst, src, shift);
11043
instruct vsrl2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11044
predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11045
match(Set dst (URShiftVL src shift));
11046
effect(TEMP tmp, DEF dst, USE src, USE shift);
11048
ins_cost(DEFAULT_COST*2);
11050
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11051
"VSHL.U64 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed2L"
11055
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11056
MacroAssembler::VELEM_SIZE_8, quad);
11057
__ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11058
MacroAssembler::VELEM_SIZE_64, quad);
11060
ins_pipe(ialu_reg_reg);
11063
instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{
11064
predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11065
match(Set dst (URShiftVL src (RShiftCntV shift)));
11067
ins_cost(DEFAULT_COST); // FIXME
11069
"VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
11073
__ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11076
ins_pipe( ialu_reg_reg ); // FIXME
11079
// ------------------- ArithmeticRightShift -----------------------------------
11081
// Bytes vector arithmetic left/right shift based on sign
11082
instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{
11083
predicate(n->as_Vector()->length() == 8);
11084
effect(DEF dst, USE src, USE shift);
11086
ins_cost(DEFAULT_COST); // FIXME
11088
"VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B"
11092
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11093
MacroAssembler::VELEM_SIZE_8, quad);
11095
ins_pipe( ialu_reg_reg ); // FIXME
11098
instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{
11099
predicate(n->as_Vector()->length() == 16);
11100
effect(DEF dst, USE src, USE shift);
11102
ins_cost(DEFAULT_COST); // FIXME
11104
"VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B"
11108
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11109
MacroAssembler::VELEM_SIZE_8, quad);
11111
ins_pipe( ialu_reg_reg ); // FIXME
11114
// Shorts vector arithmetic left/right shift based on sign
11115
instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{
11116
predicate(n->as_Vector()->length() == 4);
11117
effect(DEF dst, USE src, USE shift);
11119
ins_cost(DEFAULT_COST); // FIXME
11121
"VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S"
11125
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11126
MacroAssembler::VELEM_SIZE_16, quad);
11128
ins_pipe( ialu_reg_reg ); // FIXME
11131
instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{
11132
predicate(n->as_Vector()->length() == 8);
11133
effect(DEF dst, USE src, USE shift);
11135
ins_cost(DEFAULT_COST); // FIXME
11137
"VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S"
11141
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11142
MacroAssembler::VELEM_SIZE_16, quad);
11144
ins_pipe( ialu_reg_reg ); // FIXME
11147
// Integers vector arithmetic left/right shift based on sign
11148
instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{
11149
predicate(n->as_Vector()->length() == 2);
11150
effect(DEF dst, USE src, USE shift);
11152
ins_cost(DEFAULT_COST); // FIXME
11154
"VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I"
11158
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11159
MacroAssembler::VELEM_SIZE_32, quad);
11161
ins_pipe( ialu_reg_reg ); // FIXME
11164
instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{
11165
predicate(n->as_Vector()->length() == 4);
11166
effect(DEF dst, USE src, USE shift);
11168
ins_cost(DEFAULT_COST); // FIXME
11170
"VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I"
11174
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11175
MacroAssembler::VELEM_SIZE_32, quad);
11177
ins_pipe( ialu_reg_reg ); // FIXME
11180
// Longs vector arithmetic left/right shift based on sign
11181
instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{
11182
predicate(n->as_Vector()->length() == 2);
11183
effect(DEF dst, USE src, USE shift);
11185
ins_cost(DEFAULT_COST); // FIXME
11187
"VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L"
11191
__ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11192
MacroAssembler::VELEM_SIZE_64, quad);
11194
ins_pipe( ialu_reg_reg ); // FIXME
11197
// Byte vector arithmetic right shift
11198
instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{
11199
predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11200
match(Set dst (RShiftVB src shift));
11202
ins_cost(DEFAULT_COST); // FIXME
11204
vsha8B_reg(dst, src, shift);
11208
instruct vsra8B_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11209
predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11210
match(Set dst (RShiftVB src shift));
11213
ins_cost(DEFAULT_COST*2);
11215
"VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11216
"VSHL.S8 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed8B"
11220
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11221
MacroAssembler::VELEM_SIZE_8, quad);
11222
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11223
MacroAssembler::VELEM_SIZE_8, quad);
11225
ins_pipe(ialu_reg_reg);
11228
instruct vsra16B_reg(vecX dst, vecX src, vecX shift) %{
11229
predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift());
11230
match(Set dst (RShiftVB src shift));
11232
ins_cost(DEFAULT_COST); // FIXME
11234
vsha16B_reg(dst, src, shift);
11238
instruct vsra16B_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11239
predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift());
11240
match(Set dst (RShiftVB src shift));
11243
ins_cost(DEFAULT_COST*2);
11245
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11246
"VSHL.S8 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed16B"
11250
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11251
MacroAssembler::VELEM_SIZE_8, quad);
11252
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11253
MacroAssembler::VELEM_SIZE_8, quad);
11255
ins_pipe(ialu_reg_reg);
11258
instruct vsra8B_immI(vecD dst, vecD src, immI shift) %{
11259
predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11260
match(Set dst (RShiftVB src (RShiftCntV shift)));
11262
ins_cost(DEFAULT_COST); // FIXME
11264
"VSHR.S8 $dst.D,$src.D,$shift\t! arithmetic right shift packed8B"
11268
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11271
ins_pipe( ialu_reg_reg ); // FIXME
11274
instruct vsra16B_immI(vecX dst, vecX src, immI shift) %{
11275
predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
11276
match(Set dst (RShiftVB src (RShiftCntV shift)));
11278
ins_cost(DEFAULT_COST); // FIXME
11280
"VSHR.S8 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed16B"
11284
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11287
ins_pipe( ialu_reg_reg ); // FIXME
11290
// Shorts vector arithmetic right shift
11291
instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{
11292
predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11293
match(Set dst (RShiftVS src shift));
11295
ins_cost(DEFAULT_COST); // FIXME
11297
vsha4S_reg(dst, src, shift);
11301
instruct vsra4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11302
predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11303
match(Set dst (RShiftVS src shift));
11306
ins_cost(DEFAULT_COST*2);
11308
"VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11309
"VSHL.S16 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed4S"
11313
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11314
MacroAssembler::VELEM_SIZE_8, quad);
11315
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11316
MacroAssembler::VELEM_SIZE_16, quad);
11318
ins_pipe(ialu_reg_reg);
11321
instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{
11322
predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11323
match(Set dst (RShiftVS src shift));
11325
ins_cost(DEFAULT_COST); // FIXME
11327
vsha8S_reg(dst, src, shift);
11331
instruct vsra8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11332
predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11333
match(Set dst (RShiftVS src shift));
11336
ins_cost(DEFAULT_COST*2);
11338
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11339
"VSHL.S16 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed8S"
11343
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11344
MacroAssembler::VELEM_SIZE_8, quad);
11345
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11346
MacroAssembler::VELEM_SIZE_16, quad);
11348
ins_pipe(ialu_reg_reg);
11351
instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{
11352
predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11353
match(Set dst (RShiftVS src (RShiftCntV shift)));
11355
ins_cost(DEFAULT_COST); // FIXME
11357
"VSHR.S16 $dst.D,$src.D,$shift\t! arithmetic right shift packed4S"
11361
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11364
ins_pipe( ialu_reg_reg ); // FIXME
11367
instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{
11368
predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11369
match(Set dst (RShiftVS src (RShiftCntV shift)));
11371
ins_cost(DEFAULT_COST); // FIXME
11373
"VSHR.S16 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed8S"
11377
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11380
ins_pipe( ialu_reg_reg ); // FIXME
11383
// Integers vector arithmetic right shift
11384
instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{
11385
predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11386
match(Set dst (RShiftVI src shift));
11388
ins_cost(DEFAULT_COST); // FIXME
11390
vsha2I_reg(dst, src, shift);
11394
instruct vsra2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11395
predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11396
match(Set dst (RShiftVI src shift));
11399
ins_cost(DEFAULT_COST*2);
11401
"VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11402
"VSHL.S32 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed2I"
11406
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11407
MacroAssembler::VELEM_SIZE_8, quad);
11408
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11409
MacroAssembler::VELEM_SIZE_32, quad);
11411
ins_pipe(ialu_reg_reg);
11414
instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{
11415
predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11416
match(Set dst (RShiftVI src shift));
11418
ins_cost(DEFAULT_COST); // FIXME
11420
vsha4I_reg(dst, src, shift);
11424
instruct vsra4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11425
predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11426
match(Set dst (RShiftVI src shift));
11429
ins_cost(DEFAULT_COST*2);
11431
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11432
"VSHL.S32 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed4I"
11436
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11437
MacroAssembler::VELEM_SIZE_8, quad);
11438
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11439
MacroAssembler::VELEM_SIZE_32, quad);
11441
ins_pipe(ialu_reg_reg);
11444
instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{
11445
predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11446
match(Set dst (RShiftVI src (RShiftCntV shift)));
11448
ins_cost(DEFAULT_COST); // FIXME
11450
"VSHR.S32 $dst.D,$src.D,$shift\t! arithmetic right shift packed2I"
11454
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11457
ins_pipe( ialu_reg_reg ); // FIXME
11460
instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{
11461
predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11462
match(Set dst (RShiftVI src (RShiftCntV shift)));
11464
ins_cost(DEFAULT_COST); // FIXME
11466
"VSHR.S32 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed4I"
11470
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11473
ins_pipe( ialu_reg_reg ); // FIXME
11476
// Longs vector arithmetic right shift
11477
instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{
11478
predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11479
match(Set dst (RShiftVL src shift));
11481
ins_cost(DEFAULT_COST); // FIXME
11483
vsha2L_reg(dst, src, shift);
11487
instruct vsra2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11488
predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11489
match(Set dst (RShiftVL src shift));
11492
ins_cost(DEFAULT_COST*2);
11494
"VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11495
"VSHL.S64 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed2L"
11499
__ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11500
MacroAssembler::VELEM_SIZE_8, quad);
11501
__ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11502
MacroAssembler::VELEM_SIZE_64, quad);
11504
ins_pipe(ialu_reg_reg);
11507
instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{
11508
predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11509
match(Set dst (RShiftVL src (RShiftCntV shift)));
11511
ins_cost(DEFAULT_COST); // FIXME
11513
"VSHR.S64 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed2L"
11517
__ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11520
ins_pipe( ialu_reg_reg ); // FIXME
11523
// --------------------------------- AND --------------------------------------
11525
instruct vandD(vecD dst, vecD src1, vecD src2) %{
11526
predicate(n->as_Vector()->length_in_bytes() == 8);
11527
match(Set dst (AndV src1 src2));
11528
format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11531
__ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11534
ins_pipe( ialu_reg_reg ); // FIXME
11537
instruct vandX(vecX dst, vecX src1, vecX src2) %{
11538
predicate(n->as_Vector()->length_in_bytes() == 16);
11539
match(Set dst (AndV src1 src2));
11540
format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11543
__ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11546
ins_pipe( ialu_reg_reg ); // FIXME
11549
// --------------------------------- OR ---------------------------------------
11551
instruct vorD(vecD dst, vecD src1, vecD src2) %{
11552
predicate(n->as_Vector()->length_in_bytes() == 8);
11553
match(Set dst (OrV src1 src2));
11554
format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11557
__ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11560
ins_pipe( ialu_reg_reg ); // FIXME
11563
instruct vorX(vecX dst, vecX src1, vecX src2) %{
11564
predicate(n->as_Vector()->length_in_bytes() == 16);
11565
match(Set dst (OrV src1 src2));
11566
format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11569
__ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11572
ins_pipe( ialu_reg_reg ); // FIXME
11575
// --------------------------------- XOR --------------------------------------
11577
instruct vxorD(vecD dst, vecD src1, vecD src2) %{
11578
predicate(n->as_Vector()->length_in_bytes() == 8);
11579
match(Set dst (XorV src1 src2));
11580
format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11583
__ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11586
ins_pipe( ialu_reg_reg ); // FIXME
11589
instruct vxorX(vecX dst, vecX src1, vecX src2) %{
11590
predicate(n->as_Vector()->length_in_bytes() == 16);
11591
match(Set dst (XorV src1 src2));
11592
format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11595
__ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11598
ins_pipe( ialu_reg_reg ); // FIXME
11602
//----------PEEPHOLE RULES-----------------------------------------------------
11603
// These must follow all instruction definitions as they use the names
11604
// defined in the instructions definitions.
11606
// peepmatch ( root_instr_name [preceding_instruction]* );
11608
// peepconstraint %{
11609
// (instruction_number.operand_name relational_op instruction_number.operand_name
11611
// // instruction numbers are zero-based using left to right order in peepmatch
11613
// peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
11614
// // provide an instruction_number.operand_name for each operand that appears
11615
// // in the replacement instruction's match rule
11617
// ---------VM FLAGS---------------------------------------------------------
11619
// All peephole optimizations can be turned off using -XX:-OptoPeephole
11621
// Each peephole rule is given an identifying number starting with zero and
11622
// increasing by one in the order seen by the parser. An individual peephole
11623
// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
11624
// on the command-line.
11626
// ---------CURRENT LIMITATIONS----------------------------------------------
11628
// Only match adjacent instructions in same basic block
11629
// Only equality constraints
11630
// Only constraints between operands, not (0.dest_reg == EAX_enc)
11631
// Only one replacement instruction
11633
// ---------EXAMPLE----------------------------------------------------------
11635
// // pertinent parts of existing instructions in architecture description
11636
// instruct movI(eRegI dst, eRegI src) %{
11637
// match(Set dst (CopyI src));
11640
// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{
11641
// match(Set dst (AddI dst src));
11645
// // Change (inc mov) to lea
11647
// // increment preceded by register-register move
11648
// peepmatch ( incI_eReg movI );
11649
// // require that the destination register of the increment
11650
// // match the destination register of the move
11651
// peepconstraint ( 0.dst == 1.dst );
11652
// // construct a replacement instruction that sets
11653
// // the destination to ( move's source register + one )
11654
// peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) );
11658
// // Change load of spilled value to only a spill
11659
// instruct storeI(memory mem, eRegI src) %{
11660
// match(Set mem (StoreI mem src));
11663
// instruct loadI(eRegI dst, memory mem) %{
11664
// match(Set dst (LoadI mem));
11668
// peepmatch ( loadI storeI );
11669
// peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
11670
// peepreplace ( storeI( 1.mem 1.mem 1.src ) );
11673
//----------SMARTSPILL RULES---------------------------------------------------
11674
// These must follow all instruction definitions as they use the names
11675
// defined in the instructions definitions.
11677
// ARM will probably not have any of these rules due to RISC instruction set.
11679
//----------PIPELINE-----------------------------------------------------------
11680
// Rules which define the behavior of the target architectures pipeline.