Commit d93578fe by Richard Kenner

Initial revision

From-SVN: r8051
parent 946730d0
;;- Machine description for the AT&T DSP1600 for GNU C compiler
;; Copyright (C) 1994 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, 675 Mass Ave, Cambridge, MA 02139, 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 (\"Illegal 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 (\"Illegal 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:HI (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 mneumonic otherwise the 1610 will
attempt to transfer all 32-bits of 'y', 'p' or an accumualtor
, 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 mneumonic otherwise the 1610 will
attempt to transfer all 32-bits of 'y', 'p' or an accumualtor
, 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] = gen_rtx (MEM, BLKmode, addr0);
operands[1] = gen_rtx (MEM, BLKmode, 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")
/* Configuration file for GNU CC for AT&T DSP1600.
Copyright (C) 1993 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* #defines that need visibility everywhere. */
#define FALSE 0
#define TRUE 1
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
#define HOST_BITS_PER_INT 16
#define HOST_BITS_PER_LONG 32
#define HOST_BITS_PER_LONGLONG 64
/* Arguments to use with `exit'. */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
/* If compiled with GNU C, use the built-in alloca */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#define USE_C_ALLOCA
#endif
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment