1 ;; GCC machine description for CR16.
2 ;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
3 ;; Contributed by KPIT Cummins Infosystems Limited.
5 ;; This file is part of GCC.
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)
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.
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/>.
23 [(SP_REGNUM 15); Stack pointer
24 (RA_REGNUM 14); Return address
28 ;; Predicates & Constraints
29 (include "predicates.md")
30 (include "constraints.md")
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)
44 (define_attr "length" "" (const_int 2))
46 (define_asm_attributes
47 [(set_attr "length" "2")]
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")])
64 ; In QI mode we push 2 bytes instead of 1 byte.
65 (define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
67 ; tpush will be used to generate the 'number of registers to push' in the
69 (define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
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")])
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])
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 "")])
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")])
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")])
96 ;; Function Prologue and Epilogue
97 (define_expand "prologue"
101 cr16_expand_prologue ();
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")))]
112 return cr16_prepare_push_pop_string (0);
114 [(set_attr "length" "4")]
117 (define_expand "epilogue"
121 cr16_expand_epilogue ();
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))
134 return cr16_prepare_push_pop_string (1);
136 [(set_attr "length" "4")]
139 (define_insn "popret_RA_return"
140 [(use (reg:SI RA_REGNUM))
144 [(set_attr "length" "2")]
147 ;; Arithmetic Instruction Patterns
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")))]
156 return cr16_emit_add_sub_di (operands, <plusminus_flag>);
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")))]
165 [(set_attr "length" "2,2,4,4,6")]
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")))]
174 "<plusminus_insn>w\t%2, %0"
175 [(set_attr "length" "2,2,4")]
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")))]
184 "<plusminus_insn>b\t%2, %0"
185 [(set_attr "length" "2,2")]
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")))]
195 [(set_attr "length" "4,6")]
198 ;; Multiply and Accumulate Instructions "smachisi3/umachisi3"
199 (define_insn "<sPat>maddhisi4"
200 [(set (match_operand:SI 0 "register_operand" "=r")
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")))]
206 "mac<sPat>w\t%1, %2, %0"
207 [(set_attr "length" "2")]
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")))]
217 [(set_attr "length" "2,2,4")]
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"))))]
226 [(set_attr "length" "2")]
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" ""))]
237 if (INTVAL (operands[1]) != 1)
239 if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
241 if (INTVAL (operands[3]) == 1)
243 if (GET_MODE (operands[0]) == QImode)
245 emit_insn (gen_set_bitqi (operands[0], operands[2]));
248 else if (GET_MODE (operands[0]) == HImode)
250 emit_insn (gen_set_bithi (operands[0], operands[2]));
254 if (INTVAL (operands[3]) == 0)
256 if (GET_MODE (operands[0]) == QImode)
258 emit_insn (gen_clr_bitqi (operands[0], operands[2]));
261 else if (GET_MODE (operands[0]) == HImode)
263 emit_insn (gen_clr_bithi (operands[0], operands[2]));
270 (define_insn "set_bit<mode>"
271 [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
273 (match_operand 1 "immediate_operand" "i"))
277 [(set_attr "length" "2")]
280 (define_insn "clr_bit<mode>"
281 [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
283 (match_operand 1 "immediate_operand" "i"))
287 [(set_attr "length" "2")]
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"))
296 "sbit<tIsa>\t$%s1,%0"
297 [(set_attr "length" "2")]
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"))
306 "cbit<tIsa>\t$%r1,%0"
307 [(set_attr "length" "2")]
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")))]
317 return cr16_emit_logical_di (operands, <any_logic_flag>);
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")))]
327 [(set_attr "length" "2,2,4,6")]
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")))]
337 "<logic><QHsuffix>\t%2, %0"
338 [(set_attr "length" "<QHsz>")]
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")))]
346 "mov<szIsa>w\t%1, %0"
347 [(set_attr "length" "4")]
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")))]
354 "mov<szIsa>b\t%1, %0"
355 [(set_attr "length" "4")]
359 (define_insn "one_cmpldi2"
360 [(set (match_operand:DI 0 "register_operand" "=r")
361 (not:DI (match_operand:DI 1 "register_operand" "0")))]
365 int reg0 = REGNO (operands[0]);
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);
372 [(set_attr "length" "12")]
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")))]
380 [(set_attr "length" "2")]
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")))]
390 [(set_attr "length" "2,2")]
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")))]
399 [(set_attr "length" "2,2")]
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")))]
408 [(set_attr "length" "2,2")]
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" "")))]
417 if (GET_CODE (operands[2]) == CONST_INT)
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]);
424 if (GET_CODE (operands[2]) != CONST_INT)
425 operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
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")))]
435 [(set_attr "length" "2")]
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")))]
444 [(set_attr "length" "2")]
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")))]
453 [(set_attr "length" "2")]
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"))))]
462 [(set_attr "length" "2")]
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"))))]
471 [(set_attr "length" "2")]
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"))))]
480 [(set_attr "length" "2")]
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" "")))]
489 if (GET_CODE (operands[2]) == CONST_INT)
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]);
496 if (GET_CODE (operands[2]) != CONST_INT)
497 operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
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")))]
507 [(set_attr "length" "2")]
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")))]
516 [(set_attr "length" "2")]
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")))]
525 [(set_attr "length" "2")]
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"))))]
534 [(set_attr "length" "2")]
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"))))]
543 [(set_attr "length" "2")]
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"))))]
552 [(set_attr "length" "2")]
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)
565 ;; if Operand 1 is either register or 4-bit immediate constant
566 ;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
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
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.
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
584 ;; Case 2: Op 0 is not push_operand
585 ;; Op 1 is neither register nor unsigned 4-bit immediate
587 (define_expand "mov<mode>"
588 [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
589 (match_operand:ALLMTD 1 "general_operand" ""))]
592 if (!(reload_in_progress || reload_completed))
594 /* Only if Op0 is a register operand. */
595 if (!register_operand (operands[0], <MODE>mode))
597 if (push_operand (operands[0], <MODE>mode))
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]);
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))
610 /* CR16 does not support moving immediate to SI or SF
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]);
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]);
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]))
626 operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
632 ; ALLMT : QI,HI,SI,SF
633 ; pushCnstr : Push constraints
636 ; b : All non-sp registers
641 (define_insn "push<mode>_internal"
642 [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
643 (match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
646 [(set_attr "length" "2")]
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)"
658 if (0 == which_alternative) {
660 int reg0 = REGNO (operands[0]);
661 int reg1 = REGNO (operands[1]);
663 xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
664 xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
665 if ((reg1 + 2) != reg0)
667 output_asm_insn ("movd\t%1, %0", operands);
668 output_asm_insn ("movd\t%1, %0", xoperands);
672 output_asm_insn ("movd\t%1, %0", xoperands);
673 output_asm_insn ("movd\t%1, %0", operands);
676 else if (1 == which_alternative) {
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);}
691 else if (2 == which_alternative) {
693 int reg0 = REGNO (operands[0]), reg1 = -2 ;
696 if (MEM_P (operands[1]))
697 addr = XEXP (operands[1], 0);
700 switch (GET_CODE (addr))
707 switch (GET_CODE (XEXP (addr, 0))) {
710 reg1 = REGNO (XEXP (addr, 0));
713 reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
716 inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; 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");
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)
732 output_asm_insn ("loadd\t%1, %0", operands);
733 output_asm_insn ("loadd\t%1, %0", xoperands);
737 output_asm_insn ("loadd\t%1, %0", xoperands);
738 output_asm_insn ("loadd\t%1, %0", operands);
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);
750 [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
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)"
766 [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
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)))"
783 [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
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"
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 "" ""))
799 "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
800 [(set_attr "length" "6,6")]
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"))] ) ]
811 ;; Scond Instructions
812 (define_expand "cstore<mode>4"
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)]))]
823 (define_insn "*cmp<mode>_insn"
825 (compare (match_operand:CR16IM 0 "register_operand" "r,r")
826 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
829 [(set_attr "length" "2,4")]
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)]))]
838 [(set_attr "length" "2")]
841 ;; Jumps and Branches
842 (define_insn "indirect_jump_return"
848 [(set_attr "length" "2")]
851 (define_insn "jump_return"
852 [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
856 [(set_attr "length" "2")]
859 (define_insn "indirect_jump"
861 (match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
866 [(set_attr "length" "2,6")]
869 (define_insn "interrupt_return"
870 [(unspec_volatile [(const_int 0)] 0)
874 return cr16_prepare_push_pop_string (1);
876 [(set_attr "length" "14")]
879 (define_insn "jump_to_imm"
881 (match_operand 0 "jump_imm_operand" "i"))]
884 [(set_attr "length" "6")]
889 (label_ref (match_operand 0 "" "")))]
892 [(set_attr "length" "6")]
896 (define_insn "tablejump"
898 (match_operand:SI 0 "register_operand" "r"))
899 (use (label_ref:SI (match_operand 1 "" "")))]
902 [(set_attr "length" "2")]
906 (define_expand "call"
907 [(call (match_operand:QI 0 "memory_operand" "")
908 (match_operand 1 "" ""))]
911 if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
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]));
918 emit_call_insn (gen_cr16_call (operands[0], operands[1]));
923 (define_expand "cr16_call"
925 [(call (match_operand:QI 0 "memory_operand" "")
926 (match_operand 1 "" ""))
927 (clobber (reg:SI RA_REGNUM))])]
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"
938 if (GET_CODE (operands[0]) != CONST_INT)
939 return "loadd\t%g0, %2 \n\tjal %2";
943 [(set_attr "length" "8")]
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"
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.
958 if (GET_CODE (operands[0]) != CONST_INT)
959 return "bal (ra), %a0";
961 operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
962 return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";
964 [(set_attr "length" "6")]
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"))]
973 [(set_attr "length" "2")]
976 ;; Call Value Instructions
978 (define_expand "call_value"
979 [(set (match_operand 0 "general_operand" "")
980 (call (match_operand:QI 1 "memory_operand" "")
981 (match_operand 2 "" "")))]
984 if (flag_pic && !legitimate_pic_operand_p (operands[1]))
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]));
991 emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
996 (define_expand "cr16_call_value"
998 [(set (match_operand 0 "general_operand" "")
999 (call (match_operand 1 "memory_operand" "")
1000 (match_operand 2 "" "")))
1001 (clobber (reg:SI RA_REGNUM))])]
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"
1013 if (GET_CODE (operands[1]) != CONST_INT)
1014 return "loadd\t%g1, %3 \n\tjal %3";
1018 [(set_attr "length" "8")]
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"
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.
1034 if (GET_CODE (operands[1]) != CONST_INT)
1035 return "bal (ra), %a1";
1038 operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
1039 return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";
1042 [(set_attr "length" "6")]
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"))]
1053 [(set_attr "length" "2")]
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. */
1070 (define_insn "unspec_bro_addr"
1071 [(set (match_operand:SI 0 "register_operand" "=r")
1072 (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
1075 [(set_attr "length" "4")]
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))]
1083 [(set_attr "length" "6")]