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