OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [microblaze/] [microblaze.md] - Blame information for rev 709

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;; microblaze.md -- Machine description for Xilinx MicroBlaze processors.
2
;; Copyright 2009, 2010 Free Software Foundation, Inc.
3
 
4
;; Contributed by Michael Eager .
5
 
6
;; This file is part of GCC.
7
 
8
;; GCC is free software; you can redistribute it and/or modify
9
;; it under the terms of the GNU General Public License as published by
10
;; the Free Software Foundation; either version 3, or (at your option)
11
;; any later version.
12
 
13
;; GCC is distributed in the hope that it will be useful,
14
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
;; GNU General Public 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
;; .  */
21
 
22
(include "constraints.md")
23
(include "predicates.md")
24
 
25
;;----------------------------------------------------
26
;; Constants
27
;;----------------------------------------------------
28
(define_constants [
29
  (R_SP        1)       ;; Stack pointer reg
30
  (R_SR       15)       ;; Sub-routine return addr reg
31
  (R_IR       14)       ;; Interrupt return addr reg
32
  (R_DR       16)       ;; Debug trap return addr reg
33
  (R_ER       17)       ;; Exception return addr reg
34
  (R_TMP      18)       ;; Assembler temporary reg
35
  (R_GOT      20)       ;; GOT ptr reg
36
  (MB_PIPE_3   0)       ;; Microblaze 3-stage pipeline
37
  (MB_PIPE_5   1)       ;; Microblaze 5-stage pipeline
38
  (UNSPEC_SET_GOT       101)    ;;
39
  (UNSPEC_GOTOFF        102)    ;; GOT offset
40
  (UNSPEC_PLT           103)    ;; jump table
41
  (UNSPEC_CMP           104)    ;; signed compare
42
  (UNSPEC_CMPU          105)    ;; unsigned compare
43
])
44
 
45
 
46
;;----------------------------------------------------
47
;; Instruction Attributes
48
;;----------------------------------------------------
49
 
50
;; Classification of each insn.
51
;; branch       conditional branch
52
;; jump         unconditional jump
53
;; call         unconditional call
54
;; load         load instruction(s)
55
;; store        store instruction(s)
56
;; move         data movement within same register set
57
;; arith        integer arithmetic instruction
58
;; darith       double precision integer arithmetic instructions
59
;; imul         integer multiply
60
;; idiv         integer divide
61
;; icmp         integer compare
62
;; Xfadd                floating point add/subtract
63
;; Xfmul                floating point multiply
64
;; Xfmadd       floating point multiply-add
65
;; Xfdiv                floating point divide
66
;; Xfabs                floating point absolute value
67
;; Xfneg                floating point negation
68
;; Xfcmp                floating point compare
69
;; Xfcvt                floating point convert
70
;; Xfsqrt       floating point square root
71
;; multi        multiword sequence (or user asm statements)
72
;; nop          no operation
73
;; bshift       Shift operations
74
 
75
(define_attr "type"
76
  "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt"
77
  (const_string "unknown"))
78
 
79
;; Main data type used by the insn
80
(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"))
81
 
82
;; # instructions (4 bytes each)
83
(define_attr "length" "" (const_int 4))
84
 
85
(define_code_iterator any_return [return simple_return])
86
 
87
;;  expands to the name of the optab for a particular code.
88
(define_code_attr optab [(return "return")
89
                         (simple_return "simple_return")])
90
 
91
 
92
;;----------------------------------------------------
93
;; Attribute describing the processor.
94
;;----------------------------------------------------
95
 
96
;; Describe a user's asm statement.
97
(define_asm_attributes
98
  [(set_attr "type" "multi")])
99
 
100
;; whether or not generating calls to position independent functions
101
(define_attr "abicalls" "no,yes"
102
  (const (symbol_ref "microblaze_abicalls_attr")))
103
 
104
;;----------------------------------------------------------------
105
;; Microblaze DFA Pipeline description
106
;;----------------------------------------------------------------
107
 
108
;;-----------------------------------------------------------------
109
/*
110
   This is description of pipeline hazards based on DFA.  The
111
   following constructions can be used for this:
112
 
113
   o define_cpu_unit string [string]) describes a cpu functional unit
114
     (separated by comma).
115
 
116
     1st operand: Names of cpu function units.
117
     2nd operand: Name of automaton (see comments for
118
     DEFINE_AUTOMATON).
119
 
120
     All define_reservations and define_cpu_units should have unique
121
     names which can not be "nothing".
122
 
123
   o (exclusion_set string string) means that each CPU function unit
124
     in the first string can not be reserved simultaneously with each
125
     unit whose name is in the second string and vise versa.  CPU
126
     units in the string are separated by commas. For example, it is
127
     useful for description CPU with fully pipelined floating point
128
     functional unit which can execute simultaneously only single
129
     floating point insns or only double floating point insns.
130
 
131
   o (presence_set string string) means that each CPU function unit in
132
     the first string can not be reserved unless at least one of units
133
     whose names are in the second string is reserved.  This is an
134
     asymmetric relation.  CPU units in the string are separated by
135
     commas.  For example, it is useful for description that slot1 is
136
     reserved after slot0 reservation for a VLIW processor.
137
 
138
   o (absence_set string string) means that each CPU function unit in
139
     the first string can not be reserved only if each unit whose name
140
     is in the second string is not reserved.  This is an asymmetric
141
     relation (actually exclusion set is analogous to this one but it
142
     is symmetric).  CPU units in the string are separated by commas.
143
     For example, it is useful for description that slot0 can not be
144
     reserved after slot1 or slot2 reservation for a VLIW processor.
145
 
146
   o (define_bypass number out_insn_names in_insn_names) names bypass with
147
     given latency (the first number) from insns given by the first
148
     string (see define_insn_reservation) into insns given by the
149
     second string.  Insn names in the strings are separated by
150
     commas.
151
 
152
   o (define_automaton string) describes names of an automaton
153
     generated and used for pipeline hazards recognition.  The names
154
     are separated by comma.  Actually it is possibly to generate the
155
     single automaton but unfortunately it can be very large.  If we
156
     use more one automata, the summary size of the automata usually
157
     is less than the single one.  The automaton name is used in
158
     define_cpu_unit.  All automata should have unique names.
159
 
160
   o (define_reservation string string) names reservation (the first
161
     string) of cpu functional units (the 2nd string).  Sometimes unit
162
     reservations for different insns contain common parts.  In such
163
     case, you describe common part and use one its name (the 1st
164
     parameter) in regular expression in define_insn_reservation.  All
165
     define_reservations, define results and define_cpu_units should
166
     have unique names which can not be "nothing".
167
 
168
   o (define_insn_reservation name default_latency condition regexpr)
169
     describes reservation of cpu functional units (the 3nd operand)
170
     for instruction which is selected by the condition (the 2nd
171
     parameter).  The first parameter is used for output of debugging
172
     information.  The reservations are described by a regular
173
     expression according the following syntax:
174
 
175
       regexp = regexp "," oneof
176
              | oneof
177
 
178
       oneof = oneof "|" allof
179
             | allof
180
 
181
       allof = allof "+" repeat
182
             | repeat
183
 
184
       repeat = element "*" number
185
              | element
186
 
187
       element = cpu_function_name
188
               | reservation_name
189
               | result_name
190
               | "nothing"
191
               | "(" regexp ")"
192
 
193
       1. "," is used for describing start of the next cycle in
194
          reservation.
195
 
196
       2. "|" is used for describing the reservation described by the
197
          first regular expression *or* the reservation described by
198
          the second regular expression *or* etc.
199
 
200
       3. "+" is used for describing the reservation described by the
201
          first regular expression *and* the reservation described by
202
          the second regular expression *and* etc.
203
 
204
       4. "*" is used for convenience and simply means sequence in
205
          which the regular expression are repeated NUMBER times with
206
          cycle advancing (see ",").
207
 
208
       5. cpu function unit name which means reservation.
209
 
210
       6. reservation name -- see define_reservation.
211
 
212
       7. string "nothing" means no units reservation.
213
 
214
*/
215
;;-----------------------------------------------------------------
216
 
217
 
218
;;----------------------------------------------------------------
219
;; Microblaze 5-stage pipeline description (v5.00.a and later)
220
;;----------------------------------------------------------------
221
 
222
(define_automaton   "mbpipe_5")
223
(define_cpu_unit    "mb_issue,mb_iu,mb_wb,mb_fpu,mb_fpu_2,mb_mul,mb_mul_2,mb_div,mb_div_2,mb_bs,mb_bs_2" "mbpipe_5")
224
 
225
(define_insn_reservation "mb-integer" 1
226
  (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")
227
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
228
  "mb_issue,mb_iu,mb_wb")
229
 
230
(define_insn_reservation "mb-special-move" 2
231
  (and (eq_attr "type" "move")
232
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
233
  "mb_issue,mb_iu*2,mb_wb")
234
 
235
(define_insn_reservation "mb-mem-load" 3
236
  (and (eq_attr "type" "load,no_delay_load")
237
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
238
  "mb_issue,mb_iu,mb_wb")
239
 
240
(define_insn_reservation "mb-mem-store" 1
241
  (and (eq_attr "type" "store,no_delay_store")
242
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
243
  "mb_issue,mb_iu,mb_wb")
244
 
245
(define_insn_reservation "mb-mul" 3
246
  (and (eq_attr "type" "imul,no_delay_imul")
247
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
248
  "mb_issue,mb_mul,mb_mul_2*2,mb_wb")
249
 
250
(define_insn_reservation "mb-div" 34
251
  (and (eq_attr "type" "idiv")
252
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
253
    "mb_issue,mb_div,mb_div_2*33,mb_wb")
254
 
255
(define_insn_reservation "mb-bs" 2
256
  (and (eq_attr "type" "bshift")
257
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
258
   "mb_issue,mb_bs,mb_bs_2,mb_wb")
259
 
260
(define_insn_reservation "mb-fpu-add-sub-mul" 6
261
  (and (eq_attr "type" "fadd,frsub,fmul")
262
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
263
  "mb_issue,mb_fpu,mb_fpu_2*5,mb_wb")
264
 
265
(define_insn_reservation "mb-fpu-fcmp" 3
266
  (and (eq_attr "type" "fcmp")
267
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
268
  "mb_issue,mb_fpu,mb_fpu*2,mb_wb")
269
 
270
(define_insn_reservation "mb-fpu-div" 30
271
  (and (eq_attr "type" "fdiv")
272
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
273
  "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")
274
 
275
(define_insn_reservation "mb-fpu-sqrt" 30
276
  (and (eq_attr "type" "fsqrt")
277
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
278
  "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")
279
 
280
(define_insn_reservation "mb-fpu-fcvt" 4
281
  (and (eq_attr "type" "fcvt")
282
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
283
  "mb_issue,mb_fpu,mb_fpu_2*3,mb_wb")
284
 
285
;;----------------------------------------------------------------
286
;; Microblaze 3-stage pipeline description (for v4.00.a and earlier)
287
;;----------------------------------------------------------------
288
 
289
(define_automaton   "mbpipe_3")
290
(define_cpu_unit    "mb3_iu" "mbpipe_3")
291
 
292
(define_insn_reservation "mb3-integer" 1
293
  (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")
294
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
295
  "mb3_iu")
296
 
297
(define_insn_reservation "mb3-special-move" 2
298
  (and (eq_attr "type" "move")
299
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
300
  "mb3_iu*2")
301
 
302
(define_insn_reservation "mb3-mem-load" 2
303
  (and (eq_attr "type" "load,no_delay_load")
304
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
305
  "mb3_iu")
306
 
307
(define_insn_reservation "mb3-mem-store" 1
308
  (and (eq_attr "type" "store,no_delay_store")
309
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
310
  "mb3_iu")
311
 
312
(define_insn_reservation "mb3-mul" 3
313
  (and (eq_attr "type" "imul,no_delay_imul")
314
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
315
  "mb3_iu")
316
 
317
(define_insn_reservation "mb3-div" 34
318
  (and (eq_attr "type" "idiv")
319
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
320
    "mb3_iu")
321
 
322
(define_insn_reservation "mb3-bs" 2
323
  (and (eq_attr "type" "bshift")
324
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
325
   "mb3_iu")
326
 
327
(define_insn_reservation "mb3-fpu-add-sub-mul" 6
328
  (and (eq_attr "type" "fadd,frsub,fmul")
329
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
330
  "mb3_iu")
331
 
332
(define_insn_reservation "mb3-fpu-fcmp" 3
333
  (and (eq_attr "type" "fcmp")
334
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
335
  "mb3_iu")
336
 
337
(define_insn_reservation "mb3-fpu-div" 30
338
  (and (eq_attr "type" "fdiv")
339
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
340
  "mb3_iu")
341
 
342
(define_insn_reservation "mb3-fpu-sqrt" 30
343
  (and (eq_attr "type" "fsqrt")
344
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
345
  "mb3_iu")
346
 
347
(define_insn_reservation "mb3-fpu-fcvt" 4
348
  (and (eq_attr "type" "fcvt")
349
       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
350
  "mb3_iu")
351
 
352
(automata_option "v")
353
(automata_option "time")
354
(automata_option "progress")
355
 
356
;;----------------------------------------------------------------
357
;; Microblaze delay slot description
358
;;----------------------------------------------------------------
359
(define_delay (eq_attr "type" "branch,call,jump")
360
  [(and (eq_attr "type" "!branch,call,jump,icmp,multi,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,darith")
361
        (ior (not (match_test "microblaze_no_unsafe_delay"))
362
             (eq_attr "type" "!fadd,frsub,fmul,fdiv,fcmp,store,load")
363
             ))
364
  (nil) (nil)])
365
 
366
 
367
;;----------------------------------------------------------------
368
;; Microblaze FPU
369
;;----------------------------------------------------------------
370
 
371
(define_insn "addsf3"
372
  [(set (match_operand:SF 0 "register_operand" "=d")
373
        (plus:SF (match_operand:SF 1 "register_operand" "d")
374
                 (match_operand:SF 2 "register_operand" "d")))]
375
  "TARGET_HARD_FLOAT"
376
  "fadd\t%0,%1,%2"
377
  [(set_attr "type"     "fadd")
378
  (set_attr "mode"      "SF")
379
  (set_attr "length"    "4")])
380
 
381
(define_insn "subsf3"
382
  [(set (match_operand:SF 0 "register_operand" "=d")
383
        (minus:SF (match_operand:SF 1 "register_operand" "d")
384
                  (match_operand:SF 2 "register_operand" "d")))]
385
  "TARGET_HARD_FLOAT"
386
  "frsub\t%0,%2,%1"
387
  [(set_attr "type"     "frsub")
388
  (set_attr "mode"      "SF")
389
  (set_attr "length"    "4")])
390
 
391
(define_insn "mulsf3"
392
  [(set (match_operand:SF 0 "register_operand" "=d")
393
        (mult:SF (match_operand:SF 1 "register_operand" "d")
394
                 (match_operand:SF 2 "register_operand" "d")))]
395
  "TARGET_HARD_FLOAT"
396
  "fmul\t%0,%1,%2"
397
  [(set_attr "type"     "fmul")
398
  (set_attr "mode"      "SF")
399
  (set_attr "length"    "4")])
400
 
401
 
402
(define_insn "divsf3"
403
  [(set (match_operand:SF 0 "register_operand" "=d")
404
        (div:SF (match_operand:SF 1 "register_operand" "d")
405
                (match_operand:SF 2 "register_operand" "d")))]
406
  "TARGET_HARD_FLOAT"
407
  "fdiv\t%0,%2,%1"
408
  [(set_attr "type"     "fdiv")
409
  (set_attr "mode"      "SF")
410
  (set_attr "length"    "4")])
411
 
412
(define_insn "sqrtsf2"
413
  [(set (match_operand:SF 0 "register_operand" "=d")
414
        (sqrt:SF (match_operand:SF 1 "register_operand" "d")))]
415
  "TARGET_HARD_FLOAT && TARGET_FLOAT_SQRT"
416
  "fsqrt\t%0,%1"
417
  [(set_attr "type"     "fsqrt")
418
  (set_attr "mode"      "SF")
419
  (set_attr "length"    "4")])
420
 
421
(define_insn "floatsisf2"
422
  [(set (match_operand:SF 0 "register_operand" "=d")
423
        (float:SF (match_operand:SI 1 "register_operand" "d")))]
424
  "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT"
425
  "flt\t%0,%1"
426
  [(set_attr "type"     "fcvt")
427
  (set_attr "mode"      "SF")
428
  (set_attr "length"    "4")])
429
 
430
(define_insn "fix_truncsfsi2"
431
  [(set (match_operand:SI 0 "register_operand" "=d")
432
        (fix:SI (match_operand:SF 1 "register_operand" "d")))]
433
  "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT"
434
  "fint\t%0,%1"
435
  [(set_attr "type"     "fcvt")
436
  (set_attr "mode"      "SF")
437
  (set_attr "length"    "4")])
438
 
439
;;----------------------------------------------------------------
440
;; Add
441
;;----------------------------------------------------------------
442
 
443
;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ]
444
;; Leave carry as is
445
(define_insn "addsi3"
446
  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
447
        (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
448
                 (match_operand:SI 2 "arith_operand" "d,I,i")))]
449
  ""
450
  "@
451
   addk\t%0,%z1,%2
452
   addik\t%0,%z1,%2
453
   addik\t%0,%z1,%2"
454
  [(set_attr "type"     "arith,arith,no_delay_arith")
455
  (set_attr "mode"      "SI,SI,SI")
456
  (set_attr "length"    "4,4,8")])
457
 
458
;;----------------------------------------------------------------
459
;; Double Precision Additions
460
;;----------------------------------------------------------------
461
 
462
;; reg_DI_dest = reg_DI_src1 + DI_src2
463
 
464
;; Adding 2 DI operands in register or reg/imm
465
 
466
(define_insn "adddi3"
467
  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
468
        (plus:DI (match_operand:DI 1 "register_operand" "%d,d,d")
469
                 (match_operand:DI 2 "arith_operand32" "d,P,N")))]
470
  ""
471
  "@
472
  add\t%L0,%L1,%L2\;addc\t%M0,%M1,%M2
473
  addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0
474
  addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0\;addi\t%M0,%M0,-1"
475
  [(set_attr "type"     "darith")
476
  (set_attr "mode"      "DI")
477
  (set_attr "length"    "8,8,12")])
478
 
479
;;----------------------------------------------------------------
480
;; Subtraction
481
;;----------------------------------------------------------------
482
 
483
(define_insn "subsi3"
484
  [(set (match_operand:SI 0 "register_operand" "=d,d")
485
        (minus:SI (match_operand:SI 1 "arith_operand" "d,d")
486
                  (match_operand:SI 2 "arith_operand" "d,n")))]
487
  ""
488
  "@
489
   rsubk\t%0,%2,%z1
490
   addik\t%0,%z1,-%2"
491
  [(set_attr "type"     "arith,no_delay_arith")
492
  (set_attr "mode"      "SI")
493
  (set_attr "length"    "4,8")])
494
 
495
 
496
;;----------------------------------------------------------------
497
;; Double Precision Subtraction
498
;;----------------------------------------------------------------
499
 
500
(define_insn "subdi3"
501
  [(set (match_operand:DI 0 "register_operand" "=&d")
502
        (minus:DI (match_operand:DI 1 "register_operand" "d")
503
                  (match_operand:DI 2 "arith_operand32" "d")))]
504
  ""
505
  "@
506
   rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1"
507
  [(set_attr "type"     "darith")
508
  (set_attr "mode"      "DI")
509
  (set_attr "length"    "8")])
510
 
511
 
512
;;----------------------------------------------------------------
513
;; Multiplication
514
;;----------------------------------------------------------------
515
 
516
(define_insn "mulsi3"
517
  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
518
        (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
519
                 (match_operand:SI 2 "arith_operand" "d,I,i")))]
520
  "!TARGET_SOFT_MUL"
521
  "@
522
  mul\t%0,%1,%2
523
  muli\t%0,%1,%2
524
  muli\t%0,%1,%2"
525
  [(set_attr "type"     "imul,imul,no_delay_imul")
526
  (set_attr "mode"      "SI")
527
  (set_attr "length"    "4,4,8")])
528
 
529
(define_insn "mulsidi3"
530
  [(set (match_operand:DI 0 "register_operand" "=&d")
531
        (mult:DI
532
         (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
533
         (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
534
  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
535
  "mul\t%L0,%1,%2\;mulh\t%M0,%1,%2"
536
  [(set_attr "type"     "no_delay_arith")
537
   (set_attr "mode"     "DI")
538
   (set_attr "length"   "8")])
539
 
540
(define_insn "umulsidi3"
541
  [(set (match_operand:DI 0 "register_operand" "=&d")
542
        (mult:DI
543
         (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
544
         (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
545
  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
546
  "mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2"
547
  [(set_attr "type"     "no_delay_arith")
548
   (set_attr "mode"     "DI")
549
   (set_attr "length"   "8")])
550
 
551
(define_insn "usmulsidi3"
552
  [(set (match_operand:DI 0 "register_operand" "=&d")
553
        (mult:DI
554
         (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
555
         (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
556
  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
557
  "mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1"
558
  [(set_attr "type"     "no_delay_arith")
559
   (set_attr "mode"     "DI")
560
   (set_attr "length"   "8")])
561
 
562
(define_insn "*smulsi3_highpart"
563
  [(set (match_operand:SI 0 "register_operand" "=d")
564
        (truncate:SI
565
         (lshiftrt:DI
566
          (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "d"))
567
                   (sign_extend:DI (match_operand:SI 2 "register_operand"  "d")))
568
          (const_int 32))))]
569
  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
570
  "mulh\t%0,%1,%2"
571
  [(set_attr "type"     "imul")
572
  (set_attr "mode"      "SI")
573
  (set_attr "length"    "4")])
574
 
575
(define_insn "*umulsi3_highpart"
576
  [(set (match_operand:SI 0 "register_operand"                            "=d")
577
        (truncate:SI
578
         (lshiftrt:DI
579
          (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "d"))
580
                   (zero_extend:DI (match_operand:SI 2 "register_operand"  "d"))
581
)
582
          (const_int 32))))]
583
  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
584
  "mulhu\t%0,%1,%2"
585
  [(set_attr "type"     "imul")
586
  (set_attr "mode"      "SI")
587
  (set_attr "length"    "4")])
588
 
589
(define_insn "*usmulsi3_highpart"
590
  [(set (match_operand:SI 0 "register_operand"                            "=d")
591
        (truncate:SI
592
         (lshiftrt:DI
593
          (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "d"))
594
                   (sign_extend:DI (match_operand:SI 2 "register_operand"  "d"))
595
)
596
          (const_int 32))))]
597
  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
598
  "mulhsu\t%0,%2,%1"
599
  [(set_attr "type"     "imul")
600
  (set_attr "mode"      "SI")
601
  (set_attr "length"    "4")])
602
 
603
 
604
;;----------------------------------------------------------------
605
;; Division and remainder
606
;;----------------------------------------------------------------
607
(define_expand "divsi3"
608
  [(set (match_operand:SI 0 "register_operand" "=d")
609
        (div:SI (match_operand:SI 1 "register_operand" "d")
610
                (match_operand:SI 2 "register_operand" "d")))
611
  ]
612
  "(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)"
613
  {
614
    if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)
615
      {
616
        microblaze_expand_divide (operands);
617
        DONE;
618
      }
619
    else if (!TARGET_SOFT_DIV)
620
      {
621
        emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2]));
622
        DONE;
623
      }
624
  }
625
)
626
 
627
 
628
(define_insn "divsi3_internal"
629
  [(set (match_operand:SI 0 "register_operand" "=d")
630
        (div:SI (match_operand:SI 1 "register_operand" "d")
631
                (match_operand:SI 2 "register_operand" "d")))
632
  ]
633
  "!TARGET_SOFT_DIV"
634
  "idiv\t%0,%2,%1"
635
  [(set_attr "type"     "idiv")
636
  (set_attr "mode"      "SI")
637
  (set_attr "length"    "4")]
638
)
639
 
640
(define_insn "udivsi3"
641
  [(set (match_operand:SI 0 "register_operand" "=d")
642
        (udiv:SI (match_operand:SI 1 "register_operand" "d")
643
                 (match_operand:SI 2 "register_operand" "d")))
644
  ]
645
  "!TARGET_SOFT_DIV"
646
  "idivu\t%0,%2,%1"
647
  [(set_attr "type"     "idiv")
648
  (set_attr "mode"      "SI")
649
  (set_attr "length"    "4")])
650
 
651
 
652
;;----------------------------------------------------------------
653
;; Negation and one's complement
654
;;----------------------------------------------------------------
655
 
656
(define_insn "negsi2"
657
  [(set (match_operand:SI 0 "register_operand" "=d")
658
        (neg:SI (match_operand:SI 1 "register_operand" "d")))]
659
  ""
660
  "rsubk\t%0,%1,r0"
661
  [(set_attr "type"     "arith")
662
  (set_attr "mode"      "SI")
663
  (set_attr "length"    "4")])
664
 
665
(define_insn "negdi2"
666
  [(set (match_operand:DI 0 "register_operand" "=d")
667
        (neg:DI (match_operand:DI 1 "register_operand" "d")))]
668
  ""
669
  "rsub\t%L0,%L1,r0\;rsubc\t%M0,%M1,r0"
670
  [(set_attr "type"     "darith")
671
  (set_attr "mode"      "DI")
672
  (set_attr "length"    "8")])
673
 
674
 
675
(define_insn "one_cmplsi2"
676
  [(set (match_operand:SI 0 "register_operand" "=d")
677
        (not:SI (match_operand:SI 1 "register_operand" "d")))]
678
  ""
679
  "xori\t%0,%1,-1"
680
  [(set_attr "type"     "arith")
681
  (set_attr "mode"      "SI")
682
  (set_attr "length"    "4")])
683
 
684
(define_insn "*one_cmpldi2"
685
  [(set (match_operand:DI 0 "register_operand" "=d")
686
        (not:DI (match_operand:DI 1 "register_operand" "d")))]
687
  ""
688
  "nor\t%M0,r0,%M1\;nor\t%L0,r0,%L1"
689
  [(set_attr "type"     "darith")
690
  (set_attr "mode"      "DI")
691
  (set_attr "length"    "8")]
692
)
693
 
694
(define_split
695
  [(set (match_operand:DI 0 "register_operand" "")
696
        (not:DI (match_operand:DI 1 "register_operand" "")))]
697
  "reload_completed
698
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
699
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
700
 
701
  [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))
702
  (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
703
  "")
704
 
705
 
706
;;----------------------------------------------------------------
707
;; Logical
708
;;----------------------------------------------------------------
709
 
710
(define_insn "andsi3"
711
  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
712
        (and:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")
713
                (match_operand:SI 2 "arith_operand" "d,I,i,M")))]
714
  ""
715
  "@
716
   and\t%0,%1,%2
717
   andi\t%0,%1,%2 #and1
718
   andi\t%0,%1,%2 #and2
719
   andi\t%0,%1,%2 #and3"
720
  [(set_attr "type"     "arith,arith,no_delay_arith,no_delay_arith")
721
  (set_attr "mode"      "SI,SI,SI,SI")
722
  (set_attr "length"    "4,8,8,8")])
723
 
724
 
725
(define_insn "anddi3"
726
  [(set (match_operand:DI 0 "register_operand" "=d")
727
        (and:DI (match_operand:DI 1 "register_operand" "d")
728
                (match_operand:DI 2 "register_operand" "d")))]
729
  ""
730
  "and\t%M0,%M1,%M2\;and\t%L0,%L1,%L2"
731
  [(set_attr "type"     "darith")
732
  (set_attr "mode"      "DI")
733
  (set_attr "length"    "8")])
734
 
735
 
736
(define_split
737
  [(set (match_operand:DI 0 "register_operand" "")
738
        (and:DI (match_operand:DI 1 "register_operand" "")
739
                (match_operand:DI 2 "register_operand" "")))]
740
  "reload_completed
741
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
742
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
743
   && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
744
 
745
  [(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0)
746
                                            (subreg:SI (match_dup 2) 0)))
747
  (set (subreg:SI (match_dup 0) 4) (and:SI (subreg:SI (match_dup 1) 4)
748
                                           (subreg:SI (match_dup 2) 4)))]
749
  "")
750
 
751
(define_insn "iorsi3"
752
  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
753
        (ior:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")
754
                (match_operand:SI 2 "arith_operand" "d,I,M,i")))]
755
  ""
756
  "@
757
   or\t%0,%1,%2
758
   ori\t%0,%1,%2
759
   ori\t%0,%1,%2
760
   ori\t%0,%1,%2"
761
  [(set_attr "type"     "arith,no_delay_arith,no_delay_arith,no_delay_arith")
762
  (set_attr "mode"      "SI,SI,SI,SI")
763
  (set_attr "length"    "4,8,8,8")])
764
 
765
 
766
(define_insn "iordi3"
767
  [(set (match_operand:DI 0 "register_operand" "=d")
768
        (ior:DI (match_operand:DI 1 "register_operand" "d")
769
                (match_operand:DI 2 "register_operand" "d")))]
770
  ""
771
  "or\t%M0,%M1,%M2\;or\t%L0,%L1,%L2"
772
  [(set_attr "type"     "darith")
773
  (set_attr "mode"      "DI")
774
  (set_attr "length"    "8")]
775
)
776
 
777
 
778
(define_split
779
  [(set (match_operand:DI 0 "register_operand" "")
780
        (ior:DI (match_operand:DI 1 "register_operand" "")
781
                (match_operand:DI 2 "register_operand" "")))]
782
  "reload_completed
783
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
784
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
785
   && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
786
 
787
  [(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0)
788
                                            (subreg:SI (match_dup 2) 0)))
789
  (set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4)
790
                                           (subreg:SI (match_dup 2) 4)))]
791
  "")
792
 
793
(define_insn "xorsi3"
794
  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
795
        (xor:SI (match_operand:SI 1 "arith_operand" "%d,d,d")
796
                (match_operand:SI 2 "arith_operand" "d,I,i")))]
797
  ""
798
  "@
799
   xor\t%0,%1,%2
800
   xori\t%0,%1,%2
801
   xori\t%0,%1,%2"
802
  [(set_attr "type"     "arith,arith,no_delay_arith")
803
  (set_attr "mode"      "SI,SI,SI")
804
  (set_attr "length"    "4,8,8")])
805
 
806
(define_insn "xordi3"
807
  [(set (match_operand:DI 0 "register_operand" "=d")
808
        (xor:DI (match_operand:DI 1 "register_operand" "d")
809
                (match_operand:DI 2 "register_operand" "d")))]
810
  ""
811
  "xor\t%M0,%M1,%M2\;xor\t%L0,%L1,%L2"
812
  [(set_attr "type"     "darith")
813
  (set_attr "mode"      "DI")
814
  (set_attr "length"    "8")]
815
)
816
 
817
 
818
(define_split
819
  [(set (match_operand:DI 0 "register_operand" "")
820
        (xor:DI (match_operand:DI 1 "register_operand" "")
821
                (match_operand:DI 2 "register_operand" "")))]
822
  "reload_completed
823
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
824
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
825
   && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
826
 
827
  [(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0)
828
                                            (subreg:SI (match_dup 2) 0)))
829
  (set (subreg:SI (match_dup 0) 4) (xor:SI (subreg:SI (match_dup 1) 4)
830
                                           (subreg:SI (match_dup 2) 4)))]
831
  "")
832
 
833
;;----------------------------------------------------------------
834
;; Zero extension
835
;;----------------------------------------------------------------
836
 
837
(define_insn "zero_extendhisi2"
838
  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
839
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))]
840
  ""
841
  "@
842
  andi\t%0,%1,0xffff
843
  lhu%i1\t%0,%1
844
  lhu%i1\t%0,%1"
845
  [(set_attr "type"     "no_delay_arith,load,no_delay_load")
846
  (set_attr "mode"      "SI,SI,SI")
847
  (set_attr "length"    "8,4,8")])
848
 
849
(define_insn "zero_extendqihi2"
850
  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
851
        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]
852
  ""
853
  "@
854
  andi\t%0,%1,0x00ff
855
  lbu%i1\t%0,%1
856
  lbu%i1\t%0,%1"
857
  [(set_attr "type"     "arith,load,no_delay_load")
858
  (set_attr "mode"      "HI")
859
  (set_attr "length"    "4,4,8")])
860
 
861
(define_insn "zero_extendqisi2"
862
  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
863
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]
864
  ""
865
  "@
866
  andi\t%0,%1,0x00ff
867
  lbu%i1\t%0,%1
868
  lbu%i1\t%0,%1"
869
  [(set_attr "type"     "arith,load,no_delay_load")
870
  (set_attr "mode"      "SI,SI,SI")
871
  (set_attr "length"    "4,4,8")])
872
 
873
;;----------------------------------------------------------------
874
;; Sign extension
875
;;----------------------------------------------------------------
876
 
877
;; basic Sign Extend Operations
878
 
879
(define_insn "extendqisi2"
880
  [(set (match_operand:SI 0 "register_operand" "=d")
881
        (sign_extend:SI (match_operand:QI 1 "register_operand" "d")))]
882
  ""
883
  "sext8\t%0,%1"
884
  [(set_attr "type"     "arith")
885
  (set_attr "mode"      "SI")
886
  (set_attr "length"    "4")])
887
 
888
(define_insn "extendhisi2"
889
  [(set (match_operand:SI 0 "register_operand" "=d")
890
        (sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]
891
  ""
892
  "sext16\t%0,%1"
893
  [(set_attr "type"     "arith")
894
  (set_attr "mode"      "SI")
895
  (set_attr "length"    "4")])
896
 
897
;; Those for integer source operand are ordered
898
;; widest source type first.
899
 
900
(define_insn "extendsidi2"
901
  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
902
        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))]
903
  ""
904
  {
905
     if (which_alternative == 0)
906
       output_asm_insn ("addk\t%D0,r0,%1", operands);
907
     else
908
       output_asm_insn ("lw%i1\t%D0,%1", operands);
909
 
910
     output_asm_insn ("add\t%0,%D0,%D0", operands);
911
     output_asm_insn ("addc\t%0,r0,r0", operands);
912
     output_asm_insn ("beqi\t%0,.+8", operands);
913
     return "addi\t%0,r0,0xffffffff";
914
  }
915
  [(set_attr "type"     "multi,multi,multi")
916
  (set_attr "mode"      "DI")
917
  (set_attr "length"    "20,20,20")])
918
 
919
;;----------------------------------------------------------------
920
;; Data movement
921
;;----------------------------------------------------------------
922
 
923
;; 64-bit integer moves
924
 
925
;; Unlike most other insns, the move insns can't be split with
926
;; different predicates, because register spilling and other parts of
927
;; the compiler, have memoized the insn number already.
928
 
929
(define_expand "movdi"
930
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
931
        (match_operand:DI 1 "general_operand" ""))]
932
  ""
933
  {
934
    /* If operands[1] is a constant address illegal for pic, then we need to
935
       handle it just like microblaze_legitimize_address does.  */
936
    if (flag_pic && pic_address_needs_scratch (operands[1]))
937
    {
938
        rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0));
939
        rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
940
        emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2));
941
        DONE;
942
    }
943
 
944
 
945
    if ((reload_in_progress | reload_completed) == 0
946
        && !register_operand (operands[0], DImode)
947
        && !register_operand (operands[1], DImode)
948
        && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
949
               && operands[1] != CONST0_RTX (DImode))))
950
    {
951
 
952
      rtx temp = force_reg (DImode, operands[1]);
953
      emit_move_insn (operands[0], temp);
954
      DONE;
955
    }
956
  }
957
)
958
 
959
 
960
 
961
(define_insn "*movdi_internal"
962
  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
963
        (match_operand:DI 1 "general_operand"      " d,i,J,R,m,d,d"))]
964
  ""
965
  {
966
    switch (which_alternative)
967
    {
968
      case 0:
969
        return "addk\t%0,%1\n\taddk\t%D0,%d1";
970
      case 1:
971
        return "addik\t%0,r0,%h1\n\taddik\t%D0,r0,%j1 #li => la";
972
      case 2:
973
          return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
974
      case 3:
975
      case 4:
976
        if (reg_mentioned_p (operands[0], operands[1]))
977
          return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
978
        else
979
          return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
980
      case 5:
981
      case 6:
982
        return "swi\t%1,%0\n\tswi\t%D1,%o0";
983
    }
984
    return "unreachable";
985
  }
986
  [(set_attr "type"     "no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store")
987
  (set_attr "mode"      "DI")
988
  (set_attr "length"   "8,8,8,8,12,8,12")])
989
 
990
(define_split
991
  [(set (match_operand:DI 0 "register_operand" "")
992
        (match_operand:DI 1 "register_operand" ""))]
993
  "reload_completed
994
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
995
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
996
   && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))"
997
 
998
  [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
999
  (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
1000
  "")
1001
 
1002
(define_split
1003
  [(set (match_operand:DI 0 "register_operand" "")
1004
        (match_operand:DI 1 "register_operand" ""))]
1005
  "reload_completed
1006
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1007
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1008
   && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
1009
 
1010
  [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
1011
  (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
1012
  "")
1013
 
1014
;; Unlike most other insns, the move insns can't be split with
1015
;; different predicates, because register spilling and other parts of
1016
;; the compiler, have memoized the insn number already.
1017
 
1018
(define_expand "movsi"
1019
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
1020
        (match_operand:SI 1 "general_operand" ""))]
1021
  ""
1022
  {
1023
    if (microblaze_expand_move (SImode, operands)) DONE;
1024
  }
1025
)
1026
 
1027
;; Added for status resgisters
1028
(define_insn "movsi_status"
1029
  [(set (match_operand:SI 0 "register_operand" "=d,d,z")
1030
        (match_operand:SI 1 "register_operand" "z,d,d"))]
1031
  "interrupt_handler"
1032
  "@
1033
        mfs\t%0,%1  #mfs
1034
        addk\t%0,%1,r0 #add movsi
1035
        mts\t%0,%1  #mts"
1036
  [(set_attr "type" "move")
1037
  (set_attr "mode" "SI")
1038
  (set_attr "length" "12")])
1039
 
1040
;; This move will be not be moved to delay slot.
1041
(define_insn "*movsi_internal3"
1042
  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d")
1043
        (match_operand:SI 1 "immediate_operand" "J,I,Mnis"))]
1044
  "(register_operand (operands[0], SImode) &&
1045
           (GET_CODE (operands[1]) == CONST_INT &&
1046
                 (INTVAL (operands[1]) <= 32767 && INTVAL (operands[1]) >= -32768)))"
1047
  "@
1048
   addk\t%0,r0,r0
1049
   addik\t%0,r0,%1\t# %X1
1050
   addik\t%0,r0,%1\t# %X1"
1051
  [(set_attr "type"     "arith,arith,no_delay_arith")
1052
  (set_attr "mode"      "SI")
1053
  (set_attr "length"    "4")])
1054
 
1055
;; This move may be used for PLT label operand
1056
(define_insn "*movsi_internal5_pltop"
1057
  [(set (match_operand:SI 0 "register_operand" "=d,d")
1058
        (match_operand:SI 1 "call_insn_operand" ""))]
1059
  "(register_operand (operands[0], Pmode) &&
1060
           PLT_ADDR_P (operands[1]))"
1061
  {
1062
     gcc_unreachable ();
1063
  }
1064
  [(set_attr "type"     "load")
1065
  (set_attr "mode"      "SI")
1066
  (set_attr "length"    "4")])
1067
 
1068
(define_insn "*movsi_internal2"
1069
  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,   d,d,R, T")
1070
        (match_operand:SI 1 "move_operand"         " d,I,Mnis,R,m,dJ,dJ"))]
1071
  "(register_operand (operands[0], SImode)
1072
    || register_operand (operands[1], SImode)
1073
    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))
1074
    && (flag_pic != 2 || (GET_CODE (operands[1]) != SYMBOL_REF
1075
                         && GET_CODE (operands[1]) != LABEL_REF))"
1076
  "@
1077
   addk\t%0,%1,r0
1078
   addik\t%0,r0,%1\t# %X1
1079
   addik\t%0,%a1
1080
   lw%i1\t%0,%1
1081
   lw%i1\t%0,%1
1082
   sw%i0\t%z1,%0
1083
   sw%i0\t%z1,%0"
1084
  [(set_attr "type"     "load,load,no_delay_load,load,no_delay_load,store,no_delay_store")
1085
  (set_attr "mode"      "SI")
1086
  (set_attr "length"    "4,4,8,4,8,4,8")])
1087
 
1088
 
1089
;; 16-bit Integer moves
1090
 
1091
;; Unlike most other insns, the move insns can't be split with
1092
;; different predicates, because register spilling and other parts of
1093
;; the compiler, have memoized the insn number already.
1094
;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
1095
 
1096
(define_expand "movhi"
1097
  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1098
        (match_operand:HI 1 "general_operand" ""))]
1099
  ""
1100
  {
1101
    if ((reload_in_progress | reload_completed) == 0
1102
        && !register_operand (operands[0], HImode)
1103
        && !register_operand (operands[1], HImode)
1104
        && ((GET_CODE (operands[1]) != CONST_INT
1105
            || INTVAL (operands[1]) != 0)))
1106
    {
1107
        rtx temp = force_reg (HImode, operands[1]);
1108
        emit_move_insn (operands[0], temp);
1109
        DONE;
1110
    }
1111
  }
1112
)
1113
 
1114
(define_insn "*movhi_internal2"
1115
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m")
1116
        (match_operand:HI 1 "general_operand"       "I,d,R,m,dJ,dJ"))]
1117
  ""
1118
  "@
1119
   addik\t%0,r0,%1\t# %X1
1120
   addk\t%0,%1,r0
1121
   lhui\t%0,%1
1122
   lhui\t%0,%1
1123
   sh%i0\t%z1,%0
1124
   sh%i0\t%z1,%0"
1125
  [(set_attr "type"     "arith,move,load,no_delay_load,store,no_delay_store")
1126
  (set_attr "mode"      "HI")
1127
  (set_attr "length"    "4,4,4,8,8,8")])
1128
 
1129
;; 8-bit Integer moves
1130
 
1131
;; Unlike most other insns, the move insns can't be split with
1132
;; different predicates, because register spilling and other parts of
1133
;; the compiler, have memoized the insn number already.
1134
;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
1135
 
1136
(define_expand "movqi"
1137
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1138
        (match_operand:QI 1 "general_operand" ""))]
1139
  ""
1140
  {
1141
    if ((reload_in_progress | reload_completed) == 0
1142
        && !register_operand (operands[0], QImode)
1143
        && !register_operand (operands[1], QImode)
1144
        && ((GET_CODE (operands[1]) != CONST_INT
1145
            || INTVAL (operands[1]) != 0)))
1146
    {
1147
        rtx temp = force_reg (QImode, operands[1]);
1148
        emit_move_insn (operands[0], temp);
1149
        DONE;
1150
    }
1151
  }
1152
)
1153
 
1154
(define_insn "*movqi_internal2"
1155
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
1156
        (match_operand:QI 1 "general_operand"       "J,I,d,R,m,dJ,dJ"))]
1157
  ""
1158
  "@
1159
   addk\t%0,r0,%z1
1160
   addik\t%0,r0,%1\t# %X1
1161
   addk\t%0,%1,r0
1162
   lbu%i1\t%0,%1
1163
   lbu%i1\t%0,%1
1164
   sb%i0\t%z1,%0
1165
   sbi\t%z1,%0"
1166
  [(set_attr "type"     "arith,arith,move,load,no_delay_load,store,no_delay_store")
1167
  (set_attr "mode"      "QI")
1168
  (set_attr "length"    "4,4,8,4,8,4,8")])
1169
 
1170
;; Block moves, see microblaze.c for more details.
1171
;; Argument 0 is the destination
1172
;; Argument 1 is the source
1173
;; Argument 2 is the length
1174
;; Argument 3 is the alignment
1175
 
1176
(define_expand "movmemsi"
1177
  [(parallel [(set (match_operand:BLK 0 "general_operand")
1178
                   (match_operand:BLK 1 "general_operand"))
1179
              (use (match_operand:SI 2 ""))
1180
              (use (match_operand:SI 3 "const_int_operand"))])]
1181
  ""
1182
  {
1183
    if (microblaze_expand_block_move (operands[0], operands[1],
1184
                                      operands[2], operands[3]))
1185
        DONE;
1186
    else
1187
        FAIL;
1188
  }
1189
)
1190
 
1191
;; 32-bit floating point moves
1192
 
1193
(define_expand "movsf"
1194
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
1195
        (match_operand:SF 1 "general_operand" ""))]
1196
  ""
1197
  {
1198
    if ((reload_in_progress | reload_completed) == 0
1199
        && !register_operand (operands[0], SFmode)
1200
        && !register_operand (operands[1], SFmode)
1201
        && ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
1202
                 && operands[1] != CONST0_RTX (SFmode))))
1203
    {
1204
        rtx temp = force_reg (SFmode, operands[1]);
1205
        emit_move_insn (operands[0], temp);
1206
        DONE;
1207
    }
1208
  }
1209
)
1210
 
1211
;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
1212
;;
1213
(define_insn "*movsf_internal"
1214
  [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
1215
        (match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))]
1216
  "(register_operand (operands[0], SFmode)
1217
       || register_operand (operands[1], SFmode)
1218
       || operands[1] == CONST0_RTX (SFmode))"
1219
  "@
1220
   addk\t%0,r0,r0
1221
   addk\t%0,%1,r0
1222
   lw%i1\t%0,%1
1223
   addik\t%0,r0,%F1
1224
   lw%i1\t%0,%1
1225
   sw%i0\t%z1,%0
1226
   swi\t%z1,%0"
1227
  [(set_attr "type"     "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store")
1228
  (set_attr "mode"      "SF")
1229
  (set_attr "length"    "4,4,4,4,4,4,4")])
1230
 
1231
;; 64-bit floating point moves
1232
(define_expand "movdf"
1233
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
1234
        (match_operand:DF 1 "general_operand" ""))]
1235
  ""
1236
  {
1237
    if (flag_pic == 2) {
1238
      if (GET_CODE (operands[1]) == MEM
1239
          && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0))
1240
      {
1241
        rtx ptr_reg;
1242
        rtx result;
1243
        ptr_reg = force_reg (Pmode, XEXP (operands[1],0));
1244
        result = gen_rtx_MEM (DFmode, ptr_reg);
1245
        emit_move_insn (operands[0], result);
1246
        DONE;
1247
      }
1248
    }
1249
    if ((reload_in_progress | reload_completed) == 0
1250
        && !register_operand (operands[0], DFmode)
1251
        && !register_operand (operands[1], DFmode)
1252
        && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
1253
                 && operands[1] != CONST0_RTX (DFmode))))
1254
    {
1255
        rtx temp = force_reg (DFmode, operands[1]);
1256
        emit_move_insn (operands[0], temp);
1257
        DONE;
1258
    }
1259
  }
1260
)
1261
 
1262
;; movdf_internal
1263
;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
1264
;;
1265
(define_insn "*movdf_internal"
1266
  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,To")
1267
        (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
1268
  ""
1269
  {
1270
    switch (which_alternative)
1271
    {
1272
      case 0:
1273
        return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
1274
      case 1:
1275
      case 3:
1276
        if (reg_mentioned_p (operands[0], operands[1]))
1277
          return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
1278
        else
1279
          return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
1280
      case 2:
1281
      {
1282
        return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo";
1283
      }
1284
      case 4:
1285
        return "swi\t%1,%0\n\tswi\t%D1,%o0";
1286
    }
1287
    gcc_unreachable ();
1288
  }
1289
  [(set_attr "type"     "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store")
1290
  (set_attr "mode"      "DF")
1291
  (set_attr "length"    "4,8,8,16,8")])
1292
 
1293
(define_split
1294
  [(set (match_operand:DF 0 "register_operand" "")
1295
        (match_operand:DF 1 "register_operand" ""))]
1296
  "reload_completed
1297
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1298
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1299
   && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))"
1300
  [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
1301
  (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
1302
  "")
1303
 
1304
(define_split
1305
  [(set (match_operand:DF 0 "register_operand" "")
1306
        (match_operand:DF 1 "register_operand" ""))]
1307
  "reload_completed
1308
   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1309
   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1310
   && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
1311
  [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
1312
  (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
1313
  "")
1314
 
1315
;;----------------------------------------------------------------
1316
;; Shifts
1317
;;----------------------------------------------------------------
1318
 
1319
;;----------------------------------------------------------------
1320
;; 32-bit left shifts
1321
;;----------------------------------------------------------------
1322
(define_expand "ashlsi3"
1323
  [(set (match_operand:SI 0 "register_operand" "=&d")
1324
        (ashift:SI (match_operand:SI 1 "register_operand" "d")
1325
                   (match_operand:SI 2 "arith_operand" "")))]
1326
  ""
1327
  {
1328
    /* Avoid recursion for trivial cases. */
1329
    if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1330
      if (microblaze_expand_shift (operands))
1331
        DONE;
1332
  }
1333
)
1334
 
1335
;; Irrespective of if we have a barrel-shifter or not, we want to match
1336
;; shifts by 1 with a special pattern. When a barrel shifter is present,
1337
;; saves a cycle. If not, allows us to annotate the instruction for delay
1338
;; slot optimization
1339
(define_insn "*ashlsi3_byone"
1340
  [(set (match_operand:SI 0 "register_operand" "=d")
1341
        (ashift:SI (match_operand:SI 1 "register_operand" "d")
1342
                   (match_operand:SI 2 "arith_operand"    "I")))]
1343
  "(INTVAL (operands[2]) == 1)"
1344
  "addk\t%0,%1,%1"
1345
  [(set_attr "type"     "arith")
1346
   (set_attr "mode"     "SI")
1347
   (set_attr "length"   "4")]
1348
)
1349
 
1350
;; Barrel shift left
1351
(define_insn "ashlsi3_bshift"
1352
  [(set (match_operand:SI 0 "register_operand" "=d,d")
1353
        (ashift:SI (match_operand:SI 1 "register_operand" "d,d")
1354
                   (match_operand:SI 2 "arith_operand"    "I,d")))]
1355
  "TARGET_BARREL_SHIFT"
1356
  "@
1357
  bslli\t%0,%1,%2
1358
  bsll\t%0,%1,%2"
1359
  [(set_attr "type"     "bshift,bshift")
1360
  (set_attr "mode"      "SI,SI")
1361
  (set_attr "length"    "4,4")]
1362
)
1363
 
1364
;; The following patterns apply when there is no barrel shifter present
1365
 
1366
(define_insn "*ashlsi3_with_mul_delay"
1367
  [(set (match_operand:SI 0 "register_operand" "=d")
1368
        (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1369
                   (match_operand:SI 2 "immediate_operand" "I")))]
1370
  "!TARGET_SOFT_MUL
1371
   && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)"
1372
  "muli\t%0,%1,%m2"
1373
  ;; This MUL will not generate an imm. Can go into a delay slot.
1374
  [(set_attr "type"     "arith")
1375
   (set_attr "mode"     "SI")
1376
   (set_attr "length"   "4")]
1377
)
1378
 
1379
(define_insn "*ashlsi3_with_mul_nodelay"
1380
  [(set (match_operand:SI 0 "register_operand" "=d")
1381
        (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1382
                   (match_operand:SI 2 "immediate_operand" "I")))]
1383
  "!TARGET_SOFT_MUL"
1384
  "muli\t%0,%1,%m2"
1385
  ;; This MUL will generate an IMM. Cannot go into a delay slot
1386
  [(set_attr "type"     "no_delay_arith")
1387
   (set_attr "mode"     "SI")
1388
   (set_attr "length"   "8")]
1389
)
1390
 
1391
(define_insn "*ashlsi3_with_size_opt"
1392
  [(set (match_operand:SI 0 "register_operand" "=&d")
1393
       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1394
                   (match_operand:SI 2 "immediate_operand" "I")))]
1395
  "(INTVAL (operands[2]) > 5 && optimize_size)"
1396
  {
1397
    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1398
 
1399
    output_asm_insn ("ori\t%3,r0,%2", operands);
1400
    if (REGNO (operands[0]) != REGNO (operands[1]))
1401
        output_asm_insn ("addk\t%0,%1,r0", operands);
1402
 
1403
    output_asm_insn ("addik\t%3,%3,-1", operands);
1404
    output_asm_insn ("bneid\t%3,.-4", operands);
1405
    return "addk\t%0,%0,%0";
1406
  }
1407
  [(set_attr "type"    "multi")
1408
   (set_attr "mode"    "SI")
1409
   (set_attr "length"  "20")]
1410
)
1411
 
1412
(define_insn "*ashlsi3_with_rotate"
1413
  [(set (match_operand:SI 0 "register_operand" "=&d")
1414
       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1415
                   (match_operand:SI 2 "immediate_operand" "I")))]
1416
  "(INTVAL (operands[2]) > 17 && !optimize_size)"
1417
  {
1418
    int i, nshift;
1419
 
1420
    nshift = INTVAL (operands[2]);
1421
    operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode);
1422
 
1423
    /* We do one extra shift so that the first bit (carry) coming into the MSB
1424
       will be masked out */
1425
    output_asm_insn ("src\t%0,%1", operands);
1426
    for (i = 0; i < (32 - nshift); i++)
1427
       output_asm_insn ("src\t%0,%0", operands);
1428
 
1429
    return "andi\t%0,%0,%3";
1430
  }
1431
  [(set_attr "type"    "multi")
1432
  (set_attr "mode"     "SI")
1433
  (set_attr "length"   "80")]
1434
)
1435
 
1436
(define_insn "*ashlsi_inline"
1437
  [(set (match_operand:SI 0 "register_operand" "=&d")
1438
       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1439
                   (match_operand:SI 2 "immediate_operand" "I")))]
1440
  ""
1441
  {
1442
    int i;
1443
    int nshift = INTVAL (operands[2]);
1444
    if (REGNO (operands[0]) != REGNO (operands[1]))
1445
      output_asm_insn ("addk\t%0,r0,%1", operands);
1446
    output_asm_insn ("addk\t%0,%1,%1", operands);
1447
    for (i = 0; i < (nshift - 2); i++)
1448
      output_asm_insn ("addk\t%0,%0,%0", operands);
1449
    return "addk\t%0,%0,%0";
1450
  }
1451
  [(set_attr "type"    "multi")
1452
  (set_attr "mode"     "SI")
1453
  (set_attr "length"   "124")]
1454
)
1455
 
1456
(define_insn "*ashlsi_reg"
1457
  [(set (match_operand:SI 0 "register_operand" "=&d")
1458
       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1459
                   (match_operand:SI 2 "register_operand" "d")))]
1460
  ""
1461
  {
1462
    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1463
    output_asm_insn ("andi\t%3,%2,31", operands);
1464
    if (REGNO (operands[0]) != REGNO (operands[1]))
1465
      output_asm_insn ("addk\t%0,r0,%1", operands);
1466
    /* Exit the loop if zero shift. */
1467
    output_asm_insn ("beqid\t%3,.+20", operands);
1468
    /* Emit the loop.  */
1469
    output_asm_insn ("addk\t%0,%0,r0", operands);
1470
    output_asm_insn ("addik\t%3,%3,-1", operands);
1471
    output_asm_insn ("bneid\t%3,.-4", operands);
1472
    return "addk\t%0,%0,%0";
1473
  }
1474
  [(set_attr "type"    "multi")
1475
  (set_attr "mode"     "SI")
1476
  (set_attr "length"   "28")]
1477
)
1478
 
1479
 
1480
;;----------------------------------------------------------------
1481
;; 32-bit right shifts
1482
;;----------------------------------------------------------------
1483
(define_expand "ashrsi3"
1484
  [(set (match_operand:SI 0 "register_operand" "=&d")
1485
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1486
                     (match_operand:SI 2 "arith_operand" "")))]
1487
  ""
1488
  {
1489
    /* Avoid recursion for trivial cases. */
1490
    if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1491
      if (microblaze_expand_shift (operands))
1492
        DONE;
1493
  }
1494
)
1495
 
1496
;; Irrespective of if we have a barrel-shifter or not, we want to match
1497
;; shifts by 1 with a special pattern. When a barrel shifter is present,
1498
;; saves a cycle. If not, allows us to annotate the instruction for delay
1499
;; slot optimization
1500
(define_insn "*ashrsi3_byone"
1501
  [(set (match_operand:SI 0 "register_operand" "=d")
1502
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1503
                     (match_operand:SI 2 "arith_operand"    "I")))]
1504
  "(INTVAL (operands[2]) == 1)"
1505
  "sra\t%0,%1"
1506
  [(set_attr "type"     "arith")
1507
   (set_attr "mode"     "SI")
1508
   (set_attr "length"   "4")]
1509
)
1510
 
1511
;; Barrel shift right logical
1512
(define_insn "*ashrsi3_bshift"
1513
  [(set (match_operand:SI 0 "register_operand" "=d,d")
1514
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
1515
                     (match_operand:SI 2 "arith_operand"    "I,d")))]
1516
  "TARGET_BARREL_SHIFT"
1517
  "@
1518
  bsrai\t%0,%1,%2
1519
  bsra\t%0,%1,%2"
1520
  [(set_attr "type"     "bshift,bshift")
1521
  (set_attr "mode"      "SI,SI")
1522
  (set_attr "length"    "4,4")]
1523
)
1524
 
1525
(define_insn "*ashrsi_inline"
1526
  [(set (match_operand:SI 0 "register_operand" "=&d")
1527
       (ashiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1528
                   (match_operand:SI 2 "immediate_operand" "I")))]
1529
  ""
1530
  {
1531
    int i;
1532
    int nshift = INTVAL (operands[2]);
1533
    if (REGNO (operands[0]) != REGNO (operands[1]))
1534
      output_asm_insn ("addk\t%0,r0,%1", operands);
1535
    output_asm_insn ("sra\t%0,%1", operands);
1536
    for (i = 0; i < (nshift - 2); i++)
1537
      output_asm_insn ("sra\t%0,%0", operands);
1538
    return "sra\t%0,%0";
1539
  }
1540
  [(set_attr "type"    "multi")
1541
  (set_attr "mode"     "SI")
1542
  (set_attr "length"   "124")]
1543
)
1544
 
1545
(define_insn "*ashlri_reg"
1546
  [(set (match_operand:SI 0 "register_operand" "=&d")
1547
       (ashiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1548
                   (match_operand:SI 2 "register_operand" "d")))]
1549
  ""
1550
  {
1551
    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1552
    output_asm_insn ("andi\t%3,%2,31", operands);
1553
    if (REGNO (operands[0]) != REGNO (operands[1]))
1554
      output_asm_insn ("addk\t%0,r0,%1", operands);
1555
    /* Exit the loop if zero shift. */
1556
    output_asm_insn ("beqid\t%3,.+20", operands);
1557
    /* Emit the loop.  */
1558
    output_asm_insn ("addk\t%0,%0,r0", operands);
1559
    output_asm_insn ("addik\t%3,%3,-1", operands);
1560
    output_asm_insn ("bneid\t%3,.-4", operands);
1561
    return "sra\t%0,%0";
1562
  }
1563
  [(set_attr "type"    "multi")
1564
  (set_attr "mode"     "SI")
1565
  (set_attr "length"   "28")]
1566
)
1567
 
1568
;;----------------------------------------------------------------
1569
;; 32-bit right shifts (logical)
1570
;;----------------------------------------------------------------
1571
 
1572
(define_expand "lshrsi3"
1573
  [(set (match_operand:SI 0 "register_operand" "=&d")
1574
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1575
                     (match_operand:SI 2 "arith_operand" "")))]
1576
  ""
1577
  {
1578
    /* Avoid recursion for trivial cases. */
1579
    if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1580
      if (microblaze_expand_shift (operands))
1581
        DONE;
1582
  }
1583
)
1584
 
1585
;; Irrespective of if we have a barrel-shifter or not, we want to match
1586
;; shifts by 1 with a special pattern. When a barrel shifter is present,
1587
;; saves a cycle. If not, allows us to annotate the instruction for delay
1588
;; slot optimization
1589
(define_insn "*lshrsi3_byone"
1590
  [(set (match_operand:SI 0 "register_operand" "=d")
1591
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1592
                     (match_operand:SI 2 "arith_operand"    "I")))]
1593
  "(INTVAL (operands[2]) == 1)"
1594
  "srl\t%0,%1"
1595
  [(set_attr "type"     "arith")
1596
   (set_attr "mode"     "SI")
1597
   (set_attr "length"   "4")]
1598
)
1599
 
1600
;; Barrel shift right logical
1601
(define_insn "*lshrsi3_bshift"
1602
  [(set (match_operand:SI 0 "register_operand" "=d,d")
1603
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
1604
                     (match_operand:SI 2 "arith_operand"    "I,d")))]
1605
  "TARGET_BARREL_SHIFT"
1606
  "@
1607
  bsrli\t%0,%1,%2
1608
  bsrl\t%0,%1,%2"
1609
  [(set_attr "type"     "bshift,bshift")
1610
  (set_attr "mode"      "SI,SI")
1611
  (set_attr "length"    "4,4")]
1612
)
1613
 
1614
(define_insn "*lshrsi_inline"
1615
  [(set (match_operand:SI 0 "register_operand" "=&d")
1616
       (lshiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1617
                   (match_operand:SI 2 "immediate_operand" "I")))]
1618
  ""
1619
  {
1620
    int i;
1621
    int nshift = INTVAL (operands[2]);
1622
    if (REGNO (operands[0]) != REGNO (operands[1]))
1623
      output_asm_insn ("addk\t%0,r0,%1", operands);
1624
    output_asm_insn ("srl\t%0,%1", operands);
1625
    for (i = 0; i < (nshift - 2); i++)
1626
      output_asm_insn ("srl\t%0,%0", operands);
1627
    return "srl\t%0,%0";
1628
  }
1629
  [(set_attr "type"    "multi")
1630
  (set_attr "mode"     "SI")
1631
  (set_attr "length"   "124")]
1632
)
1633
 
1634
(define_insn "*lshlri_reg"
1635
  [(set (match_operand:SI 0 "register_operand" "=&d")
1636
       (lshiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1637
                   (match_operand:SI 2 "register_operand" "d")))]
1638
  ""
1639
  {
1640
    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1641
    output_asm_insn ("andi\t%3,%2,31", operands);
1642
    if (REGNO (operands[0]) != REGNO (operands[1]))
1643
      output_asm_insn ("addk\t%0,r0,%1", operands);
1644
    /* Exit the loop if zero shift. */
1645
    output_asm_insn ("beqid\t%3,.+20", operands);
1646
    /* Emit the loop.  */
1647
    output_asm_insn ("addk\t%0,%0,r0", operands);
1648
    output_asm_insn ("addik\t%3,%3,-1", operands);
1649
    output_asm_insn ("bneid\t%3,.-4", operands);
1650
    return "srl\t%0,%0";
1651
  }
1652
  [(set_attr "type"    "multi")
1653
  (set_attr "mode"     "SI")
1654
  (set_attr "length"   "28")]
1655
)
1656
 
1657
;;----------------------------------------------------------------
1658
;; Setting a register from an integer comparison.
1659
;;----------------------------------------------------------------
1660
(define_expand "cstoresi4"
1661
   [(set (match_operand:SI 0 "register_operand")
1662
        (match_operator:SI 1 "ordered_comparison_operator"
1663
              [(match_operand:SI 2 "register_operand")
1664
               (match_operand:SI 3 "register_operand")]))]
1665
  "TARGET_PATTERN_COMPARE"
1666
  "if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE)
1667
     FAIL;
1668
  "
1669
)
1670
 
1671
(define_insn "seq_internal_pat"
1672
  [(set (match_operand:SI 0 "register_operand" "=d")
1673
        (eq:SI
1674
               (match_operand:SI 1 "register_operand" "d")
1675
               (match_operand:SI 2 "register_operand" "d")))]
1676
  "TARGET_PATTERN_COMPARE"
1677
  "pcmpeq\t%0,%1,%2"
1678
  [(set_attr "type"     "arith")
1679
   (set_attr "mode"     "SI")
1680
   (set_attr "length"   "4")]
1681
)
1682
 
1683
(define_insn "sne_internal_pat"
1684
  [(set (match_operand:SI 0 "register_operand" "=d")
1685
        (ne:SI
1686
               (match_operand:SI 1 "register_operand" "d")
1687
               (match_operand:SI 2 "register_operand" "d")))]
1688
  "TARGET_PATTERN_COMPARE"
1689
  "pcmpne\t%0,%1,%2"
1690
  [(set_attr "type"     "arith")
1691
  (set_attr "mode"      "SI")
1692
  (set_attr "length"    "4")]
1693
)
1694
 
1695
(define_insn "signed_compare"
1696
  [(set (match_operand:SI 0 "register_operand" "=d")
1697
        (unspec
1698
                [(match_operand:SI 1 "register_operand" "d")
1699
                 (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))]
1700
  ""
1701
  "cmp\t%0,%1,%2"
1702
  [(set_attr "type"     "arith")
1703
  (set_attr "mode"      "SI")
1704
  (set_attr "length"    "4")])
1705
 
1706
(define_insn "unsigned_compare"
1707
  [(set (match_operand:SI 0 "register_operand" "=d")
1708
        (unspec
1709
                [(match_operand:SI 1 "register_operand" "d")
1710
                 (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))]
1711
  ""
1712
  "cmpu\t%0,%1,%2"
1713
  [(set_attr "type"     "arith")
1714
  (set_attr "mode"      "SI")
1715
  (set_attr "length"    "4")])
1716
 
1717
;;----------------------------------------------------------------
1718
;; Setting a register from an floating point comparison.
1719
;;----------------------------------------------------------------
1720
(define_insn "cstoresf4"
1721
   [(set (match_operand:SI 0 "register_operand")
1722
        (match_operator:SI 1 "ordered_comparison_operator"
1723
              [(match_operand:SF 2 "register_operand")
1724
               (match_operand:SF 3 "register_operand")]))]
1725
  "TARGET_HARD_FLOAT"
1726
  "fcmp.%C1\t%0,%3,%2"
1727
  [(set_attr "type"     "fcmp")
1728
   (set_attr "mode"      "SF")
1729
   (set_attr "length"    "4")]
1730
)
1731
 
1732
;;----------------------------------------------------------------
1733
;; Conditional branches
1734
;;----------------------------------------------------------------
1735
 
1736
(define_expand "cbranchsi4"
1737
  [(set (pc)
1738
        (if_then_else (match_operator 0 "ordered_comparison_operator"
1739
                       [(match_operand:SI 1 "register_operand")
1740
                        (match_operand:SI 2 "arith_operand")])
1741
                      (label_ref (match_operand 3 ""))
1742
                      (pc)))]
1743
  ""
1744
{
1745
  microblaze_expand_conditional_branch (SImode, operands);
1746
  DONE;
1747
})
1748
 
1749
(define_expand "cbranchsf4"
1750
  [(set (pc)
1751
        (if_then_else (match_operator:SI 0 "ordered_comparison_operator"
1752
                       [(match_operand:SF 1 "register_operand")
1753
                        (match_operand:SF 2 "register_operand")])
1754
                      (label_ref (match_operand 3 ""))
1755
                      (pc)))]
1756
  "TARGET_HARD_FLOAT"
1757
{
1758
  microblaze_expand_conditional_branch_sf (operands);
1759
  DONE;
1760
 
1761
})
1762
 
1763
;; Used to implement comparison instructions
1764
(define_expand "condjump"
1765
  [(set (pc)
1766
        (if_then_else (match_operand 0)
1767
                      (label_ref (match_operand 1))
1768
                      (pc)))])
1769
 
1770
(define_insn "branch_zero"
1771
  [(set (pc)
1772
        (if_then_else (match_operator:SI 0 "ordered_comparison_operator"
1773
                                 [(match_operand:SI 1 "register_operand" "d")
1774
                                  (const_int 0)])
1775
                      (match_operand:SI 2 "pc_or_label_operand" "")
1776
                      (match_operand:SI 3 "pc_or_label_operand" "")))
1777
  ]
1778
  ""
1779
  {
1780
    if (operands[3] == pc_rtx)
1781
      return "b%C0i%?\t%z1,%2";
1782
    else
1783
      return "b%N0i%?\t%z1,%3";
1784
  }
1785
  [(set_attr "type"     "branch")
1786
   (set_attr "mode"     "none")
1787
   (set_attr "length"   "4")]
1788
)
1789
 
1790
;;----------------------------------------------------------------
1791
;; Unconditional branches
1792
;;----------------------------------------------------------------
1793
(define_insn "jump"
1794
  [(set (pc)
1795
        (label_ref (match_operand 0 "" "")))]
1796
  ""
1797
  {
1798
    if (GET_CODE (operands[0]) == REG)
1799
        return "br%?\t%0";
1800
    else
1801
        return "bri%?\t%l0";
1802
  }
1803
  [(set_attr "type"     "jump")
1804
  (set_attr "mode"      "none")
1805
  (set_attr "length"    "4")])
1806
 
1807
(define_expand "indirect_jump"
1808
  [(set (pc) (match_operand 0 "register_operand" "d"))]
1809
  ""
1810
  {
1811
    rtx dest = operands[0];
1812
    if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode)
1813
      operands[0] = copy_to_mode_reg (Pmode, dest);
1814
 
1815
    emit_jump_insn (gen_indirect_jump_internal1 (operands[0]));
1816
    DONE;
1817
  }
1818
)
1819
 
1820
;; Indirect jumps. Jump to register values. Assuming absolute jumps
1821
 
1822
(define_insn "indirect_jump_internal1"
1823
  [(set (pc) (match_operand:SI 0 "register_operand" "d"))]
1824
  ""
1825
  "bra%?\t%0"
1826
  [(set_attr "type"     "jump")
1827
  (set_attr "mode"      "none")
1828
  (set_attr "length"    "4")])
1829
 
1830
(define_expand "tablejump"
1831
  [(set (pc)
1832
        (match_operand 0 "register_operand" "d"))
1833
  (use (label_ref (match_operand 1 "" "")))]
1834
  ""
1835
  {
1836
    gcc_assert (GET_MODE (operands[0]) == Pmode);
1837
 
1838
    if (!flag_pic)
1839
      emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
1840
    else
1841
      emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));
1842
    DONE;
1843
  }
1844
)
1845
 
1846
(define_insn "tablejump_internal1"
1847
  [(set (pc)
1848
        (match_operand:SI 0 "register_operand" "d"))
1849
  (use (label_ref (match_operand 1 "" "")))]
1850
  ""
1851
  "bra%?\t%0 "
1852
  [(set_attr "type"     "jump")
1853
  (set_attr "mode"      "none")
1854
  (set_attr "length"    "4")])
1855
 
1856
(define_expand "tablejump_internal3"
1857
  [(parallel [(set (pc)
1858
                   (plus:SI (match_operand:SI 0 "register_operand" "d")
1859
                            (label_ref:SI (match_operand:SI 1 "" ""))))
1860
             (use (label_ref:SI (match_dup 1)))])]
1861
  ""
1862
  ""
1863
)
1864
 
1865
;; need to change for MicroBlaze PIC
1866
(define_insn ""
1867
 [(set (pc)
1868
        (plus:SI (match_operand:SI 0 "register_operand" "d")
1869
                 (label_ref:SI (match_operand 1 "" ""))))
1870
  (use (label_ref:SI (match_dup 1)))]
1871
 "next_active_insn (insn) != 0
1872
  && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
1873
  && PREV_INSN (next_active_insn (insn)) == operands[1]
1874
  && flag_pic"
1875
  {
1876
    output_asm_insn ("addk\t%0,%0,r20",operands);
1877
    return "bra%?\t%0";
1878
}
1879
 [(set_attr "type"      "jump")
1880
  (set_attr "mode"      "none")
1881
  (set_attr "length"    "4")])
1882
 
1883
(define_expand "tablejump_internal4"
1884
  [(parallel [(set (pc)
1885
                   (plus:DI (match_operand:DI 0 "register_operand" "d")
1886
                            (label_ref:DI (match_operand:SI 1 "" ""))))
1887
             (use (label_ref:DI (match_dup 1)))])]
1888
  ""
1889
  ""
1890
)
1891
 
1892
;;----------------------------------------------------------------
1893
;; Function prologue/epilogue and stack allocation
1894
;;----------------------------------------------------------------
1895
(define_expand "prologue"
1896
  [(const_int 1)]
1897
  ""
1898
  {
1899
      microblaze_expand_prologue ();
1900
      DONE;
1901
  }
1902
)
1903
 
1904
(define_expand "epilogue"
1905
  [(use (const_int 0))]
1906
  ""
1907
  {
1908
      microblaze_expand_epilogue ();
1909
      DONE;
1910
  }
1911
)
1912
 
1913
;; An insn to allocate new stack space for dynamic use (e.g., alloca).
1914
;; We copy the return address, decrement the stack pointer and save the
1915
;; return address again at the new stack top
1916
 
1917
(define_expand "allocate_stack"
1918
  [(set (match_operand 0 "register_operand" "=r")
1919
        (minus (reg 1) (match_operand 1 "register_operand" "")))
1920
   (set (reg 1)
1921
        (minus (reg 1) (match_dup 1)))]
1922
  ""
1923
  {
1924
    rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
1925
    rtx rtmp    = gen_rtx_REG (SImode, R_TMP);
1926
    rtx neg_op0;
1927
 
1928
    emit_move_insn (rtmp, retaddr);
1929
    if (GET_CODE (operands[1]) != CONST_INT)
1930
    {
1931
        neg_op0 = gen_reg_rtx (Pmode);
1932
        emit_insn (gen_negsi2 (neg_op0, operands[1]));
1933
    } else
1934
        neg_op0 = GEN_INT (- INTVAL (operands[1]));
1935
 
1936
    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
1937
    emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp);
1938
    emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1939
    emit_insn (gen_rtx_CLOBBER (SImode, rtmp));
1940
    DONE;
1941
  }
1942
)
1943
 
1944
;; Trivial return.  Make it look like a normal return insn as that
1945
;; allows jump optimizations to work better .
1946
(define_expand "return"
1947
  [(simple_return)]
1948
  "microblaze_can_use_return_insn ()"
1949
  {}
1950
)
1951
 
1952
(define_expand "simple_return"
1953
  [(simple_return)]
1954
  ""
1955
  {}
1956
)
1957
 
1958
(define_insn "*"
1959
  [(any_return)]
1960
  ""
1961
  {
1962
    if (microblaze_is_interrupt_handler ())
1963
        return "rtid\tr14, 0\;%#";
1964
    else
1965
        return "rtsd\tr15, 8\;%#";
1966
  }
1967
  [(set_attr "type"     "jump")
1968
  (set_attr "mode"      "none")
1969
  (set_attr "length"    "4")]
1970
)
1971
 
1972
;; Normal return.
1973
 
1974
(define_insn "_internal"
1975
  [(any_return)
1976
   (use (match_operand:SI 0 "register_operand" ""))]
1977
  ""
1978
  {
1979
    if (microblaze_is_interrupt_handler ())
1980
        return "rtid\tr14,0 \;%#";
1981
    else
1982
        return "rtsd\tr15,8 \;%#";
1983
  }
1984
  [(set_attr "type"     "jump")
1985
  (set_attr "mode"      "none")
1986
  (set_attr "length"    "4")])
1987
 
1988
 
1989
;; Block any insns from across this point
1990
;; Useful to group sequences together.
1991
(define_insn "blockage"
1992
  [(unspec_volatile [(const_int 0)] 0)]
1993
  ""
1994
  ""
1995
  [(set_attr "type"     "unknown")
1996
  (set_attr "mode"      "none")
1997
  (set_attr "length"    "0")])
1998
 
1999
 
2000
;;----------------------------------------------------------------
2001
;; Function calls
2002
;;----------------------------------------------------------------
2003
 
2004
(define_expand "call"
2005
  [(parallel [(call (match_operand 0 "memory_operand" "m")
2006
                    (match_operand 1 "" "i"))
2007
             (clobber (reg:SI R_SR))
2008
             (use (match_operand 2 "" ""))
2009
             (use (match_operand 3 "" ""))])]
2010
  ""
2011
  {
2012
    rtx addr = XEXP (operands[0], 0);
2013
 
2014
    if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF
2015
        && !SYMBOL_REF_LOCAL_P (addr))
2016
      {
2017
        rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2018
        XEXP (operands[0], 0) = temp;
2019
      }
2020
 
2021
    if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
2022
        || !call_insn_operand (addr, VOIDmode))
2023
      XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);
2024
 
2025
    if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC)
2026
      emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1],
2027
                        gen_rtx_REG (SImode,
2028
                                     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2029
                                     pic_offset_table_rtx));
2030
    else
2031
      emit_call_insn (gen_call_internal0 (operands[0], operands[1],
2032
                        gen_rtx_REG (SImode,
2033
                                     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2034
 
2035
        DONE;
2036
  }
2037
)
2038
 
2039
(define_expand "call_internal0"
2040
  [(parallel [(call (match_operand 0 "" "")
2041
                    (match_operand 1 "" ""))
2042
             (clobber (match_operand:SI 2 "" ""))])]
2043
  ""
2044
  {
2045
  }
2046
)
2047
 
2048
(define_expand "call_internal_plt0"
2049
  [(parallel [(call (match_operand 0 "" "")
2050
                    (match_operand 1 "" ""))
2051
             (clobber (match_operand:SI 2 "" ""))
2052
             (use (match_operand:SI 3 "" ""))])]
2053
  ""
2054
  {
2055
  }
2056
)
2057
 
2058
(define_insn "call_internal_plt"
2059
  [(call (mem (match_operand:SI 0 "call_insn_plt_operand" ""))
2060
         (match_operand:SI 1 "" "i"))
2061
  (clobber (reg:SI R_SR))
2062
  (use (reg:SI R_GOT))]
2063
  "flag_pic"
2064
  {
2065
    register rtx target2 = gen_rtx_REG (Pmode,
2066
                              GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2067
    gen_rtx_CLOBBER (VOIDmode, target2);
2068
    return "brlid\tr15,%0\;%#";
2069
  }
2070
  [(set_attr "type"     "call")
2071
  (set_attr "mode"      "none")
2072
  (set_attr "length"    "4")])
2073
 
2074
(define_insn "call_internal1"
2075
  [(call (mem (match_operand:SI 0 "call_insn_operand" "ri"))
2076
         (match_operand:SI 1 "" "i"))
2077
  (clobber (reg:SI R_SR))]
2078
  ""
2079
  {
2080
    register rtx target = operands[0];
2081
    register rtx target2 = gen_rtx_REG (Pmode,
2082
                              GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2083
    if (GET_CODE (target) == SYMBOL_REF) {
2084
        gen_rtx_CLOBBER (VOIDmode, target2);
2085
        return "brlid\tr15,%0\;%#";
2086
    } else if (GET_CODE (target) == CONST_INT)
2087
        return "la\t%@,r0,%0\;brald\tr15,%@\;%#";
2088
    else if (GET_CODE (target) == REG)
2089
        return "brald\tr15,%0\;%#";
2090
    else {
2091
        fprintf (stderr,"Unsupported call insn\n");
2092
        return NULL;
2093
    }
2094
  }
2095
  [(set_attr "type"     "call")
2096
  (set_attr "mode"      "none")
2097
  (set_attr "length"    "4")])
2098
 
2099
;; calls.c now passes a fourth argument, make saber happy
2100
 
2101
(define_expand "call_value"
2102
  [(parallel [(set (match_operand 0 "register_operand" "=d")
2103
                   (call (match_operand 1 "memory_operand" "m")
2104
                         (match_operand 2 "" "i")))
2105
             (clobber (reg:SI R_SR))
2106
             (use (match_operand 3 "" ""))])] ;; next_arg_reg
2107
  ""
2108
  {
2109
    rtx addr = XEXP (operands[1], 0);
2110
 
2111
    if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF
2112
        && !SYMBOL_REF_LOCAL_P (addr))
2113
      {
2114
        rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2115
        XEXP (operands[1], 0) = temp;
2116
      }
2117
 
2118
    if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
2119
        || !call_insn_operand (addr, VOIDmode))
2120
      XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
2121
 
2122
    if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
2123
      emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1],
2124
                        operands[2],
2125
                        gen_rtx_REG (SImode,
2126
                                     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2127
                                     pic_offset_table_rtx));
2128
    else
2129
      emit_call_insn (gen_call_value_internal (operands[0], operands[1],
2130
                        operands[2],
2131
                        gen_rtx_REG (SImode,
2132
                                     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2133
 
2134
    DONE;
2135
  }
2136
)
2137
 
2138
 
2139
(define_expand "call_value_internal"
2140
  [(parallel [(set (match_operand 0 "" "")
2141
                   (call (match_operand 1 "" "")
2142
                         (match_operand 2 "" "")))
2143
             (clobber (match_operand:SI 3 "" ""))
2144
             ])]
2145
  ""
2146
  {}
2147
)
2148
 
2149
(define_expand "call_value_intern_plt0"
2150
  [(parallel[(set (match_operand 0 "" "")
2151
                  (call (match_operand 1 "" "")
2152
                        (match_operand 2 "" "")))
2153
             (clobber (match_operand:SI 3 "" ""))
2154
             (use (match_operand:SI 4 "" ""))])]
2155
  "flag_pic"
2156
  {}
2157
)
2158
 
2159
(define_insn "call_value_intern_plt"
2160
  [(set (match_operand:VOID 0 "register_operand" "=d")
2161
        (call (mem (match_operand:SI 1 "call_insn_plt_operand" ""))
2162
              (match_operand:SI 2 "" "i")))
2163
   (clobber (match_operand:SI 3 "register_operand" "=d"))
2164
   (use (match_operand:SI 4 "register_operand"))]
2165
  "flag_pic"
2166
  {
2167
    register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2168
 
2169
    gen_rtx_CLOBBER (VOIDmode,target2);
2170
    return "brlid\tr15,%1\;%#";
2171
  }
2172
  [(set_attr "type"     "call")
2173
  (set_attr "mode"      "none")
2174
  (set_attr "length"    "4")])
2175
 
2176
(define_insn "call_value_intern"
2177
  [(set (match_operand:VOID 0 "register_operand" "=d")
2178
        (call (mem (match_operand:VOID 1 "call_insn_operand" "ri"))
2179
              (match_operand:SI 2 "" "i")))
2180
   (clobber (match_operand:SI 3 "register_operand" "=d"))]
2181
  ""
2182
  {
2183
    register rtx target = operands[1];
2184
    register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2185
 
2186
    if (GET_CODE (target) == SYMBOL_REF){
2187
        gen_rtx_CLOBBER (VOIDmode,target2);
2188
        return "brlid\tr15,%1\;%#";
2189
    }
2190
    else if (GET_CODE (target) == CONST_INT)
2191
        return "la\t%@,r0,%1\;brald\tr15,%@\;%#";
2192
    else if (GET_CODE (target) == REG)
2193
        return "brald\tr15,%1\;%#";
2194
    else
2195
        return "Unsupported call insn\n";
2196
  }
2197
  [(set_attr "type"     "call")
2198
  (set_attr "mode"      "none")
2199
  (set_attr "length"    "4")])
2200
 
2201
 
2202
;; Call subroutine returning any type.
2203
(define_expand "untyped_call"
2204
  [(parallel [(call (match_operand 0 "" "")
2205
                    (const_int 0))
2206
             (match_operand 1 "" "")
2207
             (match_operand 2 "" "")])]
2208
  ""
2209
  {
2210
    if (operands[0])            /* silence statement not reached warnings */
2211
    {
2212
        int i;
2213
 
2214
        emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2215
 
2216
        for (i = 0; i < XVECLEN (operands[2], 0); i++)
2217
        {
2218
            rtx set = XVECEXP (operands[2], 0, i);
2219
            emit_move_insn (SET_DEST (set), SET_SRC (set));
2220
        }
2221
 
2222
        emit_insn (gen_blockage ());
2223
        DONE;
2224
      }
2225
  }
2226
)
2227
 
2228
;;----------------------------------------------------------------
2229
;; Misc.
2230
;;----------------------------------------------------------------
2231
 
2232
(define_insn "nop"
2233
  [(const_int 0)]
2234
  ""
2235
  "nop"
2236
  [(set_attr "type"     "nop")
2237
  (set_attr "mode"      "none")
2238
  (set_attr "length"    "4")])
2239
 
2240
;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference
2241
;; between "mfs" and "addik" instructions.
2242
(define_insn "set_got"
2243
  [(set (match_operand:SI 0 "register_operand" "=r")
2244
    (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))]
2245
  ""
2246
  "mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8"
2247
  [(set_attr "type" "multi")
2248
   (set_attr "length" "12")])
2249
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.