xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/or1k/or1k.md (revision a24efa7dea9f1f56c3bdb15a927d3516792ace1c)
1;; Machine description for GNU compiler, OpenRISC 1000 family, OR32 ISA
2;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3;; 2009, 2010 Free Software Foundation, Inc.
4;; Copyright (C) 2010 Embecosm Limited
5
6;; Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
7;; Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> in 2005.
8;; Floating point additions by Jungsook Yang <jungsook.yang@uci.edu>
9;;                             Julius Baxter <julius@orsoc.se> in 2010
10;; Updated for GCC 4.5 by Jeremy Bennett <jeremy.bennett@embecosm.com>
11;; and Joern Rennecke <joern.rennecke@embecosm.com> in 2010
12
13;; This file is part of GNU CC.
14
15;; This program is free software; you can redistribute it and/or modify it
16;; under the terms of the GNU General Public License as published by the Free
17;; Software Foundation; either version 3 of the License, or (at your option)
18;; any later version.
19;;
20;; This program is distributed in the hope that it will be useful, but WITHOUT
21;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
23;; more details.
24;;
25;; You should have received a copy of the GNU General Public License along
26;; with this program.  If not, see <http://www.gnu.org/licenses/>. */
27
28(define_constants [
29  (SP_REG 1)
30  (FP_REG 2) ; hard frame pointer
31  (CC_REG 34)
32
33  ;; unspec values
34  (UNSPEC_FRAME         0)
35  (UNSPEC_GOT           1)
36  (UNSPEC_GOTOFFHI      2)
37  (UNSPEC_GOTOFFLO      3)
38  (UNSPEC_TPOFFLO       4)
39  (UNSPEC_TPOFFHI       5)
40  (UNSPEC_GOTTPOFFLO    6)
41  (UNSPEC_GOTTPOFFHI    7)
42  (UNSPEC_GOTTPOFFLD    8)
43  (UNSPEC_TLSGDLO       9)
44  (UNSPEC_TLSGDHI       10)
45  (UNSPEC_SET_GOT       101)
46  (UNSPEC_CMPXCHG       201)
47  (UNSPEC_FETCH_AND_OP  202)
48])
49
50(include "predicates.md")
51
52(include "constraints.md")
53
54(define_attr "type"
55  "unknown,load,store,move,extend,logic,add,mul,shift,compare,branch,jump,fp,jump_restore"
56  (const_string "unknown"))
57
58;; Number of machine instructions required to implement an insn.
59(define_attr "length" "" (const_int 1))
60
61;; Single delay slot after branch or jump instructions, wich may contain any
62;; instruction but another branch or jump.
63;; If TARGET_DELAY_OFF is not true, then never use delay slots.
64;; If TARGET_DELAY_ON is not true, no instruction will be allowed to
65;; fill the slot, and so it will be filled by a nop instead.
66(define_delay
67  (and (match_test "!TARGET_DELAY_OFF") (eq_attr "type" "branch,jump"))
68  [(and (match_test "TARGET_DELAY_ON")
69		     (eq_attr "type" "!branch,jump")
70		     (eq_attr "length" "1")) (nil) (nil)])
71
72;; ALU is modelled as a single functional unit, which is reserved for varying
73;; numbers of slots.
74;;
75;; I think this is all incorrect for the OR1K. The latency says when the
76;; result will be ready, not how long the pipeline takes to execute.
77(define_cpu_unit "or1k_alu")
78(define_insn_reservation "bit_unit" 3 (eq_attr "type" "shift") "or1k_alu")
79(define_insn_reservation "lsu_load" 3 (eq_attr "type" "load") "or1k_alu*3")
80(define_insn_reservation "lsu_store" 2 (eq_attr "type" "store") "or1k_alu")
81(define_insn_reservation "alu_unit" 2
82                         (eq_attr "type" "add,logic,extend,move,compare")
83			 "or1k_alu")
84(define_insn_reservation "mul_unit" 16 (eq_attr "type" "mul") "or1k_alu*16")
85
86;; AI = Atomic Integers
87;; We do not support DI in our atomic operations.
88(define_mode_iterator AI [QI HI SI])
89
90;; Note: We use 'mult' here for nand since it does not have its own RTX class.
91(define_code_iterator atomic_op [plus minus and ior xor mult])
92(define_code_attr op_name
93  [(plus "add") (minus "sub") (and "and") (ior "or") (xor "xor") (mult "nand")])
94(define_code_attr op_insn
95  [(plus "add") (minus "sub") (and "and") (ior "or") (xor "xor") (mult "and")])
96(define_code_attr post_op_insn
97  [(plus "") (minus "") (and "") (ior "") (xor "")
98   (mult "l.xori  \t%3,%3,0xffff # fetch_nand: invert")])
99
100;; Called after register allocation to add any instructions needed for the
101;; prologue.  Using a prologue insn is favored compared to putting all of the
102;; instructions in output_function_prologue(), since it allows the scheduler
103;; to intermix instructions with the saves of the caller saved registers.  In
104;; some cases, it might be necessary to emit a barrier instruction as the last
105;; insn to prevent such scheduling.
106
107(define_expand "prologue"
108  [(use (const_int 1))]
109  ""
110{
111  or1k_expand_prologue ();
112  DONE;
113})
114
115;; Called after register allocation to add any instructions needed for the
116;; epilogue.  Using an epilogue insn is favored compared to putting all of the
117;; instructions in output_function_epilogue(), since it allows the scheduler
118;; to intermix instructions with the restores of the caller saved registers.
119;; In some cases, it might be necessary to emit a barrier instruction as the
120;; first insn to prevent such scheduling.
121(define_expand "epilogue"
122  [(use (const_int 2))]
123  ""
124{
125  or1k_expand_epilogue ();
126  DONE;
127})
128
129(define_insn "frame_alloc_fp"
130  [(set (reg:SI SP_REG)
131	(plus:SI (reg:SI SP_REG)
132		 (match_operand:SI 0 "nonmemory_operand" "r,I")))
133   (clobber (mem:QI (plus:SI (reg:SI FP_REG)
134			     (unspec:SI [(const_int FP_REG)] UNSPEC_FRAME))))]
135  ""
136  "@
137   l.add\tr1,r1,%0\t# allocate frame
138   l.addi\tr1,r1,%0\t# allocate frame"
139  [(set_attr "type" "add")
140   (set_attr "length" "1")])
141
142(define_insn "frame_dealloc_fp"
143  [(set (reg:SI SP_REG) (reg:SI FP_REG))
144   (clobber (mem:QI (plus:SI (reg:SI FP_REG)
145			     (unspec:SI [(const_int FP_REG)] UNSPEC_FRAME))))]
146  ""
147  "l.ori\tr1,r2,0\t# deallocate frame"
148  [(set_attr "type" "logic")
149   (set_attr "length" "1")])
150
151(define_insn "frame_dealloc_sp"
152  [(set (reg:SI SP_REG)
153	(plus:SI (reg:SI SP_REG)
154		 (match_operand:SI 0 "nonmemory_operand" "r,I")))
155   (clobber (mem:QI (plus:SI (reg:SI SP_REG)
156			     (unspec:SI [(const_int SP_REG)] UNSPEC_FRAME))))]
157  ""
158  "@
159   l.add    \tr1,r1,%0
160   l.addi   \tr1,r1,%0"
161  [(set_attr "type" "add")
162   (set_attr "length" "1")])
163
164(define_insn "return_internal"
165  [(return)
166   (use (match_operand 0 "pmode_register_operand" ""))]
167  ""
168  "l.jr    \t%0\t# return_internal%("
169  [(set_attr "type" "jump")
170   (set_attr "length" "1")])
171
172
173
174;;
175;; movQI
176;;
177
178(define_expand "movqi"
179  [(set (match_operand:QI 0 "general_operand" "")
180	(match_operand:QI 1 "general_operand" ""))]
181  ""
182  "
183      if (can_create_pseudo_p())
184        {
185          if (GET_CODE (operands[1]) == CONST_INT)
186	    {
187	      rtx reg = gen_reg_rtx (SImode);
188
189	      emit_insn (gen_movsi (reg, operands[1]));
190	      operands[1] = gen_lowpart (QImode, reg);
191	    }
192	  if (GET_CODE (operands[1]) == MEM && optimize > 0)
193	    {
194	      rtx reg = gen_reg_rtx (SImode);
195
196	      emit_insn (gen_rtx_SET (SImode, reg,
197				  gen_rtx_ZERO_EXTEND (SImode,
198						       operands[1])));
199
200	      operands[1] = gen_lowpart (QImode, reg);
201	    }
202          if (GET_CODE (operands[0]) != REG)
203	    operands[1] = force_reg (QImode, operands[1]);
204        }
205")
206
207(define_insn "*movqi_internal"
208  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,r,r,r,r")
209	(match_operand:QI 1 "general_operand"       "r,r,I,K,m"))]
210  ""
211  "@
212   l.sb    \t%0,%1\t    # movqi
213   l.ori   \t%0,%1,0\t  # movqi: move reg to reg
214   l.addi  \t%0,r0,%1\t # movqi: move immediate
215   l.ori   \t%0,r0,%1\t # movqi: move immediate
216   l.lbz   \t%0,%1\t    # movqi"
217  [(set_attr "type" "store,add,add,logic,load")])
218
219
220;;
221;; movHI
222;;
223
224(define_expand "movhi"
225  [(set (match_operand:HI 0 "general_operand" "")
226	(match_operand:HI 1 "general_operand" ""))]
227  ""
228  "
229      if (can_create_pseudo_p())
230        {
231          if (GET_CODE (operands[1]) == CONST_INT)
232	    {
233	      rtx reg = gen_reg_rtx (SImode);
234
235	      emit_insn (gen_movsi (reg, operands[1]));
236	      operands[1] = gen_lowpart (HImode, reg);
237	    }
238	  else if (GET_CODE (operands[1]) == MEM && optimize > 0)
239	    {
240	      rtx reg = gen_reg_rtx (SImode);
241
242	      emit_insn (gen_rtx_SET (SImode, reg,
243				      gen_rtx_ZERO_EXTEND (SImode,
244					   	           operands[1])));
245	      operands[1] = gen_lowpart (HImode, reg);
246	    }
247          if (GET_CODE (operands[0]) != REG)
248	    operands[1] = force_reg (HImode, operands[1]);
249        }
250")
251
252(define_insn "*movhi_internal"
253  [(set (match_operand:HI 0 "nonimmediate_operand" "=m,r,r,r,r")
254	(match_operand:HI 1 "general_operand"       "r,r,I,K,m"))]
255  ""
256  "@
257   l.sh    \t%0,%1\t # movhi
258   l.ori   \t%0,%1,0\t # movhi: move reg to reg
259   l.addi  \t%0,r0,%1\t # movhi: move immediate
260   l.ori   \t%0,r0,%1\t # movhi: move immediate
261   l.lhz   \t%0,%1\t # movhi"
262  [(set_attr "type" "store,add,add,logic,load")])
263
264(define_expand "movsi"
265  [(set (match_operand:SI 0 "general_operand" "")
266	(match_operand:SI 1 "general_operand" ""))]
267  ""
268{
269  if (or1k_expand_move (SImode, operands)) DONE;
270})
271
272;;
273;; movSI
274;;
275
276(define_insn "*movsi_insn"
277  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m")
278        (match_operand:SI 1 "input_operand"       "I,K,M,r,m,r"))]
279  "(register_operand (operands[0], SImode)
280   || (register_operand (operands[1], SImode))
281   || (operands[1] == const0_rtx))"
282  "@
283  l.addi  \t%0,r0,%1\t # move immediate I
284  l.ori   \t%0,r0,%1\t # move immediate K
285  l.movhi \t%0,hi(%1)\t # move immediate M
286  l.ori   \t%0,%1,0\t # move reg to reg
287  l.lwz   \t%0,%1\t # SI load
288  l.sw    \t%0,%1\t # SI store"
289  [(set_attr "type" "add,load,store,add,logic,move")
290   (set_attr "length" "1,1,1,1,1,1")])
291
292(define_insn "movsi_lo_sum"
293  [(set (match_operand:SI 0 "register_operand" "=r")
294	(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
295                   (match_operand:SI 2 "immediate_operand" "i")))]
296  ""
297  "l.ori   \t%0,%1,lo(%2) # movsi_lo_sum"
298 [(set_attr "type" "logic")
299   (set_attr "length" "1")])
300
301(define_insn "movsi_high"
302  [(set (match_operand:SI 0 "register_operand" "=r")
303	(high:SI (match_operand:SI 1 "immediate_operand" "i")))]
304  ""
305  "l.movhi  \t%0,hi(%1) # movsi_high"
306[(set_attr "type" "move")
307   (set_attr "length" "1")])
308
309(define_insn "movsi_gotofflo"
310  [(set (match_operand:SI 0 "register_operand" "=r")
311 	(unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
312                    (match_operand 2 "" ""))] UNSPEC_GOTOFFLO))]
313  "flag_pic"
314  "l.ori   \t%0,%1,gotofflo(%2) # movsi_gotofflo"
315  [(set_attr "type" "logic")
316   (set_attr "length" "1")])
317
318(define_insn "movsi_gotoffhi"
319  [(set (match_operand:SI 0 "register_operand" "=r")
320 	(unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFFHI))]
321  "flag_pic"
322  "l.movhi  \t%0,gotoffhi(%1) # movsi_gotoffhi"
323  [(set_attr "type" "move")
324   (set_attr "length" "1")])
325
326(define_insn "movsi_got"
327  [(set (match_operand:SI 0 "register_operand" "=r")
328        (unspec:SI [(match_operand 1 "symbolic_operand" "")] UNSPEC_GOT))
329   (use (reg:SI 16))]
330  "flag_pic"
331  "l.lwz    \t%0, got(%1)(r16)"
332  [(set_attr "type" "load")]
333)
334
335(define_insn "movsi_tlsgdlo"
336  [(set (match_operand:SI 0 "register_operand" "=r")
337	(unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
338                   (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_TLSGDLO))]
339  ""
340  "l.ori   \t%0,%1,tlsgdlo(%2) # movsi_tlsgdlo"
341 [(set_attr "type" "logic")
342   (set_attr "length" "1")])
343
344(define_insn "movsi_tlsgdhi"
345  [(set (match_operand:SI 0 "register_operand" "=r")
346	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_TLSGDHI))]
347  ""
348  "l.movhi  \t%0,tlsgdhi(%1) # movsi_tlsgdhi"
349[(set_attr "type" "move")
350   (set_attr "length" "1")])
351
352(define_insn "movsi_gottpofflo"
353  [(set (match_operand:SI 0 "register_operand" "=r")
354	(unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
355                   (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_GOTTPOFFLO))]
356  ""
357  "l.ori   \t%0,%1,gottpofflo(%2) # movsi_gottpofflo"
358 [(set_attr "type" "logic")
359   (set_attr "length" "1")])
360
361(define_insn "movsi_gottpoffhi"
362  [(set (match_operand:SI 0 "register_operand" "=r")
363	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_GOTTPOFFHI))]
364  ""
365  "l.movhi  \t%0,gottpoffhi(%1) # movsi_gottpoffhi"
366[(set_attr "type" "move")
367   (set_attr "length" "1")])
368
369(define_insn "load_gottpoff"
370  [(set (match_operand:SI 0 "register_operand" "=r")
371	(unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_GOTTPOFFLD))]
372  ""
373  "l.lwz  \t%0,0(%1) # load_gottpoff"
374[(set_attr "type" "load")
375   (set_attr "length" "1")])
376
377(define_insn "movsi_tpofflo"
378  [(set (match_operand:SI 0 "register_operand" "=r")
379	(unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
380                   (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_TPOFFLO))]
381  ""
382  "l.ori   \t%0,%1,tpofflo(%2) # movsi_tpofflo"
383 [(set_attr "type" "logic")
384   (set_attr "length" "1")])
385
386(define_insn "movsi_tpoffhi"
387  [(set (match_operand:SI 0 "register_operand" "=r")
388	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_TPOFFHI))]
389  ""
390  "l.movhi  \t%0,tpoffhi(%1) # movsi_tpoffhi"
391[(set_attr "type" "move")
392   (set_attr "length" "1")])
393
394
395(define_insn_and_split "movsi_insn_big"
396  [(set (match_operand:SI 0 "register_operand" "=r")
397	(match_operand:SI 1 "immediate_operand" "i"))]
398  "GET_CODE (operands[1]) != CONST_INT"
399  ;; the switch of or1k bfd to Rela allows us to schedule insns separately.
400  "l.movhi \t%0,hi(%1)\;l.ori   \t%0,%0,lo(%1)"
401  "(GET_CODE (operands[1]) != CONST_INT
402    || ! (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'I', \"I\")
403	  || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'K', \"K\")
404	  || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'M', \"M\")))
405   && reload_completed
406   && GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != LO_SUM"
407  [(pc)]
408{
409  if (!or1k_expand_symbol_ref(SImode, operands))
410    {
411      emit_insn (gen_movsi_high (operands[0], operands[1]));
412      emit_insn (gen_movsi_lo_sum (operands[0], operands[0], operands[1]));
413    }
414  DONE;
415}
416  [(set_attr "type" "move")
417   (set_attr "length" "2")])
418
419
420;;
421;; Conditional Branches & Moves
422;;
423
424(define_expand "addsicc"
425  [(match_operand:SI 0 "register_operand" "")
426   (match_operand 1 "comparison_operator" "")
427   (match_operand:SI 2 "register_operand" "")
428   (match_operand:SI 3 "register_operand" "")]
429  ""
430  "FAIL;")
431
432(define_expand "addhicc"
433  [(match_operand:HI 0 "register_operand" "")
434   (match_operand 1 "comparison_operator" "")
435   (match_operand:HI 2 "register_operand" "")
436   (match_operand:HI 3 "register_operand" "")]
437  ""
438  "FAIL;")
439
440(define_expand "addqicc"
441  [(match_operand:QI 0 "register_operand" "")
442   (match_operand 1 "comparison_operator" "")
443   (match_operand:QI 2 "register_operand" "")
444   (match_operand:QI 3 "register_operand" "")]
445  ""
446  "FAIL;")
447
448
449;;
450;; conditional moves
451;;
452
453(define_expand "movsicc"
454   [(set (match_operand:SI 0 "register_operand" "")
455	 (if_then_else:SI (match_operand 1 "comparison_operator" "")
456			  (match_operand:SI 2 "register_operand" "")
457			  (match_operand:SI 3 "register_operand" "")))]
458  "TARGET_MASK_CMOV"
459  "
460{
461  if (or1k_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
462    DONE;
463}")
464
465(define_expand "movhicc"
466   [(set (match_operand:HI 0 "register_operand" "")
467	 (if_then_else:SI (match_operand 1 "comparison_operator" "")
468			  (match_operand:HI 2 "register_operand" "")
469			  (match_operand:HI 3 "register_operand" "")))]
470  ""
471  "
472{
473    FAIL;
474}")
475
476(define_expand "movqicc"
477   [(set (match_operand:QI 0 "register_operand" "")
478	 (if_then_else:SI (match_operand 1 "comparison_operator" "")
479			  (match_operand:QI 2 "register_operand" "")
480			  (match_operand:QI 3 "register_operand" "")))]
481  ""
482  "
483{
484    FAIL;
485}")
486
487
488;; We use the BASE_REGS for the cmov input operands because, if rA is
489;; 0, the value of 0 is placed in rD upon truth.  Similarly for rB
490;; because we may switch the operands and rB may end up being rA.
491
492(define_insn "cmov"
493  [(set (match_operand:SI 0 "register_operand" "=r")
494	(if_then_else:SI
495	 (match_operator 1 "comparison_operator"
496			 [(match_operand 4 "cc_reg_operand" "")
497			  (const_int 0)])
498	 (match_operand:SI 2 "register_operand" "r")
499	 (match_operand:SI 3 "register_operand" "r")))]
500  "TARGET_MASK_CMOV"
501  "*
502   return or1k_output_cmov(operands);
503  ")
504
505;;
506;;  ....................
507;;
508;;	COMPARISONS
509;;
510;;  ....................
511
512;; Flow here is rather complex:
513;;
514;;  1)	The cmp{si,di,sf,df} routine is called.  It deposits the
515;;	arguments into the branch_cmp array, and the type into
516;;	branch_type.  No RTL is generated.
517;;
518;;  2)	The appropriate branch define_expand is called, which then
519;;	creates the appropriate RTL for the comparison and branch.
520;;	Different CC modes are used, based on what type of branch is
521;;	done, so that we can constrain things appropriately.  There
522;;	are assumptions in the rest of GCC that break if we fold the
523;;	operands into the branches for integer operations, and use cc0
524;;	for floating point, so we use the fp status register instead.
525;;	If needed, an appropriate temporary is created to hold the
526;;	of the integer compare.
527
528;; Compare insns are next.  Note that the RS/6000 has two types of compares,
529;; signed & unsigned, and one type of branch.
530;;
531;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
532;; insns, and branches.  We store the operands of compares until we see
533;; how it is used.
534
535;; JPB 31-Aug-10: cmpxx appears to be obsolete in GCC 4.5. Needs more
536;; investigation.
537
538;;(define_expand "cmpsi"
539;;  [(set (reg:CC CC_REG)
540;;	(compare:CC (match_operand:SI 0 "register_operand" "")
541;;		    (match_operand:SI 1 "nonmemory_operand" "")))]
542;;  ""
543;;  {
544;;   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
545;;      operands[0] = force_reg (SImode, operands[0]);
546;;      or1k_compare_op0 = operands[0];
547;;     or1k_compare_op1 = operands[1];
548;;      DONE;
549;;      })
550
551;; (define_expand "cmpsf"
552;;   [(set (reg:CC CC_REG)
553;; 	(compare:CC (match_operand:SF 0 "register_operand" "")
554;; 		    (match_operand:SF 1 "register_operand" "")))]
555;;   "TARGET_HARD_FLOAT"
556;;   {
557;;    if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
558;;       operands[0] = force_reg (SFmode, operands[0]);
559;;       or1k_compare_op0 = operands[0];
560;;       or1k_compare_op1 = operands[1];
561;;       DONE;
562;;       })
563
564(define_expand "cbranchsi4"
565  [(match_operator 0 "comparison_operator"
566    [(match_operand:SI 1 "register_operand")
567     (match_operand:SI 2 "nonmemory_operand")])
568   (match_operand 3 "")]
569   ""
570   {
571   or1k_expand_conditional_branch (operands, SImode);
572   DONE;
573   })
574
575(define_expand "cbranchsf4"
576  [(match_operator 0 "comparison_operator"
577    [(match_operand:SF 1 "register_operand")
578     (match_operand:SF 2 "register_operand")])
579   (match_operand 3 "")]
580   "TARGET_HARD_FLOAT"
581   {
582   or1k_expand_conditional_branch (operands, SFmode);
583   DONE;
584   })
585
586;;
587;; Setting a CCxx registers from comparision
588;;
589
590
591
592;; Here are the actual compare insns.
593(define_insn "*cmpsi_eq"
594  [(set (reg:CCEQ CC_REG)
595	(compare:CCEQ (match_operand:SI 0 "register_operand" "r,r")
596		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
597  ""
598  "@
599   l.sfeqi\t%0,%1 # cmpsi_eq
600   l.sfeq \t%0,%1 # cmpsi_eq"
601  [(set_attr "type" "compare")
602   (set_attr "length" "1")])
603
604(define_insn "*cmpsi_ne"
605  [(set (reg:CCNE CC_REG)
606	(compare:CCNE (match_operand:SI 0 "register_operand" "r,r")
607		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
608  ""
609  "@
610   l.sfnei\t%0,%1 # cmpsi_ne
611   l.sfne \t%0,%1 # cmpsi_ne"
612  [(set_attr "type" "compare")
613   (set_attr "length" "1")])
614
615(define_insn "*cmpsi_gt"
616  [(set (reg:CCGT CC_REG)
617	(compare:CCGT (match_operand:SI 0 "register_operand" "r,r")
618		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
619  ""
620  "@
621   l.sfgtsi\t%0,%1 # cmpsi_gt
622   l.sfgts \t%0,%1 # cmpsi_gt"
623  [(set_attr "type" "compare")
624   (set_attr "length" "1")])
625
626(define_insn "*cmpsi_gtu"
627  [(set (reg:CCGTU CC_REG)
628	(compare:CCGTU (match_operand:SI 0 "register_operand" "r,r")
629		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
630  ""
631  "@
632   l.sfgtui\t%0,%1 # cmpsi_gtu
633   l.sfgtu \t%0,%1 # cmpsi_gtu"
634  [(set_attr "type" "compare")
635   (set_attr "length" "1")])
636
637(define_insn "*cmpsi_lt"
638  [(set (reg:CCLT CC_REG)
639	(compare:CCLT (match_operand:SI 0 "register_operand" "r,r")
640		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
641  ""
642  "@
643   l.sfltsi\t%0,%1 # cmpsi_lt
644   l.sflts \t%0,%1 # cmpsi_lt"
645  [(set_attr "type" "compare")
646   (set_attr "length" "1")])
647
648(define_insn "*cmpsi_ltu"
649  [(set (reg:CCLTU CC_REG)
650	(compare:CCLTU (match_operand:SI 0 "register_operand" "r,r")
651		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
652  ""
653  "@
654   l.sfltui\t%0,%1 # cmpsi_ltu
655   l.sfltu \t%0,%1 # cmpsi_ltu"
656  [(set_attr "type" "compare")
657   (set_attr "length" "1")])
658
659(define_insn "*cmpsi_ge"
660  [(set (reg:CCGE CC_REG)
661	(compare:CCGE (match_operand:SI 0 "register_operand" "r,r")
662		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
663  ""
664  "@
665   l.sfgesi\t%0,%1 # cmpsi_ge
666   l.sfges \t%0,%1 # cmpsi_ge"
667  [(set_attr "type" "compare")
668   (set_attr "length" "1")])
669
670
671(define_insn "*cmpsi_geu"
672  [(set (reg:CCGEU CC_REG)
673	(compare:CCGEU (match_operand:SI 0 "register_operand" "r,r")
674		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
675  ""
676  "@
677   l.sfgeui\t%0,%1 # cmpsi_geu
678   l.sfgeu \t%0,%1 # cmpsi_geu"
679  [(set_attr "type" "compare")
680   (set_attr "length" "1")])
681
682
683(define_insn "*cmpsi_le"
684  [(set (reg:CCLE CC_REG)
685	(compare:CCLE (match_operand:SI 0 "register_operand" "r,r")
686		      (match_operand:SI 1 "nonmemory_operand" "I,r")))]
687  ""
688  "@
689   l.sflesi\t%0,%1 # cmpsi_le
690   l.sfles \t%0,%1 # cmpsi_le"
691  [(set_attr "type" "compare")
692   (set_attr "length" "1")])
693
694(define_insn "*cmpsi_leu"
695  [(set (reg:CCLEU CC_REG)
696	(compare:CCLEU (match_operand:SI 0 "register_operand" "r,r")
697		       (match_operand:SI 1 "nonmemory_operand" "I,r")))]
698  ""
699  "@
700   l.sfleui\t%0,%1 # cmpsi_leu
701   l.sfleu \t%0,%1 # cmpsi_leu"
702  [(set_attr "type" "compare")
703   (set_attr "length" "1")])
704
705;; Single precision floating point evaluation instructions
706(define_insn "*cmpsf_eq"
707  [(set (reg:CCEQ CC_REG)
708	(compare:CCEQ (match_operand:SF 0 "register_operand" "r,r")
709		      (match_operand:SF 1 "register_operand" "r,r")))]
710  "TARGET_HARD_FLOAT"
711  "lf.sfeq.s\t%0,%1 # cmpsf_eq"
712  [(set_attr "type" "compare")
713   (set_attr "length" "1")])
714
715(define_insn "*cmpsf_ne"
716  [(set (reg:CCNE CC_REG)
717	(compare:CCNE (match_operand:SF 0 "register_operand" "r,r")
718		      (match_operand:SF 1 "register_operand" "r,r")))]
719  "TARGET_HARD_FLOAT"
720  "lf.sfne.s\t%0,%1 # cmpsf_ne"
721  [(set_attr "type" "compare")
722   (set_attr "length" "1")])
723
724
725(define_insn "*cmpsf_gt"
726  [(set (reg:CCGT CC_REG)
727	(compare:CCGT (match_operand:SF 0 "register_operand" "r,r")
728		      (match_operand:SF 1 "register_operand" "r,r")))]
729  "TARGET_HARD_FLOAT"
730  "lf.sfgt.s\t%0,%1 # cmpsf_gt"
731  [(set_attr "type" "compare")
732   (set_attr "length" "1")])
733
734(define_insn "*cmpsf_ge"
735  [(set (reg:CCGE CC_REG)
736	(compare:CCGE (match_operand:SF 0 "register_operand" "r,r")
737		      (match_operand:SF 1 "register_operand" "r,r")))]
738  "TARGET_HARD_FLOAT"
739  "lf.sfge.s\t%0,%1 # cmpsf_ge"
740  [(set_attr "type" "compare")
741   (set_attr "length" "1")])
742
743
744(define_insn "*cmpsf_lt"
745  [(set (reg:CCLT CC_REG)
746	(compare:CCLT (match_operand:SF 0 "register_operand" "r,r")
747		      (match_operand:SF 1 "register_operand" "r,r")))]
748  "TARGET_HARD_FLOAT"
749  "lf.sflt.s\t%0,%1 # cmpsf_lt"
750  [(set_attr "type" "compare")
751   (set_attr "length" "1")])
752
753(define_insn "*cmpsf_le"
754  [(set (reg:CCLE CC_REG)
755	(compare:CCLE (match_operand:SF 0 "register_operand" "r,r")
756		      (match_operand:SF 1 "register_operand" "r,r")))]
757  "TARGET_HARD_FLOAT"
758  "lf.sfle.s\t%0,%1 # cmpsf_le"
759  [(set_attr "type" "compare")
760   (set_attr "length" "1")])
761
762(define_insn "*bf"
763  [(set (pc)
764	(if_then_else (match_operator 1 "comparison_operator"
765				      [(match_operand 2
766						      "cc_reg_operand" "")
767				       (const_int 0)])
768		      (label_ref (match_operand 0 "" ""))
769		      (pc)))]
770  ""
771  "*
772   return or1k_output_bf(operands);
773  "
774  [(set_attr "type" "branch")
775   (set_attr "length" "1")])
776
777;;
778;;
779;;
780;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
781;;
782;;
783(define_insn_and_split "movdi"
784  [(set (match_operand:DI 0 "nonimmediate_operand" "=r, r, m, r")
785	(match_operand:DI 1 "general_operand"      " r, m, r, n"))]
786  ""
787  "*
788    return or1k_output_move_double (operands);
789  "
790  "&& reload_completed && CONSTANT_P (operands[1])"
791  [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))]
792  "operands[2] = operand_subword (operands[0], 0, 0, DImode);
793   operands[3] = operand_subword (operands[1], 0, 0, DImode);
794   operands[4] = operand_subword (operands[0], 1, 0, DImode);
795   operands[5] = operand_subword (operands[1], 1, 0, DImode);"
796  [(set_attr "length" "2,2,2,3")])
797
798;; Moving double and single precision floating point values
799
800
801(define_insn "movdf"
802  [(set (match_operand:DF 0 "nonimmediate_operand" "=r, r, m, r")
803	(match_operand:DF 1 "general_operand"      " r, m, r, i"))]
804  ""
805  "*
806    return or1k_output_move_double (operands);
807  "
808  [(set_attr "length" "2,2,2,3")])
809
810
811(define_insn "movsf"
812  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
813        (match_operand:SF 1 "general_operand"  "r,m,r"))]
814  ""
815  "@
816   l.ori   \t%0,%1,0\t # movsf
817   l.lwz   \t%0,%1\t # movsf
818   l.sw    \t%0,%1\t # movsf"
819  [(set_attr "type" "move,load,store")
820   (set_attr "length" "1,1,1")])
821
822
823;;
824;; extendqisi2
825;;
826
827(define_expand "extendqisi2"
828  [(use (match_operand:SI 0 "register_operand" ""))
829   (use (match_operand:QI 1 "nonimmediate_operand" ""))]
830  ""
831  "
832{
833  if (TARGET_MASK_SEXT)
834    emit_insn (gen_extendqisi2_sext(operands[0], operands[1]));
835  else {
836    if ( GET_CODE(operands[1]) == MEM ) {
837      emit_insn (gen_extendqisi2_no_sext_mem(operands[0], operands[1]));
838    }
839    else {
840      emit_insn (gen_extendqisi2_no_sext_reg(operands[0], operands[1]));
841    }
842 }
843 DONE;
844}")
845
846(define_insn "extendqisi2_sext"
847  [(set (match_operand:SI 0 "register_operand" "=r,r")
848	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
849  "TARGET_MASK_SEXT"
850  "@
851   l.extbs \t%0,%1\t # extendqisi2_has_signed_extend
852   l.lbs   \t%0,%1\t # extendqisi2_has_signed_extend"
853  [(set_attr "length" "1,1")
854   (set_attr "type" "extend,load")])
855
856(define_insn "extendqisi2_no_sext_mem"
857  [(set (match_operand:SI 0 "register_operand" "=r")
858        (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
859  "!TARGET_MASK_SEXT"
860  "l.lbs   \t%0,%1\t # extendqisi2_no_sext_mem"
861  [(set_attr "length" "1")
862   (set_attr "type" "load")])
863
864(define_expand "extendqisi2_no_sext_reg"
865  [(set (match_dup 2)
866	(ashift:SI (match_operand:QI 1 "register_operand" "")
867		   (const_int 24)))
868   (set (match_operand:SI 0 "register_operand" "")
869	(ashiftrt:SI (match_dup 2)
870		     (const_int 24)))]
871  "!TARGET_MASK_SEXT"
872  "
873{
874  operands[1] = gen_lowpart (SImode, operands[1]);
875  operands[2] = gen_reg_rtx (SImode); }")
876
877;;
878;; extendhisi2
879;;
880
881(define_expand "extendhisi2"
882  [(use (match_operand:SI 0 "register_operand" ""))
883   (use (match_operand:HI 1 "nonimmediate_operand" ""))]
884  ""
885  "
886{
887  if (TARGET_MASK_SEXT)
888    emit_insn (gen_extendhisi2_sext(operands[0], operands[1]));
889  else {
890    if ( GET_CODE(operands[1]) == MEM ) {
891      emit_insn (gen_extendhisi2_no_sext_mem(operands[0], operands[1]));
892    }
893    else {
894      emit_insn (gen_extendhisi2_no_sext_reg(operands[0], operands[1]));
895    }
896 }
897 DONE;
898}")
899
900(define_insn "extendhisi2_sext"
901  [(set (match_operand:SI 0 "register_operand" "=r,r")
902	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
903  "TARGET_MASK_SEXT"
904  "@
905   l.exths \t%0,%1\t # extendhisi2_has_signed_extend
906   l.lhs   \t%0,%1\t # extendhisi2_has_signed_extend"
907  [(set_attr "length" "1,1")
908   (set_attr "type" "extend,load")])
909
910(define_insn "extendhisi2_no_sext_mem"
911  [(set (match_operand:SI 0 "register_operand" "=r")
912        (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
913  "!TARGET_MASK_SEXT"
914  "l.lhs   \t%0,%1\t # extendhisi2_no_sext_mem"
915  [(set_attr "length" "1")
916   (set_attr "type" "load")])
917
918(define_expand "extendhisi2_no_sext_reg"
919  [(set (match_dup 2)
920	(ashift:SI (match_operand:HI 1 "register_operand" "")
921		   (const_int 16)))
922   (set (match_operand:SI 0 "register_operand" "")
923	(ashiftrt:SI (match_dup 2)
924		     (const_int 16)))]
925  "!TARGET_MASK_SEXT"
926  "
927{
928  operands[1] = gen_lowpart (SImode, operands[1]);
929  operands[2] = gen_reg_rtx (SImode); }")
930
931
932;;
933;; zero_extend<m><n>2
934;;
935
936(define_insn "zero_extendqisi2"
937  [(set (match_operand:SI 0 "register_operand" "=r,r")
938	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
939  ""
940  "@
941   l.andi  \t%0,%1,0xff\t # zero_extendqisi2
942   l.lbz   \t%0,%1\t # zero_extendqisi2"
943  [(set_attr "type" "logic,load")
944   (set_attr "length" "1,1")])
945
946
947(define_insn "zero_extendhisi2"
948  [(set (match_operand:SI 0 "register_operand" "=r,r")
949	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
950  ""
951  "@
952   l.andi  \t%0,%1,0xffff\t # zero_extendqisi2
953   l.lhz   \t%0,%1\t # zero_extendqisi2"
954  [(set_attr "type" "logic,load")
955   (set_attr "length" "1,1")])
956
957;;
958;; Shift/rotate operations
959;;
960
961(define_insn "ashlsi3"
962  [(set (match_operand:SI 0 "register_operand" "=r,r")
963        (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
964                   (match_operand:SI 2 "nonmemory_operand" "r,L")))]
965  ""
966  "@
967   l.sll   \t%0,%1,%2 # ashlsi3
968   l.slli  \t%0,%1,%2 # ashlsi3"
969  [(set_attr "type" "shift,shift")
970   (set_attr "length" "1,1")])
971
972(define_insn "ashrsi3"
973  [(set (match_operand:SI 0 "register_operand" "=r,r")
974        (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
975                   (match_operand:SI 2 "nonmemory_operand" "r,L")))]
976  ""
977  "@
978   l.sra   \t%0,%1,%2 # ashrsi3
979   l.srai  \t%0,%1,%2 # ashrsi3"
980  [(set_attr "type" "shift,shift")
981   (set_attr "length" "1,1")])
982
983(define_insn "lshrsi3"
984  [(set (match_operand:SI 0 "register_operand" "=r,r")
985        (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
986                   (match_operand:SI 2 "nonmemory_operand" "r,L")))]
987  ""
988  "@
989   l.srl   \t%0,%1,%2 # lshrsi3
990   l.srli  \t%0,%1,%2 # lshrsi3"
991  [(set_attr "type" "shift,shift")
992   (set_attr "length" "1,1")])
993
994(define_insn "rotrsi3"
995  [(set (match_operand:SI 0 "register_operand" "=r,r")
996        (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
997                   (match_operand:SI 2 "nonmemory_operand" "r,L")))]
998  "TARGET_MASK_ROR"
999  "@
1000   l.ror   \t%0,%1,%2 # rotrsi3
1001   l.rori  \t%0,%1,%2 # rotrsi3"
1002  [(set_attr "type" "shift,shift")
1003   (set_attr "length" "1,1")])
1004
1005;;
1006;; Logical bitwise operations
1007;;
1008
1009(define_insn "andsi3"
1010  [(set (match_operand:SI 0 "register_operand" "=r,r")
1011	(and:SI (match_operand:SI 1 "register_operand" "%r,r")
1012		(match_operand:SI 2 "nonmemory_operand" "r,K")))]
1013  ""
1014  "@
1015   l.and   \t%0,%1,%2 # andsi3
1016   l.andi  \t%0,%1,%2 # andsi3"
1017  [(set_attr "type" "logic,logic")
1018   (set_attr "length" "1,1")])
1019
1020(define_insn "iorsi3"
1021  [(set (match_operand:SI 0 "register_operand" "=r,r")
1022	(ior:SI (match_operand:SI 1 "register_operand" "%r,r")
1023		(match_operand:SI 2 "nonmemory_operand" "r,K")))]
1024  ""
1025  "@
1026   l.or    \t%0,%1,%2 # iorsi3
1027   l.ori   \t%0,%1,%2 # iorsi3"
1028  [(set_attr "type" "logic,logic")
1029   (set_attr "length" "1,1")])
1030
1031(define_insn "xorsi3"
1032  [(set (match_operand:SI 0 "register_operand" "=r,r")
1033	(xor:SI (match_operand:SI 1 "register_operand" "%r,r")
1034		(match_operand:SI 2 "nonmemory_operand" "r,I")))]
1035  ""
1036  "@
1037   l.xor   \t%0,%1,%2 # xorsi3
1038   l.xori  \t%0,%1,%2 # xorsi3"
1039  [(set_attr "type" "logic,logic")
1040   (set_attr "length" "1,1")])
1041
1042(define_insn "one_cmplqi2"
1043  [(set (match_operand:QI 0 "register_operand" "=r")
1044	(not:QI (match_operand:QI 1 "register_operand" "r")))]
1045  ""
1046  "l.xori  \t%0,%1,0x00ff # one_cmplqi2"
1047  [(set_attr "type" "logic")
1048   (set_attr "length" "1")])
1049
1050(define_insn "one_cmplsi2"
1051  [(set (match_operand:SI 0 "register_operand" "=r")
1052	(not:SI (match_operand:SI 1 "register_operand" "r")))]
1053  ""
1054  "l.xori  \t%0,%1,0xffff # one_cmplsi2"
1055  [(set_attr "type" "logic")
1056   (set_attr "length" "1")])
1057
1058;;
1059;; Arithmetic operations
1060;;
1061
1062(define_insn "negsi2"
1063  [(set (match_operand:SI 0 "register_operand" "=r")
1064	(neg:SI (match_operand:SI 1 "register_operand" "r")))]
1065  ""
1066  "l.sub   \t%0,r0,%1 # negsi2"
1067  [(set_attr "type" "add")
1068   (set_attr "length" "1")])
1069
1070(define_insn "addsi3"
1071  [(set (match_operand:SI 0 "register_operand" "=r,r")
1072	(plus:SI (match_operand:SI 1 "register_operand" "%r,r")
1073		 (match_operand:SI 2 "nonmemory_operand" "r,I")))]
1074  ""
1075  "@
1076   l.add   \t%0,%1,%2 # addsi3
1077   l.addi  \t%0,%1,%2 # addsi3"
1078  [(set_attr "type" "add,add")
1079   (set_attr "length" "1,1")])
1080
1081(define_insn "subsi3"
1082  [(set (match_operand:SI 0 "register_operand" "=r,r")
1083	(minus:SI (match_operand:SI 1 "register_operand" "r,r")
1084		  (match_operand:SI 2 "nonmemory_operand" "r,I")))]
1085  ""
1086  "@
1087   l.sub   \t%0,%1,%2 # subsi3
1088   l.addi  \t%0,%1,%n2 # subsi3"
1089  [(set_attr "type" "add,add")]
1090)
1091
1092;;
1093;; mul and div
1094;;
1095
1096(define_insn "mulsi3"
1097  [(set (match_operand:SI 0 "register_operand" "=r")
1098        (mult:SI (match_operand:SI 1 "register_operand" "r")
1099                 (match_operand:SI 2 "register_operand" "r")))]
1100  "TARGET_HARD_MUL"
1101  "l.mul   \t%0,%1,%2 # mulsi3"
1102  [(set_attr "type" "mul")
1103   (set_attr "length" "1")])
1104
1105(define_insn "divsi3"
1106  [(set (match_operand:SI 0 "register_operand" "=r")
1107        (div:SI (match_operand:SI 1 "register_operand" "r")
1108                 (match_operand:SI 2 "register_operand" "r")))]
1109  "TARGET_HARD_DIV"
1110  "l.div   \t%0,%1,%2 # divsi3"
1111  [(set_attr "type" "mul")
1112   (set_attr "length" "1")])
1113
1114(define_insn "udivsi3"
1115  [(set (match_operand:SI 0 "register_operand" "=r")
1116        (udiv:SI (match_operand:SI 1 "register_operand" "r")
1117                 (match_operand:SI 2 "register_operand" "r")))]
1118  "TARGET_HARD_DIV"
1119  "l.divu  \t%0,%1,%2 # udivsi3"
1120  [(set_attr "type" "mul")
1121   (set_attr "length" "1")])
1122
1123;;
1124;; jumps
1125;;
1126
1127;; jump
1128
1129(define_expand "jump"
1130  [(set (pc)
1131	(label_ref (match_operand 0 "" "")))]
1132  ""
1133  "
1134{
1135  emit_jump_insn (gen_jump_internal (operands[0]));
1136  DONE;
1137}")
1138
1139(define_insn "jump_internal"
1140  [(set (pc)
1141	(label_ref (match_operand 0 "" "")))]
1142  ""
1143  "l.j     \t%l0 # jump_internal%("
1144  [(set_attr "type" "jump")
1145   (set_attr "length" "1")])
1146
1147;; indirect jump
1148
1149(define_expand "indirect_jump"
1150  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
1151  ""
1152  "
1153{
1154  emit_jump_insn (gen_indirect_jump_internal (operands[0]));
1155  DONE;
1156
1157}")
1158
1159(define_insn "indirect_jump_internal"
1160  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
1161  ""
1162  "l.jr    \t%0 # indirect_jump_internal%("
1163  [(set_attr "type" "jump")
1164   (set_attr "length" "1")])
1165
1166;;
1167;; calls
1168;;
1169
1170;; call
1171
1172(define_expand "call"
1173  [(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "")
1174		    (match_operand 1 "" "i"))
1175            (clobber (reg:SI 9))
1176            (use (reg:SI 16))])]
1177  ""
1178  "
1179{
1180  emit_call_insn (gen_call_internal (operands[0], operands[1]));
1181  DONE;
1182}")
1183
1184(define_insn "call_internal"
1185[(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "")
1186                  (match_operand 1 "" "i"))
1187            (clobber (reg:SI 9))
1188            (use (reg:SI 16))])]
1189  ""
1190  {
1191    if (flag_pic)
1192      {
1193	crtl->uses_pic_offset_table = 1;
1194	return "l.jal   \tplt(%S0)# call_internal%(";
1195      }
1196
1197    return "l.jal   \t%S0# call_internal%(";
1198  }
1199  [(set_attr "type" "jump")
1200   (set_attr "length" "1")])
1201
1202;; call value
1203
1204(define_expand "call_value"
1205  [(parallel [(set (match_operand 0 "register_operand" "=r")
1206		   (call (match_operand:SI 1 "sym_ref_mem_operand" "")
1207			 (match_operand 2 "" "i")))
1208            (clobber (reg:SI 9))
1209            (use (reg:SI 16))])]
1210  ""
1211  "
1212{
1213  emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2]));
1214  DONE;
1215}")
1216
1217(define_insn "call_value_internal"
1218[(parallel [(set (match_operand 0 "register_operand" "=r")
1219                  (call (match_operand:SI 1 "sym_ref_mem_operand" "")
1220                        (match_operand 2 "" "i")))
1221            (clobber (reg:SI 9))
1222            (use (reg:SI 16))])]
1223  ""
1224  {
1225    if (flag_pic)
1226      {
1227	crtl->uses_pic_offset_table = 1;
1228	return "l.jal   \tplt(%S1) # call_value_internal%(";
1229      }
1230    return "l.jal   \t%S1 # call_value_internal%(";
1231  }
1232  [(set_attr "type" "jump")
1233   (set_attr "length" "1")])
1234
1235;; indirect call value
1236
1237(define_expand "call_value_indirect"
1238  [(parallel [(set (match_operand 0 "register_operand" "=r")
1239                   (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
1240                         (match_operand 2 "" "i")))
1241            (clobber (reg:SI 9))
1242            (use (reg:SI 16))])]
1243  ""
1244  "
1245{
1246  emit_call_insn (gen_call_value_indirect_internal (operands[0], operands[1], operands[2]));
1247  DONE;
1248}")
1249
1250(define_insn "call_value_indirect_internal"
1251  [(parallel [(set (match_operand 0 "register_operand" "=r")
1252                   (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
1253                         (match_operand 2 "" "i")))
1254            (clobber (reg:SI 9))
1255            (use (reg:SI 16))])]
1256  ""
1257  "l.jalr  \t%1 # call_value_indirect_internal%("
1258  [(set_attr "type" "jump")
1259   (set_attr "length" "1")])
1260
1261;; indirect call
1262
1263(define_expand "call_indirect"
1264  [(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
1265		    (match_operand 1 "" "i"))
1266            (clobber (reg:SI 9))
1267            (use (reg:SI 16))])]
1268  ""
1269  "
1270{
1271  emit_call_insn (gen_call_indirect_internal (operands[0], operands[1]));
1272  DONE;
1273}")
1274
1275(define_insn "call_indirect_internal"
1276[(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
1277                  (match_operand 1 "" "i"))
1278            (clobber (reg:SI 9))
1279            (use (reg:SI 16))])]
1280  ""
1281  "l.jalr  \t%0 # call_indirect_internal%("
1282  [(set_attr "type" "jump")
1283   (set_attr "length" "1")])
1284
1285;; table jump
1286
1287(define_expand "tablejump"
1288  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
1289   (use (label_ref (match_operand 1 "" "")))]
1290   ""
1291  "
1292{
1293  if (CASE_VECTOR_PC_RELATIVE || flag_pic)
1294    operands[0]
1295      = force_reg (Pmode,
1296		   gen_rtx_PLUS (Pmode, operands[0],
1297				 gen_rtx_LABEL_REF (Pmode, operands[1])));
1298  emit_jump_insn (gen_tablejump_internal (operands[0], operands[1]));
1299  DONE;
1300}")
1301
1302(define_insn "tablejump_internal"
1303  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
1304   (use (label_ref (match_operand 1 "" "")))]
1305  ""
1306  "l.jr    \t%0 # tablejump_internal%("
1307  [(set_attr "type" "jump")
1308   (set_attr "length" "1")])
1309
1310
1311;; no-op
1312
1313(define_insn "nop"
1314  [(const_int 0)]
1315  ""
1316  "l.nop"
1317  [(set_attr "type" "logic")
1318   (set_attr "length" "1")])
1319
1320;;
1321;; floating point
1322;;
1323
1324;; floating point arithmetic
1325
1326(define_insn "addsf3"
1327  [(set (match_operand:SF 0 "register_operand" "=r")
1328        (plus:SF (match_operand:SF 1 "register_operand" "r")
1329                 (match_operand:SF 2 "register_operand" "r")))]
1330  "TARGET_HARD_FLOAT"
1331  "lf.add.s\t%0,%1,%2 # addsf3"
1332  [(set_attr "type"     "fp")
1333   (set_attr "length"   "1")])
1334
1335(define_insn "adddf3"
1336  [(set (match_operand:DF 0 "register_operand" "=r")
1337        (plus:DF (match_operand:DF 1 "register_operand" "r")
1338                 (match_operand:DF 2 "register_operand" "r")))]
1339  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
1340  "lf.add.d\t%0,%1,%2 # adddf3"
1341  [(set_attr "type"     "fp")
1342   (set_attr "length"   "1")])
1343
1344(define_insn "subsf3"
1345  [(set (match_operand:SF 0 "register_operand" "=r")
1346        (minus:SF (match_operand:SF 1 "register_operand" "r")
1347                 (match_operand:SF 2 "register_operand" "r")))]
1348  "TARGET_HARD_FLOAT"
1349  "lf.sub.s\t%0,%1,%2 # subsf3"
1350  [(set_attr "type"     "fp")
1351   (set_attr "length"   "1")])
1352
1353(define_insn "subdf3"
1354  [(set (match_operand:DF 0 "register_operand" "=r")
1355        (minus:DF (match_operand:DF 1 "register_operand" "r")
1356		  (match_operand:DF 2 "register_operand" "r")))]
1357  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
1358  "lf.sub.d\t%0,%1,%2 # subdf3"
1359  [(set_attr "type"     "fp")
1360   (set_attr "length"   "1")])
1361
1362(define_insn "mulsf3"
1363  [(set (match_operand:SF 0 "register_operand" "=r")
1364        (mult:SF (match_operand:SF 1 "register_operand" "r")
1365                 (match_operand:SF 2 "register_operand" "r")))]
1366  "TARGET_HARD_FLOAT"
1367  "lf.mul.s\t%0,%1,%2 # mulsf3"
1368  [(set_attr "type"     "fp")
1369   (set_attr "length"   "1")])
1370
1371(define_insn "muldf3"
1372  [(set (match_operand:DF 0 "register_operand" "=r")
1373        (mult:DF (match_operand:DF 1 "register_operand" "r")
1374                 (match_operand:DF 2 "register_operand" "r")))]
1375  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
1376  "lf.mul.d\t%0,%1,%2 # muldf3"
1377  [(set_attr "type"     "fp")
1378   (set_attr "length"   "1")])
1379
1380(define_insn "divsf3"
1381  [(set (match_operand:SF 0 "register_operand" "=r")
1382        (div:SF (match_operand:SF 1 "register_operand" "r")
1383		(match_operand:SF 2 "register_operand" "r")))]
1384  "TARGET_HARD_FLOAT"
1385  "lf.div.s\t%0,%1,%2 # divsf3"
1386  [(set_attr "type"     "fp")
1387   (set_attr "length"   "1")])
1388
1389(define_insn "divdf3"
1390  [(set (match_operand:DF 0 "register_operand" "=r")
1391        (div:DF (match_operand:DF 1 "register_operand" "r")
1392		(match_operand:DF 2 "register_operand" "r")))]
1393  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
1394  "lf.div.d\t%0,%1,%2 # divdf3"
1395  [(set_attr "type"     "fp")
1396   (set_attr "length"   "1")])
1397
1398;; Conversion between fixed point and floating point.
1399
1400
1401(define_insn "floatsisf2"
1402  [(set (match_operand:SF 0 "register_operand" "=r")
1403	(float:SF (match_operand:SI 1 "register_operand" "r")))]
1404  "TARGET_HARD_FLOAT"
1405  "lf.itof.s\t%0, %1 # floatsisf2"
1406  [(set_attr "type" "fp")
1407   (set_attr "length" "1")])
1408
1409;; not working
1410(define_insn "fixunssfsi2"
1411  [(set (match_operand:SI 0 "register_operand" "=r")
1412	(fix:SI (match_operand:SF 1 "register_operand" "r")))]
1413  "TARGET_HARD_FLOAT"
1414  "lf.ftoi.s\t%0, %1 # fixunssfsi2"
1415  [(set_attr "type" "fp")
1416   (set_attr "length" "1")])
1417
1418;; The insn to set GOT.
1419;; TODO: support for no-delay target
1420(define_insn "set_got"
1421  [(set (match_operand:SI 0 "register_operand" "=r")
1422	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
1423   (clobber (reg:SI 9))
1424   (clobber (reg:SI 16))]
1425  ""
1426  "l.jal    \t8
1427 \tl.movhi  \tr16,gotpchi(_GLOBAL_OFFSET_TABLE_-4)
1428 \tl.ori    \tr16,r16,gotpclo(_GLOBAL_OFFSET_TABLE_+0)
1429 \tl.add    \tr16,r16,r9"
1430  [(set_attr "length" "16")])
1431
1432(define_expand "atomic_compare_and_swap<mode>"
1433  [(match_operand:SI 0 "register_operand")   ;; bool output
1434   (match_operand:AI 1 "register_operand")   ;; val output
1435   (match_operand:AI 2 "memory_operand")     ;; memory
1436   (match_operand:AI 3 "register_operand")   ;; expected
1437   (match_operand:AI 4 "register_operand")   ;; desired
1438   (match_operand:SI 5 "const_int_operand")  ;; is_weak
1439   (match_operand:SI 6 "const_int_operand")  ;; mod_s
1440   (match_operand:SI 7 "const_int_operand")] ;; mod_f
1441  "0"
1442{
1443  if (<MODE>mode == SImode)
1444    emit_insn (gen_cmpxchg (operands[0], operands[1], operands[2], operands[3],
1445                            operands[4]));
1446  else
1447    or1k_expand_cmpxchg_qihi (operands[0], operands[1], operands[2],
1448                              operands[3], operands[4], INTVAL (operands[5]),
1449                              (enum memmodel) INTVAL (operands[6]),
1450                              (enum memmodel) INTVAL (operands[7]));
1451  DONE;
1452})
1453
1454(define_insn "cmpxchg"
1455   [(set (match_operand:SI 0 "register_operand" "=&r")
1456         (unspec_volatile:SI [(match_operand:SI 2 "memory_operand" "+m")]
1457          UNSPEC_CMPXCHG))
1458    (set (match_dup 2)
1459         (unspec_volatile:SI [(match_operand:SI 3 "register_operand" "r")]
1460          UNSPEC_CMPXCHG))
1461    (set (match_operand:SI 1 "register_operand" "=&r")
1462         (unspec_volatile:SI [(match_dup 2) (match_dup 3)
1463                             (match_operand:SI 4 "register_operand" "r")]
1464          UNSPEC_CMPXCHG))]
1465  ""
1466  "
1467   l.lwa   \t%1,%2   # cmpxchg: load
1468   l.sfeq  \t%1,%3   # cmpxchg: cmp
1469   l.bnf   \t1f      # cmpxchg: not expected
1470    l.ori  \t%0,r0,0 # cmpxchg: result = 0
1471   l.swa   \t%2,%4   # cmpxchg: store new
1472   l.bnf   \t1f      # cmpxchg: done
1473    l.nop
1474   l.ori   \t%0,r0,1 # cmpxchg: result = 1
14751:")
1476
1477(define_insn "cmpxchg_mask"
1478   [(set (match_operand:SI 0 "register_operand" "=&r")
1479         (unspec_volatile:SI [(match_operand:SI 2 "memory_operand" "+m")]
1480          UNSPEC_CMPXCHG))
1481    (set (match_dup 2)
1482         (unspec_volatile:SI [(match_operand:SI 3 "register_operand" "r")]
1483          UNSPEC_CMPXCHG))
1484    (set (match_operand:SI 1 "register_operand" "=&r")
1485         (unspec_volatile:SI [(match_dup 2) (match_dup 3)
1486                             (match_operand:SI 4 "register_operand" "r")
1487                             (match_operand:SI 5 "register_operand" "r")]
1488          UNSPEC_CMPXCHG))
1489   (clobber (match_scratch:SI 6 "=&r"))]
1490  ""
1491  "
1492   l.lwa   \t%6,%2    # cmpxchg: load
1493   l.and   \t%1,%6,%5 # cmpxchg: mask
1494   l.sfeq  \t%1,%3    # cmpxchg: cmp
1495   l.bnf   \t1f       # cmpxchg: not expected
1496    l.ori  \t%0,r0,0  # cmpxchg: result = 0
1497   l.xor   \t%6,%6,%1 # cmpxchg: clear
1498   l.or    \t%6,%6,%4 # cmpxchg: set
1499   l.swa   \t%2,%6    # cmpxchg: store new
1500   l.bnf   \t1f       # cmpxchg: done
1501    l.nop
1502   l.ori   \t%0,r0,1  # cmpxchg: result = 1
15031:
1504  ")
1505
1506(define_expand "atomic_fetch_<op_name><mode>"
1507  [(match_operand:AI 0 "register_operand")
1508   (match_operand:AI 1 "memory_operand")
1509   (match_operand:AI 2 "register_operand")
1510   (match_operand:SI 3 "const_int_operand")
1511   (atomic_op:AI (match_dup 0) (match_dup 1))]
1512  ""
1513{
1514  rtx ret = gen_reg_rtx (<MODE>mode);
1515  if (<MODE>mode != SImode)
1516    or1k_expand_fetch_op_qihi (operands[0], operands[1], operands[2], ret,
1517                               gen_fetch_and_<op_name>_mask);
1518  else
1519    emit_insn (gen_fetch_and_<op_name> (operands[0], operands[1], operands[2],
1520                                        ret));
1521  DONE;
1522})
1523
1524(define_expand "atomic_<op_name>_fetch<mode>"
1525  [(match_operand:AI 0 "register_operand")
1526   (match_operand:AI 1 "memory_operand")
1527   (match_operand:AI 2 "register_operand")
1528   (match_operand:SI 3 "const_int_operand")
1529   (atomic_op:AI (match_dup 0) (match_dup 1))]
1530  ""
1531{
1532  rtx ret = gen_reg_rtx (<MODE>mode);
1533  if (<MODE>mode != SImode)
1534    or1k_expand_fetch_op_qihi (ret, operands[1], operands[2], operands[0],
1535                               gen_fetch_and_<op_name>_mask);
1536  else
1537    emit_insn (gen_fetch_and_<op_name> (ret, operands[1], operands[2],
1538                                        operands[0]));
1539  DONE;
1540})
1541
1542(define_insn "fetch_and_<op_name>"
1543  [(set (match_operand:SI 0 "register_operand" "=&r")
1544        (match_operand:SI 1 "memory_operand" "+m"))
1545   (set (match_operand:SI 3 "register_operand" "=&r")
1546        (unspec_volatile:SI [(match_dup 1)
1547                             (match_operand:SI 2 "register_operand" "r")]
1548         UNSPEC_FETCH_AND_OP))
1549   (set (match_dup 1)
1550        (match_dup 3))
1551   (atomic_op:SI (match_dup 0) (match_dup 1))]
1552  ""
1553  "
15541:
1555   l.lwa   \t%0,%1  # fetch_<op_name>: load
1556   l.<op_insn>\t\t%3,%0,%2 # fetch_<op_name>: logic
1557   <post_op_insn>
1558   l.swa   \t%1,%3  # fetch_<op_name>: store new
1559   l.bnf   \t1b     # fetch_<op_name>: done
1560    l.nop
1561  ")
1562
1563(define_insn "fetch_and_<op_name>_mask"
1564  [(set (match_operand:SI 0 "register_operand" "=&r")
1565        (match_operand:SI 1 "memory_operand" "+m"))
1566   (set (match_operand:SI 3 "register_operand" "=&r")
1567        (unspec_volatile:SI [(match_dup 1)
1568                             (match_operand:SI 2 "register_operand" "r")
1569                             (match_operand:SI 4 "register_operand" "r")]
1570         UNSPEC_FETCH_AND_OP))
1571   (set (match_dup 1)
1572        (unspec_volatile:SI [(match_dup 3) (match_dup 4)] UNSPEC_FETCH_AND_OP))
1573   (clobber (match_scratch:SI 5 "=&r"))
1574   (atomic_op:SI (match_dup 0) (match_dup 1))]
1575  ""
1576  "
15771:
1578   l.lwa   \t%0,%1    # fetch_<op_name>: load
1579   l.and   \t%5,%0,%4 # fetch_<op_name>: mask
1580   l.xor   \t%5,%0,%5 # fetch_<op_name>: clear
1581   l.<op_insn>\t\t%3,%0,%2 # fetch_<op_name>: logic
1582   <post_op_insn>
1583   l.and   \t%3,%3,%4 # fetch_<op_name>: mask result
1584   l.or    \t%3,%5,%3 # fetch_<op_name>: set
1585   l.swa   \t%1,%3    # fetch_<op_name>: store new
1586   l.bnf   \t1b       # fetch_<op_name>: done
1587    l.nop
1588  ")
1589
1590;; Local variables:
1591;; mode:emacs-lisp
1592;; comment-start: ";; "
1593;; eval: (set-syntax-table (copy-sequence (syntax-table)))
1594;; eval: (modify-syntax-entry ?[ "(]")
1595;; eval: (modify-syntax-entry ?] ")[")
1596;; eval: (modify-syntax-entry ?{ "(}")
1597;; eval: (modify-syntax-entry ?} "){")
1598;; eval: (setq indent-tabs-mode t)
1599;; End:
1600