;;- Machine description for SPUR chip for GNU C compiler ;; Copyright (C) 1988 Free Software Foundation, Inc.
;; This file is part of GNU CC.
;; GNU CC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY. No author or distributor ;; accepts responsibility to anyone for the consequences of using it ;; or for whether it serves any particular purpose or works at all, ;; unless he says so in writing. Refer to the GNU CC General Public ;; License for full details.
;; Everyone is granted permission to copy, modify and redistribute ;; GNU CC, but only under the conditions described in the ;; GNU CC General Public License. A copy of this license is ;; supposed to have been given to you along with GNU CC so you ;; can know your rights and responsibilities. It should be in a ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies.
;;- See file "rtl.def" for documentation on defineinsn, match*, et. al.
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code ;;- updates for most instructions.
;;- Operand classes for the register allocator: ;; Compare instructions. ;; This pattern is used for generating an "insn" ;; which does just a compare and sets a (fictitious) condition code.
;; The actual SPUR insns are compare-and-conditional-jump. ;; The define_peephole's below recognize the combinations of ;; compares and jumps, and output each pair as a single assembler insn.
;; This controls RTL generation and register allocation. (define_insn "cmpsi" [(set (cc0)
(minus (match_operand:SI 0 "nonmemory_operand" "rK")
(match_operand:SI 1 "nonmemory_operand" "rK")))]
"" "* { cc_status.value1 = operands[0], cc_status.value2 = operands[1]; return \"\"; }")
;; We have to have this because cse can optimize the previous pattern ;; into this one.
(define_insn "tstsi" [(set (cc0)
(match_operand:SI 0 "register_operand" "r"))]
"" "* { cc_status.value1 = operands[0], cc_status.value2 = const0_rtx; return \"\"; }")
;; These control RTL generation for conditional jump insns ;; and match them for register allocation.
(define_insn "beq" [(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"eq\", \"eq\"); ")
(define_insn "bne" [(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"ne\", \"ne\"); ")
(define_insn "bgt" [(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"gt\", \"lt\"); ")
(define_insn "bgtu" [(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"ugt\", \"ult\"); ")
(define_insn "blt" [(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"lt\", \"gt\"); ")
(define_insn "bltu" [(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"ult\", \"ugt\"); ")
(define_insn "bge" [(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"ge\", \"le\"); ")
(define_insn "bgeu" [(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"uge\", \"ule\"); ")
(define_insn "ble" [(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"le\", \"ge\"); ")
(define_insn "bleu" [(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
"" "* return output_compare (operands, \"ule\", \"uge\"); ") ;; These match inverted jump insns for register allocation.
(define_insn "" [(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"ne\", \"ne\"); ")
(define_insn "" [(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"eq\", \"eq\"); ")
(define_insn "" [(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"le\", \"ge\"); ")
(define_insn "" [(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"ule\", \"uge\"); ")
(define_insn "" [(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"ge\", \"le\"); ")
(define_insn "" [(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"uge\", \"ule\"); ")
(define_insn "" [(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"lt\", \"gt\"); ")
(define_insn "" [(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"ult\", \"ugt\"); ")
(define_insn "" [(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"gt\", \"lt\"); ")
(define_insn "" [(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
"" "* return output_compare (operands, \"ugt\", \"ult\"); ") ;; Move instructions
(define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=r,m")
(match_operand:SI 1 "general_operand" "rmi,rJ"))]
"" "* { if (GET_CODE (operands[0]) == MEM)
return \"st_32 %r1,%0\";
if (GET_CODE (operands[1]) == MEM)
return \"ld_32 %0,%1\;nop\";
if (GET_CODE (operands[1]) == REG)
return \"add_nt %0,%1,$0\";
if (GET_CODE (operands[1]) == SYMBOL_REF && operands[1]->unchanging)
return \"add_nt %0,r24,$(%1-0b)\";
return \"add_nt %0,r0,%1\"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r")
(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r"))))]
"" "ld_32 %0,%1,%2\;nop") ;; Generate insns for moving single bytes.
(define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
"" " { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = copy_to_reg (operands[1]);
if (GET_CODE (operands[1]) == MEM)
{
rtx tem = gen_reg_rtx (SImode);
rtx addr = force_reg (SImode, XEXP (operands[1], 0));
emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
emit_insn (gen_rtx (SET, VOIDmode,
gen_rtx (SUBREG, SImode, operands[0], 0),
gen_rtx (ZERO_EXTRACT, SImode, tem,
gen_rtx (CONST_INT, VOIDmode, 8),
addr)));
}
else if (GET_CODE (operands[0]) == MEM)
{
rtx tem = gen_reg_rtx (SImode);
rtx addr = force_reg (SImode, XEXP (operands[0], 0));
emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
if (! CONSTANT_ADDRESS_P (operands[1]))
operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
emit_insn (gen_rtx (SET, VOIDmode,
gen_rtx (ZERO_EXTRACT, SImode, tem,
gen_rtx (CONST_INT, VOIDmode, 8),
addr),
operands[1]));
emit_move_insn (gen_rtx (MEM, SImode, addr), tem);
}
else
{
emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
}
DONE; }") ;; Recognize insns generated for moving single bytes.
(define_insn "" [(set (match_operand:QI 0 "general_operand" "=r,m")
(match_operand:QI 1 "general_operand" "rmi,r"))]
"" "* { if (GET_CODE (operands[0]) == MEM)
return \"st_32 %1,%0\";
if (GET_CODE (operands[1]) == MEM)
return \"ld_32 %0,%1\;nop\";
if (GET_CODE (operands[1]) == REG)
return \"add_nt %0,%1,$0\";
return \"add_nt %0,r0,%1\"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(const_int 8)
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "extract %0,%1,%2")
(define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(const_int 8)
(match_operand:SI 1 "nonmemory_operand" "rI"))
(match_operand:SI 2 "nonmemory_operand" "ri"))]
"" "wr_insert %1\;insert %0,%0,%2")
;; Constant propagation can optimize the previous pattern into this pattern. ;[Not any more. It could when the position-operand contains a MULT.]
;(define_insn "" ; [(set (zero_extract:QI (match_operand:SI 0 "register_operand" "+r") ; (const_int 8) ; (match_operand:SI 1 "immediate_operand" "I")) ; (match_operand:QI 2 "register_operand" "r"))] ; "GET_CODE (operands[1]) == CONST_INT ; && INTVAL (operands[1]) % 8 == 0 ; && (unsigned) INTVAL (operands[1]) < 32" ; "* ;{ ; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8); ; return \"wr_insert 0,0,%1\;insert %0,%0,%2\"; ;}") ;; The three define_expand patterns on this page ;; serve as subroutines of "movhi".
;; Generate code to fetch an aligned halfword from memory. ;; Operand 0 is the destination register (HImode). ;; Operand 1 is the memory address (SImode). ;; Operand 2 is a temporary (SImode). ;; Operand 3 is a temporary (SImode). ;; Operand 4 is a temporary (QImode).
(define_expand "loadhi" [(set (match_operand:SI 2 "register_operand" "")
(mem:SI (match_operand:SI 1 "register_operand" "")))
;; Extract the low byte. (set (subreg:SI (match_dup 5) 0)
(zero_extract:SI (match_dup 2) (const_int 8) (match_dup 1)))
;; Form address of high byte. (set (match_operand:SI 3 "register_operand" "")
(plus:SI (match_dup 1) (const_int 1)))
;; Extract the high byte. (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
(zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3)))
;; Put the high byte in with the low one. (set (zero_extract:SI (match_dup 5) (const_int 8) (const_int 1))
(subreg:SI (match_dup 4) 0))
(set (match_operand:HI 0 "register_operand" "") (match_dup 5))] "" "operands[5] = gen_reg_rtx (HImode);")
;; Generate code to store an aligned halfword into memory. ;; Operand 0 is the destination address (SImode). ;; Operand 1 is the source register (HImode, not constant). ;; Operand 2 is a temporary (SImode). ;; Operand 3 is a temporary (SImode). ;; Operand 4 is a temporary (QImode).
(define_expand "storehi" [(set (match_operand:SI 2 "register_operand" "")
(mem:SI (match_operand:SI 0 "register_operand" "")))
;; Insert the low byte. (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
(subreg:SI (match_operand:HI 1 "register_operand" "") 0))
;; Form address of high byte. (set (match_operand:SI 3 "register_operand" "")
(plus:SI (match_dup 0) (const_int 1)))
;; Extract the high byte from the source. (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
(zero_extract:SI (match_dup 1) (const_int 8) (const_int 1)))
;; Store high byte into the memory word (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
(subreg:SI (match_dup 4) 0))
;; Put memory word back into memory. (set (mem:SI (match_dup 0))
(match_dup 2))]
"" "")
;; Like storehi but operands[1] is a CONST_INT.
(define_expand "storeinthi" [(set (match_operand:SI 2 "register_operand" "")
(mem:SI (match_operand:SI 0 "register_operand" "")))
;; Insert the low byte. (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
(match_dup 5))
;; Form address of high byte. (set (match_operand:SI 3 "register_operand" "")
(plus:SI (match_dup 0) (const_int 1)))
;; Store high byte into the memory word (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
(match_dup 6))
;; Put memory word back into memory. (set (mem:SI (match_dup 0))
(match_dup 2))]
"" " operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 255);
operands[6] = gen_rtx (CONST_INT, VOIDmode,
(INTVAL (operands[1]) >> 8) & 255);
") ;; Main entry for generating insns to move halfwords.
(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
"" " { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = copy_to_reg (operands[1]);
if (GET_CODE (operands[1]) == MEM)
{
rtx insn =
emit_insn (gen_loadhi (operands[0],
force_reg (SImode, XEXP (operands[1], 0)),
gen_reg_rtx (SImode), gen_reg_rtx (SImode),
gen_reg_rtx (QImode)));
/* Tell cse what value the loadhi produces, so it detect duplicates. */
REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], 0);
}
else if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (operands[1]) == CONST_INT)
emit_insn (gen_storeinthi (force_reg (SImode, XEXP (operands[0], 0)),
operands[1],
gen_reg_rtx (SImode), gen_reg_rtx (SImode),
gen_reg_rtx (QImode)));
else
{
if (CONSTANT_P (operands[1]))
operands[1] = force_reg (HImode, operands[1]);
emit_insn (gen_storehi (force_reg (SImode, XEXP (operands[0], 0)),
operands[1],
gen_reg_rtx (SImode), gen_reg_rtx (SImode),
gen_reg_rtx (QImode)));
}
}
else
emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
DONE; }") ;; Recognize insns generated for moving halfwords. ;; (Note that the extract and insert patterns for single-byte moves ;; are also involved in recognizing some of the insns used for this purpose.)
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=r,m")
(match_operand:HI 1 "general_operand" "rmi,r"))]
"" "* { if (GET_CODE (operands[0]) == MEM)
return \"st_32 %1,%0\";
if (GET_CODE (operands[1]) == MEM)
return \"ld_32 %0,%1\;nop\";
if (GET_CODE (operands[1]) == REG)
return \"add_nt %0,%1,$0\";
return \"add_nt %0,r0,%1\"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (match_operand:HI 1 "register_operand" "r")
(const_int 8)
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "extract %0,%1,%2")
(define_insn "" [(set (zero_extract:SI (match_operand:HI 0 "register_operand" "+r")
(const_int 8)
(match_operand:SI 1 "nonmemory_operand" "rI"))
(match_operand:SI 2 "nonmemory_operand" "ri"))]
"" "wr_insert %1\;insert %0,%0,%2")
;; Constant propagation can optimize the previous pattern into this pattern.
;(define_insn "" ; [(set (zero_extract:QI (match_operand:HI 0 "register_operand" "+r") ; (const_int 8) ; (match_operand:SI 1 "immediate_operand" "I")) ; (match_operand:QI 2 "register_operand" "r"))] ; "GET_CODE (operands[1]) == CONST_INT ; && INTVAL (operands[1]) % 8 == 0 ; && (unsigned) INTVAL (operands[1]) < 32" ; "* ;{ ; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8); ; return \"wr_insert 0,0,%1\;insert %0,%0,%2\"; ;}") ;; This pattern forces (set (reg:DF ...) (const_double ...)) ;; to be reloaded by putting the constant into memory. ;; It must come before the more general movdf pattern. (define_insn "" [(set (match_operand:DF 0 "general_operand" "=r,f,o")
(match_operand:DF 1 "" "mG,m,G"))]
"GET_CODE (operands[1]) == CONST_DOUBLE" "* { if (FP_REG_P (operands[0]))
return output_fp_move_double (operands);
if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
{
operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
return \"add_nt %0,r0,$0\;add_nt %1,r0,$0\";
}
if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
{
operands[1] = adj_offsetable_operand (operands[0], 4);
return \"st_32 r0,%0\;st_32 r0,%1\";
}
return output_move_double (operands); } ")
(define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=r,m,?f,?rm")
(match_operand:DF 1 "general_operand" "rm,r,rfm,f"))]
"" "* { if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
return output_fp_move_double (operands);
return output_move_double (operands); } ")
(define_insn "movdi" [(set (match_operand:DI 0 "general_operand" "=r,m,?f,?rm")
(match_operand:DI 1 "general_operand" "rm,r,rfm,f"))]
"" "* { if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
return output_fp_move_double (operands);
return output_move_double (operands); } ")
(define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=rf,m")
(match_operand:SF 1 "general_operand" "rfm,rf"))]
"" "* { if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1]))
return \"fmov %0,%1\";
if (GET_CODE (operands[1]) == REG)
{
rtx xoperands[2];
int offset = - get_frame_size () - 8;
xoperands[1] = operands[1];
xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
output_asm_insn (\"st_32 %1,r25,%0\", xoperands);
xoperands[1] = operands[0];
output_asm_insn (\"ld_sgl %1,r25,%0\;nop\", xoperands);
return \"\";
}
return \"ld_sgl %0,%1\;nop\";
}
if (FP_REG_P (operands[1]))
{
if (GET_CODE (operands[0]) == REG)
{
rtx xoperands[2];
int offset = - get_frame_size () - 8;
xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
xoperands[1] = operands[1];
output_asm_insn (\"st_sgl %1,r25,%0\", xoperands);
xoperands[1] = operands[0];
output_asm_insn (\"ld_32 %1,r25,%0\;nop\", xoperands);
return \"\";
}
return \"st_sgl %1,%0\";
}
if (GET_CODE (operands[0]) == MEM)
return \"st_32 %r1,%0\";
if (GET_CODE (operands[1]) == MEM)
return \"ld_32 %0,%1\;nop\";
if (GET_CODE (operands[1]) == REG)
return \"add_nt %0,%1,$0\";
return \"add_nt %0,r0,%1\"; }") ;;- truncation instructions ;; I think these are unnecessary, since subreg will be used instead. ;(define_insn "truncsiqi2" ; [(set (match_operand:QI 0 "register_operand" "=r") ; (truncate:QI ; (match_operand:SI 1 "register_operand" "r")))] ; "" ; "add_nt, %0,%1,$0") ; ;(define_insn "trunchiqi2" ; [(set (match_operand:QI 0 "register_operand" "=r") ; (truncate:QI ; (match_operand:HI 1 "register_operand" "r")))] ; "" ; "add_nt, %0,%1,$0") ; ;(define_insn "truncsihi2" ; [(set (match_operand:HI 0 "register_operand" "=r") ; (truncate:HI ; (match_operand:SI 1 "register_operand" "r")))] ; "" ; "add_nt, %0,%1,$0") ;;- zero extension instructions
;; Note that the one starting from HImode comes before those for QImode ;; so that a constant operand will match HImode, not QImode. (define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "")
(and:SI (subreg:SI (match_operand:HI 1 "register_operand" "") 0)
;; This constant is invalid, but reloading will handle it.
;; It's useless to generate here the insns to construct it
;; because constant propagation would simplify them anyway.
(match_dup 2)))]
"" " operands[2] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535)); ")
(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI
(match_operand:QI 1 "register_operand" "r")))]
"" "extract %0,%1,$0")
(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI
(match_operand:QI 1 "register_operand" "r")))]
"" "extract %0,%1,$0") ;;- sign extension instructions ;; Note that the one starting from HImode comes before those for QImode ;; so that a constant operand will match HImode, not QImode.
(define_expand "extendhisi2" [(set (match_dup 2)
(and:SI (subreg:SI (match_operand:HI 1 "register_operand" "") 0)
(match_dup 4)))
(set (match_dup 3) (plus:SI (match_dup 2) (match_dup 5))) (set (match_operand:SI 0 "register_operand" "")
(xor:SI (match_dup 3) (match_dup 5)))]
"" " { operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode); operands[4] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535)); operands[5] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, -32768)); }")
(define_expand "extendqihi2" [(set (match_dup 2)
(and:HI (subreg:HI (match_operand:QI 1 "register_operand" "") 0)
(const_int 255)))
(set (match_dup 3)
(plus:SI (match_dup 2) (const_int -128)))
(set (match_operand:HI 0 "register_operand" "")
(xor:SI (match_dup 3) (const_int -128)))]
"" " { operands[2] = gen_reg_rtx (HImode); operands[3] = gen_reg_rtx (HImode); }")
(define_expand "extendqisi2" [(set (match_dup 2)
(and:SI (subreg:SI (match_operand:QI 1 "register_operand" "") 0)
(const_int 255)))
(set (match_dup 3) (plus:SI (match_dup 2) (const_int -128))) (set (match_operand:SI 0 "register_operand" "")
(xor:SI (match_dup 3) (const_int -128)))]
"" " { operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode); }") ;;- arithmetic instructions
(define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "add %0,%1,%2")
(define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "sub %0,%1,%2")
(define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "and %0,%1,%2")
(define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "or %0,%1,%2")
(define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r")
(xor:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rI")))]
"" "xor %0,%1,%2")
(define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "nonmemory_operand" "rI")))]
"" "sub %0,r0,%1")
(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_operand:SI 1 "register_operand" "r")))]
"" "xor %0,%1,$-1") ;; Floating point arithmetic instructions.
(define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f")
(plus:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
"TARGET_FPU" "fadd %0,%1,%2")
(define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f")
(plus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU" "fadd %0,%1,%2")
(define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f")
(minus:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
"TARGET_FPU" "fsub %0,%1,%2")
(define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f")
(minus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU" "fsub %0,%1,%2")
(define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f")
(mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
"TARGET_FPU" "fmul %0,%1,%2")
(define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f")
(mult:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU" "fmul %0,%1,%2")
(define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f")
(div:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
"TARGET_FPU" "fdiv %0,%1,%2")
(define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU" "fdiv %0,%1,%2")
(define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f")
(neg:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
"TARGET_FPU" "fneg %0,%1")
(define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
"TARGET_FPU" "fneg %0,%1")
(define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f")
(abs:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
"TARGET_FPU" "fabs %0,%1")
(define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f")
(abs:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
"TARGET_FPU" "fabs %0,%1") ;; Shift instructions
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "I")))]
"GET_CODE (operands[2]) == CONST_INT && (unsigned) INTVAL (operands[2]) <= 3" "sll %0,%1,%2")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 1)))]
"" "sra %0,%1,$1")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 1)))]
"" "srl %0,%1,$1")
(define_expand "ashlsi3" [(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
"" " { if (GET_CODE (operands[2]) != CONST_INT
|| (unsigned) INTVAL (operands[2]) > 3)
FAIL;
}")
(define_expand "lshlsi3" [(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
"" " { if (GET_CODE (operands[2]) != CONST_INT
|| (unsigned) INTVAL (operands[2]) > 3)
FAIL;
}")
(define_expand "ashrsi3" [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
"" " { if (GET_CODE (operands[2]) != CONST_INT
|| (unsigned) INTVAL (operands[2]) > 1)
FAIL;
}")
(define_expand "lshrsi3" [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
"" " { if (GET_CODE (operands[2]) != CONST_INT
|| (unsigned) INTVAL (operands[2]) > 1)
FAIL;
}") ;; Unconditional and other jump instructions (define_insn "jump" [(set (pc)
(label_ref (match_operand 0 "" "")))]
"" "jump %l0\;nop")
(define_insn "tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" "jump_reg r0,%0\;nop")
;;- jump to subroutine (define_insn "call" [(call (match_operand:SI 0 "memory_operand" "m")
(match_operand:SI 1 "general_operand" "g"))]
;;- Don't use operand 1 for most machines. "" "add_nt r9,%0\;call .+8\;jump_reg r0,r9\;nop")
(define_insn "call_value" [(set (match_operand 0 "" "g")
(call (match_operand:SI 1 "memory_operand" "m")
(match_operand:SI 2 "general_operand" "g")))]
;;- Don't use operand 1 for most machines. "" "add_nt r9,%1\;call .+8\;jump_reg r0,r9\;nop")
;; A memory ref with constant address is not normally valid. ;; But it is valid in a call insns. This pattern allows the ;; loading of the address to combine with the call. (define_insn "" [(call (mem:SI (match_operand:SI 0 "" "i"))
(match_operand:SI 1 "general_operand" "g"))]
;;- Don't use operand 1 for most machines. "GET_CODE (operands[0]) == SYMBOL_REF" "call %0\;nop")
(define_insn "" [(set (match_operand 0 "" "g")
(call (mem:SI (match_operand:SI 1 "" "i"))
(match_operand:SI 2 "general_operand" "g")))]
;;- Don't use operand 1 for most machines. "GET_CODE (operands[1]) == SYMBOL_REF" "call %1\;nop") ;;- Local variables: ;;- mode:emacs-lisp ;;- comment-start: ";;- " ;;- eval: (set-syntax-table (copy-sequence (syntax-table))) ;;- eval: (modify-syntax-entry ?[ "(]") ;;- eval: (modify-syntax-entry ?] ")[") ;;- eval: (modify-syntax-entry ?{ "(}") ;;- eval: (modify-syntax-entry ?} "){") ;;- End: