OSDN Git Service

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