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

Subversion Repositories openrisc

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;; GCC machine description for CR16.
2
;; Copyright (C) 2012 Free Software Foundation, Inc.
3
;; Contributed by KPIT Cummins Infosystems Limited.
4
 
5
;; This file is part of GCC.
6
 
7
;; GCC is free software; you can redistribute it and/or modify it
8
;; under the terms of the GNU General Public License as published by
9
;; the Free Software Foundation; either version 3, or (at your option)
10
;; any later version.
11
 
12
;; GCC is distributed in the hope that it will be useful, but WITHOUT
13
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
;; License for more details.
16
 
17
;; You should have received a copy of the GNU General Public License
18
;; along with GCC; see the file COPYING3.  If not see
19
;; .
20
 
21
;;  Register numbers
22
(define_constants
23
  [(SP_REGNUM 15); Stack pointer
24
   (RA_REGNUM 14); Return address
25
  ]
26
)
27
 
28
;; Predicates & Constraints
29
(include "predicates.md")
30
(include "constraints.md")
31
 
32
;; UNSPEC usage
33
(define_constants
34
  [(UNSPEC_PIC_ADDR             0)
35
   (UNSPEC_PIC_LOAD_ADDR        1)
36
   (UNSPEC_LIBRARY_OFFSET       2)
37
   (UNSPEC_SH_LIB_PUSH_R12      3)
38
   (UNSPEC_SH_LIB_POP_R12       4)
39
   (UNSPEC_RETURN_ADDR          5)
40
  ]
41
)
42
 
43
;; Attributes
44
(define_attr "length" "" (const_int 2))
45
 
46
(define_asm_attributes
47
  [(set_attr "length" "2")]
48
)
49
 
50
;;  Mode Macro Definitions
51
(define_mode_iterator CR16IM [QI HI SI])
52
(define_mode_iterator LONG   [SI SF])
53
(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
54
(define_mode_iterator DOUBLE [DI DF])
55
(define_mode_iterator SHORT  [QI HI])
56
(define_mode_attr tIsa       [(QI "b") (HI "w") (SI "d") (SF "d")])
57
(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
58
(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
59
(define_mode_attr iF         [(QI "i") (HI "i") (SI "i") (SF "F")])
60
(define_mode_attr iFD        [(DI "i") (DF "F")])
61
(define_mode_attr LL         [(QI "L") (HI "L")])
62
(define_mode_attr shImmBits  [(QI "3") (HI "4") (SI "5")])
63
 
64
; In QI mode we push 2 bytes instead of 1 byte.
65
(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
66
 
67
; tpush will be used to generate the 'number of registers to push' in the
68
; push instruction.
69
(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
70
 
71
;;  Code Macro Definitions
72
(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
73
(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
74
(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
75
(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
76
 
77
(define_code_iterator sz_xtnd    [ sign_extend       zero_extend])
78
(define_code_iterator any_cond   [eq ne gt gtu lt ltu ge geu le leu])
79
(define_code_iterator plusminus  [plus minus])
80
 
81
(define_code_attr plusminus_insn [(plus "add") (minus "sub")])
82
(define_code_attr plusminus_flag [(plus "PLUS") (minus "MINUS")])
83
(define_code_attr comm           [(plus "%") (minus "")])
84
 
85
(define_code_iterator any_logic  [and ior xor])
86
(define_code_attr logic          [(and "and") (ior "or") (xor "xor")])
87
(define_code_attr any_logic_insn [(and "and") (ior "ior") (xor "xor")])
88
(define_code_attr any_logic_flag [(and "AND") (ior "IOR") (xor "XOR")])
89
 
90
(define_mode_iterator QH         [QI HI])
91
(define_mode_attr qh             [(QI "qi") (HI "hi")])
92
(define_mode_attr QHsz           [(QI "2,2,2") (HI "2,2,4")])
93
(define_mode_attr QHsuffix       [(QI "b") (HI "w")])
94
 
95
 
96
;;  Function Prologue and Epilogue
97
(define_expand "prologue"
98
  [(const_int 0)]
99
  ""
100
  {
101
    cr16_expand_prologue ();
102
    DONE;
103
  }
104
)
105
 
106
(define_insn "push_for_prologue"
107
  [(set (reg:SI SP_REGNUM)
108
        (minus:SI (reg:SI SP_REGNUM)
109
                  (match_operand:SI 0 "immediate_operand" "i")))]
110
  "reload_completed"
111
  {
112
    return cr16_prepare_push_pop_string (0);
113
  }
114
  [(set_attr "length" "4")]
115
)
116
 
117
(define_expand "epilogue"
118
  [(return)]
119
  ""
120
  {
121
    cr16_expand_epilogue ();
122
    DONE;
123
  }
124
)
125
 
126
(define_insn "pop_and_popret_return"
127
  [(set (reg:SI SP_REGNUM)
128
        (plus:SI (reg:SI SP_REGNUM)
129
                 (match_operand:SI 0 "immediate_operand" "i")))
130
   (use (reg:SI RA_REGNUM))
131
   (return)]
132
  "reload_completed"
133
  {
134
    return cr16_prepare_push_pop_string (1);
135
  }
136
  [(set_attr "length" "4")]
137
)
138
 
139
(define_insn "popret_RA_return"
140
  [(use (reg:SI RA_REGNUM))
141
   (return)]
142
  "reload_completed"
143
  "popret\tra"
144
  [(set_attr "length" "2")]
145
)
146
 
147
;; Arithmetic Instuction  Patterns
148
 
149
;; Addition-Subtraction "adddi3/subdi3" insns.
150
(define_insn "di3"
151
  [(set (match_operand:DI 0 "register_operand" "=r")
152
        (plusminus:DI (match_operand:DI 1 "register_operand" "0")
153
                      (match_operand:DI 2 "register_operand" "r")))]
154
  ""
155
  {
156
    return cr16_emit_add_sub_di (operands, );
157
  })
158
 
159
(define_insn "addsi3"
160
  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
161
        (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
162
                 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]
163
  ""
164
  "addd\t%2, %0"
165
  [(set_attr "length" "2,2,4,4,6")]
166
)
167
 
168
;; Addition-Subtraction "addhi3/subhi3" insns.
169
(define_insn "hi3"
170
  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
171
        (plusminus:HI (match_operand:HI 1 "register_operand" "0,0,0")
172
                      (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
173
  ""
174
  "w\t%2, %0"
175
  [(set_attr "length" "2,2,4")]
176
)
177
 
178
;; Addition-Subtraction "addqi3/subqi3" insns.
179
(define_insn "qi3"
180
  [(set (match_operand:QI 0 "register_operand" "=c,c")
181
        (plusminus:QI (match_operand:QI 1 "register_operand" "0,0")
182
                      (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
183
  ""
184
  "b\t%2, %0"
185
  [(set_attr "length" "2,2")]
186
)
187
 
188
;;  Subtract Instruction
189
(define_insn "subsi3"
190
  [(set (match_operand:SI 0 "register_operand" "=r,r")
191
        (minus:SI (match_operand:SI 1 "register_operand" "0,0")
192
                  (match_operand:SI 2 "reg_si_int_operand" "r,i")))]
193
  ""
194
  "subd\t%2, %0"
195
  [(set_attr "length" "4,6")]
196
)
197
 
198
;;  Multiply and Accumulate Instructions "smachisi3/umachisi3"
199
(define_insn "maddhisi4"
200
  [(set (match_operand:SI 0 "register_operand" "=r")
201
        (plus:SI
202
        (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r"))
203
                 (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r")))
204
        (match_operand:SI 3 "register_operand" "0")))]
205
  "TARGET_MAC"
206
  "macw\t%1, %2, %0"
207
  [(set_attr "length" "2")]
208
)
209
 
210
;;  Multiply Instructions
211
(define_insn "mulhi3"
212
  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
213
        (mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
214
                 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
215
  ""
216
  "mulw\t%2, %0"
217
  [(set_attr "length" "2,2,4")]
218
)
219
 
220
(define_insn "mulqihi3"
221
  [(set (match_operand:HI 0 "register_operand" "=c")
222
        (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
223
                 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
224
  ""
225
  "mulsb\t%2, %0"
226
  [(set_attr "length" "2")]
227
)
228
 
229
;;  Bit Set/Clear Instructions
230
(define_expand "insv"
231
  [(set (zero_extract (match_operand 0 "memory_operand" "")
232
                      (match_operand 1 "immediate_operand" "")
233
                      (match_operand 2 "immediate_operand" ""))
234
        (match_operand 3 "immediate_operand" ""))]
235
  "TARGET_BIT_OPS"
236
  {
237
    if (INTVAL (operands[1]) != 1)
238
      FAIL;
239
    if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
240
      FAIL;
241
    if (INTVAL (operands[3]) == 1)
242
      {
243
        if (GET_MODE (operands[0]) == QImode)
244
          {
245
            emit_insn (gen_set_bitqi (operands[0], operands[2]));
246
            DONE;
247
          }
248
        else if (GET_MODE (operands[0]) == HImode)
249
          {
250
            emit_insn (gen_set_bithi (operands[0], operands[2]));
251
            DONE;
252
          }
253
      }
254
    if (INTVAL (operands[3]) == 0)
255
      {
256
        if (GET_MODE (operands[0]) == QImode)
257
          {
258
            emit_insn (gen_clr_bitqi (operands[0], operands[2]));
259
            DONE;
260
          }
261
        else if (GET_MODE (operands[0]) == HImode)
262
          {
263
            emit_insn (gen_clr_bithi (operands[0], operands[2]));
264
            DONE;
265
          }
266
      }
267
  }
268
)
269
 
270
(define_insn "set_bit"
271
  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
272
                            (const_int 1)
273
                            (match_operand 1 "immediate_operand" "i"))
274
        (const_int 1))]
275
  "TARGET_BIT_OPS"
276
  "sbit\t%1,%0"
277
  [(set_attr "length" "2")]
278
)
279
 
280
(define_insn "clr_bit"
281
  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
282
                            (const_int 1)
283
                            (match_operand 1 "immediate_operand" "i"))
284
        (const_int 0))]
285
  "TARGET_BIT_OPS"
286
  "cbit\t%1,%0"
287
  [(set_attr "length" "2")]
288
)
289
 
290
(define_insn "set_bit_mem"
291
  [(set (match_operand:SHORT 0 "bit_operand" "=m")
292
        (ior:SHORT (match_dup 0)
293
                   (match_operand:SHORT 1 "one_bit_operand" "i"))
294
  )]
295
  "TARGET_BIT_OPS"
296
  "sbit\t$%s1,%0"
297
  [(set_attr "length" "2")]
298
)
299
 
300
(define_insn "clear_bit_mem"
301
  [(set (match_operand:SHORT 0 "bit_operand" "=m")
302
        (and:SHORT (match_dup 0)
303
                   (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
304
  )]
305
  "TARGET_BIT_OPS"
306
  "cbit\t$%r1,%0"
307
  [(set_attr "length" "2")]
308
)
309
 
310
;;  Logical Instructions - and/ior/xor "anddi3/iordi3/xordi3"
311
(define_insn "di3"
312
  [(set (match_operand:DI 0 "register_operand" "=r")
313
        (any_logic:DI (match_operand:DI 1 "register_operand" "%0")
314
                      (match_operand:DI 2 "register_operand" "r")))]
315
  ""
316
  {
317
    return cr16_emit_logical_di (operands, );
318
  })
319
 
320
; Logical and/ior/xor "andsi3/iorsi3/xorsi3"
321
(define_insn "si3"
322
  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
323
        (any_logic:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
324
                      (match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
325
  ""
326
  "d\t%2, %0"
327
  [(set_attr "length" "2,2,4,6")]
328
)
329
 
330
; Logical and/ior/xor in HImode "andhi3/iorhi3/xorhi3"
331
; Logical and/ior/xor in QImode "andqi3/iorqi3/xorqi3"
332
(define_insn "3"
333
  [(set (match_operand:QH 0 "register_operand" "=c,c,c")
334
        (any_logic:QH (match_operand:QH 1 "register_operand" "%0,0,0")
335
                      (match_operand:QH 2 "reg_hi_int_operand" "c,M,N")))]
336
  ""
337
  "\t%2, %0"
338
  [(set_attr "length" "")]
339
)
340
 
341
;;  Sign and Zero Extend Instructions
342
(define_insn "extendhisi2"
343
  [(set (match_operand:SI 0 "register_operand" "=r")
344
        (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
345
  ""
346
  "movw\t%1, %0"
347
  [(set_attr "length" "4")]
348
)
349
 
350
(define_insn "extendqihi2"
351
  [(set (match_operand:HI 0 "register_operand" "=r")
352
        (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
353
  ""
354
  "movb\t%1, %0"
355
  [(set_attr "length" "4")]
356
)
357
 
358
;;  One's Complement
359
(define_insn "one_cmpldi2"
360
  [(set (match_operand:DI 0 "register_operand" "=r")
361
        (not:DI (match_operand:DI 1 "register_operand" "0")))]
362
  ""
363
  {
364
    rtx xoperand ;
365
    int reg0 = REGNO (operands[0]);
366
 
367
    xoperand = gen_rtx_REG (SImode, reg0 + 2);
368
    output_asm_insn ("xord\t$-1, %0", operands);
369
    output_asm_insn ("xord\t$-1, %0", &xoperand);
370
    return "" ;
371
  }
372
  [(set_attr "length" "12")]
373
)
374
 
375
(define_insn "one_cmpl2"
376
  [(set (match_operand:CR16IM 0 "register_operand" "=r")
377
        (not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
378
  ""
379
  "xor\t$-1, %0"
380
  [(set_attr "length" "2")]
381
)
382
 
383
;;  Arithmetic Left and Right Shift Instructions
384
(define_insn "ashlqi3"
385
  [(set (match_operand:QI 0 "register_operand" "=c,c")
386
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0")
387
                   (match_operand:QI 2 "nonmemory_operand" "c,I")))]
388
  ""
389
  "ashub\t%2, %0"
390
  [(set_attr "length" "2,2")]
391
)
392
 
393
(define_insn "ashlhi3"
394
  [(set (match_operand:HI 0 "register_operand" "=c,c")
395
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
396
                   (match_operand:QI 2 "nonmemory_operand" "c,J")))]
397
  ""
398
  "ashuw\t%2, %0"
399
  [(set_attr "length" "2,2")]
400
)
401
 
402
(define_insn "ashlsi3"
403
  [(set (match_operand:SI 0 "register_operand" "=r,r")
404
        (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
405
                   (match_operand:QI 2 "nonmemory_operand" "r,K")))]
406
  ""
407
  "ashud\t%2, %0"
408
  [(set_attr "length" "2,2")]
409
)
410
 
411
(define_expand "ashr3"
412
  [(set (match_operand:CR16IM 0 "register_operand" "")
413
        (ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
414
                         (match_operand:QI 2 "nonmemory_operand" "")))]
415
  ""
416
  {
417
    if (GET_CODE (operands[2]) == CONST_INT)
418
      {
419
        /* If the constant is not in range, try placing it in a reg */
420
        if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),))
421
        operands[2] = copy_to_mode_reg(QImode, operands[2]);
422
      }
423
 
424
    if (GET_CODE (operands[2]) != CONST_INT)
425
      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
426
  }
427
)
428
 
429
(define_insn "ashrqi3_imm_insn"
430
  [(set (match_operand:QI 0 "register_operand" "=c")
431
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
432
                     (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
433
  ""
434
  "ashub\t$%n2, %0"
435
  [(set_attr "length" "2")]
436
)
437
 
438
(define_insn "ashrhi3_imm_insn"
439
  [(set (match_operand:HI 0 "register_operand" "=c")
440
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
441
                     (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
442
  ""
443
  "ashuw\t$%n2, %0"
444
  [(set_attr "length" "2")]
445
)
446
 
447
(define_insn "ashrsi3_imm_insn"
448
  [(set (match_operand:SI 0 "register_operand" "=r")
449
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
450
                     (match_operand:QI 2 "shift_si_imm_operand" "i")))]
451
  ""
452
  "ashud\t$%n2, %0"
453
  [(set_attr "length" "2")]
454
)
455
 
456
(define_insn "ashrqi3_neg_insn"
457
  [(set (match_operand:QI 0 "register_operand" "=c")
458
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
459
                     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
460
  ""
461
  "ashub\t%2,%0"
462
  [(set_attr "length" "2")]
463
)
464
 
465
(define_insn "ashrhi3_neg_insn"
466
  [(set (match_operand:HI 0 "register_operand" "=c")
467
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
468
                     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
469
  ""
470
  "ashuw\t%2,%0"
471
  [(set_attr "length" "2")]
472
)
473
 
474
(define_insn "ashrdi3_neg_insn"
475
  [(set (match_operand:SI 0 "register_operand" "=r")
476
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
477
                     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
478
  ""
479
  "ashud\t%2,%0"
480
  [(set_attr "length" "2")]
481
)
482
 
483
(define_expand "lshr3"
484
  [(set (match_operand:CR16IM 0 "register_operand" "")
485
        (lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
486
                         (match_operand:QI 2 "reg_or_int_operand" "")))]
487
  ""
488
  {
489
    if (GET_CODE (operands[2]) == CONST_INT)
490
      {
491
        /* If the constant is not in range, try placing it in a reg */
492
        if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),))
493
        operands[2] = copy_to_mode_reg(QImode, operands[2]);
494
      }
495
 
496
        if (GET_CODE (operands[2]) != CONST_INT)
497
        operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
498
   }
499
)
500
 
501
(define_insn "lshrqi3_imm_insn"
502
  [(set (match_operand:QI 0 "register_operand" "=c")
503
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
504
                     (match_operand:QI 2 "shift_qi_operand" "Q")))]
505
  ""
506
  "lshb\t$%n2, %0"
507
  [(set_attr "length" "2")]
508
)
509
 
510
(define_insn "lshrhi3_imm_insn"
511
  [(set (match_operand:HI 0 "register_operand" "=c")
512
        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
513
                     (match_operand:QI 2 "shift_hi_operand" "R")))]
514
  ""
515
  "lshw\t$%n2, %0"
516
  [(set_attr "length" "2")]
517
)
518
 
519
(define_insn "lshrsi3_imm_insn"
520
  [(set (match_operand:SI 0 "register_operand" "=r")
521
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
522
                     (match_operand:QI 2 "shift_si_operand" "S")))]
523
  ""
524
  "lshd\t$%n2, %0"
525
  [(set_attr "length" "2")]
526
)
527
 
528
(define_insn "lshrqi3_neg_insn"
529
  [(set (match_operand:QI 0 "register_operand" "=c")
530
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
531
                     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
532
  ""
533
  "lshb\t%2,%0"
534
  [(set_attr "length" "2")]
535
)
536
 
537
(define_insn "lshrhi3_neg_insn"
538
  [(set (match_operand:HI 0 "register_operand" "=c")
539
        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
540
                     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
541
  ""
542
  "lshw\t%2,%0"
543
  [(set_attr "length" "2")]
544
)
545
 
546
(define_insn "lshrsi3_neg_insn"
547
  [(set (match_operand:SI 0 "register_operand" "=r")
548
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
549
                     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
550
  ""
551
  "lshd\t%2,%0"
552
  [(set_attr "length" "2")]
553
)
554
 
555
;;  Move Instructions
556
 
557
;; Move any non-immediate operand 0 to a general operand 1.
558
;; This applies only before starting the reload process
559
;; Operand 0 is not a register operand of type mode MODE
560
;; If Operand 0 is a push operand of type mode MODE
561
;; then, if Operand 1 is a non-SP register
562
;; then, Operand 1 = copy_to_mode_reg (mode, Operand 1)
563
;; endif
564
;; else
565
;; if Operand 1 is either register or 4-bit immediate constant
566
;; then, Operand 1 = copy_to_mode_reg (mode, Operand 1)
567
;; endif
568
;; endif
569
;;
570
;; What does copy_to_mode_reg (mode, rtx val) do?
571
;; Copy the value into new temp reg and return the reg where the
572
;; mode of the new reg is always mode MODE when value is constant
573
;;
574
;; Why should copy_to_mode_reg be called?
575
;; All sorts of move are nor supported by CR16. Therefore,
576
;; when unsupported move is encountered, the additional instructions
577
;; will be introduced for the purpose.
578
;;
579
;; A new move insn is inserted for Op 1 when one of the following
580
;; conditions is met.
581
;; Case 1:  Op 0 is push_operand
582
;;          Op 1 is SP register
583
;;
584
;; Case 2:  Op 0 is not push_operand
585
;;          Op 1 is neither register nor unsigned 4-bit immediate
586
 
587
(define_expand "mov"
588
  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
589
        (match_operand:ALLMTD 1 "general_operand" ""))]
590
  ""
591
  {
592
    if (!(reload_in_progress || reload_completed))
593
      {
594
        /* Only if Op0 is a register operand.  */
595
        if (!register_operand (operands[0], mode))
596
          {
597
            if (push_operand (operands[0], mode))
598
              {
599
                /* Use copy_to_mode_reg only if the register needs
600
                to be pushed is SP as CR16 does not support pushing SP.  */
601
                if (!nosp_reg_operand (operands[1], mode))
602
                  operands[1] = copy_to_mode_reg (mode, operands[1]);
603
              }
604
            else
605
              {
606
                /* Use copy_to_mode_reg if op1 is not register operand
607
                   subject to conditions inside.  */
608
                if (!register_operand (operands[1], mode))
609
                  {
610
                    /* CR16 does not support moving immediate to SI or SF
611
                       type memory.  */
612
                    if (mode == SImode || mode == SFmode ||
613
                        mode == DImode || mode == DFmode)
614
                      operands[1] = copy_to_mode_reg (mode, operands[1]);
615
                    else
616
                      /* moving imm4 is supported by CR16 instruction.  */
617
                      if (!u4bits_operand (operands[1], mode))
618
                        operands[1] = copy_to_mode_reg (mode, operands[1]);
619
                  }
620
               }
621
          }
622
 
623
          /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
624
          if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
625
            {
626
              operands[1] = legitimize_pic_address (operands[1], mode, 0);
627
            }
628
      }
629
  }
630
)
631
 
632
; ALLMT     : QI,HI,SI,SF
633
; pushCnstr : Push constraints
634
;                QI : X
635
;             HI,SI,SF,DI,DF : <
636
; b         : All non-sp registers
637
; tpush     : Push count
638
;                QI,HI : 1
639
;                SI,SF : 2
640
;                DI,DF : 4
641
(define_insn "push_internal"
642
  [(set (match_operand:ALLMTD 0 "push_operand" "=")
643
        (match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
644
  ""
645
  "push\t$,%p1"
646
  [(set_attr "length" "2")]
647
)
648
 
649
; (DI, DF) move
650
(define_insn "*mov_double"
651
  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
652
        (match_operand:DOUBLE 1 "general_operand" "r, , m, r"))]
653
  "register_operand (operands[0], DImode)
654
   || register_operand (operands[0], DFmode)
655
   || register_operand (operands[1], DImode)
656
   || register_operand (operands[1], DFmode)"
657
  {
658
    if (0 == which_alternative) {
659
      rtx xoperands[2] ;
660
      int reg0 = REGNO (operands[0]);
661
      int reg1 = REGNO (operands[1]);
662
 
663
      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
664
      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
665
      if ((reg1 + 2) != reg0)
666
        {
667
          output_asm_insn ("movd\t%1, %0", operands);
668
          output_asm_insn ("movd\t%1, %0", xoperands);
669
        }
670
      else
671
        {
672
          output_asm_insn ("movd\t%1, %0", xoperands);
673
          output_asm_insn ("movd\t%1, %0", operands);
674
        }}
675
 
676
    else if (1 == which_alternative) {
677
      rtx lo_operands[2] ;
678
      rtx hi_operands[2] ;
679
 
680
      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
681
      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
682
      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
683
                       VOIDmode == GET_MODE (operands[1])
684
                       ? DImode  : GET_MODE (operands[1]), 0);
685
      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
686
                       VOIDmode == GET_MODE (operands[1])
687
                       ? DImode  : GET_MODE (operands[1]), 4);
688
      output_asm_insn ("movd\t%1, %0", lo_operands);
689
      output_asm_insn ("movd\t%1, %0", hi_operands);}
690
 
691
    else if (2 == which_alternative) {
692
      rtx xoperands[2] ;
693
      int reg0 = REGNO (operands[0]), reg1 = -2 ;
694
      rtx addr ;
695
 
696
        if (MEM_P (operands[1]))
697
          addr = XEXP (operands[1], 0);
698
        else
699
          addr = NULL_RTX ;
700
        switch (GET_CODE (addr))
701
          {
702
            case REG:
703
            case SUBREG:
704
              reg1 = REGNO (addr);
705
              break ;
706
            case PLUS:
707
              switch (GET_CODE (XEXP (addr, 0))) {
708
                case REG:
709
                case SUBREG:
710
                  reg1 = REGNO (XEXP (addr, 0));
711
                  break ;
712
                case PLUS:
713
                  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
714
                  break ;
715
                default:
716
                  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
717
                  debug_rtx (addr);
718
                  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
719
                  debug_rtx (operands[1]);
720
                  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
721
                  break ;}
722
              break ;
723
            default:
724
              break ;
725
          }
726
 
727
        xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
728
        xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
729
        gcc_assert ((reg0 + 1) != reg1);
730
        if (reg0 != reg1  &&  (reg1 + 1) != reg0)
731
          {
732
            output_asm_insn ("loadd\t%1, %0", operands);
733
            output_asm_insn ("loadd\t%1, %0", xoperands);
734
          }
735
        else
736
          {
737
            output_asm_insn ("loadd\t%1, %0", xoperands);
738
            output_asm_insn ("loadd\t%1, %0", operands);
739
          }}
740
    else
741
      {
742
        rtx xoperands[2] ;
743
        xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
744
        xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
745
        output_asm_insn ("stord\t%1, %0", operands);
746
        output_asm_insn ("stord\t%1, %0", xoperands);
747
      }
748
    return "" ;
749
  }
750
  [(set_attr "length" "4, , , ")]
751
)
752
 
753
; All long (SI, SF) register move, load and store operations
754
; The print_operand will take care of printing the register pair
755
; when mode is SI/SF and register is in SHORT_REGS
756
(define_insn "*mov_long"
757
  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
758
        (match_operand:LONG 1 "general_operand" "r, , m, r"))]
759
  "register_operand (operands[0], mode)
760
   || register_operand (operands[1], mode)"
761
  "@
762
  mov\t%1, %0
763
  mov\t%1, %0
764
  load\t%1, %0
765
  stor\t%1, %0"
766
  [(set_attr "length" "2,,,")]
767
)
768
 
769
;; All short (QI, HI) register move, load and store operations
770
(define_insn "*mov_short"
771
  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
772
        (match_operand:SHORT 1 "general_operand" "r, , m, r, "))]
773
  "(register_operand (operands[0], mode))
774
    || (store_operand (operands[0], mode)
775
        && (register_operand (operands[1], mode)
776
            || u4bits_operand (operands[1], mode)))"
777
  "@
778
  mov\t%1, %0
779
  mov\t%1, %0
780
  load\t%1, %0
781
  stor\t%1, %0
782
  stor\t%1, %0"
783
  [(set_attr "length" "2,,,,")]
784
)
785
 
786
;;  Compare Instructions
787
; Instruction generated compares the operands in reverse order
788
; Therefore, while printing the asm, the reverse of the
789
; compare condition shall be printed.
790
(define_insn "cbranch4"
791
  [(set (pc)
792
        (if_then_else (match_operator 0 "ordered_comparison_operator"
793
                      [(match_operand:CR16IM 1 "register_operand" "r,r")
794
                       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
795
                       (label_ref (match_operand 3 "" ""))
796
                      (pc)))
797
   (clobber (cc0))]
798
  ""
799
  "cmp\t%2, %1\;b%d0\t%l3"
800
  [(set_attr "length" "6,6")]
801
)
802
 
803
(define_expand "cmp"
804
  [(parallel [(set (cc0)
805
    (compare (match_operand:CR16IM 0 "register_operand" "")
806
             (match_operand:CR16IM 1 "nonmemory_operand" "")))
807
    (clobber (match_scratch:HI 2 "=r"))] ) ]
808
  ""
809
  "")
810
 
811
;;  Scond Instructions
812
(define_expand "cstore4"
813
  [(set (cc0)
814
        (compare (match_operand:CR16IM 2 "register_operand" "")
815
                 (match_operand:CR16IM 3 "nonmemory_operand" "")))
816
   (set (match_operand:HI 0 "register_operand")
817
        (match_operator:HI 1 "ordered_comparison_operator"
818
        [(cc0) (const_int 0)]))]
819
  ""
820
  ""
821
)
822
 
823
(define_insn "*cmp_insn"
824
  [(set (cc0)
825
        (compare (match_operand:CR16IM 0 "register_operand" "r,r")
826
                 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
827
  ""
828
  "cmp\t%1, %0"
829
  [(set_attr "length" "2,4")]
830
)
831
 
832
(define_insn "sCOND_internal"
833
  [(set (match_operand:HI 0 "register_operand" "=r")
834
        (match_operator:HI 1 "ordered_comparison_operator"
835
        [(cc0) (const_int 0)]))]
836
  ""
837
  "s%d1\t%0"
838
  [(set_attr "length" "2")]
839
)
840
 
841
;;  Jumps and Branches
842
(define_insn "indirect_jump_return"
843
  [(set (pc)
844
          (reg:SI RA_REGNUM))
845
   (return)]
846
  "reload_completed"
847
  "jump\t (ra)"
848
  [(set_attr "length" "2")]
849
)
850
 
851
(define_insn "jump_return"
852
  [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
853
   (return)]
854
  "reload_completed"
855
  "jump\t(ra)"
856
  [(set_attr "length" "2")]
857
)
858
 
859
(define_insn "indirect_jump"
860
  [(set (pc)
861
        (match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
862
  ""
863
  "@
864
  jump\t%0
865
  br\t%a0"
866
  [(set_attr "length" "2,6")]
867
)
868
 
869
(define_insn "interrupt_return"
870
  [(unspec_volatile [(const_int 0)] 0)
871
   (return)]
872
  ""
873
  {
874
    return cr16_prepare_push_pop_string (1);
875
  }
876
  [(set_attr "length" "14")]
877
)
878
 
879
(define_insn "jump_to_imm"
880
  [(set (pc)
881
        (match_operand 0 "jump_imm_operand" "i"))]
882
  ""
883
  "br\t%c0"
884
  [(set_attr "length" "6")]
885
)
886
 
887
(define_insn "jump"
888
  [(set (pc)
889
        (label_ref (match_operand 0 "" "")))]
890
  ""
891
  "br\t%l0"
892
  [(set_attr "length" "6")]
893
)
894
 
895
;;  Table Jump
896
(define_insn "tablejump"
897
  [(set (pc)
898
        (match_operand:SI 0 "register_operand" "r"))
899
   (use (label_ref:SI (match_operand 1 "" "")))]
900
  "!flag_pic"
901
  "jump\t%0"
902
  [(set_attr "length" "2")]
903
)
904
 
905
;;  Call Instructions
906
(define_expand "call"
907
  [(call (match_operand:QI 0 "memory_operand" "")
908
         (match_operand 1 "" ""))]
909
  ""
910
  {
911
    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
912
      {
913
        operands[0] = gen_const_mem (QImode,
914
        legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
915
        emit_call_insn (gen_cr16_call (operands[0], operands[1]));
916
      }
917
    else
918
      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
919
      DONE;
920
  }
921
)
922
 
923
(define_expand "cr16_call"
924
  [(parallel
925
    [(call (match_operand:QI 0 "memory_operand" "")
926
           (match_operand 1 "" ""))
927
   (clobber (reg:SI RA_REGNUM))])]
928
  ""
929
  ""
930
)
931
 
932
(define_insn "cr16_call_insn_branch_pic"
933
  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
934
         (match_operand 1 "" ""))
935
   (clobber (match_operand:SI 2 "register_operand" "+r"))]
936
  "flag_pic == FAR_PIC"
937
  {
938
    if (GET_CODE (operands[0]) != CONST_INT)
939
      return "loadd\t%g0, %2 \n\tjal %2";
940
    else
941
      return "jal %2";
942
  }
943
  [(set_attr "length" "8")]
944
)
945
 
946
(define_insn "cr16_call_insn_branch"
947
  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
948
         (match_operand 1 "" ""))
949
   (clobber (match_operand:SI 2 "register_operand" "+r"))]
950
  "flag_pic == 0 || flag_pic == NEAR_PIC"
951
  {
952
    /* Print the immediate address for bal
953
       'b' is used instead of 'a' to avoid compiler calling
954
       the GO_IF_LEGITIMATE_ADDRESS which cannot
955
       perform checks on const_int code addresses as it
956
       assumes all const_int are data addresses.
957
    */
958
    if (GET_CODE (operands[0]) != CONST_INT)
959
      return "bal (ra), %a0";
960
    else
961
      operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
962
      return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";
963
  }
964
  [(set_attr "length" "6")]
965
)
966
 
967
(define_insn "cr16_call_insn_jump"
968
  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
969
         (match_operand 1 "" ""))
970
   (clobber (match_operand:SI 2 "register_operand" "+r"))]
971
  ""
972
  "jal\t%0"
973
  [(set_attr "length" "2")]
974
)
975
 
976
;;  Call Value Instructions
977
 
978
(define_expand "call_value"
979
  [(set (match_operand 0 "general_operand" "")
980
        (call (match_operand:QI 1 "memory_operand" "")
981
              (match_operand 2 "" "")))]
982
  ""
983
  {
984
    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
985
      {
986
        operands[1] = gen_const_mem (QImode,
987
        legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
988
        emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
989
      }
990
    else
991
        emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
992
    DONE;
993
  }
994
)
995
 
996
(define_expand "cr16_call_value"
997
  [(parallel
998
    [(set (match_operand 0 "general_operand" "")
999
          (call (match_operand 1 "memory_operand" "")
1000
                (match_operand 2 "" "")))
1001
     (clobber (reg:SI RA_REGNUM))])]
1002
  ""
1003
  ""
1004
)
1005
 
1006
(define_insn "cr16_call_value_insn_branch_pic"
1007
  [(set (match_operand 0 "" "=g")
1008
        (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
1009
              (match_operand 2 "" "")))
1010
   (clobber (match_operand:SI 3 "register_operand" "+r"))]
1011
  "flag_pic == FAR_PIC"
1012
  {
1013
    if (GET_CODE (operands[1]) != CONST_INT)
1014
      return "loadd\t%g1, %3 \n\tjal %3";
1015
    else
1016
      return "jal %3";
1017
  }
1018
  [(set_attr "length" "8")]
1019
)
1020
 
1021
(define_insn "cr16_call_value_insn_branch"
1022
  [(set (match_operand 0 "" "=g")
1023
        (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
1024
              (match_operand 2 "" "")))
1025
   (clobber (match_operand:SI 3 "register_operand" "+r"))]
1026
  "flag_pic == 0 || flag_pic == NEAR_PIC"
1027
  {
1028
    /* Print the immediate address for bal
1029
       'b' is used instead of 'a' to avoid compiler calling
1030
       the GO_IF_LEGITIMATE_ADDRESS which cannot
1031
       perform checks on const_int code addresses as it
1032
       assumes all const_int are data addresses.
1033
    */
1034
    if (GET_CODE (operands[1]) != CONST_INT)
1035
      return "bal (ra), %a1";
1036
    else
1037
      {
1038
        operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
1039
        return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";
1040
      }
1041
  }
1042
  [(set_attr "length" "6")]
1043
)
1044
 
1045
 
1046
(define_insn "cr16_call_value_insn_jump"
1047
  [(set (match_operand 0 "" "=g")
1048
        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
1049
              (match_operand 2 "" "")))
1050
   (clobber (match_operand:SI 3 "register_operand" "+r"))]
1051
  ""
1052
  "jal\t%1"
1053
  [(set_attr "length" "2")]
1054
)
1055
 
1056
 
1057
;;  Nop
1058
(define_insn "nop"
1059
  [(const_int 0)]
1060
  ""
1061
  "nop\t"
1062
)
1063
 
1064
;; PIC
1065
/* When generating pic, we need to load the symbol offset into a register.
1066
   So that the optimizer does not confuse this with a normal symbol load
1067
   we use an unspec.  The offset will be loaded from a constant pool entry,
1068
   since that is the only type of relocation we can use.  */
1069
 
1070
(define_insn "unspec_bro_addr"
1071
  [(set (match_operand:SI 0 "register_operand" "=r")
1072
        (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
1073
  ""
1074
  "movd \t%f1, %0"
1075
  [(set_attr "length" "4")]
1076
)
1077
 
1078
(define_insn "unspec_got_addr"
1079
  [(set (match_operand:SI 0 "register_operand" "=r")
1080
        (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
1081
  ""
1082
  "loadd \t%g1, %0"
1083
  [(set_attr "length" "6")]
1084
)

powered by: WebSVN 2.1.0

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