111
|
1 ;; GCC machine description for CR16.
|
131
|
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
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 ;; <http://www.gnu.org/licenses/>.
|
|
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 Instruction Patterns
|
|
148
|
|
149 ;; Addition-Subtraction "adddi3/subdi3" insns.
|
|
150 (define_insn "<plusminus_insn>di3"
|
|
151 [(set (match_operand:DI 0 "register_operand" "=r")
|
|
152 (plusminus:DI (match_operand:DI 1 "register_operand" "<comm>0")
|
|
153 (match_operand:DI 2 "register_operand" "r")))]
|
|
154 ""
|
|
155 {
|
|
156 return cr16_emit_add_sub_di (operands, <plusminus_flag>);
|
|
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 "<plusminus_insn>hi3"
|
|
170 [(set (match_operand:HI 0 "register_operand" "=c,c,c")
|
|
171 (plusminus:HI (match_operand:HI 1 "register_operand" "<comm>0,0,0")
|
|
172 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
|
|
173 ""
|
|
174 "<plusminus_insn>w\t%2, %0"
|
|
175 [(set_attr "length" "2,2,4")]
|
|
176 )
|
|
177
|
|
178 ;; Addition-Subtraction "addqi3/subqi3" insns.
|
|
179 (define_insn "<plusminus_insn>qi3"
|
|
180 [(set (match_operand:QI 0 "register_operand" "=c,c")
|
|
181 (plusminus:QI (match_operand:QI 1 "register_operand" "<comm>0,0")
|
|
182 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
|
|
183 ""
|
|
184 "<plusminus_insn>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 "<sPat>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 "mac<sPat>w\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<mode>"
|
|
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<tIsa>\t%1,%0"
|
|
277 [(set_attr "length" "2")]
|
|
278 )
|
|
279
|
|
280 (define_insn "clr_bit<mode>"
|
|
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<tIsa>\t%1,%0"
|
|
287 [(set_attr "length" "2")]
|
|
288 )
|
|
289
|
|
290 (define_insn "set_bit<mode>_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<tIsa>\t$%s1,%0"
|
|
297 [(set_attr "length" "2")]
|
|
298 )
|
|
299
|
|
300 (define_insn "clear_bit<mode>_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<tIsa>\t$%r1,%0"
|
|
307 [(set_attr "length" "2")]
|
|
308 )
|
|
309
|
|
310 ;; Logical Instructions - and/ior/xor "anddi3/iordi3/xordi3"
|
|
311 (define_insn "<any_logic_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, <any_logic_flag>);
|
|
318 })
|
|
319
|
|
320 ; Logical and/ior/xor "andsi3/iorsi3/xorsi3"
|
|
321 (define_insn "<any_logic_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 "<logic>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 "<any_logic_insn><qh>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 "<logic><QHsuffix>\t%2, %0"
|
|
338 [(set_attr "length" "<QHsz>")]
|
|
339 )
|
|
340
|
|
341 ;; Sign and Zero Extend Instructions
|
|
342 (define_insn "<szPat>extendhisi2"
|
|
343 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
344 (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
|
|
345 ""
|
|
346 "mov<szIsa>w\t%1, %0"
|
|
347 [(set_attr "length" "4")]
|
|
348 )
|
|
349
|
|
350 (define_insn "<szPat>extendqihi2"
|
|
351 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
352 (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
|
|
353 ""
|
|
354 "mov<szIsa>b\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_cmpl<mode>2"
|
|
376 [(set (match_operand:CR16IM 0 "register_operand" "=r")
|
|
377 (not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
|
|
378 ""
|
|
379 "xor<tIsa>\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 "ashr<mode>3"
|
|
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]),<shImmBits>))
|
|
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 "lshr<mode>3"
|
|
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]),<shImmBits>))
|
|
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>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>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<mode>"
|
|
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>mode))
|
|
596 {
|
|
597 if (push_operand (operands[0], <MODE>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>mode))
|
|
602 operands[1] = copy_to_mode_reg (<MODE>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>mode))
|
|
609 {
|
|
610 /* CR16 does not support moving immediate to SI or SF
|
|
611 type memory. */
|
|
612 if (<MODE>mode == SImode || <MODE>mode == SFmode ||
|
|
613 <MODE>mode == DImode || <MODE>mode == DFmode)
|
|
614 operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
|
|
615 else
|
|
616 /* moving imm4 is supported by CR16 instruction. */
|
|
617 if (!u4bits_operand (operands[1], <MODE>mode))
|
|
618 operands[1] = copy_to_mode_reg (<MODE>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>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<mode>_internal"
|
|
642 [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
|
|
643 (match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
|
|
644 ""
|
|
645 "push\t$<tpush>,%p1"
|
|
646 [(set_attr "length" "2")]
|
|
647 )
|
|
648
|
|
649 ; (DI, DF) move
|
|
650 (define_insn "*mov<mode>_double"
|
|
651 [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
|
|
652 (match_operand:DOUBLE 1 "general_operand" "r, <iFD>, 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 {
|
131
|
658 if (which_alternative == 0) {
|
|
659 rtx xoperands[2];
|
111
|
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
|
131
|
676 else if (which_alternative == 1) {
|
|
677 rtx lo_operands[2];
|
|
678 rtx hi_operands[2];
|
111
|
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
|
131
|
691 else if (which_alternative == 2) {
|
|
692 rtx xoperands[2];
|
|
693 int reg0 = REGNO (operands[0]), reg1 = -2;
|
|
694 rtx addr;
|
111
|
695
|
|
696 if (MEM_P (operands[1]))
|
|
697 addr = XEXP (operands[1], 0);
|
|
698 else
|
131
|
699 addr = NULL_RTX;
|
111
|
700 switch (GET_CODE (addr))
|
|
701 {
|
|
702 case REG:
|
|
703 case SUBREG:
|
|
704 reg1 = REGNO (addr);
|
131
|
705 break;
|
111
|
706 case PLUS:
|
|
707 switch (GET_CODE (XEXP (addr, 0))) {
|
|
708 case REG:
|
|
709 case SUBREG:
|
|
710 reg1 = REGNO (XEXP (addr, 0));
|
131
|
711 break;
|
111
|
712 case PLUS:
|
|
713 reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
|
131
|
714 break;
|
111
|
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");
|
131
|
721 break;}
|
|
722 break;
|
111
|
723 default:
|
131
|
724 break;
|
111
|
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 {
|
131
|
742 rtx xoperands[2];
|
111
|
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 }
|
131
|
748 return "";
|
111
|
749 }
|
|
750 [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
|
|
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<mode>_long"
|
|
757 [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
|
|
758 (match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
|
|
759 "register_operand (operands[0], <MODE>mode)
|
|
760 || register_operand (operands[1], <MODE>mode)"
|
|
761 "@
|
|
762 mov<tIsa>\t%1, %0
|
|
763 mov<tIsa>\t%1, %0
|
|
764 load<tIsa>\t%1, %0
|
|
765 stor<tIsa>\t%1, %0"
|
|
766 [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
|
|
767 )
|
|
768
|
|
769 ;; All short (QI, HI) register move, load and store operations
|
|
770 (define_insn "*mov<mode>_short"
|
|
771 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
|
|
772 (match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
|
|
773 "(register_operand (operands[0], <MODE>mode))
|
|
774 || (store_operand (operands[0], <MODE>mode)
|
|
775 && (register_operand (operands[1], <MODE>mode)
|
|
776 || u4bits_operand (operands[1], <MODE>mode)))"
|
|
777 "@
|
|
778 mov<tIsa>\t%1, %0
|
|
779 mov<tIsa>\t%1, %0
|
|
780 load<tIsa>\t%1, %0
|
|
781 stor<tIsa>\t%1, %0
|
|
782 stor<tIsa>\t%1, %0"
|
|
783 [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
|
|
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 "cbranch<mode>4"
|
|
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<tIsa>\t%2, %1\;b%d0\t%l3"
|
|
800 [(set_attr "length" "6,6")]
|
|
801 )
|
|
802
|
|
803 (define_expand "cmp<mode>"
|
|
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 "cstore<mode>4"
|
|
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<mode>_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<tIsa>\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 )
|