xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/lm32/lm32.md (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1;; Machine description of the Lattice Mico32 architecture for GNU C compiler.
2;; Contributed by Jon Beniston <jon@beniston.com>
3
4;; Copyright (C) 2009-2015 Free Software Foundation, Inc.
5
6;; This file is part of GCC.
7
8;; GCC is free software; you can redistribute it and/or modify it
9;; under the terms of the GNU General Public License as published
10;; by the Free Software Foundation; either version 3, or (at your
11;; option) any later version.
12
13;; GCC is distributed in the hope that it will be useful, but WITHOUT
14;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16;; License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING3.  If not see
20;; <http://www.gnu.org/licenses/>.
21
22;; Include predicate and constraint definitions
23(include "predicates.md")
24(include "constraints.md")
25
26
27;; Register numbers
28(define_constants
29  [(RA_REGNUM           29)	; return address register.
30  ]
31)
32
33;; LM32 specific volatile operations
34(define_constants
35  [(UNSPECV_BLOCKAGE    1)]     ; prevent scheduling across pro/epilog boundaries
36)
37
38;; LM32 specific operations
39(define_constants
40  [(UNSPEC_GOT          2)
41   (UNSPEC_GOTOFF_HI16  3)
42   (UNSPEC_GOTOFF_LO16  4)]
43)
44
45;; ---------------------------------
46;;      instruction types
47;; ---------------------------------
48
49(define_attr "type"
50  "unknown,load,store,arith,compare,shift,multiply,divide,call,icall,ubranch,uibranch,cbranch"
51  (const_string "unknown"))
52
53;; ---------------------------------
54;;      instruction lengths
55;; ---------------------------------
56
57; All instructions are 4 bytes
58; Except for branches that are out of range, and have to be implemented
59; as two instructions
60(define_attr "length" ""
61        (cond [
62                (eq_attr "type" "cbranch")
63                (if_then_else
64                        (lt (abs (minus (match_dup 2) (pc)))
65                                (const_int 32768)
66                        )
67                        (const_int 4)
68                        (const_int 8)
69                )
70              ]
71        (const_int 4))
72)
73
74;; ---------------------------------
75;;           scheduling
76;; ---------------------------------
77
78(define_automaton "lm32")
79
80(define_cpu_unit "x" "lm32")
81(define_cpu_unit "m" "lm32")
82(define_cpu_unit "w" "lm32")
83
84(define_insn_reservation "singlecycle" 1
85  (eq_attr "type" "store,arith,call,icall,ubranch,uibranch,cbranch")
86 "x")
87
88(define_insn_reservation "twocycle" 2
89  (eq_attr "type" "compare,shift,divide")
90 "x,m")
91
92(define_insn_reservation "threecycle" 3
93  (eq_attr "type" "load,multiply")
94 "x,m,w")
95
96;; ---------------------------------
97;;               mov
98;; ---------------------------------
99
100(define_expand "movqi"
101  [(set (match_operand:QI 0 "general_operand" "")
102        (match_operand:QI 1 "general_operand" ""))]
103  ""
104  "
105{
106  if (can_create_pseudo_p ())
107    {
108      if (GET_CODE (operand0) == MEM)
109        {
110          /* Source operand for store must be in a register.  */
111          operands[1] = force_reg (QImode, operands[1]);
112        }
113    }
114}")
115
116(define_expand "movhi"
117  [(set (match_operand:HI 0 "general_operand" "")
118        (match_operand:HI 1 "general_operand" ""))]
119  ""
120  "
121{
122  if (can_create_pseudo_p ())
123    {
124      if (GET_CODE (operands[0]) == MEM)
125        {
126          /* Source operand for store must be in a register.  */
127          operands[1] = force_reg (HImode, operands[1]);
128        }
129    }
130}")
131
132(define_expand "movsi"
133  [(set (match_operand:SI 0 "general_operand" "")
134        (match_operand:SI 1 "general_operand" ""))]
135  ""
136  "
137{
138  if (can_create_pseudo_p ())
139    {
140      if (GET_CODE (operands[0]) == MEM
141	  || (GET_CODE (operands[0]) == SUBREG
142	      && GET_CODE (SUBREG_REG (operands[0])) == MEM))
143        {
144          /* Source operand for store must be in a register.  */
145          operands[1] = force_reg (SImode, operands[1]);
146        }
147    }
148
149  if (flag_pic && symbolic_operand (operands[1], SImode))
150    {
151      if (GET_CODE (operands[1]) == LABEL_REF
152          || (GET_CODE (operands[1]) == SYMBOL_REF
153              && SYMBOL_REF_LOCAL_P (operands[1])
154              && !SYMBOL_REF_WEAK (operands[1])))
155        {
156          emit_insn (gen_movsi_gotoff_hi16 (operands[0], operands[1]));
157          emit_insn (gen_addsi3 (operands[0],
158                                 operands[0],
159                                 pic_offset_table_rtx));
160          emit_insn (gen_movsi_gotoff_lo16 (operands[0],
161                                            operands[0],
162                                            operands[1]));
163        }
164      else
165        emit_insn (gen_movsi_got (operands[0], operands[1]));
166      crtl->uses_pic_offset_table = 1;
167      DONE;
168    }
169  else if (flag_pic && GET_CODE (operands[1]) == CONST)
170    {
171      rtx op = XEXP (operands[1], 0);
172      if (GET_CODE (op) == PLUS)
173        {
174          rtx arg0 = XEXP (op, 0);
175          rtx arg1 = XEXP (op, 1);
176          if (GET_CODE (arg0) == LABEL_REF
177              || (GET_CODE (arg0) == SYMBOL_REF
178                  && SYMBOL_REF_LOCAL_P (arg0)
179                  && !SYMBOL_REF_WEAK (arg0)))
180            {
181              emit_insn (gen_movsi_gotoff_hi16 (operands[0], arg0));
182              emit_insn (gen_addsi3 (operands[0],
183                                     operands[0],
184                                     pic_offset_table_rtx));
185              emit_insn (gen_movsi_gotoff_lo16 (operands[0],
186                                                operands[0],
187                                                arg0));
188            }
189          else
190            emit_insn (gen_movsi_got (operands[0], arg0));
191          emit_insn (gen_addsi3 (operands[0], operands[0], arg1));
192          crtl->uses_pic_offset_table = 1;
193          DONE;
194        }
195    }
196  else if (!flag_pic && reloc_operand (operands[1], GET_MODE (operands[1])))
197    {
198      emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_HIGH (SImode, operands[1])));
199      emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_LO_SUM (SImode, operands[0], operands[1])));
200      DONE;
201    }
202  else if (GET_CODE (operands[1]) == CONST_INT)
203    {
204      if (!(satisfies_constraint_K (operands[1])
205          || satisfies_constraint_L (operands[1])
206          || satisfies_constraint_U (operands[1])))
207        {
208          emit_insn (gen_movsi_insn (operands[0],
209                                     GEN_INT (INTVAL (operands[1]) & ~0xffff)));
210          emit_insn (gen_iorsi3 (operands[0],
211                                 operands[0],
212                                 GEN_INT (INTVAL (operands[1]) & 0xffff)));
213          DONE;
214        }
215    }
216}")
217
218(define_expand "movmemsi"
219  [(parallel [(set (match_operand:BLK 0 "general_operand" "")
220		   (match_operand:BLK 1 "general_operand" ""))
221	      (use (match_operand:SI 2 "" ""))
222	      (use (match_operand:SI 3 "const_int_operand" ""))])]
223  ""
224{
225  if (!lm32_expand_block_move (operands))
226    FAIL;
227  DONE;
228})
229
230;; ---------------------------------
231;;        load/stores/moves
232;; ---------------------------------
233
234(define_insn "movsi_got"
235  [(set (match_operand:SI 0 "register_operand" "=r")
236        (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT))]
237  "flag_pic"
238  "lw       %0, (gp+got(%1))"
239  [(set_attr "type" "load")]
240)
241
242(define_insn "movsi_gotoff_hi16"
243  [(set (match_operand:SI 0 "register_operand" "=r")
244        (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF_HI16))]
245  "flag_pic"
246  "orhi     %0, r0, gotoffhi16(%1)"
247  [(set_attr "type" "load")]
248)
249
250(define_insn "movsi_gotoff_lo16"
251  [(set (match_operand:SI 0 "register_operand" "=r")
252        (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
253                             (match_operand 2 "" ""))] UNSPEC_GOTOFF_LO16))]
254  "flag_pic"
255  "addi     %0, %1, gotofflo16(%2)"
256  [(set_attr "type" "arith")]
257)
258
259(define_insn "*movsi_lo_sum"
260  [(set (match_operand:SI 0 "register_operand" "=r")
261        (lo_sum:SI (match_operand:SI 1 "register_operand" "0")
262                   (match_operand:SI 2 "reloc_operand" "i")))]
263  "!flag_pic"
264  "ori      %0, %0, lo(%2)"
265  [(set_attr "type" "arith")]
266)
267
268(define_insn "*movqi_insn"
269  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,m,r")
270        (match_operand:QI 1 "general_operand" "m,r,r,J,n"))]
271  "lm32_move_ok (QImode, operands)"
272  "@
273   lbu      %0, %1
274   or       %0, %1, r0
275   sb       %0, %1
276   sb       %0, r0
277   addi     %0, r0, %1"
278  [(set_attr "type" "load,arith,store,store,arith")]
279)
280
281(define_insn "*movhi_insn"
282  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,m,r,r")
283        (match_operand:HI 1 "general_operand" "m,r,r,J,K,L"))]
284  "lm32_move_ok (HImode, operands)"
285  "@
286   lhu      %0, %1
287   or       %0, %1, r0
288   sh       %0, %1
289   sh       %0, r0
290   addi     %0, r0, %1
291   ori      %0, r0, %1"
292  [(set_attr "type" "load,arith,store,store,arith,arith")]
293)
294
295(define_insn "movsi_insn"
296  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,m,r,r,r,r,r,r")
297        (match_operand:SI 1 "general_operand" "m,r,r,J,K,L,U,S,Y,n"))]
298  "lm32_move_ok (SImode, operands)"
299  "@
300   lw       %0, %1
301   or       %0, %1, r0
302   sw       %0, %1
303   sw       %0, r0
304   addi     %0, r0, %1
305   ori      %0, r0, %1
306   orhi     %0, r0, hi(%1)
307   mva      %0, gp(%1)
308   orhi     %0, r0, hi(%1)
309   ori      %0, r0, lo(%1); orhi     %0, %0, hi(%1)"
310  [(set_attr "type" "load,arith,store,store,arith,arith,arith,arith,arith,arith")]
311)
312
313;; ---------------------------------
314;;      sign and zero extension
315;; ---------------------------------
316
317(define_insn "*extendqihi2"
318  [(set (match_operand:HI 0 "register_operand" "=r,r")
319        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
320  "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
321  "@
322   lb       %0, %1
323   sextb    %0, %1"
324  [(set_attr "type" "load,arith")]
325)
326
327(define_insn "zero_extendqihi2"
328  [(set (match_operand:HI 0 "register_operand" "=r,r")
329        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
330  ""
331  "@
332   lbu      %0, %1
333   andi     %0, %1, 0xff"
334  [(set_attr "type" "load,arith")]
335)
336
337(define_insn "*extendqisi2"
338  [(set (match_operand:SI 0 "register_operand" "=r,r")
339        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
340  "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
341  "@
342   lb       %0, %1
343   sextb    %0, %1"
344  [(set_attr "type" "load,arith")]
345)
346
347(define_insn "zero_extendqisi2"
348  [(set (match_operand:SI 0 "register_operand" "=r,r")
349        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
350  ""
351  "@
352   lbu      %0, %1
353   andi     %0, %1, 0xff"
354  [(set_attr "type" "load,arith")]
355)
356
357(define_insn "*extendhisi2"
358  [(set (match_operand:SI 0 "register_operand" "=r,r")
359        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
360  "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
361  "@
362   lh       %0, %1
363   sexth    %0, %1"
364  [(set_attr "type" "load,arith")]
365)
366
367(define_insn "zero_extendhisi2"
368  [(set (match_operand:SI 0 "register_operand" "=r,r")
369        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
370  ""
371  "@
372   lhu      %0, %1
373   andi     %0, %1, 0xffff"
374  [(set_attr "type" "load,arith")]
375)
376
377;; ---------------------------------
378;;             compare
379;; ---------------------------------
380
381(define_expand "cstoresi4"
382  [(set (match_operand:SI 0 "register_operand")
383	(match_operator:SI 1 "ordered_comparison_operator"
384	 [(match_operand:SI 2 "register_operand")
385	  (match_operand:SI 3 "register_or_int_operand")]))]
386  ""
387{
388  lm32_expand_scc (operands);
389  DONE;
390})
391
392(define_insn "*seq"
393  [(set (match_operand:SI 0 "register_operand" "=r,r")
394        (eq:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
395               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
396  ""
397  "@
398   cmpe     %0, %z1, %2
399   cmpei    %0, %z1, %2"
400  [(set_attr "type" "compare")]
401)
402
403(define_insn "*sne"
404  [(set (match_operand:SI 0 "register_operand" "=r,r")
405        (ne:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
406               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
407  ""
408  "@
409   cmpne    %0, %z1, %2
410   cmpnei   %0, %z1, %2"
411  [(set_attr "type" "compare")]
412)
413
414(define_insn "*sgt"
415  [(set (match_operand:SI 0 "register_operand" "=r,r")
416        (gt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
417               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
418  ""
419  "@
420   cmpg     %0, %z1, %2
421   cmpgi    %0, %z1, %2"
422  [(set_attr "type" "compare")]
423)
424
425(define_insn "*sge"
426  [(set (match_operand:SI 0 "register_operand" "=r,r")
427        (ge:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
428               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
429  ""
430  "@
431   cmpge    %0, %z1, %2
432   cmpgei   %0, %z1, %2"
433  [(set_attr "type" "compare")]
434)
435
436(define_insn "*sgtu"
437  [(set (match_operand:SI 0 "register_operand" "=r,r")
438        (gtu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
439                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
440  ""
441  "@
442   cmpgu    %0, %z1, %2
443   cmpgui   %0, %z1, %2"
444  [(set_attr "type" "compare")]
445)
446
447(define_insn "*sgeu"
448  [(set (match_operand:SI 0 "register_operand" "=r,r")
449        (geu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
450                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
451  ""
452  "@
453   cmpgeu   %0, %z1, %2
454   cmpgeui  %0, %z1, %2"
455  [(set_attr "type" "compare")]
456)
457
458;; ---------------------------------
459;;       unconditional branch
460;; ---------------------------------
461
462(define_insn "jump"
463  [(set (pc) (label_ref (match_operand 0 "" "")))]
464  ""
465  "bi       %0"
466  [(set_attr "type" "ubranch")]
467)
468
469(define_insn "indirect_jump"
470  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
471  ""
472  "b        %0"
473  [(set_attr "type" "uibranch")]
474)
475
476;; ---------------------------------
477;;        conditional branch
478;; ---------------------------------
479
480(define_expand "cbranchsi4"
481  [(set (pc)
482   (if_then_else (match_operator 0 "comparison_operator"
483                  [(match_operand:SI 1 "register_operand")
484		   (match_operand:SI 2 "nonmemory_operand")])
485                 (label_ref (match_operand 3 "" ""))
486                 (pc)))]
487  ""
488  "
489{
490  lm32_expand_conditional_branch (operands);
491  DONE;
492}")
493
494(define_insn "*beq"
495  [(set (pc)
496        (if_then_else (eq:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
497                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
498                      (label_ref (match_operand 2 "" ""))
499                      (pc)))]
500  ""
501{
502  return get_attr_length (insn) == 4
503        ? "be     %z0,%z1,%2"
504        : "bne    %z0,%z1,8\n\tbi     %2";
505}
506  [(set_attr "type" "cbranch")])
507
508(define_insn "*bne"
509  [(set (pc)
510        (if_then_else (ne:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
511                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
512                      (label_ref (match_operand 2 "" ""))
513                      (pc)))]
514  ""
515{
516  return get_attr_length (insn) == 4
517        ? "bne    %z0,%z1,%2"
518        : "be     %z0,%z1,8\n\tbi     %2";
519}
520  [(set_attr "type" "cbranch")])
521
522(define_insn "*bgt"
523  [(set (pc)
524        (if_then_else (gt:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
525                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
526                      (label_ref (match_operand 2 "" ""))
527                      (pc)))]
528  ""
529{
530  return get_attr_length (insn) == 4
531        ? "bg     %z0,%z1,%2"
532        : "bge    %z1,%z0,8\n\tbi     %2";
533}
534  [(set_attr "type" "cbranch")])
535
536(define_insn "*bge"
537  [(set (pc)
538        (if_then_else (ge:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
539                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
540                      (label_ref (match_operand 2 "" ""))
541                      (pc)))]
542  ""
543{
544  return get_attr_length (insn) == 4
545        ? "bge    %z0,%z1,%2"
546        : "bg     %z1,%z0,8\n\tbi     %2";
547}
548  [(set_attr "type" "cbranch")])
549
550(define_insn "*bgtu"
551  [(set (pc)
552        (if_then_else (gtu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
553                              (match_operand:SI 1 "register_or_zero_operand" "rJ"))
554                      (label_ref (match_operand 2 "" ""))
555                      (pc)))]
556  ""
557{
558  return get_attr_length (insn) == 4
559        ? "bgu    %z0,%z1,%2"
560        : "bgeu   %z1,%z0,8\n\tbi     %2";
561}
562  [(set_attr "type" "cbranch")])
563
564(define_insn "*bgeu"
565  [(set (pc)
566        (if_then_else (geu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
567                              (match_operand:SI 1 "register_or_zero_operand" "rJ"))
568                      (label_ref (match_operand 2 "" ""))
569                      (pc)))]
570  ""
571{
572  return get_attr_length (insn) == 4
573        ? "bgeu   %z0,%z1,%2"
574        : "bgu    %z1,%z0,8\n\tbi     %2";
575}
576  [(set_attr "type" "cbranch")])
577
578;; ---------------------------------
579;;               call
580;; ---------------------------------
581
582(define_expand "call"
583  [(parallel [(call (match_operand 0 "" "")
584                    (match_operand 1 "" ""))
585              (clobber (reg:SI RA_REGNUM))
586             ])]
587  ""
588  "
589{
590  rtx addr = XEXP (operands[0], 0);
591  if (!CONSTANT_ADDRESS_P (addr))
592    XEXP (operands[0], 0) = force_reg (Pmode, addr);
593}")
594
595(define_insn "*call"
596  [(call (mem:SI (match_operand:SI 0 "call_operand" "r,s"))
597         (match_operand 1 "" ""))
598   (clobber (reg:SI RA_REGNUM))]
599  ""
600  "@
601   call     %0
602   calli    %0"
603  [(set_attr "type" "call,icall")]
604)
605
606(define_expand "call_value"
607  [(parallel [(set (match_operand 0 "" "")
608                   (call (match_operand 1 "" "")
609                         (match_operand 2 "" "")))
610              (clobber (reg:SI RA_REGNUM))
611             ])]
612  ""
613  "
614{
615  rtx addr = XEXP (operands[1], 0);
616  if (!CONSTANT_ADDRESS_P (addr))
617    XEXP (operands[1], 0) = force_reg (Pmode, addr);
618}")
619
620(define_insn "*call_value"
621  [(set (match_operand 0 "register_operand" "=r,r")
622        (call (mem:SI (match_operand:SI 1 "call_operand" "r,s"))
623              (match_operand 2 "" "")))
624   (clobber (reg:SI RA_REGNUM))]
625  ""
626  "@
627   call     %1
628   calli    %1"
629  [(set_attr "type" "call,icall")]
630)
631
632(define_insn "return_internal"
633  [(use (match_operand:SI 0 "register_operand" "r"))
634   (return)]
635  ""
636  "b        %0"
637  [(set_attr "type" "uibranch")]
638)
639
640(define_expand "return"
641  [(return)]
642  "lm32_can_use_return ()"
643  ""
644)
645
646(define_expand "simple_return"
647  [(simple_return)]
648  ""
649  ""
650)
651
652(define_insn "*return"
653  [(return)]
654  "reload_completed"
655  "ret"
656  [(set_attr "type" "uibranch")]
657)
658
659(define_insn "*simple_return"
660  [(simple_return)]
661  ""
662  "ret"
663  [(set_attr "type" "uibranch")]
664)
665
666;; ---------------------------------
667;;       switch/case statements
668;; ---------------------------------
669
670(define_expand "tablejump"
671  [(set (pc) (match_operand 0 "register_operand" ""))
672   (use (label_ref (match_operand 1 "" "")))]
673  ""
674  "
675{
676  rtx target = operands[0];
677  if (flag_pic)
678    {
679      /* For PIC, the table entry is relative to the start of the table.  */
680      rtx label = gen_reg_rtx (SImode);
681      target = gen_reg_rtx (SImode);
682      emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1]));
683      emit_insn (gen_addsi3 (target, operands[0], label));
684    }
685  emit_jump_insn (gen_tablejumpsi (target, operands[1]));
686  DONE;
687}")
688
689(define_insn "tablejumpsi"
690  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
691   (use (label_ref (match_operand 1 "" "")))]
692  ""
693  "b        %0"
694  [(set_attr "type" "ubranch")]
695)
696
697;; ---------------------------------
698;;            arithmetic
699;; ---------------------------------
700
701(define_insn "addsi3"
702  [(set (match_operand:SI 0 "register_operand" "=r,r")
703        (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
704                 (match_operand:SI 2 "register_or_K_operand" "r,K")))]
705  ""
706  "@
707   add      %0, %z1, %2
708   addi     %0, %z1, %2"
709  [(set_attr "type" "arith")]
710)
711
712(define_insn "subsi3"
713  [(set (match_operand:SI 0 "register_operand" "=r")
714        (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
715                  (match_operand:SI 2 "register_or_zero_operand" "rJ")))]
716  ""
717  "sub      %0, %z1, %z2"
718  [(set_attr "type" "arith")]
719)
720
721(define_insn "mulsi3"
722  [(set (match_operand:SI 0 "register_operand" "=r,r")
723        (mult:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
724                 (match_operand:SI 2 "register_or_K_operand" "r,K")))]
725  "TARGET_MULTIPLY_ENABLED"
726  "@
727   mul      %0, %z1, %2
728   muli     %0, %z1, %2"
729  [(set_attr "type" "multiply")]
730)
731
732(define_insn "udivsi3"
733  [(set (match_operand:SI 0 "register_operand" "=r")
734        (udiv:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
735                 (match_operand:SI 2 "register_operand" "r")))]
736  "TARGET_DIVIDE_ENABLED"
737  "divu     %0, %z1, %2"
738  [(set_attr "type" "divide")]
739)
740
741(define_insn "umodsi3"
742  [(set (match_operand:SI 0 "register_operand" "=r")
743        (umod:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
744                 (match_operand:SI 2 "register_operand" "r")))]
745  "TARGET_DIVIDE_ENABLED"
746  "modu     %0, %z1, %2"
747  [(set_attr "type" "divide")]
748)
749
750;; ---------------------------------
751;;      negation and inversion
752;; ---------------------------------
753
754(define_insn "negsi2"
755  [(set (match_operand:SI 0 "register_operand" "=r")
756        (neg:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))]
757  ""
758  "sub      %0, r0, %z1"
759  [(set_attr "type" "arith")]
760)
761
762(define_insn "one_cmplsi2"
763  [(set (match_operand:SI 0 "register_operand" "=r")
764        (not:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))]
765  ""
766  "not      %0, %z1"
767  [(set_attr "type" "arith")]
768)
769
770;; ---------------------------------
771;;             logical
772;; ---------------------------------
773
774(define_insn "andsi3"
775  [(set (match_operand:SI 0 "register_operand" "=r,r")
776        (and:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
777                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
778  ""
779  "@
780   and      %0, %z1, %2
781   andi     %0, %z1, %2"
782  [(set_attr "type" "arith")]
783)
784
785(define_insn "iorsi3"
786  [(set (match_operand:SI 0 "register_operand" "=r,r")
787        (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
788                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
789  ""
790  "@
791   or       %0, %z1, %2
792   ori      %0, %z1, %2"
793  [(set_attr "type" "arith")]
794)
795
796(define_insn "xorsi3"
797  [(set (match_operand:SI 0 "register_operand" "=r,r")
798        (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
799                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
800  ""
801  "@
802   xor      %0, %z1, %2
803   xori     %0, %z1, %2"
804  [(set_attr "type" "arith")]
805)
806
807(define_insn "*norsi3"
808  [(set (match_operand:SI 0 "register_operand" "=r,r")
809	(not:SI (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
810			(match_operand:SI 2 "register_or_L_operand" "r,L"))))]
811  ""
812  "@
813   nor      %0, %z1, %2
814   nori     %0, %z1, %2"
815  [(set_attr "type" "arith")]
816)
817
818(define_insn "*xnorsi3"
819  [(set (match_operand:SI 0 "register_operand" "=r,r")
820	(not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
821			(match_operand:SI 2 "register_or_L_operand" "r,L"))))]
822  ""
823  "@
824   xnor     %0, %z1, %2
825   xnori    %0, %z1, %2"
826  [(set_attr "type" "arith")]
827)
828
829;; ---------------------------------
830;;              shifts
831;; ---------------------------------
832
833(define_expand "ashlsi3"
834  [(set (match_operand:SI 0 "register_operand" "")
835        (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "")
836                   (match_operand:SI 2 "register_or_L_operand" "")))]
837  ""
838{
839  if (!TARGET_BARREL_SHIFT_ENABLED)
840    {
841      if (!optimize_size
842          && satisfies_constraint_L (operands[2])
843          && INTVAL (operands[2]) <= 8)
844        {
845          int i;
846          int shifts = INTVAL (operands[2]);
847
848          if (shifts == 0)
849            emit_move_insn (operands[0], operands[1]);
850          else
851            emit_insn (gen_addsi3 (operands[0], operands[1], operands[1]));
852          for (i = 1; i < shifts; i++)
853            emit_insn (gen_addsi3 (operands[0], operands[0], operands[0]));
854          DONE;
855        }
856      else
857        FAIL;
858    }
859})
860
861(define_insn "*ashlsi3"
862  [(set (match_operand:SI 0 "register_operand" "=r,r")
863        (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
864                   (match_operand:SI 2 "register_or_L_operand" "r,L")))]
865  "TARGET_BARREL_SHIFT_ENABLED"
866  "@
867   sl       %0, %z1, %2
868   sli      %0, %z1, %2"
869  [(set_attr "type" "shift")]
870)
871
872(define_expand "ashrsi3"
873  [(set (match_operand:SI 0 "register_operand" "")
874        (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "")
875                     (match_operand:SI 2 "register_or_L_operand" "")))]
876  ""
877{
878  if (!TARGET_BARREL_SHIFT_ENABLED)
879    {
880      if (!optimize_size
881          && satisfies_constraint_L (operands[2])
882          && INTVAL (operands[2]) <= 8)
883        {
884          int i;
885          int shifts = INTVAL (operands[2]);
886          rtx one = GEN_INT (1);
887
888          if (shifts == 0)
889            emit_move_insn (operands[0], operands[1]);
890          else
891            emit_insn (gen_ashrsi3_1bit (operands[0], operands[1], one));
892          for (i = 1; i < shifts; i++)
893            emit_insn (gen_ashrsi3_1bit (operands[0], operands[0], one));
894          DONE;
895        }
896      else
897        FAIL;
898    }
899})
900
901(define_insn "*ashrsi3"
902  [(set (match_operand:SI 0 "register_operand" "=r,r")
903        (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
904                     (match_operand:SI 2 "register_or_L_operand" "r,L")))]
905  "TARGET_BARREL_SHIFT_ENABLED"
906  "@
907   sr       %0, %z1, %2
908   sri      %0, %z1, %2"
909  [(set_attr "type" "shift")]
910)
911
912(define_insn "ashrsi3_1bit"
913  [(set (match_operand:SI 0 "register_operand" "=r")
914        (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
915                     (match_operand:SI 2 "constant_M_operand" "M")))]
916  "!TARGET_BARREL_SHIFT_ENABLED"
917  "sri      %0, %z1, %2"
918  [(set_attr "type" "shift")]
919)
920
921(define_expand "lshrsi3"
922  [(set (match_operand:SI 0 "register_operand" "")
923        (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "")
924                     (match_operand:SI 2 "register_or_L_operand" "")))]
925  ""
926{
927  if (!TARGET_BARREL_SHIFT_ENABLED)
928    {
929      if (!optimize_size
930          && satisfies_constraint_L (operands[2])
931          && INTVAL (operands[2]) <= 8)
932        {
933          int i;
934          int shifts = INTVAL (operands[2]);
935          rtx one = GEN_INT (1);
936
937          if (shifts == 0)
938            emit_move_insn (operands[0], operands[1]);
939          else
940            emit_insn (gen_lshrsi3_1bit (operands[0], operands[1], one));
941          for (i = 1; i < shifts; i++)
942            emit_insn (gen_lshrsi3_1bit (operands[0], operands[0], one));
943          DONE;
944        }
945      else
946        FAIL;
947    }
948})
949
950(define_insn "*lshrsi3"
951  [(set (match_operand:SI 0 "register_operand" "=r,r")
952        (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
953                     (match_operand:SI 2 "register_or_L_operand" "r,L")))]
954  "TARGET_BARREL_SHIFT_ENABLED"
955  "@
956   sru      %0, %z1, %2
957   srui     %0, %z1, %2"
958  [(set_attr "type" "shift")]
959)
960
961(define_insn "lshrsi3_1bit"
962  [(set (match_operand:SI 0 "register_operand" "=r")
963        (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
964                     (match_operand:SI 2 "constant_M_operand" "M")))]
965  "!TARGET_BARREL_SHIFT_ENABLED"
966  "srui     %0, %z1, %2"
967  [(set_attr "type" "shift")]
968)
969
970;; ---------------------------------
971;;     function entry / exit
972;; ---------------------------------
973
974(define_expand "prologue"
975  [(const_int 1)]
976  ""
977  "
978{
979  lm32_expand_prologue ();
980  DONE;
981}")
982
983(define_expand "epilogue"
984  [(return)]
985  ""
986  "
987{
988  lm32_expand_epilogue ();
989  DONE;
990}")
991
992;; ---------------------------------
993;;              nop
994;; ---------------------------------
995
996(define_insn "nop"
997  [(const_int 0)]
998  ""
999  "nop"
1000  [(set_attr "type" "arith")]
1001)
1002
1003;; ---------------------------------
1004;;             blockage
1005;; ---------------------------------
1006
1007;; used to stop the scheduler from
1008;; scheduling code across certain boundaries
1009
1010(define_insn "blockage"
1011  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
1012  ""
1013  ""
1014  [(set_attr "length" "0")]
1015)
1016