56 KiB
;;- 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" "Zrmi")
(match_operand:HI 1 "general_operand" "Zrmi")))
(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")