mirror of
https://github.com/pmret/gcc-papermario.git
synced 2024-11-08 20:02:47 +01:00
2182 lines
56 KiB
Markdown
2182 lines
56 KiB
Markdown
|
;;- Machine description for the AT&T DSP1600 for GNU C compiler
|
|||
|
;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
|
|||
|
;; Contributed by Michael Collison (collison@world.std.com).
|
|||
|
|
|||
|
;; This file is part of GNU CC.
|
|||
|
|
|||
|
;; GNU CC 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 2, or (at your option)
|
|||
|
;; any later version.
|
|||
|
|
|||
|
;; GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
|||
|
;; the Free Software Foundation, 59 Temple Place - Suite 330,
|
|||
|
;; Boston, MA 02111-1307, USA.
|
|||
|
|
|||
|
|
|||
|
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
|
|||
|
|
|||
|
;; Attribute specifications
|
|||
|
|
|||
|
; Type of each instruction. Default is arithmetic.
|
|||
|
; I'd like to write the list as this, but genattrtab won't accept it.
|
|||
|
;
|
|||
|
; "jump,cond_jump,call, ; flow-control instructions
|
|||
|
; load_i,load, store, move ; Y space address arithmetic instructions
|
|||
|
; malu,special,f3_alu,f3_alu_i ; data arithmetic unit instructions
|
|||
|
; shift_i,shift, bfield_i, bfield ; bit manipulation unit instructions
|
|||
|
; arith, ; integer unit instructions
|
|||
|
; nop
|
|||
|
|
|||
|
; Classification of each insn. Some insns of TYPE_BRANCH are multi-word.
|
|||
|
(define_attr "type"
|
|||
|
"jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,special,f3_alu,f3_alu_i,shift_i,shift,bfield_i,bfield,nop,ld_short_i"
|
|||
|
(const_string "malu"))
|
|||
|
|
|||
|
; Length in # of instructions of each insn. The values are not exact, but
|
|||
|
; are safe.
|
|||
|
(define_attr "length" ""
|
|||
|
(cond [(eq_attr "type" "cond_jump,f3_alu_i,shift_i,bfield_i,load_i")
|
|||
|
(const_int 2)]
|
|||
|
(const_int 1)))
|
|||
|
|
|||
|
|
|||
|
;; ....................
|
|||
|
;;
|
|||
|
;; Test against 0 instructions
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
|
|||
|
(define_expand "tsthi"
|
|||
|
[(set (cc0)
|
|||
|
(match_operand:HI 0 "register_operand" ""))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
dsp16xx_compare_gen = gen_tst_reg;
|
|||
|
dsp16xx_compare_op0 = operands[0];
|
|||
|
dsp16xx_compare_op1 = const0_rtx;
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "tsthi_1"
|
|||
|
[(set (cc0)
|
|||
|
(match_operand:HI 0 "register_operand" "A"))]
|
|||
|
""
|
|||
|
"%0=%0"
|
|||
|
[(set_attr "type" "malu")])
|
|||
|
|
|||
|
(define_expand "tstqi"
|
|||
|
[(set (cc0)
|
|||
|
(match_operand:QI 0 "register_operand" ""))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
dsp16xx_compare_gen = gen_tst_reg;
|
|||
|
dsp16xx_compare_op0 = operands[0];
|
|||
|
dsp16xx_compare_op1 = const0_rtx;
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "tstqi_1"
|
|||
|
[(set (cc0)
|
|||
|
(match_operand:QI 0 "register_operand" "j,q"))
|
|||
|
(clobber (match_scratch:QI 1 "=k,u"))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%1=0\;%b0-0
|
|||
|
%1=0\;%b0-0"
|
|||
|
[(set_attr "type" "malu,malu")])
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
;;
|
|||
|
;; Bit test instructions
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (cc0)
|
|||
|
(and:HI (match_operand:HI 0 "register_operand" "A,!A,A")
|
|||
|
(match_operand:HI 1 "nonmemory_operand" "Z,A,I")))]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
case 1:
|
|||
|
return \"%0&%1\";
|
|||
|
|
|||
|
case 2:
|
|||
|
return \"%0&%H1\";
|
|||
|
}
|
|||
|
}"
|
|||
|
[(set_attr "type" "f3_alu,malu,f3_alu_i")])
|
|||
|
|
|||
|
|
|||
|
;;(define_insn ""
|
|||
|
;; [(set (cc0)
|
|||
|
;; (and:QI (match_operand:QI 0 "register_operand" "h")
|
|||
|
;; (match_operand:QI 1 "const_int_operand" "I")))]
|
|||
|
;; ""
|
|||
|
;; "%b0&%H1"
|
|||
|
;; [(set_attr "type" "f3_alu_i")])
|
|||
|
|
|||
|
;;
|
|||
|
;;
|
|||
|
;; Compare Instructions
|
|||
|
;;
|
|||
|
|
|||
|
(define_expand "cmphi"
|
|||
|
[(parallel [(set (cc0)
|
|||
|
(compare (match_operand:HI 0 "general_operand" "")
|
|||
|
(match_operand:HI 1 "general_operand" "")))
|
|||
|
(clobber (match_scratch:QI 2 ""))
|
|||
|
(clobber (match_scratch:QI 3 ""))
|
|||
|
(clobber (match_scratch:QI 4 ""))
|
|||
|
(clobber (match_scratch:QI 5 ""))])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (GET_CODE (operands[1]) == CONST_INT)
|
|||
|
operands[1] = force_reg (HImode, operands[1]);
|
|||
|
|
|||
|
if (operands[0]) /* Avoid unused code warning */
|
|||
|
{
|
|||
|
dsp16xx_compare_gen = gen_compare_reg;
|
|||
|
dsp16xx_compare_op0 = operands[0];
|
|||
|
dsp16xx_compare_op1 = operands[1];
|
|||
|
DONE;
|
|||
|
}
|
|||
|
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (cc0)
|
|||
|
(compare (match_operand:HI 0 "general_operand" "Z*r*m*i")
|
|||
|
(match_operand:HI 1 "general_operand" "Z*r*m*i")))
|
|||
|
(clobber (match_scratch:QI 2 "=&A"))
|
|||
|
(clobber (match_scratch:QI 3 "=&A"))
|
|||
|
(clobber (match_scratch:QI 4 "=&A"))
|
|||
|
(clobber (match_scratch:QI 5 "=&A"))]
|
|||
|
"(save_next_cc_user_code = next_cc_user_code (insn)) == GTU \
|
|||
|
|| save_next_cc_user_code == GEU \
|
|||
|
|| save_next_cc_user_code == LTU \
|
|||
|
|| save_next_cc_user_code == LEU"
|
|||
|
"*
|
|||
|
{
|
|||
|
if (GET_CODE(operands[0]) == REG)
|
|||
|
{
|
|||
|
if (REGNO (operands[0]) == REG_Y ||
|
|||
|
REGNO (operands[0]) == REG_PROD)
|
|||
|
{
|
|||
|
output_asm_insn (\"a0=%0\", operands);
|
|||
|
}
|
|||
|
else if (IS_YBASE_REGISTER_WINDOW (REGNO(operands[0])))
|
|||
|
{
|
|||
|
output_asm_insn (\"a0=%u0\;a0l=%w0\", operands);
|
|||
|
}
|
|||
|
else
|
|||
|
fatal (\"Invalid register for compare\");
|
|||
|
}
|
|||
|
else if (GET_CODE(operands[0]) == CONST_INT)
|
|||
|
{
|
|||
|
output_asm_insn (\"a0=%U0\;a0l=%H0\", operands);
|
|||
|
}
|
|||
|
else if (GET_CODE (operands[0]) == MEM)
|
|||
|
{
|
|||
|
rtx xoperands[2];
|
|||
|
|
|||
|
xoperands[0] = gen_rtx (REG, HImode, REG_A0);
|
|||
|
xoperands[1] = operands[0];
|
|||
|
double_reg_from_memory (xoperands);
|
|||
|
}
|
|||
|
|
|||
|
if (GET_CODE(operands[1]) == REG)
|
|||
|
{
|
|||
|
if (REGNO (operands[1]) == REG_Y ||
|
|||
|
REGNO (operands[1]) == REG_PROD)
|
|||
|
{
|
|||
|
output_asm_insn (\"a1=%1\", operands);
|
|||
|
}
|
|||
|
else if (IS_YBASE_REGISTER_WINDOW (REGNO(operands[1])))
|
|||
|
{
|
|||
|
output_asm_insn (\"a1=%u1\;a1l=%w1\", operands);
|
|||
|
}
|
|||
|
else
|
|||
|
fatal (\"Invalid register for compare\");
|
|||
|
}
|
|||
|
else if (GET_CODE (operands[1]) == MEM)
|
|||
|
{
|
|||
|
rtx xoperands[2];
|
|||
|
|
|||
|
xoperands[0] = gen_rtx (REG, HImode, REG_A1);
|
|||
|
xoperands[1] = operands[1];
|
|||
|
double_reg_from_memory (xoperands);
|
|||
|
}
|
|||
|
else if (GET_CODE(operands[1]) == CONST_INT)
|
|||
|
{
|
|||
|
output_asm_insn (\"a1=%U1\;a1l=%H1\", operands);
|
|||
|
}
|
|||
|
|
|||
|
return \"psw = 0\;a0 - a1\";
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (cc0) (compare (match_operand:HI 0 "register_operand" "A,!A")
|
|||
|
(match_operand:HI 1 "register_operand" "Z,*A")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%0-%1
|
|||
|
%0-%1"
|
|||
|
[(set_attr "type" "malu,f3_alu")])
|
|||
|
|
|||
|
(define_expand "cmpqi"
|
|||
|
[(parallel [(set (cc0)
|
|||
|
(compare (match_operand:QI 0 "register_operand" "")
|
|||
|
(match_operand:QI 1 "nonmemory_operand" "")))
|
|||
|
(clobber (match_operand:QI 2 "register_operand" ""))
|
|||
|
(clobber (match_operand:QI 3 "register_operand" ""))])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (operands[0]) /* Avoid unused code warning */
|
|||
|
{
|
|||
|
dsp16xx_compare_gen = gen_compare_reg;
|
|||
|
dsp16xx_compare_op0 = operands[0];
|
|||
|
dsp16xx_compare_op1 = operands[1];
|
|||
|
DONE;
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,k,u,u,!u,u")
|
|||
|
(match_operand:QI 1 "nonmemory_operand" "w,z,u,i,w,z,k,i")))
|
|||
|
(clobber (match_scratch:QI 2 "=j,j,j,j,q,q,q,q"))
|
|||
|
(clobber (match_scratch:QI 3 "=v,y,q,X,v,y,j,X"))]
|
|||
|
"(save_next_cc_user_code = next_cc_user_code (insn)) == GTU \
|
|||
|
|| save_next_cc_user_code == GEU \
|
|||
|
|| save_next_cc_user_code == LTU \
|
|||
|
|| save_next_cc_user_code == LEU"
|
|||
|
"@
|
|||
|
%2=0\;%3=0\;%2-%3
|
|||
|
%2=0\;%3=0\;%2-%3
|
|||
|
%2=0\;%3=0\;%2-%3
|
|||
|
%2=0\;%0-%H1
|
|||
|
%2=0\;%3=0\;%2-%3
|
|||
|
%2=0\;%3=0\;%2-%3
|
|||
|
%2=0\;%3=0\;%2-%3
|
|||
|
%2=0\;%0-%H1")
|
|||
|
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,j,q,q,!q,q")
|
|||
|
(match_operand:QI 1 "nonmemory_operand" "v,y,q,i,v,y,j,i")))
|
|||
|
(clobber (match_scratch:QI 2 "=k,k,k,k,u,u,u,u"))
|
|||
|
(clobber (match_scratch:QI 3 "=w,z,u,X,w,z,k,X"))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%2=0\;%3=0\;%0-%1
|
|||
|
%2=0\;%3=0\;%0-%1
|
|||
|
%2=0\;%3=0\;%0-%1
|
|||
|
%2=0\;%b0-%H1
|
|||
|
%2=0\;%3=0\;%0-%1
|
|||
|
%2=0\;%3=0\;%0-%1
|
|||
|
%2=0\;%3=0\;%0-%1
|
|||
|
%2=0\;%b0-%H1")
|
|||
|
|
|||
|
|
|||
|
(define_expand "cmphf"
|
|||
|
[(set (cc0)
|
|||
|
(compare (match_operand:HF 0 "register_operand" "")
|
|||
|
(match_operand:HF 1 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_cmphf3_libcall)
|
|||
|
dsp16xx_cmphf3_libcall = gen_rtx (SYMBOL_REF, Pmode, CMPHF3_LIBCALL);
|
|||
|
|
|||
|
dsp16xx_compare_gen = gen_compare_reg;
|
|||
|
dsp16xx_compare_op0 = operands[0];
|
|||
|
dsp16xx_compare_op1 = operands[1];
|
|||
|
emit_library_call (dsp16xx_cmphf3_libcall, 1, HImode, 2,
|
|||
|
operands[0], HFmode,
|
|||
|
operands[1], HFmode);
|
|||
|
emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode))));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
;; ....................
|
|||
|
;;
|
|||
|
;; Add instructions
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
|
|||
|
|
|||
|
(define_insn "addhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A")
|
|||
|
(plus:HI (match_operand:HI 1 "register_operand" "%A,A,A")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "Z,d,i")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%0=%1+%2
|
|||
|
%0=%1+%2
|
|||
|
%0=%w1+%H2\;%0=%b0+%U2"
|
|||
|
[(set_attr "type" "malu,malu,f3_alu_i")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u")
|
|||
|
(plus:QI (plus:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk")
|
|||
|
(match_operand:QI 2 "register_operand" "wz,wz,uk,uk"))
|
|||
|
(match_operand:QI 3 "immediate_operand" "i,i,i,i")))
|
|||
|
(clobber (match_scratch:QI 4 "=j,q,j,q"))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%m0=%m1+%m2\;%m0=%0+%H3
|
|||
|
%m0=%m1+%m2\;%m0=%0+%H3
|
|||
|
%m0=%m1+%m2\;%m0=%0+%H3
|
|||
|
%m0=%m1+%m2\;%m0=%0+%H3")
|
|||
|
|
|||
|
(define_expand "addqi3"
|
|||
|
[(parallel [(set (match_operand:QI 0 "register_operand" "")
|
|||
|
(plus:QI (match_operand:QI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))
|
|||
|
(clobber (match_scratch:QI 3 ""))])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (reload_in_progress)
|
|||
|
{
|
|||
|
if (REG_P (operands[1]) &&
|
|||
|
(REGNO(operands[1]) == STACK_POINTER_REGNUM ||
|
|||
|
REGNO(operands[1]) == FRAME_POINTER_REGNUM) &&
|
|||
|
GET_CODE (operands[2]) == CONST_INT)
|
|||
|
{
|
|||
|
if (REG_P (operands[0]) && IS_ACCUM_REG(REGNO(operands[0])))
|
|||
|
emit_move_insn (operands[0], operands[1]);
|
|||
|
|
|||
|
operands[1] = operands[0];
|
|||
|
}
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_insn "match_addqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=!a,!a,k,u,!k,!u,h,!a")
|
|||
|
(plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,h,0")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "W,N,wzi,wzi,uk,uk,i,n")))
|
|||
|
(clobber (match_scratch:QI 3 "=X,X,j,q,j,q,X,W"))]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return \"*%0++%2\";
|
|||
|
|
|||
|
case 1:
|
|||
|
switch (INTVAL (operands[2]))
|
|||
|
{
|
|||
|
case -1:
|
|||
|
return \"*%0--\";
|
|||
|
|
|||
|
case 1:
|
|||
|
return \"*%0++\";
|
|||
|
|
|||
|
case -2:
|
|||
|
return \"*%0--\;*%0--\";
|
|||
|
|
|||
|
case 2:
|
|||
|
return \"*%0++\;*%0++\";
|
|||
|
}
|
|||
|
|
|||
|
case 2:
|
|||
|
case 3:
|
|||
|
if (!CONSTANT_P(operands[2]))
|
|||
|
return \"%m0=%m1+%m2\";
|
|||
|
else
|
|||
|
return \"%m0=%1+%H2\";
|
|||
|
|
|||
|
case 4:
|
|||
|
case 5:
|
|||
|
return \"%m0=%m1+%m2\";
|
|||
|
|
|||
|
case 6:
|
|||
|
return \"%0=%b1+%H2\";
|
|||
|
|
|||
|
case 7:
|
|||
|
return \"%3=%2\;*%0++%3\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "addhf3"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "")
|
|||
|
(plus:HF (match_operand:HF 1 "register_operand" "")
|
|||
|
(match_operand:HF 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_addhf3_libcall)
|
|||
|
dsp16xx_addhf3_libcall = gen_rtx (SYMBOL_REF, Pmode, ADDHF3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_addhf3_libcall, 1, HFmode, 2,
|
|||
|
operands[1], HFmode,
|
|||
|
operands[2], HFmode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HFmode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
;;
|
|||
|
;; Subtract instructions
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
|
|||
|
(define_insn "subhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A")
|
|||
|
(minus:HI (match_operand:HI 1 "register_operand" "A,A,A")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "Z,d,i")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%0=%1-%2
|
|||
|
%0=%1-%2
|
|||
|
%0=%w1-%H2\;%0=%b0-%U2"
|
|||
|
[(set_attr "type" "malu,malu,f3_alu_i")])
|
|||
|
|
|||
|
(define_insn "subqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=?*a,k,u,!k,!u")
|
|||
|
(minus:QI (match_operand:QI 1 "register_operand" "0,uk,uk,uk,uk")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "n,wzi,wzi,uk,uk")))
|
|||
|
(clobber (match_scratch:QI 3 "=W,j,q,j,q"))]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
switch (INTVAL (operands[2]))
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return \"\";
|
|||
|
|
|||
|
case 1:
|
|||
|
return \"*%0--\";
|
|||
|
|
|||
|
case -1:
|
|||
|
return \"*%0++\";
|
|||
|
|
|||
|
default:
|
|||
|
operands[2] = GEN_INT (-INTVAL (operands[2]));
|
|||
|
|
|||
|
if (SHORT_IMMEDIATE(operands[2]))
|
|||
|
return \"set %3=%H2\;*%0++%3\";
|
|||
|
else
|
|||
|
return \"%3=%H2\;*%0++%3\";
|
|||
|
}
|
|||
|
|
|||
|
case 1:
|
|||
|
case 2:
|
|||
|
if (!CONSTANT_P(operands[2]))
|
|||
|
return \"%m0=%m1-%m2\";
|
|||
|
else
|
|||
|
return \"%m0=%1-%H2\";
|
|||
|
|
|||
|
case 3:
|
|||
|
case 4:
|
|||
|
return \"%m0=%m1-%m2\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "subhf3"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "")
|
|||
|
(minus:HF (match_operand:HF 1 "register_operand" "")
|
|||
|
(match_operand:HF 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_subhf3_libcall)
|
|||
|
dsp16xx_subhf3_libcall = gen_rtx (SYMBOL_REF, Pmode, SUBHF3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_subhf3_libcall, 1, HFmode, 2,
|
|||
|
operands[1], HFmode,
|
|||
|
operands[2], HFmode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HFmode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "neghi2"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(neg:HI (match_operand:HI 1 "register_operand" "A")))]
|
|||
|
""
|
|||
|
"%0=-%1"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_expand "neghf2"
|
|||
|
[(set (match_operand:HF 0 "general_operand" "")
|
|||
|
(neg:HF (match_operand:HF 1 "general_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_neghf2_libcall)
|
|||
|
dsp16xx_neghf2_libcall = gen_rtx (SYMBOL_REF, Pmode, NEGHF2_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_neghf2_libcall, 1, HFmode, 1,
|
|||
|
operands[1], HFmode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HFmode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
;;
|
|||
|
;; Multiply instructions
|
|||
|
;;
|
|||
|
|
|||
|
(define_expand "mulhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(mult:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_mulhi3_libcall)
|
|||
|
dsp16xx_mulhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, MULHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_mulhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], HImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "mulqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=w")
|
|||
|
(mult:QI (match_operand:QI 1 "register_operand" "%x")
|
|||
|
(match_operand:QI 2 "register_operand" "y")))
|
|||
|
(clobber (match_scratch:QI 3 "=v"))]
|
|||
|
""
|
|||
|
"%m0=%1*%2"
|
|||
|
[(set_attr "type" "malu_mul")])
|
|||
|
|
|||
|
(define_insn "mulqihi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=t")
|
|||
|
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%x"))
|
|||
|
(sign_extend:HI (match_operand:QI 2 "register_operand" "y"))))]
|
|||
|
""
|
|||
|
"%0=%1*%2"
|
|||
|
[(set_attr "type" "malu_mul")])
|
|||
|
|
|||
|
(define_insn "umulqihi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=t")
|
|||
|
(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%x"))
|
|||
|
(zero_extend:HI (match_operand:QI 2 "register_operand" "y"))))]
|
|||
|
""
|
|||
|
"%0=%1*%2"
|
|||
|
[(set_attr "type" "malu_mul")])
|
|||
|
|
|||
|
(define_expand "mulhf3"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "")
|
|||
|
(mult:HF (match_operand:HF 1 "register_operand" "")
|
|||
|
(match_operand:HF 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_mulhf3_libcall)
|
|||
|
dsp16xx_mulhf3_libcall = gen_rtx (SYMBOL_REF, Pmode, MULHF3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_mulhf3_libcall, 1, HFmode, 2,
|
|||
|
operands[1], HFmode,
|
|||
|
operands[2], HFmode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HFmode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; *******************
|
|||
|
;;
|
|||
|
;; Divide Instructions
|
|||
|
;;
|
|||
|
|
|||
|
(define_expand "divhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(div:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_divhi3_libcall)
|
|||
|
dsp16xx_divhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, DIVHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_divhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], HImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "udivhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(udiv:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_udivhi3_libcall)
|
|||
|
dsp16xx_udivhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, UDIVHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_udivhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], HImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "divqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "")
|
|||
|
(div:QI (match_operand:QI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_divqi3_libcall)
|
|||
|
dsp16xx_divqi3_libcall = gen_rtx (SYMBOL_REF, Pmode, DIVQI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_divqi3_libcall, 1, QImode, 2,
|
|||
|
operands[1], QImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(QImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "udivqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "")
|
|||
|
(udiv:QI (match_operand:QI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_udivqi3_libcall)
|
|||
|
dsp16xx_udivqi3_libcall = gen_rtx (SYMBOL_REF, Pmode, UDIVQI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_udivqi3_libcall, 1, QImode, 2,
|
|||
|
operands[1], QImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(QImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
;;
|
|||
|
;; Modulo instructions
|
|||
|
;;
|
|||
|
;; ....................
|
|||
|
|
|||
|
(define_expand "modhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(mod:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_modhi3_libcall)
|
|||
|
dsp16xx_modhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, MODHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_modhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], HImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "umodhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(umod:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_umodhi3_libcall)
|
|||
|
dsp16xx_umodhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, UMODHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_umodhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], HImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "modqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "")
|
|||
|
(mod:QI (match_operand:QI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_modqi3_libcall)
|
|||
|
dsp16xx_modqi3_libcall = gen_rtx (SYMBOL_REF, Pmode, MODQI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_modqi3_libcall, 1, QImode, 2,
|
|||
|
operands[1], QImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(QImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "umodqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "")
|
|||
|
(umod:QI (match_operand:QI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_umodqi3_libcall)
|
|||
|
dsp16xx_umodqi3_libcall = gen_rtx (SYMBOL_REF, Pmode, UMODQI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_umodqi3_libcall, 1, QImode, 2,
|
|||
|
operands[1], QImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(QImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "divhf3"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "")
|
|||
|
(div:HF (match_operand:HF 1 "register_operand" "")
|
|||
|
(match_operand:HF 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_divhf3_libcall)
|
|||
|
dsp16xx_divhf3_libcall = gen_rtx (SYMBOL_REF, Pmode, DIVHF3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_divhf3_libcall, 1, HFmode, 2,
|
|||
|
operands[1], HFmode,
|
|||
|
operands[2], HFmode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HFmode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; ********************
|
|||
|
;;
|
|||
|
;; Logical Instructions
|
|||
|
;;
|
|||
|
|
|||
|
(define_insn "andhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,?A")
|
|||
|
(and:HI (match_operand:HI 1 "register_operand" "%A,!A,A")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "Z,A,i")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%0=%1&%2
|
|||
|
%0=%1&%2
|
|||
|
%0=%w1&%H2\;%0=%b0&%U2"
|
|||
|
[(set_attr "type" "f3_alu,f3_alu,f3_alu_i")])
|
|||
|
|
|||
|
(define_insn "andqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q")
|
|||
|
(and:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq")))
|
|||
|
(clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%1&%H2
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%b1&%H2
|
|||
|
%m0=%m1&%m2
|
|||
|
%m0=%m1&%m2")
|
|||
|
|
|||
|
(define_insn "iorhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A,?A")
|
|||
|
(ior:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "Z,A,I,i")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%0=%u1|%u2
|
|||
|
%0=%u1|%u2
|
|||
|
%0=%w1|%H2
|
|||
|
%0=%w1|%H2\;%0=%b0|%U2"
|
|||
|
[(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i")])
|
|||
|
|
|||
|
(define_insn "iorqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q")
|
|||
|
(ior:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq")))
|
|||
|
(clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%1|%H2
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%b1|%H2
|
|||
|
%m0=%m1|%m2
|
|||
|
%m0=%m1|%m2")
|
|||
|
|
|||
|
(define_insn "xorhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A,?A")
|
|||
|
(xor:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A")
|
|||
|
(match_operand:HI 2 "nonmemory_operand" "Z,A,I,i")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%0=%1^%2
|
|||
|
%0=%1^%2
|
|||
|
%0=%w1^%H2
|
|||
|
%0=%w1^%H2\;%0=%b0^%U2"
|
|||
|
[(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i")])
|
|||
|
|
|||
|
(define_insn "xorqi3"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q")
|
|||
|
(xor:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq")))
|
|||
|
(clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%1^%H2
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%b1^%H2
|
|||
|
%m0=%m1^%m2
|
|||
|
%m0=%m1^%m2")
|
|||
|
|
|||
|
(define_insn "one_cmplhi2"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(not:HI (match_operand:HI 1 "register_operand" "A")))]
|
|||
|
""
|
|||
|
"%0= ~%1"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn "one_cmplqi2"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=ku,jq")
|
|||
|
(not:QI (match_operand:QI 1 "register_operand" "ku,jq")))]
|
|||
|
""
|
|||
|
"@
|
|||
|
%m0= %1 ^ 0xffff
|
|||
|
%m0= %b1 ^ 0xffff"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; MOVE INSTRUCTIONS
|
|||
|
;;
|
|||
|
|
|||
|
(define_expand "movhi"
|
|||
|
[(set (match_operand:HI 0 "general_operand" "")
|
|||
|
(match_operand:HI 1 "general_operand" ""))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (emit_move_sequence (operands, HImode))
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_insn "match_movhi1"
|
|||
|
[(set (match_operand:HI 0 "nonimmediate_operand" "=A,Z,A,d,d,m,?d,*Y,t,f")
|
|||
|
(match_operand:HI 1 "general_operand" "d,A,K,i,m,d,*Y,?d,t,f"))]
|
|||
|
"register_operand(operands[0], HImode)
|
|||
|
|| register_operand(operands[1], HImode)"
|
|||
|
"*
|
|||
|
{
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
/* register to accumulator */
|
|||
|
case 0:
|
|||
|
return \"%0=%1\";
|
|||
|
case 1:
|
|||
|
return \"%u0=%u1\;%w0=%w1\";
|
|||
|
case 2:
|
|||
|
return \"%0=%0^%0\";
|
|||
|
case 3:
|
|||
|
return \"%u0=%U1\;%w0=%H1\";
|
|||
|
case 4:
|
|||
|
double_reg_from_memory(operands);
|
|||
|
return \"\";
|
|||
|
case 5:
|
|||
|
double_reg_to_memory(operands);
|
|||
|
return \"\";
|
|||
|
case 6:
|
|||
|
case 7:
|
|||
|
return \"%u0=%u1\;%w0=%w1\";
|
|||
|
case 8:
|
|||
|
case 9:
|
|||
|
return \"\";
|
|||
|
}
|
|||
|
}"
|
|||
|
[(set_attr "type" "move,move,load_i,load_i,load,store,load,store,move,move")])
|
|||
|
|
|||
|
|
|||
|
;; NOTE: It is cheaper to do 'y = *r0', than 'r0 = *r0'.
|
|||
|
|
|||
|
(define_expand "movqi"
|
|||
|
[(set (match_operand:QI 0 "nonimmediate_operand" "")
|
|||
|
(match_operand:QI 1 "general_operand" ""))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (emit_move_sequence (operands, QImode))
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
;; The movqi pattern with the parallel is used for addqi insns (which have a parallel)
|
|||
|
;; that are turned into moveqi insns by the flow phase. This happens when a auto-increment
|
|||
|
;; is detected.
|
|||
|
|
|||
|
(define_insn "match_movqi1"
|
|||
|
[(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>")
|
|||
|
(match_operand:QI 1 "general_operand" "r,A,J,i,m<>,D,Y,e,0,m<>,xyz"))
|
|||
|
(clobber (match_scratch:QI 2 "=X,X,X,X,X,X,X,X,X,X,X"))])]
|
|||
|
"register_operand(operands[0], QImode)
|
|||
|
|| register_operand(operands[1], QImode)"
|
|||
|
"*
|
|||
|
{
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
/* We have to use the move mnemonic otherwise the 1610 will
|
|||
|
attempt to transfer all 32-bits of 'y', 'p' or an accumulator
|
|||
|
, which we don't want */
|
|||
|
if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
|
|||
|
|| IS_ACCUM_REG(REGNO(operands[1])))
|
|||
|
return \"move %0=%1\";
|
|||
|
else
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 1:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 2:
|
|||
|
return \"set %0=%H1\";
|
|||
|
|
|||
|
case 3:
|
|||
|
return \"%0=%H1\";
|
|||
|
|
|||
|
case 4:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 5:
|
|||
|
case 6:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 7:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 8:
|
|||
|
return \"\";
|
|||
|
|
|||
|
case 9: case 10:
|
|||
|
return \"%0=%1\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "match_movqi2"
|
|||
|
[(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>")
|
|||
|
(match_operand:QI 1 "general_operand" "r,A,J,i,m<>,D,Y,e,0,m<>,xyz"))]
|
|||
|
"register_operand(operands[0], QImode)
|
|||
|
|| register_operand(operands[1], QImode)"
|
|||
|
"*
|
|||
|
{
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
/* We have to use the move mnemonic otherwise the 1610 will
|
|||
|
attempt to transfer all 32-bits of 'y', 'p' or an accumulator
|
|||
|
, which we don't want */
|
|||
|
if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
|
|||
|
|| IS_ACCUM_REG(REGNO(operands[1])))
|
|||
|
return \"move %0=%1\";
|
|||
|
else
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 1:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 2:
|
|||
|
return \"set %0=%H1\";
|
|||
|
|
|||
|
case 3:
|
|||
|
return \"%0=%H1\";
|
|||
|
|
|||
|
case 4:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 5:
|
|||
|
case 6:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 7:
|
|||
|
return \"%0=%1\";
|
|||
|
|
|||
|
case 8:
|
|||
|
return \"\";
|
|||
|
|
|||
|
case 9: case 10:
|
|||
|
return \"%0=%1\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "reload_inqi"
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=u")
|
|||
|
(match_operand:QI 1 "sp_operand" ""))
|
|||
|
(clobber (match_operand:QI 2 "register_operand" "=&q"))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
rtx addr_reg = XEXP (operands[1], 0);
|
|||
|
rtx offset = XEXP (operands[1], 1);
|
|||
|
|
|||
|
/* First, move the frame or stack pointer to the accumulator */
|
|||
|
emit_move_insn (operands[0], addr_reg);
|
|||
|
|
|||
|
/* Then generate the add insn */
|
|||
|
emit_insn (gen_rtx (PARALLEL, VOIDmode,
|
|||
|
gen_rtvec (2,
|
|||
|
gen_rtx (SET, VOIDmode, operands[0],
|
|||
|
gen_rtx (PLUS, QImode, operands[0], offset)),
|
|||
|
gen_rtx (CLOBBER, VOIDmode, operands[2]))));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "reload_inhi"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
|||
|
(match_operand:HI 1 "register_operand" "r"))
|
|||
|
(clobber (match_operand:QI 2 "register_operand" "=&h"))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
/* Check for an overlap of operand 2 (an accumulator) with
|
|||
|
the msw of operand 0. If we have an overlap we must reverse
|
|||
|
the order of the moves. */
|
|||
|
|
|||
|
if (REGNO(operands[2]) == REGNO(operands[0]))
|
|||
|
{
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]);
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]);
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]);
|
|||
|
}
|
|||
|
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "reload_outhi"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=r")
|
|||
|
(match_operand:HI 1 "register_operand" "r"))
|
|||
|
(clobber (match_operand:QI 2 "register_operand" "=&h"))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]);
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]);
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "movstrqi"
|
|||
|
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
|
|||
|
(match_operand:BLK 1 "memory_operand" ""))
|
|||
|
(use (match_operand:QI 2 "const_int_operand" ""))
|
|||
|
(use (match_operand:QI 3 "const_int_operand" ""))
|
|||
|
(clobber (match_scratch:QI 4 ""))
|
|||
|
(clobber (match_dup 5))
|
|||
|
(clobber (match_dup 6))])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
rtx addr0, addr1;
|
|||
|
|
|||
|
if (GET_CODE (operands[2]) != CONST_INT)
|
|||
|
FAIL;
|
|||
|
|
|||
|
if (INTVAL(operands[2]) > 127)
|
|||
|
FAIL;
|
|||
|
|
|||
|
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
|||
|
addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
|
|||
|
|
|||
|
operands[5] = addr0;
|
|||
|
operands[6] = addr1;
|
|||
|
|
|||
|
operands[0] = change_address (operands[0], VOIDmode, addr0);
|
|||
|
operands[1] = change_address (operands[1], VOIDmode, addr1);
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (mem:BLK (match_operand:QI 0 "register_operand" "a"))
|
|||
|
(mem:BLK (match_operand:QI 1 "register_operand" "a")))
|
|||
|
(use (match_operand:QI 2 "const_int_operand" "n"))
|
|||
|
(use (match_operand:QI 3 "immediate_operand" "i"))
|
|||
|
(clobber (match_scratch:QI 4 "=x"))
|
|||
|
(clobber (match_dup 0))
|
|||
|
(clobber (match_dup 1))]
|
|||
|
""
|
|||
|
"*
|
|||
|
{ return output_block_move (operands); }")
|
|||
|
|
|||
|
|
|||
|
;; Floating point move insns
|
|||
|
|
|||
|
|
|||
|
(define_expand "movhf"
|
|||
|
[(set (match_operand:HF 0 "general_operand" "")
|
|||
|
(match_operand:HF 1 "general_operand" ""))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (emit_move_sequence (operands, HFmode))
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "match_movhf"
|
|||
|
[(set (match_operand:HF 0 "nonimmediate_operand" "=A,Z,d,d,m,d,Y")
|
|||
|
(match_operand:HF 1 "general_operand" "d,A,F,m,d,Y,d"))]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
/* NOTE: When loading the register 16 bits at a time we
|
|||
|
MUST load the high half FIRST (because the 1610 zeros
|
|||
|
the low half) and then load the low half */
|
|||
|
|
|||
|
switch (which_alternative)
|
|||
|
{
|
|||
|
/* register to accumulator */
|
|||
|
case 0:
|
|||
|
return \"%0=%1\";
|
|||
|
case 1:
|
|||
|
return \"%u0=%u1\;%w0=%w1\";
|
|||
|
case 2:
|
|||
|
output_dsp16xx_float_const(operands);
|
|||
|
return \"\";
|
|||
|
case 3:
|
|||
|
double_reg_from_memory(operands);
|
|||
|
return \"\";
|
|||
|
case 4:
|
|||
|
double_reg_to_memory(operands);
|
|||
|
return \"\";
|
|||
|
case 5:
|
|||
|
case 6:
|
|||
|
return \"%u0=%u1\;%w0=%w1\";
|
|||
|
}
|
|||
|
}"
|
|||
|
[(set_attr "type" "move,move,load_i,load,store,load,store")])
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(define_expand "reload_inhf"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "=r")
|
|||
|
(match_operand:HF 1 "register_operand" "r"))
|
|||
|
(clobber (match_operand:QI 2 "register_operand" "=&h"))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
/* Check for an overlap of operand 2 (an accumulator) with
|
|||
|
the msw of operand 0. If we have an overlap we must reverse
|
|||
|
the order of the moves. */
|
|||
|
|
|||
|
if (REGNO(operands[2]) == REGNO(operands[0]))
|
|||
|
{
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]);
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]);
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]);
|
|||
|
}
|
|||
|
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "reload_outhf"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "=r")
|
|||
|
(match_operand:HF 1 "register_operand" "r"))
|
|||
|
(clobber (match_operand:QI 2 "register_operand" "=&h"))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]);
|
|||
|
emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode));
|
|||
|
emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]);
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; CONVERSION INSTRUCTIONS
|
|||
|
;;
|
|||
|
|
|||
|
(define_expand "extendqihi2"
|
|||
|
[(clobber (match_dup 2))
|
|||
|
(set (match_dup 3) (match_operand:QI 1 "register_operand" ""))
|
|||
|
(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(ashift:HI (match_dup 2)
|
|||
|
(const_int 16)))
|
|||
|
(set (match_dup 0)
|
|||
|
(ashiftrt:HI (match_dup 0) (const_int 16)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
operands[2] = gen_reg_rtx (HImode);
|
|||
|
operands[3] = gen_rtx (SUBREG, QImode, operands[2], 1);
|
|||
|
}")
|
|||
|
|
|||
|
;;(define_insn "extendqihi2"
|
|||
|
;; [(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
;; (sign_extend:HI (match_operand:QI 1 "register_operand" "h")))]
|
|||
|
;; ""
|
|||
|
;; "%0 = %1 >> 16")
|
|||
|
|
|||
|
;;(define_insn "zero_extendqihi2"
|
|||
|
;; [(set (match_operand:HI 0 "register_operand" "=t,f,A,?d,?A")
|
|||
|
;; (zero_extend:HI (match_operand:QI 1 "register_operand" "w,z,ku,A,r")))]
|
|||
|
;; ""
|
|||
|
;; "*
|
|||
|
;; {
|
|||
|
;; switch (which_alternative)
|
|||
|
;; {
|
|||
|
;; case 0:
|
|||
|
;; case 1:
|
|||
|
;; return \"%0=0\";
|
|||
|
;;
|
|||
|
;; case 2:
|
|||
|
;; if (REGNO(operands[1]) == (REGNO(operands[0]) + 1))
|
|||
|
;; return \"%0=0\";
|
|||
|
;; else
|
|||
|
;; return \"%w0=%1\;%0=0\";
|
|||
|
;; case 3:
|
|||
|
;; return \"%w0=%1\;%0=0\";
|
|||
|
;;
|
|||
|
;; case 4:
|
|||
|
;; if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD
|
|||
|
;; || IS_ACCUM_REG(REGNO(operands[1])))
|
|||
|
;; return \"move %w0=%1\;%0=0\";
|
|||
|
;; else
|
|||
|
;; return \"%w0=%1\;%0=0\";
|
|||
|
;; }
|
|||
|
;; }")
|
|||
|
|
|||
|
(define_expand "zero_extendqihi2"
|
|||
|
[(clobber (match_dup 2))
|
|||
|
(set (match_dup 3) (match_operand:QI 1 "register_operand" ""))
|
|||
|
(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(ashift:HI (match_dup 2)
|
|||
|
(const_int 16)))
|
|||
|
(set (match_dup 0)
|
|||
|
(lshiftrt:HI (match_dup 0) (const_int 16)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
operands[2] = gen_reg_rtx (HImode);
|
|||
|
operands[3] = gen_rtx (SUBREG, QImode, operands[2], 1);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "floathihf2"
|
|||
|
[(set (match_operand:HF 0 "register_operand" "")
|
|||
|
(float:HF (match_operand:HI 1 "register_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_floathihf2_libcall)
|
|||
|
dsp16xx_floathihf2_libcall = gen_rtx (SYMBOL_REF, Pmode, FLOATHIHF2_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_floathihf2_libcall, 1, HFmode, 1,
|
|||
|
operands[1], HImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HFmode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "fix_trunchfhi2"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(fix:HI (match_operand:HF 1 "register_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!dsp16xx_fixhfhi2_libcall)
|
|||
|
dsp16xx_fixhfhi2_libcall = gen_rtx (SYMBOL_REF, Pmode, FIXHFHI2_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_fixhfhi2_libcall, 1, HImode, 1,
|
|||
|
operands[1], HFmode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "fixuns_trunchfhi2"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(unsigned_fix:HI (match_operand:HF 1 "register_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
rtx reg1 = gen_reg_rtx (HFmode);
|
|||
|
rtx reg2 = gen_reg_rtx (HFmode);
|
|||
|
rtx reg3 = gen_reg_rtx (HImode);
|
|||
|
rtx label1 = gen_label_rtx ();
|
|||
|
rtx label2 = gen_label_rtx ();
|
|||
|
REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);
|
|||
|
|
|||
|
if (reg1) /* turn off complaints about unreached code */
|
|||
|
{
|
|||
|
emit_move_insn (reg1, immed_real_const_1 (offset, HFmode));
|
|||
|
do_pending_stack_adjust ();
|
|||
|
|
|||
|
emit_insn (gen_cmphf (operands[1], reg1));
|
|||
|
emit_jump_insn (gen_bge (label1));
|
|||
|
|
|||
|
emit_insn (gen_fix_trunchfhi2 (operands[0], operands[1]));
|
|||
|
emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
|
|||
|
gen_rtx (LABEL_REF, VOIDmode, label2)));
|
|||
|
emit_barrier ();
|
|||
|
|
|||
|
emit_label (label1);
|
|||
|
emit_insn (gen_subhf3 (reg2, operands[1], reg1));
|
|||
|
emit_move_insn (reg3, GEN_INT (0x80000000));;
|
|||
|
|
|||
|
emit_insn (gen_fix_trunchfhi2 (operands[0], reg2));
|
|||
|
emit_insn (gen_iorhi3 (operands[0], operands[0], reg3));
|
|||
|
|
|||
|
emit_label (label2);
|
|||
|
|
|||
|
/* allow REG_NOTES to be set on last insn (labels don't have enough
|
|||
|
fields, and can't be used for REG_NOTES anyway). */
|
|||
|
emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
|
|||
|
DONE;
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
;;
|
|||
|
;; SHIFT INSTRUCTIONS
|
|||
|
;;
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 1)))]
|
|||
|
""
|
|||
|
"%0=%1>>1"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 4)))]
|
|||
|
""
|
|||
|
"%0=%1>>4"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 8)))]
|
|||
|
""
|
|||
|
"%0=%1>>8"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 16)))]
|
|||
|
""
|
|||
|
"%0=%1>>16"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
;;
|
|||
|
;; Arithmetic Right shift
|
|||
|
|
|||
|
(define_expand "ashrhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!TARGET_BMU)
|
|||
|
{
|
|||
|
/* If we are shifting by a constant we can do it in 1 or more
|
|||
|
1600 core shift instructions. The core instructions can
|
|||
|
shift by 1, 4, 8, or 16. */
|
|||
|
|
|||
|
if (GET_CODE(operands[2]) == CONST_INT)
|
|||
|
;
|
|||
|
else
|
|||
|
{
|
|||
|
rtx label1 = gen_label_rtx ();
|
|||
|
rtx label2 = gen_label_rtx ();
|
|||
|
|
|||
|
#if 0
|
|||
|
if (!dsp16xx_ashrhi3_libcall)
|
|||
|
dsp16xx_ashrhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, ASHRHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_ashrhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
#else
|
|||
|
do_pending_stack_adjust ();
|
|||
|
emit_insn (gen_tstqi (operands[2]));
|
|||
|
emit_jump_insn (gen_bne (label1));
|
|||
|
emit_move_insn (operands[0], operands[1]);
|
|||
|
emit_jump_insn (gen_jump (label2));
|
|||
|
emit_barrier ();
|
|||
|
emit_label (label1);
|
|||
|
|
|||
|
if (GET_CODE(operands[2]) != MEM)
|
|||
|
{
|
|||
|
rtx stack_slot;
|
|||
|
|
|||
|
stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0);
|
|||
|
stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0));
|
|||
|
emit_move_insn (stack_slot, operands[2]);
|
|||
|
operands[2] = stack_slot;
|
|||
|
}
|
|||
|
|
|||
|
emit_insn (gen_match_ashrhi3_nobmu (operands[0], operands[1], operands[2]));
|
|||
|
emit_label (label2);
|
|||
|
DONE;
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "match_ashrhi3_bmu"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "A,A,!A")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "B,I,h")))]
|
|||
|
"TARGET_BMU"
|
|||
|
"@
|
|||
|
%0=%1>>%2
|
|||
|
%0=%1>>%H2
|
|||
|
%0=%1>>%2"
|
|||
|
[(set_attr "type" "shift,shift_i,shift")])
|
|||
|
|
|||
|
(define_insn "match_ashrhi3_nobmu"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A")
|
|||
|
(ashiftrt:HI (match_operand:HI 1 "register_operand" "A,0")
|
|||
|
(match_operand:QI 2 "general_operand" "n,m")))]
|
|||
|
"!TARGET_BMU"
|
|||
|
"*
|
|||
|
{
|
|||
|
if (which_alternative == 0)
|
|||
|
{
|
|||
|
emit_1600_core_shift (ASHIFTRT, operands, INTVAL(operands[2]));
|
|||
|
return \"\";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
output_asm_insn (\"cloop=%2\", operands);
|
|||
|
output_asm_insn (\"do 0 \{\", operands);
|
|||
|
output_asm_insn (\"%0=%0>>1\", operands);
|
|||
|
return \"\}\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; Logical Right Shift
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 1)))]
|
|||
|
""
|
|||
|
"%0=%1>>1\;%0=%b0&0x7fff"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 4)))]
|
|||
|
""
|
|||
|
"%0=%1>>4\;%0=%b0&0x0fff"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 8)))]
|
|||
|
""
|
|||
|
"%0=%1>>8\;%0=%b0&0x00ff"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 16)))]
|
|||
|
""
|
|||
|
"%0=%1>>16\;%0=%b0&0x0000"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_expand "lshrhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!TARGET_BMU)
|
|||
|
{
|
|||
|
/* If we are shifting by a constant we can do it in 1 or more
|
|||
|
1600 core shift instructions. The core instructions can
|
|||
|
shift by 1, 4, 8, or 16. */
|
|||
|
|
|||
|
if (GET_CODE(operands[2]) == CONST_INT)
|
|||
|
emit_insn (gen_match_lshrhi3_nobmu (operands[0], operands[1], operands[2]));
|
|||
|
else
|
|||
|
{
|
|||
|
rtx label1 = gen_label_rtx ();
|
|||
|
rtx label2 = gen_label_rtx ();
|
|||
|
#if 0
|
|||
|
if (!dsp16xx_lshrhi3_libcall)
|
|||
|
dsp16xx_lshrhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, LSHRHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_lshrhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
#else
|
|||
|
do_pending_stack_adjust ();
|
|||
|
emit_insn (gen_tstqi (operands[2]));
|
|||
|
emit_jump_insn (gen_bne (label1));
|
|||
|
emit_move_insn (operands[0], operands[1]);
|
|||
|
emit_jump_insn (gen_jump (label2));
|
|||
|
emit_barrier ();
|
|||
|
emit_label (label1);
|
|||
|
|
|||
|
if (GET_CODE(operands[2]) != MEM)
|
|||
|
{
|
|||
|
rtx stack_slot;
|
|||
|
|
|||
|
stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0);
|
|||
|
stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0));
|
|||
|
emit_move_insn (stack_slot, operands[2]);
|
|||
|
operands[2] = stack_slot;
|
|||
|
}
|
|||
|
|
|||
|
emit_insn (gen_match_lshrhi3_nobmu (operands[0], operands[1], operands[2]));
|
|||
|
emit_label (label2);
|
|||
|
DONE;
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "match_lshrhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A,A,!A")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "B,I,h")))]
|
|||
|
"TARGET_BMU"
|
|||
|
"@
|
|||
|
%0=%1>>>%2
|
|||
|
%0=%1>>>%H2
|
|||
|
%0=%1>>>%2"
|
|||
|
[(set_attr "type" "shift,shift_i,shift")])
|
|||
|
|
|||
|
(define_insn "match_lshrhi3_nobmu"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A")
|
|||
|
(lshiftrt:HI (match_operand:HI 1 "register_operand" "A,0")
|
|||
|
(match_operand:QI 2 "general_operand" "n,m")))
|
|||
|
(clobber (match_scratch:QI 3 "=X,Y"))]
|
|||
|
"!TARGET_BMU"
|
|||
|
"*
|
|||
|
{
|
|||
|
if (which_alternative == 0)
|
|||
|
{
|
|||
|
emit_1600_core_shift (LSHIFTRT, operands, INTVAL(operands[2]));
|
|||
|
return \"\";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
output_asm_insn (\"%3=psw\;psw=0\",operands);
|
|||
|
output_asm_insn (\"cloop=%2\", operands);
|
|||
|
output_asm_insn (\"do 0 \{\", operands);
|
|||
|
output_asm_insn (\"%0=%0>>1\", operands);
|
|||
|
output_asm_insn (\"\}\", operands);
|
|||
|
return \"psw=%3\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; Arithmetic Left shift
|
|||
|
|
|||
|
;; Start off with special case arithmetic left shift by 1,4,8 or 16.
|
|||
|
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 1)))]
|
|||
|
""
|
|||
|
"%0=%1<<1"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 4)))]
|
|||
|
""
|
|||
|
"%0=%1<<4"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 8)))]
|
|||
|
""
|
|||
|
"%0=%1<<8"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "A"))
|
|||
|
(const_int 16)))]
|
|||
|
""
|
|||
|
"%0=%1<<16"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (match_operand:HI 1 "general_operand" "A")
|
|||
|
(const_int 16)))]
|
|||
|
""
|
|||
|
"%0=%1<<16"
|
|||
|
[(set_attr "type" "special")])
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;; Normal Arithmetic Shift Left
|
|||
|
|
|||
|
|
|||
|
(define_expand "ashlhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "")))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (!TARGET_BMU)
|
|||
|
{
|
|||
|
/* If we are shifting by a constant we can do it in 1 or more
|
|||
|
1600 core shift instructions. The core instructions can
|
|||
|
shift by 1, 4, 8, or 16. */
|
|||
|
|
|||
|
if (GET_CODE(operands[2]) == CONST_INT)
|
|||
|
;
|
|||
|
else
|
|||
|
{
|
|||
|
rtx label1 = gen_label_rtx ();
|
|||
|
rtx label2 = gen_label_rtx ();
|
|||
|
#if 0
|
|||
|
if (!dsp16xx_ashlhi3_libcall)
|
|||
|
dsp16xx_ashlhi3_libcall = gen_rtx (SYMBOL_REF, Pmode, ASHLHI3_LIBCALL);
|
|||
|
|
|||
|
emit_library_call (dsp16xx_ashlhi3_libcall, 1, HImode, 2,
|
|||
|
operands[1], HImode,
|
|||
|
operands[2], QImode);
|
|||
|
emit_move_insn (operands[0], hard_libcall_value(HImode));
|
|||
|
DONE;
|
|||
|
#else
|
|||
|
do_pending_stack_adjust ();
|
|||
|
emit_insn (gen_tstqi (operands[2]));
|
|||
|
emit_jump_insn (gen_bne (label1));
|
|||
|
emit_move_insn (operands[0], operands[1]);
|
|||
|
emit_jump_insn (gen_jump (label2));
|
|||
|
emit_barrier ();
|
|||
|
emit_label (label1);
|
|||
|
|
|||
|
if (GET_CODE(operands[2]) != MEM)
|
|||
|
{
|
|||
|
rtx stack_slot;
|
|||
|
|
|||
|
stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0);
|
|||
|
stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0));
|
|||
|
emit_move_insn (stack_slot, operands[2]);
|
|||
|
operands[2] = stack_slot;
|
|||
|
}
|
|||
|
emit_insn (gen_match_ashlhi3_nobmu (operands[0], operands[1], operands[2]));
|
|||
|
emit_label (label2);
|
|||
|
DONE;
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn "match_ashlhi3"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A,A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A,A,A")
|
|||
|
(match_operand:QI 2 "nonmemory_operand" "B,I,!h")))]
|
|||
|
"TARGET_BMU"
|
|||
|
"@
|
|||
|
%0=%1<<%2\;move %u0=%u0
|
|||
|
%0=%1<<%H2\;move %u0=%u0
|
|||
|
%0=%1<<%2\;move %u0=%u0"
|
|||
|
[(set_attr "type" "shift,shift_i,shift")])
|
|||
|
|
|||
|
(define_insn "match_ashlhi3_nobmu"
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A,A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A,0")
|
|||
|
(match_operand:QI 2 "general_operand" "n,m")))]
|
|||
|
"!TARGET_BMU"
|
|||
|
"*
|
|||
|
{
|
|||
|
if (which_alternative == 0)
|
|||
|
{
|
|||
|
emit_1600_core_shift (ASHIFT, operands, INTVAL(operands[2]));
|
|||
|
return \"\";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
output_asm_insn (\"cloop=%2\", operands);
|
|||
|
output_asm_insn (\"do 0 \{\", operands);
|
|||
|
output_asm_insn (\"%0=%0<<1\", operands);
|
|||
|
return \"\}\";
|
|||
|
}
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; Jump Instructions
|
|||
|
;;
|
|||
|
|
|||
|
(define_expand "beq"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (eq (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(EQ, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
(define_expand "bne"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (ne (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(NE, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "bgt"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (gt (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(GT, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "bge"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (ge (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(GE, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "blt"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (lt (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(LT, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "ble"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (le (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(LE, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "bgtu"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (gtu (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(GTU, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "bgeu"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (geu (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(GEU, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "bltu"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (ltu (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(LTU, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_expand "bleu"
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (leu (match_dup 1)
|
|||
|
(const_int 0))
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (dsp16xx_compare_gen == gen_compare_reg)
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(LEU, dsp16xx_compare_op0, dsp16xx_compare_op1);
|
|||
|
else
|
|||
|
operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0);
|
|||
|
}")
|
|||
|
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (match_operator 1 "comparison_operator"
|
|||
|
[(cc0) (const_int 0)])
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
"!TARGET_NEAR_JUMP"
|
|||
|
"pt=%l0\;if %C1 goto pt"
|
|||
|
[(set_attr "type" "cond_jump")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (match_operator 1 "comparison_operator"
|
|||
|
[(cc0) (const_int 0)])
|
|||
|
(label_ref (match_operand 0 "" ""))
|
|||
|
(pc)))]
|
|||
|
"TARGET_NEAR_JUMP"
|
|||
|
"if %C1 goto %l0"
|
|||
|
[(set_attr "type" "cond_jump")])
|
|||
|
|
|||
|
;;
|
|||
|
;; Negated conditional jump instructions.
|
|||
|
;; These are necessary because jump optimization can turn
|
|||
|
;; direct-conditional branches into reverse-conditional
|
|||
|
;; branches.
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (match_operator 1 "comparison_operator"
|
|||
|
[(cc0) (const_int 0)])
|
|||
|
(pc)
|
|||
|
(label_ref (match_operand 0 "" ""))))]
|
|||
|
"!TARGET_NEAR_JUMP"
|
|||
|
"pt=%l0\;if %I1 goto pt"
|
|||
|
[(set_attr "type" "cond_jump")])
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(set (pc)
|
|||
|
(if_then_else (match_operator 1 "comparison_operator"
|
|||
|
[(cc0) (const_int 0)])
|
|||
|
(pc)
|
|||
|
(label_ref (match_operand 0 "" ""))))]
|
|||
|
"TARGET_NEAR_JUMP"
|
|||
|
"if %I1 goto %l0"
|
|||
|
[(set_attr "type" "cond_jump")])
|
|||
|
|
|||
|
|
|||
|
;;
|
|||
|
;; JUMPS
|
|||
|
;;
|
|||
|
|
|||
|
(define_insn "jump"
|
|||
|
[(set (pc)
|
|||
|
(label_ref (match_operand 0 "" "")))]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
if (TARGET_NEAR_JUMP)
|
|||
|
return \"goto %l0\";
|
|||
|
else
|
|||
|
return \"pt=%l0\;goto pt\";
|
|||
|
}"
|
|||
|
[(set_attr "type" "jump")])
|
|||
|
|
|||
|
|
|||
|
(define_insn "indirect_jump"
|
|||
|
[(set (pc) (match_operand:QI 0 "register_operand" "A"))]
|
|||
|
""
|
|||
|
"pt=%0\;goto pt"
|
|||
|
[(set_attr "type" "jump")])
|
|||
|
|
|||
|
(define_insn "tablejump"
|
|||
|
[(set (pc) (match_operand:QI 0 "register_operand" "A"))
|
|||
|
(use (label_ref (match_operand 1 "" "")))]
|
|||
|
""
|
|||
|
"pt=%0\;goto pt"
|
|||
|
[(set_attr "type" "jump")])
|
|||
|
|
|||
|
;;
|
|||
|
;; FUNCTION CALLS
|
|||
|
;;
|
|||
|
|
|||
|
;; Call subroutine with no return value.
|
|||
|
|
|||
|
|
|||
|
(define_expand "call"
|
|||
|
[(parallel [(call (match_operand:QI 0 "" "")
|
|||
|
(match_operand 1 "" ""))
|
|||
|
(clobber (reg:QI 24))])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (GET_CODE (operands[0]) == MEM
|
|||
|
&& ! call_address_operand (XEXP (operands[0], 0), QImode))
|
|||
|
operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
|
|||
|
force_reg (Pmode, XEXP (operands[0], 0)));
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(parallel [(call (mem:QI (match_operand:QI 0 "call_address_operand" "hR"))
|
|||
|
(match_operand 1 "" ""))
|
|||
|
(clobber (reg:QI 24))])]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
if (GET_CODE (operands[0]) == REG ||
|
|||
|
(GET_CODE(operands[0]) == SYMBOL_REF && !TARGET_NEAR_CALL))
|
|||
|
return \"pt=%0\;call pt\";
|
|||
|
else
|
|||
|
return \"call %0\";
|
|||
|
}"
|
|||
|
[(set_attr "type" "call")])
|
|||
|
|
|||
|
;; Call subroutine with return value.
|
|||
|
|
|||
|
(define_expand "call_value"
|
|||
|
[(parallel [(set (match_operand 0 "register_operand" "=f")
|
|||
|
(call (match_operand:QI 1 "call_address_operand" "hR")
|
|||
|
(match_operand:QI 2 "" "")))
|
|||
|
(clobber (reg:QI 24))])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
if (GET_CODE (operands[1]) == MEM
|
|||
|
&& ! call_address_operand (XEXP (operands[1], 0), QImode))
|
|||
|
operands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
|
|||
|
force_reg (Pmode, XEXP (operands[1], 0)));
|
|||
|
}")
|
|||
|
|
|||
|
(define_insn ""
|
|||
|
[(parallel [(set (match_operand 0 "register_operand" "=f")
|
|||
|
(call (mem:QI (match_operand:QI 1 "call_address_operand" "hR"))
|
|||
|
(match_operand:QI 2 "" "")))
|
|||
|
(clobber (reg:QI 24))])]
|
|||
|
""
|
|||
|
"*
|
|||
|
{
|
|||
|
if (GET_CODE (operands[1]) == REG ||
|
|||
|
(GET_CODE(operands[1]) == SYMBOL_REF && !TARGET_NEAR_CALL))
|
|||
|
return \"pt=%1\;call pt\";
|
|||
|
else
|
|||
|
return \"call %1\";
|
|||
|
}"
|
|||
|
[(set_attr "type" "call")])
|
|||
|
|
|||
|
|
|||
|
(define_expand "untyped_call"
|
|||
|
[(parallel [(call (match_operand 0 "" "")
|
|||
|
(const_int 0))
|
|||
|
(match_operand 1 "" "")
|
|||
|
(match_operand 2 "" "")])]
|
|||
|
""
|
|||
|
"
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
|
|||
|
|
|||
|
for (i = 0; i < XVECLEN (operands[2], 0); i++)
|
|||
|
{
|
|||
|
rtx set = XVECEXP (operands[2], 0, i);
|
|||
|
emit_move_insn (SET_DEST (set), SET_SRC (set));
|
|||
|
}
|
|||
|
|
|||
|
/* The optimizer does not know that the call sets the function value
|
|||
|
registers we stored in the result block. We avoid problems by
|
|||
|
claiming that all hard registers are used and clobbered at this
|
|||
|
point. */
|
|||
|
emit_insn (gen_blockage ());
|
|||
|
|
|||
|
DONE;
|
|||
|
}")
|
|||
|
|
|||
|
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
|
|||
|
;; all of memory. This blocks insns from being moved across this point.
|
|||
|
|
|||
|
(define_insn "blockage"
|
|||
|
[(unspec_volatile [(const_int 0)] 0)]
|
|||
|
""
|
|||
|
"")
|
|||
|
|
|||
|
(define_insn "nop"
|
|||
|
[(const_int 0)]
|
|||
|
""
|
|||
|
"nop"
|
|||
|
[(set_attr "type" "nop")])
|
|||
|
|
|||
|
;;
|
|||
|
;; PEEPHOLE PATTERNS
|
|||
|
;;
|
|||
|
|
|||
|
|
|||
|
(define_peephole
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=A")
|
|||
|
(reg:QI 16))
|
|||
|
(call (mem:QI (match_dup 0))
|
|||
|
(match_operand 1 "" "i"))]
|
|||
|
""
|
|||
|
"call pt")
|
|||
|
|
|||
|
|
|||
|
(define_peephole
|
|||
|
[(set (match_operand:QI 0 "register_operand" "=A")
|
|||
|
(reg:QI 16))
|
|||
|
(set (match_operand 1 "" "")
|
|||
|
(call (mem:QI (match_dup 0))
|
|||
|
(match_operand 2 "" "i")))]
|
|||
|
""
|
|||
|
"call pt")
|
|||
|
|
|||
|
(define_peephole
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 16)))
|
|||
|
(set (match_operand:HI 2 "register_operand" "")
|
|||
|
(match_dup 0))
|
|||
|
(set (match_dup 0)
|
|||
|
(ashiftrt:HI (match_dup 0) (const_int 16)))
|
|||
|
(set (match_dup 2)
|
|||
|
(match_dup 0))]
|
|||
|
""
|
|||
|
"%0=%1<<16\;%0=%0>>16\;%u2=%u0\;%w2=%w0")
|
|||
|
|
|||
|
(define_peephole
|
|||
|
[(set (match_operand:HI 0 "register_operand" "=A")
|
|||
|
(ashift:HI (match_operand:HI 1 "register_operand" "A")
|
|||
|
(const_int 16)))
|
|||
|
(set (match_operand:HI 2 "register_operand" "")
|
|||
|
(match_dup 0))
|
|||
|
(set (match_dup 0)
|
|||
|
(lshiftrt:HI (match_dup 0) (const_int 16)))
|
|||
|
(set (match_dup 2)
|
|||
|
(match_dup 0))]
|
|||
|
""
|
|||
|
"%0=%1<<16\;%0=%0>>16\;%0=%b0&0x0000\;%u2=%u0\;%w2=%w0")
|