jdk

Форк
0
/
arm.ad 
11680 строк · 345.5 Кб
1
//
2
// Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
3
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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
//
37
definitions %{
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
54
source_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
#include "asm/macroAssembler.hpp"
63
#include "gc/shared/barrierSetAssembler.hpp"
64

65
// Does destination need to be loaded in a register then passed to a
66
// branch instruction?
67
extern bool maybe_far_call(const CallNode *n);
68
extern bool maybe_far_call(const MachCallNode *n);
69
static inline bool cache_reachable() {
70
  return MacroAssembler::_cache_fully_reachable();
71
}
72

73
#define ldr_32 ldr
74
#define str_32 str
75
#define tst_32 tst
76
#define teq_32 teq
77
#if 1
78
extern bool PrintOptoAssembly;
79
#endif
80

81
class c2 {
82
public:
83
  static OptoRegPair return_value(int ideal_reg);
84
};
85

86
class CallStubImpl {
87

88
  //--------------------------------------------------------------
89
  //---<  Used for optimization in Compile::Shorten_branches  >---
90
  //--------------------------------------------------------------
91

92
 public:
93
  // Size of call trampoline stub.
94
  static uint size_call_trampoline() {
95
    return 0; // no call trampolines on this platform
96
  }
97

98
  // number of relocations needed by a call trampoline stub
99
  static uint reloc_call_trampoline() {
100
    return 0; // no call trampolines on this platform
101
  }
102
};
103

104
class HandlerImpl {
105

106
 public:
107

108
  static int emit_exception_handler(C2_MacroAssembler *masm);
109
  static int emit_deopt_handler(C2_MacroAssembler* masm);
110

111
  static uint size_exception_handler() {
112
    return ( 3 * 4 );
113
  }
114

115

116
  static uint size_deopt_handler() {
117
    return ( 9 * 4 );
118
  }
119

120
};
121

122
class Node::PD {
123
public:
124
  enum NodeFlags {
125
    _last_flag = Node::_last_flag
126
  };
127
};
128

129
// Assert that the given node is not a var shift.
130
bool assert_not_var_shift(const Node *n);
131
%}
132

133
source %{
134

135
// Assert that the given node is not a var shift.
136
bool assert_not_var_shift(const Node *n) {
137
  assert(!n->as_ShiftV()->is_var_shift(), "illegal var shift");
138
  return true;
139
}
140

141
#define __ masm->
142

143
static FloatRegister reg_to_FloatRegister_object(int register_encoding);
144
static Register reg_to_register_object(int register_encoding);
145

146
void PhaseOutput::pd_perform_mach_node_analysis() {
147
}
148

149
int MachNode::pd_alignment_required() const {
150
  return 1;
151
}
152

153
int MachNode::compute_padding(int current_offset) const {
154
  return 0;
155
}
156

157
// ****************************************************************************
158

159
// REQUIRED FUNCTIONALITY
160

161
// emit an interrupt that is caught by the debugger (for debugging compiler)
162
void emit_break(C2_MacroAssembler *masm) {
163
  __ breakpoint();
164
}
165

166
#ifndef PRODUCT
167
void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const {
168
  st->print("TA");
169
}
170
#endif
171

172
void MachBreakpointNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
173
  emit_break(masm);
174
}
175

176
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
177
  return MachNode::size(ra_);
178
}
179

180

181
void emit_nop(C2_MacroAssembler *masm) {
182
  __ nop();
183
}
184

185

186
void emit_call_reloc(C2_MacroAssembler *masm, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) {
187
  int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset();
188
  int call_site_offset = __ code()->insts()->mark_off();
189
  __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call
190
  address target = (address)m->method();
191
  assert(n->as_MachCall()->entry_point() == target, "sanity");
192
  assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity");
193
  assert(cache_reachable() == __ cache_fully_reachable(), "sanity");
194

195
  assert(target != nullptr, "need real address");
196

197
  int ret_addr_offset = -1;
198
  if (rspec.type() == relocInfo::runtime_call_type) {
199
    __ call(target, rspec);
200
    ret_addr_offset = __ offset();
201
  } else {
202
    // scratches Rtemp
203
    ret_addr_offset = __ patchable_call(target, rspec, true);
204
  }
205
  assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()");
206
}
207

208
//=============================================================================
209
// REQUIRED FUNCTIONALITY for encoding
210
void emit_lo(C2_MacroAssembler *masm, int val) {  }
211
void emit_hi(C2_MacroAssembler *masm, int val) {  }
212

213

214
//=============================================================================
215
const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
216

217
int ConstantTable::calculate_table_base_offset() const {
218
  int offset = -(size() / 2);
219
  // flds, fldd: 8-bit  offset multiplied by 4: +/- 1024
220
  // ldr, ldrb : 12-bit offset:                 +/- 4096
221
  if (!Assembler::is_simm10(offset)) {
222
    offset = Assembler::min_simm10;
223
  }
224
  return offset;
225
}
226

227
bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
228
void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
229
  ShouldNotReachHere();
230
}
231

232
void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const {
233
  Compile* C = ra_->C;
234
  ConstantTable& constant_table = C->output()->constant_table();
235

236
  Register r = as_Register(ra_->get_encode(this));
237
  CodeSection* consts_section = __ code()->consts();
238
  CodeSection* insts_section = __ code()->insts();
239
  // constants section size is aligned according to the align_at_start settings of the next section
240
  int consts_size = insts_section->align_at_start(consts_section->size());
241
  assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size);
242

243
  // Materialize the constant table base.
244
  address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
245
  RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
246
  __ mov_address(r, baseaddr, rspec);
247
}
248

249
uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
250
  return 8;
251
}
252

253
#ifndef PRODUCT
254
void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
255
  char reg[128];
256
  ra_->dump_register(this, reg, sizeof(reg));
257
  st->print("MOV_SLOW    &constanttable,%s\t! constant table base", reg);
258
}
259
#endif
260

261
#ifndef PRODUCT
262
void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
263
  Compile* C = ra_->C;
264

265
  for (int i = 0; i < OptoPrologueNops; i++) {
266
    st->print_cr("NOP"); st->print("\t");
267
  }
268

269
  size_t framesize = C->output()->frame_size_in_bytes();
270
  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
271
  int bangsize = C->output()->bang_size_in_bytes();
272
  // Remove two words for return addr and rbp,
273
  framesize -= 2*wordSize;
274
  bangsize -= 2*wordSize;
275

276
  // Calls to C2R adapters often do not accept exceptional returns.
277
  // We require that their callers must bang for them.  But be careful, because
278
  // some VM calls (such as call site linkage) can use several kilobytes of
279
  // stack.  But the stack safety zone should account for that.
280
  // See bugs 4446381, 4468289, 4497237.
281
  if (C->output()->need_stack_bang(bangsize)) {
282
    st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
283
  }
284
  st->print_cr("PUSH   R_FP|R_LR_LR"); st->print("\t");
285
  if (framesize != 0) {
286
    st->print   ("SUB    R_SP, R_SP, " SIZE_FORMAT,framesize);
287
  }
288

289
  if (C->stub_function() == nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
290
    st->print("ldr t0, [guard]\n\t");
291
    st->print("ldr t1, [Rthread, #thread_disarmed_guard_value_offset]\n\t");
292
    st->print("cmp t0, t1\n\t");
293
    st->print("beq skip\n\t");
294
    st->print("blr #nmethod_entry_barrier_stub\n\t");
295
    st->print("b skip\n\t");
296
    st->print("guard: int\n\t");
297
    st->print("skip:\n\t");
298
  }
299
}
300
#endif
301

302
void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
303
  Compile* C = ra_->C;
304

305
  for (int i = 0; i < OptoPrologueNops; i++) {
306
    __ nop();
307
  }
308

309
  size_t framesize = C->output()->frame_size_in_bytes();
310
  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
311
  int bangsize = C->output()->bang_size_in_bytes();
312
  // Remove two words for return addr and fp,
313
  framesize -= 2*wordSize;
314
  bangsize -= 2*wordSize;
315

316
  // Calls to C2R adapters often do not accept exceptional returns.
317
  // We require that their callers must bang for them.  But be careful, because
318
  // some VM calls (such as call site linkage) can use several kilobytes of
319
  // stack.  But the stack safety zone should account for that.
320
  // See bugs 4446381, 4468289, 4497237.
321
  if (C->output()->need_stack_bang(bangsize)) {
322
    __ arm_stack_overflow_check(bangsize, Rtemp);
323
  }
324

325
  __ raw_push(FP, LR);
326
  if (framesize != 0) {
327
    __ sub_slow(SP, SP, framesize);
328
  }
329

330
  if (C->stub_function() == nullptr) {
331
    BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
332
    bs->nmethod_entry_barrier(masm);
333
  }
334

335
  // offset from scratch buffer is not valid
336
  if (strcmp(__ code()->name(), "Compile::Fill_buffer") == 0) {
337
    C->output()->set_frame_complete( __ offset() );
338
  }
339

340
  if (C->has_mach_constant_base_node()) {
341
    // NOTE: We set the table base offset here because users might be
342
    // emitted before MachConstantBaseNode.
343
    ConstantTable& constant_table = C->output()->constant_table();
344
    constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
345
  }
346
}
347

348
uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
349
  return MachNode::size(ra_);
350
}
351

352
int MachPrologNode::reloc() const {
353
  return 10; // a large enough number
354
}
355

356
//=============================================================================
357
#ifndef PRODUCT
358
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
359
  Compile* C = ra_->C;
360

361
  size_t framesize = C->output()->frame_size_in_bytes();
362
  framesize -= 2*wordSize;
363

364
  if (framesize != 0) {
365
    st->print("ADD    R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize);
366
  }
367
  st->print("POP    R_FP|R_LR_LR");
368

369
  if (do_polling() && ra_->C->is_method_compilation()) {
370
    st->print("\n\t");
371
    st->print("MOV    Rtemp, #PollAddr\t! Load Polling address\n\t");
372
    st->print("LDR    Rtemp,[Rtemp]\t!Poll for Safepointing");
373
  }
374
}
375
#endif
376

377
void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
378
  Compile* C = ra_->C;
379

380
  size_t framesize = C->output()->frame_size_in_bytes();
381
  framesize -= 2*wordSize;
382
  if (framesize != 0) {
383
    __ add_slow(SP, SP, framesize);
384
  }
385
  __ raw_pop(FP, LR);
386

387
  // If this does safepoint polling, then do it here
388
  if (do_polling() && ra_->C->is_method_compilation()) {
389
    __ read_polling_page(Rtemp, relocInfo::poll_return_type);
390
  }
391
}
392

393
uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
394
  return MachNode::size(ra_);
395
}
396

397
int MachEpilogNode::reloc() const {
398
  return 16; // a large enough number
399
}
400

401
const Pipeline * MachEpilogNode::pipeline() const {
402
  return MachNode::pipeline_class();
403
}
404

405
//=============================================================================
406

407
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
408
enum RC { rc_bad, rc_int, rc_float, rc_stack };
409
static enum RC rc_class( OptoReg::Name reg ) {
410
  if (!OptoReg::is_valid(reg)) return rc_bad;
411
  if (OptoReg::is_stack(reg)) return rc_stack;
412
  VMReg r = OptoReg::as_VMReg(reg);
413
  if (r->is_Register()) return rc_int;
414
  assert(r->is_FloatRegister(), "must be");
415
  return rc_float;
416
}
417

418
static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) {
419
  int rlo = Matcher::_regEncode[src_first];
420
  int rhi = Matcher::_regEncode[src_second];
421
  if (!((rlo&1)==0 && (rlo+1 == rhi))) {
422
    tty->print_cr("CAUGHT BAD LDRD/STRD");
423
  }
424
  return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset);
425
}
426

427
uint MachSpillCopyNode::implementation( C2_MacroAssembler *masm,
428
                                        PhaseRegAlloc *ra_,
429
                                        bool do_size,
430
                                        outputStream* st ) const {
431
  // Get registers to move
432
  OptoReg::Name src_second = ra_->get_reg_second(in(1));
433
  OptoReg::Name src_first = ra_->get_reg_first(in(1));
434
  OptoReg::Name dst_second = ra_->get_reg_second(this );
435
  OptoReg::Name dst_first = ra_->get_reg_first(this );
436

437
  enum RC src_second_rc = rc_class(src_second);
438
  enum RC src_first_rc = rc_class(src_first);
439
  enum RC dst_second_rc = rc_class(dst_second);
440
  enum RC dst_first_rc = rc_class(dst_first);
441

442
  assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
443

444
  // Generate spill code!
445
  int size = 0;
446

447
  if (src_first == dst_first && src_second == dst_second)
448
    return size;            // Self copy, no move
449

450
#ifdef TODO
451
  if (bottom_type()->isa_vect() != nullptr) {
452
  }
453
#endif
454

455
  // Shared code does not expect instruction set capability based bailouts here.
456
  // Handle offset unreachable bailout with minimal change in shared code.
457
  // Bailout only for real instruction emit.
458
  // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
459

460
  // --------------------------------------
461
  // Check for mem-mem move.  Load into unused float registers and fall into
462
  // the float-store case.
463
  if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
464
    int offset = ra_->reg2offset(src_first);
465
    if (masm && !is_memoryfp(offset)) {
466
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
467
      return 0;
468
    } else {
469
      if (src_second_rc != rc_bad) {
470
        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
471
        src_first     = OptoReg::Name(R_mem_copy_lo_num);
472
        src_second    = OptoReg::Name(R_mem_copy_hi_num);
473
        src_first_rc  = rc_float;
474
        src_second_rc = rc_float;
475
        if (masm) {
476
          __ ldr_double(Rmemcopy, Address(SP, offset));
477
        } else if (!do_size) {
478
          st->print(LDR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
479
        }
480
      } else {
481
        src_first     = OptoReg::Name(R_mem_copy_lo_num);
482
        src_first_rc  = rc_float;
483
        if (masm) {
484
          __ ldr_float(Rmemcopy, Address(SP, offset));
485
        } else if (!do_size) {
486
          st->print(LDR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
487
        }
488
      }
489
      size += 4;
490
    }
491
  }
492

493
  if (src_second_rc == rc_stack && dst_second_rc == rc_stack) {
494
    Unimplemented();
495
  }
496

497
  // --------------------------------------
498
  // Check for integer reg-reg copy
499
  if (src_first_rc == rc_int && dst_first_rc == rc_int) {
500
    // Else normal reg-reg copy
501
    assert( src_second != dst_first, "smashed second before evacuating it" );
502
    if (masm) {
503
      __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
504
#ifndef PRODUCT
505
    } else if (!do_size) {
506
      st->print("MOV    R_%s, R_%s\t# spill",
507
                Matcher::regName[dst_first],
508
                Matcher::regName[src_first]);
509
#endif
510
    }
511
    size += 4;
512
  }
513

514
  // Check for integer store
515
  if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
516
    int offset = ra_->reg2offset(dst_first);
517
    if (masm && !is_memoryI(offset)) {
518
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
519
      return 0;
520
    } else {
521
      if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) {
522
        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
523
        if (masm) {
524
          __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
525
#ifndef PRODUCT
526
        } else if (!do_size) {
527
          if (size != 0) st->print("\n\t");
528
          st->print(STR_64 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
529
#endif
530
        }
531
        return size + 4;
532
      } else {
533
        if (masm) {
534
          __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
535
#ifndef PRODUCT
536
        } else if (!do_size) {
537
          if (size != 0) st->print("\n\t");
538
          st->print(STR_32 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
539
#endif
540
        }
541
      }
542
    }
543
    size += 4;
544
  }
545

546
  // Check for integer load
547
  if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
548
    int offset = ra_->reg2offset(src_first);
549
    if (masm && !is_memoryI(offset)) {
550
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
551
      return 0;
552
    } else {
553
      if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) {
554
        assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
555
        if (masm) {
556
          __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
557
#ifndef PRODUCT
558
        } else if (!do_size) {
559
          if (size != 0) st->print("\n\t");
560
          st->print(LDR_64 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
561
#endif
562
        }
563
        return size + 4;
564
      } else {
565
        if (masm) {
566
          __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
567
#ifndef PRODUCT
568
        } else if (!do_size) {
569
          if (size != 0) st->print("\n\t");
570
          st->print(LDR_32 "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
571
#endif
572
        }
573
      }
574
    }
575
    size += 4;
576
  }
577

578
  // Check for float reg-reg copy
579
  if (src_first_rc == rc_float && dst_first_rc == rc_float) {
580
    if (src_second_rc != rc_bad) {
581
      assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
582
      if (masm) {
583
      __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
584
#ifndef PRODUCT
585
      } else if (!do_size) {
586
        st->print(MOV_DOUBLE "    R_%s, R_%s\t# spill",
587
                  Matcher::regName[dst_first],
588
                  Matcher::regName[src_first]);
589
#endif
590
      }
591
      return 4;
592
    }
593
    if (masm) {
594
      __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
595
#ifndef PRODUCT
596
    } else if (!do_size) {
597
      st->print(MOV_FLOAT "    R_%s, R_%s\t# spill",
598
                Matcher::regName[dst_first],
599
                Matcher::regName[src_first]);
600
#endif
601
    }
602
    size = 4;
603
  }
604

605
  // Check for float store
606
  if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
607
    int offset = ra_->reg2offset(dst_first);
608
    if (masm && !is_memoryfp(offset)) {
609
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
610
      return 0;
611
    } else {
612
      // Further check for aligned-adjacent pair, so we can use a double store
613
      if (src_second_rc != rc_bad) {
614
        assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers and stack slots must be aligned/contiguous");
615
        if (masm) {
616
          __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
617
#ifndef PRODUCT
618
        } else if (!do_size) {
619
          if (size != 0) st->print("\n\t");
620
          st->print(STR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
621
#endif
622
        }
623
        return size + 4;
624
      } else {
625
        if (masm) {
626
          __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
627
#ifndef PRODUCT
628
        } else if (!do_size) {
629
          if (size != 0) st->print("\n\t");
630
          st->print(STR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
631
#endif
632
        }
633
      }
634
    }
635
    size += 4;
636
  }
637

638
  // Check for float load
639
  if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
640
    int offset = ra_->reg2offset(src_first);
641
    if (masm && !is_memoryfp(offset)) {
642
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
643
      return 0;
644
    } else {
645
      // Further check for aligned-adjacent pair, so we can use a double store
646
      if (src_second_rc != rc_bad) {
647
        assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers and stack slots must be aligned/contiguous");
648
        if (masm) {
649
          __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
650
#ifndef PRODUCT
651
        } else if (!do_size) {
652
          if (size != 0) st->print("\n\t");
653
          st->print(LDR_DOUBLE "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
654
#endif
655
        }
656
        return size + 4;
657
      } else {
658
        if (masm) {
659
          __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
660
#ifndef PRODUCT
661
        } else if (!do_size) {
662
          if (size != 0) st->print("\n\t");
663
          st->print(LDR_FLOAT "   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
664
#endif
665
        }
666
      }
667
    }
668
    size += 4;
669
  }
670

671
  // check for int reg -> float reg move
672
  if (src_first_rc == rc_int && dst_first_rc == rc_float) {
673
    // Further check for aligned-adjacent pair, so we can use a single instruction
674
    if (src_second_rc != rc_bad) {
675
      assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
676
      assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
677
      assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported");
678
      if (masm) {
679
        __ fmdrr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]), reg_to_register_object(Matcher::_regEncode[src_second]));
680
#ifndef PRODUCT
681
      } else if (!do_size) {
682
        if (size != 0) st->print("\n\t");
683
        st->print("FMDRR   R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second));
684
#endif
685
      }
686
      return size + 4;
687
    } else {
688
      if (masm) {
689
        __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
690
#ifndef PRODUCT
691
      } else if (!do_size) {
692
        if (size != 0) st->print("\n\t");
693
        st->print(FMSR "   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
694
#endif
695
      }
696
      size += 4;
697
    }
698
  }
699

700
  // check for float reg -> int reg move
701
  if (src_first_rc == rc_float && dst_first_rc == rc_int) {
702
    // Further check for aligned-adjacent pair, so we can use a single instruction
703
    if (src_second_rc != rc_bad) {
704
      assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
705
      assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
706
      assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported");
707
      if (masm) {
708
        __ fmrrd(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
709
#ifndef PRODUCT
710
      } else if (!do_size) {
711
        if (size != 0) st->print("\n\t");
712
        st->print("FMRRD   R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first));
713
#endif
714
      }
715
      return size + 4;
716
    } else {
717
      if (masm) {
718
        __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
719
#ifndef PRODUCT
720
      } else if (!do_size) {
721
        if (size != 0) st->print("\n\t");
722
        st->print(FMRS "   R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
723
#endif
724
      }
725
      size += 4;
726
    }
727
  }
728

729
  // --------------------------------------------------------------------
730
  // Check for hi bits still needing moving.  Only happens for misaligned
731
  // arguments to native calls.
732
  if (src_second == dst_second)
733
    return size;               // Self copy; no move
734
  assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
735

736
  // Check for integer reg-reg copy.  Hi bits are stuck up in the top
737
  // 32-bits of a 64-bit register, but are needed in low bits of another
738
  // register (else it's a hi-bits-to-hi-bits copy which should have
739
  // happened already as part of a 64-bit move)
740
  if (src_second_rc == rc_int && dst_second_rc == rc_int) {
741
    if (masm) {
742
      __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second]));
743
#ifndef PRODUCT
744
    } else if (!do_size) {
745
      if (size != 0) st->print("\n\t");
746
      st->print("MOV    R_%s, R_%s\t# spill high",
747
                Matcher::regName[dst_second],
748
                Matcher::regName[src_second]);
749
#endif
750
    }
751
    return size+4;
752
  }
753

754
  // Check for high word integer store
755
  if (src_second_rc == rc_int && dst_second_rc == rc_stack) {
756
    int offset = ra_->reg2offset(dst_second);
757

758
    if (masm && !is_memoryP(offset)) {
759
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
760
      return 0;
761
    } else {
762
      if (masm) {
763
        __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset));
764
#ifndef PRODUCT
765
      } else if (!do_size) {
766
        if (size != 0) st->print("\n\t");
767
        st->print("STR   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset);
768
#endif
769
      }
770
    }
771
    return size + 4;
772
  }
773

774
  // Check for high word integer load
775
  if (dst_second_rc == rc_int && src_second_rc == rc_stack) {
776
    int offset = ra_->reg2offset(src_second);
777
    if (masm && !is_memoryP(offset)) {
778
      ra_->C->record_method_not_compilable("unable to handle large constant offsets");
779
      return 0;
780
    } else {
781
      if (masm) {
782
        __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset));
783
#ifndef PRODUCT
784
      } else if (!do_size) {
785
        if (size != 0) st->print("\n\t");
786
        st->print("LDR   R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset);
787
#endif
788
      }
789
    }
790
    return size + 4;
791
  }
792

793
  Unimplemented();
794
  return 0; // Mute compiler
795
}
796

797
#ifndef PRODUCT
798
void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
799
  implementation( nullptr, ra_, false, st );
800
}
801
#endif
802

803
void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
804
  implementation( masm, ra_, false, nullptr );
805
}
806

807
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
808
  return implementation( nullptr, ra_, true, nullptr );
809
}
810

811
//=============================================================================
812
#ifndef PRODUCT
813
void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
814
  st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
815
}
816
#endif
817

818
void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc * ) const {
819
  for(int i = 0; i < _count; i += 1) {
820
    __ nop();
821
  }
822
}
823

824
uint MachNopNode::size(PhaseRegAlloc *ra_) const {
825
  return 4 * _count;
826
}
827

828

829
//=============================================================================
830
#ifndef PRODUCT
831
void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
832
  int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
833
  int reg = ra_->get_reg_first(this);
834
  st->print("ADD    %s,R_SP+#%d",Matcher::regName[reg], offset);
835
}
836
#endif
837

838
void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
839
  int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
840
  int reg = ra_->get_encode(this);
841
  Register dst = reg_to_register_object(reg);
842

843
  if (is_aimm(offset)) {
844
    __ add(dst, SP, offset);
845
  } else {
846
    __ mov_slow(dst, offset);
847
    __ add(dst, SP, dst);
848
  }
849
}
850

851
uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
852
  // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
853
  assert(ra_ == ra_->C->regalloc(), "sanity");
854
  return ra_->C->output()->scratch_emit_size(this);
855
}
856

857
//=============================================================================
858
#ifndef PRODUCT
859
#define R_RTEMP "R_R12"
860
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
861
  st->print_cr("\nUEP:");
862
  st->print_cr("\tLDR   " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
863
  st->print_cr("\tCMP   " R_RTEMP ",R_R8" );
864
  st->print   ("\tB.NE  SharedRuntime::handle_ic_miss_stub");
865
}
866
#endif
867

868
void MachUEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
869
  __ ic_check(InteriorEntryAlignment);
870
}
871

872
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
873
  return MachNode::size(ra_);
874
}
875

876

877
//=============================================================================
878

879
// Emit exception handler code.
880
int HandlerImpl::emit_exception_handler(C2_MacroAssembler* masm) {
881
  address base = __ start_a_stub(size_exception_handler());
882
  if (base == nullptr) {
883
    ciEnv::current()->record_failure("CodeCache is full");
884
    return 0;  // CodeBuffer::expand failed
885
  }
886

887
  int offset = __ offset();
888

889
  // OK to trash LR, because exception blob will kill it
890
  __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp);
891

892
  assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
893

894
  __ end_a_stub();
895

896
  return offset;
897
}
898

899
int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) {
900
  // Can't use any of the current frame's registers as we may have deopted
901
  // at a poll and everything can be live.
902
  address base = __ start_a_stub(size_deopt_handler());
903
  if (base == nullptr) {
904
    ciEnv::current()->record_failure("CodeCache is full");
905
    return 0;  // CodeBuffer::expand failed
906
  }
907

908
  int offset = __ offset();
909
  address deopt_pc = __ pc();
910

911
  __ sub(SP, SP, wordSize); // make room for saved PC
912
  __ push(LR); // save LR that may be live when we get here
913
  __ mov_relative_address(LR, deopt_pc);
914
  __ str(LR, Address(SP, wordSize)); // save deopt PC
915
  __ pop(LR); // restore LR
916
  __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);
917

918
  assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
919

920
  __ end_a_stub();
921
  return offset;
922
}
923

924
bool Matcher::match_rule_supported(int opcode) {
925
  if (!has_match_rule(opcode))
926
    return false;
927

928
  switch (opcode) {
929
  case Op_PopCountI:
930
  case Op_PopCountL:
931
    if (!UsePopCountInstruction)
932
      return false;
933
    break;
934
  case Op_LShiftCntV:
935
  case Op_RShiftCntV:
936
  case Op_AddVB:
937
  case Op_AddVS:
938
  case Op_AddVI:
939
  case Op_AddVL:
940
  case Op_SubVB:
941
  case Op_SubVS:
942
  case Op_SubVI:
943
  case Op_SubVL:
944
  case Op_MulVS:
945
  case Op_MulVI:
946
  case Op_LShiftVB:
947
  case Op_LShiftVS:
948
  case Op_LShiftVI:
949
  case Op_LShiftVL:
950
  case Op_RShiftVB:
951
  case Op_RShiftVS:
952
  case Op_RShiftVI:
953
  case Op_RShiftVL:
954
  case Op_URShiftVB:
955
  case Op_URShiftVS:
956
  case Op_URShiftVI:
957
  case Op_URShiftVL:
958
  case Op_AndV:
959
  case Op_OrV:
960
  case Op_XorV:
961
    return VM_Version::has_simd();
962
  case Op_LoadVector:
963
  case Op_StoreVector:
964
  case Op_AddVF:
965
  case Op_SubVF:
966
  case Op_MulVF:
967
    return VM_Version::has_vfp() || VM_Version::has_simd();
968
  case Op_AddVD:
969
  case Op_SubVD:
970
  case Op_MulVD:
971
  case Op_DivVF:
972
  case Op_DivVD:
973
    return VM_Version::has_vfp();
974
  }
975

976
  return true;  // Per default match rules are supported.
977
}
978

979
bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
980
  return match_rule_supported_vector(opcode, vlen, bt);
981
}
982

983
bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
984

985
  // TODO
986
  // identify extra cases that we might want to provide match rules for
987
  // e.g. Op_ vector nodes and other intrinsics while guarding with vlen
988
  bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen);
989
  // Add rules here.
990

991
  return ret_value;  // Per default match rules are supported.
992
}
993

994
bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) {
995
  return false;
996
}
997

998
bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
999
  return false;
1000
}
1001

1002
const RegMask* Matcher::predicate_reg_mask(void) {
1003
  return nullptr;
1004
}
1005

1006
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
1007
  return nullptr;
1008
}
1009

1010
// Vector calling convention not yet implemented.
1011
bool Matcher::supports_vector_calling_convention(void) {
1012
  return false;
1013
}
1014

1015
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1016
  Unimplemented();
1017
  return OptoRegPair(0, 0);
1018
}
1019

1020
// Vector width in bytes
1021
int Matcher::vector_width_in_bytes(BasicType bt) {
1022
  return MaxVectorSize;
1023
}
1024

1025
int Matcher::scalable_vector_reg_size(const BasicType bt) {
1026
  return -1;
1027
}
1028

1029
// Vector ideal reg corresponding to specified size in bytes
1030
uint Matcher::vector_ideal_reg(int size) {
1031
  assert(MaxVectorSize >= size, "");
1032
  switch(size) {
1033
    case  8: return Op_VecD;
1034
    case 16: return Op_VecX;
1035
  }
1036
  ShouldNotReachHere();
1037
  return 0;
1038
}
1039

1040
// Limits on vector size (number of elements) loaded into vector.
1041
int Matcher::max_vector_size(const BasicType bt) {
1042
  assert(is_java_primitive(bt), "only primitive type vectors");
1043
  return vector_width_in_bytes(bt)/type2aelembytes(bt);
1044
}
1045

1046
int Matcher::min_vector_size(const BasicType bt) {
1047
  assert(is_java_primitive(bt), "only primitive type vectors");
1048
  return 8/type2aelembytes(bt);
1049
}
1050

1051
int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
1052
  return Matcher::max_vector_size(bt);
1053
}
1054

1055
// Is this branch offset short enough that a short branch can be used?
1056
//
1057
// NOTE: If the platform does not provide any short branch variants, then
1058
//       this method should return false for offset 0.
1059
bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1060
  // The passed offset is relative to address of the branch.
1061
  // On ARM a branch displacement is calculated relative to address
1062
  // of the branch + 8.
1063
  //
1064
  // offset -= 8;
1065
  // return (Assembler::is_simm24(offset));
1066
  return false;
1067
}
1068

1069
MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
1070
  ShouldNotReachHere(); // generic vector operands not supported
1071
  return nullptr;
1072
}
1073

1074
bool Matcher::is_reg2reg_move(MachNode* m) {
1075
  ShouldNotReachHere();  // generic vector operands not supported
1076
  return false;
1077
}
1078

1079
bool Matcher::is_generic_vector(MachOper* opnd)  {
1080
  ShouldNotReachHere();  // generic vector operands not supported
1081
  return false;
1082
}
1083

1084
// Should the matcher clone input 'm' of node 'n'?
1085
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
1086
  if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
1087
    mstack.push(m, Visit);           // m = ShiftCntV
1088
    return true;
1089
  }
1090
  return false;
1091
}
1092

1093
// Should the Matcher clone shifts on addressing modes, expecting them
1094
// to be subsumed into complex addressing expressions or compute them
1095
// into registers?
1096
bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
1097
  return clone_base_plus_offset_address(m, mstack, address_visited);
1098
}
1099

1100
// Return whether or not this register is ever used as an argument.  This
1101
// function is used on startup to build the trampoline stubs in generateOptoStub.
1102
// Registers not mentioned will be killed by the VM call in the trampoline, and
1103
// arguments in those registers not be available to the callee.
1104
bool Matcher::can_be_java_arg( int reg ) {
1105
  if (reg == R_R0_num ||
1106
      reg == R_R1_num ||
1107
      reg == R_R2_num ||
1108
      reg == R_R3_num) return true;
1109

1110
  if (reg >= R_S0_num &&
1111
      reg <= R_S13_num) return true;
1112
  return false;
1113
}
1114

1115
bool Matcher::is_spillable_arg( int reg ) {
1116
  return can_be_java_arg(reg);
1117
}
1118

1119
uint Matcher::int_pressure_limit()
1120
{
1121
  return (INTPRESSURE == -1) ? 12 : INTPRESSURE;
1122
}
1123

1124
uint Matcher::float_pressure_limit()
1125
{
1126
  return (FLOATPRESSURE == -1) ? 30 : FLOATPRESSURE;
1127
}
1128

1129
bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
1130
  return false;
1131
}
1132

1133
// Register for DIVI projection of divmodI
1134
RegMask Matcher::divI_proj_mask() {
1135
  ShouldNotReachHere();
1136
  return RegMask();
1137
}
1138

1139
// Register for MODI projection of divmodI
1140
RegMask Matcher::modI_proj_mask() {
1141
  ShouldNotReachHere();
1142
  return RegMask();
1143
}
1144

1145
// Register for DIVL projection of divmodL
1146
RegMask Matcher::divL_proj_mask() {
1147
  ShouldNotReachHere();
1148
  return RegMask();
1149
}
1150

1151
// Register for MODL projection of divmodL
1152
RegMask Matcher::modL_proj_mask() {
1153
  ShouldNotReachHere();
1154
  return RegMask();
1155
}
1156

1157
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
1158
  return FP_REGP_mask();
1159
}
1160

1161
bool maybe_far_call(const CallNode *n) {
1162
  return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
1163
}
1164

1165
bool maybe_far_call(const MachCallNode *n) {
1166
  return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
1167
}
1168

1169
%}
1170

1171
//----------ENCODING BLOCK-----------------------------------------------------
1172
// This block specifies the encoding classes used by the compiler to output
1173
// byte streams.  Encoding classes are parameterized macros used by
1174
// Machine Instruction Nodes in order to generate the bit encoding of the
1175
// instruction.  Operands specify their base encoding interface with the
1176
// interface keyword.  There are currently supported four interfaces,
1177
// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER.  REG_INTER causes an
1178
// operand to generate a function which returns its register number when
1179
// queried.   CONST_INTER causes an operand to generate a function which
1180
// returns the value of the constant when queried.  MEMORY_INTER causes an
1181
// operand to generate four functions which return the Base Register, the
1182
// Index Register, the Scale Value, and the Offset Value of the operand when
1183
// queried.  COND_INTER causes an operand to generate six functions which
1184
// return the encoding code (ie - encoding bits for the instruction)
1185
// associated with each basic boolean condition for a conditional instruction.
1186
//
1187
// Instructions specify two basic values for encoding.  Again, a function
1188
// is available to check if the constant displacement is an oop. They use the
1189
// ins_encode keyword to specify their encoding classes (which must be
1190
// a sequence of enc_class names, and their parameters, specified in
1191
// the encoding block), and they use the
1192
// opcode keyword to specify, in order, their primary, secondary, and
1193
// tertiary opcode.  Only the opcode sections which a particular instruction
1194
// needs for encoding need to be specified.
1195
encode %{
1196
  // Set instruction mark in MacroAssembler. This is used only in
1197
  // instructions that emit bytes directly to the CodeBuffer wraped
1198
  // in the MacroAssembler. Should go away once all "instruct" are
1199
  // patched to emit bytes only using methods in MacroAssembler.
1200
  enc_class SetInstMark %{
1201
    __ set_inst_mark();
1202
  %}
1203

1204
  enc_class ClearInstMark %{
1205
    __ clear_inst_mark();
1206
  %}
1207

1208
  enc_class call_epilog %{
1209
    // nothing
1210
  %}
1211

1212
  enc_class Java_To_Runtime (method meth) %{
1213
    // CALL directly to the runtime
1214
    emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1215
  %}
1216

1217
  enc_class Java_Static_Call (method meth) %{
1218
    // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
1219
    // who we intended to call.
1220

1221
    if ( !_method) {
1222
      emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1223
    } else {
1224
      int method_index = resolved_method_index(masm);
1225
      RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1226
                                                  : static_call_Relocation::spec(method_index);
1227
      emit_call_reloc(masm, as_MachCall(), $meth, rspec);
1228

1229
      // Emit stubs for static call.
1230
      address stub = CompiledDirectCall::emit_to_interp_stub(masm);
1231
      if (stub == nullptr) {
1232
        ciEnv::current()->record_failure("CodeCache is full");
1233
        return;
1234
      }
1235
    }
1236
  %}
1237

1238
  enc_class save_last_PC %{
1239
    // preserve mark
1240
    address mark = __ inst_mark();
1241
    debug_only(int off0 = __ offset());
1242
    int ret_addr_offset = as_MachCall()->ret_addr_offset();
1243
    __ adr(LR, mark + ret_addr_offset);
1244
    __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
1245
    debug_only(int off1 = __ offset());
1246
    assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
1247
    // restore mark
1248
    __ set_inst_mark(mark);
1249
  %}
1250

1251
  enc_class preserve_SP %{
1252
    // preserve mark
1253
    address mark = __ inst_mark();
1254
    debug_only(int off0 = __ offset());
1255
    // FP is preserved across all calls, even compiled calls.
1256
    // Use it to preserve SP in places where the callee might change the SP.
1257
    __ mov(Rmh_SP_save, SP);
1258
    debug_only(int off1 = __ offset());
1259
    assert(off1 - off0 == 4, "correct size prediction");
1260
    // restore mark
1261
    __ set_inst_mark(mark);
1262
  %}
1263

1264
  enc_class restore_SP %{
1265
    __ mov(SP, Rmh_SP_save);
1266
  %}
1267

1268
  enc_class Java_Dynamic_Call (method meth) %{
1269
    Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
1270
    assert(R8_ic_reg == Ricklass, "should be");
1271
    __ set_inst_mark();
1272
    __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff);
1273
    __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16);
1274
    address  virtual_call_oop_addr = __ inst_mark();
1275
    // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
1276
    // who we intended to call.
1277
    int method_index = resolved_method_index(masm);
1278
    __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
1279
    emit_call_reloc(masm, as_MachCall(), $meth, RelocationHolder::none);
1280
  %}
1281

1282
  enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{
1283
    // FIXME: load from constant table?
1284
    // Load a constant replicated "count" times with width "width"
1285
    int count = $cnt$$constant;
1286
    int width = $wth$$constant;
1287
    assert(count*width == 4, "sanity");
1288
    int val = $src$$constant;
1289
    if (width < 4) {
1290
      int bit_width = width * 8;
1291
      val &= (((int)1) << bit_width) - 1; // mask off sign bits
1292
      for (int i = 0; i < count - 1; i++) {
1293
        val |= (val << bit_width);
1294
      }
1295
    }
1296

1297
    if (val == -1) {
1298
      __ mvn($tmp$$Register, 0);
1299
    } else if (val == 0) {
1300
      __ mov($tmp$$Register, 0);
1301
    } else {
1302
      __ movw($tmp$$Register, val & 0xffff);
1303
      __ movt($tmp$$Register, (unsigned int)val >> 16);
1304
    }
1305
    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1306
  %}
1307

1308
  enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{
1309
    // Replicate float con 2 times and pack into vector (8 bytes) in regD.
1310
    float fval = $src$$constant;
1311
    int val = *((int*)&fval);
1312

1313
    if (val == -1) {
1314
      __ mvn($tmp$$Register, 0);
1315
    } else if (val == 0) {
1316
      __ mov($tmp$$Register, 0);
1317
    } else {
1318
      __ movw($tmp$$Register, val & 0xffff);
1319
      __ movt($tmp$$Register, (unsigned int)val >> 16);
1320
    }
1321
    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1322
  %}
1323

1324
  enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
1325
    Label Ldone, Lloop;
1326

1327
    Register   str1_reg = $str1$$Register;
1328
    Register   str2_reg = $str2$$Register;
1329
    Register   cnt1_reg = $cnt1$$Register; // int
1330
    Register   cnt2_reg = $cnt2$$Register; // int
1331
    Register   tmp1_reg = $tmp1$$Register;
1332
    Register   tmp2_reg = $tmp2$$Register;
1333
    Register result_reg = $result$$Register;
1334

1335
    assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg);
1336

1337
    // Compute the minimum of the string lengths(str1_reg) and the
1338
    // difference of the string lengths (stack)
1339

1340
    // See if the lengths are different, and calculate min in str1_reg.
1341
    // Stash diff in tmp2 in case we need it for a tie-breaker.
1342
    __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg);
1343
    __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit
1344
    __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit
1345

1346
    // reallocate cnt1_reg, cnt2_reg, result_reg
1347
    // Note:  limit_reg holds the string length pre-scaled by 2
1348
    Register limit_reg = cnt1_reg;
1349
    Register  chr2_reg = cnt2_reg;
1350
    Register  chr1_reg = tmp1_reg;
1351
    // str{12} are the base pointers
1352

1353
    // Is the minimum length zero?
1354
    __ cmp_32(limit_reg, 0);
1355
    if (result_reg != tmp2_reg) {
1356
      __ mov(result_reg, tmp2_reg, eq);
1357
    }
1358
    __ b(Ldone, eq);
1359

1360
    // Load first characters
1361
    __ ldrh(chr1_reg, Address(str1_reg, 0));
1362
    __ ldrh(chr2_reg, Address(str2_reg, 0));
1363

1364
    // Compare first characters
1365
    __ subs(chr1_reg, chr1_reg, chr2_reg);
1366
    if (result_reg != chr1_reg) {
1367
      __ mov(result_reg, chr1_reg, ne);
1368
    }
1369
    __ b(Ldone, ne);
1370

1371
    {
1372
      // Check after comparing first character to see if strings are equivalent
1373
      // Check if the strings start at same location
1374
      __ cmp(str1_reg, str2_reg);
1375
      // Check if the length difference is zero
1376
      __ cond_cmp(tmp2_reg, 0, eq);
1377
      __ mov(result_reg, 0, eq); // result is zero
1378
      __ b(Ldone, eq);
1379
      // Strings might not be equal
1380
    }
1381

1382
    __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar));
1383
    if (result_reg != tmp2_reg) {
1384
      __ mov(result_reg, tmp2_reg, eq);
1385
    }
1386
    __ b(Ldone, eq);
1387

1388
    // Shift str1_reg and str2_reg to the end of the arrays, negate limit
1389
    __ add(str1_reg, str1_reg, limit_reg);
1390
    __ add(str2_reg, str2_reg, limit_reg);
1391
    __ neg(limit_reg, chr1_reg);  // limit = -(limit-2)
1392

1393
    // Compare the rest of the characters
1394
    __ bind(Lloop);
1395
    __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1396
    __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1397
    __ subs(chr1_reg, chr1_reg, chr2_reg);
1398
    if (result_reg != chr1_reg) {
1399
      __ mov(result_reg, chr1_reg, ne);
1400
    }
1401
    __ b(Ldone, ne);
1402

1403
    __ adds(limit_reg, limit_reg, sizeof(jchar));
1404
    __ b(Lloop, ne);
1405

1406
    // If strings are equal up to min length, return the length difference.
1407
    if (result_reg != tmp2_reg) {
1408
      __ mov(result_reg, tmp2_reg);
1409
    }
1410

1411
    // Otherwise, return the difference between the first mismatched chars.
1412
    __ bind(Ldone);
1413
  %}
1414

1415
  enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
1416
    Label Lchar, Lchar_loop, Ldone, Lequal;
1417

1418
    Register   str1_reg = $str1$$Register;
1419
    Register   str2_reg = $str2$$Register;
1420
    Register    cnt_reg = $cnt$$Register; // int
1421
    Register   tmp1_reg = $tmp1$$Register;
1422
    Register   tmp2_reg = $tmp2$$Register;
1423
    Register result_reg = $result$$Register;
1424

1425
    assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg);
1426

1427
    __ cmp(str1_reg, str2_reg); //same char[] ?
1428
    __ b(Lequal, eq);
1429

1430
    __ cbz_32(cnt_reg, Lequal); // count == 0
1431

1432
    //rename registers
1433
    Register limit_reg = cnt_reg;
1434
    Register  chr1_reg = tmp1_reg;
1435
    Register  chr2_reg = tmp2_reg;
1436

1437
    __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1438

1439
    //check for alignment and position the pointers to the ends
1440
    __ orr(chr1_reg, str1_reg, str2_reg);
1441
    __ tst(chr1_reg, 0x3);
1442

1443
    // notZero means at least one not 4-byte aligned.
1444
    // We could optimize the case when both arrays are not aligned
1445
    // but it is not frequent case and it requires additional checks.
1446
    __ b(Lchar, ne);
1447

1448
    // Compare char[] arrays aligned to 4 bytes.
1449
    __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
1450
                          chr1_reg, chr2_reg, Ldone);
1451

1452
    __ b(Lequal); // equal
1453

1454
    // char by char compare
1455
    __ bind(Lchar);
1456
    __ mov(result_reg, 0);
1457
    __ add(str1_reg, limit_reg, str1_reg);
1458
    __ add(str2_reg, limit_reg, str2_reg);
1459
    __ neg(limit_reg, limit_reg); //negate count
1460

1461
    // Lchar_loop
1462
    __ bind(Lchar_loop);
1463
    __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1464
    __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1465
    __ cmp(chr1_reg, chr2_reg);
1466
    __ b(Ldone, ne);
1467
    __ adds(limit_reg, limit_reg, sizeof(jchar));
1468
    __ b(Lchar_loop, ne);
1469

1470
    __ bind(Lequal);
1471
    __ mov(result_reg, 1);  //equal
1472

1473
    __ bind(Ldone);
1474
  %}
1475

1476
  enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
1477
    Label Ldone, Lloop, Lequal;
1478

1479
    Register   ary1_reg = $ary1$$Register;
1480
    Register   ary2_reg = $ary2$$Register;
1481
    Register   tmp1_reg = $tmp1$$Register;
1482
    Register   tmp2_reg = $tmp2$$Register;
1483
    Register   tmp3_reg = $tmp3$$Register;
1484
    Register result_reg = $result$$Register;
1485

1486
    assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg);
1487

1488
    int length_offset  = arrayOopDesc::length_offset_in_bytes();
1489
    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
1490

1491
    // return true if the same array
1492
    __ teq(ary1_reg, ary2_reg);
1493
    __ mov(result_reg, 1, eq);
1494
    __ b(Ldone, eq); // equal
1495

1496
    __ tst(ary1_reg, ary1_reg);
1497
    __ mov(result_reg, 0, eq);
1498
    __ b(Ldone, eq);    // not equal
1499

1500
    __ tst(ary2_reg, ary2_reg);
1501
    __ mov(result_reg, 0, eq);
1502
    __ b(Ldone, eq);    // not equal
1503

1504
    //load the lengths of arrays
1505
    __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int
1506
    __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int
1507

1508
    // return false if the two arrays are not equal length
1509
    __ teq_32(tmp1_reg, tmp2_reg);
1510
    __ mov(result_reg, 0, ne);
1511
    __ b(Ldone, ne);    // not equal
1512

1513
    __ tst(tmp1_reg, tmp1_reg);
1514
    __ mov(result_reg, 1, eq);
1515
    __ b(Ldone, eq);    // zero-length arrays are equal
1516

1517
    // load array addresses
1518
    __ add(ary1_reg, ary1_reg, base_offset);
1519
    __ add(ary2_reg, ary2_reg, base_offset);
1520

1521
    // renaming registers
1522
    Register chr1_reg  =  tmp3_reg;   // for characters in ary1
1523
    Register chr2_reg  =  tmp2_reg;   // for characters in ary2
1524
    Register limit_reg =  tmp1_reg;   // length
1525

1526
    // set byte count
1527
    __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1528

1529
    // Compare char[] arrays aligned to 4 bytes.
1530
    __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
1531
                          chr1_reg, chr2_reg, Ldone);
1532
    __ bind(Lequal);
1533
    __ mov(result_reg, 1);  //equal
1534

1535
    __ bind(Ldone);
1536
    %}
1537
%}
1538

1539
//----------FRAME--------------------------------------------------------------
1540
// Definition of frame structure and management information.
1541
//
1542
//  S T A C K   L A Y O U T    Allocators stack-slot number
1543
//                             |   (to get allocators register number
1544
//  G  Owned by    |        |  v    add VMRegImpl::stack0)
1545
//  r   CALLER     |        |
1546
//  o     |        +--------+      pad to even-align allocators stack-slot
1547
//  w     V        |  pad0  |        numbers; owned by CALLER
1548
//  t   -----------+--------+----> Matcher::_in_arg_limit, unaligned
1549
//  h     ^        |   in   |  5
1550
//        |        |  args  |  4   Holes in incoming args owned by SELF
1551
//  |     |        |        |  3
1552
//  |     |        +--------+
1553
//  V     |        | old out|      Empty on Intel, window on Sparc
1554
//        |    old |preserve|      Must be even aligned.
1555
//        |     SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned
1556
//        |        |   in   |  3   area for Intel ret address
1557
//     Owned by    |preserve|      Empty on Sparc.
1558
//       SELF      +--------+
1559
//        |        |  pad2  |  2   pad to align old SP
1560
//        |        +--------+  1
1561
//        |        | locks  |  0
1562
//        |        +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned
1563
//        |        |  pad1  | 11   pad to align new SP
1564
//        |        +--------+
1565
//        |        |        | 10
1566
//        |        | spills |  9   spills
1567
//        V        |        |  8   (pad0 slot for callee)
1568
//      -----------+--------+----> Matcher::_out_arg_limit, unaligned
1569
//        ^        |  out   |  7
1570
//        |        |  args  |  6   Holes in outgoing args owned by CALLEE
1571
//     Owned by    +--------+
1572
//      CALLEE     | new out|  6   Empty on Intel, window on Sparc
1573
//        |    new |preserve|      Must be even-aligned.
1574
//        |     SP-+--------+----> Matcher::_new_SP, even aligned
1575
//        |        |        |
1576
//
1577
// Note 1: Only region 8-11 is determined by the allocator.  Region 0-5 is
1578
//         known from SELF's arguments and the Java calling convention.
1579
//         Region 6-7 is determined per call site.
1580
// Note 2: If the calling convention leaves holes in the incoming argument
1581
//         area, those holes are owned by SELF.  Holes in the outgoing area
1582
//         are owned by the CALLEE.  Holes should not be necessary in the
1583
//         incoming area, as the Java calling convention is completely under
1584
//         the control of the AD file.  Doubles can be sorted and packed to
1585
//         avoid holes.  Holes in the outgoing arguments may be necessary for
1586
//         varargs C calling conventions.
1587
// Note 3: Region 0-3 is even aligned, with pad2 as needed.  Region 3-5 is
1588
//         even aligned with pad0 as needed.
1589
//         Region 6 is even aligned.  Region 6-7 is NOT even aligned;
1590
//         region 6-11 is even aligned; it may be padded out more so that
1591
//         the region from SP to FP meets the minimum stack alignment.
1592

1593
frame %{
1594
  // These two registers define part of the calling convention
1595
  // between compiled code and the interpreter.
1596
  inline_cache_reg(R_Ricklass);          // Inline Cache Register or Method* for I2C
1597

1598
  // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
1599
  cisc_spilling_operand_name(indOffset);
1600

1601
  // Number of stack slots consumed by a Monitor enter
1602
  sync_stack_slots(1 * VMRegImpl::slots_per_word);
1603

1604
  // Compiled code's Frame Pointer
1605
  frame_pointer(R_R13);
1606

1607
  // Stack alignment requirement
1608
  stack_alignment(StackAlignmentInBytes);
1609
  //  LP64: Alignment size in bytes (128-bit -> 16 bytes)
1610
  // !LP64: Alignment size in bytes (64-bit  ->  8 bytes)
1611

1612
  // Number of outgoing stack slots killed above the out_preserve_stack_slots
1613
  // for calls to C.  Supports the var-args backing area for register parms.
1614
  // ADLC doesn't support parsing expressions, so I folded the math by hand.
1615
  varargs_C_out_slots_killed( 0);
1616

1617
  // The after-PROLOG location of the return address.  Location of
1618
  // return address specifies a type (REG or STACK) and a number
1619
  // representing the register number (i.e. - use a register name) or
1620
  // stack slot.
1621
  // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1622
  // Otherwise, it is above the locks and verification slot and alignment word
1623
  return_addr(STACK - 1*VMRegImpl::slots_per_word +
1624
              align_up((Compile::current()->in_preserve_stack_slots() +
1625
                        Compile::current()->fixed_slots()),
1626
                       stack_alignment_in_slots()));
1627

1628
  // Location of compiled Java return values.  Same as C
1629
  return_value %{
1630
    return c2::return_value(ideal_reg);
1631
  %}
1632

1633
%}
1634

1635
//----------ATTRIBUTES---------------------------------------------------------
1636
//----------Instruction Attributes---------------------------------------------
1637
ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
1638
ins_attrib ins_size(32);           // Required size attribute (in bits)
1639
ins_attrib ins_short_branch(0);    // Required flag: is this instruction a
1640
                                   // non-matching short branch variant of some
1641
                                                            // long branch?
1642

1643
//----------OPERANDS-----------------------------------------------------------
1644
// Operand definitions must precede instruction definitions for correct parsing
1645
// in the ADLC because operands constitute user defined types which are used in
1646
// instruction definitions.
1647

1648
//----------Simple Operands----------------------------------------------------
1649
// Immediate Operands
1650
// Integer Immediate: 32-bit
1651
operand immI() %{
1652
  match(ConI);
1653

1654
  op_cost(0);
1655
  // formats are generated automatically for constants and base registers
1656
  format %{ %}
1657
  interface(CONST_INTER);
1658
%}
1659

1660
// Integer Immediate: 8-bit unsigned - for VMOV
1661
operand immU8() %{
1662
  predicate(0 <= n->get_int() && (n->get_int() <= 255));
1663
  match(ConI);
1664
  op_cost(0);
1665

1666
  format %{ %}
1667
  interface(CONST_INTER);
1668
%}
1669

1670
// Integer Immediate: 16-bit
1671
operand immI16() %{
1672
  predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw());
1673
  match(ConI);
1674
  op_cost(0);
1675

1676
  format %{ %}
1677
  interface(CONST_INTER);
1678
%}
1679

1680
// Integer Immediate: offset for half and double word loads and stores
1681
operand immIHD() %{
1682
  predicate(is_memoryHD(n->get_int()));
1683
  match(ConI);
1684
  op_cost(0);
1685
  format %{ %}
1686
  interface(CONST_INTER);
1687
%}
1688

1689
// Integer Immediate: offset for fp loads and stores
1690
operand immIFP() %{
1691
  predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0));
1692
  match(ConI);
1693
  op_cost(0);
1694

1695
  format %{ %}
1696
  interface(CONST_INTER);
1697
%}
1698

1699
// Valid scale values for addressing modes and shifts
1700
operand immU5() %{
1701
  predicate(0 <= n->get_int() && (n->get_int() <= 31));
1702
  match(ConI);
1703
  op_cost(0);
1704

1705
  format %{ %}
1706
  interface(CONST_INTER);
1707
%}
1708

1709
// Integer Immediate: 6-bit
1710
operand immU6Big() %{
1711
  predicate(n->get_int() >= 32 && n->get_int() <= 63);
1712
  match(ConI);
1713
  op_cost(0);
1714
  format %{ %}
1715
  interface(CONST_INTER);
1716
%}
1717

1718
// Integer Immediate: 0-bit
1719
operand immI0() %{
1720
  predicate(n->get_int() == 0);
1721
  match(ConI);
1722
  op_cost(0);
1723

1724
  format %{ %}
1725
  interface(CONST_INTER);
1726
%}
1727

1728
// Int Immediate non-negative
1729
operand immU31()
1730
%{
1731
  predicate(n->get_int() >= 0);
1732
  match(ConI);
1733

1734
  op_cost(0);
1735
  format %{ %}
1736
  interface(CONST_INTER);
1737
%}
1738

1739
// Integer Immediate: the values 32-63
1740
operand immI_32_63() %{
1741
  predicate(n->get_int() >= 32 && n->get_int() <= 63);
1742
  match(ConI);
1743
  op_cost(0);
1744

1745
  format %{ %}
1746
  interface(CONST_INTER);
1747
%}
1748

1749
// Immediates for special shifts (sign extend)
1750

1751
// Integer Immediate: the value 16
1752
operand immI_16() %{
1753
  predicate(n->get_int() == 16);
1754
  match(ConI);
1755
  op_cost(0);
1756

1757
  format %{ %}
1758
  interface(CONST_INTER);
1759
%}
1760

1761
// Integer Immediate: the value 24
1762
operand immI_24() %{
1763
  predicate(n->get_int() == 24);
1764
  match(ConI);
1765
  op_cost(0);
1766

1767
  format %{ %}
1768
  interface(CONST_INTER);
1769
%}
1770

1771
// Integer Immediate: the value 255
1772
operand immI_255() %{
1773
  predicate( n->get_int() == 255 );
1774
  match(ConI);
1775
  op_cost(0);
1776

1777
  format %{ %}
1778
  interface(CONST_INTER);
1779
%}
1780

1781
// Integer Immediate: the value 65535
1782
operand immI_65535() %{
1783
  predicate(n->get_int() == 65535);
1784
  match(ConI);
1785
  op_cost(0);
1786

1787
  format %{ %}
1788
  interface(CONST_INTER);
1789
%}
1790

1791
// Integer Immediates for arithmetic instructions
1792

1793
operand aimmI() %{
1794
  predicate(is_aimm(n->get_int()));
1795
  match(ConI);
1796
  op_cost(0);
1797

1798
  format %{ %}
1799
  interface(CONST_INTER);
1800
%}
1801

1802
operand aimmIneg() %{
1803
  predicate(is_aimm(-n->get_int()));
1804
  match(ConI);
1805
  op_cost(0);
1806

1807
  format %{ %}
1808
  interface(CONST_INTER);
1809
%}
1810

1811
operand aimmU31() %{
1812
  predicate((0 <= n->get_int()) && is_aimm(n->get_int()));
1813
  match(ConI);
1814
  op_cost(0);
1815

1816
  format %{ %}
1817
  interface(CONST_INTER);
1818
%}
1819

1820
// Integer Immediates for logical instructions
1821

1822
operand limmI() %{
1823
  predicate(is_limmI(n->get_int()));
1824
  match(ConI);
1825
  op_cost(0);
1826

1827
  format %{ %}
1828
  interface(CONST_INTER);
1829
%}
1830

1831
operand limmIlow8() %{
1832
  predicate(is_limmI_low(n->get_int(), 8));
1833
  match(ConI);
1834
  op_cost(0);
1835

1836
  format %{ %}
1837
  interface(CONST_INTER);
1838
%}
1839

1840
operand limmU31() %{
1841
  predicate(0 <= n->get_int() && is_limmI(n->get_int()));
1842
  match(ConI);
1843
  op_cost(0);
1844

1845
  format %{ %}
1846
  interface(CONST_INTER);
1847
%}
1848

1849
operand limmIn() %{
1850
  predicate(is_limmI(~n->get_int()));
1851
  match(ConI);
1852
  op_cost(0);
1853

1854
  format %{ %}
1855
  interface(CONST_INTER);
1856
%}
1857

1858
// Pointer Immediate: 32 or 64-bit
1859
operand immP() %{
1860
  match(ConP);
1861

1862
  op_cost(5);
1863
  // formats are generated automatically for constants and base registers
1864
  format %{ %}
1865
  interface(CONST_INTER);
1866
%}
1867

1868
operand immP0() %{
1869
  predicate(n->get_ptr() == 0);
1870
  match(ConP);
1871
  op_cost(0);
1872

1873
  format %{ %}
1874
  interface(CONST_INTER);
1875
%}
1876

1877
operand immL() %{
1878
  match(ConL);
1879
  op_cost(40);
1880
  // formats are generated automatically for constants and base registers
1881
  format %{ %}
1882
  interface(CONST_INTER);
1883
%}
1884

1885
operand immL0() %{
1886
  predicate(n->get_long() == 0L);
1887
  match(ConL);
1888
  op_cost(0);
1889
  // formats are generated automatically for constants and base registers
1890
  format %{ %}
1891
  interface(CONST_INTER);
1892
%}
1893

1894
// Long Immediate: 16-bit
1895
operand immL16() %{
1896
  predicate(n->get_long() >= 0 && n->get_long() < (1<<16)  && VM_Version::supports_movw());
1897
  match(ConL);
1898
  op_cost(0);
1899

1900
  format %{ %}
1901
  interface(CONST_INTER);
1902
%}
1903

1904
// Long Immediate: low 32-bit mask
1905
operand immL_32bits() %{
1906
  predicate(n->get_long() == 0xFFFFFFFFL);
1907
  match(ConL);
1908
  op_cost(0);
1909

1910
  format %{ %}
1911
  interface(CONST_INTER);
1912
%}
1913

1914
// Double Immediate
1915
operand immD() %{
1916
  match(ConD);
1917

1918
  op_cost(40);
1919
  format %{ %}
1920
  interface(CONST_INTER);
1921
%}
1922

1923
// Double Immediate: +0.0d.
1924
operand immD0() %{
1925
  predicate(jlong_cast(n->getd()) == 0);
1926

1927
  match(ConD);
1928
  op_cost(0);
1929
  format %{ %}
1930
  interface(CONST_INTER);
1931
%}
1932

1933
operand imm8D() %{
1934
  predicate(Assembler::double_num(n->getd()).can_be_imm8());
1935
  match(ConD);
1936

1937
  op_cost(0);
1938
  format %{ %}
1939
  interface(CONST_INTER);
1940
%}
1941

1942
// Float Immediate
1943
operand immF() %{
1944
  match(ConF);
1945

1946
  op_cost(20);
1947
  format %{ %}
1948
  interface(CONST_INTER);
1949
%}
1950

1951
// Float Immediate: +0.0f
1952
operand immF0() %{
1953
  predicate(jint_cast(n->getf()) == 0);
1954
  match(ConF);
1955

1956
  op_cost(0);
1957
  format %{ %}
1958
  interface(CONST_INTER);
1959
%}
1960

1961
// Float Immediate: encoded as 8 bits
1962
operand imm8F() %{
1963
  predicate(Assembler::float_num(n->getf()).can_be_imm8());
1964
  match(ConF);
1965

1966
  op_cost(0);
1967
  format %{ %}
1968
  interface(CONST_INTER);
1969
%}
1970

1971
// Integer Register Operands
1972
// Integer Register
1973
operand iRegI() %{
1974
  constraint(ALLOC_IN_RC(int_reg));
1975
  match(RegI);
1976
  match(R0RegI);
1977
  match(R1RegI);
1978
  match(R2RegI);
1979
  match(R3RegI);
1980
  match(R12RegI);
1981

1982
  format %{ %}
1983
  interface(REG_INTER);
1984
%}
1985

1986
// Pointer Register
1987
operand iRegP() %{
1988
  constraint(ALLOC_IN_RC(ptr_reg));
1989
  match(RegP);
1990
  match(R0RegP);
1991
  match(R1RegP);
1992
  match(R2RegP);
1993
  match(RExceptionRegP);
1994
  match(R8RegP);
1995
  match(R9RegP);
1996
  match(RthreadRegP); // FIXME: move to sp_ptr_RegP?
1997
  match(R12RegP);
1998
  match(LRRegP);
1999

2000
  match(sp_ptr_RegP);
2001
  match(store_ptr_RegP);
2002

2003
  format %{ %}
2004
  interface(REG_INTER);
2005
%}
2006

2007
// GPRs + Rthread + SP
2008
operand sp_ptr_RegP() %{
2009
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2010
  match(RegP);
2011
  match(iRegP);
2012
  match(SPRegP); // FIXME: check cost
2013

2014
  format %{ %}
2015
  interface(REG_INTER);
2016
%}
2017

2018

2019
operand R0RegP() %{
2020
  constraint(ALLOC_IN_RC(R0_regP));
2021
  match(iRegP);
2022

2023
  format %{ %}
2024
  interface(REG_INTER);
2025
%}
2026

2027
operand R1RegP() %{
2028
  constraint(ALLOC_IN_RC(R1_regP));
2029
  match(iRegP);
2030

2031
  format %{ %}
2032
  interface(REG_INTER);
2033
%}
2034

2035
operand R8RegP() %{
2036
  constraint(ALLOC_IN_RC(R8_regP));
2037
  match(iRegP);
2038

2039
  format %{ %}
2040
  interface(REG_INTER);
2041
%}
2042

2043
operand R9RegP() %{
2044
  constraint(ALLOC_IN_RC(R9_regP));
2045
  match(iRegP);
2046

2047
  format %{ %}
2048
  interface(REG_INTER);
2049
%}
2050

2051
operand R12RegP() %{
2052
  constraint(ALLOC_IN_RC(R12_regP));
2053
  match(iRegP);
2054

2055
  format %{ %}
2056
  interface(REG_INTER);
2057
%}
2058

2059
operand R2RegP() %{
2060
  constraint(ALLOC_IN_RC(R2_regP));
2061
  match(iRegP);
2062

2063
  format %{ %}
2064
  interface(REG_INTER);
2065
%}
2066

2067
operand RExceptionRegP() %{
2068
  constraint(ALLOC_IN_RC(Rexception_regP));
2069
  match(iRegP);
2070

2071
  format %{ %}
2072
  interface(REG_INTER);
2073
%}
2074

2075
operand RthreadRegP() %{
2076
  constraint(ALLOC_IN_RC(Rthread_regP));
2077
  match(iRegP);
2078

2079
  format %{ %}
2080
  interface(REG_INTER);
2081
%}
2082

2083
operand IPRegP() %{
2084
  constraint(ALLOC_IN_RC(IP_regP));
2085
  match(iRegP);
2086

2087
  format %{ %}
2088
  interface(REG_INTER);
2089
%}
2090

2091
operand SPRegP() %{
2092
  constraint(ALLOC_IN_RC(SP_regP));
2093
  match(iRegP);
2094

2095
  format %{ %}
2096
  interface(REG_INTER);
2097
%}
2098

2099
operand LRRegP() %{
2100
  constraint(ALLOC_IN_RC(LR_regP));
2101
  match(iRegP);
2102

2103
  format %{ %}
2104
  interface(REG_INTER);
2105
%}
2106

2107
operand R0RegI() %{
2108
  constraint(ALLOC_IN_RC(R0_regI));
2109
  match(iRegI);
2110

2111
  format %{ %}
2112
  interface(REG_INTER);
2113
%}
2114

2115
operand R1RegI() %{
2116
  constraint(ALLOC_IN_RC(R1_regI));
2117
  match(iRegI);
2118

2119
  format %{ %}
2120
  interface(REG_INTER);
2121
%}
2122

2123
operand R2RegI() %{
2124
  constraint(ALLOC_IN_RC(R2_regI));
2125
  match(iRegI);
2126

2127
  format %{ %}
2128
  interface(REG_INTER);
2129
%}
2130

2131
operand R3RegI() %{
2132
  constraint(ALLOC_IN_RC(R3_regI));
2133
  match(iRegI);
2134

2135
  format %{ %}
2136
  interface(REG_INTER);
2137
%}
2138

2139
operand R12RegI() %{
2140
  constraint(ALLOC_IN_RC(R12_regI));
2141
  match(iRegI);
2142

2143
  format %{ %}
2144
  interface(REG_INTER);
2145
%}
2146

2147
// Long Register
2148
operand iRegL() %{
2149
  constraint(ALLOC_IN_RC(long_reg));
2150
  match(RegL);
2151
  match(R0R1RegL);
2152
  match(R2R3RegL);
2153
//match(iRegLex);
2154

2155
  format %{ %}
2156
  interface(REG_INTER);
2157
%}
2158

2159
operand iRegLd() %{
2160
  constraint(ALLOC_IN_RC(long_reg_align));
2161
  match(iRegL); // FIXME: allows unaligned R11/R12?
2162

2163
  format %{ %}
2164
  interface(REG_INTER);
2165
%}
2166

2167
// first long arg, or return value
2168
operand R0R1RegL() %{
2169
  constraint(ALLOC_IN_RC(R0R1_regL));
2170
  match(iRegL);
2171

2172
  format %{ %}
2173
  interface(REG_INTER);
2174
%}
2175

2176
operand R2R3RegL() %{
2177
  constraint(ALLOC_IN_RC(R2R3_regL));
2178
  match(iRegL);
2179

2180
  format %{ %}
2181
  interface(REG_INTER);
2182
%}
2183

2184
// Condition Code Flag Register
2185
operand flagsReg() %{
2186
  constraint(ALLOC_IN_RC(int_flags));
2187
  match(RegFlags);
2188

2189
  format %{ "apsr" %}
2190
  interface(REG_INTER);
2191
%}
2192

2193
// Result of compare to 0 (TST)
2194
operand flagsReg_EQNELTGE() %{
2195
  constraint(ALLOC_IN_RC(int_flags));
2196
  match(RegFlags);
2197

2198
  format %{ "apsr_EQNELTGE" %}
2199
  interface(REG_INTER);
2200
%}
2201

2202
// Condition Code Register, unsigned comparisons.
2203
operand flagsRegU() %{
2204
  constraint(ALLOC_IN_RC(int_flags));
2205
  match(RegFlags);
2206
#ifdef TODO
2207
  match(RegFlagsP);
2208
#endif
2209

2210
  format %{ "apsr_U" %}
2211
  interface(REG_INTER);
2212
%}
2213

2214
// Condition Code Register, pointer comparisons.
2215
operand flagsRegP() %{
2216
  constraint(ALLOC_IN_RC(int_flags));
2217
  match(RegFlags);
2218

2219
  format %{ "apsr_P" %}
2220
  interface(REG_INTER);
2221
%}
2222

2223
// Condition Code Register, long comparisons.
2224
operand flagsRegL_LTGE() %{
2225
  constraint(ALLOC_IN_RC(int_flags));
2226
  match(RegFlags);
2227

2228
  format %{ "apsr_L_LTGE" %}
2229
  interface(REG_INTER);
2230
%}
2231

2232
operand flagsRegL_EQNE() %{
2233
  constraint(ALLOC_IN_RC(int_flags));
2234
  match(RegFlags);
2235

2236
  format %{ "apsr_L_EQNE" %}
2237
  interface(REG_INTER);
2238
%}
2239

2240
operand flagsRegL_LEGT() %{
2241
  constraint(ALLOC_IN_RC(int_flags));
2242
  match(RegFlags);
2243

2244
  format %{ "apsr_L_LEGT" %}
2245
  interface(REG_INTER);
2246
%}
2247

2248
operand flagsRegUL_LTGE() %{
2249
  constraint(ALLOC_IN_RC(int_flags));
2250
  match(RegFlags);
2251

2252
  format %{ "apsr_UL_LTGE" %}
2253
  interface(REG_INTER);
2254
%}
2255

2256
operand flagsRegUL_EQNE() %{
2257
  constraint(ALLOC_IN_RC(int_flags));
2258
  match(RegFlags);
2259

2260
  format %{ "apsr_UL_EQNE" %}
2261
  interface(REG_INTER);
2262
%}
2263

2264
operand flagsRegUL_LEGT() %{
2265
  constraint(ALLOC_IN_RC(int_flags));
2266
  match(RegFlags);
2267

2268
  format %{ "apsr_UL_LEGT" %}
2269
  interface(REG_INTER);
2270
%}
2271

2272
// Condition Code Register, floating comparisons, unordered same as "less".
2273
operand flagsRegF() %{
2274
  constraint(ALLOC_IN_RC(float_flags));
2275
  match(RegFlags);
2276

2277
  format %{ "fpscr_F" %}
2278
  interface(REG_INTER);
2279
%}
2280

2281
// Vectors
2282
operand vecD() %{
2283
  constraint(ALLOC_IN_RC(actual_dflt_reg));
2284
  match(VecD);
2285

2286
  format %{ %}
2287
  interface(REG_INTER);
2288
%}
2289

2290
operand vecX() %{
2291
  constraint(ALLOC_IN_RC(vectorx_reg));
2292
  match(VecX);
2293

2294
  format %{ %}
2295
  interface(REG_INTER);
2296
%}
2297

2298
operand regD() %{
2299
  constraint(ALLOC_IN_RC(actual_dflt_reg));
2300
  match(RegD);
2301
  match(regD_low);
2302

2303
  format %{ %}
2304
  interface(REG_INTER);
2305
%}
2306

2307
operand regF() %{
2308
  constraint(ALLOC_IN_RC(sflt_reg));
2309
  match(RegF);
2310

2311
  format %{ %}
2312
  interface(REG_INTER);
2313
%}
2314

2315
operand regD_low() %{
2316
  constraint(ALLOC_IN_RC(dflt_low_reg));
2317
  match(RegD);
2318

2319
  format %{ %}
2320
  interface(REG_INTER);
2321
%}
2322

2323
// Special Registers
2324

2325
// Method Register
2326
operand inline_cache_regP(iRegP reg) %{
2327
  constraint(ALLOC_IN_RC(Ricklass_regP));
2328
  match(reg);
2329
  format %{ %}
2330
  interface(REG_INTER);
2331
%}
2332

2333
//----------Complex Operands---------------------------------------------------
2334
// Indirect Memory Reference
2335
operand indirect(sp_ptr_RegP reg) %{
2336
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2337
  match(reg);
2338

2339
  op_cost(100);
2340
  format %{ "[$reg]" %}
2341
  interface(MEMORY_INTER) %{
2342
    base($reg);
2343
    index(0xf); // PC => no index
2344
    scale(0x0);
2345
    disp(0x0);
2346
  %}
2347
%}
2348

2349

2350
// Indirect with Offset in ]-4096, 4096[
2351
operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{
2352
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2353
  match(AddP reg offset);
2354

2355
  op_cost(100);
2356
  format %{ "[$reg + $offset]" %}
2357
  interface(MEMORY_INTER) %{
2358
    base($reg);
2359
    index(0xf); // PC => no index
2360
    scale(0x0);
2361
    disp($offset);
2362
  %}
2363
%}
2364

2365
// Indirect with offset for float load/store
2366
operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{
2367
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2368
  match(AddP reg offset);
2369

2370
  op_cost(100);
2371
  format %{ "[$reg + $offset]" %}
2372
  interface(MEMORY_INTER) %{
2373
    base($reg);
2374
    index(0xf); // PC => no index
2375
    scale(0x0);
2376
    disp($offset);
2377
  %}
2378
%}
2379

2380
// Indirect with Offset for half and double words
2381
operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{
2382
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2383
  match(AddP reg offset);
2384

2385
  op_cost(100);
2386
  format %{ "[$reg + $offset]" %}
2387
  interface(MEMORY_INTER) %{
2388
    base($reg);
2389
    index(0xf); // PC => no index
2390
    scale(0x0);
2391
    disp($offset);
2392
  %}
2393
%}
2394

2395
// Indirect with Offset and Offset+4 in ]-1024, 1024[
2396
operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{
2397
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2398
  match(AddP reg offset);
2399

2400
  op_cost(100);
2401
  format %{ "[$reg + $offset]" %}
2402
  interface(MEMORY_INTER) %{
2403
    base($reg);
2404
    index(0xf); // PC => no index
2405
    scale(0x0);
2406
    disp($offset);
2407
  %}
2408
%}
2409

2410
// Indirect with Offset and Offset+4 in ]-4096, 4096[
2411
operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{
2412
  constraint(ALLOC_IN_RC(sp_ptr_reg));
2413
  match(AddP reg offset);
2414

2415
  op_cost(100);
2416
  format %{ "[$reg + $offset]" %}
2417
  interface(MEMORY_INTER) %{
2418
    base($reg);
2419
    index(0xf); // PC => no index
2420
    scale(0x0);
2421
    disp($offset);
2422
  %}
2423
%}
2424

2425
// Indirect with Register Index
2426
operand indIndex(iRegP addr, iRegX index) %{
2427
  constraint(ALLOC_IN_RC(ptr_reg));
2428
  match(AddP addr index);
2429

2430
  op_cost(100);
2431
  format %{ "[$addr + $index]" %}
2432
  interface(MEMORY_INTER) %{
2433
    base($addr);
2434
    index($index);
2435
    scale(0x0);
2436
    disp(0x0);
2437
  %}
2438
%}
2439

2440
// Indirect Memory Times Scale Plus Index Register
2441
operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{
2442
  constraint(ALLOC_IN_RC(ptr_reg));
2443
  match(AddP addr (LShiftX index scale));
2444

2445
  op_cost(100);
2446
  format %{"[$addr + $index << $scale]" %}
2447
  interface(MEMORY_INTER) %{
2448
    base($addr);
2449
    index($index);
2450
    scale($scale);
2451
    disp(0x0);
2452
  %}
2453
%}
2454

2455
// Operands for expressing Control Flow
2456
// NOTE:  Label is a predefined operand which should not be redefined in
2457
//        the AD file.  It is generically handled within the ADLC.
2458

2459
//----------Conditional Branch Operands----------------------------------------
2460
// Comparison Op  - This is the operation of the comparison, and is limited to
2461
//                  the following set of codes:
2462
//                  L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
2463
//
2464
// Other attributes of the comparison, such as unsignedness, are specified
2465
// by the comparison instruction that sets a condition code flags register.
2466
// That result is represented by a flags operand whose subtype is appropriate
2467
// to the unsignedness (etc.) of the comparison.
2468
//
2469
// Later, the instruction which matches both the Comparison Op (a Bool) and
2470
// the flags (produced by the Cmp) specifies the coding of the comparison op
2471
// by matching a specific subtype of Bool operand below, such as cmpOpU.
2472

2473
operand cmpOp() %{
2474
  match(Bool);
2475

2476
  format %{ "" %}
2477
  interface(COND_INTER) %{
2478
    equal(0x0);
2479
    not_equal(0x1);
2480
    less(0xb);
2481
    greater_equal(0xa);
2482
    less_equal(0xd);
2483
    greater(0xc);
2484
    overflow(0x0); // unsupported/unimplemented
2485
    no_overflow(0x0); // unsupported/unimplemented
2486
  %}
2487
%}
2488

2489
// integer comparison with 0, signed
2490
operand cmpOp0() %{
2491
  match(Bool);
2492

2493
  format %{ "" %}
2494
  interface(COND_INTER) %{
2495
    equal(0x0);
2496
    not_equal(0x1);
2497
    less(0x4);
2498
    greater_equal(0x5);
2499
    less_equal(0xd); // unsupported
2500
    greater(0xc); // unsupported
2501
    overflow(0x0); // unsupported/unimplemented
2502
    no_overflow(0x0); // unsupported/unimplemented
2503
  %}
2504
%}
2505

2506
// Comparison Op, unsigned
2507
operand cmpOpU() %{
2508
  match(Bool);
2509

2510
  format %{ "u" %}
2511
  interface(COND_INTER) %{
2512
    equal(0x0);
2513
    not_equal(0x1);
2514
    less(0x3);
2515
    greater_equal(0x2);
2516
    less_equal(0x9);
2517
    greater(0x8);
2518
    overflow(0x0); // unsupported/unimplemented
2519
    no_overflow(0x0); // unsupported/unimplemented
2520
  %}
2521
%}
2522

2523
// Comparison Op, pointer (same as unsigned)
2524
operand cmpOpP() %{
2525
  match(Bool);
2526

2527
  format %{ "p" %}
2528
  interface(COND_INTER) %{
2529
    equal(0x0);
2530
    not_equal(0x1);
2531
    less(0x3);
2532
    greater_equal(0x2);
2533
    less_equal(0x9);
2534
    greater(0x8);
2535
    overflow(0x0); // unsupported/unimplemented
2536
    no_overflow(0x0); // unsupported/unimplemented
2537
  %}
2538
%}
2539

2540
operand cmpOpL() %{
2541
  match(Bool);
2542

2543
  format %{ "L" %}
2544
  interface(COND_INTER) %{
2545
    equal(0x0);
2546
    not_equal(0x1);
2547
    less(0xb);
2548
    greater_equal(0xa);
2549
    less_equal(0xd);
2550
    greater(0xc);
2551
    overflow(0x0); // unsupported/unimplemented
2552
    no_overflow(0x0); // unsupported/unimplemented
2553
  %}
2554
%}
2555

2556
operand cmpOpL_commute() %{
2557
  match(Bool);
2558

2559
  format %{ "L" %}
2560
  interface(COND_INTER) %{
2561
    equal(0x0);
2562
    not_equal(0x1);
2563
    less(0xc);
2564
    greater_equal(0xd);
2565
    less_equal(0xa);
2566
    greater(0xb);
2567
    overflow(0x0); // unsupported/unimplemented
2568
    no_overflow(0x0); // unsupported/unimplemented
2569
  %}
2570
%}
2571

2572
operand cmpOpUL() %{
2573
  match(Bool);
2574

2575
  format %{ "UL" %}
2576
  interface(COND_INTER) %{
2577
    equal(0x0);
2578
    not_equal(0x1);
2579
    less(0x3);
2580
    greater_equal(0x2);
2581
    less_equal(0x9);
2582
    greater(0x8);
2583
    overflow(0x0); // unsupported/unimplemented
2584
    no_overflow(0x0); // unsupported/unimplemented
2585
  %}
2586
%}
2587

2588
operand cmpOpUL_commute() %{
2589
  match(Bool);
2590

2591
  format %{ "UL" %}
2592
  interface(COND_INTER) %{
2593
    equal(0x0);
2594
    not_equal(0x1);
2595
    less(0x8);
2596
    greater_equal(0x9);
2597
    less_equal(0x2);
2598
    greater(0x3);
2599
    overflow(0x0); // unsupported/unimplemented
2600
    no_overflow(0x0); // unsupported/unimplemented
2601
  %}
2602
%}
2603

2604

2605
//----------OPERAND CLASSES----------------------------------------------------
2606
// Operand Classes are groups of operands that are used to simplify
2607
// instruction definitions by not requiring the AD writer to specify separate
2608
// instructions for every form of operand when the instruction accepts
2609
// multiple operand types with the same basic encoding and format.  The classic
2610
// case of this is memory operands.
2611

2612
opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale );
2613
opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale );
2614
opclass memoryF ( indirect, indOffsetFP );
2615
opclass memoryF2 ( indirect, indOffsetFPx2 );
2616
opclass memoryD ( indirect, indOffsetFP );
2617
opclass memoryfp( indirect, indOffsetFP );
2618
opclass memoryB ( indirect, indIndex, indOffsetHD );
2619
opclass memoryS ( indirect, indIndex, indOffsetHD );
2620
opclass memoryL ( indirect, indIndex, indOffsetHD );
2621

2622
opclass memoryScaledI(indIndexScale);
2623
opclass memoryScaledP(indIndexScale);
2624

2625
// when ldrex/strex is used:
2626
opclass memoryex ( indirect );
2627
opclass indIndexMemory( indIndex );
2628
opclass memorylong ( indirect, indOffset12x2 );
2629
opclass memoryvld ( indirect /* , write back mode not implemented */ );
2630

2631
//----------PIPELINE-----------------------------------------------------------
2632
pipeline %{
2633

2634
//----------ATTRIBUTES---------------------------------------------------------
2635
attributes %{
2636
  fixed_size_instructions;           // Fixed size instructions
2637
  max_instructions_per_bundle = 4;   // Up to 4 instructions per bundle
2638
  instruction_unit_size = 4;         // An instruction is 4 bytes long
2639
  instruction_fetch_unit_size = 16;  // The processor fetches one line
2640
  instruction_fetch_units = 1;       // of 16 bytes
2641

2642
  // List of nop instructions
2643
  nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR );
2644
%}
2645

2646
//----------RESOURCES----------------------------------------------------------
2647
// Resources are the functional units available to the machine
2648
resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1);
2649

2650
//----------PIPELINE DESCRIPTION-----------------------------------------------
2651
// Pipeline Description specifies the stages in the machine's pipeline
2652

2653
pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D);
2654

2655
//----------PIPELINE CLASSES---------------------------------------------------
2656
// Pipeline Classes describe the stages in which input and output are
2657
// referenced by the hardware pipeline.
2658

2659
// Integer ALU reg-reg operation
2660
pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2661
    single_instruction;
2662
    dst   : E(write);
2663
    src1  : R(read);
2664
    src2  : R(read);
2665
    IALU  : R;
2666
%}
2667

2668
// Integer ALU reg-reg long operation
2669
pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{
2670
    instruction_count(2);
2671
    dst   : E(write);
2672
    src1  : R(read);
2673
    src2  : R(read);
2674
    IALU  : R;
2675
    IALU  : R;
2676
%}
2677

2678
// Integer ALU reg-reg long dependent operation
2679
pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{
2680
    instruction_count(1); multiple_bundles;
2681
    dst   : E(write);
2682
    src1  : R(read);
2683
    src2  : R(read);
2684
    cr    : E(write);
2685
    IALU  : R(2);
2686
%}
2687

2688
// Integer ALU reg-imm operation
2689
pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{
2690
    single_instruction;
2691
    dst   : E(write);
2692
    src1  : R(read);
2693
    IALU  : R;
2694
%}
2695

2696
// Integer ALU reg-reg operation with condition code
2697
pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{
2698
    single_instruction;
2699
    dst   : E(write);
2700
    cr    : E(write);
2701
    src1  : R(read);
2702
    src2  : R(read);
2703
    IALU  : R;
2704
%}
2705

2706
// Integer ALU zero-reg operation
2707
pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{
2708
    single_instruction;
2709
    dst   : E(write);
2710
    src2  : R(read);
2711
    IALU  : R;
2712
%}
2713

2714
// Integer ALU zero-reg operation with condition code only
2715
pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{
2716
    single_instruction;
2717
    cr    : E(write);
2718
    src   : R(read);
2719
    IALU  : R;
2720
%}
2721

2722
// Integer ALU reg-reg operation with condition code only
2723
pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2724
    single_instruction;
2725
    cr    : E(write);
2726
    src1  : R(read);
2727
    src2  : R(read);
2728
    IALU  : R;
2729
%}
2730

2731
// Integer ALU reg-imm operation with condition code only
2732
pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{
2733
    single_instruction;
2734
    cr    : E(write);
2735
    src1  : R(read);
2736
    IALU  : R;
2737
%}
2738

2739
// Integer ALU reg-reg-zero operation with condition code only
2740
pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{
2741
    single_instruction;
2742
    cr    : E(write);
2743
    src1  : R(read);
2744
    src2  : R(read);
2745
    IALU  : R;
2746
%}
2747

2748
// Integer ALU reg-imm-zero operation with condition code only
2749
pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{
2750
    single_instruction;
2751
    cr    : E(write);
2752
    src1  : R(read);
2753
    IALU  : R;
2754
%}
2755

2756
// Integer ALU reg-reg operation with condition code, src1 modified
2757
pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2758
    single_instruction;
2759
    cr    : E(write);
2760
    src1  : E(write);
2761
    src1  : R(read);
2762
    src2  : R(read);
2763
    IALU  : R;
2764
%}
2765

2766
pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{
2767
    multiple_bundles;
2768
    dst   : E(write)+4;
2769
    cr    : E(write);
2770
    src1  : R(read);
2771
    src2  : R(read);
2772
    IALU  : R(3);
2773
    BR    : R(2);
2774
%}
2775

2776
// Integer ALU operation
2777
pipe_class ialu_none(iRegI dst) %{
2778
    single_instruction;
2779
    dst   : E(write);
2780
    IALU  : R;
2781
%}
2782

2783
// Integer ALU reg operation
2784
pipe_class ialu_reg(iRegI dst, iRegI src) %{
2785
    single_instruction; may_have_no_code;
2786
    dst   : E(write);
2787
    src   : R(read);
2788
    IALU  : R;
2789
%}
2790

2791
// Integer ALU reg conditional operation
2792
// This instruction has a 1 cycle stall, and cannot execute
2793
// in the same cycle as the instruction setting the condition
2794
// code. We kludge this by pretending to read the condition code
2795
// 1 cycle earlier, and by marking the functional units as busy
2796
// for 2 cycles with the result available 1 cycle later than
2797
// is really the case.
2798
pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{
2799
    single_instruction;
2800
    op2_out : C(write);
2801
    op1     : R(read);
2802
    cr      : R(read);       // This is really E, with a 1 cycle stall
2803
    BR      : R(2);
2804
    MS      : R(2);
2805
%}
2806

2807
// Integer ALU reg operation
2808
pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{
2809
    single_instruction; may_have_no_code;
2810
    dst   : E(write);
2811
    src   : R(read);
2812
    IALU  : R;
2813
%}
2814
pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{
2815
    single_instruction; may_have_no_code;
2816
    dst   : E(write);
2817
    src   : R(read);
2818
    IALU  : R;
2819
%}
2820

2821
// Two integer ALU reg operations
2822
pipe_class ialu_reg_2(iRegL dst, iRegL src) %{
2823
    instruction_count(2);
2824
    dst   : E(write);
2825
    src   : R(read);
2826
    A0    : R;
2827
    A1    : R;
2828
%}
2829

2830
// Two integer ALU reg operations
2831
pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{
2832
    instruction_count(2); may_have_no_code;
2833
    dst   : E(write);
2834
    src   : R(read);
2835
    A0    : R;
2836
    A1    : R;
2837
%}
2838

2839
// Integer ALU imm operation
2840
pipe_class ialu_imm(iRegI dst) %{
2841
    single_instruction;
2842
    dst   : E(write);
2843
    IALU  : R;
2844
%}
2845

2846
pipe_class ialu_imm_n(iRegI dst) %{
2847
    single_instruction;
2848
    dst   : E(write);
2849
    IALU  : R;
2850
%}
2851

2852
// Integer ALU reg-reg with carry operation
2853
pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{
2854
    single_instruction;
2855
    dst   : E(write);
2856
    src1  : R(read);
2857
    src2  : R(read);
2858
    IALU  : R;
2859
%}
2860

2861
// Integer ALU cc operation
2862
pipe_class ialu_cc(iRegI dst, flagsReg cc) %{
2863
    single_instruction;
2864
    dst   : E(write);
2865
    cc    : R(read);
2866
    IALU  : R;
2867
%}
2868

2869
// Integer ALU cc / second IALU operation
2870
pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{
2871
    instruction_count(1); multiple_bundles;
2872
    dst   : E(write)+1;
2873
    src   : R(read);
2874
    IALU  : R;
2875
%}
2876

2877
// Integer ALU cc / second IALU operation
2878
pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{
2879
    instruction_count(1); multiple_bundles;
2880
    dst   : E(write)+1;
2881
    p     : R(read);
2882
    q     : R(read);
2883
    IALU  : R;
2884
%}
2885

2886
// Integer ALU hi-lo-reg operation
2887
pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{
2888
    instruction_count(1); multiple_bundles;
2889
    dst   : E(write)+1;
2890
    IALU  : R(2);
2891
%}
2892

2893
// Long Constant
2894
pipe_class loadConL( iRegL dst, immL src ) %{
2895
    instruction_count(2); multiple_bundles;
2896
    dst   : E(write)+1;
2897
    IALU  : R(2);
2898
    IALU  : R(2);
2899
%}
2900

2901
// Pointer Constant
2902
pipe_class loadConP( iRegP dst, immP src ) %{
2903
    instruction_count(0); multiple_bundles;
2904
    fixed_latency(6);
2905
%}
2906

2907
// Long Constant small
2908
pipe_class loadConLlo( iRegL dst, immL src ) %{
2909
    instruction_count(2);
2910
    dst   : E(write);
2911
    IALU  : R;
2912
    IALU  : R;
2913
%}
2914

2915
// [PHH] This is wrong for 64-bit.  See LdImmF/D.
2916
pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{
2917
    instruction_count(1); multiple_bundles;
2918
    src   : R(read);
2919
    dst   : M(write)+1;
2920
    IALU  : R;
2921
    MS    : E;
2922
%}
2923

2924
// Integer ALU nop operation
2925
pipe_class ialu_nop() %{
2926
    single_instruction;
2927
    IALU  : R;
2928
%}
2929

2930
// Integer ALU nop operation
2931
pipe_class ialu_nop_A0() %{
2932
    single_instruction;
2933
    A0    : R;
2934
%}
2935

2936
// Integer ALU nop operation
2937
pipe_class ialu_nop_A1() %{
2938
    single_instruction;
2939
    A1    : R;
2940
%}
2941

2942
// Integer Multiply reg-reg operation
2943
pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2944
    single_instruction;
2945
    dst   : E(write);
2946
    src1  : R(read);
2947
    src2  : R(read);
2948
    MS    : R(5);
2949
%}
2950

2951
pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2952
    single_instruction;
2953
    dst   : E(write)+4;
2954
    src1  : R(read);
2955
    src2  : R(read);
2956
    MS    : R(6);
2957
%}
2958

2959
// Integer Divide reg-reg
2960
pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{
2961
    instruction_count(1); multiple_bundles;
2962
    dst   : E(write);
2963
    temp  : E(write);
2964
    src1  : R(read);
2965
    src2  : R(read);
2966
    temp  : R(read);
2967
    MS    : R(38);
2968
%}
2969

2970
// Long Divide
2971
pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2972
    dst  : E(write)+71;
2973
    src1 : R(read);
2974
    src2 : R(read)+1;
2975
    MS   : R(70);
2976
%}
2977

2978
// Floating Point Add Float
2979
pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{
2980
    single_instruction;
2981
    dst   : X(write);
2982
    src1  : E(read);
2983
    src2  : E(read);
2984
    FA    : R;
2985
%}
2986

2987
// Floating Point Add Double
2988
pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{
2989
    single_instruction;
2990
    dst   : X(write);
2991
    src1  : E(read);
2992
    src2  : E(read);
2993
    FA    : R;
2994
%}
2995

2996
// Floating Point Conditional Move based on integer flags
2997
pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{
2998
    single_instruction;
2999
    dst   : X(write);
3000
    src   : E(read);
3001
    cr    : R(read);
3002
    FA    : R(2);
3003
    BR    : R(2);
3004
%}
3005

3006
// Floating Point Conditional Move based on integer flags
3007
pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{
3008
    single_instruction;
3009
    dst   : X(write);
3010
    src   : E(read);
3011
    cr    : R(read);
3012
    FA    : R(2);
3013
    BR    : R(2);
3014
%}
3015

3016
// Floating Point Multiply Float
3017
pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{
3018
    single_instruction;
3019
    dst   : X(write);
3020
    src1  : E(read);
3021
    src2  : E(read);
3022
    FM    : R;
3023
%}
3024

3025
// Floating Point Multiply Double
3026
pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{
3027
    single_instruction;
3028
    dst   : X(write);
3029
    src1  : E(read);
3030
    src2  : E(read);
3031
    FM    : R;
3032
%}
3033

3034
// Floating Point Divide Float
3035
pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{
3036
    single_instruction;
3037
    dst   : X(write);
3038
    src1  : E(read);
3039
    src2  : E(read);
3040
    FM    : R;
3041
    FDIV  : C(14);
3042
%}
3043

3044
// Floating Point Divide Double
3045
pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{
3046
    single_instruction;
3047
    dst   : X(write);
3048
    src1  : E(read);
3049
    src2  : E(read);
3050
    FM    : R;
3051
    FDIV  : C(17);
3052
%}
3053

3054
// Floating Point Move/Negate/Abs Float
3055
pipe_class faddF_reg(regF dst, regF src) %{
3056
    single_instruction;
3057
    dst   : W(write);
3058
    src   : E(read);
3059
    FA    : R(1);
3060
%}
3061

3062
// Floating Point Move/Negate/Abs Double
3063
pipe_class faddD_reg(regD dst, regD src) %{
3064
    single_instruction;
3065
    dst   : W(write);
3066
    src   : E(read);
3067
    FA    : R;
3068
%}
3069

3070
// Floating Point Convert F->D
3071
pipe_class fcvtF2D(regD dst, regF src) %{
3072
    single_instruction;
3073
    dst   : X(write);
3074
    src   : E(read);
3075
    FA    : R;
3076
%}
3077

3078
// Floating Point Convert I->D
3079
pipe_class fcvtI2D(regD dst, regF src) %{
3080
    single_instruction;
3081
    dst   : X(write);
3082
    src   : E(read);
3083
    FA    : R;
3084
%}
3085

3086
// Floating Point Convert LHi->D
3087
pipe_class fcvtLHi2D(regD dst, regD src) %{
3088
    single_instruction;
3089
    dst   : X(write);
3090
    src   : E(read);
3091
    FA    : R;
3092
%}
3093

3094
// Floating Point Convert L->D
3095
pipe_class fcvtL2D(regD dst, iRegL src) %{
3096
    single_instruction;
3097
    dst   : X(write);
3098
    src   : E(read);
3099
    FA    : R;
3100
%}
3101

3102
// Floating Point Convert L->F
3103
pipe_class fcvtL2F(regF dst, iRegL src) %{
3104
    single_instruction;
3105
    dst   : X(write);
3106
    src   : E(read);
3107
    FA    : R;
3108
%}
3109

3110
// Floating Point Convert D->F
3111
pipe_class fcvtD2F(regD dst, regF src) %{
3112
    single_instruction;
3113
    dst   : X(write);
3114
    src   : E(read);
3115
    FA    : R;
3116
%}
3117

3118
// Floating Point Convert I->L
3119
pipe_class fcvtI2L(regD dst, regF src) %{
3120
    single_instruction;
3121
    dst   : X(write);
3122
    src   : E(read);
3123
    FA    : R;
3124
%}
3125

3126
// Floating Point Convert D->F
3127
pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{
3128
    instruction_count(1); multiple_bundles;
3129
    dst   : X(write)+6;
3130
    src   : E(read);
3131
    FA    : R;
3132
%}
3133

3134
// Floating Point Convert D->L
3135
pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{
3136
    instruction_count(1); multiple_bundles;
3137
    dst   : X(write)+6;
3138
    src   : E(read);
3139
    FA    : R;
3140
%}
3141

3142
// Floating Point Convert F->I
3143
pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{
3144
    instruction_count(1); multiple_bundles;
3145
    dst   : X(write)+6;
3146
    src   : E(read);
3147
    FA    : R;
3148
%}
3149

3150
// Floating Point Convert F->L
3151
pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{
3152
    instruction_count(1); multiple_bundles;
3153
    dst   : X(write)+6;
3154
    src   : E(read);
3155
    FA    : R;
3156
%}
3157

3158
// Floating Point Convert I->F
3159
pipe_class fcvtI2F(regF dst, regF src) %{
3160
    single_instruction;
3161
    dst   : X(write);
3162
    src   : E(read);
3163
    FA    : R;
3164
%}
3165

3166
// Floating Point Compare
3167
pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{
3168
    single_instruction;
3169
    cr    : X(write);
3170
    src1  : E(read);
3171
    src2  : E(read);
3172
    FA    : R;
3173
%}
3174

3175
// Floating Point Compare
3176
pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{
3177
    single_instruction;
3178
    cr    : X(write);
3179
    src1  : E(read);
3180
    src2  : E(read);
3181
    FA    : R;
3182
%}
3183

3184
// Floating Add Nop
3185
pipe_class fadd_nop() %{
3186
    single_instruction;
3187
    FA  : R;
3188
%}
3189

3190
// Integer Store to Memory
3191
pipe_class istore_mem_reg(memoryI mem, iRegI src) %{
3192
    single_instruction;
3193
    mem   : R(read);
3194
    src   : C(read);
3195
    MS    : R;
3196
%}
3197

3198
// Integer Store to Memory
3199
pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{
3200
    single_instruction;
3201
    mem   : R(read);
3202
    src   : C(read);
3203
    MS    : R;
3204
%}
3205

3206
// Float Store
3207
pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{
3208
    single_instruction;
3209
    mem : R(read);
3210
    src : C(read);
3211
    MS  : R;
3212
%}
3213

3214
// Float Store
3215
pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{
3216
    single_instruction;
3217
    mem : R(read);
3218
    MS  : R;
3219
%}
3220

3221
// Double Store
3222
pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{
3223
    instruction_count(1);
3224
    mem : R(read);
3225
    src : C(read);
3226
    MS  : R;
3227
%}
3228

3229
// Double Store
3230
pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{
3231
    single_instruction;
3232
    mem : R(read);
3233
    MS  : R;
3234
%}
3235

3236
// Integer Load (when sign bit propagation not needed)
3237
pipe_class iload_mem(iRegI dst, memoryI mem) %{
3238
    single_instruction;
3239
    mem : R(read);
3240
    dst : C(write);
3241
    MS  : R;
3242
%}
3243

3244
// Integer Load (when sign bit propagation or masking is needed)
3245
pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{
3246
    single_instruction;
3247
    mem : R(read);
3248
    dst : M(write);
3249
    MS  : R;
3250
%}
3251

3252
// Float Load
3253
pipe_class floadF_mem(regF dst, memoryF mem) %{
3254
    single_instruction;
3255
    mem : R(read);
3256
    dst : M(write);
3257
    MS  : R;
3258
%}
3259

3260
// Float Load
3261
pipe_class floadD_mem(regD dst, memoryD mem) %{
3262
    instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case
3263
    mem : R(read);
3264
    dst : M(write);
3265
    MS  : R;
3266
%}
3267

3268
// Memory Nop
3269
pipe_class mem_nop() %{
3270
    single_instruction;
3271
    MS  : R;
3272
%}
3273

3274
pipe_class sethi(iRegP dst, immI src) %{
3275
    single_instruction;
3276
    dst  : E(write);
3277
    IALU : R;
3278
%}
3279

3280
pipe_class loadPollP(iRegP poll) %{
3281
    single_instruction;
3282
    poll : R(read);
3283
    MS   : R;
3284
%}
3285

3286
pipe_class br(Universe br, label labl) %{
3287
    single_instruction_with_delay_slot;
3288
    BR  : R;
3289
%}
3290

3291
pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
3292
    single_instruction_with_delay_slot;
3293
    cr    : E(read);
3294
    BR    : R;
3295
%}
3296

3297
pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
3298
    single_instruction_with_delay_slot;
3299
    op1 : E(read);
3300
    BR  : R;
3301
    MS  : R;
3302
%}
3303

3304
pipe_class br_nop() %{
3305
    single_instruction;
3306
    BR  : R;
3307
%}
3308

3309
pipe_class simple_call(method meth) %{
3310
    instruction_count(2); multiple_bundles; force_serialization;
3311
    fixed_latency(100);
3312
    BR  : R(1);
3313
    MS  : R(1);
3314
    A0  : R(1);
3315
%}
3316

3317
pipe_class compiled_call(method meth) %{
3318
    instruction_count(1); multiple_bundles; force_serialization;
3319
    fixed_latency(100);
3320
    MS  : R(1);
3321
%}
3322

3323
pipe_class call(method meth) %{
3324
    instruction_count(0); multiple_bundles; force_serialization;
3325
    fixed_latency(100);
3326
%}
3327

3328
pipe_class tail_call(Universe ignore, label labl) %{
3329
    single_instruction; has_delay_slot;
3330
    fixed_latency(100);
3331
    BR  : R(1);
3332
    MS  : R(1);
3333
%}
3334

3335
pipe_class ret(Universe ignore) %{
3336
    single_instruction; has_delay_slot;
3337
    BR  : R(1);
3338
    MS  : R(1);
3339
%}
3340

3341
// The real do-nothing guy
3342
pipe_class empty( ) %{
3343
    instruction_count(0);
3344
%}
3345

3346
pipe_class long_memory_op() %{
3347
    instruction_count(0); multiple_bundles; force_serialization;
3348
    fixed_latency(25);
3349
    MS  : R(1);
3350
%}
3351

3352
// Check-cast
3353
pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{
3354
    array : R(read);
3355
    match  : R(read);
3356
    IALU   : R(2);
3357
    BR     : R(2);
3358
    MS     : R;
3359
%}
3360

3361
// Convert FPU flags into +1,0,-1
3362
pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{
3363
    src1  : E(read);
3364
    src2  : E(read);
3365
    dst   : E(write);
3366
    FA    : R;
3367
    MS    : R(2);
3368
    BR    : R(2);
3369
%}
3370

3371
// Compare for p < q, and conditionally add y
3372
pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
3373
    p     : E(read);
3374
    q     : E(read);
3375
    y     : E(read);
3376
    IALU  : R(3)
3377
%}
3378

3379
// Perform a compare, then move conditionally in a branch delay slot.
3380
pipe_class min_max( iRegI src2, iRegI srcdst ) %{
3381
    src2   : E(read);
3382
    srcdst : E(read);
3383
    IALU   : R;
3384
    BR     : R;
3385
%}
3386

3387
// Define the class for the Nop node
3388
define %{
3389
   MachNop = ialu_nop;
3390
%}
3391

3392
%}
3393

3394
//----------INSTRUCTIONS-------------------------------------------------------
3395

3396
//------------Special Nop instructions for bundling - no match rules-----------
3397
// Nop using the A0 functional unit
3398
instruct Nop_A0() %{
3399
  ins_pipe(ialu_nop_A0);
3400
%}
3401

3402
// Nop using the A1 functional unit
3403
instruct Nop_A1( ) %{
3404
  ins_pipe(ialu_nop_A1);
3405
%}
3406

3407
// Nop using the memory functional unit
3408
instruct Nop_MS( ) %{
3409
  ins_pipe(mem_nop);
3410
%}
3411

3412
// Nop using the floating add functional unit
3413
instruct Nop_FA( ) %{
3414
  ins_pipe(fadd_nop);
3415
%}
3416

3417
// Nop using the branch functional unit
3418
instruct Nop_BR( ) %{
3419
  ins_pipe(br_nop);
3420
%}
3421

3422
//----------Load/Store/Move Instructions---------------------------------------
3423
//----------Load Instructions--------------------------------------------------
3424
// Load Byte (8bit signed)
3425
instruct loadB(iRegI dst, memoryB mem) %{
3426
  match(Set dst (LoadB mem));
3427
  ins_cost(MEMORY_REF_COST);
3428

3429
  size(4);
3430
  format %{ "LDRSB   $dst,$mem\t! byte -> int" %}
3431
  ins_encode %{
3432
    __ ldrsb($dst$$Register, $mem$$Address);
3433
  %}
3434
  ins_pipe(iload_mask_mem);
3435
%}
3436

3437
// Load Byte (8bit signed) into a Long Register
3438
instruct loadB2L(iRegL dst, memoryB mem) %{
3439
  match(Set dst (ConvI2L (LoadB mem)));
3440
  ins_cost(MEMORY_REF_COST);
3441

3442
  size(8);
3443
  format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t"
3444
            "ASR   $dst.hi,$dst.lo,31" %}
3445
  ins_encode %{
3446
    __ ldrsb($dst$$Register, $mem$$Address);
3447
    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3448
  %}
3449
  ins_pipe(iload_mask_mem);
3450
%}
3451

3452
// Load Unsigned Byte (8bit UNsigned) into an int reg
3453
instruct loadUB(iRegI dst, memoryB mem) %{
3454
  match(Set dst (LoadUB mem));
3455
  ins_cost(MEMORY_REF_COST);
3456

3457
  size(4);
3458
  format %{ "LDRB   $dst,$mem\t! ubyte -> int" %}
3459
  ins_encode %{
3460
    __ ldrb($dst$$Register, $mem$$Address);
3461
  %}
3462
  ins_pipe(iload_mem);
3463
%}
3464

3465
// Load Unsigned Byte (8bit UNsigned) into a Long Register
3466
instruct loadUB2L(iRegL dst, memoryB mem) %{
3467
  match(Set dst (ConvI2L (LoadUB mem)));
3468
  ins_cost(MEMORY_REF_COST);
3469

3470
  size(8);
3471
  format %{ "LDRB  $dst.lo,$mem\t! ubyte -> long\n\t"
3472
            "MOV   $dst.hi,0" %}
3473
  ins_encode %{
3474
    __ ldrb($dst$$Register, $mem$$Address);
3475
    __ mov($dst$$Register->successor(), 0);
3476
  %}
3477
  ins_pipe(iload_mem);
3478
%}
3479

3480
// Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register
3481
instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{
3482
  match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
3483

3484
  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3485
  size(12);
3486
  format %{ "LDRB  $dst.lo,$mem\t! ubyte -> long\n\t"
3487
            "MOV   $dst.hi,0\n\t"
3488
            "AND  $dst.lo,$dst.lo,$mask" %}
3489
  ins_encode %{
3490
    __ ldrb($dst$$Register, $mem$$Address);
3491
    __ mov($dst$$Register->successor(), 0);
3492
    __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
3493
  %}
3494
  ins_pipe(iload_mem);
3495
%}
3496

3497
// Load Short (16bit signed)
3498

3499
instruct loadS(iRegI dst, memoryS mem) %{
3500
  match(Set dst (LoadS mem));
3501
  ins_cost(MEMORY_REF_COST);
3502

3503
  size(4);
3504
  format %{ "LDRSH   $dst,$mem\t! short" %}
3505
  ins_encode %{
3506
    __ ldrsh($dst$$Register, $mem$$Address);
3507
  %}
3508
  ins_pipe(iload_mask_mem);
3509
%}
3510

3511
// Load Short (16 bit signed) to Byte (8 bit signed)
3512
instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3513
  match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
3514
  ins_cost(MEMORY_REF_COST);
3515

3516
  size(4);
3517

3518
  format %{ "LDRSB   $dst,$mem\t! short -> byte" %}
3519
  ins_encode %{
3520
    __ ldrsb($dst$$Register, $mem$$Address);
3521
  %}
3522
  ins_pipe(iload_mask_mem);
3523
%}
3524

3525
// Load Short (16bit signed) into a Long Register
3526
instruct loadS2L(iRegL dst, memoryS mem) %{
3527
  match(Set dst (ConvI2L (LoadS mem)));
3528
  ins_cost(MEMORY_REF_COST);
3529

3530
  size(8);
3531
  format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t"
3532
            "ASR   $dst.hi,$dst.lo,31" %}
3533
  ins_encode %{
3534
    __ ldrsh($dst$$Register, $mem$$Address);
3535
    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3536
  %}
3537
  ins_pipe(iload_mask_mem);
3538
%}
3539

3540
// Load Unsigned Short/Char (16bit UNsigned)
3541

3542

3543
instruct loadUS(iRegI dst, memoryS mem) %{
3544
  match(Set dst (LoadUS mem));
3545
  ins_cost(MEMORY_REF_COST);
3546

3547
  size(4);
3548
  format %{ "LDRH   $dst,$mem\t! ushort/char" %}
3549
  ins_encode %{
3550
    __ ldrh($dst$$Register, $mem$$Address);
3551
  %}
3552
  ins_pipe(iload_mem);
3553
%}
3554

3555
// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
3556
instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{
3557
  match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
3558
  ins_cost(MEMORY_REF_COST);
3559

3560
  size(4);
3561
  format %{ "LDRSB   $dst,$mem\t! ushort -> byte" %}
3562
  ins_encode %{
3563
    __ ldrsb($dst$$Register, $mem$$Address);
3564
  %}
3565
  ins_pipe(iload_mask_mem);
3566
%}
3567

3568
// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
3569
instruct loadUS2L(iRegL dst, memoryS mem) %{
3570
  match(Set dst (ConvI2L (LoadUS mem)));
3571
  ins_cost(MEMORY_REF_COST);
3572

3573
  size(8);
3574
  format %{ "LDRH  $dst.lo,$mem\t! short -> long\n\t"
3575
            "MOV   $dst.hi, 0" %}
3576
  ins_encode %{
3577
    __ ldrh($dst$$Register, $mem$$Address);
3578
    __ mov($dst$$Register->successor(), 0);
3579
  %}
3580
  ins_pipe(iload_mem);
3581
%}
3582

3583
// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register
3584
instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3585
  match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3586
  ins_cost(MEMORY_REF_COST);
3587

3588
  size(8);
3589
  format %{ "LDRB  $dst.lo,$mem\t! \n\t"
3590
            "MOV   $dst.hi, 0" %}
3591
  ins_encode %{
3592
    __ ldrb($dst$$Register, $mem$$Address);
3593
    __ mov($dst$$Register->successor(), 0);
3594
  %}
3595
  ins_pipe(iload_mem);
3596
%}
3597

3598
// Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register
3599
instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{
3600
  match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3601
  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3602

3603
  size(12);
3604
  format %{ "LDRH   $dst,$mem\t! ushort/char & mask -> long\n\t"
3605
            "MOV    $dst.hi, 0\n\t"
3606
            "AND    $dst,$dst,$mask" %}
3607
  ins_encode %{
3608
    __ ldrh($dst$$Register, $mem$$Address);
3609
    __ mov($dst$$Register->successor(), 0);
3610
    __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3611
  %}
3612
  ins_pipe(iload_mem);
3613
%}
3614

3615
// Load Integer
3616

3617

3618
instruct loadI(iRegI dst, memoryI mem) %{
3619
  match(Set dst (LoadI mem));
3620
  ins_cost(MEMORY_REF_COST);
3621

3622
  size(4);
3623
  format %{ "ldr_s32 $dst,$mem\t! int" %}
3624
  ins_encode %{
3625
    __ ldr_s32($dst$$Register, $mem$$Address);
3626
  %}
3627
  ins_pipe(iload_mem);
3628
%}
3629

3630
// Load Integer to Byte (8 bit signed)
3631
instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3632
  match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
3633
  ins_cost(MEMORY_REF_COST);
3634

3635
  size(4);
3636

3637
  format %{ "LDRSB   $dst,$mem\t! int -> byte" %}
3638
  ins_encode %{
3639
    __ ldrsb($dst$$Register, $mem$$Address);
3640
  %}
3641
  ins_pipe(iload_mask_mem);
3642
%}
3643

3644
// Load Integer to Unsigned Byte (8 bit UNsigned)
3645
instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{
3646
  match(Set dst (AndI (LoadI mem) mask));
3647
  ins_cost(MEMORY_REF_COST);
3648

3649
  size(4);
3650

3651
  format %{ "LDRB   $dst,$mem\t! int -> ubyte" %}
3652
  ins_encode %{
3653
    __ ldrb($dst$$Register, $mem$$Address);
3654
  %}
3655
  ins_pipe(iload_mask_mem);
3656
%}
3657

3658
// Load Integer to Short (16 bit signed)
3659
instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{
3660
  match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
3661
  ins_cost(MEMORY_REF_COST);
3662

3663
  size(4);
3664
  format %{ "LDRSH   $dst,$mem\t! int -> short" %}
3665
  ins_encode %{
3666
    __ ldrsh($dst$$Register, $mem$$Address);
3667
  %}
3668
  ins_pipe(iload_mask_mem);
3669
%}
3670

3671
// Load Integer to Unsigned Short (16 bit UNsigned)
3672
instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{
3673
  match(Set dst (AndI (LoadI mem) mask));
3674
  ins_cost(MEMORY_REF_COST);
3675

3676
  size(4);
3677
  format %{ "LDRH   $dst,$mem\t! int -> ushort/char" %}
3678
  ins_encode %{
3679
    __ ldrh($dst$$Register, $mem$$Address);
3680
  %}
3681
  ins_pipe(iload_mask_mem);
3682
%}
3683

3684
// Load Integer into a Long Register
3685
instruct loadI2L(iRegL dst, memoryI mem) %{
3686
  match(Set dst (ConvI2L (LoadI mem)));
3687
  ins_cost(MEMORY_REF_COST);
3688

3689
  size(8);
3690
  format %{ "LDR   $dst.lo,$mem\t! int -> long\n\t"
3691
            "ASR   $dst.hi,$dst.lo,31\t! int->long" %}
3692
  ins_encode %{
3693
    __ ldr($dst$$Register, $mem$$Address);
3694
    __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3695
  %}
3696
  ins_pipe(iload_mask_mem);
3697
%}
3698

3699
// Load Integer with mask 0xFF into a Long Register
3700
instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3701
  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3702
  ins_cost(MEMORY_REF_COST);
3703

3704
  size(8);
3705
  format %{ "LDRB   $dst.lo,$mem\t! int & 0xFF -> long\n\t"
3706
            "MOV    $dst.hi, 0" %}
3707
  ins_encode %{
3708
    __ ldrb($dst$$Register, $mem$$Address);
3709
    __ mov($dst$$Register->successor(), 0);
3710
  %}
3711
  ins_pipe(iload_mem);
3712
%}
3713

3714
// Load Integer with mask 0xFFFF into a Long Register
3715
instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{
3716
  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3717
  ins_cost(MEMORY_REF_COST);
3718

3719
  size(8);
3720
  format %{ "LDRH   $dst,$mem\t! int & 0xFFFF -> long\n\t"
3721
            "MOV    $dst.hi, 0" %}
3722
  ins_encode %{
3723
    __ ldrh($dst$$Register, $mem$$Address);
3724
    __ mov($dst$$Register->successor(), 0);
3725
  %}
3726
  ins_pipe(iload_mask_mem);
3727
%}
3728

3729
// Load Integer with a 31-bit immediate mask into a Long Register
3730
instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{
3731
  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3732
  ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3733

3734
  size(12);
3735
  format %{ "LDR   $dst.lo,$mem\t! int -> long\n\t"
3736
            "MOV    $dst.hi, 0\n\t"
3737
            "AND   $dst,$dst,$mask" %}
3738

3739
  ins_encode %{
3740
    __ ldr($dst$$Register, $mem$$Address);
3741
    __ mov($dst$$Register->successor(), 0);
3742
    __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3743
  %}
3744
  ins_pipe(iload_mem);
3745
%}
3746

3747
// Load Integer with a 31-bit mask into a Long Register
3748
// FIXME: use iRegI mask, remove tmp?
3749
instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{
3750
  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3751
  effect(TEMP dst, TEMP tmp);
3752

3753
  ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST);
3754
  size(20);
3755
  format %{ "LDR      $mem,$dst\t! int & 31-bit mask -> long\n\t"
3756
            "MOV      $dst.hi, 0\n\t"
3757
            "MOV_SLOW $tmp,$mask\n\t"
3758
            "AND      $dst,$tmp,$dst" %}
3759
  ins_encode %{
3760
    __ ldr($dst$$Register, $mem$$Address);
3761
    __ mov($dst$$Register->successor(), 0);
3762
    __ mov_slow($tmp$$Register, $mask$$constant);
3763
    __ andr($dst$$Register, $dst$$Register, $tmp$$Register);
3764
  %}
3765
  ins_pipe(iload_mem);
3766
%}
3767

3768
// Load Unsigned Integer into a Long Register
3769
instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{
3770
  match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
3771
  ins_cost(MEMORY_REF_COST);
3772

3773
  size(8);
3774
  format %{ "LDR   $dst.lo,$mem\t! uint -> long\n\t"
3775
            "MOV   $dst.hi,0" %}
3776
  ins_encode %{
3777
    __ ldr($dst$$Register, $mem$$Address);
3778
    __ mov($dst$$Register->successor(), 0);
3779
  %}
3780
  ins_pipe(iload_mem);
3781
%}
3782

3783
// Load Long
3784

3785

3786
instruct loadL(iRegLd dst, memoryL mem ) %{
3787
  predicate(!((LoadLNode*)n)->require_atomic_access());
3788
  match(Set dst (LoadL mem));
3789
  effect(TEMP dst);
3790
  ins_cost(MEMORY_REF_COST);
3791

3792
  size(4);
3793
  format %{ "ldr_64  $dst,$mem\t! long" %}
3794
  ins_encode %{
3795
    __ ldr_64($dst$$Register, $mem$$Address);
3796
  %}
3797
  ins_pipe(iload_mem);
3798
%}
3799

3800
instruct loadL_2instr(iRegL dst, memorylong mem ) %{
3801
  predicate(!((LoadLNode*)n)->require_atomic_access());
3802
  match(Set dst (LoadL mem));
3803
  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
3804

3805
  size(8);
3806
  format %{ "LDR    $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3807
            "LDR    $dst.hi,$mem+4 or $mem" %}
3808
  ins_encode %{
3809
    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3810
    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3811

3812
    if ($dst$$Register == reg_to_register_object($mem$$base)) {
3813
      __ ldr($dst$$Register->successor(), Amemhi);
3814
      __ ldr($dst$$Register, Amemlo);
3815
    } else {
3816
      __ ldr($dst$$Register, Amemlo);
3817
      __ ldr($dst$$Register->successor(), Amemhi);
3818
    }
3819
  %}
3820
  ins_pipe(iload_mem);
3821
%}
3822

3823
instruct loadL_volatile(iRegL dst, indirect mem ) %{
3824
  predicate(((LoadLNode*)n)->require_atomic_access());
3825
  match(Set dst (LoadL mem));
3826
  ins_cost(MEMORY_REF_COST);
3827

3828
  size(4);
3829
  format %{ "LDMIA    $dst,$mem\t! long" %}
3830
  ins_encode %{
3831
    // FIXME: why is ldmia considered atomic?  Should be ldrexd
3832
    RegisterSet set($dst$$Register);
3833
    set = set | reg_to_register_object($dst$$reg + 1);
3834
    __ ldmia(reg_to_register_object($mem$$base), set);
3835
  %}
3836
  ins_pipe(iload_mem);
3837
%}
3838

3839
instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{
3840
  predicate(((LoadLNode*)n)->require_atomic_access());
3841
  match(Set dst (LoadL mem));
3842
  ins_cost(MEMORY_REF_COST);
3843

3844
  size(8);
3845
  format %{ "FLDD      S14, $mem"
3846
            "FMRRD    $dst, S14\t! long \n't" %}
3847
  ins_encode %{
3848
    __ fldd(S14, $mem$$Address);
3849
    __ fmrrd($dst$$Register, $dst$$Register->successor(), S14);
3850
  %}
3851
  ins_pipe(iload_mem);
3852
%}
3853

3854
instruct loadL_unaligned(iRegL dst, memorylong mem ) %{
3855
  match(Set dst (LoadL_unaligned mem));
3856
  ins_cost(MEMORY_REF_COST);
3857

3858
  size(8);
3859
  format %{ "LDR    $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3860
            "LDR    $dst.hi,$mem+4" %}
3861
  ins_encode %{
3862
    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3863
    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3864

3865
    if ($dst$$Register == reg_to_register_object($mem$$base)) {
3866
      __ ldr($dst$$Register->successor(), Amemhi);
3867
      __ ldr($dst$$Register, Amemlo);
3868
    } else {
3869
      __ ldr($dst$$Register, Amemlo);
3870
      __ ldr($dst$$Register->successor(), Amemhi);
3871
    }
3872
  %}
3873
  ins_pipe(iload_mem);
3874
%}
3875

3876
// Load Range
3877
instruct loadRange(iRegI dst, memoryI mem) %{
3878
  match(Set dst (LoadRange mem));
3879
  ins_cost(MEMORY_REF_COST);
3880

3881
  size(4);
3882
  format %{ "LDR_u32 $dst,$mem\t! range" %}
3883
  ins_encode %{
3884
    __ ldr_u32($dst$$Register, $mem$$Address);
3885
  %}
3886
  ins_pipe(iload_mem);
3887
%}
3888

3889
// Load Pointer
3890

3891

3892
instruct loadP(iRegP dst, memoryP mem) %{
3893
  match(Set dst (LoadP mem));
3894
  ins_cost(MEMORY_REF_COST);
3895
  size(4);
3896

3897
  format %{ "LDR   $dst,$mem\t! ptr" %}
3898
  ins_encode %{
3899
    __ ldr($dst$$Register, $mem$$Address);
3900
  %}
3901
  ins_pipe(iload_mem);
3902
%}
3903

3904
#ifdef XXX
3905
// FIXME XXXX
3906
//instruct loadSP(iRegP dst, memoryP mem) %{
3907
instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{
3908
  match(Set dst (LoadP mem));
3909
  effect(TEMP tmp);
3910
  ins_cost(MEMORY_REF_COST+1);
3911
  size(8);
3912

3913
  format %{ "LDR   $tmp,$mem\t! ptr\n\t"
3914
            "MOV   $dst,$tmp\t! ptr" %}
3915
  ins_encode %{
3916
    __ ldr($tmp$$Register, $mem$$Address);
3917
    __ mov($dst$$Register, $tmp$$Register);
3918
  %}
3919
  ins_pipe(iload_mem);
3920
%}
3921
#endif
3922

3923
#ifdef _LP64
3924
// Load Compressed Pointer
3925

3926
// XXX This variant shouldn't be necessary if 6217251 is implemented
3927
instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
3928
  match(Set dst (LoadN (AddP mem off)));
3929
  ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
3930
  effect(TEMP tmp);
3931
  size(4 * 2);
3932

3933
  format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %}
3934
  ins_encode %{
3935
    Register base = reg_to_register_object($mem$$base);
3936
    __ add($tmp$$Register, base, $off$$constant);
3937
    Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3938
    __ ldr_u32($dst$$Register, nmem);
3939
  %}
3940
  ins_pipe(iload_mem);
3941
%}
3942

3943
instruct loadN(iRegN dst, memoryI mem) %{
3944
  match(Set dst (LoadN mem));
3945
  ins_cost(MEMORY_REF_COST);
3946
  size(4);
3947

3948
  format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %}
3949
  ins_encode %{
3950
    __ ldr_u32($dst$$Register, $mem$$Address);
3951
  %}
3952
  ins_pipe(iload_mem);
3953
%}
3954
#endif
3955

3956
// Load Klass Pointer
3957
instruct loadKlass(iRegP dst, memoryI mem) %{
3958
  match(Set dst (LoadKlass mem));
3959
  ins_cost(MEMORY_REF_COST);
3960
  size(4);
3961

3962
  format %{ "LDR   $dst,$mem\t! klass ptr" %}
3963
  ins_encode %{
3964
    __ ldr($dst$$Register, $mem$$Address);
3965
  %}
3966
  ins_pipe(iload_mem);
3967
%}
3968

3969
#ifdef _LP64
3970
// Load narrow Klass Pointer
3971
instruct loadNKlass(iRegN dst, memoryI mem) %{
3972
  match(Set dst (LoadNKlass mem));
3973
  ins_cost(MEMORY_REF_COST);
3974
  size(4);
3975

3976
  format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %}
3977
  ins_encode %{
3978
    __ ldr_u32($dst$$Register, $mem$$Address);
3979
  %}
3980
  ins_pipe(iload_mem);
3981
%}
3982
#endif
3983

3984

3985
instruct loadD(regD dst, memoryD mem) %{
3986
  match(Set dst (LoadD mem));
3987
  ins_cost(MEMORY_REF_COST);
3988

3989
  size(4);
3990
  // FIXME: needs to be atomic, but  ARMv7 A.R.M. guarantees
3991
  // only LDREXD and STREXD are 64-bit single-copy atomic
3992
  format %{ "FLDD   $dst,$mem" %}
3993
  ins_encode %{
3994
    __ ldr_double($dst$$FloatRegister, $mem$$Address);
3995
  %}
3996
  ins_pipe(floadD_mem);
3997
%}
3998

3999
// Load Double - UNaligned
4000
instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{
4001
  match(Set dst (LoadD_unaligned mem));
4002
  ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
4003
  size(8);
4004
  format %{ "FLDS    $dst.lo,$mem\t! misaligned double\n"
4005
          "\tFLDS    $dst.hi,$mem+4\t!" %}
4006
  ins_encode %{
4007
    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4008
    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4009
      __ flds($dst$$FloatRegister, Amemlo);
4010
      __ flds($dst$$FloatRegister->successor(), Amemhi);
4011
  %}
4012
  ins_pipe(iload_mem);
4013
%}
4014

4015

4016
instruct loadF(regF dst, memoryF mem) %{
4017
  match(Set dst (LoadF mem));
4018

4019
  ins_cost(MEMORY_REF_COST);
4020
  size(4);
4021
  format %{ "FLDS    $dst,$mem" %}
4022
  ins_encode %{
4023
    __ ldr_float($dst$$FloatRegister, $mem$$Address);
4024
  %}
4025
  ins_pipe(floadF_mem);
4026
%}
4027

4028

4029
// // Load Constant
4030
instruct loadConI( iRegI dst, immI src ) %{
4031
  match(Set dst src);
4032
  ins_cost(DEFAULT_COST * 3/2);
4033
  format %{ "MOV_SLOW    $dst, $src" %}
4034
  ins_encode %{
4035
    __ mov_slow($dst$$Register, $src$$constant);
4036
  %}
4037
  ins_pipe(ialu_hi_lo_reg);
4038
%}
4039

4040
instruct loadConIMov( iRegI dst, immIMov src ) %{
4041
  match(Set dst src);
4042
  size(4);
4043
  format %{ "MOV    $dst, $src" %}
4044
  ins_encode %{
4045
    __ mov($dst$$Register, $src$$constant);
4046
  %}
4047
  ins_pipe(ialu_imm);
4048
%}
4049

4050
instruct loadConIMovn( iRegI dst, immIRotn src ) %{
4051
  match(Set dst src);
4052
  size(4);
4053
  format %{ "MVN    $dst, ~$src" %}
4054
  ins_encode %{
4055
    __ mvn($dst$$Register, ~$src$$constant);
4056
  %}
4057
  ins_pipe(ialu_imm_n);
4058
%}
4059

4060
instruct loadConI16( iRegI dst, immI16 src ) %{
4061
  match(Set dst src);
4062
  size(4);
4063
  format %{ "MOVW    $dst, $src" %}
4064
  ins_encode %{
4065
    __ movw($dst$$Register, $src$$constant);
4066
  %}
4067
  ins_pipe(ialu_imm_n);
4068
%}
4069

4070
instruct loadConP(iRegP dst, immP src) %{
4071
  match(Set dst src);
4072
  ins_cost(DEFAULT_COST * 3/2);
4073
  format %{ "MOV_SLOW    $dst,$src\t!ptr" %}
4074
  ins_encode %{
4075
    relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc();
4076
    intptr_t val = $src$$constant;
4077
    if (constant_reloc == relocInfo::oop_type) {
4078
      __ mov_oop($dst$$Register, (jobject)val);
4079
    } else if (constant_reloc == relocInfo::metadata_type) {
4080
      __ mov_metadata($dst$$Register, (Metadata*)val);
4081
    } else {
4082
      __ mov_slow($dst$$Register, val);
4083
    }
4084
  %}
4085
  ins_pipe(loadConP);
4086
%}
4087

4088

4089
instruct loadConL(iRegL dst, immL src) %{
4090
  match(Set dst src);
4091
  ins_cost(DEFAULT_COST * 4);
4092
  format %{ "MOV_SLOW   $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t"
4093
            "MOV_SLOW   $dst.hi, $src >> 32" %}
4094
  ins_encode %{
4095
    __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL);
4096
    __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32);
4097
  %}
4098
  ins_pipe(loadConL);
4099
%}
4100

4101
instruct loadConL16( iRegL dst, immL16 src ) %{
4102
  match(Set dst src);
4103
  ins_cost(DEFAULT_COST * 2);
4104

4105
  size(8);
4106
  format %{ "MOVW    $dst.lo, $src \n\t"
4107
            "MOVW    $dst.hi, 0 \n\t" %}
4108
  ins_encode %{
4109
    __ movw($dst$$Register, $src$$constant);
4110
    __ movw($dst$$Register->successor(), 0);
4111
  %}
4112
  ins_pipe(ialu_imm);
4113
%}
4114

4115
instruct loadConF_imm8(regF dst, imm8F src) %{
4116
  match(Set dst src);
4117
  ins_cost(DEFAULT_COST);
4118
  size(4);
4119

4120
  format %{ "FCONSTS      $dst, $src"%}
4121

4122
  ins_encode %{
4123
    __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8());
4124
  %}
4125
  ins_pipe(loadConFD); // FIXME
4126
%}
4127

4128

4129
instruct loadConF(regF dst, immF src, iRegI tmp) %{
4130
  match(Set dst src);
4131
  ins_cost(DEFAULT_COST * 2);
4132
  effect(TEMP tmp);
4133
  size(3*4);
4134

4135
  format %{ "MOV_SLOW  $tmp, $src\n\t"
4136
            "FMSR      $dst, $tmp"%}
4137

4138
  ins_encode %{
4139
    // FIXME revisit once 6961697 is in
4140
    union {
4141
      jfloat f;
4142
      int i;
4143
    } v;
4144
    v.f = $src$$constant;
4145
    __ mov_slow($tmp$$Register, v.i);
4146
    __ fmsr($dst$$FloatRegister, $tmp$$Register);
4147
  %}
4148
  ins_pipe(loadConFD); // FIXME
4149
%}
4150

4151
instruct loadConD_imm8(regD dst, imm8D src) %{
4152
  match(Set dst src);
4153
  ins_cost(DEFAULT_COST);
4154
  size(4);
4155

4156
  format %{ "FCONSTD      $dst, $src"%}
4157

4158
  ins_encode %{
4159
    __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8());
4160
  %}
4161
  ins_pipe(loadConFD); // FIXME
4162
%}
4163

4164
instruct loadConD(regD dst, immD src, iRegP tmp) %{
4165
  match(Set dst src);
4166
  effect(TEMP tmp);
4167
  ins_cost(MEMORY_REF_COST);
4168
  format %{ "FLDD  $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %}
4169

4170
  ins_encode %{
4171
    Register r = $constanttablebase;
4172
    int offset  = $constantoffset($src);
4173
    if (!is_memoryD(offset)) {                // can't use a predicate
4174
                                              // in load constant instructs
4175
      __ add_slow($tmp$$Register, r, offset);
4176
      r = $tmp$$Register;
4177
      offset = 0;
4178
    }
4179
    __ ldr_double($dst$$FloatRegister, Address(r, offset));
4180
  %}
4181
  ins_pipe(loadConFD);
4182
%}
4183

4184
// Prefetch instructions.
4185
// Must be safe to execute with invalid address (cannot fault).
4186

4187
instruct prefetchAlloc_mp( memoryP mem ) %{
4188
  predicate(VM_Version::has_multiprocessing_extensions());
4189
  match( PrefetchAllocation mem );
4190
  ins_cost(MEMORY_REF_COST);
4191
  size(4);
4192

4193
  format %{ "PLDW $mem\t! Prefetch allocation" %}
4194
  ins_encode %{
4195
    __ pldw($mem$$Address);
4196
  %}
4197
  ins_pipe(iload_mem);
4198
%}
4199

4200
instruct prefetchAlloc_sp( memoryP mem ) %{
4201
  predicate(!VM_Version::has_multiprocessing_extensions());
4202
  match( PrefetchAllocation mem );
4203
  ins_cost(MEMORY_REF_COST);
4204
  size(4);
4205

4206
  format %{ "PLD $mem\t! Prefetch allocation" %}
4207
  ins_encode %{
4208
    __ pld($mem$$Address);
4209
  %}
4210
  ins_pipe(iload_mem);
4211
%}
4212

4213

4214
//----------Store Instructions-------------------------------------------------
4215
// Store Byte
4216
instruct storeB(memoryB mem, store_RegI src) %{
4217
  match(Set mem (StoreB mem src));
4218
  ins_cost(MEMORY_REF_COST);
4219

4220
  size(4);
4221
  format %{ "STRB    $src,$mem\t! byte" %}
4222
  ins_encode %{
4223
    __ strb($src$$Register, $mem$$Address);
4224
  %}
4225
  ins_pipe(istore_mem_reg);
4226
%}
4227

4228
instruct storeCM(memoryB mem, store_RegI src) %{
4229
  match(Set mem (StoreCM mem src));
4230
  ins_cost(MEMORY_REF_COST);
4231

4232
  size(4);
4233
  format %{ "STRB    $src,$mem\t! CMS card-mark byte" %}
4234
  ins_encode %{
4235
    __ strb($src$$Register, $mem$$Address);
4236
  %}
4237
  ins_pipe(istore_mem_reg);
4238
%}
4239

4240
// Store Char/Short
4241

4242

4243
instruct storeC(memoryS mem, store_RegI src) %{
4244
  match(Set mem (StoreC mem src));
4245
  ins_cost(MEMORY_REF_COST);
4246

4247
  size(4);
4248
  format %{ "STRH    $src,$mem\t! short" %}
4249
  ins_encode %{
4250
    __ strh($src$$Register, $mem$$Address);
4251
  %}
4252
  ins_pipe(istore_mem_reg);
4253
%}
4254

4255
// Store Integer
4256

4257

4258
instruct storeI(memoryI mem, store_RegI src) %{
4259
  match(Set mem (StoreI mem src));
4260
  ins_cost(MEMORY_REF_COST);
4261

4262
  size(4);
4263
  format %{ "str_32 $src,$mem" %}
4264
  ins_encode %{
4265
    __ str_32($src$$Register, $mem$$Address);
4266
  %}
4267
  ins_pipe(istore_mem_reg);
4268
%}
4269

4270
// Store Long
4271

4272

4273
instruct storeL(memoryL mem, store_RegLd src) %{
4274
  predicate(!((StoreLNode*)n)->require_atomic_access());
4275
  match(Set mem (StoreL mem src));
4276
  ins_cost(MEMORY_REF_COST);
4277

4278
  size(4);
4279
  format %{ "str_64  $src,$mem\t! long\n\t" %}
4280

4281
  ins_encode %{
4282
    __ str_64($src$$Register, $mem$$Address);
4283
  %}
4284
  ins_pipe(istore_mem_reg);
4285
%}
4286

4287
instruct storeL_2instr(memorylong mem, iRegL src) %{
4288
  predicate(!((StoreLNode*)n)->require_atomic_access());
4289
  match(Set mem (StoreL mem src));
4290
  ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4291

4292
  size(8);
4293
  format %{ "STR    $src.lo,$mem\t! long\n\t"
4294
            "STR    $src.hi,$mem+4" %}
4295

4296
  ins_encode %{
4297
    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4298
    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4299
    __ str($src$$Register, Amemlo);
4300
    __ str($src$$Register->successor(), Amemhi);
4301
  %}
4302
  ins_pipe(istore_mem_reg);
4303
%}
4304

4305
instruct storeL_volatile(indirect mem, iRegL src) %{
4306
  predicate(((StoreLNode*)n)->require_atomic_access());
4307
  match(Set mem (StoreL mem src));
4308
  ins_cost(MEMORY_REF_COST);
4309
  size(4);
4310
  format %{ "STMIA    $src,$mem\t! long" %}
4311
  ins_encode %{
4312
    // FIXME: why is stmia considered atomic?  Should be strexd
4313
    RegisterSet set($src$$Register);
4314
    set = set | reg_to_register_object($src$$reg + 1);
4315
    __ stmia(reg_to_register_object($mem$$base), set);
4316
  %}
4317
  ins_pipe(istore_mem_reg);
4318
%}
4319

4320
instruct storeL_volatile_fp(memoryD mem, iRegL src) %{
4321
  predicate(((StoreLNode*)n)->require_atomic_access());
4322
  match(Set mem (StoreL mem src));
4323
  ins_cost(MEMORY_REF_COST);
4324
  size(8);
4325
  format %{ "FMDRR    S14, $src\t! long \n\t"
4326
            "FSTD     S14, $mem" %}
4327
  ins_encode %{
4328
    __ fmdrr(S14, $src$$Register, $src$$Register->successor());
4329
    __ fstd(S14, $mem$$Address);
4330
  %}
4331
  ins_pipe(istore_mem_reg);
4332
%}
4333

4334
#ifdef XXX
4335
// Move SP Pointer
4336
//instruct movSP(sp_ptr_RegP dst, SPRegP src) %{
4337
//instruct movSP(iRegP dst, SPRegP src) %{
4338
instruct movSP(store_ptr_RegP dst, SPRegP src) %{
4339
  match(Set dst src);
4340
//predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
4341
  ins_cost(MEMORY_REF_COST);
4342
  size(4);
4343

4344
  format %{ "MOV    $dst,$src\t! SP ptr\n\t" %}
4345
  ins_encode %{
4346
    assert(false, "XXX1 got here");
4347
    __ mov($dst$$Register, SP);
4348
    __ mov($dst$$Register, $src$$Register);
4349
  %}
4350
  ins_pipe(ialu_reg);
4351
%}
4352
#endif
4353

4354

4355
// Store Pointer
4356

4357

4358
instruct storeP(memoryP mem, store_ptr_RegP src) %{
4359
  match(Set mem (StoreP mem src));
4360
  ins_cost(MEMORY_REF_COST);
4361
  size(4);
4362

4363
  format %{ "STR    $src,$mem\t! ptr" %}
4364
  ins_encode %{
4365
    __ str($src$$Register, $mem$$Address);
4366
  %}
4367
  ins_pipe(istore_mem_spORreg);
4368
%}
4369

4370

4371
#ifdef _LP64
4372
// Store Compressed Pointer
4373

4374

4375
instruct storeN(memoryI mem, store_RegN src) %{
4376
  match(Set mem (StoreN mem src));
4377
  ins_cost(MEMORY_REF_COST);
4378
  size(4);
4379

4380
  format %{ "str_32 $src,$mem\t! compressed ptr" %}
4381
  ins_encode %{
4382
    __ str_32($src$$Register, $mem$$Address);
4383
  %}
4384
  ins_pipe(istore_mem_reg);
4385
%}
4386

4387

4388
// Store Compressed Klass Pointer
4389
instruct storeNKlass(memoryI mem, store_RegN src) %{
4390
  match(Set mem (StoreNKlass mem src));
4391
  ins_cost(MEMORY_REF_COST);
4392
  size(4);
4393

4394
  format %{ "str_32 $src,$mem\t! compressed klass ptr" %}
4395
  ins_encode %{
4396
    __ str_32($src$$Register, $mem$$Address);
4397
  %}
4398
  ins_pipe(istore_mem_reg);
4399
%}
4400
#endif
4401

4402
// Store Double
4403

4404

4405
instruct storeD(memoryD mem, regD src) %{
4406
  match(Set mem (StoreD mem src));
4407
  ins_cost(MEMORY_REF_COST);
4408

4409
  size(4);
4410
  // FIXME: needs to be atomic, but  ARMv7 A.R.M. guarantees
4411
  // only LDREXD and STREXD are 64-bit single-copy atomic
4412
  format %{ "FSTD   $src,$mem" %}
4413
  ins_encode %{
4414
    __ str_double($src$$FloatRegister, $mem$$Address);
4415
  %}
4416
  ins_pipe(fstoreD_mem_reg);
4417
%}
4418

4419

4420
// Store Float
4421

4422

4423
instruct storeF( memoryF mem, regF src) %{
4424
  match(Set mem (StoreF mem src));
4425
  ins_cost(MEMORY_REF_COST);
4426

4427
  size(4);
4428
  format %{ "FSTS    $src,$mem" %}
4429
  ins_encode %{
4430
    __ str_float($src$$FloatRegister, $mem$$Address);
4431
  %}
4432
  ins_pipe(fstoreF_mem_reg);
4433
%}
4434

4435

4436
//----------MemBar Instructions-----------------------------------------------
4437
// Memory barrier flavors
4438

4439
// pattern-match out unnecessary membars
4440
instruct membar_storestore() %{
4441
  match(MemBarStoreStore);
4442
  match(StoreStoreFence);
4443
  ins_cost(4*MEMORY_REF_COST);
4444

4445
  size(4);
4446
  format %{ "MEMBAR-storestore" %}
4447
  ins_encode %{
4448
    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
4449
  %}
4450
  ins_pipe(long_memory_op);
4451
%}
4452

4453
instruct membar_acquire() %{
4454
  match(MemBarAcquire);
4455
  match(LoadFence);
4456
  ins_cost(4*MEMORY_REF_COST);
4457

4458
  size(4);
4459
  format %{ "MEMBAR-acquire" %}
4460
  ins_encode %{
4461
    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg);
4462
  %}
4463
  ins_pipe(long_memory_op);
4464
%}
4465

4466
instruct membar_acquire_lock() %{
4467
  match(MemBarAcquireLock);
4468
  ins_cost(0);
4469

4470
  size(0);
4471
  format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %}
4472
  ins_encode( );
4473
  ins_pipe(empty);
4474
%}
4475

4476
instruct membar_release() %{
4477
  match(MemBarRelease);
4478
  match(StoreFence);
4479
  ins_cost(4*MEMORY_REF_COST);
4480

4481
  size(4);
4482
  format %{ "MEMBAR-release" %}
4483
  ins_encode %{
4484
    __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg);
4485
  %}
4486
  ins_pipe(long_memory_op);
4487
%}
4488

4489
instruct membar_release_lock() %{
4490
  match(MemBarReleaseLock);
4491
  ins_cost(0);
4492

4493
  size(0);
4494
  format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %}
4495
  ins_encode( );
4496
  ins_pipe(empty);
4497
%}
4498

4499
instruct membar_volatile() %{
4500
  match(MemBarVolatile);
4501
  ins_cost(4*MEMORY_REF_COST);
4502

4503
  size(4);
4504
  format %{ "MEMBAR-volatile" %}
4505
  ins_encode %{
4506
    __ membar(MacroAssembler::StoreLoad, noreg);
4507
  %}
4508
  ins_pipe(long_memory_op);
4509
%}
4510

4511
instruct unnecessary_membar_volatile() %{
4512
  match(MemBarVolatile);
4513
  predicate(Matcher::post_store_load_barrier(n));
4514
  ins_cost(0);
4515

4516
  size(0);
4517
  format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %}
4518
  ins_encode( );
4519
  ins_pipe(empty);
4520
%}
4521

4522
//----------Register Move Instructions-----------------------------------------
4523
// instruct roundDouble_nop(regD dst) %{
4524
//   match(Set dst (RoundDouble dst));
4525
//   ins_pipe(empty);
4526
// %}
4527

4528

4529
// instruct roundFloat_nop(regF dst) %{
4530
//   match(Set dst (RoundFloat dst));
4531
//   ins_pipe(empty);
4532
// %}
4533

4534

4535

4536
// Cast Index to Pointer for unsafe natives
4537
instruct castX2P(iRegX src, iRegP dst) %{
4538
  match(Set dst (CastX2P src));
4539

4540
  format %{ "MOV    $dst,$src\t! IntX->Ptr if $dst != $src" %}
4541
  ins_encode %{
4542
    if ($dst$$Register !=  $src$$Register) {
4543
      __ mov($dst$$Register, $src$$Register);
4544
    }
4545
  %}
4546
  ins_pipe(ialu_reg);
4547
%}
4548

4549
// Cast Pointer to Index for unsafe natives
4550
instruct castP2X(iRegP src, iRegX dst) %{
4551
  match(Set dst (CastP2X src));
4552

4553
  format %{ "MOV    $dst,$src\t! Ptr->IntX if $dst != $src" %}
4554
  ins_encode %{
4555
    if ($dst$$Register !=  $src$$Register) {
4556
      __ mov($dst$$Register, $src$$Register);
4557
    }
4558
  %}
4559
  ins_pipe(ialu_reg);
4560
%}
4561

4562
//----------Conditional Move---------------------------------------------------
4563
// Conditional move
4564
instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{
4565
  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4566
  ins_cost(150);
4567
  size(4);
4568
  format %{ "MOV$cmp  $dst,$src\t! int" %}
4569
  ins_encode %{
4570
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4571
  %}
4572
  ins_pipe(ialu_reg);
4573
%}
4574

4575

4576
instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{
4577
  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4578
  ins_cost(140);
4579
  size(4);
4580
  format %{ "MOV$cmp  $dst,$src" %}
4581
  ins_encode %{
4582
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4583
  %}
4584
  ins_pipe(ialu_imm);
4585
%}
4586

4587
instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{
4588
  match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4589
  ins_cost(140);
4590
  size(4);
4591
  format %{ "MOVw$cmp  $dst,$src" %}
4592
  ins_encode %{
4593
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4594
  %}
4595
  ins_pipe(ialu_imm);
4596
%}
4597

4598
instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{
4599
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4600
  ins_cost(150);
4601
  size(4);
4602
  format %{ "MOV$cmp  $dst,$src" %}
4603
  ins_encode %{
4604
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4605
  %}
4606
  ins_pipe(ialu_reg);
4607
%}
4608

4609

4610
instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{
4611
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4612
  ins_cost(140);
4613
  size(4);
4614
  format %{ "MOV$cmp  $dst,$src" %}
4615
  ins_encode %{
4616
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4617
  %}
4618
  ins_pipe(ialu_imm);
4619
%}
4620

4621
instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{
4622
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4623
  ins_cost(140);
4624
  size(4);
4625
  format %{ "MOVw$cmp  $dst,$src" %}
4626
  ins_encode %{
4627
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4628
  %}
4629
  ins_pipe(ialu_imm);
4630
%}
4631

4632
instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{
4633
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4634
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4635
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4636
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4637
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4638
  ins_cost(150);
4639
  size(4);
4640
  format %{ "MOV$cmp  $dst,$src" %}
4641
  ins_encode %{
4642
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4643
  %}
4644
  ins_pipe(ialu_reg);
4645
%}
4646

4647
instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{
4648
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4649
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4650
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4651
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4652
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4653
  ins_cost(140);
4654
  size(4);
4655
  format %{ "MOV$cmp  $dst,$src" %}
4656
  ins_encode %{
4657
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4658
  %}
4659
  ins_pipe(ialu_imm);
4660
%}
4661

4662
instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{
4663
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4664
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4665
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4666
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4667
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4668
  ins_cost(140);
4669
  size(4);
4670
  format %{ "MOVW$cmp  $dst,$src" %}
4671
  ins_encode %{
4672
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4673
  %}
4674
  ins_pipe(ialu_imm);
4675
%}
4676

4677
instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
4678
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4679
  ins_cost(150);
4680
  size(4);
4681
  format %{ "MOV$cmp  $dst,$src" %}
4682
  ins_encode %{
4683
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4684
  %}
4685
  ins_pipe(ialu_reg);
4686
%}
4687

4688
instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{
4689
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4690
  ins_cost(140);
4691
  size(4);
4692
  format %{ "MOV$cmp  $dst,$src" %}
4693
  ins_encode %{
4694
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4695
  %}
4696
  ins_pipe(ialu_imm);
4697
%}
4698

4699
instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{
4700
  match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4701
  ins_cost(140);
4702
  size(4);
4703
  format %{ "MOVW$cmp  $dst,$src" %}
4704
  ins_encode %{
4705
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4706
  %}
4707
  ins_pipe(ialu_imm);
4708
%}
4709

4710
// Conditional move
4711
instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
4712
  match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4713
  ins_cost(150);
4714
  size(4);
4715
  format %{ "MOV$cmp  $dst,$src" %}
4716
  ins_encode %{
4717
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4718
  %}
4719
  ins_pipe(ialu_reg);
4720
%}
4721

4722
instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{
4723
  match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
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

4733
// This instruction also works with CmpN so we don't need cmovPN_reg.
4734
instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
4735
  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4736
  ins_cost(150);
4737

4738
  size(4);
4739
  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4740
  ins_encode %{
4741
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4742
  %}
4743
  ins_pipe(ialu_reg);
4744
%}
4745

4746
instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{
4747
  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4748
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4749
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4750
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4751
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4752
  ins_cost(150);
4753

4754
  size(4);
4755
  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4756
  ins_encode %{
4757
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4758
  %}
4759
  ins_pipe(ialu_reg);
4760
%}
4761

4762
instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
4763
  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4764
  ins_cost(150);
4765

4766
  size(4);
4767
  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4768
  ins_encode %{
4769
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4770
  %}
4771
  ins_pipe(ialu_reg);
4772
%}
4773

4774
instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
4775
  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4776
  ins_cost(140);
4777

4778
  size(4);
4779
  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4780
  ins_encode %{
4781
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4782
  %}
4783
  ins_pipe(ialu_imm);
4784
%}
4785

4786
instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{
4787
  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4788
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4789
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4790
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4791
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4792
  ins_cost(140);
4793

4794
  size(4);
4795
  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4796
  ins_encode %{
4797
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4798
  %}
4799
  ins_pipe(ialu_imm);
4800
%}
4801

4802
instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
4803
  match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4804
  ins_cost(140);
4805

4806
  size(4);
4807
  format %{ "MOV$cmp  $dst,$src\t! ptr" %}
4808
  ins_encode %{
4809
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4810
  %}
4811
  ins_pipe(ialu_imm);
4812
%}
4813

4814

4815
// Conditional move
4816
instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{
4817
  match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src)));
4818
  ins_cost(150);
4819
  size(4);
4820
  format %{ "FCPYS$cmp $dst,$src" %}
4821
  ins_encode %{
4822
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4823
  %}
4824
  ins_pipe(int_conditional_float_move);
4825
%}
4826

4827
instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
4828
  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4829
  ins_cost(150);
4830

4831
  size(4);
4832
  format %{ "FCPYS$cmp $dst,$src" %}
4833
  ins_encode %{
4834
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4835
  %}
4836
  ins_pipe(int_conditional_float_move);
4837
%}
4838

4839
instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{
4840
  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4841
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4842
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4843
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4844
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4845
  ins_cost(150);
4846

4847
  size(4);
4848
  format %{ "FCPYS$cmp $dst,$src" %}
4849
  ins_encode %{
4850
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4851
  %}
4852
  ins_pipe(int_conditional_float_move);
4853
%}
4854

4855
instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
4856
  match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4857
  ins_cost(150);
4858

4859
  size(4);
4860
  format %{ "FCPYS$cmp $dst,$src" %}
4861
  ins_encode %{
4862
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4863
  %}
4864
  ins_pipe(int_conditional_float_move);
4865
%}
4866

4867
// Conditional move
4868
instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{
4869
  match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src)));
4870
  ins_cost(150);
4871
  size(4);
4872
  format %{ "FCPYD$cmp $dst,$src" %}
4873
  ins_encode %{
4874
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4875
  %}
4876
  ins_pipe(int_conditional_double_move);
4877
%}
4878

4879
instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
4880
  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4881
  ins_cost(150);
4882

4883
  size(4);
4884
  format %{ "FCPYD$cmp $dst,$src" %}
4885
  ins_encode %{
4886
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4887
  %}
4888
  ins_pipe(int_conditional_double_move);
4889
%}
4890

4891
instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{
4892
  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4893
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4894
  ins_cost(150);
4895

4896
  size(4);
4897
  format %{ "FCPYD$cmp $dst,$src" %}
4898
  ins_encode %{
4899
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4900
  %}
4901
  ins_pipe(int_conditional_double_move);
4902
%}
4903

4904
instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
4905
  match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4906
  ins_cost(150);
4907

4908
  size(4);
4909
  format %{ "FCPYD$cmp $dst,$src" %}
4910
  ins_encode %{
4911
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4912
  %}
4913
  ins_pipe(int_conditional_double_move);
4914
%}
4915

4916
// Conditional move
4917
instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{
4918
  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4919
  ins_cost(150);
4920

4921
  size(8);
4922
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
4923
            "MOV$cmp  $dst.hi,$src.hi" %}
4924
  ins_encode %{
4925
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4926
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4927
  %}
4928
  ins_pipe(ialu_reg);
4929
%}
4930

4931
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
4932
// (hi($con$$constant), lo($con$$constant)) becomes
4933
instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{
4934
  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4935
  ins_cost(140);
4936

4937
  size(8);
4938
  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
4939
            "MOV$cmp  $dst.hi,0" %}
4940
  ins_encode %{
4941
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4942
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4943
  %}
4944
  ins_pipe(ialu_imm);
4945
%}
4946

4947
instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{
4948
  match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4949
  ins_cost(140);
4950

4951
  size(8);
4952
  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
4953
            "MOV$cmp  $dst.hi,0" %}
4954
  ins_encode %{
4955
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4956
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4957
  %}
4958
  ins_pipe(ialu_imm);
4959
%}
4960

4961
instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
4962
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4963
  ins_cost(150);
4964

4965
  size(8);
4966
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
4967
            "MOV$cmp  $dst.hi,$src.hi" %}
4968
  ins_encode %{
4969
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4970
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4971
  %}
4972
  ins_pipe(ialu_reg);
4973
%}
4974

4975
instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{
4976
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4977
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4978
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4979
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4980
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4981
  ins_cost(150);
4982

4983
  size(8);
4984
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
4985
            "MOV$cmp  $dst.hi,$src.hi" %}
4986
  ins_encode %{
4987
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4988
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4989
  %}
4990
  ins_pipe(ialu_reg);
4991
%}
4992

4993
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
4994
// (hi($con$$constant), lo($con$$constant)) becomes
4995
instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{
4996
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4997
  ins_cost(140);
4998

4999
  size(8);
5000
  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5001
            "MOV$cmp  $dst.hi,0" %}
5002
  ins_encode %{
5003
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5004
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5005
  %}
5006
  ins_pipe(ialu_imm);
5007
%}
5008

5009
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5010
// (hi($con$$constant), lo($con$$constant)) becomes
5011
instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{
5012
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5013
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5014
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5015
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5016
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5017
  ins_cost(140);
5018

5019
  size(8);
5020
  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5021
            "MOV$cmp  $dst.hi,0" %}
5022
  ins_encode %{
5023
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5024
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5025
  %}
5026
  ins_pipe(ialu_imm);
5027
%}
5028

5029
instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{
5030
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5031
  ins_cost(140);
5032

5033
  size(8);
5034
  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5035
            "MOV$cmp  $dst.hi,0" %}
5036
  ins_encode %{
5037
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5038
    __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5039
  %}
5040
  ins_pipe(ialu_imm);
5041
%}
5042

5043
instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{
5044
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5045
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
5046
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
5047
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5048
            _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5049
  ins_cost(140);
5050

5051
  size(8);
5052
  format %{ "MOV$cmp  $dst.lo,$src\t! long\n\t"
5053
            "MOV$cmp  $dst.hi,0" %}
5054
  ins_encode %{
5055
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5056
    __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5057
  %}
5058
  ins_pipe(ialu_imm);
5059
%}
5060

5061
instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
5062
  match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5063
  ins_cost(150);
5064

5065
  size(8);
5066
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
5067
            "MOV$cmp  $dst.hi,$src.hi" %}
5068
  ins_encode %{
5069
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5070
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5071
  %}
5072
  ins_pipe(ialu_reg);
5073
%}
5074

5075

5076
//----------OS and Locking Instructions----------------------------------------
5077

5078
// This name is KNOWN by the ADLC and cannot be changed.
5079
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
5080
// for this guy.
5081
instruct tlsLoadP(RthreadRegP dst) %{
5082
  match(Set dst (ThreadLocal));
5083

5084
  size(0);
5085
  ins_cost(0);
5086
  format %{ "! TLS is in $dst" %}
5087
  ins_encode( /*empty encoding*/ );
5088
  ins_pipe(ialu_none);
5089
%}
5090

5091
instruct checkCastPP( iRegP dst ) %{
5092
  match(Set dst (CheckCastPP dst));
5093

5094
  size(0);
5095
  format %{ "! checkcastPP of $dst" %}
5096
  ins_encode( /*empty encoding*/ );
5097
  ins_pipe(empty);
5098
%}
5099

5100

5101
instruct castPP( iRegP dst ) %{
5102
  match(Set dst (CastPP dst));
5103
  format %{ "! castPP of $dst" %}
5104
  ins_encode( /*empty encoding*/ );
5105
  ins_pipe(empty);
5106
%}
5107

5108
instruct castII( iRegI dst ) %{
5109
  match(Set dst (CastII dst));
5110
  format %{ "! castII of $dst" %}
5111
  ins_encode( /*empty encoding*/ );
5112
  ins_cost(0);
5113
  ins_pipe(empty);
5114
%}
5115

5116
instruct castLL( iRegL dst ) %{
5117
  match(Set dst (CastLL dst));
5118
  format %{ "! castLL of $dst" %}
5119
  ins_encode( /*empty encoding*/ );
5120
  ins_cost(0);
5121
  ins_pipe(empty);
5122
%}
5123

5124
instruct castFF( regF dst ) %{
5125
  match(Set dst (CastFF dst));
5126
  format %{ "! castFF of $dst" %}
5127
  ins_encode( /*empty encoding*/ );
5128
  ins_cost(0);
5129
  ins_pipe(empty);
5130
%}
5131

5132
instruct castDD( regD dst ) %{
5133
  match(Set dst (CastDD dst));
5134
  format %{ "! castDD of $dst" %}
5135
  ins_encode( /*empty encoding*/ );
5136
  ins_cost(0);
5137
  ins_pipe(empty);
5138
%}
5139

5140
instruct castVVD( vecD dst ) %{
5141
  match(Set dst (CastVV dst));
5142
  format %{ "! castVV of $dst" %}
5143
  ins_encode( /*empty encoding*/ );
5144
  ins_cost(0);
5145
  ins_pipe(empty);
5146
%}
5147

5148
instruct castVVX( vecX dst ) %{
5149
  match(Set dst (CastVV dst));
5150
  format %{ "! castVV of $dst" %}
5151
  ins_encode( /*empty encoding*/ );
5152
  ins_cost(0);
5153
  ins_pipe(empty);
5154
%}
5155

5156

5157
//----------Arithmetic Instructions--------------------------------------------
5158
// Addition Instructions
5159
// Register Addition
5160
instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5161
  match(Set dst (AddI src1 src2));
5162

5163
  size(4);
5164
  format %{ "add_32 $dst,$src1,$src2\t! int" %}
5165
  ins_encode %{
5166
    __ add_32($dst$$Register, $src1$$Register, $src2$$Register);
5167
  %}
5168
  ins_pipe(ialu_reg_reg);
5169
%}
5170

5171
instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5172
  match(Set dst (AddI (LShiftI src1 src2) src3));
5173

5174
  size(4);
5175
  format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5176
  ins_encode %{
5177
    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5178
  %}
5179
  ins_pipe(ialu_reg_reg);
5180
%}
5181

5182

5183
instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5184
  match(Set dst (AddI (LShiftI src1 src2) src3));
5185

5186
  size(4);
5187
  format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5188
  ins_encode %{
5189
    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5190
  %}
5191
  ins_pipe(ialu_reg_reg);
5192
%}
5193

5194
instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5195
  match(Set dst (AddI (RShiftI src1 src2) src3));
5196

5197
  size(4);
5198
  format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5199
  ins_encode %{
5200
    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5201
  %}
5202
  ins_pipe(ialu_reg_reg);
5203
%}
5204

5205
instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5206
  match(Set dst (AddI (RShiftI src1 src2) src3));
5207

5208
  size(4);
5209
  format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5210
  ins_encode %{
5211
    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5212
  %}
5213
  ins_pipe(ialu_reg_reg);
5214
%}
5215

5216
instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5217
  match(Set dst (AddI (URShiftI src1 src2) src3));
5218

5219
  size(4);
5220
  format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5221
  ins_encode %{
5222
    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5223
  %}
5224
  ins_pipe(ialu_reg_reg);
5225
%}
5226

5227
instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5228
  match(Set dst (AddI (URShiftI src1 src2) src3));
5229

5230
  size(4);
5231
  format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5232
  ins_encode %{
5233
    __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5234
  %}
5235
  ins_pipe(ialu_reg_reg);
5236
%}
5237

5238
// Immediate Addition
5239
instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5240
  match(Set dst (AddI src1 src2));
5241

5242
  size(4);
5243
  format %{ "add_32 $dst,$src1,$src2\t! int" %}
5244
  ins_encode %{
5245
    __ add_32($dst$$Register, $src1$$Register, $src2$$constant);
5246
  %}
5247
  ins_pipe(ialu_reg_imm);
5248
%}
5249

5250
// Pointer Register Addition
5251
instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{
5252
  match(Set dst (AddP src1 src2));
5253

5254
  size(4);
5255
  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
5256
  ins_encode %{
5257
    __ add($dst$$Register, $src1$$Register, $src2$$Register);
5258
  %}
5259
  ins_pipe(ialu_reg_reg);
5260
%}
5261

5262

5263
// shifted iRegX operand
5264
operand shiftedX(iRegX src2, shimmX src3) %{
5265
//constraint(ALLOC_IN_RC(sp_ptr_reg));
5266
  match(LShiftX src2 src3);
5267

5268
  op_cost(1);
5269
  format %{ "$src2 << $src3" %}
5270
  interface(MEMORY_INTER) %{
5271
    base($src2);
5272
    index(0xff);
5273
    scale($src3);
5274
    disp(0x0);
5275
  %}
5276
%}
5277

5278
instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{
5279
  match(Set dst (AddP src1 src2));
5280

5281
  ins_cost(DEFAULT_COST * 3/2);
5282
  size(4);
5283
  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
5284
  ins_encode %{
5285
    Register base = reg_to_register_object($src2$$base);
5286
    __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale));
5287
  %}
5288
  ins_pipe(ialu_reg_reg);
5289
%}
5290

5291
// Pointer Immediate Addition
5292
instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{
5293
  match(Set dst (AddP src1 src2));
5294

5295
  size(4);
5296
  format %{ "ADD    $dst,$src1,$src2\t! ptr" %}
5297
  ins_encode %{
5298
    __ add($dst$$Register, $src1$$Register, $src2$$constant);
5299
  %}
5300
  ins_pipe(ialu_reg_imm);
5301
%}
5302

5303
// Long Addition
5304
instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{
5305
  match(Set dst (AddL src1 src2));
5306
  effect(KILL ccr);
5307
  size(8);
5308
  format %{ "ADDS    $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5309
            "ADC     $dst.hi,$src1.hi,$src2.hi" %}
5310
  ins_encode %{
5311
    __ adds($dst$$Register, $src1$$Register, $src2$$Register);
5312
    __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5313
  %}
5314
  ins_pipe(ialu_reg_reg);
5315
%}
5316

5317
// TODO
5318

5319
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5320
// (hi($con$$constant), lo($con$$constant)) becomes
5321
instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
5322
  match(Set dst (AddL src1 con));
5323
  effect(KILL ccr);
5324
  size(8);
5325
  format %{ "ADDS    $dst.lo,$src1.lo,$con\t! long\n\t"
5326
            "ADC     $dst.hi,$src1.hi,0" %}
5327
  ins_encode %{
5328
    __ adds($dst$$Register, $src1$$Register, $con$$constant);
5329
    __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5330
  %}
5331
  ins_pipe(ialu_reg_imm);
5332
%}
5333

5334
// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
5335

5336
instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
5337
  match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5338
  effect( KILL ccr, TEMP tmp);
5339
  size(32);
5340
  format %{ "loop: \n\t"
5341
            "LDREXD   $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5342
            "CMP      $tmp.lo, $oldval.lo\n\t"
5343
            "CMP.eq   $tmp.hi, $oldval.hi\n\t"
5344
            "STREXD.eq $tmp, $newval, $mem\n\t"
5345
            "MOV.ne   $tmp, 0 \n\t"
5346
            "XORS.eq  $tmp,$tmp, 1 \n\t"
5347
            "B.eq     loop \n\t"
5348
            "MOV      $res, $tmp" %}
5349
  ins_encode %{
5350
    Label loop;
5351
    __ bind(loop);
5352
    __ ldrexd($tmp$$Register, $mem$$Address);
5353
    __ cmp($tmp$$Register, $oldval$$Register);
5354
    __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq);
5355
    __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5356
    __ mov($tmp$$Register, 0, ne);
5357
    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5358
    __ b(loop, eq);
5359
    __ mov($res$$Register, $tmp$$Register);
5360
  %}
5361
  ins_pipe( long_memory_op );
5362
%}
5363

5364

5365
instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5366
  match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5367
  effect( KILL ccr, TEMP tmp);
5368
  size(28);
5369
  format %{ "loop: \n\t"
5370
            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5371
            "CMP      $tmp, $oldval\n\t"
5372
            "STREX.eq $tmp, $newval, $mem\n\t"
5373
            "MOV.ne   $tmp, 0 \n\t"
5374
            "XORS.eq  $tmp,$tmp, 1 \n\t"
5375
            "B.eq     loop \n\t"
5376
            "MOV      $res, $tmp" %}
5377

5378
  ins_encode %{
5379
    Label loop;
5380
    __ bind(loop);
5381
    __ ldrex($tmp$$Register,$mem$$Address);
5382
    __ cmp($tmp$$Register, $oldval$$Register);
5383
    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5384
    __ mov($tmp$$Register, 0, ne);
5385
    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5386
    __ b(loop, eq);
5387
    __ mov($res$$Register, $tmp$$Register);
5388
  %}
5389
  ins_pipe( long_memory_op );
5390
%}
5391

5392
instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5393
  match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5394
  effect( KILL ccr, TEMP tmp);
5395
  size(28);
5396
  format %{ "loop: \n\t"
5397
            "LDREX    $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5398
            "CMP      $tmp, $oldval\n\t"
5399
            "STREX.eq $tmp, $newval, $mem\n\t"
5400
            "MOV.ne   $tmp, 0 \n\t"
5401
            "EORS.eq  $tmp,$tmp, 1 \n\t"
5402
            "B.eq     loop \n\t"
5403
            "MOV      $res, $tmp" %}
5404

5405
  ins_encode %{
5406
    Label loop;
5407
    __ bind(loop);
5408
    __ ldrex($tmp$$Register,$mem$$Address);
5409
    __ cmp($tmp$$Register, $oldval$$Register);
5410
    __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5411
    __ mov($tmp$$Register, 0, ne);
5412
    __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5413
    __ b(loop, eq);
5414
    __ mov($res$$Register, $tmp$$Register);
5415
  %}
5416
  ins_pipe( long_memory_op );
5417
%}
5418

5419
instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5420
  predicate(n->as_LoadStore()->result_not_used());
5421
  match(Set dummy (GetAndAddI mem add));
5422
  effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5423
  size(20);
5424
  format %{ "loop: \n\t"
5425
            "LDREX    $tmp1, $mem\n\t"
5426
            "ADD      $tmp1, $tmp1, $add\n\t"
5427
            "STREX    $tmp2, $tmp1, $mem\n\t"
5428
            "CMP      $tmp2, 0 \n\t"
5429
            "B.ne     loop \n\t" %}
5430

5431
  ins_encode %{
5432
    Label loop;
5433
    __ bind(loop);
5434
    __ ldrex($tmp1$$Register,$mem$$Address);
5435
    __ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
5436
    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5437
    __ cmp($tmp2$$Register, 0);
5438
    __ b(loop, ne);
5439
  %}
5440
  ins_pipe( long_memory_op );
5441
%}
5442

5443
instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5444
  predicate(n->as_LoadStore()->result_not_used());
5445
  match(Set dummy (GetAndAddI mem add));
5446
  effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5447
  size(20);
5448
  format %{ "loop: \n\t"
5449
            "LDREX    $tmp1, $mem\n\t"
5450
            "ADD      $tmp1, $tmp1, $add\n\t"
5451
            "STREX    $tmp2, $tmp1, $mem\n\t"
5452
            "CMP      $tmp2, 0 \n\t"
5453
            "B.ne     loop \n\t" %}
5454

5455
  ins_encode %{
5456
    Label loop;
5457
    __ bind(loop);
5458
    __ ldrex($tmp1$$Register,$mem$$Address);
5459
    __ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
5460
    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5461
    __ cmp($tmp2$$Register, 0);
5462
    __ b(loop, ne);
5463
  %}
5464
  ins_pipe( long_memory_op );
5465
%}
5466

5467
instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5468
  match(Set res (GetAndAddI mem add));
5469
  effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5470
  size(20);
5471
  format %{ "loop: \n\t"
5472
            "LDREX    $res, $mem\n\t"
5473
            "ADD      $tmp1, $res, $add\n\t"
5474
            "STREX    $tmp2, $tmp1, $mem\n\t"
5475
            "CMP      $tmp2, 0 \n\t"
5476
            "B.ne     loop \n\t" %}
5477

5478
  ins_encode %{
5479
    Label loop;
5480
    __ bind(loop);
5481
    __ ldrex($res$$Register,$mem$$Address);
5482
    __ add($tmp1$$Register, $res$$Register, $add$$constant);
5483
    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5484
    __ cmp($tmp2$$Register, 0);
5485
    __ b(loop, ne);
5486
  %}
5487
  ins_pipe( long_memory_op );
5488
%}
5489

5490
instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5491
  match(Set res (GetAndAddI mem add));
5492
  effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5493
  size(20);
5494
  format %{ "loop: \n\t"
5495
            "LDREX    $res, $mem\n\t"
5496
            "ADD      $tmp1, $res, $add\n\t"
5497
            "STREX    $tmp2, $tmp1, $mem\n\t"
5498
            "CMP      $tmp2, 0 \n\t"
5499
            "B.ne     loop \n\t" %}
5500

5501
  ins_encode %{
5502
    Label loop;
5503
    __ bind(loop);
5504
    __ ldrex($res$$Register,$mem$$Address);
5505
    __ add($tmp1$$Register, $res$$Register, $add$$Register);
5506
    __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5507
    __ cmp($tmp2$$Register, 0);
5508
    __ b(loop, ne);
5509
  %}
5510
  ins_pipe( long_memory_op );
5511
%}
5512

5513
instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5514
  predicate(n->as_LoadStore()->result_not_used());
5515
  match(Set dummy (GetAndAddL mem add));
5516
  effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5517
  size(24);
5518
  format %{ "loop: \n\t"
5519
            "LDREXD   $tmp1, $mem\n\t"
5520
            "ADDS     $tmp1.lo, $tmp1.lo, $add.lo\n\t"
5521
            "ADC      $tmp1.hi, $tmp1.hi, $add.hi\n\t"
5522
            "STREXD   $tmp2, $tmp1, $mem\n\t"
5523
            "CMP      $tmp2, 0 \n\t"
5524
            "B.ne     loop \n\t" %}
5525

5526
  ins_encode %{
5527
    Label loop;
5528
    __ bind(loop);
5529
    __ ldrexd($tmp1$$Register, $mem$$Address);
5530
    __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register);
5531
    __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor());
5532
    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5533
    __ cmp($tmp2$$Register, 0);
5534
    __ b(loop, ne);
5535
  %}
5536
  ins_pipe( long_memory_op );
5537
%}
5538

5539
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5540
// (hi($con$$constant), lo($con$$constant)) becomes
5541
instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5542
  predicate(n->as_LoadStore()->result_not_used());
5543
  match(Set dummy (GetAndAddL mem add));
5544
  effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5545
  size(24);
5546
  format %{ "loop: \n\t"
5547
            "LDREXD   $tmp1, $mem\n\t"
5548
            "ADDS     $tmp1.lo, $tmp1.lo, $add\n\t"
5549
            "ADC      $tmp1.hi, $tmp1.hi, 0\n\t"
5550
            "STREXD   $tmp2, $tmp1, $mem\n\t"
5551
            "CMP      $tmp2, 0 \n\t"
5552
            "B.ne     loop \n\t" %}
5553

5554
  ins_encode %{
5555
    Label loop;
5556
    __ bind(loop);
5557
    __ ldrexd($tmp1$$Register, $mem$$Address);
5558
    __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant);
5559
    __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0);
5560
    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5561
    __ cmp($tmp2$$Register, 0);
5562
    __ b(loop, ne);
5563
  %}
5564
  ins_pipe( long_memory_op );
5565
%}
5566

5567
instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5568
  match(Set res (GetAndAddL mem add));
5569
  effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5570
  size(24);
5571
  format %{ "loop: \n\t"
5572
            "LDREXD   $res, $mem\n\t"
5573
            "ADDS     $tmp1.lo, $res.lo, $add.lo\n\t"
5574
            "ADC      $tmp1.hi, $res.hi, $add.hi\n\t"
5575
            "STREXD   $tmp2, $tmp1, $mem\n\t"
5576
            "CMP      $tmp2, 0 \n\t"
5577
            "B.ne     loop \n\t" %}
5578

5579
  ins_encode %{
5580
    Label loop;
5581
    __ bind(loop);
5582
    __ ldrexd($res$$Register, $mem$$Address);
5583
    __ adds($tmp1$$Register, $res$$Register, $add$$Register);
5584
    __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor());
5585
    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5586
    __ cmp($tmp2$$Register, 0);
5587
    __ b(loop, ne);
5588
  %}
5589
  ins_pipe( long_memory_op );
5590
%}
5591

5592
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5593
// (hi($con$$constant), lo($con$$constant)) becomes
5594
instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5595
  match(Set res (GetAndAddL mem add));
5596
  effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5597
  size(24);
5598
  format %{ "loop: \n\t"
5599
            "LDREXD   $res, $mem\n\t"
5600
            "ADDS     $tmp1.lo, $res.lo, $add\n\t"
5601
            "ADC      $tmp1.hi, $res.hi, 0\n\t"
5602
            "STREXD   $tmp2, $tmp1, $mem\n\t"
5603
            "CMP      $tmp2, 0 \n\t"
5604
            "B.ne     loop \n\t" %}
5605

5606
  ins_encode %{
5607
    Label loop;
5608
    __ bind(loop);
5609
    __ ldrexd($res$$Register, $mem$$Address);
5610
    __ adds($tmp1$$Register, $res$$Register, $add$$constant);
5611
    __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0);
5612
    __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5613
    __ cmp($tmp2$$Register, 0);
5614
    __ b(loop, ne);
5615
  %}
5616
  ins_pipe( long_memory_op );
5617
%}
5618

5619
instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
5620
  match(Set res (GetAndSetI mem newval));
5621
  effect(KILL ccr, TEMP tmp, TEMP res);
5622
  size(16);
5623
  format %{ "loop: \n\t"
5624
            "LDREX    $res, $mem\n\t"
5625
            "STREX    $tmp, $newval, $mem\n\t"
5626
            "CMP      $tmp, 0 \n\t"
5627
            "B.ne     loop \n\t" %}
5628

5629
  ins_encode %{
5630
    Label loop;
5631
    __ bind(loop);
5632
    __ ldrex($res$$Register,$mem$$Address);
5633
    __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5634
    __ cmp($tmp$$Register, 0);
5635
    __ b(loop, ne);
5636
  %}
5637
  ins_pipe( long_memory_op );
5638
%}
5639

5640
instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{
5641
  match(Set res (GetAndSetL mem newval));
5642
  effect( KILL ccr, TEMP tmp, TEMP res);
5643
  size(16);
5644
  format %{ "loop: \n\t"
5645
            "LDREXD   $res, $mem\n\t"
5646
            "STREXD   $tmp, $newval, $mem\n\t"
5647
            "CMP      $tmp, 0 \n\t"
5648
            "B.ne     loop \n\t" %}
5649

5650
  ins_encode %{
5651
    Label loop;
5652
    __ bind(loop);
5653
    __ ldrexd($res$$Register, $mem$$Address);
5654
    __ strexd($tmp$$Register, $newval$$Register, $mem$$Address);
5655
    __ cmp($tmp$$Register, 0);
5656
    __ b(loop, ne);
5657
  %}
5658
  ins_pipe( long_memory_op );
5659
%}
5660

5661
instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{
5662
  match(Set res (GetAndSetP mem newval));
5663
  effect(KILL ccr, TEMP tmp, TEMP res);
5664
  size(16);
5665
  format %{ "loop: \n\t"
5666
            "LDREX    $res, $mem\n\t"
5667
            "STREX    $tmp, $newval, $mem\n\t"
5668
            "CMP      $tmp, 0 \n\t"
5669
            "B.ne     loop \n\t" %}
5670

5671
  ins_encode %{
5672
    Label loop;
5673
    __ bind(loop);
5674
    __ ldrex($res$$Register,$mem$$Address);
5675
    __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5676
    __ cmp($tmp$$Register, 0);
5677
    __ b(loop, ne);
5678
  %}
5679
  ins_pipe( long_memory_op );
5680
%}
5681

5682
//---------------------
5683
// Subtraction Instructions
5684
// Register Subtraction
5685
instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5686
  match(Set dst (SubI src1 src2));
5687

5688
  size(4);
5689
  format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5690
  ins_encode %{
5691
    __ sub_32($dst$$Register, $src1$$Register, $src2$$Register);
5692
  %}
5693
  ins_pipe(ialu_reg_reg);
5694
%}
5695

5696
instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5697
  match(Set dst (SubI src1 (LShiftI src2 src3)));
5698

5699
  size(4);
5700
  format %{ "SUB    $dst,$src1,$src2<<$src3" %}
5701
  ins_encode %{
5702
    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
5703
  %}
5704
  ins_pipe(ialu_reg_reg);
5705
%}
5706

5707
instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5708
  match(Set dst (SubI src1 (LShiftI src2 src3)));
5709

5710
  size(4);
5711
  format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %}
5712
  ins_encode %{
5713
    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
5714
  %}
5715
  ins_pipe(ialu_reg_reg);
5716
%}
5717

5718
instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5719
  match(Set dst (SubI src1 (RShiftI src2 src3)));
5720

5721
  size(4);
5722
  format %{ "SUB    $dst,$src1,$src2>>$src3" %}
5723
  ins_encode %{
5724
    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
5725
  %}
5726
  ins_pipe(ialu_reg_reg);
5727
%}
5728

5729
instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5730
  match(Set dst (SubI src1 (RShiftI src2 src3)));
5731

5732
  size(4);
5733
  format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %}
5734
  ins_encode %{
5735
    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
5736
  %}
5737
  ins_pipe(ialu_reg_reg);
5738
%}
5739

5740
instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5741
  match(Set dst (SubI src1 (URShiftI src2 src3)));
5742

5743
  size(4);
5744
  format %{ "SUB    $dst,$src1,$src2>>>$src3" %}
5745
  ins_encode %{
5746
    __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
5747
  %}
5748
  ins_pipe(ialu_reg_reg);
5749
%}
5750

5751
instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5752
  match(Set dst (SubI src1 (URShiftI src2 src3)));
5753

5754
  size(4);
5755
  format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %}
5756
  ins_encode %{
5757
    __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
5758
  %}
5759
  ins_pipe(ialu_reg_reg);
5760
%}
5761

5762
instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5763
  match(Set dst (SubI (LShiftI src1 src2) src3));
5764

5765
  size(4);
5766
  format %{ "RSB    $dst,$src3,$src1<<$src2" %}
5767
  ins_encode %{
5768
    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5769
  %}
5770
  ins_pipe(ialu_reg_reg);
5771
%}
5772

5773
instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5774
  match(Set dst (SubI (LShiftI src1 src2) src3));
5775

5776
  size(4);
5777
  format %{ "RSB    $dst,$src3,$src1<<$src2" %}
5778
  ins_encode %{
5779
    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5780
  %}
5781
  ins_pipe(ialu_reg_reg);
5782
%}
5783

5784
instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5785
  match(Set dst (SubI (RShiftI src1 src2) src3));
5786

5787
  size(4);
5788
  format %{ "RSB    $dst,$src3,$src1>>$src2" %}
5789
  ins_encode %{
5790
    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5791
  %}
5792
  ins_pipe(ialu_reg_reg);
5793
%}
5794

5795
instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5796
  match(Set dst (SubI (RShiftI src1 src2) src3));
5797

5798
  size(4);
5799
  format %{ "RSB    $dst,$src3,$src1>>$src2" %}
5800
  ins_encode %{
5801
    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5802
  %}
5803
  ins_pipe(ialu_reg_reg);
5804
%}
5805

5806
instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5807
  match(Set dst (SubI (URShiftI src1 src2) src3));
5808

5809
  size(4);
5810
  format %{ "RSB    $dst,$src3,$src1>>>$src2" %}
5811
  ins_encode %{
5812
    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5813
  %}
5814
  ins_pipe(ialu_reg_reg);
5815
%}
5816

5817
instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5818
  match(Set dst (SubI (URShiftI src1 src2) src3));
5819

5820
  size(4);
5821
  format %{ "RSB    $dst,$src3,$src1>>>$src2" %}
5822
  ins_encode %{
5823
    __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5824
  %}
5825
  ins_pipe(ialu_reg_reg);
5826
%}
5827

5828
// Immediate Subtraction
5829
instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5830
  match(Set dst (SubI src1 src2));
5831

5832
  size(4);
5833
  format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5834
  ins_encode %{
5835
    __ sub_32($dst$$Register, $src1$$Register, $src2$$constant);
5836
  %}
5837
  ins_pipe(ialu_reg_imm);
5838
%}
5839

5840
instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{
5841
  match(Set dst (AddI src1 src2));
5842

5843
  size(4);
5844
  format %{ "sub_32 $dst,$src1,-($src2)\t! int" %}
5845
  ins_encode %{
5846
    __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant);
5847
  %}
5848
  ins_pipe(ialu_reg_imm);
5849
%}
5850

5851
instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{
5852
  match(Set dst (SubI src1 src2));
5853

5854
  size(4);
5855
  format %{ "RSB    $dst,$src2,src1" %}
5856
  ins_encode %{
5857
    __ rsb($dst$$Register, $src2$$Register, $src1$$constant);
5858
  %}
5859
  ins_pipe(ialu_zero_reg);
5860
%}
5861

5862
// Register Subtraction
5863
instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{
5864
  match(Set dst (SubL src1 src2));
5865
  effect (KILL icc);
5866

5867
  size(8);
5868
  format %{ "SUBS   $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5869
            "SBC    $dst.hi,$src1.hi,$src2.hi" %}
5870
  ins_encode %{
5871
    __ subs($dst$$Register, $src1$$Register, $src2$$Register);
5872
    __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5873
  %}
5874
  ins_pipe(ialu_reg_reg);
5875
%}
5876

5877
// TODO
5878

5879
// Immediate Subtraction
5880
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
5881
// (hi($con$$constant), lo($con$$constant)) becomes
5882
instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{
5883
  match(Set dst (SubL src1 con));
5884
  effect (KILL icc);
5885

5886
  size(8);
5887
  format %{ "SUB    $dst.lo,$src1.lo,$con\t! long\n\t"
5888
            "SBC    $dst.hi,$src1.hi,0" %}
5889
  ins_encode %{
5890
    __ subs($dst$$Register, $src1$$Register, $con$$constant);
5891
    __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5892
  %}
5893
  ins_pipe(ialu_reg_imm);
5894
%}
5895

5896
// Long negation
5897
instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{
5898
  match(Set dst (SubL zero src2));
5899
  effect (KILL icc);
5900

5901
  size(8);
5902
  format %{ "RSBS   $dst.lo,$src2.lo,0\t! long\n\t"
5903
            "RSC    $dst.hi,$src2.hi,0" %}
5904
  ins_encode %{
5905
    __ rsbs($dst$$Register, $src2$$Register, 0);
5906
    __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0);
5907
  %}
5908
  ins_pipe(ialu_zero_reg);
5909
%}
5910

5911
// Multiplication Instructions
5912
// Integer Multiplication
5913
// Register Multiplication
5914
instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5915
  match(Set dst (MulI src1 src2));
5916

5917
  size(4);
5918
  format %{ "mul_32 $dst,$src1,$src2" %}
5919
  ins_encode %{
5920
    __ mul_32($dst$$Register, $src1$$Register, $src2$$Register);
5921
  %}
5922
  ins_pipe(imul_reg_reg);
5923
%}
5924

5925
instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{
5926
  effect(DEF dst, USE src1, USE src2);
5927
  size(4);
5928
  format %{ "MUL  $dst.hi,$src1.lo,$src2.hi\t! long" %}
5929
  ins_encode %{
5930
    __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor());
5931
  %}
5932
  ins_pipe(imul_reg_reg);
5933
%}
5934

5935
instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5936
  effect(USE_DEF dst, USE src1, USE src2);
5937
  size(8);
5938
  format %{ "MLA  $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t"
5939
            "MOV  $dst.lo, 0"%}
5940
  ins_encode %{
5941
    __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor());
5942
    __ mov($dst$$Register, 0);
5943
  %}
5944
  ins_pipe(imul_reg_reg);
5945
%}
5946

5947
instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5948
  effect(USE_DEF dst, USE src1, USE src2);
5949
  size(4);
5950
  format %{ "UMLAL  $dst.lo,$dst.hi,$src1,$src2\t! long" %}
5951
  ins_encode %{
5952
    __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register);
5953
  %}
5954
  ins_pipe(imul_reg_reg);
5955
%}
5956

5957
instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
5958
  match(Set dst (MulL src1 src2));
5959

5960
  expand %{
5961
    mulL_lo1_hi2(dst, src1, src2);
5962
    mulL_hi1_lo2(dst, src1, src2);
5963
    mulL_lo1_lo2(dst, src1, src2);
5964
  %}
5965
%}
5966

5967
// Integer Division
5968
// Register Division
5969
instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{
5970
  match(Set dst (DivI src1 src2));
5971
  effect( KILL ccr, KILL src1, KILL src2, KILL lr);
5972
  ins_cost((2+71)*DEFAULT_COST);
5973

5974
  format %{ "DIV   $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %}
5975
  ins_encode %{
5976
    __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
5977
  %}
5978
  ins_pipe(sdiv_reg_reg);
5979
%}
5980

5981
// Register Long Division
5982
instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
5983
  match(Set dst (DivL src1 src2));
5984
  effect(CALL);
5985
  ins_cost(DEFAULT_COST*71);
5986
  format %{ "DIVL  $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %}
5987
  ins_encode %{
5988
    address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv);
5989
    __ call(target, relocInfo::runtime_call_type);
5990
  %}
5991
  ins_pipe(divL_reg_reg);
5992
%}
5993

5994
// Integer Remainder
5995
// Register Remainder
5996
instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{
5997
  match(Set dst (ModI src1 src2));
5998
  effect( KILL ccr, KILL temp, KILL src2, KILL lr);
5999

6000
  format %{ "MODI   $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %}
6001
  ins_encode %{
6002
    __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
6003
  %}
6004
  ins_pipe(sdiv_reg_reg);
6005
%}
6006

6007
// Register Long Remainder
6008
instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
6009
  match(Set dst (ModL src1 src2));
6010
  effect(CALL);
6011
  ins_cost(MEMORY_REF_COST); // FIXME
6012
  format %{ "modL    $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %}
6013
  ins_encode %{
6014
    address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
6015
    __ call(target, relocInfo::runtime_call_type);
6016
  %}
6017
  ins_pipe(divL_reg_reg);
6018
%}
6019

6020
// Integer Shift Instructions
6021

6022
// Register Shift Left
6023
instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6024
  match(Set dst (LShiftI src1 src2));
6025

6026
  size(4);
6027
  format %{ "LSL  $dst,$src1,$src2 \n\t" %}
6028
  ins_encode %{
6029
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6030
  %}
6031
  ins_pipe(ialu_reg_reg);
6032
%}
6033

6034
// Register Shift Left Immediate
6035
instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6036
  match(Set dst (LShiftI src1 src2));
6037

6038
  size(4);
6039
  format %{ "LSL    $dst,$src1,$src2\t! int" %}
6040
  ins_encode %{
6041
    __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
6042
  %}
6043
  ins_pipe(ialu_reg_imm);
6044
%}
6045

6046
instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6047
  effect(USE_DEF dst, USE src1, USE src2);
6048
  size(4);
6049
  format %{"OR  $dst.hi,$dst.hi,($src1.hi << $src2)"  %}
6050
  ins_encode %{
6051
    __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register));
6052
  %}
6053
  ins_pipe(ialu_reg_reg);
6054
%}
6055

6056
instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6057
  effect(USE_DEF dst, USE src1, USE src2);
6058
  size(4);
6059
  format %{ "LSL  $dst.lo,$src1.lo,$src2 \n\t" %}
6060
  ins_encode %{
6061
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6062
  %}
6063
  ins_pipe(ialu_reg_reg);
6064
%}
6065

6066
instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6067
  effect(DEF dst, USE src1, USE src2, KILL ccr);
6068
  size(16);
6069
  format %{ "SUBS  $dst.hi,$src2,32 \n\t"
6070
            "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t"
6071
            "RSBmi $dst.hi,$dst.hi,0 \n\t"
6072
            "LSRmi $dst.hi,$src1.lo,$dst.hi" %}
6073

6074
  ins_encode %{
6075
    // $src1$$Register and $dst$$Register->successor() can't be the same
6076
    __ subs($dst$$Register->successor(), $src2$$Register, 32);
6077
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl);
6078
    __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi);
6079
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi);
6080
  %}
6081
  ins_pipe(ialu_reg_reg);
6082
%}
6083

6084
instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6085
  match(Set dst (LShiftL src1 src2));
6086

6087
  expand %{
6088
    flagsReg ccr;
6089
    shlL_reg_reg_overlap(dst, src1, src2, ccr);
6090
    shlL_reg_reg_merge_hi(dst, src1, src2);
6091
    shlL_reg_reg_merge_lo(dst, src1, src2);
6092
  %}
6093
%}
6094

6095
// Register Shift Left Immediate
6096
instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6097
  match(Set dst (LShiftL src1 src2));
6098

6099
  size(8);
6100
  format %{ "LSL   $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t"
6101
            "MOV   $dst.lo, 0" %}
6102
  ins_encode %{
6103
    if ($src2$$constant == 32) {
6104
      __ mov($dst$$Register->successor(), $src1$$Register);
6105
    } else {
6106
      __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32));
6107
    }
6108
    __ mov($dst$$Register, 0);
6109
  %}
6110
  ins_pipe(ialu_reg_imm);
6111
%}
6112

6113
instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6114
  match(Set dst (LShiftL src1 src2));
6115

6116
  size(12);
6117
  format %{ "LSL   $dst.hi,$src1.lo,$src2\n\t"
6118
            "OR    $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t"
6119
            "LSL   $dst.lo,$src1.lo,$src2" %}
6120
  ins_encode %{
6121
    // The order of the following 3 instructions matters: src1.lo and
6122
    // dst.hi can't overlap but src.hi and dst.hi can.
6123
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant));
6124
    __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant));
6125
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6126
  %}
6127
  ins_pipe(ialu_reg_imm);
6128
%}
6129

6130
// Register Arithmetic Shift Right
6131
instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6132
  match(Set dst (RShiftI src1 src2));
6133
  size(4);
6134
  format %{ "ASR    $dst,$src1,$src2\t! int" %}
6135
  ins_encode %{
6136
    __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
6137
  %}
6138
  ins_pipe(ialu_reg_reg);
6139
%}
6140

6141
// Register Arithmetic Shift Right Immediate
6142
instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6143
  match(Set dst (RShiftI src1 src2));
6144

6145
  size(4);
6146
  format %{ "ASR    $dst,$src1,$src2" %}
6147
  ins_encode %{
6148
    __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
6149
  %}
6150
  ins_pipe(ialu_reg_imm);
6151
%}
6152

6153
// Register Shift Right Arithmetic Long
6154
instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6155
  effect(USE_DEF dst, USE src1, USE src2);
6156
  size(4);
6157
  format %{ "OR  $dst.lo,$dst.lo,($src1.lo >> $src2)"  %}
6158
  ins_encode %{
6159
    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6160
  %}
6161
  ins_pipe(ialu_reg_reg);
6162
%}
6163

6164
instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6165
  effect(USE_DEF dst, USE src1, USE src2);
6166
  size(4);
6167
  format %{ "ASR  $dst.hi,$src1.hi,$src2 \n\t" %}
6168
  ins_encode %{
6169
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register));
6170
  %}
6171
  ins_pipe(ialu_reg_reg);
6172
%}
6173

6174
instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6175
  effect(DEF dst, USE src1, USE src2, KILL ccr);
6176
  size(16);
6177
  format %{ "SUBS  $dst.lo,$src2,32 \n\t"
6178
            "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t"
6179
            "RSBmi $dst.lo,$dst.lo,0 \n\t"
6180
            "LSLmi $dst.lo,$src1.hi,$dst.lo" %}
6181

6182
  ins_encode %{
6183
    // $src1$$Register->successor() and $dst$$Register can't be the same
6184
    __ subs($dst$$Register, $src2$$Register, 32);
6185
    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl);
6186
    __ rsb($dst$$Register, $dst$$Register, 0, mi);
6187
    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6188
  %}
6189
  ins_pipe(ialu_reg_reg);
6190
%}
6191

6192
instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6193
  match(Set dst (RShiftL src1 src2));
6194

6195
  expand %{
6196
    flagsReg ccr;
6197
    sarL_reg_reg_overlap(dst, src1, src2, ccr);
6198
    sarL_reg_reg_merge_lo(dst, src1, src2);
6199
    sarL_reg_reg_merge_hi(dst, src1, src2);
6200
  %}
6201
%}
6202

6203
// Register Shift Left Immediate
6204
instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6205
  match(Set dst (RShiftL src1 src2));
6206

6207
  size(8);
6208
  format %{ "ASR   $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6209
            "ASR   $dst.hi,$src1.hi, $src2" %}
6210
  ins_encode %{
6211
    if ($src2$$constant == 32) {
6212
      __ mov($dst$$Register, $src1$$Register->successor());
6213
    } else{
6214
      __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32));
6215
    }
6216
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0));
6217
  %}
6218

6219
  ins_pipe(ialu_reg_imm);
6220
%}
6221

6222
instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6223
  match(Set dst (RShiftL src1 src2));
6224
  size(12);
6225
  format %{ "LSR   $dst.lo,$src1.lo,$src2\n\t"
6226
            "OR    $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6227
            "ASR   $dst.hi,$src1.hi,$src2" %}
6228
  ins_encode %{
6229
    // The order of the following 3 instructions matters: src1.lo and
6230
    // dst.hi can't overlap but src.hi and dst.hi can.
6231
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6232
    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6233
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant));
6234
  %}
6235
  ins_pipe(ialu_reg_imm);
6236
%}
6237

6238
// Register Shift Right
6239
instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6240
  match(Set dst (URShiftI src1 src2));
6241
  size(4);
6242
  format %{ "LSR    $dst,$src1,$src2\t! int" %}
6243
  ins_encode %{
6244
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6245
  %}
6246
  ins_pipe(ialu_reg_reg);
6247
%}
6248

6249
// Register Shift Right Immediate
6250
instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6251
  match(Set dst (URShiftI src1 src2));
6252

6253
  size(4);
6254
  format %{ "LSR    $dst,$src1,$src2" %}
6255
  ins_encode %{
6256
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6257
  %}
6258
  ins_pipe(ialu_reg_imm);
6259
%}
6260

6261
// Register Shift Right
6262
instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6263
  effect(USE_DEF dst, USE src1, USE src2);
6264
  size(4);
6265
  format %{ "OR   $dst.lo,$dst,($src1.lo >>> $src2)"  %}
6266
  ins_encode %{
6267
    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6268
  %}
6269
  ins_pipe(ialu_reg_reg);
6270
%}
6271

6272
instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6273
  effect(USE_DEF dst, USE src1, USE src2);
6274
  size(4);
6275
  format %{ "LSR  $dst.hi,$src1.hi,$src2 \n\t" %}
6276
  ins_encode %{
6277
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register));
6278
  %}
6279
  ins_pipe(ialu_reg_reg);
6280
%}
6281

6282
instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6283
  effect(DEF dst, USE src1, USE src2, KILL ccr);
6284
  size(16);
6285
  format %{ "SUBS  $dst,$src2,32 \n\t"
6286
            "LSRpl $dst,$src1.hi,$dst \n\t"
6287
            "RSBmi $dst,$dst,0 \n\t"
6288
            "LSLmi $dst,$src1.hi,$dst" %}
6289

6290
  ins_encode %{
6291
    // $src1$$Register->successor() and $dst$$Register can't be the same
6292
    __ subs($dst$$Register, $src2$$Register, 32);
6293
    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl);
6294
    __ rsb($dst$$Register, $dst$$Register, 0, mi);
6295
    __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6296
  %}
6297
  ins_pipe(ialu_reg_reg);
6298
%}
6299

6300
instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6301
  match(Set dst (URShiftL src1 src2));
6302

6303
  expand %{
6304
    flagsReg ccr;
6305
    shrL_reg_reg_overlap(dst, src1, src2, ccr);
6306
    shrL_reg_reg_merge_lo(dst, src1, src2);
6307
    shrL_reg_reg_merge_hi(dst, src1, src2);
6308
  %}
6309
%}
6310

6311
// Register Shift Right Immediate
6312
instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6313
  match(Set dst (URShiftL src1 src2));
6314

6315
  size(8);
6316
  format %{ "LSR   $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6317
            "MOV   $dst.hi, 0" %}
6318
  ins_encode %{
6319
    if ($src2$$constant == 32) {
6320
      __ mov($dst$$Register, $src1$$Register->successor());
6321
    } else {
6322
      __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32));
6323
    }
6324
    __ mov($dst$$Register->successor(), 0);
6325
  %}
6326

6327
  ins_pipe(ialu_reg_imm);
6328
%}
6329

6330
instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6331
  match(Set dst (URShiftL src1 src2));
6332

6333
  size(12);
6334
  format %{ "LSR   $dst.lo,$src1.lo,$src2\n\t"
6335
            "OR    $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6336
            "LSR   $dst.hi,$src1.hi,$src2" %}
6337
  ins_encode %{
6338
    // The order of the following 3 instructions matters: src1.lo and
6339
    // dst.hi can't overlap but src.hi and dst.hi can.
6340
    __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6341
    __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6342
    __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant));
6343
  %}
6344
  ins_pipe(ialu_reg_imm);
6345
%}
6346

6347

6348
instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{
6349
  match(Set dst (URShiftI (CastP2X src1) src2));
6350
  size(4);
6351
  format %{ "LSR    $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %}
6352
  ins_encode %{
6353
    __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant);
6354
  %}
6355
  ins_pipe(ialu_reg_imm);
6356
%}
6357

6358
//----------Floating Point Arithmetic Instructions-----------------------------
6359

6360
//  Add float single precision
6361
instruct addF_reg_reg(regF dst, regF src1, regF src2) %{
6362
  match(Set dst (AddF src1 src2));
6363

6364
  size(4);
6365
  format %{ "FADDS  $dst,$src1,$src2" %}
6366
  ins_encode %{
6367
    __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6368
  %}
6369

6370
  ins_pipe(faddF_reg_reg);
6371
%}
6372

6373
//  Add float double precision
6374
instruct addD_reg_reg(regD dst, regD src1, regD src2) %{
6375
  match(Set dst (AddD src1 src2));
6376

6377
  size(4);
6378
  format %{ "FADDD  $dst,$src1,$src2" %}
6379
  ins_encode %{
6380
    __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6381
  %}
6382

6383
  ins_pipe(faddD_reg_reg);
6384
%}
6385

6386
//  Sub float single precision
6387
instruct subF_reg_reg(regF dst, regF src1, regF src2) %{
6388
  match(Set dst (SubF src1 src2));
6389

6390
  size(4);
6391
  format %{ "FSUBS  $dst,$src1,$src2" %}
6392
  ins_encode %{
6393
    __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6394
  %}
6395
  ins_pipe(faddF_reg_reg);
6396
%}
6397

6398
//  Sub float double precision
6399
instruct subD_reg_reg(regD dst, regD src1, regD src2) %{
6400
  match(Set dst (SubD src1 src2));
6401

6402
  size(4);
6403
  format %{ "FSUBD  $dst,$src1,$src2" %}
6404
  ins_encode %{
6405
    __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6406
  %}
6407
  ins_pipe(faddD_reg_reg);
6408
%}
6409

6410
//  Mul float single precision
6411
instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{
6412
  match(Set dst (MulF src1 src2));
6413

6414
  size(4);
6415
  format %{ "FMULS  $dst,$src1,$src2" %}
6416
  ins_encode %{
6417
    __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6418
  %}
6419

6420
  ins_pipe(fmulF_reg_reg);
6421
%}
6422

6423
//  Mul float double precision
6424
instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{
6425
  match(Set dst (MulD src1 src2));
6426

6427
  size(4);
6428
  format %{ "FMULD  $dst,$src1,$src2" %}
6429
  ins_encode %{
6430
    __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6431
  %}
6432

6433
  ins_pipe(fmulD_reg_reg);
6434
%}
6435

6436
//  Div float single precision
6437
instruct divF_reg_reg(regF dst, regF src1, regF src2) %{
6438
  match(Set dst (DivF src1 src2));
6439

6440
  size(4);
6441
  format %{ "FDIVS  $dst,$src1,$src2" %}
6442
  ins_encode %{
6443
    __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6444
  %}
6445

6446
  ins_pipe(fdivF_reg_reg);
6447
%}
6448

6449
//  Div float double precision
6450
instruct divD_reg_reg(regD dst, regD src1, regD src2) %{
6451
  match(Set dst (DivD src1 src2));
6452

6453
  size(4);
6454
  format %{ "FDIVD  $dst,$src1,$src2" %}
6455
  ins_encode %{
6456
    __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6457
  %}
6458

6459
  ins_pipe(fdivD_reg_reg);
6460
%}
6461

6462
//  Absolute float double precision
6463
instruct absD_reg(regD dst, regD src) %{
6464
  match(Set dst (AbsD src));
6465

6466
  size(4);
6467
  format %{ "FABSd  $dst,$src" %}
6468
  ins_encode %{
6469
    __ abs_double($dst$$FloatRegister, $src$$FloatRegister);
6470
  %}
6471
  ins_pipe(faddD_reg);
6472
%}
6473

6474
//  Absolute float single precision
6475
instruct absF_reg(regF dst, regF src) %{
6476
  match(Set dst (AbsF src));
6477
  format %{ "FABSs  $dst,$src" %}
6478
  ins_encode %{
6479
    __ abs_float($dst$$FloatRegister, $src$$FloatRegister);
6480
  %}
6481
  ins_pipe(faddF_reg);
6482
%}
6483

6484
instruct negF_reg(regF dst, regF src) %{
6485
  match(Set dst (NegF src));
6486

6487
  size(4);
6488
  format %{ "FNEGs  $dst,$src" %}
6489
  ins_encode %{
6490
    __ neg_float($dst$$FloatRegister, $src$$FloatRegister);
6491
  %}
6492
  ins_pipe(faddF_reg);
6493
%}
6494

6495
instruct negD_reg(regD dst, regD src) %{
6496
  match(Set dst (NegD src));
6497

6498
  format %{ "FNEGd  $dst,$src" %}
6499
  ins_encode %{
6500
    __ neg_double($dst$$FloatRegister, $src$$FloatRegister);
6501
  %}
6502
  ins_pipe(faddD_reg);
6503
%}
6504

6505
//  Sqrt float double precision
6506
instruct sqrtF_reg_reg(regF dst, regF src) %{
6507
  match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
6508

6509
  size(4);
6510
  format %{ "FSQRTS $dst,$src" %}
6511
  ins_encode %{
6512
    __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister);
6513
  %}
6514
  ins_pipe(fdivF_reg_reg);
6515
%}
6516

6517
//  Sqrt float double precision
6518
instruct sqrtD_reg_reg(regD dst, regD src) %{
6519
  match(Set dst (SqrtD src));
6520

6521
  size(4);
6522
  format %{ "FSQRTD $dst,$src" %}
6523
  ins_encode %{
6524
    __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister);
6525
  %}
6526
  ins_pipe(fdivD_reg_reg);
6527
%}
6528

6529
//----------Logical Instructions-----------------------------------------------
6530
// And Instructions
6531
// Register And
6532
instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6533
  match(Set dst (AndI src1 src2));
6534

6535
  size(4);
6536
  format %{ "and_32 $dst,$src1,$src2" %}
6537
  ins_encode %{
6538
    __ and_32($dst$$Register, $src1$$Register, $src2$$Register);
6539
  %}
6540
  ins_pipe(ialu_reg_reg);
6541
%}
6542

6543
instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6544
  match(Set dst (AndI src1 (LShiftI src2 src3)));
6545

6546
  size(4);
6547
  format %{ "AND    $dst,$src1,$src2<<$src3" %}
6548
  ins_encode %{
6549
    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6550
  %}
6551
  ins_pipe(ialu_reg_reg);
6552
%}
6553

6554
instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6555
  match(Set dst (AndI src1 (LShiftI src2 src3)));
6556

6557
  size(4);
6558
  format %{ "and_32 $dst,$src1,$src2<<$src3" %}
6559
  ins_encode %{
6560
    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6561
  %}
6562
  ins_pipe(ialu_reg_reg);
6563
%}
6564

6565
instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6566
  match(Set dst (AndI src1 (RShiftI src2 src3)));
6567

6568
  size(4);
6569
  format %{ "AND    $dst,$src1,$src2>>$src3" %}
6570
  ins_encode %{
6571
    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6572
  %}
6573
  ins_pipe(ialu_reg_reg);
6574
%}
6575

6576
instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6577
  match(Set dst (AndI src1 (RShiftI src2 src3)));
6578

6579
  size(4);
6580
  format %{ "and_32 $dst,$src1,$src2>>$src3" %}
6581
  ins_encode %{
6582
    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6583
  %}
6584
  ins_pipe(ialu_reg_reg);
6585
%}
6586

6587
instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6588
  match(Set dst (AndI src1 (URShiftI src2 src3)));
6589

6590
  size(4);
6591
  format %{ "AND    $dst,$src1,$src2>>>$src3" %}
6592
  ins_encode %{
6593
    __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6594
  %}
6595
  ins_pipe(ialu_reg_reg);
6596
%}
6597

6598
instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6599
  match(Set dst (AndI src1 (URShiftI src2 src3)));
6600

6601
  size(4);
6602
  format %{ "and_32 $dst,$src1,$src2>>>$src3" %}
6603
  ins_encode %{
6604
    __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6605
  %}
6606
  ins_pipe(ialu_reg_reg);
6607
%}
6608

6609
// Immediate And
6610
instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6611
  match(Set dst (AndI src1 src2));
6612

6613
  size(4);
6614
  format %{ "and_32 $dst,$src1,$src2\t! int" %}
6615
  ins_encode %{
6616
    __ and_32($dst$$Register, $src1$$Register, $src2$$constant);
6617
  %}
6618
  ins_pipe(ialu_reg_imm);
6619
%}
6620

6621
instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{
6622
  match(Set dst (AndI src1 src2));
6623

6624
  size(4);
6625
  format %{ "bic    $dst,$src1,~$src2\t! int" %}
6626
  ins_encode %{
6627
    __ bic($dst$$Register, $src1$$Register, ~$src2$$constant);
6628
  %}
6629
  ins_pipe(ialu_reg_imm);
6630
%}
6631

6632
// Register And Long
6633
instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6634
  match(Set dst (AndL src1 src2));
6635

6636
  ins_cost(DEFAULT_COST);
6637
  size(8);
6638
  format %{ "AND    $dst,$src1,$src2\t! long" %}
6639
  ins_encode %{
6640
    __ andr($dst$$Register, $src1$$Register, $src2$$Register);
6641
    __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6642
  %}
6643
  ins_pipe(ialu_reg_reg);
6644
%}
6645

6646
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6647
// (hi($con$$constant), lo($con$$constant)) becomes
6648
instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6649
  match(Set dst (AndL src1 con));
6650
  ins_cost(DEFAULT_COST);
6651
  size(8);
6652
  format %{ "AND    $dst,$src1,$con\t! long" %}
6653
  ins_encode %{
6654
    __ andr($dst$$Register, $src1$$Register, $con$$constant);
6655
    __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6656
  %}
6657
  ins_pipe(ialu_reg_imm);
6658
%}
6659

6660
// Or Instructions
6661
// Register Or
6662
instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6663
  match(Set dst (OrI src1 src2));
6664

6665
  size(4);
6666
  format %{ "orr_32 $dst,$src1,$src2\t! int" %}
6667
  ins_encode %{
6668
    __ orr_32($dst$$Register, $src1$$Register, $src2$$Register);
6669
  %}
6670
  ins_pipe(ialu_reg_reg);
6671
%}
6672

6673
instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6674
  match(Set dst (OrI src1 (LShiftI src2 src3)));
6675

6676
  size(4);
6677
  format %{ "OR    $dst,$src1,$src2<<$src3" %}
6678
  ins_encode %{
6679
    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6680
  %}
6681
  ins_pipe(ialu_reg_reg);
6682
%}
6683

6684
instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6685
  match(Set dst (OrI src1 (LShiftI src2 src3)));
6686

6687
  size(4);
6688
  format %{ "orr_32 $dst,$src1,$src2<<$src3" %}
6689
  ins_encode %{
6690
    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6691
  %}
6692
  ins_pipe(ialu_reg_reg);
6693
%}
6694

6695
instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6696
  match(Set dst (OrI src1 (RShiftI src2 src3)));
6697

6698
  size(4);
6699
  format %{ "OR    $dst,$src1,$src2>>$src3" %}
6700
  ins_encode %{
6701
    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6702
  %}
6703
  ins_pipe(ialu_reg_reg);
6704
%}
6705

6706
instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6707
  match(Set dst (OrI src1 (RShiftI src2 src3)));
6708

6709
  size(4);
6710
  format %{ "orr_32 $dst,$src1,$src2>>$src3" %}
6711
  ins_encode %{
6712
    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6713
  %}
6714
  ins_pipe(ialu_reg_reg);
6715
%}
6716

6717
instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6718
  match(Set dst (OrI src1 (URShiftI src2 src3)));
6719

6720
  size(4);
6721
  format %{ "OR    $dst,$src1,$src2>>>$src3" %}
6722
  ins_encode %{
6723
    __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6724
  %}
6725
  ins_pipe(ialu_reg_reg);
6726
%}
6727

6728
instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6729
  match(Set dst (OrI src1 (URShiftI src2 src3)));
6730

6731
  size(4);
6732
  format %{ "orr_32 $dst,$src1,$src2>>>$src3" %}
6733
  ins_encode %{
6734
    __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6735
  %}
6736
  ins_pipe(ialu_reg_reg);
6737
%}
6738

6739
// Immediate Or
6740
instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6741
  match(Set dst (OrI src1 src2));
6742

6743
  size(4);
6744
  format %{ "orr_32  $dst,$src1,$src2" %}
6745
  ins_encode %{
6746
    __ orr_32($dst$$Register, $src1$$Register, $src2$$constant);
6747
  %}
6748
  ins_pipe(ialu_reg_imm);
6749
%}
6750
// TODO: orn_32 with limmIn
6751

6752
// Register Or Long
6753
instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6754
  match(Set dst (OrL src1 src2));
6755

6756
  ins_cost(DEFAULT_COST);
6757
  size(8);
6758
  format %{ "OR     $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
6759
            "OR     $dst.hi,$src1.hi,$src2.hi" %}
6760
  ins_encode %{
6761
    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6762
    __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6763
  %}
6764
  ins_pipe(ialu_reg_reg);
6765
%}
6766

6767
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6768
// (hi($con$$constant), lo($con$$constant)) becomes
6769
instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6770
  match(Set dst (OrL src1 con));
6771
  ins_cost(DEFAULT_COST);
6772
  size(8);
6773
  format %{ "OR     $dst.lo,$src1.lo,$con\t! long\n\t"
6774
            "OR     $dst.hi,$src1.hi,$con" %}
6775
  ins_encode %{
6776
    __ orr($dst$$Register, $src1$$Register, $con$$constant);
6777
    __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6778
  %}
6779
  ins_pipe(ialu_reg_imm);
6780
%}
6781

6782
#ifdef TODO
6783
// Use SPRegP to match Rthread (TLS register) without spilling.
6784
// Use store_ptr_RegP to match Rthread (TLS register) without spilling.
6785
// Use sp_ptr_RegP to match Rthread (TLS register) without spilling.
6786
instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{
6787
  match(Set dst (OrI src1 (CastP2X src2)));
6788
  size(4);
6789
  format %{ "OR     $dst,$src1,$src2" %}
6790
  ins_encode %{
6791
    __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6792
  %}
6793
  ins_pipe(ialu_reg_reg);
6794
%}
6795
#endif
6796

6797
// Xor Instructions
6798
// Register Xor
6799
instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6800
  match(Set dst (XorI src1 src2));
6801

6802
  size(4);
6803
  format %{ "eor_32 $dst,$src1,$src2" %}
6804
  ins_encode %{
6805
    __ eor_32($dst$$Register, $src1$$Register, $src2$$Register);
6806
  %}
6807
  ins_pipe(ialu_reg_reg);
6808
%}
6809

6810
instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6811
  match(Set dst (XorI src1 (LShiftI src2 src3)));
6812

6813
  size(4);
6814
  format %{ "XOR    $dst,$src1,$src2<<$src3" %}
6815
  ins_encode %{
6816
    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6817
  %}
6818
  ins_pipe(ialu_reg_reg);
6819
%}
6820

6821
instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6822
  match(Set dst (XorI src1 (LShiftI src2 src3)));
6823

6824
  size(4);
6825
  format %{ "eor_32 $dst,$src1,$src2<<$src3" %}
6826
  ins_encode %{
6827
    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6828
  %}
6829
  ins_pipe(ialu_reg_reg);
6830
%}
6831

6832
instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6833
  match(Set dst (XorI src1 (RShiftI src2 src3)));
6834

6835
  size(4);
6836
  format %{ "XOR    $dst,$src1,$src2>>$src3" %}
6837
  ins_encode %{
6838
    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6839
  %}
6840
  ins_pipe(ialu_reg_reg);
6841
%}
6842

6843
instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6844
  match(Set dst (XorI src1 (RShiftI src2 src3)));
6845

6846
  size(4);
6847
  format %{ "eor_32 $dst,$src1,$src2>>$src3" %}
6848
  ins_encode %{
6849
    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6850
  %}
6851
  ins_pipe(ialu_reg_reg);
6852
%}
6853

6854
instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6855
  match(Set dst (XorI src1 (URShiftI src2 src3)));
6856

6857
  size(4);
6858
  format %{ "XOR    $dst,$src1,$src2>>>$src3" %}
6859
  ins_encode %{
6860
    __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6861
  %}
6862
  ins_pipe(ialu_reg_reg);
6863
%}
6864

6865
instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6866
  match(Set dst (XorI src1 (URShiftI src2 src3)));
6867

6868
  size(4);
6869
  format %{ "eor_32 $dst,$src1,$src2>>>$src3" %}
6870
  ins_encode %{
6871
    __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6872
  %}
6873
  ins_pipe(ialu_reg_reg);
6874
%}
6875

6876
// Immediate Xor
6877
instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{
6878
  match(Set dst (XorI src1 src2));
6879

6880
  size(4);
6881
  format %{ "eor_32 $dst,$src1,$src2" %}
6882
  ins_encode %{
6883
    __ eor_32($dst$$Register, $src1$$Register, $src2$$constant);
6884
  %}
6885
  ins_pipe(ialu_reg_imm);
6886
%}
6887

6888
// Register Xor Long
6889
instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6890
  match(Set dst (XorL src1 src2));
6891
  ins_cost(DEFAULT_COST);
6892
  size(8);
6893
  format %{ "XOR     $dst.hi,$src1.hi,$src2.hi\t! long\n\t"
6894
            "XOR     $dst.lo,$src1.lo,$src2.lo\t! long" %}
6895
  ins_encode %{
6896
    __ eor($dst$$Register, $src1$$Register, $src2$$Register);
6897
    __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6898
  %}
6899
  ins_pipe(ialu_reg_reg);
6900
%}
6901

6902
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
6903
// (hi($con$$constant), lo($con$$constant)) becomes
6904
instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6905
  match(Set dst (XorL src1 con));
6906
  ins_cost(DEFAULT_COST);
6907
  size(8);
6908
  format %{ "XOR     $dst.hi,$src1.hi,$con\t! long\n\t"
6909
            "XOR     $dst.lo,$src1.lo,0\t! long" %}
6910
  ins_encode %{
6911
    __ eor($dst$$Register, $src1$$Register, $con$$constant);
6912
    __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0);
6913
  %}
6914
  ins_pipe(ialu_reg_imm);
6915
%}
6916

6917
instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
6918
  match(Set dst (CmpLTMask p q));
6919
  effect( KILL ccr );
6920
  ins_cost(DEFAULT_COST*3);
6921
  format %{ "CMP    $p,$q\n\t"
6922
            "MOV    $dst, #0\n\t"
6923
            "MOV.lt $dst, #-1" %}
6924
  ins_encode %{
6925
    __ cmp($p$$Register, $q$$Register);
6926
    __ mov($dst$$Register, 0);
6927
    __ mvn($dst$$Register, 0, lt);
6928
  %}
6929
  ins_pipe(ialu_reg_reg_ialu);
6930
%}
6931

6932
instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{
6933
  match(Set dst (CmpLTMask p q));
6934
  effect( KILL ccr );
6935
  ins_cost(DEFAULT_COST*3);
6936
  format %{ "CMP    $p,$q\n\t"
6937
            "MOV    $dst, #0\n\t"
6938
            "MOV.lt $dst, #-1" %}
6939
  ins_encode %{
6940
    __ cmp($p$$Register, $q$$constant);
6941
    __ mov($dst$$Register, 0);
6942
    __ mvn($dst$$Register, 0, lt);
6943
  %}
6944
  ins_pipe(ialu_reg_reg_ialu);
6945
%}
6946

6947
instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{
6948
  match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6949
  effect( KILL ccr );
6950
  ins_cost(DEFAULT_COST*2);
6951
  format %{ "CMP    $p,$q\n\t"
6952
            "ADD.lt $z,$y,$z" %}
6953
  ins_encode %{
6954
    __ cmp($p$$Register, $q$$Register);
6955
    __ add($z$$Register, $y$$Register, $z$$Register, lt);
6956
  %}
6957
  ins_pipe( cadd_cmpltmask );
6958
%}
6959

6960
// FIXME: remove unused "dst"
6961
instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{
6962
  match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6963
  effect( KILL ccr );
6964
  ins_cost(DEFAULT_COST*2);
6965
  format %{ "CMP    $p,$q\n\t"
6966
            "ADD.lt $z,$y,$z" %}
6967
  ins_encode %{
6968
    __ cmp($p$$Register, $q$$constant);
6969
    __ add($z$$Register, $y$$Register, $z$$Register, lt);
6970
  %}
6971
  ins_pipe( cadd_cmpltmask );
6972
%}
6973

6974
instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
6975
  match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
6976
  effect( KILL ccr );
6977
  ins_cost(DEFAULT_COST*2);
6978
  format %{ "SUBS   $p,$p,$q\n\t"
6979
            "ADD.lt $p,$y,$p" %}
6980
  ins_encode %{
6981
    __ subs($p$$Register, $p$$Register, $q$$Register);
6982
    __ add($p$$Register, $y$$Register, $p$$Register, lt);
6983
  %}
6984
  ins_pipe( cadd_cmpltmask );
6985
%}
6986

6987
//----------Arithmetic Conversion Instructions---------------------------------
6988
// The conversions operations are all Alpha sorted.  Please keep it that way!
6989

6990
instruct convD2F_reg(regF dst, regD src) %{
6991
  match(Set dst (ConvD2F src));
6992
  size(4);
6993
  format %{ "FCVTSD  $dst,$src" %}
6994
  ins_encode %{
6995
    __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister);
6996
  %}
6997
  ins_pipe(fcvtD2F);
6998
%}
6999

7000
// Convert a double to an int in a float register.
7001
// If the double is a NAN, stuff a zero in instead.
7002

7003
instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{
7004
  match(Set dst (ConvD2I src));
7005
  effect( TEMP tmp );
7006
  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7007
  format %{ "FTOSIZD  $tmp,$src\n\t"
7008
            "FMRS     $dst, $tmp" %}
7009
  ins_encode %{
7010
    __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister);
7011
    __ fmrs($dst$$Register, $tmp$$FloatRegister);
7012
  %}
7013
  ins_pipe(fcvtD2I);
7014
%}
7015

7016
// Convert a double to a long in a double register.
7017
// If the double is a NAN, stuff a zero in instead.
7018

7019
// Double to Long conversion
7020
instruct convD2L_reg(R0R1RegL dst, regD src) %{
7021
  match(Set dst (ConvD2L src));
7022
  effect(CALL);
7023
  ins_cost(MEMORY_REF_COST); // FIXME
7024
  format %{ "convD2L    $dst,$src\t ! call to SharedRuntime::d2l" %}
7025
  ins_encode %{
7026
#ifndef __ABI_HARD__
7027
    __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7028
#else
7029
    if ($src$$FloatRegister != D0) {
7030
      __ mov_double(D0, $src$$FloatRegister);
7031
    }
7032
#endif
7033
    address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
7034
    __ call(target, relocInfo::runtime_call_type);
7035
  %}
7036
  ins_pipe(fcvtD2L);
7037
%}
7038

7039
instruct convF2D_reg(regD dst, regF src) %{
7040
  match(Set dst (ConvF2D src));
7041
  size(4);
7042
  format %{ "FCVTDS  $dst,$src" %}
7043
  ins_encode %{
7044
    __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister);
7045
  %}
7046
  ins_pipe(fcvtF2D);
7047
%}
7048

7049
instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{
7050
  match(Set dst (ConvF2I src));
7051
  effect( TEMP tmp );
7052
  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7053
  size(8);
7054
  format %{ "FTOSIZS  $tmp,$src\n\t"
7055
            "FMRS     $dst, $tmp" %}
7056
  ins_encode %{
7057
    __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister);
7058
    __ fmrs($dst$$Register, $tmp$$FloatRegister);
7059
  %}
7060
  ins_pipe(fcvtF2I);
7061
%}
7062

7063
// Float to Long conversion
7064
instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{
7065
  match(Set dst (ConvF2L src));
7066
  ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7067
  effect(CALL);
7068
  format %{ "convF2L  $dst,$src\t! call to SharedRuntime::f2l" %}
7069
  ins_encode %{
7070
#ifndef __ABI_HARD__
7071
    __ fmrs($arg1$$Register, $src$$FloatRegister);
7072
#else
7073
    if($src$$FloatRegister != S0) {
7074
      __ mov_float(S0, $src$$FloatRegister);
7075
    }
7076
#endif
7077
    address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
7078
    __ call(target, relocInfo::runtime_call_type);
7079
  %}
7080
  ins_pipe(fcvtF2L);
7081
%}
7082

7083
instruct convI2D_reg_reg(iRegI src, regD_low dst) %{
7084
  match(Set dst (ConvI2D src));
7085
  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7086
  size(8);
7087
  format %{ "FMSR     $dst,$src \n\t"
7088
            "FSITOD   $dst $dst"%}
7089
  ins_encode %{
7090
      __ fmsr($dst$$FloatRegister, $src$$Register);
7091
      __ fsitod($dst$$FloatRegister, $dst$$FloatRegister);
7092
  %}
7093
  ins_pipe(fcvtI2D);
7094
%}
7095

7096
instruct convI2F_reg_reg( regF dst, iRegI src ) %{
7097
  match(Set dst (ConvI2F src));
7098
  ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7099
  size(8);
7100
  format %{ "FMSR     $dst,$src \n\t"
7101
            "FSITOS   $dst, $dst"%}
7102
  ins_encode %{
7103
      __ fmsr($dst$$FloatRegister, $src$$Register);
7104
      __ fsitos($dst$$FloatRegister, $dst$$FloatRegister);
7105
  %}
7106
  ins_pipe(fcvtI2F);
7107
%}
7108

7109
instruct convI2L_reg(iRegL dst, iRegI src) %{
7110
  match(Set dst (ConvI2L src));
7111
  size(8);
7112
  format %{ "MOV    $dst.lo, $src \n\t"
7113
            "ASR    $dst.hi,$src,31\t! int->long" %}
7114
  ins_encode %{
7115
    __ mov($dst$$Register, $src$$Register);
7116
    __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31));
7117
  %}
7118
  ins_pipe(ialu_reg_reg);
7119
%}
7120

7121
// Zero-extend convert int to long
7122
instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{
7123
  match(Set dst (AndL (ConvI2L src) mask) );
7124
  size(8);
7125
  format %{ "MOV    $dst.lo,$src.lo\t! zero-extend int to long\n\t"
7126
            "MOV    $dst.hi, 0"%}
7127
  ins_encode %{
7128
    __ mov($dst$$Register, $src$$Register);
7129
    __ mov($dst$$Register->successor(), 0);
7130
  %}
7131
  ins_pipe(ialu_reg_reg);
7132
%}
7133

7134
// Zero-extend long
7135
instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
7136
  match(Set dst (AndL src mask) );
7137
  size(8);
7138
  format %{ "MOV    $dst.lo,$src.lo\t! zero-extend long\n\t"
7139
            "MOV    $dst.hi, 0"%}
7140
  ins_encode %{
7141
    __ mov($dst$$Register, $src$$Register);
7142
    __ mov($dst$$Register->successor(), 0);
7143
  %}
7144
  ins_pipe(ialu_reg_reg);
7145
%}
7146

7147
instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
7148
  match(Set dst (MoveF2I src));
7149
  effect(DEF dst, USE src);
7150
  ins_cost(MEMORY_REF_COST); // FIXME
7151

7152
  size(4);
7153
  format %{ "FMRS   $dst,$src\t! MoveF2I" %}
7154
  ins_encode %{
7155
    __ fmrs($dst$$Register, $src$$FloatRegister);
7156
  %}
7157
  ins_pipe(iload_mem); // FIXME
7158
%}
7159

7160
instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
7161
  match(Set dst (MoveI2F src));
7162
  ins_cost(MEMORY_REF_COST); // FIXME
7163

7164
  size(4);
7165
  format %{ "FMSR   $dst,$src\t! MoveI2F" %}
7166
  ins_encode %{
7167
    __ fmsr($dst$$FloatRegister, $src$$Register);
7168
  %}
7169
  ins_pipe(iload_mem); // FIXME
7170
%}
7171

7172
instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
7173
  match(Set dst (MoveD2L src));
7174
  effect(DEF dst, USE src);
7175
  ins_cost(MEMORY_REF_COST); // FIXME
7176

7177
  size(4);
7178
  format %{ "FMRRD    $dst,$src\t! MoveD2L" %}
7179
  ins_encode %{
7180
    __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7181
  %}
7182
  ins_pipe(iload_mem); // FIXME
7183
%}
7184

7185
instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
7186
  match(Set dst (MoveL2D src));
7187
  effect(DEF dst, USE src);
7188
  ins_cost(MEMORY_REF_COST); // FIXME
7189

7190
  size(4);
7191
  format %{ "FMDRR   $dst,$src\t! MoveL2D" %}
7192
  ins_encode %{
7193
    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7194
  %}
7195
  ins_pipe(ialu_reg_reg); // FIXME
7196
%}
7197

7198
//-----------
7199
// Long to Double conversion
7200

7201
// Magic constant, 0x43300000
7202
instruct loadConI_x43300000(iRegI dst) %{
7203
  effect(DEF dst);
7204
  size(8);
7205
  format %{ "MOV_SLOW  $dst,0x43300000\t! 2^52" %}
7206
  ins_encode %{
7207
    __ mov_slow($dst$$Register, 0x43300000);
7208
  %}
7209
  ins_pipe(ialu_none);
7210
%}
7211

7212
// Magic constant, 0x41f00000
7213
instruct loadConI_x41f00000(iRegI dst) %{
7214
  effect(DEF dst);
7215
  size(8);
7216
  format %{ "MOV_SLOW  $dst, 0x41f00000\t! 2^32" %}
7217
  ins_encode %{
7218
    __ mov_slow($dst$$Register, 0x41f00000);
7219
  %}
7220
  ins_pipe(ialu_none);
7221
%}
7222

7223
instruct loadConI_x0(iRegI dst) %{
7224
  effect(DEF dst);
7225
  size(4);
7226
  format %{ "MOV  $dst, 0x0\t! 0" %}
7227
  ins_encode %{
7228
    __ mov($dst$$Register, 0);
7229
  %}
7230
  ins_pipe(ialu_none);
7231
%}
7232

7233
// Construct a double from two float halves
7234
instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{
7235
  effect(DEF dst, USE src1, USE src2);
7236
  size(8);
7237
  format %{ "FCPYS  $dst.hi,$src1.hi\n\t"
7238
            "FCPYS  $dst.lo,$src2.lo" %}
7239
  ins_encode %{
7240
    __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor());
7241
    __ fcpys($dst$$FloatRegister, $src2$$FloatRegister);
7242
  %}
7243
  ins_pipe(faddD_reg_reg);
7244
%}
7245

7246
// Convert integer in high half of a double register (in the lower half of
7247
// the double register file) to double
7248
instruct convI2D_regDHi_regD(regD dst, regD_low src) %{
7249
  effect(DEF dst, USE src);
7250
  size(4);
7251
  format %{ "FSITOD  $dst,$src" %}
7252
  ins_encode %{
7253
    __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor());
7254
  %}
7255
  ins_pipe(fcvtLHi2D);
7256
%}
7257

7258
// Add float double precision
7259
instruct addD_regD_regD(regD dst, regD src1, regD src2) %{
7260
  effect(DEF dst, USE src1, USE src2);
7261
  size(4);
7262
  format %{ "FADDD  $dst,$src1,$src2" %}
7263
  ins_encode %{
7264
    __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7265
  %}
7266
  ins_pipe(faddD_reg_reg);
7267
%}
7268

7269
// Sub float double precision
7270
instruct subD_regD_regD(regD dst, regD src1, regD src2) %{
7271
  effect(DEF dst, USE src1, USE src2);
7272
  size(4);
7273
  format %{ "FSUBD  $dst,$src1,$src2" %}
7274
  ins_encode %{
7275
    __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7276
  %}
7277
  ins_pipe(faddD_reg_reg);
7278
%}
7279

7280
// Mul float double precision
7281
instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{
7282
  effect(DEF dst, USE src1, USE src2);
7283
  size(4);
7284
  format %{ "FMULD  $dst,$src1,$src2" %}
7285
  ins_encode %{
7286
    __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7287
  %}
7288
  ins_pipe(fmulD_reg_reg);
7289
%}
7290

7291
instruct regL_to_regD(regD dst, iRegL src) %{
7292
  // No match rule to avoid chain rule match.
7293
  effect(DEF dst, USE src);
7294
  ins_cost(MEMORY_REF_COST);
7295
  size(4);
7296
  format %{ "FMDRR   $dst,$src\t! regL to regD" %}
7297
  ins_encode %{
7298
    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7299
  %}
7300
  ins_pipe(ialu_reg_reg); // FIXME
7301
%}
7302

7303
instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{
7304
  // No match rule to avoid chain rule match.
7305
  effect(DEF dst, USE src1, USE src2);
7306
  ins_cost(MEMORY_REF_COST);
7307
  size(4);
7308
  format %{ "FMDRR   $dst,$src1,$src2\t! regI,regI to regD" %}
7309
  ins_encode %{
7310
    __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register);
7311
  %}
7312
  ins_pipe(ialu_reg_reg); // FIXME
7313
%}
7314

7315
instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{
7316
  match(Set dst (ConvL2D src));
7317
  ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME
7318

7319
  expand %{
7320
    regD_low   tmpsrc;
7321
    iRegI      ix43300000;
7322
    iRegI      ix41f00000;
7323
    iRegI      ix0;
7324
    regD_low   dx43300000;
7325
    regD       dx41f00000;
7326
    regD       tmp1;
7327
    regD_low   tmp2;
7328
    regD       tmp3;
7329
    regD       tmp4;
7330

7331
    regL_to_regD(tmpsrc, src);
7332

7333
    loadConI_x43300000(ix43300000);
7334
    loadConI_x41f00000(ix41f00000);
7335
    loadConI_x0(ix0);
7336

7337
    regI_regI_to_regD(dx43300000, ix0, ix43300000);
7338
    regI_regI_to_regD(dx41f00000, ix0, ix41f00000);
7339

7340
    convI2D_regDHi_regD(tmp1, tmpsrc);
7341
    regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc);
7342
    subD_regD_regD(tmp3, tmp2, dx43300000);
7343
    mulD_regD_regD(tmp4, tmp1, dx41f00000);
7344
    addD_regD_regD(dst, tmp3, tmp4);
7345
  %}
7346
%}
7347

7348
instruct convL2I_reg(iRegI dst, iRegL src) %{
7349
  match(Set dst (ConvL2I src));
7350
  size(4);
7351
  format %{ "MOV    $dst,$src.lo\t! long->int" %}
7352
  ins_encode %{
7353
    __ mov($dst$$Register, $src$$Register);
7354
  %}
7355
  ins_pipe(ialu_move_reg_I_to_L);
7356
%}
7357

7358
// Register Shift Right Immediate
7359
instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{
7360
  match(Set dst (ConvL2I (RShiftL src cnt)));
7361
  size(4);
7362
  format %{ "ASR    $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %}
7363
  ins_encode %{
7364
    if ($cnt$$constant == 32) {
7365
      __ mov($dst$$Register, $src$$Register->successor());
7366
    } else {
7367
      __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32));
7368
    }
7369
  %}
7370
  ins_pipe(ialu_reg_imm);
7371
%}
7372

7373

7374
//----------Control Flow Instructions------------------------------------------
7375
// Compare Instructions
7376
// Compare Integers
7377
instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{
7378
  match(Set icc (CmpI op1 op2));
7379
  effect( DEF icc, USE op1, USE op2 );
7380

7381
  size(4);
7382
  format %{ "cmp_32 $op1,$op2\t! int" %}
7383
  ins_encode %{
7384
    __ cmp_32($op1$$Register, $op2$$Register);
7385
  %}
7386
  ins_pipe(ialu_cconly_reg_reg);
7387
%}
7388

7389
#ifdef _LP64
7390
// Compare compressed pointers
7391
instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{
7392
  match(Set icc (CmpN op1 op2));
7393
  effect( DEF icc, USE op1, USE op2 );
7394

7395
  size(4);
7396
  format %{ "cmp_32 $op1,$op2\t! int" %}
7397
  ins_encode %{
7398
    __ cmp_32($op1$$Register, $op2$$Register);
7399
  %}
7400
  ins_pipe(ialu_cconly_reg_reg);
7401
%}
7402
#endif
7403

7404
instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
7405
  match(Set icc (CmpU op1 op2));
7406

7407
  size(4);
7408
  format %{ "cmp_32 $op1,$op2\t! unsigned int" %}
7409
  ins_encode %{
7410
    __ cmp_32($op1$$Register, $op2$$Register);
7411
  %}
7412
  ins_pipe(ialu_cconly_reg_reg);
7413
%}
7414

7415
instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{
7416
  match(Set icc (CmpI op1 op2));
7417
  effect( DEF icc, USE op1 );
7418

7419
  size(4);
7420
  format %{ "cmn_32 $op1,-$op2\t! int" %}
7421
  ins_encode %{
7422
    __ cmn_32($op1$$Register, -$op2$$constant);
7423
  %}
7424
  ins_pipe(ialu_cconly_reg_imm);
7425
%}
7426

7427
instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{
7428
  match(Set icc (CmpI op1 op2));
7429
  effect( DEF icc, USE op1 );
7430

7431
  size(4);
7432
  format %{ "cmp_32 $op1,$op2\t! int" %}
7433
  ins_encode %{
7434
    __ cmp_32($op1$$Register, $op2$$constant);
7435
  %}
7436
  ins_pipe(ialu_cconly_reg_imm);
7437
%}
7438

7439
instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{
7440
  match(Set icc (CmpI (AndI op1 op2) zero));
7441
  size(4);
7442
  format %{ "tst_32 $op2,$op1" %}
7443

7444
  ins_encode %{
7445
    __ tst_32($op1$$Register, $op2$$Register);
7446
  %}
7447
  ins_pipe(ialu_cconly_reg_reg_zero);
7448
%}
7449

7450
instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7451
  match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7452
  size(4);
7453
  format %{ "TST   $op2,$op1<<$op3" %}
7454

7455
  ins_encode %{
7456
    __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register));
7457
  %}
7458
  ins_pipe(ialu_cconly_reg_reg_zero);
7459
%}
7460

7461
instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7462
  match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7463
  size(4);
7464
  format %{ "tst_32 $op2,$op1<<$op3" %}
7465

7466
  ins_encode %{
7467
    __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant));
7468
  %}
7469
  ins_pipe(ialu_cconly_reg_reg_zero);
7470
%}
7471

7472
instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7473
  match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7474
  size(4);
7475
  format %{ "TST   $op2,$op1<<$op3" %}
7476

7477
  ins_encode %{
7478
    __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register));
7479
  %}
7480
  ins_pipe(ialu_cconly_reg_reg_zero);
7481
%}
7482

7483
instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7484
  match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7485
  size(4);
7486
  format %{ "tst_32 $op2,$op1<<$op3" %}
7487

7488
  ins_encode %{
7489
    __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant));
7490
  %}
7491
  ins_pipe(ialu_cconly_reg_reg_zero);
7492
%}
7493

7494
instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7495
  match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7496
  size(4);
7497
  format %{ "TST   $op2,$op1<<$op3" %}
7498

7499
  ins_encode %{
7500
    __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register));
7501
  %}
7502
  ins_pipe(ialu_cconly_reg_reg_zero);
7503
%}
7504

7505
instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7506
  match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7507
  size(4);
7508
  format %{ "tst_32 $op2,$op1<<$op3" %}
7509

7510
  ins_encode %{
7511
    __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant));
7512
  %}
7513
  ins_pipe(ialu_cconly_reg_reg_zero);
7514
%}
7515

7516
instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{
7517
  match(Set icc (CmpI (AndI op1 op2) zero));
7518
  size(4);
7519
  format %{ "tst_32 $op2,$op1" %}
7520

7521
  ins_encode %{
7522
    __ tst_32($op1$$Register, $op2$$constant);
7523
  %}
7524
  ins_pipe(ialu_cconly_reg_imm_zero);
7525
%}
7526

7527
instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7528
  match(Set xcc (CmpL op1 op2));
7529
  effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7530

7531
  size(8);
7532
  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! long\n\t"
7533
            "SBCS    $tmp,$op1.hi,$op2.hi" %}
7534
  ins_encode %{
7535
    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7536
    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7537
  %}
7538
  ins_pipe(ialu_cconly_reg_reg);
7539
%}
7540

7541
instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7542
  match(Set xcc (CmpUL op1 op2));
7543
  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7544

7545
  size(8);
7546
  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
7547
            "SBCS    $tmp,$op1.hi,$op2.hi" %}
7548
  ins_encode %{
7549
    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7550
    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7551
  %}
7552
  ins_pipe(ialu_cconly_reg_reg);
7553
%}
7554

7555
instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
7556
  match(Set xcc (CmpL op1 op2));
7557
  effect( DEF xcc, USE op1, USE op2 );
7558

7559
  size(8);
7560
  format %{ "TEQ    $op1.hi,$op2.hi\t\t! long\n\t"
7561
            "TEQ.eq $op1.lo,$op2.lo" %}
7562
  ins_encode %{
7563
    __ teq($op1$$Register->successor(), $op2$$Register->successor());
7564
    __ teq($op1$$Register, $op2$$Register, eq);
7565
  %}
7566
  ins_pipe(ialu_cconly_reg_reg);
7567
%}
7568

7569
instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7570
  match(Set xcc (CmpL op1 op2));
7571
  effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7572

7573
  size(8);
7574
  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! long\n\t"
7575
            "SBCS    $tmp,$op2.hi,$op1.hi" %}
7576
  ins_encode %{
7577
    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7578
    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7579
  %}
7580
  ins_pipe(ialu_cconly_reg_reg);
7581
%}
7582

7583
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7584
// (hi($con$$constant), lo($con$$constant)) becomes
7585
instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7586
  match(Set xcc (CmpL op1 con));
7587
  effect( DEF xcc, USE op1, USE con, TEMP tmp );
7588

7589
  size(8);
7590
  format %{ "SUBS    $tmp,$op1.low,$con\t\t! long\n\t"
7591
            "SBCS    $tmp,$op1.hi,0" %}
7592
  ins_encode %{
7593
    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7594
    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7595
  %}
7596

7597
  ins_pipe(ialu_cconly_reg_reg);
7598
%}
7599

7600
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7601
// (hi($con$$constant), lo($con$$constant)) becomes
7602
instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{
7603
  match(Set xcc (CmpL op1 con));
7604
  effect( DEF xcc, USE op1, USE con );
7605

7606
  size(8);
7607
  format %{ "TEQ    $op1.hi,0\t\t! long\n\t"
7608
            "TEQ.eq $op1.lo,$con" %}
7609
  ins_encode %{
7610
    __ teq($op1$$Register->successor(), 0);
7611
    __ teq($op1$$Register, $con$$constant, eq);
7612
  %}
7613

7614
  ins_pipe(ialu_cconly_reg_reg);
7615
%}
7616

7617
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7618
// (hi($con$$constant), lo($con$$constant)) becomes
7619
instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7620
  match(Set xcc (CmpL op1 con));
7621
  effect( DEF xcc, USE op1, USE con, TEMP tmp );
7622

7623
  size(8);
7624
  format %{ "RSBS    $tmp,$op1.low,$con\t\t! long\n\t"
7625
            "RSCS    $tmp,$op1.hi,0" %}
7626
  ins_encode %{
7627
    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7628
    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7629
  %}
7630

7631
  ins_pipe(ialu_cconly_reg_reg);
7632
%}
7633

7634
instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
7635
  match(Set xcc (CmpUL op1 op2));
7636
  effect(DEF xcc, USE op1, USE op2);
7637

7638
  size(8);
7639
  format %{ "TEQ    $op1.hi,$op2.hi\t\t! unsigned long\n\t"
7640
            "TEQ.eq $op1.lo,$op2.lo" %}
7641
  ins_encode %{
7642
    __ teq($op1$$Register->successor(), $op2$$Register->successor());
7643
    __ teq($op1$$Register, $op2$$Register, eq);
7644
  %}
7645
  ins_pipe(ialu_cconly_reg_reg);
7646
%}
7647

7648
instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7649
  match(Set xcc (CmpUL op1 op2));
7650
  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7651

7652
  size(8);
7653
  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
7654
            "SBCS    $tmp,$op2.hi,$op1.hi" %}
7655
  ins_encode %{
7656
    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7657
    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7658
  %}
7659
  ins_pipe(ialu_cconly_reg_reg);
7660
%}
7661

7662
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7663
// (hi($con$$constant), lo($con$$constant)) becomes
7664
instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7665
  match(Set xcc (CmpUL op1 con));
7666
  effect(DEF xcc, USE op1, USE con, TEMP tmp);
7667

7668
  size(8);
7669
  format %{ "SUBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7670
            "SBCS    $tmp,$op1.hi,0" %}
7671
  ins_encode %{
7672
    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7673
    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7674
  %}
7675

7676
  ins_pipe(ialu_cconly_reg_reg);
7677
%}
7678

7679
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7680
// (hi($con$$constant), lo($con$$constant)) becomes
7681
instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
7682
  match(Set xcc (CmpUL op1 con));
7683
  effect(DEF xcc, USE op1, USE con);
7684

7685
  size(8);
7686
  format %{ "TEQ    $op1.hi,0\t\t! unsigned long\n\t"
7687
            "TEQ.eq $op1.lo,$con" %}
7688
  ins_encode %{
7689
    __ teq($op1$$Register->successor(), 0);
7690
    __ teq($op1$$Register, $con$$constant, eq);
7691
  %}
7692

7693
  ins_pipe(ialu_cconly_reg_reg);
7694
%}
7695

7696
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
7697
// (hi($con$$constant), lo($con$$constant)) becomes
7698
instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7699
  match(Set xcc (CmpUL op1 con));
7700
  effect(DEF xcc, USE op1, USE con, TEMP tmp);
7701

7702
  size(8);
7703
  format %{ "RSBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7704
            "RSCS    $tmp,$op1.hi,0" %}
7705
  ins_encode %{
7706
    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7707
    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7708
  %}
7709

7710
  ins_pipe(ialu_cconly_reg_reg);
7711
%}
7712

7713
/* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
7714
/*   match(Set xcc (CmpL (AndL op1 op2) zero)); */
7715
/*   ins_encode %{ */
7716
/*     __ stop("testL_reg_reg unimplemented"); */
7717
/*   %} */
7718
/*   ins_pipe(ialu_cconly_reg_reg); */
7719
/* %} */
7720

7721
/* // useful for checking the alignment of a pointer: */
7722
/* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */
7723
/*   match(Set xcc (CmpL (AndL op1 con) zero)); */
7724
/*   ins_encode %{ */
7725
/*     __ stop("testL_reg_con unimplemented"); */
7726
/*   %} */
7727
/*   ins_pipe(ialu_cconly_reg_reg); */
7728
/* %} */
7729

7730
instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{
7731
  match(Set icc (CmpU op1 op2));
7732

7733
  size(4);
7734
  format %{ "cmp_32 $op1,$op2\t! unsigned" %}
7735
  ins_encode %{
7736
    __ cmp_32($op1$$Register, $op2$$constant);
7737
  %}
7738
  ins_pipe(ialu_cconly_reg_imm);
7739
%}
7740

7741
// Compare Pointers
7742
instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
7743
  match(Set pcc (CmpP op1 op2));
7744

7745
  size(4);
7746
  format %{ "CMP    $op1,$op2\t! ptr" %}
7747
  ins_encode %{
7748
    __ cmp($op1$$Register, $op2$$Register);
7749
  %}
7750
  ins_pipe(ialu_cconly_reg_reg);
7751
%}
7752

7753
instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{
7754
  match(Set pcc (CmpP op1 op2));
7755

7756
  size(4);
7757
  format %{ "CMP    $op1,$op2\t! ptr" %}
7758
  ins_encode %{
7759
    assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?");
7760
    __ cmp($op1$$Register, $op2$$constant);
7761
  %}
7762
  ins_pipe(ialu_cconly_reg_imm);
7763
%}
7764

7765
//----------Max and Min--------------------------------------------------------
7766
// Min Instructions
7767
// Conditional move for min
7768
instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{
7769
  effect( USE_DEF op2, USE op1, USE icc );
7770

7771
  size(4);
7772
  format %{ "MOV.lt  $op2,$op1\t! min" %}
7773
  ins_encode %{
7774
    __ mov($op2$$Register, $op1$$Register, lt);
7775
  %}
7776
  ins_pipe(ialu_reg_flags);
7777
%}
7778

7779
// Min Register with Register.
7780
instruct minI_eReg(iRegI op1, iRegI op2) %{
7781
  match(Set op2 (MinI op1 op2));
7782
  ins_cost(DEFAULT_COST*2);
7783
  expand %{
7784
    flagsReg icc;
7785
    compI_iReg(icc,op1,op2);
7786
    cmovI_reg_lt(op2,op1,icc);
7787
  %}
7788
%}
7789

7790
// Max Instructions
7791
// Conditional move for max
7792
instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{
7793
  effect( USE_DEF op2, USE op1, USE icc );
7794
  format %{ "MOV.gt  $op2,$op1\t! max" %}
7795
  ins_encode %{
7796
    __ mov($op2$$Register, $op1$$Register, gt);
7797
  %}
7798
  ins_pipe(ialu_reg_flags);
7799
%}
7800

7801
// Max Register with Register
7802
instruct maxI_eReg(iRegI op1, iRegI op2) %{
7803
  match(Set op2 (MaxI op1 op2));
7804
  ins_cost(DEFAULT_COST*2);
7805
  expand %{
7806
    flagsReg icc;
7807
    compI_iReg(icc,op1,op2);
7808
    cmovI_reg_gt(op2,op1,icc);
7809
  %}
7810
%}
7811

7812

7813
//----------Float Compares----------------------------------------------------
7814
// Compare floating, generate condition code
7815
instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{
7816
  match(Set icc (CmpF src1 src2));
7817
  effect(KILL fcc);
7818

7819
  size(8);
7820
  format %{ "FCMPs  $src1,$src2\n\t"
7821
            "FMSTAT" %}
7822
  ins_encode %{
7823
    __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7824
    __ fmstat();
7825
  %}
7826
  ins_pipe(faddF_fcc_reg_reg_zero);
7827
%}
7828

7829
instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{
7830
  match(Set icc (CmpF src1 src2));
7831
  effect(KILL fcc);
7832

7833
  size(8);
7834
  format %{ "FCMPs  $src1,$src2\n\t"
7835
            "FMSTAT" %}
7836
  ins_encode %{
7837
    __ fcmpzs($src1$$FloatRegister);
7838
    __ fmstat();
7839
  %}
7840
  ins_pipe(faddF_fcc_reg_reg_zero);
7841
%}
7842

7843
instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{
7844
  match(Set icc (CmpD src1 src2));
7845
  effect(KILL fcc);
7846

7847
  size(8);
7848
  format %{ "FCMPd  $src1,$src2 \n\t"
7849
            "FMSTAT" %}
7850
  ins_encode %{
7851
    __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7852
    __ fmstat();
7853
  %}
7854
  ins_pipe(faddD_fcc_reg_reg_zero);
7855
%}
7856

7857
instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{
7858
  match(Set icc (CmpD src1 src2));
7859
  effect(KILL fcc);
7860

7861
  size(8);
7862
  format %{ "FCMPZd  $src1,$src2 \n\t"
7863
            "FMSTAT" %}
7864
  ins_encode %{
7865
    __ fcmpzd($src1$$FloatRegister);
7866
    __ fmstat();
7867
  %}
7868
  ins_pipe(faddD_fcc_reg_reg_zero);
7869
%}
7870

7871
// Compare floating, generate -1,0,1
7872
instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{
7873
  match(Set dst (CmpF3 src1 src2));
7874
  effect(KILL fcc);
7875
  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7876
  size(20);
7877
  // same number of instructions as code using conditional moves but
7878
  // doesn't kill integer condition register
7879
  format %{ "FCMPs  $dst,$src1,$src2 \n\t"
7880
            "VMRS   $dst, FPSCR \n\t"
7881
            "OR     $dst, $dst, 0x08000000 \n\t"
7882
            "EOR    $dst, $dst, $dst << 3 \n\t"
7883
            "MOV    $dst, $dst >> 30" %}
7884
  ins_encode %{
7885
    __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7886
    __ floating_cmp($dst$$Register);
7887
  %}
7888
  ins_pipe( floating_cmp );
7889
%}
7890

7891
instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{
7892
  match(Set dst (CmpF3 src1 src2));
7893
  effect(KILL fcc);
7894
  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7895
  size(20);
7896
  // same number of instructions as code using conditional moves but
7897
  // doesn't kill integer condition register
7898
  format %{ "FCMPZs $dst,$src1,$src2 \n\t"
7899
            "VMRS   $dst, FPSCR \n\t"
7900
            "OR     $dst, $dst, 0x08000000 \n\t"
7901
            "EOR    $dst, $dst, $dst << 3 \n\t"
7902
            "MOV    $dst, $dst >> 30" %}
7903
  ins_encode %{
7904
    __ fcmpzs($src1$$FloatRegister);
7905
    __ floating_cmp($dst$$Register);
7906
  %}
7907
  ins_pipe( floating_cmp );
7908
%}
7909

7910
instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{
7911
  match(Set dst (CmpD3 src1 src2));
7912
  effect(KILL fcc);
7913
  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7914
  size(20);
7915
  // same number of instructions as code using conditional moves but
7916
  // doesn't kill integer condition register
7917
  format %{ "FCMPd  $dst,$src1,$src2 \n\t"
7918
            "VMRS   $dst, FPSCR \n\t"
7919
            "OR     $dst, $dst, 0x08000000 \n\t"
7920
            "EOR    $dst, $dst, $dst << 3 \n\t"
7921
            "MOV    $dst, $dst >> 30" %}
7922
  ins_encode %{
7923
    __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7924
    __ floating_cmp($dst$$Register);
7925
  %}
7926
  ins_pipe( floating_cmp );
7927
%}
7928

7929
instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{
7930
  match(Set dst (CmpD3 src1 src2));
7931
  effect(KILL fcc);
7932
  ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7933
  size(20);
7934
  // same number of instructions as code using conditional moves but
7935
  // doesn't kill integer condition register
7936
  format %{ "FCMPZd $dst,$src1,$src2 \n\t"
7937
            "VMRS   $dst, FPSCR \n\t"
7938
            "OR     $dst, $dst, 0x08000000 \n\t"
7939
            "EOR    $dst, $dst, $dst << 3 \n\t"
7940
            "MOV    $dst, $dst >> 30" %}
7941
  ins_encode %{
7942
    __ fcmpzd($src1$$FloatRegister);
7943
    __ floating_cmp($dst$$Register);
7944
  %}
7945
  ins_pipe( floating_cmp );
7946
%}
7947

7948
//----------Branches---------------------------------------------------------
7949
// Jump
7950
// (compare 'operand indIndex' and 'instruct addP_reg_reg' above)
7951
// FIXME
7952
instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{
7953
  match(Jump switch_val);
7954
  effect(TEMP tmp);
7955
  ins_cost(350);
7956
  format %{  "ADD    $tmp, $constanttablebase, $switch_val\n\t"
7957
             "LDR    $tmp,[$tmp + $constantoffset]\n\t"
7958
             "BX     $tmp" %}
7959
  size(20);
7960
  ins_encode %{
7961
    Register table_reg;
7962
    Register label_reg = $tmp$$Register;
7963
    if (constant_offset() == 0) {
7964
      table_reg = $constanttablebase;
7965
      __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7966
    } else {
7967
      table_reg = $tmp$$Register;
7968
      int offset = $constantoffset;
7969
      if (is_memoryP(offset)) {
7970
        __ add(table_reg, $constanttablebase, $switch_val$$Register);
7971
        __ ldr(label_reg, Address(table_reg, offset));
7972
      } else {
7973
        __ mov_slow(table_reg, $constantoffset);
7974
        __ add(table_reg, $constanttablebase, table_reg);
7975
        __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7976
      }
7977
    }
7978
    __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor?
7979
    //    __ ldr(PC, Address($table$$Register, $switch_val$$Register));
7980
  %}
7981
  ins_pipe(ialu_reg_reg);
7982
%}
7983

7984
// // Direct Branch.
7985
instruct branch(label labl) %{
7986
  match(Goto);
7987
  effect(USE labl);
7988

7989
  size(4);
7990
  ins_cost(BRANCH_COST);
7991
  format %{ "B     $labl" %}
7992
  ins_encode %{
7993
    __ b(*($labl$$label));
7994
  %}
7995
  ins_pipe(br);
7996
%}
7997

7998
// Conditional Direct Branch
7999
instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
8000
  match(If cmp icc);
8001
  effect(USE labl);
8002

8003
  size(4);
8004
  ins_cost(BRANCH_COST);
8005
  format %{ "B$cmp   $icc,$labl" %}
8006
  ins_encode %{
8007
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8008
  %}
8009
  ins_pipe(br_cc);
8010
%}
8011

8012
#ifdef ARM
8013
instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{
8014
  match(If cmp icc);
8015
  effect(USE labl);
8016
  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8017

8018
  size(4);
8019
  ins_cost(BRANCH_COST);
8020
  format %{ "B$cmp   $icc,$labl" %}
8021
  ins_encode %{
8022
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8023
  %}
8024
  ins_pipe(br_cc);
8025
%}
8026
#endif
8027

8028

8029
instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
8030
  match(If cmp icc);
8031
  effect(USE labl);
8032

8033
  size(4);
8034
  ins_cost(BRANCH_COST);
8035
  format %{ "B$cmp  $icc,$labl" %}
8036
  ins_encode %{
8037
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8038
  %}
8039
  ins_pipe(br_cc);
8040
%}
8041

8042
instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{
8043
  match(If cmp pcc);
8044
  effect(USE labl);
8045

8046
  size(4);
8047
  ins_cost(BRANCH_COST);
8048
  format %{ "B$cmp  $pcc,$labl" %}
8049
  ins_encode %{
8050
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8051
  %}
8052
  ins_pipe(br_cc);
8053
%}
8054

8055
instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{
8056
  match(If cmp xcc);
8057
  effect(USE labl);
8058
  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8059

8060
  size(4);
8061
  ins_cost(BRANCH_COST);
8062
  format %{ "B$cmp  $xcc,$labl" %}
8063
  ins_encode %{
8064
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8065
  %}
8066
  ins_pipe(br_cc);
8067
%}
8068

8069
instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{
8070
  match(If cmp xcc);
8071
  effect(USE labl);
8072
  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8073

8074
  size(4);
8075
  ins_cost(BRANCH_COST);
8076
  format %{ "B$cmp  $xcc,$labl" %}
8077
  ins_encode %{
8078
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8079
  %}
8080
  ins_pipe(br_cc);
8081
%}
8082

8083
instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
8084
  match(If cmp xcc);
8085
  effect(USE labl);
8086
  predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
8087

8088
  size(4);
8089
  ins_cost(BRANCH_COST);
8090
  format %{ "B$cmp  $xcc,$labl" %}
8091
  ins_encode %{
8092
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8093
  %}
8094
  ins_pipe(br_cc);
8095
%}
8096

8097
instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
8098
  match(If cmp xcc);
8099
  effect(USE labl);
8100
  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8101

8102
  size(4);
8103
  ins_cost(BRANCH_COST);
8104
  format %{ "B$cmp  $xcc,$labl" %}
8105
  ins_encode %{
8106
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8107
  %}
8108
  ins_pipe(br_cc);
8109
%}
8110

8111
instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
8112
  match(If cmp xcc);
8113
  effect(USE labl);
8114
  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8115

8116
  size(4);
8117
  ins_cost(BRANCH_COST);
8118
  format %{ "B$cmp  $xcc,$labl" %}
8119
  ins_encode %{
8120
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8121
  %}
8122
  ins_pipe(br_cc);
8123
%}
8124

8125
instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
8126
  match(If cmp xcc);
8127
  effect(USE labl);
8128
  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
8129

8130
  size(4);
8131
  ins_cost(BRANCH_COST);
8132
  format %{ "B$cmp  $xcc,$labl" %}
8133
  ins_encode %{
8134
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8135
  %}
8136
  ins_pipe(br_cc);
8137
%}
8138

8139
instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
8140
  match(CountedLoopEnd cmp icc);
8141
  effect(USE labl);
8142

8143
  size(4);
8144
  ins_cost(BRANCH_COST);
8145
  format %{ "B$cmp   $icc,$labl\t! Loop end" %}
8146
  ins_encode %{
8147
    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8148
  %}
8149
  ins_pipe(br_cc);
8150
%}
8151

8152
// instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{
8153
//   match(CountedLoopEnd cmp icc);
8154
//   ins_pipe(br_cc);
8155
// %}
8156

8157
// ============================================================================
8158
// Long Compare
8159
//
8160
// Currently we hold longs in 2 registers.  Comparing such values efficiently
8161
// is tricky.  The flavor of compare used depends on whether we are testing
8162
// for LT, LE, or EQ.  For a simple LT test we can check just the sign bit.
8163
// The GE test is the negated LT test.  The LE test can be had by commuting
8164
// the operands (yielding a GE test) and then negating; negate again for the
8165
// GT test.  The EQ test is done by ORcc'ing the high and low halves, and the
8166
// NE test is negated from that.
8167

8168
// Due to a shortcoming in the ADLC, it mixes up expressions like:
8169
// (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)).  Note the
8170
// difference between 'Y' and '0L'.  The tree-matches for the CmpI sections
8171
// are collapsed internally in the ADLC's dfa-gen code.  The match for
8172
// (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
8173
// foo match ends up with the wrong leaf.  One fix is to not match both
8174
// reg-reg and reg-zero forms of long-compare.  This is unfortunate because
8175
// both forms beat the trinary form of long-compare and both are very useful
8176
// on Intel which has so few registers.
8177

8178
// instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
8179
//   match(If cmp xcc);
8180
//   ins_pipe(br_cc);
8181
// %}
8182

8183
// Manifest a CmpL3 result in an integer register.  Very painful.
8184
// This is the test to avoid.
8185
instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
8186
  match(Set dst (CmpL3 src1 src2) );
8187
  effect( KILL ccr );
8188
  ins_cost(6*DEFAULT_COST); // FIXME
8189
  size(32);
8190
  format %{
8191
      "CMP    $src1.hi, $src2.hi\t\t! long\n"
8192
    "\tMOV.gt $dst, 1\n"
8193
    "\tmvn.lt $dst, 0\n"
8194
    "\tB.ne   done\n"
8195
    "\tSUBS   $dst, $src1.lo, $src2.lo\n"
8196
    "\tMOV.hi $dst, 1\n"
8197
    "\tmvn.lo $dst, 0\n"
8198
    "done:"     %}
8199
  ins_encode %{
8200
    Label done;
8201
    __ cmp($src1$$Register->successor(), $src2$$Register->successor());
8202
    __ mov($dst$$Register, 1, gt);
8203
    __ mvn($dst$$Register, 0, lt);
8204
    __ b(done, ne);
8205
    __ subs($dst$$Register, $src1$$Register, $src2$$Register);
8206
    __ mov($dst$$Register, 1, hi);
8207
    __ mvn($dst$$Register, 0, lo);
8208
    __ bind(done);
8209
  %}
8210
  ins_pipe(cmpL_reg);
8211
%}
8212

8213
// Conditional move
8214
instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{
8215
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8216
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8217

8218
  ins_cost(150);
8219
  size(8);
8220
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8221
            "MOV$cmp  $dst,$src.hi" %}
8222
  ins_encode %{
8223
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8224
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8225
  %}
8226
  ins_pipe(ialu_reg);
8227
%}
8228

8229
instruct cmovLL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{
8230
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8231
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8232

8233
  ins_cost(150);
8234
  size(8);
8235
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8236
            "MOV$cmp  $dst,$src.hi" %}
8237
  ins_encode %{
8238
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8239
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8240
  %}
8241
  ins_pipe(ialu_reg);
8242
%}
8243

8244
instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{
8245
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8246
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8247

8248
  ins_cost(150);
8249
  size(8);
8250
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8251
            "MOV$cmp  $dst,$src.hi" %}
8252
  ins_encode %{
8253
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8254
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8255
  %}
8256
  ins_pipe(ialu_reg);
8257
%}
8258

8259
instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{
8260
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8261
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8262

8263
  ins_cost(150);
8264
  size(8);
8265
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8266
            "MOV$cmp  $dst,$src.hi" %}
8267
  ins_encode %{
8268
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8269
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8270
  %}
8271
  ins_pipe(ialu_reg);
8272
%}
8273

8274
instruct cmovLL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{
8275
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8276
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8277

8278
  ins_cost(150);
8279
  size(8);
8280
  format %{ "MOV$cmp  $dst.lo,$src.lo\t! long\n\t"
8281
            "MOV$cmp  $dst,$src.hi" %}
8282
  ins_encode %{
8283
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8284
    __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8285
  %}
8286
  ins_pipe(ialu_reg);
8287
%}
8288

8289
instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{
8290
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8291
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8292
  ins_cost(140);
8293
  size(8);
8294
  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8295
            "MOV$cmp  $dst,0" %}
8296
  ins_encode %{
8297
    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8298
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8299
  %}
8300
  ins_pipe(ialu_imm);
8301
%}
8302

8303
instruct cmovLL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{
8304
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8305
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8306
  ins_cost(140);
8307
  size(8);
8308
  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8309
            "MOV$cmp  $dst,0" %}
8310
  ins_encode %{
8311
    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8312
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8313
  %}
8314
  ins_pipe(ialu_imm);
8315
%}
8316

8317
instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{
8318
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8319
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8320
  ins_cost(140);
8321
  size(8);
8322
  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8323
            "MOV$cmp  $dst,0" %}
8324
  ins_encode %{
8325
    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8326
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8327
  %}
8328
  ins_pipe(ialu_imm);
8329
%}
8330

8331
instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{
8332
  match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8333
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8334
  ins_cost(140);
8335
  size(8);
8336
  format %{ "MOV$cmp  $dst.lo,0\t! long\n\t"
8337
            "MOV$cmp  $dst,0" %}
8338
  ins_encode %{
8339
    __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8340
    __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8341
  %}
8342
  ins_pipe(ialu_imm);
8343
%}
8344

8345
instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{
8346
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8347
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8348

8349
  ins_cost(150);
8350
  size(4);
8351
  format %{ "MOV$cmp  $dst,$src" %}
8352
  ins_encode %{
8353
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8354
  %}
8355
  ins_pipe(ialu_reg);
8356
%}
8357

8358
instruct cmovIL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, iRegI src) %{
8359
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8360
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8361

8362
  ins_cost(150);
8363
  size(4);
8364
  format %{ "MOV$cmp  $dst,$src" %}
8365
  ins_encode %{
8366
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8367
  %}
8368
  ins_pipe(ialu_reg);
8369
%}
8370

8371
instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{
8372
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8373
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8374

8375
  ins_cost(150);
8376
  size(4);
8377
  format %{ "MOV$cmp  $dst,$src" %}
8378
  ins_encode %{
8379
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8380
  %}
8381
  ins_pipe(ialu_reg);
8382
%}
8383

8384
instruct cmovIL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, iRegI src) %{
8385
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8386
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8387

8388
  ins_cost(150);
8389
  size(4);
8390
  format %{ "MOV$cmp  $dst,$src" %}
8391
  ins_encode %{
8392
   __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8393
  %}
8394
  ins_pipe(ialu_reg);
8395
%}
8396

8397
instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{
8398
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8399
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8400

8401
  ins_cost(150);
8402
  size(4);
8403
  format %{ "MOV$cmp  $dst,$src" %}
8404
  ins_encode %{
8405
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8406
  %}
8407
  ins_pipe(ialu_reg);
8408
%}
8409

8410
instruct cmovIL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, iRegI src) %{
8411
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8412
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8413

8414
  ins_cost(150);
8415
  size(4);
8416
  format %{ "MOV$cmp  $dst,$src" %}
8417
  ins_encode %{
8418
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8419
  %}
8420
  ins_pipe(ialu_reg);
8421
%}
8422

8423
instruct cmovIL_imm16_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{
8424
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8425
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8426

8427
  ins_cost(140);
8428
  size(4);
8429
  format %{ "MOVW$cmp  $dst,$src" %}
8430
  ins_encode %{
8431
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8432
  %}
8433
  ins_pipe(ialu_imm);
8434
%}
8435

8436
instruct cmovIL_imm16_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immI16 src) %{
8437
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8438
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8439

8440
  ins_cost(140);
8441
  size(4);
8442
  format %{ "MOVW$cmp  $dst,$src" %}
8443
  ins_encode %{
8444
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8445
  %}
8446
  ins_pipe(ialu_imm);
8447
%}
8448

8449
instruct cmovIL_imm16_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{
8450
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8451
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8452

8453
  ins_cost(140);
8454
  size(4);
8455
  format %{ "MOVW$cmp  $dst,$src" %}
8456
  ins_encode %{
8457
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8458
  %}
8459
  ins_pipe(ialu_imm);
8460
%}
8461

8462
instruct cmovIL_imm16_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immI16 src) %{
8463
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8464
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8465

8466
  ins_cost(140);
8467
  size(4);
8468
  format %{ "MOVW$cmp  $dst,$src" %}
8469
  ins_encode %{
8470
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8471
  %}
8472
  ins_pipe(ialu_imm);
8473
%}
8474

8475
instruct cmovIL_imm16_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{
8476
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8477
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8478

8479
  ins_cost(140);
8480
  size(4);
8481
  format %{ "MOVW$cmp  $dst,$src" %}
8482
  ins_encode %{
8483
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8484
  %}
8485
  ins_pipe(ialu_imm);
8486
%}
8487

8488
instruct cmovIL_imm16_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immI16 src) %{
8489
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8490
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8491

8492
  ins_cost(140);
8493
  size(4);
8494
  format %{ "MOVW$cmp  $dst,$src" %}
8495
  ins_encode %{
8496
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8497
  %}
8498
  ins_pipe(ialu_imm);
8499
%}
8500

8501
instruct cmovIL_immMov_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immIMov src) %{
8502
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8503
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8504

8505
  ins_cost(140);
8506
  size(4);
8507
  format %{ "MOV$cmp  $dst,$src" %}
8508
  ins_encode %{
8509
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8510
  %}
8511
  ins_pipe(ialu_imm);
8512
%}
8513

8514
instruct cmovIL_immMov_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immIMov src) %{
8515
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8516
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8517

8518
  ins_cost(140);
8519
  size(4);
8520
  format %{ "MOV$cmp  $dst,$src" %}
8521
  ins_encode %{
8522
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8523
  %}
8524
  ins_pipe(ialu_imm);
8525
%}
8526

8527
instruct cmovIL_immMov_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immIMov src) %{
8528
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8529
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8530

8531
  ins_cost(140);
8532
  size(4);
8533
  format %{ "MOV$cmp  $dst,$src" %}
8534
  ins_encode %{
8535
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8536
  %}
8537
  ins_pipe(ialu_imm);
8538
%}
8539

8540
instruct cmovIL_immMov_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immIMov src) %{
8541
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8542
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8543

8544
  ins_cost(140);
8545
  size(4);
8546
  format %{ "MOV$cmp  $dst,$src" %}
8547
  ins_encode %{
8548
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8549
  %}
8550
  ins_pipe(ialu_imm);
8551
%}
8552

8553
instruct cmovIL_immMov_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immIMov src) %{
8554
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8555
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8556

8557
  ins_cost(140);
8558
  size(4);
8559
  format %{ "MOV$cmp  $dst,$src" %}
8560
  ins_encode %{
8561
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8562
  %}
8563
  ins_pipe(ialu_imm);
8564
%}
8565

8566
instruct cmovIL_immMov_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immIMov src) %{
8567
  match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8568
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8569

8570
  ins_cost(140);
8571
  size(4);
8572
  format %{ "MOV$cmp  $dst,$src" %}
8573
  ins_encode %{
8574
    __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8575
  %}
8576
  ins_pipe(ialu_imm);
8577
%}
8578

8579
instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{
8580
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8581
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8582

8583
  ins_cost(150);
8584
  size(4);
8585
  format %{ "MOV$cmp  $dst,$src" %}
8586
  ins_encode %{
8587
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8588
  %}
8589
  ins_pipe(ialu_reg);
8590
%}
8591

8592
instruct cmovPL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, iRegP src) %{
8593
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8594
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8595

8596
  ins_cost(150);
8597
  size(4);
8598
  format %{ "MOV$cmp  $dst,$src" %}
8599
  ins_encode %{
8600
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8601
  %}
8602
  ins_pipe(ialu_reg);
8603
%}
8604

8605
instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{
8606
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8607
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8608

8609
  ins_cost(150);
8610
  size(4);
8611
  format %{ "MOV$cmp  $dst,$src" %}
8612
  ins_encode %{
8613
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8614
  %}
8615
  ins_pipe(ialu_reg);
8616
%}
8617

8618
instruct cmovPL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, iRegP src) %{
8619
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8620
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8621

8622
  ins_cost(150);
8623
  size(4);
8624
  format %{ "MOV$cmp  $dst,$src" %}
8625
  ins_encode %{
8626
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8627
  %}
8628
  ins_pipe(ialu_reg);
8629
%}
8630

8631
instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{
8632
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8633
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8634

8635
  ins_cost(150);
8636
  size(4);
8637
  format %{ "MOV$cmp  $dst,$src" %}
8638
  ins_encode %{
8639
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8640
  %}
8641
  ins_pipe(ialu_reg);
8642
%}
8643

8644
instruct cmovPL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, iRegP src) %{
8645
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8646
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8647

8648
  ins_cost(150);
8649
  size(4);
8650
  format %{ "MOV$cmp  $dst,$src" %}
8651
  ins_encode %{
8652
    __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8653
  %}
8654
  ins_pipe(ialu_reg);
8655
%}
8656

8657
instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{
8658
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8659
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8660

8661
  ins_cost(140);
8662
  size(4);
8663
  format %{ "MOVW$cmp  $dst,$src" %}
8664
  ins_encode %{
8665
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8666
  %}
8667
  ins_pipe(ialu_imm);
8668
%}
8669

8670
instruct cmovPL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, immP0 src) %{
8671
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8672
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8673

8674
  ins_cost(140);
8675
  size(4);
8676
  format %{ "MOVW$cmp  $dst,$src" %}
8677
  ins_encode %{
8678
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8679
  %}
8680
  ins_pipe(ialu_imm);
8681
%}
8682

8683
instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{
8684
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8685
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8686

8687
  ins_cost(140);
8688
  size(4);
8689
  format %{ "MOVW$cmp  $dst,$src" %}
8690
  ins_encode %{
8691
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8692
  %}
8693
  ins_pipe(ialu_imm);
8694
%}
8695

8696
instruct cmovPL_imm_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, immP0 src) %{
8697
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8698
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8699

8700
  ins_cost(140);
8701
  size(4);
8702
  format %{ "MOVW$cmp  $dst,$src" %}
8703
  ins_encode %{
8704
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8705
  %}
8706
  ins_pipe(ialu_imm);
8707
%}
8708

8709
instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{
8710
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8711
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8712

8713
  ins_cost(140);
8714
  size(4);
8715
  format %{ "MOVW$cmp  $dst,$src" %}
8716
  ins_encode %{
8717
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8718
  %}
8719
  ins_pipe(ialu_imm);
8720
%}
8721

8722
instruct cmovPL_imm_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, immP0 src) %{
8723
  match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8724
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8725

8726
  ins_cost(140);
8727
  size(4);
8728
  format %{ "MOVW$cmp  $dst,$src" %}
8729
  ins_encode %{
8730
    __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8731
  %}
8732
  ins_pipe(ialu_imm);
8733
%}
8734

8735
instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{
8736
  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8737
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8738
  ins_cost(150);
8739
  size(4);
8740
  format %{ "FCPYS$cmp $dst,$src" %}
8741
  ins_encode %{
8742
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8743
  %}
8744
  ins_pipe(int_conditional_float_move);
8745
%}
8746

8747
instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{
8748
  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8749
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8750
  ins_cost(150);
8751
  size(4);
8752
  format %{ "FCPYS$cmp $dst,$src" %}
8753
  ins_encode %{
8754
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8755
  %}
8756
  ins_pipe(int_conditional_float_move);
8757
%}
8758

8759
instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{
8760
  match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8761
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8762
  ins_cost(150);
8763
  size(4);
8764
  format %{ "FCPYS$cmp $dst,$src" %}
8765
  ins_encode %{
8766
    __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8767
  %}
8768
  ins_pipe(int_conditional_float_move);
8769
%}
8770

8771
instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{
8772
  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8773
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8774

8775
  ins_cost(150);
8776
  size(4);
8777
  format %{ "FCPYD$cmp $dst,$src" %}
8778
  ins_encode %{
8779
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8780
  %}
8781
  ins_pipe(int_conditional_float_move);
8782
%}
8783

8784
instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{
8785
  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8786
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8787

8788
  ins_cost(150);
8789
  size(4);
8790
  format %{ "FCPYD$cmp $dst,$src" %}
8791
  ins_encode %{
8792
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8793
  %}
8794
  ins_pipe(int_conditional_float_move);
8795
%}
8796

8797
instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{
8798
  match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8799
  predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8800

8801
  ins_cost(150);
8802
  size(4);
8803
  format %{ "FCPYD$cmp $dst,$src" %}
8804
  ins_encode %{
8805
    __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8806
  %}
8807
  ins_pipe(int_conditional_float_move);
8808
%}
8809

8810
// ============================================================================
8811
// Safepoint Instruction
8812
// rather than KILL R12, it would be better to use any reg as
8813
// TEMP. Can't do that at this point because it crashes the compiler
8814
instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
8815
  match(SafePoint poll);
8816
  effect(USE poll, KILL tmp, KILL icc);
8817

8818
  size(4);
8819
  format %{ "LDR   $tmp,[$poll]\t! Safepoint: poll for GC" %}
8820
  ins_encode %{
8821
    __ relocate(relocInfo::poll_type);
8822
    __ ldr($tmp$$Register, Address($poll$$Register));
8823
  %}
8824
  ins_pipe(loadPollP);
8825
%}
8826

8827

8828
// ============================================================================
8829
// Call Instructions
8830
// Call Java Static Instruction
8831
instruct CallStaticJavaDirect( method meth ) %{
8832
  match(CallStaticJava);
8833
  predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
8834
  effect(USE meth);
8835

8836
  ins_cost(CALL_COST);
8837
  format %{ "CALL,static ==> " %}
8838
  ins_encode( SetInstMark, Java_Static_Call( meth ), call_epilog, ClearInstMark );
8839
  ins_pipe(simple_call);
8840
%}
8841

8842
// Call Java Static Instruction (method handle version)
8843
instruct CallStaticJavaHandle( method meth ) %{
8844
  match(CallStaticJava);
8845
  predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
8846
  effect(USE meth);
8847
  // FP is saved by all callees (for interpreter stack correction).
8848
  // We use it here for a similar purpose, in {preserve,restore}_FP.
8849

8850
  ins_cost(CALL_COST);
8851
  format %{ "CALL,static/MethodHandle ==> " %}
8852
  ins_encode( SetInstMark, preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog, ClearInstMark );
8853
  ins_pipe(simple_call);
8854
%}
8855

8856
// Call Java Dynamic Instruction
8857
instruct CallDynamicJavaDirect( method meth ) %{
8858
  match(CallDynamicJava);
8859
  effect(USE meth);
8860

8861
  ins_cost(CALL_COST);
8862
  format %{ "MOV_OOP    (empty),R_R8\n\t"
8863
            "CALL,dynamic  ; NOP ==> " %}
8864
  ins_encode( SetInstMark, Java_Dynamic_Call( meth ), call_epilog, ClearInstMark );
8865
  ins_pipe(call);
8866
%}
8867

8868
// Call Runtime Instruction
8869
instruct CallRuntimeDirect(method meth) %{
8870
  match(CallRuntime);
8871
  effect(USE meth);
8872
  ins_cost(CALL_COST);
8873
  format %{ "CALL,runtime" %}
8874
  ins_encode( SetInstMark, Java_To_Runtime( meth ),
8875
              call_epilog, ClearInstMark );
8876
  ins_pipe(simple_call);
8877
%}
8878

8879
// Call runtime without safepoint - same as CallRuntime
8880
instruct CallLeafDirect(method meth) %{
8881
  match(CallLeaf);
8882
  effect(USE meth);
8883
  ins_cost(CALL_COST);
8884
  format %{ "CALL,runtime leaf" %}
8885
  // TODO: need save_last_PC here?
8886
  ins_encode( SetInstMark, Java_To_Runtime( meth ),
8887
              call_epilog, ClearInstMark );
8888
  ins_pipe(simple_call);
8889
%}
8890

8891
// Call runtime without safepoint - same as CallLeaf
8892
instruct CallLeafNoFPDirect(method meth) %{
8893
  match(CallLeafNoFP);
8894
  effect(USE meth);
8895
  ins_cost(CALL_COST);
8896
  format %{ "CALL,runtime leaf nofp" %}
8897
  // TODO: need save_last_PC here?
8898
  ins_encode( SetInstMark, Java_To_Runtime( meth ),
8899
              call_epilog, ClearInstMark );
8900
  ins_pipe(simple_call);
8901
%}
8902

8903
// Tail Call; Jump from runtime stub to Java code.
8904
// Also known as an 'interprocedural jump'.
8905
// Target of jump will eventually return to caller.
8906
// TailJump below removes the return address.
8907
instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{
8908
  match(TailCall jump_target method_ptr);
8909

8910
  ins_cost(CALL_COST);
8911
  format %{ "MOV    Rexception_pc, LR\n\t"
8912
            "jump   $jump_target  \t! $method_ptr holds method" %}
8913
  ins_encode %{
8914
    __ mov(Rexception_pc, LR);   // this is used only to call
8915
                                 // StubRoutines::forward_exception_entry()
8916
                                 // which expects PC of exception in
8917
                                 // R5. FIXME?
8918
    __ jump($jump_target$$Register);
8919
  %}
8920
  ins_pipe(tail_call);
8921
%}
8922

8923

8924
// Return Instruction
8925
instruct Ret() %{
8926
  match(Return);
8927

8928
  format %{ "ret LR" %}
8929

8930
  ins_encode %{
8931
    __ ret(LR);
8932
  %}
8933

8934
  ins_pipe(br);
8935
%}
8936

8937

8938
// Tail Jump; remove the return address; jump to target.
8939
// TailCall above leaves the return address around.
8940
// TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2).
8941
// ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a
8942
// "restore" before this instruction (in Epilogue), we need to materialize it
8943
// in %i0.
8944
instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{
8945
  match( TailJump jump_target ex_oop );
8946
  ins_cost(CALL_COST);
8947
  format %{ "MOV    Rexception_pc, LR\n\t"
8948
            "jump   $jump_target \t! $ex_oop holds exc. oop" %}
8949
  ins_encode %{
8950
    __ mov(Rexception_pc, LR);
8951
    __ jump($jump_target$$Register);
8952
  %}
8953
  ins_pipe(tail_call);
8954
%}
8955

8956
// Create exception oop: created by stack-crawling runtime code.
8957
// Created exception is now available to this handler, and is setup
8958
// just prior to jumping to this handler.  No code emitted.
8959
instruct CreateException( RExceptionRegP ex_oop )
8960
%{
8961
  match(Set ex_oop (CreateEx));
8962
  ins_cost(0);
8963

8964
  size(0);
8965
  // use the following format syntax
8966
  format %{ "! exception oop is in Rexception_obj; no code emitted" %}
8967
  ins_encode();
8968
  ins_pipe(empty);
8969
%}
8970

8971

8972
// Rethrow exception:
8973
// The exception oop will come in the first argument position.
8974
// Then JUMP (not call) to the rethrow stub code.
8975
instruct RethrowException()
8976
%{
8977
  match(Rethrow);
8978
  ins_cost(CALL_COST);
8979

8980
  // use the following format syntax
8981
  format %{ "b    rethrow_stub" %}
8982
  ins_encode %{
8983
    Register scratch = R1_tmp;
8984
    assert_different_registers(scratch, c_rarg0, LR);
8985
    __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch);
8986
  %}
8987
  ins_pipe(tail_call);
8988
%}
8989

8990

8991
// Die now
8992
instruct ShouldNotReachHere( )
8993
%{
8994
  match(Halt);
8995
  ins_cost(CALL_COST);
8996

8997
  // Use the following format syntax
8998
  format %{ "ShouldNotReachHere" %}
8999
  ins_encode %{
9000
    if (is_reachable()) {
9001
      __ stop(_halt_reason);
9002
    }
9003
  %}
9004
  ins_pipe(tail_call);
9005
%}
9006

9007
// ============================================================================
9008
// The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
9009
// array for an instance of the superklass.  Set a hidden internal cache on a
9010
// hit (cache is checked with exposed code in gen_subtype_check()).  Return
9011
// not zero for a miss or zero for a hit.  The encoding ALSO sets flags.
9012
instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{
9013
  match(Set index (PartialSubtypeCheck sub super));
9014
  effect( KILL pcc, KILL lr );
9015
  ins_cost(DEFAULT_COST*10);
9016
  format %{ "CALL   PartialSubtypeCheck" %}
9017
  ins_encode %{
9018
    __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type);
9019
  %}
9020
  ins_pipe(partial_subtype_check_pipe);
9021
%}
9022

9023
/* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */
9024
/*   match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */
9025
/*   ins_pipe(partial_subtype_check_pipe); */
9026
/* %} */
9027

9028

9029
// ============================================================================
9030
// inlined locking and unlocking
9031

9032
instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch )
9033
%{
9034
  match(Set pcc (FastLock object box));
9035

9036
  effect(TEMP scratch, TEMP scratch2);
9037
  ins_cost(DEFAULT_COST*3);
9038

9039
  format %{ "FASTLOCK  $object, $box; KILL $scratch, $scratch2" %}
9040
  ins_encode %{
9041
    __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
9042
  %}
9043
  ins_pipe(long_memory_op);
9044
%}
9045

9046
instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{
9047
  match(Set pcc (FastUnlock object box));
9048
  effect(TEMP scratch, TEMP scratch2);
9049
  ins_cost(100);
9050

9051
  format %{ "FASTUNLOCK  $object, $box; KILL $scratch, $scratch2" %}
9052
  ins_encode %{
9053
    __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
9054
  %}
9055
  ins_pipe(long_memory_op);
9056
%}
9057

9058
// Count and Base registers are fixed because the allocator cannot
9059
// kill unknown registers.  The encodings are generic.
9060
instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{
9061
  match(Set dummy (ClearArray cnt base));
9062
  effect(TEMP temp, TEMP zero, KILL cpsr);
9063
  ins_cost(300);
9064
  format %{ "MOV    $zero,0\n"
9065
      "        MOV    $temp,$cnt\n"
9066
      "loop:   SUBS   $temp,$temp,4\t! Count down a dword of bytes\n"
9067
      "        STR.ge $zero,[$base+$temp]\t! delay slot"
9068
      "        B.gt   loop\t\t! Clearing loop\n" %}
9069
  ins_encode %{
9070
    __ mov($zero$$Register, 0);
9071
    __ mov($temp$$Register, $cnt$$Register);
9072
    Label loop;
9073
    __ bind(loop);
9074
    __ subs($temp$$Register, $temp$$Register, 4);
9075
    __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge);
9076
    __ b(loop, gt);
9077
  %}
9078
  ins_pipe(long_memory_op);
9079
%}
9080

9081
#ifdef XXX
9082
// FIXME: Why R0/R1/R2/R3?
9083
instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result,
9084
                        iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
9085
  predicate(!CompactStrings);
9086
  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
9087
  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2);
9088
  ins_cost(300);
9089
  format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result   // TEMP $tmp1, $tmp2" %}
9090
  ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) );
9091

9092
  ins_pipe(long_memory_op);
9093
%}
9094

9095
// FIXME: Why R0/R1/R2?
9096
instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2,
9097
                       flagsReg ccr) %{
9098
  predicate(!CompactStrings);
9099
  match(Set result (StrEquals (Binary str1 str2) cnt));
9100
  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr);
9101

9102
  ins_cost(300);
9103
  format %{ "String Equals $str1,$str2,$cnt -> $result   // TEMP $tmp1, $tmp2" %}
9104
  ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) );
9105
  ins_pipe(long_memory_op);
9106
%}
9107

9108
// FIXME: Why R0/R1?
9109
instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result,
9110
                      flagsReg ccr) %{
9111
  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
9112
  match(Set result (AryEq ary1 ary2));
9113
  effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr);
9114

9115
  ins_cost(300);
9116
  format %{ "Array Equals $ary1,$ary2 -> $result   // TEMP $tmp1,$tmp2,$tmp3" %}
9117
  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result));
9118
  ins_pipe(long_memory_op);
9119
%}
9120
#endif
9121

9122
//---------- Zeros Count Instructions ------------------------------------------
9123

9124
instruct countLeadingZerosI(iRegI dst, iRegI src) %{
9125
  match(Set dst (CountLeadingZerosI src));
9126
  size(4);
9127
  format %{ "CLZ_32 $dst,$src" %}
9128
  ins_encode %{
9129
    __ clz_32($dst$$Register, $src$$Register);
9130
  %}
9131
  ins_pipe(ialu_reg);
9132
%}
9133

9134
instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9135
  match(Set dst (CountLeadingZerosL src));
9136
  effect(TEMP tmp, TEMP dst, KILL ccr);
9137
  size(16);
9138
  format %{ "CLZ    $dst,$src.hi\n\t"
9139
            "TEQ    $dst,32\n\t"
9140
            "CLZ.eq $tmp,$src.lo\n\t"
9141
            "ADD.eq $dst, $dst, $tmp\n\t" %}
9142
  ins_encode %{
9143
    __ clz($dst$$Register, $src$$Register->successor());
9144
    __ teq($dst$$Register, 32);
9145
    __ clz($tmp$$Register, $src$$Register, eq);
9146
    __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9147
  %}
9148
  ins_pipe(ialu_reg);
9149
%}
9150

9151
instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{
9152
  match(Set dst (CountTrailingZerosI src));
9153
  effect(TEMP tmp);
9154
  size(8);
9155
  format %{ "RBIT_32 $tmp, $src\n\t"
9156
            "CLZ_32  $dst,$tmp" %}
9157
  ins_encode %{
9158
    __ rbit_32($tmp$$Register, $src$$Register);
9159
    __ clz_32($dst$$Register, $tmp$$Register);
9160
  %}
9161
  ins_pipe(ialu_reg);
9162
%}
9163

9164
instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9165
  match(Set dst (CountTrailingZerosL src));
9166
  effect(TEMP tmp, TEMP dst, KILL ccr);
9167
  size(24);
9168
  format %{ "RBIT   $tmp,$src.lo\n\t"
9169
            "CLZ    $dst,$tmp\n\t"
9170
            "TEQ    $dst,32\n\t"
9171
            "RBIT   $tmp,$src.hi\n\t"
9172
            "CLZ.eq $tmp,$tmp\n\t"
9173
            "ADD.eq $dst,$dst,$tmp\n\t" %}
9174
  ins_encode %{
9175
    __ rbit($tmp$$Register, $src$$Register);
9176
    __ clz($dst$$Register, $tmp$$Register);
9177
    __ teq($dst$$Register, 32);
9178
    __ rbit($tmp$$Register, $src$$Register->successor());
9179
    __ clz($tmp$$Register, $tmp$$Register, eq);
9180
    __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9181
  %}
9182
  ins_pipe(ialu_reg);
9183
%}
9184

9185

9186
//---------- Population Count Instructions -------------------------------------
9187

9188
instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
9189
  predicate(UsePopCountInstruction);
9190
  match(Set dst (PopCountI src));
9191
  effect(TEMP tmp);
9192

9193
  format %{ "FMSR       $tmp,$src\n\t"
9194
            "VCNT.8     $tmp,$tmp\n\t"
9195
            "VPADDL.U8  $tmp,$tmp\n\t"
9196
            "VPADDL.U16 $tmp,$tmp\n\t"
9197
            "FMRS       $dst,$tmp" %}
9198
  size(20);
9199

9200
  ins_encode %{
9201
    __ fmsr($tmp$$FloatRegister, $src$$Register);
9202
    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9203
    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9204
    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9205
    __ fmrs($dst$$Register, $tmp$$FloatRegister);
9206
  %}
9207
  ins_pipe(ialu_reg); // FIXME
9208
%}
9209

9210
// Note: Long.bitCount(long) returns an int.
9211
instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{
9212
  predicate(UsePopCountInstruction);
9213
  match(Set dst (PopCountL src));
9214
  effect(TEMP tmp);
9215

9216
  format %{ "FMDRR       $tmp,$src.lo,$src.hi\n\t"
9217
            "VCNT.8      $tmp,$tmp\n\t"
9218
            "VPADDL.U8   $tmp,$tmp\n\t"
9219
            "VPADDL.U16  $tmp,$tmp\n\t"
9220
            "VPADDL.U32  $tmp,$tmp\n\t"
9221
            "FMRS        $dst,$tmp" %}
9222

9223
  size(32);
9224

9225
  ins_encode %{
9226
    __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor());
9227
    __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9228
    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9229
    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9230
    __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0);
9231
    __ fmrs($dst$$Register, $tmp$$FloatRegister);
9232
  %}
9233
  ins_pipe(ialu_reg);
9234
%}
9235

9236

9237
// ============================================================================
9238
//------------Bytes reverse--------------------------------------------------
9239

9240
instruct bytes_reverse_int(iRegI dst, iRegI src) %{
9241
  match(Set dst (ReverseBytesI src));
9242

9243
  size(4);
9244
  format %{ "REV32 $dst,$src" %}
9245
  ins_encode %{
9246
    __ rev($dst$$Register, $src$$Register);
9247
  %}
9248
  ins_pipe( iload_mem ); // FIXME
9249
%}
9250

9251
instruct bytes_reverse_long(iRegL dst, iRegL src) %{
9252
  match(Set dst (ReverseBytesL src));
9253
  effect(TEMP dst);
9254
  size(8);
9255
  format %{ "REV $dst.lo,$src.lo\n\t"
9256
            "REV $dst.hi,$src.hi" %}
9257
  ins_encode %{
9258
    __ rev($dst$$Register, $src$$Register->successor());
9259
    __ rev($dst$$Register->successor(), $src$$Register);
9260
  %}
9261
  ins_pipe( iload_mem ); // FIXME
9262
%}
9263

9264
instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
9265
  match(Set dst (ReverseBytesUS src));
9266
  size(4);
9267
  format %{ "REV16 $dst,$src" %}
9268
  ins_encode %{
9269
    __ rev16($dst$$Register, $src$$Register);
9270
  %}
9271
  ins_pipe( iload_mem ); // FIXME
9272
%}
9273

9274
instruct bytes_reverse_short(iRegI dst, iRegI src) %{
9275
  match(Set dst (ReverseBytesS src));
9276
  size(4);
9277
  format %{ "REVSH $dst,$src" %}
9278
  ins_encode %{
9279
    __ revsh($dst$$Register, $src$$Register);
9280
  %}
9281
  ins_pipe( iload_mem ); // FIXME
9282
%}
9283

9284

9285
// ====================VECTOR INSTRUCTIONS=====================================
9286

9287
// Load Aligned Packed values into a Double Register
9288
instruct loadV8(vecD dst, memoryD mem) %{
9289
  predicate(n->as_LoadVector()->memory_size() == 8);
9290
  match(Set dst (LoadVector mem));
9291
  ins_cost(MEMORY_REF_COST);
9292
  size(4);
9293
  format %{ "FLDD   $mem,$dst\t! load vector (8 bytes)" %}
9294
  ins_encode %{
9295
    __ ldr_double($dst$$FloatRegister, $mem$$Address);
9296
  %}
9297
  ins_pipe(floadD_mem);
9298
%}
9299

9300
// Load Aligned Packed values into a Double Register Pair
9301
instruct loadV16(vecX dst, memoryvld mem) %{
9302
  predicate(n->as_LoadVector()->memory_size() == 16);
9303
  match(Set dst (LoadVector mem));
9304
  ins_cost(MEMORY_REF_COST);
9305
  size(4);
9306
  format %{ "VLD1   $mem,$dst.Q\t! load vector (16 bytes)" %}
9307
  ins_encode %{
9308
    __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9309
  %}
9310
  ins_pipe(floadD_mem); // FIXME
9311
%}
9312

9313
// Store Vector in Double register to memory
9314
instruct storeV8(memoryD mem, vecD src) %{
9315
  predicate(n->as_StoreVector()->memory_size() == 8);
9316
  match(Set mem (StoreVector mem src));
9317
  ins_cost(MEMORY_REF_COST);
9318
  size(4);
9319
  format %{ "FSTD   $src,$mem\t! store vector (8 bytes)" %}
9320
  ins_encode %{
9321
    __ str_double($src$$FloatRegister, $mem$$Address);
9322
  %}
9323
  ins_pipe(fstoreD_mem_reg);
9324
%}
9325

9326
// Store Vector in Double Register Pair to memory
9327
instruct storeV16(memoryvld mem, vecX src) %{
9328
  predicate(n->as_StoreVector()->memory_size() == 16);
9329
  match(Set mem (StoreVector mem src));
9330
  ins_cost(MEMORY_REF_COST);
9331
  size(4);
9332
  format %{ "VST1   $src,$mem\t! store vector (16 bytes)" %}
9333
  ins_encode %{
9334
    __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9335
  %}
9336
  ins_pipe(fstoreD_mem_reg); // FIXME
9337
%}
9338

9339
// Replicate scalar to packed byte values in Double register
9340
instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{
9341
  predicate(n->as_Vector()->length() == 8 &&
9342
            Matcher::vector_element_basic_type(n) == T_BYTE);
9343
  match(Set dst (Replicate src));
9344
  ins_cost(DEFAULT_COST*4);
9345
  effect(TEMP tmp);
9346
  size(16);
9347

9348
  // FIXME: could use PKH instruction instead?
9349
  format %{ "LSL      $tmp, $src, 24 \n\t"
9350
            "OR       $tmp, $tmp, ($tmp >> 8) \n\t"
9351
            "OR       $tmp, $tmp, ($tmp >> 16) \n\t"
9352
            "FMDRR    $dst,$tmp,$tmp\t" %}
9353
  ins_encode %{
9354
    __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24));
9355
    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8));
9356
    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9357
    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9358
  %}
9359
  ins_pipe(ialu_reg); // FIXME
9360
%}
9361

9362
// Replicate scalar to packed byte values in Double register
9363
instruct Repl8B_reg_simd(vecD dst, iRegI src) %{
9364
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9365
            Matcher::vector_element_basic_type(n) == T_BYTE);
9366
  match(Set dst (Replicate src));
9367
  size(4);
9368

9369
  format %{ "VDUP.8 $dst,$src\t" %}
9370
  ins_encode %{
9371
    bool quad = false;
9372
    __ vdupI($dst$$FloatRegister, $src$$Register,
9373
             MacroAssembler::VELEM_SIZE_8, quad);
9374
  %}
9375
  ins_pipe(ialu_reg); // FIXME
9376
%}
9377

9378
// Replicate scalar to packed byte values in Double register pair
9379
instruct Repl16B_reg(vecX dst, iRegI src) %{
9380
  predicate(n->as_Vector()->length_in_bytes() == 16 &&
9381
            Matcher::vector_element_basic_type(n) == T_BYTE);
9382
  match(Set dst (Replicate src));
9383
  size(4);
9384

9385
  format %{ "VDUP.8 $dst.Q,$src\t" %}
9386
  ins_encode %{
9387
    bool quad = true;
9388
    __ vdupI($dst$$FloatRegister, $src$$Register,
9389
             MacroAssembler::VELEM_SIZE_8, quad);
9390
  %}
9391
  ins_pipe(ialu_reg); // FIXME
9392
%}
9393

9394
// Replicate scalar constant to packed byte values in Double register
9395
instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{
9396
  predicate(n->as_Vector()->length() == 8 &&
9397
            Matcher::vector_element_basic_type(n) == T_BYTE);
9398
  match(Set dst (Replicate src));
9399
  ins_cost(DEFAULT_COST*2);
9400
  effect(TEMP tmp);
9401
  size(12);
9402

9403
  format %{ "MOV      $tmp, Repl4($src))\n\t"
9404
            "FMDRR    $dst,$tmp,$tmp\t" %}
9405
  ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) );
9406
  ins_pipe(loadConFD); // FIXME
9407
%}
9408

9409
// Replicate scalar constant to packed byte values in Double register
9410
// TODO: support negative constants with MVNI?
9411
instruct Repl8B_immU8(vecD dst, immU8 src) %{
9412
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9413
            Matcher::vector_element_basic_type(n) == T_BYTE);
9414
  match(Set dst (Replicate src));
9415
  size(4);
9416

9417
  format %{ "VMOV.U8  $dst,$src" %}
9418
  ins_encode %{
9419
    bool quad = false;
9420
    __ vmovI($dst$$FloatRegister, $src$$constant,
9421
             MacroAssembler::VELEM_SIZE_8, quad);
9422
  %}
9423
  ins_pipe(loadConFD); // FIXME
9424
%}
9425

9426
// Replicate scalar constant to packed byte values in Double register pair
9427
instruct Repl16B_immU8(vecX dst, immU8 src) %{
9428
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9429
            Matcher::vector_element_basic_type(n) == T_BYTE);
9430
  match(Set dst (Replicate src));
9431
  size(4);
9432

9433
  format %{ "VMOV.U8  $dst.Q,$src" %}
9434
  ins_encode %{
9435
    bool quad = true;
9436
    __ vmovI($dst$$FloatRegister, $src$$constant,
9437
             MacroAssembler::VELEM_SIZE_8, quad);
9438
  %}
9439
  ins_pipe(loadConFD); // FIXME
9440
%}
9441

9442
// Replicate scalar to packed short/char values into Double register
9443
instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{
9444
  predicate(n->as_Vector()->length() == 4 &&
9445
            Matcher::vector_element_basic_type(n) == T_SHORT);
9446
  match(Set dst (Replicate src));
9447
  ins_cost(DEFAULT_COST*3);
9448
  effect(TEMP tmp);
9449
  size(12);
9450

9451
  // FIXME: could use PKH instruction instead?
9452
  format %{ "LSL      $tmp, $src, 16 \n\t"
9453
            "OR       $tmp, $tmp, ($tmp >> 16) \n\t"
9454
            "FMDRR    $dst,$tmp,$tmp\t" %}
9455
  ins_encode %{
9456
    __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16));
9457
    __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9458
    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9459
  %}
9460
  ins_pipe(ialu_reg); // FIXME
9461
%}
9462

9463
// Replicate scalar to packed byte values in Double register
9464
instruct Repl4S_reg_simd(vecD dst, iRegI src) %{
9465
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9466
            Matcher::vector_element_basic_type(n) == T_SHORT);
9467
  match(Set dst (Replicate src));
9468
  size(4);
9469

9470
  format %{ "VDUP.16 $dst,$src\t" %}
9471
  ins_encode %{
9472
    bool quad = false;
9473
    __ vdupI($dst$$FloatRegister, $src$$Register,
9474
             MacroAssembler::VELEM_SIZE_16, quad);
9475
  %}
9476
  ins_pipe(ialu_reg); // FIXME
9477
%}
9478

9479
// Replicate scalar to packed byte values in Double register pair
9480
instruct Repl8S_reg(vecX dst, iRegI src) %{
9481
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9482
            Matcher::vector_element_basic_type(n) == T_SHORT);
9483
  match(Set dst (Replicate src));
9484
  size(4);
9485

9486
  format %{ "VDUP.16 $dst.Q,$src\t" %}
9487
  ins_encode %{
9488
    bool quad = true;
9489
    __ vdupI($dst$$FloatRegister, $src$$Register,
9490
             MacroAssembler::VELEM_SIZE_16, quad);
9491
  %}
9492
  ins_pipe(ialu_reg); // FIXME
9493
%}
9494

9495

9496
// Replicate scalar constant to packed short/char values in Double register
9497
instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{
9498
  predicate(n->as_Vector()->length() == 4 &&
9499
            Matcher::vector_element_basic_type(n) == T_SHORT);
9500
  match(Set dst (Replicate src));
9501
  effect(TEMP tmp);
9502
  size(12);
9503
  ins_cost(DEFAULT_COST*4); // FIXME
9504

9505
  format %{ "MOV      $tmp, Repl2($src))\n\t"
9506
            "FMDRR    $dst,$tmp,$tmp\t" %}
9507
  ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) );
9508
  ins_pipe(loadConFD); // FIXME
9509
%}
9510

9511
// Replicate scalar constant to packed byte values in Double register
9512
instruct Repl4S_immU8(vecD dst, immU8 src) %{
9513
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9514
            Matcher::vector_element_basic_type(n) == T_SHORT);
9515
  match(Set dst (Replicate src));
9516
  size(4);
9517

9518
  format %{ "VMOV.U16  $dst,$src" %}
9519
  ins_encode %{
9520
    bool quad = false;
9521
    __ vmovI($dst$$FloatRegister, $src$$constant,
9522
             MacroAssembler::VELEM_SIZE_16, quad);
9523
  %}
9524
  ins_pipe(loadConFD); // FIXME
9525
%}
9526

9527
// Replicate scalar constant to packed byte values in Double register pair
9528
instruct Repl8S_immU8(vecX dst, immU8 src) %{
9529
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9530
            Matcher::vector_element_basic_type(n) == T_SHORT);
9531
  match(Set dst (Replicate src));
9532
  size(4);
9533

9534
  format %{ "VMOV.U16  $dst.Q,$src" %}
9535
  ins_encode %{
9536
    bool quad = true;
9537
    __ vmovI($dst$$FloatRegister, $src$$constant,
9538
             MacroAssembler::VELEM_SIZE_16, quad);
9539
  %}
9540
  ins_pipe(loadConFD); // FIXME
9541
%}
9542

9543
// Replicate scalar to packed int values in Double register
9544
instruct Repl2I_reg(vecD dst, iRegI src) %{
9545
  predicate(n->as_Vector()->length() == 2 &&
9546
            Matcher::vector_element_basic_type(n) == T_INT);
9547
  match(Set dst (Replicate src));
9548
  size(4);
9549

9550
  format %{ "FMDRR    $dst,$src,$src\t" %}
9551
  ins_encode %{
9552
    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9553
  %}
9554
  ins_pipe(ialu_reg); // FIXME
9555
%}
9556

9557
// Replicate scalar to packed int values in Double register pair
9558
instruct Repl4I_reg(vecX dst, iRegI src) %{
9559
  predicate(n->as_Vector()->length() == 4 &&
9560
            Matcher::vector_element_basic_type(n) == T_INT);
9561
  match(Set dst (Replicate src));
9562
  ins_cost(DEFAULT_COST*2);
9563
  size(8);
9564

9565
  format %{ "FMDRR    $dst.lo,$src,$src\n\t"
9566
            "FMDRR    $dst.hi,$src,$src" %}
9567

9568
  ins_encode %{
9569
    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9570
    __ fmdrr($dst$$FloatRegister->successor()->successor(),
9571
             $src$$Register, $src$$Register);
9572
  %}
9573
  ins_pipe(ialu_reg); // FIXME
9574
%}
9575

9576
// Replicate scalar to packed int values in Double register
9577
instruct Repl2I_reg_simd(vecD dst, iRegI src) %{
9578
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9579
            Matcher::vector_element_basic_type(n) == T_INT);
9580
  match(Set dst (Replicate src));
9581
  size(4);
9582

9583
  format %{ "VDUP.32 $dst.D,$src\t" %}
9584
  ins_encode %{
9585
    bool quad = false;
9586
    __ vdupI($dst$$FloatRegister, $src$$Register,
9587
             MacroAssembler::VELEM_SIZE_32, quad);
9588
  %}
9589
  ins_pipe(ialu_reg); // FIXME
9590
%}
9591

9592
// Replicate scalar to packed int values in Double register pair
9593
instruct Repl4I_reg_simd(vecX dst, iRegI src) %{
9594
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9595
            Matcher::vector_element_basic_type(n) == T_INT);
9596
  match(Set dst (Replicate src));
9597
  size(4);
9598

9599
  format %{ "VDUP.32 $dst.Q,$src\t" %}
9600
  ins_encode %{
9601
    bool quad = true;
9602
    __ vdupI($dst$$FloatRegister, $src$$Register,
9603
             MacroAssembler::VELEM_SIZE_32, quad);
9604
  %}
9605
  ins_pipe(ialu_reg); // FIXME
9606
%}
9607

9608

9609
// Replicate scalar zero constant to packed int values in Double register
9610
instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{
9611
  predicate(n->as_Vector()->length() == 2 &&
9612
            Matcher::vector_element_basic_type(n) == T_INT);
9613
  match(Set dst (Replicate src));
9614
  effect(TEMP tmp);
9615
  size(12);
9616
  ins_cost(DEFAULT_COST*4); // FIXME
9617

9618
  format %{ "MOV      $tmp, Repl1($src))\n\t"
9619
            "FMDRR    $dst,$tmp,$tmp\t" %}
9620
  ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) );
9621
  ins_pipe(loadConFD); // FIXME
9622
%}
9623

9624
// Replicate scalar constant to packed byte values in Double register
9625
instruct Repl2I_immU8(vecD dst, immU8 src) %{
9626
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9627
            Matcher::vector_element_basic_type(n) == T_INT);
9628
  match(Set dst (Replicate src));
9629
  size(4);
9630

9631
  format %{ "VMOV.I32  $dst.D,$src" %}
9632
  ins_encode %{
9633
    bool quad = false;
9634
    __ vmovI($dst$$FloatRegister, $src$$constant,
9635
             MacroAssembler::VELEM_SIZE_32, quad);
9636
  %}
9637
  ins_pipe(loadConFD); // FIXME
9638
%}
9639

9640
// Replicate scalar constant to packed byte values in Double register pair
9641
instruct Repl4I_immU8(vecX dst, immU8 src) %{
9642
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9643
            Matcher::vector_element_basic_type(n) == T_INT);
9644
  match(Set dst (Replicate src));
9645
  size(4);
9646

9647
  format %{ "VMOV.I32  $dst.Q,$src" %}
9648
  ins_encode %{
9649
    bool quad = true;
9650
    __ vmovI($dst$$FloatRegister, $src$$constant,
9651
             MacroAssembler::VELEM_SIZE_32, quad);
9652
  %}
9653
  ins_pipe(loadConFD); // FIXME
9654
%}
9655

9656
// Replicate scalar to packed byte values in Double register pair
9657
instruct Repl2L_reg(vecX dst, iRegL src) %{
9658
  predicate(n->as_Vector()->length() == 2 &&
9659
            Matcher::vector_element_basic_type(n) == T_LONG);
9660
  match(Set dst (Replicate src));
9661
  size(8);
9662
  ins_cost(DEFAULT_COST*2); // FIXME
9663

9664
  format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n"
9665
            "FMDRR $dst.D.next,$src.lo,$src.hi" %}
9666
  ins_encode %{
9667
    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
9668
    __ fmdrr($dst$$FloatRegister->successor()->successor(),
9669
             $src$$Register, $src$$Register->successor());
9670
  %}
9671
  ins_pipe(ialu_reg); // FIXME
9672
%}
9673

9674

9675
// Replicate scalar to packed float values in Double register
9676
instruct Repl2F_regI(vecD dst, iRegI src) %{
9677
  predicate(n->as_Vector()->length() == 2 &&
9678
            Matcher::vector_element_basic_type(n) == T_FLOAT);
9679
  match(Set dst (Replicate src));
9680
  size(4);
9681

9682
  format %{ "FMDRR    $dst.D,$src,$src\t" %}
9683
  ins_encode %{
9684
    __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9685
  %}
9686
  ins_pipe(ialu_reg); // FIXME
9687
%}
9688

9689
// Replicate scalar to packed float values in Double register
9690
instruct Repl2F_reg_vfp(vecD dst, regF src) %{
9691
  predicate(n->as_Vector()->length() == 2 &&
9692
            Matcher::vector_element_basic_type(n) == T_FLOAT);
9693
  match(Set dst (Replicate src));
9694
  size(4*2);
9695
  ins_cost(DEFAULT_COST*2); // FIXME
9696

9697
  expand %{
9698
    iRegI tmp;
9699
    MoveF2I_reg_reg(tmp, src);
9700
    Repl2F_regI(dst,tmp);
9701
  %}
9702
%}
9703

9704
// Replicate scalar to packed float values in Double register
9705
instruct Repl2F_reg_simd(vecD dst, regF src) %{
9706
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9707
            Matcher::vector_element_basic_type(n) == T_FLOAT);
9708
  match(Set dst (Replicate src));
9709
  size(4);
9710
  ins_cost(DEFAULT_COST); // FIXME
9711

9712
  format %{ "VDUP.32  $dst.D,$src.D\t" %}
9713
  ins_encode %{
9714
    bool quad = false;
9715
    __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9716
  %}
9717
  ins_pipe(ialu_reg); // FIXME
9718
%}
9719

9720
// Replicate scalar to packed float values in Double register pair
9721
instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{
9722
  predicate(n->as_Vector()->length() == 4 &&
9723
            Matcher::vector_element_basic_type(n) == T_FLOAT);
9724
  match(Set dst (Replicate src));
9725
  effect(TEMP tmp);
9726
  size(4*3);
9727
  ins_cost(DEFAULT_COST*3); // FIXME
9728

9729
  format %{ "FMRS     $tmp,$src\n\t"
9730
            "FMDRR    $dst.D,$tmp,$tmp\n\t"
9731
            "FMDRR    $dst.D.next,$tmp,$tmp\t" %}
9732
  ins_encode %{
9733
    __ fmrs($tmp$$Register, $src$$FloatRegister);
9734
    __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9735
    __ fmdrr($dst$$FloatRegister->successor()->successor(),
9736
             $tmp$$Register, $tmp$$Register);
9737
  %}
9738
  ins_pipe(ialu_reg); // FIXME
9739
%}
9740

9741
// Replicate scalar to packed float values in Double register pair
9742
instruct Repl4F_reg_simd(vecX dst, regF src) %{
9743
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9744
            Matcher::vector_element_basic_type(n) == T_FLOAT);
9745
  match(Set dst (Replicate src));
9746
  size(4);
9747
  ins_cost(DEFAULT_COST); // FIXME
9748

9749
  format %{ "VDUP.32  $dst.Q,$src.D\t" %}
9750
  ins_encode %{
9751
    bool quad = true;
9752
    __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9753
  %}
9754
  ins_pipe(ialu_reg); // FIXME
9755
%}
9756

9757
// Replicate scalar zero constant to packed float values in Double register
9758
instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{
9759
  predicate(n->as_Vector()->length() == 2 &&
9760
            Matcher::vector_element_basic_type(n) == T_FLOAT);
9761
  match(Set dst (Replicate src));
9762
  effect(TEMP tmp);
9763
  size(12);
9764
  ins_cost(DEFAULT_COST*4); // FIXME
9765

9766
  format %{ "MOV      $tmp, Repl1($src))\n\t"
9767
            "FMDRR    $dst,$tmp,$tmp\t" %}
9768
  ins_encode( LdReplImmF(src, dst, tmp) );
9769
  ins_pipe(loadConFD); // FIXME
9770
%}
9771

9772
// Replicate scalar to packed double float values in Double register pair
9773
instruct Repl2D_reg(vecX dst, regD src) %{
9774
  predicate(n->as_Vector()->length() == 2 &&
9775
            Matcher::vector_element_basic_type(n) == T_DOUBLE);
9776
  match(Set dst (Replicate src));
9777
  size(4*2);
9778
  ins_cost(DEFAULT_COST*2); // FIXME
9779

9780
  format %{ "FCPYD    $dst.D.a,$src\n\t"
9781
            "FCPYD    $dst.D.b,$src\t" %}
9782
  ins_encode %{
9783
    FloatRegister dsta = $dst$$FloatRegister;
9784
    FloatRegister src = $src$$FloatRegister;
9785
    __ fcpyd(dsta, src);
9786
    FloatRegister dstb = dsta->successor()->successor();
9787
    __ fcpyd(dstb, src);
9788
  %}
9789
  ins_pipe(ialu_reg); // FIXME
9790
%}
9791

9792
// ====================VECTOR ARITHMETIC=======================================
9793

9794
// --------------------------------- ADD --------------------------------------
9795

9796
// Bytes vector add
9797
instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{
9798
  predicate(n->as_Vector()->length() == 8);
9799
  match(Set dst (AddVB src1 src2));
9800
  format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %}
9801
  size(4);
9802
  ins_encode %{
9803
    bool quad = false;
9804
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9805
             MacroAssembler::VELEM_SIZE_8, quad);
9806
  %}
9807
  ins_pipe( ialu_reg_reg ); // FIXME
9808
%}
9809

9810
instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
9811
  predicate(n->as_Vector()->length() == 16);
9812
  match(Set dst (AddVB src1 src2));
9813
  size(4);
9814
  format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %}
9815
  ins_encode %{
9816
    bool quad = true;
9817
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9818
             MacroAssembler::VELEM_SIZE_8, quad);
9819
  %}
9820
  ins_pipe( ialu_reg_reg ); // FIXME
9821
%}
9822

9823
// Shorts/Chars vector add
9824
instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{
9825
  predicate(n->as_Vector()->length() == 4);
9826
  match(Set dst (AddVS src1 src2));
9827
  size(4);
9828
  format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %}
9829
  ins_encode %{
9830
    bool quad = false;
9831
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9832
             MacroAssembler::VELEM_SIZE_16, quad);
9833
  %}
9834
  ins_pipe( ialu_reg_reg ); // FIXME
9835
%}
9836

9837
instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
9838
  predicate(n->as_Vector()->length() == 8);
9839
  match(Set dst (AddVS src1 src2));
9840
  size(4);
9841
  format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %}
9842
  ins_encode %{
9843
    bool quad = true;
9844
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9845
             MacroAssembler::VELEM_SIZE_16, quad);
9846
  %}
9847
  ins_pipe( ialu_reg_reg ); // FIXME
9848
%}
9849

9850
// Integers vector add
9851
instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{
9852
  predicate(n->as_Vector()->length() == 2);
9853
  match(Set dst (AddVI src1 src2));
9854
  size(4);
9855
  format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %}
9856
  ins_encode %{
9857
    bool quad = false;
9858
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9859
             MacroAssembler::VELEM_SIZE_32, quad);
9860
  %}
9861
  ins_pipe( ialu_reg_reg ); // FIXME
9862
%}
9863

9864
instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
9865
  predicate(n->as_Vector()->length() == 4);
9866
  match(Set dst (AddVI src1 src2));
9867
  size(4);
9868
  format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %}
9869
  ins_encode %{
9870
    bool quad = true;
9871
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9872
             MacroAssembler::VELEM_SIZE_32, quad);
9873
  %}
9874
  ins_pipe( ialu_reg_reg ); // FIXME
9875
%}
9876

9877
// Longs vector add
9878
instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
9879
  predicate(n->as_Vector()->length() == 2);
9880
  match(Set dst (AddVL src1 src2));
9881
  size(4);
9882
  format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %}
9883
  ins_encode %{
9884
    bool quad = true;
9885
    __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9886
             MacroAssembler::VELEM_SIZE_64, quad);
9887
  %}
9888
  ins_pipe( ialu_reg_reg ); // FIXME
9889
%}
9890

9891
// Floats vector add
9892
instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{
9893
  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
9894
  match(Set dst (AddVF src1 src2));
9895
  size(4);
9896
  format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %}
9897
  ins_encode %{
9898
    bool quad = false;
9899
    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9900
             MacroAssembler::VFA_SIZE_F32, quad);
9901
  %}
9902
  ins_pipe( faddD_reg_reg ); // FIXME
9903
%}
9904

9905
instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
9906
  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
9907
  match(Set dst (AddVF src1 src2));
9908
  ins_cost(DEFAULT_COST*2); // FIXME
9909

9910
  size(4*2);
9911
  format %{ "FADDS  $dst.a,$src1.a,$src2.a\n\t"
9912
            "FADDS  $dst.b,$src1.b,$src2.b" %}
9913
  ins_encode %{
9914
    __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9915
    __ add_float($dst$$FloatRegister->successor(),
9916
             $src1$$FloatRegister->successor(),
9917
             $src2$$FloatRegister->successor());
9918
  %}
9919

9920
  ins_pipe(faddF_reg_reg); // FIXME
9921
%}
9922

9923
instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{
9924
  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
9925
  match(Set dst (AddVF src1 src2));
9926
  size(4);
9927
  format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %}
9928
  ins_encode %{
9929
    bool quad = true;
9930
    __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9931
             MacroAssembler::VFA_SIZE_F32, quad);
9932
  %}
9933
  ins_pipe( faddD_reg_reg ); // FIXME
9934
%}
9935

9936
instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9937
  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
9938
  match(Set dst (AddVF src1 src2));
9939
  size(4*4);
9940
  ins_cost(DEFAULT_COST*4); // FIXME
9941

9942
  format %{ "FADDS  $dst.a,$src1.a,$src2.a\n\t"
9943
            "FADDS  $dst.b,$src1.b,$src2.b\n\t"
9944
            "FADDS  $dst.c,$src1.c,$src2.c\n\t"
9945
            "FADDS  $dst.d,$src1.d,$src2.d" %}
9946

9947
  ins_encode %{
9948
    FloatRegister dsta = $dst$$FloatRegister;
9949
    FloatRegister src1a = $src1$$FloatRegister;
9950
    FloatRegister src2a = $src2$$FloatRegister;
9951
    __ add_float(dsta, src1a, src2a);
9952
    FloatRegister dstb = dsta->successor();
9953
    FloatRegister src1b = src1a->successor();
9954
    FloatRegister src2b = src2a->successor();
9955
    __ add_float(dstb, src1b, src2b);
9956
    FloatRegister dstc = dstb->successor();
9957
    FloatRegister src1c = src1b->successor();
9958
    FloatRegister src2c = src2b->successor();
9959
    __ add_float(dstc, src1c, src2c);
9960
    FloatRegister dstd = dstc->successor();
9961
    FloatRegister src1d = src1c->successor();
9962
    FloatRegister src2d = src2c->successor();
9963
    __ add_float(dstd, src1d, src2d);
9964
  %}
9965

9966
  ins_pipe(faddF_reg_reg); // FIXME
9967
%}
9968

9969
instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9970
  predicate(n->as_Vector()->length() == 2);
9971
  match(Set dst (AddVD src1 src2));
9972
  size(4*2);
9973
  ins_cost(DEFAULT_COST*2); // FIXME
9974

9975
  format %{ "FADDD  $dst.a,$src1.a,$src2.a\n\t"
9976
            "FADDD  $dst.b,$src1.b,$src2.b" %}
9977

9978
  ins_encode %{
9979
    FloatRegister dsta = $dst$$FloatRegister;
9980
    FloatRegister src1a = $src1$$FloatRegister;
9981
    FloatRegister src2a = $src2$$FloatRegister;
9982
    __ add_double(dsta, src1a, src2a);
9983
    FloatRegister dstb = dsta->successor()->successor();
9984
    FloatRegister src1b = src1a->successor()->successor();
9985
    FloatRegister src2b = src2a->successor()->successor();
9986
    __ add_double(dstb, src1b, src2b);
9987
  %}
9988

9989
  ins_pipe(faddF_reg_reg); // FIXME
9990
%}
9991

9992

9993
// Bytes vector sub
9994
instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{
9995
  predicate(n->as_Vector()->length() == 8);
9996
  match(Set dst (SubVB src1 src2));
9997
  size(4);
9998
  format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %}
9999
  ins_encode %{
10000
    bool quad = false;
10001
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10002
             MacroAssembler::VELEM_SIZE_8, quad);
10003
  %}
10004
  ins_pipe( ialu_reg_reg ); // FIXME
10005
%}
10006

10007
instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
10008
  predicate(n->as_Vector()->length() == 16);
10009
  match(Set dst (SubVB src1 src2));
10010
  size(4);
10011
  format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %}
10012
  ins_encode %{
10013
    bool quad = true;
10014
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10015
             MacroAssembler::VELEM_SIZE_8, quad);
10016
  %}
10017
  ins_pipe( ialu_reg_reg ); // FIXME
10018
%}
10019

10020
// Shorts/Chars vector sub
10021
instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{
10022
  predicate(n->as_Vector()->length() == 4);
10023
  match(Set dst (SubVS src1 src2));
10024
  size(4);
10025
  format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %}
10026
  ins_encode %{
10027
    bool quad = false;
10028
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10029
             MacroAssembler::VELEM_SIZE_16, quad);
10030
  %}
10031
  ins_pipe( ialu_reg_reg ); // FIXME
10032
%}
10033

10034
instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{
10035
  predicate(n->as_Vector()->length() == 8);
10036
  match(Set dst (SubVS src1 src2));
10037
  size(4);
10038
  format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %}
10039
  ins_encode %{
10040
    bool quad = true;
10041
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10042
             MacroAssembler::VELEM_SIZE_16, quad);
10043
  %}
10044
  ins_pipe( ialu_reg_reg ); // FIXME
10045
%}
10046

10047
// Integers vector sub
10048
instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{
10049
  predicate(n->as_Vector()->length() == 2);
10050
  match(Set dst (SubVI src1 src2));
10051
  size(4);
10052
  format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %}
10053
  ins_encode %{
10054
    bool quad = false;
10055
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10056
             MacroAssembler::VELEM_SIZE_32, quad);
10057
  %}
10058
  ins_pipe( ialu_reg_reg ); // FIXME
10059
%}
10060

10061
instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
10062
  predicate(n->as_Vector()->length() == 4);
10063
  match(Set dst (SubVI src1 src2));
10064
  size(4);
10065
  format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %}
10066
  ins_encode %{
10067
    bool quad = true;
10068
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10069
             MacroAssembler::VELEM_SIZE_32, quad);
10070
  %}
10071
  ins_pipe( ialu_reg_reg ); // FIXME
10072
%}
10073

10074
// Longs vector sub
10075
instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
10076
  predicate(n->as_Vector()->length() == 2);
10077
  match(Set dst (SubVL src1 src2));
10078
  size(4);
10079
  format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %}
10080
  ins_encode %{
10081
    bool quad = true;
10082
    __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10083
             MacroAssembler::VELEM_SIZE_64, quad);
10084
  %}
10085
  ins_pipe( ialu_reg_reg ); // FIXME
10086
%}
10087

10088
// Floats vector sub
10089
instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{
10090
  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10091
  match(Set dst (SubVF src1 src2));
10092
  size(4);
10093
  format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %}
10094
  ins_encode %{
10095
    bool quad = false;
10096
    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10097
             MacroAssembler::VFA_SIZE_F32, quad);
10098
  %}
10099
  ins_pipe( faddF_reg_reg ); // FIXME
10100
%}
10101

10102
instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10103
  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10104
  match(Set dst (SubVF src1 src2));
10105
  size(4*2);
10106
  ins_cost(DEFAULT_COST*2); // FIXME
10107

10108
  format %{ "FSUBS  $dst.a,$src1.a,$src2.a\n\t"
10109
            "FSUBS  $dst.b,$src1.b,$src2.b" %}
10110

10111
  ins_encode %{
10112
    FloatRegister dsta = $dst$$FloatRegister;
10113
    FloatRegister src1a = $src1$$FloatRegister;
10114
    FloatRegister src2a = $src2$$FloatRegister;
10115
    __ sub_float(dsta, src1a, src2a);
10116
    FloatRegister dstb = dsta->successor();
10117
    FloatRegister src1b = src1a->successor();
10118
    FloatRegister src2b = src2a->successor();
10119
    __ sub_float(dstb, src1b, src2b);
10120
  %}
10121

10122
  ins_pipe(faddF_reg_reg); // FIXME
10123
%}
10124

10125

10126
instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
10127
  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10128
  match(Set dst (SubVF src1 src2));
10129
  size(4);
10130
  format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %}
10131
  ins_encode %{
10132
    bool quad = true;
10133
    __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10134
             MacroAssembler::VFA_SIZE_F32, quad);
10135
  %}
10136
  ins_pipe( faddF_reg_reg ); // FIXME
10137
%}
10138

10139
instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10140
  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10141
  match(Set dst (SubVF src1 src2));
10142
  size(4*4);
10143
  ins_cost(DEFAULT_COST*4); // FIXME
10144

10145
  format %{ "FSUBS  $dst.a,$src1.a,$src2.a\n\t"
10146
            "FSUBS  $dst.b,$src1.b,$src2.b\n\t"
10147
            "FSUBS  $dst.c,$src1.c,$src2.c\n\t"
10148
            "FSUBS  $dst.d,$src1.d,$src2.d" %}
10149

10150
  ins_encode %{
10151
    FloatRegister dsta = $dst$$FloatRegister;
10152
    FloatRegister src1a = $src1$$FloatRegister;
10153
    FloatRegister src2a = $src2$$FloatRegister;
10154
    __ sub_float(dsta, src1a, src2a);
10155
    FloatRegister dstb = dsta->successor();
10156
    FloatRegister src1b = src1a->successor();
10157
    FloatRegister src2b = src2a->successor();
10158
    __ sub_float(dstb, src1b, src2b);
10159
    FloatRegister dstc = dstb->successor();
10160
    FloatRegister src1c = src1b->successor();
10161
    FloatRegister src2c = src2b->successor();
10162
    __ sub_float(dstc, src1c, src2c);
10163
    FloatRegister dstd = dstc->successor();
10164
    FloatRegister src1d = src1c->successor();
10165
    FloatRegister src2d = src2c->successor();
10166
    __ sub_float(dstd, src1d, src2d);
10167
  %}
10168

10169
  ins_pipe(faddF_reg_reg); // FIXME
10170
%}
10171

10172
instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10173
  predicate(n->as_Vector()->length() == 2);
10174
  match(Set dst (SubVD src1 src2));
10175
  size(4*2);
10176
  ins_cost(DEFAULT_COST*2); // FIXME
10177

10178
  format %{ "FSUBD  $dst.a,$src1.a,$src2.a\n\t"
10179
            "FSUBD  $dst.b,$src1.b,$src2.b" %}
10180

10181
  ins_encode %{
10182
    FloatRegister dsta = $dst$$FloatRegister;
10183
    FloatRegister src1a = $src1$$FloatRegister;
10184
    FloatRegister src2a = $src2$$FloatRegister;
10185
    __ sub_double(dsta, src1a, src2a);
10186
    FloatRegister dstb = dsta->successor()->successor();
10187
    FloatRegister src1b = src1a->successor()->successor();
10188
    FloatRegister src2b = src2a->successor()->successor();
10189
    __ sub_double(dstb, src1b, src2b);
10190
  %}
10191

10192
  ins_pipe(faddF_reg_reg); // FIXME
10193
%}
10194

10195
// Shorts/Chars vector mul
10196
instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{
10197
  predicate(n->as_Vector()->length() == 4);
10198
  match(Set dst (MulVS src1 src2));
10199
  size(4);
10200
  format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %}
10201
  ins_encode %{
10202
    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10203
             MacroAssembler::VELEM_SIZE_16, 0);
10204
  %}
10205
  ins_pipe( ialu_reg_reg ); // FIXME
10206
%}
10207

10208
instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{
10209
  predicate(n->as_Vector()->length() == 8);
10210
  match(Set dst (MulVS src1 src2));
10211
  size(4);
10212
  format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %}
10213
  ins_encode %{
10214
    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10215
             MacroAssembler::VELEM_SIZE_16, 1);
10216
  %}
10217
  ins_pipe( ialu_reg_reg ); // FIXME
10218
%}
10219

10220
// Integers vector mul
10221
instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{
10222
  predicate(n->as_Vector()->length() == 2);
10223
  match(Set dst (MulVI src1 src2));
10224
  size(4);
10225
  format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %}
10226
  ins_encode %{
10227
    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10228
             MacroAssembler::VELEM_SIZE_32, 0);
10229
  %}
10230
  ins_pipe( ialu_reg_reg ); // FIXME
10231
%}
10232

10233
instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
10234
  predicate(n->as_Vector()->length() == 4);
10235
  match(Set dst (MulVI src1 src2));
10236
  size(4);
10237
  format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %}
10238
  ins_encode %{
10239
    __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10240
             MacroAssembler::VELEM_SIZE_32, 1);
10241
  %}
10242
  ins_pipe( ialu_reg_reg ); // FIXME
10243
%}
10244

10245
// Floats vector mul
10246
instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{
10247
  predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10248
  match(Set dst (MulVF src1 src2));
10249
  size(4);
10250
  format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %}
10251
  ins_encode %{
10252
    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10253
             MacroAssembler::VFA_SIZE_F32, 0);
10254
  %}
10255
  ins_pipe( fmulF_reg_reg ); // FIXME
10256
%}
10257

10258
instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10259
  predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10260
  match(Set dst (MulVF src1 src2));
10261
  size(4*2);
10262
  ins_cost(DEFAULT_COST*2); // FIXME
10263

10264
  format %{ "FMULS  $dst.a,$src1.a,$src2.a\n\t"
10265
            "FMULS  $dst.b,$src1.b,$src2.b" %}
10266
  ins_encode %{
10267
    __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10268
    __ mul_float($dst$$FloatRegister->successor(),
10269
             $src1$$FloatRegister->successor(),
10270
             $src2$$FloatRegister->successor());
10271
  %}
10272

10273
  ins_pipe(fmulF_reg_reg); // FIXME
10274
%}
10275

10276
instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
10277
  predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10278
  match(Set dst (MulVF src1 src2));
10279
  size(4);
10280
  format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %}
10281
  ins_encode %{
10282
    __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10283
             MacroAssembler::VFA_SIZE_F32, 1);
10284
  %}
10285
  ins_pipe( fmulF_reg_reg ); // FIXME
10286
%}
10287

10288
instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10289
  predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10290
  match(Set dst (MulVF src1 src2));
10291
  size(4*4);
10292
  ins_cost(DEFAULT_COST*4); // FIXME
10293

10294
  format %{ "FMULS  $dst.a,$src1.a,$src2.a\n\t"
10295
            "FMULS  $dst.b,$src1.b,$src2.b\n\t"
10296
            "FMULS  $dst.c,$src1.c,$src2.c\n\t"
10297
            "FMULS  $dst.d,$src1.d,$src2.d" %}
10298

10299
  ins_encode %{
10300
    FloatRegister dsta = $dst$$FloatRegister;
10301
    FloatRegister src1a = $src1$$FloatRegister;
10302
    FloatRegister src2a = $src2$$FloatRegister;
10303
    __ mul_float(dsta, src1a, src2a);
10304
    FloatRegister dstb = dsta->successor();
10305
    FloatRegister src1b = src1a->successor();
10306
    FloatRegister src2b = src2a->successor();
10307
    __ mul_float(dstb, src1b, src2b);
10308
    FloatRegister dstc = dstb->successor();
10309
    FloatRegister src1c = src1b->successor();
10310
    FloatRegister src2c = src2b->successor();
10311
    __ mul_float(dstc, src1c, src2c);
10312
    FloatRegister dstd = dstc->successor();
10313
    FloatRegister src1d = src1c->successor();
10314
    FloatRegister src2d = src2c->successor();
10315
    __ mul_float(dstd, src1d, src2d);
10316
  %}
10317

10318
  ins_pipe(fmulF_reg_reg); // FIXME
10319
%}
10320

10321
instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10322
  predicate(n->as_Vector()->length() == 2);
10323
  match(Set dst (MulVD src1 src2));
10324
  size(4*2);
10325
  ins_cost(DEFAULT_COST*2); // FIXME
10326

10327
  format %{ "FMULD  $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10328
            "FMULD  $dst.D.b,$src1.D.b,$src2.D.b" %}
10329
  ins_encode %{
10330
    FloatRegister dsta = $dst$$FloatRegister;
10331
    FloatRegister src1a = $src1$$FloatRegister;
10332
    FloatRegister src2a = $src2$$FloatRegister;
10333
    __ mul_double(dsta, src1a, src2a);
10334
    FloatRegister dstb = dsta->successor()->successor();
10335
    FloatRegister src1b = src1a->successor()->successor();
10336
    FloatRegister src2b = src2a->successor()->successor();
10337
    __ mul_double(dstb, src1b, src2b);
10338
  %}
10339

10340
  ins_pipe(fmulD_reg_reg); // FIXME
10341
%}
10342

10343

10344
// Floats vector div
10345
instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10346
  predicate(n->as_Vector()->length() == 2);
10347
  match(Set dst (DivVF src1 src2));
10348
  size(4*2);
10349
  ins_cost(DEFAULT_COST*2); // FIXME
10350

10351
  format %{ "FDIVS  $dst.a,$src1.a,$src2.a\n\t"
10352
            "FDIVS  $dst.b,$src1.b,$src2.b" %}
10353
  ins_encode %{
10354
    __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10355
    __ div_float($dst$$FloatRegister->successor(),
10356
             $src1$$FloatRegister->successor(),
10357
             $src2$$FloatRegister->successor());
10358
  %}
10359

10360
  ins_pipe(fdivF_reg_reg); // FIXME
10361
%}
10362

10363
instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10364
  predicate(n->as_Vector()->length() == 4);
10365
  match(Set dst (DivVF src1 src2));
10366
  size(4*4);
10367
  ins_cost(DEFAULT_COST*4); // FIXME
10368

10369
  format %{ "FDIVS  $dst.a,$src1.a,$src2.a\n\t"
10370
            "FDIVS  $dst.b,$src1.b,$src2.b\n\t"
10371
            "FDIVS  $dst.c,$src1.c,$src2.c\n\t"
10372
            "FDIVS  $dst.d,$src1.d,$src2.d" %}
10373

10374
  ins_encode %{
10375
    FloatRegister dsta = $dst$$FloatRegister;
10376
    FloatRegister src1a = $src1$$FloatRegister;
10377
    FloatRegister src2a = $src2$$FloatRegister;
10378
    __ div_float(dsta, src1a, src2a);
10379
    FloatRegister dstb = dsta->successor();
10380
    FloatRegister src1b = src1a->successor();
10381
    FloatRegister src2b = src2a->successor();
10382
    __ div_float(dstb, src1b, src2b);
10383
    FloatRegister dstc = dstb->successor();
10384
    FloatRegister src1c = src1b->successor();
10385
    FloatRegister src2c = src2b->successor();
10386
    __ div_float(dstc, src1c, src2c);
10387
    FloatRegister dstd = dstc->successor();
10388
    FloatRegister src1d = src1c->successor();
10389
    FloatRegister src2d = src2c->successor();
10390
    __ div_float(dstd, src1d, src2d);
10391
  %}
10392

10393
  ins_pipe(fdivF_reg_reg); // FIXME
10394
%}
10395

10396
instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10397
  predicate(n->as_Vector()->length() == 2);
10398
  match(Set dst (DivVD src1 src2));
10399
  size(4*2);
10400
  ins_cost(DEFAULT_COST*2); // FIXME
10401

10402
  format %{ "FDIVD  $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10403
            "FDIVD  $dst.D.b,$src1.D.b,$src2.D.b" %}
10404
  ins_encode %{
10405
    FloatRegister dsta = $dst$$FloatRegister;
10406
    FloatRegister src1a = $src1$$FloatRegister;
10407
    FloatRegister src2a = $src2$$FloatRegister;
10408
    __ div_double(dsta, src1a, src2a);
10409
    FloatRegister dstb = dsta->successor()->successor();
10410
    FloatRegister src1b = src1a->successor()->successor();
10411
    FloatRegister src2b = src2a->successor()->successor();
10412
    __ div_double(dstb, src1b, src2b);
10413
  %}
10414

10415
  ins_pipe(fdivD_reg_reg); // FIXME
10416
%}
10417

10418
// --------------------------------- NEG --------------------------------------
10419

10420
instruct vneg8B_reg(vecD dst, vecD src) %{
10421
  predicate(n->as_Vector()->length_in_bytes() == 8);
10422
  effect(DEF dst, USE src);
10423
  size(4);
10424
  ins_cost(DEFAULT_COST); // FIXME
10425
  format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %}
10426
  ins_encode %{
10427
    bool quad = false;
10428
    __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10429
              MacroAssembler::VELEM_SIZE_8, quad);
10430
  %}
10431
  ins_pipe( ialu_reg_reg ); // FIXME
10432
%}
10433

10434
instruct vneg16B_reg(vecX dst, vecX src) %{
10435
  predicate(n->as_Vector()->length_in_bytes() == 16);
10436
  effect(DEF dst, USE src);
10437
  size(4);
10438
  ins_cost(DEFAULT_COST); // FIXME
10439
  format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %}
10440
  ins_encode %{
10441
    bool _float = false;
10442
    bool quad = true;
10443
    __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10444
              MacroAssembler::VELEM_SIZE_8, quad);
10445
  %}
10446
  ins_pipe( ialu_reg_reg ); // FIXME
10447
%}
10448

10449
// ------------------------------ ShiftCount ----------------------------------
10450

10451
instruct vslcntD(vecD dst, iRegI cnt) %{
10452
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10453
  match(Set dst (LShiftCntV cnt));
10454
  size(4);
10455
  ins_cost(DEFAULT_COST); // FIXME
10456
  expand %{
10457
    Repl8B_reg_simd(dst, cnt);
10458
  %}
10459
%}
10460

10461
instruct vslcntX(vecX dst, iRegI cnt) %{
10462
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10463
  match(Set dst (LShiftCntV cnt));
10464
  size(4);
10465
  ins_cost(DEFAULT_COST); // FIXME
10466
  expand %{
10467
    Repl16B_reg(dst, cnt);
10468
  %}
10469
%}
10470

10471
// Low bits of vector "shift" elements are used, so it
10472
// doesn't matter if we treat it as ints or bytes here.
10473
instruct vsrcntD(vecD dst, iRegI cnt) %{
10474
  predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10475
  match(Set dst (RShiftCntV cnt));
10476
  size(4*2);
10477
  ins_cost(DEFAULT_COST*2); // FIXME
10478

10479
  format %{ "VDUP.8 $dst.D,$cnt\n\t"
10480
            "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %}
10481
  ins_encode %{
10482
    bool quad = false;
10483
    __ vdupI($dst$$FloatRegister, $cnt$$Register,
10484
             MacroAssembler::VELEM_SIZE_8, quad);
10485
    __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10486
              MacroAssembler::VELEM_SIZE_8, quad);
10487
  %}
10488
  ins_pipe( ialu_reg_reg ); // FIXME
10489
%}
10490

10491
instruct vsrcntX(vecX dst, iRegI cnt) %{
10492
  predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10493
  match(Set dst (RShiftCntV cnt));
10494
  size(4*2);
10495
  ins_cost(DEFAULT_COST*2); // FIXME
10496
  format %{ "VDUP.8 $dst.Q,$cnt\n\t"
10497
            "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %}
10498
  ins_encode %{
10499
    bool quad = true;
10500
    __ vdupI($dst$$FloatRegister, $cnt$$Register,
10501
             MacroAssembler::VELEM_SIZE_8, quad);
10502
    __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10503
              MacroAssembler::VELEM_SIZE_8, quad);
10504
  %}
10505
  ins_pipe( ialu_reg_reg ); // FIXME
10506
%}
10507

10508
// ------------------------------ LogicalShift --------------------------------
10509

10510
// Byte vector logical left/right shift based on sign
10511
instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{
10512
  predicate(n->as_Vector()->length() == 8);
10513
  effect(DEF dst, USE src, USE shift);
10514
  size(4);
10515
  ins_cost(DEFAULT_COST); // FIXME
10516
  format %{
10517
    "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B"
10518
  %}
10519
  ins_encode %{
10520
    bool quad = false;
10521
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10522
              MacroAssembler::VELEM_SIZE_8, quad);
10523
  %}
10524
  ins_pipe( ialu_reg_reg ); // FIXME
10525
%}
10526

10527
instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{
10528
  predicate(n->as_Vector()->length() == 16);
10529
  effect(DEF dst, USE src, USE shift);
10530
  size(4);
10531
  ins_cost(DEFAULT_COST); // FIXME
10532
  format %{
10533
    "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B"
10534
  %}
10535
  ins_encode %{
10536
    bool quad = true;
10537
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10538
              MacroAssembler::VELEM_SIZE_8, quad);
10539
  %}
10540
  ins_pipe( ialu_reg_reg ); // FIXME
10541
%}
10542

10543
// Shorts/Char vector logical left/right shift based on sign
10544
instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{
10545
  predicate(n->as_Vector()->length() == 4);
10546
  effect(DEF dst, USE src, USE shift);
10547
  size(4);
10548
  ins_cost(DEFAULT_COST); // FIXME
10549
  format %{
10550
    "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S"
10551
  %}
10552
  ins_encode %{
10553
    bool quad = false;
10554
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10555
              MacroAssembler::VELEM_SIZE_16, quad);
10556
  %}
10557
  ins_pipe( ialu_reg_reg ); // FIXME
10558
%}
10559

10560
instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{
10561
  predicate(n->as_Vector()->length() == 8);
10562
  effect(DEF dst, USE src, USE shift);
10563
  size(4);
10564
  ins_cost(DEFAULT_COST); // FIXME
10565
  format %{
10566
    "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S"
10567
  %}
10568
  ins_encode %{
10569
    bool quad = true;
10570
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10571
              MacroAssembler::VELEM_SIZE_16, quad);
10572
  %}
10573
  ins_pipe( ialu_reg_reg ); // FIXME
10574
%}
10575

10576
// Integers vector logical left/right shift based on sign
10577
instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{
10578
  predicate(n->as_Vector()->length() == 2);
10579
  effect(DEF dst, USE src, USE shift);
10580
  size(4);
10581
  ins_cost(DEFAULT_COST); // FIXME
10582
  format %{
10583
    "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I"
10584
  %}
10585
  ins_encode %{
10586
    bool quad = false;
10587
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10588
              MacroAssembler::VELEM_SIZE_32, quad);
10589
  %}
10590
  ins_pipe( ialu_reg_reg ); // FIXME
10591
%}
10592

10593
instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{
10594
  predicate(n->as_Vector()->length() == 4);
10595
  effect(DEF dst, USE src, USE shift);
10596
  size(4);
10597
  ins_cost(DEFAULT_COST); // FIXME
10598
  format %{
10599
    "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I"
10600
  %}
10601
  ins_encode %{
10602
    bool quad = true;
10603
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10604
              MacroAssembler::VELEM_SIZE_32, quad);
10605
  %}
10606
  ins_pipe( ialu_reg_reg ); // FIXME
10607
%}
10608

10609
// Longs vector logical left/right shift based on sign
10610
instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{
10611
  predicate(n->as_Vector()->length() == 2);
10612
  effect(DEF dst, USE src, USE shift);
10613
  size(4);
10614
  ins_cost(DEFAULT_COST); // FIXME
10615
  format %{
10616
    "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L"
10617
  %}
10618
  ins_encode %{
10619
    bool quad = true;
10620
    __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10621
              MacroAssembler::VELEM_SIZE_64, quad);
10622
  %}
10623
  ins_pipe( ialu_reg_reg ); // FIXME
10624
%}
10625

10626
// ------------------------------ LogicalLeftShift ----------------------------
10627

10628
// Byte vector logical left shift
10629
instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{
10630
  predicate(n->as_Vector()->length() == 8);
10631
  match(Set dst (LShiftVB src shift));
10632
  size(4*1);
10633
  ins_cost(DEFAULT_COST*1); // FIXME
10634
  expand %{
10635
    vsh8B_reg(dst, src, shift);
10636
  %}
10637
%}
10638

10639
instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{
10640
  predicate(n->as_Vector()->length() == 16);
10641
  match(Set dst (LShiftVB src shift));
10642
  size(4*1);
10643
  ins_cost(DEFAULT_COST*1); // FIXME
10644
  expand %{
10645
    vsh16B_reg(dst, src, shift);
10646
  %}
10647
%}
10648

10649
instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{
10650
  predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10651
  match(Set dst (LShiftVB src (LShiftCntV shift)));
10652
  size(4);
10653
  ins_cost(DEFAULT_COST); // FIXME
10654
  format %{
10655
    "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B"
10656
  %}
10657
  ins_encode %{
10658
    bool quad = false;
10659
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10660
             quad);
10661
  %}
10662
  ins_pipe( ialu_reg_reg ); // FIXME
10663
%}
10664

10665
instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{
10666
  predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
10667
  match(Set dst (LShiftVB src (LShiftCntV shift)));
10668
  size(4);
10669
  ins_cost(DEFAULT_COST); // FIXME
10670
  format %{
10671
    "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B"
10672
  %}
10673
  ins_encode %{
10674
    bool quad = true;
10675
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10676
             quad);
10677
  %}
10678
  ins_pipe( ialu_reg_reg ); // FIXME
10679
%}
10680

10681
// Shorts/Chars vector logical left shift
10682
instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{
10683
  predicate(n->as_Vector()->length() == 4);
10684
  match(Set dst (LShiftVS src shift));
10685
  size(4*1);
10686
  ins_cost(DEFAULT_COST*1); // FIXME
10687
  expand %{
10688
    vsh4S_reg(dst, src, shift);
10689
  %}
10690
%}
10691

10692
instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{
10693
  predicate(n->as_Vector()->length() == 8);
10694
  match(Set dst (LShiftVS src shift));
10695
  size(4*1);
10696
  ins_cost(DEFAULT_COST*1); // FIXME
10697
  expand %{
10698
    vsh8S_reg(dst, src, shift);
10699
  %}
10700
%}
10701

10702
instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{
10703
  predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10704
  match(Set dst (LShiftVS src (LShiftCntV shift)));
10705
  size(4);
10706
  ins_cost(DEFAULT_COST); // FIXME
10707
  format %{
10708
    "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S"
10709
  %}
10710
  ins_encode %{
10711
    bool quad = false;
10712
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10713
             quad);
10714
  %}
10715
  ins_pipe( ialu_reg_reg ); // FIXME
10716
%}
10717

10718
instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{
10719
  predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10720
  match(Set dst (LShiftVS src shift));
10721
  size(4);
10722
  ins_cost(DEFAULT_COST); // FIXME
10723
  format %{
10724
    "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S"
10725
  %}
10726
  ins_encode %{
10727
    bool quad = true;
10728
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10729
             quad);
10730
  %}
10731
  ins_pipe( ialu_reg_reg ); // FIXME
10732
%}
10733

10734
// Integers vector logical left shift
10735
instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{
10736
  predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10737
  match(Set dst (LShiftVI src shift));
10738
  size(4*1);
10739
  ins_cost(DEFAULT_COST*1); // FIXME
10740
  expand %{
10741
    vsh2I_reg(dst, src, shift);
10742
  %}
10743
%}
10744

10745
instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{
10746
  predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10747
  match(Set dst (LShiftVI src shift));
10748
  size(4*1);
10749
  ins_cost(DEFAULT_COST*1); // FIXME
10750
  expand %{
10751
    vsh4I_reg(dst, src, shift);
10752
  %}
10753
%}
10754

10755
instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{
10756
  predicate(n->as_Vector()->length() == 2 &&
10757
            VM_Version::has_simd() &&
10758
            assert_not_var_shift(n));
10759
  match(Set dst (LShiftVI src (LShiftCntV shift)));
10760
  size(4);
10761
  ins_cost(DEFAULT_COST); // FIXME
10762
  format %{
10763
    "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I"
10764
  %}
10765
  ins_encode %{
10766
    bool quad = false;
10767
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10768
             quad);
10769
  %}
10770
  ins_pipe( ialu_reg_reg ); // FIXME
10771
%}
10772

10773
instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{
10774
  predicate(n->as_Vector()->length() == 4 &&
10775
            VM_Version::has_simd() &&
10776
            assert_not_var_shift(n));
10777
  match(Set dst (LShiftVI src (LShiftCntV shift)));
10778
  size(4);
10779
  ins_cost(DEFAULT_COST); // FIXME
10780
  format %{
10781
    "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I"
10782
  %}
10783
  ins_encode %{
10784
    bool quad = true;
10785
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10786
             quad);
10787
  %}
10788
  ins_pipe( ialu_reg_reg ); // FIXME
10789
%}
10790

10791
// Longs vector logical left shift
10792
instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{
10793
  predicate(n->as_Vector()->length() == 2);
10794
  match(Set dst (LShiftVL src shift));
10795
  size(4*1);
10796
  ins_cost(DEFAULT_COST*1); // FIXME
10797
  expand %{
10798
    vsh2L_reg(dst, src, shift);
10799
  %}
10800
%}
10801

10802
instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{
10803
  predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
10804
  match(Set dst (LShiftVL src (LShiftCntV shift)));
10805
  size(4);
10806
  ins_cost(DEFAULT_COST); // FIXME
10807
  format %{
10808
    "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L"
10809
  %}
10810
  ins_encode %{
10811
    bool quad = true;
10812
    __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
10813
             quad);
10814
  %}
10815
  ins_pipe( ialu_reg_reg ); // FIXME
10816
%}
10817

10818
// ----------------------- LogicalRightShift -----------------------------------
10819

10820
// Bytes/Shorts vector logical right shift produces incorrect Java result
10821
// for negative data because java code convert short value into int with
10822
// sign extension before a shift.
10823

10824
// Right shift with vector shift count on aarch32 SIMD is implemented as left
10825
// shift by negative shift count value.
10826
//
10827
// Method is_var_shift() denotes that vector shift count is a variable shift:
10828
// 1) for this case, vector shift count should be negated before conducting
10829
//    right shifts. E.g., vsrl4S_reg_var rule.
10830
// 2) for the opposite case, vector shift count is generated via RShiftCntV
10831
//    rules and is already negated there. Hence, no negation is needed.
10832
//    E.g., vsrl4S_reg rule.
10833

10834
// Chars vector logical right shift
10835
instruct vsrl4S_reg(vecD dst, vecD src, vecD shift) %{
10836
  predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
10837
  match(Set dst (URShiftVS src shift));
10838
  size(4);
10839
  ins_cost(DEFAULT_COST);
10840
  expand %{
10841
    vsh4S_reg(dst, src, shift);
10842
  %}
10843
%}
10844

10845
instruct vsrl4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10846
  predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
10847
  match(Set dst (URShiftVS src shift));
10848
  effect(TEMP tmp);
10849
  size(4*2);
10850
  ins_cost(DEFAULT_COST*2);
10851
  format %{
10852
    "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10853
    "VSHL.U16 $dst.D,$src.D,$tmp.D\t! logical right shift packed4S"
10854
  %}
10855
  ins_encode %{
10856
    bool quad = false;
10857
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10858
             MacroAssembler::VELEM_SIZE_8, quad);
10859
    __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10860
              MacroAssembler::VELEM_SIZE_16, quad);
10861
  %}
10862
  ins_pipe(ialu_reg_reg);
10863
%}
10864

10865
instruct vsrl8S_reg(vecX dst, vecX src, vecX shift) %{
10866
  predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
10867
  match(Set dst (URShiftVS src shift));
10868
  size(4);
10869
  ins_cost(DEFAULT_COST);
10870
  expand %{
10871
    vsh8S_reg(dst, src, shift);
10872
  %}
10873
%}
10874

10875
instruct vsrl8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10876
  predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
10877
  match(Set dst (URShiftVS src shift));
10878
  effect(TEMP tmp);
10879
  size(4*2);
10880
  ins_cost(DEFAULT_COST*2);
10881
  format %{
10882
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10883
    "VSHL.U16 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed8S"
10884
  %}
10885
  ins_encode %{
10886
    bool quad = true;
10887
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10888
             MacroAssembler::VELEM_SIZE_8, quad);
10889
    __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10890
              MacroAssembler::VELEM_SIZE_16, quad);
10891
  %}
10892
  ins_pipe(ialu_reg_reg);
10893
%}
10894

10895
instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{
10896
  predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10897
  match(Set dst (URShiftVS src (RShiftCntV shift)));
10898
  size(4);
10899
  ins_cost(DEFAULT_COST); // FIXME
10900
  format %{
10901
    "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
10902
  %}
10903
  ins_encode %{
10904
    bool quad = false;
10905
    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10906
             quad);
10907
  %}
10908
  ins_pipe( ialu_reg_reg ); // FIXME
10909
%}
10910

10911
instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{
10912
  predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10913
  match(Set dst (URShiftVS src (RShiftCntV shift)));
10914
  size(4);
10915
  ins_cost(DEFAULT_COST); // FIXME
10916
  format %{
10917
    "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
10918
  %}
10919
  ins_encode %{
10920
    bool quad = true;
10921
    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10922
             quad);
10923
  %}
10924
  ins_pipe( ialu_reg_reg ); // FIXME
10925
%}
10926

10927
// Integers vector logical right shift
10928
instruct vsrl2I_reg(vecD dst, vecD src, vecD shift) %{
10929
  predicate(n->as_Vector()->length() == 2 &&
10930
            VM_Version::has_simd() &&
10931
            !n->as_ShiftV()->is_var_shift());
10932
  match(Set dst (URShiftVI src shift));
10933
  size(4);
10934
  ins_cost(DEFAULT_COST);
10935
  expand %{
10936
    vsh2I_reg(dst, src, shift);
10937
  %}
10938
%}
10939

10940
instruct vsrl2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10941
  predicate(n->as_Vector()->length() == 2 &&
10942
            VM_Version::has_simd() &&
10943
            n->as_ShiftV()->is_var_shift());
10944
  match(Set dst (URShiftVI src shift));
10945
  effect(TEMP tmp);
10946
  size(4*2);
10947
  ins_cost(DEFAULT_COST*2);
10948
  format %{
10949
    "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10950
    "VSHL.U32 $dst.D,$src.D,$tmp.D\t! logical right shift packed2I"
10951
  %}
10952
  ins_encode %{
10953
    bool quad = false;
10954
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10955
             MacroAssembler::VELEM_SIZE_8, quad);
10956
    __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10957
              MacroAssembler::VELEM_SIZE_32, quad);
10958
  %}
10959
  ins_pipe(ialu_reg_reg);
10960
%}
10961

10962
instruct vsrl4I_reg(vecX dst, vecX src, vecX shift) %{
10963
  predicate(n->as_Vector()->length() == 4 &&
10964
            VM_Version::has_simd() &&
10965
            !n->as_ShiftV()->is_var_shift());
10966
  match(Set dst (URShiftVI src shift));
10967
  size(4);
10968
  ins_cost(DEFAULT_COST);
10969
  expand %{
10970
    vsh4I_reg(dst, src, shift);
10971
  %}
10972
%}
10973

10974
instruct vsrl4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10975
  predicate(n->as_Vector()->length() == 4 &&
10976
            VM_Version::has_simd() &&
10977
            n->as_ShiftV()->is_var_shift());
10978
  match(Set dst (URShiftVI src shift));
10979
  effect(TEMP tmp);
10980
  size(4*2);
10981
  ins_cost(DEFAULT_COST*2);
10982
  format %{
10983
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10984
    "VSHL.U32 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed4I"
10985
  %}
10986
  ins_encode %{
10987
    bool quad = true;
10988
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10989
             MacroAssembler::VELEM_SIZE_8, quad);
10990
    __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10991
              MacroAssembler::VELEM_SIZE_32, quad);
10992
  %}
10993
  ins_pipe(ialu_reg_reg);
10994
%}
10995

10996
instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{
10997
  predicate(n->as_Vector()->length() == 2 &&
10998
            VM_Version::has_simd() &&
10999
            assert_not_var_shift(n));
11000
  match(Set dst (URShiftVI src (RShiftCntV shift)));
11001
  size(4);
11002
  ins_cost(DEFAULT_COST); // FIXME
11003
  format %{
11004
    "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
11005
  %}
11006
  ins_encode %{
11007
    bool quad = false;
11008
    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11009
             quad);
11010
  %}
11011
  ins_pipe( ialu_reg_reg ); // FIXME
11012
%}
11013

11014
instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{
11015
  predicate(n->as_Vector()->length() == 4 &&
11016
            VM_Version::has_simd() &&
11017
            assert_not_var_shift(n));
11018
  match(Set dst (URShiftVI src (RShiftCntV shift)));
11019
  size(4);
11020
  ins_cost(DEFAULT_COST); // FIXME
11021
  format %{
11022
    "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
11023
  %}
11024
  ins_encode %{
11025
    bool quad = true;
11026
    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11027
             quad);
11028
  %}
11029
  ins_pipe( ialu_reg_reg ); // FIXME
11030
%}
11031

11032
// Longs vector logical right shift
11033
instruct vsrl2L_reg(vecX dst, vecX src, vecX shift) %{
11034
  predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11035
  match(Set dst (URShiftVL src shift));
11036
  size(4);
11037
  ins_cost(DEFAULT_COST);
11038
  expand %{
11039
    vsh2L_reg(dst, src, shift);
11040
  %}
11041
%}
11042

11043
instruct vsrl2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11044
  predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11045
  match(Set dst (URShiftVL src shift));
11046
  effect(TEMP tmp, DEF dst, USE src, USE shift);
11047
  size(4*2);
11048
  ins_cost(DEFAULT_COST*2);
11049
  format %{
11050
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11051
    "VSHL.U64 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed2L"
11052
  %}
11053
  ins_encode %{
11054
    bool quad = true;
11055
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11056
             MacroAssembler::VELEM_SIZE_8, quad);
11057
    __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11058
              MacroAssembler::VELEM_SIZE_64, quad);
11059
  %}
11060
  ins_pipe(ialu_reg_reg);
11061
%}
11062

11063
instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{
11064
  predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11065
  match(Set dst (URShiftVL src (RShiftCntV shift)));
11066
  size(4);
11067
  ins_cost(DEFAULT_COST); // FIXME
11068
  format %{
11069
    "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
11070
  %}
11071
  ins_encode %{
11072
    bool quad = true;
11073
    __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11074
             quad);
11075
  %}
11076
  ins_pipe( ialu_reg_reg ); // FIXME
11077
%}
11078

11079
// ------------------- ArithmeticRightShift -----------------------------------
11080

11081
// Bytes vector arithmetic left/right shift based on sign
11082
instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{
11083
  predicate(n->as_Vector()->length() == 8);
11084
  effect(DEF dst, USE src, USE shift);
11085
  size(4);
11086
  ins_cost(DEFAULT_COST); // FIXME
11087
  format %{
11088
    "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B"
11089
  %}
11090
  ins_encode %{
11091
    bool quad = false;
11092
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11093
              MacroAssembler::VELEM_SIZE_8, quad);
11094
  %}
11095
  ins_pipe( ialu_reg_reg ); // FIXME
11096
%}
11097

11098
instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{
11099
  predicate(n->as_Vector()->length() == 16);
11100
  effect(DEF dst, USE src, USE shift);
11101
  size(4);
11102
  ins_cost(DEFAULT_COST); // FIXME
11103
  format %{
11104
    "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B"
11105
  %}
11106
  ins_encode %{
11107
    bool quad = true;
11108
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11109
              MacroAssembler::VELEM_SIZE_8, quad);
11110
  %}
11111
  ins_pipe( ialu_reg_reg ); // FIXME
11112
%}
11113

11114
// Shorts vector arithmetic left/right shift based on sign
11115
instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{
11116
  predicate(n->as_Vector()->length() == 4);
11117
  effect(DEF dst, USE src, USE shift);
11118
  size(4);
11119
  ins_cost(DEFAULT_COST); // FIXME
11120
  format %{
11121
    "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S"
11122
  %}
11123
  ins_encode %{
11124
    bool quad = false;
11125
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11126
              MacroAssembler::VELEM_SIZE_16, quad);
11127
  %}
11128
  ins_pipe( ialu_reg_reg ); // FIXME
11129
%}
11130

11131
instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{
11132
  predicate(n->as_Vector()->length() == 8);
11133
  effect(DEF dst, USE src, USE shift);
11134
  size(4);
11135
  ins_cost(DEFAULT_COST); // FIXME
11136
  format %{
11137
    "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S"
11138
  %}
11139
  ins_encode %{
11140
    bool quad = true;
11141
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11142
              MacroAssembler::VELEM_SIZE_16, quad);
11143
  %}
11144
  ins_pipe( ialu_reg_reg ); // FIXME
11145
%}
11146

11147
// Integers vector arithmetic left/right shift based on sign
11148
instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{
11149
  predicate(n->as_Vector()->length() == 2);
11150
  effect(DEF dst, USE src, USE shift);
11151
  size(4);
11152
  ins_cost(DEFAULT_COST); // FIXME
11153
  format %{
11154
    "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I"
11155
  %}
11156
  ins_encode %{
11157
    bool quad = false;
11158
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11159
              MacroAssembler::VELEM_SIZE_32, quad);
11160
  %}
11161
  ins_pipe( ialu_reg_reg ); // FIXME
11162
%}
11163

11164
instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{
11165
  predicate(n->as_Vector()->length() == 4);
11166
  effect(DEF dst, USE src, USE shift);
11167
  size(4);
11168
  ins_cost(DEFAULT_COST); // FIXME
11169
  format %{
11170
    "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I"
11171
  %}
11172
  ins_encode %{
11173
    bool quad = true;
11174
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11175
              MacroAssembler::VELEM_SIZE_32, quad);
11176
  %}
11177
  ins_pipe( ialu_reg_reg ); // FIXME
11178
%}
11179

11180
// Longs vector arithmetic left/right shift based on sign
11181
instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{
11182
  predicate(n->as_Vector()->length() == 2);
11183
  effect(DEF dst, USE src, USE shift);
11184
  size(4);
11185
  ins_cost(DEFAULT_COST); // FIXME
11186
  format %{
11187
    "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L"
11188
  %}
11189
  ins_encode %{
11190
    bool quad = true;
11191
    __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11192
              MacroAssembler::VELEM_SIZE_64, quad);
11193
  %}
11194
  ins_pipe( ialu_reg_reg ); // FIXME
11195
%}
11196

11197
// Byte vector arithmetic right shift
11198
instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{
11199
  predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11200
  match(Set dst (RShiftVB src shift));
11201
  size(4);
11202
  ins_cost(DEFAULT_COST); // FIXME
11203
  expand %{
11204
    vsha8B_reg(dst, src, shift);
11205
  %}
11206
%}
11207

11208
instruct vsra8B_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11209
  predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11210
  match(Set dst (RShiftVB src shift));
11211
  effect(TEMP tmp);
11212
  size(4*2);
11213
  ins_cost(DEFAULT_COST*2);
11214
  format %{
11215
    "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11216
    "VSHL.S8 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed8B"
11217
  %}
11218
  ins_encode %{
11219
    bool quad = false;
11220
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11221
             MacroAssembler::VELEM_SIZE_8, quad);
11222
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11223
              MacroAssembler::VELEM_SIZE_8, quad);
11224
  %}
11225
  ins_pipe(ialu_reg_reg);
11226
%}
11227

11228
instruct vsra16B_reg(vecX dst, vecX src, vecX shift) %{
11229
  predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift());
11230
  match(Set dst (RShiftVB src shift));
11231
  size(4);
11232
  ins_cost(DEFAULT_COST); // FIXME
11233
  expand %{
11234
    vsha16B_reg(dst, src, shift);
11235
  %}
11236
%}
11237

11238
instruct vsra16B_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11239
  predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift());
11240
  match(Set dst (RShiftVB src shift));
11241
  effect(TEMP tmp);
11242
  size(4*2);
11243
  ins_cost(DEFAULT_COST*2);
11244
  format %{
11245
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11246
    "VSHL.S8 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed16B"
11247
  %}
11248
  ins_encode %{
11249
    bool quad = true;
11250
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11251
             MacroAssembler::VELEM_SIZE_8, quad);
11252
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11253
              MacroAssembler::VELEM_SIZE_8, quad);
11254
  %}
11255
  ins_pipe(ialu_reg_reg);
11256
%}
11257

11258
instruct vsra8B_immI(vecD dst, vecD src, immI shift) %{
11259
  predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11260
  match(Set dst (RShiftVB src (RShiftCntV shift)));
11261
  size(4);
11262
  ins_cost(DEFAULT_COST); // FIXME
11263
  format %{
11264
    "VSHR.S8 $dst.D,$src.D,$shift\t! arithmetic right shift packed8B"
11265
  %}
11266
  ins_encode %{
11267
    bool quad = false;
11268
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11269
             quad);
11270
  %}
11271
  ins_pipe( ialu_reg_reg ); // FIXME
11272
%}
11273

11274
instruct vsra16B_immI(vecX dst, vecX src, immI shift) %{
11275
  predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
11276
  match(Set dst (RShiftVB src (RShiftCntV shift)));
11277
  size(4);
11278
  ins_cost(DEFAULT_COST); // FIXME
11279
  format %{
11280
    "VSHR.S8 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed16B"
11281
  %}
11282
  ins_encode %{
11283
    bool quad = true;
11284
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11285
             quad);
11286
  %}
11287
  ins_pipe( ialu_reg_reg ); // FIXME
11288
%}
11289

11290
// Shorts vector arithmetic right shift
11291
instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{
11292
  predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11293
  match(Set dst (RShiftVS src shift));
11294
  size(4);
11295
  ins_cost(DEFAULT_COST); // FIXME
11296
  expand %{
11297
    vsha4S_reg(dst, src, shift);
11298
  %}
11299
%}
11300

11301
instruct vsra4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11302
  predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11303
  match(Set dst (RShiftVS src shift));
11304
  effect(TEMP tmp);
11305
  size(4*2);
11306
  ins_cost(DEFAULT_COST*2);
11307
  format %{
11308
    "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11309
    "VSHL.S16 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed4S"
11310
  %}
11311
  ins_encode %{
11312
    bool quad = false;
11313
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11314
             MacroAssembler::VELEM_SIZE_8, quad);
11315
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11316
              MacroAssembler::VELEM_SIZE_16, quad);
11317
  %}
11318
  ins_pipe(ialu_reg_reg);
11319
%}
11320

11321
instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{
11322
  predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11323
  match(Set dst (RShiftVS src shift));
11324
  size(4);
11325
  ins_cost(DEFAULT_COST); // FIXME
11326
  expand %{
11327
    vsha8S_reg(dst, src, shift);
11328
  %}
11329
%}
11330

11331
instruct vsra8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11332
  predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11333
  match(Set dst (RShiftVS src shift));
11334
  effect(TEMP tmp);
11335
  size(4*2);
11336
  ins_cost(DEFAULT_COST*2);
11337
  format %{
11338
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11339
    "VSHL.S16 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed8S"
11340
  %}
11341
  ins_encode %{
11342
    bool quad = true;
11343
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11344
             MacroAssembler::VELEM_SIZE_8, quad);
11345
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11346
              MacroAssembler::VELEM_SIZE_16, quad);
11347
  %}
11348
  ins_pipe(ialu_reg_reg);
11349
%}
11350

11351
instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{
11352
  predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11353
  match(Set dst (RShiftVS src (RShiftCntV shift)));
11354
  size(4);
11355
  ins_cost(DEFAULT_COST); // FIXME
11356
  format %{
11357
    "VSHR.S16 $dst.D,$src.D,$shift\t! arithmetic right shift packed4S"
11358
  %}
11359
  ins_encode %{
11360
    bool quad = false;
11361
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11362
             quad);
11363
  %}
11364
  ins_pipe( ialu_reg_reg ); // FIXME
11365
%}
11366

11367
instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{
11368
  predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11369
  match(Set dst (RShiftVS src (RShiftCntV shift)));
11370
  size(4);
11371
  ins_cost(DEFAULT_COST); // FIXME
11372
  format %{
11373
    "VSHR.S16 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed8S"
11374
  %}
11375
  ins_encode %{
11376
    bool quad = true;
11377
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11378
             quad);
11379
  %}
11380
  ins_pipe( ialu_reg_reg ); // FIXME
11381
%}
11382

11383
// Integers vector arithmetic right shift
11384
instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{
11385
  predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11386
  match(Set dst (RShiftVI src shift));
11387
  size(4);
11388
  ins_cost(DEFAULT_COST); // FIXME
11389
  expand %{
11390
    vsha2I_reg(dst, src, shift);
11391
  %}
11392
%}
11393

11394
instruct vsra2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11395
  predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11396
  match(Set dst (RShiftVI src shift));
11397
  effect(TEMP tmp);
11398
  size(4*2);
11399
  ins_cost(DEFAULT_COST*2);
11400
  format %{
11401
    "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11402
    "VSHL.S32 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed2I"
11403
  %}
11404
  ins_encode %{
11405
    bool quad = false;
11406
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11407
             MacroAssembler::VELEM_SIZE_8, quad);
11408
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11409
              MacroAssembler::VELEM_SIZE_32, quad);
11410
  %}
11411
  ins_pipe(ialu_reg_reg);
11412
%}
11413

11414
instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{
11415
  predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11416
  match(Set dst (RShiftVI src shift));
11417
  size(4);
11418
  ins_cost(DEFAULT_COST); // FIXME
11419
  expand %{
11420
    vsha4I_reg(dst, src, shift);
11421
  %}
11422
%}
11423

11424
instruct vsra4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11425
  predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11426
  match(Set dst (RShiftVI src shift));
11427
  effect(TEMP tmp);
11428
  size(4*2);
11429
  ins_cost(DEFAULT_COST*2);
11430
  format %{
11431
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11432
    "VSHL.S32 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed4I"
11433
  %}
11434
  ins_encode %{
11435
    bool quad = true;
11436
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11437
             MacroAssembler::VELEM_SIZE_8, quad);
11438
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11439
              MacroAssembler::VELEM_SIZE_32, quad);
11440
  %}
11441
  ins_pipe(ialu_reg_reg);
11442
%}
11443

11444
instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{
11445
  predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11446
  match(Set dst (RShiftVI src (RShiftCntV shift)));
11447
  size(4);
11448
  ins_cost(DEFAULT_COST); // FIXME
11449
  format %{
11450
    "VSHR.S32 $dst.D,$src.D,$shift\t! arithmetic right shift packed2I"
11451
  %}
11452
  ins_encode %{
11453
    bool quad = false;
11454
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11455
             quad);
11456
  %}
11457
  ins_pipe( ialu_reg_reg ); // FIXME
11458
%}
11459

11460
instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{
11461
  predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11462
  match(Set dst (RShiftVI src (RShiftCntV shift)));
11463
  size(4);
11464
  ins_cost(DEFAULT_COST); // FIXME
11465
  format %{
11466
    "VSHR.S32 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed4I"
11467
  %}
11468
  ins_encode %{
11469
    bool quad = true;
11470
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11471
             quad);
11472
  %}
11473
  ins_pipe( ialu_reg_reg ); // FIXME
11474
%}
11475

11476
// Longs vector arithmetic right shift
11477
instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{
11478
  predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11479
  match(Set dst (RShiftVL src shift));
11480
  size(4);
11481
  ins_cost(DEFAULT_COST); // FIXME
11482
  expand %{
11483
    vsha2L_reg(dst, src, shift);
11484
  %}
11485
%}
11486

11487
instruct vsra2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11488
  predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11489
  match(Set dst (RShiftVL src shift));
11490
  effect(TEMP tmp);
11491
  size(4*2);
11492
  ins_cost(DEFAULT_COST*2);
11493
  format %{
11494
    "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11495
    "VSHL.S64 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed2L"
11496
  %}
11497
  ins_encode %{
11498
    bool quad = true;
11499
    __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11500
             MacroAssembler::VELEM_SIZE_8, quad);
11501
    __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11502
              MacroAssembler::VELEM_SIZE_64, quad);
11503
  %}
11504
  ins_pipe(ialu_reg_reg);
11505
%}
11506

11507
instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{
11508
  predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11509
  match(Set dst (RShiftVL src (RShiftCntV shift)));
11510
  size(4);
11511
  ins_cost(DEFAULT_COST); // FIXME
11512
  format %{
11513
    "VSHR.S64 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed2L"
11514
  %}
11515
  ins_encode %{
11516
    bool quad = true;
11517
    __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11518
             quad);
11519
  %}
11520
  ins_pipe( ialu_reg_reg ); // FIXME
11521
%}
11522

11523
// --------------------------------- AND --------------------------------------
11524

11525
instruct vandD(vecD dst, vecD src1, vecD src2) %{
11526
  predicate(n->as_Vector()->length_in_bytes() == 8);
11527
  match(Set dst (AndV src1 src2));
11528
  format %{ "VAND    $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11529
  ins_encode %{
11530
    bool quad = false;
11531
    __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11532
             quad);
11533
  %}
11534
  ins_pipe( ialu_reg_reg ); // FIXME
11535
%}
11536

11537
instruct vandX(vecX dst, vecX src1, vecX src2) %{
11538
  predicate(n->as_Vector()->length_in_bytes() == 16);
11539
  match(Set dst (AndV src1 src2));
11540
  format %{ "VAND    $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11541
  ins_encode %{
11542
    bool quad = true;
11543
    __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11544
             quad);
11545
  %}
11546
  ins_pipe( ialu_reg_reg ); // FIXME
11547
%}
11548

11549
// --------------------------------- OR ---------------------------------------
11550

11551
instruct vorD(vecD dst, vecD src1, vecD src2) %{
11552
  predicate(n->as_Vector()->length_in_bytes() == 8);
11553
  match(Set dst (OrV src1 src2));
11554
  format %{ "VOR     $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11555
  ins_encode %{
11556
    bool quad = false;
11557
    __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11558
            quad);
11559
  %}
11560
  ins_pipe( ialu_reg_reg ); // FIXME
11561
%}
11562

11563
instruct vorX(vecX dst, vecX src1, vecX src2) %{
11564
  predicate(n->as_Vector()->length_in_bytes() == 16);
11565
  match(Set dst (OrV src1 src2));
11566
  format %{ "VOR     $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11567
  ins_encode %{
11568
    bool quad = true;
11569
    __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11570
            quad);
11571
  %}
11572
  ins_pipe( ialu_reg_reg ); // FIXME
11573
%}
11574

11575
// --------------------------------- XOR --------------------------------------
11576

11577
instruct vxorD(vecD dst, vecD src1, vecD src2) %{
11578
  predicate(n->as_Vector()->length_in_bytes() == 8);
11579
  match(Set dst (XorV src1 src2));
11580
  format %{ "VXOR    $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11581
  ins_encode %{
11582
    bool quad = false;
11583
    __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11584
             quad);
11585
  %}
11586
  ins_pipe( ialu_reg_reg ); // FIXME
11587
%}
11588

11589
instruct vxorX(vecX dst, vecX src1, vecX src2) %{
11590
  predicate(n->as_Vector()->length_in_bytes() == 16);
11591
  match(Set dst (XorV src1 src2));
11592
  format %{ "VXOR    $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11593
  ins_encode %{
11594
    bool quad = true;
11595
    __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11596
             quad);
11597
  %}
11598
  ins_pipe( ialu_reg_reg ); // FIXME
11599
%}
11600

11601

11602
//----------PEEPHOLE RULES-----------------------------------------------------
11603
// These must follow all instruction definitions as they use the names
11604
// defined in the instructions definitions.
11605
//
11606
// peepmatch ( root_instr_name [preceding_instruction]* );
11607
//
11608
// peepconstraint %{
11609
// (instruction_number.operand_name relational_op instruction_number.operand_name
11610
//  [, ...] );
11611
// // instruction numbers are zero-based using left to right order in peepmatch
11612
//
11613
// peepreplace ( instr_name  ( [instruction_number.operand_name]* ) );
11614
// // provide an instruction_number.operand_name for each operand that appears
11615
// // in the replacement instruction's match rule
11616
//
11617
// ---------VM FLAGS---------------------------------------------------------
11618
//
11619
// All peephole optimizations can be turned off using -XX:-OptoPeephole
11620
//
11621
// Each peephole rule is given an identifying number starting with zero and
11622
// increasing by one in the order seen by the parser.  An individual peephole
11623
// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
11624
// on the command-line.
11625
//
11626
// ---------CURRENT LIMITATIONS----------------------------------------------
11627
//
11628
// Only match adjacent instructions in same basic block
11629
// Only equality constraints
11630
// Only constraints between operands, not (0.dest_reg == EAX_enc)
11631
// Only one replacement instruction
11632
//
11633
// ---------EXAMPLE----------------------------------------------------------
11634
//
11635
// // pertinent parts of existing instructions in architecture description
11636
// instruct movI(eRegI dst, eRegI src) %{
11637
//   match(Set dst (CopyI src));
11638
// %}
11639
//
11640
// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{
11641
//   match(Set dst (AddI dst src));
11642
//   effect(KILL cr);
11643
// %}
11644
//
11645
// // Change (inc mov) to lea
11646
// peephole %{
11647
//   // increment preceded by register-register move
11648
//   peepmatch ( incI_eReg movI );
11649
//   // require that the destination register of the increment
11650
//   // match the destination register of the move
11651
//   peepconstraint ( 0.dst == 1.dst );
11652
//   // construct a replacement instruction that sets
11653
//   // the destination to ( move's source register + one )
11654
//   peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) );
11655
// %}
11656
//
11657

11658
// // Change load of spilled value to only a spill
11659
// instruct storeI(memory mem, eRegI src) %{
11660
//   match(Set mem (StoreI mem src));
11661
// %}
11662
//
11663
// instruct loadI(eRegI dst, memory mem) %{
11664
//   match(Set dst (LoadI mem));
11665
// %}
11666
//
11667
// peephole %{
11668
//   peepmatch ( loadI storeI );
11669
//   peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
11670
//   peepreplace ( storeI( 1.mem 1.mem 1.src ) );
11671
// %}
11672

11673
//----------SMARTSPILL RULES---------------------------------------------------
11674
// These must follow all instruction definitions as they use the names
11675
// defined in the instructions definitions.
11676
//
11677
// ARM will probably not have any of these rules due to RISC instruction set.
11678

11679
//----------PIPELINE-----------------------------------------------------------
11680
// Rules which define the behavior of the target architectures pipeline.
11681

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.