aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/rl78/rl78.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/rl78/rl78.md')
-rw-r--r--gcc-4.9/gcc/config/rl78/rl78.md443
1 files changed, 443 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/config/rl78/rl78.md b/gcc-4.9/gcc/config/rl78/rl78.md
new file mode 100644
index 000000000..eb4c468ca
--- /dev/null
+++ b/gcc-4.9/gcc/config/rl78/rl78.md
@@ -0,0 +1,443 @@
+;; Machine Description for Renesas RL78 processors
+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
+;; Contributed by Red Hat.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_constants
+ [
+ (AX_REG 0)
+ (X_REG 0)
+ (A_REG 1)
+ (BC_REG 2)
+ (C_REG 2)
+ (B_REG 3)
+ (DE_REG 4)
+ (E_REG 4)
+ (D_REG 5)
+ (HL_REG 6)
+ (L_REG 6)
+ (H_REG 7)
+
+ (FP_REG 22)
+ (SP_REG 32)
+ (CC_REG 34)
+ (ES_REG 35)
+ (CS_REG 36)
+
+ (UNS_PROLOG 1)
+ (UNS_EPILOG 1)
+ (UNS_RETI 2)
+ (UNS_RETB 3)
+
+ (UNS_SET_RB 10)
+ (UNS_ES_ADDR 11)
+
+ (UNS_TRAMPOLINE_INIT 20)
+ (UNS_TRAMPOLINE_UNINIT 21)
+ (UNS_NONLOCAL_GOTO 22)
+
+ ])
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ )
+
+(define_mode_iterator QHI [QI HI])
+
+(include "predicates.md")
+(include "constraints.md")
+(include "rl78-expand.md")
+(include "rl78-virt.md")
+(include "rl78-real.md")
+
+
+;; Function Prologue/Epilogue Instructions
+
+(define_expand "prologue"
+ [(const_int 0)]
+ ""
+ "rl78_expand_prologue (); DONE;"
+)
+
+(define_expand "epilogue"
+ [(const_int 0)]
+ ""
+ "rl78_expand_epilogue (); DONE;"
+)
+
+(define_expand "sibcall_epilogue"
+ [(return)]
+ ""
+ "FAIL;"
+)
+
+(define_insn "rl78_return"
+ [(return)]
+ ""
+ "ret"
+)
+
+(define_insn "interrupt_return"
+ [(unspec_volatile [(return)] UNS_RETI) ]
+ ""
+ "reti"
+)
+
+(define_insn "brk_interrupt_return"
+ [(unspec_volatile [(return)] UNS_RETB) ]
+ ""
+ "retb"
+)
+
+(define_expand "eh_return"
+ [(match_operand:HI 0 "" "")]
+ ""
+ "rl78_expand_eh_epilogue (operands[0]);
+ emit_barrier ();
+ DONE;"
+)
+
+;; These are used only by prologue/epilogue so it's "safe" to pass
+;; virtual registers.
+(define_insn "push"
+ [(set (reg:HI SP_REG)
+ (plus:HI (reg:HI SP_REG)
+ (const_int -2)))
+ (set (mem:HI (reg:HI SP_REG))
+ (match_operand:HI 0 "register_operand" "ABDT,vZint"))]
+ ""
+ "@
+ push\t%v0
+ push\t%v0 ; %0"
+)
+
+(define_insn "pop"
+ [(set (match_operand:HI 0 "register_operand" "=ABDT,vZint")
+ (mem:HI (reg:HI SP_REG)))
+ (set (reg:HI SP_REG)
+ (plus:HI (reg:HI SP_REG)
+ (const_int 2)))]
+ ""
+ "@
+ pop\t%v0
+ pop\t%v0 ; %0"
+)
+
+(define_insn "sel_rb"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)]
+ "!TARGET_G10"
+ "sel\trb%u0"
+ )
+
+(define_insn "trampoline_init"
+ [(set (match_operand 0 "register_operand" "=Z08W")
+ (unspec_volatile [(match_operand 1 "register_operand" "Z08W")
+ (match_operand 2 "register_operand" "Z10W")
+ ] UNS_TRAMPOLINE_INIT))
+ ]
+ ""
+ "call !!___trampoline_init ; %0 <= %1 %2"
+ )
+
+(define_insn "trampoline_uninit"
+ [(unspec_volatile [(const_int 0)] UNS_TRAMPOLINE_UNINIT)
+ ]
+ ""
+ "call !!___trampoline_uninit"
+ )
+
+;; GCC restores $fp *before* using it to access values on the *old*
+;; frame. So, we do it ourselves, to ensure this is not the case.
+;; Note that while %1 is usually a label_ref, we allow for a
+;; non-immediate as well.
+(define_expand "nonlocal_goto"
+ [(set (pc)
+ (unspec_volatile [(match_operand 0 "" "") ;; fp (ignore)
+ (match_operand 1 "" "vi") ;; target
+ (match_operand 2 "" "vi") ;; sp
+ (match_operand 3 "" "vi") ;; ?
+ ] UNS_NONLOCAL_GOTO))
+ ]
+ ""
+ "emit_jump_insn (gen_nonlocal_goto_insn (operands[0], operands[1], operands[2], operands[3]));
+ emit_barrier ();
+ DONE;"
+ )
+
+(define_insn "nonlocal_goto_insn"
+ [(set (pc)
+ (unspec_volatile [(match_operand 0 "" "") ;; fp (ignore)
+ (match_operand 1 "" "vi") ;; target
+ (match_operand 2 "" "vi") ;; sp
+ (match_operand 3 "" "vi") ;; ?
+ ] UNS_NONLOCAL_GOTO))
+ ]
+ ""
+ "; nonlocal goto
+ movw ax, %3
+ movw r22, ax
+ movw ax, %2
+ movw sp, ax
+ movw ax, %1
+ br ax
+"
+ )
+
+;;======================================================================
+;;
+;; "macro" insns - cases where inline chunks of code are more
+;; efficient than anything else.
+
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&vm")
+ (plus:SI (match_operand:SI 1 "general_operand" "vim")
+ (match_operand 2 "general_operand" "vim")))
+ ]
+ ""
+ "emit_insn (gen_addsi3_internal_virt (operands[0], operands[1], operands[2]));
+ DONE;"
+)
+
+(define_insn "addsi3_internal_virt"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm")
+ (plus:SI (match_operand:SI 1 "general_operand" "0, vim, vim")
+ (match_operand 2 "general_operand" "vim,vim,vim")))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
+ "rl78_virt_insns_ok ()"
+ ""
+ [(set_attr "valloc" "macax")]
+)
+
+(define_insn "addsi3_internal_real"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU")
+ (plus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU")
+ (match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1")))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
+ "rl78_real_insns_ok ()"
+ "@
+ movw ax,%h1 \;addw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;incw ax \;addw ax,%H2 \;movw %H0,ax
+ movw ax,%h1 \;addw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;incw ax \;addw ax,%H2 \;movw %H0,ax
+ movw ax,%h1 \;addw ax,%h2 \;movw bc, ax \;movw ax,%H1 \;sknc \;incw ax \;addw ax,%H2 \;movw %H0,ax \;movw ax,bc \;movw %h0, ax"
+ [(set_attr "valloc" "macax")]
+)
+
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&vm")
+ (minus:SI (match_operand:SI 1 "general_operand" "vim")
+ (match_operand 2 "general_operand" "vim")))
+ ]
+ ""
+ "emit_insn (gen_subsi3_internal_virt (operands[0], operands[1], operands[2]));
+ DONE;"
+)
+
+(define_insn "subsi3_internal_virt"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm")
+ (minus:SI (match_operand:SI 1 "general_operand" "0, vim, vim")
+ (match_operand 2 "general_operand" "vim,vim,vim")))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
+ "rl78_virt_insns_ok ()"
+ ""
+ [(set_attr "valloc" "macax")]
+)
+
+(define_insn "subsi3_internal_real"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU")
+ (minus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU")
+ (match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1")))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
+ "rl78_real_insns_ok ()"
+ "@
+ movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax
+ movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax
+ movw ax,%h1 \;subw ax,%h2 \;movw bc, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax \;movw ax,bc \;movw %h0, ax"
+ [(set_attr "valloc" "macax")]
+)
+
+(define_expand "mulqi3"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (mult:QI (match_operand:QI 1 "general_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ ]
+ "" ; mulu supported by all targets
+ ""
+)
+
+(define_expand "mulhi3"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (mult:HI (match_operand:HI 1 "general_operand" "")
+ (match_operand:HI 2 "nonmemory_operand" "")))
+ ]
+ "! RL78_MUL_NONE"
+ ""
+)
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=&v")
+ (mult:SI (match_operand:SI 1 "general_operand" "+vim")
+ (match_operand:SI 2 "nonmemory_operand" "vi")))
+ ]
+ "! RL78_MUL_NONE"
+ ""
+)
+
+(define_insn "*mulqi3_rl78"
+ [(set (match_operand:QI 0 "register_operand" "=&v")
+ (mult:QI (match_operand:QI 1 "general_operand" "+viU")
+ (match_operand:QI 2 "general_operand" "vi")))
+ ]
+ "" ; mulu supported by all targets
+ "; mulqi macro %0 = %1 * %2
+ mov a, %h1
+ mov x, a
+ mov a, %h2
+ mulu x ; ax = a * x
+ mov a, x
+ mov %h0, a
+ ; end of mulqi macro"
+;; [(set_attr "valloc" "macax")]
+)
+
+(define_insn "*mulhi3_rl78"
+ [(set (match_operand:HI 0 "register_operand" "=&v")
+ (mult:HI (match_operand:HI 1 "general_operand" "+viU")
+ (match_operand:HI 2 "general_operand" "vi")))
+ ]
+ "RL78_MUL_RL78"
+ "; mulhi macro %0 = %1 * %2
+ movw ax, %h1
+ movw bc, %h2
+ mulhu ; bcax = bc * ax
+ movw %h0, ax
+ ; end of mulhi macro"
+;; [(set_attr "valloc" "macax")]
+)
+
+(define_insn "*mulhi3_g13"
+ [(set (match_operand:HI 0 "register_operand" "=&v")
+ (mult:HI (match_operand:HI 1 "general_operand" "+viU")
+ (match_operand:HI 2 "general_operand" "vi")))
+ ]
+ "RL78_MUL_G13"
+ "; mulhi macro %0 = %1 * %2
+ mov a, #0x00
+ mov !0xf00e8, a ; MDUC
+ movw ax, %h1
+ movw 0xffff0, ax ; MDAL
+ movw ax, %h2
+ movw 0xffff2, ax ; MDAH
+ nop ; mdb = mdal * mdah
+ movw ax, 0xffff6 ; MDBL
+ movw %h0, ax
+ ; end of mulhi macro"
+;; [(set_attr "valloc" "umul")]
+)
+
+;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it
+;; because we're only using the lower 16 bits (which is the upper 16
+;; bits of the result).
+(define_insn "mulsi3_rl78"
+ [(set (match_operand:SI 0 "register_operand" "=&v")
+ (mult:SI (match_operand:SI 1 "general_operand" "+viU")
+ (match_operand:SI 2 "general_operand" "vi")))
+ ]
+ "RL78_MUL_RL78"
+ "; mulsi macro %0 = %1 * %2
+ movw ax, %h1
+ movw bc, %h2
+ MULHU ; bcax = bc * ax
+ movw %h0, ax
+ movw ax, bc
+ movw 0xffff0, ax
+ movw ax, %H1
+ movw bc, %h2
+ MACHU ; MACR += bc * ax
+ movw ax, %h1
+ movw bc, %H2
+ MACHU ; MACR += bc * ax
+ movw ax, 0xffff0
+ movw %H0, ax
+ ; end of mulsi macro"
+ [(set_attr "valloc" "macax")]
+ )
+
+;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH.
+;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH.
+;; 0xF00E0 is MDCL. 0xF00E2 is MDCH.
+;; 0xF00E8 is MDUC.
+;; Warning: this matches the silicon not the documentation.
+(define_insn "mulsi3_g13"
+ [(set (match_operand:SI 0 "register_operand" "=&v")
+ (mult:SI (match_operand:SI 1 "general_operand" "viU")
+ (match_operand:SI 2 "general_operand" "viU")))
+ ]
+ "RL78_MUL_G13"
+ "; mulsi macro %0 = %1 * %2
+ mov a, #0x00
+ mov !0xf00e8, a ; MDUC
+ movw ax, %h1
+ movw 0xffff0, ax ; MDAL
+ movw ax, %h2
+ movw 0xffff2, ax ; MDAH
+ nop ; mdb = mdal * mdah
+ movw ax, 0xffff6 ; MDBL
+ movw %h0, ax
+
+ mov a, #0x40
+ mov !0xf00e8, a ; MDUC
+ movw ax, 0xffff4 ; MDBH
+ movw !0xf00e0, ax ; MDCL
+ movw ax, #0
+ movw !0xf00e2, ax ; MDCL
+ movw ax, %H1
+ movw 0xffff0, ax ; MDAL
+ movw ax, %h2
+ movw 0xffff2, ax ; MDAH
+ nop ; mdc += mdal * mdah
+
+ mov a, #0x40
+ mov !0xf00e8, a ; MDUC
+ movw ax, %h1
+ movw 0xffff0, ax ; MDAL
+ movw ax, %H2
+ movw 0xffff2, ax ; MDAH
+ nop ; mdc += mdal * mdah
+ nop ; Additional nop for MAC
+ movw ax, !0xf00e0 ; MDCL
+ movw %H0, ax
+ ; end of mulsi macro"
+ [(set_attr "valloc" "macax")]
+ )
+
+(define_expand "es_addr"
+ [(unspec:SI [(reg:QI ES_REG)
+ (match_operand:HI 0 "" "")
+ ] UNS_ES_ADDR)]
+ ""
+ ""
+)