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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [avr/] [avr-dimode.md] - Blame information for rev 713

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

Line No. Rev Author Line
1 709 jeremybenn
;;   Machine description for GNU compiler,
2
;;   for Atmel AVR micro controllers.
3
;;   Copyright (C) 1998 - 2011
4
;;   Free Software Foundation, Inc.
5
;;   Contributed by Georg Lay (avr@gjlay.de)
6
;;
7
;; This file is part of GCC.
8
;;
9
;; GCC is free software; you can redistribute it and/or modify
10
;; it under the terms of the GNU General Public License as published by
11
;; the Free Software Foundation; either version 3, or (at your option)
12
;; any later version.
13
;;
14
;; GCC is distributed in the hope that it will be useful,
15
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
;; GNU General Public License for more details.
18
;;
19
;; You should have received a copy of the GNU General Public License
20
;; along with GCC; see the file COPYING3.  If not see
21
;; .
22
 
23
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24
 
25
;; The purpose of this file is to provide a light-weight DImode
26
;; implementation for AVR.  The trouble with DImode is that tree -> RTL
27
;; lowering leads to really unpleasant code for operations that don't
28
;; work byte-wise like NEG, PLUS, MINUS, etc.  Defining optabs entries for
29
;; them won't help because the optab machinery assumes these operations
30
;; are cheap and does not check if a libgcc implementation is available.
31
;;
32
;; The DImode insns are all straight forward -- except movdi.  The approach
33
;; of this implementation is to provide DImode insns without the burden of
34
;; introducing movdi.
35
;;
36
;; The caveat is that if there are insns for some mode, there must also be a
37
;; respective move insn that describes reloads.  Therefore, this
38
;; implementation uses an accumulator-based model with two hard-coded,
39
;; accumulator-like registers
40
;;
41
;;    A[] = reg:DI 18
42
;;    B[] = reg:DI 10
43
;;
44
;; so that no DImode insn contains pseudos or needs reloading.
45
 
46
(define_constants
47
  [(ACC_A       18)
48
   (ACC_B       10)])
49
 
50
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
51
;; Addition
52
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
53
 
54
(define_expand "adddi3"
55
  [(parallel [(match_operand:DI 0 "general_operand" "")
56
              (match_operand:DI 1 "general_operand" "")
57
              (match_operand:DI 2 "general_operand" "")])]
58
  "avr_have_dimode"
59
  {
60
    rtx acc_a = gen_rtx_REG (DImode, ACC_A);
61
 
62
    emit_move_insn (acc_a, operands[1]);
63
 
64
    if (s8_operand (operands[2], VOIDmode))
65
      {
66
        emit_move_insn (gen_rtx_REG (QImode, REG_X), operands[2]);
67
        emit_insn (gen_adddi3_const8_insn ());
68
      }
69
    else if (CONST_INT_P (operands[2])
70
             || CONST_DOUBLE_P (operands[2]))
71
      {
72
        emit_insn (gen_adddi3_const_insn (operands[2]));
73
      }
74
    else
75
      {
76
        emit_move_insn (gen_rtx_REG (DImode, ACC_B), operands[2]);
77
        emit_insn (gen_adddi3_insn ());
78
      }
79
 
80
    emit_move_insn (operands[0], acc_a);
81
    DONE;
82
  })
83
 
84
(define_insn "adddi3_insn"
85
  [(set (reg:DI ACC_A)
86
        (plus:DI (reg:DI ACC_A)
87
                 (reg:DI ACC_B)))]
88
  "avr_have_dimode"
89
  "%~call __adddi3"
90
  [(set_attr "adjust_len" "call")
91
   (set_attr "cc" "clobber")])
92
 
93
(define_insn "adddi3_const8_insn"
94
  [(set (reg:DI ACC_A)
95
        (plus:DI (reg:DI ACC_A)
96
                 (sign_extend:DI (reg:QI REG_X))))]
97
  "avr_have_dimode"
98
  "%~call __adddi3_s8"
99
  [(set_attr "adjust_len" "call")
100
   (set_attr "cc" "clobber")])
101
 
102
(define_insn "adddi3_const_insn"
103
  [(set (reg:DI ACC_A)
104
        (plus:DI (reg:DI ACC_A)
105
                 (match_operand:DI 0 "const_double_operand" "n")))]
106
  "avr_have_dimode
107
   && !s8_operand (operands[0], VOIDmode)"
108
  {
109
    return avr_out_plus64 (operands[0], NULL);
110
  }
111
  [(set_attr "adjust_len" "plus64")
112
   (set_attr "cc" "clobber")])
113
 
114
 
115
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
116
;; Subtraction
117
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
118
 
119
(define_expand "subdi3"
120
  [(parallel [(match_operand:DI 0 "general_operand" "")
121
              (match_operand:DI 1 "general_operand" "")
122
              (match_operand:DI 2 "general_operand" "")])]
123
  "avr_have_dimode"
124
  {
125
    rtx acc_a = gen_rtx_REG (DImode, ACC_A);
126
 
127
    emit_move_insn (acc_a, operands[1]);
128
    emit_move_insn (gen_rtx_REG (DImode, ACC_B), operands[2]);
129
    emit_insn (gen_subdi3_insn ());
130
    emit_move_insn (operands[0], acc_a);
131
    DONE;
132
  })
133
 
134
(define_insn "subdi3_insn"
135
  [(set (reg:DI ACC_A)
136
        (minus:DI (reg:DI ACC_A)
137
                  (reg:DI ACC_B)))]
138
  "avr_have_dimode"
139
  "%~call __subdi3"
140
  [(set_attr "adjust_len" "call")
141
   (set_attr "cc" "set_czn")])
142
 
143
 
144
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
145
;; Negation
146
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147
 
148
(define_expand "negdi2"
149
  [(parallel [(match_operand:DI 0 "general_operand" "")
150
              (match_operand:DI 1 "general_operand" "")])]
151
  "avr_have_dimode"
152
  {
153
    rtx acc_a = gen_rtx_REG (DImode, ACC_A);
154
 
155
    emit_move_insn (acc_a, operands[1]);
156
    emit_insn (gen_negdi2_insn ());
157
    emit_move_insn (operands[0], acc_a);
158
    DONE;
159
  })
160
 
161
(define_insn "negdi2_insn"
162
  [(set (reg:DI ACC_A)
163
        (neg:DI (reg:DI ACC_A)))]
164
  "avr_have_dimode"
165
  "%~call __negdi2"
166
  [(set_attr "adjust_len" "call")
167
   (set_attr "cc" "clobber")])
168
 
169
 
170
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
171
;; Comparison
172
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
173
 
174
(define_expand "conditional_jump"
175
  [(set (pc)
176
        (if_then_else
177
         (match_operator 0 "ordered_comparison_operator" [(cc0)
178
                                                          (const_int 0)])
179
         (label_ref (match_operand 1 "" ""))
180
         (pc)))]
181
  "avr_have_dimode")
182
 
183
(define_expand "cbranchdi4"
184
  [(parallel [(match_operand:DI 1 "register_operand" "")
185
              (match_operand:DI 2 "nonmemory_operand" "")
186
              (match_operator 0 "ordered_comparison_operator" [(cc0)
187
                                                               (const_int 0)])
188
              (label_ref (match_operand 3 "" ""))])]
189
  "avr_have_dimode"
190
  {
191
    rtx acc_a = gen_rtx_REG (DImode, ACC_A);
192
 
193
    emit_move_insn (acc_a, operands[1]);
194
 
195
    if (s8_operand (operands[2], VOIDmode))
196
      {
197
        emit_move_insn (gen_rtx_REG (QImode, REG_X), operands[2]);
198
        emit_insn (gen_compare_const8_di2 ());
199
      }
200
    else if (CONST_INT_P (operands[2])
201
             || CONST_DOUBLE_P (operands[2]))
202
      {
203
        emit_insn (gen_compare_const_di2 (operands[2]));
204
      }
205
    else
206
      {
207
        emit_move_insn (gen_rtx_REG (DImode, ACC_B), operands[2]);
208
        emit_insn (gen_compare_di2 ());
209
      }
210
 
211
    emit_jump_insn (gen_conditional_jump (operands[0], operands[3]));
212
    DONE;
213
  })
214
 
215
(define_insn "compare_di2"
216
  [(set (cc0)
217
        (compare (reg:DI ACC_A)
218
                 (reg:DI ACC_B)))]
219
  "avr_have_dimode"
220
  "%~call __cmpdi2"
221
  [(set_attr "adjust_len" "call")
222
   (set_attr "cc" "compare")])
223
 
224
(define_insn "compare_const8_di2"
225
  [(set (cc0)
226
        (compare (reg:DI ACC_A)
227
                 (sign_extend:DI (reg:QI REG_X))))]
228
  "avr_have_dimode"
229
  "%~call __cmpdi2_s8"
230
  [(set_attr "adjust_len" "call")
231
   (set_attr "cc" "compare")])
232
 
233
(define_insn "compare_const_di2"
234
  [(set (cc0)
235
        (compare (reg:DI ACC_A)
236
                 (match_operand:DI 0 "const_double_operand" "n")))
237
   (clobber (match_scratch:QI 1 "=&d"))]
238
  "avr_have_dimode
239
   && !s8_operand (operands[0], VOIDmode)"
240
  {
241
    return avr_out_compare64 (insn, operands, NULL);
242
  }
243
  [(set_attr "adjust_len" "compare64")
244
   (set_attr "cc" "compare")])
245
 
246
 
247
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
248
;; Shifts and Rotate
249
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
250
 
251
(define_code_iterator di_shifts
252
  [ashift ashiftrt lshiftrt rotate])
253
 
254
;; Shift functions from libgcc are called without defining these insns,
255
;; but with them we can describe their reduced register footprint.
256
 
257
;; "ashldi3"
258
;; "ashrdi3"
259
;; "lshrdi3"
260
;; "rotldi3"
261
(define_expand "di3"
262
  [(parallel [(match_operand:DI 0 "general_operand" "")
263
              (di_shifts:DI (match_operand:DI 1 "general_operand" "")
264
                            (match_operand:QI 2 "general_operand" ""))])]
265
  "avr_have_dimode"
266
  {
267
    rtx acc_a = gen_rtx_REG (DImode, ACC_A);
268
 
269
    emit_move_insn (acc_a, operands[1]);
270
    emit_move_insn (gen_rtx_REG (QImode, 16), operands[2]);
271
    emit_insn (gen_di3_insn ());
272
    emit_move_insn (operands[0], acc_a);
273
    DONE;
274
  })
275
 
276
(define_insn "di3_insn"
277
  [(set (reg:DI ACC_A)
278
        (di_shifts:DI (reg:DI ACC_A)
279
                      (reg:QI 16)))]
280
  "avr_have_dimode"
281
  "%~call __di3"
282
  [(set_attr "adjust_len" "call")
283
   (set_attr "cc" "clobber")])

powered by: WebSVN 2.1.0

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