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-2018 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 (operands[0], gen_rtx_HIGH (SImode, operands[1])));
199      emit_insn (gen_rtx_SET (operands[0], gen_rtx_LO_SUM (SImode, operands[0],
200							   operands[1])));
201      DONE;
202    }
203  else if (GET_CODE (operands[1]) == CONST_INT)
204    {
205      if (!(satisfies_constraint_K (operands[1])
206          || satisfies_constraint_L (operands[1])
207          || satisfies_constraint_U (operands[1])))
208        {
209          emit_insn (gen_movsi_insn (operands[0],
210                                     GEN_INT (INTVAL (operands[1]) & ~0xffff)));
211          emit_insn (gen_iorsi3 (operands[0],
212                                 operands[0],
213                                 GEN_INT (INTVAL (operands[1]) & 0xffff)));
214          DONE;
215        }
216    }
217}")
218
219(define_expand "movmemsi"
220  [(parallel [(set (match_operand:BLK 0 "general_operand" "")
221		   (match_operand:BLK 1 "general_operand" ""))
222	      (use (match_operand:SI 2 "" ""))
223	      (use (match_operand:SI 3 "const_int_operand" ""))])]
224  ""
225{
226  if (!lm32_expand_block_move (operands))
227    FAIL;
228  DONE;
229})
230
231;; ---------------------------------
232;;        load/stores/moves
233;; ---------------------------------
234
235(define_insn "movsi_got"
236  [(set (match_operand:SI 0 "register_operand" "=r")
237        (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT))]
238  "flag_pic"
239  "lw       %0, (gp+got(%1))"
240  [(set_attr "type" "load")]
241)
242
243(define_insn "movsi_gotoff_hi16"
244  [(set (match_operand:SI 0 "register_operand" "=r")
245        (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF_HI16))]
246  "flag_pic"
247  "orhi     %0, r0, gotoffhi16(%1)"
248  [(set_attr "type" "load")]
249)
250
251(define_insn "movsi_gotoff_lo16"
252  [(set (match_operand:SI 0 "register_operand" "=r")
253        (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
254                             (match_operand 2 "" ""))] UNSPEC_GOTOFF_LO16))]
255  "flag_pic"
256  "addi     %0, %1, gotofflo16(%2)"
257  [(set_attr "type" "arith")]
258)
259
260(define_insn "*movsi_lo_sum"
261  [(set (match_operand:SI 0 "register_operand" "=r")
262        (lo_sum:SI (match_operand:SI 1 "register_operand" "0")
263                   (match_operand:SI 2 "reloc_operand" "i")))]
264  "!flag_pic"
265  "ori      %0, %0, lo(%2)"
266  [(set_attr "type" "arith")]
267)
268
269(define_insn "*movqi_insn"
270  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,m,r")
271        (match_operand:QI 1 "general_operand" "m,r,r,J,n"))]
272  "lm32_move_ok (QImode, operands)"
273  "@
274   lbu      %0, %1
275   or       %0, %1, r0
276   sb       %0, %1
277   sb       %0, r0
278   addi     %0, r0, %1"
279  [(set_attr "type" "load,arith,store,store,arith")]
280)
281
282(define_insn "*movhi_insn"
283  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,m,r,r")
284        (match_operand:HI 1 "general_operand" "m,r,r,J,K,L"))]
285  "lm32_move_ok (HImode, operands)"
286  "@
287   lhu      %0, %1
288   or       %0, %1, r0
289   sh       %0, %1
290   sh       %0, r0
291   addi     %0, r0, %1
292   ori      %0, r0, %1"
293  [(set_attr "type" "load,arith,store,store,arith,arith")]
294)
295
296(define_insn "movsi_insn"
297  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,m,r,r,r,r,r,r")
298        (match_operand:SI 1 "general_operand" "m,r,r,J,K,L,U,S,Y,n"))]
299  "lm32_move_ok (SImode, operands)"
300  "@
301   lw       %0, %1
302   or       %0, %1, r0
303   sw       %0, %1
304   sw       %0, r0
305   addi     %0, r0, %1
306   ori      %0, r0, %1
307   orhi     %0, r0, hi(%1)
308   mva      %0, gp(%1)
309   orhi     %0, r0, hi(%1)
310   ori      %0, r0, lo(%1); orhi     %0, %0, hi(%1)"
311  [(set_attr "type" "load,arith,store,store,arith,arith,arith,arith,arith,arith")]
312)
313
314;; ---------------------------------
315;;      sign and zero extension
316;; ---------------------------------
317
318(define_insn "*extendqihi2"
319  [(set (match_operand:HI 0 "register_operand" "=r,r")
320        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
321  "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
322  "@
323   lb       %0, %1
324   sextb    %0, %1"
325  [(set_attr "type" "load,arith")]
326)
327
328(define_insn "zero_extendqihi2"
329  [(set (match_operand:HI 0 "register_operand" "=r,r")
330        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
331  ""
332  "@
333   lbu      %0, %1
334   andi     %0, %1, 0xff"
335  [(set_attr "type" "load,arith")]
336)
337
338(define_insn "*extendqisi2"
339  [(set (match_operand:SI 0 "register_operand" "=r,r")
340        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
341  "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
342  "@
343   lb       %0, %1
344   sextb    %0, %1"
345  [(set_attr "type" "load,arith")]
346)
347
348(define_insn "zero_extendqisi2"
349  [(set (match_operand:SI 0 "register_operand" "=r,r")
350        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
351  ""
352  "@
353   lbu      %0, %1
354   andi     %0, %1, 0xff"
355  [(set_attr "type" "load,arith")]
356)
357
358(define_insn "*extendhisi2"
359  [(set (match_operand:SI 0 "register_operand" "=r,r")
360        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
361  "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
362  "@
363   lh       %0, %1
364   sexth    %0, %1"
365  [(set_attr "type" "load,arith")]
366)
367
368(define_insn "zero_extendhisi2"
369  [(set (match_operand:SI 0 "register_operand" "=r,r")
370        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
371  ""
372  "@
373   lhu      %0, %1
374   andi     %0, %1, 0xffff"
375  [(set_attr "type" "load,arith")]
376)
377
378;; ---------------------------------
379;;             compare
380;; ---------------------------------
381
382(define_expand "cstoresi4"
383  [(set (match_operand:SI 0 "register_operand")
384	(match_operator:SI 1 "ordered_comparison_operator"
385	 [(match_operand:SI 2 "register_operand")
386	  (match_operand:SI 3 "register_or_int_operand")]))]
387  ""
388{
389  lm32_expand_scc (operands);
390  DONE;
391})
392
393(define_insn "*seq"
394  [(set (match_operand:SI 0 "register_operand" "=r,r")
395        (eq:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
396               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
397  ""
398  "@
399   cmpe     %0, %z1, %2
400   cmpei    %0, %z1, %2"
401  [(set_attr "type" "compare")]
402)
403
404(define_insn "*sne"
405  [(set (match_operand:SI 0 "register_operand" "=r,r")
406        (ne:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
407               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
408  ""
409  "@
410   cmpne    %0, %z1, %2
411   cmpnei   %0, %z1, %2"
412  [(set_attr "type" "compare")]
413)
414
415(define_insn "*sgt"
416  [(set (match_operand:SI 0 "register_operand" "=r,r")
417        (gt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
418               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
419  ""
420  "@
421   cmpg     %0, %z1, %2
422   cmpgi    %0, %z1, %2"
423  [(set_attr "type" "compare")]
424)
425
426(define_insn "*sge"
427  [(set (match_operand:SI 0 "register_operand" "=r,r")
428        (ge:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
429               (match_operand:SI 2 "register_or_K_operand" "r,K")))]
430  ""
431  "@
432   cmpge    %0, %z1, %2
433   cmpgei   %0, %z1, %2"
434  [(set_attr "type" "compare")]
435)
436
437(define_insn "*sgtu"
438  [(set (match_operand:SI 0 "register_operand" "=r,r")
439        (gtu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
440                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
441  ""
442  "@
443   cmpgu    %0, %z1, %2
444   cmpgui   %0, %z1, %2"
445  [(set_attr "type" "compare")]
446)
447
448(define_insn "*sgeu"
449  [(set (match_operand:SI 0 "register_operand" "=r,r")
450        (geu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
451                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
452  ""
453  "@
454   cmpgeu   %0, %z1, %2
455   cmpgeui  %0, %z1, %2"
456  [(set_attr "type" "compare")]
457)
458
459;; ---------------------------------
460;;       unconditional branch
461;; ---------------------------------
462
463(define_insn "jump"
464  [(set (pc) (label_ref (match_operand 0 "" "")))]
465  ""
466  "bi       %0"
467  [(set_attr "type" "ubranch")]
468)
469
470(define_insn "indirect_jump"
471  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
472  ""
473  "b        %0"
474  [(set_attr "type" "uibranch")]
475)
476
477;; ---------------------------------
478;;        conditional branch
479;; ---------------------------------
480
481(define_expand "cbranchsi4"
482  [(set (pc)
483   (if_then_else (match_operator 0 "comparison_operator"
484                  [(match_operand:SI 1 "register_operand")
485		   (match_operand:SI 2 "nonmemory_operand")])
486                 (label_ref (match_operand 3 "" ""))
487                 (pc)))]
488  ""
489  "
490{
491  lm32_expand_conditional_branch (operands);
492  DONE;
493}")
494
495(define_insn "*beq"
496  [(set (pc)
497        (if_then_else (eq:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
498                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
499                      (label_ref (match_operand 2 "" ""))
500                      (pc)))]
501  ""
502{
503  return get_attr_length (insn) == 4
504        ? "be     %z0,%z1,%2"
505        : "bne    %z0,%z1,8\n\tbi     %2";
506}
507  [(set_attr "type" "cbranch")])
508
509(define_insn "*bne"
510  [(set (pc)
511        (if_then_else (ne:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
512                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
513                      (label_ref (match_operand 2 "" ""))
514                      (pc)))]
515  ""
516{
517  return get_attr_length (insn) == 4
518        ? "bne    %z0,%z1,%2"
519        : "be     %z0,%z1,8\n\tbi     %2";
520}
521  [(set_attr "type" "cbranch")])
522
523(define_insn "*bgt"
524  [(set (pc)
525        (if_then_else (gt:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
526                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
527                      (label_ref (match_operand 2 "" ""))
528                      (pc)))]
529  ""
530{
531  return get_attr_length (insn) == 4
532        ? "bg     %z0,%z1,%2"
533        : "bge    %z1,%z0,8\n\tbi     %2";
534}
535  [(set_attr "type" "cbranch")])
536
537(define_insn "*bge"
538  [(set (pc)
539        (if_then_else (ge:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
540                             (match_operand:SI 1 "register_or_zero_operand" "rJ"))
541                      (label_ref (match_operand 2 "" ""))
542                      (pc)))]
543  ""
544{
545  return get_attr_length (insn) == 4
546        ? "bge    %z0,%z1,%2"
547        : "bg     %z1,%z0,8\n\tbi     %2";
548}
549  [(set_attr "type" "cbranch")])
550
551(define_insn "*bgtu"
552  [(set (pc)
553        (if_then_else (gtu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
554                              (match_operand:SI 1 "register_or_zero_operand" "rJ"))
555                      (label_ref (match_operand 2 "" ""))
556                      (pc)))]
557  ""
558{
559  return get_attr_length (insn) == 4
560        ? "bgu    %z0,%z1,%2"
561        : "bgeu   %z1,%z0,8\n\tbi     %2";
562}
563  [(set_attr "type" "cbranch")])
564
565(define_insn "*bgeu"
566  [(set (pc)
567        (if_then_else (geu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
568                              (match_operand:SI 1 "register_or_zero_operand" "rJ"))
569                      (label_ref (match_operand 2 "" ""))
570                      (pc)))]
571  ""
572{
573  return get_attr_length (insn) == 4
574        ? "bgeu   %z0,%z1,%2"
575        : "bgu    %z1,%z0,8\n\tbi     %2";
576}
577  [(set_attr "type" "cbranch")])
578
579;; ---------------------------------
580;;               call
581;; ---------------------------------
582
583(define_expand "call"
584  [(parallel [(call (match_operand 0 "" "")
585                    (match_operand 1 "" ""))
586              (clobber (reg:SI RA_REGNUM))
587             ])]
588  ""
589  "
590{
591  rtx addr = XEXP (operands[0], 0);
592  if (!CONSTANT_ADDRESS_P (addr))
593    XEXP (operands[0], 0) = force_reg (Pmode, addr);
594}")
595
596(define_insn "*call"
597  [(call (mem:SI (match_operand:SI 0 "call_operand" "r,s"))
598         (match_operand 1 "" ""))
599   (clobber (reg:SI RA_REGNUM))]
600  ""
601  "@
602   call     %0
603   calli    %0"
604  [(set_attr "type" "call,icall")]
605)
606
607(define_expand "call_value"
608  [(parallel [(set (match_operand 0 "" "")
609                   (call (match_operand 1 "" "")
610                         (match_operand 2 "" "")))
611              (clobber (reg:SI RA_REGNUM))
612             ])]
613  ""
614  "
615{
616  rtx addr = XEXP (operands[1], 0);
617  if (!CONSTANT_ADDRESS_P (addr))
618    XEXP (operands[1], 0) = force_reg (Pmode, addr);
619}")
620
621(define_insn "*call_value"
622  [(set (match_operand 0 "register_operand" "=r,r")
623        (call (mem:SI (match_operand:SI 1 "call_operand" "r,s"))
624              (match_operand 2 "" "")))
625   (clobber (reg:SI RA_REGNUM))]
626  ""
627  "@
628   call     %1
629   calli    %1"
630  [(set_attr "type" "call,icall")]
631)
632
633(define_insn "return_internal"
634  [(use (match_operand:SI 0 "register_operand" "r"))
635   (return)]
636  ""
637  "b        %0"
638  [(set_attr "type" "uibranch")]
639)
640
641(define_expand "return"
642  [(return)]
643  "lm32_can_use_return ()"
644  ""
645)
646
647(define_expand "simple_return"
648  [(simple_return)]
649  ""
650  ""
651)
652
653(define_insn "*return"
654  [(return)]
655  "reload_completed"
656  "ret"
657  [(set_attr "type" "uibranch")]
658)
659
660(define_insn "*simple_return"
661  [(simple_return)]
662  ""
663  "ret"
664  [(set_attr "type" "uibranch")]
665)
666
667;; ---------------------------------
668;;       switch/case statements
669;; ---------------------------------
670
671(define_expand "tablejump"
672  [(set (pc) (match_operand 0 "register_operand" ""))
673   (use (label_ref (match_operand 1 "" "")))]
674  ""
675  "
676{
677  rtx target = operands[0];
678  if (flag_pic)
679    {
680      /* For PIC, the table entry is relative to the start of the table.  */
681      rtx label = gen_reg_rtx (SImode);
682      target = gen_reg_rtx (SImode);
683      emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1]));
684      emit_insn (gen_addsi3 (target, operands[0], label));
685    }
686  emit_jump_insn (gen_tablejumpsi (target, operands[1]));
687  DONE;
688}")
689
690(define_insn "tablejumpsi"
691  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
692   (use (label_ref (match_operand 1 "" "")))]
693  ""
694  "b        %0"
695  [(set_attr "type" "ubranch")]
696)
697
698;; ---------------------------------
699;;            arithmetic
700;; ---------------------------------
701
702(define_insn "addsi3"
703  [(set (match_operand:SI 0 "register_operand" "=r,r")
704        (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
705                 (match_operand:SI 2 "register_or_K_operand" "r,K")))]
706  ""
707  "@
708   add      %0, %z1, %2
709   addi     %0, %z1, %2"
710  [(set_attr "type" "arith")]
711)
712
713(define_insn "subsi3"
714  [(set (match_operand:SI 0 "register_operand" "=r")
715        (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
716                  (match_operand:SI 2 "register_or_zero_operand" "rJ")))]
717  ""
718  "sub      %0, %z1, %z2"
719  [(set_attr "type" "arith")]
720)
721
722(define_insn "mulsi3"
723  [(set (match_operand:SI 0 "register_operand" "=r,r")
724        (mult:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
725                 (match_operand:SI 2 "register_or_K_operand" "r,K")))]
726  "TARGET_MULTIPLY_ENABLED"
727  "@
728   mul      %0, %z1, %2
729   muli     %0, %z1, %2"
730  [(set_attr "type" "multiply")]
731)
732
733(define_insn "udivsi3"
734  [(set (match_operand:SI 0 "register_operand" "=r")
735        (udiv:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
736                 (match_operand:SI 2 "register_operand" "r")))]
737  "TARGET_DIVIDE_ENABLED"
738  "divu     %0, %z1, %2"
739  [(set_attr "type" "divide")]
740)
741
742(define_insn "umodsi3"
743  [(set (match_operand:SI 0 "register_operand" "=r")
744        (umod:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
745                 (match_operand:SI 2 "register_operand" "r")))]
746  "TARGET_DIVIDE_ENABLED"
747  "modu     %0, %z1, %2"
748  [(set_attr "type" "divide")]
749)
750
751;; ---------------------------------
752;;      negation and inversion
753;; ---------------------------------
754
755(define_insn "negsi2"
756  [(set (match_operand:SI 0 "register_operand" "=r")
757        (neg:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))]
758  ""
759  "sub      %0, r0, %z1"
760  [(set_attr "type" "arith")]
761)
762
763(define_insn "one_cmplsi2"
764  [(set (match_operand:SI 0 "register_operand" "=r")
765        (not:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))]
766  ""
767  "not      %0, %z1"
768  [(set_attr "type" "arith")]
769)
770
771;; ---------------------------------
772;;             logical
773;; ---------------------------------
774
775(define_insn "andsi3"
776  [(set (match_operand:SI 0 "register_operand" "=r,r")
777        (and:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
778                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
779  ""
780  "@
781   and      %0, %z1, %2
782   andi     %0, %z1, %2"
783  [(set_attr "type" "arith")]
784)
785
786(define_insn "iorsi3"
787  [(set (match_operand:SI 0 "register_operand" "=r,r")
788        (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
789                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
790  ""
791  "@
792   or       %0, %z1, %2
793   ori      %0, %z1, %2"
794  [(set_attr "type" "arith")]
795)
796
797(define_insn "xorsi3"
798  [(set (match_operand:SI 0 "register_operand" "=r,r")
799        (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
800                (match_operand:SI 2 "register_or_L_operand" "r,L")))]
801  ""
802  "@
803   xor      %0, %z1, %2
804   xori     %0, %z1, %2"
805  [(set_attr "type" "arith")]
806)
807
808(define_insn "*norsi3"
809  [(set (match_operand:SI 0 "register_operand" "=r,r")
810	(not:SI (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
811			(match_operand:SI 2 "register_or_L_operand" "r,L"))))]
812  ""
813  "@
814   nor      %0, %z1, %2
815   nori     %0, %z1, %2"
816  [(set_attr "type" "arith")]
817)
818
819(define_insn "*xnorsi3"
820  [(set (match_operand:SI 0 "register_operand" "=r,r")
821	(not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
822			(match_operand:SI 2 "register_or_L_operand" "r,L"))))]
823  ""
824  "@
825   xnor     %0, %z1, %2
826   xnori    %0, %z1, %2"
827  [(set_attr "type" "arith")]
828)
829
830;; ---------------------------------
831;;              shifts
832;; ---------------------------------
833
834(define_expand "ashlsi3"
835  [(set (match_operand:SI 0 "register_operand" "")
836        (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "")
837                   (match_operand:SI 2 "register_or_L_operand" "")))]
838  ""
839{
840  if (!TARGET_BARREL_SHIFT_ENABLED)
841    {
842      if (!optimize_size
843          && satisfies_constraint_L (operands[2])
844          && INTVAL (operands[2]) <= 8)
845        {
846          int i;
847          int shifts = INTVAL (operands[2]);
848
849          if (shifts == 0)
850            emit_move_insn (operands[0], operands[1]);
851          else
852            emit_insn (gen_addsi3 (operands[0], operands[1], operands[1]));
853          for (i = 1; i < shifts; i++)
854            emit_insn (gen_addsi3 (operands[0], operands[0], operands[0]));
855          DONE;
856        }
857      else
858        FAIL;
859    }
860})
861
862(define_insn "*ashlsi3"
863  [(set (match_operand:SI 0 "register_operand" "=r,r")
864        (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
865                   (match_operand:SI 2 "register_or_L_operand" "r,L")))]
866  "TARGET_BARREL_SHIFT_ENABLED"
867  "@
868   sl       %0, %z1, %2
869   sli      %0, %z1, %2"
870  [(set_attr "type" "shift")]
871)
872
873(define_expand "ashrsi3"
874  [(set (match_operand:SI 0 "register_operand" "")
875        (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "")
876                     (match_operand:SI 2 "register_or_L_operand" "")))]
877  ""
878{
879  if (!TARGET_BARREL_SHIFT_ENABLED)
880    {
881      if (!optimize_size
882          && satisfies_constraint_L (operands[2])
883          && INTVAL (operands[2]) <= 8)
884        {
885          int i;
886          int shifts = INTVAL (operands[2]);
887          rtx one = GEN_INT (1);
888
889          if (shifts == 0)
890            emit_move_insn (operands[0], operands[1]);
891          else
892            emit_insn (gen_ashrsi3_1bit (operands[0], operands[1], one));
893          for (i = 1; i < shifts; i++)
894            emit_insn (gen_ashrsi3_1bit (operands[0], operands[0], one));
895          DONE;
896        }
897      else
898        FAIL;
899    }
900})
901
902(define_insn "*ashrsi3"
903  [(set (match_operand:SI 0 "register_operand" "=r,r")
904        (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
905                     (match_operand:SI 2 "register_or_L_operand" "r,L")))]
906  "TARGET_BARREL_SHIFT_ENABLED"
907  "@
908   sr       %0, %z1, %2
909   sri      %0, %z1, %2"
910  [(set_attr "type" "shift")]
911)
912
913(define_insn "ashrsi3_1bit"
914  [(set (match_operand:SI 0 "register_operand" "=r")
915        (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
916                     (match_operand:SI 2 "constant_M_operand" "M")))]
917  "!TARGET_BARREL_SHIFT_ENABLED"
918  "sri      %0, %z1, %2"
919  [(set_attr "type" "shift")]
920)
921
922(define_expand "lshrsi3"
923  [(set (match_operand:SI 0 "register_operand" "")
924        (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "")
925                     (match_operand:SI 2 "register_or_L_operand" "")))]
926  ""
927{
928  if (!TARGET_BARREL_SHIFT_ENABLED)
929    {
930      if (!optimize_size
931          && satisfies_constraint_L (operands[2])
932          && INTVAL (operands[2]) <= 8)
933        {
934          int i;
935          int shifts = INTVAL (operands[2]);
936          rtx one = GEN_INT (1);
937
938          if (shifts == 0)
939            emit_move_insn (operands[0], operands[1]);
940          else
941            emit_insn (gen_lshrsi3_1bit (operands[0], operands[1], one));
942          for (i = 1; i < shifts; i++)
943            emit_insn (gen_lshrsi3_1bit (operands[0], operands[0], one));
944          DONE;
945        }
946      else
947        FAIL;
948    }
949})
950
951(define_insn "*lshrsi3"
952  [(set (match_operand:SI 0 "register_operand" "=r,r")
953        (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
954                     (match_operand:SI 2 "register_or_L_operand" "r,L")))]
955  "TARGET_BARREL_SHIFT_ENABLED"
956  "@
957   sru      %0, %z1, %2
958   srui     %0, %z1, %2"
959  [(set_attr "type" "shift")]
960)
961
962(define_insn "lshrsi3_1bit"
963  [(set (match_operand:SI 0 "register_operand" "=r")
964        (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
965                     (match_operand:SI 2 "constant_M_operand" "M")))]
966  "!TARGET_BARREL_SHIFT_ENABLED"
967  "srui     %0, %z1, %2"
968  [(set_attr "type" "shift")]
969)
970
971;; ---------------------------------
972;;     function entry / exit
973;; ---------------------------------
974
975(define_expand "prologue"
976  [(const_int 1)]
977  ""
978  "
979{
980  lm32_expand_prologue ();
981  DONE;
982}")
983
984(define_expand "epilogue"
985  [(return)]
986  ""
987  "
988{
989  lm32_expand_epilogue ();
990  DONE;
991}")
992
993;; ---------------------------------
994;;              nop
995;; ---------------------------------
996
997(define_insn "nop"
998  [(const_int 0)]
999  ""
1000  "nop"
1001  [(set_attr "type" "arith")]
1002)
1003
1004;; ---------------------------------
1005;;             blockage
1006;; ---------------------------------
1007
1008;; used to stop the scheduler from
1009;; scheduling code across certain boundaries
1010
1011(define_insn "blockage"
1012  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
1013  ""
1014  ""
1015  [(set_attr "length" "0")]
1016)
1017