1//
2// Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
3// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4//
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.
8//
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).
14//
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.
18//
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
21// questions.
22//
23
24// ARM Architecture Description File
25
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]
29// Format:
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>");
36//
37definitions %{
38// The default cost (of an ALU instruction).
39  int_def DEFAULT_COST      (    100,     100);
40  int_def HUGE_COST         (1000000, 1000000);
41
42// Memory refs are twice as expensive as run-of-the-mill.
43  int_def MEMORY_REF_COST   (    200, DEFAULT_COST * 2);
44
45// Branches are even more expensive.
46  int_def BRANCH_COST       (    300, DEFAULT_COST * 3);
47  int_def CALL_COST         (    300, DEFAULT_COST * 3);
48%}
49
50
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
54source_hpp %{
55// Header information of the source block.
56// Method declarations/definitions which are used outside
57// the ad-scope can conveniently be defined here.
58//
59// To keep related declarations/definitions/uses close together,
60// we switch between source %{ }% and source_hpp %{ }% freely as needed.
61
62// Does destination need to be loaded in a register then passed to a
63// branch instruction?
64extern bool maybe_far_call(const CallNode *n);
65extern bool maybe_far_call(const MachCallNode *n);
66static inline bool cache_reachable() {
67  return MacroAssembler::_cache_fully_reachable();
68}
69
70#ifdef AARCH64
71#define ldr_32 ldr_w
72#define str_32 str_w
73#else
74#define ldr_32 ldr
75#define str_32 str
76#define tst_32 tst
77#define teq_32 teq
78#endif
79#if 1
80extern bool PrintOptoAssembly;
81#endif
82
83class c2 {
84public:
85  static OptoRegPair return_value(int ideal_reg);
86};
87
88class CallStubImpl {
89
90  //--------------------------------------------------------------
91  //---<  Used for optimization in Compile::Shorten_branches  >---
92  //--------------------------------------------------------------
93
94 public:
95  // Size of call trampoline stub.
96  static uint size_call_trampoline() {
97    return 0; // no call trampolines on this platform
98  }
99
100  // number of relocations needed by a call trampoline stub
101  static uint reloc_call_trampoline() {
102    return 0; // no call trampolines on this platform
103  }
104};
105
106class HandlerImpl {
107
108 public:
109
110  static int emit_exception_handler(CodeBuffer &cbuf);
111  static int emit_deopt_handler(CodeBuffer& cbuf);
112
113  static uint size_exception_handler() {
114#ifdef AARCH64
115    // ldr_literal; br; (pad); <literal>
116    return 3 * Assembler::InstructionSize + wordSize;
117#else
118    return ( 3 * 4 );
119#endif
120  }
121
122
123  static uint size_deopt_handler() {
124    return ( 9 * 4 );
125  }
126
127};
128
129%}
130
131source %{
132#define __ _masm.
133
134static FloatRegister reg_to_FloatRegister_object(int register_encoding);
135static Register reg_to_register_object(int register_encoding);
136
137
138// ****************************************************************************
139
140// REQUIRED FUNCTIONALITY
141
142// Indicate if the safepoint node needs the polling page as an input.
143// Since ARM does not have absolute addressing, it does.
144bool SafePointNode::needs_polling_address_input() {
145  return true;
146}
147
148// emit an interrupt that is caught by the debugger (for debugging compiler)
149void emit_break(CodeBuffer &cbuf) {
150  MacroAssembler _masm(&cbuf);
151  __ breakpoint();
152}
153
154#ifndef PRODUCT
155void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const {
156  st->print("TA");
157}
158#endif
159
160void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
161  emit_break(cbuf);
162}
163
164uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
165  return MachNode::size(ra_);
166}
167
168
169void emit_nop(CodeBuffer &cbuf) {
170  MacroAssembler _masm(&cbuf);
171  __ nop();
172}
173
174
175void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) {
176  int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset();
177  int call_site_offset = cbuf.insts()->mark_off();
178  MacroAssembler _masm(&cbuf);
179  __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call
180  address target = (address)m->method();
181  assert(n->as_MachCall()->entry_point() == target, "sanity");
182  assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity");
183  assert(cache_reachable() == __ cache_fully_reachable(), "sanity");
184
185  assert(target != NULL, "need real address");
186
187  int ret_addr_offset = -1;
188  if (rspec.type() == relocInfo::runtime_call_type) {
189    __ call(target, rspec);
190    ret_addr_offset = __ offset();
191  } else {
192    // scratches Rtemp
193    ret_addr_offset = __ patchable_call(target, rspec, true);
194  }
195  assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()");
196}
197
198//=============================================================================
199// REQUIRED FUNCTIONALITY for encoding
200void emit_lo(CodeBuffer &cbuf, int val) {  }
201void emit_hi(CodeBuffer &cbuf, int val) {  }
202
203
204//=============================================================================
205const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
206
207int Compile::ConstantTable::calculate_table_base_offset() const {
208#ifdef AARCH64
209  return 0;
210#else
211  int offset = -(size() / 2);
212  // flds, fldd: 8-bit  offset multiplied by 4: +/- 1024
213  // ldr, ldrb : 12-bit offset:                 +/- 4096
214  if (!Assembler::is_simm10(offset)) {
215    offset = Assembler::min_simm10;
216  }
217  return offset;
218#endif
219}
220
221bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
222void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
223  ShouldNotReachHere();
224}
225
226void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
227  Compile* C = ra_->C;
228  Compile::ConstantTable& constant_table = C->constant_table();
229  MacroAssembler _masm(&cbuf);
230
231  Register r = as_Register(ra_->get_encode(this));
232  CodeSection* consts_section = __ code()->consts();
233  int consts_size = consts_section->align_at_start(consts_section->size());
234  assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size);
235
236  // Materialize the constant table base.
237  address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
238  RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
239  __ mov_address(r, baseaddr, rspec);
240}
241
242uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
243#ifdef AARCH64
244  return 5 * Assembler::InstructionSize;
245#else
246  return 8;
247#endif
248}
249
250#ifndef PRODUCT
251void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
252  char reg[128];
253  ra_->dump_register(this, reg);
254  st->print("MOV_SLOW    &constanttable,%s\t! constant table base", reg);
255}
256#endif
257
258#ifndef PRODUCT
259void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
260  Compile* C = ra_->C;
261
262  for (int i = 0; i < OptoPrologueNops; i++) {
263    st->print_cr("NOP"); st->print("\t");
264  }
265#ifdef AARCH64
266  if (OptoPrologueNops <= 0) {
267    st->print_cr("NOP\t! required for safe patching");
268    st->print("\t");
269  }
270#endif
271
272  size_t framesize = C->frame_size_in_bytes();
273  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
274  int bangsize = C->bang_size_in_bytes();
275  // Remove two words for return addr and rbp,
276  framesize -= 2*wordSize;
277  bangsize -= 2*wordSize;
278
279  // Calls to C2R adapters often do not accept exceptional returns.
280  // We require that their callers must bang for them.  But be careful, because
281  // some VM calls (such as call site linkage) can use several kilobytes of
282  // stack.  But the stack safety zone should account for that.
283  // See bugs 4446381, 4468289, 4497237.
284  if (C->need_stack_bang(bangsize)) {
285    st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
286  }
287  st->print_cr("PUSH   R_FP|R_LR_LR"); st->print("\t");
288  if (framesize != 0) {
289    st->print   ("SUB    R_SP, R_SP, " SIZE_FORMAT,framesize);
290  }
291}
292#endif
293
294void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
295  Compile* C = ra_->C;
296  MacroAssembler _masm(&cbuf);
297
298  for (int i = 0; i < OptoPrologueNops; i++) {
299    __ nop();
300  }
301#ifdef AARCH64
302  if (OptoPrologueNops <= 0) {
303    __ nop(); // required for safe patching by patch_verified_entry()
304  }
305#endif
306
307  size_t framesize = C->frame_size_in_bytes();
308  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
309  int bangsize = C->bang_size_in_bytes();
310  // Remove two words for return addr and fp,
311  framesize -= 2*wordSize;
312  bangsize -= 2*wordSize;
313
314  // Calls to C2R adapters often do not accept exceptional returns.
315  // We require that their callers must bang for them.  But be careful, because
316  // some VM calls (such as call site linkage) can use several kilobytes of
317  // stack.  But the stack safety zone should account for that.
318  // See bugs 4446381, 4468289, 4497237.
319  if (C->need_stack_bang(bangsize)) {
320    __ arm_stack_overflow_check(bangsize, Rtemp);
321  }
322
323  __ raw_push(FP, LR);
324  if (framesize != 0) {
325    __ sub_slow(SP, SP, framesize);
326  }
327
328  // offset from scratch buffer is not valid
329  if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) {
330    C->set_frame_complete( __ offset() );
331  }
332
333  if (C->has_mach_constant_base_node()) {
334    // NOTE: We set the table base offset here because users might be
335    // emitted before MachConstantBaseNode.
336    Compile::ConstantTable& constant_table = C->constant_table();
337    constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
338  }
339}
340
341uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
342  return MachNode::size(ra_);
343}
344
345int MachPrologNode::reloc() const {
346  return 10; // a large enough number
347}
348
349//=============================================================================
350#ifndef PRODUCT
351void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
352  Compile* C = ra_->C;
353
354  size_t framesize = C->frame_size_in_bytes();
355  framesize -= 2*wordSize;
356
357  if (framesize != 0) {
358    st->print("ADD    R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize);
359  }
360  st->print("POP    R_FP|R_LR_LR");
361
362  if (do_polling() && ra_->C->is_method_compilation()) {
363    st->print("\n\t");
364#ifdef AARCH64
365    if (MacroAssembler::page_reachable_from_cache(os::get_polling_page())) {
366      st->print("ADRP     Rtemp, #PollAddr\t! Load Polling address\n\t");
367      st->print("LDR      ZR,[Rtemp + #PollAddr & 0xfff]\t!Poll for Safepointing");
368    } else {
369      st->print("mov_slow Rtemp, #PollAddr\t! Load Polling address\n\t");
370      st->print("LDR      ZR,[Rtemp]\t!Poll for Safepointing");
371    }
372#else
373    st->print("MOV    Rtemp, #PollAddr\t! Load Polling address\n\t");
374    st->print("LDR    Rtemp,[Rtemp]\t!Poll for Safepointing");
375#endif
376  }
377}
378#endif
379
380void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
381  MacroAssembler _masm(&cbuf);
382  Compile* C = ra_->C;
383
384  size_t framesize = C->frame_size_in_bytes();
385  framesize -= 2*wordSize;
386  if (framesize != 0) {
387    __ add_slow(SP, SP, framesize);
388  }
389  __ raw_pop(FP, LR);
390
391  // If this does safepoint polling, then do it here
392  if (do_polling() && ra_->C->is_method_compilation()) {
393#ifdef AARCH64
394    if (false && MacroAssembler::page_reachable_from_cache(os::get_polling_page())) {
395/* FIXME: TODO
396      __ relocate(relocInfo::xxx);
397      __ adrp(Rtemp, (intptr_t)os::get_polling_page());
398      __ relocate(relocInfo::poll_return_type);
399      int offset = os::get_polling_page() & 0xfff;
400      __ ldr(ZR, Address(Rtemp + offset));
401*/
402    } else {
403      __ mov_address(Rtemp, (address)os::get_polling_page(), symbolic_Relocation::polling_page_reference);
404      __ relocate(relocInfo::poll_return_type);
405      __ ldr(ZR, Address(Rtemp));
406    }
407#else
408    // mov_slow here is usually one or two instruction
409    __ mov_address(Rtemp, (address)os::get_polling_page(), symbolic_Relocation::polling_page_reference);
410    __ relocate(relocInfo::poll_return_type);
411    __ ldr(Rtemp, Address(Rtemp));
412#endif
413  }
414}
415
416uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
417#ifdef AARCH64
418  // allow for added alignment nop from mov_address bind_literal
419  return MachNode::size(ra_) + 1 * Assembler::InstructionSize;
420#else
421  return MachNode::size(ra_);
422#endif
423}
424
425int MachEpilogNode::reloc() const {
426  return 16; // a large enough number
427}
428
429const Pipeline * MachEpilogNode::pipeline() const {
430  return MachNode::pipeline_class();
431}
432
433int MachEpilogNode::safepoint_offset() const {
434  assert( do_polling(), "no return for this epilog node");
435  //  return MacroAssembler::size_of_sethi(os::get_polling_page());
436  Unimplemented();
437  return 0;
438}
439
440//=============================================================================
441
442// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
443enum RC { rc_bad, rc_int, rc_float, rc_stack };
444static enum RC rc_class( OptoReg::Name reg ) {
445  if (!OptoReg::is_valid(reg)) return rc_bad;
446  if (OptoReg::is_stack(reg)) return rc_stack;
447  VMReg r = OptoReg::as_VMReg(reg);
448  if (r->is_Register()) return rc_int;
449  assert(r->is_FloatRegister(), "must be");
450  return rc_float;
451}
452
453static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) {
454#ifdef AARCH64
455  return is_memoryHD(offset);
456#else
457  int rlo = Matcher::_regEncode[src_first];
458  int rhi = Matcher::_regEncode[src_second];
459  if (!((rlo&1)==0 && (rlo+1 == rhi))) {
460    tty->print_cr("CAUGHT BAD LDRD/STRD");
461  }
462  return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset);
463#endif
464}
465
466uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
467                                        PhaseRegAlloc *ra_,
468                                        bool do_size,
469                                        outputStream* st ) const {
470  // Get registers to move
471  OptoReg::Name src_second = ra_->get_reg_second(in(1));
472  OptoReg::Name src_first = ra_->get_reg_first(in(1));
473  OptoReg::Name dst_second = ra_->get_reg_second(this );
474  OptoReg::Name dst_first = ra_->get_reg_first(this );
475
476  enum RC src_second_rc = rc_class(src_second);
477  enum RC src_first_rc = rc_class(src_first);
478  enum RC dst_second_rc = rc_class(dst_second);
479  enum RC dst_first_rc = rc_class(dst_first);
480
481  assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
482
483  // Generate spill code!
484  int size = 0;
485
486  if (src_first == dst_first && src_second == dst_second)
487    return size;            // Self copy, no move
488
489#ifdef TODO
490  if (bottom_type()->isa_vect() != NULL) {
491  }
492#endif
493
494  // Shared code does not expect instruction set capability based bailouts here.
495  // Handle offset unreachable bailout with minimal change in shared code.
496  // Bailout only for real instruction emit.
497  // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
498
499  MacroAssembler _masm(cbuf);
500
501  // --------------------------------------
502  // Check for mem-mem move.  Load into unused float registers and fall into
503  // the float-store case.
504  if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
505    int offset = ra_->reg2offset(src_first);
506    if (cbuf && !is_memoryfp(offset)) {
507      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
508      return 0;
509    } else {
510      if (src_second_rc != rc_bad) {
511        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
512        src_first     = OptoReg::Name(R_mem_copy_lo_num);
513        src_second    = OptoReg::Name(R_mem_copy_hi_num);
514        src_first_rc  = rc_float;
515        src_second_rc = rc_float;
516        if (cbuf) {
517          __ ldr_double(Rmemcopy, Address(SP, offset));
518        } else if (!do_size) {
519          st->print(LDR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
520        }
521      } else {
522        src_first     = OptoReg::Name(R_mem_copy_lo_num);
523        src_first_rc  = rc_float;
524        if (cbuf) {
525          __ ldr_float(Rmemcopy, Address(SP, offset));
526        } else if (!do_size) {
527          st->print(LDR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
528        }
529      }
530      size += 4;
531    }
532  }
533
534  if (src_second_rc == rc_stack && dst_second_rc == rc_stack) {
535    Unimplemented();
536  }
537
538  // --------------------------------------
539  // Check for integer reg-reg copy
540  if (src_first_rc == rc_int && dst_first_rc == rc_int) {
541    // Else normal reg-reg copy
542    assert( src_second != dst_first, "smashed second before evacuating it" );
543    if (cbuf) {
544      __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
545#ifndef PRODUCT
546    } else if (!do_size) {
547      st->print("MOV    R_%s, R_%s\t# spill",
548                Matcher::regName[dst_first],
549                Matcher::regName[src_first]);
550#endif
551    }
552#ifdef AARCH64
553    if (src_first+1 == src_second && dst_first+1 == dst_second) {
554      return size + 4;
555    }
556#endif
557    size += 4;
558  }
559
560  // Check for integer store
561  if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
562    int offset = ra_->reg2offset(dst_first);
563    if (cbuf && !is_memoryI(offset)) {
564      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
565      return 0;
566    } else {
567      if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) {
568        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
569        if (cbuf) {
570          __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
571#ifndef PRODUCT
572        } else if (!do_size) {
573          if (size != 0) st->print("\n\t");
574          st->print(STR_64 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
575#endif
576        }
577        return size + 4;
578      } else {
579        if (cbuf) {
580          __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
581#ifndef PRODUCT
582        } else if (!do_size) {
583          if (size != 0) st->print("\n\t");
584          st->print(STR_32 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
585#endif
586        }
587      }
588    }
589    size += 4;
590  }
591
592  // Check for integer load
593  if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
594    int offset = ra_->reg2offset(src_first);
595    if (cbuf && !is_memoryI(offset)) {
596      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
597      return 0;
598    } else {
599      if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) {
600        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
601        if (cbuf) {
602          __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
603#ifndef PRODUCT
604        } else if (!do_size) {
605          if (size != 0) st->print("\n\t");
606          st->print(LDR_64 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
607#endif
608        }
609        return size + 4;
610      } else {
611        if (cbuf) {
612          __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
613#ifndef PRODUCT
614        } else if (!do_size) {
615          if (size != 0) st->print("\n\t");
616          st->print(LDR_32 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
617#endif
618        }
619      }
620    }
621    size += 4;
622  }
623
624  // Check for float reg-reg copy
625  if (src_first_rc == rc_float && dst_first_rc == rc_float) {
626    if (src_second_rc != rc_bad) {
627      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");
628      if (cbuf) {
629      __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
630#ifndef PRODUCT
631      } else if (!do_size) {
632        st->print(MOV_DOUBLE "    R_%s, R_%s\t# spill",
633                  Matcher::regName[dst_first],
634                  Matcher::regName[src_first]);
635#endif
636      }
637      return 4;
638    }
639    if (cbuf) {
640      __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
641#ifndef PRODUCT
642    } else if (!do_size) {
643      st->print(MOV_FLOAT "    R_%s, R_%s\t# spill",
644                Matcher::regName[dst_first],
645                Matcher::regName[src_first]);
646#endif
647    }
648    size = 4;
649  }
650
651  // Check for float store
652  if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
653    int offset = ra_->reg2offset(dst_first);
654    if (cbuf && !is_memoryfp(offset)) {
655      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
656      return 0;
657    } else {
658      // Further check for aligned-adjacent pair, so we can use a double store
659      if (src_second_rc != rc_bad) {
660        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");
661        if (cbuf) {
662          __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
663#ifndef PRODUCT
664        } else if (!do_size) {
665          if (size != 0) st->print("\n\t");
666          st->print(STR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
667#endif
668        }
669        return size + 4;
670      } else {
671        if (cbuf) {
672          __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
673#ifndef PRODUCT
674        } else if (!do_size) {
675          if (size != 0) st->print("\n\t");
676          st->print(STR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
677#endif
678        }
679      }
680    }
681    size += 4;
682  }
683
684  // Check for float load
685  if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
686    int offset = ra_->reg2offset(src_first);
687    if (cbuf && !is_memoryfp(offset)) {
688      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
689      return 0;
690    } else {
691      // Further check for aligned-adjacent pair, so we can use a double store
692      if (src_second_rc != rc_bad) {
693        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");
694        if (cbuf) {
695          __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
696#ifndef PRODUCT
697        } else if (!do_size) {
698          if (size != 0) st->print("\n\t");
699          st->print(LDR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
700#endif
701        }
702        return size + 4;
703      } else {
704        if (cbuf) {
705          __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
706#ifndef PRODUCT
707        } else if (!do_size) {
708          if (size != 0) st->print("\n\t");
709          st->print(LDR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
710#endif
711        }
712      }
713    }
714    size += 4;
715  }
716
717  // check for int reg -> float reg move
718  if (src_first_rc == rc_int && dst_first_rc == rc_float) {
719    // Further check for aligned-adjacent pair, so we can use a single instruction
720    if (src_second_rc != rc_bad) {
721      assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
722      assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
723      assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported");
724      if (cbuf) {
725#ifdef AARCH64
726        __ fmov_dx(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
727#else
728        __ 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]));
729#endif
730#ifndef PRODUCT
731      } else if (!do_size) {
732        if (size != 0) st->print("\n\t");
733#ifdef AARCH64
734        st->print("FMOV_DX   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
735#else
736        st->print("FMDRR   R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second));
737#endif
738#endif
739      }
740      return size + 4;
741    } else {
742      if (cbuf) {
743        __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
744#ifndef PRODUCT
745      } else if (!do_size) {
746        if (size != 0) st->print("\n\t");
747        st->print(FMSR "   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
748#endif
749      }
750      size += 4;
751    }
752  }
753
754  // check for float reg -> int reg move
755  if (src_first_rc == rc_float && dst_first_rc == rc_int) {
756    // Further check for aligned-adjacent pair, so we can use a single instruction
757    if (src_second_rc != rc_bad) {
758      assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
759      assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
760      assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported");
761      if (cbuf) {
762#ifdef AARCH64
763        __ fmov_xd(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
764#else
765        __ 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]));
766#endif
767#ifndef PRODUCT
768      } else if (!do_size) {
769        if (size != 0) st->print("\n\t");
770#ifdef AARCH64
771        st->print("FMOV_XD R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
772#else
773        st->print("FMRRD   R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first));
774#endif
775#endif
776      }
777      return size + 4;
778    } else {
779      if (cbuf) {
780        __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
781#ifndef PRODUCT
782      } else if (!do_size) {
783        if (size != 0) st->print("\n\t");
784        st->print(FMRS "   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
785#endif
786      }
787      size += 4;
788    }
789  }
790
791  // --------------------------------------------------------------------
792  // Check for hi bits still needing moving.  Only happens for misaligned
793  // arguments to native calls.
794  if (src_second == dst_second)
795    return size;               // Self copy; no move
796  assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
797
798#ifndef AARCH64
799  // Check for integer reg-reg copy.  Hi bits are stuck up in the top
800  // 32-bits of a 64-bit register, but are needed in low bits of another
801  // register (else it's a hi-bits-to-hi-bits copy which should have
802  // happened already as part of a 64-bit move)
803  if (src_second_rc == rc_int && dst_second_rc == rc_int) {
804    if (cbuf) {
805      __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second]));
806#ifndef PRODUCT
807    } else if (!do_size) {
808      if (size != 0) st->print("\n\t");
809      st->print("MOV    R_%s, R_%s\t# spill high",
810                Matcher::regName[dst_second],
811                Matcher::regName[src_second]);
812#endif
813    }
814    return size+4;
815  }
816
817  // Check for high word integer store
818  if (src_second_rc == rc_int && dst_second_rc == rc_stack) {
819    int offset = ra_->reg2offset(dst_second);
820
821    if (cbuf && !is_memoryP(offset)) {
822      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
823      return 0;
824    } else {
825      if (cbuf) {
826        __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset));
827#ifndef PRODUCT
828      } else if (!do_size) {
829        if (size != 0) st->print("\n\t");
830        st->print("STR   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset);
831#endif
832      }
833    }
834    return size + 4;
835  }
836
837  // Check for high word integer load
838  if (dst_second_rc == rc_int && src_second_rc == rc_stack) {
839    int offset = ra_->reg2offset(src_second);
840    if (cbuf && !is_memoryP(offset)) {
841      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
842      return 0;
843    } else {
844      if (cbuf) {
845        __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset));
846#ifndef PRODUCT
847      } else if (!do_size) {
848        if (size != 0) st->print("\n\t");
849        st->print("LDR   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset);
850#endif
851      }
852    }
853    return size + 4;
854  }
855#endif
856
857  Unimplemented();
858  return 0; // Mute compiler
859}
860
861#ifndef PRODUCT
862void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
863  implementation( NULL, ra_, false, st );
864}
865#endif
866
867void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
868  implementation( &cbuf, ra_, false, NULL );
869}
870
871uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
872  return implementation( NULL, ra_, true, NULL );
873}
874
875//=============================================================================
876#ifndef PRODUCT
877void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
878  st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
879}
880#endif
881
882void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const {
883  MacroAssembler _masm(&cbuf);
884  for(int i = 0; i < _count; i += 1) {
885    __ nop();
886  }
887}
888
889uint MachNopNode::size(PhaseRegAlloc *ra_) const {
890  return 4 * _count;
891}
892
893
894//=============================================================================
895#ifndef PRODUCT
896void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
897  int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
898  int reg = ra_->get_reg_first(this);
899  st->print("ADD    %s,R_SP+#%d",Matcher::regName[reg], offset);
900}
901#endif
902
903void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
904  MacroAssembler _masm(&cbuf);
905  int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
906  int reg = ra_->get_encode(this);
907  Register dst = reg_to_register_object(reg);
908
909  if (is_aimm(offset)) {
910    __ add(dst, SP, offset);
911  } else {
912    __ mov_slow(dst, offset);
913#ifdef AARCH64
914    __ add(dst, SP, dst, ex_lsl);
915#else
916    __ add(dst, SP, dst);
917#endif
918  }
919}
920
921uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
922  // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
923  assert(ra_ == ra_->C->regalloc(), "sanity");
924  return ra_->C->scratch_emit_size(this);
925}
926
927//=============================================================================
928#ifndef PRODUCT
929#ifdef AARCH64
930#define R_RTEMP "R_R16"
931#else
932#define R_RTEMP "R_R12"
933#endif
934void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
935  st->print_cr("\nUEP:");
936  if (UseCompressedClassPointers) {
937    st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
938    st->print_cr("\tdecode_klass " R_RTEMP);
939  } else {
940    st->print_cr("\tLDR   " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
941  }
942  st->print_cr("\tCMP   " R_RTEMP ",R_R8" );
943  st->print   ("\tB.NE  SharedRuntime::handle_ic_miss_stub");
944}
945#endif
946
947void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
948  MacroAssembler _masm(&cbuf);
949  Register iCache  = reg_to_register_object(Matcher::inline_cache_reg_encode());
950  assert(iCache == Ricklass, "should be");
951  Register receiver = R0;
952
953  __ load_klass(Rtemp, receiver);
954  __ cmp(Rtemp, iCache);
955#ifdef AARCH64
956  Label match;
957  __ b(match, eq);
958  __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp);
959  __ bind(match);
960#else
961  __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
962#endif
963}
964
965uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
966  return MachNode::size(ra_);
967}
968
969
970//=============================================================================
971
972// Emit exception handler code.
973int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
974  MacroAssembler _masm(&cbuf);
975
976  address base = __ start_a_stub(size_exception_handler());
977  if (base == NULL) {
978    ciEnv::current()->record_failure("CodeCache is full");
979    return 0;  // CodeBuffer::expand failed
980  }
981
982  int offset = __ offset();
983
984  // OK to trash LR, because exception blob will kill it
985  __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp);
986
987  assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
988
989  __ end_a_stub();
990
991  return offset;
992}
993
994int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
995  // Can't use any of the current frame's registers as we may have deopted
996  // at a poll and everything can be live.
997  MacroAssembler _masm(&cbuf);
998
999  address base = __ start_a_stub(size_deopt_handler());
1000  if (base == NULL) {
1001    ciEnv::current()->record_failure("CodeCache is full");
1002    return 0;  // CodeBuffer::expand failed
1003  }
1004
1005  int offset = __ offset();
1006  address deopt_pc = __ pc();
1007
1008#ifdef AARCH64
1009  // See LR saved by caller in sharedRuntime_arm.cpp
1010  // see also hse1 ws
1011  // see also LIR_Assembler::emit_deopt_handler
1012
1013  __ raw_push(LR, LR); // preserve LR in both slots
1014  __ mov_relative_address(LR, deopt_pc);
1015  __ str(LR, Address(SP, 1 * wordSize)); // save deopt PC
1016  // OK to kill LR, because deopt blob will restore it from SP[0]
1017  __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, LR_tmp);
1018#else
1019  __ sub(SP, SP, wordSize); // make room for saved PC
1020  __ push(LR); // save LR that may be live when we get here
1021  __ mov_relative_address(LR, deopt_pc);
1022  __ str(LR, Address(SP, wordSize)); // save deopt PC
1023  __ pop(LR); // restore LR
1024  __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);
1025#endif
1026
1027  assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
1028
1029  __ end_a_stub();
1030  return offset;
1031}
1032
1033const bool Matcher::match_rule_supported(int opcode) {
1034  if (!has_match_rule(opcode))
1035    return false;
1036
1037  switch (opcode) {
1038  case Op_PopCountI:
1039  case Op_PopCountL:
1040    if (!UsePopCountInstruction)
1041      return false;
1042    break;
1043  case Op_LShiftCntV:
1044  case Op_RShiftCntV:
1045  case Op_AddVB:
1046  case Op_AddVS:
1047  case Op_AddVI:
1048  case Op_AddVL:
1049  case Op_SubVB:
1050  case Op_SubVS:
1051  case Op_SubVI:
1052  case Op_SubVL:
1053  case Op_MulVS:
1054  case Op_MulVI:
1055  case Op_LShiftVB:
1056  case Op_LShiftVS:
1057  case Op_LShiftVI:
1058  case Op_LShiftVL:
1059  case Op_RShiftVB:
1060  case Op_RShiftVS:
1061  case Op_RShiftVI:
1062  case Op_RShiftVL:
1063  case Op_URShiftVB:
1064  case Op_URShiftVS:
1065  case Op_URShiftVI:
1066  case Op_URShiftVL:
1067  case Op_AndV:
1068  case Op_OrV:
1069  case Op_XorV:
1070    return VM_Version::has_simd();
1071  case Op_LoadVector:
1072  case Op_StoreVector:
1073  case Op_AddVF:
1074  case Op_SubVF:
1075  case Op_MulVF:
1076#ifdef AARCH64
1077    return VM_Version::has_simd();
1078#else
1079    return VM_Version::has_vfp() || VM_Version::has_simd();
1080#endif
1081  case Op_AddVD:
1082  case Op_SubVD:
1083  case Op_MulVD:
1084  case Op_DivVF:
1085  case Op_DivVD:
1086#ifdef AARCH64
1087    return VM_Version::has_simd();
1088#else
1089    return VM_Version::has_vfp();
1090#endif
1091  }
1092
1093  return true;  // Per default match rules are supported.
1094}
1095
1096const bool Matcher::match_rule_supported_vector(int opcode, int vlen) {
1097
1098  // TODO
1099  // identify extra cases that we might want to provide match rules for
1100  // e.g. Op_ vector nodes and other intrinsics while guarding with vlen
1101  bool ret_value = match_rule_supported(opcode);
1102  // Add rules here.
1103
1104  return ret_value;  // Per default match rules are supported.
1105}
1106
1107const bool Matcher::has_predicated_vectors(void) {
1108  return false;
1109}
1110
1111const int Matcher::float_pressure(int default_pressure_threshold) {
1112  return default_pressure_threshold;
1113}
1114
1115int Matcher::regnum_to_fpu_offset(int regnum) {
1116  return regnum - 32; // The FP registers are in the second chunk
1117}
1118
1119// Vector width in bytes
1120const int Matcher::vector_width_in_bytes(BasicType bt) {
1121  return MaxVectorSize;
1122}
1123
1124// Vector ideal reg corresponding to specified size in bytes
1125const uint Matcher::vector_ideal_reg(int size) {
1126  assert(MaxVectorSize >= size, "");
1127  switch(size) {
1128    case  8: return Op_VecD;
1129    case 16: return Op_VecX;
1130  }
1131  ShouldNotReachHere();
1132  return 0;
1133}
1134
1135const uint Matcher::vector_shift_count_ideal_reg(int size) {
1136  return vector_ideal_reg(size);
1137}
1138
1139// Limits on vector size (number of elements) loaded into vector.
1140const int Matcher::max_vector_size(const BasicType bt) {
1141  assert(is_java_primitive(bt), "only primitive type vectors");
1142  return vector_width_in_bytes(bt)/type2aelembytes(bt);
1143}
1144
1145const int Matcher::min_vector_size(const BasicType bt) {
1146  assert(is_java_primitive(bt), "only primitive type vectors");
1147  return 8/type2aelembytes(bt);
1148}
1149
1150// ARM doesn't support misaligned vectors store/load.
1151const bool Matcher::misaligned_vectors_ok() {
1152  return false;
1153}
1154
1155// ARM doesn't support AES intrinsics
1156const bool Matcher::pass_original_key_for_aes() {
1157  return false;
1158}
1159
1160const bool Matcher::convL2FSupported(void) {
1161#ifdef AARCH64
1162  return true;
1163#else
1164  return false;
1165#endif
1166}
1167
1168// Is this branch offset short enough that a short branch can be used?
1169//
1170// NOTE: If the platform does not provide any short branch variants, then
1171//       this method should return false for offset 0.
1172bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1173  // The passed offset is relative to address of the branch.
1174  // On ARM a branch displacement is calculated relative to address
1175  // of the branch + 8.
1176  //
1177  // offset -= 8;
1178  // return (Assembler::is_simm24(offset));
1179  return false;
1180}
1181
1182const bool Matcher::isSimpleConstant64(jlong value) {
1183  // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?.
1184#ifdef AARCH64
1185  return (value == 0);
1186#else
1187  return false;
1188#endif
1189}
1190
1191// No scaling for the parameter the ClearArray node.
1192const bool Matcher::init_array_count_is_in_bytes = true;
1193
1194#ifdef AARCH64
1195const int Matcher::long_cmove_cost() { return 1; }
1196#else
1197// Needs 2 CMOV's for longs.
1198const int Matcher::long_cmove_cost() { return 2; }
1199#endif
1200
1201#ifdef AARCH64
1202const int Matcher::float_cmove_cost() { return 1; }
1203#else
1204// CMOVF/CMOVD are expensive on ARM.
1205const int Matcher::float_cmove_cost() { return ConditionalMoveLimit; }
1206#endif
1207
1208// Does the CPU require late expand (see block.cpp for description of late expand)?
1209const bool Matcher::require_postalloc_expand = false;
1210
1211// Do we need to mask the count passed to shift instructions or does
1212// the cpu only look at the lower 5/6 bits anyway?
1213// FIXME: does this handle vector shifts as well?
1214#ifdef AARCH64
1215const bool Matcher::need_masked_shift_count = false;
1216#else
1217const bool Matcher::need_masked_shift_count = true;
1218#endif
1219
1220const bool Matcher::convi2l_type_required = true;
1221
1222// Should the Matcher clone shifts on addressing modes, expecting them
1223// to be subsumed into complex addressing expressions or compute them
1224// into registers?
1225bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
1226  return clone_base_plus_offset_address(m, mstack, address_visited);
1227}
1228
1229void Compile::reshape_address(AddPNode* addp) {
1230}
1231
1232bool Matcher::narrow_oop_use_complex_address() {
1233  NOT_LP64(ShouldNotCallThis());
1234  assert(UseCompressedOops, "only for compressed oops code");
1235  return false;
1236}
1237
1238bool Matcher::narrow_klass_use_complex_address() {
1239  NOT_LP64(ShouldNotCallThis());
1240  assert(UseCompressedClassPointers, "only for compressed klass code");
1241  return false;
1242}
1243
1244bool Matcher::const_oop_prefer_decode() {
1245  NOT_LP64(ShouldNotCallThis());
1246  return true;
1247}
1248
1249bool Matcher::const_klass_prefer_decode() {
1250  NOT_LP64(ShouldNotCallThis());
1251  return true;
1252}
1253
1254// Is it better to copy float constants, or load them directly from memory?
1255// Intel can load a float constant from a direct address, requiring no
1256// extra registers.  Most RISCs will have to materialize an address into a
1257// register first, so they would do better to copy the constant from stack.
1258const bool Matcher::rematerialize_float_constants = false;
1259
1260// If CPU can load and store mis-aligned doubles directly then no fixup is
1261// needed.  Else we split the double into 2 integer pieces and move it
1262// piece-by-piece.  Only happens when passing doubles into C code as the
1263// Java calling convention forces doubles to be aligned.
1264#ifdef AARCH64
1265// On stack replacement support:
1266// We don't need Load[DL]_unaligned support, because interpreter stack
1267// has correct alignment
1268const bool Matcher::misaligned_doubles_ok = true;
1269#else
1270const bool Matcher::misaligned_doubles_ok = false;
1271#endif
1272
1273// No-op on ARM.
1274void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) {
1275}
1276
1277// Advertise here if the CPU requires explicit rounding operations
1278// to implement the UseStrictFP mode.
1279const bool Matcher::strict_fp_requires_explicit_rounding = false;
1280
1281// Are floats converted to double when stored to stack during deoptimization?
1282// ARM does not handle callee-save floats.
1283bool Matcher::float_in_double() {
1284  return false;
1285}
1286
1287// Do ints take an entire long register or just half?
1288// Note that we if-def off of _LP64.
1289// The relevant question is how the int is callee-saved.  In _LP64
1290// the whole long is written but de-opt'ing will have to extract
1291// the relevant 32 bits, in not-_LP64 only the low 32 bits is written.
1292#ifdef _LP64
1293const bool Matcher::int_in_long = true;
1294#else
1295const bool Matcher::int_in_long = false;
1296#endif
1297
1298// Return whether or not this register is ever used as an argument.  This
1299// function is used on startup to build the trampoline stubs in generateOptoStub.
1300// Registers not mentioned will be killed by the VM call in the trampoline, and
1301// arguments in those registers not be available to the callee.
1302bool Matcher::can_be_java_arg( int reg ) {
1303#ifdef AARCH64
1304  if (reg >= R_R0_num && reg < R_R8_num) return true;
1305  if (reg >= R_V0_num && reg <= R_V7b_num && ((reg & 3) < 2)) return true;
1306#else
1307  if (reg == R_R0_num ||
1308      reg == R_R1_num ||
1309      reg == R_R2_num ||
1310      reg == R_R3_num) return true;
1311
1312  if (reg >= R_S0_num &&
1313      reg <= R_S13_num) return true;
1314#endif
1315  return false;
1316}
1317
1318bool Matcher::is_spillable_arg( int reg ) {
1319  return can_be_java_arg(reg);
1320}
1321
1322bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
1323  return false;
1324}
1325
1326// Register for DIVI projection of divmodI
1327RegMask Matcher::divI_proj_mask() {
1328  ShouldNotReachHere();
1329  return RegMask();
1330}
1331
1332// Register for MODI projection of divmodI
1333RegMask Matcher::modI_proj_mask() {
1334  ShouldNotReachHere();
1335  return RegMask();
1336}
1337
1338// Register for DIVL projection of divmodL
1339RegMask Matcher::divL_proj_mask() {
1340  ShouldNotReachHere();
1341  return RegMask();
1342}
1343
1344// Register for MODL projection of divmodL
1345RegMask Matcher::modL_proj_mask() {
1346  ShouldNotReachHere();
1347  return RegMask();
1348}
1349
1350const RegMask Matcher::method_handle_invoke_SP_save_mask() {
1351  return FP_REGP_mask();
1352}
1353
1354bool maybe_far_call(const CallNode *n) {
1355  return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
1356}
1357
1358bool maybe_far_call(const MachCallNode *n) {
1359  return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
1360}
1361
1362%}
1363
1364//----------ENCODING BLOCK-----------------------------------------------------
1365// This block specifies the encoding classes used by the compiler to output
1366// byte streams.  Encoding classes are parameterized macros used by
1367// Machine Instruction Nodes in order to generate the bit encoding of the
1368// instruction.  Operands specify their base encoding interface with the
1369// interface keyword.  There are currently supported four interfaces,
1370// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER.  REG_INTER causes an
1371// operand to generate a function which returns its register number when
1372// queried.   CONST_INTER causes an operand to generate a function which
1373// returns the value of the constant when queried.  MEMORY_INTER causes an
1374// operand to generate four functions which return the Base Register, the
1375// Index Register, the Scale Value, and the Offset Value of the operand when
1376// queried.  COND_INTER causes an operand to generate six functions which
1377// return the encoding code (ie - encoding bits for the instruction)
1378// associated with each basic boolean condition for a conditional instruction.
1379//
1380// Instructions specify two basic values for encoding.  Again, a function
1381// is available to check if the constant displacement is an oop. They use the
1382// ins_encode keyword to specify their encoding classes (which must be
1383// a sequence of enc_class names, and their parameters, specified in
1384// the encoding block), and they use the
1385// opcode keyword to specify, in order, their primary, secondary, and
1386// tertiary opcode.  Only the opcode sections which a particular instruction
1387// needs for encoding need to be specified.
1388encode %{
1389  enc_class call_epilog %{
1390    // nothing
1391  %}
1392
1393  enc_class Java_To_Runtime (method meth) %{
1394    // CALL directly to the runtime
1395    emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec());
1396  %}
1397
1398  enc_class Java_Static_Call (method meth) %{
1399    // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
1400    // who we intended to call.
1401
1402    if ( !_method) {
1403      emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec());
1404    } else {
1405      int method_index = resolved_method_index(cbuf);
1406      RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1407                                                  : static_call_Relocation::spec(method_index);
1408      emit_call_reloc(cbuf, as_MachCall(), $meth, rspec);
1409
1410      // Emit stubs for static call.
1411      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
1412      if (stub == NULL) {
1413        ciEnv::current()->record_failure("CodeCache is full");
1414        return;
1415      }
1416    }
1417  %}
1418
1419  enc_class save_last_PC %{
1420    // preserve mark
1421    address mark = cbuf.insts()->mark();
1422    debug_only(int off0 = cbuf.insts_size());
1423    MacroAssembler _masm(&cbuf);
1424    int ret_addr_offset = as_MachCall()->ret_addr_offset();
1425    __ adr(LR, mark + ret_addr_offset);
1426    __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
1427    debug_only(int off1 = cbuf.insts_size());
1428    assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
1429    // restore mark
1430    cbuf.insts()->set_mark(mark);
1431  %}
1432
1433  enc_class preserve_SP %{
1434    // preserve mark
1435    address mark = cbuf.insts()->mark();
1436    debug_only(int off0 = cbuf.insts_size());
1437    MacroAssembler _masm(&cbuf);
1438    // FP is preserved across all calls, even compiled calls.
1439    // Use it to preserve SP in places where the callee might change the SP.
1440    __ mov(Rmh_SP_save, SP);
1441    debug_only(int off1 = cbuf.insts_size());
1442    assert(off1 - off0 == 4, "correct size prediction");
1443    // restore mark
1444    cbuf.insts()->set_mark(mark);
1445  %}
1446
1447  enc_class restore_SP %{
1448    MacroAssembler _masm(&cbuf);
1449    __ mov(SP, Rmh_SP_save);
1450  %}
1451
1452  enc_class Java_Dynamic_Call (method meth) %{
1453    MacroAssembler _masm(&cbuf);
1454    Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
1455    assert(R8_ic_reg == Ricklass, "should be");
1456    __ set_inst_mark();
1457#ifdef AARCH64
1458// TODO: see C1 LIR_Assembler::ic_call()
1459    InlinedAddress oop_literal((address)Universe::non_oop_word());
1460    int offset = __ offset();
1461    int fixed_size = mov_oop_size * 4;
1462    if (VM_Version::prefer_moves_over_load_literal()) {
1463      uintptr_t val = (uintptr_t)Universe::non_oop_word();
1464      __ movz(R8_ic_reg, (val >>  0) & 0xffff,  0);
1465      __ movk(R8_ic_reg, (val >> 16) & 0xffff, 16);
1466      __ movk(R8_ic_reg, (val >> 32) & 0xffff, 32);
1467      __ movk(R8_ic_reg, (val >> 48) & 0xffff, 48);
1468    } else {
1469      __ ldr_literal(R8_ic_reg, oop_literal);
1470    }
1471    assert(__ offset() - offset == fixed_size, "bad mov_oop size");
1472#else
1473    __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff);
1474    __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16);
1475#endif
1476    address  virtual_call_oop_addr = __ inst_mark();
1477    // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
1478    // who we intended to call.
1479    int method_index = resolved_method_index(cbuf);
1480    __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
1481    emit_call_reloc(cbuf, as_MachCall(), $meth, RelocationHolder::none);
1482#ifdef AARCH64
1483    if (!VM_Version::prefer_moves_over_load_literal()) {
1484      Label skip_literal;
1485      __ b(skip_literal);
1486      int off2 = __ offset();
1487      __ bind_literal(oop_literal);
1488      if (__ offset() - off2 == wordSize) {
1489        // no padding, so insert nop for worst-case sizing
1490        __ nop();
1491      }
1492      __ bind(skip_literal);
1493    }
1494#endif
1495  %}
1496
1497  enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{
1498    // FIXME: load from constant table?
1499    // Load a constant replicated "count" times with width "width"
1500    int count = $cnt$$constant;
1501    int width = $wth$$constant;
1502    assert(count*width == 4, "sanity");
1503    int val = $src$$constant;
1504    if (width < 4) {
1505      int bit_width = width * 8;
1506      val &= (((int)1) << bit_width) - 1; // mask off sign bits
1507      for (int i = 0; i < count - 1; i++) {
1508        val |= (val << bit_width);
1509      }
1510    }
1511    MacroAssembler _masm(&cbuf);
1512
1513    if (val == -1) {
1514      __ mvn($tmp$$Register, 0);
1515    } else if (val == 0) {
1516      __ mov($tmp$$Register, 0);
1517    } else {
1518      __ movw($tmp$$Register, val & 0xffff);
1519      __ movt($tmp$$Register, (unsigned int)val >> 16);
1520    }
1521    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1522  %}
1523
1524  enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{
1525    // Replicate float con 2 times and pack into vector (8 bytes) in regD.
1526    float fval = $src$$constant;
1527    int val = *((int*)&fval);
1528    MacroAssembler _masm(&cbuf);
1529
1530    if (val == -1) {
1531      __ mvn($tmp$$Register, 0);
1532    } else if (val == 0) {
1533      __ mov($tmp$$Register, 0);
1534    } else {
1535      __ movw($tmp$$Register, val & 0xffff);
1536      __ movt($tmp$$Register, (unsigned int)val >> 16);
1537    }
1538    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1539  %}
1540
1541  enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
1542    Label Ldone, Lloop;
1543    MacroAssembler _masm(&cbuf);
1544
1545    Register   str1_reg = $str1$$Register;
1546    Register   str2_reg = $str2$$Register;
1547    Register   cnt1_reg = $cnt1$$Register; // int
1548    Register   cnt2_reg = $cnt2$$Register; // int
1549    Register   tmp1_reg = $tmp1$$Register;
1550    Register   tmp2_reg = $tmp2$$Register;
1551    Register result_reg = $result$$Register;
1552
1553    assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg);
1554
1555    // Compute the minimum of the string lengths(str1_reg) and the
1556    // difference of the string lengths (stack)
1557
1558    // See if the lengths are different, and calculate min in str1_reg.
1559    // Stash diff in tmp2 in case we need it for a tie-breaker.
1560    __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg);
1561#ifdef AARCH64
1562    Label Lskip;
1563    __ _lsl_w(cnt1_reg, cnt1_reg, exact_log2(sizeof(jchar))); // scale the limit
1564    __ b(Lskip, mi);
1565    __ _lsl_w(cnt1_reg, cnt2_reg, exact_log2(sizeof(jchar))); // scale the limit
1566    __ bind(Lskip);
1567#else
1568    __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit
1569    __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit
1570#endif
1571
1572    // reallocate cnt1_reg, cnt2_reg, result_reg
1573    // Note:  limit_reg holds the string length pre-scaled by 2
1574    Register limit_reg = cnt1_reg;
1575    Register  chr2_reg = cnt2_reg;
1576    Register  chr1_reg = tmp1_reg;
1577    // str{12} are the base pointers
1578
1579    // Is the minimum length zero?
1580    __ cmp_32(limit_reg, 0);
1581    if (result_reg != tmp2_reg) {
1582      __ mov(result_reg, tmp2_reg, eq);
1583    }
1584    __ b(Ldone, eq);
1585
1586    // Load first characters
1587    __ ldrh(chr1_reg, Address(str1_reg, 0));
1588    __ ldrh(chr2_reg, Address(str2_reg, 0));
1589
1590    // Compare first characters
1591    __ subs(chr1_reg, chr1_reg, chr2_reg);
1592    if (result_reg != chr1_reg) {
1593      __ mov(result_reg, chr1_reg, ne);
1594    }
1595    __ b(Ldone, ne);
1596
1597    {
1598      // Check after comparing first character to see if strings are equivalent
1599      // Check if the strings start at same location
1600      __ cmp(str1_reg, str2_reg);
1601      // Check if the length difference is zero
1602      __ cond_cmp(tmp2_reg, 0, eq);
1603      __ mov(result_reg, 0, eq); // result is zero
1604      __ b(Ldone, eq);
1605      // Strings might not be equal
1606    }
1607
1608    __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar));
1609    if (result_reg != tmp2_reg) {
1610      __ mov(result_reg, tmp2_reg, eq);
1611    }
1612    __ b(Ldone, eq);
1613
1614    // Shift str1_reg and str2_reg to the end of the arrays, negate limit
1615    __ add(str1_reg, str1_reg, limit_reg);
1616    __ add(str2_reg, str2_reg, limit_reg);
1617    __ neg(limit_reg, chr1_reg);  // limit = -(limit-2)
1618
1619    // Compare the rest of the characters
1620    __ bind(Lloop);
1621    __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1622    __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1623    __ subs(chr1_reg, chr1_reg, chr2_reg);
1624    if (result_reg != chr1_reg) {
1625      __ mov(result_reg, chr1_reg, ne);
1626    }
1627    __ b(Ldone, ne);
1628
1629    __ adds(limit_reg, limit_reg, sizeof(jchar));
1630    __ b(Lloop, ne);
1631
1632    // If strings are equal up to min length, return the length difference.
1633    if (result_reg != tmp2_reg) {
1634      __ mov(result_reg, tmp2_reg);
1635    }
1636
1637    // Otherwise, return the difference between the first mismatched chars.
1638    __ bind(Ldone);
1639  %}
1640
1641  enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
1642    Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone, Lequal;
1643    MacroAssembler _masm(&cbuf);
1644
1645    Register   str1_reg = $str1$$Register;
1646    Register   str2_reg = $str2$$Register;
1647    Register    cnt_reg = $cnt$$Register; // int
1648    Register   tmp1_reg = $tmp1$$Register;
1649    Register   tmp2_reg = $tmp2$$Register;
1650    Register result_reg = $result$$Register;
1651
1652    assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg);
1653
1654    __ cmp(str1_reg, str2_reg); //same char[] ?
1655    __ b(Lequal, eq);
1656
1657    __ cbz_32(cnt_reg, Lequal); // count == 0
1658
1659    //rename registers
1660    Register limit_reg = cnt_reg;
1661    Register  chr1_reg = tmp1_reg;
1662    Register  chr2_reg = tmp2_reg;
1663
1664    __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1665
1666    //check for alignment and position the pointers to the ends
1667    __ orr(chr1_reg, str1_reg, str2_reg);
1668    __ tst(chr1_reg, 0x3);
1669
1670    // notZero means at least one not 4-byte aligned.
1671    // We could optimize the case when both arrays are not aligned
1672    // but it is not frequent case and it requires additional checks.
1673    __ b(Lchar, ne);
1674
1675    // Compare char[] arrays aligned to 4 bytes.
1676    __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
1677                          chr1_reg, chr2_reg, Ldone);
1678
1679    __ b(Lequal); // equal
1680
1681    // char by char compare
1682    __ bind(Lchar);
1683    __ mov(result_reg, 0);
1684    __ add(str1_reg, limit_reg, str1_reg);
1685    __ add(str2_reg, limit_reg, str2_reg);
1686    __ neg(limit_reg, limit_reg); //negate count
1687
1688    // Lchar_loop
1689    __ bind(Lchar_loop);
1690    __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1691    __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1692    __ cmp(chr1_reg, chr2_reg);
1693    __ b(Ldone, ne);
1694    __ adds(limit_reg, limit_reg, sizeof(jchar));
1695    __ b(Lchar_loop, ne);
1696
1697    __ bind(Lequal);
1698    __ mov(result_reg, 1);  //equal
1699
1700    __ bind(Ldone);
1701  %}
1702
1703  enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
1704    Label Lvector, Ldone, Lloop, Lequal;
1705    MacroAssembler _masm(&cbuf);
1706
1707    Register   ary1_reg = $ary1$$Register;
1708    Register   ary2_reg = $ary2$$Register;
1709    Register   tmp1_reg = $tmp1$$Register;
1710    Register   tmp2_reg = $tmp2$$Register;
1711    Register   tmp3_reg = $tmp3$$Register;
1712    Register result_reg = $result$$Register;
1713
1714    assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg);
1715
1716    int length_offset  = arrayOopDesc::length_offset_in_bytes();
1717    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
1718
1719    // return true if the same array
1720#ifdef AARCH64
1721    __ cmp(ary1_reg, ary2_reg);
1722    __ b(Lequal, eq);
1723
1724    __ mov(result_reg, 0);
1725
1726    __ cbz(ary1_reg, Ldone); // not equal
1727
1728    __ cbz(ary2_reg, Ldone); // not equal
1729#else
1730    __ teq(ary1_reg, ary2_reg);
1731    __ mov(result_reg, 1, eq);
1732    __ b(Ldone, eq); // equal
1733
1734    __ tst(ary1_reg, ary1_reg);
1735    __ mov(result_reg, 0, eq);
1736    __ b(Ldone, eq);    // not equal
1737
1738    __ tst(ary2_reg, ary2_reg);
1739    __ mov(result_reg, 0, eq);
1740    __ b(Ldone, eq);    // not equal
1741#endif
1742
1743    //load the lengths of arrays
1744    __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int
1745    __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int
1746
1747    // return false if the two arrays are not equal length
1748#ifdef AARCH64
1749    __ cmp_w(tmp1_reg, tmp2_reg);
1750    __ b(Ldone, ne);    // not equal
1751
1752    __ cbz_w(tmp1_reg, Lequal); // zero-length arrays are equal
1753#else
1754    __ teq_32(tmp1_reg, tmp2_reg);
1755    __ mov(result_reg, 0, ne);
1756    __ b(Ldone, ne);    // not equal
1757
1758    __ tst(tmp1_reg, tmp1_reg);
1759    __ mov(result_reg, 1, eq);
1760    __ b(Ldone, eq);    // zero-length arrays are equal
1761#endif
1762
1763    // load array addresses
1764    __ add(ary1_reg, ary1_reg, base_offset);
1765    __ add(ary2_reg, ary2_reg, base_offset);
1766
1767    // renaming registers
1768    Register chr1_reg  =  tmp3_reg;   // for characters in ary1
1769    Register chr2_reg  =  tmp2_reg;   // for characters in ary2
1770    Register limit_reg =  tmp1_reg;   // length
1771
1772    // set byte count
1773    __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1774
1775    // Compare char[] arrays aligned to 4 bytes.
1776    __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
1777                          chr1_reg, chr2_reg, Ldone);
1778    __ bind(Lequal);
1779    __ mov(result_reg, 1);  //equal
1780
1781    __ bind(Ldone);
1782    %}
1783%}
1784
1785//----------FRAME--------------------------------------------------------------
1786// Definition of frame structure and management information.
1787//
1788//  S T A C K   L A Y O U T    Allocators stack-slot number
1789//                             |   (to get allocators register number
1790//  G  Owned by    |        |  v    add VMRegImpl::stack0)
1791//  r   CALLER     |        |
1792//  o     |        +--------+      pad to even-align allocators stack-slot
1793//  w     V        |  pad0  |        numbers; owned by CALLER
1794//  t   -----------+--------+----> Matcher::_in_arg_limit, unaligned
1795//  h     ^        |   in   |  5
1796//        |        |  args  |  4   Holes in incoming args owned by SELF
1797//  |     |        |        |  3
1798//  |     |        +--------+
1799//  V     |        | old out|      Empty on Intel, window on Sparc
1800//        |    old |preserve|      Must be even aligned.
1801//        |     SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned
1802//        |        |   in   |  3   area for Intel ret address
1803//     Owned by    |preserve|      Empty on Sparc.
1804//       SELF      +--------+
1805//        |        |  pad2  |  2   pad to align old SP
1806//        |        +--------+  1
1807//        |        | locks  |  0
1808//        |        +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned
1809//        |        |  pad1  | 11   pad to align new SP
1810//        |        +--------+
1811//        |        |        | 10
1812//        |        | spills |  9   spills
1813//        V        |        |  8   (pad0 slot for callee)
1814//      -----------+--------+----> Matcher::_out_arg_limit, unaligned
1815//        ^        |  out   |  7
1816//        |        |  args  |  6   Holes in outgoing args owned by CALLEE
1817//     Owned by    +--------+
1818//      CALLEE     | new out|  6   Empty on Intel, window on Sparc
1819//        |    new |preserve|      Must be even-aligned.
1820//        |     SP-+--------+----> Matcher::_new_SP, even aligned
1821//        |        |        |
1822//
1823// Note 1: Only region 8-11 is determined by the allocator.  Region 0-5 is
1824//         known from SELF's arguments and the Java calling convention.
1825//         Region 6-7 is determined per call site.
1826// Note 2: If the calling convention leaves holes in the incoming argument
1827//         area, those holes are owned by SELF.  Holes in the outgoing area
1828//         are owned by the CALLEE.  Holes should not be nessecary in the
1829//         incoming area, as the Java calling convention is completely under
1830//         the control of the AD file.  Doubles can be sorted and packed to
1831//         avoid holes.  Holes in the outgoing arguments may be nessecary for
1832//         varargs C calling conventions.
1833// Note 3: Region 0-3 is even aligned, with pad2 as needed.  Region 3-5 is
1834//         even aligned with pad0 as needed.
1835//         Region 6 is even aligned.  Region 6-7 is NOT even aligned;
1836//         region 6-11 is even aligned; it may be padded out more so that
1837//         the region from SP to FP meets the minimum stack alignment.
1838
1839frame %{
1840  // What direction does stack grow in (assumed to be same for native & Java)
1841  stack_direction(TOWARDS_LOW);
1842
1843  // These two registers define part of the calling convention
1844  // between compiled code and the interpreter.
1845  inline_cache_reg(R_Ricklass);          // Inline Cache Register or Method* for I2C
1846  interpreter_method_oop_reg(R_Rmethod); // Method Oop Register when calling interpreter
1847
1848  // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
1849  cisc_spilling_operand_name(indOffset);
1850
1851  // Number of stack slots consumed by a Monitor enter
1852  sync_stack_slots(1 * VMRegImpl::slots_per_word);
1853
1854  // Compiled code's Frame Pointer
1855#ifdef AARCH64
1856  frame_pointer(R_SP);
1857#else
1858  frame_pointer(R_R13);
1859#endif
1860
1861  // Stack alignment requirement
1862  stack_alignment(StackAlignmentInBytes);
1863  //  LP64: Alignment size in bytes (128-bit -> 16 bytes)
1864  // !LP64: Alignment size in bytes (64-bit  ->  8 bytes)
1865
1866  // Number of stack slots between incoming argument block and the start of
1867  // a new frame.  The PROLOG must add this many slots to the stack.  The
1868  // EPILOG must remove this many slots.
1869  // FP + LR
1870  in_preserve_stack_slots(2 * VMRegImpl::slots_per_word);
1871
1872  // Number of outgoing stack slots killed above the out_preserve_stack_slots
1873  // for calls to C.  Supports the var-args backing area for register parms.
1874  // ADLC doesn't support parsing expressions, so I folded the math by hand.
1875  varargs_C_out_slots_killed( 0);
1876
1877  // The after-PROLOG location of the return address.  Location of
1878  // return address specifies a type (REG or STACK) and a number
1879  // representing the register number (i.e. - use a register name) or
1880  // stack slot.
1881  // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1882  // Otherwise, it is above the locks and verification slot and alignment word
1883  return_addr(STACK - 1*VMRegImpl::slots_per_word +
1884              align_up((Compile::current()->in_preserve_stack_slots() +
1885                        Compile::current()->fixed_slots()),
1886                       stack_alignment_in_slots()));
1887
1888  // Body of function which returns an OptoRegs array locating
1889  // arguments either in registers or in stack slots for calling
1890  // java
1891  calling_convention %{
1892    (void) SharedRuntime::java_calling_convention(sig_bt, regs, length, is_outgoing);
1893
1894  %}
1895
1896  // Body of function which returns an OptoRegs array locating
1897  // arguments either in registers or in stack slots for callin
1898  // C.
1899  c_calling_convention %{
1900    // This is obviously always outgoing
1901    (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length);
1902  %}
1903
1904  // Location of compiled Java return values.  Same as C
1905  return_value %{
1906    return c2::return_value(ideal_reg);
1907  %}
1908
1909%}
1910
1911//----------ATTRIBUTES---------------------------------------------------------
1912//----------Instruction Attributes---------------------------------------------
1913ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
1914ins_attrib ins_size(32);           // Required size attribute (in bits)
1915ins_attrib ins_short_branch(0);    // Required flag: is this instruction a
1916                                   // non-matching short branch variant of some
1917                                                            // long branch?
1918
1919//----------OPERANDS-----------------------------------------------------------
1920// Operand definitions must precede instruction definitions for correct parsing
1921// in the ADLC because operands constitute user defined types which are used in
1922// instruction definitions.
1923
1924//----------Simple Operands----------------------------------------------------
1925// Immediate Operands
1926// Integer Immediate: 32-bit
1927operand immI() %{
1928  match(ConI);
1929
1930  op_cost(0);
1931  // formats are generated automatically for constants and base registers
1932  format %{ %}
1933  interface(CONST_INTER);
1934%}
1935
1936// Integer Immediate: 8-bit unsigned - for VMOV
1937operand immU8() %{
1938  predicate(0 <= n->get_int() && (n->get_int() <= 255));
1939  match(ConI);
1940  op_cost(0);
1941
1942  format %{ %}
1943  interface(CONST_INTER);
1944%}
1945
1946// Integer Immediate: 16-bit
1947operand immI16() %{
1948  predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw());
1949  match(ConI);
1950  op_cost(0);
1951
1952  format %{ %}
1953  interface(CONST_INTER);
1954%}
1955
1956#ifndef AARCH64
1957// Integer Immediate: offset for half and double word loads and stores
1958operand immIHD() %{
1959  predicate(is_memoryHD(n->get_int()));
1960  match(ConI);
1961  op_cost(0);
1962  format %{ %}
1963  interface(CONST_INTER);
1964%}
1965
1966// Integer Immediate: offset for fp loads and stores
1967operand immIFP() %{
1968  predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0));
1969  match(ConI);
1970  op_cost(0);
1971
1972  format %{ %}
1973  interface(CONST_INTER);
1974%}
1975#endif
1976
1977// Valid scale values for addressing modes and shifts
1978operand immU5() %{
1979  predicate(0 <= n->get_int() && (n->get_int() <= 31));
1980  match(ConI);
1981  op_cost(0);
1982
1983  format %{ %}
1984  interface(CONST_INTER);
1985%}
1986
1987// Integer Immediate: 6-bit
1988operand immU6Big() %{
1989  predicate(n->get_int() >= 32 && n->get_int() <= 63);
1990  match(ConI);
1991  op_cost(0);
1992  format %{ %}
1993  interface(CONST_INTER);
1994%}
1995
1996// Integer Immediate: 0-bit
1997operand immI0() %{
1998  predicate(n->get_int() == 0);
1999  match(ConI);
2000  op_cost(0);
2001
2002  format %{ %}
2003  interface(CONST_INTER);
2004%}
2005
2006// Integer Immediate: the value 1
2007operand immI_1() %{
2008  predicate(n->get_int() == 1);
2009  match(ConI);
2010  op_cost(0);
2011
2012  format %{ %}
2013  interface(CONST_INTER);
2014%}
2015
2016// Integer Immediate: the value 2
2017operand immI_2() %{
2018  predicate(n->get_int() == 2);
2019  match(ConI);
2020  op_cost(0);
2021
2022  format %{ %}
2023  interface(CONST_INTER);
2024%}
2025
2026// Integer Immediate: the value 3
2027operand immI_3() %{
2028  predicate(n->get_int() == 3);
2029  match(ConI);
2030  op_cost(0);
2031
2032  format %{ %}
2033  interface(CONST_INTER);
2034%}
2035
2036// Integer Immediate: the value 4
2037operand immI_4() %{
2038  predicate(n->get_int() == 4);
2039  match(ConI);
2040  op_cost(0);
2041
2042  format %{ %}
2043  interface(CONST_INTER);
2044%}
2045
2046// Integer Immediate: the value 8
2047operand immI_8() %{
2048  predicate(n->get_int() == 8);
2049  match(ConI);
2050  op_cost(0);
2051
2052  format %{ %}
2053  interface(CONST_INTER);
2054%}
2055
2056// Int Immediate non-negative
2057operand immU31()
2058%{
2059  predicate(n->get_int() >= 0);
2060  match(ConI);
2061
2062  op_cost(0);
2063  format %{ %}
2064  interface(CONST_INTER);
2065%}
2066
2067// Integer Immediate: the values 32-63
2068operand immI_32_63() %{
2069  predicate(n->get_int() >= 32 && n->get_int() <= 63);
2070  match(ConI);
2071  op_cost(0);
2072
2073  format %{ %}
2074  interface(CONST_INTER);
2075%}
2076
2077// Immediates for special shifts (sign extend)
2078
2079// Integer Immediate: the value 16
2080operand immI_16() %{
2081  predicate(n->get_int() == 16);
2082  match(ConI);
2083  op_cost(0);
2084
2085  format %{ %}
2086  interface(CONST_INTER);
2087%}
2088
2089// Integer Immediate: the value 24
2090operand immI_24() %{
2091  predicate(n->get_int() == 24);
2092  match(ConI);
2093  op_cost(0);
2094
2095  format %{ %}
2096  interface(CONST_INTER);
2097%}
2098
2099// Integer Immediate: the value 255
2100operand immI_255() %{
2101  predicate( n->get_int() == 255 );
2102  match(ConI);
2103  op_cost(0);
2104
2105  format %{ %}
2106  interface(CONST_INTER);
2107%}
2108
2109// Integer Immediate: the value 65535
2110operand immI_65535() %{
2111  predicate(n->get_int() == 65535);
2112  match(ConI);
2113  op_cost(0);
2114
2115  format %{ %}
2116  interface(CONST_INTER);
2117%}
2118
2119// Integer Immediates for arithmetic instructions
2120
2121operand aimmI() %{
2122  predicate(is_aimm(n->get_int()));
2123  match(ConI);
2124  op_cost(0);
2125
2126  format %{ %}
2127  interface(CONST_INTER);
2128%}
2129
2130operand aimmIneg() %{
2131  predicate(is_aimm(-n->get_int()));
2132  match(ConI);
2133  op_cost(0);
2134
2135  format %{ %}
2136  interface(CONST_INTER);
2137%}
2138
2139operand aimmU31() %{
2140  predicate((0 <= n->get_int()) && is_aimm(n->get_int()));
2141  match(ConI);
2142  op_cost(0);
2143
2144  format %{ %}
2145  interface(CONST_INTER);
2146%}
2147
2148// Integer Immediates for logical instructions
2149
2150operand limmI() %{
2151  predicate(is_limmI(n->get_int()));
2152  match(ConI);
2153  op_cost(0);
2154
2155  format %{ %}
2156  interface(CONST_INTER);
2157%}
2158
2159operand limmIlow8() %{
2160  predicate(is_limmI_low(n->get_int(), 8));
2161  match(ConI);
2162  op_cost(0);
2163
2164  format %{ %}
2165  interface(CONST_INTER);
2166%}
2167
2168operand limmU31() %{
2169  predicate(0 <= n->get_int() && is_limmI(n->get_int()));
2170  match(ConI);
2171  op_cost(0);
2172
2173  format %{ %}
2174  interface(CONST_INTER);
2175%}
2176
2177operand limmIn() %{
2178  predicate(is_limmI(~n->get_int()));
2179  match(ConI);
2180  op_cost(0);
2181
2182  format %{ %}
2183  interface(CONST_INTER);
2184%}
2185
2186#ifdef AARCH64
2187// Long Immediate: for logical instruction
2188operand limmL() %{
2189  predicate(is_limmL(n->get_long()));
2190  match(ConL);
2191  op_cost(0);
2192
2193  format %{ %}
2194  interface(CONST_INTER);
2195%}
2196
2197operand limmLn() %{
2198  predicate(is_limmL(~n->get_long()));
2199  match(ConL);
2200  op_cost(0);
2201
2202  format %{ %}
2203  interface(CONST_INTER);
2204%}
2205
2206// Long Immediate: for arithmetic instruction
2207operand aimmL() %{
2208  predicate(is_aimm(n->get_long()));
2209  match(ConL);
2210  op_cost(0);
2211
2212  format %{ %}
2213  interface(CONST_INTER);
2214%}
2215
2216operand aimmLneg() %{
2217  predicate(is_aimm(-n->get_long()));
2218  match(ConL);
2219  op_cost(0);
2220
2221  format %{ %}
2222  interface(CONST_INTER);
2223%}
2224#endif // AARCH64
2225
2226// Long Immediate: the value FF
2227operand immL_FF() %{
2228  predicate( n->get_long() == 0xFFL );
2229  match(ConL);
2230  op_cost(0);
2231
2232  format %{ %}
2233  interface(CONST_INTER);
2234%}
2235
2236// Long Immediate: the value FFFF
2237operand immL_FFFF() %{
2238  predicate( n->get_long() == 0xFFFFL );
2239  match(ConL);
2240  op_cost(0);
2241
2242  format %{ %}
2243  interface(CONST_INTER);
2244%}
2245
2246// Pointer Immediate: 32 or 64-bit
2247operand immP() %{
2248  match(ConP);
2249
2250  op_cost(5);
2251  // formats are generated automatically for constants and base registers
2252  format %{ %}
2253  interface(CONST_INTER);
2254%}
2255
2256operand immP0() %{
2257  predicate(n->get_ptr() == 0);
2258  match(ConP);
2259  op_cost(0);
2260
2261  format %{ %}
2262  interface(CONST_INTER);
2263%}
2264
2265operand immP_poll() %{
2266  predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
2267  match(ConP);
2268
2269  // formats are generated automatically for constants and base registers
2270  format %{ %}
2271  interface(CONST_INTER);
2272%}
2273
2274// Pointer Immediate
2275operand immN()
2276%{
2277  match(ConN);
2278
2279  op_cost(10);
2280  format %{ %}
2281  interface(CONST_INTER);
2282%}
2283
2284operand immNKlass()
2285%{
2286  match(ConNKlass);
2287
2288  op_cost(10);
2289  format %{ %}
2290  interface(CONST_INTER);
2291%}
2292
2293// NULL Pointer Immediate
2294operand immN0()
2295%{
2296  predicate(n->get_narrowcon() == 0);
2297  match(ConN);
2298
2299  op_cost(0);
2300  format %{ %}
2301  interface(CONST_INTER);
2302%}
2303
2304operand immL() %{
2305  match(ConL);
2306  op_cost(40);
2307  // formats are generated automatically for constants and base registers
2308  format %{ %}
2309  interface(CONST_INTER);
2310%}
2311
2312operand immL0() %{
2313  predicate(n->get_long() == 0L);
2314  match(ConL);
2315  op_cost(0);
2316  // formats are generated automatically for constants and base registers
2317  format %{ %}
2318  interface(CONST_INTER);
2319%}
2320
2321// Long Immediate: 16-bit
2322operand immL16() %{
2323  predicate(n->get_long() >= 0 && n->get_long() < (1<<16)  && VM_Version::supports_movw());
2324  match(ConL);
2325  op_cost(0);
2326
2327  format %{ %}
2328  interface(CONST_INTER);
2329%}
2330
2331// Long Immediate: low 32-bit mask
2332operand immL_32bits() %{
2333  predicate(n->get_long() == 0xFFFFFFFFL);
2334  match(ConL);
2335  op_cost(0);
2336
2337  format %{ %}
2338  interface(CONST_INTER);
2339%}
2340
2341// Double Immediate
2342operand immD() %{
2343  match(ConD);
2344
2345  op_cost(40);
2346  format %{ %}
2347  interface(CONST_INTER);
2348%}
2349
2350// Double Immediate: +0.0d.
2351operand immD0() %{
2352  predicate(jlong_cast(n->getd()) == 0);
2353
2354  match(ConD);
2355  op_cost(0);
2356  format %{ %}
2357  interface(CONST_INTER);
2358%}
2359
2360operand imm8D() %{
2361  predicate(Assembler::double_num(n->getd()).can_be_imm8());
2362  match(ConD);
2363
2364  op_cost(0);
2365  format %{ %}
2366  interface(CONST_INTER);
2367%}
2368
2369// Float Immediate
2370operand immF() %{
2371  match(ConF);
2372
2373  op_cost(20);
2374  format %{ %}
2375  interface(CONST_INTER);
2376%}
2377
2378// Float Immediate: +0.0f
2379operand immF0() %{
2380  predicate(jint_cast(n->getf()) == 0);
2381  match(ConF);
2382
2383  op_cost(0);
2384  format %{ %}
2385  interface(CONST_INTER);
2386%}
2387
2388// Float Immediate: encoded as 8 bits
2389operand imm8F() %{
2390  predicate(Assembler::float_num(n->getf()).can_be_imm8());
2391  match(ConF);
2392
2393  op_cost(0);
2394  format %{ %}
2395  interface(CONST_INTER);
2396%}
2397
2398// Integer Register Operands
2399// Integer Register
2400operand iRegI() %{
2401  constraint(ALLOC_IN_RC(int_reg));
2402  match(RegI);
2403  match(R0RegI);
2404  match(R1RegI);
2405  match(R2RegI);
2406  match(R3RegI);
2407#ifdef AARCH64
2408  match(ZRRegI);
2409#else
2410  match(R12RegI);
2411#endif
2412
2413  format %{ %}
2414  interface(REG_INTER);
2415%}
2416
2417// Pointer Register
2418operand iRegP() %{
2419  constraint(ALLOC_IN_RC(ptr_reg));
2420  match(RegP);
2421  match(R0RegP);
2422  match(R1RegP);
2423  match(R2RegP);
2424  match(RExceptionRegP);
2425  match(R8RegP);
2426  match(R9RegP);
2427  match(RthreadRegP); // FIXME: move to sp_ptr_RegP?
2428  match(R12RegP);
2429  match(LRRegP);
2430
2431  match(sp_ptr_RegP);
2432  match(store_ptr_RegP);
2433
2434  format %{ %}
2435  interface(REG_INTER);
2436%}
2437
2438// GPRs + Rthread + SP
2439operand sp_ptr_RegP() %{
2440  constraint(ALLOC_IN_RC(sp_ptr_reg));
2441  match(RegP);
2442  match(iRegP);
2443  match(SPRegP); // FIXME: check cost
2444
2445  format %{ %}
2446  interface(REG_INTER);
2447%}
2448
2449#ifdef AARCH64
2450// Like sp_ptr_reg, but exclude regs (Aarch64 SP) that can't be
2451// stored directly.  Includes ZR, so can't be used as a destination.
2452operand store_ptr_RegP() %{
2453  constraint(ALLOC_IN_RC(store_ptr_reg));
2454  match(RegP);
2455  match(iRegP);
2456  match(ZRRegP);
2457
2458  format %{ %}
2459  interface(REG_INTER);
2460%}
2461
2462operand store_RegI() %{
2463  constraint(ALLOC_IN_RC(store_reg));
2464  match(RegI);
2465  match(iRegI);
2466  match(ZRRegI);
2467
2468  format %{ %}
2469  interface(REG_INTER);
2470%}
2471
2472operand store_RegL() %{
2473  constraint(ALLOC_IN_RC(store_ptr_reg));
2474  match(RegL);
2475  match(iRegL);
2476  match(ZRRegL);
2477
2478  format %{ %}
2479  interface(REG_INTER);
2480%}
2481
2482operand store_RegN() %{
2483  constraint(ALLOC_IN_RC(store_reg));
2484  match(RegN);
2485  match(iRegN);
2486  match(ZRRegN);
2487
2488  format %{ %}
2489  interface(REG_INTER);
2490%}
2491#endif
2492
2493operand R0RegP() %{
2494  constraint(ALLOC_IN_RC(R0_regP));
2495  match(iRegP);
2496
2497  format %{ %}
2498  interface(REG_INTER);
2499%}
2500
2501operand R1RegP() %{
2502  constraint(ALLOC_IN_RC(R1_regP));
2503  match(iRegP);
2504
2505  format %{ %}
2506  interface(REG_INTER);
2507%}
2508
2509operand R2RegP() %{
2510  constraint(ALLOC_IN_RC(R2_regP));
2511  match(iRegP);
2512
2513  format %{ %}
2514  interface(REG_INTER);
2515%}
2516
2517operand RExceptionRegP() %{
2518  constraint(ALLOC_IN_RC(Rexception_regP));
2519  match(iRegP);
2520
2521  format %{ %}
2522  interface(REG_INTER);
2523%}
2524
2525operand RthreadRegP() %{
2526  constraint(ALLOC_IN_RC(Rthread_regP));
2527  match(iRegP);
2528
2529  format %{ %}
2530  interface(REG_INTER);
2531%}
2532
2533operand IPRegP() %{
2534  constraint(ALLOC_IN_RC(IP_regP));
2535  match(iRegP);
2536
2537  format %{ %}
2538  interface(REG_INTER);
2539%}
2540
2541operand LRRegP() %{
2542  constraint(ALLOC_IN_RC(LR_regP));
2543  match(iRegP);
2544
2545  format %{ %}
2546  interface(REG_INTER);
2547%}
2548
2549operand R0RegI() %{
2550  constraint(ALLOC_IN_RC(R0_regI));
2551  match(iRegI);
2552
2553  format %{ %}
2554  interface(REG_INTER);
2555%}
2556
2557operand R1RegI() %{
2558  constraint(ALLOC_IN_RC(R1_regI));
2559  match(iRegI);
2560
2561  format %{ %}
2562  interface(REG_INTER);
2563%}
2564
2565operand R2RegI() %{
2566  constraint(ALLOC_IN_RC(R2_regI));
2567  match(iRegI);
2568
2569  format %{ %}
2570  interface(REG_INTER);
2571%}
2572
2573operand R3RegI() %{
2574  constraint(ALLOC_IN_RC(R3_regI));
2575  match(iRegI);
2576
2577  format %{ %}
2578  interface(REG_INTER);
2579%}
2580
2581#ifndef AARCH64
2582operand R12RegI() %{
2583  constraint(ALLOC_IN_RC(R12_regI));
2584  match(iRegI);
2585
2586  format %{ %}
2587  interface(REG_INTER);
2588%}
2589#endif
2590
2591// Long Register
2592operand iRegL() %{
2593  constraint(ALLOC_IN_RC(long_reg));
2594  match(RegL);
2595#ifdef AARCH64
2596  match(iRegLd);
2597#else
2598  match(R0R1RegL);
2599  match(R2R3RegL);
2600#endif
2601//match(iRegLex);
2602
2603  format %{ %}
2604  interface(REG_INTER);
2605%}
2606
2607operand iRegLd() %{
2608  constraint(ALLOC_IN_RC(long_reg_align));
2609  match(iRegL); // FIXME: allows unaligned R11/R12?
2610
2611  format %{ %}
2612  interface(REG_INTER);
2613%}
2614
2615#ifndef AARCH64
2616// first long arg, or return value
2617operand R0R1RegL() %{
2618  constraint(ALLOC_IN_RC(R0R1_regL));
2619  match(iRegL);
2620
2621  format %{ %}
2622  interface(REG_INTER);
2623%}
2624
2625operand R2R3RegL() %{
2626  constraint(ALLOC_IN_RC(R2R3_regL));
2627  match(iRegL);
2628
2629  format %{ %}
2630  interface(REG_INTER);
2631%}
2632#endif
2633
2634// Condition Code Flag Register
2635operand flagsReg() %{
2636  constraint(ALLOC_IN_RC(int_flags));
2637  match(RegFlags);
2638
2639  format %{ "apsr" %}
2640  interface(REG_INTER);
2641%}
2642
2643// Result of compare to 0 (TST)
2644operand flagsReg_EQNELTGE() %{
2645  constraint(ALLOC_IN_RC(int_flags));
2646  match(RegFlags);
2647
2648  format %{ "apsr_EQNELTGE" %}
2649  interface(REG_INTER);
2650%}
2651
2652// Condition Code Register, unsigned comparisons.
2653operand flagsRegU() %{
2654  constraint(ALLOC_IN_RC(int_flags));
2655  match(RegFlags);
2656#ifdef TODO
2657  match(RegFlagsP);
2658#endif
2659
2660  format %{ "apsr_U" %}
2661  interface(REG_INTER);
2662%}
2663
2664// Condition Code Register, pointer comparisons.
2665operand flagsRegP() %{
2666  constraint(ALLOC_IN_RC(int_flags));
2667  match(RegFlags);
2668
2669  format %{ "apsr_P" %}
2670  interface(REG_INTER);
2671%}
2672
2673// Condition Code Register, long comparisons.
2674#ifndef AARCH64
2675operand flagsRegL_LTGE() %{
2676  constraint(ALLOC_IN_RC(int_flags));
2677  match(RegFlags);
2678
2679  format %{ "apsr_L_LTGE" %}
2680  interface(REG_INTER);
2681%}
2682
2683operand flagsRegL_EQNE() %{
2684  constraint(ALLOC_IN_RC(int_flags));
2685  match(RegFlags);
2686
2687  format %{ "apsr_L_EQNE" %}
2688  interface(REG_INTER);
2689%}
2690
2691operand flagsRegL_LEGT() %{
2692  constraint(ALLOC_IN_RC(int_flags));
2693  match(RegFlags);
2694
2695  format %{ "apsr_L_LEGT" %}
2696  interface(REG_INTER);
2697%}
2698
2699operand flagsRegUL_LTGE() %{
2700  constraint(ALLOC_IN_RC(int_flags));
2701  match(RegFlags);
2702
2703  format %{ "apsr_UL_LTGE" %}
2704  interface(REG_INTER);
2705%}
2706
2707operand flagsRegUL_EQNE() %{
2708  constraint(ALLOC_IN_RC(int_flags));
2709  match(RegFlags);
2710
2711  format %{ "apsr_UL_EQNE" %}
2712  interface(REG_INTER);
2713%}
2714
2715operand flagsRegUL_LEGT() %{
2716  constraint(ALLOC_IN_RC(int_flags));
2717  match(RegFlags);
2718
2719  format %{ "apsr_UL_LEGT" %}
2720  interface(REG_INTER);
2721%}
2722#endif
2723
2724// Condition Code Register, floating comparisons, unordered same as "less".
2725operand flagsRegF() %{
2726  constraint(ALLOC_IN_RC(float_flags));
2727  match(RegFlags);
2728
2729  format %{ "fpscr_F" %}
2730  interface(REG_INTER);
2731%}
2732
2733// Vectors
2734operand vecD() %{
2735  constraint(ALLOC_IN_RC(actual_dflt_reg));
2736  match(VecD);
2737
2738  format %{ %}
2739  interface(REG_INTER);
2740%}
2741
2742operand vecX() %{
2743  constraint(ALLOC_IN_RC(vectorx_reg));
2744  match(VecX);
2745
2746  format %{ %}
2747  interface(REG_INTER);
2748%}
2749
2750operand regD() %{
2751  constraint(ALLOC_IN_RC(actual_dflt_reg));
2752  match(RegD);
2753  match(regD_low);
2754
2755  format %{ %}
2756  interface(REG_INTER);
2757%}
2758
2759operand regF() %{
2760  constraint(ALLOC_IN_RC(sflt_reg));
2761  match(RegF);
2762
2763  format %{ %}
2764  interface(REG_INTER);
2765%}
2766
2767operand regD_low() %{
2768  constraint(ALLOC_IN_RC(dflt_low_reg));
2769  match(RegD);
2770
2771  format %{ %}
2772  interface(REG_INTER);
2773%}
2774
2775// Special Registers
2776
2777// Method Register
2778operand inline_cache_regP(iRegP reg) %{
2779  constraint(ALLOC_IN_RC(Ricklass_regP));
2780  match(reg);
2781  format %{ %}
2782  interface(REG_INTER);
2783%}
2784
2785operand interpreter_method_oop_regP(iRegP reg) %{
2786  constraint(ALLOC_IN_RC(Rmethod_regP));
2787  match(reg);
2788  format %{ %}
2789  interface(REG_INTER);
2790%}
2791
2792
2793//----------Complex Operands---------------------------------------------------
2794// Indirect Memory Reference
2795operand indirect(sp_ptr_RegP reg) %{
2796  constraint(ALLOC_IN_RC(sp_ptr_reg));
2797  match(reg);
2798
2799  op_cost(100);
2800  format %{ "[$reg]" %}
2801  interface(MEMORY_INTER) %{
2802    base($reg);
2803#ifdef AARCH64
2804    index(0xff); // 0xff => no index
2805#else
2806    index(0xf); // PC => no index
2807#endif
2808    scale(0x0);
2809    disp(0x0);
2810  %}
2811%}
2812
2813#ifdef AARCH64
2814// Indirect with scaled*1 uimm12 offset
2815operand indOffsetU12ScaleB(sp_ptr_RegP reg, immUL12 offset) %{
2816  constraint(ALLOC_IN_RC(sp_ptr_reg));
2817  match(AddP reg offset);
2818
2819  op_cost(100);
2820  format %{ "[$reg + $offset]" %}
2821  interface(MEMORY_INTER) %{
2822    base($reg);
2823#ifdef AARCH64
2824    index(0xff); // 0xff => no index
2825#else
2826    index(0xf); // PC => no index
2827#endif
2828    scale(0x0);
2829    disp($offset);
2830  %}
2831%}
2832
2833// Indirect with scaled*2 uimm12 offset
2834operand indOffsetU12ScaleS(sp_ptr_RegP reg, immUL12x2 offset) %{
2835  constraint(ALLOC_IN_RC(sp_ptr_reg));
2836  match(AddP reg offset);
2837
2838  op_cost(100);
2839  format %{ "[$reg + $offset]" %}
2840  interface(MEMORY_INTER) %{
2841    base($reg);
2842#ifdef AARCH64
2843    index(0xff); // 0xff => no index
2844#else
2845    index(0xf); // PC => no index
2846#endif
2847    scale(0x0);
2848    disp($offset);
2849  %}
2850%}
2851
2852// Indirect with scaled*4 uimm12 offset
2853operand indOffsetU12ScaleI(sp_ptr_RegP reg, immUL12x4 offset) %{
2854  constraint(ALLOC_IN_RC(sp_ptr_reg));
2855  match(AddP reg offset);
2856
2857  op_cost(100);
2858  format %{ "[$reg + $offset]" %}
2859  interface(MEMORY_INTER) %{
2860    base($reg);
2861#ifdef AARCH64
2862    index(0xff); // 0xff => no index
2863#else
2864    index(0xf); // PC => no index
2865#endif
2866    scale(0x0);
2867    disp($offset);
2868  %}
2869%}
2870
2871// Indirect with scaled*8 uimm12 offset
2872operand indOffsetU12ScaleL(sp_ptr_RegP reg, immUL12x8 offset) %{
2873  constraint(ALLOC_IN_RC(sp_ptr_reg));
2874  match(AddP reg offset);
2875
2876  op_cost(100);
2877  format %{ "[$reg + $offset]" %}
2878  interface(MEMORY_INTER) %{
2879    base($reg);
2880#ifdef AARCH64
2881    index(0xff); // 0xff => no index
2882#else
2883    index(0xf); // PC => no index
2884#endif
2885    scale(0x0);
2886    disp($offset);
2887  %}
2888%}
2889
2890// Indirect with scaled*16 uimm12 offset
2891operand indOffsetU12ScaleQ(sp_ptr_RegP reg, immUL12x16 offset) %{
2892  constraint(ALLOC_IN_RC(sp_ptr_reg));
2893  match(AddP reg offset);
2894
2895  op_cost(100);
2896  format %{ "[$reg + $offset]" %}
2897  interface(MEMORY_INTER) %{
2898    base($reg);
2899#ifdef AARCH64
2900    index(0xff); // 0xff => no index
2901#else
2902    index(0xf); // PC => no index
2903#endif
2904    scale(0x0);
2905    disp($offset);
2906  %}
2907%}
2908
2909#else // ! AARCH64
2910
2911// Indirect with Offset in ]-4096, 4096[
2912operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{
2913  constraint(ALLOC_IN_RC(sp_ptr_reg));
2914  match(AddP reg offset);
2915
2916  op_cost(100);
2917  format %{ "[$reg + $offset]" %}
2918  interface(MEMORY_INTER) %{
2919    base($reg);
2920#ifdef AARCH64
2921    index(0xff); // 0xff => no index
2922#else
2923    index(0xf); // PC => no index
2924#endif
2925    scale(0x0);
2926    disp($offset);
2927  %}
2928%}
2929
2930// Indirect with offset for float load/store
2931operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{
2932  constraint(ALLOC_IN_RC(sp_ptr_reg));
2933  match(AddP reg offset);
2934
2935  op_cost(100);
2936  format %{ "[$reg + $offset]" %}
2937  interface(MEMORY_INTER) %{
2938    base($reg);
2939#ifdef AARCH64
2940    index(0xff); // 0xff => no index
2941#else
2942    index(0xf); // PC => no index
2943#endif
2944    scale(0x0);
2945    disp($offset);
2946  %}
2947%}
2948
2949// Indirect with Offset for half and double words
2950operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{
2951  constraint(ALLOC_IN_RC(sp_ptr_reg));
2952  match(AddP reg offset);
2953
2954  op_cost(100);
2955  format %{ "[$reg + $offset]" %}
2956  interface(MEMORY_INTER) %{
2957    base($reg);
2958#ifdef AARCH64
2959    index(0xff); // 0xff => no index
2960#else
2961    index(0xf); // PC => no index
2962#endif
2963    scale(0x0);
2964    disp($offset);
2965  %}
2966%}
2967
2968// Indirect with Offset and Offset+4 in ]-1024, 1024[
2969operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{
2970  constraint(ALLOC_IN_RC(sp_ptr_reg));
2971  match(AddP reg offset);
2972
2973  op_cost(100);
2974  format %{ "[$reg + $offset]" %}
2975  interface(MEMORY_INTER) %{
2976    base($reg);
2977#ifdef AARCH64
2978    index(0xff); // 0xff => no index
2979#else
2980    index(0xf); // PC => no index
2981#endif
2982    scale(0x0);
2983    disp($offset);
2984  %}
2985%}
2986
2987// Indirect with Offset and Offset+4 in ]-4096, 4096[
2988operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{
2989  constraint(ALLOC_IN_RC(sp_ptr_reg));
2990  match(AddP reg offset);
2991
2992  op_cost(100);
2993  format %{ "[$reg + $offset]" %}
2994  interface(MEMORY_INTER) %{
2995    base($reg);
2996#ifdef AARCH64
2997    index(0xff); // 0xff => no index
2998#else
2999    index(0xf); // PC => no index
3000#endif
3001    scale(0x0);
3002    disp($offset);
3003  %}
3004%}
3005#endif // !AARCH64
3006
3007// Indirect with Register Index
3008operand indIndex(iRegP addr, iRegX index) %{
3009  constraint(ALLOC_IN_RC(ptr_reg));
3010  match(AddP addr index);
3011
3012  op_cost(100);
3013  format %{ "[$addr + $index]" %}
3014  interface(MEMORY_INTER) %{
3015    base($addr);
3016    index($index);
3017    scale(0x0);
3018    disp(0x0);
3019  %}
3020%}
3021
3022#ifdef AARCH64
3023// Indirect Memory Times Scale Plus Index Register
3024operand indIndexScaleS(iRegP addr, iRegX index, immI_1 scale) %{
3025  constraint(ALLOC_IN_RC(ptr_reg));
3026  match(AddP addr (LShiftX index scale));
3027
3028  op_cost(100);
3029  format %{"[$addr + $index << $scale]" %}
3030  interface(MEMORY_INTER) %{
3031    base($addr);
3032    index($index);
3033    scale($scale);
3034    disp(0x0);
3035  %}
3036%}
3037
3038// Indirect Memory Times Scale Plus 32-bit Index Register
3039operand indIndexIScaleS(iRegP addr, iRegI index, immI_1 scale) %{
3040  constraint(ALLOC_IN_RC(ptr_reg));
3041  match(AddP addr (LShiftX (ConvI2L index) scale));
3042
3043  op_cost(100);
3044  format %{"[$addr + $index.w << $scale]" %}
3045  interface(MEMORY_INTER) %{
3046    base($addr);
3047    index($index);
3048    scale($scale);
3049    disp(0x7fffffff); // sxtw
3050  %}
3051%}
3052
3053// Indirect Memory Times Scale Plus Index Register
3054operand indIndexScaleI(iRegP addr, iRegX index, immI_2 scale) %{
3055  constraint(ALLOC_IN_RC(ptr_reg));
3056  match(AddP addr (LShiftX index scale));
3057
3058  op_cost(100);
3059  format %{"[$addr + $index << $scale]" %}
3060  interface(MEMORY_INTER) %{
3061    base($addr);
3062    index($index);
3063    scale($scale);
3064    disp(0x0);
3065  %}
3066%}
3067
3068// Indirect Memory Times Scale Plus 32-bit Index Register
3069operand indIndexIScaleI(iRegP addr, iRegI index, immI_2 scale) %{
3070  constraint(ALLOC_IN_RC(ptr_reg));
3071  match(AddP addr (LShiftX (ConvI2L index) scale));
3072
3073  op_cost(100);
3074  format %{"[$addr + $index.w << $scale]" %}
3075  interface(MEMORY_INTER) %{
3076    base($addr);
3077    index($index);
3078    scale($scale);
3079    disp(0x7fffffff); // sxtw
3080  %}
3081%}
3082
3083// Indirect Memory Times Scale Plus Index Register
3084operand indIndexScaleL(iRegP addr, iRegX index, immI_3 scale) %{
3085  constraint(ALLOC_IN_RC(ptr_reg));
3086  match(AddP addr (LShiftX index scale));
3087
3088  op_cost(100);
3089  format %{"[$addr + $index << $scale]" %}
3090  interface(MEMORY_INTER) %{
3091    base($addr);
3092    index($index);
3093    scale($scale);
3094    disp(0x0);
3095  %}
3096%}
3097
3098// Indirect Memory Times Scale Plus 32-bit Index Register
3099operand indIndexIScaleL(iRegP addr, iRegI index, immI_3 scale) %{
3100  constraint(ALLOC_IN_RC(ptr_reg));
3101  match(AddP addr (LShiftX (ConvI2L index) scale));
3102
3103  op_cost(100);
3104  format %{"[$addr + $index.w << $scale]" %}
3105  interface(MEMORY_INTER) %{
3106    base($addr);
3107    index($index);
3108    scale($scale);
3109    disp(0x7fffffff); // sxtw
3110  %}
3111%}
3112
3113// Indirect Memory Times Scale Plus Index Register
3114operand indIndexScaleQ(iRegP addr, iRegX index, immI_4 scale) %{
3115  constraint(ALLOC_IN_RC(ptr_reg));
3116  match(AddP addr (LShiftX index scale));
3117
3118  op_cost(100);
3119  format %{"[$addr + $index << $scale]" %}
3120  interface(MEMORY_INTER) %{
3121    base($addr);
3122    index($index);
3123    scale($scale);
3124    disp(0x0);
3125  %}
3126%}
3127
3128// Indirect Memory Times Scale Plus 32-bit Index Register
3129operand indIndexIScaleQ(iRegP addr, iRegI index, immI_4 scale) %{
3130  constraint(ALLOC_IN_RC(ptr_reg));
3131  match(AddP addr (LShiftX (ConvI2L index) scale));
3132
3133  op_cost(100);
3134  format %{"[$addr + $index.w << $scale]" %}
3135  interface(MEMORY_INTER) %{
3136    base($addr);
3137    index($index);
3138    scale($scale);
3139    disp(0x7fffffff); // sxtw
3140  %}
3141%}
3142#else
3143// Indirect Memory Times Scale Plus Index Register
3144operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{
3145  constraint(ALLOC_IN_RC(ptr_reg));
3146  match(AddP addr (LShiftX index scale));
3147
3148  op_cost(100);
3149  format %{"[$addr + $index << $scale]" %}
3150  interface(MEMORY_INTER) %{
3151    base($addr);
3152    index($index);
3153    scale($scale);
3154    disp(0x0);
3155  %}
3156%}
3157#endif
3158
3159// Operands for expressing Control Flow
3160// NOTE:  Label is a predefined operand which should not be redefined in
3161//        the AD file.  It is generically handled within the ADLC.
3162
3163//----------Conditional Branch Operands----------------------------------------
3164// Comparison Op  - This is the operation of the comparison, and is limited to
3165//                  the following set of codes:
3166//                  L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
3167//
3168// Other attributes of the comparison, such as unsignedness, are specified
3169// by the comparison instruction that sets a condition code flags register.
3170// That result is represented by a flags operand whose subtype is appropriate
3171// to the unsignedness (etc.) of the comparison.
3172//
3173// Later, the instruction which matches both the Comparison Op (a Bool) and
3174// the flags (produced by the Cmp) specifies the coding of the comparison op
3175// by matching a specific subtype of Bool operand below, such as cmpOpU.
3176
3177operand cmpOp() %{
3178  match(Bool);
3179
3180  format %{ "" %}
3181  interface(COND_INTER) %{
3182    equal(0x0);
3183    not_equal(0x1);
3184    less(0xb);
3185    greater_equal(0xa);
3186    less_equal(0xd);
3187    greater(0xc);
3188    overflow(0x0); // unsupported/unimplemented
3189    no_overflow(0x0); // unsupported/unimplemented
3190  %}
3191%}
3192
3193// integer comparison with 0, signed
3194operand cmpOp0() %{
3195  match(Bool);
3196
3197  format %{ "" %}
3198  interface(COND_INTER) %{
3199    equal(0x0);
3200    not_equal(0x1);
3201    less(0x4);
3202    greater_equal(0x5);
3203    less_equal(0xd); // unsupported
3204    greater(0xc); // unsupported
3205    overflow(0x0); // unsupported/unimplemented
3206    no_overflow(0x0); // unsupported/unimplemented
3207  %}
3208%}
3209
3210// Comparison Op, unsigned
3211operand cmpOpU() %{
3212  match(Bool);
3213
3214  format %{ "u" %}
3215  interface(COND_INTER) %{
3216    equal(0x0);
3217    not_equal(0x1);
3218    less(0x3);
3219    greater_equal(0x2);
3220    less_equal(0x9);
3221    greater(0x8);
3222    overflow(0x0); // unsupported/unimplemented
3223    no_overflow(0x0); // unsupported/unimplemented
3224  %}
3225%}
3226
3227// Comparison Op, pointer (same as unsigned)
3228operand cmpOpP() %{
3229  match(Bool);
3230
3231  format %{ "p" %}
3232  interface(COND_INTER) %{
3233    equal(0x0);
3234    not_equal(0x1);
3235    less(0x3);
3236    greater_equal(0x2);
3237    less_equal(0x9);
3238    greater(0x8);
3239    overflow(0x0); // unsupported/unimplemented
3240    no_overflow(0x0); // unsupported/unimplemented
3241  %}
3242%}
3243
3244operand cmpOpL() %{
3245  match(Bool);
3246
3247  format %{ "L" %}
3248  interface(COND_INTER) %{
3249    equal(0x0);
3250    not_equal(0x1);
3251    less(0xb);
3252    greater_equal(0xa);
3253    less_equal(0xd);
3254    greater(0xc);
3255    overflow(0x0); // unsupported/unimplemented
3256    no_overflow(0x0); // unsupported/unimplemented
3257  %}
3258%}
3259
3260operand cmpOpL_commute() %{
3261  match(Bool);
3262
3263  format %{ "L" %}
3264  interface(COND_INTER) %{
3265    equal(0x0);
3266    not_equal(0x1);
3267    less(0xc);
3268    greater_equal(0xd);
3269    less_equal(0xa);
3270    greater(0xb);
3271    overflow(0x0); // unsupported/unimplemented
3272    no_overflow(0x0); // unsupported/unimplemented
3273  %}
3274%}
3275
3276operand cmpOpUL() %{
3277  match(Bool);
3278
3279  format %{ "UL" %}
3280  interface(COND_INTER) %{
3281    equal(0x0);
3282    not_equal(0x1);
3283    less(0x3);
3284    greater_equal(0x2);
3285    less_equal(0x9);
3286    greater(0x8);
3287    overflow(0x0); // unsupported/unimplemented
3288    no_overflow(0x0); // unsupported/unimplemented
3289  %}
3290%}
3291
3292operand cmpOpUL_commute() %{
3293  match(Bool);
3294
3295  format %{ "UL" %}
3296  interface(COND_INTER) %{
3297    equal(0x0);
3298    not_equal(0x1);
3299    less(0x8);
3300    greater_equal(0x9);
3301    less_equal(0x2);
3302    greater(0x3);
3303    overflow(0x0); // unsupported/unimplemented
3304    no_overflow(0x0); // unsupported/unimplemented
3305  %}
3306%}
3307
3308
3309//----------OPERAND CLASSES----------------------------------------------------
3310// Operand Classes are groups of operands that are used to simplify
3311// instruction definitions by not requiring the AD writer to specify separate
3312// instructions for every form of operand when the instruction accepts
3313// multiple operand types with the same basic encoding and format.  The classic
3314// case of this is memory operands.
3315#ifdef AARCH64
3316opclass memoryB(indirect, indIndex, indOffsetU12ScaleB);
3317opclass memoryS(indirect, indIndex, indIndexScaleS, indIndexIScaleS, indOffsetU12ScaleS);
3318opclass memoryI(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI);
3319opclass memoryL(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL);
3320opclass memoryP(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL);
3321opclass memoryQ(indirect, indIndex, indIndexScaleQ, indIndexIScaleQ, indOffsetU12ScaleQ);
3322opclass memoryF(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI);
3323opclass memoryD(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL);
3324
3325opclass memoryScaledS(indIndexScaleS, indIndexIScaleS);
3326opclass memoryScaledI(indIndexScaleI, indIndexIScaleI);
3327opclass memoryScaledL(indIndexScaleL, indIndexIScaleL);
3328opclass memoryScaledP(indIndexScaleL, indIndexIScaleL);
3329opclass memoryScaledQ(indIndexScaleQ, indIndexIScaleQ);
3330opclass memoryScaledF(indIndexScaleI, indIndexIScaleI);
3331opclass memoryScaledD(indIndexScaleL, indIndexIScaleL);
3332// when ldrex/strex is used:
3333opclass memoryex ( indirect );
3334opclass indIndexMemory( indIndex );
3335opclass memoryvld ( indirect /* , write back mode not implemented */ );
3336
3337#else
3338
3339opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale );
3340opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale );
3341opclass memoryF ( indirect, indOffsetFP );
3342opclass memoryF2 ( indirect, indOffsetFPx2 );
3343opclass memoryD ( indirect, indOffsetFP );
3344opclass memoryfp( indirect, indOffsetFP );
3345opclass memoryB ( indirect, indIndex, indOffsetHD );
3346opclass memoryS ( indirect, indIndex, indOffsetHD );
3347opclass memoryL ( indirect, indIndex, indOffsetHD );
3348
3349opclass memoryScaledI(indIndexScale);
3350opclass memoryScaledP(indIndexScale);
3351
3352// when ldrex/strex is used:
3353opclass memoryex ( indirect );
3354opclass indIndexMemory( indIndex );
3355opclass memorylong ( indirect, indOffset12x2 );
3356opclass memoryvld ( indirect /* , write back mode not implemented */ );
3357#endif
3358
3359//----------PIPELINE-----------------------------------------------------------
3360pipeline %{
3361
3362//----------ATTRIBUTES---------------------------------------------------------
3363attributes %{
3364  fixed_size_instructions;           // Fixed size instructions
3365  max_instructions_per_bundle = 4;   // Up to 4 instructions per bundle
3366  instruction_unit_size = 4;         // An instruction is 4 bytes long
3367  instruction_fetch_unit_size = 16;  // The processor fetches one line
3368  instruction_fetch_units = 1;       // of 16 bytes
3369
3370  // List of nop instructions
3371  nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR );
3372%}
3373
3374//----------RESOURCES----------------------------------------------------------
3375// Resources are the functional units available to the machine
3376resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1);
3377
3378//----------PIPELINE DESCRIPTION-----------------------------------------------
3379// Pipeline Description specifies the stages in the machine's pipeline
3380
3381pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D);
3382
3383//----------PIPELINE CLASSES---------------------------------------------------
3384// Pipeline Classes describe the stages in which input and output are
3385// referenced by the hardware pipeline.
3386
3387// Integer ALU reg-reg operation
3388pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
3389    single_instruction;
3390    dst   : E(write);
3391    src1  : R(read);
3392    src2  : R(read);
3393    IALU  : R;
3394%}
3395
3396// Integer ALU reg-reg long operation
3397pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{
3398    instruction_count(2);
3399    dst   : E(write);
3400    src1  : R(read);
3401    src2  : R(read);
3402    IALU  : R;
3403    IALU  : R;
3404%}
3405
3406// Integer ALU reg-reg long dependent operation
3407pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{
3408    instruction_count(1); multiple_bundles;
3409    dst   : E(write);
3410    src1  : R(read);
3411    src2  : R(read);
3412    cr    : E(write);
3413    IALU  : R(2);
3414%}
3415
3416// Integer ALU reg-imm operaion
3417pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{
3418    single_instruction;
3419    dst   : E(write);
3420    src1  : R(read);
3421    IALU  : R;
3422%}
3423
3424// Integer ALU reg-reg operation with condition code
3425pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{
3426    single_instruction;
3427    dst   : E(write);
3428    cr    : E(write);
3429    src1  : R(read);
3430    src2  : R(read);
3431    IALU  : R;
3432%}
3433
3434// Integer ALU zero-reg operation
3435pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{
3436    single_instruction;
3437    dst   : E(write);
3438    src2  : R(read);
3439    IALU  : R;
3440%}
3441
3442// Integer ALU zero-reg operation with condition code only
3443pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{
3444    single_instruction;
3445    cr    : E(write);
3446    src   : R(read);
3447    IALU  : R;
3448%}
3449
3450// Integer ALU reg-reg operation with condition code only
3451pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
3452    single_instruction;
3453    cr    : E(write);
3454    src1  : R(read);
3455    src2  : R(read);
3456    IALU  : R;
3457%}
3458
3459// Integer ALU reg-imm operation with condition code only
3460pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{
3461    single_instruction;
3462    cr    : E(write);
3463    src1  : R(read);
3464    IALU  : R;
3465%}
3466
3467// Integer ALU reg-reg-zero operation with condition code only
3468pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{
3469    single_instruction;
3470    cr    : E(write);
3471    src1  : R(read);
3472    src2  : R(read);
3473    IALU  : R;
3474%}
3475
3476// Integer ALU reg-imm-zero operation with condition code only
3477pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{
3478    single_instruction;
3479    cr    : E(write);
3480    src1  : R(read);
3481    IALU  : R;
3482%}
3483
3484// Integer ALU reg-reg operation with condition code, src1 modified
3485pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
3486    single_instruction;
3487    cr    : E(write);
3488    src1  : E(write);
3489    src1  : R(read);
3490    src2  : R(read);
3491    IALU  : R;
3492%}
3493
3494pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{
3495    multiple_bundles;
3496    dst   : E(write)+4;
3497    cr    : E(write);
3498    src1  : R(read);
3499    src2  : R(read);
3500    IALU  : R(3);
3501    BR    : R(2);
3502%}
3503
3504// Integer ALU operation
3505pipe_class ialu_none(iRegI dst) %{
3506    single_instruction;
3507    dst   : E(write);
3508    IALU  : R;
3509%}
3510
3511// Integer ALU reg operation
3512pipe_class ialu_reg(iRegI dst, iRegI src) %{
3513    single_instruction; may_have_no_code;
3514    dst   : E(write);
3515    src   : R(read);
3516    IALU  : R;
3517%}
3518
3519// Integer ALU reg conditional operation
3520// This instruction has a 1 cycle stall, and cannot execute
3521// in the same cycle as the instruction setting the condition
3522// code. We kludge this by pretending to read the condition code
3523// 1 cycle earlier, and by marking the functional units as busy
3524// for 2 cycles with the result available 1 cycle later than
3525// is really the case.
3526pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{
3527    single_instruction;
3528    op2_out : C(write);
3529    op1     : R(read);
3530    cr      : R(read);       // This is really E, with a 1 cycle stall
3531    BR      : R(2);
3532    MS      : R(2);
3533%}
3534
3535// Integer ALU reg operation
3536pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{
3537    single_instruction; may_have_no_code;
3538    dst   : E(write);
3539    src   : R(read);
3540    IALU  : R;
3541%}
3542pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{
3543    single_instruction; may_have_no_code;
3544    dst   : E(write);
3545    src   : R(read);
3546    IALU  : R;
3547%}
3548
3549// Two integer ALU reg operations
3550pipe_class ialu_reg_2(iRegL dst, iRegL src) %{
3551    instruction_count(2);
3552    dst   : E(write);
3553    src   : R(read);
3554    A0    : R;
3555    A1    : R;
3556%}
3557
3558// Two integer ALU reg operations
3559pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{
3560    instruction_count(2); may_have_no_code;
3561    dst   : E(write);
3562    src   : R(read);
3563    A0    : R;
3564    A1    : R;
3565%}
3566
3567// Integer ALU imm operation
3568pipe_class ialu_imm(iRegI dst) %{
3569    single_instruction;
3570    dst   : E(write);
3571    IALU  : R;
3572%}
3573
3574pipe_class ialu_imm_n(iRegI dst) %{
3575    single_instruction;
3576    dst   : E(write);
3577    IALU  : R;
3578%}
3579
3580// Integer ALU reg-reg with carry operation
3581pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{
3582    single_instruction;
3583    dst   : E(write);
3584    src1  : R(read);
3585    src2  : R(read);
3586    IALU  : R;
3587%}
3588
3589// Integer ALU cc operation
3590pipe_class ialu_cc(iRegI dst, flagsReg cc) %{
3591    single_instruction;
3592    dst   : E(write);
3593    cc    : R(read);
3594    IALU  : R;
3595%}
3596
3597// Integer ALU cc / second IALU operation
3598pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{
3599    instruction_count(1); multiple_bundles;
3600    dst   : E(write)+1;
3601    src   : R(read);
3602    IALU  : R;
3603%}
3604
3605// Integer ALU cc / second IALU operation
3606pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{
3607    instruction_count(1); multiple_bundles;
3608    dst   : E(write)+1;
3609    p     : R(read);
3610    q     : R(read);
3611    IALU  : R;
3612%}
3613
3614// Integer ALU hi-lo-reg operation
3615pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{
3616    instruction_count(1); multiple_bundles;
3617    dst   : E(write)+1;
3618    IALU  : R(2);
3619%}
3620
3621// Long Constant
3622pipe_class loadConL( iRegL dst, immL src ) %{
3623    instruction_count(2); multiple_bundles;
3624    dst   : E(write)+1;
3625    IALU  : R(2);
3626    IALU  : R(2);
3627%}
3628
3629// Pointer Constant
3630pipe_class loadConP( iRegP dst, immP src ) %{
3631    instruction_count(0); multiple_bundles;
3632    fixed_latency(6);
3633%}
3634
3635// Polling Address
3636pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{
3637    dst   : E(write);
3638    IALU  : R;
3639%}
3640
3641// Long Constant small
3642pipe_class loadConLlo( iRegL dst, immL src ) %{
3643    instruction_count(2);
3644    dst   : E(write);
3645    IALU  : R;
3646    IALU  : R;
3647%}
3648
3649// [PHH] This is wrong for 64-bit.  See LdImmF/D.
3650pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{
3651    instruction_count(1); multiple_bundles;
3652    src   : R(read);
3653    dst   : M(write)+1;
3654    IALU  : R;
3655    MS    : E;
3656%}
3657
3658// Integer ALU nop operation
3659pipe_class ialu_nop() %{
3660    single_instruction;
3661    IALU  : R;
3662%}
3663
3664// Integer ALU nop operation
3665pipe_class ialu_nop_A0() %{
3666    single_instruction;
3667    A0    : R;
3668%}
3669
3670// Integer ALU nop operation
3671pipe_class ialu_nop_A1() %{
3672    single_instruction;
3673    A1    : R;
3674%}
3675
3676// Integer Multiply reg-reg operation
3677pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
3678    single_instruction;
3679    dst   : E(write);
3680    src1  : R(read);
3681    src2  : R(read);
3682    MS    : R(5);
3683%}
3684
3685pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
3686    single_instruction;
3687    dst   : E(write)+4;
3688    src1  : R(read);
3689    src2  : R(read);
3690    MS    : R(6);
3691%}
3692
3693// Integer Divide reg-reg
3694pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{
3695    instruction_count(1); multiple_bundles;
3696    dst   : E(write);
3697    temp  : E(write);
3698    src1  : R(read);
3699    src2  : R(read);
3700    temp  : R(read);
3701    MS    : R(38);
3702%}
3703
3704// Long Divide
3705pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
3706    dst  : E(write)+71;
3707    src1 : R(read);
3708    src2 : R(read)+1;
3709    MS   : R(70);
3710%}
3711
3712// Floating Point Add Float
3713pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{
3714    single_instruction;
3715    dst   : X(write);
3716    src1  : E(read);
3717    src2  : E(read);
3718    FA    : R;
3719%}
3720
3721// Floating Point Add Double
3722pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{
3723    single_instruction;
3724    dst   : X(write);
3725    src1  : E(read);
3726    src2  : E(read);
3727    FA    : R;
3728%}
3729
3730// Floating Point Conditional Move based on integer flags
3731pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{
3732    single_instruction;
3733    dst   : X(write);
3734    src   : E(read);
3735    cr    : R(read);
3736    FA    : R(2);
3737    BR    : R(2);
3738%}
3739
3740// Floating Point Conditional Move based on integer flags
3741pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{
3742    single_instruction;
3743    dst   : X(write);
3744    src   : E(read);
3745    cr    : R(read);
3746    FA    : R(2);
3747    BR    : R(2);
3748%}
3749
3750// Floating Point Multiply Float
3751pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{
3752    single_instruction;
3753    dst   : X(write);
3754    src1  : E(read);
3755    src2  : E(read);
3756    FM    : R;
3757%}
3758
3759// Floating Point Multiply Double
3760pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{
3761    single_instruction;
3762    dst   : X(write);
3763    src1  : E(read);
3764    src2  : E(read);
3765    FM    : R;
3766%}
3767
3768// Floating Point Divide Float
3769pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{
3770    single_instruction;
3771    dst   : X(write);
3772    src1  : E(read);
3773    src2  : E(read);
3774    FM    : R;
3775    FDIV  : C(14);
3776%}
3777
3778// Floating Point Divide Double
3779pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{
3780    single_instruction;
3781    dst   : X(write);
3782    src1  : E(read);
3783    src2  : E(read);
3784    FM    : R;
3785    FDIV  : C(17);
3786%}
3787
3788// Floating Point Move/Negate/Abs Float
3789pipe_class faddF_reg(regF dst, regF src) %{
3790    single_instruction;
3791    dst   : W(write);
3792    src   : E(read);
3793    FA    : R(1);
3794%}
3795
3796// Floating Point Move/Negate/Abs Double
3797pipe_class faddD_reg(regD dst, regD src) %{
3798    single_instruction;
3799    dst   : W(write);
3800    src   : E(read);
3801    FA    : R;
3802%}
3803
3804// Floating Point Convert F->D
3805pipe_class fcvtF2D(regD dst, regF src) %{
3806    single_instruction;
3807    dst   : X(write);
3808    src   : E(read);
3809    FA    : R;
3810%}
3811
3812// Floating Point Convert I->D
3813pipe_class fcvtI2D(regD dst, regF src) %{
3814    single_instruction;
3815    dst   : X(write);
3816    src   : E(read);
3817    FA    : R;
3818%}
3819
3820// Floating Point Convert LHi->D
3821pipe_class fcvtLHi2D(regD dst, regD src) %{
3822    single_instruction;
3823    dst   : X(write);
3824    src   : E(read);
3825    FA    : R;
3826%}
3827
3828// Floating Point Convert L->D
3829pipe_class fcvtL2D(regD dst, iRegL src) %{
3830    single_instruction;
3831    dst   : X(write);
3832    src   : E(read);
3833    FA    : R;
3834%}
3835
3836// Floating Point Convert L->F
3837pipe_class fcvtL2F(regF dst, iRegL src) %{
3838    single_instruction;
3839    dst   : X(write);
3840    src   : E(read);
3841    FA    : R;
3842%}
3843
3844// Floating Point Convert D->F
3845pipe_class fcvtD2F(regD dst, regF src) %{
3846    single_instruction;
3847    dst   : X(write);
3848    src   : E(read);
3849    FA    : R;
3850%}
3851
3852// Floating Point Convert I->L
3853pipe_class fcvtI2L(regD dst, regF src) %{
3854    single_instruction;
3855    dst   : X(write);
3856    src   : E(read);
3857    FA    : R;
3858%}
3859
3860// Floating Point Convert D->F
3861pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{
3862    instruction_count(1); multiple_bundles;
3863    dst   : X(write)+6;
3864    src   : E(read);
3865    FA    : R;
3866%}
3867
3868// Floating Point Convert D->L
3869pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{
3870    instruction_count(1); multiple_bundles;
3871    dst   : X(write)+6;
3872    src   : E(read);
3873    FA    : R;
3874%}
3875
3876// Floating Point Convert F->I
3877pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{
3878    instruction_count(1); multiple_bundles;
3879    dst   : X(write)+6;
3880    src   : E(read);
3881    FA    : R;
3882%}
3883
3884// Floating Point Convert F->L
3885pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{
3886    instruction_count(1); multiple_bundles;
3887    dst   : X(write)+6;
3888    src   : E(read);
3889    FA    : R;
3890%}
3891
3892// Floating Point Convert I->F
3893pipe_class fcvtI2F(regF dst, regF src) %{
3894    single_instruction;
3895    dst   : X(write);
3896    src   : E(read);
3897    FA    : R;
3898%}
3899
3900// Floating Point Compare
3901pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{
3902    single_instruction;
3903    cr    : X(write);
3904    src1  : E(read);
3905    src2  : E(read);
3906    FA    : R;
3907%}
3908
3909// Floating Point Compare
3910pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{
3911    single_instruction;
3912    cr    : X(write);
3913    src1  : E(read);
3914    src2  : E(read);
3915    FA    : R;
3916%}
3917
3918// Floating Add Nop
3919pipe_class fadd_nop() %{
3920    single_instruction;
3921    FA  : R;
3922%}
3923
3924// Integer Store to Memory
3925pipe_class istore_mem_reg(memoryI mem, iRegI src) %{
3926    single_instruction;
3927    mem   : R(read);
3928    src   : C(read);
3929    MS    : R;
3930%}
3931
3932// Integer Store to Memory
3933pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{
3934    single_instruction;
3935    mem   : R(read);
3936    src   : C(read);
3937    MS    : R;
3938%}
3939
3940// Float Store
3941pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{
3942    single_instruction;
3943    mem : R(read);
3944    src : C(read);
3945    MS  : R;
3946%}
3947
3948// Float Store
3949pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{
3950    single_instruction;
3951    mem : R(read);
3952    MS  : R;
3953%}
3954
3955// Double Store
3956pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{
3957    instruction_count(1);
3958    mem : R(read);
3959    src : C(read);
3960    MS  : R;
3961%}
3962
3963// Double Store
3964pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{
3965    single_instruction;
3966    mem : R(read);
3967    MS  : R;
3968%}
3969
3970// Integer Load (when sign bit propagation not needed)
3971pipe_class iload_mem(iRegI dst, memoryI mem) %{
3972    single_instruction;
3973    mem : R(read);
3974    dst : C(write);
3975    MS  : R;
3976%}
3977
3978// Integer Load (when sign bit propagation or masking is needed)
3979pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{
3980    single_instruction;
3981    mem : R(read);
3982    dst : M(write);
3983    MS  : R;
3984%}
3985
3986// Float Load
3987pipe_class floadF_mem(regF dst, memoryF mem) %{
3988    single_instruction;
3989    mem : R(read);
3990    dst : M(write);
3991    MS  : R;
3992%}
3993
3994// Float Load
3995pipe_class floadD_mem(regD dst, memoryD mem) %{
3996    instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case
3997    mem : R(read);
3998    dst : M(write);
3999    MS  : R;
4000%}
4001
4002// Memory Nop
4003pipe_class mem_nop() %{
4004    single_instruction;
4005    MS  : R;
4006%}
4007
4008pipe_class sethi(iRegP dst, immI src) %{
4009    single_instruction;
4010    dst  : E(write);
4011    IALU : R;
4012%}
4013
4014pipe_class loadPollP(iRegP poll) %{
4015    single_instruction;
4016    poll : R(read);
4017    MS   : R;
4018%}
4019
4020pipe_class br(Universe br, label labl) %{
4021    single_instruction_with_delay_slot;
4022    BR  : R;
4023%}
4024
4025pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
4026    single_instruction_with_delay_slot;
4027    cr    : E(read);
4028    BR    : R;
4029%}
4030
4031pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
4032    single_instruction_with_delay_slot;
4033    op1 : E(read);
4034    BR  : R;
4035    MS  : R;
4036%}
4037
4038pipe_class br_nop() %{
4039    single_instruction;
4040    BR  : R;
4041%}
4042
4043pipe_class simple_call(method meth) %{
4044    instruction_count(2); multiple_bundles; force_serialization;
4045    fixed_latency(100);
4046    BR  : R(1);
4047    MS  : R(1);
4048    A0  : R(1);
4049%}
4050
4051pipe_class compiled_call(method meth) %{
4052    instruction_count(1); multiple_bundles; force_serialization;
4053    fixed_latency(100);
4054    MS  : R(1);
4055%}
4056
4057pipe_class call(method meth) %{
4058    instruction_count(0); multiple_bundles; force_serialization;
4059    fixed_latency(100);
4060%}
4061
4062pipe_class tail_call(Universe ignore, label labl) %{
4063    single_instruction; has_delay_slot;
4064    fixed_latency(100);
4065    BR  : R(1);
4066    MS  : R(1);
4067%}
4068
4069pipe_class ret(Universe ignore) %{
4070    single_instruction; has_delay_slot;
4071    BR  : R(1);
4072    MS  : R(1);
4073%}
4074
4075// The real do-nothing guy
4076pipe_class empty( ) %{
4077    instruction_count(0);
4078%}
4079
4080pipe_class long_memory_op() %{
4081    instruction_count(0); multiple_bundles; force_serialization;
4082    fixed_latency(25);
4083    MS  : R(1);
4084%}
4085
4086// Check-cast
4087pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{
4088    array : R(read);
4089    match  : R(read);
4090    IALU   : R(2);
4091    BR     : R(2);
4092    MS     : R;
4093%}
4094
4095// Convert FPU flags into +1,0,-1
4096pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{
4097    src1  : E(read);
4098    src2  : E(read);
4099    dst   : E(write);
4100    FA    : R;
4101    MS    : R(2);
4102    BR    : R(2);
4103%}
4104
4105// Compare for p < q, and conditionally add y
4106pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
4107    p     : E(read);
4108    q     : E(read);
4109    y     : E(read);
4110    IALU  : R(3)
4111%}
4112
4113// Perform a compare, then move conditionally in a branch delay slot.
4114pipe_class min_max( iRegI src2, iRegI srcdst ) %{
4115    src2   : E(read);
4116    srcdst : E(read);
4117    IALU   : R;
4118    BR     : R;
4119%}
4120
4121// Define the class for the Nop node
4122define %{
4123   MachNop = ialu_nop;
4124%}
4125
4126%}
4127
4128//----------INSTRUCTIONS-------------------------------------------------------
4129
4130//------------Special Nop instructions for bundling - no match rules-----------
4131// Nop using the A0 functional unit
4132instruct Nop_A0() %{
4133  ins_pipe(ialu_nop_A0);
4134%}
4135
4136// Nop using the A1 functional unit
4137instruct Nop_A1( ) %{
4138  ins_pipe(ialu_nop_A1);
4139%}
4140
4141// Nop using the memory functional unit
4142instruct Nop_MS( ) %{
4143  ins_pipe(mem_nop);
4144%}
4145
4146// Nop using the floating add functional unit
4147instruct Nop_FA( ) %{
4148  ins_pipe(fadd_nop);
4149%}
4150
4151// Nop using the branch functional unit
4152instruct Nop_BR( ) %{
4153  ins_pipe(br_nop);
4154%}
4155
4156//----------Load/Store/Move Instructions---------------------------------------
4157//----------Load Instructions--------------------------------------------------
4158// Load Byte (8bit signed)
4159instruct loadB(iRegI dst, memoryB mem) %{
4160  match(Set dst (LoadB mem));
4161  ins_cost(MEMORY_REF_COST);
4162
4163  size(4);
4164  format %{ "LDRSB   $dst,$mem\t! byte -> int" %}
4165  ins_encode %{
4166    // High 32 bits are harmlessly set on Aarch64
4167    __ ldrsb($dst$$Register, $mem$$Address);
4168  %}
4169  ins_pipe(iload_mask_mem);
4170%}
4171
4172// Load Byte (8bit signed) into a Long Register
4173instruct loadB2L(iRegL dst, memoryB mem) %{
4174  match(Set dst (ConvI2L (LoadB mem)));
4175  ins_cost(MEMORY_REF_COST);
4176
4177#ifdef AARCH64
4178  size(4);
4179  format %{ "LDRSB $dst,$mem\t! byte -> long"  %}
4180  ins_encode %{
4181    __ ldrsb($dst$$Register, $mem$$Address);
4182  %}
4183#else
4184  size(8);
4185  format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t"
4186            "ASR   $dst.hi,$dst.lo,31" %}
4187  ins_encode %{
4188    __ ldrsb($dst$$Register, $mem$$Address);
4189    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
4190  %}
4191#endif
4192  ins_pipe(iload_mask_mem);
4193%}
4194
4195// Load Unsigned Byte (8bit UNsigned) into an int reg
4196instruct loadUB(iRegI dst, memoryB mem) %{
4197  match(Set dst (LoadUB mem));
4198  ins_cost(MEMORY_REF_COST);
4199
4200  size(4);
4201  format %{ "LDRB   $dst,$mem\t! ubyte -> int" %}
4202  ins_encode %{
4203    __ ldrb($dst$$Register, $mem$$Address);
4204  %}
4205  ins_pipe(iload_mem);
4206%}
4207
4208// Load Unsigned Byte (8bit UNsigned) into a Long Register
4209instruct loadUB2L(iRegL dst, memoryB mem) %{
4210  match(Set dst (ConvI2L (LoadUB mem)));
4211  ins_cost(MEMORY_REF_COST);
4212
4213#ifdef AARCH64
4214  size(4);
4215  format %{ "LDRB  $dst,$mem\t! ubyte -> long"  %}
4216  ins_encode %{
4217    __ ldrb($dst$$Register, $mem$$Address);
4218  %}
4219#else
4220  size(8);
4221  format %{ "LDRB  $dst.lo,$mem\t! ubyte -> long\n\t"
4222            "MOV   $dst.hi,0" %}
4223  ins_encode %{
4224    __ ldrb($dst$$Register, $mem$$Address);
4225    __ mov($dst$$Register->successor(), 0);
4226  %}
4227#endif
4228  ins_pipe(iload_mem);
4229%}
4230
4231// Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register
4232instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{
4233  match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
4234
4235#ifdef AARCH64
4236  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4237  size(8);
4238  format %{ "LDRB  $dst,$mem\t! ubyte -> long\n\t"
4239            "AND  $dst,$dst,$mask" %}
4240  ins_encode %{
4241    __ ldrb($dst$$Register, $mem$$Address);
4242    __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
4243  %}
4244#else
4245  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
4246  size(12);
4247  format %{ "LDRB  $dst.lo,$mem\t! ubyte -> long\n\t"
4248            "MOV   $dst.hi,0\n\t"
4249            "AND  $dst.lo,$dst.lo,$mask" %}
4250  ins_encode %{
4251    __ ldrb($dst$$Register, $mem$$Address);
4252    __ mov($dst$$Register->successor(), 0);
4253    __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
4254  %}
4255#endif
4256  ins_pipe(iload_mem);
4257%}
4258
4259// Load Short (16bit signed)
4260#ifdef AARCH64
4261// XXX This variant shouldn't be necessary if 6217251 is implemented
4262instruct loadSoff(iRegI dst, memoryScaledS mem, aimmX off, iRegP tmp) %{
4263  match(Set dst (LoadS (AddP mem off)));
4264  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4265  effect(TEMP tmp);
4266  size(4 * 2);
4267
4268  format %{ "LDRSH   $dst,$mem+$off\t! short temp=$tmp" %}
4269  ins_encode %{
4270    Register base = reg_to_register_object($mem$$base);
4271    __ add($tmp$$Register, base, $off$$constant);
4272    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4273    __ ldrsh($dst$$Register, nmem);
4274  %}
4275  ins_pipe(iload_mask_mem);
4276%}
4277#endif
4278
4279instruct loadS(iRegI dst, memoryS mem) %{
4280  match(Set dst (LoadS mem));
4281  ins_cost(MEMORY_REF_COST);
4282
4283  size(4);
4284  format %{ "LDRSH   $dst,$mem\t! short" %}
4285  ins_encode %{
4286    __ ldrsh($dst$$Register, $mem$$Address);
4287  %}
4288  ins_pipe(iload_mask_mem);
4289%}
4290
4291// Load Short (16 bit signed) to Byte (8 bit signed)
4292instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
4293  match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
4294  ins_cost(MEMORY_REF_COST);
4295
4296  size(4);
4297
4298  format %{ "LDRSB   $dst,$mem\t! short -> byte" %}
4299  ins_encode %{
4300    // High 32 bits are harmlessly set on Aarch64
4301    __ ldrsb($dst$$Register, $mem$$Address);
4302  %}
4303  ins_pipe(iload_mask_mem);
4304%}
4305
4306// Load Short (16bit signed) into a Long Register
4307instruct loadS2L(iRegL dst, memoryS mem) %{
4308  match(Set dst (ConvI2L (LoadS mem)));
4309  ins_cost(MEMORY_REF_COST);
4310
4311#ifdef AARCH64
4312  size(4);
4313  format %{ "LDRSH $dst,$mem\t! short -> long"  %}
4314  ins_encode %{
4315    __ ldrsh($dst$$Register, $mem$$Address);
4316  %}
4317#else
4318  size(8);
4319  format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t"
4320            "ASR   $dst.hi,$dst.lo,31" %}
4321  ins_encode %{
4322    __ ldrsh($dst$$Register, $mem$$Address);
4323    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
4324  %}
4325#endif
4326  ins_pipe(iload_mask_mem);
4327%}
4328
4329// Load Unsigned Short/Char (16bit UNsigned)
4330
4331#ifdef AARCH64
4332// XXX This variant shouldn't be necessary if 6217251 is implemented
4333instruct loadUSoff(iRegI dst, memoryScaledS mem, aimmX off, iRegP tmp) %{
4334  match(Set dst (LoadUS (AddP mem off)));
4335  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4336  effect(TEMP tmp);
4337  size(4 * 2);
4338
4339  format %{ "LDRH   $dst,$mem+$off\t! ushort/char temp=$tmp" %}
4340  ins_encode %{
4341    Register base = reg_to_register_object($mem$$base);
4342    __ add($tmp$$Register, base, $off$$constant);
4343    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4344    __ ldrh($dst$$Register, nmem);
4345  %}
4346  ins_pipe(iload_mem);
4347%}
4348#endif
4349
4350instruct loadUS(iRegI dst, memoryS mem) %{
4351  match(Set dst (LoadUS mem));
4352  ins_cost(MEMORY_REF_COST);
4353
4354  size(4);
4355  format %{ "LDRH   $dst,$mem\t! ushort/char" %}
4356  ins_encode %{
4357    __ ldrh($dst$$Register, $mem$$Address);
4358  %}
4359  ins_pipe(iload_mem);
4360%}
4361
4362// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
4363instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{
4364  match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
4365  ins_cost(MEMORY_REF_COST);
4366
4367  size(4);
4368  format %{ "LDRSB   $dst,$mem\t! ushort -> byte" %}
4369  ins_encode %{
4370    __ ldrsb($dst$$Register, $mem$$Address);
4371  %}
4372  ins_pipe(iload_mask_mem);
4373%}
4374
4375// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
4376instruct loadUS2L(iRegL dst, memoryS mem) %{
4377  match(Set dst (ConvI2L (LoadUS mem)));
4378  ins_cost(MEMORY_REF_COST);
4379
4380#ifdef AARCH64
4381  size(4);
4382  format %{ "LDRH  $dst,$mem\t! short -> long"  %}
4383  ins_encode %{
4384    __ ldrh($dst$$Register, $mem$$Address);
4385  %}
4386#else
4387  size(8);
4388  format %{ "LDRH  $dst.lo,$mem\t! short -> long\n\t"
4389            "MOV   $dst.hi, 0" %}
4390  ins_encode %{
4391    __ ldrh($dst$$Register, $mem$$Address);
4392    __ mov($dst$$Register->successor(), 0);
4393  %}
4394#endif
4395  ins_pipe(iload_mem);
4396%}
4397
4398// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register
4399instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
4400  match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
4401  ins_cost(MEMORY_REF_COST);
4402
4403#ifdef AARCH64
4404  size(4);
4405  format %{ "LDRB  $dst,$mem"  %}
4406  ins_encode %{
4407    __ ldrb($dst$$Register, $mem$$Address);
4408  %}
4409#else
4410  size(8);
4411  format %{ "LDRB  $dst.lo,$mem\t! \n\t"
4412            "MOV   $dst.hi, 0" %}
4413  ins_encode %{
4414    __ ldrb($dst$$Register, $mem$$Address);
4415    __ mov($dst$$Register->successor(), 0);
4416  %}
4417#endif
4418  ins_pipe(iload_mem);
4419%}
4420
4421// Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register
4422instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{
4423  match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
4424#ifdef AARCH64
4425  ins_cost(MEMORY_REF_COST + 1*DEFAULT_COST);
4426
4427  size(8);
4428  format %{ "LDRH   $dst,$mem\t! ushort/char & mask -> long\n\t"
4429            "AND    $dst,$dst,$mask" %}
4430  ins_encode %{
4431    __ ldrh($dst$$Register, $mem$$Address);
4432    __ andr($dst$$Register, $dst$$Register, (uintx)$mask$$constant);
4433  %}
4434#else
4435  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
4436
4437  size(12);
4438  format %{ "LDRH   $dst,$mem\t! ushort/char & mask -> long\n\t"
4439            "MOV    $dst.hi, 0\n\t"
4440            "AND    $dst,$dst,$mask" %}
4441  ins_encode %{
4442    __ ldrh($dst$$Register, $mem$$Address);
4443    __ mov($dst$$Register->successor(), 0);
4444    __ andr($dst$$Register, $dst$$Register, $mask$$constant);
4445  %}
4446#endif
4447  ins_pipe(iload_mem);
4448%}
4449
4450// Load Integer
4451
4452#ifdef AARCH64
4453// XXX This variant shouldn't be necessary if 6217251 is implemented
4454instruct loadIoff(iRegI dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
4455  match(Set dst (LoadI (AddP mem off)));
4456  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4457  effect(TEMP tmp);
4458  size(4 * 2);
4459
4460  format %{ "ldr_s32 $dst,$mem+$off\t! int temp=$tmp" %}
4461  ins_encode %{
4462    Register base = reg_to_register_object($mem$$base);
4463    __ add($tmp$$Register, base, $off$$constant);
4464    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4465    __ ldr_s32($dst$$Register, nmem);
4466  %}
4467  ins_pipe(iload_mem);
4468%}
4469#endif
4470
4471instruct loadI(iRegI dst, memoryI mem) %{
4472  match(Set dst (LoadI mem));
4473  ins_cost(MEMORY_REF_COST);
4474
4475  size(4);
4476  format %{ "ldr_s32 $dst,$mem\t! int" %}
4477  ins_encode %{
4478    __ ldr_s32($dst$$Register, $mem$$Address);
4479  %}
4480  ins_pipe(iload_mem);
4481%}
4482
4483// Load Integer to Byte (8 bit signed)
4484instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
4485  match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
4486  ins_cost(MEMORY_REF_COST);
4487
4488  size(4);
4489
4490  format %{ "LDRSB   $dst,$mem\t! int -> byte" %}
4491  ins_encode %{
4492    __ ldrsb($dst$$Register, $mem$$Address);
4493  %}
4494  ins_pipe(iload_mask_mem);
4495%}
4496
4497// Load Integer to Unsigned Byte (8 bit UNsigned)
4498instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{
4499  match(Set dst (AndI (LoadI mem) mask));
4500  ins_cost(MEMORY_REF_COST);
4501
4502  size(4);
4503
4504  format %{ "LDRB   $dst,$mem\t! int -> ubyte" %}
4505  ins_encode %{
4506    __ ldrb($dst$$Register, $mem$$Address);
4507  %}
4508  ins_pipe(iload_mask_mem);
4509%}
4510
4511// Load Integer to Short (16 bit signed)
4512instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{
4513  match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
4514  ins_cost(MEMORY_REF_COST);
4515
4516  size(4);
4517  format %{ "LDRSH   $dst,$mem\t! int -> short" %}
4518  ins_encode %{
4519    __ ldrsh($dst$$Register, $mem$$Address);
4520  %}
4521  ins_pipe(iload_mask_mem);
4522%}
4523
4524// Load Integer to Unsigned Short (16 bit UNsigned)
4525instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{
4526  match(Set dst (AndI (LoadI mem) mask));
4527  ins_cost(MEMORY_REF_COST);
4528
4529  size(4);
4530  format %{ "LDRH   $dst,$mem\t! int -> ushort/char" %}
4531  ins_encode %{
4532    __ ldrh($dst$$Register, $mem$$Address);
4533  %}
4534  ins_pipe(iload_mask_mem);
4535%}
4536
4537// Load Integer into a Long Register
4538instruct loadI2L(iRegL dst, memoryI mem) %{
4539  match(Set dst (ConvI2L (LoadI mem)));
4540#ifdef AARCH64
4541  ins_cost(MEMORY_REF_COST);
4542
4543  size(4);
4544  format %{ "LDRSW $dst.lo,$mem\t! int -> long"  %}
4545  ins_encode %{
4546    __ ldr_s32($dst$$Register, $mem$$Address);
4547  %}
4548#else
4549  ins_cost(MEMORY_REF_COST);
4550
4551  size(8);
4552  format %{ "LDR   $dst.lo,$mem\t! int -> long\n\t"
4553            "ASR   $dst.hi,$dst.lo,31\t! int->long" %}
4554  ins_encode %{
4555    __ ldr($dst$$Register, $mem$$Address);
4556    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
4557  %}
4558#endif
4559  ins_pipe(iload_mask_mem);
4560%}
4561
4562// Load Integer with mask 0xFF into a Long Register
4563instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
4564  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4565#ifdef AARCH64
4566  ins_cost(MEMORY_REF_COST);
4567
4568  size(4);
4569  format %{ "LDRB   $dst.lo,$mem\t! int & 0xFF -> long"  %}
4570  ins_encode %{
4571    __ ldrb($dst$$Register, $mem$$Address);
4572  %}
4573#else
4574  ins_cost(MEMORY_REF_COST);
4575
4576  size(8);
4577  format %{ "LDRB   $dst.lo,$mem\t! int & 0xFF -> long\n\t"
4578            "MOV    $dst.hi, 0" %}
4579  ins_encode %{
4580    __ ldrb($dst$$Register, $mem$$Address);
4581    __ mov($dst$$Register->successor(), 0);
4582  %}
4583#endif
4584  ins_pipe(iload_mem);
4585%}
4586
4587// Load Integer with mask 0xFFFF into a Long Register
4588instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{
4589  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4590  ins_cost(MEMORY_REF_COST);
4591
4592#ifdef AARCH64
4593  size(4);
4594  format %{ "LDRH   $dst,$mem\t! int & 0xFFFF -> long" %}
4595  ins_encode %{
4596    __ ldrh($dst$$Register, $mem$$Address);
4597  %}
4598#else
4599  size(8);
4600  format %{ "LDRH   $dst,$mem\t! int & 0xFFFF -> long\n\t"
4601            "MOV    $dst.hi, 0" %}
4602  ins_encode %{
4603    __ ldrh($dst$$Register, $mem$$Address);
4604    __ mov($dst$$Register->successor(), 0);
4605  %}
4606#endif
4607  ins_pipe(iload_mask_mem);
4608%}
4609
4610#ifdef AARCH64
4611// Load Integer with an immediate mask into a Long Register
4612instruct loadI2L_limmI(iRegL dst, memoryI mem, limmI mask) %{
4613  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4614  ins_cost(MEMORY_REF_COST + 1*DEFAULT_COST);
4615
4616  size(8);
4617  format %{ "LDRSW $dst,$mem\t! int -> long\n\t"
4618            "AND   $dst,$dst,$mask" %}
4619
4620  ins_encode %{
4621    __ ldr_s32($dst$$Register, $mem$$Address);
4622    __ andr($dst$$Register, $dst$$Register, (uintx)$mask$$constant);
4623  %}
4624  ins_pipe(iload_mem);
4625%}
4626#else
4627// Load Integer with a 31-bit immediate mask into a Long Register
4628instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{
4629  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4630  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
4631
4632  size(12);
4633  format %{ "LDR   $dst.lo,$mem\t! int -> long\n\t"
4634            "MOV    $dst.hi, 0\n\t"
4635            "AND   $dst,$dst,$mask" %}
4636
4637  ins_encode %{
4638    __ ldr($dst$$Register, $mem$$Address);
4639    __ mov($dst$$Register->successor(), 0);
4640    __ andr($dst$$Register, $dst$$Register, $mask$$constant);
4641  %}
4642  ins_pipe(iload_mem);
4643%}
4644#endif
4645
4646#ifdef AARCH64
4647// Load Integer with mask into a Long Register
4648// FIXME: use signedRegI mask, remove tmp?
4649instruct loadI2L_immI(iRegL dst, memoryI mem, immI mask, iRegI tmp) %{
4650  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4651  effect(TEMP dst, TEMP tmp);
4652
4653  ins_cost(MEMORY_REF_COST + 3*DEFAULT_COST);
4654  format %{ "LDRSW    $mem,$dst\t! int & 31-bit mask -> long\n\t"
4655            "MOV_SLOW $tmp,$mask\n\t"
4656            "AND      $dst,$tmp,$dst" %}
4657  ins_encode %{
4658    __ ldrsw($dst$$Register, $mem$$Address);
4659    __ mov_slow($tmp$$Register, $mask$$constant);
4660    __ andr($dst$$Register, $dst$$Register, $tmp$$Register);
4661  %}
4662  ins_pipe(iload_mem);
4663%}
4664#else
4665// Load Integer with a 31-bit mask into a Long Register
4666// FIXME: use iRegI mask, remove tmp?
4667instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{
4668  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4669  effect(TEMP dst, TEMP tmp);
4670
4671  ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST);
4672  size(20);
4673  format %{ "LDR      $mem,$dst\t! int & 31-bit mask -> long\n\t"
4674            "MOV      $dst.hi, 0\n\t"
4675            "MOV_SLOW $tmp,$mask\n\t"
4676            "AND      $dst,$tmp,$dst" %}
4677  ins_encode %{
4678    __ ldr($dst$$Register, $mem$$Address);
4679    __ mov($dst$$Register->successor(), 0);
4680    __ mov_slow($tmp$$Register, $mask$$constant);
4681    __ andr($dst$$Register, $dst$$Register, $tmp$$Register);
4682  %}
4683  ins_pipe(iload_mem);
4684%}
4685#endif
4686
4687// Load Unsigned Integer into a Long Register
4688instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{
4689  match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
4690  ins_cost(MEMORY_REF_COST);
4691
4692#ifdef AARCH64
4693//size(4);
4694  format %{ "LDR_w $dst,$mem\t! uint -> long" %}
4695  ins_encode %{
4696    __ ldr_w($dst$$Register, $mem$$Address);
4697  %}
4698#else
4699  size(8);
4700  format %{ "LDR   $dst.lo,$mem\t! uint -> long\n\t"
4701            "MOV   $dst.hi,0" %}
4702  ins_encode %{
4703    __ ldr($dst$$Register, $mem$$Address);
4704    __ mov($dst$$Register->successor(), 0);
4705  %}
4706#endif
4707  ins_pipe(iload_mem);
4708%}
4709
4710// Load Long
4711
4712#ifdef AARCH64
4713// XXX This variant shouldn't be necessary if 6217251 is implemented
4714instruct loadLoff(iRegLd dst, memoryScaledL mem, aimmX off, iRegP tmp) %{
4715  match(Set dst (LoadL (AddP mem off)));
4716  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4717  effect(TEMP tmp);
4718  size(4 * 2);
4719
4720  format %{ "LDR    $dst,$mem+$off\t! long temp=$tmp" %}
4721  ins_encode %{
4722    Register base = reg_to_register_object($mem$$base);
4723    __ add($tmp$$Register, base, $off$$constant);
4724    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4725    __ ldr($dst$$Register, nmem);
4726  %}
4727  ins_pipe(iload_mem);
4728%}
4729#endif
4730
4731instruct loadL(iRegLd dst, memoryL mem ) %{
4732#ifdef AARCH64
4733  // already atomic for Aarch64
4734#else
4735  predicate(!((LoadLNode*)n)->require_atomic_access());
4736#endif
4737  match(Set dst (LoadL mem));
4738  effect(TEMP dst);
4739  ins_cost(MEMORY_REF_COST);
4740
4741  size(4);
4742  format %{ "ldr_64  $dst,$mem\t! long" %}
4743  ins_encode %{
4744    __ ldr_64($dst$$Register, $mem$$Address);
4745  %}
4746  ins_pipe(iload_mem);
4747%}
4748
4749#ifndef AARCH64
4750instruct loadL_2instr(iRegL dst, memorylong mem ) %{
4751  predicate(!((LoadLNode*)n)->require_atomic_access());
4752  match(Set dst (LoadL mem));
4753  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4754
4755  size(8);
4756  format %{ "LDR    $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
4757            "LDR    $dst.hi,$mem+4 or $mem" %}
4758  ins_encode %{
4759    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4760    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4761
4762    if ($dst$$Register == reg_to_register_object($mem$$base)) {
4763      __ ldr($dst$$Register->successor(), Amemhi);
4764      __ ldr($dst$$Register, Amemlo);
4765    } else {
4766      __ ldr($dst$$Register, Amemlo);
4767      __ ldr($dst$$Register->successor(), Amemhi);
4768    }
4769  %}
4770  ins_pipe(iload_mem);
4771%}
4772
4773instruct loadL_volatile(iRegL dst, indirect mem ) %{
4774  predicate(((LoadLNode*)n)->require_atomic_access());
4775  match(Set dst (LoadL mem));
4776  ins_cost(MEMORY_REF_COST);
4777
4778  size(4);
4779  format %{ "LDMIA    $dst,$mem\t! long" %}
4780  ins_encode %{
4781    // FIXME: why is ldmia considered atomic?  Should be ldrexd
4782    RegisterSet set($dst$$Register);
4783    set = set | reg_to_register_object($dst$$reg + 1);
4784    __ ldmia(reg_to_register_object($mem$$base), set);
4785  %}
4786  ins_pipe(iload_mem);
4787%}
4788
4789instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{
4790  predicate(((LoadLNode*)n)->require_atomic_access());
4791  match(Set dst (LoadL mem));
4792  ins_cost(MEMORY_REF_COST);
4793
4794  size(8);
4795  format %{ "FLDD      S14, $mem"
4796            "FMRRD    $dst, S14\t! long \n't" %}
4797  ins_encode %{
4798    __ fldd(S14, $mem$$Address);
4799    __ fmrrd($dst$$Register, $dst$$Register->successor(), S14);
4800  %}
4801  ins_pipe(iload_mem);
4802%}
4803
4804instruct loadL_unaligned(iRegL dst, memorylong mem ) %{
4805  match(Set dst (LoadL_unaligned mem));
4806  ins_cost(MEMORY_REF_COST);
4807
4808  size(8);
4809  format %{ "LDR    $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
4810            "LDR    $dst.hi,$mem+4" %}
4811  ins_encode %{
4812    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4813    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4814
4815    if ($dst$$Register == reg_to_register_object($mem$$base)) {
4816      __ ldr($dst$$Register->successor(), Amemhi);
4817      __ ldr($dst$$Register, Amemlo);
4818    } else {
4819      __ ldr($dst$$Register, Amemlo);
4820      __ ldr($dst$$Register->successor(), Amemhi);
4821    }
4822  %}
4823  ins_pipe(iload_mem);
4824%}
4825#endif // !AARCH64
4826
4827// Load Range
4828instruct loadRange(iRegI dst, memoryI mem) %{
4829  match(Set dst (LoadRange mem));
4830  ins_cost(MEMORY_REF_COST);
4831
4832  size(4);
4833  format %{ "LDR_u32 $dst,$mem\t! range" %}
4834  ins_encode %{
4835    __ ldr_u32($dst$$Register, $mem$$Address);
4836  %}
4837  ins_pipe(iload_mem);
4838%}
4839
4840// Load Pointer
4841
4842#ifdef AARCH64
4843// XXX This variant shouldn't be necessary if 6217251 is implemented
4844instruct loadPoff(iRegP dst, memoryScaledP mem, aimmX off, iRegP tmp) %{
4845  match(Set dst (LoadP (AddP mem off)));
4846  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4847  effect(TEMP tmp);
4848  size(4 * 2);
4849
4850  format %{ "LDR    $dst,$mem+$off\t! ptr temp=$tmp" %}
4851  ins_encode %{
4852    Register base = reg_to_register_object($mem$$base);
4853    __ add($tmp$$Register, base, $off$$constant);
4854    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4855    __ ldr($dst$$Register, nmem);
4856  %}
4857  ins_pipe(iload_mem);
4858%}
4859#endif
4860
4861instruct loadP(iRegP dst, memoryP mem) %{
4862  match(Set dst (LoadP mem));
4863  ins_cost(MEMORY_REF_COST);
4864  size(4);
4865
4866  format %{ "LDR   $dst,$mem\t! ptr" %}
4867  ins_encode %{
4868    __ ldr($dst$$Register, $mem$$Address);
4869  %}
4870  ins_pipe(iload_mem);
4871%}
4872
4873#ifdef XXX
4874// FIXME XXXX
4875//instruct loadSP(iRegP dst, memoryP mem) %{
4876instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{
4877  match(Set dst (LoadP mem));
4878  effect(TEMP tmp);
4879  ins_cost(MEMORY_REF_COST+1);
4880  size(8);
4881
4882  format %{ "LDR   $tmp,$mem\t! ptr\n\t"
4883            "MOV   $dst,$tmp\t! ptr" %}
4884  ins_encode %{
4885    __ ldr($tmp$$Register, $mem$$Address);
4886    __ mov($dst$$Register, $tmp$$Register);
4887  %}
4888  ins_pipe(iload_mem);
4889%}
4890#endif
4891
4892#ifdef _LP64
4893// Load Compressed Pointer
4894
4895// XXX This variant shouldn't be necessary if 6217251 is implemented
4896instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
4897  match(Set dst (LoadN (AddP mem off)));
4898  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4899  effect(TEMP tmp);
4900  size(4 * 2);
4901
4902  format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %}
4903  ins_encode %{
4904    Register base = reg_to_register_object($mem$$base);
4905    __ add($tmp$$Register, base, $off$$constant);
4906    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4907    __ ldr_u32($dst$$Register, nmem);
4908  %}
4909  ins_pipe(iload_mem);
4910%}
4911
4912instruct loadN(iRegN dst, memoryI mem) %{
4913  match(Set dst (LoadN mem));
4914  ins_cost(MEMORY_REF_COST);
4915  size(4);
4916
4917  format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %}
4918  ins_encode %{
4919    __ ldr_u32($dst$$Register, $mem$$Address);
4920  %}
4921  ins_pipe(iload_mem);
4922%}
4923#endif
4924
4925// Load Klass Pointer
4926instruct loadKlass(iRegP dst, memoryI mem) %{
4927  match(Set dst (LoadKlass mem));
4928  ins_cost(MEMORY_REF_COST);
4929  size(4);
4930
4931  format %{ "LDR   $dst,$mem\t! klass ptr" %}
4932  ins_encode %{
4933    __ ldr($dst$$Register, $mem$$Address);
4934  %}
4935  ins_pipe(iload_mem);
4936%}
4937
4938#ifdef _LP64
4939// Load narrow Klass Pointer
4940instruct loadNKlass(iRegN dst, memoryI mem) %{
4941  match(Set dst (LoadNKlass mem));
4942  ins_cost(MEMORY_REF_COST);
4943  size(4);
4944
4945  format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %}
4946  ins_encode %{
4947    __ ldr_u32($dst$$Register, $mem$$Address);
4948  %}
4949  ins_pipe(iload_mem);
4950%}
4951#endif
4952
4953#ifdef AARCH64
4954// XXX This variant shouldn't be necessary if 6217251 is implemented
4955instruct loadDoff(regD dst, memoryScaledD mem, aimmX off, iRegP tmp) %{
4956  match(Set dst (LoadD (AddP mem off)));
4957  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4958  effect(TEMP tmp);
4959  size(4 * 2);
4960
4961  format %{ "ldr    $dst,$mem+$off\t! double temp=$tmp" %}
4962  ins_encode %{
4963    Register base = reg_to_register_object($mem$$base);
4964    __ add($tmp$$Register, base, $off$$constant);
4965    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4966    __ ldr_d($dst$$FloatRegister, nmem);
4967  %}
4968  ins_pipe(floadD_mem);
4969%}
4970#endif
4971
4972instruct loadD(regD dst, memoryD mem) %{
4973  match(Set dst (LoadD mem));
4974  ins_cost(MEMORY_REF_COST);
4975
4976  size(4);
4977  // FIXME: needs to be atomic, but  ARMv7 A.R.M. guarantees
4978  // only LDREXD and STREXD are 64-bit single-copy atomic
4979  format %{ "FLDD   $dst,$mem" %}
4980  ins_encode %{
4981    __ ldr_double($dst$$FloatRegister, $mem$$Address);
4982  %}
4983  ins_pipe(floadD_mem);
4984%}
4985
4986#ifndef AARCH64
4987// Load Double - UNaligned
4988instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{
4989  match(Set dst (LoadD_unaligned mem));
4990  ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
4991  size(8);
4992  format %{ "FLDS    $dst.lo,$mem\t! misaligned double\n"
4993          "\tFLDS    $dst.hi,$mem+4\t!" %}
4994  ins_encode %{
4995    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4996    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4997      __ flds($dst$$FloatRegister, Amemlo);
4998      __ flds($dst$$FloatRegister->successor(), Amemhi);
4999  %}
5000  ins_pipe(iload_mem);
5001%}
5002#endif
5003
5004#ifdef AARCH64
5005// XXX This variant shouldn't be necessary if 6217251 is implemented
5006instruct loadFoff(regF dst, memoryScaledF mem, aimmX off, iRegP tmp) %{
5007  match(Set dst (LoadF (AddP mem off)));
5008  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5009  effect(TEMP tmp);
5010  size(4 * 2);
5011
5012  format %{ "ldr    $dst,$mem+$off\t! float temp=$tmp" %}
5013  ins_encode %{
5014    Register base = reg_to_register_object($mem$$base);
5015    __ add($tmp$$Register, base, $off$$constant);
5016    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5017    __ ldr_s($dst$$FloatRegister, nmem);
5018  %}
5019  ins_pipe(floadF_mem);
5020%}
5021#endif
5022
5023instruct loadF(regF dst, memoryF mem) %{
5024  match(Set dst (LoadF mem));
5025
5026  ins_cost(MEMORY_REF_COST);
5027  size(4);
5028  format %{ "FLDS    $dst,$mem" %}
5029  ins_encode %{
5030    __ ldr_float($dst$$FloatRegister, $mem$$Address);
5031  %}
5032  ins_pipe(floadF_mem);
5033%}
5034
5035#ifdef AARCH64
5036instruct load_limmI(iRegI dst, limmI src) %{
5037  match(Set dst src);
5038  ins_cost(DEFAULT_COST + 1); // + 1 because MOV is preferred
5039  format %{ "ORR_w  $dst, ZR, $src\t! int"  %}
5040  ins_encode %{
5041    __ orr_w($dst$$Register, ZR, (uintx)$src$$constant);
5042  %}
5043  ins_pipe(ialu_imm);
5044%}
5045#endif
5046
5047// // Load Constant
5048instruct loadConI( iRegI dst, immI src ) %{
5049  match(Set dst src);
5050  ins_cost(DEFAULT_COST * 3/2);
5051  format %{ "MOV_SLOW    $dst, $src" %}
5052  ins_encode %{
5053    __ mov_slow($dst$$Register, $src$$constant);
5054  %}
5055  ins_pipe(ialu_hi_lo_reg);
5056%}
5057
5058instruct loadConIMov( iRegI dst, immIMov src ) %{
5059  match(Set dst src);
5060  size(4);
5061  format %{ "MOV    $dst, $src" %}
5062  ins_encode %{
5063    __ mov($dst$$Register, $src$$constant);
5064  %}
5065  ins_pipe(ialu_imm);
5066%}
5067
5068#ifndef AARCH64
5069instruct loadConIMovn( iRegI dst, immIRotn src ) %{
5070  match(Set dst src);
5071  size(4);
5072  format %{ "MVN    $dst, ~$src" %}
5073  ins_encode %{
5074    __ mvn($dst$$Register, ~$src$$constant);
5075  %}
5076  ins_pipe(ialu_imm_n);
5077%}
5078#endif
5079
5080instruct loadConI16( iRegI dst, immI16 src ) %{
5081  match(Set dst src);
5082  size(4);
5083#ifdef AARCH64
5084  format %{ "MOVZ_w  $dst, $src" %}
5085#else
5086  format %{ "MOVW    $dst, $src" %}
5087#endif
5088  ins_encode %{
5089#ifdef AARCH64
5090    __ mov_w($dst$$Register, $src$$constant);
5091#else
5092    __ movw($dst$$Register, $src$$constant);
5093#endif
5094  %}
5095  ins_pipe(ialu_imm_n);
5096%}
5097
5098instruct loadConP(iRegP dst, immP src) %{
5099  match(Set dst src);
5100  ins_cost(DEFAULT_COST * 3/2);
5101  format %{ "MOV_SLOW    $dst,$src\t!ptr" %}
5102  ins_encode %{
5103    relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc();
5104    intptr_t val = $src$$constant;
5105    if (constant_reloc == relocInfo::oop_type) {
5106      __ mov_oop($dst$$Register, (jobject)val);
5107    } else if (constant_reloc == relocInfo::metadata_type) {
5108      __ mov_metadata($dst$$Register, (Metadata*)val);
5109    } else {
5110      __ mov_slow($dst$$Register, val);
5111    }
5112  %}
5113  ins_pipe(loadConP);
5114%}
5115
5116
5117instruct loadConP_poll(iRegP dst, immP_poll src) %{
5118  match(Set dst src);
5119  ins_cost(DEFAULT_COST);
5120  format %{ "MOV_SLOW    $dst,$src\t!ptr" %}
5121  ins_encode %{
5122      __ mov_slow($dst$$Register, $src$$constant);
5123  %}
5124  ins_pipe(loadConP_poll);
5125%}
5126
5127#ifdef AARCH64
5128instruct loadConP0(iRegP dst, immP0 src) %{
5129  match(Set dst src);
5130  ins_cost(DEFAULT_COST);
5131  format %{ "MOV    $dst,ZR\t!ptr" %}
5132  ins_encode %{
5133    __ mov($dst$$Register, ZR);
5134  %}
5135  ins_pipe(ialu_none);
5136%}
5137
5138instruct loadConN(iRegN dst, immN src) %{
5139  match(Set dst src);
5140  ins_cost(DEFAULT_COST * 3/2);
5141  format %{ "SET    $dst,$src\t! compressed ptr" %}
5142  ins_encode %{
5143    Register dst = $dst$$Register;
5144    // FIXME: use $constanttablebase?
5145    __ set_narrow_oop(dst, (jobject)$src$$constant);
5146  %}
5147  ins_pipe(ialu_hi_lo_reg);
5148%}
5149
5150instruct loadConN0(iRegN dst, immN0 src) %{
5151  match(Set dst src);
5152  ins_cost(DEFAULT_COST);
5153  format %{ "MOV    $dst,ZR\t! compressed ptr" %}
5154  ins_encode %{
5155    __ mov($dst$$Register, ZR);
5156  %}
5157  ins_pipe(ialu_none);
5158%}
5159
5160instruct loadConNKlass(iRegN dst, immNKlass src) %{
5161  match(Set dst src);
5162  ins_cost(DEFAULT_COST * 3/2);
5163  format %{ "SET    $dst,$src\t! compressed klass ptr" %}
5164  ins_encode %{
5165    Register dst = $dst$$Register;
5166    // FIXME: use $constanttablebase?
5167    __ set_narrow_klass(dst, (Klass*)$src$$constant);
5168  %}
5169  ins_pipe(ialu_hi_lo_reg);
5170%}
5171
5172instruct load_limmL(iRegL dst, limmL src) %{
5173  match(Set dst src);
5174  ins_cost(DEFAULT_COST);
5175  format %{ "ORR    $dst, ZR, $src\t! long"  %}
5176  ins_encode %{
5177    __ orr($dst$$Register, ZR, (uintx)$src$$constant);
5178  %}
5179  ins_pipe(loadConL);
5180%}
5181instruct load_immLMov(iRegL dst, immLMov src) %{
5182  match(Set dst src);
5183  ins_cost(DEFAULT_COST);
5184  format %{ "MOV    $dst, $src\t! long"  %}
5185  ins_encode %{
5186    __ mov($dst$$Register, $src$$constant);
5187  %}
5188  ins_pipe(loadConL);
5189%}
5190instruct loadConL(iRegL dst, immL src) %{
5191  match(Set dst src);
5192  ins_cost(DEFAULT_COST * 4); // worst case
5193  format %{ "mov_slow   $dst, $src\t! long"  %}
5194  ins_encode %{
5195    // FIXME: use $constanttablebase?
5196    __ mov_slow($dst$$Register, $src$$constant);
5197  %}
5198  ins_pipe(loadConL);
5199%}
5200#else
5201instruct loadConL(iRegL dst, immL src) %{
5202  match(Set dst src);
5203  ins_cost(DEFAULT_COST * 4);
5204  format %{ "MOV_SLOW   $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t"
5205            "MOV_SLOW   $dst.hi, $src >> 32" %}
5206  ins_encode %{
5207    __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL);
5208    __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32);
5209  %}
5210  ins_pipe(loadConL);
5211%}
5212
5213instruct loadConL16( iRegL dst, immL16 src ) %{
5214  match(Set dst src);
5215  ins_cost(DEFAULT_COST * 2);
5216
5217  size(8);
5218  format %{ "MOVW    $dst.lo, $src \n\t"
5219            "MOVW    $dst.hi, 0 \n\t" %}
5220  ins_encode %{
5221    __ movw($dst$$Register, $src$$constant);
5222    __ movw($dst$$Register->successor(), 0);
5223  %}
5224  ins_pipe(ialu_imm);
5225%}
5226#endif
5227
5228instruct loadConF_imm8(regF dst, imm8F src) %{
5229  match(Set dst src);
5230  ins_cost(DEFAULT_COST);
5231  size(4);
5232
5233  format %{ "FCONSTS      $dst, $src"%}
5234
5235  ins_encode %{
5236    __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8());
5237  %}
5238  ins_pipe(loadConFD); // FIXME
5239%}
5240
5241#ifdef AARCH64
5242instruct loadIConF(iRegI dst, immF src) %{
5243  match(Set dst src);
5244  ins_cost(DEFAULT_COST * 2);
5245
5246  format %{ "MOV_SLOW  $dst, $src\t! loadIConF"  %}
5247
5248  ins_encode %{
5249    // FIXME revisit once 6961697 is in
5250    union {
5251      jfloat f;
5252      int i;
5253    } v;
5254    v.f = $src$$constant;
5255    __ mov_slow($dst$$Register, v.i);
5256  %}
5257  ins_pipe(ialu_imm);
5258%}
5259#endif
5260
5261instruct loadConF(regF dst, immF src, iRegI tmp) %{
5262  match(Set dst src);
5263  ins_cost(DEFAULT_COST * 2);
5264  effect(TEMP tmp);
5265  size(3*4);
5266
5267  format %{ "MOV_SLOW  $tmp, $src\n\t"
5268            "FMSR      $dst, $tmp"%}
5269
5270  ins_encode %{
5271    // FIXME revisit once 6961697 is in
5272    union {
5273      jfloat f;
5274      int i;
5275    } v;
5276    v.f = $src$$constant;
5277    __ mov_slow($tmp$$Register, v.i);
5278    __ fmsr($dst$$FloatRegister, $tmp$$Register);
5279  %}
5280  ins_pipe(loadConFD); // FIXME
5281%}
5282
5283instruct loadConD_imm8(regD dst, imm8D src) %{
5284  match(Set dst src);
5285  ins_cost(DEFAULT_COST);
5286  size(4);
5287
5288  format %{ "FCONSTD      $dst, $src"%}
5289
5290  ins_encode %{
5291    __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8());
5292  %}
5293  ins_pipe(loadConFD); // FIXME
5294%}
5295
5296instruct loadConD(regD dst, immD src, iRegP tmp) %{
5297  match(Set dst src);
5298  effect(TEMP tmp);
5299  ins_cost(MEMORY_REF_COST);
5300  format %{ "FLDD  $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %}
5301
5302  ins_encode %{
5303    Register r = $constanttablebase;
5304    int offset  = $constantoffset($src);
5305    if (!is_memoryD(offset)) {                // can't use a predicate
5306                                              // in load constant instructs
5307      __ add_slow($tmp$$Register, r, offset);
5308      r = $tmp$$Register;
5309      offset = 0;
5310    }
5311    __ ldr_double($dst$$FloatRegister, Address(r, offset));
5312  %}
5313  ins_pipe(loadConFD);
5314%}
5315
5316// Prefetch instructions.
5317// Must be safe to execute with invalid address (cannot fault).
5318
5319instruct prefetchAlloc_mp( memoryP mem ) %{
5320  predicate(os::is_MP());
5321  match( PrefetchAllocation mem );
5322  ins_cost(MEMORY_REF_COST);
5323  size(4);
5324
5325  format %{ "PLDW $mem\t! Prefetch allocation" %}
5326  ins_encode %{
5327#ifdef AARCH64
5328    __ prfm(pstl1keep, $mem$$Address);
5329#else
5330    __ pldw($mem$$Address);
5331#endif
5332  %}
5333  ins_pipe(iload_mem);
5334%}
5335
5336instruct prefetchAlloc_sp( memoryP mem ) %{
5337  predicate(!os::is_MP());
5338  match( PrefetchAllocation mem );
5339  ins_cost(MEMORY_REF_COST);
5340  size(4);
5341
5342  format %{ "PLD $mem\t! Prefetch allocation" %}
5343  ins_encode %{
5344#ifdef AARCH64
5345    __ prfm(pstl1keep, $mem$$Address);
5346#else
5347    __ pld($mem$$Address);
5348#endif
5349  %}
5350  ins_pipe(iload_mem);
5351%}
5352
5353//----------Store Instructions-------------------------------------------------
5354// Store Byte
5355instruct storeB(memoryB mem, store_RegI src) %{
5356  match(Set mem (StoreB mem src));
5357  ins_cost(MEMORY_REF_COST);
5358
5359  size(4);
5360  format %{ "STRB    $src,$mem\t! byte" %}
5361  ins_encode %{
5362    __ strb($src$$Register, $mem$$Address);
5363  %}
5364  ins_pipe(istore_mem_reg);
5365%}
5366
5367instruct storeCM(memoryB mem, store_RegI src) %{
5368  match(Set mem (StoreCM mem src));
5369  ins_cost(MEMORY_REF_COST);
5370
5371  size(4);
5372  format %{ "STRB    $src,$mem\t! CMS card-mark byte" %}
5373  ins_encode %{
5374    __ strb($src$$Register, $mem$$Address);
5375  %}
5376  ins_pipe(istore_mem_reg);
5377%}
5378
5379// Store Char/Short
5380
5381#ifdef AARCH64
5382// XXX This variant shouldn't be necessary if 6217251 is implemented
5383instruct storeCoff(store_RegI src, memoryScaledS mem, aimmX off, iRegP tmp) %{
5384  match(Set mem (StoreC (AddP mem off) src));
5385  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5386  effect(TEMP tmp);
5387  size(4 * 2);
5388
5389  format %{ "STRH    $src,$mem+$off\t! short temp=$tmp" %}
5390  ins_encode %{
5391    Register base = reg_to_register_object($mem$$base);
5392    __ add($tmp$$Register, base, $off$$constant);
5393    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5394    __ strh($src$$Register, nmem);
5395  %}
5396  ins_pipe(istore_mem_reg);
5397%}
5398#endif
5399
5400instruct storeC(memoryS mem, store_RegI src) %{
5401  match(Set mem (StoreC mem src));
5402  ins_cost(MEMORY_REF_COST);
5403
5404  size(4);
5405  format %{ "STRH    $src,$mem\t! short" %}
5406  ins_encode %{
5407    __ strh($src$$Register, $mem$$Address);
5408  %}
5409  ins_pipe(istore_mem_reg);
5410%}
5411
5412// Store Integer
5413
5414#ifdef AARCH64
5415// XXX This variant shouldn't be necessary if 6217251 is implemented
5416instruct storeIoff(store_RegI src, memoryScaledI mem, aimmX off, iRegP tmp) %{
5417  match(Set mem (StoreI (AddP mem off) src));
5418  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5419  effect(TEMP tmp);
5420  size(4 * 2);
5421
5422  format %{ "str_32 $src,$mem+$off\t! int temp=$tmp" %}
5423  ins_encode %{
5424    Register base = reg_to_register_object($mem$$base);
5425    __ add($tmp$$Register, base, $off$$constant);
5426    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5427    __ str_32($src$$Register, nmem);
5428  %}
5429  ins_pipe(istore_mem_reg);
5430%}
5431#endif
5432
5433instruct storeI(memoryI mem, store_RegI src) %{
5434  match(Set mem (StoreI mem src));
5435  ins_cost(MEMORY_REF_COST);
5436
5437  size(4);
5438  format %{ "str_32 $src,$mem" %}
5439  ins_encode %{
5440    __ str_32($src$$Register, $mem$$Address);
5441  %}
5442  ins_pipe(istore_mem_reg);
5443%}
5444
5445// Store Long
5446
5447#ifdef AARCH64
5448// XXX This variant shouldn't be necessary if 6217251 is implemented
5449instruct storeLoff(store_RegLd src, memoryScaledL mem, aimmX off, iRegP tmp) %{
5450  match(Set mem (StoreL (AddP mem off) src));
5451  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5452  effect(TEMP tmp);
5453  size(4 * 2);
5454
5455  format %{ "str_64 $src,$mem+$off\t! long temp=$tmp" %}
5456  ins_encode %{
5457    Register base = reg_to_register_object($mem$$base);
5458    __ add($tmp$$Register, base, $off$$constant);
5459    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5460    __ str_64($src$$Register, nmem);
5461  %}
5462  ins_pipe(istore_mem_reg);
5463%}
5464#endif
5465
5466instruct storeL(memoryL mem, store_RegLd src) %{
5467#ifdef AARCH64
5468  // already atomic for Aarch64
5469#else
5470  predicate(!((StoreLNode*)n)->require_atomic_access());
5471#endif
5472  match(Set mem (StoreL mem src));
5473  ins_cost(MEMORY_REF_COST);
5474
5475  size(4);
5476  format %{ "str_64  $src,$mem\t! long\n\t" %}
5477
5478  ins_encode %{
5479    __ str_64($src$$Register, $mem$$Address);
5480  %}
5481  ins_pipe(istore_mem_reg);
5482%}
5483
5484#ifndef AARCH64
5485instruct storeL_2instr(memorylong mem, iRegL src) %{
5486  predicate(!((StoreLNode*)n)->require_atomic_access());
5487  match(Set mem (StoreL mem src));
5488  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
5489
5490  size(8);
5491  format %{ "STR    $src.lo,$mem\t! long\n\t"
5492            "STR    $src.hi,$mem+4" %}
5493
5494  ins_encode %{
5495    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5496    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
5497    __ str($src$$Register, Amemlo);
5498    __ str($src$$Register->successor(), Amemhi);
5499  %}
5500  ins_pipe(istore_mem_reg);
5501%}
5502
5503instruct storeL_volatile(indirect mem, iRegL src) %{
5504  predicate(((StoreLNode*)n)->require_atomic_access());
5505  match(Set mem (StoreL mem src));
5506  ins_cost(MEMORY_REF_COST);
5507  size(4);
5508  format %{ "STMIA    $src,$mem\t! long" %}
5509  ins_encode %{
5510    // FIXME: why is stmia considered atomic?  Should be strexd
5511    RegisterSet set($src$$Register);
5512    set = set | reg_to_register_object($src$$reg + 1);
5513    __ stmia(reg_to_register_object($mem$$base), set);
5514  %}
5515  ins_pipe(istore_mem_reg);
5516%}
5517#endif // !AARCH64
5518
5519#ifndef AARCH64
5520instruct storeL_volatile_fp(memoryD mem, iRegL src) %{
5521  predicate(((StoreLNode*)n)->require_atomic_access());
5522  match(Set mem (StoreL mem src));
5523  ins_cost(MEMORY_REF_COST);
5524  size(8);
5525  format %{ "FMDRR    S14, $src\t! long \n\t"
5526            "FSTD     S14, $mem" %}
5527  ins_encode %{
5528    __ fmdrr(S14, $src$$Register, $src$$Register->successor());
5529    __ fstd(S14, $mem$$Address);
5530  %}
5531  ins_pipe(istore_mem_reg);
5532%}
5533#endif
5534
5535#ifdef XXX
5536// Move SP Pointer
5537//instruct movSP(sp_ptr_RegP dst, SPRegP src) %{
5538//instruct movSP(iRegP dst, SPRegP src) %{
5539instruct movSP(store_ptr_RegP dst, SPRegP src) %{
5540  match(Set dst src);
5541//predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
5542  ins_cost(MEMORY_REF_COST);
5543  size(4);
5544
5545  format %{ "MOV    $dst,$src\t! SP ptr\n\t" %}
5546  ins_encode %{
5547    assert(false, "XXX1 got here");
5548    __ mov($dst$$Register, SP);
5549    __ mov($dst$$Register, $src$$Register);
5550  %}
5551  ins_pipe(ialu_reg);
5552%}
5553#endif
5554
5555#ifdef AARCH64
5556// FIXME
5557// Store SP Pointer
5558instruct storeSP(memoryP mem, SPRegP src, iRegP tmp) %{
5559  match(Set mem (StoreP mem src));
5560  predicate(_kids[1]->_leaf->is_Proj() && _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
5561  // Multiple StoreP rules, different only in register mask.
5562  // Matcher makes the last always valid.  The others will
5563  // only be valid if they cost less than the last valid
5564  // rule.  So cost(rule1) < cost(rule2) < cost(last)
5565  // Unlike immediates, register constraints are not checked
5566  // at match time.
5567  ins_cost(MEMORY_REF_COST+DEFAULT_COST+4);
5568  effect(TEMP tmp);
5569  size(8);
5570
5571  format %{ "MOV    $tmp,$src\t! SP ptr\n\t"
5572            "STR    $tmp,$mem\t! SP ptr" %}
5573  ins_encode %{
5574    assert($src$$Register == SP, "SP expected");
5575    __ mov($tmp$$Register, $src$$Register);
5576    __ str($tmp$$Register, $mem$$Address);
5577  %}
5578  ins_pipe(istore_mem_spORreg); // FIXME
5579%}
5580#endif // AARCH64
5581
5582// Store Pointer
5583
5584#ifdef AARCH64
5585// XXX This variant shouldn't be necessary if 6217251 is implemented
5586instruct storePoff(store_ptr_RegP src, memoryScaledP mem, aimmX off, iRegP tmp) %{
5587  predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con != TypeFunc::FramePtr);
5588  match(Set mem (StoreP (AddP mem off) src));
5589  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5590  effect(TEMP tmp);
5591  size(4 * 2);
5592
5593  format %{ "STR    $src,$mem+$off\t! ptr temp=$tmp" %}
5594  ins_encode %{
5595    Register base = reg_to_register_object($mem$$base);
5596    __ add($tmp$$Register, base, $off$$constant);
5597    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5598    __ str($src$$Register, nmem);
5599  %}
5600  ins_pipe(istore_mem_reg);
5601%}
5602#endif
5603
5604instruct storeP(memoryP mem, store_ptr_RegP src) %{
5605  match(Set mem (StoreP mem src));
5606#ifdef AARCH64
5607  predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con != TypeFunc::FramePtr);
5608#endif
5609  ins_cost(MEMORY_REF_COST);
5610  size(4);
5611
5612  format %{ "STR    $src,$mem\t! ptr" %}
5613  ins_encode %{
5614    __ str($src$$Register, $mem$$Address);
5615  %}
5616  ins_pipe(istore_mem_spORreg);
5617%}
5618
5619#ifdef AARCH64
5620// Store NULL Pointer
5621instruct storeP0(memoryP mem, immP0 src) %{
5622  match(Set mem (StoreP mem src));
5623  ins_cost(MEMORY_REF_COST);
5624  size(4);
5625
5626  format %{ "STR    ZR,$mem\t! ptr" %}
5627  ins_encode %{
5628    __ str(ZR, $mem$$Address);
5629  %}
5630  ins_pipe(istore_mem_spORreg);
5631%}
5632#endif // AARCH64
5633
5634#ifdef _LP64
5635// Store Compressed Pointer
5636
5637#ifdef AARCH64
5638// XXX This variant shouldn't be necessary if 6217251 is implemented
5639instruct storeNoff(store_RegN src, memoryScaledI mem, aimmX off, iRegP tmp) %{
5640  match(Set mem (StoreN (AddP mem off) src));
5641  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5642  effect(TEMP tmp);
5643  size(4 * 2);
5644
5645  format %{ "str_32 $src,$mem+$off\t! compressed ptr temp=$tmp" %}
5646  ins_encode %{
5647    Register base = reg_to_register_object($mem$$base);
5648    __ add($tmp$$Register, base, $off$$constant);
5649    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5650    __ str_32($src$$Register, nmem);
5651  %}
5652  ins_pipe(istore_mem_reg);
5653%}
5654#endif
5655
5656instruct storeN(memoryI mem, store_RegN src) %{
5657  match(Set mem (StoreN mem src));
5658  ins_cost(MEMORY_REF_COST);
5659  size(4);
5660
5661  format %{ "str_32 $src,$mem\t! compressed ptr" %}
5662  ins_encode %{
5663    __ str_32($src$$Register, $mem$$Address);
5664  %}
5665  ins_pipe(istore_mem_reg);
5666%}
5667
5668#ifdef AARCH64
5669// Store NULL Pointer
5670instruct storeN0(memoryI mem, immN0 src) %{
5671  match(Set mem (StoreN mem src));
5672  ins_cost(MEMORY_REF_COST);
5673  size(4);
5674
5675  format %{ "str_32 ZR,$mem\t! compressed ptr" %}
5676  ins_encode %{
5677    __ str_32(ZR, $mem$$Address);
5678  %}
5679  ins_pipe(istore_mem_reg);
5680%}
5681#endif
5682
5683// Store Compressed Klass Pointer
5684instruct storeNKlass(memoryI mem, store_RegN src) %{
5685  match(Set mem (StoreNKlass mem src));
5686  ins_cost(MEMORY_REF_COST);
5687  size(4);
5688
5689  format %{ "str_32 $src,$mem\t! compressed klass ptr" %}
5690  ins_encode %{
5691    __ str_32($src$$Register, $mem$$Address);
5692  %}
5693  ins_pipe(istore_mem_reg);
5694%}
5695#endif
5696
5697// Store Double
5698
5699#ifdef AARCH64
5700// XXX This variant shouldn't be necessary if 6217251 is implemented
5701instruct storeDoff(regD src, memoryScaledD mem, aimmX off, iRegP tmp) %{
5702  match(Set mem (StoreD (AddP mem off) src));
5703  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5704  effect(TEMP tmp);
5705  size(4 * 2);
5706
5707  format %{ "STR    $src,$mem+$off\t! double temp=$tmp" %}
5708  ins_encode %{
5709    Register base = reg_to_register_object($mem$$base);
5710    __ add($tmp$$Register, base, $off$$constant);
5711    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5712    __ str_d($src$$FloatRegister, nmem);
5713  %}
5714  ins_pipe(fstoreD_mem_reg);
5715%}
5716#endif
5717
5718instruct storeD(memoryD mem, regD src) %{
5719  match(Set mem (StoreD mem src));
5720  ins_cost(MEMORY_REF_COST);
5721
5722  size(4);
5723  // FIXME: needs to be atomic, but  ARMv7 A.R.M. guarantees
5724  // only LDREXD and STREXD are 64-bit single-copy atomic
5725  format %{ "FSTD   $src,$mem" %}
5726  ins_encode %{
5727    __ str_double($src$$FloatRegister, $mem$$Address);
5728  %}
5729  ins_pipe(fstoreD_mem_reg);
5730%}
5731
5732#ifdef AARCH64
5733instruct movI2F(regF dst, iRegI src) %{
5734  match(Set dst src);
5735  size(4);
5736
5737  format %{ "FMOV_sw $dst,$src\t! movI2F" %}
5738  ins_encode %{
5739    __ fmov_sw($dst$$FloatRegister, $src$$Register);
5740  %}
5741  ins_pipe(ialu_reg); // FIXME
5742%}
5743
5744instruct movF2I(iRegI dst, regF src) %{
5745  match(Set dst src);
5746  size(4);
5747
5748  format %{ "FMOV_ws $dst,$src\t! movF2I" %}
5749  ins_encode %{
5750    __ fmov_ws($dst$$Register, $src$$FloatRegister);
5751  %}
5752  ins_pipe(ialu_reg); // FIXME
5753%}
5754#endif
5755
5756// Store Float
5757
5758#ifdef AARCH64
5759// XXX This variant shouldn't be necessary if 6217251 is implemented
5760instruct storeFoff(regF src, memoryScaledF mem, aimmX off, iRegP tmp) %{
5761  match(Set mem (StoreF (AddP mem off) src));
5762  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
5763  effect(TEMP tmp);
5764  size(4 * 2);
5765
5766  format %{ "str_s  $src,$mem+$off\t! float temp=$tmp" %}
5767  ins_encode %{
5768    Register base = reg_to_register_object($mem$$base);
5769    __ add($tmp$$Register, base, $off$$constant);
5770    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
5771    __ str_s($src$$FloatRegister, nmem);
5772  %}
5773  ins_pipe(fstoreF_mem_reg);
5774%}
5775#endif
5776
5777instruct storeF( memoryF mem, regF src) %{
5778  match(Set mem (StoreF mem src));
5779  ins_cost(MEMORY_REF_COST);
5780
5781  size(4);
5782  format %{ "FSTS    $src,$mem" %}
5783  ins_encode %{
5784    __ str_float($src$$FloatRegister, $mem$$Address);
5785  %}
5786  ins_pipe(fstoreF_mem_reg);
5787%}
5788
5789#ifdef AARCH64
5790// Convert oop pointer into compressed form
5791instruct encodeHeapOop(iRegN dst, iRegP src, flagsReg ccr) %{
5792  predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
5793  match(Set dst (EncodeP src));
5794  effect(KILL ccr);
5795  format %{ "encode_heap_oop $dst, $src" %}
5796  ins_encode %{
5797    __ encode_heap_oop($dst$$Register, $src$$Register);
5798  %}
5799  ins_pipe(ialu_reg);
5800%}
5801
5802instruct encodeHeapOop_not_null(iRegN dst, iRegP src) %{
5803  predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull);
5804  match(Set dst (EncodeP src));
5805  format %{ "encode_heap_oop_not_null $dst, $src" %}
5806  ins_encode %{
5807    __ encode_heap_oop_not_null($dst$$Register, $src$$Register);
5808  %}
5809  ins_pipe(ialu_reg);
5810%}
5811
5812instruct decodeHeapOop(iRegP dst, iRegN src, flagsReg ccr) %{
5813  predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
5814            n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant);
5815  match(Set dst (DecodeN src));
5816  effect(KILL ccr);
5817  format %{ "decode_heap_oop $dst, $src" %}
5818  ins_encode %{
5819    __ decode_heap_oop($dst$$Register, $src$$Register);
5820  %}
5821  ins_pipe(ialu_reg);
5822%}
5823
5824instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{
5825  predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
5826            n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant);
5827  match(Set dst (DecodeN src));
5828  format %{ "decode_heap_oop_not_null $dst, $src" %}
5829  ins_encode %{
5830    __ decode_heap_oop_not_null($dst$$Register, $src$$Register);
5831  %}
5832  ins_pipe(ialu_reg);
5833%}
5834
5835instruct encodeKlass_not_null(iRegN dst, iRegP src) %{
5836  match(Set dst (EncodePKlass src));
5837  format %{ "encode_klass_not_null $dst, $src" %}
5838  ins_encode %{
5839    __ encode_klass_not_null($dst$$Register, $src$$Register);
5840  %}
5841  ins_pipe(ialu_reg);
5842%}
5843
5844instruct decodeKlass_not_null(iRegP dst, iRegN src) %{
5845  match(Set dst (DecodeNKlass src));
5846  format %{ "decode_klass_not_null $dst, $src" %}
5847  ins_encode %{
5848    __ decode_klass_not_null($dst$$Register, $src$$Register);
5849  %}
5850  ins_pipe(ialu_reg);
5851%}
5852#endif // AARCH64
5853
5854//----------MemBar Instructions-----------------------------------------------
5855// Memory barrier flavors
5856
5857// TODO: take advantage of Aarch64 load-acquire, store-release, etc
5858// pattern-match out unnecessary membars
5859instruct membar_storestore() %{
5860  match(MemBarStoreStore);
5861  ins_cost(4*MEMORY_REF_COST);
5862
5863  size(4);
5864  format %{ "MEMBAR-storestore" %}
5865  ins_encode %{
5866    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
5867  %}
5868  ins_pipe(long_memory_op);
5869%}
5870
5871instruct membar_acquire() %{
5872  match(MemBarAcquire);
5873  match(LoadFence);
5874  ins_cost(4*MEMORY_REF_COST);
5875
5876  size(4);
5877  format %{ "MEMBAR-acquire" %}
5878  ins_encode %{
5879    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg);
5880  %}
5881  ins_pipe(long_memory_op);
5882%}
5883
5884instruct membar_acquire_lock() %{
5885  match(MemBarAcquireLock);
5886  ins_cost(0);
5887
5888  size(0);
5889  format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %}
5890  ins_encode( );
5891  ins_pipe(empty);
5892%}
5893
5894instruct membar_release() %{
5895  match(MemBarRelease);
5896  match(StoreFence);
5897  ins_cost(4*MEMORY_REF_COST);
5898
5899  size(4);
5900  format %{ "MEMBAR-release" %}
5901  ins_encode %{
5902    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg);
5903  %}
5904  ins_pipe(long_memory_op);
5905%}
5906
5907instruct membar_release_lock() %{
5908  match(MemBarReleaseLock);
5909  ins_cost(0);
5910
5911  size(0);
5912  format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %}
5913  ins_encode( );
5914  ins_pipe(empty);
5915%}
5916
5917instruct membar_volatile() %{
5918  match(MemBarVolatile);
5919  ins_cost(4*MEMORY_REF_COST);
5920
5921  size(4);
5922  format %{ "MEMBAR-volatile" %}
5923  ins_encode %{
5924    __ membar(MacroAssembler::StoreLoad, noreg);
5925  %}
5926  ins_pipe(long_memory_op);
5927%}
5928
5929instruct unnecessary_membar_volatile() %{
5930  match(MemBarVolatile);
5931  predicate(Matcher::post_store_load_barrier(n));
5932  ins_cost(0);
5933
5934  size(0);
5935  format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %}
5936  ins_encode( );
5937  ins_pipe(empty);
5938%}
5939
5940//----------Register Move Instructions-----------------------------------------
5941// instruct roundDouble_nop(regD dst) %{
5942//   match(Set dst (RoundDouble dst));
5943//   ins_pipe(empty);
5944// %}
5945
5946
5947// instruct roundFloat_nop(regF dst) %{
5948//   match(Set dst (RoundFloat dst));
5949//   ins_pipe(empty);
5950// %}
5951
5952
5953#ifdef AARCH64
5954// 0 constant in register
5955instruct zrImmI0(ZRRegI dst, immI0 imm) %{
5956  match(Set dst imm);
5957  size(0);
5958  ins_cost(0);
5959
5960  format %{ "! ZR (int 0)" %}
5961  ins_encode( /*empty encoding*/ );
5962  ins_pipe(ialu_none);
5963%}
5964
5965// 0 constant in register
5966instruct zrImmL0(ZRRegL dst, immL0 imm) %{
5967  match(Set dst imm);
5968  size(0);
5969  ins_cost(0);
5970
5971  format %{ "! ZR (long 0)" %}
5972  ins_encode( /*empty encoding*/ );
5973  ins_pipe(ialu_none);
5974%}
5975
5976#ifdef XXX
5977// 0 constant in register
5978instruct zrImmN0(ZRRegN dst, immN0 imm) %{
5979  match(Set dst imm);
5980  size(0);
5981  ins_cost(0);
5982
5983  format %{ "! ZR (compressed pointer NULL)" %}
5984  ins_encode( /*empty encoding*/ );
5985  ins_pipe(ialu_none);
5986%}
5987
5988// 0 constant in register
5989instruct zrImmP0(ZRRegP dst, immP0 imm) %{
5990  match(Set dst imm);
5991  size(0);
5992  ins_cost(0);
5993
5994  format %{ "! ZR (NULL)" %}
5995  ins_encode( /*empty encoding*/ );
5996  ins_pipe(ialu_none);
5997%}
5998#endif
5999#endif // AARCH64
6000
6001// Cast Index to Pointer for unsafe natives
6002instruct castX2P(iRegX src, iRegP dst) %{
6003  match(Set dst (CastX2P src));
6004
6005  format %{ "MOV    $dst,$src\t! IntX->Ptr if $dst != $src" %}
6006  ins_encode %{
6007    if ($dst$$Register !=  $src$$Register) {
6008      __ mov($dst$$Register, $src$$Register);
6009    }
6010  %}
6011  ins_pipe(ialu_reg);
6012%}
6013
6014// Cast Pointer to Index for unsafe natives
6015instruct castP2X(iRegP src, iRegX dst) %{
6016  match(Set dst (CastP2X src));
6017
6018  format %{ "MOV    $dst,$src\t! Ptr->IntX if $dst != $src" %}
6019  ins_encode %{
6020    if ($dst$$Register !=  $src$$Register) {
6021      __ mov($dst$$Register, $src$$Register);
6022    }
6023  %}
6024  ins_pipe(ialu_reg);
6025%}
6026
6027#ifndef AARCH64
6028//----------Conditional Move---------------------------------------------------
6029// Conditional move
6030instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{
6031  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
6032  ins_cost(150);
6033  size(4);
6034  format %{ "MOV$cmp  $dst,$src\t! int" %}
6035  ins_encode %{
6036    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6037  %}
6038  ins_pipe(ialu_reg);
6039%}
6040#endif
6041
6042#ifdef AARCH64
6043instruct cmovI_reg3(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src1, iRegI src2) %{
6044  match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1)));
6045  ins_cost(150);
6046  size(4);
6047  format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %}
6048  ins_encode %{
6049    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6050  %}
6051  ins_pipe(ialu_reg);
6052%}
6053
6054instruct cmovL_reg3(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src1, iRegL src2) %{
6055  match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1)));
6056  ins_cost(150);
6057  size(4);
6058  format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %}
6059  ins_encode %{
6060    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6061  %}
6062  ins_pipe(ialu_reg);
6063%}
6064
6065instruct cmovP_reg3(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src1, iRegP src2) %{
6066  match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1)));
6067  ins_cost(150);
6068  size(4);
6069  format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %}
6070  ins_encode %{
6071    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6072  %}
6073  ins_pipe(ialu_reg);
6074%}
6075
6076instruct cmovN_reg3(cmpOp cmp, flagsReg icc, iRegN dst, iRegN src1, iRegN src2) %{
6077  match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1)));
6078  ins_cost(150);
6079  size(4);
6080  format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %}
6081  ins_encode %{
6082    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6083  %}
6084  ins_pipe(ialu_reg);
6085%}
6086
6087instruct cmovIP_reg3(cmpOpP cmp, flagsRegP icc, iRegI dst, iRegI src1, iRegI src2) %{
6088  match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1)));
6089  ins_cost(150);
6090  size(4);
6091  format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %}
6092  ins_encode %{
6093    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6094  %}
6095  ins_pipe(ialu_reg);
6096%}
6097
6098instruct cmovLP_reg3(cmpOpP cmp, flagsRegP icc, iRegL dst, iRegL src1, iRegL src2) %{
6099  match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1)));
6100  ins_cost(150);
6101  size(4);
6102  format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %}
6103  ins_encode %{
6104    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6105  %}
6106  ins_pipe(ialu_reg);
6107%}
6108
6109instruct cmovPP_reg3(cmpOpP cmp, flagsRegP icc, iRegP dst, iRegP src1, iRegP src2) %{
6110  match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1)));
6111  ins_cost(150);
6112  size(4);
6113  format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %}
6114  ins_encode %{
6115    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6116  %}
6117  ins_pipe(ialu_reg);
6118%}
6119
6120instruct cmovNP_reg3(cmpOpP cmp, flagsRegP icc, iRegN dst, iRegN src1, iRegN src2) %{
6121  match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1)));
6122  ins_cost(150);
6123  size(4);
6124  format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %}
6125  ins_encode %{
6126    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6127  %}
6128  ins_pipe(ialu_reg);
6129%}
6130
6131instruct cmovIU_reg3(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src1, iRegI src2) %{
6132  match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1)));
6133  ins_cost(150);
6134  size(4);
6135  format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %}
6136  ins_encode %{
6137    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6138  %}
6139  ins_pipe(ialu_reg);
6140%}
6141
6142instruct cmovLU_reg3(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src1, iRegL src2) %{
6143  match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1)));
6144  ins_cost(150);
6145  size(4);
6146  format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %}
6147  ins_encode %{
6148    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6149  %}
6150  ins_pipe(ialu_reg);
6151%}
6152
6153instruct cmovPU_reg3(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src1, iRegP src2) %{
6154  match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1)));
6155  ins_cost(150);
6156  size(4);
6157  format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %}
6158  ins_encode %{
6159    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6160  %}
6161  ins_pipe(ialu_reg);
6162%}
6163
6164instruct cmovNU_reg3(cmpOpU cmp, flagsRegU icc, iRegN dst, iRegN src1, iRegN src2) %{
6165  match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1)));
6166  ins_cost(150);
6167  size(4);
6168  format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %}
6169  ins_encode %{
6170    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6171  %}
6172  ins_pipe(ialu_reg);
6173%}
6174
6175instruct cmovIZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src1, iRegI src2) %{
6176  match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1)));
6177  ins_cost(150);
6178  size(4);
6179  format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %}
6180  ins_encode %{
6181    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6182  %}
6183  ins_pipe(ialu_reg);
6184%}
6185
6186instruct cmovLZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src1, iRegL src2) %{
6187  match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1)));
6188  ins_cost(150);
6189  size(4);
6190  format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %}
6191  ins_encode %{
6192    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6193  %}
6194  ins_pipe(ialu_reg);
6195%}
6196
6197instruct cmovPZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src1, iRegP src2) %{
6198  match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1)));
6199  ins_cost(150);
6200  size(4);
6201  format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %}
6202  ins_encode %{
6203    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6204  %}
6205  ins_pipe(ialu_reg);
6206%}
6207
6208instruct cmovNZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegN dst, iRegN src1, iRegN src2) %{
6209  match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1)));
6210  ins_cost(150);
6211  size(4);
6212  format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %}
6213  ins_encode %{
6214    __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode));
6215  %}
6216  ins_pipe(ialu_reg);
6217%}
6218#endif // AARCH64
6219
6220#ifndef AARCH64
6221instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{
6222  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
6223  ins_cost(140);
6224  size(4);
6225  format %{ "MOV$cmp  $dst,$src" %}
6226  ins_encode %{
6227    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6228  %}
6229  ins_pipe(ialu_imm);
6230%}
6231
6232instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{
6233  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
6234  ins_cost(140);
6235  size(4);
6236  format %{ "MOVw$cmp  $dst,$src" %}
6237  ins_encode %{
6238    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6239  %}
6240  ins_pipe(ialu_imm);
6241%}
6242#endif
6243
6244instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{
6245  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6246  ins_cost(150);
6247  size(4);
6248  format %{ "MOV$cmp  $dst,$src" %}
6249  ins_encode %{
6250    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6251  %}
6252  ins_pipe(ialu_reg);
6253%}
6254
6255#ifdef AARCH64
6256instruct cmovL_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
6257  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6258  ins_cost(150);
6259  size(4);
6260  format %{ "MOV$cmp  $dst,$src\t! long" %}
6261  ins_encode %{
6262    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6263  %}
6264  ins_pipe(ialu_reg);
6265%}
6266#endif
6267
6268#ifndef AARCH64
6269instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{
6270  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6271  ins_cost(140);
6272  size(4);
6273  format %{ "MOV$cmp  $dst,$src" %}
6274  ins_encode %{
6275    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6276  %}
6277  ins_pipe(ialu_imm);
6278%}
6279
6280instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{
6281  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6282  ins_cost(140);
6283  size(4);
6284  format %{ "MOVw$cmp  $dst,$src" %}
6285  ins_encode %{
6286    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6287  %}
6288  ins_pipe(ialu_imm);
6289%}
6290#endif
6291
6292instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{
6293  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6294  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6295            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6296            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6297            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6298  ins_cost(150);
6299  size(4);
6300  format %{ "MOV$cmp  $dst,$src" %}
6301  ins_encode %{
6302    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6303  %}
6304  ins_pipe(ialu_reg);
6305%}
6306
6307#ifndef AARCH64
6308instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{
6309  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6310  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6311            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6312            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6313            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6314  ins_cost(140);
6315  size(4);
6316  format %{ "MOV$cmp  $dst,$src" %}
6317  ins_encode %{
6318    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6319  %}
6320  ins_pipe(ialu_imm);
6321%}
6322
6323instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{
6324  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6325  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6326            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6327            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6328            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6329  ins_cost(140);
6330  size(4);
6331  format %{ "MOVW$cmp  $dst,$src" %}
6332  ins_encode %{
6333    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6334  %}
6335  ins_pipe(ialu_imm);
6336%}
6337#endif
6338
6339instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
6340  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6341  ins_cost(150);
6342  size(4);
6343  format %{ "MOV$cmp  $dst,$src" %}
6344  ins_encode %{
6345    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6346  %}
6347  ins_pipe(ialu_reg);
6348%}
6349
6350#ifndef AARCH64
6351instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{
6352  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6353  ins_cost(140);
6354  size(4);
6355  format %{ "MOV$cmp  $dst,$src" %}
6356  ins_encode %{
6357    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6358  %}
6359  ins_pipe(ialu_imm);
6360%}
6361
6362instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{
6363  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
6364  ins_cost(140);
6365  size(4);
6366  format %{ "MOVW$cmp  $dst,$src" %}
6367  ins_encode %{
6368    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6369  %}
6370  ins_pipe(ialu_imm);
6371%}
6372#endif
6373
6374// Conditional move
6375instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
6376  match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
6377  ins_cost(150);
6378  size(4);
6379  format %{ "MOV$cmp  $dst,$src" %}
6380  ins_encode %{
6381    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6382  %}
6383  ins_pipe(ialu_reg);
6384%}
6385
6386instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{
6387  match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
6388  ins_cost(140);
6389  size(4);
6390#ifdef AARCH64
6391  format %{ "MOV$cmp  $dst,ZR" %}
6392#else
6393  format %{ "MOV$cmp  $dst,$src" %}
6394#endif
6395  ins_encode %{
6396#ifdef AARCH64
6397    __ mov($dst$$Register,             ZR, (AsmCondition)($cmp$$cmpcode));
6398#else
6399    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6400#endif
6401  %}
6402  ins_pipe(ialu_imm);
6403%}
6404
6405// This instruction also works with CmpN so we don't need cmovPN_reg.
6406instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
6407  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
6408  ins_cost(150);
6409
6410  size(4);
6411  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
6412  ins_encode %{
6413    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6414  %}
6415  ins_pipe(ialu_reg);
6416%}
6417
6418instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{
6419  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
6420  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6421            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6422            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6423            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6424  ins_cost(150);
6425
6426  size(4);
6427  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
6428  ins_encode %{
6429    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6430  %}
6431  ins_pipe(ialu_reg);
6432%}
6433
6434instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
6435  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
6436  ins_cost(150);
6437
6438  size(4);
6439  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
6440  ins_encode %{
6441    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6442  %}
6443  ins_pipe(ialu_reg);
6444%}
6445
6446instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
6447  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
6448  ins_cost(140);
6449
6450  size(4);
6451#ifdef AARCH64
6452  format %{ "MOV$cmp  $dst,ZR\t! ptr" %}
6453#else
6454  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
6455#endif
6456  ins_encode %{
6457#ifdef AARCH64
6458    __ mov($dst$$Register,             ZR, (AsmCondition)($cmp$$cmpcode));
6459#else
6460    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6461#endif
6462  %}
6463  ins_pipe(ialu_imm);
6464%}
6465
6466instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{
6467  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
6468  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6469            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6470            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6471            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6472  ins_cost(140);
6473
6474  size(4);
6475#ifdef AARCH64
6476  format %{ "MOV$cmp  $dst,ZR\t! ptr" %}
6477#else
6478  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
6479#endif
6480  ins_encode %{
6481#ifdef AARCH64
6482    __ mov($dst$$Register,             ZR, (AsmCondition)($cmp$$cmpcode));
6483#else
6484    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6485#endif
6486  %}
6487  ins_pipe(ialu_imm);
6488%}
6489
6490instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
6491  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
6492  ins_cost(140);
6493
6494  size(4);
6495#ifdef AARCH64
6496  format %{ "MOV$cmp  $dst,ZR\t! ptr" %}
6497#else
6498  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
6499#endif
6500  ins_encode %{
6501#ifdef AARCH64
6502    __ mov($dst$$Register,             ZR, (AsmCondition)($cmp$$cmpcode));
6503#else
6504    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6505#endif
6506  %}
6507  ins_pipe(ialu_imm);
6508%}
6509
6510#ifdef AARCH64
6511// Conditional move
6512instruct cmovF_reg(cmpOp cmp, flagsReg icc, regF dst, regF src1, regF src2) %{
6513  match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1)));
6514  ins_cost(150);
6515  size(4);
6516  format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %}
6517  ins_encode %{
6518    __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6519  %}
6520  ins_pipe(int_conditional_float_move);
6521%}
6522
6523instruct cmovD_reg(cmpOp cmp, flagsReg icc, regD dst, regD src1, regD src2) %{
6524  match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1)));
6525  ins_cost(150);
6526  size(4);
6527  format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %}
6528  ins_encode %{
6529    __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6530  %}
6531  ins_pipe(int_conditional_float_move);
6532%}
6533
6534instruct cmovFP_reg(cmpOpP cmp, flagsRegP icc, regF dst, regF src1, regF src2) %{
6535  match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1)));
6536  ins_cost(150);
6537  size(4);
6538  format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %}
6539  ins_encode %{
6540    __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6541  %}
6542  ins_pipe(int_conditional_float_move);
6543%}
6544
6545instruct cmovDP_reg(cmpOpP cmp, flagsRegP icc, regD dst, regD src1, regD src2) %{
6546  match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1)));
6547  ins_cost(150);
6548  size(4);
6549  format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %}
6550  ins_encode %{
6551    __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6552  %}
6553  ins_pipe(int_conditional_float_move);
6554%}
6555
6556instruct cmovFU_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src1, regF src2) %{
6557  match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1)));
6558  ins_cost(150);
6559  size(4);
6560  format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %}
6561  ins_encode %{
6562    __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6563  %}
6564  ins_pipe(int_conditional_float_move);
6565%}
6566
6567instruct cmovDU_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src1, regD src2) %{
6568  match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1)));
6569  ins_cost(150);
6570  size(4);
6571  format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %}
6572  ins_encode %{
6573    __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6574  %}
6575  ins_pipe(int_conditional_float_move);
6576%}
6577
6578instruct cmovFZ_reg(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src1, regF src2) %{
6579  match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1)));
6580  ins_cost(150);
6581  size(4);
6582  format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %}
6583  ins_encode %{
6584    __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6585  %}
6586  ins_pipe(int_conditional_float_move);
6587%}
6588
6589instruct cmovDZ_reg(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src1, regD src2) %{
6590  match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1)));
6591  ins_cost(150);
6592  size(4);
6593  format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %}
6594  ins_encode %{
6595    __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6596  %}
6597  ins_pipe(int_conditional_float_move);
6598%}
6599
6600#else // !AARCH64
6601
6602// Conditional move
6603instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{
6604  match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src)));
6605  ins_cost(150);
6606  size(4);
6607  format %{ "FCPYS$cmp $dst,$src" %}
6608  ins_encode %{
6609    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6610  %}
6611  ins_pipe(int_conditional_float_move);
6612%}
6613
6614instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
6615  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
6616  ins_cost(150);
6617
6618  size(4);
6619  format %{ "FCPYS$cmp $dst,$src" %}
6620  ins_encode %{
6621    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6622  %}
6623  ins_pipe(int_conditional_float_move);
6624%}
6625
6626instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{
6627  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
6628  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6629            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6630            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6631            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6632  ins_cost(150);
6633
6634  size(4);
6635  format %{ "FCPYS$cmp $dst,$src" %}
6636  ins_encode %{
6637    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6638  %}
6639  ins_pipe(int_conditional_float_move);
6640%}
6641
6642instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
6643  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
6644  ins_cost(150);
6645
6646  size(4);
6647  format %{ "FCPYS$cmp $dst,$src" %}
6648  ins_encode %{
6649    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6650  %}
6651  ins_pipe(int_conditional_float_move);
6652%}
6653
6654// Conditional move
6655instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{
6656  match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src)));
6657  ins_cost(150);
6658  size(4);
6659  format %{ "FCPYD$cmp $dst,$src" %}
6660  ins_encode %{
6661    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6662  %}
6663  ins_pipe(int_conditional_double_move);
6664%}
6665
6666instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
6667  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
6668  ins_cost(150);
6669
6670  size(4);
6671  format %{ "FCPYD$cmp $dst,$src" %}
6672  ins_encode %{
6673    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6674  %}
6675  ins_pipe(int_conditional_double_move);
6676%}
6677
6678instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{
6679  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
6680  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);
6681  ins_cost(150);
6682
6683  size(4);
6684  format %{ "FCPYD$cmp $dst,$src" %}
6685  ins_encode %{
6686    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6687  %}
6688  ins_pipe(int_conditional_double_move);
6689%}
6690
6691instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
6692  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
6693  ins_cost(150);
6694
6695  size(4);
6696  format %{ "FCPYD$cmp $dst,$src" %}
6697  ins_encode %{
6698    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
6699  %}
6700  ins_pipe(int_conditional_double_move);
6701%}
6702
6703// Conditional move
6704instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{
6705  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
6706  ins_cost(150);
6707
6708  size(8);
6709  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
6710            "MOV$cmp  $dst.hi,$src.hi" %}
6711  ins_encode %{
6712    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6713    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
6714  %}
6715  ins_pipe(ialu_reg);
6716%}
6717
6718// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6719// (hi($con$$constant), lo($con$$constant)) becomes
6720instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{
6721  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
6722  ins_cost(140);
6723
6724  size(8);
6725  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
6726            "MOV$cmp  $dst.hi,0" %}
6727  ins_encode %{
6728    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6729    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
6730  %}
6731  ins_pipe(ialu_imm);
6732%}
6733
6734instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{
6735  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
6736  ins_cost(140);
6737
6738  size(8);
6739  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
6740            "MOV$cmp  $dst.hi,0" %}
6741  ins_encode %{
6742    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6743    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
6744  %}
6745  ins_pipe(ialu_imm);
6746%}
6747
6748instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
6749  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6750  ins_cost(150);
6751
6752  size(8);
6753  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
6754            "MOV$cmp  $dst.hi,$src.hi" %}
6755  ins_encode %{
6756    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6757    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
6758  %}
6759  ins_pipe(ialu_reg);
6760%}
6761
6762instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{
6763  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6764  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6765            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6766            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6767            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6768  ins_cost(150);
6769
6770  size(8);
6771  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
6772            "MOV$cmp  $dst.hi,$src.hi" %}
6773  ins_encode %{
6774    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6775    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
6776  %}
6777  ins_pipe(ialu_reg);
6778%}
6779
6780// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6781// (hi($con$$constant), lo($con$$constant)) becomes
6782instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{
6783  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6784  ins_cost(140);
6785
6786  size(8);
6787  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
6788            "MOV$cmp  $dst.hi,0" %}
6789  ins_encode %{
6790    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6791    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
6792  %}
6793  ins_pipe(ialu_imm);
6794%}
6795
6796// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6797// (hi($con$$constant), lo($con$$constant)) becomes
6798instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{
6799  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6800  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6801            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6802            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6803            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6804  ins_cost(140);
6805
6806  size(8);
6807  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
6808            "MOV$cmp  $dst.hi,0" %}
6809  ins_encode %{
6810    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6811    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
6812  %}
6813  ins_pipe(ialu_imm);
6814%}
6815
6816instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{
6817  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6818  ins_cost(140);
6819
6820  size(8);
6821  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
6822            "MOV$cmp  $dst.hi,0" %}
6823  ins_encode %{
6824    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6825    __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
6826  %}
6827  ins_pipe(ialu_imm);
6828%}
6829
6830instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{
6831  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6832  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
6833            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
6834            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
6835            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
6836  ins_cost(140);
6837
6838  size(8);
6839  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
6840            "MOV$cmp  $dst.hi,0" %}
6841  ins_encode %{
6842    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
6843    __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
6844  %}
6845  ins_pipe(ialu_imm);
6846%}
6847
6848instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
6849  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
6850  ins_cost(150);
6851
6852  size(8);
6853  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
6854            "MOV$cmp  $dst.hi,$src.hi" %}
6855  ins_encode %{
6856    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
6857    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
6858  %}
6859  ins_pipe(ialu_reg);
6860%}
6861#endif // !AARCH64
6862
6863
6864//----------OS and Locking Instructions----------------------------------------
6865
6866// This name is KNOWN by the ADLC and cannot be changed.
6867// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
6868// for this guy.
6869instruct tlsLoadP(RthreadRegP dst) %{
6870  match(Set dst (ThreadLocal));
6871
6872  size(0);
6873  ins_cost(0);
6874  format %{ "! TLS is in $dst" %}
6875  ins_encode( /*empty encoding*/ );
6876  ins_pipe(ialu_none);
6877%}
6878
6879instruct checkCastPP( iRegP dst ) %{
6880  match(Set dst (CheckCastPP dst));
6881
6882  size(0);
6883  format %{ "! checkcastPP of $dst" %}
6884  ins_encode( /*empty encoding*/ );
6885  ins_pipe(empty);
6886%}
6887
6888
6889instruct castPP( iRegP dst ) %{
6890  match(Set dst (CastPP dst));
6891  format %{ "! castPP of $dst" %}
6892  ins_encode( /*empty encoding*/ );
6893  ins_pipe(empty);
6894%}
6895
6896instruct castII( iRegI dst ) %{
6897  match(Set dst (CastII dst));
6898  format %{ "! castII of $dst" %}
6899  ins_encode( /*empty encoding*/ );
6900  ins_cost(0);
6901  ins_pipe(empty);
6902%}
6903
6904//----------Arithmetic Instructions--------------------------------------------
6905// Addition Instructions
6906// Register Addition
6907instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6908  match(Set dst (AddI src1 src2));
6909
6910  size(4);
6911  format %{ "add_32 $dst,$src1,$src2\t! int" %}
6912  ins_encode %{
6913    __ add_32($dst$$Register, $src1$$Register, $src2$$Register);
6914  %}
6915  ins_pipe(ialu_reg_reg);
6916%}
6917
6918#ifndef AARCH64
6919instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6920  match(Set dst (AddI (LShiftI src1 src2) src3));
6921
6922  size(4);
6923  format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
6924  ins_encode %{
6925    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6926  %}
6927  ins_pipe(ialu_reg_reg);
6928%}
6929#endif
6930
6931#ifdef AARCH64
6932#ifdef TODO
6933instruct addshlL_reg_imm_reg(iRegL dst, iRegL src1, immU6 src2, iRegL src3) %{
6934  match(Set dst (AddL (LShiftL src1 src2) src3));
6935
6936  size(4);
6937  format %{ "ADD    $dst,$src3,$src1<<$src2\t! long" %}
6938  ins_encode %{
6939    __ add($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6940  %}
6941  ins_pipe(ialu_reg_reg);
6942%}
6943#endif
6944#endif
6945
6946instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
6947  match(Set dst (AddI (LShiftI src1 src2) src3));
6948
6949  size(4);
6950  format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
6951  ins_encode %{
6952    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6953  %}
6954  ins_pipe(ialu_reg_reg);
6955%}
6956
6957#ifndef AARCH64
6958instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6959  match(Set dst (AddI (RShiftI src1 src2) src3));
6960
6961  size(4);
6962  format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
6963  ins_encode %{
6964    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
6965  %}
6966  ins_pipe(ialu_reg_reg);
6967%}
6968#endif
6969
6970instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
6971  match(Set dst (AddI (RShiftI src1 src2) src3));
6972
6973  size(4);
6974  format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
6975  ins_encode %{
6976    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
6977  %}
6978  ins_pipe(ialu_reg_reg);
6979%}
6980
6981#ifndef AARCH64
6982instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6983  match(Set dst (AddI (URShiftI src1 src2) src3));
6984
6985  size(4);
6986  format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
6987  ins_encode %{
6988    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6989  %}
6990  ins_pipe(ialu_reg_reg);
6991%}
6992#endif
6993
6994instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
6995  match(Set dst (AddI (URShiftI src1 src2) src3));
6996
6997  size(4);
6998  format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
6999  ins_encode %{
7000    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
7001  %}
7002  ins_pipe(ialu_reg_reg);
7003%}
7004
7005// Immediate Addition
7006instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
7007  match(Set dst (AddI src1 src2));
7008
7009  size(4);
7010  format %{ "add_32 $dst,$src1,$src2\t! int" %}
7011  ins_encode %{
7012    __ add_32($dst$$Register, $src1$$Register, $src2$$constant);
7013  %}
7014  ins_pipe(ialu_reg_imm);
7015%}
7016
7017// Pointer Register Addition
7018instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{
7019  match(Set dst (AddP src1 src2));
7020
7021  size(4);
7022  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
7023  ins_encode %{
7024    __ add($dst$$Register, $src1$$Register, $src2$$Register);
7025  %}
7026  ins_pipe(ialu_reg_reg);
7027%}
7028
7029#ifdef AARCH64
7030// unshifted I2L operand
7031operand unshiftedI2L(iRegI src2) %{
7032//constraint(ALLOC_IN_RC(sp_ptr_reg));
7033  match(ConvI2L src2);
7034
7035  op_cost(1);
7036  format %{ "$src2.w" %}
7037  interface(MEMORY_INTER) %{
7038    base($src2);
7039    index(0xff);
7040    scale(0x0);
7041    disp(0x0);
7042  %}
7043%}
7044
7045// shifted I2L operand
7046operand shiftedI2L(iRegI src2, immI_0_4 src3) %{
7047//constraint(ALLOC_IN_RC(sp_ptr_reg));
7048  match(LShiftX (ConvI2L src2) src3);
7049
7050  op_cost(1);
7051  format %{ "$src2.w << $src3" %}
7052  interface(MEMORY_INTER) %{
7053    base($src2);
7054    index(0xff);
7055    scale($src3);
7056    disp(0x0);
7057  %}
7058%}
7059
7060opclass shiftedRegI(shiftedI2L, unshiftedI2L);
7061
7062instruct shlL_reg_regI(iRegL dst, iRegI src1, immU6 src2) %{
7063  match(Set dst (LShiftL (ConvI2L src1) src2));
7064
7065  size(4);
7066  format %{ "LSL    $dst,$src1.w,$src2\t! ptr" %}
7067  ins_encode %{
7068    int c = $src2$$constant;
7069    int r = 64 - c;
7070    int s = 31;
7071    if (s >= r) {
7072      s = r - 1;
7073    }
7074    __ sbfm($dst$$Register, $src1$$Register, r, s);
7075  %}
7076  ins_pipe(ialu_reg_reg);
7077%}
7078
7079instruct addP_reg_regI(iRegP dst, iRegP src1, shiftedRegI src2) %{
7080  match(Set dst (AddP src1 src2));
7081
7082  ins_cost(DEFAULT_COST * 3/2);
7083  size(4);
7084  format %{ "ADD    $dst,$src1,$src2, sxtw\t! ptr" %}
7085  ins_encode %{
7086    Register base = reg_to_register_object($src2$$base);
7087    __ add($dst$$Register, $src1$$Register, base, ex_sxtw, $src2$$scale);
7088  %}
7089  ins_pipe(ialu_reg_reg);
7090%}
7091#endif
7092
7093// shifted iRegX operand
7094operand shiftedX(iRegX src2, shimmX src3) %{
7095//constraint(ALLOC_IN_RC(sp_ptr_reg));
7096  match(LShiftX src2 src3);
7097
7098  op_cost(1);
7099  format %{ "$src2 << $src3" %}
7100  interface(MEMORY_INTER) %{
7101    base($src2);
7102    index(0xff);
7103    scale($src3);
7104    disp(0x0);
7105  %}
7106%}
7107
7108instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{
7109  match(Set dst (AddP src1 src2));
7110
7111  ins_cost(DEFAULT_COST * 3/2);
7112  size(4);
7113  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
7114  ins_encode %{
7115    Register base = reg_to_register_object($src2$$base);
7116    __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale));
7117  %}
7118  ins_pipe(ialu_reg_reg);
7119%}
7120
7121// Pointer Immediate Addition
7122instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{
7123  match(Set dst (AddP src1 src2));
7124
7125  size(4);
7126  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
7127  ins_encode %{
7128    __ add($dst$$Register, $src1$$Register, $src2$$constant);
7129  %}
7130  ins_pipe(ialu_reg_imm);
7131%}
7132
7133// Long Addition
7134#ifdef AARCH64
7135instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
7136  match(Set dst (AddL src1 src2));
7137  size(4);
7138  format %{ "ADD     $dst,$src1,$src2\t! long" %}
7139  ins_encode %{
7140    __ add($dst$$Register, $src1$$Register, $src2$$Register);
7141  %}
7142  ins_pipe(ialu_reg_reg);
7143%}
7144
7145instruct addL_reg_regI(iRegL dst, iRegL src1, shiftedRegI src2) %{
7146  match(Set dst (AddL src1 src2));
7147
7148  ins_cost(DEFAULT_COST * 3/2);
7149  size(4);
7150  format %{ "ADD    $dst,$src1,$src2, sxtw\t! long" %}
7151  ins_encode %{
7152    Register base = reg_to_register_object($src2$$base);
7153    __ add($dst$$Register, $src1$$Register, base, ex_sxtw, $src2$$scale);
7154  %}
7155  ins_pipe(ialu_reg_reg);
7156%}
7157#else
7158instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{
7159  match(Set dst (AddL src1 src2));
7160  effect(KILL ccr);
7161  size(8);
7162  format %{ "ADDS    $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
7163            "ADC     $dst.hi,$src1.hi,$src2.hi" %}
7164  ins_encode %{
7165    __ adds($dst$$Register, $src1$$Register, $src2$$Register);
7166    __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
7167  %}
7168  ins_pipe(ialu_reg_reg);
7169%}
7170#endif
7171
7172#ifdef AARCH64
7173// Immediate Addition
7174instruct addL_reg_aimm(iRegL dst, iRegL src1, aimmL src2) %{
7175  match(Set dst (AddL src1 src2));
7176
7177  size(4);
7178  format %{ "ADD    $dst,$src1,$src2\t! long" %}
7179  ins_encode %{
7180    __ add($dst$$Register, $src1$$Register, $src2$$constant);
7181  %}
7182  ins_pipe(ialu_reg_imm);
7183%}
7184
7185instruct addL_reg_immLneg(iRegL dst, iRegL src1, aimmLneg src2) %{
7186  match(Set dst (SubL src1 src2));
7187
7188  size(4);
7189  format %{ "ADD    $dst,$src1,-($src2)\t! long" %}
7190  ins_encode %{
7191    __ add($dst$$Register, $src1$$Register, -$src2$$constant);
7192  %}
7193  ins_pipe(ialu_reg_imm);
7194%}
7195#else
7196// TODO
7197#endif
7198
7199#ifndef AARCH64
7200// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7201// (hi($con$$constant), lo($con$$constant)) becomes
7202instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
7203  match(Set dst (AddL src1 con));
7204  effect(KILL ccr);
7205  size(8);
7206  format %{ "ADDS    $dst.lo,$src1.lo,$con\t! long\n\t"
7207            "ADC     $dst.hi,$src1.hi,0" %}
7208  ins_encode %{
7209    __ adds($dst$$Register, $src1$$Register, $con$$constant);
7210    __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0);
7211  %}
7212  ins_pipe(ialu_reg_imm);
7213%}
7214#endif
7215
7216//----------Conditional_store--------------------------------------------------
7217// Conditional-store of the updated heap-top.
7218// Used during allocation of the shared heap.
7219// Sets flags (EQ) on success.
7220
7221// TODO: optimize out barriers with AArch64 load-acquire/store-release
7222// LoadP-locked.
7223instruct loadPLocked(iRegP dst, memoryex mem) %{
7224  match(Set dst (LoadPLocked mem));
7225  size(4);
7226  format %{ "LDREX  $dst,$mem" %}
7227  ins_encode %{
7228#ifdef AARCH64
7229    Register base = reg_to_register_object($mem$$base);
7230    __ ldxr($dst$$Register, base);
7231#else
7232    __ ldrex($dst$$Register,$mem$$Address);
7233#endif
7234  %}
7235  ins_pipe(iload_mem);
7236%}
7237
7238instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{
7239  predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node
7240  match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval)));
7241  effect( TEMP tmp );
7242  size(8);
7243  format %{ "STREX  $tmp,$newval,$heap_top_ptr\n\t"
7244            "CMP    $tmp, 0" %}
7245  ins_encode %{
7246#ifdef AARCH64
7247    Register base = reg_to_register_object($heap_top_ptr$$base);
7248    __ stxr($tmp$$Register, $newval$$Register, base);
7249#else
7250    __ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address);
7251#endif
7252    __ cmp($tmp$$Register, 0);
7253  %}
7254  ins_pipe( long_memory_op );
7255%}
7256
7257// Conditional-store of an intx value.
7258instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{
7259#ifdef AARCH64
7260  match(Set icc (StoreLConditional mem (Binary oldval newval)));
7261  effect( TEMP tmp );
7262  size(28);
7263  format %{ "loop:\n\t"
7264            "LDXR     $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t"
7265            "SUBS     $tmp, $tmp, $oldval\n\t"
7266            "B.ne     done\n\t"
7267            "STXR     $tmp, $newval, $mem\n\t"
7268            "CBNZ_w   $tmp, loop\n\t"
7269            "CMP      $tmp, 0\n\t"
7270            "done:\n\t"
7271            "membar   LoadStore|LoadLoad" %}
7272#else
7273  match(Set icc (StoreIConditional mem (Binary oldval newval)));
7274  effect( TEMP tmp );
7275  size(28);
7276  format %{ "loop: \n\t"
7277            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t"
7278            "XORS     $tmp,$tmp, $oldval\n\t"
7279            "STREX.eq $tmp, $newval, $mem\n\t"
7280            "CMP.eq   $tmp, 1 \n\t"
7281            "B.eq     loop \n\t"
7282            "TEQ      $tmp, 0\n\t"
7283            "membar   LoadStore|LoadLoad" %}
7284#endif
7285  ins_encode %{
7286    Label loop;
7287    __ bind(loop);
7288#ifdef AARCH64
7289// FIXME: use load-acquire/store-release, remove membar?
7290    Label done;
7291    Register base = reg_to_register_object($mem$$base);
7292    __ ldxr($tmp$$Register, base);
7293    __ subs($tmp$$Register, $tmp$$Register, $oldval$$Register);
7294    __ b(done, ne);
7295    __ stxr($tmp$$Register, $newval$$Register, base);
7296    __ cbnz_w($tmp$$Register, loop);
7297    __ cmp($tmp$$Register, 0);
7298    __ bind(done);
7299#else
7300    __ ldrex($tmp$$Register, $mem$$Address);
7301    __ eors($tmp$$Register, $tmp$$Register, $oldval$$Register);
7302    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
7303    __ cmp($tmp$$Register, 1, eq);
7304    __ b(loop, eq);
7305    __ teq($tmp$$Register, 0);
7306#endif
7307    // used by biased locking only. Requires a membar.
7308    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg);
7309  %}
7310  ins_pipe( long_memory_op );
7311%}
7312
7313// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
7314
7315#ifdef AARCH64
7316// TODO: if combined with membar, elide membar and use
7317// load-acquire/store-release if appropriate
7318instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegL newval, iRegI res, iRegI tmp, flagsReg ccr) %{
7319  match(Set res (CompareAndSwapL mem (Binary oldval newval)));
7320  effect( KILL ccr, TEMP tmp);
7321  size(24);
7322  format %{ "loop:\n\t"
7323            "LDXR     $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7324            "CMP      $tmp, $oldval\n\t"
7325            "B.ne     done\n\t"
7326            "STXR     $tmp, $newval, $mem\n\t"
7327            "CBNZ_w   $tmp, loop\n\t"
7328            "done:\n\t"
7329            "CSET_w   $res, eq" %}
7330  ins_encode %{
7331    Register base = reg_to_register_object($mem$$base);
7332    Label loop, done;
7333    __ bind(loop);
7334    __ ldxr($tmp$$Register, base);
7335    __ cmp($tmp$$Register, $oldval$$Register);
7336    __ b(done, ne);
7337    __ stxr($tmp$$Register, $newval$$Register, base);
7338    __ cbnz_w($tmp$$Register, loop);
7339    __ bind(done);
7340    __ cset_w($res$$Register, eq);
7341  %}
7342  ins_pipe( long_memory_op );
7343%}
7344
7345instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
7346  match(Set res (CompareAndSwapI mem (Binary oldval newval)));
7347  effect( KILL ccr, TEMP tmp);
7348  size(24);
7349  format %{ "loop:\n\t"
7350            "LDXR_w   $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7351            "CMP_w    $tmp, $oldval\n\t"
7352            "B.ne     done\n\t"
7353            "STXR_w   $tmp, $newval, $mem\n\t"
7354            "CBNZ_w   $tmp, loop\n\t"
7355            "done:\n\t"
7356            "CSET_w   $res, eq" %}
7357  ins_encode %{
7358    Register base = reg_to_register_object($mem$$base);
7359    Label loop, done;
7360    __ bind(loop);
7361    __ ldxr_w($tmp$$Register, base);
7362    __ cmp_w($tmp$$Register, $oldval$$Register);
7363    __ b(done, ne);
7364    __ stxr_w($tmp$$Register, $newval$$Register,  base);
7365    __ cbnz_w($tmp$$Register, loop);
7366    __ bind(done);
7367    __ cset_w($res$$Register, eq);
7368  %}
7369  ins_pipe( long_memory_op );
7370%}
7371
7372// tmp must use iRegI instead of iRegN until 8051805 is fixed.
7373instruct compareAndSwapN_bool(memoryex mem, iRegN oldval, iRegN newval, iRegI res, iRegI tmp, flagsReg ccr) %{
7374  match(Set res (CompareAndSwapN mem (Binary oldval newval)));
7375  effect( KILL ccr, TEMP tmp);
7376  size(24);
7377  format %{ "loop:\n\t"
7378            "LDXR_w   $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7379            "CMP_w    $tmp, $oldval\n\t"
7380            "B.ne     done\n\t"
7381            "STXR_w   $tmp, $newval, $mem\n\t"
7382            "CBNZ_w   $tmp, loop\n\t"
7383            "done:\n\t"
7384            "CSET_w   $res, eq" %}
7385  ins_encode %{
7386    Register base = reg_to_register_object($mem$$base);
7387    Label loop, done;
7388    __ bind(loop);
7389    __ ldxr_w($tmp$$Register, base);
7390    __ cmp_w($tmp$$Register, $oldval$$Register);
7391    __ b(done, ne);
7392    __ stxr_w($tmp$$Register, $newval$$Register,  base);
7393    __ cbnz_w($tmp$$Register, loop);
7394    __ bind(done);
7395    __ cset_w($res$$Register, eq);
7396  %}
7397  ins_pipe( long_memory_op );
7398%}
7399
7400instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr) %{
7401  match(Set res (CompareAndSwapP mem (Binary oldval newval)));
7402  effect( KILL ccr, TEMP tmp);
7403  size(24);
7404  format %{ "loop:\n\t"
7405            "LDXR     $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7406            "CMP      $tmp, $oldval\n\t"
7407            "B.ne     done\n\t"
7408            "STXR     $tmp, $newval, $mem\n\t"
7409            "CBNZ_w   $tmp, loop\n\t"
7410            "done:\n\t"
7411            "CSET_w   $res, eq" %}
7412  ins_encode %{
7413    Register base = reg_to_register_object($mem$$base);
7414    Label loop, done;
7415    __ bind(loop);
7416    __ ldxr($tmp$$Register, base);
7417    __ cmp($tmp$$Register, $oldval$$Register);
7418    __ b(done, ne);
7419    __ stxr($tmp$$Register, $newval$$Register,  base);
7420    __ cbnz_w($tmp$$Register, loop);
7421    __ bind(done);
7422    __ cset_w($res$$Register, eq);
7423  %}
7424  ins_pipe( long_memory_op );
7425%}
7426#else // !AARCH64
7427instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
7428  match(Set res (CompareAndSwapL mem (Binary oldval newval)));
7429  effect( KILL ccr, TEMP tmp);
7430  size(32);
7431  format %{ "loop: \n\t"
7432            "LDREXD   $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7433            "CMP      $tmp.lo, $oldval.lo\n\t"
7434            "CMP.eq   $tmp.hi, $oldval.hi\n\t"
7435            "STREXD.eq $tmp, $newval, $mem\n\t"
7436            "MOV.ne   $tmp, 0 \n\t"
7437            "XORS.eq  $tmp,$tmp, 1 \n\t"
7438            "B.eq     loop \n\t"
7439            "MOV      $res, $tmp" %}
7440  ins_encode %{
7441    Label loop;
7442    __ bind(loop);
7443    __ ldrexd($tmp$$Register, $mem$$Address);
7444    __ cmp($tmp$$Register, $oldval$$Register);
7445    __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq);
7446    __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq);
7447    __ mov($tmp$$Register, 0, ne);
7448    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
7449    __ b(loop, eq);
7450    __ mov($res$$Register, $tmp$$Register);
7451  %}
7452  ins_pipe( long_memory_op );
7453%}
7454
7455
7456instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
7457  match(Set res (CompareAndSwapI mem (Binary oldval newval)));
7458  effect( KILL ccr, TEMP tmp);
7459  size(28);
7460  format %{ "loop: \n\t"
7461            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7462            "CMP      $tmp, $oldval\n\t"
7463            "STREX.eq $tmp, $newval, $mem\n\t"
7464            "MOV.ne   $tmp, 0 \n\t"
7465            "XORS.eq  $tmp,$tmp, 1 \n\t"
7466            "B.eq     loop \n\t"
7467            "MOV      $res, $tmp" %}
7468
7469  ins_encode %{
7470    Label loop;
7471    __ bind(loop);
7472    __ ldrex($tmp$$Register,$mem$$Address);
7473    __ cmp($tmp$$Register, $oldval$$Register);
7474    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
7475    __ mov($tmp$$Register, 0, ne);
7476    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
7477    __ b(loop, eq);
7478    __ mov($res$$Register, $tmp$$Register);
7479  %}
7480  ins_pipe( long_memory_op );
7481%}
7482
7483instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
7484  match(Set res (CompareAndSwapP mem (Binary oldval newval)));
7485  effect( KILL ccr, TEMP tmp);
7486  size(28);
7487  format %{ "loop: \n\t"
7488            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
7489            "CMP      $tmp, $oldval\n\t"
7490            "STREX.eq $tmp, $newval, $mem\n\t"
7491            "MOV.ne   $tmp, 0 \n\t"
7492            "EORS.eq  $tmp,$tmp, 1 \n\t"
7493            "B.eq     loop \n\t"
7494            "MOV      $res, $tmp" %}
7495
7496  ins_encode %{
7497    Label loop;
7498    __ bind(loop);
7499    __ ldrex($tmp$$Register,$mem$$Address);
7500    __ cmp($tmp$$Register, $oldval$$Register);
7501    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
7502    __ mov($tmp$$Register, 0, ne);
7503    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
7504    __ b(loop, eq);
7505    __ mov($res$$Register, $tmp$$Register);
7506  %}
7507  ins_pipe( long_memory_op );
7508%}
7509#endif // !AARCH64
7510
7511#ifdef AARCH64
7512instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2) %{
7513  predicate(n->as_LoadStore()->result_not_used());
7514  match(Set dummy (GetAndAddI mem add));
7515  effect(TEMP tmp1, TEMP tmp2);
7516  size(16);
7517  format %{ "loop:\n\t"
7518            "LDXR_w   $tmp1, $mem\n\t"
7519            "ADD_w    $tmp1, $tmp1, $add\n\t"
7520            "STXR_w   $tmp2, $tmp1, $mem\n\t"
7521            "CBNZ_w   $tmp2, loop" %}
7522
7523  ins_encode %{
7524    Label loop;
7525    Register base = reg_to_register_object($mem$$base);
7526    __ bind(loop);
7527    __ ldxr_w($tmp1$$Register, base);
7528    __ add_w($tmp1$$Register, $tmp1$$Register, $add$$constant);
7529    __ stxr_w($tmp2$$Register, $tmp1$$Register, base);
7530    __ cbnz_w($tmp2$$Register, loop);
7531  %}
7532  ins_pipe( long_memory_op );
7533%}
7534#else
7535instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
7536  predicate(n->as_LoadStore()->result_not_used());
7537  match(Set dummy (GetAndAddI mem add));
7538  effect(KILL ccr, TEMP tmp1, TEMP tmp2);
7539  size(20);
7540  format %{ "loop: \n\t"
7541            "LDREX    $tmp1, $mem\n\t"
7542            "ADD      $tmp1, $tmp1, $add\n\t"
7543            "STREX    $tmp2, $tmp1, $mem\n\t"
7544            "CMP      $tmp2, 0 \n\t"
7545            "B.ne     loop \n\t" %}
7546
7547  ins_encode %{
7548    Label loop;
7549    __ bind(loop);
7550    __ ldrex($tmp1$$Register,$mem$$Address);
7551    __ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
7552    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7553    __ cmp($tmp2$$Register, 0);
7554    __ b(loop, ne);
7555  %}
7556  ins_pipe( long_memory_op );
7557%}
7558#endif
7559
7560#ifdef AARCH64
7561instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2) %{
7562  predicate(n->as_LoadStore()->result_not_used());
7563  match(Set dummy (GetAndAddI mem add));
7564  effect(TEMP tmp1, TEMP tmp2);
7565  size(16);
7566  format %{ "loop:\n\t"
7567            "LDXR_w   $tmp1, $mem\n\t"
7568            "ADD_w    $tmp1, $tmp1, $add\n\t"
7569            "STXR_w   $tmp2, $tmp1, $mem\n\t"
7570            "CBNZ_w   $tmp2, loop" %}
7571
7572  ins_encode %{
7573    Label loop;
7574    Register base = reg_to_register_object($mem$$base);
7575    __ bind(loop);
7576    __ ldxr_w($tmp1$$Register, base);
7577    __ add_w($tmp1$$Register, $tmp1$$Register, $add$$Register);
7578    __ stxr_w($tmp2$$Register, $tmp1$$Register, base);
7579    __ cbnz_w($tmp2$$Register, loop);
7580  %}
7581  ins_pipe( long_memory_op );
7582%}
7583#else
7584instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
7585  predicate(n->as_LoadStore()->result_not_used());
7586  match(Set dummy (GetAndAddI mem add));
7587  effect(KILL ccr, TEMP tmp1, TEMP tmp2);
7588  size(20);
7589  format %{ "loop: \n\t"
7590            "LDREX    $tmp1, $mem\n\t"
7591            "ADD      $tmp1, $tmp1, $add\n\t"
7592            "STREX    $tmp2, $tmp1, $mem\n\t"
7593            "CMP      $tmp2, 0 \n\t"
7594            "B.ne     loop \n\t" %}
7595
7596  ins_encode %{
7597    Label loop;
7598    __ bind(loop);
7599    __ ldrex($tmp1$$Register,$mem$$Address);
7600    __ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
7601    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7602    __ cmp($tmp2$$Register, 0);
7603    __ b(loop, ne);
7604  %}
7605  ins_pipe( long_memory_op );
7606%}
7607#endif
7608
7609#ifdef AARCH64
7610instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2) %{
7611  match(Set res (GetAndAddI mem add));
7612  effect(TEMP tmp1, TEMP tmp2, TEMP res);
7613  size(16);
7614  format %{ "loop:\n\t"
7615            "LDXR_w   $res, $mem\n\t"
7616            "ADD_w    $tmp1, $res, $add\n\t"
7617            "STXR_w   $tmp2, $tmp1, $mem\n\t"
7618            "CBNZ_w   $tmp2, loop" %}
7619
7620  ins_encode %{
7621    Label loop;
7622    Register base = reg_to_register_object($mem$$base);
7623    __ bind(loop);
7624    __ ldxr_w($res$$Register, base);
7625    __ add_w($tmp1$$Register, $res$$Register, $add$$constant);
7626    __ stxr_w($tmp2$$Register, $tmp1$$Register, base);
7627    __ cbnz_w($tmp2$$Register, loop);
7628  %}
7629  ins_pipe( long_memory_op );
7630%}
7631#else
7632instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
7633  match(Set res (GetAndAddI mem add));
7634  effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
7635  size(20);
7636  format %{ "loop: \n\t"
7637            "LDREX    $res, $mem\n\t"
7638            "ADD      $tmp1, $res, $add\n\t"
7639            "STREX    $tmp2, $tmp1, $mem\n\t"
7640            "CMP      $tmp2, 0 \n\t"
7641            "B.ne     loop \n\t" %}
7642
7643  ins_encode %{
7644    Label loop;
7645    __ bind(loop);
7646    __ ldrex($res$$Register,$mem$$Address);
7647    __ add($tmp1$$Register, $res$$Register, $add$$constant);
7648    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7649    __ cmp($tmp2$$Register, 0);
7650    __ b(loop, ne);
7651  %}
7652  ins_pipe( long_memory_op );
7653%}
7654#endif
7655
7656#ifdef AARCH64
7657instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2) %{
7658  match(Set res (GetAndAddI mem add));
7659  effect(TEMP tmp1, TEMP tmp2, TEMP res);
7660  size(16);
7661  format %{ "loop:\n\t"
7662            "LDXR_w   $res, $mem\n\t"
7663            "ADD_w    $tmp1, $res, $add\n\t"
7664            "STXR_w   $tmp2, $tmp1, $mem\n\t"
7665            "CBNZ_w   $tmp2, loop" %}
7666
7667  ins_encode %{
7668    Label loop;
7669    Register base = reg_to_register_object($mem$$base);
7670    __ bind(loop);
7671    __ ldxr_w($res$$Register, base);
7672    __ add_w($tmp1$$Register, $res$$Register, $add$$Register);
7673    __ stxr_w($tmp2$$Register, $tmp1$$Register, base);
7674    __ cbnz_w($tmp2$$Register, loop);
7675  %}
7676  ins_pipe( long_memory_op );
7677%}
7678#else
7679instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
7680  match(Set res (GetAndAddI mem add));
7681  effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
7682  size(20);
7683  format %{ "loop: \n\t"
7684            "LDREX    $res, $mem\n\t"
7685            "ADD      $tmp1, $res, $add\n\t"
7686            "STREX    $tmp2, $tmp1, $mem\n\t"
7687            "CMP      $tmp2, 0 \n\t"
7688            "B.ne     loop \n\t" %}
7689
7690  ins_encode %{
7691    Label loop;
7692    __ bind(loop);
7693    __ ldrex($res$$Register,$mem$$Address);
7694    __ add($tmp1$$Register, $res$$Register, $add$$Register);
7695    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7696    __ cmp($tmp2$$Register, 0);
7697    __ b(loop, ne);
7698  %}
7699  ins_pipe( long_memory_op );
7700%}
7701#endif
7702
7703#ifdef AARCH64
7704instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegL tmp1, iRegI tmp2) %{
7705  predicate(n->as_LoadStore()->result_not_used());
7706  match(Set dummy (GetAndAddL mem add));
7707  effect(TEMP tmp1, TEMP tmp2);
7708  size(16);
7709  format %{ "loop:\n\t"
7710            "LDXR     $tmp1, $mem\n\t"
7711            "ADD      $tmp1, $tmp1, $add\n\t"
7712            "STXR     $tmp2, $tmp1, $mem\n\t"
7713            "CBNZ_w   $tmp2, loop" %}
7714
7715  ins_encode %{
7716    Label loop;
7717    Register base = reg_to_register_object($mem$$base);
7718    __ bind(loop);
7719    __ ldxr($tmp1$$Register, base);
7720    __ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
7721    __ stxr($tmp2$$Register, $tmp1$$Register, base);
7722    __ cbnz_w($tmp2$$Register, loop);
7723  %}
7724  ins_pipe( long_memory_op );
7725%}
7726#else
7727instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
7728  predicate(n->as_LoadStore()->result_not_used());
7729  match(Set dummy (GetAndAddL mem add));
7730  effect( KILL ccr, TEMP tmp1, TEMP tmp2);
7731  size(24);
7732  format %{ "loop: \n\t"
7733            "LDREXD   $tmp1, $mem\n\t"
7734            "ADDS     $tmp1.lo, $tmp1.lo, $add.lo\n\t"
7735            "ADC      $tmp1.hi, $tmp1.hi, $add.hi\n\t"
7736            "STREXD   $tmp2, $tmp1, $mem\n\t"
7737            "CMP      $tmp2, 0 \n\t"
7738            "B.ne     loop \n\t" %}
7739
7740  ins_encode %{
7741    Label loop;
7742    __ bind(loop);
7743    __ ldrexd($tmp1$$Register, $mem$$Address);
7744    __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register);
7745    __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor());
7746    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7747    __ cmp($tmp2$$Register, 0);
7748    __ b(loop, ne);
7749  %}
7750  ins_pipe( long_memory_op );
7751%}
7752#endif
7753
7754#ifdef AARCH64
7755instruct xaddL_imm_no_res(memoryex mem, aimmL add, Universe dummy, iRegL tmp1, iRegI tmp2) %{
7756  predicate(n->as_LoadStore()->result_not_used());
7757  match(Set dummy (GetAndAddL mem add));
7758  effect(TEMP tmp1, TEMP tmp2);
7759  size(16);
7760  format %{ "loop:\n\t"
7761            "LDXR     $tmp1, $mem\n\t"
7762            "ADD      $tmp1, $tmp1, $add\n\t"
7763            "STXR     $tmp2, $tmp1, $mem\n\t"
7764            "CBNZ_w   $tmp2, loop" %}
7765
7766  ins_encode %{
7767    Label loop;
7768    Register base = reg_to_register_object($mem$$base);
7769    __ bind(loop);
7770    __ ldxr($tmp1$$Register, base);
7771    __ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
7772    __ stxr($tmp2$$Register, $tmp1$$Register, base);
7773    __ cbnz_w($tmp2$$Register, loop);
7774  %}
7775  ins_pipe( long_memory_op );
7776%}
7777#else
7778// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7779// (hi($con$$constant), lo($con$$constant)) becomes
7780instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
7781  predicate(n->as_LoadStore()->result_not_used());
7782  match(Set dummy (GetAndAddL mem add));
7783  effect( KILL ccr, TEMP tmp1, TEMP tmp2);
7784  size(24);
7785  format %{ "loop: \n\t"
7786            "LDREXD   $tmp1, $mem\n\t"
7787            "ADDS     $tmp1.lo, $tmp1.lo, $add\n\t"
7788            "ADC      $tmp1.hi, $tmp1.hi, 0\n\t"
7789            "STREXD   $tmp2, $tmp1, $mem\n\t"
7790            "CMP      $tmp2, 0 \n\t"
7791            "B.ne     loop \n\t" %}
7792
7793  ins_encode %{
7794    Label loop;
7795    __ bind(loop);
7796    __ ldrexd($tmp1$$Register, $mem$$Address);
7797    __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant);
7798    __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0);
7799    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7800    __ cmp($tmp2$$Register, 0);
7801    __ b(loop, ne);
7802  %}
7803  ins_pipe( long_memory_op );
7804%}
7805#endif
7806
7807#ifdef AARCH64
7808instruct xaddL_reg(memoryex mem, iRegL add, iRegL res, iRegL tmp1, iRegI tmp2) %{
7809  match(Set res (GetAndAddL mem add));
7810  effect(TEMP tmp1, TEMP tmp2, TEMP res);
7811  size(16);
7812  format %{ "loop:\n\t"
7813            "LDXR     $res, $mem\n\t"
7814            "ADD      $tmp1, $res, $add\n\t"
7815            "STXR     $tmp2, $tmp1, $mem\n\t"
7816            "CBNZ_w   $tmp2, loop" %}
7817
7818  ins_encode %{
7819    Label loop;
7820    Register base = reg_to_register_object($mem$$base);
7821    __ bind(loop);
7822    __ ldxr($res$$Register, base);
7823    __ add($tmp1$$Register, $res$$Register, $add$$Register);
7824    __ stxr($tmp2$$Register, $tmp1$$Register, base);
7825    __ cbnz_w($tmp2$$Register, loop);
7826  %}
7827  ins_pipe( long_memory_op );
7828%}
7829#else
7830instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
7831  match(Set res (GetAndAddL mem add));
7832  effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
7833  size(24);
7834  format %{ "loop: \n\t"
7835            "LDREXD   $res, $mem\n\t"
7836            "ADDS     $tmp1.lo, $res.lo, $add.lo\n\t"
7837            "ADC      $tmp1.hi, $res.hi, $add.hi\n\t"
7838            "STREXD   $tmp2, $tmp1, $mem\n\t"
7839            "CMP      $tmp2, 0 \n\t"
7840            "B.ne     loop \n\t" %}
7841
7842  ins_encode %{
7843    Label loop;
7844    __ bind(loop);
7845    __ ldrexd($res$$Register, $mem$$Address);
7846    __ adds($tmp1$$Register, $res$$Register, $add$$Register);
7847    __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor());
7848    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7849    __ cmp($tmp2$$Register, 0);
7850    __ b(loop, ne);
7851  %}
7852  ins_pipe( long_memory_op );
7853%}
7854#endif
7855
7856#ifdef AARCH64
7857instruct xaddL_imm(memoryex mem, aimmL add, iRegL res, iRegL tmp1, iRegI tmp2) %{
7858  match(Set res (GetAndAddL mem add));
7859  effect(TEMP tmp1, TEMP tmp2, TEMP res);
7860  size(16);
7861  format %{ "loop:\n\t"
7862            "LDXR     $res, $mem\n\t"
7863            "ADD      $tmp1, $res, $add\n\t"
7864            "STXR     $tmp2, $tmp1, $mem\n\t"
7865            "CBNZ_w   $tmp2, loop" %}
7866
7867  ins_encode %{
7868    Label loop;
7869    Register base = reg_to_register_object($mem$$base);
7870    __ bind(loop);
7871    __ ldxr($res$$Register, base);
7872    __ add($tmp1$$Register, $res$$Register, $add$$constant);
7873    __ stxr($tmp2$$Register, $tmp1$$Register, base);
7874    __ cbnz_w($tmp2$$Register, loop);
7875  %}
7876  ins_pipe( long_memory_op );
7877%}
7878#else
7879// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7880// (hi($con$$constant), lo($con$$constant)) becomes
7881instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
7882  match(Set res (GetAndAddL mem add));
7883  effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
7884  size(24);
7885  format %{ "loop: \n\t"
7886            "LDREXD   $res, $mem\n\t"
7887            "ADDS     $tmp1.lo, $res.lo, $add\n\t"
7888            "ADC      $tmp1.hi, $res.hi, 0\n\t"
7889            "STREXD   $tmp2, $tmp1, $mem\n\t"
7890            "CMP      $tmp2, 0 \n\t"
7891            "B.ne     loop \n\t" %}
7892
7893  ins_encode %{
7894    Label loop;
7895    __ bind(loop);
7896    __ ldrexd($res$$Register, $mem$$Address);
7897    __ adds($tmp1$$Register, $res$$Register, $add$$constant);
7898    __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0);
7899    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
7900    __ cmp($tmp2$$Register, 0);
7901    __ b(loop, ne);
7902  %}
7903  ins_pipe( long_memory_op );
7904%}
7905#endif
7906
7907#ifdef AARCH64
7908instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp) %{
7909  match(Set res (GetAndSetI mem newval));
7910  effect(TEMP tmp, TEMP res);
7911  size(12);
7912  format %{ "loop:\n\t"
7913            "LDXR_w   $res, $mem\n\t"
7914            "STXR_w   $tmp, $newval, $mem\n\t"
7915            "CBNZ_w   $tmp, loop" %}
7916
7917  ins_encode %{
7918    Label loop;
7919    Register base = reg_to_register_object($mem$$base);
7920    __ bind(loop);
7921    __ ldxr_w($res$$Register, base);
7922    __ stxr_w($tmp$$Register, $newval$$Register, base);
7923    __ cbnz_w($tmp$$Register, loop);
7924  %}
7925  ins_pipe( long_memory_op );
7926%}
7927
7928#ifdef XXX
7929// Disabled until 8051805 is fixed.
7930instruct xchgN(memoryex mem, iRegN newval, iRegN res, iRegN tmp) %{
7931  match(Set res (GetAndSetN mem newval));
7932  effect(TEMP tmp, TEMP res);
7933  size(12);
7934  format %{ "loop:\n\t"
7935            "LDXR_w   $res, $mem\n\t"
7936            "STXR_w   $tmp, $newval, $mem\n\t"
7937            "CBNZ_w   $tmp, loop" %}
7938
7939  ins_encode %{
7940    Label loop;
7941    Register base = reg_to_register_object($mem$$base);
7942    __ bind(loop);
7943    __ ldxr_w($res$$Register, base);
7944    __ stxr_w($tmp$$Register, $newval$$Register, base);
7945    __ cbnz_w($tmp$$Register, loop);
7946  %}
7947  ins_pipe( long_memory_op );
7948%}
7949#endif
7950#else
7951instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
7952  match(Set res (GetAndSetI mem newval));
7953  effect(KILL ccr, TEMP tmp, TEMP res);
7954  size(16);
7955  format %{ "loop: \n\t"
7956            "LDREX    $res, $mem\n\t"
7957            "STREX    $tmp, $newval, $mem\n\t"
7958            "CMP      $tmp, 0 \n\t"
7959            "B.ne     loop \n\t" %}
7960
7961  ins_encode %{
7962    Label loop;
7963    __ bind(loop);
7964    __ ldrex($res$$Register,$mem$$Address);
7965    __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
7966    __ cmp($tmp$$Register, 0);
7967    __ b(loop, ne);
7968  %}
7969  ins_pipe( long_memory_op );
7970%}
7971#endif
7972
7973#ifdef AARCH64
7974instruct xchgL(memoryex mem, iRegL newval, iRegL res, iRegI tmp) %{
7975  match(Set res (GetAndSetL mem newval));
7976  effect(TEMP tmp, TEMP res);
7977  size(12);
7978  format %{ "loop:\n\t"
7979            "LDXR     $res, $mem\n\t"
7980            "STXR     $tmp, $newval, $mem\n\t"
7981            "CBNZ_w   $tmp, loop" %}
7982
7983  ins_encode %{
7984    Label loop;
7985    Register base = reg_to_register_object($mem$$base);
7986    __ bind(loop);
7987    __ ldxr($res$$Register, base);
7988    __ stxr($tmp$$Register, $newval$$Register, base);
7989    __ cbnz_w($tmp$$Register, loop);
7990  %}
7991  ins_pipe( long_memory_op );
7992%}
7993#else
7994instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{
7995  match(Set res (GetAndSetL mem newval));
7996  effect( KILL ccr, TEMP tmp, TEMP res);
7997  size(16);
7998  format %{ "loop: \n\t"
7999            "LDREXD   $res, $mem\n\t"
8000            "STREXD   $tmp, $newval, $mem\n\t"
8001            "CMP      $tmp, 0 \n\t"
8002            "B.ne     loop \n\t" %}
8003
8004  ins_encode %{
8005    Label loop;
8006    __ bind(loop);
8007    __ ldrexd($res$$Register, $mem$$Address);
8008    __ strexd($tmp$$Register, $newval$$Register, $mem$$Address);
8009    __ cmp($tmp$$Register, 0);
8010    __ b(loop, ne);
8011  %}
8012  ins_pipe( long_memory_op );
8013%}
8014#endif // !AARCH64
8015
8016#ifdef AARCH64
8017instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp) %{
8018  match(Set res (GetAndSetP mem newval));
8019  effect(TEMP tmp, TEMP res);
8020  size(12);
8021  format %{ "loop:\n\t"
8022            "LDREX    $res, $mem\n\t"
8023            "STREX    $tmp, $newval, $mem\n\t"
8024            "CBNZ_w   $tmp, loop" %}
8025
8026  ins_encode %{
8027    Label loop;
8028    Register base = reg_to_register_object($mem$$base);
8029    __ bind(loop);
8030    __ ldrex($res$$Register, base);
8031    __ strex($tmp$$Register, $newval$$Register, base);
8032    __ cbnz_w($tmp$$Register, loop);
8033  %}
8034  ins_pipe( long_memory_op );
8035%}
8036#else
8037instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{
8038  match(Set res (GetAndSetP mem newval));
8039  effect(KILL ccr, TEMP tmp, TEMP res);
8040  size(16);
8041  format %{ "loop: \n\t"
8042            "LDREX    $res, $mem\n\t"
8043            "STREX    $tmp, $newval, $mem\n\t"
8044            "CMP      $tmp, 0 \n\t"
8045            "B.ne     loop \n\t" %}
8046
8047  ins_encode %{
8048    Label loop;
8049    __ bind(loop);
8050    __ ldrex($res$$Register,$mem$$Address);
8051    __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
8052    __ cmp($tmp$$Register, 0);
8053    __ b(loop, ne);
8054  %}
8055  ins_pipe( long_memory_op );
8056%}
8057#endif // !AARCH64
8058
8059//---------------------
8060// Subtraction Instructions
8061// Register Subtraction
8062instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
8063  match(Set dst (SubI src1 src2));
8064
8065  size(4);
8066  format %{ "sub_32 $dst,$src1,$src2\t! int" %}
8067  ins_encode %{
8068    __ sub_32($dst$$Register, $src1$$Register, $src2$$Register);
8069  %}
8070  ins_pipe(ialu_reg_reg);
8071%}
8072
8073#ifndef AARCH64
8074instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8075  match(Set dst (SubI src1 (LShiftI src2 src3)));
8076
8077  size(4);
8078  format %{ "SUB    $dst,$src1,$src2<<$src3" %}
8079  ins_encode %{
8080    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
8081  %}
8082  ins_pipe(ialu_reg_reg);
8083%}
8084#endif
8085
8086instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
8087  match(Set dst (SubI src1 (LShiftI src2 src3)));
8088
8089  size(4);
8090  format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %}
8091  ins_encode %{
8092    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
8093  %}
8094  ins_pipe(ialu_reg_reg);
8095%}
8096
8097#ifndef AARCH64
8098instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8099  match(Set dst (SubI src1 (RShiftI src2 src3)));
8100
8101  size(4);
8102  format %{ "SUB    $dst,$src1,$src2>>$src3" %}
8103  ins_encode %{
8104    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
8105  %}
8106  ins_pipe(ialu_reg_reg);
8107%}
8108#endif
8109
8110instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
8111  match(Set dst (SubI src1 (RShiftI src2 src3)));
8112
8113  size(4);
8114  format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %}
8115  ins_encode %{
8116    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
8117  %}
8118  ins_pipe(ialu_reg_reg);
8119%}
8120
8121#ifndef AARCH64
8122instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8123  match(Set dst (SubI src1 (URShiftI src2 src3)));
8124
8125  size(4);
8126  format %{ "SUB    $dst,$src1,$src2>>>$src3" %}
8127  ins_encode %{
8128    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
8129  %}
8130  ins_pipe(ialu_reg_reg);
8131%}
8132#endif
8133
8134instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
8135  match(Set dst (SubI src1 (URShiftI src2 src3)));
8136
8137  size(4);
8138  format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %}
8139  ins_encode %{
8140    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
8141  %}
8142  ins_pipe(ialu_reg_reg);
8143%}
8144
8145#ifndef AARCH64
8146instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8147  match(Set dst (SubI (LShiftI src1 src2) src3));
8148
8149  size(4);
8150  format %{ "RSB    $dst,$src3,$src1<<$src2" %}
8151  ins_encode %{
8152    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
8153  %}
8154  ins_pipe(ialu_reg_reg);
8155%}
8156
8157instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
8158  match(Set dst (SubI (LShiftI src1 src2) src3));
8159
8160  size(4);
8161  format %{ "RSB    $dst,$src3,$src1<<$src2" %}
8162  ins_encode %{
8163    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
8164  %}
8165  ins_pipe(ialu_reg_reg);
8166%}
8167
8168instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8169  match(Set dst (SubI (RShiftI src1 src2) src3));
8170
8171  size(4);
8172  format %{ "RSB    $dst,$src3,$src1>>$src2" %}
8173  ins_encode %{
8174    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
8175  %}
8176  ins_pipe(ialu_reg_reg);
8177%}
8178
8179instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
8180  match(Set dst (SubI (RShiftI src1 src2) src3));
8181
8182  size(4);
8183  format %{ "RSB    $dst,$src3,$src1>>$src2" %}
8184  ins_encode %{
8185    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
8186  %}
8187  ins_pipe(ialu_reg_reg);
8188%}
8189
8190instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8191  match(Set dst (SubI (URShiftI src1 src2) src3));
8192
8193  size(4);
8194  format %{ "RSB    $dst,$src3,$src1>>>$src2" %}
8195  ins_encode %{
8196    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
8197  %}
8198  ins_pipe(ialu_reg_reg);
8199%}
8200
8201instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
8202  match(Set dst (SubI (URShiftI src1 src2) src3));
8203
8204  size(4);
8205  format %{ "RSB    $dst,$src3,$src1>>>$src2" %}
8206  ins_encode %{
8207    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
8208  %}
8209  ins_pipe(ialu_reg_reg);
8210%}
8211#endif
8212
8213// Immediate Subtraction
8214instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
8215  match(Set dst (SubI src1 src2));
8216
8217  size(4);
8218  format %{ "sub_32 $dst,$src1,$src2\t! int" %}
8219  ins_encode %{
8220    __ sub_32($dst$$Register, $src1$$Register, $src2$$constant);
8221  %}
8222  ins_pipe(ialu_reg_imm);
8223%}
8224
8225instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{
8226  match(Set dst (AddI src1 src2));
8227
8228  size(4);
8229  format %{ "sub_32 $dst,$src1,-($src2)\t! int" %}
8230  ins_encode %{
8231    __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant);
8232  %}
8233  ins_pipe(ialu_reg_imm);
8234%}
8235
8236#ifndef AARCH64
8237instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{
8238  match(Set dst (SubI src1 src2));
8239
8240  size(4);
8241  format %{ "RSB    $dst,$src2,src1" %}
8242  ins_encode %{
8243    __ rsb($dst$$Register, $src2$$Register, $src1$$constant);
8244  %}
8245  ins_pipe(ialu_zero_reg);
8246%}
8247#endif
8248
8249// Register Subtraction
8250#ifdef AARCH64
8251instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
8252  match(Set dst (SubL src1 src2));
8253
8254  size(4);
8255  format %{ "SUB    $dst,$src1,$src2\t! long" %}
8256  ins_encode %{
8257    __ sub($dst$$Register, $src1$$Register, $src2$$Register);
8258  %}
8259  ins_pipe(ialu_reg_reg);
8260%}
8261#else
8262instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{
8263  match(Set dst (SubL src1 src2));
8264  effect (KILL icc);
8265
8266  size(8);
8267  format %{ "SUBS   $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
8268            "SBC    $dst.hi,$src1.hi,$src2.hi" %}
8269  ins_encode %{
8270    __ subs($dst$$Register, $src1$$Register, $src2$$Register);
8271    __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
8272  %}
8273  ins_pipe(ialu_reg_reg);
8274%}
8275#endif
8276
8277#ifdef AARCH64
8278// Immediate Subtraction
8279instruct subL_reg_aimm(iRegL dst, iRegL src1, aimmL src2) %{
8280  match(Set dst (SubL src1 src2));
8281
8282  size(4);
8283  format %{ "SUB    $dst,$src1,$src2\t! long" %}
8284  ins_encode %{
8285    __ sub($dst$$Register, $src1$$Register, $src2$$constant);
8286  %}
8287  ins_pipe(ialu_reg_imm);
8288%}
8289
8290instruct subL_reg_immLneg(iRegL dst, iRegL src1, aimmLneg src2) %{
8291  match(Set dst (AddL src1 src2));
8292
8293  size(4);
8294  format %{ "SUB    $dst,$src1,-($src2)\t! long" %}
8295  ins_encode %{
8296    __ sub($dst$$Register, $src1$$Register, -$src2$$constant);
8297  %}
8298  ins_pipe(ialu_reg_imm);
8299%}
8300#else
8301// TODO
8302#endif
8303
8304#ifndef AARCH64
8305// Immediate Subtraction
8306// TODO: try immLRot2 instead, (0, $con$$constant) becomes
8307// (hi($con$$constant), lo($con$$constant)) becomes
8308instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{
8309  match(Set dst (SubL src1 con));
8310  effect (KILL icc);
8311
8312  size(8);
8313  format %{ "SUB    $dst.lo,$src1.lo,$con\t! long\n\t"
8314            "SBC    $dst.hi,$src1.hi,0" %}
8315  ins_encode %{
8316    __ subs($dst$$Register, $src1$$Register, $con$$constant);
8317    __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0);
8318  %}
8319  ins_pipe(ialu_reg_imm);
8320%}
8321
8322// Long negation
8323instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{
8324  match(Set dst (SubL zero src2));
8325  effect (KILL icc);
8326
8327  size(8);
8328  format %{ "RSBS   $dst.lo,$src2.lo,0\t! long\n\t"
8329            "RSC    $dst.hi,$src2.hi,0" %}
8330  ins_encode %{
8331    __ rsbs($dst$$Register, $src2$$Register, 0);
8332    __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0);
8333  %}
8334  ins_pipe(ialu_zero_reg);
8335%}
8336#endif // !AARCH64
8337
8338// Multiplication Instructions
8339// Integer Multiplication
8340// Register Multiplication
8341instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
8342  match(Set dst (MulI src1 src2));
8343
8344  size(4);
8345  format %{ "mul_32 $dst,$src1,$src2" %}
8346  ins_encode %{
8347    __ mul_32($dst$$Register, $src1$$Register, $src2$$Register);
8348  %}
8349  ins_pipe(imul_reg_reg);
8350%}
8351
8352#ifdef AARCH64
8353instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
8354  match(Set dst (MulL src1 src2));
8355  size(4);
8356  format %{ "MUL  $dst,$src1,$src2\t! long" %}
8357  ins_encode %{
8358    __ mul($dst$$Register, $src1$$Register, $src2$$Register);
8359  %}
8360  ins_pipe(imul_reg_reg);
8361%}
8362#else
8363instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{
8364  effect(DEF dst, USE src1, USE src2);
8365  size(4);
8366  format %{ "MUL  $dst.hi,$src1.lo,$src2.hi\t! long" %}
8367  ins_encode %{
8368    __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor());
8369  %}
8370  ins_pipe(imul_reg_reg);
8371%}
8372
8373instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
8374  effect(USE_DEF dst, USE src1, USE src2);
8375  size(8);
8376  format %{ "MLA  $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t"
8377            "MOV  $dst.lo, 0"%}
8378  ins_encode %{
8379    __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor());
8380    __ mov($dst$$Register, 0);
8381  %}
8382  ins_pipe(imul_reg_reg);
8383%}
8384
8385instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
8386  effect(USE_DEF dst, USE src1, USE src2);
8387  size(4);
8388  format %{ "UMLAL  $dst.lo,$dst.hi,$src1,$src2\t! long" %}
8389  ins_encode %{
8390    __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register);
8391  %}
8392  ins_pipe(imul_reg_reg);
8393%}
8394
8395instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
8396  match(Set dst (MulL src1 src2));
8397
8398  expand %{
8399    mulL_lo1_hi2(dst, src1, src2);
8400    mulL_hi1_lo2(dst, src1, src2);
8401    mulL_lo1_lo2(dst, src1, src2);
8402  %}
8403%}
8404#endif // !AARCH64
8405
8406// Integer Division
8407// Register Division
8408#ifdef AARCH64
8409instruct divI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
8410  match(Set dst (DivI src1 src2));
8411
8412  size(4);
8413  format %{ "SDIV    $dst,$src1,$src2\t! 32-bit" %}
8414  ins_encode %{
8415    __ sdiv_w($dst$$Register, $src1$$Register, $src2$$Register);
8416  %}
8417  ins_pipe(ialu_reg_reg); // FIXME
8418%}
8419#else
8420instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{
8421  match(Set dst (DivI src1 src2));
8422  effect( KILL ccr, KILL src1, KILL src2, KILL lr);
8423  ins_cost((2+71)*DEFAULT_COST);
8424
8425  format %{ "DIV   $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %}
8426  ins_encode %{
8427    __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
8428  %}
8429  ins_pipe(sdiv_reg_reg);
8430%}
8431#endif
8432
8433// Register Long Division
8434#ifdef AARCH64
8435instruct divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
8436  match(Set dst (DivL src1 src2));
8437
8438  size(4);
8439  format %{ "SDIV    $dst,$src1,$src2" %}
8440  ins_encode %{
8441    __ sdiv($dst$$Register, $src1$$Register, $src2$$Register);
8442  %}
8443  ins_pipe(ialu_reg_reg); // FIXME
8444%}
8445#else
8446instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
8447  match(Set dst (DivL src1 src2));
8448  effect(CALL);
8449  ins_cost(DEFAULT_COST*71);
8450  format %{ "DIVL  $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %}
8451  ins_encode %{
8452    address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv);
8453    __ call(target, relocInfo::runtime_call_type);
8454  %}
8455  ins_pipe(divL_reg_reg);
8456%}
8457#endif
8458
8459// Integer Remainder
8460// Register Remainder
8461#ifdef AARCH64
8462#ifdef TODO
8463instruct msubI_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
8464  match(Set dst (SubI src1 (MulI src2 src3)));
8465
8466  size(4);
8467  format %{ "MSUB    $dst,$src2,$src3,$src1\t! 32-bit\n\t" %}
8468  ins_encode %{
8469    __ msub_w($dst$$Register, $src2$$Register, $src3$$Register, $src1$$Register);
8470  %}
8471  ins_pipe(ialu_reg_reg); // FIXME
8472%}
8473#endif
8474
8475instruct modI_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp) %{
8476  match(Set dst (ModI src1 src2));
8477  effect(TEMP temp);
8478
8479  size(8);
8480  format %{ "SDIV    $temp,$src1,$src2\t! 32-bit\n\t"
8481            "MSUB    $dst,$src2,$temp,$src1\t! 32-bit\n\t" %}
8482  ins_encode %{
8483    __ sdiv_w($temp$$Register, $src1$$Register, $src2$$Register);
8484    __ msub_w($dst$$Register, $src2$$Register, $temp$$Register, $src1$$Register);
8485  %}
8486  ins_pipe(ialu_reg_reg); // FIXME
8487%}
8488#else
8489instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{
8490  match(Set dst (ModI src1 src2));
8491  effect( KILL ccr, KILL temp, KILL src2, KILL lr);
8492
8493  format %{ "MODI   $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %}
8494  ins_encode %{
8495    __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
8496  %}
8497  ins_pipe(sdiv_reg_reg);
8498%}
8499#endif
8500
8501// Register Long Remainder
8502#ifdef AARCH64
8503instruct modL_reg_reg(iRegL dst, iRegL src1, iRegL src2, iRegL temp) %{
8504  match(Set dst (ModL src1 src2));
8505  effect(TEMP temp);
8506
8507  size(8);
8508  format %{ "SDIV    $temp,$src1,$src2\n\t"
8509            "MSUB    $dst,$src2,$temp,$src1" %}
8510  ins_encode %{
8511    __ sdiv($temp$$Register, $src1$$Register, $src2$$Register);
8512    __ msub($dst$$Register, $src2$$Register, $temp$$Register, $src1$$Register);
8513  %}
8514  ins_pipe(ialu_reg_reg); // FIXME
8515%}
8516#else
8517instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
8518  match(Set dst (ModL src1 src2));
8519  effect(CALL);
8520  ins_cost(MEMORY_REF_COST); // FIXME
8521  format %{ "modL    $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %}
8522  ins_encode %{
8523    address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
8524    __ call(target, relocInfo::runtime_call_type);
8525  %}
8526  ins_pipe(divL_reg_reg);
8527%}
8528#endif
8529
8530// Integer Shift Instructions
8531
8532// Register Shift Left
8533instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
8534  match(Set dst (LShiftI src1 src2));
8535
8536  size(4);
8537#ifdef AARCH64
8538  format %{ "LSLV   $dst,$src1,$src2\t! int" %}
8539  ins_encode %{
8540    __ lslv_w($dst$$Register, $src1$$Register, $src2$$Register);
8541  %}
8542#else
8543  format %{ "LSL  $dst,$src1,$src2 \n\t" %}
8544  ins_encode %{
8545    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
8546  %}
8547#endif
8548  ins_pipe(ialu_reg_reg);
8549%}
8550
8551// Register Shift Left Immediate
8552instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
8553  match(Set dst (LShiftI src1 src2));
8554
8555  size(4);
8556#ifdef AARCH64
8557  format %{ "LSL_w  $dst,$src1,$src2\t! int" %}
8558  ins_encode %{
8559    __ _lsl($dst$$Register, $src1$$Register, $src2$$constant);
8560  %}
8561#else
8562  format %{ "LSL    $dst,$src1,$src2\t! int" %}
8563  ins_encode %{
8564    __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
8565  %}
8566#endif
8567  ins_pipe(ialu_reg_imm);
8568%}
8569
8570#ifndef AARCH64
8571instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
8572  effect(USE_DEF dst, USE src1, USE src2);
8573  size(4);
8574  format %{"OR  $dst.hi,$dst.hi,($src1.hi << $src2)"  %}
8575  ins_encode %{
8576    __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register));
8577  %}
8578  ins_pipe(ialu_reg_reg);
8579%}
8580
8581instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
8582  effect(USE_DEF dst, USE src1, USE src2);
8583  size(4);
8584  format %{ "LSL  $dst.lo,$src1.lo,$src2 \n\t" %}
8585  ins_encode %{
8586    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
8587  %}
8588  ins_pipe(ialu_reg_reg);
8589%}
8590
8591instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
8592  effect(DEF dst, USE src1, USE src2, KILL ccr);
8593  size(16);
8594  format %{ "SUBS  $dst.hi,$src2,32 \n\t"
8595            "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t"
8596            "RSBmi $dst.hi,$dst.hi,0 \n\t"
8597            "LSRmi $dst.hi,$src1.lo,$dst.hi" %}
8598
8599  ins_encode %{
8600    // $src1$$Register and $dst$$Register->successor() can't be the same
8601    __ subs($dst$$Register->successor(), $src2$$Register, 32);
8602    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl);
8603    __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi);
8604    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi);
8605  %}
8606  ins_pipe(ialu_reg_reg);
8607%}
8608#endif // !AARCH64
8609
8610instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
8611  match(Set dst (LShiftL src1 src2));
8612
8613#ifdef AARCH64
8614  size(4);
8615  format %{ "LSLV  $dst,$src1,$src2\t! long" %}
8616  ins_encode %{
8617    __ lslv($dst$$Register, $src1$$Register, $src2$$Register);
8618  %}
8619  ins_pipe(ialu_reg_reg);
8620#else
8621  expand %{
8622    flagsReg ccr;
8623    shlL_reg_reg_overlap(dst, src1, src2, ccr);
8624    shlL_reg_reg_merge_hi(dst, src1, src2);
8625    shlL_reg_reg_merge_lo(dst, src1, src2);
8626  %}
8627#endif
8628%}
8629
8630#ifdef AARCH64
8631instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{
8632  match(Set dst (LShiftL src1 src2));
8633
8634  size(4);
8635  format %{ "LSL    $dst,$src1,$src2\t! long" %}
8636  ins_encode %{
8637    __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
8638  %}
8639  ins_pipe(ialu_reg_imm);
8640%}
8641#else
8642// Register Shift Left Immediate
8643instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
8644  match(Set dst (LShiftL src1 src2));
8645
8646  size(8);
8647  format %{ "LSL   $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t"
8648            "MOV   $dst.lo, 0" %}
8649  ins_encode %{
8650    if ($src2$$constant == 32) {
8651      __ mov($dst$$Register->successor(), $src1$$Register);
8652    } else {
8653      __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32));
8654    }
8655    __ mov($dst$$Register, 0);
8656  %}
8657  ins_pipe(ialu_reg_imm);
8658%}
8659
8660instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
8661  match(Set dst (LShiftL src1 src2));
8662
8663  size(12);
8664  format %{ "LSL   $dst.hi,$src1.lo,$src2\n\t"
8665            "OR    $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t"
8666            "LSL   $dst.lo,$src1.lo,$src2" %}
8667  ins_encode %{
8668    // The order of the following 3 instructions matters: src1.lo and
8669    // dst.hi can't overlap but src.hi and dst.hi can.
8670    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant));
8671    __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant));
8672    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
8673  %}
8674  ins_pipe(ialu_reg_imm);
8675%}
8676#endif // !AARCH64
8677
8678// Register Arithmetic Shift Right
8679instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
8680  match(Set dst (RShiftI src1 src2));
8681  size(4);
8682#ifdef AARCH64
8683  format %{ "ASRV   $dst,$src1,$src2\t! int" %}
8684  ins_encode %{
8685    __ asrv_w($dst$$Register, $src1$$Register, $src2$$Register);
8686  %}
8687#else
8688  format %{ "ASR    $dst,$src1,$src2\t! int" %}
8689  ins_encode %{
8690    __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
8691  %}
8692#endif
8693  ins_pipe(ialu_reg_reg);
8694%}
8695
8696// Register Arithmetic Shift Right Immediate
8697instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
8698  match(Set dst (RShiftI src1 src2));
8699
8700  size(4);
8701#ifdef AARCH64
8702  format %{ "ASR_w  $dst,$src1,$src2" %}
8703  ins_encode %{
8704    __ _asr_w($dst$$Register, $src1$$Register, $src2$$constant);
8705  %}
8706#else
8707  format %{ "ASR    $dst,$src1,$src2" %}
8708  ins_encode %{
8709    __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
8710  %}
8711#endif
8712  ins_pipe(ialu_reg_imm);
8713%}
8714
8715#ifndef AARCH64
8716// Register Shift Right Arithmetic Long
8717instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
8718  effect(USE_DEF dst, USE src1, USE src2);
8719  size(4);
8720  format %{ "OR  $dst.lo,$dst.lo,($src1.lo >> $src2)"  %}
8721  ins_encode %{
8722    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
8723  %}
8724  ins_pipe(ialu_reg_reg);
8725%}
8726
8727instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
8728  effect(USE_DEF dst, USE src1, USE src2);
8729  size(4);
8730  format %{ "ASR  $dst.hi,$src1.hi,$src2 \n\t" %}
8731  ins_encode %{
8732    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register));
8733  %}
8734  ins_pipe(ialu_reg_reg);
8735%}
8736
8737instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
8738  effect(DEF dst, USE src1, USE src2, KILL ccr);
8739  size(16);
8740  format %{ "SUBS  $dst.lo,$src2,32 \n\t"
8741            "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t"
8742            "RSBmi $dst.lo,$dst.lo,0 \n\t"
8743            "LSLmi $dst.lo,$src1.hi,$dst.lo" %}
8744
8745  ins_encode %{
8746    // $src1$$Register->successor() and $dst$$Register can't be the same
8747    __ subs($dst$$Register, $src2$$Register, 32);
8748    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl);
8749    __ rsb($dst$$Register, $dst$$Register, 0, mi);
8750    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
8751  %}
8752  ins_pipe(ialu_reg_reg);
8753%}
8754#endif // !AARCH64
8755
8756instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
8757  match(Set dst (RShiftL src1 src2));
8758
8759#ifdef AARCH64
8760  size(4);
8761  format %{ "ASRV  $dst,$src1,$src2\t! long" %}
8762  ins_encode %{
8763    __ asrv($dst$$Register, $src1$$Register, $src2$$Register);
8764  %}
8765  ins_pipe(ialu_reg_reg);
8766#else
8767  expand %{
8768    flagsReg ccr;
8769    sarL_reg_reg_overlap(dst, src1, src2, ccr);
8770    sarL_reg_reg_merge_lo(dst, src1, src2);
8771    sarL_reg_reg_merge_hi(dst, src1, src2);
8772  %}
8773#endif
8774%}
8775
8776// Register Shift Left Immediate
8777#ifdef AARCH64
8778instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{
8779  match(Set dst (RShiftL src1 src2));
8780
8781  size(4);
8782  format %{ "ASR    $dst,$src1,$src2\t! long" %}
8783  ins_encode %{
8784    __ _asr($dst$$Register, $src1$$Register, $src2$$constant);
8785  %}
8786  ins_pipe(ialu_reg_imm);
8787%}
8788#else
8789instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
8790  match(Set dst (RShiftL src1 src2));
8791
8792  size(8);
8793  format %{ "ASR   $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
8794            "ASR   $dst.hi,$src1.hi, $src2" %}
8795  ins_encode %{
8796    if ($src2$$constant == 32) {
8797      __ mov($dst$$Register, $src1$$Register->successor());
8798    } else{
8799      __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32));
8800    }
8801    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0));
8802  %}
8803
8804  ins_pipe(ialu_reg_imm);
8805%}
8806
8807instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
8808  match(Set dst (RShiftL src1 src2));
8809  size(12);
8810  format %{ "LSR   $dst.lo,$src1.lo,$src2\n\t"
8811            "OR    $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
8812            "ASR   $dst.hi,$src1.hi,$src2" %}
8813  ins_encode %{
8814    // The order of the following 3 instructions matters: src1.lo and
8815    // dst.hi can't overlap but src.hi and dst.hi can.
8816    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
8817    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
8818    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant));
8819  %}
8820  ins_pipe(ialu_reg_imm);
8821%}
8822#endif
8823
8824// Register Shift Right
8825instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
8826  match(Set dst (URShiftI src1 src2));
8827  size(4);
8828#ifdef AARCH64
8829  format %{ "LSRV   $dst,$src1,$src2\t! int" %}
8830  ins_encode %{
8831    __ lsrv_w($dst$$Register, $src1$$Register, $src2$$Register);
8832  %}
8833#else
8834  format %{ "LSR    $dst,$src1,$src2\t! int" %}
8835  ins_encode %{
8836    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
8837  %}
8838#endif
8839  ins_pipe(ialu_reg_reg);
8840%}
8841
8842// Register Shift Right Immediate
8843instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
8844  match(Set dst (URShiftI src1 src2));
8845
8846  size(4);
8847#ifdef AARCH64
8848  format %{ "LSR_w  $dst,$src1,$src2" %}
8849  ins_encode %{
8850    __ _lsr_w($dst$$Register, $src1$$Register, $src2$$constant);
8851  %}
8852#else
8853  format %{ "LSR    $dst,$src1,$src2" %}
8854  ins_encode %{
8855    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
8856  %}
8857#endif
8858  ins_pipe(ialu_reg_imm);
8859%}
8860
8861#ifndef AARCH64
8862// Register Shift Right
8863instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
8864  effect(USE_DEF dst, USE src1, USE src2);
8865  size(4);
8866  format %{ "OR   $dst.lo,$dst,($src1.lo >>> $src2)"  %}
8867  ins_encode %{
8868    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
8869  %}
8870  ins_pipe(ialu_reg_reg);
8871%}
8872
8873instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
8874  effect(USE_DEF dst, USE src1, USE src2);
8875  size(4);
8876  format %{ "LSR  $dst.hi,$src1.hi,$src2 \n\t" %}
8877  ins_encode %{
8878    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register));
8879  %}
8880  ins_pipe(ialu_reg_reg);
8881%}
8882
8883instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
8884  effect(DEF dst, USE src1, USE src2, KILL ccr);
8885  size(16);
8886  format %{ "SUBS  $dst,$src2,32 \n\t"
8887            "LSRpl $dst,$src1.hi,$dst \n\t"
8888            "RSBmi $dst,$dst,0 \n\t"
8889            "LSLmi $dst,$src1.hi,$dst" %}
8890
8891  ins_encode %{
8892    // $src1$$Register->successor() and $dst$$Register can't be the same
8893    __ subs($dst$$Register, $src2$$Register, 32);
8894    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl);
8895    __ rsb($dst$$Register, $dst$$Register, 0, mi);
8896    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
8897  %}
8898  ins_pipe(ialu_reg_reg);
8899%}
8900#endif // !AARCH64
8901
8902instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
8903  match(Set dst (URShiftL src1 src2));
8904
8905#ifdef AARCH64
8906  size(4);
8907  format %{ "LSRV  $dst,$src1,$src2\t! long" %}
8908  ins_encode %{
8909    __ lsrv($dst$$Register, $src1$$Register, $src2$$Register);
8910  %}
8911  ins_pipe(ialu_reg_reg);
8912#else
8913  expand %{
8914    flagsReg ccr;
8915    shrL_reg_reg_overlap(dst, src1, src2, ccr);
8916    shrL_reg_reg_merge_lo(dst, src1, src2);
8917    shrL_reg_reg_merge_hi(dst, src1, src2);
8918  %}
8919#endif
8920%}
8921
8922// Register Shift Right Immediate
8923#ifdef AARCH64
8924instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{
8925  match(Set dst (URShiftL src1 src2));
8926
8927  size(4);
8928  format %{ "LSR    $dst,$src1,$src2" %}
8929  ins_encode %{
8930    __ _lsr($dst$$Register, $src1$$Register, $src2$$constant);
8931  %}
8932  ins_pipe(ialu_reg_imm);
8933%}
8934#else
8935instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
8936  match(Set dst (URShiftL src1 src2));
8937
8938  size(8);
8939  format %{ "LSR   $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
8940            "MOV   $dst.hi, 0" %}
8941  ins_encode %{
8942    if ($src2$$constant == 32) {
8943      __ mov($dst$$Register, $src1$$Register->successor());
8944    } else {
8945      __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32));
8946    }
8947    __ mov($dst$$Register->successor(), 0);
8948  %}
8949
8950  ins_pipe(ialu_reg_imm);
8951%}
8952
8953instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
8954  match(Set dst (URShiftL src1 src2));
8955
8956  size(12);
8957  format %{ "LSR   $dst.lo,$src1.lo,$src2\n\t"
8958            "OR    $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
8959            "LSR   $dst.hi,$src1.hi,$src2" %}
8960  ins_encode %{
8961    // The order of the following 3 instructions matters: src1.lo and
8962    // dst.hi can't overlap but src.hi and dst.hi can.
8963    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
8964    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
8965    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant));
8966  %}
8967  ins_pipe(ialu_reg_imm);
8968%}
8969#endif // !AARCH64
8970
8971
8972instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{
8973  match(Set dst (URShiftI (CastP2X src1) src2));
8974  size(4);
8975  format %{ "LSR    $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %}
8976  ins_encode %{
8977    __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant);
8978  %}
8979  ins_pipe(ialu_reg_imm);
8980%}
8981
8982//----------Floating Point Arithmetic Instructions-----------------------------
8983
8984//  Add float single precision
8985instruct addF_reg_reg(regF dst, regF src1, regF src2) %{
8986  match(Set dst (AddF src1 src2));
8987
8988  size(4);
8989  format %{ "FADDS  $dst,$src1,$src2" %}
8990  ins_encode %{
8991    __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
8992  %}
8993
8994  ins_pipe(faddF_reg_reg);
8995%}
8996
8997//  Add float double precision
8998instruct addD_reg_reg(regD dst, regD src1, regD src2) %{
8999  match(Set dst (AddD src1 src2));
9000
9001  size(4);
9002  format %{ "FADDD  $dst,$src1,$src2" %}
9003  ins_encode %{
9004    __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9005  %}
9006
9007  ins_pipe(faddD_reg_reg);
9008%}
9009
9010//  Sub float single precision
9011instruct subF_reg_reg(regF dst, regF src1, regF src2) %{
9012  match(Set dst (SubF src1 src2));
9013
9014  size(4);
9015  format %{ "FSUBS  $dst,$src1,$src2" %}
9016  ins_encode %{
9017    __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9018  %}
9019  ins_pipe(faddF_reg_reg);
9020%}
9021
9022//  Sub float double precision
9023instruct subD_reg_reg(regD dst, regD src1, regD src2) %{
9024  match(Set dst (SubD src1 src2));
9025
9026  size(4);
9027  format %{ "FSUBD  $dst,$src1,$src2" %}
9028  ins_encode %{
9029    __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9030  %}
9031  ins_pipe(faddD_reg_reg);
9032%}
9033
9034//  Mul float single precision
9035instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{
9036  match(Set dst (MulF src1 src2));
9037
9038  size(4);
9039  format %{ "FMULS  $dst,$src1,$src2" %}
9040  ins_encode %{
9041    __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9042  %}
9043
9044  ins_pipe(fmulF_reg_reg);
9045%}
9046
9047//  Mul float double precision
9048instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{
9049  match(Set dst (MulD src1 src2));
9050
9051  size(4);
9052  format %{ "FMULD  $dst,$src1,$src2" %}
9053  ins_encode %{
9054    __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9055  %}
9056
9057  ins_pipe(fmulD_reg_reg);
9058%}
9059
9060//  Div float single precision
9061instruct divF_reg_reg(regF dst, regF src1, regF src2) %{
9062  match(Set dst (DivF src1 src2));
9063
9064  size(4);
9065  format %{ "FDIVS  $dst,$src1,$src2" %}
9066  ins_encode %{
9067    __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9068  %}
9069
9070  ins_pipe(fdivF_reg_reg);
9071%}
9072
9073//  Div float double precision
9074instruct divD_reg_reg(regD dst, regD src1, regD src2) %{
9075  match(Set dst (DivD src1 src2));
9076
9077  size(4);
9078  format %{ "FDIVD  $dst,$src1,$src2" %}
9079  ins_encode %{
9080    __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9081  %}
9082
9083  ins_pipe(fdivD_reg_reg);
9084%}
9085
9086//  Absolute float double precision
9087instruct absD_reg(regD dst, regD src) %{
9088  match(Set dst (AbsD src));
9089
9090  size(4);
9091  format %{ "FABSd  $dst,$src" %}
9092  ins_encode %{
9093    __ abs_double($dst$$FloatRegister, $src$$FloatRegister);
9094  %}
9095  ins_pipe(faddD_reg);
9096%}
9097
9098//  Absolute float single precision
9099instruct absF_reg(regF dst, regF src) %{
9100  match(Set dst (AbsF src));
9101  format %{ "FABSs  $dst,$src" %}
9102  ins_encode %{
9103    __ abs_float($dst$$FloatRegister, $src$$FloatRegister);
9104  %}
9105  ins_pipe(faddF_reg);
9106%}
9107
9108instruct negF_reg(regF dst, regF src) %{
9109  match(Set dst (NegF src));
9110
9111  size(4);
9112  format %{ "FNEGs  $dst,$src" %}
9113  ins_encode %{
9114    __ neg_float($dst$$FloatRegister, $src$$FloatRegister);
9115  %}
9116  ins_pipe(faddF_reg);
9117%}
9118
9119instruct negD_reg(regD dst, regD src) %{
9120  match(Set dst (NegD src));
9121
9122  format %{ "FNEGd  $dst,$src" %}
9123  ins_encode %{
9124    __ neg_double($dst$$FloatRegister, $src$$FloatRegister);
9125  %}
9126  ins_pipe(faddD_reg);
9127%}
9128
9129//  Sqrt float double precision
9130instruct sqrtF_reg_reg(regF dst, regF src) %{
9131  match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
9132
9133  size(4);
9134  format %{ "FSQRTS $dst,$src" %}
9135  ins_encode %{
9136    __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister);
9137  %}
9138  ins_pipe(fdivF_reg_reg);
9139%}
9140
9141//  Sqrt float double precision
9142instruct sqrtD_reg_reg(regD dst, regD src) %{
9143  match(Set dst (SqrtD src));
9144
9145  size(4);
9146  format %{ "FSQRTD $dst,$src" %}
9147  ins_encode %{
9148    __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister);
9149  %}
9150  ins_pipe(fdivD_reg_reg);
9151%}
9152
9153//----------Logical Instructions-----------------------------------------------
9154// And Instructions
9155// Register And
9156instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
9157  match(Set dst (AndI src1 src2));
9158
9159  size(4);
9160  format %{ "and_32 $dst,$src1,$src2" %}
9161  ins_encode %{
9162    __ and_32($dst$$Register, $src1$$Register, $src2$$Register);
9163  %}
9164  ins_pipe(ialu_reg_reg);
9165%}
9166
9167#ifndef AARCH64
9168instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9169  match(Set dst (AndI src1 (LShiftI src2 src3)));
9170
9171  size(4);
9172  format %{ "AND    $dst,$src1,$src2<<$src3" %}
9173  ins_encode %{
9174    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
9175  %}
9176  ins_pipe(ialu_reg_reg);
9177%}
9178#endif
9179
9180instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9181  match(Set dst (AndI src1 (LShiftI src2 src3)));
9182
9183  size(4);
9184  format %{ "and_32 $dst,$src1,$src2<<$src3" %}
9185  ins_encode %{
9186    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
9187  %}
9188  ins_pipe(ialu_reg_reg);
9189%}
9190
9191#ifndef AARCH64
9192instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9193  match(Set dst (AndI src1 (RShiftI src2 src3)));
9194
9195  size(4);
9196  format %{ "AND    $dst,$src1,$src2>>$src3" %}
9197  ins_encode %{
9198    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
9199  %}
9200  ins_pipe(ialu_reg_reg);
9201%}
9202#endif
9203
9204instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9205  match(Set dst (AndI src1 (RShiftI src2 src3)));
9206
9207  size(4);
9208  format %{ "and_32 $dst,$src1,$src2>>$src3" %}
9209  ins_encode %{
9210    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
9211  %}
9212  ins_pipe(ialu_reg_reg);
9213%}
9214
9215#ifndef AARCH64
9216instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9217  match(Set dst (AndI src1 (URShiftI src2 src3)));
9218
9219  size(4);
9220  format %{ "AND    $dst,$src1,$src2>>>$src3" %}
9221  ins_encode %{
9222    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
9223  %}
9224  ins_pipe(ialu_reg_reg);
9225%}
9226#endif
9227
9228instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9229  match(Set dst (AndI src1 (URShiftI src2 src3)));
9230
9231  size(4);
9232  format %{ "and_32 $dst,$src1,$src2>>>$src3" %}
9233  ins_encode %{
9234    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
9235  %}
9236  ins_pipe(ialu_reg_reg);
9237%}
9238
9239// Immediate And
9240instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
9241  match(Set dst (AndI src1 src2));
9242
9243  size(4);
9244  format %{ "and_32 $dst,$src1,$src2\t! int" %}
9245  ins_encode %{
9246    __ and_32($dst$$Register, $src1$$Register, $src2$$constant);
9247  %}
9248  ins_pipe(ialu_reg_imm);
9249%}
9250
9251#ifndef AARCH64
9252instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{
9253  match(Set dst (AndI src1 src2));
9254
9255  size(4);
9256  format %{ "bic    $dst,$src1,~$src2\t! int" %}
9257  ins_encode %{
9258    __ bic($dst$$Register, $src1$$Register, ~$src2$$constant);
9259  %}
9260  ins_pipe(ialu_reg_imm);
9261%}
9262#endif
9263
9264// Register And Long
9265instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
9266  match(Set dst (AndL src1 src2));
9267
9268  ins_cost(DEFAULT_COST);
9269#ifdef AARCH64
9270  size(4);
9271  format %{ "AND    $dst,$src1,$src2\t! long" %}
9272  ins_encode %{
9273    __ andr($dst$$Register, $src1$$Register, $src2$$Register);
9274  %}
9275#else
9276  size(8);
9277  format %{ "AND    $dst,$src1,$src2\t! long" %}
9278  ins_encode %{
9279    __ andr($dst$$Register, $src1$$Register, $src2$$Register);
9280    __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
9281  %}
9282#endif
9283  ins_pipe(ialu_reg_reg);
9284%}
9285
9286#ifdef AARCH64
9287// Immediate And
9288instruct andL_reg_limm(iRegL dst, iRegL src1, limmL src2) %{
9289  match(Set dst (AndL src1 src2));
9290
9291  size(4);
9292  format %{ "AND    $dst,$src1,$src2\t! long" %}
9293  ins_encode %{
9294    __ andr($dst$$Register, $src1$$Register, (uintx)$src2$$constant);
9295  %}
9296  ins_pipe(ialu_reg_imm);
9297%}
9298#else
9299// TODO: try immLRot2 instead, (0, $con$$constant) becomes
9300// (hi($con$$constant), lo($con$$constant)) becomes
9301instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
9302  match(Set dst (AndL src1 con));
9303  ins_cost(DEFAULT_COST);
9304  size(8);
9305  format %{ "AND    $dst,$src1,$con\t! long" %}
9306  ins_encode %{
9307    __ andr($dst$$Register, $src1$$Register, $con$$constant);
9308    __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0);
9309  %}
9310  ins_pipe(ialu_reg_imm);
9311%}
9312#endif
9313
9314// Or Instructions
9315// Register Or
9316instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
9317  match(Set dst (OrI src1 src2));
9318
9319  size(4);
9320  format %{ "orr_32 $dst,$src1,$src2\t! int" %}
9321  ins_encode %{
9322    __ orr_32($dst$$Register, $src1$$Register, $src2$$Register);
9323  %}
9324  ins_pipe(ialu_reg_reg);
9325%}
9326
9327#ifndef AARCH64
9328instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9329  match(Set dst (OrI src1 (LShiftI src2 src3)));
9330
9331  size(4);
9332  format %{ "OR    $dst,$src1,$src2<<$src3" %}
9333  ins_encode %{
9334    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
9335  %}
9336  ins_pipe(ialu_reg_reg);
9337%}
9338#endif
9339
9340instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9341  match(Set dst (OrI src1 (LShiftI src2 src3)));
9342
9343  size(4);
9344  format %{ "orr_32 $dst,$src1,$src2<<$src3" %}
9345  ins_encode %{
9346    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
9347  %}
9348  ins_pipe(ialu_reg_reg);
9349%}
9350
9351#ifndef AARCH64
9352instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9353  match(Set dst (OrI src1 (RShiftI src2 src3)));
9354
9355  size(4);
9356  format %{ "OR    $dst,$src1,$src2>>$src3" %}
9357  ins_encode %{
9358    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
9359  %}
9360  ins_pipe(ialu_reg_reg);
9361%}
9362#endif
9363
9364instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9365  match(Set dst (OrI src1 (RShiftI src2 src3)));
9366
9367  size(4);
9368  format %{ "orr_32 $dst,$src1,$src2>>$src3" %}
9369  ins_encode %{
9370    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
9371  %}
9372  ins_pipe(ialu_reg_reg);
9373%}
9374
9375#ifndef AARCH64
9376instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9377  match(Set dst (OrI src1 (URShiftI src2 src3)));
9378
9379  size(4);
9380  format %{ "OR    $dst,$src1,$src2>>>$src3" %}
9381  ins_encode %{
9382    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
9383  %}
9384  ins_pipe(ialu_reg_reg);
9385%}
9386#endif
9387
9388instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9389  match(Set dst (OrI src1 (URShiftI src2 src3)));
9390
9391  size(4);
9392  format %{ "orr_32 $dst,$src1,$src2>>>$src3" %}
9393  ins_encode %{
9394    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
9395  %}
9396  ins_pipe(ialu_reg_reg);
9397%}
9398
9399// Immediate Or
9400instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
9401  match(Set dst (OrI src1 src2));
9402
9403  size(4);
9404  format %{ "orr_32  $dst,$src1,$src2" %}
9405  ins_encode %{
9406    __ orr_32($dst$$Register, $src1$$Register, $src2$$constant);
9407  %}
9408  ins_pipe(ialu_reg_imm);
9409%}
9410// TODO: orn_32 with limmIn
9411
9412// Register Or Long
9413instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
9414  match(Set dst (OrL src1 src2));
9415
9416  ins_cost(DEFAULT_COST);
9417#ifdef AARCH64
9418  size(4);
9419  format %{ "OR     $dst,$src1,$src2\t! long" %}
9420  ins_encode %{
9421    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
9422  %}
9423#else
9424  size(8);
9425  format %{ "OR     $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
9426            "OR     $dst.hi,$src1.hi,$src2.hi" %}
9427  ins_encode %{
9428    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
9429    __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
9430  %}
9431#endif
9432  ins_pipe(ialu_reg_reg);
9433%}
9434
9435#ifdef AARCH64
9436instruct orL_reg_limm(iRegL dst, iRegL src1, limmL src2) %{
9437  match(Set dst (OrL src1 src2));
9438
9439  size(4);
9440  format %{ "ORR    $dst,$src1,$src2\t! long" %}
9441  ins_encode %{
9442    __ orr($dst$$Register, $src1$$Register, (uintx)$src2$$constant);
9443  %}
9444  ins_pipe(ialu_reg_imm);
9445%}
9446#else
9447// TODO: try immLRot2 instead, (0, $con$$constant) becomes
9448// (hi($con$$constant), lo($con$$constant)) becomes
9449instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
9450  match(Set dst (OrL src1 con));
9451  ins_cost(DEFAULT_COST);
9452  size(8);
9453  format %{ "OR     $dst.lo,$src1.lo,$con\t! long\n\t"
9454            "OR     $dst.hi,$src1.hi,$con" %}
9455  ins_encode %{
9456    __ orr($dst$$Register, $src1$$Register, $con$$constant);
9457    __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0);
9458  %}
9459  ins_pipe(ialu_reg_imm);
9460%}
9461#endif
9462
9463#ifdef TODO
9464// Use SPRegP to match Rthread (TLS register) without spilling.
9465// Use store_ptr_RegP to match Rthread (TLS register) without spilling.
9466// Use sp_ptr_RegP to match Rthread (TLS register) without spilling.
9467instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{
9468  match(Set dst (OrI src1 (CastP2X src2)));
9469  size(4);
9470  format %{ "OR     $dst,$src1,$src2" %}
9471  ins_encode %{
9472    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
9473  %}
9474  ins_pipe(ialu_reg_reg);
9475%}
9476#endif
9477
9478// Xor Instructions
9479// Register Xor
9480instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
9481  match(Set dst (XorI src1 src2));
9482
9483  size(4);
9484  format %{ "eor_32 $dst,$src1,$src2" %}
9485  ins_encode %{
9486    __ eor_32($dst$$Register, $src1$$Register, $src2$$Register);
9487  %}
9488  ins_pipe(ialu_reg_reg);
9489%}
9490
9491#ifndef AARCH64
9492instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9493  match(Set dst (XorI src1 (LShiftI src2 src3)));
9494
9495  size(4);
9496  format %{ "XOR    $dst,$src1,$src2<<$src3" %}
9497  ins_encode %{
9498    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
9499  %}
9500  ins_pipe(ialu_reg_reg);
9501%}
9502#endif
9503
9504instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9505  match(Set dst (XorI src1 (LShiftI src2 src3)));
9506
9507  size(4);
9508  format %{ "eor_32 $dst,$src1,$src2<<$src3" %}
9509  ins_encode %{
9510    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
9511  %}
9512  ins_pipe(ialu_reg_reg);
9513%}
9514
9515#ifndef AARCH64
9516instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9517  match(Set dst (XorI src1 (RShiftI src2 src3)));
9518
9519  size(4);
9520  format %{ "XOR    $dst,$src1,$src2>>$src3" %}
9521  ins_encode %{
9522    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
9523  %}
9524  ins_pipe(ialu_reg_reg);
9525%}
9526#endif
9527
9528instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9529  match(Set dst (XorI src1 (RShiftI src2 src3)));
9530
9531  size(4);
9532  format %{ "eor_32 $dst,$src1,$src2>>$src3" %}
9533  ins_encode %{
9534    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
9535  %}
9536  ins_pipe(ialu_reg_reg);
9537%}
9538
9539#ifndef AARCH64
9540instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
9541  match(Set dst (XorI src1 (URShiftI src2 src3)));
9542
9543  size(4);
9544  format %{ "XOR    $dst,$src1,$src2>>>$src3" %}
9545  ins_encode %{
9546    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
9547  %}
9548  ins_pipe(ialu_reg_reg);
9549%}
9550#endif
9551
9552instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
9553  match(Set dst (XorI src1 (URShiftI src2 src3)));
9554
9555  size(4);
9556  format %{ "eor_32 $dst,$src1,$src2>>>$src3" %}
9557  ins_encode %{
9558    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
9559  %}
9560  ins_pipe(ialu_reg_reg);
9561%}
9562
9563// Immediate Xor
9564instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{
9565  match(Set dst (XorI src1 src2));
9566
9567  size(4);
9568  format %{ "eor_32 $dst,$src1,$src2" %}
9569  ins_encode %{
9570    __ eor_32($dst$$Register, $src1$$Register, $src2$$constant);
9571  %}
9572  ins_pipe(ialu_reg_imm);
9573%}
9574
9575// Register Xor Long
9576instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
9577  match(Set dst (XorL src1 src2));
9578  ins_cost(DEFAULT_COST);
9579#ifdef AARCH64
9580  size(4);
9581  format %{ "XOR     $dst,$src1,$src2\t! long" %}
9582  ins_encode %{
9583    __ eor($dst$$Register, $src1$$Register, $src2$$Register);
9584  %}
9585#else
9586  size(8);
9587  format %{ "XOR     $dst.hi,$src1.hi,$src2.hi\t! long\n\t"
9588            "XOR     $dst.lo,$src1.lo,$src2.lo\t! long" %}
9589  ins_encode %{
9590    __ eor($dst$$Register, $src1$$Register, $src2$$Register);
9591    __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
9592  %}
9593#endif
9594  ins_pipe(ialu_reg_reg);
9595%}
9596
9597#ifdef AARCH64
9598instruct xorL_reg_limmL(iRegL dst, iRegL src1, limmL con) %{
9599  match(Set dst (XorL src1 con));
9600  ins_cost(DEFAULT_COST);
9601  size(4);
9602  format %{ "EOR     $dst,$src1,$con\t! long" %}
9603  ins_encode %{
9604    __ eor($dst$$Register, $src1$$Register, (uintx)$con$$constant);
9605  %}
9606  ins_pipe(ialu_reg_imm);
9607%}
9608#else
9609// TODO: try immLRot2 instead, (0, $con$$constant) becomes
9610// (hi($con$$constant), lo($con$$constant)) becomes
9611instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
9612  match(Set dst (XorL src1 con));
9613  ins_cost(DEFAULT_COST);
9614  size(8);
9615  format %{ "XOR     $dst.hi,$src1.hi,$con\t! long\n\t"
9616            "XOR     $dst.lo,$src1.lo,0\t! long" %}
9617  ins_encode %{
9618    __ eor($dst$$Register, $src1$$Register, $con$$constant);
9619    __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0);
9620  %}
9621  ins_pipe(ialu_reg_imm);
9622%}
9623#endif // AARCH64
9624
9625//----------Convert to Boolean-------------------------------------------------
9626instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{
9627  match(Set dst (Conv2B src));
9628  effect(KILL ccr);
9629#ifdef AARCH64
9630  size(8);
9631  ins_cost(DEFAULT_COST*2);
9632  format %{ "cmp_32 $src,ZR\n\t"
9633            "cset_w $dst, ne" %}
9634  ins_encode %{
9635    __ cmp_32($src$$Register, ZR);
9636    __ cset_w($dst$$Register, ne);
9637  %}
9638#else
9639  size(12);
9640  ins_cost(DEFAULT_COST*2);
9641  format %{ "TST    $src,$src \n\t"
9642            "MOV    $dst, 0   \n\t"
9643            "MOV.ne $dst, 1" %}
9644  ins_encode %{ // FIXME: can do better?
9645    __ tst($src$$Register, $src$$Register);
9646    __ mov($dst$$Register, 0);
9647    __ mov($dst$$Register, 1, ne);
9648  %}
9649#endif
9650  ins_pipe(ialu_reg_ialu);
9651%}
9652
9653instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{
9654  match(Set dst (Conv2B src));
9655  effect(KILL ccr);
9656#ifdef AARCH64
9657  size(8);
9658  ins_cost(DEFAULT_COST*2);
9659  format %{ "CMP    $src,ZR\n\t"
9660            "cset   $dst, ne" %}
9661  ins_encode %{
9662    __ cmp($src$$Register, ZR);
9663    __ cset($dst$$Register, ne);
9664  %}
9665#else
9666  size(12);
9667  ins_cost(DEFAULT_COST*2);
9668  format %{ "TST    $src,$src \n\t"
9669            "MOV    $dst, 0   \n\t"
9670            "MOV.ne $dst, 1" %}
9671  ins_encode %{
9672    __ tst($src$$Register, $src$$Register);
9673    __ mov($dst$$Register, 0);
9674    __ mov($dst$$Register, 1, ne);
9675  %}
9676#endif
9677  ins_pipe(ialu_reg_ialu);
9678%}
9679
9680instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
9681  match(Set dst (CmpLTMask p q));
9682  effect( KILL ccr );
9683#ifdef AARCH64
9684  size(8);
9685  ins_cost(DEFAULT_COST*2);
9686  format %{ "CMP_w   $p,$q\n\t"
9687            "CSETM_w $dst, lt" %}
9688  ins_encode %{
9689    __ cmp_w($p$$Register, $q$$Register);
9690    __ csetm_w($dst$$Register, lt);
9691  %}
9692#else
9693  ins_cost(DEFAULT_COST*3);
9694  format %{ "CMP    $p,$q\n\t"
9695            "MOV    $dst, #0\n\t"
9696            "MOV.lt $dst, #-1" %}
9697  ins_encode %{
9698    __ cmp($p$$Register, $q$$Register);
9699    __ mov($dst$$Register, 0);
9700    __ mvn($dst$$Register, 0, lt);
9701  %}
9702#endif
9703  ins_pipe(ialu_reg_reg_ialu);
9704%}
9705
9706instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{
9707  match(Set dst (CmpLTMask p q));
9708  effect( KILL ccr );
9709#ifdef AARCH64
9710  size(8);
9711  ins_cost(DEFAULT_COST*2);
9712  format %{ "CMP_w   $p,$q\n\t"
9713            "CSETM_w $dst, lt" %}
9714  ins_encode %{
9715    __ cmp_w($p$$Register, $q$$constant);
9716    __ csetm_w($dst$$Register, lt);
9717  %}
9718#else
9719  ins_cost(DEFAULT_COST*3);
9720  format %{ "CMP    $p,$q\n\t"
9721            "MOV    $dst, #0\n\t"
9722            "MOV.lt $dst, #-1" %}
9723  ins_encode %{
9724    __ cmp($p$$Register, $q$$constant);
9725    __ mov($dst$$Register, 0);
9726    __ mvn($dst$$Register, 0, lt);
9727  %}
9728#endif
9729  ins_pipe(ialu_reg_reg_ialu);
9730%}
9731
9732#ifdef AARCH64
9733instruct cadd_cmpLTMask3( iRegI dst, iRegI p, iRegI q, iRegI y, iRegI x, flagsReg ccr ) %{
9734  match(Set dst (AddI (AndI (CmpLTMask p q) y) x));
9735  effect( TEMP dst, KILL ccr );
9736  size(12);
9737  ins_cost(DEFAULT_COST*3);
9738  format %{ "CMP_w  $p,$q\n\t"
9739            "ADD_w  $dst,$y,$x\n\t"
9740            "CSEL_w $dst,$dst,$x,lt" %}
9741  ins_encode %{
9742    __ cmp_w($p$$Register, $q$$Register);
9743    __ add_w($dst$$Register, $y$$Register, $x$$Register);
9744    __ csel_w($dst$$Register, $dst$$Register, $x$$Register, lt);
9745  %}
9746  ins_pipe( cadd_cmpltmask );
9747%}
9748#else
9749instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{
9750  match(Set z (AddI (AndI (CmpLTMask p q) y) z));
9751  effect( KILL ccr );
9752  ins_cost(DEFAULT_COST*2);
9753  format %{ "CMP    $p,$q\n\t"
9754            "ADD.lt $z,$y,$z" %}
9755  ins_encode %{
9756    __ cmp($p$$Register, $q$$Register);
9757    __ add($z$$Register, $y$$Register, $z$$Register, lt);
9758  %}
9759  ins_pipe( cadd_cmpltmask );
9760%}
9761#endif
9762
9763#ifdef AARCH64
9764instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI x, flagsReg ccr ) %{
9765  match(Set dst (AddI (AndI (CmpLTMask p q) y) x));
9766  effect( TEMP dst, KILL ccr );
9767  size(12);
9768  ins_cost(DEFAULT_COST*3);
9769  format %{ "CMP_w  $p,$q\n\t"
9770            "ADD_w  $dst,$y,$x\n\t"
9771            "CSEL_w $dst,$dst,$x,lt" %}
9772  ins_encode %{
9773    __ cmp_w($p$$Register, $q$$constant);
9774    __ add_w($dst$$Register, $y$$Register, $x$$Register);
9775    __ csel_w($dst$$Register, $dst$$Register, $x$$Register, lt);
9776  %}
9777  ins_pipe( cadd_cmpltmask );
9778%}
9779#else
9780// FIXME: remove unused "dst"
9781instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{
9782  match(Set z (AddI (AndI (CmpLTMask p q) y) z));
9783  effect( KILL ccr );
9784  ins_cost(DEFAULT_COST*2);
9785  format %{ "CMP    $p,$q\n\t"
9786            "ADD.lt $z,$y,$z" %}
9787  ins_encode %{
9788    __ cmp($p$$Register, $q$$constant);
9789    __ add($z$$Register, $y$$Register, $z$$Register, lt);
9790  %}
9791  ins_pipe( cadd_cmpltmask );
9792%}
9793#endif // !AARCH64
9794
9795#ifdef AARCH64
9796instruct cadd_cmpLTMask( iRegI dst, iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
9797  match(Set dst (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
9798  effect( TEMP dst, KILL ccr );
9799  size(12);
9800  ins_cost(DEFAULT_COST*3);
9801  format %{ "SUBS_w $p,$p,$q\n\t"
9802            "ADD_w  $dst,$y,$p\n\t"
9803            "CSEL_w $dst,$dst,$p,lt" %}
9804  ins_encode %{
9805    __ subs_w($p$$Register, $p$$Register, $q$$Register);
9806    __ add_w($dst$$Register, $y$$Register, $p$$Register);
9807    __ csel_w($dst$$Register, $dst$$Register, $p$$Register, lt);
9808  %}
9809  ins_pipe( cadd_cmpltmask ); // FIXME
9810%}
9811#else
9812instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
9813  match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
9814  effect( KILL ccr );
9815  ins_cost(DEFAULT_COST*2);
9816  format %{ "SUBS   $p,$p,$q\n\t"
9817            "ADD.lt $p,$y,$p" %}
9818  ins_encode %{
9819    __ subs($p$$Register, $p$$Register, $q$$Register);
9820    __ add($p$$Register, $y$$Register, $p$$Register, lt);
9821  %}
9822  ins_pipe( cadd_cmpltmask );
9823%}
9824#endif
9825
9826//----------Arithmetic Conversion Instructions---------------------------------
9827// The conversions operations are all Alpha sorted.  Please keep it that way!
9828
9829instruct convD2F_reg(regF dst, regD src) %{
9830  match(Set dst (ConvD2F src));
9831  size(4);
9832  format %{ "FCVTSD  $dst,$src" %}
9833  ins_encode %{
9834    __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister);
9835  %}
9836  ins_pipe(fcvtD2F);
9837%}
9838
9839// Convert a double to an int in a float register.
9840// If the double is a NAN, stuff a zero in instead.
9841
9842#ifdef AARCH64
9843instruct convD2I_reg_reg(iRegI dst, regD src) %{
9844  match(Set dst (ConvD2I src));
9845  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9846  format %{ "FCVTZS_wd $dst, $src" %}
9847  ins_encode %{
9848    __ fcvtzs_wd($dst$$Register, $src$$FloatRegister);
9849  %}
9850  ins_pipe(fcvtD2I);
9851%}
9852
9853instruct convD2L_reg_reg(iRegL dst, regD src) %{
9854  match(Set dst (ConvD2L src));
9855  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9856  format %{ "FCVTZS_xd $dst, $src" %}
9857  ins_encode %{
9858    __ fcvtzs_xd($dst$$Register, $src$$FloatRegister);
9859  %}
9860  ins_pipe(fcvtD2L);
9861%}
9862#else
9863instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{
9864  match(Set dst (ConvD2I src));
9865  effect( TEMP tmp );
9866  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9867  format %{ "FTOSIZD  $tmp,$src\n\t"
9868            "FMRS     $dst, $tmp" %}
9869  ins_encode %{
9870    __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister);
9871    __ fmrs($dst$$Register, $tmp$$FloatRegister);
9872  %}
9873  ins_pipe(fcvtD2I);
9874%}
9875#endif
9876
9877// Convert a double to a long in a double register.
9878// If the double is a NAN, stuff a zero in instead.
9879
9880#ifndef AARCH64
9881// Double to Long conversion
9882instruct convD2L_reg(R0R1RegL dst, regD src) %{
9883  match(Set dst (ConvD2L src));
9884  effect(CALL);
9885  ins_cost(MEMORY_REF_COST); // FIXME
9886  format %{ "convD2L    $dst,$src\t ! call to SharedRuntime::d2l" %}
9887  ins_encode %{
9888#ifndef __ABI_HARD__
9889    __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
9890#else
9891    if ($src$$FloatRegister != D0) {
9892      __ mov_double(D0, $src$$FloatRegister);
9893    }
9894#endif
9895    address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
9896    __ call(target, relocInfo::runtime_call_type);
9897  %}
9898  ins_pipe(fcvtD2L);
9899%}
9900#endif
9901
9902instruct convF2D_reg(regD dst, regF src) %{
9903  match(Set dst (ConvF2D src));
9904  size(4);
9905  format %{ "FCVTDS  $dst,$src" %}
9906  ins_encode %{
9907    __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister);
9908  %}
9909  ins_pipe(fcvtF2D);
9910%}
9911
9912#ifdef AARCH64
9913instruct convF2I_reg_reg(iRegI dst, regF src) %{
9914  match(Set dst (ConvF2I src));
9915  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9916  size(4);
9917  format %{ "FCVTZS_ws $dst, $src" %}
9918  ins_encode %{
9919    __ fcvtzs_ws($dst$$Register, $src$$FloatRegister);
9920  %}
9921  ins_pipe(fcvtF2I);
9922%}
9923
9924instruct convF2L_reg_reg(iRegL dst, regF src) %{
9925  match(Set dst (ConvF2L src));
9926  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9927  size(4);
9928  format %{ "FCVTZS_xs $dst, $src" %}
9929  ins_encode %{
9930    __ fcvtzs_xs($dst$$Register, $src$$FloatRegister);
9931  %}
9932  ins_pipe(fcvtF2L);
9933%}
9934#else
9935instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{
9936  match(Set dst (ConvF2I src));
9937  effect( TEMP tmp );
9938  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9939  size(8);
9940  format %{ "FTOSIZS  $tmp,$src\n\t"
9941            "FMRS     $dst, $tmp" %}
9942  ins_encode %{
9943    __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister);
9944    __ fmrs($dst$$Register, $tmp$$FloatRegister);
9945  %}
9946  ins_pipe(fcvtF2I);
9947%}
9948
9949// Float to Long conversion
9950instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{
9951  match(Set dst (ConvF2L src));
9952  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
9953  effect(CALL);
9954  format %{ "convF2L  $dst,$src\t! call to SharedRuntime::f2l" %}
9955  ins_encode %{
9956#ifndef __ABI_HARD__
9957    __ fmrs($arg1$$Register, $src$$FloatRegister);
9958#else
9959    if($src$$FloatRegister != S0) {
9960      __ mov_float(S0, $src$$FloatRegister);
9961    }
9962#endif
9963    address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
9964    __ call(target, relocInfo::runtime_call_type);
9965  %}
9966  ins_pipe(fcvtF2L);
9967%}
9968#endif
9969
9970#ifdef AARCH64
9971instruct convI2D_reg_reg(iRegI src, regD dst) %{
9972  match(Set dst (ConvI2D src));
9973  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
9974  size(4);
9975  format %{ "SCVTF_dw $dst,$src" %}
9976  ins_encode %{
9977      __ scvtf_dw($dst$$FloatRegister, $src$$Register);
9978  %}
9979  ins_pipe(fcvtI2D);
9980%}
9981#else
9982instruct convI2D_reg_reg(iRegI src, regD_low dst) %{
9983  match(Set dst (ConvI2D src));
9984  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
9985  size(8);
9986  format %{ "FMSR     $dst,$src \n\t"
9987            "FSITOD   $dst $dst"%}
9988  ins_encode %{
9989      __ fmsr($dst$$FloatRegister, $src$$Register);
9990      __ fsitod($dst$$FloatRegister, $dst$$FloatRegister);
9991  %}
9992  ins_pipe(fcvtI2D);
9993%}
9994#endif
9995
9996instruct convI2F_reg_reg( regF dst, iRegI src ) %{
9997  match(Set dst (ConvI2F src));
9998  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
9999#ifdef AARCH64
10000  size(4);
10001  format %{ "SCVTF_sw $dst,$src" %}
10002  ins_encode %{
10003      __ scvtf_sw($dst$$FloatRegister, $src$$Register);
10004  %}
10005#else
10006  size(8);
10007  format %{ "FMSR     $dst,$src \n\t"
10008            "FSITOS   $dst, $dst"%}
10009  ins_encode %{
10010      __ fmsr($dst$$FloatRegister, $src$$Register);
10011      __ fsitos($dst$$FloatRegister, $dst$$FloatRegister);
10012  %}
10013#endif
10014  ins_pipe(fcvtI2F);
10015%}
10016
10017instruct convI2L_reg(iRegL dst, iRegI src) %{
10018  match(Set dst (ConvI2L src));
10019#ifdef AARCH64
10020  size(4);
10021  format %{ "SXTW   $dst,$src\t! int->long" %}
10022  ins_encode %{
10023    __ sxtw($dst$$Register, $src$$Register);
10024  %}
10025#else
10026  size(8);
10027  format %{ "MOV    $dst.lo, $src \n\t"
10028            "ASR    $dst.hi,$src,31\t! int->long" %}
10029  ins_encode %{
10030    __ mov($dst$$Register, $src$$Register);
10031    __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31));
10032  %}
10033#endif
10034  ins_pipe(ialu_reg_reg);
10035%}
10036
10037// Zero-extend convert int to long
10038instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{
10039  match(Set dst (AndL (ConvI2L src) mask) );
10040#ifdef AARCH64
10041  size(4);
10042  format %{ "mov_w  $dst,$src\t! zero-extend int to long"  %}
10043  ins_encode %{
10044    __ mov_w($dst$$Register, $src$$Register);
10045  %}
10046#else
10047  size(8);
10048  format %{ "MOV    $dst.lo,$src.lo\t! zero-extend int to long\n\t"
10049            "MOV    $dst.hi, 0"%}
10050  ins_encode %{
10051    __ mov($dst$$Register, $src$$Register);
10052    __ mov($dst$$Register->successor(), 0);
10053  %}
10054#endif
10055  ins_pipe(ialu_reg_reg);
10056%}
10057
10058// Zero-extend long
10059instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
10060  match(Set dst (AndL src mask) );
10061#ifdef AARCH64
10062  size(4);
10063  format %{ "mov_w  $dst,$src\t! zero-extend long"  %}
10064  ins_encode %{
10065    __ mov_w($dst$$Register, $src$$Register);
10066  %}
10067#else
10068  size(8);
10069  format %{ "MOV    $dst.lo,$src.lo\t! zero-extend long\n\t"
10070            "MOV    $dst.hi, 0"%}
10071  ins_encode %{
10072    __ mov($dst$$Register, $src$$Register);
10073    __ mov($dst$$Register->successor(), 0);
10074  %}
10075#endif
10076  ins_pipe(ialu_reg_reg);
10077%}
10078
10079instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
10080  match(Set dst (MoveF2I src));
10081  effect(DEF dst, USE src);
10082  ins_cost(MEMORY_REF_COST); // FIXME
10083
10084  size(4);
10085  format %{ "FMRS   $dst,$src\t! MoveF2I" %}
10086  ins_encode %{
10087    __ fmrs($dst$$Register, $src$$FloatRegister);
10088  %}
10089  ins_pipe(iload_mem); // FIXME
10090%}
10091
10092instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
10093  match(Set dst (MoveI2F src));
10094  ins_cost(MEMORY_REF_COST); // FIXME
10095
10096  size(4);
10097  format %{ "FMSR   $dst,$src\t! MoveI2F" %}
10098  ins_encode %{
10099    __ fmsr($dst$$FloatRegister, $src$$Register);
10100  %}
10101  ins_pipe(iload_mem); // FIXME
10102%}
10103
10104instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
10105  match(Set dst (MoveD2L src));
10106  effect(DEF dst, USE src);
10107  ins_cost(MEMORY_REF_COST); // FIXME
10108
10109  size(4);
10110#ifdef AARCH64
10111  format %{ "FMOV_xd  $dst,$src\t! MoveD2L" %}
10112  ins_encode %{
10113    __ fmov_xd($dst$$Register, $src$$FloatRegister);
10114  %}
10115#else
10116  format %{ "FMRRD    $dst,$src\t! MoveD2L" %}
10117  ins_encode %{
10118    __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
10119  %}
10120#endif
10121  ins_pipe(iload_mem); // FIXME
10122%}
10123
10124instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
10125  match(Set dst (MoveL2D src));
10126  effect(DEF dst, USE src);
10127  ins_cost(MEMORY_REF_COST); // FIXME
10128
10129  size(4);
10130#ifdef AARCH64
10131  format %{ "FMOV_dx $dst,$src\t! MoveL2D" %}
10132  ins_encode %{
10133    __ fmov_dx($dst$$FloatRegister, $src$$Register);
10134  %}
10135#else
10136  format %{ "FMDRR   $dst,$src\t! MoveL2D" %}
10137  ins_encode %{
10138    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
10139  %}
10140#endif
10141  ins_pipe(ialu_reg_reg); // FIXME
10142%}
10143
10144//-----------
10145// Long to Double conversion
10146
10147#ifdef AARCH64
10148instruct convL2D(regD dst, iRegL src) %{
10149  match(Set dst (ConvL2D src));
10150  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
10151  size(4);
10152  format %{ "SCVTF_dx $dst, $src" %}
10153  ins_encode %{
10154    __ scvtf_dx($dst$$FloatRegister, $src$$Register);
10155  %}
10156  ins_pipe(fcvtL2D);
10157%}
10158
10159instruct convL2F(regF dst, iRegL src) %{
10160  match(Set dst (ConvL2F src));
10161  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
10162  size(4);
10163  format %{ "SCVTF_sx $dst, $src" %}
10164  ins_encode %{
10165    __ scvtf_sx($dst$$FloatRegister, $src$$Register);
10166  %}
10167  ins_pipe(fcvtL2F);
10168%}
10169#else
10170// Magic constant, 0x43300000
10171instruct loadConI_x43300000(iRegI dst) %{
10172  effect(DEF dst);
10173  size(8);
10174  format %{ "MOV_SLOW  $dst,0x43300000\t! 2^52" %}
10175  ins_encode %{
10176    __ mov_slow($dst$$Register, 0x43300000);
10177  %}
10178  ins_pipe(ialu_none);
10179%}
10180
10181// Magic constant, 0x41f00000
10182instruct loadConI_x41f00000(iRegI dst) %{
10183  effect(DEF dst);
10184  size(8);
10185  format %{ "MOV_SLOW  $dst, 0x41f00000\t! 2^32" %}
10186  ins_encode %{
10187    __ mov_slow($dst$$Register, 0x41f00000);
10188  %}
10189  ins_pipe(ialu_none);
10190%}
10191
10192instruct loadConI_x0(iRegI dst) %{
10193  effect(DEF dst);
10194  size(4);
10195  format %{ "MOV  $dst, 0x0\t! 0" %}
10196  ins_encode %{
10197    __ mov($dst$$Register, 0);
10198  %}
10199  ins_pipe(ialu_none);
10200%}
10201
10202// Construct a double from two float halves
10203instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{
10204  effect(DEF dst, USE src1, USE src2);
10205  size(8);
10206  format %{ "FCPYS  $dst.hi,$src1.hi\n\t"
10207            "FCPYS  $dst.lo,$src2.lo" %}
10208  ins_encode %{
10209    __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor());
10210    __ fcpys($dst$$FloatRegister, $src2$$FloatRegister);
10211  %}
10212  ins_pipe(faddD_reg_reg);
10213%}
10214
10215#ifndef AARCH64
10216// Convert integer in high half of a double register (in the lower half of
10217// the double register file) to double
10218instruct convI2D_regDHi_regD(regD dst, regD_low src) %{
10219  effect(DEF dst, USE src);
10220  size(4);
10221  format %{ "FSITOD  $dst,$src" %}
10222  ins_encode %{
10223    __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor());
10224  %}
10225  ins_pipe(fcvtLHi2D);
10226%}
10227#endif
10228
10229// Add float double precision
10230instruct addD_regD_regD(regD dst, regD src1, regD src2) %{
10231  effect(DEF dst, USE src1, USE src2);
10232  size(4);
10233  format %{ "FADDD  $dst,$src1,$src2" %}
10234  ins_encode %{
10235    __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10236  %}
10237  ins_pipe(faddD_reg_reg);
10238%}
10239
10240// Sub float double precision
10241instruct subD_regD_regD(regD dst, regD src1, regD src2) %{
10242  effect(DEF dst, USE src1, USE src2);
10243  size(4);
10244  format %{ "FSUBD  $dst,$src1,$src2" %}
10245  ins_encode %{
10246    __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10247  %}
10248  ins_pipe(faddD_reg_reg);
10249%}
10250
10251// Mul float double precision
10252instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{
10253  effect(DEF dst, USE src1, USE src2);
10254  size(4);
10255  format %{ "FMULD  $dst,$src1,$src2" %}
10256  ins_encode %{
10257    __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10258  %}
10259  ins_pipe(fmulD_reg_reg);
10260%}
10261
10262instruct regL_to_regD(regD dst, iRegL src) %{
10263  // No match rule to avoid chain rule match.
10264  effect(DEF dst, USE src);
10265  ins_cost(MEMORY_REF_COST);
10266  size(4);
10267  format %{ "FMDRR   $dst,$src\t! regL to regD" %}
10268  ins_encode %{
10269    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
10270  %}
10271  ins_pipe(ialu_reg_reg); // FIXME
10272%}
10273
10274instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{
10275  // No match rule to avoid chain rule match.
10276  effect(DEF dst, USE src1, USE src2);
10277  ins_cost(MEMORY_REF_COST);
10278  size(4);
10279  format %{ "FMDRR   $dst,$src1,$src2\t! regI,regI to regD" %}
10280  ins_encode %{
10281    __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register);
10282  %}
10283  ins_pipe(ialu_reg_reg); // FIXME
10284%}
10285
10286instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{
10287  match(Set dst (ConvL2D src));
10288  ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME
10289
10290  expand %{
10291    regD_low   tmpsrc;
10292    iRegI      ix43300000;
10293    iRegI      ix41f00000;
10294    iRegI      ix0;
10295    regD_low   dx43300000;
10296    regD       dx41f00000;
10297    regD       tmp1;
10298    regD_low   tmp2;
10299    regD       tmp3;
10300    regD       tmp4;
10301
10302    regL_to_regD(tmpsrc, src);
10303
10304    loadConI_x43300000(ix43300000);
10305    loadConI_x41f00000(ix41f00000);
10306    loadConI_x0(ix0);
10307
10308    regI_regI_to_regD(dx43300000, ix0, ix43300000);
10309    regI_regI_to_regD(dx41f00000, ix0, ix41f00000);
10310
10311    convI2D_regDHi_regD(tmp1, tmpsrc);
10312    regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc);
10313    subD_regD_regD(tmp3, tmp2, dx43300000);
10314    mulD_regD_regD(tmp4, tmp1, dx41f00000);
10315    addD_regD_regD(dst, tmp3, tmp4);
10316  %}
10317%}
10318#endif // !AARCH64
10319
10320instruct convL2I_reg(iRegI dst, iRegL src) %{
10321  match(Set dst (ConvL2I src));
10322  size(4);
10323#ifdef AARCH64
10324  format %{ "MOV_w  $dst,$src\t! long->int" %}
10325  ins_encode %{
10326    __ mov_w($dst$$Register, $src$$Register);
10327  %}
10328#else
10329  format %{ "MOV    $dst,$src.lo\t! long->int" %}
10330  ins_encode %{
10331    __ mov($dst$$Register, $src$$Register);
10332  %}
10333#endif
10334  ins_pipe(ialu_move_reg_I_to_L);
10335%}
10336
10337#ifndef AARCH64
10338// Register Shift Right Immediate
10339instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{
10340  match(Set dst (ConvL2I (RShiftL src cnt)));
10341  size(4);
10342  format %{ "ASR    $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %}
10343  ins_encode %{
10344    if ($cnt$$constant == 32) {
10345      __ mov($dst$$Register, $src$$Register->successor());
10346    } else {
10347      __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32));
10348    }
10349  %}
10350  ins_pipe(ialu_reg_imm);
10351%}
10352#endif
10353
10354
10355//----------Control Flow Instructions------------------------------------------
10356// Compare Instructions
10357// Compare Integers
10358instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{
10359  match(Set icc (CmpI op1 op2));
10360  effect( DEF icc, USE op1, USE op2 );
10361
10362  size(4);
10363  format %{ "cmp_32 $op1,$op2\t! int" %}
10364  ins_encode %{
10365    __ cmp_32($op1$$Register, $op2$$Register);
10366  %}
10367  ins_pipe(ialu_cconly_reg_reg);
10368%}
10369
10370#ifdef _LP64
10371// Compare compressed pointers
10372instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{
10373  match(Set icc (CmpN op1 op2));
10374  effect( DEF icc, USE op1, USE op2 );
10375
10376  size(4);
10377  format %{ "cmp_32 $op1,$op2\t! int" %}
10378  ins_encode %{
10379    __ cmp_32($op1$$Register, $op2$$Register);
10380  %}
10381  ins_pipe(ialu_cconly_reg_reg);
10382%}
10383#endif
10384
10385instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
10386  match(Set icc (CmpU op1 op2));
10387
10388  size(4);
10389  format %{ "cmp_32 $op1,$op2\t! unsigned int" %}
10390  ins_encode %{
10391    __ cmp_32($op1$$Register, $op2$$Register);
10392  %}
10393  ins_pipe(ialu_cconly_reg_reg);
10394%}
10395
10396instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{
10397  match(Set icc (CmpI op1 op2));
10398  effect( DEF icc, USE op1 );
10399
10400  size(4);
10401  format %{ "cmn_32 $op1,-$op2\t! int" %}
10402  ins_encode %{
10403    __ cmn_32($op1$$Register, -$op2$$constant);
10404  %}
10405  ins_pipe(ialu_cconly_reg_imm);
10406%}
10407
10408instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{
10409  match(Set icc (CmpI op1 op2));
10410  effect( DEF icc, USE op1 );
10411
10412  size(4);
10413  format %{ "cmp_32 $op1,$op2\t! int" %}
10414  ins_encode %{
10415    __ cmp_32($op1$$Register, $op2$$constant);
10416  %}
10417  ins_pipe(ialu_cconly_reg_imm);
10418%}
10419
10420instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{
10421  match(Set icc (CmpI (AndI op1 op2) zero));
10422  size(4);
10423  format %{ "tst_32 $op2,$op1" %}
10424
10425  ins_encode %{
10426    __ tst_32($op1$$Register, $op2$$Register);
10427  %}
10428  ins_pipe(ialu_cconly_reg_reg_zero);
10429%}
10430
10431#ifndef AARCH64
10432instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
10433  match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
10434  size(4);
10435  format %{ "TST   $op2,$op1<<$op3" %}
10436
10437  ins_encode %{
10438    __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register));
10439  %}
10440  ins_pipe(ialu_cconly_reg_reg_zero);
10441%}
10442#endif
10443
10444instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
10445  match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
10446  size(4);
10447  format %{ "tst_32 $op2,$op1<<$op3" %}
10448
10449  ins_encode %{
10450    __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant));
10451  %}
10452  ins_pipe(ialu_cconly_reg_reg_zero);
10453%}
10454
10455#ifndef AARCH64
10456instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
10457  match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
10458  size(4);
10459  format %{ "TST   $op2,$op1<<$op3" %}
10460
10461  ins_encode %{
10462    __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register));
10463  %}
10464  ins_pipe(ialu_cconly_reg_reg_zero);
10465%}
10466#endif
10467
10468instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
10469  match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
10470  size(4);
10471  format %{ "tst_32 $op2,$op1<<$op3" %}
10472
10473  ins_encode %{
10474    __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant));
10475  %}
10476  ins_pipe(ialu_cconly_reg_reg_zero);
10477%}
10478
10479#ifndef AARCH64
10480instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
10481  match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
10482  size(4);
10483  format %{ "TST   $op2,$op1<<$op3" %}
10484
10485  ins_encode %{
10486    __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register));
10487  %}
10488  ins_pipe(ialu_cconly_reg_reg_zero);
10489%}
10490#endif
10491
10492instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
10493  match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
10494  size(4);
10495  format %{ "tst_32 $op2,$op1<<$op3" %}
10496
10497  ins_encode %{
10498    __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant));
10499  %}
10500  ins_pipe(ialu_cconly_reg_reg_zero);
10501%}
10502
10503instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{
10504  match(Set icc (CmpI (AndI op1 op2) zero));
10505  size(4);
10506  format %{ "tst_32 $op2,$op1" %}
10507
10508  ins_encode %{
10509    __ tst_32($op1$$Register, $op2$$constant);
10510  %}
10511  ins_pipe(ialu_cconly_reg_imm_zero);
10512%}
10513
10514#ifdef AARCH64
10515instruct compL_reg_reg(flagsReg xcc, iRegL op1, iRegL op2)
10516%{
10517  match(Set xcc (CmpL op1 op2));
10518  effect( DEF xcc, USE op1, USE op2 );
10519
10520  size(4);
10521  format %{ "CMP     $op1,$op2\t! long" %}
10522  ins_encode %{
10523    __ cmp($op1$$Register, $op2$$Register);
10524  %}
10525  ins_pipe(ialu_cconly_reg_reg);
10526%}
10527
10528instruct compUL_iReg(flagsRegU xcc, iRegL op1, iRegL op2) %{
10529  match(Set xcc (CmpUL op1 op2));
10530
10531  size(4);
10532  format %{ "CMP     $op1,$op2\t! unsigned long" %}
10533  ins_encode %{
10534    __ cmp($op1$$Register, $op2$$Register);
10535  %}
10536  ins_pipe(ialu_cconly_reg_reg);
10537%}
10538#else
10539instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
10540  match(Set xcc (CmpL op1 op2));
10541  effect( DEF xcc, USE op1, USE op2, TEMP tmp );
10542
10543  size(8);
10544  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! long\n\t"
10545            "SBCS    $tmp,$op1.hi,$op2.hi" %}
10546  ins_encode %{
10547    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
10548    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
10549  %}
10550  ins_pipe(ialu_cconly_reg_reg);
10551%}
10552
10553instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
10554  match(Set xcc (CmpUL op1 op2));
10555  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
10556
10557  size(8);
10558  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
10559            "SBCS    $tmp,$op1.hi,$op2.hi" %}
10560  ins_encode %{
10561    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
10562    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
10563  %}
10564  ins_pipe(ialu_cconly_reg_reg);
10565%}
10566#endif
10567
10568#ifdef AARCH64
10569instruct compL_reg_con(flagsReg xcc, iRegL op1, aimmL con) %{
10570  match(Set xcc (CmpL op1 con));
10571  effect( DEF xcc, USE op1, USE con );
10572
10573  size(8);
10574  format %{ "CMP     $op1,$con\t\t! long"  %}
10575  ins_encode %{
10576    __ cmp($op1$$Register, $con$$constant);
10577  %}
10578
10579  ins_pipe(ialu_cconly_reg_imm);
10580%}
10581
10582instruct compUL_reg_con(flagsRegU xcc, iRegL op1, aimmL con) %{
10583  match(Set xcc (CmpUL op1 con));
10584  effect(DEF xcc, USE op1, USE con);
10585
10586  size(8);
10587  format %{ "CMP     $op1,$con\t\t! unsigned long"  %}
10588  ins_encode %{
10589    __ cmp($op1$$Register, $con$$constant);
10590  %}
10591
10592  ins_pipe(ialu_cconly_reg_imm);
10593%}
10594#else
10595instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
10596  match(Set xcc (CmpL op1 op2));
10597  effect( DEF xcc, USE op1, USE op2 );
10598
10599  size(8);
10600  format %{ "TEQ    $op1.hi,$op2.hi\t\t! long\n\t"
10601            "TEQ.eq $op1.lo,$op2.lo" %}
10602  ins_encode %{
10603    __ teq($op1$$Register->successor(), $op2$$Register->successor());
10604    __ teq($op1$$Register, $op2$$Register, eq);
10605  %}
10606  ins_pipe(ialu_cconly_reg_reg);
10607%}
10608
10609instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
10610  match(Set xcc (CmpL op1 op2));
10611  effect( DEF xcc, USE op1, USE op2, TEMP tmp );
10612
10613  size(8);
10614  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! long\n\t"
10615            "SBCS    $tmp,$op2.hi,$op1.hi" %}
10616  ins_encode %{
10617    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
10618    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
10619  %}
10620  ins_pipe(ialu_cconly_reg_reg);
10621%}
10622
10623// TODO: try immLRot2 instead, (0, $con$$constant) becomes
10624// (hi($con$$constant), lo($con$$constant)) becomes
10625instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
10626  match(Set xcc (CmpL op1 con));
10627  effect( DEF xcc, USE op1, USE con, TEMP tmp );
10628
10629  size(8);
10630  format %{ "SUBS    $tmp,$op1.low,$con\t\t! long\n\t"
10631            "SBCS    $tmp,$op1.hi,0" %}
10632  ins_encode %{
10633    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
10634    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
10635  %}
10636
10637  ins_pipe(ialu_cconly_reg_reg);
10638%}
10639
10640// TODO: try immLRot2 instead, (0, $con$$constant) becomes
10641// (hi($con$$constant), lo($con$$constant)) becomes
10642instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{
10643  match(Set xcc (CmpL op1 con));
10644  effect( DEF xcc, USE op1, USE con );
10645
10646  size(8);
10647  format %{ "TEQ    $op1.hi,0\t\t! long\n\t"
10648            "TEQ.eq $op1.lo,$con" %}
10649  ins_encode %{
10650    __ teq($op1$$Register->successor(), 0);
10651    __ teq($op1$$Register, $con$$constant, eq);
10652  %}
10653
10654  ins_pipe(ialu_cconly_reg_reg);
10655%}
10656
10657// TODO: try immLRot2 instead, (0, $con$$constant) becomes
10658// (hi($con$$constant), lo($con$$constant)) becomes
10659instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
10660  match(Set xcc (CmpL op1 con));
10661  effect( DEF xcc, USE op1, USE con, TEMP tmp );
10662
10663  size(8);
10664  format %{ "RSBS    $tmp,$op1.low,$con\t\t! long\n\t"
10665            "RSCS    $tmp,$op1.hi,0" %}
10666  ins_encode %{
10667    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
10668    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
10669  %}
10670
10671  ins_pipe(ialu_cconly_reg_reg);
10672%}
10673
10674instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
10675  match(Set xcc (CmpUL op1 op2));
10676  effect(DEF xcc, USE op1, USE op2);
10677
10678  size(8);
10679  format %{ "TEQ    $op1.hi,$op2.hi\t\t! unsigned long\n\t"
10680            "TEQ.eq $op1.lo,$op2.lo" %}
10681  ins_encode %{
10682    __ teq($op1$$Register->successor(), $op2$$Register->successor());
10683    __ teq($op1$$Register, $op2$$Register, eq);
10684  %}
10685  ins_pipe(ialu_cconly_reg_reg);
10686%}
10687
10688instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
10689  match(Set xcc (CmpUL op1 op2));
10690  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
10691
10692  size(8);
10693  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
10694            "SBCS    $tmp,$op2.hi,$op1.hi" %}
10695  ins_encode %{
10696    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
10697    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
10698  %}
10699  ins_pipe(ialu_cconly_reg_reg);
10700%}
10701
10702// TODO: try immLRot2 instead, (0, $con$$constant) becomes
10703// (hi($con$$constant), lo($con$$constant)) becomes
10704instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
10705  match(Set xcc (CmpUL op1 con));
10706  effect(DEF xcc, USE op1, USE con, TEMP tmp);
10707
10708  size(8);
10709  format %{ "SUBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
10710            "SBCS    $tmp,$op1.hi,0" %}
10711  ins_encode %{
10712    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
10713    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
10714  %}
10715
10716  ins_pipe(ialu_cconly_reg_reg);
10717%}
10718
10719// TODO: try immLRot2 instead, (0, $con$$constant) becomes
10720// (hi($con$$constant), lo($con$$constant)) becomes
10721instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
10722  match(Set xcc (CmpUL op1 con));
10723  effect(DEF xcc, USE op1, USE con);
10724
10725  size(8);
10726  format %{ "TEQ    $op1.hi,0\t\t! unsigned long\n\t"
10727            "TEQ.eq $op1.lo,$con" %}
10728  ins_encode %{
10729    __ teq($op1$$Register->successor(), 0);
10730    __ teq($op1$$Register, $con$$constant, eq);
10731  %}
10732
10733  ins_pipe(ialu_cconly_reg_reg);
10734%}
10735
10736// TODO: try immLRot2 instead, (0, $con$$constant) becomes
10737// (hi($con$$constant), lo($con$$constant)) becomes
10738instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
10739  match(Set xcc (CmpUL op1 con));
10740  effect(DEF xcc, USE op1, USE con, TEMP tmp);
10741
10742  size(8);
10743  format %{ "RSBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
10744            "RSCS    $tmp,$op1.hi,0" %}
10745  ins_encode %{
10746    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
10747    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
10748  %}
10749
10750  ins_pipe(ialu_cconly_reg_reg);
10751%}
10752#endif
10753
10754/* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
10755/*   match(Set xcc (CmpL (AndL op1 op2) zero)); */
10756/*   ins_encode %{ */
10757/*     __ stop("testL_reg_reg unimplemented"); */
10758/*   %} */
10759/*   ins_pipe(ialu_cconly_reg_reg); */
10760/* %} */
10761
10762/* // useful for checking the alignment of a pointer: */
10763/* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */
10764/*   match(Set xcc (CmpL (AndL op1 con) zero)); */
10765/*   ins_encode %{ */
10766/*     __ stop("testL_reg_con unimplemented"); */
10767/*   %} */
10768/*   ins_pipe(ialu_cconly_reg_reg); */
10769/* %} */
10770
10771instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{
10772  match(Set icc (CmpU op1 op2));
10773
10774  size(4);
10775  format %{ "cmp_32 $op1,$op2\t! unsigned" %}
10776  ins_encode %{
10777    __ cmp_32($op1$$Register, $op2$$constant);
10778  %}
10779  ins_pipe(ialu_cconly_reg_imm);
10780%}
10781
10782// Compare Pointers
10783instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
10784  match(Set pcc (CmpP op1 op2));
10785
10786  size(4);
10787  format %{ "CMP    $op1,$op2\t! ptr" %}
10788  ins_encode %{
10789    __ cmp($op1$$Register, $op2$$Register);
10790  %}
10791  ins_pipe(ialu_cconly_reg_reg);
10792%}
10793
10794instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{
10795  match(Set pcc (CmpP op1 op2));
10796
10797  size(4);
10798  format %{ "CMP    $op1,$op2\t! ptr" %}
10799  ins_encode %{
10800    assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?");
10801    __ cmp($op1$$Register, $op2$$constant);
10802  %}
10803  ins_pipe(ialu_cconly_reg_imm);
10804%}
10805
10806//----------Max and Min--------------------------------------------------------
10807// Min Instructions
10808// Conditional move for min
10809instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{
10810  effect( USE_DEF op2, USE op1, USE icc );
10811
10812  size(4);
10813  format %{ "MOV.lt  $op2,$op1\t! min" %}
10814  ins_encode %{
10815    __ mov($op2$$Register, $op1$$Register, lt);
10816  %}
10817  ins_pipe(ialu_reg_flags);
10818%}
10819
10820// Min Register with Register.
10821instruct minI_eReg(iRegI op1, iRegI op2) %{
10822  match(Set op2 (MinI op1 op2));
10823  ins_cost(DEFAULT_COST*2);
10824  expand %{
10825    flagsReg icc;
10826    compI_iReg(icc,op1,op2);
10827    cmovI_reg_lt(op2,op1,icc);
10828  %}
10829%}
10830
10831// Max Instructions
10832// Conditional move for max
10833instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{
10834  effect( USE_DEF op2, USE op1, USE icc );
10835  format %{ "MOV.gt  $op2,$op1\t! max" %}
10836  ins_encode %{
10837    __ mov($op2$$Register, $op1$$Register, gt);
10838  %}
10839  ins_pipe(ialu_reg_flags);
10840%}
10841
10842// Max Register with Register
10843instruct maxI_eReg(iRegI op1, iRegI op2) %{
10844  match(Set op2 (MaxI op1 op2));
10845  ins_cost(DEFAULT_COST*2);
10846  expand %{
10847    flagsReg icc;
10848    compI_iReg(icc,op1,op2);
10849    cmovI_reg_gt(op2,op1,icc);
10850  %}
10851%}
10852
10853
10854//----------Float Compares----------------------------------------------------
10855// Compare floating, generate condition code
10856instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{
10857  match(Set icc (CmpF src1 src2));
10858  effect(KILL fcc);
10859
10860#ifdef AARCH64
10861  size(4);
10862  format %{ "FCMP_s  $src1,$src2" %}
10863  ins_encode %{
10864    __ fcmp_s($src1$$FloatRegister, $src2$$FloatRegister);
10865  %}
10866#else
10867  size(8);
10868  format %{ "FCMPs  $src1,$src2\n\t"
10869            "FMSTAT" %}
10870  ins_encode %{
10871    __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
10872    __ fmstat();
10873  %}
10874#endif
10875  ins_pipe(faddF_fcc_reg_reg_zero);
10876%}
10877
10878instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{
10879  match(Set icc (CmpF src1 src2));
10880  effect(KILL fcc);
10881
10882#ifdef AARCH64
10883  size(4);
10884  format %{ "FCMP0_s $src1" %}
10885  ins_encode %{
10886    __ fcmp0_s($src1$$FloatRegister);
10887  %}
10888#else
10889  size(8);
10890  format %{ "FCMPs  $src1,$src2\n\t"
10891            "FMSTAT" %}
10892  ins_encode %{
10893    __ fcmpzs($src1$$FloatRegister);
10894    __ fmstat();
10895  %}
10896#endif
10897  ins_pipe(faddF_fcc_reg_reg_zero);
10898%}
10899
10900instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{
10901  match(Set icc (CmpD src1 src2));
10902  effect(KILL fcc);
10903
10904#ifdef AARCH64
10905  size(4);
10906  format %{ "FCMP_d $src1,$src2" %}
10907  ins_encode %{
10908    __ fcmp_d($src1$$FloatRegister, $src2$$FloatRegister);
10909  %}
10910#else
10911  size(8);
10912  format %{ "FCMPd  $src1,$src2 \n\t"
10913            "FMSTAT" %}
10914  ins_encode %{
10915    __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
10916    __ fmstat();
10917  %}
10918#endif
10919  ins_pipe(faddD_fcc_reg_reg_zero);
10920%}
10921
10922instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{
10923  match(Set icc (CmpD src1 src2));
10924  effect(KILL fcc);
10925
10926#ifdef AARCH64
10927  size(8);
10928  format %{ "FCMP0_d $src1" %}
10929  ins_encode %{
10930    __ fcmp0_d($src1$$FloatRegister);
10931  %}
10932#else
10933  size(8);
10934  format %{ "FCMPZd  $src1,$src2 \n\t"
10935            "FMSTAT" %}
10936  ins_encode %{
10937    __ fcmpzd($src1$$FloatRegister);
10938    __ fmstat();
10939  %}
10940#endif
10941  ins_pipe(faddD_fcc_reg_reg_zero);
10942%}
10943
10944#ifdef AARCH64
10945// Compare floating, generate -1,0,1
10946instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsReg icc) %{
10947  match(Set dst (CmpF3 src1 src2));
10948  // effect(KILL fcc); // nobody cares if flagsRegF is killed
10949  effect(KILL icc);
10950  ins_cost(DEFAULT_COST*3); // FIXME
10951  size(12);
10952  format %{ "FCMP_s $src1,$src2\n\t"
10953            "CSET   $dst, gt\n\t"
10954            "CSINV  $dst, $dst, ZR, ge" %}
10955  ins_encode %{
10956    Register dst = $dst$$Register;
10957    __ fcmp_s($src1$$FloatRegister, $src2$$FloatRegister);
10958    __ cset(dst, gt);            // 1 if '>', else 0
10959    __ csinv(dst, dst, ZR, ge);  // previous value if '>=', else -1
10960  %}
10961  ins_pipe( floating_cmp ); // FIXME
10962%}
10963
10964// Compare floating, generate -1,0,1
10965instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsReg icc) %{
10966  match(Set dst (CmpD3 src1 src2));
10967  // effect(KILL fcc); // nobody cares if flagsRegF is killed
10968  effect(KILL icc);
10969  ins_cost(DEFAULT_COST*3); // FIXME
10970  size(12);
10971  format %{ "FCMP_d $src1,$src2\n\t"
10972            "CSET   $dst, gt\n\t"
10973            "CSINV  $dst, $dst, ZR, ge" %}
10974  ins_encode %{
10975    Register dst = $dst$$Register;
10976    __ fcmp_d($src1$$FloatRegister, $src2$$FloatRegister);
10977    __ cset(dst, gt);            // 1 if '>', else 0
10978    __ csinv(dst, dst, ZR, ge);  // previous value if '>=', else -1
10979  %}
10980  ins_pipe( floating_cmp ); // FIXME
10981%}
10982
10983// Compare floating, generate -1,0,1
10984instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsReg icc) %{
10985  match(Set dst (CmpF3 src1 src2));
10986  // effect(KILL fcc); // nobody cares if flagsRegF is killed
10987  effect(KILL icc);
10988  ins_cost(DEFAULT_COST*3); // FIXME
10989  size(12);
10990  format %{ "FCMP0_s $src1\n\t"
10991            "CSET   $dst, gt\n\t"
10992            "CSINV  $dst, $dst, ZR, ge" %}
10993  ins_encode %{
10994    Register dst = $dst$$Register;
10995    __ fcmp0_s($src1$$FloatRegister);
10996    __ cset(dst, gt);            // 1 if '>', else 0
10997    __ csinv(dst, dst, ZR, ge);  // previous value if '>=', else -1
10998  %}
10999  ins_pipe( floating_cmp ); // FIXME
11000%}
11001
11002// Compare floating, generate -1,0,1
11003instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsReg icc) %{
11004  match(Set dst (CmpD3 src1 src2));
11005  // effect(KILL fcc); // nobody cares if flagsRegF is killed
11006  effect(KILL icc);
11007  ins_cost(DEFAULT_COST*3); // FIXME
11008  size(12);
11009  format %{ "FCMP0_d $src1\n\t"
11010            "CSET   $dst, gt\n\t"
11011            "CSINV  $dst, $dst, ZR, ge" %}
11012  ins_encode %{
11013    Register dst = $dst$$Register;
11014    __ fcmp0_d($src1$$FloatRegister);
11015    __ cset(dst, gt);            // 1 if '>', else 0
11016    __ csinv(dst, dst, ZR, ge);  // previous value if '>=', else -1
11017  %}
11018  ins_pipe( floating_cmp ); // FIXME
11019%}
11020#else
11021// Compare floating, generate -1,0,1
11022instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{
11023  match(Set dst (CmpF3 src1 src2));
11024  effect(KILL fcc);
11025  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
11026  size(20);
11027  // same number of instructions as code using conditional moves but
11028  // doesn't kill integer condition register
11029  format %{ "FCMPs  $dst,$src1,$src2 \n\t"
11030            "VMRS   $dst, FPSCR \n\t"
11031            "OR     $dst, $dst, 0x08000000 \n\t"
11032            "EOR    $dst, $dst, $dst << 3 \n\t"
11033            "MOV    $dst, $dst >> 30" %}
11034  ins_encode %{
11035    __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
11036    __ floating_cmp($dst$$Register);
11037  %}
11038  ins_pipe( floating_cmp );
11039%}
11040
11041instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{
11042  match(Set dst (CmpF3 src1 src2));
11043  effect(KILL fcc);
11044  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
11045  size(20);
11046  // same number of instructions as code using conditional moves but
11047  // doesn't kill integer condition register
11048  format %{ "FCMPZs $dst,$src1,$src2 \n\t"
11049            "VMRS   $dst, FPSCR \n\t"
11050            "OR     $dst, $dst, 0x08000000 \n\t"
11051            "EOR    $dst, $dst, $dst << 3 \n\t"
11052            "MOV    $dst, $dst >> 30" %}
11053  ins_encode %{
11054    __ fcmpzs($src1$$FloatRegister);
11055    __ floating_cmp($dst$$Register);
11056  %}
11057  ins_pipe( floating_cmp );
11058%}
11059
11060instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{
11061  match(Set dst (CmpD3 src1 src2));
11062  effect(KILL fcc);
11063  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
11064  size(20);
11065  // same number of instructions as code using conditional moves but
11066  // doesn't kill integer condition register
11067  format %{ "FCMPd  $dst,$src1,$src2 \n\t"
11068            "VMRS   $dst, FPSCR \n\t"
11069            "OR     $dst, $dst, 0x08000000 \n\t"
11070            "EOR    $dst, $dst, $dst << 3 \n\t"
11071            "MOV    $dst, $dst >> 30" %}
11072  ins_encode %{
11073    __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
11074    __ floating_cmp($dst$$Register);
11075  %}
11076  ins_pipe( floating_cmp );
11077%}
11078
11079instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{
11080  match(Set dst (CmpD3 src1 src2));
11081  effect(KILL fcc);
11082  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
11083  size(20);
11084  // same number of instructions as code using conditional moves but
11085  // doesn't kill integer condition register
11086  format %{ "FCMPZd $dst,$src1,$src2 \n\t"
11087            "VMRS   $dst, FPSCR \n\t"
11088            "OR     $dst, $dst, 0x08000000 \n\t"
11089            "EOR    $dst, $dst, $dst << 3 \n\t"
11090            "MOV    $dst, $dst >> 30" %}
11091  ins_encode %{
11092    __ fcmpzd($src1$$FloatRegister);
11093    __ floating_cmp($dst$$Register);
11094  %}
11095  ins_pipe( floating_cmp );
11096%}
11097#endif // !AARCH64
11098
11099//----------Branches---------------------------------------------------------
11100// Jump
11101// (compare 'operand indIndex' and 'instruct addP_reg_reg' above)
11102// FIXME
11103instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{
11104  match(Jump switch_val);
11105  effect(TEMP tmp);
11106  ins_cost(350);
11107  format %{  "ADD    $tmp, $constanttablebase, $switch_val\n\t"
11108             "LDR    $tmp,[$tmp + $constantoffset]\n\t"
11109             "BX     $tmp" %}
11110  size(20);
11111  ins_encode %{
11112    Register table_reg;
11113    Register label_reg = $tmp$$Register;
11114    if (constant_offset() == 0) {
11115      table_reg = $constanttablebase;
11116      __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
11117    } else {
11118      table_reg = $tmp$$Register;
11119      int offset = $constantoffset;
11120      if (is_memoryP(offset)) {
11121        __ add(table_reg, $constanttablebase, $switch_val$$Register);
11122        __ ldr(label_reg, Address(table_reg, offset));
11123      } else {
11124        __ mov_slow(table_reg, $constantoffset);
11125        __ add(table_reg, $constanttablebase, table_reg);
11126        __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
11127      }
11128    }
11129    __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor?
11130    //    __ ldr(PC, Address($table$$Register, $switch_val$$Register));
11131  %}
11132  ins_pipe(ialu_reg_reg);
11133%}
11134
11135// // Direct Branch.
11136instruct branch(label labl) %{
11137  match(Goto);
11138  effect(USE labl);
11139
11140  size(4);
11141  ins_cost(BRANCH_COST);
11142  format %{ "B     $labl" %}
11143  ins_encode %{
11144    __ b(*($labl$$label));
11145  %}
11146  ins_pipe(br);
11147%}
11148
11149// Conditional Direct Branch
11150instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
11151  match(If cmp icc);
11152  effect(USE labl);
11153
11154  size(4);
11155  ins_cost(BRANCH_COST);
11156  format %{ "B$cmp   $icc,$labl" %}
11157  ins_encode %{
11158    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11159  %}
11160  ins_pipe(br_cc);
11161%}
11162
11163#ifdef ARM
11164instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{
11165  match(If cmp icc);
11166  effect(USE labl);
11167  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);
11168
11169  size(4);
11170  ins_cost(BRANCH_COST);
11171  format %{ "B$cmp   $icc,$labl" %}
11172  ins_encode %{
11173    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11174  %}
11175  ins_pipe(br_cc);
11176%}
11177#endif
11178
11179#ifdef AARCH64
11180instruct cbzI(cmpOp cmp, iRegI op1, immI0 op2, label labl) %{
11181  match(If cmp (CmpI op1 op2));
11182  effect(USE labl);
11183  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
11184            _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
11185  size(4);
11186  ins_cost(BRANCH_COST);
11187  format %{ "CB{N}Z $op1, $labl\t! int $cmp" %}
11188  ins_encode %{
11189    if ($cmp$$cmpcode == eq) {
11190      __ cbz_w($op1$$Register, *($labl$$label));
11191    } else {
11192      __ cbnz_w($op1$$Register, *($labl$$label));
11193    }
11194  %}
11195  ins_pipe(br_cc); // FIXME
11196%}
11197
11198instruct cbzP(cmpOpP cmp, iRegP op1, immP0 op2, label labl) %{
11199  match(If cmp (CmpP op1 op2));
11200  effect(USE labl);
11201  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
11202            _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
11203  size(4);
11204  ins_cost(BRANCH_COST);
11205  format %{ "CB{N}Z $op1, $labl\t! ptr $cmp" %}
11206  ins_encode %{
11207    if ($cmp$$cmpcode == eq) {
11208      __ cbz($op1$$Register, *($labl$$label));
11209    } else {
11210      __ cbnz($op1$$Register, *($labl$$label));
11211    }
11212  %}
11213  ins_pipe(br_cc); // FIXME
11214%}
11215
11216instruct cbzL(cmpOpL cmp, iRegL op1, immL0 op2, label labl) %{
11217  match(If cmp (CmpL op1 op2));
11218  effect(USE labl);
11219  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
11220            _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
11221  size(4);
11222  ins_cost(BRANCH_COST);
11223  format %{ "CB{N}Z $op1, $labl\t! long $cmp" %}
11224  ins_encode %{
11225    if ($cmp$$cmpcode == eq) {
11226      __ cbz($op1$$Register, *($labl$$label));
11227    } else {
11228      __ cbnz($op1$$Register, *($labl$$label));
11229    }
11230  %}
11231  ins_pipe(br_cc); // FIXME
11232%}
11233#endif
11234
11235instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
11236  match(If cmp icc);
11237  effect(USE labl);
11238
11239  size(4);
11240  ins_cost(BRANCH_COST);
11241  format %{ "B$cmp  $icc,$labl" %}
11242  ins_encode %{
11243    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11244  %}
11245  ins_pipe(br_cc);
11246%}
11247
11248instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{
11249  match(If cmp pcc);
11250  effect(USE labl);
11251
11252  size(4);
11253  ins_cost(BRANCH_COST);
11254  format %{ "B$cmp  $pcc,$labl" %}
11255  ins_encode %{
11256    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11257  %}
11258  ins_pipe(br_cc);
11259%}
11260
11261#ifndef AARCH64
11262instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{
11263  match(If cmp xcc);
11264  effect(USE labl);
11265  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11266
11267  size(4);
11268  ins_cost(BRANCH_COST);
11269  format %{ "B$cmp  $xcc,$labl" %}
11270  ins_encode %{
11271    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11272  %}
11273  ins_pipe(br_cc);
11274%}
11275
11276instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{
11277  match(If cmp xcc);
11278  effect(USE labl);
11279  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11280
11281  size(4);
11282  ins_cost(BRANCH_COST);
11283  format %{ "B$cmp  $xcc,$labl" %}
11284  ins_encode %{
11285    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11286  %}
11287  ins_pipe(br_cc);
11288%}
11289
11290instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
11291  match(If cmp xcc);
11292  effect(USE labl);
11293  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
11294
11295  size(4);
11296  ins_cost(BRANCH_COST);
11297  format %{ "B$cmp  $xcc,$labl" %}
11298  ins_encode %{
11299    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11300  %}
11301  ins_pipe(br_cc);
11302%}
11303
11304instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
11305  match(If cmp xcc);
11306  effect(USE labl);
11307  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
11308
11309  size(4);
11310  ins_cost(BRANCH_COST);
11311  format %{ "B$cmp  $xcc,$labl" %}
11312  ins_encode %{
11313    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11314  %}
11315  ins_pipe(br_cc);
11316%}
11317
11318instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
11319  match(If cmp xcc);
11320  effect(USE labl);
11321  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
11322
11323  size(4);
11324  ins_cost(BRANCH_COST);
11325  format %{ "B$cmp  $xcc,$labl" %}
11326  ins_encode %{
11327    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11328  %}
11329  ins_pipe(br_cc);
11330%}
11331
11332instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
11333  match(If cmp xcc);
11334  effect(USE labl);
11335  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
11336
11337  size(4);
11338  ins_cost(BRANCH_COST);
11339  format %{ "B$cmp  $xcc,$labl" %}
11340  ins_encode %{
11341    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11342  %}
11343  ins_pipe(br_cc);
11344%}
11345#endif
11346
11347instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
11348  match(CountedLoopEnd cmp icc);
11349  effect(USE labl);
11350
11351  size(4);
11352  ins_cost(BRANCH_COST);
11353  format %{ "B$cmp   $icc,$labl\t! Loop end" %}
11354  ins_encode %{
11355    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
11356  %}
11357  ins_pipe(br_cc);
11358%}
11359
11360// instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{
11361//   match(CountedLoopEnd cmp icc);
11362//   ins_pipe(br_cc);
11363// %}
11364
11365// ============================================================================
11366// Long Compare
11367//
11368// Currently we hold longs in 2 registers.  Comparing such values efficiently
11369// is tricky.  The flavor of compare used depends on whether we are testing
11370// for LT, LE, or EQ.  For a simple LT test we can check just the sign bit.
11371// The GE test is the negated LT test.  The LE test can be had by commuting
11372// the operands (yielding a GE test) and then negating; negate again for the
11373// GT test.  The EQ test is done by ORcc'ing the high and low halves, and the
11374// NE test is negated from that.
11375
11376// Due to a shortcoming in the ADLC, it mixes up expressions like:
11377// (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)).  Note the
11378// difference between 'Y' and '0L'.  The tree-matches for the CmpI sections
11379// are collapsed internally in the ADLC's dfa-gen code.  The match for
11380// (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
11381// foo match ends up with the wrong leaf.  One fix is to not match both
11382// reg-reg and reg-zero forms of long-compare.  This is unfortunate because
11383// both forms beat the trinary form of long-compare and both are very useful
11384// on Intel which has so few registers.
11385
11386// instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
11387//   match(If cmp xcc);
11388//   ins_pipe(br_cc);
11389// %}
11390
11391// Manifest a CmpL3 result in an integer register.  Very painful.
11392// This is the test to avoid.
11393#ifdef AARCH64
11394instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr) %{
11395  match(Set dst (CmpL3 src1 src2));
11396  // effect(KILL fcc); // nobody cares if flagsRegF is killed
11397  effect(KILL ccr);
11398  ins_cost(DEFAULT_COST*3); // FIXME
11399  size(12);
11400  format %{ "CMP    $src1,$src2\n\t"
11401            "CSET   $dst, gt\n\t"
11402            "CSINV  $dst, $dst, ZR, ge" %}
11403  ins_encode %{
11404    Register dst = $dst$$Register;
11405    __ cmp($src1$$Register, $src2$$Register);
11406    __ cset(dst, gt);            // 1 if '>', else 0
11407    __ csinv(dst, dst, ZR, ge);  // previous value if '>=', else -1
11408  %}
11409  ins_pipe( ialu_cconly_reg_reg ); // FIXME
11410%}
11411// TODO cmpL3_reg_imm
11412#else
11413instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
11414  match(Set dst (CmpL3 src1 src2) );
11415  effect( KILL ccr );
11416  ins_cost(6*DEFAULT_COST); // FIXME
11417  size(32);
11418  format %{
11419      "CMP    $src1.hi, $src2.hi\t\t! long\n"
11420    "\tMOV.gt $dst, 1\n"
11421    "\tmvn.lt $dst, 0\n"
11422    "\tB.ne   done\n"
11423    "\tSUBS   $dst, $src1.lo, $src2.lo\n"
11424    "\tMOV.hi $dst, 1\n"
11425    "\tmvn.lo $dst, 0\n"
11426    "done:"     %}
11427  ins_encode %{
11428    Label done;
11429    __ cmp($src1$$Register->successor(), $src2$$Register->successor());
11430    __ mov($dst$$Register, 1, gt);
11431    __ mvn($dst$$Register, 0, lt);
11432    __ b(done, ne);
11433    __ subs($dst$$Register, $src1$$Register, $src2$$Register);
11434    __ mov($dst$$Register, 1, hi);
11435    __ mvn($dst$$Register, 0, lo);
11436    __ bind(done);
11437  %}
11438  ins_pipe(cmpL_reg);
11439%}
11440#endif
11441
11442#ifndef AARCH64
11443// Conditional move
11444instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{
11445  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
11446  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11447
11448  ins_cost(150);
11449  size(8);
11450  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
11451            "MOV$cmp  $dst,$src.hi" %}
11452  ins_encode %{
11453    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11454    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
11455  %}
11456  ins_pipe(ialu_reg);
11457%}
11458
11459instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{
11460  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
11461  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11462
11463  ins_cost(150);
11464  size(8);
11465  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
11466            "MOV$cmp  $dst,$src.hi" %}
11467  ins_encode %{
11468    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11469    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
11470  %}
11471  ins_pipe(ialu_reg);
11472%}
11473
11474instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{
11475  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
11476  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11477
11478  ins_cost(150);
11479  size(8);
11480  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
11481            "MOV$cmp  $dst,$src.hi" %}
11482  ins_encode %{
11483    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11484    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
11485  %}
11486  ins_pipe(ialu_reg);
11487%}
11488
11489instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{
11490  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
11491  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11492  ins_cost(140);
11493  size(8);
11494  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
11495            "MOV$cmp  $dst,0" %}
11496  ins_encode %{
11497    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
11498    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
11499  %}
11500  ins_pipe(ialu_imm);
11501%}
11502
11503instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{
11504  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
11505  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11506  ins_cost(140);
11507  size(8);
11508  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
11509            "MOV$cmp  $dst,0" %}
11510  ins_encode %{
11511    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
11512    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
11513  %}
11514  ins_pipe(ialu_imm);
11515%}
11516
11517instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{
11518  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
11519  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11520  ins_cost(140);
11521  size(8);
11522  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
11523            "MOV$cmp  $dst,0" %}
11524  ins_encode %{
11525    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
11526    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
11527  %}
11528  ins_pipe(ialu_imm);
11529%}
11530#endif // !AARCH64
11531
11532#ifndef AARCH64
11533instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{
11534  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
11535  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11536
11537  ins_cost(150);
11538  size(4);
11539  format %{ "MOV$cmp  $dst,$src" %}
11540  ins_encode %{
11541    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11542  %}
11543  ins_pipe(ialu_reg);
11544%}
11545
11546instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{
11547  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
11548  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11549
11550  ins_cost(150);
11551  size(4);
11552  format %{ "MOV$cmp  $dst,$src" %}
11553  ins_encode %{
11554    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11555  %}
11556  ins_pipe(ialu_reg);
11557%}
11558
11559instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{
11560  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
11561  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11562
11563  ins_cost(150);
11564  size(4);
11565  format %{ "MOV$cmp  $dst,$src" %}
11566  ins_encode %{
11567    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11568  %}
11569  ins_pipe(ialu_reg);
11570%}
11571#endif // !AARCH64
11572
11573#ifndef AARCH64
11574instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{
11575  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
11576  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11577
11578  ins_cost(140);
11579  format %{ "MOVW$cmp  $dst,$src" %}
11580  ins_encode %{
11581    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
11582  %}
11583  ins_pipe(ialu_imm);
11584%}
11585
11586instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{
11587  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
11588  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11589
11590  ins_cost(140);
11591  format %{ "MOVW$cmp  $dst,$src" %}
11592  ins_encode %{
11593    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
11594  %}
11595  ins_pipe(ialu_imm);
11596%}
11597
11598instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{
11599  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
11600  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11601
11602  ins_cost(140);
11603  format %{ "MOVW$cmp  $dst,$src" %}
11604  ins_encode %{
11605    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
11606  %}
11607  ins_pipe(ialu_imm);
11608%}
11609
11610instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{
11611  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
11612  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11613
11614  ins_cost(150);
11615  size(4);
11616  format %{ "MOV$cmp  $dst,$src" %}
11617  ins_encode %{
11618    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11619  %}
11620  ins_pipe(ialu_reg);
11621%}
11622
11623instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{
11624  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
11625  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11626
11627  ins_cost(150);
11628  size(4);
11629  format %{ "MOV$cmp  $dst,$src" %}
11630  ins_encode %{
11631    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11632  %}
11633  ins_pipe(ialu_reg);
11634%}
11635
11636instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{
11637  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
11638  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11639
11640  ins_cost(150);
11641  size(4);
11642  format %{ "MOV$cmp  $dst,$src" %}
11643  ins_encode %{
11644    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
11645  %}
11646  ins_pipe(ialu_reg);
11647%}
11648
11649instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{
11650  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
11651  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11652
11653  ins_cost(140);
11654  format %{ "MOVW$cmp  $dst,$src" %}
11655  ins_encode %{
11656    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
11657  %}
11658  ins_pipe(ialu_imm);
11659%}
11660
11661instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{
11662  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
11663  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11664
11665  ins_cost(140);
11666  format %{ "MOVW$cmp  $dst,$src" %}
11667  ins_encode %{
11668    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
11669  %}
11670  ins_pipe(ialu_imm);
11671%}
11672
11673instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{
11674  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
11675  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11676
11677  ins_cost(140);
11678  format %{ "MOVW$cmp  $dst,$src" %}
11679  ins_encode %{
11680    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
11681  %}
11682  ins_pipe(ialu_imm);
11683%}
11684
11685instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{
11686  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
11687  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11688  ins_cost(150);
11689  size(4);
11690  format %{ "FCPYS$cmp $dst,$src" %}
11691  ins_encode %{
11692    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
11693  %}
11694  ins_pipe(int_conditional_float_move);
11695%}
11696
11697instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{
11698  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
11699  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11700  ins_cost(150);
11701  size(4);
11702  format %{ "FCPYS$cmp $dst,$src" %}
11703  ins_encode %{
11704    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
11705  %}
11706  ins_pipe(int_conditional_float_move);
11707%}
11708
11709instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{
11710  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
11711  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11712  ins_cost(150);
11713  size(4);
11714  format %{ "FCPYS$cmp $dst,$src" %}
11715  ins_encode %{
11716    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
11717  %}
11718  ins_pipe(int_conditional_float_move);
11719%}
11720
11721instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{
11722  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
11723  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
11724
11725  ins_cost(150);
11726  size(4);
11727  format %{ "FCPYD$cmp $dst,$src" %}
11728  ins_encode %{
11729    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
11730  %}
11731  ins_pipe(int_conditional_float_move);
11732%}
11733
11734instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{
11735  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
11736  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
11737
11738  ins_cost(150);
11739  size(4);
11740  format %{ "FCPYD$cmp $dst,$src" %}
11741  ins_encode %{
11742    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
11743  %}
11744  ins_pipe(int_conditional_float_move);
11745%}
11746
11747instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{
11748  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
11749  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
11750
11751  ins_cost(150);
11752  size(4);
11753  format %{ "FCPYD$cmp $dst,$src" %}
11754  ins_encode %{
11755    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
11756  %}
11757  ins_pipe(int_conditional_float_move);
11758%}
11759#endif // !AARCH64
11760
11761// ============================================================================
11762// Safepoint Instruction
11763#ifdef AARCH64
11764instruct safePoint_poll(iRegP poll, flagsReg icc, RtempRegP tmp) %{
11765  match(SafePoint poll);
11766  // The handler stub kills Rtemp
11767  effect(USE poll, KILL tmp, KILL icc);
11768
11769  size(4);
11770  format %{ "LDR   ZR,[$poll]\t! Safepoint: poll for GC" %}
11771  ins_encode %{
11772    __ relocate(relocInfo::poll_type);
11773    __ ldr(ZR, Address($poll$$Register));
11774  %}
11775  ins_pipe(loadPollP);
11776%}
11777#else
11778// rather than KILL R12, it would be better to use any reg as
11779// TEMP. Can't do that at this point because it crashes the compiler
11780instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
11781  match(SafePoint poll);
11782  effect(USE poll, KILL tmp, KILL icc);
11783
11784  size(4);
11785  format %{ "LDR   $tmp,[$poll]\t! Safepoint: poll for GC" %}
11786  ins_encode %{
11787    __ relocate(relocInfo::poll_type);
11788    __ ldr($tmp$$Register, Address($poll$$Register));
11789  %}
11790  ins_pipe(loadPollP);
11791%}
11792#endif
11793
11794
11795// ============================================================================
11796// Call Instructions
11797// Call Java Static Instruction
11798instruct CallStaticJavaDirect( method meth ) %{
11799  match(CallStaticJava);
11800  predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
11801  effect(USE meth);
11802
11803  ins_cost(CALL_COST);
11804  format %{ "CALL,static ==> " %}
11805  ins_encode( Java_Static_Call( meth ), call_epilog );
11806  ins_pipe(simple_call);
11807%}
11808
11809// Call Java Static Instruction (method handle version)
11810instruct CallStaticJavaHandle( method meth ) %{
11811  match(CallStaticJava);
11812  predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
11813  effect(USE meth);
11814  // FP is saved by all callees (for interpreter stack correction).
11815  // We use it here for a similar purpose, in {preserve,restore}_FP.
11816
11817  ins_cost(CALL_COST);
11818  format %{ "CALL,static/MethodHandle ==> " %}
11819  ins_encode( preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog );
11820  ins_pipe(simple_call);
11821%}
11822
11823// Call Java Dynamic Instruction
11824instruct CallDynamicJavaDirect( method meth ) %{
11825  match(CallDynamicJava);
11826  effect(USE meth);
11827
11828  ins_cost(CALL_COST);
11829  format %{ "MOV_OOP    (empty),R_R8\n\t"
11830            "CALL,dynamic  ; NOP ==> " %}
11831  ins_encode( Java_Dynamic_Call( meth ), call_epilog );
11832  ins_pipe(call);
11833%}
11834
11835// Call Runtime Instruction
11836instruct CallRuntimeDirect(method meth) %{
11837  match(CallRuntime);
11838  effect(USE meth);
11839  ins_cost(CALL_COST);
11840  format %{ "CALL,runtime" %}
11841#ifdef AARCH64
11842  ins_encode( save_last_PC, Java_To_Runtime( meth ),
11843              call_epilog );
11844#else
11845  ins_encode( Java_To_Runtime( meth ),
11846              call_epilog );
11847#endif
11848  ins_pipe(simple_call);
11849%}
11850
11851// Call runtime without safepoint - same as CallRuntime
11852instruct CallLeafDirect(method meth) %{
11853  match(CallLeaf);
11854  effect(USE meth);
11855  ins_cost(CALL_COST);
11856  format %{ "CALL,runtime leaf" %}
11857  // TODO: ned save_last_PC here?
11858  ins_encode( Java_To_Runtime( meth ),
11859              call_epilog );
11860  ins_pipe(simple_call);
11861%}
11862
11863// Call runtime without safepoint - same as CallLeaf
11864instruct CallLeafNoFPDirect(method meth) %{
11865  match(CallLeafNoFP);
11866  effect(USE meth);
11867  ins_cost(CALL_COST);
11868  format %{ "CALL,runtime leaf nofp" %}
11869  // TODO: ned save_last_PC here?
11870  ins_encode( Java_To_Runtime( meth ),
11871              call_epilog );
11872  ins_pipe(simple_call);
11873%}
11874
11875// Tail Call; Jump from runtime stub to Java code.
11876// Also known as an 'interprocedural jump'.
11877// Target of jump will eventually return to caller.
11878// TailJump below removes the return address.
11879instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_oop) %{
11880  match(TailCall jump_target method_oop );
11881
11882  ins_cost(CALL_COST);
11883  format %{ "MOV    Rexception_pc, LR\n\t"
11884            "jump   $jump_target  \t! $method_oop holds method oop" %}
11885  ins_encode %{
11886    __ mov(Rexception_pc, LR);   // this is used only to call
11887                                 // StubRoutines::forward_exception_entry()
11888                                 // which expects PC of exception in
11889                                 // R5. FIXME?
11890    __ jump($jump_target$$Register);
11891  %}
11892  ins_pipe(tail_call);
11893%}
11894
11895
11896// Return Instruction
11897instruct Ret() %{
11898  match(Return);
11899
11900  format %{ "ret LR" %}
11901
11902  ins_encode %{
11903    __ ret(LR);
11904  %}
11905
11906  ins_pipe(br);
11907%}
11908
11909
11910// Tail Jump; remove the return address; jump to target.
11911// TailCall above leaves the return address around.
11912// TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2).
11913// ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a
11914// "restore" before this instruction (in Epilogue), we need to materialize it
11915// in %i0.
11916instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{
11917  match( TailJump jump_target ex_oop );
11918  ins_cost(CALL_COST);
11919  format %{ "MOV    Rexception_pc, LR\n\t"
11920            "jump   $jump_target \t! $ex_oop holds exc. oop" %}
11921  ins_encode %{
11922    __ mov(Rexception_pc, LR);
11923    __ jump($jump_target$$Register);
11924  %}
11925  ins_pipe(tail_call);
11926%}
11927
11928// Create exception oop: created by stack-crawling runtime code.
11929// Created exception is now available to this handler, and is setup
11930// just prior to jumping to this handler.  No code emitted.
11931instruct CreateException( RExceptionRegP ex_oop )
11932%{
11933  match(Set ex_oop (CreateEx));
11934  ins_cost(0);
11935
11936  size(0);
11937  // use the following format syntax
11938  format %{ "! exception oop is in Rexception_obj; no code emitted" %}
11939  ins_encode();
11940  ins_pipe(empty);
11941%}
11942
11943
11944// Rethrow exception:
11945// The exception oop will come in the first argument position.
11946// Then JUMP (not call) to the rethrow stub code.
11947instruct RethrowException()
11948%{
11949  match(Rethrow);
11950  ins_cost(CALL_COST);
11951
11952  // use the following format syntax
11953  format %{ "b    rethrow_stub" %}
11954  ins_encode %{
11955    Register scratch = R1_tmp;
11956    assert_different_registers(scratch, c_rarg0, LR);
11957    __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch);
11958  %}
11959  ins_pipe(tail_call);
11960%}
11961
11962
11963// Die now
11964instruct ShouldNotReachHere( )
11965%{
11966  match(Halt);
11967  ins_cost(CALL_COST);
11968
11969  // Use the following format syntax
11970  format %{ "ShouldNotReachHere" %}
11971  ins_encode %{
11972    if (is_reachable()) {
11973#ifdef AARCH64
11974      __ dpcs1(0xdead);
11975#else
11976      __ udf(0xdead);
11977#endif
11978    }
11979  %}
11980  ins_pipe(tail_call);
11981%}
11982
11983// ============================================================================
11984// The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
11985// array for an instance of the superklass.  Set a hidden internal cache on a
11986// hit (cache is checked with exposed code in gen_subtype_check()).  Return
11987// not zero for a miss or zero for a hit.  The encoding ALSO sets flags.
11988instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{
11989  match(Set index (PartialSubtypeCheck sub super));
11990  effect( KILL pcc, KILL lr );
11991  ins_cost(DEFAULT_COST*10);
11992  format %{ "CALL   PartialSubtypeCheck" %}
11993  ins_encode %{
11994    __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type);
11995  %}
11996  ins_pipe(partial_subtype_check_pipe);
11997%}
11998
11999/* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */
12000/*   match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */
12001/*   ins_pipe(partial_subtype_check_pipe); */
12002/* %} */
12003
12004
12005// ============================================================================
12006// inlined locking and unlocking
12007
12008#ifdef AARCH64
12009instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 )
12010#else
12011instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch )
12012#endif
12013%{
12014  match(Set pcc (FastLock object box));
12015
12016#ifdef AARCH64
12017  effect(TEMP scratch, TEMP scratch2, TEMP scratch3);
12018#else
12019  predicate(!(UseBiasedLocking && !UseOptoBiasInlining));
12020  effect(TEMP scratch, TEMP scratch2);
12021#endif
12022  ins_cost(DEFAULT_COST*3);
12023
12024#ifdef AARCH64
12025  format %{ "FASTLOCK  $object, $box; KILL $scratch, $scratch2, $scratch3" %}
12026  ins_encode %{
12027    __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register);
12028  %}
12029#else
12030  format %{ "FASTLOCK  $object, $box; KILL $scratch, $scratch2" %}
12031  ins_encode %{
12032    __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
12033  %}
12034#endif
12035  ins_pipe(long_memory_op);
12036%}
12037
12038
12039#ifdef AARCH64
12040instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) %{
12041  match(Set pcc (FastUnlock object box));
12042  effect(TEMP scratch, TEMP scratch2, TEMP scratch3);
12043  ins_cost(100);
12044
12045  format %{ "FASTUNLOCK  $object, $box; KILL $scratch, $scratch2, $scratch3" %}
12046  ins_encode %{
12047    __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register);
12048  %}
12049  ins_pipe(long_memory_op);
12050%}
12051#else
12052instruct cmpFastLock_noBiasInline(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2,
12053                                  iRegP scratch, iRegP scratch3) %{
12054  match(Set pcc (FastLock object box));
12055  predicate(UseBiasedLocking && !UseOptoBiasInlining);
12056
12057  effect(TEMP scratch, TEMP scratch2, TEMP scratch3);
12058  ins_cost(DEFAULT_COST*5);
12059
12060  format %{ "FASTLOCK  $object, $box; KILL $scratch, $scratch2, $scratch3" %}
12061  ins_encode %{
12062    __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register);
12063  %}
12064  ins_pipe(long_memory_op);
12065%}
12066
12067instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{
12068  match(Set pcc (FastUnlock object box));
12069  effect(TEMP scratch, TEMP scratch2);
12070  ins_cost(100);
12071
12072  format %{ "FASTUNLOCK  $object, $box; KILL $scratch, $scratch2" %}
12073  ins_encode %{
12074    __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
12075  %}
12076  ins_pipe(long_memory_op);
12077%}
12078#endif
12079
12080#ifdef AARCH64
12081// TODO: add version that takes immI cnt?
12082instruct clear_array(iRegX cnt, iRegP base, iRegP ptr, iRegX temp, Universe dummy, flagsReg cpsr) %{
12083  match(Set dummy (ClearArray cnt base));
12084  effect(TEMP temp, TEMP ptr, KILL cpsr);
12085  ins_cost(300);
12086  format %{
12087      "        MOV    $temp,$cnt\n"
12088      "        ADD    $ptr,$base,$cnt\n"
12089      "        SUBS   $temp,$temp,16\t! Count down dword pair in bytes\n"
12090      "        B.lt   done16\n"
12091      "loop:   STP    ZR,ZR,[$ptr,-16]!\n"
12092      "        SUBS   $temp,$temp,16\t! Count down dword pair in bytes\n"
12093      "        B.ge   loop\t! Clearing loop\n"
12094      "done16: ADDS   $temp,$temp,8\t! Room for 1 more long?\n"
12095      "        B.lt   done\n"
12096      "        STR    ZR,[$base+$temp]\n"
12097      "done:"
12098  %}
12099  ins_encode %{
12100    // TODO: preload?
12101    __ mov($temp$$Register, $cnt$$Register);
12102    __ add($ptr$$Register, $base$$Register, $cnt$$Register);
12103    Label loop, done, done16;
12104    __ subs($temp$$Register, $temp$$Register, 16);
12105    __ b(done16, lt);
12106    __ bind(loop);
12107    __ stp(ZR, ZR, Address($ptr$$Register, -16, pre_indexed));
12108    __ subs($temp$$Register, $temp$$Register, 16);
12109    __ b(loop, ge);
12110    __ bind(done16);
12111    __ adds($temp$$Register, $temp$$Register, 8);
12112    __ b(done, lt);
12113    // $temp should be 0 here
12114    __ str(ZR, Address($base$$Register, $temp$$Register));
12115    __ bind(done);
12116  %}
12117  ins_pipe(long_memory_op);
12118%}
12119#else
12120// Count and Base registers are fixed because the allocator cannot
12121// kill unknown registers.  The encodings are generic.
12122instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{
12123  match(Set dummy (ClearArray cnt base));
12124  effect(TEMP temp, TEMP zero, KILL cpsr);
12125  ins_cost(300);
12126  format %{ "MOV    $zero,0\n"
12127      "        MOV    $temp,$cnt\n"
12128      "loop:   SUBS   $temp,$temp,4\t! Count down a dword of bytes\n"
12129      "        STR.ge $zero,[$base+$temp]\t! delay slot"
12130      "        B.gt   loop\t\t! Clearing loop\n" %}
12131  ins_encode %{
12132    __ mov($zero$$Register, 0);
12133    __ mov($temp$$Register, $cnt$$Register);
12134    Label(loop);
12135    __ bind(loop);
12136    __ subs($temp$$Register, $temp$$Register, 4);
12137    __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge);
12138    __ b(loop, gt);
12139  %}
12140  ins_pipe(long_memory_op);
12141%}
12142#endif
12143
12144#ifdef XXX
12145// FIXME: Why R0/R1/R2/R3?
12146instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result,
12147                        iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
12148  predicate(!CompactStrings);
12149  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12150  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2);
12151  ins_cost(300);
12152  format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result   // TEMP $tmp1, $tmp2" %}
12153  ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) );
12154
12155  ins_pipe(long_memory_op);
12156%}
12157
12158// FIXME: Why R0/R1/R2?
12159instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2,
12160                       flagsReg ccr) %{
12161  predicate(!CompactStrings);
12162  match(Set result (StrEquals (Binary str1 str2) cnt));
12163  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr);
12164
12165  ins_cost(300);
12166  format %{ "String Equals $str1,$str2,$cnt -> $result   // TEMP $tmp1, $tmp2" %}
12167  ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) );
12168  ins_pipe(long_memory_op);
12169%}
12170
12171// FIXME: Why R0/R1?
12172instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result,
12173                      flagsReg ccr) %{
12174  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
12175  match(Set result (AryEq ary1 ary2));
12176  effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr);
12177
12178  ins_cost(300);
12179  format %{ "Array Equals $ary1,$ary2 -> $result   // TEMP $tmp1,$tmp2,$tmp3" %}
12180  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result));
12181  ins_pipe(long_memory_op);
12182%}
12183#endif
12184
12185//---------- Zeros Count Instructions ------------------------------------------
12186
12187instruct countLeadingZerosI(iRegI dst, iRegI src) %{
12188  match(Set dst (CountLeadingZerosI src));
12189  size(4);
12190  format %{ "CLZ_32 $dst,$src" %}
12191  ins_encode %{
12192    __ clz_32($dst$$Register, $src$$Register);
12193  %}
12194  ins_pipe(ialu_reg);
12195%}
12196
12197#ifdef AARCH64
12198instruct countLeadingZerosL(iRegI dst, iRegL src) %{
12199  match(Set dst (CountLeadingZerosL src));
12200  size(4);
12201  format %{ "CLZ $dst,$src" %}
12202  ins_encode %{
12203    __ clz($dst$$Register, $src$$Register);
12204  %}
12205  ins_pipe(ialu_reg);
12206%}
12207#else
12208instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
12209  match(Set dst (CountLeadingZerosL src));
12210  effect(TEMP tmp, TEMP dst, KILL ccr);
12211  size(16);
12212  format %{ "CLZ    $dst,$src.hi\n\t"
12213            "TEQ    $dst,32\n\t"
12214            "CLZ.eq $tmp,$src.lo\n\t"
12215            "ADD.eq $dst, $dst, $tmp\n\t" %}
12216  ins_encode %{
12217    __ clz($dst$$Register, $src$$Register->successor());
12218    __ teq($dst$$Register, 32);
12219    __ clz($tmp$$Register, $src$$Register, eq);
12220    __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
12221  %}
12222  ins_pipe(ialu_reg);
12223%}
12224#endif
12225
12226instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{
12227  match(Set dst (CountTrailingZerosI src));
12228  effect(TEMP tmp);
12229  size(8);
12230  format %{ "RBIT_32 $tmp, $src\n\t"
12231            "CLZ_32  $dst,$tmp" %}
12232  ins_encode %{
12233    __ rbit_32($tmp$$Register, $src$$Register);
12234    __ clz_32($dst$$Register, $tmp$$Register);
12235  %}
12236  ins_pipe(ialu_reg);
12237%}
12238
12239#ifdef AARCH64
12240instruct countTrailingZerosL(iRegI dst, iRegL src, iRegL tmp) %{
12241  match(Set dst (CountTrailingZerosL src));
12242  effect(TEMP tmp);
12243  size(8);
12244  format %{ "RBIT $tmp, $src\n\t"
12245            "CLZ  $dst,$tmp" %}
12246  ins_encode %{
12247    __ rbit($tmp$$Register, $src$$Register);
12248    __ clz($dst$$Register, $tmp$$Register);
12249  %}
12250  ins_pipe(ialu_reg);
12251%}
12252#else
12253instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
12254  match(Set dst (CountTrailingZerosL src));
12255  effect(TEMP tmp, TEMP dst, KILL ccr);
12256  size(24);
12257  format %{ "RBIT   $tmp,$src.lo\n\t"
12258            "CLZ    $dst,$tmp\n\t"
12259            "TEQ    $dst,32\n\t"
12260            "RBIT   $tmp,$src.hi\n\t"
12261            "CLZ.eq $tmp,$tmp\n\t"
12262            "ADD.eq $dst,$dst,$tmp\n\t" %}
12263  ins_encode %{
12264    __ rbit($tmp$$Register, $src$$Register);
12265    __ clz($dst$$Register, $tmp$$Register);
12266    __ teq($dst$$Register, 32);
12267    __ rbit($tmp$$Register, $src$$Register->successor());
12268    __ clz($tmp$$Register, $tmp$$Register, eq);
12269    __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
12270  %}
12271  ins_pipe(ialu_reg);
12272%}
12273#endif
12274
12275
12276//---------- Population Count Instructions -------------------------------------
12277
12278#ifdef AARCH64
12279instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
12280  predicate(UsePopCountInstruction);
12281  match(Set dst (PopCountI src));
12282  effect(TEMP tmp);
12283  size(20);
12284
12285  format %{ "MOV_W      $dst,$src\n\t"
12286            "FMOV_dx    $tmp,$dst\n\t"
12287            "VCNT       $tmp.8B,$tmp.8B\n\t"
12288            "ADDV       $tmp.B,$tmp.8B\n\t"
12289            "FMRS       $dst,$tmp" %}
12290
12291  ins_encode %{
12292    __ mov_w($dst$$Register, $src$$Register);
12293    __ fmov_dx($tmp$$FloatRegister, $dst$$Register);
12294    int quad = 0;
12295    int cnt_size = 0; // VELEM_SIZE_8
12296    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size);
12297    int add_size = 0; // VELEM_SIZE_8
12298    __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size);
12299    __ fmrs($dst$$Register, $tmp$$FloatRegister);
12300  %}
12301  ins_pipe(ialu_reg); // FIXME
12302%}
12303#else
12304instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
12305  predicate(UsePopCountInstruction);
12306  match(Set dst (PopCountI src));
12307  effect(TEMP tmp);
12308
12309  format %{ "FMSR       $tmp,$src\n\t"
12310            "VCNT.8     $tmp,$tmp\n\t"
12311            "VPADDL.U8  $tmp,$tmp\n\t"
12312            "VPADDL.U16 $tmp,$tmp\n\t"
12313            "FMRS       $dst,$tmp" %}
12314  size(20);
12315
12316  ins_encode %{
12317    __ fmsr($tmp$$FloatRegister, $src$$Register);
12318    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
12319    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
12320    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
12321    __ fmrs($dst$$Register, $tmp$$FloatRegister);
12322  %}
12323  ins_pipe(ialu_reg); // FIXME
12324%}
12325#endif
12326
12327#ifdef AARCH64
12328instruct popCountL(iRegI dst, iRegL src, regD tmp) %{
12329  predicate(UsePopCountInstruction);
12330  match(Set dst (PopCountL src));
12331  effect(TEMP tmp);
12332  size(16);
12333
12334  format %{ "FMOV_dx    $tmp,$src\n\t"
12335            "VCNT       $tmp.8B,$tmp.8B\n\t"
12336            "ADDV       $tmp.B,$tmp.8B\n\t"
12337            "FMOV_ws    $dst,$tmp" %}
12338
12339  ins_encode %{
12340    __ fmov_dx($tmp$$FloatRegister, $src$$Register);
12341    int quad = 0;
12342    int cnt_size = 0;
12343    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size);
12344    int add_size = 0;
12345    __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size);
12346    __ fmov_ws($dst$$Register, $tmp$$FloatRegister);
12347  %}
12348  ins_pipe(ialu_reg); // FIXME
12349%}
12350#else
12351// Note: Long.bitCount(long) returns an int.
12352instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{
12353  predicate(UsePopCountInstruction);
12354  match(Set dst (PopCountL src));
12355  effect(TEMP tmp);
12356
12357  format %{ "FMDRR       $tmp,$src.lo,$src.hi\n\t"
12358            "VCNT.8      $tmp,$tmp\n\t"
12359            "VPADDL.U8   $tmp,$tmp\n\t"
12360            "VPADDL.U16  $tmp,$tmp\n\t"
12361            "VPADDL.U32  $tmp,$tmp\n\t"
12362            "FMRS        $dst,$tmp" %}
12363
12364  size(32);
12365
12366  ins_encode %{
12367    __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor());
12368    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
12369    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
12370    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
12371    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0);
12372    __ fmrs($dst$$Register, $tmp$$FloatRegister);
12373  %}
12374  ins_pipe(ialu_reg);
12375%}
12376#endif
12377
12378
12379// ============================================================================
12380//------------Bytes reverse--------------------------------------------------
12381
12382instruct bytes_reverse_int(iRegI dst, iRegI src) %{
12383  match(Set dst (ReverseBytesI src));
12384
12385  size(4);
12386  format %{ "REV32 $dst,$src" %}
12387  ins_encode %{
12388#ifdef AARCH64
12389    __ rev_w($dst$$Register, $src$$Register);
12390    // high 32 bits zeroed, not sign extended
12391#else
12392    __ rev($dst$$Register, $src$$Register);
12393#endif
12394  %}
12395  ins_pipe( iload_mem ); // FIXME
12396%}
12397
12398instruct bytes_reverse_long(iRegL dst, iRegL src) %{
12399  match(Set dst (ReverseBytesL src));
12400#ifdef AARCH64
12401//size(4);
12402  format %{ "REV $dst,$src"  %}
12403  ins_encode %{
12404    __ rev($dst$$Register, $src$$Register);
12405  %}
12406  ins_pipe(ialu_reg_reg); // FIXME
12407#else
12408  effect(TEMP dst);
12409  size(8);
12410  format %{ "REV $dst.lo,$src.lo\n\t"
12411            "REV $dst.hi,$src.hi" %}
12412  ins_encode %{
12413    __ rev($dst$$Register, $src$$Register->successor());
12414    __ rev($dst$$Register->successor(), $src$$Register);
12415  %}
12416  ins_pipe( iload_mem ); // FIXME
12417#endif
12418%}
12419
12420instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
12421  match(Set dst (ReverseBytesUS src));
12422#ifdef AARCH64
12423  size(4);
12424  format %{ "REV16_W $dst,$src" %}
12425  ins_encode %{
12426    __ rev16_w($dst$$Register, $src$$Register);
12427    // high 32 bits zeroed
12428  %}
12429#else
12430  size(4);
12431  format %{ "REV16 $dst,$src" %}
12432  ins_encode %{
12433    __ rev16($dst$$Register, $src$$Register);
12434  %}
12435#endif
12436  ins_pipe( iload_mem ); // FIXME
12437%}
12438
12439instruct bytes_reverse_short(iRegI dst, iRegI src) %{
12440  match(Set dst (ReverseBytesS src));
12441#ifdef AARCH64
12442  size(8);
12443  format %{ "REV16_W $dst,$src\n\t"
12444            "SIGN_EXT16 $dst" %}
12445  ins_encode %{
12446    __ rev16_w($dst$$Register, $src$$Register);
12447    __ sign_extend($dst$$Register, $dst$$Register, 16);
12448  %}
12449#else
12450  size(4);
12451  format %{ "REVSH $dst,$src" %}
12452  ins_encode %{
12453    __ revsh($dst$$Register, $src$$Register);
12454  %}
12455#endif
12456  ins_pipe( iload_mem ); // FIXME
12457%}
12458
12459
12460// ====================VECTOR INSTRUCTIONS=====================================
12461
12462// Load Aligned Packed values into a Double Register
12463instruct loadV8(vecD dst, memoryD mem) %{
12464  predicate(n->as_LoadVector()->memory_size() == 8);
12465  match(Set dst (LoadVector mem));
12466  ins_cost(MEMORY_REF_COST);
12467  size(4);
12468  format %{ "FLDD   $mem,$dst\t! load vector (8 bytes)" %}
12469  ins_encode %{
12470    __ ldr_double($dst$$FloatRegister, $mem$$Address);
12471  %}
12472  ins_pipe(floadD_mem);
12473%}
12474
12475// Load Aligned Packed values into a Double Register Pair
12476instruct loadV16(vecX dst, memoryvld mem) %{
12477  predicate(n->as_LoadVector()->memory_size() == 16);
12478  match(Set dst (LoadVector mem));
12479  ins_cost(MEMORY_REF_COST);
12480  size(4);
12481  format %{ "VLD1   $mem,$dst.Q\t! load vector (16 bytes)" %}
12482  ins_encode %{
12483    __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
12484  %}
12485  ins_pipe(floadD_mem); // FIXME
12486%}
12487
12488// Store Vector in Double register to memory
12489instruct storeV8(memoryD mem, vecD src) %{
12490  predicate(n->as_StoreVector()->memory_size() == 8);
12491  match(Set mem (StoreVector mem src));
12492  ins_cost(MEMORY_REF_COST);
12493  size(4);
12494  format %{ "FSTD   $src,$mem\t! store vector (8 bytes)" %}
12495  ins_encode %{
12496    __ str_double($src$$FloatRegister, $mem$$Address);
12497  %}
12498  ins_pipe(fstoreD_mem_reg);
12499%}
12500
12501// Store Vector in Double Register Pair to memory
12502instruct storeV16(memoryvld mem, vecX src) %{
12503  predicate(n->as_StoreVector()->memory_size() == 16);
12504  match(Set mem (StoreVector mem src));
12505  ins_cost(MEMORY_REF_COST);
12506  size(4);
12507  format %{ "VST1   $src,$mem\t! store vector (16 bytes)" %}
12508  ins_encode %{
12509    __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
12510  %}
12511  ins_pipe(fstoreD_mem_reg); // FIXME
12512%}
12513
12514#ifndef AARCH64
12515// Replicate scalar to packed byte values in Double register
12516instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{
12517  predicate(n->as_Vector()->length() == 8);
12518  match(Set dst (ReplicateB src));
12519  ins_cost(DEFAULT_COST*4);
12520  effect(TEMP tmp);
12521  size(16);
12522
12523  // FIXME: could use PKH instruction instead?
12524  format %{ "LSL      $tmp, $src, 24 \n\t"
12525            "OR       $tmp, $tmp, ($tmp >> 8) \n\t"
12526            "OR       $tmp, $tmp, ($tmp >> 16) \n\t"
12527            "FMDRR    $dst,$tmp,$tmp\t" %}
12528  ins_encode %{
12529    __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24));
12530    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8));
12531    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
12532    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
12533  %}
12534  ins_pipe(ialu_reg); // FIXME
12535%}
12536#endif /* !AARCH64 */
12537
12538// Replicate scalar to packed byte values in Double register
12539instruct Repl8B_reg_simd(vecD dst, iRegI src) %{
12540  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12541  match(Set dst (ReplicateB src));
12542  size(4);
12543
12544  format %{ "VDUP.8 $dst,$src\t" %}
12545  ins_encode %{
12546    bool quad = false;
12547    __ vdupI($dst$$FloatRegister, $src$$Register,
12548             MacroAssembler::VELEM_SIZE_8, quad);
12549  %}
12550  ins_pipe(ialu_reg); // FIXME
12551%}
12552
12553// Replicate scalar to packed byte values in Double register pair
12554instruct Repl16B_reg(vecX dst, iRegI src) %{
12555  predicate(n->as_Vector()->length_in_bytes() == 16);
12556  match(Set dst (ReplicateB src));
12557  size(4);
12558
12559  format %{ "VDUP.8 $dst.Q,$src\t" %}
12560  ins_encode %{
12561    bool quad = true;
12562    __ vdupI($dst$$FloatRegister, $src$$Register,
12563             MacroAssembler::VELEM_SIZE_8, quad);
12564  %}
12565  ins_pipe(ialu_reg); // FIXME
12566%}
12567
12568#ifndef AARCH64
12569// Replicate scalar constant to packed byte values in Double register
12570instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{
12571  predicate(n->as_Vector()->length() == 8);
12572  match(Set dst (ReplicateB src));
12573  ins_cost(DEFAULT_COST*2);
12574  effect(TEMP tmp);
12575  size(12);
12576
12577  format %{ "MOV      $tmp, Repl4($src))\n\t"
12578            "FMDRR    $dst,$tmp,$tmp\t" %}
12579  ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) );
12580  ins_pipe(loadConFD); // FIXME
12581%}
12582#endif /* !AARCH64 */
12583
12584// Replicate scalar constant to packed byte values in Double register
12585// TODO: support negative constants with MVNI?
12586instruct Repl8B_immU8(vecD dst, immU8 src) %{
12587  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12588  match(Set dst (ReplicateB src));
12589  size(4);
12590
12591  format %{ "VMOV.U8  $dst,$src" %}
12592  ins_encode %{
12593    bool quad = false;
12594    __ vmovI($dst$$FloatRegister, $src$$constant,
12595             MacroAssembler::VELEM_SIZE_8, quad);
12596  %}
12597  ins_pipe(loadConFD); // FIXME
12598%}
12599
12600// Replicate scalar constant to packed byte values in Double register pair
12601instruct Repl16B_immU8(vecX dst, immU8 src) %{
12602  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
12603  match(Set dst (ReplicateB src));
12604  size(4);
12605
12606  format %{ "VMOV.U8  $dst.Q,$src" %}
12607  ins_encode %{
12608    bool quad = true;
12609    __ vmovI($dst$$FloatRegister, $src$$constant,
12610             MacroAssembler::VELEM_SIZE_8, quad);
12611  %}
12612  ins_pipe(loadConFD); // FIXME
12613%}
12614
12615#ifndef AARCH64
12616// Replicate scalar to packed short/char values into Double register
12617instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{
12618  predicate(n->as_Vector()->length() == 4);
12619  match(Set dst (ReplicateS src));
12620  ins_cost(DEFAULT_COST*3);
12621  effect(TEMP tmp);
12622  size(12);
12623
12624  // FIXME: could use PKH instruction instead?
12625  format %{ "LSL      $tmp, $src, 16 \n\t"
12626            "OR       $tmp, $tmp, ($tmp >> 16) \n\t"
12627            "FMDRR    $dst,$tmp,$tmp\t" %}
12628  ins_encode %{
12629    __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16));
12630    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
12631    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
12632  %}
12633  ins_pipe(ialu_reg); // FIXME
12634%}
12635#endif /* !AARCH64 */
12636
12637// Replicate scalar to packed byte values in Double register
12638instruct Repl4S_reg_simd(vecD dst, iRegI src) %{
12639  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12640  match(Set dst (ReplicateS src));
12641  size(4);
12642
12643  format %{ "VDUP.16 $dst,$src\t" %}
12644  ins_encode %{
12645    bool quad = false;
12646    __ vdupI($dst$$FloatRegister, $src$$Register,
12647             MacroAssembler::VELEM_SIZE_16, quad);
12648  %}
12649  ins_pipe(ialu_reg); // FIXME
12650%}
12651
12652// Replicate scalar to packed byte values in Double register pair
12653instruct Repl8S_reg(vecX dst, iRegI src) %{
12654  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
12655  match(Set dst (ReplicateS src));
12656  size(4);
12657
12658  format %{ "VDUP.16 $dst.Q,$src\t" %}
12659  ins_encode %{
12660    bool quad = true;
12661    __ vdupI($dst$$FloatRegister, $src$$Register,
12662             MacroAssembler::VELEM_SIZE_16, quad);
12663  %}
12664  ins_pipe(ialu_reg); // FIXME
12665%}
12666
12667
12668#ifndef AARCH64
12669// Replicate scalar constant to packed short/char values in Double register
12670instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{
12671  predicate(n->as_Vector()->length() == 4);
12672  match(Set dst (ReplicateS src));
12673  effect(TEMP tmp);
12674  size(12);
12675  ins_cost(DEFAULT_COST*4); // FIXME
12676
12677  format %{ "MOV      $tmp, Repl2($src))\n\t"
12678            "FMDRR    $dst,$tmp,$tmp\t" %}
12679  ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) );
12680  ins_pipe(loadConFD); // FIXME
12681%}
12682#endif /* !AARCH64 */
12683
12684// Replicate scalar constant to packed byte values in Double register
12685instruct Repl4S_immU8(vecD dst, immU8 src) %{
12686  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12687  match(Set dst (ReplicateS src));
12688  size(4);
12689
12690  format %{ "VMOV.U16  $dst,$src" %}
12691  ins_encode %{
12692    bool quad = false;
12693    __ vmovI($dst$$FloatRegister, $src$$constant,
12694             MacroAssembler::VELEM_SIZE_16, quad);
12695  %}
12696  ins_pipe(loadConFD); // FIXME
12697%}
12698
12699// Replicate scalar constant to packed byte values in Double register pair
12700instruct Repl8S_immU8(vecX dst, immU8 src) %{
12701  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
12702  match(Set dst (ReplicateS src));
12703  size(4);
12704
12705  format %{ "VMOV.U16  $dst.Q,$src" %}
12706  ins_encode %{
12707    bool quad = true;
12708    __ vmovI($dst$$FloatRegister, $src$$constant,
12709             MacroAssembler::VELEM_SIZE_16, quad);
12710  %}
12711  ins_pipe(loadConFD); // FIXME
12712%}
12713
12714#ifndef AARCH64
12715// Replicate scalar to packed int values in Double register
12716instruct Repl2I_reg(vecD dst, iRegI src) %{
12717  predicate(n->as_Vector()->length() == 2);
12718  match(Set dst (ReplicateI src));
12719  size(4);
12720
12721  format %{ "FMDRR    $dst,$src,$src\t" %}
12722  ins_encode %{
12723    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
12724  %}
12725  ins_pipe(ialu_reg); // FIXME
12726%}
12727
12728// Replicate scalar to packed int values in Double register pair
12729instruct Repl4I_reg(vecX dst, iRegI src) %{
12730  predicate(n->as_Vector()->length() == 4);
12731  match(Set dst (ReplicateI src));
12732  ins_cost(DEFAULT_COST*2);
12733  size(8);
12734
12735  format %{ "FMDRR    $dst.lo,$src,$src\n\t"
12736            "FMDRR    $dst.hi,$src,$src" %}
12737
12738  ins_encode %{
12739    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
12740    __ fmdrr($dst$$FloatRegister->successor()->successor(),
12741             $src$$Register, $src$$Register);
12742  %}
12743  ins_pipe(ialu_reg); // FIXME
12744%}
12745#endif /* !AARCH64 */
12746
12747// Replicate scalar to packed int values in Double register
12748instruct Repl2I_reg_simd(vecD dst, iRegI src) %{
12749  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12750  match(Set dst (ReplicateI src));
12751  size(4);
12752
12753  format %{ "VDUP.32 $dst.D,$src\t" %}
12754  ins_encode %{
12755    bool quad = false;
12756    __ vdupI($dst$$FloatRegister, $src$$Register,
12757             MacroAssembler::VELEM_SIZE_32, quad);
12758  %}
12759  ins_pipe(ialu_reg); // FIXME
12760%}
12761
12762// Replicate scalar to packed int values in Double register pair
12763instruct Repl4I_reg_simd(vecX dst, iRegI src) %{
12764  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
12765  match(Set dst (ReplicateI src));
12766  size(4);
12767
12768  format %{ "VDUP.32 $dst.Q,$src\t" %}
12769  ins_encode %{
12770    bool quad = true;
12771    __ vdupI($dst$$FloatRegister, $src$$Register,
12772             MacroAssembler::VELEM_SIZE_32, quad);
12773  %}
12774  ins_pipe(ialu_reg); // FIXME
12775%}
12776
12777
12778#ifndef AARCH64
12779// Replicate scalar zero constant to packed int values in Double register
12780instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{
12781  predicate(n->as_Vector()->length() == 2);
12782  match(Set dst (ReplicateI src));
12783  effect(TEMP tmp);
12784  size(12);
12785  ins_cost(DEFAULT_COST*4); // FIXME
12786
12787  format %{ "MOV      $tmp, Repl1($src))\n\t"
12788            "FMDRR    $dst,$tmp,$tmp\t" %}
12789  ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) );
12790  ins_pipe(loadConFD); // FIXME
12791%}
12792#endif /* !AARCH64 */
12793
12794// Replicate scalar constant to packed byte values in Double register
12795instruct Repl2I_immU8(vecD dst, immU8 src) %{
12796  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12797  match(Set dst (ReplicateI src));
12798  size(4);
12799
12800  format %{ "VMOV.I32  $dst.D,$src" %}
12801  ins_encode %{
12802    bool quad = false;
12803    __ vmovI($dst$$FloatRegister, $src$$constant,
12804             MacroAssembler::VELEM_SIZE_32, quad);
12805  %}
12806  ins_pipe(loadConFD); // FIXME
12807%}
12808
12809// Replicate scalar constant to packed byte values in Double register pair
12810instruct Repl4I_immU8(vecX dst, immU8 src) %{
12811  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
12812  match(Set dst (ReplicateI src));
12813  size(4);
12814
12815  format %{ "VMOV.I32  $dst.Q,$src" %}
12816  ins_encode %{
12817    bool quad = true;
12818    __ vmovI($dst$$FloatRegister, $src$$constant,
12819             MacroAssembler::VELEM_SIZE_32, quad);
12820  %}
12821  ins_pipe(loadConFD); // FIXME
12822%}
12823
12824#ifdef AARCH64
12825// Replicate scalar to packed byte values in Double register pair
12826instruct Repl2L_reg(vecX dst, iRegL src) %{
12827  predicate(n->as_Vector()->length() == 2);
12828  match(Set dst (ReplicateL src));
12829  size(4*1);
12830  ins_cost(DEFAULT_COST*1); // FIXME
12831
12832  format %{ "VDUP.2D $dst.Q,$src\t" %}
12833  ins_encode %{
12834    bool quad = true;
12835    __ vdupI($dst$$FloatRegister, $src$$Register,
12836             MacroAssembler::VELEM_SIZE_64, quad);
12837  %}
12838  ins_pipe(ialu_reg); // FIXME
12839%}
12840#else /* !AARCH64 */
12841// Replicate scalar to packed byte values in Double register pair
12842instruct Repl2L_reg(vecX dst, iRegL src) %{
12843  predicate(n->as_Vector()->length() == 2);
12844  match(Set dst (ReplicateL src));
12845  size(8);
12846  ins_cost(DEFAULT_COST*2); // FIXME
12847
12848  format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n"
12849            "FMDRR $dst.D.next,$src.lo,$src.hi" %}
12850  ins_encode %{
12851    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
12852    __ fmdrr($dst$$FloatRegister->successor()->successor(),
12853             $src$$Register, $src$$Register->successor());
12854  %}
12855  ins_pipe(ialu_reg); // FIXME
12856%}
12857
12858
12859// Replicate scalar to packed float values in Double register
12860instruct Repl2F_regI(vecD dst, iRegI src) %{
12861  predicate(n->as_Vector()->length() == 2);
12862  match(Set dst (ReplicateF src));
12863  size(4);
12864
12865  format %{ "FMDRR    $dst.D,$src,$src\t" %}
12866  ins_encode %{
12867    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
12868  %}
12869  ins_pipe(ialu_reg); // FIXME
12870%}
12871
12872// Replicate scalar to packed float values in Double register
12873instruct Repl2F_reg_vfp(vecD dst, regF src) %{
12874  predicate(n->as_Vector()->length() == 2);
12875  match(Set dst (ReplicateF src));
12876  size(4*2);
12877  ins_cost(DEFAULT_COST*2); // FIXME
12878
12879  expand %{
12880    iRegI tmp;
12881    MoveF2I_reg_reg(tmp, src);
12882    Repl2F_regI(dst,tmp);
12883  %}
12884%}
12885#endif /* !AARCH64 */
12886
12887// Replicate scalar to packed float values in Double register
12888instruct Repl2F_reg_simd(vecD dst, regF src) %{
12889  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
12890  match(Set dst (ReplicateF src));
12891  size(4);
12892  ins_cost(DEFAULT_COST); // FIXME
12893
12894  format %{ "VDUP.32  $dst.D,$src.D\t" %}
12895  ins_encode %{
12896    bool quad = false;
12897    __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
12898  %}
12899  ins_pipe(ialu_reg); // FIXME
12900%}
12901
12902#ifndef AARCH64
12903// Replicate scalar to packed float values in Double register pair
12904instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{
12905  predicate(n->as_Vector()->length() == 4);
12906  match(Set dst (ReplicateF src));
12907  effect(TEMP tmp);
12908  size(4*3);
12909  ins_cost(DEFAULT_COST*3); // FIXME
12910
12911  format %{ "FMRS     $tmp,$src\n\t"
12912            "FMDRR    $dst.D,$tmp,$tmp\n\t"
12913            "FMDRR    $dst.D.next,$tmp,$tmp\t" %}
12914  ins_encode %{
12915    __ fmrs($tmp$$Register, $src$$FloatRegister);
12916    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
12917    __ fmdrr($dst$$FloatRegister->successor()->successor(),
12918             $tmp$$Register, $tmp$$Register);
12919  %}
12920  ins_pipe(ialu_reg); // FIXME
12921%}
12922#endif /* !AARCH64 */
12923
12924// Replicate scalar to packed float values in Double register pair
12925instruct Repl4F_reg_simd(vecX dst, regF src) %{
12926  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
12927  match(Set dst (ReplicateF src));
12928  size(4);
12929  ins_cost(DEFAULT_COST); // FIXME
12930
12931  format %{ "VDUP.32  $dst.Q,$src.D\t" %}
12932  ins_encode %{
12933    bool quad = true;
12934    __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
12935  %}
12936  ins_pipe(ialu_reg); // FIXME
12937%}
12938
12939#ifndef AARCH64
12940// Replicate scalar zero constant to packed float values in Double register
12941instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{
12942  predicate(n->as_Vector()->length() == 2);
12943  match(Set dst (ReplicateF src));
12944  effect(TEMP tmp);
12945  size(12);
12946  ins_cost(DEFAULT_COST*4); // FIXME
12947
12948  format %{ "MOV      $tmp, Repl1($src))\n\t"
12949            "FMDRR    $dst,$tmp,$tmp\t" %}
12950  ins_encode( LdReplImmF(src, dst, tmp) );
12951  ins_pipe(loadConFD); // FIXME
12952%}
12953#endif /* !AAARCH64 */
12954
12955// Replicate scalar to packed double float values in Double register pair
12956instruct Repl2D_reg(vecX dst, regD src) %{
12957#ifdef AARCH64
12958  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
12959  match(Set dst (ReplicateD src));
12960  size(4*1);
12961  ins_cost(DEFAULT_COST*1); // FIXME
12962
12963  format %{ "VDUP     $dst.2D,$src\t" %}
12964  ins_encode %{
12965    bool quad = true;
12966    __ vdupD($dst$$FloatRegister, $src$$FloatRegister, quad);
12967  %}
12968#else
12969  predicate(n->as_Vector()->length() == 2);
12970  match(Set dst (ReplicateD src));
12971  size(4*2);
12972  ins_cost(DEFAULT_COST*2); // FIXME
12973
12974  format %{ "FCPYD    $dst.D.a,$src\n\t"
12975            "FCPYD    $dst.D.b,$src\t" %}
12976  ins_encode %{
12977    FloatRegister dsta = $dst$$FloatRegister;
12978    FloatRegister src = $src$$FloatRegister;
12979    __ fcpyd(dsta, src);
12980    FloatRegister dstb = dsta->successor()->successor();
12981    __ fcpyd(dstb, src);
12982  %}
12983#endif
12984  ins_pipe(ialu_reg); // FIXME
12985%}
12986
12987// ====================VECTOR ARITHMETIC=======================================
12988
12989// --------------------------------- ADD --------------------------------------
12990
12991// Bytes vector add
12992instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{
12993  predicate(n->as_Vector()->length() == 8);
12994  match(Set dst (AddVB src1 src2));
12995  format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %}
12996  size(4);
12997  ins_encode %{
12998    bool quad = false;
12999    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13000             MacroAssembler::VELEM_SIZE_8, quad);
13001  %}
13002  ins_pipe( ialu_reg_reg ); // FIXME
13003%}
13004
13005instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
13006  predicate(n->as_Vector()->length() == 16);
13007  match(Set dst (AddVB src1 src2));
13008  size(4);
13009  format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %}
13010  ins_encode %{
13011    bool quad = true;
13012    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13013             MacroAssembler::VELEM_SIZE_8, quad);
13014  %}
13015  ins_pipe( ialu_reg_reg ); // FIXME
13016%}
13017
13018// Shorts/Chars vector add
13019instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{
13020  predicate(n->as_Vector()->length() == 4);
13021  match(Set dst (AddVS src1 src2));
13022  size(4);
13023  format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %}
13024  ins_encode %{
13025    bool quad = false;
13026    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13027             MacroAssembler::VELEM_SIZE_16, quad);
13028  %}
13029  ins_pipe( ialu_reg_reg ); // FIXME
13030%}
13031
13032instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
13033  predicate(n->as_Vector()->length() == 8);
13034  match(Set dst (AddVS src1 src2));
13035  size(4);
13036  format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %}
13037  ins_encode %{
13038    bool quad = true;
13039    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13040             MacroAssembler::VELEM_SIZE_16, quad);
13041  %}
13042  ins_pipe( ialu_reg_reg ); // FIXME
13043%}
13044
13045// Integers vector add
13046instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{
13047  predicate(n->as_Vector()->length() == 2);
13048  match(Set dst (AddVI src1 src2));
13049  size(4);
13050  format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %}
13051  ins_encode %{
13052    bool quad = false;
13053    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13054             MacroAssembler::VELEM_SIZE_32, quad);
13055  %}
13056  ins_pipe( ialu_reg_reg ); // FIXME
13057%}
13058
13059instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
13060  predicate(n->as_Vector()->length() == 4);
13061  match(Set dst (AddVI src1 src2));
13062  size(4);
13063  format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %}
13064  ins_encode %{
13065    bool quad = true;
13066    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13067             MacroAssembler::VELEM_SIZE_32, quad);
13068  %}
13069  ins_pipe( ialu_reg_reg ); // FIXME
13070%}
13071
13072// Longs vector add
13073instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
13074  predicate(n->as_Vector()->length() == 2);
13075  match(Set dst (AddVL src1 src2));
13076  size(4);
13077  format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %}
13078  ins_encode %{
13079    bool quad = true;
13080    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13081             MacroAssembler::VELEM_SIZE_64, quad);
13082  %}
13083  ins_pipe( ialu_reg_reg ); // FIXME
13084%}
13085
13086// Floats vector add
13087instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{
13088  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
13089  match(Set dst (AddVF src1 src2));
13090  size(4);
13091  format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %}
13092  ins_encode %{
13093    bool quad = false;
13094    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13095             MacroAssembler::VFA_SIZE_F32, quad);
13096  %}
13097  ins_pipe( faddD_reg_reg ); // FIXME
13098%}
13099
13100#ifndef AARCH64
13101instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
13102  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
13103  match(Set dst (AddVF src1 src2));
13104  ins_cost(DEFAULT_COST*2); // FIXME
13105
13106  size(4*2);
13107  format %{ "FADDS  $dst.a,$src1.a,$src2.a\n\t"
13108            "FADDS  $dst.b,$src1.b,$src2.b" %}
13109  ins_encode %{
13110    __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
13111    __ add_float($dst$$FloatRegister->successor(),
13112             $src1$$FloatRegister->successor(),
13113             $src2$$FloatRegister->successor());
13114  %}
13115
13116  ins_pipe(faddF_reg_reg); // FIXME
13117%}
13118#endif
13119
13120instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{
13121  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
13122  match(Set dst (AddVF src1 src2));
13123  size(4);
13124  format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %}
13125  ins_encode %{
13126    bool quad = true;
13127    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13128             MacroAssembler::VFA_SIZE_F32, quad);
13129  %}
13130  ins_pipe( faddD_reg_reg ); // FIXME
13131%}
13132
13133#ifdef AARCH64
13134instruct vadd2D_reg_simd(vecX dst, vecX src1, vecX src2) %{
13135  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
13136  match(Set dst (AddVD src1 src2));
13137  size(4);
13138  format %{ "VADD.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %}
13139  ins_encode %{
13140    bool quad = true;
13141    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13142             MacroAssembler::VFA_SIZE_F64, quad);
13143  %}
13144  ins_pipe( faddD_reg_reg ); // FIXME
13145%}
13146#else
13147instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13148  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
13149  match(Set dst (AddVF src1 src2));
13150  size(4*4);
13151  ins_cost(DEFAULT_COST*4); // FIXME
13152
13153  format %{ "FADDS  $dst.a,$src1.a,$src2.a\n\t"
13154            "FADDS  $dst.b,$src1.b,$src2.b\n\t"
13155            "FADDS  $dst.c,$src1.c,$src2.c\n\t"
13156            "FADDS  $dst.d,$src1.d,$src2.d" %}
13157
13158  ins_encode %{
13159    FloatRegister dsta = $dst$$FloatRegister;
13160    FloatRegister src1a = $src1$$FloatRegister;
13161    FloatRegister src2a = $src2$$FloatRegister;
13162    __ add_float(dsta, src1a, src2a);
13163    FloatRegister dstb = dsta->successor();
13164    FloatRegister src1b = src1a->successor();
13165    FloatRegister src2b = src2a->successor();
13166    __ add_float(dstb, src1b, src2b);
13167    FloatRegister dstc = dstb->successor();
13168    FloatRegister src1c = src1b->successor();
13169    FloatRegister src2c = src2b->successor();
13170    __ add_float(dstc, src1c, src2c);
13171    FloatRegister dstd = dstc->successor();
13172    FloatRegister src1d = src1c->successor();
13173    FloatRegister src2d = src2c->successor();
13174    __ add_float(dstd, src1d, src2d);
13175  %}
13176
13177  ins_pipe(faddF_reg_reg); // FIXME
13178%}
13179
13180instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13181  predicate(n->as_Vector()->length() == 2);
13182  match(Set dst (AddVD src1 src2));
13183  size(4*2);
13184  ins_cost(DEFAULT_COST*2); // FIXME
13185
13186  format %{ "FADDD  $dst.a,$src1.a,$src2.a\n\t"
13187            "FADDD  $dst.b,$src1.b,$src2.b" %}
13188
13189  ins_encode %{
13190    FloatRegister dsta = $dst$$FloatRegister;
13191    FloatRegister src1a = $src1$$FloatRegister;
13192    FloatRegister src2a = $src2$$FloatRegister;
13193    __ add_double(dsta, src1a, src2a);
13194    FloatRegister dstb = dsta->successor()->successor();
13195    FloatRegister src1b = src1a->successor()->successor();
13196    FloatRegister src2b = src2a->successor()->successor();
13197    __ add_double(dstb, src1b, src2b);
13198  %}
13199
13200  ins_pipe(faddF_reg_reg); // FIXME
13201%}
13202#endif
13203
13204
13205// Bytes vector sub
13206instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{
13207  predicate(n->as_Vector()->length() == 8);
13208  match(Set dst (SubVB src1 src2));
13209  size(4);
13210  format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %}
13211  ins_encode %{
13212    bool quad = false;
13213    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13214             MacroAssembler::VELEM_SIZE_8, quad);
13215  %}
13216  ins_pipe( ialu_reg_reg ); // FIXME
13217%}
13218
13219instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
13220  predicate(n->as_Vector()->length() == 16);
13221  match(Set dst (SubVB src1 src2));
13222  size(4);
13223  format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %}
13224  ins_encode %{
13225    bool quad = true;
13226    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13227             MacroAssembler::VELEM_SIZE_8, quad);
13228  %}
13229  ins_pipe( ialu_reg_reg ); // FIXME
13230%}
13231
13232// Shorts/Chars vector sub
13233instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{
13234  predicate(n->as_Vector()->length() == 4);
13235  match(Set dst (SubVS src1 src2));
13236  size(4);
13237  format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %}
13238  ins_encode %{
13239    bool quad = false;
13240    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13241             MacroAssembler::VELEM_SIZE_16, quad);
13242  %}
13243  ins_pipe( ialu_reg_reg ); // FIXME
13244%}
13245
13246instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{
13247  predicate(n->as_Vector()->length() == 8);
13248  match(Set dst (SubVS src1 src2));
13249  size(4);
13250  format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %}
13251  ins_encode %{
13252    bool quad = true;
13253    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13254             MacroAssembler::VELEM_SIZE_16, quad);
13255  %}
13256  ins_pipe( ialu_reg_reg ); // FIXME
13257%}
13258
13259// Integers vector sub
13260instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{
13261  predicate(n->as_Vector()->length() == 2);
13262  match(Set dst (SubVI src1 src2));
13263  size(4);
13264  format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %}
13265  ins_encode %{
13266    bool quad = false;
13267    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13268             MacroAssembler::VELEM_SIZE_32, quad);
13269  %}
13270  ins_pipe( ialu_reg_reg ); // FIXME
13271%}
13272
13273instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
13274  predicate(n->as_Vector()->length() == 4);
13275  match(Set dst (SubVI src1 src2));
13276  size(4);
13277  format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %}
13278  ins_encode %{
13279    bool quad = true;
13280    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13281             MacroAssembler::VELEM_SIZE_32, quad);
13282  %}
13283  ins_pipe( ialu_reg_reg ); // FIXME
13284%}
13285
13286// Longs vector sub
13287instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
13288  predicate(n->as_Vector()->length() == 2);
13289  match(Set dst (SubVL src1 src2));
13290  size(4);
13291  format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %}
13292  ins_encode %{
13293    bool quad = true;
13294    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13295             MacroAssembler::VELEM_SIZE_64, quad);
13296  %}
13297  ins_pipe( ialu_reg_reg ); // FIXME
13298%}
13299
13300// Floats vector sub
13301instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{
13302  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
13303  match(Set dst (SubVF src1 src2));
13304  size(4);
13305  format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %}
13306  ins_encode %{
13307    bool quad = false;
13308    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13309             MacroAssembler::VFA_SIZE_F32, quad);
13310  %}
13311  ins_pipe( faddF_reg_reg ); // FIXME
13312%}
13313
13314#ifndef AARCH64
13315instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
13316  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
13317  match(Set dst (SubVF src1 src2));
13318  size(4*2);
13319  ins_cost(DEFAULT_COST*2); // FIXME
13320
13321  format %{ "FSUBS  $dst.a,$src1.a,$src2.a\n\t"
13322            "FSUBS  $dst.b,$src1.b,$src2.b" %}
13323
13324  ins_encode %{
13325    FloatRegister dsta = $dst$$FloatRegister;
13326    FloatRegister src1a = $src1$$FloatRegister;
13327    FloatRegister src2a = $src2$$FloatRegister;
13328    __ sub_float(dsta, src1a, src2a);
13329    FloatRegister dstb = dsta->successor();
13330    FloatRegister src1b = src1a->successor();
13331    FloatRegister src2b = src2a->successor();
13332    __ sub_float(dstb, src1b, src2b);
13333  %}
13334
13335  ins_pipe(faddF_reg_reg); // FIXME
13336%}
13337#endif
13338
13339
13340instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
13341  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
13342  match(Set dst (SubVF src1 src2));
13343  size(4);
13344  format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %}
13345  ins_encode %{
13346    bool quad = true;
13347    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13348             MacroAssembler::VFA_SIZE_F32, quad);
13349  %}
13350  ins_pipe( faddF_reg_reg ); // FIXME
13351%}
13352
13353#ifdef AARCH64
13354instruct vsub2D_reg_simd(vecX dst, vecX src1, vecX src2) %{
13355  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
13356  match(Set dst (SubVD src1 src2));
13357  size(4);
13358  format %{ "VSUB.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %}
13359  ins_encode %{
13360    bool quad = true;
13361    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13362             MacroAssembler::VFA_SIZE_F64, quad);
13363  %}
13364  ins_pipe( faddD_reg_reg ); // FIXME
13365%}
13366#else
13367instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13368  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
13369  match(Set dst (SubVF src1 src2));
13370  size(4*4);
13371  ins_cost(DEFAULT_COST*4); // FIXME
13372
13373  format %{ "FSUBS  $dst.a,$src1.a,$src2.a\n\t"
13374            "FSUBS  $dst.b,$src1.b,$src2.b\n\t"
13375            "FSUBS  $dst.c,$src1.c,$src2.c\n\t"
13376            "FSUBS  $dst.d,$src1.d,$src2.d" %}
13377
13378  ins_encode %{
13379    FloatRegister dsta = $dst$$FloatRegister;
13380    FloatRegister src1a = $src1$$FloatRegister;
13381    FloatRegister src2a = $src2$$FloatRegister;
13382    __ sub_float(dsta, src1a, src2a);
13383    FloatRegister dstb = dsta->successor();
13384    FloatRegister src1b = src1a->successor();
13385    FloatRegister src2b = src2a->successor();
13386    __ sub_float(dstb, src1b, src2b);
13387    FloatRegister dstc = dstb->successor();
13388    FloatRegister src1c = src1b->successor();
13389    FloatRegister src2c = src2b->successor();
13390    __ sub_float(dstc, src1c, src2c);
13391    FloatRegister dstd = dstc->successor();
13392    FloatRegister src1d = src1c->successor();
13393    FloatRegister src2d = src2c->successor();
13394    __ sub_float(dstd, src1d, src2d);
13395  %}
13396
13397  ins_pipe(faddF_reg_reg); // FIXME
13398%}
13399
13400instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13401  predicate(n->as_Vector()->length() == 2);
13402  match(Set dst (SubVD src1 src2));
13403  size(4*2);
13404  ins_cost(DEFAULT_COST*2); // FIXME
13405
13406  format %{ "FSUBD  $dst.a,$src1.a,$src2.a\n\t"
13407            "FSUBD  $dst.b,$src1.b,$src2.b" %}
13408
13409  ins_encode %{
13410    FloatRegister dsta = $dst$$FloatRegister;
13411    FloatRegister src1a = $src1$$FloatRegister;
13412    FloatRegister src2a = $src2$$FloatRegister;
13413    __ sub_double(dsta, src1a, src2a);
13414    FloatRegister dstb = dsta->successor()->successor();
13415    FloatRegister src1b = src1a->successor()->successor();
13416    FloatRegister src2b = src2a->successor()->successor();
13417    __ sub_double(dstb, src1b, src2b);
13418  %}
13419
13420  ins_pipe(faddF_reg_reg); // FIXME
13421%}
13422#endif
13423
13424// Shorts/Chars vector mul
13425instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{
13426  predicate(n->as_Vector()->length() == 4);
13427  match(Set dst (MulVS src1 src2));
13428  size(4);
13429  format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %}
13430  ins_encode %{
13431    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13432             MacroAssembler::VELEM_SIZE_16, 0);
13433  %}
13434  ins_pipe( ialu_reg_reg ); // FIXME
13435%}
13436
13437instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{
13438  predicate(n->as_Vector()->length() == 8);
13439  match(Set dst (MulVS src1 src2));
13440  size(4);
13441  format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %}
13442  ins_encode %{
13443    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13444             MacroAssembler::VELEM_SIZE_16, 1);
13445  %}
13446  ins_pipe( ialu_reg_reg ); // FIXME
13447%}
13448
13449// Integers vector mul
13450instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{
13451  predicate(n->as_Vector()->length() == 2);
13452  match(Set dst (MulVI src1 src2));
13453  size(4);
13454  format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %}
13455  ins_encode %{
13456    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13457             MacroAssembler::VELEM_SIZE_32, 0);
13458  %}
13459  ins_pipe( ialu_reg_reg ); // FIXME
13460%}
13461
13462instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
13463  predicate(n->as_Vector()->length() == 4);
13464  match(Set dst (MulVI src1 src2));
13465  size(4);
13466  format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %}
13467  ins_encode %{
13468    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13469             MacroAssembler::VELEM_SIZE_32, 1);
13470  %}
13471  ins_pipe( ialu_reg_reg ); // FIXME
13472%}
13473
13474// Floats vector mul
13475instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{
13476  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
13477  match(Set dst (MulVF src1 src2));
13478  size(4);
13479  format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %}
13480  ins_encode %{
13481    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13482             MacroAssembler::VFA_SIZE_F32, 0);
13483  %}
13484  ins_pipe( fmulF_reg_reg ); // FIXME
13485%}
13486
13487#ifndef AARCH64
13488instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
13489  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
13490  match(Set dst (MulVF src1 src2));
13491  size(4*2);
13492  ins_cost(DEFAULT_COST*2); // FIXME
13493
13494  format %{ "FMULS  $dst.a,$src1.a,$src2.a\n\t"
13495            "FMULS  $dst.b,$src1.b,$src2.b" %}
13496  ins_encode %{
13497    __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
13498    __ mul_float($dst$$FloatRegister->successor(),
13499             $src1$$FloatRegister->successor(),
13500             $src2$$FloatRegister->successor());
13501  %}
13502
13503  ins_pipe(fmulF_reg_reg); // FIXME
13504%}
13505#endif
13506
13507instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
13508  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
13509  match(Set dst (MulVF src1 src2));
13510  size(4);
13511  format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %}
13512  ins_encode %{
13513    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13514             MacroAssembler::VFA_SIZE_F32, 1);
13515  %}
13516  ins_pipe( fmulF_reg_reg ); // FIXME
13517%}
13518
13519#ifndef AARCH64
13520instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13521  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
13522  match(Set dst (MulVF src1 src2));
13523  size(4*4);
13524  ins_cost(DEFAULT_COST*4); // FIXME
13525
13526  format %{ "FMULS  $dst.a,$src1.a,$src2.a\n\t"
13527            "FMULS  $dst.b,$src1.b,$src2.b\n\t"
13528            "FMULS  $dst.c,$src1.c,$src2.c\n\t"
13529            "FMULS  $dst.d,$src1.d,$src2.d" %}
13530
13531  ins_encode %{
13532    FloatRegister dsta = $dst$$FloatRegister;
13533    FloatRegister src1a = $src1$$FloatRegister;
13534    FloatRegister src2a = $src2$$FloatRegister;
13535    __ mul_float(dsta, src1a, src2a);
13536    FloatRegister dstb = dsta->successor();
13537    FloatRegister src1b = src1a->successor();
13538    FloatRegister src2b = src2a->successor();
13539    __ mul_float(dstb, src1b, src2b);
13540    FloatRegister dstc = dstb->successor();
13541    FloatRegister src1c = src1b->successor();
13542    FloatRegister src2c = src2b->successor();
13543    __ mul_float(dstc, src1c, src2c);
13544    FloatRegister dstd = dstc->successor();
13545    FloatRegister src1d = src1c->successor();
13546    FloatRegister src2d = src2c->successor();
13547    __ mul_float(dstd, src1d, src2d);
13548  %}
13549
13550  ins_pipe(fmulF_reg_reg); // FIXME
13551%}
13552#endif
13553
13554#ifdef AARCH64
13555instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{
13556  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
13557  match(Set dst (MulVD src1 src2));
13558  size(4*1);
13559  ins_cost(DEFAULT_COST*1); // FIXME
13560
13561  format %{ "FMUL.2D $dst,$src1,$src2\t! double[2]" %}
13562  ins_encode %{
13563    int quad = 1;
13564    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13565             MacroAssembler::VFA_SIZE_F64, quad);
13566  %}
13567
13568  ins_pipe(fdivF_reg_reg); // FIXME
13569%}
13570#else
13571instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13572  predicate(n->as_Vector()->length() == 2);
13573  match(Set dst (MulVD src1 src2));
13574  size(4*2);
13575  ins_cost(DEFAULT_COST*2); // FIXME
13576
13577  format %{ "FMULD  $dst.D.a,$src1.D.a,$src2.D.a\n\t"
13578            "FMULD  $dst.D.b,$src1.D.b,$src2.D.b" %}
13579  ins_encode %{
13580    FloatRegister dsta = $dst$$FloatRegister;
13581    FloatRegister src1a = $src1$$FloatRegister;
13582    FloatRegister src2a = $src2$$FloatRegister;
13583    __ mul_double(dsta, src1a, src2a);
13584    FloatRegister dstb = dsta->successor()->successor();
13585    FloatRegister src1b = src1a->successor()->successor();
13586    FloatRegister src2b = src2a->successor()->successor();
13587    __ mul_double(dstb, src1b, src2b);
13588  %}
13589
13590  ins_pipe(fmulD_reg_reg); // FIXME
13591%}
13592#endif
13593
13594
13595// Floats vector div
13596instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
13597  predicate(n->as_Vector()->length() == 2);
13598  match(Set dst (DivVF src1 src2));
13599#ifdef AARCH64
13600  size(4*1);
13601  ins_cost(DEFAULT_COST*1); // FIXME
13602
13603  format %{ "FDIV.2S $dst,$src1,$src2\t! float[2]" %}
13604  ins_encode %{
13605    int quad = 0;
13606    __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13607             MacroAssembler::VFA_SIZE_F32, quad);
13608  %}
13609
13610  ins_pipe(fdivF_reg_reg); // FIXME
13611#else
13612  size(4*2);
13613  ins_cost(DEFAULT_COST*2); // FIXME
13614
13615  format %{ "FDIVS  $dst.a,$src1.a,$src2.a\n\t"
13616            "FDIVS  $dst.b,$src1.b,$src2.b" %}
13617  ins_encode %{
13618    __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
13619    __ div_float($dst$$FloatRegister->successor(),
13620             $src1$$FloatRegister->successor(),
13621             $src2$$FloatRegister->successor());
13622  %}
13623
13624  ins_pipe(fdivF_reg_reg); // FIXME
13625#endif
13626%}
13627
13628instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13629  predicate(n->as_Vector()->length() == 4);
13630  match(Set dst (DivVF src1 src2));
13631#ifdef AARCH64
13632  size(4*1);
13633  ins_cost(DEFAULT_COST*1); // FIXME
13634
13635  format %{ "FDIV.4S $dst,$src1,$src2\t! float[4]" %}
13636  ins_encode %{
13637    int quad = 1;
13638    __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13639             MacroAssembler::VFA_SIZE_F32, quad);
13640  %}
13641
13642  ins_pipe(fdivF_reg_reg); // FIXME
13643#else
13644  size(4*4);
13645  ins_cost(DEFAULT_COST*4); // FIXME
13646
13647  format %{ "FDIVS  $dst.a,$src1.a,$src2.a\n\t"
13648            "FDIVS  $dst.b,$src1.b,$src2.b\n\t"
13649            "FDIVS  $dst.c,$src1.c,$src2.c\n\t"
13650            "FDIVS  $dst.d,$src1.d,$src2.d" %}
13651
13652  ins_encode %{
13653    FloatRegister dsta = $dst$$FloatRegister;
13654    FloatRegister src1a = $src1$$FloatRegister;
13655    FloatRegister src2a = $src2$$FloatRegister;
13656    __ div_float(dsta, src1a, src2a);
13657    FloatRegister dstb = dsta->successor();
13658    FloatRegister src1b = src1a->successor();
13659    FloatRegister src2b = src2a->successor();
13660    __ div_float(dstb, src1b, src2b);
13661    FloatRegister dstc = dstb->successor();
13662    FloatRegister src1c = src1b->successor();
13663    FloatRegister src2c = src2b->successor();
13664    __ div_float(dstc, src1c, src2c);
13665    FloatRegister dstd = dstc->successor();
13666    FloatRegister src1d = src1c->successor();
13667    FloatRegister src2d = src2c->successor();
13668    __ div_float(dstd, src1d, src2d);
13669  %}
13670
13671  ins_pipe(fdivF_reg_reg); // FIXME
13672#endif
13673%}
13674
13675#ifdef AARCH64
13676instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{
13677  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
13678  match(Set dst (DivVD src1 src2));
13679  size(4*1);
13680  ins_cost(DEFAULT_COST*1); // FIXME
13681
13682  format %{ "FDIV.2D $dst,$src1,$src2\t! double[2]" %}
13683  ins_encode %{
13684    int quad = 1;
13685    __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
13686             MacroAssembler::VFA_SIZE_F64, quad);
13687  %}
13688
13689  ins_pipe(fdivF_reg_reg); // FIXME
13690%}
13691#else
13692instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
13693  predicate(n->as_Vector()->length() == 2);
13694  match(Set dst (DivVD src1 src2));
13695  size(4*2);
13696  ins_cost(DEFAULT_COST*2); // FIXME
13697
13698  format %{ "FDIVD  $dst.D.a,$src1.D.a,$src2.D.a\n\t"
13699            "FDIVD  $dst.D.b,$src1.D.b,$src2.D.b" %}
13700  ins_encode %{
13701    FloatRegister dsta = $dst$$FloatRegister;
13702    FloatRegister src1a = $src1$$FloatRegister;
13703    FloatRegister src2a = $src2$$FloatRegister;
13704    __ div_double(dsta, src1a, src2a);
13705    FloatRegister dstb = dsta->successor()->successor();
13706    FloatRegister src1b = src1a->successor()->successor();
13707    FloatRegister src2b = src2a->successor()->successor();
13708    __ div_double(dstb, src1b, src2b);
13709  %}
13710
13711  ins_pipe(fdivD_reg_reg); // FIXME
13712%}
13713#endif
13714
13715// --------------------------------- NEG --------------------------------------
13716
13717instruct vneg8B_reg(vecD dst, vecD src) %{
13718  predicate(n->as_Vector()->length_in_bytes() == 8);
13719  effect(DEF dst, USE src);
13720  size(4);
13721  ins_cost(DEFAULT_COST); // FIXME
13722  format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %}
13723  ins_encode %{
13724    bool quad = false;
13725    __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
13726              MacroAssembler::VELEM_SIZE_8, quad);
13727  %}
13728  ins_pipe( ialu_reg_reg ); // FIXME
13729%}
13730
13731instruct vneg16B_reg(vecX dst, vecX src) %{
13732  predicate(n->as_Vector()->length_in_bytes() == 16);
13733  effect(DEF dst, USE src);
13734  size(4);
13735  ins_cost(DEFAULT_COST); // FIXME
13736  format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %}
13737  ins_encode %{
13738    bool _float = false;
13739    bool quad = true;
13740    __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
13741              MacroAssembler::VELEM_SIZE_8, quad);
13742  %}
13743  ins_pipe( ialu_reg_reg ); // FIXME
13744%}
13745
13746// ------------------------------ Shift ---------------------------------------
13747
13748instruct vslcntD(vecD dst, iRegI cnt) %{
13749  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
13750  match(Set dst (LShiftCntV cnt));
13751  size(4);
13752  ins_cost(DEFAULT_COST); // FIXME
13753  expand %{
13754    Repl8B_reg_simd(dst, cnt);
13755  %}
13756%}
13757
13758instruct vslcntX(vecX dst, iRegI cnt) %{
13759  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
13760  match(Set dst (LShiftCntV cnt));
13761  size(4);
13762  ins_cost(DEFAULT_COST); // FIXME
13763  expand %{
13764    Repl16B_reg(dst, cnt);
13765  %}
13766%}
13767
13768// Low bits of vector "shift" elements are used, so it
13769// doesn't matter if we treat it as ints or bytes here.
13770instruct vsrcntD(vecD dst, iRegI cnt) %{
13771  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
13772  match(Set dst (RShiftCntV cnt));
13773  size(4*2);
13774  ins_cost(DEFAULT_COST*2); // FIXME
13775
13776  format %{ "VDUP.8 $dst.D,$cnt\n\t"
13777            "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %}
13778  ins_encode %{
13779    bool quad = false;
13780    __ vdupI($dst$$FloatRegister, $cnt$$Register,
13781             MacroAssembler::VELEM_SIZE_8, quad);
13782    __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
13783              MacroAssembler::VELEM_SIZE_8, quad);
13784  %}
13785  ins_pipe( ialu_reg_reg ); // FIXME
13786%}
13787
13788instruct vsrcntX(vecX dst, iRegI cnt) %{
13789  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
13790  match(Set dst (RShiftCntV cnt));
13791  size(4*2);
13792  ins_cost(DEFAULT_COST*2); // FIXME
13793  format %{ "VDUP.8 $dst.Q,$cnt\n\t"
13794            "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %}
13795  ins_encode %{
13796    bool quad = true;
13797    __ vdupI($dst$$FloatRegister, $cnt$$Register,
13798             MacroAssembler::VELEM_SIZE_8, quad);
13799    __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
13800              MacroAssembler::VELEM_SIZE_8, quad);
13801  %}
13802  ins_pipe( ialu_reg_reg ); // FIXME
13803%}
13804
13805// Byte vector logical left/right shift based on sign
13806instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{
13807  predicate(n->as_Vector()->length() == 8);
13808  effect(DEF dst, USE src, USE shift);
13809  size(4);
13810  ins_cost(DEFAULT_COST); // FIXME
13811  format %{
13812    "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B"
13813  %}
13814  ins_encode %{
13815    bool quad = false;
13816    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13817              MacroAssembler::VELEM_SIZE_8, quad);
13818  %}
13819  ins_pipe( ialu_reg_reg ); // FIXME
13820%}
13821
13822instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{
13823  predicate(n->as_Vector()->length() == 16);
13824  effect(DEF dst, USE src, USE shift);
13825  size(4);
13826  ins_cost(DEFAULT_COST); // FIXME
13827  format %{
13828    "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B"
13829  %}
13830  ins_encode %{
13831    bool quad = true;
13832    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13833              MacroAssembler::VELEM_SIZE_8, quad);
13834  %}
13835  ins_pipe( ialu_reg_reg ); // FIXME
13836%}
13837
13838// Shorts/Char vector logical left/right shift based on sign
13839instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{
13840  predicate(n->as_Vector()->length() == 4);
13841  effect(DEF dst, USE src, USE shift);
13842  size(4);
13843  ins_cost(DEFAULT_COST); // FIXME
13844  format %{
13845    "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S"
13846  %}
13847  ins_encode %{
13848    bool quad = false;
13849    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13850              MacroAssembler::VELEM_SIZE_16, quad);
13851  %}
13852  ins_pipe( ialu_reg_reg ); // FIXME
13853%}
13854
13855instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{
13856  predicate(n->as_Vector()->length() == 8);
13857  effect(DEF dst, USE src, USE shift);
13858  size(4);
13859  ins_cost(DEFAULT_COST); // FIXME
13860  format %{
13861    "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S"
13862  %}
13863  ins_encode %{
13864    bool quad = true;
13865    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13866              MacroAssembler::VELEM_SIZE_16, quad);
13867  %}
13868  ins_pipe( ialu_reg_reg ); // FIXME
13869%}
13870
13871// Integers vector logical left/right shift based on sign
13872instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{
13873  predicate(n->as_Vector()->length() == 2);
13874  effect(DEF dst, USE src, USE shift);
13875  size(4);
13876  ins_cost(DEFAULT_COST); // FIXME
13877  format %{
13878    "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I"
13879  %}
13880  ins_encode %{
13881    bool quad = false;
13882    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13883              MacroAssembler::VELEM_SIZE_32, quad);
13884  %}
13885  ins_pipe( ialu_reg_reg ); // FIXME
13886%}
13887
13888instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{
13889  predicate(n->as_Vector()->length() == 4);
13890  effect(DEF dst, USE src, USE shift);
13891  size(4);
13892  ins_cost(DEFAULT_COST); // FIXME
13893  format %{
13894    "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I"
13895  %}
13896  ins_encode %{
13897    bool quad = true;
13898    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13899              MacroAssembler::VELEM_SIZE_32, quad);
13900  %}
13901  ins_pipe( ialu_reg_reg ); // FIXME
13902%}
13903
13904// Longs vector logical left/right shift based on sign
13905instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{
13906  predicate(n->as_Vector()->length() == 2);
13907  effect(DEF dst, USE src, USE shift);
13908  size(4);
13909  ins_cost(DEFAULT_COST); // FIXME
13910  format %{
13911    "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L"
13912  %}
13913  ins_encode %{
13914    bool quad = true;
13915    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
13916              MacroAssembler::VELEM_SIZE_64, quad);
13917  %}
13918  ins_pipe( ialu_reg_reg ); // FIXME
13919%}
13920
13921// ------------------------------ LeftShift -----------------------------------
13922
13923// Byte vector left shift
13924instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{
13925  predicate(n->as_Vector()->length() == 8);
13926  match(Set dst (LShiftVB src shift));
13927  size(4*1);
13928  ins_cost(DEFAULT_COST*1); // FIXME
13929  expand %{
13930    vsh8B_reg(dst, src, shift);
13931  %}
13932%}
13933
13934instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{
13935  predicate(n->as_Vector()->length() == 16);
13936  match(Set dst (LShiftVB src shift));
13937  size(4*1);
13938  ins_cost(DEFAULT_COST*1); // FIXME
13939  expand %{
13940    vsh16B_reg(dst, src, shift);
13941  %}
13942%}
13943
13944instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{
13945  predicate(n->as_Vector()->length() == 8);
13946  match(Set dst (LShiftVB src shift));
13947  size(4);
13948  ins_cost(DEFAULT_COST); // FIXME
13949  format %{
13950    "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B"
13951  %}
13952  ins_encode %{
13953    bool quad = false;
13954    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
13955             quad);
13956  %}
13957  ins_pipe( ialu_reg_reg ); // FIXME
13958%}
13959
13960instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{
13961  predicate(n->as_Vector()->length() == 16);
13962  match(Set dst (LShiftVB src shift));
13963  size(4);
13964  ins_cost(DEFAULT_COST); // FIXME
13965  format %{
13966    "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B"
13967  %}
13968  ins_encode %{
13969    bool quad = true;
13970    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
13971             quad);
13972  %}
13973  ins_pipe( ialu_reg_reg ); // FIXME
13974%}
13975
13976// Shorts/Chars vector logical left/right shift
13977instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{
13978  predicate(n->as_Vector()->length() == 4);
13979  match(Set dst (LShiftVS src shift));
13980  match(Set dst (URShiftVS src shift));
13981  size(4*1);
13982  ins_cost(DEFAULT_COST*1); // FIXME
13983  expand %{
13984    vsh4S_reg(dst, src, shift);
13985  %}
13986%}
13987
13988instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{
13989  predicate(n->as_Vector()->length() == 8);
13990  match(Set dst (LShiftVS src shift));
13991  match(Set dst (URShiftVS src shift));
13992  size(4*1);
13993  ins_cost(DEFAULT_COST*1); // FIXME
13994  expand %{
13995    vsh8S_reg(dst, src, shift);
13996  %}
13997%}
13998
13999instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{
14000  predicate(n->as_Vector()->length() == 4);
14001  match(Set dst (LShiftVS src shift));
14002  size(4);
14003  ins_cost(DEFAULT_COST); // FIXME
14004  format %{
14005    "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S"
14006  %}
14007  ins_encode %{
14008    bool quad = false;
14009    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
14010             quad);
14011  %}
14012  ins_pipe( ialu_reg_reg ); // FIXME
14013%}
14014
14015instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{
14016  predicate(n->as_Vector()->length() == 8);
14017  match(Set dst (LShiftVS src shift));
14018  size(4);
14019  ins_cost(DEFAULT_COST); // FIXME
14020  format %{
14021    "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S"
14022  %}
14023  ins_encode %{
14024    bool quad = true;
14025    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
14026             quad);
14027  %}
14028  ins_pipe( ialu_reg_reg ); // FIXME
14029%}
14030
14031// Integers vector logical left/right shift
14032instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{
14033  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
14034  match(Set dst (LShiftVI src shift));
14035  match(Set dst (URShiftVI src shift));
14036  size(4*1);
14037  ins_cost(DEFAULT_COST*1); // FIXME
14038  expand %{
14039    vsh2I_reg(dst, src, shift);
14040  %}
14041%}
14042
14043instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{
14044  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
14045  match(Set dst (LShiftVI src shift));
14046  match(Set dst (URShiftVI src shift));
14047  size(4*1);
14048  ins_cost(DEFAULT_COST*1); // FIXME
14049  expand %{
14050    vsh4I_reg(dst, src, shift);
14051  %}
14052%}
14053
14054instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{
14055  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
14056  match(Set dst (LShiftVI src shift));
14057  size(4);
14058  ins_cost(DEFAULT_COST); // FIXME
14059  format %{
14060    "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I"
14061  %}
14062  ins_encode %{
14063    bool quad = false;
14064    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
14065             quad);
14066  %}
14067  ins_pipe( ialu_reg_reg ); // FIXME
14068%}
14069
14070instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{
14071  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
14072  match(Set dst (LShiftVI src shift));
14073  size(4);
14074  ins_cost(DEFAULT_COST); // FIXME
14075  format %{
14076    "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I"
14077  %}
14078  ins_encode %{
14079    bool quad = true;
14080    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
14081             quad);
14082  %}
14083  ins_pipe( ialu_reg_reg ); // FIXME
14084%}
14085
14086// Longs vector logical left/right shift
14087instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{
14088  predicate(n->as_Vector()->length() == 2);
14089  match(Set dst (LShiftVL src shift));
14090  match(Set dst (URShiftVL src shift));
14091  size(4*1);
14092  ins_cost(DEFAULT_COST*1); // FIXME
14093  expand %{
14094    vsh2L_reg(dst, src, shift);
14095  %}
14096%}
14097
14098instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{
14099  predicate(n->as_Vector()->length() == 2);
14100  match(Set dst (LShiftVL src shift));
14101  size(4);
14102  ins_cost(DEFAULT_COST); // FIXME
14103  format %{
14104    "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L"
14105  %}
14106  ins_encode %{
14107    bool quad = true;
14108    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
14109             quad);
14110  %}
14111  ins_pipe( ialu_reg_reg ); // FIXME
14112%}
14113
14114// ----------------------- LogicalRightShift -----------------------------------
14115
14116// Bytes/Shorts vector logical right shift produces incorrect Java result
14117// for negative data because java code convert short value into int with
14118// sign extension before a shift.
14119
14120// Chars vector logical right shift
14121instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{
14122  predicate(n->as_Vector()->length() == 4);
14123  match(Set dst (URShiftVS src shift));
14124  size(4);
14125  ins_cost(DEFAULT_COST); // FIXME
14126  format %{
14127    "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
14128  %}
14129  ins_encode %{
14130    bool quad = false;
14131    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
14132             quad);
14133  %}
14134  ins_pipe( ialu_reg_reg ); // FIXME
14135%}
14136
14137instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{
14138  predicate(n->as_Vector()->length() == 8);
14139  match(Set dst (URShiftVS src shift));
14140  size(4);
14141  ins_cost(DEFAULT_COST); // FIXME
14142  format %{
14143    "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
14144  %}
14145  ins_encode %{
14146    bool quad = true;
14147    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
14148             quad);
14149  %}
14150  ins_pipe( ialu_reg_reg ); // FIXME
14151%}
14152
14153// Integers vector logical right shift
14154instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{
14155  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
14156  match(Set dst (URShiftVI src shift));
14157  size(4);
14158  ins_cost(DEFAULT_COST); // FIXME
14159  format %{
14160    "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
14161  %}
14162  ins_encode %{
14163    bool quad = false;
14164    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
14165             quad);
14166  %}
14167  ins_pipe( ialu_reg_reg ); // FIXME
14168%}
14169
14170instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{
14171  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
14172  match(Set dst (URShiftVI src shift));
14173  size(4);
14174  ins_cost(DEFAULT_COST); // FIXME
14175  format %{
14176    "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
14177  %}
14178  ins_encode %{
14179    bool quad = true;
14180    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
14181             quad);
14182  %}
14183  ins_pipe( ialu_reg_reg ); // FIXME
14184%}
14185
14186// Longs vector logical right shift
14187instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{
14188  predicate(n->as_Vector()->length() == 2);
14189  match(Set dst (URShiftVL src shift));
14190  size(4);
14191  ins_cost(DEFAULT_COST); // FIXME
14192  format %{
14193    "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
14194  %}
14195  ins_encode %{
14196    bool quad = true;
14197    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
14198             quad);
14199  %}
14200  ins_pipe( ialu_reg_reg ); // FIXME
14201%}
14202
14203// ------------------- ArithmeticRightShift -----------------------------------
14204
14205// Bytes vector arithmetic left/right shift based on sign
14206instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{
14207  predicate(n->as_Vector()->length() == 8);
14208  effect(DEF dst, USE src, USE shift);
14209  size(4);
14210  ins_cost(DEFAULT_COST); // FIXME
14211  format %{
14212    "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B"
14213  %}
14214  ins_encode %{
14215    bool quad = false;
14216    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14217              MacroAssembler::VELEM_SIZE_8, quad);
14218  %}
14219  ins_pipe( ialu_reg_reg ); // FIXME
14220%}
14221
14222instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{
14223  predicate(n->as_Vector()->length() == 16);
14224  effect(DEF dst, USE src, USE shift);
14225  size(4);
14226  ins_cost(DEFAULT_COST); // FIXME
14227  format %{
14228    "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B"
14229  %}
14230  ins_encode %{
14231    bool quad = true;
14232    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14233              MacroAssembler::VELEM_SIZE_8, quad);
14234  %}
14235  ins_pipe( ialu_reg_reg ); // FIXME
14236%}
14237
14238// Shorts vector arithmetic left/right shift based on sign
14239instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{
14240  predicate(n->as_Vector()->length() == 4);
14241  effect(DEF dst, USE src, USE shift);
14242  size(4);
14243  ins_cost(DEFAULT_COST); // FIXME
14244  format %{
14245    "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S"
14246  %}
14247  ins_encode %{
14248    bool quad = false;
14249    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14250              MacroAssembler::VELEM_SIZE_16, quad);
14251  %}
14252  ins_pipe( ialu_reg_reg ); // FIXME
14253%}
14254
14255instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{
14256  predicate(n->as_Vector()->length() == 8);
14257  effect(DEF dst, USE src, USE shift);
14258  size(4);
14259  ins_cost(DEFAULT_COST); // FIXME
14260  format %{
14261    "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S"
14262  %}
14263  ins_encode %{
14264    bool quad = true;
14265    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14266              MacroAssembler::VELEM_SIZE_16, quad);
14267  %}
14268  ins_pipe( ialu_reg_reg ); // FIXME
14269%}
14270
14271// Integers vector arithmetic left/right shift based on sign
14272instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{
14273  predicate(n->as_Vector()->length() == 2);
14274  effect(DEF dst, USE src, USE shift);
14275  size(4);
14276  ins_cost(DEFAULT_COST); // FIXME
14277  format %{
14278    "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I"
14279  %}
14280  ins_encode %{
14281    bool quad = false;
14282    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14283              MacroAssembler::VELEM_SIZE_32, quad);
14284  %}
14285  ins_pipe( ialu_reg_reg ); // FIXME
14286%}
14287
14288instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{
14289  predicate(n->as_Vector()->length() == 4);
14290  effect(DEF dst, USE src, USE shift);
14291  size(4);
14292  ins_cost(DEFAULT_COST); // FIXME
14293  format %{
14294    "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I"
14295  %}
14296  ins_encode %{
14297    bool quad = true;
14298    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14299              MacroAssembler::VELEM_SIZE_32, quad);
14300  %}
14301  ins_pipe( ialu_reg_reg ); // FIXME
14302%}
14303
14304// Longs vector arithmetic left/right shift based on sign
14305instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{
14306  predicate(n->as_Vector()->length() == 2);
14307  effect(DEF dst, USE src, USE shift);
14308  size(4);
14309  ins_cost(DEFAULT_COST); // FIXME
14310  format %{
14311    "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L"
14312  %}
14313  ins_encode %{
14314    bool quad = true;
14315    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
14316              MacroAssembler::VELEM_SIZE_64, quad);
14317  %}
14318  ins_pipe( ialu_reg_reg ); // FIXME
14319%}
14320
14321// Byte vector arithmetic right shift
14322
14323instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{
14324  predicate(n->as_Vector()->length() == 8);
14325  match(Set dst (RShiftVB src shift));
14326  size(4);
14327  ins_cost(DEFAULT_COST); // FIXME
14328  expand %{
14329    vsha8B_reg(dst, src, shift);
14330  %}
14331%}
14332
14333instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{
14334  predicate(n->as_Vector()->length() == 16);
14335  match(Set dst (RShiftVB src shift));
14336  size(4);
14337  ins_cost(DEFAULT_COST); // FIXME
14338  expand %{
14339    vsha16B_reg(dst, src, shift);
14340  %}
14341%}
14342
14343instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{
14344  predicate(n->as_Vector()->length() == 8);
14345  match(Set dst (RShiftVB src shift));
14346  size(4);
14347  ins_cost(DEFAULT_COST); // FIXME
14348  format %{
14349    "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B"
14350  %}
14351  ins_encode %{
14352    bool quad = false;
14353    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
14354             quad);
14355  %}
14356  ins_pipe( ialu_reg_reg ); // FIXME
14357%}
14358
14359instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{
14360  predicate(n->as_Vector()->length() == 16);
14361  match(Set dst (RShiftVB src shift));
14362  size(4);
14363  ins_cost(DEFAULT_COST); // FIXME
14364  format %{
14365    "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B"
14366  %}
14367  ins_encode %{
14368    bool quad = true;
14369    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
14370             quad);
14371  %}
14372  ins_pipe( ialu_reg_reg ); // FIXME
14373%}
14374
14375// Shorts vector arithmetic right shift
14376instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{
14377  predicate(n->as_Vector()->length() == 4);
14378  match(Set dst (RShiftVS src shift));
14379  size(4);
14380  ins_cost(DEFAULT_COST); // FIXME
14381  expand %{
14382    vsha4S_reg(dst, src, shift);
14383  %}
14384%}
14385
14386instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{
14387  predicate(n->as_Vector()->length() == 8);
14388  match(Set dst (RShiftVS src shift));
14389  size(4);
14390  ins_cost(DEFAULT_COST); // FIXME
14391  expand %{
14392    vsha8S_reg(dst, src, shift);
14393  %}
14394%}
14395
14396instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{
14397  predicate(n->as_Vector()->length() == 4);
14398  match(Set dst (RShiftVS src shift));
14399  size(4);
14400  ins_cost(DEFAULT_COST); // FIXME
14401  format %{
14402    "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
14403  %}
14404  ins_encode %{
14405    bool quad = false;
14406    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
14407             quad);
14408  %}
14409  ins_pipe( ialu_reg_reg ); // FIXME
14410%}
14411
14412instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{
14413  predicate(n->as_Vector()->length() == 8);
14414  match(Set dst (RShiftVS src shift));
14415  size(4);
14416  ins_cost(DEFAULT_COST); // FIXME
14417  format %{
14418    "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
14419  %}
14420  ins_encode %{
14421    bool quad = true;
14422    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
14423             quad);
14424  %}
14425  ins_pipe( ialu_reg_reg ); // FIXME
14426%}
14427
14428// Integers vector arithmetic right shift
14429instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{
14430  predicate(n->as_Vector()->length() == 2);
14431  match(Set dst (RShiftVI src shift));
14432  size(4);
14433  ins_cost(DEFAULT_COST); // FIXME
14434  expand %{
14435    vsha2I_reg(dst, src, shift);
14436  %}
14437%}
14438
14439instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{
14440  predicate(n->as_Vector()->length() == 4);
14441  match(Set dst (RShiftVI src shift));
14442  size(4);
14443  ins_cost(DEFAULT_COST); // FIXME
14444  expand %{
14445    vsha4I_reg(dst, src, shift);
14446  %}
14447%}
14448
14449instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{
14450  predicate(n->as_Vector()->length() == 2);
14451  match(Set dst (RShiftVI src shift));
14452  size(4);
14453  ins_cost(DEFAULT_COST); // FIXME
14454  format %{
14455    "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
14456  %}
14457  ins_encode %{
14458    bool quad = false;
14459    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
14460             quad);
14461  %}
14462  ins_pipe( ialu_reg_reg ); // FIXME
14463%}
14464
14465instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{
14466  predicate(n->as_Vector()->length() == 4);
14467  match(Set dst (RShiftVI src shift));
14468  size(4);
14469  ins_cost(DEFAULT_COST); // FIXME
14470  format %{
14471    "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
14472  %}
14473  ins_encode %{
14474    bool quad = true;
14475    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
14476             quad);
14477  %}
14478  ins_pipe( ialu_reg_reg ); // FIXME
14479%}
14480
14481// Longs vector arithmetic right shift
14482instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{
14483  predicate(n->as_Vector()->length() == 2);
14484  match(Set dst (RShiftVL src shift));
14485  size(4);
14486  ins_cost(DEFAULT_COST); // FIXME
14487  expand %{
14488    vsha2L_reg(dst, src, shift);
14489  %}
14490%}
14491
14492instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{
14493  predicate(n->as_Vector()->length() == 2);
14494  match(Set dst (RShiftVL src shift));
14495  size(4);
14496  ins_cost(DEFAULT_COST); // FIXME
14497  format %{
14498    "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
14499  %}
14500  ins_encode %{
14501    bool quad = true;
14502    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
14503             quad);
14504  %}
14505  ins_pipe( ialu_reg_reg ); // FIXME
14506%}
14507
14508// --------------------------------- AND --------------------------------------
14509
14510instruct vandD(vecD dst, vecD src1, vecD src2) %{
14511  predicate(n->as_Vector()->length_in_bytes() == 8);
14512  match(Set dst (AndV src1 src2));
14513  format %{ "VAND    $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
14514  ins_encode %{
14515    bool quad = false;
14516    __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
14517             quad);
14518  %}
14519  ins_pipe( ialu_reg_reg ); // FIXME
14520%}
14521
14522instruct vandX(vecX dst, vecX src1, vecX src2) %{
14523  predicate(n->as_Vector()->length_in_bytes() == 16);
14524  match(Set dst (AndV src1 src2));
14525  format %{ "VAND    $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
14526  ins_encode %{
14527    bool quad = true;
14528    __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
14529             quad);
14530  %}
14531  ins_pipe( ialu_reg_reg ); // FIXME
14532%}
14533
14534// --------------------------------- OR ---------------------------------------
14535
14536instruct vorD(vecD dst, vecD src1, vecD src2) %{
14537  predicate(n->as_Vector()->length_in_bytes() == 8);
14538  match(Set dst (OrV src1 src2));
14539  format %{ "VOR     $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
14540  ins_encode %{
14541    bool quad = false;
14542    __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
14543            quad);
14544  %}
14545  ins_pipe( ialu_reg_reg ); // FIXME
14546%}
14547
14548instruct vorX(vecX dst, vecX src1, vecX src2) %{
14549  predicate(n->as_Vector()->length_in_bytes() == 16);
14550  match(Set dst (OrV src1 src2));
14551  format %{ "VOR     $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
14552  ins_encode %{
14553    bool quad = true;
14554    __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
14555            quad);
14556  %}
14557  ins_pipe( ialu_reg_reg ); // FIXME
14558%}
14559
14560// --------------------------------- XOR --------------------------------------
14561
14562instruct vxorD(vecD dst, vecD src1, vecD src2) %{
14563  predicate(n->as_Vector()->length_in_bytes() == 8);
14564  match(Set dst (XorV src1 src2));
14565  format %{ "VXOR    $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
14566  ins_encode %{
14567    bool quad = false;
14568    __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
14569             quad);
14570  %}
14571  ins_pipe( ialu_reg_reg ); // FIXME
14572%}
14573
14574instruct vxorX(vecX dst, vecX src1, vecX src2) %{
14575  predicate(n->as_Vector()->length_in_bytes() == 16);
14576  match(Set dst (XorV src1 src2));
14577  format %{ "VXOR    $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
14578  ins_encode %{
14579    bool quad = true;
14580    __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
14581             quad);
14582  %}
14583  ins_pipe( ialu_reg_reg ); // FIXME
14584%}
14585
14586
14587//----------PEEPHOLE RULES-----------------------------------------------------
14588// These must follow all instruction definitions as they use the names
14589// defined in the instructions definitions.
14590//
14591// peepmatch ( root_instr_name [preceding_instruction]* );
14592//
14593// peepconstraint %{
14594// (instruction_number.operand_name relational_op instruction_number.operand_name
14595//  [, ...] );
14596// // instruction numbers are zero-based using left to right order in peepmatch
14597//
14598// peepreplace ( instr_name  ( [instruction_number.operand_name]* ) );
14599// // provide an instruction_number.operand_name for each operand that appears
14600// // in the replacement instruction's match rule
14601//
14602// ---------VM FLAGS---------------------------------------------------------
14603//
14604// All peephole optimizations can be turned off using -XX:-OptoPeephole
14605//
14606// Each peephole rule is given an identifying number starting with zero and
14607// increasing by one in the order seen by the parser.  An individual peephole
14608// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
14609// on the command-line.
14610//
14611// ---------CURRENT LIMITATIONS----------------------------------------------
14612//
14613// Only match adjacent instructions in same basic block
14614// Only equality constraints
14615// Only constraints between operands, not (0.dest_reg == EAX_enc)
14616// Only one replacement instruction
14617//
14618// ---------EXAMPLE----------------------------------------------------------
14619//
14620// // pertinent parts of existing instructions in architecture description
14621// instruct movI(eRegI dst, eRegI src) %{
14622//   match(Set dst (CopyI src));
14623// %}
14624//
14625// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{
14626//   match(Set dst (AddI dst src));
14627//   effect(KILL cr);
14628// %}
14629//
14630// // Change (inc mov) to lea
14631// peephole %{
14632//   // increment preceeded by register-register move
14633//   peepmatch ( incI_eReg movI );
14634//   // require that the destination register of the increment
14635//   // match the destination register of the move
14636//   peepconstraint ( 0.dst == 1.dst );
14637//   // construct a replacement instruction that sets
14638//   // the destination to ( move's source register + one )
14639//   peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) );
14640// %}
14641//
14642
14643// // Change load of spilled value to only a spill
14644// instruct storeI(memory mem, eRegI src) %{
14645//   match(Set mem (StoreI mem src));
14646// %}
14647//
14648// instruct loadI(eRegI dst, memory mem) %{
14649//   match(Set dst (LoadI mem));
14650// %}
14651//
14652// peephole %{
14653//   peepmatch ( loadI storeI );
14654//   peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
14655//   peepreplace ( storeI( 1.mem 1.mem 1.src ) );
14656// %}
14657
14658//----------SMARTSPILL RULES---------------------------------------------------
14659// These must follow all instruction definitions as they use the names
14660// defined in the instructions definitions.
14661//
14662// ARM will probably not have any of these rules due to RISC instruction set.
14663
14664//----------PIPELINE-----------------------------------------------------------
14665// Rules which define the behavior of the target architectures pipeline.
14666