xtensa: Eliminate double MEMW insertions for volatile memory
[official-gcc.git] / gcc / config / lm32 / lm32.md
blob574fb12e0ce208a549c742b124beb224a00d53fe
1 ;; Machine description of the Lattice Mico32 architecture for GNU C compiler.
2 ;; Contributed by Jon Beniston <jon@beniston.com>
4 ;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
6 ;; This file is part of GCC.
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.
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.
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/>.  
22 ;; Include predicate and constraint definitions
23 (include "predicates.md")
24 (include "constraints.md")
27 ;; Register numbers
28 (define_constants
29   [(RA_REGNUM           29)     ; return address register.
30   ]
33 ;; LM32 specific volatile operations
34 (define_constants
35   [(UNSPECV_BLOCKAGE    1)]     ; prevent scheduling across pro/epilog boundaries
38 ;; LM32 specific operations
39 (define_constants
40   [(UNSPEC_GOT          2)
41    (UNSPEC_GOTOFF_HI16  3)
42    (UNSPEC_GOTOFF_LO16  4)]     
45 ;; --------------------------------- 
46 ;;      instruction types
47 ;; ---------------------------------
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))
73                     
74 ;; ---------------------------------
75 ;;           scheduling 
76 ;; ---------------------------------
78 (define_automaton "lm32")
80 (define_cpu_unit "x" "lm32")
81 (define_cpu_unit "m" "lm32")
82 (define_cpu_unit "w" "lm32")
84 (define_insn_reservation "singlecycle" 1
85   (eq_attr "type" "store,arith,call,icall,ubranch,uibranch,cbranch")
86  "x")
88 (define_insn_reservation "twocycle" 2
89   (eq_attr "type" "compare,shift,divide")
90  "x,m") 
92 (define_insn_reservation "threecycle" 3
93   (eq_attr "type" "load,multiply")
94  "x,m,w")
96 ;; ---------------------------------
97 ;;               mov 
98 ;; ---------------------------------
100 (define_expand "movqi"
101   [(set (match_operand:QI 0 "general_operand" "")
102         (match_operand:QI 1 "general_operand" ""))]
103   ""
104   "
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     }
116 (define_expand "movhi"
117   [(set (match_operand:HI 0 "general_operand" "")
118         (match_operand:HI 1 "general_operand" ""))]
119   ""
120   "
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     }
132 (define_expand "movsi"
133   [(set (match_operand:SI 0 "general_operand" "")
134         (match_operand:SI 1 "general_operand" ""))]
135   ""
136   "
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     }
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     }    
219 (define_expand "cpymemsi"
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   ""
226   if (!lm32_expand_block_move (operands))
227     FAIL;
228   DONE;
231 ;; ---------------------------------
232 ;;        load/stores/moves 
233 ;; ---------------------------------
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")]
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")]
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")]
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")]
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")]   
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")]   
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")]   
314 ;; ---------------------------------
315 ;;      sign and zero extension 
316 ;; ---------------------------------
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")]
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")]  
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")]
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")]  
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")]
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")]  
378 ;; ---------------------------------
379 ;;             compare 
380 ;; ---------------------------------
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   ""
389   lm32_expand_scc (operands);
390   DONE;
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")]
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")]
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")]
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")]
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")]
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")]
459 ;; ---------------------------------
460 ;;       unconditional branch
461 ;; ---------------------------------
463 (define_insn "jump"
464   [(set (pc) (label_ref (match_operand 0 "" "")))]
465   ""
466   "bi       %0"
467   [(set_attr "type" "ubranch")]
470 (define_insn "indirect_jump"
471   [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
472   ""
473   "b        %0"
474   [(set_attr "type" "uibranch")]
477 ;; ---------------------------------
478 ;;        conditional branch
479 ;; ---------------------------------
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;
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   ""
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")])
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   ""
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")])
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   ""
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")])
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   ""
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")])
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   ""
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")])
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   ""
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")])
579 ;; ---------------------------------
580 ;;               call 
581 ;; ---------------------------------
583 (define_expand "call"
584   [(parallel [(call (match_operand 0 "" "")
585                     (match_operand 1 "" ""))
586               (clobber (reg:SI RA_REGNUM))
587              ])]
588   ""
589   "
591   rtx addr = XEXP (operands[0], 0);
592   if (!CONSTANT_ADDRESS_P (addr))
593     XEXP (operands[0], 0) = force_reg (Pmode, addr);
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")]  
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   "
616   rtx addr = XEXP (operands[1], 0);
617   if (!CONSTANT_ADDRESS_P (addr))
618     XEXP (operands[1], 0) = force_reg (Pmode, addr); 
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")]  
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")]  
641 (define_expand "return"
642   [(return)]
643   "lm32_can_use_return ()"
644   ""
647 (define_expand "simple_return"
648   [(simple_return)]
649   ""
650   ""
653 (define_insn "*return"
654   [(return)]
655   "reload_completed"
656   "ret"
657   [(set_attr "type" "uibranch")]  
660 (define_insn "*simple_return"
661   [(simple_return)]
662   ""
663   "ret"
664   [(set_attr "type" "uibranch")]  
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   "
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;
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")]  
698 ;; ---------------------------------
699 ;;            arithmetic 
700 ;; ---------------------------------
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")]  
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")]  
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")]
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")]
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")]
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 )      
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")]
771 ;; ---------------------------------
772 ;;             logical 
773 ;; ---------------------------------
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")]
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")]
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")]
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 )                
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 )                
830 ;; ---------------------------------
831 ;;              shifts 
832 ;; ---------------------------------
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   ""
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 })  
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")]
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   ""
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")]
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")]
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   ""
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 })  
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")]   
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")]   
971 ;; ---------------------------------
972 ;;     function entry / exit 
973 ;; ---------------------------------
975 (define_expand "prologue"
976   [(const_int 1)]
977   ""
978   "
980   lm32_expand_prologue ();
981   DONE;
984 (define_expand "epilogue"
985   [(return)]
986   ""
987   "
989   lm32_expand_epilogue ();
990   DONE;
993 ;; ---------------------------------
994 ;;              nop 
995 ;; ---------------------------------
997 (define_insn "nop"  
998   [(const_int 0)]
999   ""
1000   "nop"
1001   [(set_attr "type" "arith")]
1004 ;; ---------------------------------
1005 ;;             blockage 
1006 ;; ---------------------------------
1008 ;; used to stop the scheduler from 
1009 ;; scheduling code across certain boundaries
1011 (define_insn "blockage"
1012   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
1013   ""
1014   ""
1015   [(set_attr "length" "0")]