1//
2// Copyright (c) 2008, 2021, 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#define ldr_32 ldr
71#define str_32 str
72#define tst_32 tst
73#define teq_32 teq
74#if 1
75extern bool PrintOptoAssembly;
76#endif
77
78class c2 {
79public:
80  static OptoRegPair return_value(int ideal_reg);
81};
82
83class CallStubImpl {
84
85  //--------------------------------------------------------------
86  //---<  Used for optimization in Compile::Shorten_branches  >---
87  //--------------------------------------------------------------
88
89 public:
90  // Size of call trampoline stub.
91  static uint size_call_trampoline() {
92    return 0; // no call trampolines on this platform
93  }
94
95  // number of relocations needed by a call trampoline stub
96  static uint reloc_call_trampoline() {
97    return 0; // no call trampolines on this platform
98  }
99};
100
101class HandlerImpl {
102
103 public:
104
105  static int emit_exception_handler(CodeBuffer &cbuf);
106  static int emit_deopt_handler(CodeBuffer& cbuf);
107
108  static uint size_exception_handler() {
109    return ( 3 * 4 );
110  }
111
112
113  static uint size_deopt_handler() {
114    return ( 9 * 4 );
115  }
116
117};
118
119class Node::PD {
120public:
121  enum NodeFlags {
122    _last_flag = Node::_last_flag
123  };
124};
125
126%}
127
128source %{
129#define __ _masm.
130
131static FloatRegister reg_to_FloatRegister_object(int register_encoding);
132static Register reg_to_register_object(int register_encoding);
133
134void PhaseOutput::pd_perform_mach_node_analysis() {
135}
136
137int MachNode::pd_alignment_required() const {
138  return 1;
139}
140
141int MachNode::compute_padding(int current_offset) const {
142  return 0;
143}
144
145// ****************************************************************************
146
147// REQUIRED FUNCTIONALITY
148
149// emit an interrupt that is caught by the debugger (for debugging compiler)
150void emit_break(CodeBuffer &cbuf) {
151  C2_MacroAssembler _masm(&cbuf);
152  __ breakpoint();
153}
154
155#ifndef PRODUCT
156void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const {
157  st->print("TA");
158}
159#endif
160
161void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
162  emit_break(cbuf);
163}
164
165uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
166  return MachNode::size(ra_);
167}
168
169
170void emit_nop(CodeBuffer &cbuf) {
171  C2_MacroAssembler _masm(&cbuf);
172  __ nop();
173}
174
175
176void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) {
177  int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset();
178  int call_site_offset = cbuf.insts()->mark_off();
179  C2_MacroAssembler _masm(&cbuf);
180  __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call
181  address target = (address)m->method();
182  assert(n->as_MachCall()->entry_point() == target, "sanity");
183  assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity");
184  assert(cache_reachable() == __ cache_fully_reachable(), "sanity");
185
186  assert(target != NULL, "need real address");
187
188  int ret_addr_offset = -1;
189  if (rspec.type() == relocInfo::runtime_call_type) {
190    __ call(target, rspec);
191    ret_addr_offset = __ offset();
192  } else {
193    // scratches Rtemp
194    ret_addr_offset = __ patchable_call(target, rspec, true);
195  }
196  assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()");
197}
198
199//=============================================================================
200// REQUIRED FUNCTIONALITY for encoding
201void emit_lo(CodeBuffer &cbuf, int val) {  }
202void emit_hi(CodeBuffer &cbuf, int val) {  }
203
204
205//=============================================================================
206const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
207
208int ConstantTable::calculate_table_base_offset() const {
209  int offset = -(size() / 2);
210  // flds, fldd: 8-bit  offset multiplied by 4: +/- 1024
211  // ldr, ldrb : 12-bit offset:                 +/- 4096
212  if (!Assembler::is_simm10(offset)) {
213    offset = Assembler::min_simm10;
214  }
215  return offset;
216}
217
218bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
219void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
220  ShouldNotReachHere();
221}
222
223void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
224  Compile* C = ra_->C;
225  ConstantTable& constant_table = C->output()->constant_table();
226  C2_MacroAssembler _masm(&cbuf);
227
228  Register r = as_Register(ra_->get_encode(this));
229  CodeSection* consts_section = __ code()->consts();
230  int consts_size = consts_section->align_at_start(consts_section->size());
231  assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size);
232
233  // Materialize the constant table base.
234  address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
235  RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
236  __ mov_address(r, baseaddr, rspec);
237}
238
239uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
240  return 8;
241}
242
243#ifndef PRODUCT
244void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
245  char reg[128];
246  ra_->dump_register(this, reg);
247  st->print("MOV_SLOW    &constanttable,%s\t! constant table base", reg);
248}
249#endif
250
251#ifndef PRODUCT
252void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
253  Compile* C = ra_->C;
254
255  for (int i = 0; i < OptoPrologueNops; i++) {
256    st->print_cr("NOP"); st->print("\t");
257  }
258
259  size_t framesize = C->output()->frame_size_in_bytes();
260  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
261  int bangsize = C->output()->bang_size_in_bytes();
262  // Remove two words for return addr and rbp,
263  framesize -= 2*wordSize;
264  bangsize -= 2*wordSize;
265
266  // Calls to C2R adapters often do not accept exceptional returns.
267  // We require that their callers must bang for them.  But be careful, because
268  // some VM calls (such as call site linkage) can use several kilobytes of
269  // stack.  But the stack safety zone should account for that.
270  // See bugs 4446381, 4468289, 4497237.
271  if (C->output()->need_stack_bang(bangsize)) {
272    st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
273  }
274  st->print_cr("PUSH   R_FP|R_LR_LR"); st->print("\t");
275  if (framesize != 0) {
276    st->print   ("SUB    R_SP, R_SP, " SIZE_FORMAT,framesize);
277  }
278}
279#endif
280
281void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
282  Compile* C = ra_->C;
283  C2_MacroAssembler _masm(&cbuf);
284
285  for (int i = 0; i < OptoPrologueNops; i++) {
286    __ nop();
287  }
288
289  size_t framesize = C->output()->frame_size_in_bytes();
290  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
291  int bangsize = C->output()->bang_size_in_bytes();
292  // Remove two words for return addr and fp,
293  framesize -= 2*wordSize;
294  bangsize -= 2*wordSize;
295
296  // Calls to C2R adapters often do not accept exceptional returns.
297  // We require that their callers must bang for them.  But be careful, because
298  // some VM calls (such as call site linkage) can use several kilobytes of
299  // stack.  But the stack safety zone should account for that.
300  // See bugs 4446381, 4468289, 4497237.
301  if (C->output()->need_stack_bang(bangsize)) {
302    __ arm_stack_overflow_check(bangsize, Rtemp);
303  }
304
305  __ raw_push(FP, LR);
306  if (framesize != 0) {
307    __ sub_slow(SP, SP, framesize);
308  }
309
310  // offset from scratch buffer is not valid
311  if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) {
312    C->output()->set_frame_complete( __ offset() );
313  }
314
315  if (C->has_mach_constant_base_node()) {
316    // NOTE: We set the table base offset here because users might be
317    // emitted before MachConstantBaseNode.
318    ConstantTable& constant_table = C->output()->constant_table();
319    constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
320  }
321}
322
323uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
324  return MachNode::size(ra_);
325}
326
327int MachPrologNode::reloc() const {
328  return 10; // a large enough number
329}
330
331//=============================================================================
332#ifndef PRODUCT
333void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
334  Compile* C = ra_->C;
335
336  size_t framesize = C->output()->frame_size_in_bytes();
337  framesize -= 2*wordSize;
338
339  if (framesize != 0) {
340    st->print("ADD    R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize);
341  }
342  st->print("POP    R_FP|R_LR_LR");
343
344  if (do_polling() && ra_->C->is_method_compilation()) {
345    st->print("\n\t");
346    st->print("MOV    Rtemp, #PollAddr\t! Load Polling address\n\t");
347    st->print("LDR    Rtemp,[Rtemp]\t!Poll for Safepointing");
348  }
349}
350#endif
351
352void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
353  C2_MacroAssembler _masm(&cbuf);
354  Compile* C = ra_->C;
355
356  size_t framesize = C->output()->frame_size_in_bytes();
357  framesize -= 2*wordSize;
358  if (framesize != 0) {
359    __ add_slow(SP, SP, framesize);
360  }
361  __ raw_pop(FP, LR);
362
363  // If this does safepoint polling, then do it here
364  if (do_polling() && ra_->C->is_method_compilation()) {
365    __ read_polling_page(Rtemp, relocInfo::poll_return_type);
366  }
367}
368
369uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
370  return MachNode::size(ra_);
371}
372
373int MachEpilogNode::reloc() const {
374  return 16; // a large enough number
375}
376
377const Pipeline * MachEpilogNode::pipeline() const {
378  return MachNode::pipeline_class();
379}
380
381//=============================================================================
382
383// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
384enum RC { rc_bad, rc_int, rc_float, rc_stack };
385static enum RC rc_class( OptoReg::Name reg ) {
386  if (!OptoReg::is_valid(reg)) return rc_bad;
387  if (OptoReg::is_stack(reg)) return rc_stack;
388  VMReg r = OptoReg::as_VMReg(reg);
389  if (r->is_Register()) return rc_int;
390  assert(r->is_FloatRegister(), "must be");
391  return rc_float;
392}
393
394static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) {
395  int rlo = Matcher::_regEncode[src_first];
396  int rhi = Matcher::_regEncode[src_second];
397  if (!((rlo&1)==0 && (rlo+1 == rhi))) {
398    tty->print_cr("CAUGHT BAD LDRD/STRD");
399  }
400  return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset);
401}
402
403uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
404                                        PhaseRegAlloc *ra_,
405                                        bool do_size,
406                                        outputStream* st ) const {
407  // Get registers to move
408  OptoReg::Name src_second = ra_->get_reg_second(in(1));
409  OptoReg::Name src_first = ra_->get_reg_first(in(1));
410  OptoReg::Name dst_second = ra_->get_reg_second(this );
411  OptoReg::Name dst_first = ra_->get_reg_first(this );
412
413  enum RC src_second_rc = rc_class(src_second);
414  enum RC src_first_rc = rc_class(src_first);
415  enum RC dst_second_rc = rc_class(dst_second);
416  enum RC dst_first_rc = rc_class(dst_first);
417
418  assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
419
420  // Generate spill code!
421  int size = 0;
422
423  if (src_first == dst_first && src_second == dst_second)
424    return size;            // Self copy, no move
425
426#ifdef TODO
427  if (bottom_type()->isa_vect() != NULL) {
428  }
429#endif
430
431  // Shared code does not expect instruction set capability based bailouts here.
432  // Handle offset unreachable bailout with minimal change in shared code.
433  // Bailout only for real instruction emit.
434  // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
435
436  C2_MacroAssembler _masm(cbuf);
437
438  // --------------------------------------
439  // Check for mem-mem move.  Load into unused float registers and fall into
440  // the float-store case.
441  if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
442    int offset = ra_->reg2offset(src_first);
443    if (cbuf && !is_memoryfp(offset)) {
444      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
445      return 0;
446    } else {
447      if (src_second_rc != rc_bad) {
448        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
449        src_first     = OptoReg::Name(R_mem_copy_lo_num);
450        src_second    = OptoReg::Name(R_mem_copy_hi_num);
451        src_first_rc  = rc_float;
452        src_second_rc = rc_float;
453        if (cbuf) {
454          __ ldr_double(Rmemcopy, Address(SP, offset));
455        } else if (!do_size) {
456          st->print(LDR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
457        }
458      } else {
459        src_first     = OptoReg::Name(R_mem_copy_lo_num);
460        src_first_rc  = rc_float;
461        if (cbuf) {
462          __ ldr_float(Rmemcopy, Address(SP, offset));
463        } else if (!do_size) {
464          st->print(LDR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
465        }
466      }
467      size += 4;
468    }
469  }
470
471  if (src_second_rc == rc_stack && dst_second_rc == rc_stack) {
472    Unimplemented();
473  }
474
475  // --------------------------------------
476  // Check for integer reg-reg copy
477  if (src_first_rc == rc_int && dst_first_rc == rc_int) {
478    // Else normal reg-reg copy
479    assert( src_second != dst_first, "smashed second before evacuating it" );
480    if (cbuf) {
481      __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
482#ifndef PRODUCT
483    } else if (!do_size) {
484      st->print("MOV    R_%s, R_%s\t# spill",
485                Matcher::regName[dst_first],
486                Matcher::regName[src_first]);
487#endif
488    }
489    size += 4;
490  }
491
492  // Check for integer store
493  if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
494    int offset = ra_->reg2offset(dst_first);
495    if (cbuf && !is_memoryI(offset)) {
496      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
497      return 0;
498    } else {
499      if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) {
500        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
501        if (cbuf) {
502          __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
503#ifndef PRODUCT
504        } else if (!do_size) {
505          if (size != 0) st->print("\n\t");
506          st->print(STR_64 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
507#endif
508        }
509        return size + 4;
510      } else {
511        if (cbuf) {
512          __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
513#ifndef PRODUCT
514        } else if (!do_size) {
515          if (size != 0) st->print("\n\t");
516          st->print(STR_32 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
517#endif
518        }
519      }
520    }
521    size += 4;
522  }
523
524  // Check for integer load
525  if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
526    int offset = ra_->reg2offset(src_first);
527    if (cbuf && !is_memoryI(offset)) {
528      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
529      return 0;
530    } else {
531      if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) {
532        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
533        if (cbuf) {
534          __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
535#ifndef PRODUCT
536        } else if (!do_size) {
537          if (size != 0) st->print("\n\t");
538          st->print(LDR_64 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
539#endif
540        }
541        return size + 4;
542      } else {
543        if (cbuf) {
544          __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
545#ifndef PRODUCT
546        } else if (!do_size) {
547          if (size != 0) st->print("\n\t");
548          st->print(LDR_32 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
549#endif
550        }
551      }
552    }
553    size += 4;
554  }
555
556  // Check for float reg-reg copy
557  if (src_first_rc == rc_float && dst_first_rc == rc_float) {
558    if (src_second_rc != rc_bad) {
559      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");
560      if (cbuf) {
561      __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
562#ifndef PRODUCT
563      } else if (!do_size) {
564        st->print(MOV_DOUBLE "    R_%s, R_%s\t# spill",
565                  Matcher::regName[dst_first],
566                  Matcher::regName[src_first]);
567#endif
568      }
569      return 4;
570    }
571    if (cbuf) {
572      __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
573#ifndef PRODUCT
574    } else if (!do_size) {
575      st->print(MOV_FLOAT "    R_%s, R_%s\t# spill",
576                Matcher::regName[dst_first],
577                Matcher::regName[src_first]);
578#endif
579    }
580    size = 4;
581  }
582
583  // Check for float store
584  if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
585    int offset = ra_->reg2offset(dst_first);
586    if (cbuf && !is_memoryfp(offset)) {
587      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
588      return 0;
589    } else {
590      // Further check for aligned-adjacent pair, so we can use a double store
591      if (src_second_rc != rc_bad) {
592        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");
593        if (cbuf) {
594          __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
595#ifndef PRODUCT
596        } else if (!do_size) {
597          if (size != 0) st->print("\n\t");
598          st->print(STR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
599#endif
600        }
601        return size + 4;
602      } else {
603        if (cbuf) {
604          __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
605#ifndef PRODUCT
606        } else if (!do_size) {
607          if (size != 0) st->print("\n\t");
608          st->print(STR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
609#endif
610        }
611      }
612    }
613    size += 4;
614  }
615
616  // Check for float load
617  if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
618    int offset = ra_->reg2offset(src_first);
619    if (cbuf && !is_memoryfp(offset)) {
620      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
621      return 0;
622    } else {
623      // Further check for aligned-adjacent pair, so we can use a double store
624      if (src_second_rc != rc_bad) {
625        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");
626        if (cbuf) {
627          __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
628#ifndef PRODUCT
629        } else if (!do_size) {
630          if (size != 0) st->print("\n\t");
631          st->print(LDR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
632#endif
633        }
634        return size + 4;
635      } else {
636        if (cbuf) {
637          __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
638#ifndef PRODUCT
639        } else if (!do_size) {
640          if (size != 0) st->print("\n\t");
641          st->print(LDR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
642#endif
643        }
644      }
645    }
646    size += 4;
647  }
648
649  // check for int reg -> float reg move
650  if (src_first_rc == rc_int && dst_first_rc == rc_float) {
651    // Further check for aligned-adjacent pair, so we can use a single instruction
652    if (src_second_rc != rc_bad) {
653      assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
654      assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
655      assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported");
656      if (cbuf) {
657        __ 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]));
658#ifndef PRODUCT
659      } else if (!do_size) {
660        if (size != 0) st->print("\n\t");
661        st->print("FMDRR   R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second));
662#endif
663      }
664      return size + 4;
665    } else {
666      if (cbuf) {
667        __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
668#ifndef PRODUCT
669      } else if (!do_size) {
670        if (size != 0) st->print("\n\t");
671        st->print(FMSR "   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
672#endif
673      }
674      size += 4;
675    }
676  }
677
678  // check for float reg -> int reg move
679  if (src_first_rc == rc_float && dst_first_rc == rc_int) {
680    // Further check for aligned-adjacent pair, so we can use a single instruction
681    if (src_second_rc != rc_bad) {
682      assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
683      assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
684      assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported");
685      if (cbuf) {
686        __ 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]));
687#ifndef PRODUCT
688      } else if (!do_size) {
689        if (size != 0) st->print("\n\t");
690        st->print("FMRRD   R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first));
691#endif
692      }
693      return size + 4;
694    } else {
695      if (cbuf) {
696        __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
697#ifndef PRODUCT
698      } else if (!do_size) {
699        if (size != 0) st->print("\n\t");
700        st->print(FMRS "   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
701#endif
702      }
703      size += 4;
704    }
705  }
706
707  // --------------------------------------------------------------------
708  // Check for hi bits still needing moving.  Only happens for misaligned
709  // arguments to native calls.
710  if (src_second == dst_second)
711    return size;               // Self copy; no move
712  assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
713
714  // Check for integer reg-reg copy.  Hi bits are stuck up in the top
715  // 32-bits of a 64-bit register, but are needed in low bits of another
716  // register (else it's a hi-bits-to-hi-bits copy which should have
717  // happened already as part of a 64-bit move)
718  if (src_second_rc == rc_int && dst_second_rc == rc_int) {
719    if (cbuf) {
720      __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second]));
721#ifndef PRODUCT
722    } else if (!do_size) {
723      if (size != 0) st->print("\n\t");
724      st->print("MOV    R_%s, R_%s\t# spill high",
725                Matcher::regName[dst_second],
726                Matcher::regName[src_second]);
727#endif
728    }
729    return size+4;
730  }
731
732  // Check for high word integer store
733  if (src_second_rc == rc_int && dst_second_rc == rc_stack) {
734    int offset = ra_->reg2offset(dst_second);
735
736    if (cbuf && !is_memoryP(offset)) {
737      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
738      return 0;
739    } else {
740      if (cbuf) {
741        __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset));
742#ifndef PRODUCT
743      } else if (!do_size) {
744        if (size != 0) st->print("\n\t");
745        st->print("STR   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset);
746#endif
747      }
748    }
749    return size + 4;
750  }
751
752  // Check for high word integer load
753  if (dst_second_rc == rc_int && src_second_rc == rc_stack) {
754    int offset = ra_->reg2offset(src_second);
755    if (cbuf && !is_memoryP(offset)) {
756      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
757      return 0;
758    } else {
759      if (cbuf) {
760        __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset));
761#ifndef PRODUCT
762      } else if (!do_size) {
763        if (size != 0) st->print("\n\t");
764        st->print("LDR   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset);
765#endif
766      }
767    }
768    return size + 4;
769  }
770
771  Unimplemented();
772  return 0; // Mute compiler
773}
774
775#ifndef PRODUCT
776void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
777  implementation( NULL, ra_, false, st );
778}
779#endif
780
781void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
782  implementation( &cbuf, ra_, false, NULL );
783}
784
785uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
786  return implementation( NULL, ra_, true, NULL );
787}
788
789//=============================================================================
790#ifndef PRODUCT
791void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
792  st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
793}
794#endif
795
796void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const {
797  C2_MacroAssembler _masm(&cbuf);
798  for(int i = 0; i < _count; i += 1) {
799    __ nop();
800  }
801}
802
803uint MachNopNode::size(PhaseRegAlloc *ra_) const {
804  return 4 * _count;
805}
806
807
808//=============================================================================
809#ifndef PRODUCT
810void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
811  int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
812  int reg = ra_->get_reg_first(this);
813  st->print("ADD    %s,R_SP+#%d",Matcher::regName[reg], offset);
814}
815#endif
816
817void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
818  C2_MacroAssembler _masm(&cbuf);
819  int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
820  int reg = ra_->get_encode(this);
821  Register dst = reg_to_register_object(reg);
822
823  if (is_aimm(offset)) {
824    __ add(dst, SP, offset);
825  } else {
826    __ mov_slow(dst, offset);
827    __ add(dst, SP, dst);
828  }
829}
830
831uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
832  // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
833  assert(ra_ == ra_->C->regalloc(), "sanity");
834  return ra_->C->output()->scratch_emit_size(this);
835}
836
837//=============================================================================
838#ifndef PRODUCT
839#define R_RTEMP "R_R12"
840void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
841  st->print_cr("\nUEP:");
842  if (UseCompressedClassPointers) {
843    st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
844    st->print_cr("\tdecode_klass " R_RTEMP);
845  } else {
846    st->print_cr("\tLDR   " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
847  }
848  st->print_cr("\tCMP   " R_RTEMP ",R_R8" );
849  st->print   ("\tB.NE  SharedRuntime::handle_ic_miss_stub");
850}
851#endif
852
853void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
854  C2_MacroAssembler _masm(&cbuf);
855  Register iCache  = reg_to_register_object(Matcher::inline_cache_reg_encode());
856  assert(iCache == Ricklass, "should be");
857  Register receiver = R0;
858
859  __ load_klass(Rtemp, receiver);
860  __ cmp(Rtemp, iCache);
861  __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
862}
863
864uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
865  return MachNode::size(ra_);
866}
867
868
869//=============================================================================
870
871// Emit exception handler code.
872int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
873  C2_MacroAssembler _masm(&cbuf);
874
875  address base = __ start_a_stub(size_exception_handler());
876  if (base == NULL) {
877    ciEnv::current()->record_failure("CodeCache is full");
878    return 0;  // CodeBuffer::expand failed
879  }
880
881  int offset = __ offset();
882
883  // OK to trash LR, because exception blob will kill it
884  __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp);
885
886  assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
887
888  __ end_a_stub();
889
890  return offset;
891}
892
893int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
894  // Can't use any of the current frame's registers as we may have deopted
895  // at a poll and everything can be live.
896  C2_MacroAssembler _masm(&cbuf);
897
898  address base = __ start_a_stub(size_deopt_handler());
899  if (base == NULL) {
900    ciEnv::current()->record_failure("CodeCache is full");
901    return 0;  // CodeBuffer::expand failed
902  }
903
904  int offset = __ offset();
905  address deopt_pc = __ pc();
906
907  __ sub(SP, SP, wordSize); // make room for saved PC
908  __ push(LR); // save LR that may be live when we get here
909  __ mov_relative_address(LR, deopt_pc);
910  __ str(LR, Address(SP, wordSize)); // save deopt PC
911  __ pop(LR); // restore LR
912  __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);
913
914  assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
915
916  __ end_a_stub();
917  return offset;
918}
919
920const bool Matcher::match_rule_supported(int opcode) {
921  if (!has_match_rule(opcode))
922    return false;
923
924  switch (opcode) {
925  case Op_PopCountI:
926  case Op_PopCountL:
927    if (!UsePopCountInstruction)
928      return false;
929    break;
930  case Op_LShiftCntV:
931  case Op_RShiftCntV:
932  case Op_AddVB:
933  case Op_AddVS:
934  case Op_AddVI:
935  case Op_AddVL:
936  case Op_SubVB:
937  case Op_SubVS:
938  case Op_SubVI:
939  case Op_SubVL:
940  case Op_MulVS:
941  case Op_MulVI:
942  case Op_LShiftVB:
943  case Op_LShiftVS:
944  case Op_LShiftVI:
945  case Op_LShiftVL:
946  case Op_RShiftVB:
947  case Op_RShiftVS:
948  case Op_RShiftVI:
949  case Op_RShiftVL:
950  case Op_URShiftVB:
951  case Op_URShiftVS:
952  case Op_URShiftVI:
953  case Op_URShiftVL:
954  case Op_AndV:
955  case Op_OrV:
956  case Op_XorV:
957    return VM_Version::has_simd();
958  case Op_LoadVector:
959  case Op_StoreVector:
960  case Op_AddVF:
961  case Op_SubVF:
962  case Op_MulVF:
963    return VM_Version::has_vfp() || VM_Version::has_simd();
964  case Op_AddVD:
965  case Op_SubVD:
966  case Op_MulVD:
967  case Op_DivVF:
968  case Op_DivVD:
969    return VM_Version::has_vfp();
970  }
971
972  return true;  // Per default match rules are supported.
973}
974
975const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
976
977  // TODO
978  // identify extra cases that we might want to provide match rules for
979  // e.g. Op_ vector nodes and other intrinsics while guarding with vlen
980  bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen);
981  // Add rules here.
982
983  return ret_value;  // Per default match rules are supported.
984}
985
986const RegMask* Matcher::predicate_reg_mask(void) {
987  return NULL;
988}
989
990const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) {
991  return NULL;
992}
993
994// Vector calling convention not yet implemented.
995const bool Matcher::supports_vector_calling_convention(void) {
996  return false;
997}
998
999OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1000  Unimplemented();
1001  return OptoRegPair(0, 0);
1002}
1003
1004const int Matcher::float_pressure(int default_pressure_threshold) {
1005  return default_pressure_threshold;
1006}
1007
1008// Vector width in bytes
1009const int Matcher::vector_width_in_bytes(BasicType bt) {
1010  return MaxVectorSize;
1011}
1012
1013const int Matcher::scalable_vector_reg_size(const BasicType bt) {
1014  return -1;
1015}
1016
1017// Vector ideal reg corresponding to specified size in bytes
1018const uint Matcher::vector_ideal_reg(int size) {
1019  assert(MaxVectorSize >= size, "");
1020  switch(size) {
1021    case  8: return Op_VecD;
1022    case 16: return Op_VecX;
1023  }
1024  ShouldNotReachHere();
1025  return 0;
1026}
1027
1028// Limits on vector size (number of elements) loaded into vector.
1029const int Matcher::max_vector_size(const BasicType bt) {
1030  assert(is_java_primitive(bt), "only primitive type vectors");
1031  return vector_width_in_bytes(bt)/type2aelembytes(bt);
1032}
1033
1034const int Matcher::min_vector_size(const BasicType bt) {
1035  assert(is_java_primitive(bt), "only primitive type vectors");
1036  return 8/type2aelembytes(bt);
1037}
1038
1039// Is this branch offset short enough that a short branch can be used?
1040//
1041// NOTE: If the platform does not provide any short branch variants, then
1042//       this method should return false for offset 0.
1043bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1044  // The passed offset is relative to address of the branch.
1045  // On ARM a branch displacement is calculated relative to address
1046  // of the branch + 8.
1047  //
1048  // offset -= 8;
1049  // return (Assembler::is_simm24(offset));
1050  return false;
1051}
1052
1053MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
1054  ShouldNotReachHere(); // generic vector operands not supported
1055  return NULL;
1056}
1057
1058bool Matcher::is_generic_reg2reg_move(MachNode* m) {
1059  ShouldNotReachHere();  // generic vector operands not supported
1060  return false;
1061}
1062
1063bool Matcher::is_generic_vector(MachOper* opnd)  {
1064  ShouldNotReachHere();  // generic vector operands not supported
1065  return false;
1066}
1067
1068// Should the matcher clone input 'm' of node 'n'?
1069bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
1070  if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
1071    mstack.push(m, Visit);           // m = ShiftCntV
1072    return true;
1073  }
1074  return false;
1075}
1076
1077// Should the Matcher clone shifts on addressing modes, expecting them
1078// to be subsumed into complex addressing expressions or compute them
1079// into registers?
1080bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
1081  return clone_base_plus_offset_address(m, mstack, address_visited);
1082}
1083
1084// Return whether or not this register is ever used as an argument.  This
1085// function is used on startup to build the trampoline stubs in generateOptoStub.
1086// Registers not mentioned will be killed by the VM call in the trampoline, and
1087// arguments in those registers not be available to the callee.
1088bool Matcher::can_be_java_arg( int reg ) {
1089  if (reg == R_R0_num ||
1090      reg == R_R1_num ||
1091      reg == R_R2_num ||
1092      reg == R_R3_num) return true;
1093
1094  if (reg >= R_S0_num &&
1095      reg <= R_S13_num) return true;
1096  return false;
1097}
1098
1099bool Matcher::is_spillable_arg( int reg ) {
1100  return can_be_java_arg(reg);
1101}
1102
1103bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
1104  return false;
1105}
1106
1107// Register for DIVI projection of divmodI
1108RegMask Matcher::divI_proj_mask() {
1109  ShouldNotReachHere();
1110  return RegMask();
1111}
1112
1113// Register for MODI projection of divmodI
1114RegMask Matcher::modI_proj_mask() {
1115  ShouldNotReachHere();
1116  return RegMask();
1117}
1118
1119// Register for DIVL projection of divmodL
1120RegMask Matcher::divL_proj_mask() {
1121  ShouldNotReachHere();
1122  return RegMask();
1123}
1124
1125// Register for MODL projection of divmodL
1126RegMask Matcher::modL_proj_mask() {
1127  ShouldNotReachHere();
1128  return RegMask();
1129}
1130
1131const RegMask Matcher::method_handle_invoke_SP_save_mask() {
1132  return FP_REGP_mask();
1133}
1134
1135bool maybe_far_call(const CallNode *n) {
1136  return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
1137}
1138
1139bool maybe_far_call(const MachCallNode *n) {
1140  return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
1141}
1142
1143%}
1144
1145//----------ENCODING BLOCK-----------------------------------------------------
1146// This block specifies the encoding classes used by the compiler to output
1147// byte streams.  Encoding classes are parameterized macros used by
1148// Machine Instruction Nodes in order to generate the bit encoding of the
1149// instruction.  Operands specify their base encoding interface with the
1150// interface keyword.  There are currently supported four interfaces,
1151// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER.  REG_INTER causes an
1152// operand to generate a function which returns its register number when
1153// queried.   CONST_INTER causes an operand to generate a function which
1154// returns the value of the constant when queried.  MEMORY_INTER causes an
1155// operand to generate four functions which return the Base Register, the
1156// Index Register, the Scale Value, and the Offset Value of the operand when
1157// queried.  COND_INTER causes an operand to generate six functions which
1158// return the encoding code (ie - encoding bits for the instruction)
1159// associated with each basic boolean condition for a conditional instruction.
1160//
1161// Instructions specify two basic values for encoding.  Again, a function
1162// is available to check if the constant displacement is an oop. They use the
1163// ins_encode keyword to specify their encoding classes (which must be
1164// a sequence of enc_class names, and their parameters, specified in
1165// the encoding block), and they use the
1166// opcode keyword to specify, in order, their primary, secondary, and
1167// tertiary opcode.  Only the opcode sections which a particular instruction
1168// needs for encoding need to be specified.
1169encode %{
1170  enc_class call_epilog %{
1171    // nothing
1172  %}
1173
1174  enc_class Java_To_Runtime (method meth) %{
1175    // CALL directly to the runtime
1176    emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec());
1177  %}
1178
1179  enc_class Java_Static_Call (method meth) %{
1180    // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
1181    // who we intended to call.
1182
1183    if ( !_method) {
1184      emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec());
1185    } else {
1186      int method_index = resolved_method_index(cbuf);
1187      RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1188                                                  : static_call_Relocation::spec(method_index);
1189      emit_call_reloc(cbuf, as_MachCall(), $meth, rspec);
1190
1191      // Emit stubs for static call.
1192      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
1193      if (stub == NULL) {
1194        ciEnv::current()->record_failure("CodeCache is full");
1195        return;
1196      }
1197    }
1198  %}
1199
1200  enc_class save_last_PC %{
1201    // preserve mark
1202    address mark = cbuf.insts()->mark();
1203    debug_only(int off0 = cbuf.insts_size());
1204    C2_MacroAssembler _masm(&cbuf);
1205    int ret_addr_offset = as_MachCall()->ret_addr_offset();
1206    __ adr(LR, mark + ret_addr_offset);
1207    __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
1208    debug_only(int off1 = cbuf.insts_size());
1209    assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
1210    // restore mark
1211    cbuf.insts()->set_mark(mark);
1212  %}
1213
1214  enc_class preserve_SP %{
1215    // preserve mark
1216    address mark = cbuf.insts()->mark();
1217    debug_only(int off0 = cbuf.insts_size());
1218    C2_MacroAssembler _masm(&cbuf);
1219    // FP is preserved across all calls, even compiled calls.
1220    // Use it to preserve SP in places where the callee might change the SP.
1221    __ mov(Rmh_SP_save, SP);
1222    debug_only(int off1 = cbuf.insts_size());
1223    assert(off1 - off0 == 4, "correct size prediction");
1224    // restore mark
1225    cbuf.insts()->set_mark(mark);
1226  %}
1227
1228  enc_class restore_SP %{
1229    C2_MacroAssembler _masm(&cbuf);
1230    __ mov(SP, Rmh_SP_save);
1231  %}
1232
1233  enc_class Java_Dynamic_Call (method meth) %{
1234    C2_MacroAssembler _masm(&cbuf);
1235    Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
1236    assert(R8_ic_reg == Ricklass, "should be");
1237    __ set_inst_mark();
1238    __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff);
1239    __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16);
1240    address  virtual_call_oop_addr = __ inst_mark();
1241    // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
1242    // who we intended to call.
1243    int method_index = resolved_method_index(cbuf);
1244    __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
1245    emit_call_reloc(cbuf, as_MachCall(), $meth, RelocationHolder::none);
1246  %}
1247
1248  enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{
1249    // FIXME: load from constant table?
1250    // Load a constant replicated "count" times with width "width"
1251    int count = $cnt$$constant;
1252    int width = $wth$$constant;
1253    assert(count*width == 4, "sanity");
1254    int val = $src$$constant;
1255    if (width < 4) {
1256      int bit_width = width * 8;
1257      val &= (((int)1) << bit_width) - 1; // mask off sign bits
1258      for (int i = 0; i < count - 1; i++) {
1259        val |= (val << bit_width);
1260      }
1261    }
1262    C2_MacroAssembler _masm(&cbuf);
1263
1264    if (val == -1) {
1265      __ mvn($tmp$$Register, 0);
1266    } else if (val == 0) {
1267      __ mov($tmp$$Register, 0);
1268    } else {
1269      __ movw($tmp$$Register, val & 0xffff);
1270      __ movt($tmp$$Register, (unsigned int)val >> 16);
1271    }
1272    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1273  %}
1274
1275  enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{
1276    // Replicate float con 2 times and pack into vector (8 bytes) in regD.
1277    float fval = $src$$constant;
1278    int val = *((int*)&fval);
1279    C2_MacroAssembler _masm(&cbuf);
1280
1281    if (val == -1) {
1282      __ mvn($tmp$$Register, 0);
1283    } else if (val == 0) {
1284      __ mov($tmp$$Register, 0);
1285    } else {
1286      __ movw($tmp$$Register, val & 0xffff);
1287      __ movt($tmp$$Register, (unsigned int)val >> 16);
1288    }
1289    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1290  %}
1291
1292  enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
1293    Label Ldone, Lloop;
1294    C2_MacroAssembler _masm(&cbuf);
1295
1296    Register   str1_reg = $str1$$Register;
1297    Register   str2_reg = $str2$$Register;
1298    Register   cnt1_reg = $cnt1$$Register; // int
1299    Register   cnt2_reg = $cnt2$$Register; // int
1300    Register   tmp1_reg = $tmp1$$Register;
1301    Register   tmp2_reg = $tmp2$$Register;
1302    Register result_reg = $result$$Register;
1303
1304    assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg);
1305
1306    // Compute the minimum of the string lengths(str1_reg) and the
1307    // difference of the string lengths (stack)
1308
1309    // See if the lengths are different, and calculate min in str1_reg.
1310    // Stash diff in tmp2 in case we need it for a tie-breaker.
1311    __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg);
1312    __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit
1313    __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit
1314
1315    // reallocate cnt1_reg, cnt2_reg, result_reg
1316    // Note:  limit_reg holds the string length pre-scaled by 2
1317    Register limit_reg = cnt1_reg;
1318    Register  chr2_reg = cnt2_reg;
1319    Register  chr1_reg = tmp1_reg;
1320    // str{12} are the base pointers
1321
1322    // Is the minimum length zero?
1323    __ cmp_32(limit_reg, 0);
1324    if (result_reg != tmp2_reg) {
1325      __ mov(result_reg, tmp2_reg, eq);
1326    }
1327    __ b(Ldone, eq);
1328
1329    // Load first characters
1330    __ ldrh(chr1_reg, Address(str1_reg, 0));
1331    __ ldrh(chr2_reg, Address(str2_reg, 0));
1332
1333    // Compare first characters
1334    __ subs(chr1_reg, chr1_reg, chr2_reg);
1335    if (result_reg != chr1_reg) {
1336      __ mov(result_reg, chr1_reg, ne);
1337    }
1338    __ b(Ldone, ne);
1339
1340    {
1341      // Check after comparing first character to see if strings are equivalent
1342      // Check if the strings start at same location
1343      __ cmp(str1_reg, str2_reg);
1344      // Check if the length difference is zero
1345      __ cond_cmp(tmp2_reg, 0, eq);
1346      __ mov(result_reg, 0, eq); // result is zero
1347      __ b(Ldone, eq);
1348      // Strings might not be equal
1349    }
1350
1351    __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar));
1352    if (result_reg != tmp2_reg) {
1353      __ mov(result_reg, tmp2_reg, eq);
1354    }
1355    __ b(Ldone, eq);
1356
1357    // Shift str1_reg and str2_reg to the end of the arrays, negate limit
1358    __ add(str1_reg, str1_reg, limit_reg);
1359    __ add(str2_reg, str2_reg, limit_reg);
1360    __ neg(limit_reg, chr1_reg);  // limit = -(limit-2)
1361
1362    // Compare the rest of the characters
1363    __ bind(Lloop);
1364    __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1365    __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1366    __ subs(chr1_reg, chr1_reg, chr2_reg);
1367    if (result_reg != chr1_reg) {
1368      __ mov(result_reg, chr1_reg, ne);
1369    }
1370    __ b(Ldone, ne);
1371
1372    __ adds(limit_reg, limit_reg, sizeof(jchar));
1373    __ b(Lloop, ne);
1374
1375    // If strings are equal up to min length, return the length difference.
1376    if (result_reg != tmp2_reg) {
1377      __ mov(result_reg, tmp2_reg);
1378    }
1379
1380    // Otherwise, return the difference between the first mismatched chars.
1381    __ bind(Ldone);
1382  %}
1383
1384  enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
1385    Label Lchar, Lchar_loop, Ldone, Lequal;
1386    C2_MacroAssembler _masm(&cbuf);
1387
1388    Register   str1_reg = $str1$$Register;
1389    Register   str2_reg = $str2$$Register;
1390    Register    cnt_reg = $cnt$$Register; // int
1391    Register   tmp1_reg = $tmp1$$Register;
1392    Register   tmp2_reg = $tmp2$$Register;
1393    Register result_reg = $result$$Register;
1394
1395    assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg);
1396
1397    __ cmp(str1_reg, str2_reg); //same char[] ?
1398    __ b(Lequal, eq);
1399
1400    __ cbz_32(cnt_reg, Lequal); // count == 0
1401
1402    //rename registers
1403    Register limit_reg = cnt_reg;
1404    Register  chr1_reg = tmp1_reg;
1405    Register  chr2_reg = tmp2_reg;
1406
1407    __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1408
1409    //check for alignment and position the pointers to the ends
1410    __ orr(chr1_reg, str1_reg, str2_reg);
1411    __ tst(chr1_reg, 0x3);
1412
1413    // notZero means at least one not 4-byte aligned.
1414    // We could optimize the case when both arrays are not aligned
1415    // but it is not frequent case and it requires additional checks.
1416    __ b(Lchar, ne);
1417
1418    // Compare char[] arrays aligned to 4 bytes.
1419    __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
1420                          chr1_reg, chr2_reg, Ldone);
1421
1422    __ b(Lequal); // equal
1423
1424    // char by char compare
1425    __ bind(Lchar);
1426    __ mov(result_reg, 0);
1427    __ add(str1_reg, limit_reg, str1_reg);
1428    __ add(str2_reg, limit_reg, str2_reg);
1429    __ neg(limit_reg, limit_reg); //negate count
1430
1431    // Lchar_loop
1432    __ bind(Lchar_loop);
1433    __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1434    __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1435    __ cmp(chr1_reg, chr2_reg);
1436    __ b(Ldone, ne);
1437    __ adds(limit_reg, limit_reg, sizeof(jchar));
1438    __ b(Lchar_loop, ne);
1439
1440    __ bind(Lequal);
1441    __ mov(result_reg, 1);  //equal
1442
1443    __ bind(Ldone);
1444  %}
1445
1446  enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
1447    Label Ldone, Lloop, Lequal;
1448    C2_MacroAssembler _masm(&cbuf);
1449
1450    Register   ary1_reg = $ary1$$Register;
1451    Register   ary2_reg = $ary2$$Register;
1452    Register   tmp1_reg = $tmp1$$Register;
1453    Register   tmp2_reg = $tmp2$$Register;
1454    Register   tmp3_reg = $tmp3$$Register;
1455    Register result_reg = $result$$Register;
1456
1457    assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg);
1458
1459    int length_offset  = arrayOopDesc::length_offset_in_bytes();
1460    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
1461
1462    // return true if the same array
1463    __ teq(ary1_reg, ary2_reg);
1464    __ mov(result_reg, 1, eq);
1465    __ b(Ldone, eq); // equal
1466
1467    __ tst(ary1_reg, ary1_reg);
1468    __ mov(result_reg, 0, eq);
1469    __ b(Ldone, eq);    // not equal
1470
1471    __ tst(ary2_reg, ary2_reg);
1472    __ mov(result_reg, 0, eq);
1473    __ b(Ldone, eq);    // not equal
1474
1475    //load the lengths of arrays
1476    __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int
1477    __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int
1478
1479    // return false if the two arrays are not equal length
1480    __ teq_32(tmp1_reg, tmp2_reg);
1481    __ mov(result_reg, 0, ne);
1482    __ b(Ldone, ne);    // not equal
1483
1484    __ tst(tmp1_reg, tmp1_reg);
1485    __ mov(result_reg, 1, eq);
1486    __ b(Ldone, eq);    // zero-length arrays are equal
1487
1488    // load array addresses
1489    __ add(ary1_reg, ary1_reg, base_offset);
1490    __ add(ary2_reg, ary2_reg, base_offset);
1491
1492    // renaming registers
1493    Register chr1_reg  =  tmp3_reg;   // for characters in ary1
1494    Register chr2_reg  =  tmp2_reg;   // for characters in ary2
1495    Register limit_reg =  tmp1_reg;   // length
1496
1497    // set byte count
1498    __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1499
1500    // Compare char[] arrays aligned to 4 bytes.
1501    __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
1502                          chr1_reg, chr2_reg, Ldone);
1503    __ bind(Lequal);
1504    __ mov(result_reg, 1);  //equal
1505
1506    __ bind(Ldone);
1507    %}
1508%}
1509
1510//----------FRAME--------------------------------------------------------------
1511// Definition of frame structure and management information.
1512//
1513//  S T A C K   L A Y O U T    Allocators stack-slot number
1514//                             |   (to get allocators register number
1515//  G  Owned by    |        |  v    add VMRegImpl::stack0)
1516//  r   CALLER     |        |
1517//  o     |        +--------+      pad to even-align allocators stack-slot
1518//  w     V        |  pad0  |        numbers; owned by CALLER
1519//  t   -----------+--------+----> Matcher::_in_arg_limit, unaligned
1520//  h     ^        |   in   |  5
1521//        |        |  args  |  4   Holes in incoming args owned by SELF
1522//  |     |        |        |  3
1523//  |     |        +--------+
1524//  V     |        | old out|      Empty on Intel, window on Sparc
1525//        |    old |preserve|      Must be even aligned.
1526//        |     SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned
1527//        |        |   in   |  3   area for Intel ret address
1528//     Owned by    |preserve|      Empty on Sparc.
1529//       SELF      +--------+
1530//        |        |  pad2  |  2   pad to align old SP
1531//        |        +--------+  1
1532//        |        | locks  |  0
1533//        |        +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned
1534//        |        |  pad1  | 11   pad to align new SP
1535//        |        +--------+
1536//        |        |        | 10
1537//        |        | spills |  9   spills
1538//        V        |        |  8   (pad0 slot for callee)
1539//      -----------+--------+----> Matcher::_out_arg_limit, unaligned
1540//        ^        |  out   |  7
1541//        |        |  args  |  6   Holes in outgoing args owned by CALLEE
1542//     Owned by    +--------+
1543//      CALLEE     | new out|  6   Empty on Intel, window on Sparc
1544//        |    new |preserve|      Must be even-aligned.
1545//        |     SP-+--------+----> Matcher::_new_SP, even aligned
1546//        |        |        |
1547//
1548// Note 1: Only region 8-11 is determined by the allocator.  Region 0-5 is
1549//         known from SELF's arguments and the Java calling convention.
1550//         Region 6-7 is determined per call site.
1551// Note 2: If the calling convention leaves holes in the incoming argument
1552//         area, those holes are owned by SELF.  Holes in the outgoing area
1553//         are owned by the CALLEE.  Holes should not be nessecary in the
1554//         incoming area, as the Java calling convention is completely under
1555//         the control of the AD file.  Doubles can be sorted and packed to
1556//         avoid holes.  Holes in the outgoing arguments may be nessecary for
1557//         varargs C calling conventions.
1558// Note 3: Region 0-3 is even aligned, with pad2 as needed.  Region 3-5 is
1559//         even aligned with pad0 as needed.
1560//         Region 6 is even aligned.  Region 6-7 is NOT even aligned;
1561//         region 6-11 is even aligned; it may be padded out more so that
1562//         the region from SP to FP meets the minimum stack alignment.
1563
1564frame %{
1565  // These two registers define part of the calling convention
1566  // between compiled code and the interpreter.
1567  inline_cache_reg(R_Ricklass);          // Inline Cache Register or Method* for I2C
1568
1569  // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
1570  cisc_spilling_operand_name(indOffset);
1571
1572  // Number of stack slots consumed by a Monitor enter
1573  sync_stack_slots(1 * VMRegImpl::slots_per_word);
1574
1575  // Compiled code's Frame Pointer
1576  frame_pointer(R_R13);
1577
1578  // Stack alignment requirement
1579  stack_alignment(StackAlignmentInBytes);
1580  //  LP64: Alignment size in bytes (128-bit -> 16 bytes)
1581  // !LP64: Alignment size in bytes (64-bit  ->  8 bytes)
1582
1583  // Number of outgoing stack slots killed above the out_preserve_stack_slots
1584  // for calls to C.  Supports the var-args backing area for register parms.
1585  // ADLC doesn't support parsing expressions, so I folded the math by hand.
1586  varargs_C_out_slots_killed( 0);
1587
1588  // The after-PROLOG location of the return address.  Location of
1589  // return address specifies a type (REG or STACK) and a number
1590  // representing the register number (i.e. - use a register name) or
1591  // stack slot.
1592  // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1593  // Otherwise, it is above the locks and verification slot and alignment word
1594  return_addr(STACK - 1*VMRegImpl::slots_per_word +
1595              align_up((Compile::current()->in_preserve_stack_slots() +
1596                        Compile::current()->fixed_slots()),
1597                       stack_alignment_in_slots()));
1598
1599  // Location of compiled Java return values.  Same as C
1600  return_value %{
1601    return c2::return_value(ideal_reg);
1602  %}
1603
1604%}
1605
1606//----------ATTRIBUTES---------------------------------------------------------
1607//----------Instruction Attributes---------------------------------------------
1608ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
1609ins_attrib ins_size(32);           // Required size attribute (in bits)
1610ins_attrib ins_short_branch(0);    // Required flag: is this instruction a
1611                                   // non-matching short branch variant of some
1612                                                            // long branch?
1613
1614//----------OPERANDS-----------------------------------------------------------
1615// Operand definitions must precede instruction definitions for correct parsing
1616// in the ADLC because operands constitute user defined types which are used in
1617// instruction definitions.
1618
1619//----------Simple Operands----------------------------------------------------
1620// Immediate Operands
1621// Integer Immediate: 32-bit
1622operand immI() %{
1623  match(ConI);
1624
1625  op_cost(0);
1626  // formats are generated automatically for constants and base registers
1627  format %{ %}
1628  interface(CONST_INTER);
1629%}
1630
1631// Integer Immediate: 8-bit unsigned - for VMOV
1632operand immU8() %{
1633  predicate(0 <= n->get_int() && (n->get_int() <= 255));
1634  match(ConI);
1635  op_cost(0);
1636
1637  format %{ %}
1638  interface(CONST_INTER);
1639%}
1640
1641// Integer Immediate: 16-bit
1642operand immI16() %{
1643  predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw());
1644  match(ConI);
1645  op_cost(0);
1646
1647  format %{ %}
1648  interface(CONST_INTER);
1649%}
1650
1651// Integer Immediate: offset for half and double word loads and stores
1652operand immIHD() %{
1653  predicate(is_memoryHD(n->get_int()));
1654  match(ConI);
1655  op_cost(0);
1656  format %{ %}
1657  interface(CONST_INTER);
1658%}
1659
1660// Integer Immediate: offset for fp loads and stores
1661operand immIFP() %{
1662  predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0));
1663  match(ConI);
1664  op_cost(0);
1665
1666  format %{ %}
1667  interface(CONST_INTER);
1668%}
1669
1670// Valid scale values for addressing modes and shifts
1671operand immU5() %{
1672  predicate(0 <= n->get_int() && (n->get_int() <= 31));
1673  match(ConI);
1674  op_cost(0);
1675
1676  format %{ %}
1677  interface(CONST_INTER);
1678%}
1679
1680// Integer Immediate: 6-bit
1681operand immU6Big() %{
1682  predicate(n->get_int() >= 32 && n->get_int() <= 63);
1683  match(ConI);
1684  op_cost(0);
1685  format %{ %}
1686  interface(CONST_INTER);
1687%}
1688
1689// Integer Immediate: 0-bit
1690operand immI0() %{
1691  predicate(n->get_int() == 0);
1692  match(ConI);
1693  op_cost(0);
1694
1695  format %{ %}
1696  interface(CONST_INTER);
1697%}
1698
1699// Integer Immediate: the value 1
1700operand immI_1() %{
1701  predicate(n->get_int() == 1);
1702  match(ConI);
1703  op_cost(0);
1704
1705  format %{ %}
1706  interface(CONST_INTER);
1707%}
1708
1709// Integer Immediate: the value 2
1710operand immI_2() %{
1711  predicate(n->get_int() == 2);
1712  match(ConI);
1713  op_cost(0);
1714
1715  format %{ %}
1716  interface(CONST_INTER);
1717%}
1718
1719// Integer Immediate: the value 3
1720operand immI_3() %{
1721  predicate(n->get_int() == 3);
1722  match(ConI);
1723  op_cost(0);
1724
1725  format %{ %}
1726  interface(CONST_INTER);
1727%}
1728
1729// Integer Immediate: the value 4
1730operand immI_4() %{
1731  predicate(n->get_int() == 4);
1732  match(ConI);
1733  op_cost(0);
1734
1735  format %{ %}
1736  interface(CONST_INTER);
1737%}
1738
1739// Integer Immediate: the value 8
1740operand immI_8() %{
1741  predicate(n->get_int() == 8);
1742  match(ConI);
1743  op_cost(0);
1744
1745  format %{ %}
1746  interface(CONST_INTER);
1747%}
1748
1749// Int Immediate non-negative
1750operand immU31()
1751%{
1752  predicate(n->get_int() >= 0);
1753  match(ConI);
1754
1755  op_cost(0);
1756  format %{ %}
1757  interface(CONST_INTER);
1758%}
1759
1760// Integer Immediate: the values 32-63
1761operand immI_32_63() %{
1762  predicate(n->get_int() >= 32 && n->get_int() <= 63);
1763  match(ConI);
1764  op_cost(0);
1765
1766  format %{ %}
1767  interface(CONST_INTER);
1768%}
1769
1770// Immediates for special shifts (sign extend)
1771
1772// Integer Immediate: the value 16
1773operand immI_16() %{
1774  predicate(n->get_int() == 16);
1775  match(ConI);
1776  op_cost(0);
1777
1778  format %{ %}
1779  interface(CONST_INTER);
1780%}
1781
1782// Integer Immediate: the value 24
1783operand immI_24() %{
1784  predicate(n->get_int() == 24);
1785  match(ConI);
1786  op_cost(0);
1787
1788  format %{ %}
1789  interface(CONST_INTER);
1790%}
1791
1792// Integer Immediate: the value 255
1793operand immI_255() %{
1794  predicate( n->get_int() == 255 );
1795  match(ConI);
1796  op_cost(0);
1797
1798  format %{ %}
1799  interface(CONST_INTER);
1800%}
1801
1802// Integer Immediate: the value 65535
1803operand immI_65535() %{
1804  predicate(n->get_int() == 65535);
1805  match(ConI);
1806  op_cost(0);
1807
1808  format %{ %}
1809  interface(CONST_INTER);
1810%}
1811
1812// Integer Immediates for arithmetic instructions
1813
1814operand aimmI() %{
1815  predicate(is_aimm(n->get_int()));
1816  match(ConI);
1817  op_cost(0);
1818
1819  format %{ %}
1820  interface(CONST_INTER);
1821%}
1822
1823operand aimmIneg() %{
1824  predicate(is_aimm(-n->get_int()));
1825  match(ConI);
1826  op_cost(0);
1827
1828  format %{ %}
1829  interface(CONST_INTER);
1830%}
1831
1832operand aimmU31() %{
1833  predicate((0 <= n->get_int()) && is_aimm(n->get_int()));
1834  match(ConI);
1835  op_cost(0);
1836
1837  format %{ %}
1838  interface(CONST_INTER);
1839%}
1840
1841// Integer Immediates for logical instructions
1842
1843operand limmI() %{
1844  predicate(is_limmI(n->get_int()));
1845  match(ConI);
1846  op_cost(0);
1847
1848  format %{ %}
1849  interface(CONST_INTER);
1850%}
1851
1852operand limmIlow8() %{
1853  predicate(is_limmI_low(n->get_int(), 8));
1854  match(ConI);
1855  op_cost(0);
1856
1857  format %{ %}
1858  interface(CONST_INTER);
1859%}
1860
1861operand limmU31() %{
1862  predicate(0 <= n->get_int() && is_limmI(n->get_int()));
1863  match(ConI);
1864  op_cost(0);
1865
1866  format %{ %}
1867  interface(CONST_INTER);
1868%}
1869
1870operand limmIn() %{
1871  predicate(is_limmI(~n->get_int()));
1872  match(ConI);
1873  op_cost(0);
1874
1875  format %{ %}
1876  interface(CONST_INTER);
1877%}
1878
1879
1880// Long Immediate: the value FF
1881operand immL_FF() %{
1882  predicate( n->get_long() == 0xFFL );
1883  match(ConL);
1884  op_cost(0);
1885
1886  format %{ %}
1887  interface(CONST_INTER);
1888%}
1889
1890// Long Immediate: the value FFFF
1891operand immL_FFFF() %{
1892  predicate( n->get_long() == 0xFFFFL );
1893  match(ConL);
1894  op_cost(0);
1895
1896  format %{ %}
1897  interface(CONST_INTER);
1898%}
1899
1900// Pointer Immediate: 32 or 64-bit
1901operand immP() %{
1902  match(ConP);
1903
1904  op_cost(5);
1905  // formats are generated automatically for constants and base registers
1906  format %{ %}
1907  interface(CONST_INTER);
1908%}
1909
1910operand immP0() %{
1911  predicate(n->get_ptr() == 0);
1912  match(ConP);
1913  op_cost(0);
1914
1915  format %{ %}
1916  interface(CONST_INTER);
1917%}
1918
1919// Pointer Immediate
1920operand immN()
1921%{
1922  match(ConN);
1923
1924  op_cost(10);
1925  format %{ %}
1926  interface(CONST_INTER);
1927%}
1928
1929operand immNKlass()
1930%{
1931  match(ConNKlass);
1932
1933  op_cost(10);
1934  format %{ %}
1935  interface(CONST_INTER);
1936%}
1937
1938// NULL Pointer Immediate
1939operand immN0()
1940%{
1941  predicate(n->get_narrowcon() == 0);
1942  match(ConN);
1943
1944  op_cost(0);
1945  format %{ %}
1946  interface(CONST_INTER);
1947%}
1948
1949operand immL() %{
1950  match(ConL);
1951  op_cost(40);
1952  // formats are generated automatically for constants and base registers
1953  format %{ %}
1954  interface(CONST_INTER);
1955%}
1956
1957operand immL0() %{
1958  predicate(n->get_long() == 0L);
1959  match(ConL);
1960  op_cost(0);
1961  // formats are generated automatically for constants and base registers
1962  format %{ %}
1963  interface(CONST_INTER);
1964%}
1965
1966// Long Immediate: 16-bit
1967operand immL16() %{
1968  predicate(n->get_long() >= 0 && n->get_long() < (1<<16)  && VM_Version::supports_movw());
1969  match(ConL);
1970  op_cost(0);
1971
1972  format %{ %}
1973  interface(CONST_INTER);
1974%}
1975
1976// Long Immediate: low 32-bit mask
1977operand immL_32bits() %{
1978  predicate(n->get_long() == 0xFFFFFFFFL);
1979  match(ConL);
1980  op_cost(0);
1981
1982  format %{ %}
1983  interface(CONST_INTER);
1984%}
1985
1986// Double Immediate
1987operand immD() %{
1988  match(ConD);
1989
1990  op_cost(40);
1991  format %{ %}
1992  interface(CONST_INTER);
1993%}
1994
1995// Double Immediate: +0.0d.
1996operand immD0() %{
1997  predicate(jlong_cast(n->getd()) == 0);
1998
1999  match(ConD);
2000  op_cost(0);
2001  format %{ %}
2002  interface(CONST_INTER);
2003%}
2004
2005operand imm8D() %{
2006  predicate(Assembler::double_num(n->getd()).can_be_imm8());
2007  match(ConD);
2008
2009  op_cost(0);
2010  format %{ %}
2011  interface(CONST_INTER);
2012%}
2013
2014// Float Immediate
2015operand immF() %{
2016  match(ConF);
2017
2018  op_cost(20);
2019  format %{ %}
2020  interface(CONST_INTER);
2021%}
2022
2023// Float Immediate: +0.0f
2024operand immF0() %{
2025  predicate(jint_cast(n->getf()) == 0);
2026  match(ConF);
2027
2028  op_cost(0);
2029  format %{ %}
2030  interface(CONST_INTER);
2031%}
2032
2033// Float Immediate: encoded as 8 bits
2034operand imm8F() %{
2035  predicate(Assembler::float_num(n->getf()).can_be_imm8());
2036  match(ConF);
2037
2038  op_cost(0);
2039  format %{ %}
2040  interface(CONST_INTER);
2041%}
2042
2043// Integer Register Operands
2044// Integer Register
2045operand iRegI() %{
2046  constraint(ALLOC_IN_RC(int_reg));
2047  match(RegI);
2048  match(R0RegI);
2049  match(R1RegI);
2050  match(R2RegI);
2051  match(R3RegI);
2052  match(R12RegI);
2053
2054  format %{ %}
2055  interface(REG_INTER);
2056%}
2057
2058// Pointer Register
2059operand iRegP() %{
2060  constraint(ALLOC_IN_RC(ptr_reg));
2061  match(RegP);
2062  match(R0RegP);
2063  match(R1RegP);
2064  match(R2RegP);
2065  match(RExceptionRegP);
2066  match(R8RegP);
2067  match(R9RegP);
2068  match(RthreadRegP); // FIXME: move to sp_ptr_RegP?
2069  match(R12RegP);
2070  match(LRRegP);
2071
2072  match(sp_ptr_RegP);
2073  match(store_ptr_RegP);
2074
2075  format %{ %}
2076  interface(REG_INTER);
2077%}
2078
2079// GPRs + Rthread + SP
2080operand sp_ptr_RegP() %{
2081  constraint(ALLOC_IN_RC(sp_ptr_reg));
2082  match(RegP);
2083  match(iRegP);
2084  match(SPRegP); // FIXME: check cost
2085
2086  format %{ %}
2087  interface(REG_INTER);
2088%}
2089
2090
2091operand R0RegP() %{
2092  constraint(ALLOC_IN_RC(R0_regP));
2093  match(iRegP);
2094
2095  format %{ %}
2096  interface(REG_INTER);
2097%}
2098
2099operand R1RegP() %{
2100  constraint(ALLOC_IN_RC(R1_regP));
2101  match(iRegP);
2102
2103  format %{ %}
2104  interface(REG_INTER);
2105%}
2106
2107operand R8RegP() %{
2108  constraint(ALLOC_IN_RC(R8_regP));
2109  match(iRegP);
2110
2111  format %{ %}
2112  interface(REG_INTER);
2113%}
2114
2115operand R9RegP() %{
2116  constraint(ALLOC_IN_RC(R9_regP));
2117  match(iRegP);
2118
2119  format %{ %}
2120  interface(REG_INTER);
2121%}
2122
2123operand R12RegP() %{
2124  constraint(ALLOC_IN_RC(R12_regP));
2125  match(iRegP);
2126
2127  format %{ %}
2128  interface(REG_INTER);
2129%}
2130
2131operand R2RegP() %{
2132  constraint(ALLOC_IN_RC(R2_regP));
2133  match(iRegP);
2134
2135  format %{ %}
2136  interface(REG_INTER);
2137%}
2138
2139operand RExceptionRegP() %{
2140  constraint(ALLOC_IN_RC(Rexception_regP));
2141  match(iRegP);
2142
2143  format %{ %}
2144  interface(REG_INTER);
2145%}
2146
2147operand RthreadRegP() %{
2148  constraint(ALLOC_IN_RC(Rthread_regP));
2149  match(iRegP);
2150
2151  format %{ %}
2152  interface(REG_INTER);
2153%}
2154
2155operand IPRegP() %{
2156  constraint(ALLOC_IN_RC(IP_regP));
2157  match(iRegP);
2158
2159  format %{ %}
2160  interface(REG_INTER);
2161%}
2162
2163operand SPRegP() %{
2164  constraint(ALLOC_IN_RC(SP_regP));
2165  match(iRegP);
2166
2167  format %{ %}
2168  interface(REG_INTER);
2169%}
2170
2171operand LRRegP() %{
2172  constraint(ALLOC_IN_RC(LR_regP));
2173  match(iRegP);
2174
2175  format %{ %}
2176  interface(REG_INTER);
2177%}
2178
2179operand R0RegI() %{
2180  constraint(ALLOC_IN_RC(R0_regI));
2181  match(iRegI);
2182
2183  format %{ %}
2184  interface(REG_INTER);
2185%}
2186
2187operand R1RegI() %{
2188  constraint(ALLOC_IN_RC(R1_regI));
2189  match(iRegI);
2190
2191  format %{ %}
2192  interface(REG_INTER);
2193%}
2194
2195operand R2RegI() %{
2196  constraint(ALLOC_IN_RC(R2_regI));
2197  match(iRegI);
2198
2199  format %{ %}
2200  interface(REG_INTER);
2201%}
2202
2203operand R3RegI() %{
2204  constraint(ALLOC_IN_RC(R3_regI));
2205  match(iRegI);
2206
2207  format %{ %}
2208  interface(REG_INTER);
2209%}
2210
2211operand R12RegI() %{
2212  constraint(ALLOC_IN_RC(R12_regI));
2213  match(iRegI);
2214
2215  format %{ %}
2216  interface(REG_INTER);
2217%}
2218
2219// Long Register
2220operand iRegL() %{
2221  constraint(ALLOC_IN_RC(long_reg));
2222  match(RegL);
2223  match(R0R1RegL);
2224  match(R2R3RegL);
2225//match(iRegLex);
2226
2227  format %{ %}
2228  interface(REG_INTER);
2229%}
2230
2231operand iRegLd() %{
2232  constraint(ALLOC_IN_RC(long_reg_align));
2233  match(iRegL); // FIXME: allows unaligned R11/R12?
2234
2235  format %{ %}
2236  interface(REG_INTER);
2237%}
2238
2239// first long arg, or return value
2240operand R0R1RegL() %{
2241  constraint(ALLOC_IN_RC(R0R1_regL));
2242  match(iRegL);
2243
2244  format %{ %}
2245  interface(REG_INTER);
2246%}
2247
2248operand R2R3RegL() %{
2249  constraint(ALLOC_IN_RC(R2R3_regL));
2250  match(iRegL);
2251
2252  format %{ %}
2253  interface(REG_INTER);
2254%}
2255
2256// Condition Code Flag Register
2257operand flagsReg() %{
2258  constraint(ALLOC_IN_RC(int_flags));
2259  match(RegFlags);
2260
2261  format %{ "apsr" %}
2262  interface(REG_INTER);
2263%}
2264
2265// Result of compare to 0 (TST)
2266operand flagsReg_EQNELTGE() %{
2267  constraint(ALLOC_IN_RC(int_flags));
2268  match(RegFlags);
2269
2270  format %{ "apsr_EQNELTGE" %}
2271  interface(REG_INTER);
2272%}
2273
2274// Condition Code Register, unsigned comparisons.
2275operand flagsRegU() %{
2276  constraint(ALLOC_IN_RC(int_flags));
2277  match(RegFlags);
2278#ifdef TODO
2279  match(RegFlagsP);
2280#endif
2281
2282  format %{ "apsr_U" %}
2283  interface(REG_INTER);
2284%}
2285
2286// Condition Code Register, pointer comparisons.
2287operand flagsRegP() %{
2288  constraint(ALLOC_IN_RC(int_flags));
2289  match(RegFlags);
2290
2291  format %{ "apsr_P" %}
2292  interface(REG_INTER);
2293%}
2294
2295// Condition Code Register, long comparisons.
2296operand flagsRegL_LTGE() %{
2297  constraint(ALLOC_IN_RC(int_flags));
2298  match(RegFlags);
2299
2300  format %{ "apsr_L_LTGE" %}
2301  interface(REG_INTER);
2302%}
2303
2304operand flagsRegL_EQNE() %{
2305  constraint(ALLOC_IN_RC(int_flags));
2306  match(RegFlags);
2307
2308  format %{ "apsr_L_EQNE" %}
2309  interface(REG_INTER);
2310%}
2311
2312operand flagsRegL_LEGT() %{
2313  constraint(ALLOC_IN_RC(int_flags));
2314  match(RegFlags);
2315
2316  format %{ "apsr_L_LEGT" %}
2317  interface(REG_INTER);
2318%}
2319
2320operand flagsRegUL_LTGE() %{
2321  constraint(ALLOC_IN_RC(int_flags));
2322  match(RegFlags);
2323
2324  format %{ "apsr_UL_LTGE" %}
2325  interface(REG_INTER);
2326%}
2327
2328operand flagsRegUL_EQNE() %{
2329  constraint(ALLOC_IN_RC(int_flags));
2330  match(RegFlags);
2331
2332  format %{ "apsr_UL_EQNE" %}
2333  interface(REG_INTER);
2334%}
2335
2336operand flagsRegUL_LEGT() %{
2337  constraint(ALLOC_IN_RC(int_flags));
2338  match(RegFlags);
2339
2340  format %{ "apsr_UL_LEGT" %}
2341  interface(REG_INTER);
2342%}
2343
2344// Condition Code Register, floating comparisons, unordered same as "less".
2345operand flagsRegF() %{
2346  constraint(ALLOC_IN_RC(float_flags));
2347  match(RegFlags);
2348
2349  format %{ "fpscr_F" %}
2350  interface(REG_INTER);
2351%}
2352
2353// Vectors
2354operand vecD() %{
2355  constraint(ALLOC_IN_RC(actual_dflt_reg));
2356  match(VecD);
2357
2358  format %{ %}
2359  interface(REG_INTER);
2360%}
2361
2362operand vecX() %{
2363  constraint(ALLOC_IN_RC(vectorx_reg));
2364  match(VecX);
2365
2366  format %{ %}
2367  interface(REG_INTER);
2368%}
2369
2370operand regD() %{
2371  constraint(ALLOC_IN_RC(actual_dflt_reg));
2372  match(RegD);
2373  match(regD_low);
2374
2375  format %{ %}
2376  interface(REG_INTER);
2377%}
2378
2379operand regF() %{
2380  constraint(ALLOC_IN_RC(sflt_reg));
2381  match(RegF);
2382
2383  format %{ %}
2384  interface(REG_INTER);
2385%}
2386
2387operand regD_low() %{
2388  constraint(ALLOC_IN_RC(dflt_low_reg));
2389  match(RegD);
2390
2391  format %{ %}
2392  interface(REG_INTER);
2393%}
2394
2395// Special Registers
2396
2397// Method Register
2398operand inline_cache_regP(iRegP reg) %{
2399  constraint(ALLOC_IN_RC(Ricklass_regP));
2400  match(reg);
2401  format %{ %}
2402  interface(REG_INTER);
2403%}
2404
2405//----------Complex Operands---------------------------------------------------
2406// Indirect Memory Reference
2407operand indirect(sp_ptr_RegP reg) %{
2408  constraint(ALLOC_IN_RC(sp_ptr_reg));
2409  match(reg);
2410
2411  op_cost(100);
2412  format %{ "[$reg]" %}
2413  interface(MEMORY_INTER) %{
2414    base($reg);
2415    index(0xf); // PC => no index
2416    scale(0x0);
2417    disp(0x0);
2418  %}
2419%}
2420
2421
2422// Indirect with Offset in ]-4096, 4096[
2423operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{
2424  constraint(ALLOC_IN_RC(sp_ptr_reg));
2425  match(AddP reg offset);
2426
2427  op_cost(100);
2428  format %{ "[$reg + $offset]" %}
2429  interface(MEMORY_INTER) %{
2430    base($reg);
2431    index(0xf); // PC => no index
2432    scale(0x0);
2433    disp($offset);
2434  %}
2435%}
2436
2437// Indirect with offset for float load/store
2438operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{
2439  constraint(ALLOC_IN_RC(sp_ptr_reg));
2440  match(AddP reg offset);
2441
2442  op_cost(100);
2443  format %{ "[$reg + $offset]" %}
2444  interface(MEMORY_INTER) %{
2445    base($reg);
2446    index(0xf); // PC => no index
2447    scale(0x0);
2448    disp($offset);
2449  %}
2450%}
2451
2452// Indirect with Offset for half and double words
2453operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{
2454  constraint(ALLOC_IN_RC(sp_ptr_reg));
2455  match(AddP reg offset);
2456
2457  op_cost(100);
2458  format %{ "[$reg + $offset]" %}
2459  interface(MEMORY_INTER) %{
2460    base($reg);
2461    index(0xf); // PC => no index
2462    scale(0x0);
2463    disp($offset);
2464  %}
2465%}
2466
2467// Indirect with Offset and Offset+4 in ]-1024, 1024[
2468operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{
2469  constraint(ALLOC_IN_RC(sp_ptr_reg));
2470  match(AddP reg offset);
2471
2472  op_cost(100);
2473  format %{ "[$reg + $offset]" %}
2474  interface(MEMORY_INTER) %{
2475    base($reg);
2476    index(0xf); // PC => no index
2477    scale(0x0);
2478    disp($offset);
2479  %}
2480%}
2481
2482// Indirect with Offset and Offset+4 in ]-4096, 4096[
2483operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{
2484  constraint(ALLOC_IN_RC(sp_ptr_reg));
2485  match(AddP reg offset);
2486
2487  op_cost(100);
2488  format %{ "[$reg + $offset]" %}
2489  interface(MEMORY_INTER) %{
2490    base($reg);
2491    index(0xf); // PC => no index
2492    scale(0x0);
2493    disp($offset);
2494  %}
2495%}
2496
2497// Indirect with Register Index
2498operand indIndex(iRegP addr, iRegX index) %{
2499  constraint(ALLOC_IN_RC(ptr_reg));
2500  match(AddP addr index);
2501
2502  op_cost(100);
2503  format %{ "[$addr + $index]" %}
2504  interface(MEMORY_INTER) %{
2505    base($addr);
2506    index($index);
2507    scale(0x0);
2508    disp(0x0);
2509  %}
2510%}
2511
2512// Indirect Memory Times Scale Plus Index Register
2513operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{
2514  constraint(ALLOC_IN_RC(ptr_reg));
2515  match(AddP addr (LShiftX index scale));
2516
2517  op_cost(100);
2518  format %{"[$addr + $index << $scale]" %}
2519  interface(MEMORY_INTER) %{
2520    base($addr);
2521    index($index);
2522    scale($scale);
2523    disp(0x0);
2524  %}
2525%}
2526
2527// Operands for expressing Control Flow
2528// NOTE:  Label is a predefined operand which should not be redefined in
2529//        the AD file.  It is generically handled within the ADLC.
2530
2531//----------Conditional Branch Operands----------------------------------------
2532// Comparison Op  - This is the operation of the comparison, and is limited to
2533//                  the following set of codes:
2534//                  L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
2535//
2536// Other attributes of the comparison, such as unsignedness, are specified
2537// by the comparison instruction that sets a condition code flags register.
2538// That result is represented by a flags operand whose subtype is appropriate
2539// to the unsignedness (etc.) of the comparison.
2540//
2541// Later, the instruction which matches both the Comparison Op (a Bool) and
2542// the flags (produced by the Cmp) specifies the coding of the comparison op
2543// by matching a specific subtype of Bool operand below, such as cmpOpU.
2544
2545operand cmpOp() %{
2546  match(Bool);
2547
2548  format %{ "" %}
2549  interface(COND_INTER) %{
2550    equal(0x0);
2551    not_equal(0x1);
2552    less(0xb);
2553    greater_equal(0xa);
2554    less_equal(0xd);
2555    greater(0xc);
2556    overflow(0x0); // unsupported/unimplemented
2557    no_overflow(0x0); // unsupported/unimplemented
2558  %}
2559%}
2560
2561// integer comparison with 0, signed
2562operand cmpOp0() %{
2563  match(Bool);
2564
2565  format %{ "" %}
2566  interface(COND_INTER) %{
2567    equal(0x0);
2568    not_equal(0x1);
2569    less(0x4);
2570    greater_equal(0x5);
2571    less_equal(0xd); // unsupported
2572    greater(0xc); // unsupported
2573    overflow(0x0); // unsupported/unimplemented
2574    no_overflow(0x0); // unsupported/unimplemented
2575  %}
2576%}
2577
2578// Comparison Op, unsigned
2579operand cmpOpU() %{
2580  match(Bool);
2581
2582  format %{ "u" %}
2583  interface(COND_INTER) %{
2584    equal(0x0);
2585    not_equal(0x1);
2586    less(0x3);
2587    greater_equal(0x2);
2588    less_equal(0x9);
2589    greater(0x8);
2590    overflow(0x0); // unsupported/unimplemented
2591    no_overflow(0x0); // unsupported/unimplemented
2592  %}
2593%}
2594
2595// Comparison Op, pointer (same as unsigned)
2596operand cmpOpP() %{
2597  match(Bool);
2598
2599  format %{ "p" %}
2600  interface(COND_INTER) %{
2601    equal(0x0);
2602    not_equal(0x1);
2603    less(0x3);
2604    greater_equal(0x2);
2605    less_equal(0x9);
2606    greater(0x8);
2607    overflow(0x0); // unsupported/unimplemented
2608    no_overflow(0x0); // unsupported/unimplemented
2609  %}
2610%}
2611
2612operand cmpOpL() %{
2613  match(Bool);
2614
2615  format %{ "L" %}
2616  interface(COND_INTER) %{
2617    equal(0x0);
2618    not_equal(0x1);
2619    less(0xb);
2620    greater_equal(0xa);
2621    less_equal(0xd);
2622    greater(0xc);
2623    overflow(0x0); // unsupported/unimplemented
2624    no_overflow(0x0); // unsupported/unimplemented
2625  %}
2626%}
2627
2628operand cmpOpL_commute() %{
2629  match(Bool);
2630
2631  format %{ "L" %}
2632  interface(COND_INTER) %{
2633    equal(0x0);
2634    not_equal(0x1);
2635    less(0xc);
2636    greater_equal(0xd);
2637    less_equal(0xa);
2638    greater(0xb);
2639    overflow(0x0); // unsupported/unimplemented
2640    no_overflow(0x0); // unsupported/unimplemented
2641  %}
2642%}
2643
2644operand cmpOpUL() %{
2645  match(Bool);
2646
2647  format %{ "UL" %}
2648  interface(COND_INTER) %{
2649    equal(0x0);
2650    not_equal(0x1);
2651    less(0x3);
2652    greater_equal(0x2);
2653    less_equal(0x9);
2654    greater(0x8);
2655    overflow(0x0); // unsupported/unimplemented
2656    no_overflow(0x0); // unsupported/unimplemented
2657  %}
2658%}
2659
2660operand cmpOpUL_commute() %{
2661  match(Bool);
2662
2663  format %{ "UL" %}
2664  interface(COND_INTER) %{
2665    equal(0x0);
2666    not_equal(0x1);
2667    less(0x8);
2668    greater_equal(0x9);
2669    less_equal(0x2);
2670    greater(0x3);
2671    overflow(0x0); // unsupported/unimplemented
2672    no_overflow(0x0); // unsupported/unimplemented
2673  %}
2674%}
2675
2676
2677//----------OPERAND CLASSES----------------------------------------------------
2678// Operand Classes are groups of operands that are used to simplify
2679// instruction definitions by not requiring the AD writer to specify separate
2680// instructions for every form of operand when the instruction accepts
2681// multiple operand types with the same basic encoding and format.  The classic
2682// case of this is memory operands.
2683
2684opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale );
2685opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale );
2686opclass memoryF ( indirect, indOffsetFP );
2687opclass memoryF2 ( indirect, indOffsetFPx2 );
2688opclass memoryD ( indirect, indOffsetFP );
2689opclass memoryfp( indirect, indOffsetFP );
2690opclass memoryB ( indirect, indIndex, indOffsetHD );
2691opclass memoryS ( indirect, indIndex, indOffsetHD );
2692opclass memoryL ( indirect, indIndex, indOffsetHD );
2693
2694opclass memoryScaledI(indIndexScale);
2695opclass memoryScaledP(indIndexScale);
2696
2697// when ldrex/strex is used:
2698opclass memoryex ( indirect );
2699opclass indIndexMemory( indIndex );
2700opclass memorylong ( indirect, indOffset12x2 );
2701opclass memoryvld ( indirect /* , write back mode not implemented */ );
2702
2703//----------PIPELINE-----------------------------------------------------------
2704pipeline %{
2705
2706//----------ATTRIBUTES---------------------------------------------------------
2707attributes %{
2708  fixed_size_instructions;           // Fixed size instructions
2709  max_instructions_per_bundle = 4;   // Up to 4 instructions per bundle
2710  instruction_unit_size = 4;         // An instruction is 4 bytes long
2711  instruction_fetch_unit_size = 16;  // The processor fetches one line
2712  instruction_fetch_units = 1;       // of 16 bytes
2713
2714  // List of nop instructions
2715  nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR );
2716%}
2717
2718//----------RESOURCES----------------------------------------------------------
2719// Resources are the functional units available to the machine
2720resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1);
2721
2722//----------PIPELINE DESCRIPTION-----------------------------------------------
2723// Pipeline Description specifies the stages in the machine's pipeline
2724
2725pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D);
2726
2727//----------PIPELINE CLASSES---------------------------------------------------
2728// Pipeline Classes describe the stages in which input and output are
2729// referenced by the hardware pipeline.
2730
2731// Integer ALU reg-reg operation
2732pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2733    single_instruction;
2734    dst   : E(write);
2735    src1  : R(read);
2736    src2  : R(read);
2737    IALU  : R;
2738%}
2739
2740// Integer ALU reg-reg long operation
2741pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{
2742    instruction_count(2);
2743    dst   : E(write);
2744    src1  : R(read);
2745    src2  : R(read);
2746    IALU  : R;
2747    IALU  : R;
2748%}
2749
2750// Integer ALU reg-reg long dependent operation
2751pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{
2752    instruction_count(1); multiple_bundles;
2753    dst   : E(write);
2754    src1  : R(read);
2755    src2  : R(read);
2756    cr    : E(write);
2757    IALU  : R(2);
2758%}
2759
2760// Integer ALU reg-imm operaion
2761pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{
2762    single_instruction;
2763    dst   : E(write);
2764    src1  : R(read);
2765    IALU  : R;
2766%}
2767
2768// Integer ALU reg-reg operation with condition code
2769pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{
2770    single_instruction;
2771    dst   : E(write);
2772    cr    : E(write);
2773    src1  : R(read);
2774    src2  : R(read);
2775    IALU  : R;
2776%}
2777
2778// Integer ALU zero-reg operation
2779pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{
2780    single_instruction;
2781    dst   : E(write);
2782    src2  : R(read);
2783    IALU  : R;
2784%}
2785
2786// Integer ALU zero-reg operation with condition code only
2787pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{
2788    single_instruction;
2789    cr    : E(write);
2790    src   : R(read);
2791    IALU  : R;
2792%}
2793
2794// Integer ALU reg-reg operation with condition code only
2795pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2796    single_instruction;
2797    cr    : E(write);
2798    src1  : R(read);
2799    src2  : R(read);
2800    IALU  : R;
2801%}
2802
2803// Integer ALU reg-imm operation with condition code only
2804pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{
2805    single_instruction;
2806    cr    : E(write);
2807    src1  : R(read);
2808    IALU  : R;
2809%}
2810
2811// Integer ALU reg-reg-zero operation with condition code only
2812pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{
2813    single_instruction;
2814    cr    : E(write);
2815    src1  : R(read);
2816    src2  : R(read);
2817    IALU  : R;
2818%}
2819
2820// Integer ALU reg-imm-zero operation with condition code only
2821pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{
2822    single_instruction;
2823    cr    : E(write);
2824    src1  : R(read);
2825    IALU  : R;
2826%}
2827
2828// Integer ALU reg-reg operation with condition code, src1 modified
2829pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2830    single_instruction;
2831    cr    : E(write);
2832    src1  : E(write);
2833    src1  : R(read);
2834    src2  : R(read);
2835    IALU  : R;
2836%}
2837
2838pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{
2839    multiple_bundles;
2840    dst   : E(write)+4;
2841    cr    : E(write);
2842    src1  : R(read);
2843    src2  : R(read);
2844    IALU  : R(3);
2845    BR    : R(2);
2846%}
2847
2848// Integer ALU operation
2849pipe_class ialu_none(iRegI dst) %{
2850    single_instruction;
2851    dst   : E(write);
2852    IALU  : R;
2853%}
2854
2855// Integer ALU reg operation
2856pipe_class ialu_reg(iRegI dst, iRegI src) %{
2857    single_instruction; may_have_no_code;
2858    dst   : E(write);
2859    src   : R(read);
2860    IALU  : R;
2861%}
2862
2863// Integer ALU reg conditional operation
2864// This instruction has a 1 cycle stall, and cannot execute
2865// in the same cycle as the instruction setting the condition
2866// code. We kludge this by pretending to read the condition code
2867// 1 cycle earlier, and by marking the functional units as busy
2868// for 2 cycles with the result available 1 cycle later than
2869// is really the case.
2870pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{
2871    single_instruction;
2872    op2_out : C(write);
2873    op1     : R(read);
2874    cr      : R(read);       // This is really E, with a 1 cycle stall
2875    BR      : R(2);
2876    MS      : R(2);
2877%}
2878
2879// Integer ALU reg operation
2880pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{
2881    single_instruction; may_have_no_code;
2882    dst   : E(write);
2883    src   : R(read);
2884    IALU  : R;
2885%}
2886pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{
2887    single_instruction; may_have_no_code;
2888    dst   : E(write);
2889    src   : R(read);
2890    IALU  : R;
2891%}
2892
2893// Two integer ALU reg operations
2894pipe_class ialu_reg_2(iRegL dst, iRegL src) %{
2895    instruction_count(2);
2896    dst   : E(write);
2897    src   : R(read);
2898    A0    : R;
2899    A1    : R;
2900%}
2901
2902// Two integer ALU reg operations
2903pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{
2904    instruction_count(2); may_have_no_code;
2905    dst   : E(write);
2906    src   : R(read);
2907    A0    : R;
2908    A1    : R;
2909%}
2910
2911// Integer ALU imm operation
2912pipe_class ialu_imm(iRegI dst) %{
2913    single_instruction;
2914    dst   : E(write);
2915    IALU  : R;
2916%}
2917
2918pipe_class ialu_imm_n(iRegI dst) %{
2919    single_instruction;
2920    dst   : E(write);
2921    IALU  : R;
2922%}
2923
2924// Integer ALU reg-reg with carry operation
2925pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{
2926    single_instruction;
2927    dst   : E(write);
2928    src1  : R(read);
2929    src2  : R(read);
2930    IALU  : R;
2931%}
2932
2933// Integer ALU cc operation
2934pipe_class ialu_cc(iRegI dst, flagsReg cc) %{
2935    single_instruction;
2936    dst   : E(write);
2937    cc    : R(read);
2938    IALU  : R;
2939%}
2940
2941// Integer ALU cc / second IALU operation
2942pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{
2943    instruction_count(1); multiple_bundles;
2944    dst   : E(write)+1;
2945    src   : R(read);
2946    IALU  : R;
2947%}
2948
2949// Integer ALU cc / second IALU operation
2950pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{
2951    instruction_count(1); multiple_bundles;
2952    dst   : E(write)+1;
2953    p     : R(read);
2954    q     : R(read);
2955    IALU  : R;
2956%}
2957
2958// Integer ALU hi-lo-reg operation
2959pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{
2960    instruction_count(1); multiple_bundles;
2961    dst   : E(write)+1;
2962    IALU  : R(2);
2963%}
2964
2965// Long Constant
2966pipe_class loadConL( iRegL dst, immL src ) %{
2967    instruction_count(2); multiple_bundles;
2968    dst   : E(write)+1;
2969    IALU  : R(2);
2970    IALU  : R(2);
2971%}
2972
2973// Pointer Constant
2974pipe_class loadConP( iRegP dst, immP src ) %{
2975    instruction_count(0); multiple_bundles;
2976    fixed_latency(6);
2977%}
2978
2979// Long Constant small
2980pipe_class loadConLlo( iRegL dst, immL src ) %{
2981    instruction_count(2);
2982    dst   : E(write);
2983    IALU  : R;
2984    IALU  : R;
2985%}
2986
2987// [PHH] This is wrong for 64-bit.  See LdImmF/D.
2988pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{
2989    instruction_count(1); multiple_bundles;
2990    src   : R(read);
2991    dst   : M(write)+1;
2992    IALU  : R;
2993    MS    : E;
2994%}
2995
2996// Integer ALU nop operation
2997pipe_class ialu_nop() %{
2998    single_instruction;
2999    IALU  : R;
3000%}
3001
3002// Integer ALU nop operation
3003pipe_class ialu_nop_A0() %{
3004    single_instruction;
3005    A0    : R;
3006%}
3007
3008// Integer ALU nop operation
3009pipe_class ialu_nop_A1() %{
3010    single_instruction;
3011    A1    : R;
3012%}
3013
3014// Integer Multiply reg-reg operation
3015pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
3016    single_instruction;
3017    dst   : E(write);
3018    src1  : R(read);
3019    src2  : R(read);
3020    MS    : R(5);
3021%}
3022
3023pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
3024    single_instruction;
3025    dst   : E(write)+4;
3026    src1  : R(read);
3027    src2  : R(read);
3028    MS    : R(6);
3029%}
3030
3031// Integer Divide reg-reg
3032pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{
3033    instruction_count(1); multiple_bundles;
3034    dst   : E(write);
3035    temp  : E(write);
3036    src1  : R(read);
3037    src2  : R(read);
3038    temp  : R(read);
3039    MS    : R(38);
3040%}
3041
3042// Long Divide
3043pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
3044    dst  : E(write)+71;
3045    src1 : R(read);
3046    src2 : R(read)+1;
3047    MS   : R(70);
3048%}
3049
3050// Floating Point Add Float
3051pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{
3052    single_instruction;
3053    dst   : X(write);
3054    src1  : E(read);
3055    src2  : E(read);
3056    FA    : R;
3057%}
3058
3059// Floating Point Add Double
3060pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{
3061    single_instruction;
3062    dst   : X(write);
3063    src1  : E(read);
3064    src2  : E(read);
3065    FA    : R;
3066%}
3067
3068// Floating Point Conditional Move based on integer flags
3069pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{
3070    single_instruction;
3071    dst   : X(write);
3072    src   : E(read);
3073    cr    : R(read);
3074    FA    : R(2);
3075    BR    : R(2);
3076%}
3077
3078// Floating Point Conditional Move based on integer flags
3079pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{
3080    single_instruction;
3081    dst   : X(write);
3082    src   : E(read);
3083    cr    : R(read);
3084    FA    : R(2);
3085    BR    : R(2);
3086%}
3087
3088// Floating Point Multiply Float
3089pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{
3090    single_instruction;
3091    dst   : X(write);
3092    src1  : E(read);
3093    src2  : E(read);
3094    FM    : R;
3095%}
3096
3097// Floating Point Multiply Double
3098pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{
3099    single_instruction;
3100    dst   : X(write);
3101    src1  : E(read);
3102    src2  : E(read);
3103    FM    : R;
3104%}
3105
3106// Floating Point Divide Float
3107pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{
3108    single_instruction;
3109    dst   : X(write);
3110    src1  : E(read);
3111    src2  : E(read);
3112    FM    : R;
3113    FDIV  : C(14);
3114%}
3115
3116// Floating Point Divide Double
3117pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{
3118    single_instruction;
3119    dst   : X(write);
3120    src1  : E(read);
3121    src2  : E(read);
3122    FM    : R;
3123    FDIV  : C(17);
3124%}
3125
3126// Floating Point Move/Negate/Abs Float
3127pipe_class faddF_reg(regF dst, regF src) %{
3128    single_instruction;
3129    dst   : W(write);
3130    src   : E(read);
3131    FA    : R(1);
3132%}
3133
3134// Floating Point Move/Negate/Abs Double
3135pipe_class faddD_reg(regD dst, regD src) %{
3136    single_instruction;
3137    dst   : W(write);
3138    src   : E(read);
3139    FA    : R;
3140%}
3141
3142// Floating Point Convert F->D
3143pipe_class fcvtF2D(regD dst, regF src) %{
3144    single_instruction;
3145    dst   : X(write);
3146    src   : E(read);
3147    FA    : R;
3148%}
3149
3150// Floating Point Convert I->D
3151pipe_class fcvtI2D(regD dst, regF src) %{
3152    single_instruction;
3153    dst   : X(write);
3154    src   : E(read);
3155    FA    : R;
3156%}
3157
3158// Floating Point Convert LHi->D
3159pipe_class fcvtLHi2D(regD dst, regD src) %{
3160    single_instruction;
3161    dst   : X(write);
3162    src   : E(read);
3163    FA    : R;
3164%}
3165
3166// Floating Point Convert L->D
3167pipe_class fcvtL2D(regD dst, iRegL src) %{
3168    single_instruction;
3169    dst   : X(write);
3170    src   : E(read);
3171    FA    : R;
3172%}
3173
3174// Floating Point Convert L->F
3175pipe_class fcvtL2F(regF dst, iRegL src) %{
3176    single_instruction;
3177    dst   : X(write);
3178    src   : E(read);
3179    FA    : R;
3180%}
3181
3182// Floating Point Convert D->F
3183pipe_class fcvtD2F(regD dst, regF src) %{
3184    single_instruction;
3185    dst   : X(write);
3186    src   : E(read);
3187    FA    : R;
3188%}
3189
3190// Floating Point Convert I->L
3191pipe_class fcvtI2L(regD dst, regF src) %{
3192    single_instruction;
3193    dst   : X(write);
3194    src   : E(read);
3195    FA    : R;
3196%}
3197
3198// Floating Point Convert D->F
3199pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{
3200    instruction_count(1); multiple_bundles;
3201    dst   : X(write)+6;
3202    src   : E(read);
3203    FA    : R;
3204%}
3205
3206// Floating Point Convert D->L
3207pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{
3208    instruction_count(1); multiple_bundles;
3209    dst   : X(write)+6;
3210    src   : E(read);
3211    FA    : R;
3212%}
3213
3214// Floating Point Convert F->I
3215pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{
3216    instruction_count(1); multiple_bundles;
3217    dst   : X(write)+6;
3218    src   : E(read);
3219    FA    : R;
3220%}
3221
3222// Floating Point Convert F->L
3223pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{
3224    instruction_count(1); multiple_bundles;
3225    dst   : X(write)+6;
3226    src   : E(read);
3227    FA    : R;
3228%}
3229
3230// Floating Point Convert I->F
3231pipe_class fcvtI2F(regF dst, regF src) %{
3232    single_instruction;
3233    dst   : X(write);
3234    src   : E(read);
3235    FA    : R;
3236%}
3237
3238// Floating Point Compare
3239pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{
3240    single_instruction;
3241    cr    : X(write);
3242    src1  : E(read);
3243    src2  : E(read);
3244    FA    : R;
3245%}
3246
3247// Floating Point Compare
3248pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{
3249    single_instruction;
3250    cr    : X(write);
3251    src1  : E(read);
3252    src2  : E(read);
3253    FA    : R;
3254%}
3255
3256// Floating Add Nop
3257pipe_class fadd_nop() %{
3258    single_instruction;
3259    FA  : R;
3260%}
3261
3262// Integer Store to Memory
3263pipe_class istore_mem_reg(memoryI mem, iRegI src) %{
3264    single_instruction;
3265    mem   : R(read);
3266    src   : C(read);
3267    MS    : R;
3268%}
3269
3270// Integer Store to Memory
3271pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{
3272    single_instruction;
3273    mem   : R(read);
3274    src   : C(read);
3275    MS    : R;
3276%}
3277
3278// Float Store
3279pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{
3280    single_instruction;
3281    mem : R(read);
3282    src : C(read);
3283    MS  : R;
3284%}
3285
3286// Float Store
3287pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{
3288    single_instruction;
3289    mem : R(read);
3290    MS  : R;
3291%}
3292
3293// Double Store
3294pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{
3295    instruction_count(1);
3296    mem : R(read);
3297    src : C(read);
3298    MS  : R;
3299%}
3300
3301// Double Store
3302pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{
3303    single_instruction;
3304    mem : R(read);
3305    MS  : R;
3306%}
3307
3308// Integer Load (when sign bit propagation not needed)
3309pipe_class iload_mem(iRegI dst, memoryI mem) %{
3310    single_instruction;
3311    mem : R(read);
3312    dst : C(write);
3313    MS  : R;
3314%}
3315
3316// Integer Load (when sign bit propagation or masking is needed)
3317pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{
3318    single_instruction;
3319    mem : R(read);
3320    dst : M(write);
3321    MS  : R;
3322%}
3323
3324// Float Load
3325pipe_class floadF_mem(regF dst, memoryF mem) %{
3326    single_instruction;
3327    mem : R(read);
3328    dst : M(write);
3329    MS  : R;
3330%}
3331
3332// Float Load
3333pipe_class floadD_mem(regD dst, memoryD mem) %{
3334    instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case
3335    mem : R(read);
3336    dst : M(write);
3337    MS  : R;
3338%}
3339
3340// Memory Nop
3341pipe_class mem_nop() %{
3342    single_instruction;
3343    MS  : R;
3344%}
3345
3346pipe_class sethi(iRegP dst, immI src) %{
3347    single_instruction;
3348    dst  : E(write);
3349    IALU : R;
3350%}
3351
3352pipe_class loadPollP(iRegP poll) %{
3353    single_instruction;
3354    poll : R(read);
3355    MS   : R;
3356%}
3357
3358pipe_class br(Universe br, label labl) %{
3359    single_instruction_with_delay_slot;
3360    BR  : R;
3361%}
3362
3363pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
3364    single_instruction_with_delay_slot;
3365    cr    : E(read);
3366    BR    : R;
3367%}
3368
3369pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
3370    single_instruction_with_delay_slot;
3371    op1 : E(read);
3372    BR  : R;
3373    MS  : R;
3374%}
3375
3376pipe_class br_nop() %{
3377    single_instruction;
3378    BR  : R;
3379%}
3380
3381pipe_class simple_call(method meth) %{
3382    instruction_count(2); multiple_bundles; force_serialization;
3383    fixed_latency(100);
3384    BR  : R(1);
3385    MS  : R(1);
3386    A0  : R(1);
3387%}
3388
3389pipe_class compiled_call(method meth) %{
3390    instruction_count(1); multiple_bundles; force_serialization;
3391    fixed_latency(100);
3392    MS  : R(1);
3393%}
3394
3395pipe_class call(method meth) %{
3396    instruction_count(0); multiple_bundles; force_serialization;
3397    fixed_latency(100);
3398%}
3399
3400pipe_class tail_call(Universe ignore, label labl) %{
3401    single_instruction; has_delay_slot;
3402    fixed_latency(100);
3403    BR  : R(1);
3404    MS  : R(1);
3405%}
3406
3407pipe_class ret(Universe ignore) %{
3408    single_instruction; has_delay_slot;
3409    BR  : R(1);
3410    MS  : R(1);
3411%}
3412
3413// The real do-nothing guy
3414pipe_class empty( ) %{
3415    instruction_count(0);
3416%}
3417
3418pipe_class long_memory_op() %{
3419    instruction_count(0); multiple_bundles; force_serialization;
3420    fixed_latency(25);
3421    MS  : R(1);
3422%}
3423
3424// Check-cast
3425pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{
3426    array : R(read);
3427    match  : R(read);
3428    IALU   : R(2);
3429    BR     : R(2);
3430    MS     : R;
3431%}
3432
3433// Convert FPU flags into +1,0,-1
3434pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{
3435    src1  : E(read);
3436    src2  : E(read);
3437    dst   : E(write);
3438    FA    : R;
3439    MS    : R(2);
3440    BR    : R(2);
3441%}
3442
3443// Compare for p < q, and conditionally add y
3444pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
3445    p     : E(read);
3446    q     : E(read);
3447    y     : E(read);
3448    IALU  : R(3)
3449%}
3450
3451// Perform a compare, then move conditionally in a branch delay slot.
3452pipe_class min_max( iRegI src2, iRegI srcdst ) %{
3453    src2   : E(read);
3454    srcdst : E(read);
3455    IALU   : R;
3456    BR     : R;
3457%}
3458
3459// Define the class for the Nop node
3460define %{
3461   MachNop = ialu_nop;
3462%}
3463
3464%}
3465
3466//----------INSTRUCTIONS-------------------------------------------------------
3467
3468//------------Special Nop instructions for bundling - no match rules-----------
3469// Nop using the A0 functional unit
3470instruct Nop_A0() %{
3471  ins_pipe(ialu_nop_A0);
3472%}
3473
3474// Nop using the A1 functional unit
3475instruct Nop_A1( ) %{
3476  ins_pipe(ialu_nop_A1);
3477%}
3478
3479// Nop using the memory functional unit
3480instruct Nop_MS( ) %{
3481  ins_pipe(mem_nop);
3482%}
3483
3484// Nop using the floating add functional unit
3485instruct Nop_FA( ) %{
3486  ins_pipe(fadd_nop);
3487%}
3488
3489// Nop using the branch functional unit
3490instruct Nop_BR( ) %{
3491  ins_pipe(br_nop);
3492%}
3493
3494//----------Load/Store/Move Instructions---------------------------------------
3495//----------Load Instructions--------------------------------------------------
3496// Load Byte (8bit signed)
3497instruct loadB(iRegI dst, memoryB mem) %{
3498  match(Set dst (LoadB mem));
3499  ins_cost(MEMORY_REF_COST);
3500
3501  size(4);
3502  format %{ "LDRSB   $dst,$mem\t! byte -> int" %}
3503  ins_encode %{
3504    __ ldrsb($dst$$Register, $mem$$Address);
3505  %}
3506  ins_pipe(iload_mask_mem);
3507%}
3508
3509// Load Byte (8bit signed) into a Long Register
3510instruct loadB2L(iRegL dst, memoryB mem) %{
3511  match(Set dst (ConvI2L (LoadB mem)));
3512  ins_cost(MEMORY_REF_COST);
3513
3514  size(8);
3515  format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t"
3516            "ASR   $dst.hi,$dst.lo,31" %}
3517  ins_encode %{
3518    __ ldrsb($dst$$Register, $mem$$Address);
3519    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3520  %}
3521  ins_pipe(iload_mask_mem);
3522%}
3523
3524// Load Unsigned Byte (8bit UNsigned) into an int reg
3525instruct loadUB(iRegI dst, memoryB mem) %{
3526  match(Set dst (LoadUB mem));
3527  ins_cost(MEMORY_REF_COST);
3528
3529  size(4);
3530  format %{ "LDRB   $dst,$mem\t! ubyte -> int" %}
3531  ins_encode %{
3532    __ ldrb($dst$$Register, $mem$$Address);
3533  %}
3534  ins_pipe(iload_mem);
3535%}
3536
3537// Load Unsigned Byte (8bit UNsigned) into a Long Register
3538instruct loadUB2L(iRegL dst, memoryB mem) %{
3539  match(Set dst (ConvI2L (LoadUB mem)));
3540  ins_cost(MEMORY_REF_COST);
3541
3542  size(8);
3543  format %{ "LDRB  $dst.lo,$mem\t! ubyte -> long\n\t"
3544            "MOV   $dst.hi,0" %}
3545  ins_encode %{
3546    __ ldrb($dst$$Register, $mem$$Address);
3547    __ mov($dst$$Register->successor(), 0);
3548  %}
3549  ins_pipe(iload_mem);
3550%}
3551
3552// Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register
3553instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{
3554  match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
3555
3556  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3557  size(12);
3558  format %{ "LDRB  $dst.lo,$mem\t! ubyte -> long\n\t"
3559            "MOV   $dst.hi,0\n\t"
3560            "AND  $dst.lo,$dst.lo,$mask" %}
3561  ins_encode %{
3562    __ ldrb($dst$$Register, $mem$$Address);
3563    __ mov($dst$$Register->successor(), 0);
3564    __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
3565  %}
3566  ins_pipe(iload_mem);
3567%}
3568
3569// Load Short (16bit signed)
3570
3571instruct loadS(iRegI dst, memoryS mem) %{
3572  match(Set dst (LoadS mem));
3573  ins_cost(MEMORY_REF_COST);
3574
3575  size(4);
3576  format %{ "LDRSH   $dst,$mem\t! short" %}
3577  ins_encode %{
3578    __ ldrsh($dst$$Register, $mem$$Address);
3579  %}
3580  ins_pipe(iload_mask_mem);
3581%}
3582
3583// Load Short (16 bit signed) to Byte (8 bit signed)
3584instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3585  match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
3586  ins_cost(MEMORY_REF_COST);
3587
3588  size(4);
3589
3590  format %{ "LDRSB   $dst,$mem\t! short -> byte" %}
3591  ins_encode %{
3592    __ ldrsb($dst$$Register, $mem$$Address);
3593  %}
3594  ins_pipe(iload_mask_mem);
3595%}
3596
3597// Load Short (16bit signed) into a Long Register
3598instruct loadS2L(iRegL dst, memoryS mem) %{
3599  match(Set dst (ConvI2L (LoadS mem)));
3600  ins_cost(MEMORY_REF_COST);
3601
3602  size(8);
3603  format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t"
3604            "ASR   $dst.hi,$dst.lo,31" %}
3605  ins_encode %{
3606    __ ldrsh($dst$$Register, $mem$$Address);
3607    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3608  %}
3609  ins_pipe(iload_mask_mem);
3610%}
3611
3612// Load Unsigned Short/Char (16bit UNsigned)
3613
3614
3615instruct loadUS(iRegI dst, memoryS mem) %{
3616  match(Set dst (LoadUS mem));
3617  ins_cost(MEMORY_REF_COST);
3618
3619  size(4);
3620  format %{ "LDRH   $dst,$mem\t! ushort/char" %}
3621  ins_encode %{
3622    __ ldrh($dst$$Register, $mem$$Address);
3623  %}
3624  ins_pipe(iload_mem);
3625%}
3626
3627// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
3628instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{
3629  match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
3630  ins_cost(MEMORY_REF_COST);
3631
3632  size(4);
3633  format %{ "LDRSB   $dst,$mem\t! ushort -> byte" %}
3634  ins_encode %{
3635    __ ldrsb($dst$$Register, $mem$$Address);
3636  %}
3637  ins_pipe(iload_mask_mem);
3638%}
3639
3640// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
3641instruct loadUS2L(iRegL dst, memoryS mem) %{
3642  match(Set dst (ConvI2L (LoadUS mem)));
3643  ins_cost(MEMORY_REF_COST);
3644
3645  size(8);
3646  format %{ "LDRH  $dst.lo,$mem\t! short -> long\n\t"
3647            "MOV   $dst.hi, 0" %}
3648  ins_encode %{
3649    __ ldrh($dst$$Register, $mem$$Address);
3650    __ mov($dst$$Register->successor(), 0);
3651  %}
3652  ins_pipe(iload_mem);
3653%}
3654
3655// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register
3656instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3657  match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3658  ins_cost(MEMORY_REF_COST);
3659
3660  size(8);
3661  format %{ "LDRB  $dst.lo,$mem\t! \n\t"
3662            "MOV   $dst.hi, 0" %}
3663  ins_encode %{
3664    __ ldrb($dst$$Register, $mem$$Address);
3665    __ mov($dst$$Register->successor(), 0);
3666  %}
3667  ins_pipe(iload_mem);
3668%}
3669
3670// Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register
3671instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{
3672  match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3673  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3674
3675  size(12);
3676  format %{ "LDRH   $dst,$mem\t! ushort/char & mask -> long\n\t"
3677            "MOV    $dst.hi, 0\n\t"
3678            "AND    $dst,$dst,$mask" %}
3679  ins_encode %{
3680    __ ldrh($dst$$Register, $mem$$Address);
3681    __ mov($dst$$Register->successor(), 0);
3682    __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3683  %}
3684  ins_pipe(iload_mem);
3685%}
3686
3687// Load Integer
3688
3689
3690instruct loadI(iRegI dst, memoryI mem) %{
3691  match(Set dst (LoadI mem));
3692  ins_cost(MEMORY_REF_COST);
3693
3694  size(4);
3695  format %{ "ldr_s32 $dst,$mem\t! int" %}
3696  ins_encode %{
3697    __ ldr_s32($dst$$Register, $mem$$Address);
3698  %}
3699  ins_pipe(iload_mem);
3700%}
3701
3702// Load Integer to Byte (8 bit signed)
3703instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3704  match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
3705  ins_cost(MEMORY_REF_COST);
3706
3707  size(4);
3708
3709  format %{ "LDRSB   $dst,$mem\t! int -> byte" %}
3710  ins_encode %{
3711    __ ldrsb($dst$$Register, $mem$$Address);
3712  %}
3713  ins_pipe(iload_mask_mem);
3714%}
3715
3716// Load Integer to Unsigned Byte (8 bit UNsigned)
3717instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{
3718  match(Set dst (AndI (LoadI mem) mask));
3719  ins_cost(MEMORY_REF_COST);
3720
3721  size(4);
3722
3723  format %{ "LDRB   $dst,$mem\t! int -> ubyte" %}
3724  ins_encode %{
3725    __ ldrb($dst$$Register, $mem$$Address);
3726  %}
3727  ins_pipe(iload_mask_mem);
3728%}
3729
3730// Load Integer to Short (16 bit signed)
3731instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{
3732  match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
3733  ins_cost(MEMORY_REF_COST);
3734
3735  size(4);
3736  format %{ "LDRSH   $dst,$mem\t! int -> short" %}
3737  ins_encode %{
3738    __ ldrsh($dst$$Register, $mem$$Address);
3739  %}
3740  ins_pipe(iload_mask_mem);
3741%}
3742
3743// Load Integer to Unsigned Short (16 bit UNsigned)
3744instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{
3745  match(Set dst (AndI (LoadI mem) mask));
3746  ins_cost(MEMORY_REF_COST);
3747
3748  size(4);
3749  format %{ "LDRH   $dst,$mem\t! int -> ushort/char" %}
3750  ins_encode %{
3751    __ ldrh($dst$$Register, $mem$$Address);
3752  %}
3753  ins_pipe(iload_mask_mem);
3754%}
3755
3756// Load Integer into a Long Register
3757instruct loadI2L(iRegL dst, memoryI mem) %{
3758  match(Set dst (ConvI2L (LoadI mem)));
3759  ins_cost(MEMORY_REF_COST);
3760
3761  size(8);
3762  format %{ "LDR   $dst.lo,$mem\t! int -> long\n\t"
3763            "ASR   $dst.hi,$dst.lo,31\t! int->long" %}
3764  ins_encode %{
3765    __ ldr($dst$$Register, $mem$$Address);
3766    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3767  %}
3768  ins_pipe(iload_mask_mem);
3769%}
3770
3771// Load Integer with mask 0xFF into a Long Register
3772instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3773  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3774  ins_cost(MEMORY_REF_COST);
3775
3776  size(8);
3777  format %{ "LDRB   $dst.lo,$mem\t! int & 0xFF -> long\n\t"
3778            "MOV    $dst.hi, 0" %}
3779  ins_encode %{
3780    __ ldrb($dst$$Register, $mem$$Address);
3781    __ mov($dst$$Register->successor(), 0);
3782  %}
3783  ins_pipe(iload_mem);
3784%}
3785
3786// Load Integer with mask 0xFFFF into a Long Register
3787instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{
3788  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3789  ins_cost(MEMORY_REF_COST);
3790
3791  size(8);
3792  format %{ "LDRH   $dst,$mem\t! int & 0xFFFF -> long\n\t"
3793            "MOV    $dst.hi, 0" %}
3794  ins_encode %{
3795    __ ldrh($dst$$Register, $mem$$Address);
3796    __ mov($dst$$Register->successor(), 0);
3797  %}
3798  ins_pipe(iload_mask_mem);
3799%}
3800
3801// Load Integer with a 31-bit immediate mask into a Long Register
3802instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{
3803  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3804  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3805
3806  size(12);
3807  format %{ "LDR   $dst.lo,$mem\t! int -> long\n\t"
3808            "MOV    $dst.hi, 0\n\t"
3809            "AND   $dst,$dst,$mask" %}
3810
3811  ins_encode %{
3812    __ ldr($dst$$Register, $mem$$Address);
3813    __ mov($dst$$Register->successor(), 0);
3814    __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3815  %}
3816  ins_pipe(iload_mem);
3817%}
3818
3819// Load Integer with a 31-bit mask into a Long Register
3820// FIXME: use iRegI mask, remove tmp?
3821instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{
3822  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3823  effect(TEMP dst, TEMP tmp);
3824
3825  ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST);
3826  size(20);
3827  format %{ "LDR      $mem,$dst\t! int & 31-bit mask -> long\n\t"
3828            "MOV      $dst.hi, 0\n\t"
3829            "MOV_SLOW $tmp,$mask\n\t"
3830            "AND      $dst,$tmp,$dst" %}
3831  ins_encode %{
3832    __ ldr($dst$$Register, $mem$$Address);
3833    __ mov($dst$$Register->successor(), 0);
3834    __ mov_slow($tmp$$Register, $mask$$constant);
3835    __ andr($dst$$Register, $dst$$Register, $tmp$$Register);
3836  %}
3837  ins_pipe(iload_mem);
3838%}
3839
3840// Load Unsigned Integer into a Long Register
3841instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{
3842  match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
3843  ins_cost(MEMORY_REF_COST);
3844
3845  size(8);
3846  format %{ "LDR   $dst.lo,$mem\t! uint -> long\n\t"
3847            "MOV   $dst.hi,0" %}
3848  ins_encode %{
3849    __ ldr($dst$$Register, $mem$$Address);
3850    __ mov($dst$$Register->successor(), 0);
3851  %}
3852  ins_pipe(iload_mem);
3853%}
3854
3855// Load Long
3856
3857
3858instruct loadL(iRegLd dst, memoryL mem ) %{
3859  predicate(!((LoadLNode*)n)->require_atomic_access());
3860  match(Set dst (LoadL mem));
3861  effect(TEMP dst);
3862  ins_cost(MEMORY_REF_COST);
3863
3864  size(4);
3865  format %{ "ldr_64  $dst,$mem\t! long" %}
3866  ins_encode %{
3867    __ ldr_64($dst$$Register, $mem$$Address);
3868  %}
3869  ins_pipe(iload_mem);
3870%}
3871
3872instruct loadL_2instr(iRegL dst, memorylong mem ) %{
3873  predicate(!((LoadLNode*)n)->require_atomic_access());
3874  match(Set dst (LoadL mem));
3875  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
3876
3877  size(8);
3878  format %{ "LDR    $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3879            "LDR    $dst.hi,$mem+4 or $mem" %}
3880  ins_encode %{
3881    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3882    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3883
3884    if ($dst$$Register == reg_to_register_object($mem$$base)) {
3885      __ ldr($dst$$Register->successor(), Amemhi);
3886      __ ldr($dst$$Register, Amemlo);
3887    } else {
3888      __ ldr($dst$$Register, Amemlo);
3889      __ ldr($dst$$Register->successor(), Amemhi);
3890    }
3891  %}
3892  ins_pipe(iload_mem);
3893%}
3894
3895instruct loadL_volatile(iRegL dst, indirect mem ) %{
3896  predicate(((LoadLNode*)n)->require_atomic_access());
3897  match(Set dst (LoadL mem));
3898  ins_cost(MEMORY_REF_COST);
3899
3900  size(4);
3901  format %{ "LDMIA    $dst,$mem\t! long" %}
3902  ins_encode %{
3903    // FIXME: why is ldmia considered atomic?  Should be ldrexd
3904    RegisterSet set($dst$$Register);
3905    set = set | reg_to_register_object($dst$$reg + 1);
3906    __ ldmia(reg_to_register_object($mem$$base), set);
3907  %}
3908  ins_pipe(iload_mem);
3909%}
3910
3911instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{
3912  predicate(((LoadLNode*)n)->require_atomic_access());
3913  match(Set dst (LoadL mem));
3914  ins_cost(MEMORY_REF_COST);
3915
3916  size(8);
3917  format %{ "FLDD      S14, $mem"
3918            "FMRRD    $dst, S14\t! long \n't" %}
3919  ins_encode %{
3920    __ fldd(S14, $mem$$Address);
3921    __ fmrrd($dst$$Register, $dst$$Register->successor(), S14);
3922  %}
3923  ins_pipe(iload_mem);
3924%}
3925
3926instruct loadL_unaligned(iRegL dst, memorylong mem ) %{
3927  match(Set dst (LoadL_unaligned mem));
3928  ins_cost(MEMORY_REF_COST);
3929
3930  size(8);
3931  format %{ "LDR    $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3932            "LDR    $dst.hi,$mem+4" %}
3933  ins_encode %{
3934    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3935    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3936
3937    if ($dst$$Register == reg_to_register_object($mem$$base)) {
3938      __ ldr($dst$$Register->successor(), Amemhi);
3939      __ ldr($dst$$Register, Amemlo);
3940    } else {
3941      __ ldr($dst$$Register, Amemlo);
3942      __ ldr($dst$$Register->successor(), Amemhi);
3943    }
3944  %}
3945  ins_pipe(iload_mem);
3946%}
3947
3948// Load Range
3949instruct loadRange(iRegI dst, memoryI mem) %{
3950  match(Set dst (LoadRange mem));
3951  ins_cost(MEMORY_REF_COST);
3952
3953  size(4);
3954  format %{ "LDR_u32 $dst,$mem\t! range" %}
3955  ins_encode %{
3956    __ ldr_u32($dst$$Register, $mem$$Address);
3957  %}
3958  ins_pipe(iload_mem);
3959%}
3960
3961// Load Pointer
3962
3963
3964instruct loadP(iRegP dst, memoryP mem) %{
3965  match(Set dst (LoadP mem));
3966  ins_cost(MEMORY_REF_COST);
3967  size(4);
3968
3969  format %{ "LDR   $dst,$mem\t! ptr" %}
3970  ins_encode %{
3971    __ ldr($dst$$Register, $mem$$Address);
3972  %}
3973  ins_pipe(iload_mem);
3974%}
3975
3976#ifdef XXX
3977// FIXME XXXX
3978//instruct loadSP(iRegP dst, memoryP mem) %{
3979instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{
3980  match(Set dst (LoadP mem));
3981  effect(TEMP tmp);
3982  ins_cost(MEMORY_REF_COST+1);
3983  size(8);
3984
3985  format %{ "LDR   $tmp,$mem\t! ptr\n\t"
3986            "MOV   $dst,$tmp\t! ptr" %}
3987  ins_encode %{
3988    __ ldr($tmp$$Register, $mem$$Address);
3989    __ mov($dst$$Register, $tmp$$Register);
3990  %}
3991  ins_pipe(iload_mem);
3992%}
3993#endif
3994
3995#ifdef _LP64
3996// Load Compressed Pointer
3997
3998// XXX This variant shouldn't be necessary if 6217251 is implemented
3999instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
4000  match(Set dst (LoadN (AddP mem off)));
4001  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
4002  effect(TEMP tmp);
4003  size(4 * 2);
4004
4005  format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %}
4006  ins_encode %{
4007    Register base = reg_to_register_object($mem$$base);
4008    __ add($tmp$$Register, base, $off$$constant);
4009    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4010    __ ldr_u32($dst$$Register, nmem);
4011  %}
4012  ins_pipe(iload_mem);
4013%}
4014
4015instruct loadN(iRegN dst, memoryI mem) %{
4016  match(Set dst (LoadN mem));
4017  ins_cost(MEMORY_REF_COST);
4018  size(4);
4019
4020  format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %}
4021  ins_encode %{
4022    __ ldr_u32($dst$$Register, $mem$$Address);
4023  %}
4024  ins_pipe(iload_mem);
4025%}
4026#endif
4027
4028// Load Klass Pointer
4029instruct loadKlass(iRegP dst, memoryI mem) %{
4030  match(Set dst (LoadKlass mem));
4031  ins_cost(MEMORY_REF_COST);
4032  size(4);
4033
4034  format %{ "LDR   $dst,$mem\t! klass ptr" %}
4035  ins_encode %{
4036    __ ldr($dst$$Register, $mem$$Address);
4037  %}
4038  ins_pipe(iload_mem);
4039%}
4040
4041#ifdef _LP64
4042// Load narrow Klass Pointer
4043instruct loadNKlass(iRegN dst, memoryI mem) %{
4044  match(Set dst (LoadNKlass mem));
4045  ins_cost(MEMORY_REF_COST);
4046  size(4);
4047
4048  format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %}
4049  ins_encode %{
4050    __ ldr_u32($dst$$Register, $mem$$Address);
4051  %}
4052  ins_pipe(iload_mem);
4053%}
4054#endif
4055
4056
4057instruct loadD(regD dst, memoryD mem) %{
4058  match(Set dst (LoadD mem));
4059  ins_cost(MEMORY_REF_COST);
4060
4061  size(4);
4062  // FIXME: needs to be atomic, but  ARMv7 A.R.M. guarantees
4063  // only LDREXD and STREXD are 64-bit single-copy atomic
4064  format %{ "FLDD   $dst,$mem" %}
4065  ins_encode %{
4066    __ ldr_double($dst$$FloatRegister, $mem$$Address);
4067  %}
4068  ins_pipe(floadD_mem);
4069%}
4070
4071// Load Double - UNaligned
4072instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{
4073  match(Set dst (LoadD_unaligned mem));
4074  ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
4075  size(8);
4076  format %{ "FLDS    $dst.lo,$mem\t! misaligned double\n"
4077          "\tFLDS    $dst.hi,$mem+4\t!" %}
4078  ins_encode %{
4079    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4080    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4081      __ flds($dst$$FloatRegister, Amemlo);
4082      __ flds($dst$$FloatRegister->successor(), Amemhi);
4083  %}
4084  ins_pipe(iload_mem);
4085%}
4086
4087
4088instruct loadF(regF dst, memoryF mem) %{
4089  match(Set dst (LoadF mem));
4090
4091  ins_cost(MEMORY_REF_COST);
4092  size(4);
4093  format %{ "FLDS    $dst,$mem" %}
4094  ins_encode %{
4095    __ ldr_float($dst$$FloatRegister, $mem$$Address);
4096  %}
4097  ins_pipe(floadF_mem);
4098%}
4099
4100
4101// // Load Constant
4102instruct loadConI( iRegI dst, immI src ) %{
4103  match(Set dst src);
4104  ins_cost(DEFAULT_COST * 3/2);
4105  format %{ "MOV_SLOW    $dst, $src" %}
4106  ins_encode %{
4107    __ mov_slow($dst$$Register, $src$$constant);
4108  %}
4109  ins_pipe(ialu_hi_lo_reg);
4110%}
4111
4112instruct loadConIMov( iRegI dst, immIMov src ) %{
4113  match(Set dst src);
4114  size(4);
4115  format %{ "MOV    $dst, $src" %}
4116  ins_encode %{
4117    __ mov($dst$$Register, $src$$constant);
4118  %}
4119  ins_pipe(ialu_imm);
4120%}
4121
4122instruct loadConIMovn( iRegI dst, immIRotn src ) %{
4123  match(Set dst src);
4124  size(4);
4125  format %{ "MVN    $dst, ~$src" %}
4126  ins_encode %{
4127    __ mvn($dst$$Register, ~$src$$constant);
4128  %}
4129  ins_pipe(ialu_imm_n);
4130%}
4131
4132instruct loadConI16( iRegI dst, immI16 src ) %{
4133  match(Set dst src);
4134  size(4);
4135  format %{ "MOVW    $dst, $src" %}
4136  ins_encode %{
4137    __ movw($dst$$Register, $src$$constant);
4138  %}
4139  ins_pipe(ialu_imm_n);
4140%}
4141
4142instruct loadConP(iRegP dst, immP src) %{
4143  match(Set dst src);
4144  ins_cost(DEFAULT_COST * 3/2);
4145  format %{ "MOV_SLOW    $dst,$src\t!ptr" %}
4146  ins_encode %{
4147    relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc();
4148    intptr_t val = $src$$constant;
4149    if (constant_reloc == relocInfo::oop_type) {
4150      __ mov_oop($dst$$Register, (jobject)val);
4151    } else if (constant_reloc == relocInfo::metadata_type) {
4152      __ mov_metadata($dst$$Register, (Metadata*)val);
4153    } else {
4154      __ mov_slow($dst$$Register, val);
4155    }
4156  %}
4157  ins_pipe(loadConP);
4158%}
4159
4160
4161instruct loadConL(iRegL dst, immL src) %{
4162  match(Set dst src);
4163  ins_cost(DEFAULT_COST * 4);
4164  format %{ "MOV_SLOW   $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t"
4165            "MOV_SLOW   $dst.hi, $src >> 32" %}
4166  ins_encode %{
4167    __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL);
4168    __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32);
4169  %}
4170  ins_pipe(loadConL);
4171%}
4172
4173instruct loadConL16( iRegL dst, immL16 src ) %{
4174  match(Set dst src);
4175  ins_cost(DEFAULT_COST * 2);
4176
4177  size(8);
4178  format %{ "MOVW    $dst.lo, $src \n\t"
4179            "MOVW    $dst.hi, 0 \n\t" %}
4180  ins_encode %{
4181    __ movw($dst$$Register, $src$$constant);
4182    __ movw($dst$$Register->successor(), 0);
4183  %}
4184  ins_pipe(ialu_imm);
4185%}
4186
4187instruct loadConF_imm8(regF dst, imm8F src) %{
4188  match(Set dst src);
4189  ins_cost(DEFAULT_COST);
4190  size(4);
4191
4192  format %{ "FCONSTS      $dst, $src"%}
4193
4194  ins_encode %{
4195    __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8());
4196  %}
4197  ins_pipe(loadConFD); // FIXME
4198%}
4199
4200
4201instruct loadConF(regF dst, immF src, iRegI tmp) %{
4202  match(Set dst src);
4203  ins_cost(DEFAULT_COST * 2);
4204  effect(TEMP tmp);
4205  size(3*4);
4206
4207  format %{ "MOV_SLOW  $tmp, $src\n\t"
4208            "FMSR      $dst, $tmp"%}
4209
4210  ins_encode %{
4211    // FIXME revisit once 6961697 is in
4212    union {
4213      jfloat f;
4214      int i;
4215    } v;
4216    v.f = $src$$constant;
4217    __ mov_slow($tmp$$Register, v.i);
4218    __ fmsr($dst$$FloatRegister, $tmp$$Register);
4219  %}
4220  ins_pipe(loadConFD); // FIXME
4221%}
4222
4223instruct loadConD_imm8(regD dst, imm8D src) %{
4224  match(Set dst src);
4225  ins_cost(DEFAULT_COST);
4226  size(4);
4227
4228  format %{ "FCONSTD      $dst, $src"%}
4229
4230  ins_encode %{
4231    __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8());
4232  %}
4233  ins_pipe(loadConFD); // FIXME
4234%}
4235
4236instruct loadConD(regD dst, immD src, iRegP tmp) %{
4237  match(Set dst src);
4238  effect(TEMP tmp);
4239  ins_cost(MEMORY_REF_COST);
4240  format %{ "FLDD  $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %}
4241
4242  ins_encode %{
4243    Register r = $constanttablebase;
4244    int offset  = $constantoffset($src);
4245    if (!is_memoryD(offset)) {                // can't use a predicate
4246                                              // in load constant instructs
4247      __ add_slow($tmp$$Register, r, offset);
4248      r = $tmp$$Register;
4249      offset = 0;
4250    }
4251    __ ldr_double($dst$$FloatRegister, Address(r, offset));
4252  %}
4253  ins_pipe(loadConFD);
4254%}
4255
4256// Prefetch instructions.
4257// Must be safe to execute with invalid address (cannot fault).
4258
4259instruct prefetchAlloc_mp( memoryP mem ) %{
4260  predicate(VM_Version::has_multiprocessing_extensions());
4261  match( PrefetchAllocation mem );
4262  ins_cost(MEMORY_REF_COST);
4263  size(4);
4264
4265  format %{ "PLDW $mem\t! Prefetch allocation" %}
4266  ins_encode %{
4267    __ pldw($mem$$Address);
4268  %}
4269  ins_pipe(iload_mem);
4270%}
4271
4272instruct prefetchAlloc_sp( memoryP mem ) %{
4273  predicate(!VM_Version::has_multiprocessing_extensions());
4274  match( PrefetchAllocation mem );
4275  ins_cost(MEMORY_REF_COST);
4276  size(4);
4277
4278  format %{ "PLD $mem\t! Prefetch allocation" %}
4279  ins_encode %{
4280    __ pld($mem$$Address);
4281  %}
4282  ins_pipe(iload_mem);
4283%}
4284
4285
4286//----------Store Instructions-------------------------------------------------
4287// Store Byte
4288instruct storeB(memoryB mem, store_RegI src) %{
4289  match(Set mem (StoreB mem src));
4290  ins_cost(MEMORY_REF_COST);
4291
4292  size(4);
4293  format %{ "STRB    $src,$mem\t! byte" %}
4294  ins_encode %{
4295    __ strb($src$$Register, $mem$$Address);
4296  %}
4297  ins_pipe(istore_mem_reg);
4298%}
4299
4300instruct storeCM(memoryB mem, store_RegI src) %{
4301  match(Set mem (StoreCM mem src));
4302  ins_cost(MEMORY_REF_COST);
4303
4304  size(4);
4305  format %{ "STRB    $src,$mem\t! CMS card-mark byte" %}
4306  ins_encode %{
4307    __ strb($src$$Register, $mem$$Address);
4308  %}
4309  ins_pipe(istore_mem_reg);
4310%}
4311
4312// Store Char/Short
4313
4314
4315instruct storeC(memoryS mem, store_RegI src) %{
4316  match(Set mem (StoreC mem src));
4317  ins_cost(MEMORY_REF_COST);
4318
4319  size(4);
4320  format %{ "STRH    $src,$mem\t! short" %}
4321  ins_encode %{
4322    __ strh($src$$Register, $mem$$Address);
4323  %}
4324  ins_pipe(istore_mem_reg);
4325%}
4326
4327// Store Integer
4328
4329
4330instruct storeI(memoryI mem, store_RegI src) %{
4331  match(Set mem (StoreI mem src));
4332  ins_cost(MEMORY_REF_COST);
4333
4334  size(4);
4335  format %{ "str_32 $src,$mem" %}
4336  ins_encode %{
4337    __ str_32($src$$Register, $mem$$Address);
4338  %}
4339  ins_pipe(istore_mem_reg);
4340%}
4341
4342// Store Long
4343
4344
4345instruct storeL(memoryL mem, store_RegLd src) %{
4346  predicate(!((StoreLNode*)n)->require_atomic_access());
4347  match(Set mem (StoreL mem src));
4348  ins_cost(MEMORY_REF_COST);
4349
4350  size(4);
4351  format %{ "str_64  $src,$mem\t! long\n\t" %}
4352
4353  ins_encode %{
4354    __ str_64($src$$Register, $mem$$Address);
4355  %}
4356  ins_pipe(istore_mem_reg);
4357%}
4358
4359instruct storeL_2instr(memorylong mem, iRegL src) %{
4360  predicate(!((StoreLNode*)n)->require_atomic_access());
4361  match(Set mem (StoreL mem src));
4362  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4363
4364  size(8);
4365  format %{ "STR    $src.lo,$mem\t! long\n\t"
4366            "STR    $src.hi,$mem+4" %}
4367
4368  ins_encode %{
4369    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4370    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4371    __ str($src$$Register, Amemlo);
4372    __ str($src$$Register->successor(), Amemhi);
4373  %}
4374  ins_pipe(istore_mem_reg);
4375%}
4376
4377instruct storeL_volatile(indirect mem, iRegL src) %{
4378  predicate(((StoreLNode*)n)->require_atomic_access());
4379  match(Set mem (StoreL mem src));
4380  ins_cost(MEMORY_REF_COST);
4381  size(4);
4382  format %{ "STMIA    $src,$mem\t! long" %}
4383  ins_encode %{
4384    // FIXME: why is stmia considered atomic?  Should be strexd
4385    RegisterSet set($src$$Register);
4386    set = set | reg_to_register_object($src$$reg + 1);
4387    __ stmia(reg_to_register_object($mem$$base), set);
4388  %}
4389  ins_pipe(istore_mem_reg);
4390%}
4391
4392instruct storeL_volatile_fp(memoryD mem, iRegL src) %{
4393  predicate(((StoreLNode*)n)->require_atomic_access());
4394  match(Set mem (StoreL mem src));
4395  ins_cost(MEMORY_REF_COST);
4396  size(8);
4397  format %{ "FMDRR    S14, $src\t! long \n\t"
4398            "FSTD     S14, $mem" %}
4399  ins_encode %{
4400    __ fmdrr(S14, $src$$Register, $src$$Register->successor());
4401    __ fstd(S14, $mem$$Address);
4402  %}
4403  ins_pipe(istore_mem_reg);
4404%}
4405
4406#ifdef XXX
4407// Move SP Pointer
4408//instruct movSP(sp_ptr_RegP dst, SPRegP src) %{
4409//instruct movSP(iRegP dst, SPRegP src) %{
4410instruct movSP(store_ptr_RegP dst, SPRegP src) %{
4411  match(Set dst src);
4412//predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
4413  ins_cost(MEMORY_REF_COST);
4414  size(4);
4415
4416  format %{ "MOV    $dst,$src\t! SP ptr\n\t" %}
4417  ins_encode %{
4418    assert(false, "XXX1 got here");
4419    __ mov($dst$$Register, SP);
4420    __ mov($dst$$Register, $src$$Register);
4421  %}
4422  ins_pipe(ialu_reg);
4423%}
4424#endif
4425
4426
4427// Store Pointer
4428
4429
4430instruct storeP(memoryP mem, store_ptr_RegP src) %{
4431  match(Set mem (StoreP mem src));
4432  ins_cost(MEMORY_REF_COST);
4433  size(4);
4434
4435  format %{ "STR    $src,$mem\t! ptr" %}
4436  ins_encode %{
4437    __ str($src$$Register, $mem$$Address);
4438  %}
4439  ins_pipe(istore_mem_spORreg);
4440%}
4441
4442
4443#ifdef _LP64
4444// Store Compressed Pointer
4445
4446
4447instruct storeN(memoryI mem, store_RegN src) %{
4448  match(Set mem (StoreN mem src));
4449  ins_cost(MEMORY_REF_COST);
4450  size(4);
4451
4452  format %{ "str_32 $src,$mem\t! compressed ptr" %}
4453  ins_encode %{
4454    __ str_32($src$$Register, $mem$$Address);
4455  %}
4456  ins_pipe(istore_mem_reg);
4457%}
4458
4459
4460// Store Compressed Klass Pointer
4461instruct storeNKlass(memoryI mem, store_RegN src) %{
4462  match(Set mem (StoreNKlass mem src));
4463  ins_cost(MEMORY_REF_COST);
4464  size(4);
4465
4466  format %{ "str_32 $src,$mem\t! compressed klass ptr" %}
4467  ins_encode %{
4468    __ str_32($src$$Register, $mem$$Address);
4469  %}
4470  ins_pipe(istore_mem_reg);
4471%}
4472#endif
4473
4474// Store Double
4475
4476
4477instruct storeD(memoryD mem, regD src) %{
4478  match(Set mem (StoreD mem src));
4479  ins_cost(MEMORY_REF_COST);
4480
4481  size(4);
4482  // FIXME: needs to be atomic, but  ARMv7 A.R.M. guarantees
4483  // only LDREXD and STREXD are 64-bit single-copy atomic
4484  format %{ "FSTD   $src,$mem" %}
4485  ins_encode %{
4486    __ str_double($src$$FloatRegister, $mem$$Address);
4487  %}
4488  ins_pipe(fstoreD_mem_reg);
4489%}
4490
4491
4492// Store Float
4493
4494
4495instruct storeF( memoryF mem, regF src) %{
4496  match(Set mem (StoreF mem src));
4497  ins_cost(MEMORY_REF_COST);
4498
4499  size(4);
4500  format %{ "FSTS    $src,$mem" %}
4501  ins_encode %{
4502    __ str_float($src$$FloatRegister, $mem$$Address);
4503  %}
4504  ins_pipe(fstoreF_mem_reg);
4505%}
4506
4507
4508//----------MemBar Instructions-----------------------------------------------
4509// Memory barrier flavors
4510
4511// pattern-match out unnecessary membars
4512instruct membar_storestore() %{
4513  match(MemBarStoreStore);
4514  ins_cost(4*MEMORY_REF_COST);
4515
4516  size(4);
4517  format %{ "MEMBAR-storestore" %}
4518  ins_encode %{
4519    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
4520  %}
4521  ins_pipe(long_memory_op);
4522%}
4523
4524instruct membar_acquire() %{
4525  match(MemBarAcquire);
4526  match(LoadFence);
4527  ins_cost(4*MEMORY_REF_COST);
4528
4529  size(4);
4530  format %{ "MEMBAR-acquire" %}
4531  ins_encode %{
4532    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg);
4533  %}
4534  ins_pipe(long_memory_op);
4535%}
4536
4537instruct membar_acquire_lock() %{
4538  match(MemBarAcquireLock);
4539  ins_cost(0);
4540
4541  size(0);
4542  format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %}
4543  ins_encode( );
4544  ins_pipe(empty);
4545%}
4546
4547instruct membar_release() %{
4548  match(MemBarRelease);
4549  match(StoreFence);
4550  ins_cost(4*MEMORY_REF_COST);
4551
4552  size(4);
4553  format %{ "MEMBAR-release" %}
4554  ins_encode %{
4555    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg);
4556  %}
4557  ins_pipe(long_memory_op);
4558%}
4559
4560instruct membar_release_lock() %{
4561  match(MemBarReleaseLock);
4562  ins_cost(0);
4563
4564  size(0);
4565  format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %}
4566  ins_encode( );
4567  ins_pipe(empty);
4568%}
4569
4570instruct membar_volatile() %{
4571  match(MemBarVolatile);
4572  ins_cost(4*MEMORY_REF_COST);
4573
4574  size(4);
4575  format %{ "MEMBAR-volatile" %}
4576  ins_encode %{
4577    __ membar(MacroAssembler::StoreLoad, noreg);
4578  %}
4579  ins_pipe(long_memory_op);
4580%}
4581
4582instruct unnecessary_membar_volatile() %{
4583  match(MemBarVolatile);
4584  predicate(Matcher::post_store_load_barrier(n));
4585  ins_cost(0);
4586
4587  size(0);
4588  format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %}
4589  ins_encode( );
4590  ins_pipe(empty);
4591%}
4592
4593//----------Register Move Instructions-----------------------------------------
4594// instruct roundDouble_nop(regD dst) %{
4595//   match(Set dst (RoundDouble dst));
4596//   ins_pipe(empty);
4597// %}
4598
4599
4600// instruct roundFloat_nop(regF dst) %{
4601//   match(Set dst (RoundFloat dst));
4602//   ins_pipe(empty);
4603// %}
4604
4605
4606
4607// Cast Index to Pointer for unsafe natives
4608instruct castX2P(iRegX src, iRegP dst) %{
4609  match(Set dst (CastX2P src));
4610
4611  format %{ "MOV    $dst,$src\t! IntX->Ptr if $dst != $src" %}
4612  ins_encode %{
4613    if ($dst$$Register !=  $src$$Register) {
4614      __ mov($dst$$Register, $src$$Register);
4615    }
4616  %}
4617  ins_pipe(ialu_reg);
4618%}
4619
4620// Cast Pointer to Index for unsafe natives
4621instruct castP2X(iRegP src, iRegX dst) %{
4622  match(Set dst (CastP2X src));
4623
4624  format %{ "MOV    $dst,$src\t! Ptr->IntX if $dst != $src" %}
4625  ins_encode %{
4626    if ($dst$$Register !=  $src$$Register) {
4627      __ mov($dst$$Register, $src$$Register);
4628    }
4629  %}
4630  ins_pipe(ialu_reg);
4631%}
4632
4633//----------Conditional Move---------------------------------------------------
4634// Conditional move
4635instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{
4636  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4637  ins_cost(150);
4638  size(4);
4639  format %{ "MOV$cmp  $dst,$src\t! int" %}
4640  ins_encode %{
4641    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4642  %}
4643  ins_pipe(ialu_reg);
4644%}
4645
4646
4647instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{
4648  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4649  ins_cost(140);
4650  size(4);
4651  format %{ "MOV$cmp  $dst,$src" %}
4652  ins_encode %{
4653    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4654  %}
4655  ins_pipe(ialu_imm);
4656%}
4657
4658instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{
4659  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4660  ins_cost(140);
4661  size(4);
4662  format %{ "MOVw$cmp  $dst,$src" %}
4663  ins_encode %{
4664    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4665  %}
4666  ins_pipe(ialu_imm);
4667%}
4668
4669instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{
4670  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4671  ins_cost(150);
4672  size(4);
4673  format %{ "MOV$cmp  $dst,$src" %}
4674  ins_encode %{
4675    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4676  %}
4677  ins_pipe(ialu_reg);
4678%}
4679
4680
4681instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{
4682  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4683  ins_cost(140);
4684  size(4);
4685  format %{ "MOV$cmp  $dst,$src" %}
4686  ins_encode %{
4687    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4688  %}
4689  ins_pipe(ialu_imm);
4690%}
4691
4692instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{
4693  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4694  ins_cost(140);
4695  size(4);
4696  format %{ "MOVw$cmp  $dst,$src" %}
4697  ins_encode %{
4698    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4699  %}
4700  ins_pipe(ialu_imm);
4701%}
4702
4703instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{
4704  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4705  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4706            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4707            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4708            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4709  ins_cost(150);
4710  size(4);
4711  format %{ "MOV$cmp  $dst,$src" %}
4712  ins_encode %{
4713    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4714  %}
4715  ins_pipe(ialu_reg);
4716%}
4717
4718instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{
4719  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4720  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4721            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4722            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4723            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4724  ins_cost(140);
4725  size(4);
4726  format %{ "MOV$cmp  $dst,$src" %}
4727  ins_encode %{
4728    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4729  %}
4730  ins_pipe(ialu_imm);
4731%}
4732
4733instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{
4734  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4735  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4736            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4737            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4738            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4739  ins_cost(140);
4740  size(4);
4741  format %{ "MOVW$cmp  $dst,$src" %}
4742  ins_encode %{
4743    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4744  %}
4745  ins_pipe(ialu_imm);
4746%}
4747
4748instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
4749  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4750  ins_cost(150);
4751  size(4);
4752  format %{ "MOV$cmp  $dst,$src" %}
4753  ins_encode %{
4754    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4755  %}
4756  ins_pipe(ialu_reg);
4757%}
4758
4759instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{
4760  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4761  ins_cost(140);
4762  size(4);
4763  format %{ "MOV$cmp  $dst,$src" %}
4764  ins_encode %{
4765    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4766  %}
4767  ins_pipe(ialu_imm);
4768%}
4769
4770instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{
4771  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4772  ins_cost(140);
4773  size(4);
4774  format %{ "MOVW$cmp  $dst,$src" %}
4775  ins_encode %{
4776    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4777  %}
4778  ins_pipe(ialu_imm);
4779%}
4780
4781// Conditional move
4782instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
4783  match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4784  ins_cost(150);
4785  size(4);
4786  format %{ "MOV$cmp  $dst,$src" %}
4787  ins_encode %{
4788    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4789  %}
4790  ins_pipe(ialu_reg);
4791%}
4792
4793instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{
4794  match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4795  ins_cost(140);
4796  size(4);
4797  format %{ "MOV$cmp  $dst,$src" %}
4798  ins_encode %{
4799    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4800  %}
4801  ins_pipe(ialu_imm);
4802%}
4803
4804// This instruction also works with CmpN so we don't need cmovPN_reg.
4805instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
4806  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4807  ins_cost(150);
4808
4809  size(4);
4810  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4811  ins_encode %{
4812    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4813  %}
4814  ins_pipe(ialu_reg);
4815%}
4816
4817instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{
4818  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4819  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4820            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4821            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4822            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4823  ins_cost(150);
4824
4825  size(4);
4826  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4827  ins_encode %{
4828    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4829  %}
4830  ins_pipe(ialu_reg);
4831%}
4832
4833instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
4834  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4835  ins_cost(150);
4836
4837  size(4);
4838  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4839  ins_encode %{
4840    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4841  %}
4842  ins_pipe(ialu_reg);
4843%}
4844
4845instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
4846  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4847  ins_cost(140);
4848
4849  size(4);
4850  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4851  ins_encode %{
4852    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4853  %}
4854  ins_pipe(ialu_imm);
4855%}
4856
4857instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{
4858  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4859  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4860            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4861            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4862            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4863  ins_cost(140);
4864
4865  size(4);
4866  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4867  ins_encode %{
4868    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4869  %}
4870  ins_pipe(ialu_imm);
4871%}
4872
4873instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
4874  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4875  ins_cost(140);
4876
4877  size(4);
4878  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4879  ins_encode %{
4880    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4881  %}
4882  ins_pipe(ialu_imm);
4883%}
4884
4885
4886// Conditional move
4887instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{
4888  match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src)));
4889  ins_cost(150);
4890  size(4);
4891  format %{ "FCPYS$cmp $dst,$src" %}
4892  ins_encode %{
4893    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4894  %}
4895  ins_pipe(int_conditional_float_move);
4896%}
4897
4898instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
4899  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4900  ins_cost(150);
4901
4902  size(4);
4903  format %{ "FCPYS$cmp $dst,$src" %}
4904  ins_encode %{
4905    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4906  %}
4907  ins_pipe(int_conditional_float_move);
4908%}
4909
4910instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{
4911  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4912  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4913            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4914            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4915            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4916  ins_cost(150);
4917
4918  size(4);
4919  format %{ "FCPYS$cmp $dst,$src" %}
4920  ins_encode %{
4921    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4922  %}
4923  ins_pipe(int_conditional_float_move);
4924%}
4925
4926instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
4927  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4928  ins_cost(150);
4929
4930  size(4);
4931  format %{ "FCPYS$cmp $dst,$src" %}
4932  ins_encode %{
4933    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4934  %}
4935  ins_pipe(int_conditional_float_move);
4936%}
4937
4938// Conditional move
4939instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{
4940  match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src)));
4941  ins_cost(150);
4942  size(4);
4943  format %{ "FCPYD$cmp $dst,$src" %}
4944  ins_encode %{
4945    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4946  %}
4947  ins_pipe(int_conditional_double_move);
4948%}
4949
4950instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
4951  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4952  ins_cost(150);
4953
4954  size(4);
4955  format %{ "FCPYD$cmp $dst,$src" %}
4956  ins_encode %{
4957    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4958  %}
4959  ins_pipe(int_conditional_double_move);
4960%}
4961
4962instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{
4963  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4964  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);
4965  ins_cost(150);
4966
4967  size(4);
4968  format %{ "FCPYD$cmp $dst,$src" %}
4969  ins_encode %{
4970    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4971  %}
4972  ins_pipe(int_conditional_double_move);
4973%}
4974
4975instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
4976  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4977  ins_cost(150);
4978
4979  size(4);
4980  format %{ "FCPYD$cmp $dst,$src" %}
4981  ins_encode %{
4982    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4983  %}
4984  ins_pipe(int_conditional_double_move);
4985%}
4986
4987// Conditional move
4988instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{
4989  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4990  ins_cost(150);
4991
4992  size(8);
4993  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
4994            "MOV$cmp  $dst.hi,$src.hi" %}
4995  ins_encode %{
4996    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4997    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4998  %}
4999  ins_pipe(ialu_reg);
5000%}
5001
5002// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5003// (hi($con$$constant), lo($con$$constant)) becomes
5004instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{
5005  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
5006  ins_cost(140);
5007
5008  size(8);
5009  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5010            "MOV$cmp  $dst.hi,0" %}
5011  ins_encode %{
5012    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5013    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5014  %}
5015  ins_pipe(ialu_imm);
5016%}
5017
5018instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{
5019  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
5020  ins_cost(140);
5021
5022  size(8);
5023  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5024            "MOV$cmp  $dst.hi,0" %}
5025  ins_encode %{
5026    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5027    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5028  %}
5029  ins_pipe(ialu_imm);
5030%}
5031
5032instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
5033  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5034  ins_cost(150);
5035
5036  size(8);
5037  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
5038            "MOV$cmp  $dst.hi,$src.hi" %}
5039  ins_encode %{
5040    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5041    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5042  %}
5043  ins_pipe(ialu_reg);
5044%}
5045
5046instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{
5047  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5048  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5049            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5050            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5051            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5052  ins_cost(150);
5053
5054  size(8);
5055  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
5056            "MOV$cmp  $dst.hi,$src.hi" %}
5057  ins_encode %{
5058    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5059    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5060  %}
5061  ins_pipe(ialu_reg);
5062%}
5063
5064// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5065// (hi($con$$constant), lo($con$$constant)) becomes
5066instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{
5067  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5068  ins_cost(140);
5069
5070  size(8);
5071  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5072            "MOV$cmp  $dst.hi,0" %}
5073  ins_encode %{
5074    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5075    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5076  %}
5077  ins_pipe(ialu_imm);
5078%}
5079
5080// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5081// (hi($con$$constant), lo($con$$constant)) becomes
5082instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{
5083  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5084  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5085            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5086            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5087            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5088  ins_cost(140);
5089
5090  size(8);
5091  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5092            "MOV$cmp  $dst.hi,0" %}
5093  ins_encode %{
5094    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5095    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5096  %}
5097  ins_pipe(ialu_imm);
5098%}
5099
5100instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{
5101  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5102  ins_cost(140);
5103
5104  size(8);
5105  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5106            "MOV$cmp  $dst.hi,0" %}
5107  ins_encode %{
5108    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5109    __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5110  %}
5111  ins_pipe(ialu_imm);
5112%}
5113
5114instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{
5115  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5116  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5117            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5118            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5119            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5120  ins_cost(140);
5121
5122  size(8);
5123  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5124            "MOV$cmp  $dst.hi,0" %}
5125  ins_encode %{
5126    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5127    __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5128  %}
5129  ins_pipe(ialu_imm);
5130%}
5131
5132instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
5133  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5134  ins_cost(150);
5135
5136  size(8);
5137  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
5138            "MOV$cmp  $dst.hi,$src.hi" %}
5139  ins_encode %{
5140    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5141    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5142  %}
5143  ins_pipe(ialu_reg);
5144%}
5145
5146
5147//----------OS and Locking Instructions----------------------------------------
5148
5149// This name is KNOWN by the ADLC and cannot be changed.
5150// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
5151// for this guy.
5152instruct tlsLoadP(RthreadRegP dst) %{
5153  match(Set dst (ThreadLocal));
5154
5155  size(0);
5156  ins_cost(0);
5157  format %{ "! TLS is in $dst" %}
5158  ins_encode( /*empty encoding*/ );
5159  ins_pipe(ialu_none);
5160%}
5161
5162instruct checkCastPP( iRegP dst ) %{
5163  match(Set dst (CheckCastPP dst));
5164
5165  size(0);
5166  format %{ "! checkcastPP of $dst" %}
5167  ins_encode( /*empty encoding*/ );
5168  ins_pipe(empty);
5169%}
5170
5171
5172instruct castPP( iRegP dst ) %{
5173  match(Set dst (CastPP dst));
5174  format %{ "! castPP of $dst" %}
5175  ins_encode( /*empty encoding*/ );
5176  ins_pipe(empty);
5177%}
5178
5179instruct castII( iRegI dst ) %{
5180  match(Set dst (CastII dst));
5181  format %{ "! castII of $dst" %}
5182  ins_encode( /*empty encoding*/ );
5183  ins_cost(0);
5184  ins_pipe(empty);
5185%}
5186
5187instruct castLL( iRegL dst ) %{
5188  match(Set dst (CastLL dst));
5189  format %{ "! castLL of $dst" %}
5190  ins_encode( /*empty encoding*/ );
5191  ins_cost(0);
5192  ins_pipe(empty);
5193%}
5194
5195instruct castFF( regF dst ) %{
5196  match(Set dst (CastFF dst));
5197  format %{ "! castFF of $dst" %}
5198  ins_encode( /*empty encoding*/ );
5199  ins_cost(0);
5200  ins_pipe(empty);
5201%}
5202
5203instruct castDD( regD dst ) %{
5204  match(Set dst (CastDD dst));
5205  format %{ "! castDD of $dst" %}
5206  ins_encode( /*empty encoding*/ );
5207  ins_cost(0);
5208  ins_pipe(empty);
5209%}
5210
5211instruct castVVD( vecD dst ) %{
5212  match(Set dst (CastVV dst));
5213  format %{ "! castVV of $dst" %}
5214  ins_encode( /*empty encoding*/ );
5215  ins_cost(0);
5216  ins_pipe(empty);
5217%}
5218
5219instruct castVVX( vecX dst ) %{
5220  match(Set dst (CastVV dst));
5221  format %{ "! castVV of $dst" %}
5222  ins_encode( /*empty encoding*/ );
5223  ins_cost(0);
5224  ins_pipe(empty);
5225%}
5226
5227
5228//----------Arithmetic Instructions--------------------------------------------
5229// Addition Instructions
5230// Register Addition
5231instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5232  match(Set dst (AddI src1 src2));
5233
5234  size(4);
5235  format %{ "add_32 $dst,$src1,$src2\t! int" %}
5236  ins_encode %{
5237    __ add_32($dst$$Register, $src1$$Register, $src2$$Register);
5238  %}
5239  ins_pipe(ialu_reg_reg);
5240%}
5241
5242instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5243  match(Set dst (AddI (LShiftI src1 src2) src3));
5244
5245  size(4);
5246  format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5247  ins_encode %{
5248    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5249  %}
5250  ins_pipe(ialu_reg_reg);
5251%}
5252
5253
5254instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5255  match(Set dst (AddI (LShiftI src1 src2) src3));
5256
5257  size(4);
5258  format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5259  ins_encode %{
5260    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5261  %}
5262  ins_pipe(ialu_reg_reg);
5263%}
5264
5265instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5266  match(Set dst (AddI (RShiftI src1 src2) src3));
5267
5268  size(4);
5269  format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5270  ins_encode %{
5271    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5272  %}
5273  ins_pipe(ialu_reg_reg);
5274%}
5275
5276instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5277  match(Set dst (AddI (RShiftI src1 src2) src3));
5278
5279  size(4);
5280  format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5281  ins_encode %{
5282    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5283  %}
5284  ins_pipe(ialu_reg_reg);
5285%}
5286
5287instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5288  match(Set dst (AddI (URShiftI src1 src2) src3));
5289
5290  size(4);
5291  format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5292  ins_encode %{
5293    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5294  %}
5295  ins_pipe(ialu_reg_reg);
5296%}
5297
5298instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5299  match(Set dst (AddI (URShiftI src1 src2) src3));
5300
5301  size(4);
5302  format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5303  ins_encode %{
5304    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5305  %}
5306  ins_pipe(ialu_reg_reg);
5307%}
5308
5309// Immediate Addition
5310instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5311  match(Set dst (AddI src1 src2));
5312
5313  size(4);
5314  format %{ "add_32 $dst,$src1,$src2\t! int" %}
5315  ins_encode %{
5316    __ add_32($dst$$Register, $src1$$Register, $src2$$constant);
5317  %}
5318  ins_pipe(ialu_reg_imm);
5319%}
5320
5321// Pointer Register Addition
5322instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{
5323  match(Set dst (AddP src1 src2));
5324
5325  size(4);
5326  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
5327  ins_encode %{
5328    __ add($dst$$Register, $src1$$Register, $src2$$Register);
5329  %}
5330  ins_pipe(ialu_reg_reg);
5331%}
5332
5333
5334// shifted iRegX operand
5335operand shiftedX(iRegX src2, shimmX src3) %{
5336//constraint(ALLOC_IN_RC(sp_ptr_reg));
5337  match(LShiftX src2 src3);
5338
5339  op_cost(1);
5340  format %{ "$src2 << $src3" %}
5341  interface(MEMORY_INTER) %{
5342    base($src2);
5343    index(0xff);
5344    scale($src3);
5345    disp(0x0);
5346  %}
5347%}
5348
5349instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{
5350  match(Set dst (AddP src1 src2));
5351
5352  ins_cost(DEFAULT_COST * 3/2);
5353  size(4);
5354  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
5355  ins_encode %{
5356    Register base = reg_to_register_object($src2$$base);
5357    __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale));
5358  %}
5359  ins_pipe(ialu_reg_reg);
5360%}
5361
5362// Pointer Immediate Addition
5363instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{
5364  match(Set dst (AddP src1 src2));
5365
5366  size(4);
5367  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
5368  ins_encode %{
5369    __ add($dst$$Register, $src1$$Register, $src2$$constant);
5370  %}
5371  ins_pipe(ialu_reg_imm);
5372%}
5373
5374// Long Addition
5375instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{
5376  match(Set dst (AddL src1 src2));
5377  effect(KILL ccr);
5378  size(8);
5379  format %{ "ADDS    $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5380            "ADC     $dst.hi,$src1.hi,$src2.hi" %}
5381  ins_encode %{
5382    __ adds($dst$$Register, $src1$$Register, $src2$$Register);
5383    __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5384  %}
5385  ins_pipe(ialu_reg_reg);
5386%}
5387
5388// TODO
5389
5390// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5391// (hi($con$$constant), lo($con$$constant)) becomes
5392instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
5393  match(Set dst (AddL src1 con));
5394  effect(KILL ccr);
5395  size(8);
5396  format %{ "ADDS    $dst.lo,$src1.lo,$con\t! long\n\t"
5397            "ADC     $dst.hi,$src1.hi,0" %}
5398  ins_encode %{
5399    __ adds($dst$$Register, $src1$$Register, $con$$constant);
5400    __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5401  %}
5402  ins_pipe(ialu_reg_imm);
5403%}
5404
5405//----------Conditional_store--------------------------------------------------
5406// Conditional-store of the updated heap-top.
5407// Used during allocation of the shared heap.
5408// Sets flags (EQ) on success.
5409
5410// LoadP-locked.
5411instruct loadPLocked(iRegP dst, memoryex mem) %{
5412  match(Set dst (LoadPLocked mem));
5413  size(4);
5414  format %{ "LDREX  $dst,$mem" %}
5415  ins_encode %{
5416    __ ldrex($dst$$Register,$mem$$Address);
5417  %}
5418  ins_pipe(iload_mem);
5419%}
5420
5421instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{
5422  predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node
5423  match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval)));
5424  effect( TEMP tmp );
5425  size(8);
5426  format %{ "STREX  $tmp,$newval,$heap_top_ptr\n\t"
5427            "CMP    $tmp, 0" %}
5428  ins_encode %{
5429    __ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address);
5430    __ cmp($tmp$$Register, 0);
5431  %}
5432  ins_pipe( long_memory_op );
5433%}
5434
5435// Conditional-store of an intx value.
5436instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{
5437  match(Set icc (StoreIConditional mem (Binary oldval newval)));
5438  effect( TEMP tmp );
5439  size(28);
5440  format %{ "loop: \n\t"
5441            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t"
5442            "XORS     $tmp,$tmp, $oldval\n\t"
5443            "STREX.eq $tmp, $newval, $mem\n\t"
5444            "CMP.eq   $tmp, 1 \n\t"
5445            "B.eq     loop \n\t"
5446            "TEQ      $tmp, 0\n\t"
5447            "membar   LoadStore|LoadLoad" %}
5448  ins_encode %{
5449    Label loop;
5450    __ bind(loop);
5451    __ ldrex($tmp$$Register, $mem$$Address);
5452    __ eors($tmp$$Register, $tmp$$Register, $oldval$$Register);
5453    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5454    __ cmp($tmp$$Register, 1, eq);
5455    __ b(loop, eq);
5456    __ teq($tmp$$Register, 0);
5457    // used by biased locking only. Requires a membar.
5458    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg);
5459  %}
5460  ins_pipe( long_memory_op );
5461%}
5462
5463// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
5464
5465instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
5466  match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5467  effect( KILL ccr, TEMP tmp);
5468  size(32);
5469  format %{ "loop: \n\t"
5470            "LDREXD   $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5471            "CMP      $tmp.lo, $oldval.lo\n\t"
5472            "CMP.eq   $tmp.hi, $oldval.hi\n\t"
5473            "STREXD.eq $tmp, $newval, $mem\n\t"
5474            "MOV.ne   $tmp, 0 \n\t"
5475            "XORS.eq  $tmp,$tmp, 1 \n\t"
5476            "B.eq     loop \n\t"
5477            "MOV      $res, $tmp" %}
5478  ins_encode %{
5479    Label loop;
5480    __ bind(loop);
5481    __ ldrexd($tmp$$Register, $mem$$Address);
5482    __ cmp($tmp$$Register, $oldval$$Register);
5483    __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq);
5484    __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5485    __ mov($tmp$$Register, 0, ne);
5486    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5487    __ b(loop, eq);
5488    __ mov($res$$Register, $tmp$$Register);
5489  %}
5490  ins_pipe( long_memory_op );
5491%}
5492
5493
5494instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5495  match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5496  effect( KILL ccr, TEMP tmp);
5497  size(28);
5498  format %{ "loop: \n\t"
5499            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5500            "CMP      $tmp, $oldval\n\t"
5501            "STREX.eq $tmp, $newval, $mem\n\t"
5502            "MOV.ne   $tmp, 0 \n\t"
5503            "XORS.eq  $tmp,$tmp, 1 \n\t"
5504            "B.eq     loop \n\t"
5505            "MOV      $res, $tmp" %}
5506
5507  ins_encode %{
5508    Label loop;
5509    __ bind(loop);
5510    __ ldrex($tmp$$Register,$mem$$Address);
5511    __ cmp($tmp$$Register, $oldval$$Register);
5512    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5513    __ mov($tmp$$Register, 0, ne);
5514    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5515    __ b(loop, eq);
5516    __ mov($res$$Register, $tmp$$Register);
5517  %}
5518  ins_pipe( long_memory_op );
5519%}
5520
5521instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5522  match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5523  effect( KILL ccr, TEMP tmp);
5524  size(28);
5525  format %{ "loop: \n\t"
5526            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5527            "CMP      $tmp, $oldval\n\t"
5528            "STREX.eq $tmp, $newval, $mem\n\t"
5529            "MOV.ne   $tmp, 0 \n\t"
5530            "EORS.eq  $tmp,$tmp, 1 \n\t"
5531            "B.eq     loop \n\t"
5532            "MOV      $res, $tmp" %}
5533
5534  ins_encode %{
5535    Label loop;
5536    __ bind(loop);
5537    __ ldrex($tmp$$Register,$mem$$Address);
5538    __ cmp($tmp$$Register, $oldval$$Register);
5539    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5540    __ mov($tmp$$Register, 0, ne);
5541    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5542    __ b(loop, eq);
5543    __ mov($res$$Register, $tmp$$Register);
5544  %}
5545  ins_pipe( long_memory_op );
5546%}
5547
5548instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5549  predicate(n->as_LoadStore()->result_not_used());
5550  match(Set dummy (GetAndAddI mem add));
5551  effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5552  size(20);
5553  format %{ "loop: \n\t"
5554            "LDREX    $tmp1, $mem\n\t"
5555            "ADD      $tmp1, $tmp1, $add\n\t"
5556            "STREX    $tmp2, $tmp1, $mem\n\t"
5557            "CMP      $tmp2, 0 \n\t"
5558            "B.ne     loop \n\t" %}
5559
5560  ins_encode %{
5561    Label loop;
5562    __ bind(loop);
5563    __ ldrex($tmp1$$Register,$mem$$Address);
5564    __ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
5565    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5566    __ cmp($tmp2$$Register, 0);
5567    __ b(loop, ne);
5568  %}
5569  ins_pipe( long_memory_op );
5570%}
5571
5572instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5573  predicate(n->as_LoadStore()->result_not_used());
5574  match(Set dummy (GetAndAddI mem add));
5575  effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5576  size(20);
5577  format %{ "loop: \n\t"
5578            "LDREX    $tmp1, $mem\n\t"
5579            "ADD      $tmp1, $tmp1, $add\n\t"
5580            "STREX    $tmp2, $tmp1, $mem\n\t"
5581            "CMP      $tmp2, 0 \n\t"
5582            "B.ne     loop \n\t" %}
5583
5584  ins_encode %{
5585    Label loop;
5586    __ bind(loop);
5587    __ ldrex($tmp1$$Register,$mem$$Address);
5588    __ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
5589    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5590    __ cmp($tmp2$$Register, 0);
5591    __ b(loop, ne);
5592  %}
5593  ins_pipe( long_memory_op );
5594%}
5595
5596instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5597  match(Set res (GetAndAddI mem add));
5598  effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5599  size(20);
5600  format %{ "loop: \n\t"
5601            "LDREX    $res, $mem\n\t"
5602            "ADD      $tmp1, $res, $add\n\t"
5603            "STREX    $tmp2, $tmp1, $mem\n\t"
5604            "CMP      $tmp2, 0 \n\t"
5605            "B.ne     loop \n\t" %}
5606
5607  ins_encode %{
5608    Label loop;
5609    __ bind(loop);
5610    __ ldrex($res$$Register,$mem$$Address);
5611    __ add($tmp1$$Register, $res$$Register, $add$$constant);
5612    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5613    __ cmp($tmp2$$Register, 0);
5614    __ b(loop, ne);
5615  %}
5616  ins_pipe( long_memory_op );
5617%}
5618
5619instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5620  match(Set res (GetAndAddI mem add));
5621  effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5622  size(20);
5623  format %{ "loop: \n\t"
5624            "LDREX    $res, $mem\n\t"
5625            "ADD      $tmp1, $res, $add\n\t"
5626            "STREX    $tmp2, $tmp1, $mem\n\t"
5627            "CMP      $tmp2, 0 \n\t"
5628            "B.ne     loop \n\t" %}
5629
5630  ins_encode %{
5631    Label loop;
5632    __ bind(loop);
5633    __ ldrex($res$$Register,$mem$$Address);
5634    __ add($tmp1$$Register, $res$$Register, $add$$Register);
5635    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5636    __ cmp($tmp2$$Register, 0);
5637    __ b(loop, ne);
5638  %}
5639  ins_pipe( long_memory_op );
5640%}
5641
5642instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5643  predicate(n->as_LoadStore()->result_not_used());
5644  match(Set dummy (GetAndAddL mem add));
5645  effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5646  size(24);
5647  format %{ "loop: \n\t"
5648            "LDREXD   $tmp1, $mem\n\t"
5649            "ADDS     $tmp1.lo, $tmp1.lo, $add.lo\n\t"
5650            "ADC      $tmp1.hi, $tmp1.hi, $add.hi\n\t"
5651            "STREXD   $tmp2, $tmp1, $mem\n\t"
5652            "CMP      $tmp2, 0 \n\t"
5653            "B.ne     loop \n\t" %}
5654
5655  ins_encode %{
5656    Label loop;
5657    __ bind(loop);
5658    __ ldrexd($tmp1$$Register, $mem$$Address);
5659    __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register);
5660    __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor());
5661    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5662    __ cmp($tmp2$$Register, 0);
5663    __ b(loop, ne);
5664  %}
5665  ins_pipe( long_memory_op );
5666%}
5667
5668// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5669// (hi($con$$constant), lo($con$$constant)) becomes
5670instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5671  predicate(n->as_LoadStore()->result_not_used());
5672  match(Set dummy (GetAndAddL mem add));
5673  effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5674  size(24);
5675  format %{ "loop: \n\t"
5676            "LDREXD   $tmp1, $mem\n\t"
5677            "ADDS     $tmp1.lo, $tmp1.lo, $add\n\t"
5678            "ADC      $tmp1.hi, $tmp1.hi, 0\n\t"
5679            "STREXD   $tmp2, $tmp1, $mem\n\t"
5680            "CMP      $tmp2, 0 \n\t"
5681            "B.ne     loop \n\t" %}
5682
5683  ins_encode %{
5684    Label loop;
5685    __ bind(loop);
5686    __ ldrexd($tmp1$$Register, $mem$$Address);
5687    __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant);
5688    __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0);
5689    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5690    __ cmp($tmp2$$Register, 0);
5691    __ b(loop, ne);
5692  %}
5693  ins_pipe( long_memory_op );
5694%}
5695
5696instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5697  match(Set res (GetAndAddL mem add));
5698  effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5699  size(24);
5700  format %{ "loop: \n\t"
5701            "LDREXD   $res, $mem\n\t"
5702            "ADDS     $tmp1.lo, $res.lo, $add.lo\n\t"
5703            "ADC      $tmp1.hi, $res.hi, $add.hi\n\t"
5704            "STREXD   $tmp2, $tmp1, $mem\n\t"
5705            "CMP      $tmp2, 0 \n\t"
5706            "B.ne     loop \n\t" %}
5707
5708  ins_encode %{
5709    Label loop;
5710    __ bind(loop);
5711    __ ldrexd($res$$Register, $mem$$Address);
5712    __ adds($tmp1$$Register, $res$$Register, $add$$Register);
5713    __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor());
5714    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5715    __ cmp($tmp2$$Register, 0);
5716    __ b(loop, ne);
5717  %}
5718  ins_pipe( long_memory_op );
5719%}
5720
5721// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5722// (hi($con$$constant), lo($con$$constant)) becomes
5723instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5724  match(Set res (GetAndAddL mem add));
5725  effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5726  size(24);
5727  format %{ "loop: \n\t"
5728            "LDREXD   $res, $mem\n\t"
5729            "ADDS     $tmp1.lo, $res.lo, $add\n\t"
5730            "ADC      $tmp1.hi, $res.hi, 0\n\t"
5731            "STREXD   $tmp2, $tmp1, $mem\n\t"
5732            "CMP      $tmp2, 0 \n\t"
5733            "B.ne     loop \n\t" %}
5734
5735  ins_encode %{
5736    Label loop;
5737    __ bind(loop);
5738    __ ldrexd($res$$Register, $mem$$Address);
5739    __ adds($tmp1$$Register, $res$$Register, $add$$constant);
5740    __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0);
5741    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5742    __ cmp($tmp2$$Register, 0);
5743    __ b(loop, ne);
5744  %}
5745  ins_pipe( long_memory_op );
5746%}
5747
5748instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
5749  match(Set res (GetAndSetI mem newval));
5750  effect(KILL ccr, TEMP tmp, TEMP res);
5751  size(16);
5752  format %{ "loop: \n\t"
5753            "LDREX    $res, $mem\n\t"
5754            "STREX    $tmp, $newval, $mem\n\t"
5755            "CMP      $tmp, 0 \n\t"
5756            "B.ne     loop \n\t" %}
5757
5758  ins_encode %{
5759    Label loop;
5760    __ bind(loop);
5761    __ ldrex($res$$Register,$mem$$Address);
5762    __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5763    __ cmp($tmp$$Register, 0);
5764    __ b(loop, ne);
5765  %}
5766  ins_pipe( long_memory_op );
5767%}
5768
5769instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{
5770  match(Set res (GetAndSetL mem newval));
5771  effect( KILL ccr, TEMP tmp, TEMP res);
5772  size(16);
5773  format %{ "loop: \n\t"
5774            "LDREXD   $res, $mem\n\t"
5775            "STREXD   $tmp, $newval, $mem\n\t"
5776            "CMP      $tmp, 0 \n\t"
5777            "B.ne     loop \n\t" %}
5778
5779  ins_encode %{
5780    Label loop;
5781    __ bind(loop);
5782    __ ldrexd($res$$Register, $mem$$Address);
5783    __ strexd($tmp$$Register, $newval$$Register, $mem$$Address);
5784    __ cmp($tmp$$Register, 0);
5785    __ b(loop, ne);
5786  %}
5787  ins_pipe( long_memory_op );
5788%}
5789
5790instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{
5791  match(Set res (GetAndSetP mem newval));
5792  effect(KILL ccr, TEMP tmp, TEMP res);
5793  size(16);
5794  format %{ "loop: \n\t"
5795            "LDREX    $res, $mem\n\t"
5796            "STREX    $tmp, $newval, $mem\n\t"
5797            "CMP      $tmp, 0 \n\t"
5798            "B.ne     loop \n\t" %}
5799
5800  ins_encode %{
5801    Label loop;
5802    __ bind(loop);
5803    __ ldrex($res$$Register,$mem$$Address);
5804    __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5805    __ cmp($tmp$$Register, 0);
5806    __ b(loop, ne);
5807  %}
5808  ins_pipe( long_memory_op );
5809%}
5810
5811//---------------------
5812// Subtraction Instructions
5813// Register Subtraction
5814instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5815  match(Set dst (SubI src1 src2));
5816
5817  size(4);
5818  format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5819  ins_encode %{
5820    __ sub_32($dst$$Register, $src1$$Register, $src2$$Register);
5821  %}
5822  ins_pipe(ialu_reg_reg);
5823%}
5824
5825instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5826  match(Set dst (SubI src1 (LShiftI src2 src3)));
5827
5828  size(4);
5829  format %{ "SUB    $dst,$src1,$src2<<$src3" %}
5830  ins_encode %{
5831    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
5832  %}
5833  ins_pipe(ialu_reg_reg);
5834%}
5835
5836instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5837  match(Set dst (SubI src1 (LShiftI src2 src3)));
5838
5839  size(4);
5840  format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %}
5841  ins_encode %{
5842    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
5843  %}
5844  ins_pipe(ialu_reg_reg);
5845%}
5846
5847instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5848  match(Set dst (SubI src1 (RShiftI src2 src3)));
5849
5850  size(4);
5851  format %{ "SUB    $dst,$src1,$src2>>$src3" %}
5852  ins_encode %{
5853    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
5854  %}
5855  ins_pipe(ialu_reg_reg);
5856%}
5857
5858instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5859  match(Set dst (SubI src1 (RShiftI src2 src3)));
5860
5861  size(4);
5862  format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %}
5863  ins_encode %{
5864    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
5865  %}
5866  ins_pipe(ialu_reg_reg);
5867%}
5868
5869instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5870  match(Set dst (SubI src1 (URShiftI src2 src3)));
5871
5872  size(4);
5873  format %{ "SUB    $dst,$src1,$src2>>>$src3" %}
5874  ins_encode %{
5875    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
5876  %}
5877  ins_pipe(ialu_reg_reg);
5878%}
5879
5880instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5881  match(Set dst (SubI src1 (URShiftI src2 src3)));
5882
5883  size(4);
5884  format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %}
5885  ins_encode %{
5886    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
5887  %}
5888  ins_pipe(ialu_reg_reg);
5889%}
5890
5891instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5892  match(Set dst (SubI (LShiftI src1 src2) src3));
5893
5894  size(4);
5895  format %{ "RSB    $dst,$src3,$src1<<$src2" %}
5896  ins_encode %{
5897    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5898  %}
5899  ins_pipe(ialu_reg_reg);
5900%}
5901
5902instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5903  match(Set dst (SubI (LShiftI src1 src2) src3));
5904
5905  size(4);
5906  format %{ "RSB    $dst,$src3,$src1<<$src2" %}
5907  ins_encode %{
5908    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5909  %}
5910  ins_pipe(ialu_reg_reg);
5911%}
5912
5913instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5914  match(Set dst (SubI (RShiftI src1 src2) src3));
5915
5916  size(4);
5917  format %{ "RSB    $dst,$src3,$src1>>$src2" %}
5918  ins_encode %{
5919    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5920  %}
5921  ins_pipe(ialu_reg_reg);
5922%}
5923
5924instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5925  match(Set dst (SubI (RShiftI src1 src2) src3));
5926
5927  size(4);
5928  format %{ "RSB    $dst,$src3,$src1>>$src2" %}
5929  ins_encode %{
5930    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5931  %}
5932  ins_pipe(ialu_reg_reg);
5933%}
5934
5935instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5936  match(Set dst (SubI (URShiftI src1 src2) src3));
5937
5938  size(4);
5939  format %{ "RSB    $dst,$src3,$src1>>>$src2" %}
5940  ins_encode %{
5941    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5942  %}
5943  ins_pipe(ialu_reg_reg);
5944%}
5945
5946instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5947  match(Set dst (SubI (URShiftI src1 src2) src3));
5948
5949  size(4);
5950  format %{ "RSB    $dst,$src3,$src1>>>$src2" %}
5951  ins_encode %{
5952    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5953  %}
5954  ins_pipe(ialu_reg_reg);
5955%}
5956
5957// Immediate Subtraction
5958instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5959  match(Set dst (SubI src1 src2));
5960
5961  size(4);
5962  format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5963  ins_encode %{
5964    __ sub_32($dst$$Register, $src1$$Register, $src2$$constant);
5965  %}
5966  ins_pipe(ialu_reg_imm);
5967%}
5968
5969instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{
5970  match(Set dst (AddI src1 src2));
5971
5972  size(4);
5973  format %{ "sub_32 $dst,$src1,-($src2)\t! int" %}
5974  ins_encode %{
5975    __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant);
5976  %}
5977  ins_pipe(ialu_reg_imm);
5978%}
5979
5980instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{
5981  match(Set dst (SubI src1 src2));
5982
5983  size(4);
5984  format %{ "RSB    $dst,$src2,src1" %}
5985  ins_encode %{
5986    __ rsb($dst$$Register, $src2$$Register, $src1$$constant);
5987  %}
5988  ins_pipe(ialu_zero_reg);
5989%}
5990
5991// Register Subtraction
5992instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{
5993  match(Set dst (SubL src1 src2));
5994  effect (KILL icc);
5995
5996  size(8);
5997  format %{ "SUBS   $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5998            "SBC    $dst.hi,$src1.hi,$src2.hi" %}
5999  ins_encode %{
6000    __ subs($dst$$Register, $src1$$Register, $src2$$Register);
6001    __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6002  %}
6003  ins_pipe(ialu_reg_reg);
6004%}
6005
6006// TODO
6007
6008// Immediate Subtraction
6009// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6010// (hi($con$$constant), lo($con$$constant)) becomes
6011instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{
6012  match(Set dst (SubL src1 con));
6013  effect (KILL icc);
6014
6015  size(8);
6016  format %{ "SUB    $dst.lo,$src1.lo,$con\t! long\n\t"
6017            "SBC    $dst.hi,$src1.hi,0" %}
6018  ins_encode %{
6019    __ subs($dst$$Register, $src1$$Register, $con$$constant);
6020    __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0);
6021  %}
6022  ins_pipe(ialu_reg_imm);
6023%}
6024
6025// Long negation
6026instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{
6027  match(Set dst (SubL zero src2));
6028  effect (KILL icc);
6029
6030  size(8);
6031  format %{ "RSBS   $dst.lo,$src2.lo,0\t! long\n\t"
6032            "RSC    $dst.hi,$src2.hi,0" %}
6033  ins_encode %{
6034    __ rsbs($dst$$Register, $src2$$Register, 0);
6035    __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0);
6036  %}
6037  ins_pipe(ialu_zero_reg);
6038%}
6039
6040// Multiplication Instructions
6041// Integer Multiplication
6042// Register Multiplication
6043instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6044  match(Set dst (MulI src1 src2));
6045
6046  size(4);
6047  format %{ "mul_32 $dst,$src1,$src2" %}
6048  ins_encode %{
6049    __ mul_32($dst$$Register, $src1$$Register, $src2$$Register);
6050  %}
6051  ins_pipe(imul_reg_reg);
6052%}
6053
6054instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{
6055  effect(DEF dst, USE src1, USE src2);
6056  size(4);
6057  format %{ "MUL  $dst.hi,$src1.lo,$src2.hi\t! long" %}
6058  ins_encode %{
6059    __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor());
6060  %}
6061  ins_pipe(imul_reg_reg);
6062%}
6063
6064instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
6065  effect(USE_DEF dst, USE src1, USE src2);
6066  size(8);
6067  format %{ "MLA  $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t"
6068            "MOV  $dst.lo, 0"%}
6069  ins_encode %{
6070    __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor());
6071    __ mov($dst$$Register, 0);
6072  %}
6073  ins_pipe(imul_reg_reg);
6074%}
6075
6076instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
6077  effect(USE_DEF dst, USE src1, USE src2);
6078  size(4);
6079  format %{ "UMLAL  $dst.lo,$dst.hi,$src1,$src2\t! long" %}
6080  ins_encode %{
6081    __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register);
6082  %}
6083  ins_pipe(imul_reg_reg);
6084%}
6085
6086instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6087  match(Set dst (MulL src1 src2));
6088
6089  expand %{
6090    mulL_lo1_hi2(dst, src1, src2);
6091    mulL_hi1_lo2(dst, src1, src2);
6092    mulL_lo1_lo2(dst, src1, src2);
6093  %}
6094%}
6095
6096// Integer Division
6097// Register Division
6098instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{
6099  match(Set dst (DivI src1 src2));
6100  effect( KILL ccr, KILL src1, KILL src2, KILL lr);
6101  ins_cost((2+71)*DEFAULT_COST);
6102
6103  format %{ "DIV   $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %}
6104  ins_encode %{
6105    __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
6106  %}
6107  ins_pipe(sdiv_reg_reg);
6108%}
6109
6110// Register Long Division
6111instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
6112  match(Set dst (DivL src1 src2));
6113  effect(CALL);
6114  ins_cost(DEFAULT_COST*71);
6115  format %{ "DIVL  $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %}
6116  ins_encode %{
6117    address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv);
6118    __ call(target, relocInfo::runtime_call_type);
6119  %}
6120  ins_pipe(divL_reg_reg);
6121%}
6122
6123// Integer Remainder
6124// Register Remainder
6125instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{
6126  match(Set dst (ModI src1 src2));
6127  effect( KILL ccr, KILL temp, KILL src2, KILL lr);
6128
6129  format %{ "MODI   $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %}
6130  ins_encode %{
6131    __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
6132  %}
6133  ins_pipe(sdiv_reg_reg);
6134%}
6135
6136// Register Long Remainder
6137instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
6138  match(Set dst (ModL src1 src2));
6139  effect(CALL);
6140  ins_cost(MEMORY_REF_COST); // FIXME
6141  format %{ "modL    $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %}
6142  ins_encode %{
6143    address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
6144    __ call(target, relocInfo::runtime_call_type);
6145  %}
6146  ins_pipe(divL_reg_reg);
6147%}
6148
6149// Integer Shift Instructions
6150
6151// Register Shift Left
6152instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6153  match(Set dst (LShiftI src1 src2));
6154
6155  size(4);
6156  format %{ "LSL  $dst,$src1,$src2 \n\t" %}
6157  ins_encode %{
6158    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6159  %}
6160  ins_pipe(ialu_reg_reg);
6161%}
6162
6163// Register Shift Left Immediate
6164instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6165  match(Set dst (LShiftI src1 src2));
6166
6167  size(4);
6168  format %{ "LSL    $dst,$src1,$src2\t! int" %}
6169  ins_encode %{
6170    __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
6171  %}
6172  ins_pipe(ialu_reg_imm);
6173%}
6174
6175instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6176  effect(USE_DEF dst, USE src1, USE src2);
6177  size(4);
6178  format %{"OR  $dst.hi,$dst.hi,($src1.hi << $src2)"  %}
6179  ins_encode %{
6180    __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register));
6181  %}
6182  ins_pipe(ialu_reg_reg);
6183%}
6184
6185instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6186  effect(USE_DEF dst, USE src1, USE src2);
6187  size(4);
6188  format %{ "LSL  $dst.lo,$src1.lo,$src2 \n\t" %}
6189  ins_encode %{
6190    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6191  %}
6192  ins_pipe(ialu_reg_reg);
6193%}
6194
6195instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6196  effect(DEF dst, USE src1, USE src2, KILL ccr);
6197  size(16);
6198  format %{ "SUBS  $dst.hi,$src2,32 \n\t"
6199            "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t"
6200            "RSBmi $dst.hi,$dst.hi,0 \n\t"
6201            "LSRmi $dst.hi,$src1.lo,$dst.hi" %}
6202
6203  ins_encode %{
6204    // $src1$$Register and $dst$$Register->successor() can't be the same
6205    __ subs($dst$$Register->successor(), $src2$$Register, 32);
6206    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl);
6207    __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi);
6208    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi);
6209  %}
6210  ins_pipe(ialu_reg_reg);
6211%}
6212
6213instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6214  match(Set dst (LShiftL src1 src2));
6215
6216  expand %{
6217    flagsReg ccr;
6218    shlL_reg_reg_overlap(dst, src1, src2, ccr);
6219    shlL_reg_reg_merge_hi(dst, src1, src2);
6220    shlL_reg_reg_merge_lo(dst, src1, src2);
6221  %}
6222%}
6223
6224// Register Shift Left Immediate
6225instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6226  match(Set dst (LShiftL src1 src2));
6227
6228  size(8);
6229  format %{ "LSL   $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t"
6230            "MOV   $dst.lo, 0" %}
6231  ins_encode %{
6232    if ($src2$$constant == 32) {
6233      __ mov($dst$$Register->successor(), $src1$$Register);
6234    } else {
6235      __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32));
6236    }
6237    __ mov($dst$$Register, 0);
6238  %}
6239  ins_pipe(ialu_reg_imm);
6240%}
6241
6242instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6243  match(Set dst (LShiftL src1 src2));
6244
6245  size(12);
6246  format %{ "LSL   $dst.hi,$src1.lo,$src2\n\t"
6247            "OR    $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t"
6248            "LSL   $dst.lo,$src1.lo,$src2" %}
6249  ins_encode %{
6250    // The order of the following 3 instructions matters: src1.lo and
6251    // dst.hi can't overlap but src.hi and dst.hi can.
6252    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant));
6253    __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant));
6254    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6255  %}
6256  ins_pipe(ialu_reg_imm);
6257%}
6258
6259// Register Arithmetic Shift Right
6260instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6261  match(Set dst (RShiftI src1 src2));
6262  size(4);
6263  format %{ "ASR    $dst,$src1,$src2\t! int" %}
6264  ins_encode %{
6265    __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
6266  %}
6267  ins_pipe(ialu_reg_reg);
6268%}
6269
6270// Register Arithmetic Shift Right Immediate
6271instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6272  match(Set dst (RShiftI src1 src2));
6273
6274  size(4);
6275  format %{ "ASR    $dst,$src1,$src2" %}
6276  ins_encode %{
6277    __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
6278  %}
6279  ins_pipe(ialu_reg_imm);
6280%}
6281
6282// Register Shift Right Arithmetic Long
6283instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6284  effect(USE_DEF dst, USE src1, USE src2);
6285  size(4);
6286  format %{ "OR  $dst.lo,$dst.lo,($src1.lo >> $src2)"  %}
6287  ins_encode %{
6288    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6289  %}
6290  ins_pipe(ialu_reg_reg);
6291%}
6292
6293instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6294  effect(USE_DEF dst, USE src1, USE src2);
6295  size(4);
6296  format %{ "ASR  $dst.hi,$src1.hi,$src2 \n\t" %}
6297  ins_encode %{
6298    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register));
6299  %}
6300  ins_pipe(ialu_reg_reg);
6301%}
6302
6303instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6304  effect(DEF dst, USE src1, USE src2, KILL ccr);
6305  size(16);
6306  format %{ "SUBS  $dst.lo,$src2,32 \n\t"
6307            "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t"
6308            "RSBmi $dst.lo,$dst.lo,0 \n\t"
6309            "LSLmi $dst.lo,$src1.hi,$dst.lo" %}
6310
6311  ins_encode %{
6312    // $src1$$Register->successor() and $dst$$Register can't be the same
6313    __ subs($dst$$Register, $src2$$Register, 32);
6314    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl);
6315    __ rsb($dst$$Register, $dst$$Register, 0, mi);
6316    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6317  %}
6318  ins_pipe(ialu_reg_reg);
6319%}
6320
6321instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6322  match(Set dst (RShiftL src1 src2));
6323
6324  expand %{
6325    flagsReg ccr;
6326    sarL_reg_reg_overlap(dst, src1, src2, ccr);
6327    sarL_reg_reg_merge_lo(dst, src1, src2);
6328    sarL_reg_reg_merge_hi(dst, src1, src2);
6329  %}
6330%}
6331
6332// Register Shift Left Immediate
6333instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6334  match(Set dst (RShiftL src1 src2));
6335
6336  size(8);
6337  format %{ "ASR   $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6338            "ASR   $dst.hi,$src1.hi, $src2" %}
6339  ins_encode %{
6340    if ($src2$$constant == 32) {
6341      __ mov($dst$$Register, $src1$$Register->successor());
6342    } else{
6343      __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32));
6344    }
6345    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0));
6346  %}
6347
6348  ins_pipe(ialu_reg_imm);
6349%}
6350
6351instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6352  match(Set dst (RShiftL src1 src2));
6353  size(12);
6354  format %{ "LSR   $dst.lo,$src1.lo,$src2\n\t"
6355            "OR    $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6356            "ASR   $dst.hi,$src1.hi,$src2" %}
6357  ins_encode %{
6358    // The order of the following 3 instructions matters: src1.lo and
6359    // dst.hi can't overlap but src.hi and dst.hi can.
6360    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6361    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6362    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant));
6363  %}
6364  ins_pipe(ialu_reg_imm);
6365%}
6366
6367// Register Shift Right
6368instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6369  match(Set dst (URShiftI src1 src2));
6370  size(4);
6371  format %{ "LSR    $dst,$src1,$src2\t! int" %}
6372  ins_encode %{
6373    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6374  %}
6375  ins_pipe(ialu_reg_reg);
6376%}
6377
6378// Register Shift Right Immediate
6379instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6380  match(Set dst (URShiftI src1 src2));
6381
6382  size(4);
6383  format %{ "LSR    $dst,$src1,$src2" %}
6384  ins_encode %{
6385    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6386  %}
6387  ins_pipe(ialu_reg_imm);
6388%}
6389
6390// Register Shift Right
6391instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6392  effect(USE_DEF dst, USE src1, USE src2);
6393  size(4);
6394  format %{ "OR   $dst.lo,$dst,($src1.lo >>> $src2)"  %}
6395  ins_encode %{
6396    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6397  %}
6398  ins_pipe(ialu_reg_reg);
6399%}
6400
6401instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6402  effect(USE_DEF dst, USE src1, USE src2);
6403  size(4);
6404  format %{ "LSR  $dst.hi,$src1.hi,$src2 \n\t" %}
6405  ins_encode %{
6406    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register));
6407  %}
6408  ins_pipe(ialu_reg_reg);
6409%}
6410
6411instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6412  effect(DEF dst, USE src1, USE src2, KILL ccr);
6413  size(16);
6414  format %{ "SUBS  $dst,$src2,32 \n\t"
6415            "LSRpl $dst,$src1.hi,$dst \n\t"
6416            "RSBmi $dst,$dst,0 \n\t"
6417            "LSLmi $dst,$src1.hi,$dst" %}
6418
6419  ins_encode %{
6420    // $src1$$Register->successor() and $dst$$Register can't be the same
6421    __ subs($dst$$Register, $src2$$Register, 32);
6422    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl);
6423    __ rsb($dst$$Register, $dst$$Register, 0, mi);
6424    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6425  %}
6426  ins_pipe(ialu_reg_reg);
6427%}
6428
6429instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6430  match(Set dst (URShiftL src1 src2));
6431
6432  expand %{
6433    flagsReg ccr;
6434    shrL_reg_reg_overlap(dst, src1, src2, ccr);
6435    shrL_reg_reg_merge_lo(dst, src1, src2);
6436    shrL_reg_reg_merge_hi(dst, src1, src2);
6437  %}
6438%}
6439
6440// Register Shift Right Immediate
6441instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6442  match(Set dst (URShiftL src1 src2));
6443
6444  size(8);
6445  format %{ "LSR   $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6446            "MOV   $dst.hi, 0" %}
6447  ins_encode %{
6448    if ($src2$$constant == 32) {
6449      __ mov($dst$$Register, $src1$$Register->successor());
6450    } else {
6451      __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32));
6452    }
6453    __ mov($dst$$Register->successor(), 0);
6454  %}
6455
6456  ins_pipe(ialu_reg_imm);
6457%}
6458
6459instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6460  match(Set dst (URShiftL src1 src2));
6461
6462  size(12);
6463  format %{ "LSR   $dst.lo,$src1.lo,$src2\n\t"
6464            "OR    $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6465            "LSR   $dst.hi,$src1.hi,$src2" %}
6466  ins_encode %{
6467    // The order of the following 3 instructions matters: src1.lo and
6468    // dst.hi can't overlap but src.hi and dst.hi can.
6469    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6470    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6471    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant));
6472  %}
6473  ins_pipe(ialu_reg_imm);
6474%}
6475
6476
6477instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{
6478  match(Set dst (URShiftI (CastP2X src1) src2));
6479  size(4);
6480  format %{ "LSR    $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %}
6481  ins_encode %{
6482    __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant);
6483  %}
6484  ins_pipe(ialu_reg_imm);
6485%}
6486
6487//----------Floating Point Arithmetic Instructions-----------------------------
6488
6489//  Add float single precision
6490instruct addF_reg_reg(regF dst, regF src1, regF src2) %{
6491  match(Set dst (AddF src1 src2));
6492
6493  size(4);
6494  format %{ "FADDS  $dst,$src1,$src2" %}
6495  ins_encode %{
6496    __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6497  %}
6498
6499  ins_pipe(faddF_reg_reg);
6500%}
6501
6502//  Add float double precision
6503instruct addD_reg_reg(regD dst, regD src1, regD src2) %{
6504  match(Set dst (AddD src1 src2));
6505
6506  size(4);
6507  format %{ "FADDD  $dst,$src1,$src2" %}
6508  ins_encode %{
6509    __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6510  %}
6511
6512  ins_pipe(faddD_reg_reg);
6513%}
6514
6515//  Sub float single precision
6516instruct subF_reg_reg(regF dst, regF src1, regF src2) %{
6517  match(Set dst (SubF src1 src2));
6518
6519  size(4);
6520  format %{ "FSUBS  $dst,$src1,$src2" %}
6521  ins_encode %{
6522    __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6523  %}
6524  ins_pipe(faddF_reg_reg);
6525%}
6526
6527//  Sub float double precision
6528instruct subD_reg_reg(regD dst, regD src1, regD src2) %{
6529  match(Set dst (SubD src1 src2));
6530
6531  size(4);
6532  format %{ "FSUBD  $dst,$src1,$src2" %}
6533  ins_encode %{
6534    __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6535  %}
6536  ins_pipe(faddD_reg_reg);
6537%}
6538
6539//  Mul float single precision
6540instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{
6541  match(Set dst (MulF src1 src2));
6542
6543  size(4);
6544  format %{ "FMULS  $dst,$src1,$src2" %}
6545  ins_encode %{
6546    __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6547  %}
6548
6549  ins_pipe(fmulF_reg_reg);
6550%}
6551
6552//  Mul float double precision
6553instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{
6554  match(Set dst (MulD src1 src2));
6555
6556  size(4);
6557  format %{ "FMULD  $dst,$src1,$src2" %}
6558  ins_encode %{
6559    __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6560  %}
6561
6562  ins_pipe(fmulD_reg_reg);
6563%}
6564
6565//  Div float single precision
6566instruct divF_reg_reg(regF dst, regF src1, regF src2) %{
6567  match(Set dst (DivF src1 src2));
6568
6569  size(4);
6570  format %{ "FDIVS  $dst,$src1,$src2" %}
6571  ins_encode %{
6572    __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6573  %}
6574
6575  ins_pipe(fdivF_reg_reg);
6576%}
6577
6578//  Div float double precision
6579instruct divD_reg_reg(regD dst, regD src1, regD src2) %{
6580  match(Set dst (DivD src1 src2));
6581
6582  size(4);
6583  format %{ "FDIVD  $dst,$src1,$src2" %}
6584  ins_encode %{
6585    __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6586  %}
6587
6588  ins_pipe(fdivD_reg_reg);
6589%}
6590
6591//  Absolute float double precision
6592instruct absD_reg(regD dst, regD src) %{
6593  match(Set dst (AbsD src));
6594
6595  size(4);
6596  format %{ "FABSd  $dst,$src" %}
6597  ins_encode %{
6598    __ abs_double($dst$$FloatRegister, $src$$FloatRegister);
6599  %}
6600  ins_pipe(faddD_reg);
6601%}
6602
6603//  Absolute float single precision
6604instruct absF_reg(regF dst, regF src) %{
6605  match(Set dst (AbsF src));
6606  format %{ "FABSs  $dst,$src" %}
6607  ins_encode %{
6608    __ abs_float($dst$$FloatRegister, $src$$FloatRegister);
6609  %}
6610  ins_pipe(faddF_reg);
6611%}
6612
6613instruct negF_reg(regF dst, regF src) %{
6614  match(Set dst (NegF src));
6615
6616  size(4);
6617  format %{ "FNEGs  $dst,$src" %}
6618  ins_encode %{
6619    __ neg_float($dst$$FloatRegister, $src$$FloatRegister);
6620  %}
6621  ins_pipe(faddF_reg);
6622%}
6623
6624instruct negD_reg(regD dst, regD src) %{
6625  match(Set dst (NegD src));
6626
6627  format %{ "FNEGd  $dst,$src" %}
6628  ins_encode %{
6629    __ neg_double($dst$$FloatRegister, $src$$FloatRegister);
6630  %}
6631  ins_pipe(faddD_reg);
6632%}
6633
6634//  Sqrt float double precision
6635instruct sqrtF_reg_reg(regF dst, regF src) %{
6636  match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
6637
6638  size(4);
6639  format %{ "FSQRTS $dst,$src" %}
6640  ins_encode %{
6641    __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister);
6642  %}
6643  ins_pipe(fdivF_reg_reg);
6644%}
6645
6646//  Sqrt float double precision
6647instruct sqrtD_reg_reg(regD dst, regD src) %{
6648  match(Set dst (SqrtD src));
6649
6650  size(4);
6651  format %{ "FSQRTD $dst,$src" %}
6652  ins_encode %{
6653    __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister);
6654  %}
6655  ins_pipe(fdivD_reg_reg);
6656%}
6657
6658//----------Logical Instructions-----------------------------------------------
6659// And Instructions
6660// Register And
6661instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6662  match(Set dst (AndI src1 src2));
6663
6664  size(4);
6665  format %{ "and_32 $dst,$src1,$src2" %}
6666  ins_encode %{
6667    __ and_32($dst$$Register, $src1$$Register, $src2$$Register);
6668  %}
6669  ins_pipe(ialu_reg_reg);
6670%}
6671
6672instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6673  match(Set dst (AndI src1 (LShiftI src2 src3)));
6674
6675  size(4);
6676  format %{ "AND    $dst,$src1,$src2<<$src3" %}
6677  ins_encode %{
6678    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6679  %}
6680  ins_pipe(ialu_reg_reg);
6681%}
6682
6683instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6684  match(Set dst (AndI src1 (LShiftI src2 src3)));
6685
6686  size(4);
6687  format %{ "and_32 $dst,$src1,$src2<<$src3" %}
6688  ins_encode %{
6689    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6690  %}
6691  ins_pipe(ialu_reg_reg);
6692%}
6693
6694instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6695  match(Set dst (AndI src1 (RShiftI src2 src3)));
6696
6697  size(4);
6698  format %{ "AND    $dst,$src1,$src2>>$src3" %}
6699  ins_encode %{
6700    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6701  %}
6702  ins_pipe(ialu_reg_reg);
6703%}
6704
6705instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6706  match(Set dst (AndI src1 (RShiftI src2 src3)));
6707
6708  size(4);
6709  format %{ "and_32 $dst,$src1,$src2>>$src3" %}
6710  ins_encode %{
6711    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6712  %}
6713  ins_pipe(ialu_reg_reg);
6714%}
6715
6716instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6717  match(Set dst (AndI src1 (URShiftI src2 src3)));
6718
6719  size(4);
6720  format %{ "AND    $dst,$src1,$src2>>>$src3" %}
6721  ins_encode %{
6722    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6723  %}
6724  ins_pipe(ialu_reg_reg);
6725%}
6726
6727instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6728  match(Set dst (AndI src1 (URShiftI src2 src3)));
6729
6730  size(4);
6731  format %{ "and_32 $dst,$src1,$src2>>>$src3" %}
6732  ins_encode %{
6733    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6734  %}
6735  ins_pipe(ialu_reg_reg);
6736%}
6737
6738// Immediate And
6739instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6740  match(Set dst (AndI src1 src2));
6741
6742  size(4);
6743  format %{ "and_32 $dst,$src1,$src2\t! int" %}
6744  ins_encode %{
6745    __ and_32($dst$$Register, $src1$$Register, $src2$$constant);
6746  %}
6747  ins_pipe(ialu_reg_imm);
6748%}
6749
6750instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{
6751  match(Set dst (AndI src1 src2));
6752
6753  size(4);
6754  format %{ "bic    $dst,$src1,~$src2\t! int" %}
6755  ins_encode %{
6756    __ bic($dst$$Register, $src1$$Register, ~$src2$$constant);
6757  %}
6758  ins_pipe(ialu_reg_imm);
6759%}
6760
6761// Register And Long
6762instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6763  match(Set dst (AndL src1 src2));
6764
6765  ins_cost(DEFAULT_COST);
6766  size(8);
6767  format %{ "AND    $dst,$src1,$src2\t! long" %}
6768  ins_encode %{
6769    __ andr($dst$$Register, $src1$$Register, $src2$$Register);
6770    __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6771  %}
6772  ins_pipe(ialu_reg_reg);
6773%}
6774
6775// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6776// (hi($con$$constant), lo($con$$constant)) becomes
6777instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6778  match(Set dst (AndL src1 con));
6779  ins_cost(DEFAULT_COST);
6780  size(8);
6781  format %{ "AND    $dst,$src1,$con\t! long" %}
6782  ins_encode %{
6783    __ andr($dst$$Register, $src1$$Register, $con$$constant);
6784    __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6785  %}
6786  ins_pipe(ialu_reg_imm);
6787%}
6788
6789// Or Instructions
6790// Register Or
6791instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6792  match(Set dst (OrI src1 src2));
6793
6794  size(4);
6795  format %{ "orr_32 $dst,$src1,$src2\t! int" %}
6796  ins_encode %{
6797    __ orr_32($dst$$Register, $src1$$Register, $src2$$Register);
6798  %}
6799  ins_pipe(ialu_reg_reg);
6800%}
6801
6802instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6803  match(Set dst (OrI src1 (LShiftI src2 src3)));
6804
6805  size(4);
6806  format %{ "OR    $dst,$src1,$src2<<$src3" %}
6807  ins_encode %{
6808    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6809  %}
6810  ins_pipe(ialu_reg_reg);
6811%}
6812
6813instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6814  match(Set dst (OrI src1 (LShiftI src2 src3)));
6815
6816  size(4);
6817  format %{ "orr_32 $dst,$src1,$src2<<$src3" %}
6818  ins_encode %{
6819    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6820  %}
6821  ins_pipe(ialu_reg_reg);
6822%}
6823
6824instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6825  match(Set dst (OrI src1 (RShiftI src2 src3)));
6826
6827  size(4);
6828  format %{ "OR    $dst,$src1,$src2>>$src3" %}
6829  ins_encode %{
6830    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6831  %}
6832  ins_pipe(ialu_reg_reg);
6833%}
6834
6835instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6836  match(Set dst (OrI src1 (RShiftI src2 src3)));
6837
6838  size(4);
6839  format %{ "orr_32 $dst,$src1,$src2>>$src3" %}
6840  ins_encode %{
6841    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6842  %}
6843  ins_pipe(ialu_reg_reg);
6844%}
6845
6846instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6847  match(Set dst (OrI src1 (URShiftI src2 src3)));
6848
6849  size(4);
6850  format %{ "OR    $dst,$src1,$src2>>>$src3" %}
6851  ins_encode %{
6852    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6853  %}
6854  ins_pipe(ialu_reg_reg);
6855%}
6856
6857instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6858  match(Set dst (OrI src1 (URShiftI src2 src3)));
6859
6860  size(4);
6861  format %{ "orr_32 $dst,$src1,$src2>>>$src3" %}
6862  ins_encode %{
6863    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6864  %}
6865  ins_pipe(ialu_reg_reg);
6866%}
6867
6868// Immediate Or
6869instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6870  match(Set dst (OrI src1 src2));
6871
6872  size(4);
6873  format %{ "orr_32  $dst,$src1,$src2" %}
6874  ins_encode %{
6875    __ orr_32($dst$$Register, $src1$$Register, $src2$$constant);
6876  %}
6877  ins_pipe(ialu_reg_imm);
6878%}
6879// TODO: orn_32 with limmIn
6880
6881// Register Or Long
6882instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6883  match(Set dst (OrL src1 src2));
6884
6885  ins_cost(DEFAULT_COST);
6886  size(8);
6887  format %{ "OR     $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
6888            "OR     $dst.hi,$src1.hi,$src2.hi" %}
6889  ins_encode %{
6890    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6891    __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6892  %}
6893  ins_pipe(ialu_reg_reg);
6894%}
6895
6896// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6897// (hi($con$$constant), lo($con$$constant)) becomes
6898instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6899  match(Set dst (OrL src1 con));
6900  ins_cost(DEFAULT_COST);
6901  size(8);
6902  format %{ "OR     $dst.lo,$src1.lo,$con\t! long\n\t"
6903            "OR     $dst.hi,$src1.hi,$con" %}
6904  ins_encode %{
6905    __ orr($dst$$Register, $src1$$Register, $con$$constant);
6906    __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6907  %}
6908  ins_pipe(ialu_reg_imm);
6909%}
6910
6911#ifdef TODO
6912// Use SPRegP to match Rthread (TLS register) without spilling.
6913// Use store_ptr_RegP to match Rthread (TLS register) without spilling.
6914// Use sp_ptr_RegP to match Rthread (TLS register) without spilling.
6915instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{
6916  match(Set dst (OrI src1 (CastP2X src2)));
6917  size(4);
6918  format %{ "OR     $dst,$src1,$src2" %}
6919  ins_encode %{
6920    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6921  %}
6922  ins_pipe(ialu_reg_reg);
6923%}
6924#endif
6925
6926// Xor Instructions
6927// Register Xor
6928instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6929  match(Set dst (XorI src1 src2));
6930
6931  size(4);
6932  format %{ "eor_32 $dst,$src1,$src2" %}
6933  ins_encode %{
6934    __ eor_32($dst$$Register, $src1$$Register, $src2$$Register);
6935  %}
6936  ins_pipe(ialu_reg_reg);
6937%}
6938
6939instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6940  match(Set dst (XorI src1 (LShiftI src2 src3)));
6941
6942  size(4);
6943  format %{ "XOR    $dst,$src1,$src2<<$src3" %}
6944  ins_encode %{
6945    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6946  %}
6947  ins_pipe(ialu_reg_reg);
6948%}
6949
6950instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6951  match(Set dst (XorI src1 (LShiftI src2 src3)));
6952
6953  size(4);
6954  format %{ "eor_32 $dst,$src1,$src2<<$src3" %}
6955  ins_encode %{
6956    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6957  %}
6958  ins_pipe(ialu_reg_reg);
6959%}
6960
6961instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6962  match(Set dst (XorI src1 (RShiftI src2 src3)));
6963
6964  size(4);
6965  format %{ "XOR    $dst,$src1,$src2>>$src3" %}
6966  ins_encode %{
6967    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6968  %}
6969  ins_pipe(ialu_reg_reg);
6970%}
6971
6972instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6973  match(Set dst (XorI src1 (RShiftI src2 src3)));
6974
6975  size(4);
6976  format %{ "eor_32 $dst,$src1,$src2>>$src3" %}
6977  ins_encode %{
6978    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6979  %}
6980  ins_pipe(ialu_reg_reg);
6981%}
6982
6983instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6984  match(Set dst (XorI src1 (URShiftI src2 src3)));
6985
6986  size(4);
6987  format %{ "XOR    $dst,$src1,$src2>>>$src3" %}
6988  ins_encode %{
6989    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6990  %}
6991  ins_pipe(ialu_reg_reg);
6992%}
6993
6994instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6995  match(Set dst (XorI src1 (URShiftI src2 src3)));
6996
6997  size(4);
6998  format %{ "eor_32 $dst,$src1,$src2>>>$src3" %}
6999  ins_encode %{
7000    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
7001  %}
7002  ins_pipe(ialu_reg_reg);
7003%}
7004
7005// Immediate Xor
7006instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{
7007  match(Set dst (XorI src1 src2));
7008
7009  size(4);
7010  format %{ "eor_32 $dst,$src1,$src2" %}
7011  ins_encode %{
7012    __ eor_32($dst$$Register, $src1$$Register, $src2$$constant);
7013  %}
7014  ins_pipe(ialu_reg_imm);
7015%}
7016
7017// Register Xor Long
7018instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
7019  match(Set dst (XorL src1 src2));
7020  ins_cost(DEFAULT_COST);
7021  size(8);
7022  format %{ "XOR     $dst.hi,$src1.hi,$src2.hi\t! long\n\t"
7023            "XOR     $dst.lo,$src1.lo,$src2.lo\t! long" %}
7024  ins_encode %{
7025    __ eor($dst$$Register, $src1$$Register, $src2$$Register);
7026    __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
7027  %}
7028  ins_pipe(ialu_reg_reg);
7029%}
7030
7031// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7032// (hi($con$$constant), lo($con$$constant)) becomes
7033instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
7034  match(Set dst (XorL src1 con));
7035  ins_cost(DEFAULT_COST);
7036  size(8);
7037  format %{ "XOR     $dst.hi,$src1.hi,$con\t! long\n\t"
7038            "XOR     $dst.lo,$src1.lo,0\t! long" %}
7039  ins_encode %{
7040    __ eor($dst$$Register, $src1$$Register, $con$$constant);
7041    __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0);
7042  %}
7043  ins_pipe(ialu_reg_imm);
7044%}
7045
7046//----------Convert to Boolean-------------------------------------------------
7047instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{
7048  match(Set dst (Conv2B src));
7049  effect(KILL ccr);
7050  size(12);
7051  ins_cost(DEFAULT_COST*2);
7052  format %{ "TST    $src,$src \n\t"
7053            "MOV    $dst, 0   \n\t"
7054            "MOV.ne $dst, 1" %}
7055  ins_encode %{ // FIXME: can do better?
7056    __ tst($src$$Register, $src$$Register);
7057    __ mov($dst$$Register, 0);
7058    __ mov($dst$$Register, 1, ne);
7059  %}
7060  ins_pipe(ialu_reg_ialu);
7061%}
7062
7063instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{
7064  match(Set dst (Conv2B src));
7065  effect(KILL ccr);
7066  size(12);
7067  ins_cost(DEFAULT_COST*2);
7068  format %{ "TST    $src,$src \n\t"
7069            "MOV    $dst, 0   \n\t"
7070            "MOV.ne $dst, 1" %}
7071  ins_encode %{
7072    __ tst($src$$Register, $src$$Register);
7073    __ mov($dst$$Register, 0);
7074    __ mov($dst$$Register, 1, ne);
7075  %}
7076  ins_pipe(ialu_reg_ialu);
7077%}
7078
7079instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
7080  match(Set dst (CmpLTMask p q));
7081  effect( KILL ccr );
7082  ins_cost(DEFAULT_COST*3);
7083  format %{ "CMP    $p,$q\n\t"
7084            "MOV    $dst, #0\n\t"
7085            "MOV.lt $dst, #-1" %}
7086  ins_encode %{
7087    __ cmp($p$$Register, $q$$Register);
7088    __ mov($dst$$Register, 0);
7089    __ mvn($dst$$Register, 0, lt);
7090  %}
7091  ins_pipe(ialu_reg_reg_ialu);
7092%}
7093
7094instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{
7095  match(Set dst (CmpLTMask p q));
7096  effect( KILL ccr );
7097  ins_cost(DEFAULT_COST*3);
7098  format %{ "CMP    $p,$q\n\t"
7099            "MOV    $dst, #0\n\t"
7100            "MOV.lt $dst, #-1" %}
7101  ins_encode %{
7102    __ cmp($p$$Register, $q$$constant);
7103    __ mov($dst$$Register, 0);
7104    __ mvn($dst$$Register, 0, lt);
7105  %}
7106  ins_pipe(ialu_reg_reg_ialu);
7107%}
7108
7109instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{
7110  match(Set z (AddI (AndI (CmpLTMask p q) y) z));
7111  effect( KILL ccr );
7112  ins_cost(DEFAULT_COST*2);
7113  format %{ "CMP    $p,$q\n\t"
7114            "ADD.lt $z,$y,$z" %}
7115  ins_encode %{
7116    __ cmp($p$$Register, $q$$Register);
7117    __ add($z$$Register, $y$$Register, $z$$Register, lt);
7118  %}
7119  ins_pipe( cadd_cmpltmask );
7120%}
7121
7122// FIXME: remove unused "dst"
7123instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{
7124  match(Set z (AddI (AndI (CmpLTMask p q) y) z));
7125  effect( KILL ccr );
7126  ins_cost(DEFAULT_COST*2);
7127  format %{ "CMP    $p,$q\n\t"
7128            "ADD.lt $z,$y,$z" %}
7129  ins_encode %{
7130    __ cmp($p$$Register, $q$$constant);
7131    __ add($z$$Register, $y$$Register, $z$$Register, lt);
7132  %}
7133  ins_pipe( cadd_cmpltmask );
7134%}
7135
7136instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
7137  match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
7138  effect( KILL ccr );
7139  ins_cost(DEFAULT_COST*2);
7140  format %{ "SUBS   $p,$p,$q\n\t"
7141            "ADD.lt $p,$y,$p" %}
7142  ins_encode %{
7143    __ subs($p$$Register, $p$$Register, $q$$Register);
7144    __ add($p$$Register, $y$$Register, $p$$Register, lt);
7145  %}
7146  ins_pipe( cadd_cmpltmask );
7147%}
7148
7149//----------Arithmetic Conversion Instructions---------------------------------
7150// The conversions operations are all Alpha sorted.  Please keep it that way!
7151
7152instruct convD2F_reg(regF dst, regD src) %{
7153  match(Set dst (ConvD2F src));
7154  size(4);
7155  format %{ "FCVTSD  $dst,$src" %}
7156  ins_encode %{
7157    __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister);
7158  %}
7159  ins_pipe(fcvtD2F);
7160%}
7161
7162// Convert a double to an int in a float register.
7163// If the double is a NAN, stuff a zero in instead.
7164
7165instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{
7166  match(Set dst (ConvD2I src));
7167  effect( TEMP tmp );
7168  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7169  format %{ "FTOSIZD  $tmp,$src\n\t"
7170            "FMRS     $dst, $tmp" %}
7171  ins_encode %{
7172    __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister);
7173    __ fmrs($dst$$Register, $tmp$$FloatRegister);
7174  %}
7175  ins_pipe(fcvtD2I);
7176%}
7177
7178// Convert a double to a long in a double register.
7179// If the double is a NAN, stuff a zero in instead.
7180
7181// Double to Long conversion
7182instruct convD2L_reg(R0R1RegL dst, regD src) %{
7183  match(Set dst (ConvD2L src));
7184  effect(CALL);
7185  ins_cost(MEMORY_REF_COST); // FIXME
7186  format %{ "convD2L    $dst,$src\t ! call to SharedRuntime::d2l" %}
7187  ins_encode %{
7188#ifndef __ABI_HARD__
7189    __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7190#else
7191    if ($src$$FloatRegister != D0) {
7192      __ mov_double(D0, $src$$FloatRegister);
7193    }
7194#endif
7195    address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
7196    __ call(target, relocInfo::runtime_call_type);
7197  %}
7198  ins_pipe(fcvtD2L);
7199%}
7200
7201instruct convF2D_reg(regD dst, regF src) %{
7202  match(Set dst (ConvF2D src));
7203  size(4);
7204  format %{ "FCVTDS  $dst,$src" %}
7205  ins_encode %{
7206    __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister);
7207  %}
7208  ins_pipe(fcvtF2D);
7209%}
7210
7211instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{
7212  match(Set dst (ConvF2I src));
7213  effect( TEMP tmp );
7214  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7215  size(8);
7216  format %{ "FTOSIZS  $tmp,$src\n\t"
7217            "FMRS     $dst, $tmp" %}
7218  ins_encode %{
7219    __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister);
7220    __ fmrs($dst$$Register, $tmp$$FloatRegister);
7221  %}
7222  ins_pipe(fcvtF2I);
7223%}
7224
7225// Float to Long conversion
7226instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{
7227  match(Set dst (ConvF2L src));
7228  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7229  effect(CALL);
7230  format %{ "convF2L  $dst,$src\t! call to SharedRuntime::f2l" %}
7231  ins_encode %{
7232#ifndef __ABI_HARD__
7233    __ fmrs($arg1$$Register, $src$$FloatRegister);
7234#else
7235    if($src$$FloatRegister != S0) {
7236      __ mov_float(S0, $src$$FloatRegister);
7237    }
7238#endif
7239    address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
7240    __ call(target, relocInfo::runtime_call_type);
7241  %}
7242  ins_pipe(fcvtF2L);
7243%}
7244
7245instruct convI2D_reg_reg(iRegI src, regD_low dst) %{
7246  match(Set dst (ConvI2D src));
7247  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7248  size(8);
7249  format %{ "FMSR     $dst,$src \n\t"
7250            "FSITOD   $dst $dst"%}
7251  ins_encode %{
7252      __ fmsr($dst$$FloatRegister, $src$$Register);
7253      __ fsitod($dst$$FloatRegister, $dst$$FloatRegister);
7254  %}
7255  ins_pipe(fcvtI2D);
7256%}
7257
7258instruct convI2F_reg_reg( regF dst, iRegI src ) %{
7259  match(Set dst (ConvI2F src));
7260  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7261  size(8);
7262  format %{ "FMSR     $dst,$src \n\t"
7263            "FSITOS   $dst, $dst"%}
7264  ins_encode %{
7265      __ fmsr($dst$$FloatRegister, $src$$Register);
7266      __ fsitos($dst$$FloatRegister, $dst$$FloatRegister);
7267  %}
7268  ins_pipe(fcvtI2F);
7269%}
7270
7271instruct convI2L_reg(iRegL dst, iRegI src) %{
7272  match(Set dst (ConvI2L src));
7273  size(8);
7274  format %{ "MOV    $dst.lo, $src \n\t"
7275            "ASR    $dst.hi,$src,31\t! int->long" %}
7276  ins_encode %{
7277    __ mov($dst$$Register, $src$$Register);
7278    __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31));
7279  %}
7280  ins_pipe(ialu_reg_reg);
7281%}
7282
7283// Zero-extend convert int to long
7284instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{
7285  match(Set dst (AndL (ConvI2L src) mask) );
7286  size(8);
7287  format %{ "MOV    $dst.lo,$src.lo\t! zero-extend int to long\n\t"
7288            "MOV    $dst.hi, 0"%}
7289  ins_encode %{
7290    __ mov($dst$$Register, $src$$Register);
7291    __ mov($dst$$Register->successor(), 0);
7292  %}
7293  ins_pipe(ialu_reg_reg);
7294%}
7295
7296// Zero-extend long
7297instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
7298  match(Set dst (AndL src mask) );
7299  size(8);
7300  format %{ "MOV    $dst.lo,$src.lo\t! zero-extend long\n\t"
7301            "MOV    $dst.hi, 0"%}
7302  ins_encode %{
7303    __ mov($dst$$Register, $src$$Register);
7304    __ mov($dst$$Register->successor(), 0);
7305  %}
7306  ins_pipe(ialu_reg_reg);
7307%}
7308
7309instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
7310  match(Set dst (MoveF2I src));
7311  effect(DEF dst, USE src);
7312  ins_cost(MEMORY_REF_COST); // FIXME
7313
7314  size(4);
7315  format %{ "FMRS   $dst,$src\t! MoveF2I" %}
7316  ins_encode %{
7317    __ fmrs($dst$$Register, $src$$FloatRegister);
7318  %}
7319  ins_pipe(iload_mem); // FIXME
7320%}
7321
7322instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
7323  match(Set dst (MoveI2F src));
7324  ins_cost(MEMORY_REF_COST); // FIXME
7325
7326  size(4);
7327  format %{ "FMSR   $dst,$src\t! MoveI2F" %}
7328  ins_encode %{
7329    __ fmsr($dst$$FloatRegister, $src$$Register);
7330  %}
7331  ins_pipe(iload_mem); // FIXME
7332%}
7333
7334instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
7335  match(Set dst (MoveD2L src));
7336  effect(DEF dst, USE src);
7337  ins_cost(MEMORY_REF_COST); // FIXME
7338
7339  size(4);
7340  format %{ "FMRRD    $dst,$src\t! MoveD2L" %}
7341  ins_encode %{
7342    __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7343  %}
7344  ins_pipe(iload_mem); // FIXME
7345%}
7346
7347instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
7348  match(Set dst (MoveL2D src));
7349  effect(DEF dst, USE src);
7350  ins_cost(MEMORY_REF_COST); // FIXME
7351
7352  size(4);
7353  format %{ "FMDRR   $dst,$src\t! MoveL2D" %}
7354  ins_encode %{
7355    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7356  %}
7357  ins_pipe(ialu_reg_reg); // FIXME
7358%}
7359
7360//-----------
7361// Long to Double conversion
7362
7363// Magic constant, 0x43300000
7364instruct loadConI_x43300000(iRegI dst) %{
7365  effect(DEF dst);
7366  size(8);
7367  format %{ "MOV_SLOW  $dst,0x43300000\t! 2^52" %}
7368  ins_encode %{
7369    __ mov_slow($dst$$Register, 0x43300000);
7370  %}
7371  ins_pipe(ialu_none);
7372%}
7373
7374// Magic constant, 0x41f00000
7375instruct loadConI_x41f00000(iRegI dst) %{
7376  effect(DEF dst);
7377  size(8);
7378  format %{ "MOV_SLOW  $dst, 0x41f00000\t! 2^32" %}
7379  ins_encode %{
7380    __ mov_slow($dst$$Register, 0x41f00000);
7381  %}
7382  ins_pipe(ialu_none);
7383%}
7384
7385instruct loadConI_x0(iRegI dst) %{
7386  effect(DEF dst);
7387  size(4);
7388  format %{ "MOV  $dst, 0x0\t! 0" %}
7389  ins_encode %{
7390    __ mov($dst$$Register, 0);
7391  %}
7392  ins_pipe(ialu_none);
7393%}
7394
7395// Construct a double from two float halves
7396instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{
7397  effect(DEF dst, USE src1, USE src2);
7398  size(8);
7399  format %{ "FCPYS  $dst.hi,$src1.hi\n\t"
7400            "FCPYS  $dst.lo,$src2.lo" %}
7401  ins_encode %{
7402    __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor());
7403    __ fcpys($dst$$FloatRegister, $src2$$FloatRegister);
7404  %}
7405  ins_pipe(faddD_reg_reg);
7406%}
7407
7408// Convert integer in high half of a double register (in the lower half of
7409// the double register file) to double
7410instruct convI2D_regDHi_regD(regD dst, regD_low src) %{
7411  effect(DEF dst, USE src);
7412  size(4);
7413  format %{ "FSITOD  $dst,$src" %}
7414  ins_encode %{
7415    __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor());
7416  %}
7417  ins_pipe(fcvtLHi2D);
7418%}
7419
7420// Add float double precision
7421instruct addD_regD_regD(regD dst, regD src1, regD src2) %{
7422  effect(DEF dst, USE src1, USE src2);
7423  size(4);
7424  format %{ "FADDD  $dst,$src1,$src2" %}
7425  ins_encode %{
7426    __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7427  %}
7428  ins_pipe(faddD_reg_reg);
7429%}
7430
7431// Sub float double precision
7432instruct subD_regD_regD(regD dst, regD src1, regD src2) %{
7433  effect(DEF dst, USE src1, USE src2);
7434  size(4);
7435  format %{ "FSUBD  $dst,$src1,$src2" %}
7436  ins_encode %{
7437    __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7438  %}
7439  ins_pipe(faddD_reg_reg);
7440%}
7441
7442// Mul float double precision
7443instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{
7444  effect(DEF dst, USE src1, USE src2);
7445  size(4);
7446  format %{ "FMULD  $dst,$src1,$src2" %}
7447  ins_encode %{
7448    __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7449  %}
7450  ins_pipe(fmulD_reg_reg);
7451%}
7452
7453instruct regL_to_regD(regD dst, iRegL src) %{
7454  // No match rule to avoid chain rule match.
7455  effect(DEF dst, USE src);
7456  ins_cost(MEMORY_REF_COST);
7457  size(4);
7458  format %{ "FMDRR   $dst,$src\t! regL to regD" %}
7459  ins_encode %{
7460    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7461  %}
7462  ins_pipe(ialu_reg_reg); // FIXME
7463%}
7464
7465instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{
7466  // No match rule to avoid chain rule match.
7467  effect(DEF dst, USE src1, USE src2);
7468  ins_cost(MEMORY_REF_COST);
7469  size(4);
7470  format %{ "FMDRR   $dst,$src1,$src2\t! regI,regI to regD" %}
7471  ins_encode %{
7472    __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register);
7473  %}
7474  ins_pipe(ialu_reg_reg); // FIXME
7475%}
7476
7477instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{
7478  match(Set dst (ConvL2D src));
7479  ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME
7480
7481  expand %{
7482    regD_low   tmpsrc;
7483    iRegI      ix43300000;
7484    iRegI      ix41f00000;
7485    iRegI      ix0;
7486    regD_low   dx43300000;
7487    regD       dx41f00000;
7488    regD       tmp1;
7489    regD_low   tmp2;
7490    regD       tmp3;
7491    regD       tmp4;
7492
7493    regL_to_regD(tmpsrc, src);
7494
7495    loadConI_x43300000(ix43300000);
7496    loadConI_x41f00000(ix41f00000);
7497    loadConI_x0(ix0);
7498
7499    regI_regI_to_regD(dx43300000, ix0, ix43300000);
7500    regI_regI_to_regD(dx41f00000, ix0, ix41f00000);
7501
7502    convI2D_regDHi_regD(tmp1, tmpsrc);
7503    regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc);
7504    subD_regD_regD(tmp3, tmp2, dx43300000);
7505    mulD_regD_regD(tmp4, tmp1, dx41f00000);
7506    addD_regD_regD(dst, tmp3, tmp4);
7507  %}
7508%}
7509
7510instruct convL2I_reg(iRegI dst, iRegL src) %{
7511  match(Set dst (ConvL2I src));
7512  size(4);
7513  format %{ "MOV    $dst,$src.lo\t! long->int" %}
7514  ins_encode %{
7515    __ mov($dst$$Register, $src$$Register);
7516  %}
7517  ins_pipe(ialu_move_reg_I_to_L);
7518%}
7519
7520// Register Shift Right Immediate
7521instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{
7522  match(Set dst (ConvL2I (RShiftL src cnt)));
7523  size(4);
7524  format %{ "ASR    $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %}
7525  ins_encode %{
7526    if ($cnt$$constant == 32) {
7527      __ mov($dst$$Register, $src$$Register->successor());
7528    } else {
7529      __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32));
7530    }
7531  %}
7532  ins_pipe(ialu_reg_imm);
7533%}
7534
7535
7536//----------Control Flow Instructions------------------------------------------
7537// Compare Instructions
7538// Compare Integers
7539instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{
7540  match(Set icc (CmpI op1 op2));
7541  effect( DEF icc, USE op1, USE op2 );
7542
7543  size(4);
7544  format %{ "cmp_32 $op1,$op2\t! int" %}
7545  ins_encode %{
7546    __ cmp_32($op1$$Register, $op2$$Register);
7547  %}
7548  ins_pipe(ialu_cconly_reg_reg);
7549%}
7550
7551#ifdef _LP64
7552// Compare compressed pointers
7553instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{
7554  match(Set icc (CmpN op1 op2));
7555  effect( DEF icc, USE op1, USE op2 );
7556
7557  size(4);
7558  format %{ "cmp_32 $op1,$op2\t! int" %}
7559  ins_encode %{
7560    __ cmp_32($op1$$Register, $op2$$Register);
7561  %}
7562  ins_pipe(ialu_cconly_reg_reg);
7563%}
7564#endif
7565
7566instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
7567  match(Set icc (CmpU op1 op2));
7568
7569  size(4);
7570  format %{ "cmp_32 $op1,$op2\t! unsigned int" %}
7571  ins_encode %{
7572    __ cmp_32($op1$$Register, $op2$$Register);
7573  %}
7574  ins_pipe(ialu_cconly_reg_reg);
7575%}
7576
7577instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{
7578  match(Set icc (CmpI op1 op2));
7579  effect( DEF icc, USE op1 );
7580
7581  size(4);
7582  format %{ "cmn_32 $op1,-$op2\t! int" %}
7583  ins_encode %{
7584    __ cmn_32($op1$$Register, -$op2$$constant);
7585  %}
7586  ins_pipe(ialu_cconly_reg_imm);
7587%}
7588
7589instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{
7590  match(Set icc (CmpI op1 op2));
7591  effect( DEF icc, USE op1 );
7592
7593  size(4);
7594  format %{ "cmp_32 $op1,$op2\t! int" %}
7595  ins_encode %{
7596    __ cmp_32($op1$$Register, $op2$$constant);
7597  %}
7598  ins_pipe(ialu_cconly_reg_imm);
7599%}
7600
7601instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{
7602  match(Set icc (CmpI (AndI op1 op2) zero));
7603  size(4);
7604  format %{ "tst_32 $op2,$op1" %}
7605
7606  ins_encode %{
7607    __ tst_32($op1$$Register, $op2$$Register);
7608  %}
7609  ins_pipe(ialu_cconly_reg_reg_zero);
7610%}
7611
7612instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7613  match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7614  size(4);
7615  format %{ "TST   $op2,$op1<<$op3" %}
7616
7617  ins_encode %{
7618    __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register));
7619  %}
7620  ins_pipe(ialu_cconly_reg_reg_zero);
7621%}
7622
7623instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7624  match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7625  size(4);
7626  format %{ "tst_32 $op2,$op1<<$op3" %}
7627
7628  ins_encode %{
7629    __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant));
7630  %}
7631  ins_pipe(ialu_cconly_reg_reg_zero);
7632%}
7633
7634instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7635  match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7636  size(4);
7637  format %{ "TST   $op2,$op1<<$op3" %}
7638
7639  ins_encode %{
7640    __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register));
7641  %}
7642  ins_pipe(ialu_cconly_reg_reg_zero);
7643%}
7644
7645instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7646  match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7647  size(4);
7648  format %{ "tst_32 $op2,$op1<<$op3" %}
7649
7650  ins_encode %{
7651    __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant));
7652  %}
7653  ins_pipe(ialu_cconly_reg_reg_zero);
7654%}
7655
7656instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7657  match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7658  size(4);
7659  format %{ "TST   $op2,$op1<<$op3" %}
7660
7661  ins_encode %{
7662    __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register));
7663  %}
7664  ins_pipe(ialu_cconly_reg_reg_zero);
7665%}
7666
7667instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7668  match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7669  size(4);
7670  format %{ "tst_32 $op2,$op1<<$op3" %}
7671
7672  ins_encode %{
7673    __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant));
7674  %}
7675  ins_pipe(ialu_cconly_reg_reg_zero);
7676%}
7677
7678instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{
7679  match(Set icc (CmpI (AndI op1 op2) zero));
7680  size(4);
7681  format %{ "tst_32 $op2,$op1" %}
7682
7683  ins_encode %{
7684    __ tst_32($op1$$Register, $op2$$constant);
7685  %}
7686  ins_pipe(ialu_cconly_reg_imm_zero);
7687%}
7688
7689instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7690  match(Set xcc (CmpL op1 op2));
7691  effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7692
7693  size(8);
7694  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! long\n\t"
7695            "SBCS    $tmp,$op1.hi,$op2.hi" %}
7696  ins_encode %{
7697    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7698    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7699  %}
7700  ins_pipe(ialu_cconly_reg_reg);
7701%}
7702
7703instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7704  match(Set xcc (CmpUL op1 op2));
7705  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7706
7707  size(8);
7708  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
7709            "SBCS    $tmp,$op1.hi,$op2.hi" %}
7710  ins_encode %{
7711    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7712    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7713  %}
7714  ins_pipe(ialu_cconly_reg_reg);
7715%}
7716
7717instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
7718  match(Set xcc (CmpL op1 op2));
7719  effect( DEF xcc, USE op1, USE op2 );
7720
7721  size(8);
7722  format %{ "TEQ    $op1.hi,$op2.hi\t\t! long\n\t"
7723            "TEQ.eq $op1.lo,$op2.lo" %}
7724  ins_encode %{
7725    __ teq($op1$$Register->successor(), $op2$$Register->successor());
7726    __ teq($op1$$Register, $op2$$Register, eq);
7727  %}
7728  ins_pipe(ialu_cconly_reg_reg);
7729%}
7730
7731instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7732  match(Set xcc (CmpL op1 op2));
7733  effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7734
7735  size(8);
7736  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! long\n\t"
7737            "SBCS    $tmp,$op2.hi,$op1.hi" %}
7738  ins_encode %{
7739    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7740    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7741  %}
7742  ins_pipe(ialu_cconly_reg_reg);
7743%}
7744
7745// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7746// (hi($con$$constant), lo($con$$constant)) becomes
7747instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7748  match(Set xcc (CmpL op1 con));
7749  effect( DEF xcc, USE op1, USE con, TEMP tmp );
7750
7751  size(8);
7752  format %{ "SUBS    $tmp,$op1.low,$con\t\t! long\n\t"
7753            "SBCS    $tmp,$op1.hi,0" %}
7754  ins_encode %{
7755    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7756    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7757  %}
7758
7759  ins_pipe(ialu_cconly_reg_reg);
7760%}
7761
7762// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7763// (hi($con$$constant), lo($con$$constant)) becomes
7764instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{
7765  match(Set xcc (CmpL op1 con));
7766  effect( DEF xcc, USE op1, USE con );
7767
7768  size(8);
7769  format %{ "TEQ    $op1.hi,0\t\t! long\n\t"
7770            "TEQ.eq $op1.lo,$con" %}
7771  ins_encode %{
7772    __ teq($op1$$Register->successor(), 0);
7773    __ teq($op1$$Register, $con$$constant, eq);
7774  %}
7775
7776  ins_pipe(ialu_cconly_reg_reg);
7777%}
7778
7779// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7780// (hi($con$$constant), lo($con$$constant)) becomes
7781instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7782  match(Set xcc (CmpL op1 con));
7783  effect( DEF xcc, USE op1, USE con, TEMP tmp );
7784
7785  size(8);
7786  format %{ "RSBS    $tmp,$op1.low,$con\t\t! long\n\t"
7787            "RSCS    $tmp,$op1.hi,0" %}
7788  ins_encode %{
7789    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7790    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7791  %}
7792
7793  ins_pipe(ialu_cconly_reg_reg);
7794%}
7795
7796instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
7797  match(Set xcc (CmpUL op1 op2));
7798  effect(DEF xcc, USE op1, USE op2);
7799
7800  size(8);
7801  format %{ "TEQ    $op1.hi,$op2.hi\t\t! unsigned long\n\t"
7802            "TEQ.eq $op1.lo,$op2.lo" %}
7803  ins_encode %{
7804    __ teq($op1$$Register->successor(), $op2$$Register->successor());
7805    __ teq($op1$$Register, $op2$$Register, eq);
7806  %}
7807  ins_pipe(ialu_cconly_reg_reg);
7808%}
7809
7810instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7811  match(Set xcc (CmpUL op1 op2));
7812  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7813
7814  size(8);
7815  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
7816            "SBCS    $tmp,$op2.hi,$op1.hi" %}
7817  ins_encode %{
7818    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7819    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7820  %}
7821  ins_pipe(ialu_cconly_reg_reg);
7822%}
7823
7824// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7825// (hi($con$$constant), lo($con$$constant)) becomes
7826instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7827  match(Set xcc (CmpUL op1 con));
7828  effect(DEF xcc, USE op1, USE con, TEMP tmp);
7829
7830  size(8);
7831  format %{ "SUBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7832            "SBCS    $tmp,$op1.hi,0" %}
7833  ins_encode %{
7834    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7835    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7836  %}
7837
7838  ins_pipe(ialu_cconly_reg_reg);
7839%}
7840
7841// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7842// (hi($con$$constant), lo($con$$constant)) becomes
7843instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
7844  match(Set xcc (CmpUL op1 con));
7845  effect(DEF xcc, USE op1, USE con);
7846
7847  size(8);
7848  format %{ "TEQ    $op1.hi,0\t\t! unsigned long\n\t"
7849            "TEQ.eq $op1.lo,$con" %}
7850  ins_encode %{
7851    __ teq($op1$$Register->successor(), 0);
7852    __ teq($op1$$Register, $con$$constant, eq);
7853  %}
7854
7855  ins_pipe(ialu_cconly_reg_reg);
7856%}
7857
7858// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7859// (hi($con$$constant), lo($con$$constant)) becomes
7860instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7861  match(Set xcc (CmpUL op1 con));
7862  effect(DEF xcc, USE op1, USE con, TEMP tmp);
7863
7864  size(8);
7865  format %{ "RSBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7866            "RSCS    $tmp,$op1.hi,0" %}
7867  ins_encode %{
7868    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7869    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7870  %}
7871
7872  ins_pipe(ialu_cconly_reg_reg);
7873%}
7874
7875/* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
7876/*   match(Set xcc (CmpL (AndL op1 op2) zero)); */
7877/*   ins_encode %{ */
7878/*     __ stop("testL_reg_reg unimplemented"); */
7879/*   %} */
7880/*   ins_pipe(ialu_cconly_reg_reg); */
7881/* %} */
7882
7883/* // useful for checking the alignment of a pointer: */
7884/* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */
7885/*   match(Set xcc (CmpL (AndL op1 con) zero)); */
7886/*   ins_encode %{ */
7887/*     __ stop("testL_reg_con unimplemented"); */
7888/*   %} */
7889/*   ins_pipe(ialu_cconly_reg_reg); */
7890/* %} */
7891
7892instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{
7893  match(Set icc (CmpU op1 op2));
7894
7895  size(4);
7896  format %{ "cmp_32 $op1,$op2\t! unsigned" %}
7897  ins_encode %{
7898    __ cmp_32($op1$$Register, $op2$$constant);
7899  %}
7900  ins_pipe(ialu_cconly_reg_imm);
7901%}
7902
7903// Compare Pointers
7904instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
7905  match(Set pcc (CmpP op1 op2));
7906
7907  size(4);
7908  format %{ "CMP    $op1,$op2\t! ptr" %}
7909  ins_encode %{
7910    __ cmp($op1$$Register, $op2$$Register);
7911  %}
7912  ins_pipe(ialu_cconly_reg_reg);
7913%}
7914
7915instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{
7916  match(Set pcc (CmpP op1 op2));
7917
7918  size(4);
7919  format %{ "CMP    $op1,$op2\t! ptr" %}
7920  ins_encode %{
7921    assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?");
7922    __ cmp($op1$$Register, $op2$$constant);
7923  %}
7924  ins_pipe(ialu_cconly_reg_imm);
7925%}
7926
7927//----------Max and Min--------------------------------------------------------
7928// Min Instructions
7929// Conditional move for min
7930instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{
7931  effect( USE_DEF op2, USE op1, USE icc );
7932
7933  size(4);
7934  format %{ "MOV.lt  $op2,$op1\t! min" %}
7935  ins_encode %{
7936    __ mov($op2$$Register, $op1$$Register, lt);
7937  %}
7938  ins_pipe(ialu_reg_flags);
7939%}
7940
7941// Min Register with Register.
7942instruct minI_eReg(iRegI op1, iRegI op2) %{
7943  match(Set op2 (MinI op1 op2));
7944  ins_cost(DEFAULT_COST*2);
7945  expand %{
7946    flagsReg icc;
7947    compI_iReg(icc,op1,op2);
7948    cmovI_reg_lt(op2,op1,icc);
7949  %}
7950%}
7951
7952// Max Instructions
7953// Conditional move for max
7954instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{
7955  effect( USE_DEF op2, USE op1, USE icc );
7956  format %{ "MOV.gt  $op2,$op1\t! max" %}
7957  ins_encode %{
7958    __ mov($op2$$Register, $op1$$Register, gt);
7959  %}
7960  ins_pipe(ialu_reg_flags);
7961%}
7962
7963// Max Register with Register
7964instruct maxI_eReg(iRegI op1, iRegI op2) %{
7965  match(Set op2 (MaxI op1 op2));
7966  ins_cost(DEFAULT_COST*2);
7967  expand %{
7968    flagsReg icc;
7969    compI_iReg(icc,op1,op2);
7970    cmovI_reg_gt(op2,op1,icc);
7971  %}
7972%}
7973
7974
7975//----------Float Compares----------------------------------------------------
7976// Compare floating, generate condition code
7977instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{
7978  match(Set icc (CmpF src1 src2));
7979  effect(KILL fcc);
7980
7981  size(8);
7982  format %{ "FCMPs  $src1,$src2\n\t"
7983            "FMSTAT" %}
7984  ins_encode %{
7985    __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7986    __ fmstat();
7987  %}
7988  ins_pipe(faddF_fcc_reg_reg_zero);
7989%}
7990
7991instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{
7992  match(Set icc (CmpF src1 src2));
7993  effect(KILL fcc);
7994
7995  size(8);
7996  format %{ "FCMPs  $src1,$src2\n\t"
7997            "FMSTAT" %}
7998  ins_encode %{
7999    __ fcmpzs($src1$$FloatRegister);
8000    __ fmstat();
8001  %}
8002  ins_pipe(faddF_fcc_reg_reg_zero);
8003%}
8004
8005instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{
8006  match(Set icc (CmpD src1 src2));
8007  effect(KILL fcc);
8008
8009  size(8);
8010  format %{ "FCMPd  $src1,$src2 \n\t"
8011            "FMSTAT" %}
8012  ins_encode %{
8013    __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
8014    __ fmstat();
8015  %}
8016  ins_pipe(faddD_fcc_reg_reg_zero);
8017%}
8018
8019instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{
8020  match(Set icc (CmpD src1 src2));
8021  effect(KILL fcc);
8022
8023  size(8);
8024  format %{ "FCMPZd  $src1,$src2 \n\t"
8025            "FMSTAT" %}
8026  ins_encode %{
8027    __ fcmpzd($src1$$FloatRegister);
8028    __ fmstat();
8029  %}
8030  ins_pipe(faddD_fcc_reg_reg_zero);
8031%}
8032
8033// Compare floating, generate -1,0,1
8034instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{
8035  match(Set dst (CmpF3 src1 src2));
8036  effect(KILL fcc);
8037  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
8038  size(20);
8039  // same number of instructions as code using conditional moves but
8040  // doesn't kill integer condition register
8041  format %{ "FCMPs  $dst,$src1,$src2 \n\t"
8042            "VMRS   $dst, FPSCR \n\t"
8043            "OR     $dst, $dst, 0x08000000 \n\t"
8044            "EOR    $dst, $dst, $dst << 3 \n\t"
8045            "MOV    $dst, $dst >> 30" %}
8046  ins_encode %{
8047    __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
8048    __ floating_cmp($dst$$Register);
8049  %}
8050  ins_pipe( floating_cmp );
8051%}
8052
8053instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{
8054  match(Set dst (CmpF3 src1 src2));
8055  effect(KILL fcc);
8056  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
8057  size(20);
8058  // same number of instructions as code using conditional moves but
8059  // doesn't kill integer condition register
8060  format %{ "FCMPZs $dst,$src1,$src2 \n\t"
8061            "VMRS   $dst, FPSCR \n\t"
8062            "OR     $dst, $dst, 0x08000000 \n\t"
8063            "EOR    $dst, $dst, $dst << 3 \n\t"
8064            "MOV    $dst, $dst >> 30" %}
8065  ins_encode %{
8066    __ fcmpzs($src1$$FloatRegister);
8067    __ floating_cmp($dst$$Register);
8068  %}
8069  ins_pipe( floating_cmp );
8070%}
8071
8072instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{
8073  match(Set dst (CmpD3 src1 src2));
8074  effect(KILL fcc);
8075  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
8076  size(20);
8077  // same number of instructions as code using conditional moves but
8078  // doesn't kill integer condition register
8079  format %{ "FCMPd  $dst,$src1,$src2 \n\t"
8080            "VMRS   $dst, FPSCR \n\t"
8081            "OR     $dst, $dst, 0x08000000 \n\t"
8082            "EOR    $dst, $dst, $dst << 3 \n\t"
8083            "MOV    $dst, $dst >> 30" %}
8084  ins_encode %{
8085    __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
8086    __ floating_cmp($dst$$Register);
8087  %}
8088  ins_pipe( floating_cmp );
8089%}
8090
8091instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{
8092  match(Set dst (CmpD3 src1 src2));
8093  effect(KILL fcc);
8094  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
8095  size(20);
8096  // same number of instructions as code using conditional moves but
8097  // doesn't kill integer condition register
8098  format %{ "FCMPZd $dst,$src1,$src2 \n\t"
8099            "VMRS   $dst, FPSCR \n\t"
8100            "OR     $dst, $dst, 0x08000000 \n\t"
8101            "EOR    $dst, $dst, $dst << 3 \n\t"
8102            "MOV    $dst, $dst >> 30" %}
8103  ins_encode %{
8104    __ fcmpzd($src1$$FloatRegister);
8105    __ floating_cmp($dst$$Register);
8106  %}
8107  ins_pipe( floating_cmp );
8108%}
8109
8110//----------Branches---------------------------------------------------------
8111// Jump
8112// (compare 'operand indIndex' and 'instruct addP_reg_reg' above)
8113// FIXME
8114instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{
8115  match(Jump switch_val);
8116  effect(TEMP tmp);
8117  ins_cost(350);
8118  format %{  "ADD    $tmp, $constanttablebase, $switch_val\n\t"
8119             "LDR    $tmp,[$tmp + $constantoffset]\n\t"
8120             "BX     $tmp" %}
8121  size(20);
8122  ins_encode %{
8123    Register table_reg;
8124    Register label_reg = $tmp$$Register;
8125    if (constant_offset() == 0) {
8126      table_reg = $constanttablebase;
8127      __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
8128    } else {
8129      table_reg = $tmp$$Register;
8130      int offset = $constantoffset;
8131      if (is_memoryP(offset)) {
8132        __ add(table_reg, $constanttablebase, $switch_val$$Register);
8133        __ ldr(label_reg, Address(table_reg, offset));
8134      } else {
8135        __ mov_slow(table_reg, $constantoffset);
8136        __ add(table_reg, $constanttablebase, table_reg);
8137        __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
8138      }
8139    }
8140    __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor?
8141    //    __ ldr(PC, Address($table$$Register, $switch_val$$Register));
8142  %}
8143  ins_pipe(ialu_reg_reg);
8144%}
8145
8146// // Direct Branch.
8147instruct branch(label labl) %{
8148  match(Goto);
8149  effect(USE labl);
8150
8151  size(4);
8152  ins_cost(BRANCH_COST);
8153  format %{ "B     $labl" %}
8154  ins_encode %{
8155    __ b(*($labl$$label));
8156  %}
8157  ins_pipe(br);
8158%}
8159
8160// Conditional Direct Branch
8161instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
8162  match(If cmp icc);
8163  effect(USE labl);
8164
8165  size(4);
8166  ins_cost(BRANCH_COST);
8167  format %{ "B$cmp   $icc,$labl" %}
8168  ins_encode %{
8169    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8170  %}
8171  ins_pipe(br_cc);
8172%}
8173
8174#ifdef ARM
8175instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{
8176  match(If cmp icc);
8177  effect(USE labl);
8178  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);
8179
8180  size(4);
8181  ins_cost(BRANCH_COST);
8182  format %{ "B$cmp   $icc,$labl" %}
8183  ins_encode %{
8184    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8185  %}
8186  ins_pipe(br_cc);
8187%}
8188#endif
8189
8190
8191instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
8192  match(If cmp icc);
8193  effect(USE labl);
8194
8195  size(4);
8196  ins_cost(BRANCH_COST);
8197  format %{ "B$cmp  $icc,$labl" %}
8198  ins_encode %{
8199    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8200  %}
8201  ins_pipe(br_cc);
8202%}
8203
8204instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{
8205  match(If cmp pcc);
8206  effect(USE labl);
8207
8208  size(4);
8209  ins_cost(BRANCH_COST);
8210  format %{ "B$cmp  $pcc,$labl" %}
8211  ins_encode %{
8212    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8213  %}
8214  ins_pipe(br_cc);
8215%}
8216
8217instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{
8218  match(If cmp xcc);
8219  effect(USE labl);
8220  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8221
8222  size(4);
8223  ins_cost(BRANCH_COST);
8224  format %{ "B$cmp  $xcc,$labl" %}
8225  ins_encode %{
8226    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8227  %}
8228  ins_pipe(br_cc);
8229%}
8230
8231instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{
8232  match(If cmp xcc);
8233  effect(USE labl);
8234  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8235
8236  size(4);
8237  ins_cost(BRANCH_COST);
8238  format %{ "B$cmp  $xcc,$labl" %}
8239  ins_encode %{
8240    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8241  %}
8242  ins_pipe(br_cc);
8243%}
8244
8245instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
8246  match(If cmp xcc);
8247  effect(USE labl);
8248  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
8249
8250  size(4);
8251  ins_cost(BRANCH_COST);
8252  format %{ "B$cmp  $xcc,$labl" %}
8253  ins_encode %{
8254    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8255  %}
8256  ins_pipe(br_cc);
8257%}
8258
8259instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
8260  match(If cmp xcc);
8261  effect(USE labl);
8262  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8263
8264  size(4);
8265  ins_cost(BRANCH_COST);
8266  format %{ "B$cmp  $xcc,$labl" %}
8267  ins_encode %{
8268    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8269  %}
8270  ins_pipe(br_cc);
8271%}
8272
8273instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
8274  match(If cmp xcc);
8275  effect(USE labl);
8276  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8277
8278  size(4);
8279  ins_cost(BRANCH_COST);
8280  format %{ "B$cmp  $xcc,$labl" %}
8281  ins_encode %{
8282    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8283  %}
8284  ins_pipe(br_cc);
8285%}
8286
8287instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
8288  match(If cmp xcc);
8289  effect(USE labl);
8290  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
8291
8292  size(4);
8293  ins_cost(BRANCH_COST);
8294  format %{ "B$cmp  $xcc,$labl" %}
8295  ins_encode %{
8296    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8297  %}
8298  ins_pipe(br_cc);
8299%}
8300
8301instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
8302  match(CountedLoopEnd cmp icc);
8303  effect(USE labl);
8304
8305  size(4);
8306  ins_cost(BRANCH_COST);
8307  format %{ "B$cmp   $icc,$labl\t! Loop end" %}
8308  ins_encode %{
8309    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8310  %}
8311  ins_pipe(br_cc);
8312%}
8313
8314// instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{
8315//   match(CountedLoopEnd cmp icc);
8316//   ins_pipe(br_cc);
8317// %}
8318
8319// ============================================================================
8320// Long Compare
8321//
8322// Currently we hold longs in 2 registers.  Comparing such values efficiently
8323// is tricky.  The flavor of compare used depends on whether we are testing
8324// for LT, LE, or EQ.  For a simple LT test we can check just the sign bit.
8325// The GE test is the negated LT test.  The LE test can be had by commuting
8326// the operands (yielding a GE test) and then negating; negate again for the
8327// GT test.  The EQ test is done by ORcc'ing the high and low halves, and the
8328// NE test is negated from that.
8329
8330// Due to a shortcoming in the ADLC, it mixes up expressions like:
8331// (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)).  Note the
8332// difference between 'Y' and '0L'.  The tree-matches for the CmpI sections
8333// are collapsed internally in the ADLC's dfa-gen code.  The match for
8334// (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
8335// foo match ends up with the wrong leaf.  One fix is to not match both
8336// reg-reg and reg-zero forms of long-compare.  This is unfortunate because
8337// both forms beat the trinary form of long-compare and both are very useful
8338// on Intel which has so few registers.
8339
8340// instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
8341//   match(If cmp xcc);
8342//   ins_pipe(br_cc);
8343// %}
8344
8345// Manifest a CmpL3 result in an integer register.  Very painful.
8346// This is the test to avoid.
8347instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
8348  match(Set dst (CmpL3 src1 src2) );
8349  effect( KILL ccr );
8350  ins_cost(6*DEFAULT_COST); // FIXME
8351  size(32);
8352  format %{
8353      "CMP    $src1.hi, $src2.hi\t\t! long\n"
8354    "\tMOV.gt $dst, 1\n"
8355    "\tmvn.lt $dst, 0\n"
8356    "\tB.ne   done\n"
8357    "\tSUBS   $dst, $src1.lo, $src2.lo\n"
8358    "\tMOV.hi $dst, 1\n"
8359    "\tmvn.lo $dst, 0\n"
8360    "done:"     %}
8361  ins_encode %{
8362    Label done;
8363    __ cmp($src1$$Register->successor(), $src2$$Register->successor());
8364    __ mov($dst$$Register, 1, gt);
8365    __ mvn($dst$$Register, 0, lt);
8366    __ b(done, ne);
8367    __ subs($dst$$Register, $src1$$Register, $src2$$Register);
8368    __ mov($dst$$Register, 1, hi);
8369    __ mvn($dst$$Register, 0, lo);
8370    __ bind(done);
8371  %}
8372  ins_pipe(cmpL_reg);
8373%}
8374
8375// Conditional move
8376instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{
8377  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8378  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8379
8380  ins_cost(150);
8381  size(8);
8382  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8383            "MOV$cmp  $dst,$src.hi" %}
8384  ins_encode %{
8385    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8386    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8387  %}
8388  ins_pipe(ialu_reg);
8389%}
8390
8391instruct cmovLL_reg_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{
8392  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8393  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8394
8395  ins_cost(150);
8396  size(8);
8397  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8398            "MOV$cmp  $dst,$src.hi" %}
8399  ins_encode %{
8400    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8401    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8402  %}
8403  ins_pipe(ialu_reg);
8404%}
8405
8406instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{
8407  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8408  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8409
8410  ins_cost(150);
8411  size(8);
8412  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8413            "MOV$cmp  $dst,$src.hi" %}
8414  ins_encode %{
8415    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8416    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8417  %}
8418  ins_pipe(ialu_reg);
8419%}
8420
8421instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{
8422  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8423  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8424
8425  ins_cost(150);
8426  size(8);
8427  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8428            "MOV$cmp  $dst,$src.hi" %}
8429  ins_encode %{
8430    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8431    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8432  %}
8433  ins_pipe(ialu_reg);
8434%}
8435
8436instruct cmovLL_reg_LEGT_U(cmpOpL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{
8437  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8438  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8439
8440  ins_cost(150);
8441  size(8);
8442  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8443            "MOV$cmp  $dst,$src.hi" %}
8444  ins_encode %{
8445    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8446    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8447  %}
8448  ins_pipe(ialu_reg);
8449%}
8450
8451instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{
8452  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8453  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8454  ins_cost(140);
8455  size(8);
8456  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8457            "MOV$cmp  $dst,0" %}
8458  ins_encode %{
8459    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8460    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8461  %}
8462  ins_pipe(ialu_imm);
8463%}
8464
8465instruct cmovLL_imm_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{
8466  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8467  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8468  ins_cost(140);
8469  size(8);
8470  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8471            "MOV$cmp  $dst,0" %}
8472  ins_encode %{
8473    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8474    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8475  %}
8476  ins_pipe(ialu_imm);
8477%}
8478
8479instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{
8480  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8481  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8482  ins_cost(140);
8483  size(8);
8484  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8485            "MOV$cmp  $dst,0" %}
8486  ins_encode %{
8487    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8488    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8489  %}
8490  ins_pipe(ialu_imm);
8491%}
8492
8493instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{
8494  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8495  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8496  ins_cost(140);
8497  size(8);
8498  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8499            "MOV$cmp  $dst,0" %}
8500  ins_encode %{
8501    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8502    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8503  %}
8504  ins_pipe(ialu_imm);
8505%}
8506
8507instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{
8508  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8509  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8510
8511  ins_cost(150);
8512  size(4);
8513  format %{ "MOV$cmp  $dst,$src" %}
8514  ins_encode %{
8515    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8516  %}
8517  ins_pipe(ialu_reg);
8518%}
8519
8520instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{
8521  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8522  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8523
8524  ins_cost(150);
8525  size(4);
8526  format %{ "MOV$cmp  $dst,$src" %}
8527  ins_encode %{
8528    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8529  %}
8530  ins_pipe(ialu_reg);
8531%}
8532
8533instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{
8534  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8535  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8536
8537  ins_cost(150);
8538  size(4);
8539  format %{ "MOV$cmp  $dst,$src" %}
8540  ins_encode %{
8541    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8542  %}
8543  ins_pipe(ialu_reg);
8544%}
8545
8546instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{
8547  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8548  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8549
8550  ins_cost(140);
8551  format %{ "MOVW$cmp  $dst,$src" %}
8552  ins_encode %{
8553    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8554  %}
8555  ins_pipe(ialu_imm);
8556%}
8557
8558instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{
8559  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8560  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8561
8562  ins_cost(140);
8563  format %{ "MOVW$cmp  $dst,$src" %}
8564  ins_encode %{
8565    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8566  %}
8567  ins_pipe(ialu_imm);
8568%}
8569
8570instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{
8571  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8572  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8573
8574  ins_cost(140);
8575  format %{ "MOVW$cmp  $dst,$src" %}
8576  ins_encode %{
8577    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8578  %}
8579  ins_pipe(ialu_imm);
8580%}
8581
8582instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{
8583  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8584  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8585
8586  ins_cost(150);
8587  size(4);
8588  format %{ "MOV$cmp  $dst,$src" %}
8589  ins_encode %{
8590    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8591  %}
8592  ins_pipe(ialu_reg);
8593%}
8594
8595instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{
8596  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8597  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8598
8599  ins_cost(150);
8600  size(4);
8601  format %{ "MOV$cmp  $dst,$src" %}
8602  ins_encode %{
8603    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8604  %}
8605  ins_pipe(ialu_reg);
8606%}
8607
8608instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{
8609  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8610  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8611
8612  ins_cost(150);
8613  size(4);
8614  format %{ "MOV$cmp  $dst,$src" %}
8615  ins_encode %{
8616    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8617  %}
8618  ins_pipe(ialu_reg);
8619%}
8620
8621instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{
8622  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8623  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8624
8625  ins_cost(140);
8626  format %{ "MOVW$cmp  $dst,$src" %}
8627  ins_encode %{
8628    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8629  %}
8630  ins_pipe(ialu_imm);
8631%}
8632
8633instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{
8634  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8635  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8636
8637  ins_cost(140);
8638  format %{ "MOVW$cmp  $dst,$src" %}
8639  ins_encode %{
8640    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8641  %}
8642  ins_pipe(ialu_imm);
8643%}
8644
8645instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{
8646  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8647  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8648
8649  ins_cost(140);
8650  format %{ "MOVW$cmp  $dst,$src" %}
8651  ins_encode %{
8652    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8653  %}
8654  ins_pipe(ialu_imm);
8655%}
8656
8657instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{
8658  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8659  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8660  ins_cost(150);
8661  size(4);
8662  format %{ "FCPYS$cmp $dst,$src" %}
8663  ins_encode %{
8664    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8665  %}
8666  ins_pipe(int_conditional_float_move);
8667%}
8668
8669instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{
8670  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8671  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8672  ins_cost(150);
8673  size(4);
8674  format %{ "FCPYS$cmp $dst,$src" %}
8675  ins_encode %{
8676    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8677  %}
8678  ins_pipe(int_conditional_float_move);
8679%}
8680
8681instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{
8682  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8683  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8684  ins_cost(150);
8685  size(4);
8686  format %{ "FCPYS$cmp $dst,$src" %}
8687  ins_encode %{
8688    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8689  %}
8690  ins_pipe(int_conditional_float_move);
8691%}
8692
8693instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{
8694  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8695  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8696
8697  ins_cost(150);
8698  size(4);
8699  format %{ "FCPYD$cmp $dst,$src" %}
8700  ins_encode %{
8701    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8702  %}
8703  ins_pipe(int_conditional_float_move);
8704%}
8705
8706instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{
8707  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8708  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8709
8710  ins_cost(150);
8711  size(4);
8712  format %{ "FCPYD$cmp $dst,$src" %}
8713  ins_encode %{
8714    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8715  %}
8716  ins_pipe(int_conditional_float_move);
8717%}
8718
8719instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{
8720  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8721  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt );
8722
8723  ins_cost(150);
8724  size(4);
8725  format %{ "FCPYD$cmp $dst,$src" %}
8726  ins_encode %{
8727    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8728  %}
8729  ins_pipe(int_conditional_float_move);
8730%}
8731
8732// ============================================================================
8733// Safepoint Instruction
8734// rather than KILL R12, it would be better to use any reg as
8735// TEMP. Can't do that at this point because it crashes the compiler
8736instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
8737  match(SafePoint poll);
8738  effect(USE poll, KILL tmp, KILL icc);
8739
8740  size(4);
8741  format %{ "LDR   $tmp,[$poll]\t! Safepoint: poll for GC" %}
8742  ins_encode %{
8743    __ relocate(relocInfo::poll_type);
8744    __ ldr($tmp$$Register, Address($poll$$Register));
8745  %}
8746  ins_pipe(loadPollP);
8747%}
8748
8749
8750// ============================================================================
8751// Call Instructions
8752// Call Java Static Instruction
8753instruct CallStaticJavaDirect( method meth ) %{
8754  match(CallStaticJava);
8755  predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
8756  effect(USE meth);
8757
8758  ins_cost(CALL_COST);
8759  format %{ "CALL,static ==> " %}
8760  ins_encode( Java_Static_Call( meth ), call_epilog );
8761  ins_pipe(simple_call);
8762%}
8763
8764// Call Java Static Instruction (method handle version)
8765instruct CallStaticJavaHandle( method meth ) %{
8766  match(CallStaticJava);
8767  predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
8768  effect(USE meth);
8769  // FP is saved by all callees (for interpreter stack correction).
8770  // We use it here for a similar purpose, in {preserve,restore}_FP.
8771
8772  ins_cost(CALL_COST);
8773  format %{ "CALL,static/MethodHandle ==> " %}
8774  ins_encode( preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog );
8775  ins_pipe(simple_call);
8776%}
8777
8778// Call Java Dynamic Instruction
8779instruct CallDynamicJavaDirect( method meth ) %{
8780  match(CallDynamicJava);
8781  effect(USE meth);
8782
8783  ins_cost(CALL_COST);
8784  format %{ "MOV_OOP    (empty),R_R8\n\t"
8785            "CALL,dynamic  ; NOP ==> " %}
8786  ins_encode( Java_Dynamic_Call( meth ), call_epilog );
8787  ins_pipe(call);
8788%}
8789
8790// Call Runtime Instruction
8791instruct CallRuntimeDirect(method meth) %{
8792  match(CallRuntime);
8793  effect(USE meth);
8794  ins_cost(CALL_COST);
8795  format %{ "CALL,runtime" %}
8796  ins_encode( Java_To_Runtime( meth ),
8797              call_epilog );
8798  ins_pipe(simple_call);
8799%}
8800
8801// Call runtime without safepoint - same as CallRuntime
8802instruct CallLeafDirect(method meth) %{
8803  match(CallLeaf);
8804  effect(USE meth);
8805  ins_cost(CALL_COST);
8806  format %{ "CALL,runtime leaf" %}
8807  // TODO: ned save_last_PC here?
8808  ins_encode( Java_To_Runtime( meth ),
8809              call_epilog );
8810  ins_pipe(simple_call);
8811%}
8812
8813// Call runtime without safepoint - same as CallLeaf
8814instruct CallLeafNoFPDirect(method meth) %{
8815  match(CallLeafNoFP);
8816  effect(USE meth);
8817  ins_cost(CALL_COST);
8818  format %{ "CALL,runtime leaf nofp" %}
8819  // TODO: ned save_last_PC here?
8820  ins_encode( Java_To_Runtime( meth ),
8821              call_epilog );
8822  ins_pipe(simple_call);
8823%}
8824
8825// Tail Call; Jump from runtime stub to Java code.
8826// Also known as an 'interprocedural jump'.
8827// Target of jump will eventually return to caller.
8828// TailJump below removes the return address.
8829instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{
8830  match(TailCall jump_target method_ptr);
8831
8832  ins_cost(CALL_COST);
8833  format %{ "MOV    Rexception_pc, LR\n\t"
8834            "jump   $jump_target  \t! $method_ptr holds method" %}
8835  ins_encode %{
8836    __ mov(Rexception_pc, LR);   // this is used only to call
8837                                 // StubRoutines::forward_exception_entry()
8838                                 // which expects PC of exception in
8839                                 // R5. FIXME?
8840    __ jump($jump_target$$Register);
8841  %}
8842  ins_pipe(tail_call);
8843%}
8844
8845
8846// Return Instruction
8847instruct Ret() %{
8848  match(Return);
8849
8850  format %{ "ret LR" %}
8851
8852  ins_encode %{
8853    __ ret(LR);
8854  %}
8855
8856  ins_pipe(br);
8857%}
8858
8859
8860// Tail Jump; remove the return address; jump to target.
8861// TailCall above leaves the return address around.
8862// TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2).
8863// ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a
8864// "restore" before this instruction (in Epilogue), we need to materialize it
8865// in %i0.
8866instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{
8867  match( TailJump jump_target ex_oop );
8868  ins_cost(CALL_COST);
8869  format %{ "MOV    Rexception_pc, LR\n\t"
8870            "jump   $jump_target \t! $ex_oop holds exc. oop" %}
8871  ins_encode %{
8872    __ mov(Rexception_pc, LR);
8873    __ jump($jump_target$$Register);
8874  %}
8875  ins_pipe(tail_call);
8876%}
8877
8878// Create exception oop: created by stack-crawling runtime code.
8879// Created exception is now available to this handler, and is setup
8880// just prior to jumping to this handler.  No code emitted.
8881instruct CreateException( RExceptionRegP ex_oop )
8882%{
8883  match(Set ex_oop (CreateEx));
8884  ins_cost(0);
8885
8886  size(0);
8887  // use the following format syntax
8888  format %{ "! exception oop is in Rexception_obj; no code emitted" %}
8889  ins_encode();
8890  ins_pipe(empty);
8891%}
8892
8893
8894// Rethrow exception:
8895// The exception oop will come in the first argument position.
8896// Then JUMP (not call) to the rethrow stub code.
8897instruct RethrowException()
8898%{
8899  match(Rethrow);
8900  ins_cost(CALL_COST);
8901
8902  // use the following format syntax
8903  format %{ "b    rethrow_stub" %}
8904  ins_encode %{
8905    Register scratch = R1_tmp;
8906    assert_different_registers(scratch, c_rarg0, LR);
8907    __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch);
8908  %}
8909  ins_pipe(tail_call);
8910%}
8911
8912
8913// Die now
8914instruct ShouldNotReachHere( )
8915%{
8916  match(Halt);
8917  ins_cost(CALL_COST);
8918
8919  // Use the following format syntax
8920  format %{ "ShouldNotReachHere" %}
8921  ins_encode %{
8922    if (is_reachable()) {
8923      __ stop(_halt_reason);
8924    }
8925  %}
8926  ins_pipe(tail_call);
8927%}
8928
8929// ============================================================================
8930// The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
8931// array for an instance of the superklass.  Set a hidden internal cache on a
8932// hit (cache is checked with exposed code in gen_subtype_check()).  Return
8933// not zero for a miss or zero for a hit.  The encoding ALSO sets flags.
8934instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{
8935  match(Set index (PartialSubtypeCheck sub super));
8936  effect( KILL pcc, KILL lr );
8937  ins_cost(DEFAULT_COST*10);
8938  format %{ "CALL   PartialSubtypeCheck" %}
8939  ins_encode %{
8940    __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type);
8941  %}
8942  ins_pipe(partial_subtype_check_pipe);
8943%}
8944
8945/* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */
8946/*   match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */
8947/*   ins_pipe(partial_subtype_check_pipe); */
8948/* %} */
8949
8950
8951// ============================================================================
8952// inlined locking and unlocking
8953
8954instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch )
8955%{
8956  match(Set pcc (FastLock object box));
8957  predicate(!(UseBiasedLocking && !UseOptoBiasInlining));
8958
8959  effect(TEMP scratch, TEMP scratch2);
8960  ins_cost(DEFAULT_COST*3);
8961
8962  format %{ "FASTLOCK  $object, $box; KILL $scratch, $scratch2" %}
8963  ins_encode %{
8964    __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
8965  %}
8966  ins_pipe(long_memory_op);
8967%}
8968
8969instruct cmpFastLock_noBiasInline(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2,
8970                                  iRegP scratch, iRegP scratch3) %{
8971  match(Set pcc (FastLock object box));
8972  predicate(UseBiasedLocking && !UseOptoBiasInlining);
8973
8974  effect(TEMP scratch, TEMP scratch2, TEMP scratch3);
8975  ins_cost(DEFAULT_COST*5);
8976
8977  format %{ "FASTLOCK  $object, $box; KILL $scratch, $scratch2, $scratch3" %}
8978  ins_encode %{
8979    __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register);
8980  %}
8981  ins_pipe(long_memory_op);
8982%}
8983
8984
8985instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{
8986  match(Set pcc (FastUnlock object box));
8987  effect(TEMP scratch, TEMP scratch2);
8988  ins_cost(100);
8989
8990  format %{ "FASTUNLOCK  $object, $box; KILL $scratch, $scratch2" %}
8991  ins_encode %{
8992    __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
8993  %}
8994  ins_pipe(long_memory_op);
8995%}
8996
8997// Count and Base registers are fixed because the allocator cannot
8998// kill unknown registers.  The encodings are generic.
8999instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{
9000  match(Set dummy (ClearArray cnt base));
9001  effect(TEMP temp, TEMP zero, KILL cpsr);
9002  ins_cost(300);
9003  format %{ "MOV    $zero,0\n"
9004      "        MOV    $temp,$cnt\n"
9005      "loop:   SUBS   $temp,$temp,4\t! Count down a dword of bytes\n"
9006      "        STR.ge $zero,[$base+$temp]\t! delay slot"
9007      "        B.gt   loop\t\t! Clearing loop\n" %}
9008  ins_encode %{
9009    __ mov($zero$$Register, 0);
9010    __ mov($temp$$Register, $cnt$$Register);
9011    Label(loop);
9012    __ bind(loop);
9013    __ subs($temp$$Register, $temp$$Register, 4);
9014    __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge);
9015    __ b(loop, gt);
9016  %}
9017  ins_pipe(long_memory_op);
9018%}
9019
9020#ifdef XXX
9021// FIXME: Why R0/R1/R2/R3?
9022instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result,
9023                        iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
9024  predicate(!CompactStrings);
9025  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
9026  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2);
9027  ins_cost(300);
9028  format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result   // TEMP $tmp1, $tmp2" %}
9029  ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) );
9030
9031  ins_pipe(long_memory_op);
9032%}
9033
9034// FIXME: Why R0/R1/R2?
9035instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2,
9036                       flagsReg ccr) %{
9037  predicate(!CompactStrings);
9038  match(Set result (StrEquals (Binary str1 str2) cnt));
9039  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr);
9040
9041  ins_cost(300);
9042  format %{ "String Equals $str1,$str2,$cnt -> $result   // TEMP $tmp1, $tmp2" %}
9043  ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) );
9044  ins_pipe(long_memory_op);
9045%}
9046
9047// FIXME: Why R0/R1?
9048instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result,
9049                      flagsReg ccr) %{
9050  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
9051  match(Set result (AryEq ary1 ary2));
9052  effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr);
9053
9054  ins_cost(300);
9055  format %{ "Array Equals $ary1,$ary2 -> $result   // TEMP $tmp1,$tmp2,$tmp3" %}
9056  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result));
9057  ins_pipe(long_memory_op);
9058%}
9059#endif
9060
9061//---------- Zeros Count Instructions ------------------------------------------
9062
9063instruct countLeadingZerosI(iRegI dst, iRegI src) %{
9064  match(Set dst (CountLeadingZerosI src));
9065  size(4);
9066  format %{ "CLZ_32 $dst,$src" %}
9067  ins_encode %{
9068    __ clz_32($dst$$Register, $src$$Register);
9069  %}
9070  ins_pipe(ialu_reg);
9071%}
9072
9073instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9074  match(Set dst (CountLeadingZerosL src));
9075  effect(TEMP tmp, TEMP dst, KILL ccr);
9076  size(16);
9077  format %{ "CLZ    $dst,$src.hi\n\t"
9078            "TEQ    $dst,32\n\t"
9079            "CLZ.eq $tmp,$src.lo\n\t"
9080            "ADD.eq $dst, $dst, $tmp\n\t" %}
9081  ins_encode %{
9082    __ clz($dst$$Register, $src$$Register->successor());
9083    __ teq($dst$$Register, 32);
9084    __ clz($tmp$$Register, $src$$Register, eq);
9085    __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9086  %}
9087  ins_pipe(ialu_reg);
9088%}
9089
9090instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{
9091  match(Set dst (CountTrailingZerosI src));
9092  effect(TEMP tmp);
9093  size(8);
9094  format %{ "RBIT_32 $tmp, $src\n\t"
9095            "CLZ_32  $dst,$tmp" %}
9096  ins_encode %{
9097    __ rbit_32($tmp$$Register, $src$$Register);
9098    __ clz_32($dst$$Register, $tmp$$Register);
9099  %}
9100  ins_pipe(ialu_reg);
9101%}
9102
9103instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9104  match(Set dst (CountTrailingZerosL src));
9105  effect(TEMP tmp, TEMP dst, KILL ccr);
9106  size(24);
9107  format %{ "RBIT   $tmp,$src.lo\n\t"
9108            "CLZ    $dst,$tmp\n\t"
9109            "TEQ    $dst,32\n\t"
9110            "RBIT   $tmp,$src.hi\n\t"
9111            "CLZ.eq $tmp,$tmp\n\t"
9112            "ADD.eq $dst,$dst,$tmp\n\t" %}
9113  ins_encode %{
9114    __ rbit($tmp$$Register, $src$$Register);
9115    __ clz($dst$$Register, $tmp$$Register);
9116    __ teq($dst$$Register, 32);
9117    __ rbit($tmp$$Register, $src$$Register->successor());
9118    __ clz($tmp$$Register, $tmp$$Register, eq);
9119    __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9120  %}
9121  ins_pipe(ialu_reg);
9122%}
9123
9124
9125//---------- Population Count Instructions -------------------------------------
9126
9127instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
9128  predicate(UsePopCountInstruction);
9129  match(Set dst (PopCountI src));
9130  effect(TEMP tmp);
9131
9132  format %{ "FMSR       $tmp,$src\n\t"
9133            "VCNT.8     $tmp,$tmp\n\t"
9134            "VPADDL.U8  $tmp,$tmp\n\t"
9135            "VPADDL.U16 $tmp,$tmp\n\t"
9136            "FMRS       $dst,$tmp" %}
9137  size(20);
9138
9139  ins_encode %{
9140    __ fmsr($tmp$$FloatRegister, $src$$Register);
9141    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9142    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9143    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9144    __ fmrs($dst$$Register, $tmp$$FloatRegister);
9145  %}
9146  ins_pipe(ialu_reg); // FIXME
9147%}
9148
9149// Note: Long.bitCount(long) returns an int.
9150instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{
9151  predicate(UsePopCountInstruction);
9152  match(Set dst (PopCountL src));
9153  effect(TEMP tmp);
9154
9155  format %{ "FMDRR       $tmp,$src.lo,$src.hi\n\t"
9156            "VCNT.8      $tmp,$tmp\n\t"
9157            "VPADDL.U8   $tmp,$tmp\n\t"
9158            "VPADDL.U16  $tmp,$tmp\n\t"
9159            "VPADDL.U32  $tmp,$tmp\n\t"
9160            "FMRS        $dst,$tmp" %}
9161
9162  size(32);
9163
9164  ins_encode %{
9165    __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor());
9166    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9167    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9168    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9169    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0);
9170    __ fmrs($dst$$Register, $tmp$$FloatRegister);
9171  %}
9172  ins_pipe(ialu_reg);
9173%}
9174
9175
9176// ============================================================================
9177//------------Bytes reverse--------------------------------------------------
9178
9179instruct bytes_reverse_int(iRegI dst, iRegI src) %{
9180  match(Set dst (ReverseBytesI src));
9181
9182  size(4);
9183  format %{ "REV32 $dst,$src" %}
9184  ins_encode %{
9185    __ rev($dst$$Register, $src$$Register);
9186  %}
9187  ins_pipe( iload_mem ); // FIXME
9188%}
9189
9190instruct bytes_reverse_long(iRegL dst, iRegL src) %{
9191  match(Set dst (ReverseBytesL src));
9192  effect(TEMP dst);
9193  size(8);
9194  format %{ "REV $dst.lo,$src.lo\n\t"
9195            "REV $dst.hi,$src.hi" %}
9196  ins_encode %{
9197    __ rev($dst$$Register, $src$$Register->successor());
9198    __ rev($dst$$Register->successor(), $src$$Register);
9199  %}
9200  ins_pipe( iload_mem ); // FIXME
9201%}
9202
9203instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
9204  match(Set dst (ReverseBytesUS src));
9205  size(4);
9206  format %{ "REV16 $dst,$src" %}
9207  ins_encode %{
9208    __ rev16($dst$$Register, $src$$Register);
9209  %}
9210  ins_pipe( iload_mem ); // FIXME
9211%}
9212
9213instruct bytes_reverse_short(iRegI dst, iRegI src) %{
9214  match(Set dst (ReverseBytesS src));
9215  size(4);
9216  format %{ "REVSH $dst,$src" %}
9217  ins_encode %{
9218    __ revsh($dst$$Register, $src$$Register);
9219  %}
9220  ins_pipe( iload_mem ); // FIXME
9221%}
9222
9223
9224// ====================VECTOR INSTRUCTIONS=====================================
9225
9226// Load Aligned Packed values into a Double Register
9227instruct loadV8(vecD dst, memoryD mem) %{
9228  predicate(n->as_LoadVector()->memory_size() == 8);
9229  match(Set dst (LoadVector mem));
9230  ins_cost(MEMORY_REF_COST);
9231  size(4);
9232  format %{ "FLDD   $mem,$dst\t! load vector (8 bytes)" %}
9233  ins_encode %{
9234    __ ldr_double($dst$$FloatRegister, $mem$$Address);
9235  %}
9236  ins_pipe(floadD_mem);
9237%}
9238
9239// Load Aligned Packed values into a Double Register Pair
9240instruct loadV16(vecX dst, memoryvld mem) %{
9241  predicate(n->as_LoadVector()->memory_size() == 16);
9242  match(Set dst (LoadVector mem));
9243  ins_cost(MEMORY_REF_COST);
9244  size(4);
9245  format %{ "VLD1   $mem,$dst.Q\t! load vector (16 bytes)" %}
9246  ins_encode %{
9247    __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9248  %}
9249  ins_pipe(floadD_mem); // FIXME
9250%}
9251
9252// Store Vector in Double register to memory
9253instruct storeV8(memoryD mem, vecD src) %{
9254  predicate(n->as_StoreVector()->memory_size() == 8);
9255  match(Set mem (StoreVector mem src));
9256  ins_cost(MEMORY_REF_COST);
9257  size(4);
9258  format %{ "FSTD   $src,$mem\t! store vector (8 bytes)" %}
9259  ins_encode %{
9260    __ str_double($src$$FloatRegister, $mem$$Address);
9261  %}
9262  ins_pipe(fstoreD_mem_reg);
9263%}
9264
9265// Store Vector in Double Register Pair to memory
9266instruct storeV16(memoryvld mem, vecX src) %{
9267  predicate(n->as_StoreVector()->memory_size() == 16);
9268  match(Set mem (StoreVector mem src));
9269  ins_cost(MEMORY_REF_COST);
9270  size(4);
9271  format %{ "VST1   $src,$mem\t! store vector (16 bytes)" %}
9272  ins_encode %{
9273    __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9274  %}
9275  ins_pipe(fstoreD_mem_reg); // FIXME
9276%}
9277
9278// Replicate scalar to packed byte values in Double register
9279instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{
9280  predicate(n->as_Vector()->length() == 8);
9281  match(Set dst (ReplicateB src));
9282  ins_cost(DEFAULT_COST*4);
9283  effect(TEMP tmp);
9284  size(16);
9285
9286  // FIXME: could use PKH instruction instead?
9287  format %{ "LSL      $tmp, $src, 24 \n\t"
9288            "OR       $tmp, $tmp, ($tmp >> 8) \n\t"
9289            "OR       $tmp, $tmp, ($tmp >> 16) \n\t"
9290            "FMDRR    $dst,$tmp,$tmp\t" %}
9291  ins_encode %{
9292    __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24));
9293    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8));
9294    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9295    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9296  %}
9297  ins_pipe(ialu_reg); // FIXME
9298%}
9299
9300// Replicate scalar to packed byte values in Double register
9301instruct Repl8B_reg_simd(vecD dst, iRegI src) %{
9302  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9303  match(Set dst (ReplicateB src));
9304  size(4);
9305
9306  format %{ "VDUP.8 $dst,$src\t" %}
9307  ins_encode %{
9308    bool quad = false;
9309    __ vdupI($dst$$FloatRegister, $src$$Register,
9310             MacroAssembler::VELEM_SIZE_8, quad);
9311  %}
9312  ins_pipe(ialu_reg); // FIXME
9313%}
9314
9315// Replicate scalar to packed byte values in Double register pair
9316instruct Repl16B_reg(vecX dst, iRegI src) %{
9317  predicate(n->as_Vector()->length_in_bytes() == 16);
9318  match(Set dst (ReplicateB src));
9319  size(4);
9320
9321  format %{ "VDUP.8 $dst.Q,$src\t" %}
9322  ins_encode %{
9323    bool quad = true;
9324    __ vdupI($dst$$FloatRegister, $src$$Register,
9325             MacroAssembler::VELEM_SIZE_8, quad);
9326  %}
9327  ins_pipe(ialu_reg); // FIXME
9328%}
9329
9330// Replicate scalar constant to packed byte values in Double register
9331instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{
9332  predicate(n->as_Vector()->length() == 8);
9333  match(Set dst (ReplicateB src));
9334  ins_cost(DEFAULT_COST*2);
9335  effect(TEMP tmp);
9336  size(12);
9337
9338  format %{ "MOV      $tmp, Repl4($src))\n\t"
9339            "FMDRR    $dst,$tmp,$tmp\t" %}
9340  ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) );
9341  ins_pipe(loadConFD); // FIXME
9342%}
9343
9344// Replicate scalar constant to packed byte values in Double register
9345// TODO: support negative constants with MVNI?
9346instruct Repl8B_immU8(vecD dst, immU8 src) %{
9347  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9348  match(Set dst (ReplicateB src));
9349  size(4);
9350
9351  format %{ "VMOV.U8  $dst,$src" %}
9352  ins_encode %{
9353    bool quad = false;
9354    __ vmovI($dst$$FloatRegister, $src$$constant,
9355             MacroAssembler::VELEM_SIZE_8, quad);
9356  %}
9357  ins_pipe(loadConFD); // FIXME
9358%}
9359
9360// Replicate scalar constant to packed byte values in Double register pair
9361instruct Repl16B_immU8(vecX dst, immU8 src) %{
9362  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
9363  match(Set dst (ReplicateB src));
9364  size(4);
9365
9366  format %{ "VMOV.U8  $dst.Q,$src" %}
9367  ins_encode %{
9368    bool quad = true;
9369    __ vmovI($dst$$FloatRegister, $src$$constant,
9370             MacroAssembler::VELEM_SIZE_8, quad);
9371  %}
9372  ins_pipe(loadConFD); // FIXME
9373%}
9374
9375// Replicate scalar to packed short/char values into Double register
9376instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{
9377  predicate(n->as_Vector()->length() == 4);
9378  match(Set dst (ReplicateS src));
9379  ins_cost(DEFAULT_COST*3);
9380  effect(TEMP tmp);
9381  size(12);
9382
9383  // FIXME: could use PKH instruction instead?
9384  format %{ "LSL      $tmp, $src, 16 \n\t"
9385            "OR       $tmp, $tmp, ($tmp >> 16) \n\t"
9386            "FMDRR    $dst,$tmp,$tmp\t" %}
9387  ins_encode %{
9388    __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16));
9389    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9390    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9391  %}
9392  ins_pipe(ialu_reg); // FIXME
9393%}
9394
9395// Replicate scalar to packed byte values in Double register
9396instruct Repl4S_reg_simd(vecD dst, iRegI src) %{
9397  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9398  match(Set dst (ReplicateS src));
9399  size(4);
9400
9401  format %{ "VDUP.16 $dst,$src\t" %}
9402  ins_encode %{
9403    bool quad = false;
9404    __ vdupI($dst$$FloatRegister, $src$$Register,
9405             MacroAssembler::VELEM_SIZE_16, quad);
9406  %}
9407  ins_pipe(ialu_reg); // FIXME
9408%}
9409
9410// Replicate scalar to packed byte values in Double register pair
9411instruct Repl8S_reg(vecX dst, iRegI src) %{
9412  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
9413  match(Set dst (ReplicateS src));
9414  size(4);
9415
9416  format %{ "VDUP.16 $dst.Q,$src\t" %}
9417  ins_encode %{
9418    bool quad = true;
9419    __ vdupI($dst$$FloatRegister, $src$$Register,
9420             MacroAssembler::VELEM_SIZE_16, quad);
9421  %}
9422  ins_pipe(ialu_reg); // FIXME
9423%}
9424
9425
9426// Replicate scalar constant to packed short/char values in Double register
9427instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{
9428  predicate(n->as_Vector()->length() == 4);
9429  match(Set dst (ReplicateS src));
9430  effect(TEMP tmp);
9431  size(12);
9432  ins_cost(DEFAULT_COST*4); // FIXME
9433
9434  format %{ "MOV      $tmp, Repl2($src))\n\t"
9435            "FMDRR    $dst,$tmp,$tmp\t" %}
9436  ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) );
9437  ins_pipe(loadConFD); // FIXME
9438%}
9439
9440// Replicate scalar constant to packed byte values in Double register
9441instruct Repl4S_immU8(vecD dst, immU8 src) %{
9442  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9443  match(Set dst (ReplicateS src));
9444  size(4);
9445
9446  format %{ "VMOV.U16  $dst,$src" %}
9447  ins_encode %{
9448    bool quad = false;
9449    __ vmovI($dst$$FloatRegister, $src$$constant,
9450             MacroAssembler::VELEM_SIZE_16, quad);
9451  %}
9452  ins_pipe(loadConFD); // FIXME
9453%}
9454
9455// Replicate scalar constant to packed byte values in Double register pair
9456instruct Repl8S_immU8(vecX dst, immU8 src) %{
9457  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
9458  match(Set dst (ReplicateS src));
9459  size(4);
9460
9461  format %{ "VMOV.U16  $dst.Q,$src" %}
9462  ins_encode %{
9463    bool quad = true;
9464    __ vmovI($dst$$FloatRegister, $src$$constant,
9465             MacroAssembler::VELEM_SIZE_16, quad);
9466  %}
9467  ins_pipe(loadConFD); // FIXME
9468%}
9469
9470// Replicate scalar to packed int values in Double register
9471instruct Repl2I_reg(vecD dst, iRegI src) %{
9472  predicate(n->as_Vector()->length() == 2);
9473  match(Set dst (ReplicateI src));
9474  size(4);
9475
9476  format %{ "FMDRR    $dst,$src,$src\t" %}
9477  ins_encode %{
9478    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9479  %}
9480  ins_pipe(ialu_reg); // FIXME
9481%}
9482
9483// Replicate scalar to packed int values in Double register pair
9484instruct Repl4I_reg(vecX dst, iRegI src) %{
9485  predicate(n->as_Vector()->length() == 4);
9486  match(Set dst (ReplicateI src));
9487  ins_cost(DEFAULT_COST*2);
9488  size(8);
9489
9490  format %{ "FMDRR    $dst.lo,$src,$src\n\t"
9491            "FMDRR    $dst.hi,$src,$src" %}
9492
9493  ins_encode %{
9494    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9495    __ fmdrr($dst$$FloatRegister->successor()->successor(),
9496             $src$$Register, $src$$Register);
9497  %}
9498  ins_pipe(ialu_reg); // FIXME
9499%}
9500
9501// Replicate scalar to packed int values in Double register
9502instruct Repl2I_reg_simd(vecD dst, iRegI src) %{
9503  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9504  match(Set dst (ReplicateI src));
9505  size(4);
9506
9507  format %{ "VDUP.32 $dst.D,$src\t" %}
9508  ins_encode %{
9509    bool quad = false;
9510    __ vdupI($dst$$FloatRegister, $src$$Register,
9511             MacroAssembler::VELEM_SIZE_32, quad);
9512  %}
9513  ins_pipe(ialu_reg); // FIXME
9514%}
9515
9516// Replicate scalar to packed int values in Double register pair
9517instruct Repl4I_reg_simd(vecX dst, iRegI src) %{
9518  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
9519  match(Set dst (ReplicateI src));
9520  size(4);
9521
9522  format %{ "VDUP.32 $dst.Q,$src\t" %}
9523  ins_encode %{
9524    bool quad = true;
9525    __ vdupI($dst$$FloatRegister, $src$$Register,
9526             MacroAssembler::VELEM_SIZE_32, quad);
9527  %}
9528  ins_pipe(ialu_reg); // FIXME
9529%}
9530
9531
9532// Replicate scalar zero constant to packed int values in Double register
9533instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{
9534  predicate(n->as_Vector()->length() == 2);
9535  match(Set dst (ReplicateI src));
9536  effect(TEMP tmp);
9537  size(12);
9538  ins_cost(DEFAULT_COST*4); // FIXME
9539
9540  format %{ "MOV      $tmp, Repl1($src))\n\t"
9541            "FMDRR    $dst,$tmp,$tmp\t" %}
9542  ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) );
9543  ins_pipe(loadConFD); // FIXME
9544%}
9545
9546// Replicate scalar constant to packed byte values in Double register
9547instruct Repl2I_immU8(vecD dst, immU8 src) %{
9548  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9549  match(Set dst (ReplicateI src));
9550  size(4);
9551
9552  format %{ "VMOV.I32  $dst.D,$src" %}
9553  ins_encode %{
9554    bool quad = false;
9555    __ vmovI($dst$$FloatRegister, $src$$constant,
9556             MacroAssembler::VELEM_SIZE_32, quad);
9557  %}
9558  ins_pipe(loadConFD); // FIXME
9559%}
9560
9561// Replicate scalar constant to packed byte values in Double register pair
9562instruct Repl4I_immU8(vecX dst, immU8 src) %{
9563  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
9564  match(Set dst (ReplicateI src));
9565  size(4);
9566
9567  format %{ "VMOV.I32  $dst.Q,$src" %}
9568  ins_encode %{
9569    bool quad = true;
9570    __ vmovI($dst$$FloatRegister, $src$$constant,
9571             MacroAssembler::VELEM_SIZE_32, quad);
9572  %}
9573  ins_pipe(loadConFD); // FIXME
9574%}
9575
9576// Replicate scalar to packed byte values in Double register pair
9577instruct Repl2L_reg(vecX dst, iRegL src) %{
9578  predicate(n->as_Vector()->length() == 2);
9579  match(Set dst (ReplicateL src));
9580  size(8);
9581  ins_cost(DEFAULT_COST*2); // FIXME
9582
9583  format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n"
9584            "FMDRR $dst.D.next,$src.lo,$src.hi" %}
9585  ins_encode %{
9586    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
9587    __ fmdrr($dst$$FloatRegister->successor()->successor(),
9588             $src$$Register, $src$$Register->successor());
9589  %}
9590  ins_pipe(ialu_reg); // FIXME
9591%}
9592
9593
9594// Replicate scalar to packed float values in Double register
9595instruct Repl2F_regI(vecD dst, iRegI src) %{
9596  predicate(n->as_Vector()->length() == 2);
9597  match(Set dst (ReplicateF src));
9598  size(4);
9599
9600  format %{ "FMDRR    $dst.D,$src,$src\t" %}
9601  ins_encode %{
9602    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9603  %}
9604  ins_pipe(ialu_reg); // FIXME
9605%}
9606
9607// Replicate scalar to packed float values in Double register
9608instruct Repl2F_reg_vfp(vecD dst, regF src) %{
9609  predicate(n->as_Vector()->length() == 2);
9610  match(Set dst (ReplicateF src));
9611  size(4*2);
9612  ins_cost(DEFAULT_COST*2); // FIXME
9613
9614  expand %{
9615    iRegI tmp;
9616    MoveF2I_reg_reg(tmp, src);
9617    Repl2F_regI(dst,tmp);
9618  %}
9619%}
9620
9621// Replicate scalar to packed float values in Double register
9622instruct Repl2F_reg_simd(vecD dst, regF src) %{
9623  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
9624  match(Set dst (ReplicateF src));
9625  size(4);
9626  ins_cost(DEFAULT_COST); // FIXME
9627
9628  format %{ "VDUP.32  $dst.D,$src.D\t" %}
9629  ins_encode %{
9630    bool quad = false;
9631    __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9632  %}
9633  ins_pipe(ialu_reg); // FIXME
9634%}
9635
9636// Replicate scalar to packed float values in Double register pair
9637instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{
9638  predicate(n->as_Vector()->length() == 4);
9639  match(Set dst (ReplicateF src));
9640  effect(TEMP tmp);
9641  size(4*3);
9642  ins_cost(DEFAULT_COST*3); // FIXME
9643
9644  format %{ "FMRS     $tmp,$src\n\t"
9645            "FMDRR    $dst.D,$tmp,$tmp\n\t"
9646            "FMDRR    $dst.D.next,$tmp,$tmp\t" %}
9647  ins_encode %{
9648    __ fmrs($tmp$$Register, $src$$FloatRegister);
9649    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9650    __ fmdrr($dst$$FloatRegister->successor()->successor(),
9651             $tmp$$Register, $tmp$$Register);
9652  %}
9653  ins_pipe(ialu_reg); // FIXME
9654%}
9655
9656// Replicate scalar to packed float values in Double register pair
9657instruct Repl4F_reg_simd(vecX dst, regF src) %{
9658  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
9659  match(Set dst (ReplicateF src));
9660  size(4);
9661  ins_cost(DEFAULT_COST); // FIXME
9662
9663  format %{ "VDUP.32  $dst.Q,$src.D\t" %}
9664  ins_encode %{
9665    bool quad = true;
9666    __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9667  %}
9668  ins_pipe(ialu_reg); // FIXME
9669%}
9670
9671// Replicate scalar zero constant to packed float values in Double register
9672instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{
9673  predicate(n->as_Vector()->length() == 2);
9674  match(Set dst (ReplicateF src));
9675  effect(TEMP tmp);
9676  size(12);
9677  ins_cost(DEFAULT_COST*4); // FIXME
9678
9679  format %{ "MOV      $tmp, Repl1($src))\n\t"
9680            "FMDRR    $dst,$tmp,$tmp\t" %}
9681  ins_encode( LdReplImmF(src, dst, tmp) );
9682  ins_pipe(loadConFD); // FIXME
9683%}
9684
9685// Replicate scalar to packed double float values in Double register pair
9686instruct Repl2D_reg(vecX dst, regD src) %{
9687  predicate(n->as_Vector()->length() == 2);
9688  match(Set dst (ReplicateD src));
9689  size(4*2);
9690  ins_cost(DEFAULT_COST*2); // FIXME
9691
9692  format %{ "FCPYD    $dst.D.a,$src\n\t"
9693            "FCPYD    $dst.D.b,$src\t" %}
9694  ins_encode %{
9695    FloatRegister dsta = $dst$$FloatRegister;
9696    FloatRegister src = $src$$FloatRegister;
9697    __ fcpyd(dsta, src);
9698    FloatRegister dstb = dsta->successor()->successor();
9699    __ fcpyd(dstb, src);
9700  %}
9701  ins_pipe(ialu_reg); // FIXME
9702%}
9703
9704// ====================VECTOR ARITHMETIC=======================================
9705
9706// --------------------------------- ADD --------------------------------------
9707
9708// Bytes vector add
9709instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{
9710  predicate(n->as_Vector()->length() == 8);
9711  match(Set dst (AddVB src1 src2));
9712  format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %}
9713  size(4);
9714  ins_encode %{
9715    bool quad = false;
9716    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9717             MacroAssembler::VELEM_SIZE_8, quad);
9718  %}
9719  ins_pipe( ialu_reg_reg ); // FIXME
9720%}
9721
9722instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
9723  predicate(n->as_Vector()->length() == 16);
9724  match(Set dst (AddVB src1 src2));
9725  size(4);
9726  format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %}
9727  ins_encode %{
9728    bool quad = true;
9729    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9730             MacroAssembler::VELEM_SIZE_8, quad);
9731  %}
9732  ins_pipe( ialu_reg_reg ); // FIXME
9733%}
9734
9735// Shorts/Chars vector add
9736instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{
9737  predicate(n->as_Vector()->length() == 4);
9738  match(Set dst (AddVS src1 src2));
9739  size(4);
9740  format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %}
9741  ins_encode %{
9742    bool quad = false;
9743    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9744             MacroAssembler::VELEM_SIZE_16, quad);
9745  %}
9746  ins_pipe( ialu_reg_reg ); // FIXME
9747%}
9748
9749instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
9750  predicate(n->as_Vector()->length() == 8);
9751  match(Set dst (AddVS src1 src2));
9752  size(4);
9753  format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %}
9754  ins_encode %{
9755    bool quad = true;
9756    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9757             MacroAssembler::VELEM_SIZE_16, quad);
9758  %}
9759  ins_pipe( ialu_reg_reg ); // FIXME
9760%}
9761
9762// Integers vector add
9763instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{
9764  predicate(n->as_Vector()->length() == 2);
9765  match(Set dst (AddVI src1 src2));
9766  size(4);
9767  format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %}
9768  ins_encode %{
9769    bool quad = false;
9770    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9771             MacroAssembler::VELEM_SIZE_32, quad);
9772  %}
9773  ins_pipe( ialu_reg_reg ); // FIXME
9774%}
9775
9776instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
9777  predicate(n->as_Vector()->length() == 4);
9778  match(Set dst (AddVI src1 src2));
9779  size(4);
9780  format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %}
9781  ins_encode %{
9782    bool quad = true;
9783    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9784             MacroAssembler::VELEM_SIZE_32, quad);
9785  %}
9786  ins_pipe( ialu_reg_reg ); // FIXME
9787%}
9788
9789// Longs vector add
9790instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
9791  predicate(n->as_Vector()->length() == 2);
9792  match(Set dst (AddVL src1 src2));
9793  size(4);
9794  format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %}
9795  ins_encode %{
9796    bool quad = true;
9797    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9798             MacroAssembler::VELEM_SIZE_64, quad);
9799  %}
9800  ins_pipe( ialu_reg_reg ); // FIXME
9801%}
9802
9803// Floats vector add
9804instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{
9805  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
9806  match(Set dst (AddVF src1 src2));
9807  size(4);
9808  format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %}
9809  ins_encode %{
9810    bool quad = false;
9811    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9812             MacroAssembler::VFA_SIZE_F32, quad);
9813  %}
9814  ins_pipe( faddD_reg_reg ); // FIXME
9815%}
9816
9817instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
9818  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
9819  match(Set dst (AddVF src1 src2));
9820  ins_cost(DEFAULT_COST*2); // FIXME
9821
9822  size(4*2);
9823  format %{ "FADDS  $dst.a,$src1.a,$src2.a\n\t"
9824            "FADDS  $dst.b,$src1.b,$src2.b" %}
9825  ins_encode %{
9826    __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9827    __ add_float($dst$$FloatRegister->successor(),
9828             $src1$$FloatRegister->successor(),
9829             $src2$$FloatRegister->successor());
9830  %}
9831
9832  ins_pipe(faddF_reg_reg); // FIXME
9833%}
9834
9835instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{
9836  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
9837  match(Set dst (AddVF src1 src2));
9838  size(4);
9839  format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %}
9840  ins_encode %{
9841    bool quad = true;
9842    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9843             MacroAssembler::VFA_SIZE_F32, quad);
9844  %}
9845  ins_pipe( faddD_reg_reg ); // FIXME
9846%}
9847
9848instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9849  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
9850  match(Set dst (AddVF src1 src2));
9851  size(4*4);
9852  ins_cost(DEFAULT_COST*4); // FIXME
9853
9854  format %{ "FADDS  $dst.a,$src1.a,$src2.a\n\t"
9855            "FADDS  $dst.b,$src1.b,$src2.b\n\t"
9856            "FADDS  $dst.c,$src1.c,$src2.c\n\t"
9857            "FADDS  $dst.d,$src1.d,$src2.d" %}
9858
9859  ins_encode %{
9860    FloatRegister dsta = $dst$$FloatRegister;
9861    FloatRegister src1a = $src1$$FloatRegister;
9862    FloatRegister src2a = $src2$$FloatRegister;
9863    __ add_float(dsta, src1a, src2a);
9864    FloatRegister dstb = dsta->successor();
9865    FloatRegister src1b = src1a->successor();
9866    FloatRegister src2b = src2a->successor();
9867    __ add_float(dstb, src1b, src2b);
9868    FloatRegister dstc = dstb->successor();
9869    FloatRegister src1c = src1b->successor();
9870    FloatRegister src2c = src2b->successor();
9871    __ add_float(dstc, src1c, src2c);
9872    FloatRegister dstd = dstc->successor();
9873    FloatRegister src1d = src1c->successor();
9874    FloatRegister src2d = src2c->successor();
9875    __ add_float(dstd, src1d, src2d);
9876  %}
9877
9878  ins_pipe(faddF_reg_reg); // FIXME
9879%}
9880
9881instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9882  predicate(n->as_Vector()->length() == 2);
9883  match(Set dst (AddVD src1 src2));
9884  size(4*2);
9885  ins_cost(DEFAULT_COST*2); // FIXME
9886
9887  format %{ "FADDD  $dst.a,$src1.a,$src2.a\n\t"
9888            "FADDD  $dst.b,$src1.b,$src2.b" %}
9889
9890  ins_encode %{
9891    FloatRegister dsta = $dst$$FloatRegister;
9892    FloatRegister src1a = $src1$$FloatRegister;
9893    FloatRegister src2a = $src2$$FloatRegister;
9894    __ add_double(dsta, src1a, src2a);
9895    FloatRegister dstb = dsta->successor()->successor();
9896    FloatRegister src1b = src1a->successor()->successor();
9897    FloatRegister src2b = src2a->successor()->successor();
9898    __ add_double(dstb, src1b, src2b);
9899  %}
9900
9901  ins_pipe(faddF_reg_reg); // FIXME
9902%}
9903
9904
9905// Bytes vector sub
9906instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{
9907  predicate(n->as_Vector()->length() == 8);
9908  match(Set dst (SubVB src1 src2));
9909  size(4);
9910  format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %}
9911  ins_encode %{
9912    bool quad = false;
9913    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9914             MacroAssembler::VELEM_SIZE_8, quad);
9915  %}
9916  ins_pipe( ialu_reg_reg ); // FIXME
9917%}
9918
9919instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
9920  predicate(n->as_Vector()->length() == 16);
9921  match(Set dst (SubVB src1 src2));
9922  size(4);
9923  format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %}
9924  ins_encode %{
9925    bool quad = true;
9926    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9927             MacroAssembler::VELEM_SIZE_8, quad);
9928  %}
9929  ins_pipe( ialu_reg_reg ); // FIXME
9930%}
9931
9932// Shorts/Chars vector sub
9933instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{
9934  predicate(n->as_Vector()->length() == 4);
9935  match(Set dst (SubVS src1 src2));
9936  size(4);
9937  format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %}
9938  ins_encode %{
9939    bool quad = false;
9940    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9941             MacroAssembler::VELEM_SIZE_16, quad);
9942  %}
9943  ins_pipe( ialu_reg_reg ); // FIXME
9944%}
9945
9946instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{
9947  predicate(n->as_Vector()->length() == 8);
9948  match(Set dst (SubVS src1 src2));
9949  size(4);
9950  format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %}
9951  ins_encode %{
9952    bool quad = true;
9953    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9954             MacroAssembler::VELEM_SIZE_16, quad);
9955  %}
9956  ins_pipe( ialu_reg_reg ); // FIXME
9957%}
9958
9959// Integers vector sub
9960instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{
9961  predicate(n->as_Vector()->length() == 2);
9962  match(Set dst (SubVI src1 src2));
9963  size(4);
9964  format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %}
9965  ins_encode %{
9966    bool quad = false;
9967    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9968             MacroAssembler::VELEM_SIZE_32, quad);
9969  %}
9970  ins_pipe( ialu_reg_reg ); // FIXME
9971%}
9972
9973instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
9974  predicate(n->as_Vector()->length() == 4);
9975  match(Set dst (SubVI src1 src2));
9976  size(4);
9977  format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %}
9978  ins_encode %{
9979    bool quad = true;
9980    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9981             MacroAssembler::VELEM_SIZE_32, quad);
9982  %}
9983  ins_pipe( ialu_reg_reg ); // FIXME
9984%}
9985
9986// Longs vector sub
9987instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
9988  predicate(n->as_Vector()->length() == 2);
9989  match(Set dst (SubVL src1 src2));
9990  size(4);
9991  format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %}
9992  ins_encode %{
9993    bool quad = true;
9994    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9995             MacroAssembler::VELEM_SIZE_64, quad);
9996  %}
9997  ins_pipe( ialu_reg_reg ); // FIXME
9998%}
9999
10000// Floats vector sub
10001instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{
10002  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10003  match(Set dst (SubVF src1 src2));
10004  size(4);
10005  format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %}
10006  ins_encode %{
10007    bool quad = false;
10008    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10009             MacroAssembler::VFA_SIZE_F32, quad);
10010  %}
10011  ins_pipe( faddF_reg_reg ); // FIXME
10012%}
10013
10014instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10015  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10016  match(Set dst (SubVF src1 src2));
10017  size(4*2);
10018  ins_cost(DEFAULT_COST*2); // FIXME
10019
10020  format %{ "FSUBS  $dst.a,$src1.a,$src2.a\n\t"
10021            "FSUBS  $dst.b,$src1.b,$src2.b" %}
10022
10023  ins_encode %{
10024    FloatRegister dsta = $dst$$FloatRegister;
10025    FloatRegister src1a = $src1$$FloatRegister;
10026    FloatRegister src2a = $src2$$FloatRegister;
10027    __ sub_float(dsta, src1a, src2a);
10028    FloatRegister dstb = dsta->successor();
10029    FloatRegister src1b = src1a->successor();
10030    FloatRegister src2b = src2a->successor();
10031    __ sub_float(dstb, src1b, src2b);
10032  %}
10033
10034  ins_pipe(faddF_reg_reg); // FIXME
10035%}
10036
10037
10038instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
10039  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10040  match(Set dst (SubVF src1 src2));
10041  size(4);
10042  format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %}
10043  ins_encode %{
10044    bool quad = true;
10045    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10046             MacroAssembler::VFA_SIZE_F32, quad);
10047  %}
10048  ins_pipe( faddF_reg_reg ); // FIXME
10049%}
10050
10051instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10052  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10053  match(Set dst (SubVF src1 src2));
10054  size(4*4);
10055  ins_cost(DEFAULT_COST*4); // FIXME
10056
10057  format %{ "FSUBS  $dst.a,$src1.a,$src2.a\n\t"
10058            "FSUBS  $dst.b,$src1.b,$src2.b\n\t"
10059            "FSUBS  $dst.c,$src1.c,$src2.c\n\t"
10060            "FSUBS  $dst.d,$src1.d,$src2.d" %}
10061
10062  ins_encode %{
10063    FloatRegister dsta = $dst$$FloatRegister;
10064    FloatRegister src1a = $src1$$FloatRegister;
10065    FloatRegister src2a = $src2$$FloatRegister;
10066    __ sub_float(dsta, src1a, src2a);
10067    FloatRegister dstb = dsta->successor();
10068    FloatRegister src1b = src1a->successor();
10069    FloatRegister src2b = src2a->successor();
10070    __ sub_float(dstb, src1b, src2b);
10071    FloatRegister dstc = dstb->successor();
10072    FloatRegister src1c = src1b->successor();
10073    FloatRegister src2c = src2b->successor();
10074    __ sub_float(dstc, src1c, src2c);
10075    FloatRegister dstd = dstc->successor();
10076    FloatRegister src1d = src1c->successor();
10077    FloatRegister src2d = src2c->successor();
10078    __ sub_float(dstd, src1d, src2d);
10079  %}
10080
10081  ins_pipe(faddF_reg_reg); // FIXME
10082%}
10083
10084instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10085  predicate(n->as_Vector()->length() == 2);
10086  match(Set dst (SubVD src1 src2));
10087  size(4*2);
10088  ins_cost(DEFAULT_COST*2); // FIXME
10089
10090  format %{ "FSUBD  $dst.a,$src1.a,$src2.a\n\t"
10091            "FSUBD  $dst.b,$src1.b,$src2.b" %}
10092
10093  ins_encode %{
10094    FloatRegister dsta = $dst$$FloatRegister;
10095    FloatRegister src1a = $src1$$FloatRegister;
10096    FloatRegister src2a = $src2$$FloatRegister;
10097    __ sub_double(dsta, src1a, src2a);
10098    FloatRegister dstb = dsta->successor()->successor();
10099    FloatRegister src1b = src1a->successor()->successor();
10100    FloatRegister src2b = src2a->successor()->successor();
10101    __ sub_double(dstb, src1b, src2b);
10102  %}
10103
10104  ins_pipe(faddF_reg_reg); // FIXME
10105%}
10106
10107// Shorts/Chars vector mul
10108instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{
10109  predicate(n->as_Vector()->length() == 4);
10110  match(Set dst (MulVS src1 src2));
10111  size(4);
10112  format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %}
10113  ins_encode %{
10114    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10115             MacroAssembler::VELEM_SIZE_16, 0);
10116  %}
10117  ins_pipe( ialu_reg_reg ); // FIXME
10118%}
10119
10120instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{
10121  predicate(n->as_Vector()->length() == 8);
10122  match(Set dst (MulVS src1 src2));
10123  size(4);
10124  format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %}
10125  ins_encode %{
10126    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10127             MacroAssembler::VELEM_SIZE_16, 1);
10128  %}
10129  ins_pipe( ialu_reg_reg ); // FIXME
10130%}
10131
10132// Integers vector mul
10133instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{
10134  predicate(n->as_Vector()->length() == 2);
10135  match(Set dst (MulVI src1 src2));
10136  size(4);
10137  format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %}
10138  ins_encode %{
10139    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10140             MacroAssembler::VELEM_SIZE_32, 0);
10141  %}
10142  ins_pipe( ialu_reg_reg ); // FIXME
10143%}
10144
10145instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
10146  predicate(n->as_Vector()->length() == 4);
10147  match(Set dst (MulVI src1 src2));
10148  size(4);
10149  format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %}
10150  ins_encode %{
10151    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10152             MacroAssembler::VELEM_SIZE_32, 1);
10153  %}
10154  ins_pipe( ialu_reg_reg ); // FIXME
10155%}
10156
10157// Floats vector mul
10158instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{
10159  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10160  match(Set dst (MulVF src1 src2));
10161  size(4);
10162  format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %}
10163  ins_encode %{
10164    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10165             MacroAssembler::VFA_SIZE_F32, 0);
10166  %}
10167  ins_pipe( fmulF_reg_reg ); // FIXME
10168%}
10169
10170instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10171  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10172  match(Set dst (MulVF src1 src2));
10173  size(4*2);
10174  ins_cost(DEFAULT_COST*2); // FIXME
10175
10176  format %{ "FMULS  $dst.a,$src1.a,$src2.a\n\t"
10177            "FMULS  $dst.b,$src1.b,$src2.b" %}
10178  ins_encode %{
10179    __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10180    __ mul_float($dst$$FloatRegister->successor(),
10181             $src1$$FloatRegister->successor(),
10182             $src2$$FloatRegister->successor());
10183  %}
10184
10185  ins_pipe(fmulF_reg_reg); // FIXME
10186%}
10187
10188instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
10189  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10190  match(Set dst (MulVF src1 src2));
10191  size(4);
10192  format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %}
10193  ins_encode %{
10194    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10195             MacroAssembler::VFA_SIZE_F32, 1);
10196  %}
10197  ins_pipe( fmulF_reg_reg ); // FIXME
10198%}
10199
10200instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10201  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10202  match(Set dst (MulVF src1 src2));
10203  size(4*4);
10204  ins_cost(DEFAULT_COST*4); // FIXME
10205
10206  format %{ "FMULS  $dst.a,$src1.a,$src2.a\n\t"
10207            "FMULS  $dst.b,$src1.b,$src2.b\n\t"
10208            "FMULS  $dst.c,$src1.c,$src2.c\n\t"
10209            "FMULS  $dst.d,$src1.d,$src2.d" %}
10210
10211  ins_encode %{
10212    FloatRegister dsta = $dst$$FloatRegister;
10213    FloatRegister src1a = $src1$$FloatRegister;
10214    FloatRegister src2a = $src2$$FloatRegister;
10215    __ mul_float(dsta, src1a, src2a);
10216    FloatRegister dstb = dsta->successor();
10217    FloatRegister src1b = src1a->successor();
10218    FloatRegister src2b = src2a->successor();
10219    __ mul_float(dstb, src1b, src2b);
10220    FloatRegister dstc = dstb->successor();
10221    FloatRegister src1c = src1b->successor();
10222    FloatRegister src2c = src2b->successor();
10223    __ mul_float(dstc, src1c, src2c);
10224    FloatRegister dstd = dstc->successor();
10225    FloatRegister src1d = src1c->successor();
10226    FloatRegister src2d = src2c->successor();
10227    __ mul_float(dstd, src1d, src2d);
10228  %}
10229
10230  ins_pipe(fmulF_reg_reg); // FIXME
10231%}
10232
10233instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10234  predicate(n->as_Vector()->length() == 2);
10235  match(Set dst (MulVD src1 src2));
10236  size(4*2);
10237  ins_cost(DEFAULT_COST*2); // FIXME
10238
10239  format %{ "FMULD  $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10240            "FMULD  $dst.D.b,$src1.D.b,$src2.D.b" %}
10241  ins_encode %{
10242    FloatRegister dsta = $dst$$FloatRegister;
10243    FloatRegister src1a = $src1$$FloatRegister;
10244    FloatRegister src2a = $src2$$FloatRegister;
10245    __ mul_double(dsta, src1a, src2a);
10246    FloatRegister dstb = dsta->successor()->successor();
10247    FloatRegister src1b = src1a->successor()->successor();
10248    FloatRegister src2b = src2a->successor()->successor();
10249    __ mul_double(dstb, src1b, src2b);
10250  %}
10251
10252  ins_pipe(fmulD_reg_reg); // FIXME
10253%}
10254
10255
10256// Floats vector div
10257instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10258  predicate(n->as_Vector()->length() == 2);
10259  match(Set dst (DivVF src1 src2));
10260  size(4*2);
10261  ins_cost(DEFAULT_COST*2); // FIXME
10262
10263  format %{ "FDIVS  $dst.a,$src1.a,$src2.a\n\t"
10264            "FDIVS  $dst.b,$src1.b,$src2.b" %}
10265  ins_encode %{
10266    __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10267    __ div_float($dst$$FloatRegister->successor(),
10268             $src1$$FloatRegister->successor(),
10269             $src2$$FloatRegister->successor());
10270  %}
10271
10272  ins_pipe(fdivF_reg_reg); // FIXME
10273%}
10274
10275instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10276  predicate(n->as_Vector()->length() == 4);
10277  match(Set dst (DivVF src1 src2));
10278  size(4*4);
10279  ins_cost(DEFAULT_COST*4); // FIXME
10280
10281  format %{ "FDIVS  $dst.a,$src1.a,$src2.a\n\t"
10282            "FDIVS  $dst.b,$src1.b,$src2.b\n\t"
10283            "FDIVS  $dst.c,$src1.c,$src2.c\n\t"
10284            "FDIVS  $dst.d,$src1.d,$src2.d" %}
10285
10286  ins_encode %{
10287    FloatRegister dsta = $dst$$FloatRegister;
10288    FloatRegister src1a = $src1$$FloatRegister;
10289    FloatRegister src2a = $src2$$FloatRegister;
10290    __ div_float(dsta, src1a, src2a);
10291    FloatRegister dstb = dsta->successor();
10292    FloatRegister src1b = src1a->successor();
10293    FloatRegister src2b = src2a->successor();
10294    __ div_float(dstb, src1b, src2b);
10295    FloatRegister dstc = dstb->successor();
10296    FloatRegister src1c = src1b->successor();
10297    FloatRegister src2c = src2b->successor();
10298    __ div_float(dstc, src1c, src2c);
10299    FloatRegister dstd = dstc->successor();
10300    FloatRegister src1d = src1c->successor();
10301    FloatRegister src2d = src2c->successor();
10302    __ div_float(dstd, src1d, src2d);
10303  %}
10304
10305  ins_pipe(fdivF_reg_reg); // FIXME
10306%}
10307
10308instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10309  predicate(n->as_Vector()->length() == 2);
10310  match(Set dst (DivVD src1 src2));
10311  size(4*2);
10312  ins_cost(DEFAULT_COST*2); // FIXME
10313
10314  format %{ "FDIVD  $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10315            "FDIVD  $dst.D.b,$src1.D.b,$src2.D.b" %}
10316  ins_encode %{
10317    FloatRegister dsta = $dst$$FloatRegister;
10318    FloatRegister src1a = $src1$$FloatRegister;
10319    FloatRegister src2a = $src2$$FloatRegister;
10320    __ div_double(dsta, src1a, src2a);
10321    FloatRegister dstb = dsta->successor()->successor();
10322    FloatRegister src1b = src1a->successor()->successor();
10323    FloatRegister src2b = src2a->successor()->successor();
10324    __ div_double(dstb, src1b, src2b);
10325  %}
10326
10327  ins_pipe(fdivD_reg_reg); // FIXME
10328%}
10329
10330// --------------------------------- NEG --------------------------------------
10331
10332instruct vneg8B_reg(vecD dst, vecD src) %{
10333  predicate(n->as_Vector()->length_in_bytes() == 8);
10334  effect(DEF dst, USE src);
10335  size(4);
10336  ins_cost(DEFAULT_COST); // FIXME
10337  format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %}
10338  ins_encode %{
10339    bool quad = false;
10340    __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10341              MacroAssembler::VELEM_SIZE_8, quad);
10342  %}
10343  ins_pipe( ialu_reg_reg ); // FIXME
10344%}
10345
10346instruct vneg16B_reg(vecX dst, vecX src) %{
10347  predicate(n->as_Vector()->length_in_bytes() == 16);
10348  effect(DEF dst, USE src);
10349  size(4);
10350  ins_cost(DEFAULT_COST); // FIXME
10351  format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %}
10352  ins_encode %{
10353    bool _float = false;
10354    bool quad = true;
10355    __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10356              MacroAssembler::VELEM_SIZE_8, quad);
10357  %}
10358  ins_pipe( ialu_reg_reg ); // FIXME
10359%}
10360
10361// ------------------------------ Shift ---------------------------------------
10362
10363instruct vslcntD(vecD dst, iRegI cnt) %{
10364  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10365  match(Set dst (LShiftCntV cnt));
10366  size(4);
10367  ins_cost(DEFAULT_COST); // FIXME
10368  expand %{
10369    Repl8B_reg_simd(dst, cnt);
10370  %}
10371%}
10372
10373instruct vslcntX(vecX dst, iRegI cnt) %{
10374  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10375  match(Set dst (LShiftCntV cnt));
10376  size(4);
10377  ins_cost(DEFAULT_COST); // FIXME
10378  expand %{
10379    Repl16B_reg(dst, cnt);
10380  %}
10381%}
10382
10383// Low bits of vector "shift" elements are used, so it
10384// doesn't matter if we treat it as ints or bytes here.
10385instruct vsrcntD(vecD dst, iRegI cnt) %{
10386  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10387  match(Set dst (RShiftCntV cnt));
10388  size(4*2);
10389  ins_cost(DEFAULT_COST*2); // FIXME
10390
10391  format %{ "VDUP.8 $dst.D,$cnt\n\t"
10392            "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %}
10393  ins_encode %{
10394    bool quad = false;
10395    __ vdupI($dst$$FloatRegister, $cnt$$Register,
10396             MacroAssembler::VELEM_SIZE_8, quad);
10397    __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10398              MacroAssembler::VELEM_SIZE_8, quad);
10399  %}
10400  ins_pipe( ialu_reg_reg ); // FIXME
10401%}
10402
10403instruct vsrcntX(vecX dst, iRegI cnt) %{
10404  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10405  match(Set dst (RShiftCntV cnt));
10406  size(4*2);
10407  ins_cost(DEFAULT_COST*2); // FIXME
10408  format %{ "VDUP.8 $dst.Q,$cnt\n\t"
10409            "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %}
10410  ins_encode %{
10411    bool quad = true;
10412    __ vdupI($dst$$FloatRegister, $cnt$$Register,
10413             MacroAssembler::VELEM_SIZE_8, quad);
10414    __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10415              MacroAssembler::VELEM_SIZE_8, quad);
10416  %}
10417  ins_pipe( ialu_reg_reg ); // FIXME
10418%}
10419
10420// Byte vector logical left/right shift based on sign
10421instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{
10422  predicate(n->as_Vector()->length() == 8);
10423  effect(DEF dst, USE src, USE shift);
10424  size(4);
10425  ins_cost(DEFAULT_COST); // FIXME
10426  format %{
10427    "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B"
10428  %}
10429  ins_encode %{
10430    bool quad = false;
10431    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10432              MacroAssembler::VELEM_SIZE_8, quad);
10433  %}
10434  ins_pipe( ialu_reg_reg ); // FIXME
10435%}
10436
10437instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{
10438  predicate(n->as_Vector()->length() == 16);
10439  effect(DEF dst, USE src, USE shift);
10440  size(4);
10441  ins_cost(DEFAULT_COST); // FIXME
10442  format %{
10443    "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B"
10444  %}
10445  ins_encode %{
10446    bool quad = true;
10447    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10448              MacroAssembler::VELEM_SIZE_8, quad);
10449  %}
10450  ins_pipe( ialu_reg_reg ); // FIXME
10451%}
10452
10453// Shorts/Char vector logical left/right shift based on sign
10454instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{
10455  predicate(n->as_Vector()->length() == 4);
10456  effect(DEF dst, USE src, USE shift);
10457  size(4);
10458  ins_cost(DEFAULT_COST); // FIXME
10459  format %{
10460    "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S"
10461  %}
10462  ins_encode %{
10463    bool quad = false;
10464    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10465              MacroAssembler::VELEM_SIZE_16, quad);
10466  %}
10467  ins_pipe( ialu_reg_reg ); // FIXME
10468%}
10469
10470instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{
10471  predicate(n->as_Vector()->length() == 8);
10472  effect(DEF dst, USE src, USE shift);
10473  size(4);
10474  ins_cost(DEFAULT_COST); // FIXME
10475  format %{
10476    "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S"
10477  %}
10478  ins_encode %{
10479    bool quad = true;
10480    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10481              MacroAssembler::VELEM_SIZE_16, quad);
10482  %}
10483  ins_pipe( ialu_reg_reg ); // FIXME
10484%}
10485
10486// Integers vector logical left/right shift based on sign
10487instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{
10488  predicate(n->as_Vector()->length() == 2);
10489  effect(DEF dst, USE src, USE shift);
10490  size(4);
10491  ins_cost(DEFAULT_COST); // FIXME
10492  format %{
10493    "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I"
10494  %}
10495  ins_encode %{
10496    bool quad = false;
10497    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10498              MacroAssembler::VELEM_SIZE_32, quad);
10499  %}
10500  ins_pipe( ialu_reg_reg ); // FIXME
10501%}
10502
10503instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{
10504  predicate(n->as_Vector()->length() == 4);
10505  effect(DEF dst, USE src, USE shift);
10506  size(4);
10507  ins_cost(DEFAULT_COST); // FIXME
10508  format %{
10509    "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I"
10510  %}
10511  ins_encode %{
10512    bool quad = true;
10513    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10514              MacroAssembler::VELEM_SIZE_32, quad);
10515  %}
10516  ins_pipe( ialu_reg_reg ); // FIXME
10517%}
10518
10519// Longs vector logical left/right shift based on sign
10520instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{
10521  predicate(n->as_Vector()->length() == 2);
10522  effect(DEF dst, USE src, USE shift);
10523  size(4);
10524  ins_cost(DEFAULT_COST); // FIXME
10525  format %{
10526    "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L"
10527  %}
10528  ins_encode %{
10529    bool quad = true;
10530    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10531              MacroAssembler::VELEM_SIZE_64, quad);
10532  %}
10533  ins_pipe( ialu_reg_reg ); // FIXME
10534%}
10535
10536// ------------------------------ LeftShift -----------------------------------
10537
10538// Byte vector left shift
10539instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{
10540  predicate(n->as_Vector()->length() == 8);
10541  match(Set dst (LShiftVB src shift));
10542  size(4*1);
10543  ins_cost(DEFAULT_COST*1); // FIXME
10544  expand %{
10545    vsh8B_reg(dst, src, shift);
10546  %}
10547%}
10548
10549instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{
10550  predicate(n->as_Vector()->length() == 16);
10551  match(Set dst (LShiftVB src shift));
10552  size(4*1);
10553  ins_cost(DEFAULT_COST*1); // FIXME
10554  expand %{
10555    vsh16B_reg(dst, src, shift);
10556  %}
10557%}
10558
10559instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{
10560  predicate(n->as_Vector()->length() == 8);
10561  match(Set dst (LShiftVB src (LShiftCntV shift)));
10562  size(4);
10563  ins_cost(DEFAULT_COST); // FIXME
10564  format %{
10565    "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B"
10566  %}
10567  ins_encode %{
10568    bool quad = false;
10569    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10570             quad);
10571  %}
10572  ins_pipe( ialu_reg_reg ); // FIXME
10573%}
10574
10575instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{
10576  predicate(n->as_Vector()->length() == 16);
10577  match(Set dst (LShiftVB src (LShiftCntV shift)));
10578  size(4);
10579  ins_cost(DEFAULT_COST); // FIXME
10580  format %{
10581    "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B"
10582  %}
10583  ins_encode %{
10584    bool quad = true;
10585    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10586             quad);
10587  %}
10588  ins_pipe( ialu_reg_reg ); // FIXME
10589%}
10590
10591// Shorts/Chars vector logical left/right shift
10592instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{
10593  predicate(n->as_Vector()->length() == 4);
10594  match(Set dst (LShiftVS src shift));
10595  match(Set dst (URShiftVS src shift));
10596  size(4*1);
10597  ins_cost(DEFAULT_COST*1); // FIXME
10598  expand %{
10599    vsh4S_reg(dst, src, shift);
10600  %}
10601%}
10602
10603instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{
10604  predicate(n->as_Vector()->length() == 8);
10605  match(Set dst (LShiftVS src shift));
10606  match(Set dst (URShiftVS src shift));
10607  size(4*1);
10608  ins_cost(DEFAULT_COST*1); // FIXME
10609  expand %{
10610    vsh8S_reg(dst, src, shift);
10611  %}
10612%}
10613
10614instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{
10615  predicate(n->as_Vector()->length() == 4);
10616  match(Set dst (LShiftVS src (LShiftCntV shift)));
10617  size(4);
10618  ins_cost(DEFAULT_COST); // FIXME
10619  format %{
10620    "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S"
10621  %}
10622  ins_encode %{
10623    bool quad = false;
10624    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10625             quad);
10626  %}
10627  ins_pipe( ialu_reg_reg ); // FIXME
10628%}
10629
10630instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{
10631  predicate(n->as_Vector()->length() == 8);
10632  match(Set dst (LShiftVS src shift));
10633  size(4);
10634  ins_cost(DEFAULT_COST); // FIXME
10635  format %{
10636    "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S"
10637  %}
10638  ins_encode %{
10639    bool quad = true;
10640    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10641             quad);
10642  %}
10643  ins_pipe( ialu_reg_reg ); // FIXME
10644%}
10645
10646// Integers vector logical left/right shift
10647instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{
10648  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10649  match(Set dst (LShiftVI src shift));
10650  match(Set dst (URShiftVI src shift));
10651  size(4*1);
10652  ins_cost(DEFAULT_COST*1); // FIXME
10653  expand %{
10654    vsh2I_reg(dst, src, shift);
10655  %}
10656%}
10657
10658instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{
10659  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10660  match(Set dst (LShiftVI src shift));
10661  match(Set dst (URShiftVI src shift));
10662  size(4*1);
10663  ins_cost(DEFAULT_COST*1); // FIXME
10664  expand %{
10665    vsh4I_reg(dst, src, shift);
10666  %}
10667%}
10668
10669instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{
10670  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10671  match(Set dst (LShiftVI src (LShiftCntV shift)));
10672  size(4);
10673  ins_cost(DEFAULT_COST); // FIXME
10674  format %{
10675    "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I"
10676  %}
10677  ins_encode %{
10678    bool quad = false;
10679    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10680             quad);
10681  %}
10682  ins_pipe( ialu_reg_reg ); // FIXME
10683%}
10684
10685instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{
10686  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10687  match(Set dst (LShiftVI src (LShiftCntV shift)));
10688  size(4);
10689  ins_cost(DEFAULT_COST); // FIXME
10690  format %{
10691    "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I"
10692  %}
10693  ins_encode %{
10694    bool quad = true;
10695    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10696             quad);
10697  %}
10698  ins_pipe( ialu_reg_reg ); // FIXME
10699%}
10700
10701// Longs vector logical left/right shift
10702instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{
10703  predicate(n->as_Vector()->length() == 2);
10704  match(Set dst (LShiftVL src shift));
10705  match(Set dst (URShiftVL src shift));
10706  size(4*1);
10707  ins_cost(DEFAULT_COST*1); // FIXME
10708  expand %{
10709    vsh2L_reg(dst, src, shift);
10710  %}
10711%}
10712
10713instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{
10714  predicate(n->as_Vector()->length() == 2);
10715  match(Set dst (LShiftVL src (LShiftCntV shift)));
10716  size(4);
10717  ins_cost(DEFAULT_COST); // FIXME
10718  format %{
10719    "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L"
10720  %}
10721  ins_encode %{
10722    bool quad = true;
10723    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
10724             quad);
10725  %}
10726  ins_pipe( ialu_reg_reg ); // FIXME
10727%}
10728
10729// ----------------------- LogicalRightShift -----------------------------------
10730
10731// Bytes/Shorts vector logical right shift produces incorrect Java result
10732// for negative data because java code convert short value into int with
10733// sign extension before a shift.
10734
10735// Chars vector logical right shift
10736instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{
10737  predicate(n->as_Vector()->length() == 4);
10738  match(Set dst (URShiftVS src (RShiftCntV shift)));
10739  size(4);
10740  ins_cost(DEFAULT_COST); // FIXME
10741  format %{
10742    "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
10743  %}
10744  ins_encode %{
10745    bool quad = false;
10746    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10747             quad);
10748  %}
10749  ins_pipe( ialu_reg_reg ); // FIXME
10750%}
10751
10752instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{
10753  predicate(n->as_Vector()->length() == 8);
10754  match(Set dst (URShiftVS src (RShiftCntV shift)));
10755  size(4);
10756  ins_cost(DEFAULT_COST); // FIXME
10757  format %{
10758    "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
10759  %}
10760  ins_encode %{
10761    bool quad = true;
10762    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10763             quad);
10764  %}
10765  ins_pipe( ialu_reg_reg ); // FIXME
10766%}
10767
10768// Integers vector logical right shift
10769instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{
10770  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10771  match(Set dst (URShiftVI src (RShiftCntV shift)));
10772  size(4);
10773  ins_cost(DEFAULT_COST); // FIXME
10774  format %{
10775    "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
10776  %}
10777  ins_encode %{
10778    bool quad = false;
10779    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10780             quad);
10781  %}
10782  ins_pipe( ialu_reg_reg ); // FIXME
10783%}
10784
10785instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{
10786  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10787  match(Set dst (URShiftVI src (RShiftCntV shift)));
10788  size(4);
10789  ins_cost(DEFAULT_COST); // FIXME
10790  format %{
10791    "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
10792  %}
10793  ins_encode %{
10794    bool quad = true;
10795    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10796             quad);
10797  %}
10798  ins_pipe( ialu_reg_reg ); // FIXME
10799%}
10800
10801// Longs vector logical right shift
10802instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{
10803  predicate(n->as_Vector()->length() == 2);
10804  match(Set dst (URShiftVL src (RShiftCntV shift)));
10805  size(4);
10806  ins_cost(DEFAULT_COST); // FIXME
10807  format %{
10808    "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
10809  %}
10810  ins_encode %{
10811    bool quad = true;
10812    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
10813             quad);
10814  %}
10815  ins_pipe( ialu_reg_reg ); // FIXME
10816%}
10817
10818// ------------------- ArithmeticRightShift -----------------------------------
10819
10820// Bytes vector arithmetic left/right shift based on sign
10821instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{
10822  predicate(n->as_Vector()->length() == 8);
10823  effect(DEF dst, USE src, USE shift);
10824  size(4);
10825  ins_cost(DEFAULT_COST); // FIXME
10826  format %{
10827    "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B"
10828  %}
10829  ins_encode %{
10830    bool quad = false;
10831    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10832              MacroAssembler::VELEM_SIZE_8, quad);
10833  %}
10834  ins_pipe( ialu_reg_reg ); // FIXME
10835%}
10836
10837instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{
10838  predicate(n->as_Vector()->length() == 16);
10839  effect(DEF dst, USE src, USE shift);
10840  size(4);
10841  ins_cost(DEFAULT_COST); // FIXME
10842  format %{
10843    "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B"
10844  %}
10845  ins_encode %{
10846    bool quad = true;
10847    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10848              MacroAssembler::VELEM_SIZE_8, quad);
10849  %}
10850  ins_pipe( ialu_reg_reg ); // FIXME
10851%}
10852
10853// Shorts vector arithmetic left/right shift based on sign
10854instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{
10855  predicate(n->as_Vector()->length() == 4);
10856  effect(DEF dst, USE src, USE shift);
10857  size(4);
10858  ins_cost(DEFAULT_COST); // FIXME
10859  format %{
10860    "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S"
10861  %}
10862  ins_encode %{
10863    bool quad = false;
10864    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10865              MacroAssembler::VELEM_SIZE_16, quad);
10866  %}
10867  ins_pipe( ialu_reg_reg ); // FIXME
10868%}
10869
10870instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{
10871  predicate(n->as_Vector()->length() == 8);
10872  effect(DEF dst, USE src, USE shift);
10873  size(4);
10874  ins_cost(DEFAULT_COST); // FIXME
10875  format %{
10876    "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S"
10877  %}
10878  ins_encode %{
10879    bool quad = true;
10880    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10881              MacroAssembler::VELEM_SIZE_16, quad);
10882  %}
10883  ins_pipe( ialu_reg_reg ); // FIXME
10884%}
10885
10886// Integers vector arithmetic left/right shift based on sign
10887instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{
10888  predicate(n->as_Vector()->length() == 2);
10889  effect(DEF dst, USE src, USE shift);
10890  size(4);
10891  ins_cost(DEFAULT_COST); // FIXME
10892  format %{
10893    "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I"
10894  %}
10895  ins_encode %{
10896    bool quad = false;
10897    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10898              MacroAssembler::VELEM_SIZE_32, quad);
10899  %}
10900  ins_pipe( ialu_reg_reg ); // FIXME
10901%}
10902
10903instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{
10904  predicate(n->as_Vector()->length() == 4);
10905  effect(DEF dst, USE src, USE shift);
10906  size(4);
10907  ins_cost(DEFAULT_COST); // FIXME
10908  format %{
10909    "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I"
10910  %}
10911  ins_encode %{
10912    bool quad = true;
10913    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10914              MacroAssembler::VELEM_SIZE_32, quad);
10915  %}
10916  ins_pipe( ialu_reg_reg ); // FIXME
10917%}
10918
10919// Longs vector arithmetic left/right shift based on sign
10920instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{
10921  predicate(n->as_Vector()->length() == 2);
10922  effect(DEF dst, USE src, USE shift);
10923  size(4);
10924  ins_cost(DEFAULT_COST); // FIXME
10925  format %{
10926    "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L"
10927  %}
10928  ins_encode %{
10929    bool quad = true;
10930    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10931              MacroAssembler::VELEM_SIZE_64, quad);
10932  %}
10933  ins_pipe( ialu_reg_reg ); // FIXME
10934%}
10935
10936// Byte vector arithmetic right shift
10937
10938instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{
10939  predicate(n->as_Vector()->length() == 8);
10940  match(Set dst (RShiftVB src shift));
10941  size(4);
10942  ins_cost(DEFAULT_COST); // FIXME
10943  expand %{
10944    vsha8B_reg(dst, src, shift);
10945  %}
10946%}
10947
10948instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{
10949  predicate(n->as_Vector()->length() == 16);
10950  match(Set dst (RShiftVB src shift));
10951  size(4);
10952  ins_cost(DEFAULT_COST); // FIXME
10953  expand %{
10954    vsha16B_reg(dst, src, shift);
10955  %}
10956%}
10957
10958instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{
10959  predicate(n->as_Vector()->length() == 8);
10960  match(Set dst (RShiftVB src shift));
10961  size(4);
10962  ins_cost(DEFAULT_COST); // FIXME
10963  format %{
10964    "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B"
10965  %}
10966  ins_encode %{
10967    bool quad = false;
10968    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10969             quad);
10970  %}
10971  ins_pipe( ialu_reg_reg ); // FIXME
10972%}
10973
10974instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{
10975  predicate(n->as_Vector()->length() == 16);
10976  match(Set dst (RShiftVB src shift));
10977  size(4);
10978  ins_cost(DEFAULT_COST); // FIXME
10979  format %{
10980    "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B"
10981  %}
10982  ins_encode %{
10983    bool quad = true;
10984    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10985             quad);
10986  %}
10987  ins_pipe( ialu_reg_reg ); // FIXME
10988%}
10989
10990// Shorts vector arithmetic right shift
10991instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{
10992  predicate(n->as_Vector()->length() == 4);
10993  match(Set dst (RShiftVS src shift));
10994  size(4);
10995  ins_cost(DEFAULT_COST); // FIXME
10996  expand %{
10997    vsha4S_reg(dst, src, shift);
10998  %}
10999%}
11000
11001instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{
11002  predicate(n->as_Vector()->length() == 8);
11003  match(Set dst (RShiftVS src shift));
11004  size(4);
11005  ins_cost(DEFAULT_COST); // FIXME
11006  expand %{
11007    vsha8S_reg(dst, src, shift);
11008  %}
11009%}
11010
11011instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{
11012  predicate(n->as_Vector()->length() == 4);
11013  match(Set dst (RShiftVS src shift));
11014  size(4);
11015  ins_cost(DEFAULT_COST); // FIXME
11016  format %{
11017    "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
11018  %}
11019  ins_encode %{
11020    bool quad = false;
11021    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11022             quad);
11023  %}
11024  ins_pipe( ialu_reg_reg ); // FIXME
11025%}
11026
11027instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{
11028  predicate(n->as_Vector()->length() == 8);
11029  match(Set dst (RShiftVS src shift));
11030  size(4);
11031  ins_cost(DEFAULT_COST); // FIXME
11032  format %{
11033    "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
11034  %}
11035  ins_encode %{
11036    bool quad = true;
11037    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11038             quad);
11039  %}
11040  ins_pipe( ialu_reg_reg ); // FIXME
11041%}
11042
11043// Integers vector arithmetic right shift
11044instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{
11045  predicate(n->as_Vector()->length() == 2);
11046  match(Set dst (RShiftVI src shift));
11047  size(4);
11048  ins_cost(DEFAULT_COST); // FIXME
11049  expand %{
11050    vsha2I_reg(dst, src, shift);
11051  %}
11052%}
11053
11054instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{
11055  predicate(n->as_Vector()->length() == 4);
11056  match(Set dst (RShiftVI src shift));
11057  size(4);
11058  ins_cost(DEFAULT_COST); // FIXME
11059  expand %{
11060    vsha4I_reg(dst, src, shift);
11061  %}
11062%}
11063
11064instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{
11065  predicate(n->as_Vector()->length() == 2);
11066  match(Set dst (RShiftVI src shift));
11067  size(4);
11068  ins_cost(DEFAULT_COST); // FIXME
11069  format %{
11070    "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
11071  %}
11072  ins_encode %{
11073    bool quad = false;
11074    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11075             quad);
11076  %}
11077  ins_pipe( ialu_reg_reg ); // FIXME
11078%}
11079
11080instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{
11081  predicate(n->as_Vector()->length() == 4);
11082  match(Set dst (RShiftVI src shift));
11083  size(4);
11084  ins_cost(DEFAULT_COST); // FIXME
11085  format %{
11086    "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
11087  %}
11088  ins_encode %{
11089    bool quad = true;
11090    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11091             quad);
11092  %}
11093  ins_pipe( ialu_reg_reg ); // FIXME
11094%}
11095
11096// Longs vector arithmetic right shift
11097instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{
11098  predicate(n->as_Vector()->length() == 2);
11099  match(Set dst (RShiftVL src shift));
11100  size(4);
11101  ins_cost(DEFAULT_COST); // FIXME
11102  expand %{
11103    vsha2L_reg(dst, src, shift);
11104  %}
11105%}
11106
11107instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{
11108  predicate(n->as_Vector()->length() == 2);
11109  match(Set dst (RShiftVL src shift));
11110  size(4);
11111  ins_cost(DEFAULT_COST); // FIXME
11112  format %{
11113    "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
11114  %}
11115  ins_encode %{
11116    bool quad = true;
11117    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11118             quad);
11119  %}
11120  ins_pipe( ialu_reg_reg ); // FIXME
11121%}
11122
11123// --------------------------------- AND --------------------------------------
11124
11125instruct vandD(vecD dst, vecD src1, vecD src2) %{
11126  predicate(n->as_Vector()->length_in_bytes() == 8);
11127  match(Set dst (AndV src1 src2));
11128  format %{ "VAND    $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11129  ins_encode %{
11130    bool quad = false;
11131    __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11132             quad);
11133  %}
11134  ins_pipe( ialu_reg_reg ); // FIXME
11135%}
11136
11137instruct vandX(vecX dst, vecX src1, vecX src2) %{
11138  predicate(n->as_Vector()->length_in_bytes() == 16);
11139  match(Set dst (AndV src1 src2));
11140  format %{ "VAND    $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11141  ins_encode %{
11142    bool quad = true;
11143    __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11144             quad);
11145  %}
11146  ins_pipe( ialu_reg_reg ); // FIXME
11147%}
11148
11149// --------------------------------- OR ---------------------------------------
11150
11151instruct vorD(vecD dst, vecD src1, vecD src2) %{
11152  predicate(n->as_Vector()->length_in_bytes() == 8);
11153  match(Set dst (OrV src1 src2));
11154  format %{ "VOR     $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11155  ins_encode %{
11156    bool quad = false;
11157    __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11158            quad);
11159  %}
11160  ins_pipe( ialu_reg_reg ); // FIXME
11161%}
11162
11163instruct vorX(vecX dst, vecX src1, vecX src2) %{
11164  predicate(n->as_Vector()->length_in_bytes() == 16);
11165  match(Set dst (OrV src1 src2));
11166  format %{ "VOR     $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11167  ins_encode %{
11168    bool quad = true;
11169    __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11170            quad);
11171  %}
11172  ins_pipe( ialu_reg_reg ); // FIXME
11173%}
11174
11175// --------------------------------- XOR --------------------------------------
11176
11177instruct vxorD(vecD dst, vecD src1, vecD src2) %{
11178  predicate(n->as_Vector()->length_in_bytes() == 8);
11179  match(Set dst (XorV src1 src2));
11180  format %{ "VXOR    $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11181  ins_encode %{
11182    bool quad = false;
11183    __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11184             quad);
11185  %}
11186  ins_pipe( ialu_reg_reg ); // FIXME
11187%}
11188
11189instruct vxorX(vecX dst, vecX src1, vecX src2) %{
11190  predicate(n->as_Vector()->length_in_bytes() == 16);
11191  match(Set dst (XorV src1 src2));
11192  format %{ "VXOR    $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11193  ins_encode %{
11194    bool quad = true;
11195    __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11196             quad);
11197  %}
11198  ins_pipe( ialu_reg_reg ); // FIXME
11199%}
11200
11201
11202//----------PEEPHOLE RULES-----------------------------------------------------
11203// These must follow all instruction definitions as they use the names
11204// defined in the instructions definitions.
11205//
11206// peepmatch ( root_instr_name [preceding_instruction]* );
11207//
11208// peepconstraint %{
11209// (instruction_number.operand_name relational_op instruction_number.operand_name
11210//  [, ...] );
11211// // instruction numbers are zero-based using left to right order in peepmatch
11212//
11213// peepreplace ( instr_name  ( [instruction_number.operand_name]* ) );
11214// // provide an instruction_number.operand_name for each operand that appears
11215// // in the replacement instruction's match rule
11216//
11217// ---------VM FLAGS---------------------------------------------------------
11218//
11219// All peephole optimizations can be turned off using -XX:-OptoPeephole
11220//
11221// Each peephole rule is given an identifying number starting with zero and
11222// increasing by one in the order seen by the parser.  An individual peephole
11223// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
11224// on the command-line.
11225//
11226// ---------CURRENT LIMITATIONS----------------------------------------------
11227//
11228// Only match adjacent instructions in same basic block
11229// Only equality constraints
11230// Only constraints between operands, not (0.dest_reg == EAX_enc)
11231// Only one replacement instruction
11232//
11233// ---------EXAMPLE----------------------------------------------------------
11234//
11235// // pertinent parts of existing instructions in architecture description
11236// instruct movI(eRegI dst, eRegI src) %{
11237//   match(Set dst (CopyI src));
11238// %}
11239//
11240// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{
11241//   match(Set dst (AddI dst src));
11242//   effect(KILL cr);
11243// %}
11244//
11245// // Change (inc mov) to lea
11246// peephole %{
11247//   // increment preceeded by register-register move
11248//   peepmatch ( incI_eReg movI );
11249//   // require that the destination register of the increment
11250//   // match the destination register of the move
11251//   peepconstraint ( 0.dst == 1.dst );
11252//   // construct a replacement instruction that sets
11253//   // the destination to ( move's source register + one )
11254//   peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) );
11255// %}
11256//
11257
11258// // Change load of spilled value to only a spill
11259// instruct storeI(memory mem, eRegI src) %{
11260//   match(Set mem (StoreI mem src));
11261// %}
11262//
11263// instruct loadI(eRegI dst, memory mem) %{
11264//   match(Set dst (LoadI mem));
11265// %}
11266//
11267// peephole %{
11268//   peepmatch ( loadI storeI );
11269//   peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
11270//   peepreplace ( storeI( 1.mem 1.mem 1.src ) );
11271// %}
11272
11273//----------SMARTSPILL RULES---------------------------------------------------
11274// These must follow all instruction definitions as they use the names
11275// defined in the instructions definitions.
11276//
11277// ARM will probably not have any of these rules due to RISC instruction set.
11278
11279//----------PIPELINE-----------------------------------------------------------
11280// Rules which define the behavior of the target architectures pipeline.
11281