;;- Machine description for GNU compiler ;;- Fujitsu Gmicro Version ;;- Ported by M.Yuhara, Fujitsu Laboratories LTD. ;; ;; Copyright (C) 1990 Free Software Foundation, Inc. ;; 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. ;; Among other things, the copyright ;; notice and this notice must be preserved on all copies. ;; 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. ;;- instruction definitions ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ;;- When naming insn's (operand 0 of define_insn) be careful about using ;;- names from other targets machine descriptions. ;;- cpp macro #define NOTICE_UPDATE_CC is essentially a no-op for the ;;- gmicro; no compares are eliminated. ;;- The original structure of this file is m68k.md. ;; ??? Work to be done: ;; Add patterns for ACB and SCB instructions. ;; Add define_insn patterns to recognize the insns that extend a byte ;; to a word and add it into a word, etc. ;;- Some of these insn's are composites of several Gmicro op codes. ;;- The assembler (or final @@??) insures that the appropriate one is ;;- selected. (define_insn "" [(set (match_operand:DF 0 "push_operand" "=m") (match_operand:DF 1 "general_operand" "rmfF"))] "" "* { if (FPU_REG_P (operands[1])) return \"fmov.d %f1,%0\"; return output_move_double (operands); }") (define_insn "" [(set (match_operand:DI 0 "push_operand" "=m") (match_operand:DF 1 "general_operand" "rmF"))] "" "* { return output_move_double (operands); }") ;; We don't want to allow a constant operand for test insns because ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway. (define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "rm"))] "" "cmp:z.w #0,%0") (define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" "rm"))] "" "cmp:z.h #0,%0") (define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" "rm"))] "" "cmp:z.b #0,%0") (define_insn "tstsf" [(set (cc0) (match_operand:SF 0 "general_operand" "fmF"))] "TARGET_FPU" "* { cc_status.flags = CC_IN_FPU; return \"ftst.s %0\"; }") (define_insn "tstdf" [(set (cc0) (match_operand:DF 0 "general_operand" "fmF"))] "TARGET_FPU" "* { cc_status.flags = CC_IN_FPU; return \"ftst.d %0\"; }") ;; compare instructions. ;; (operand0 - operand1) (define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "ri,rm") (match_operand:SI 1 "general_operand" "rm,rmi")))] "" "* { int signed_flag = my_signed_comp (insn); if (which_alternative == 0) { cc_status.flags |= CC_REVERSED; if (signed_flag && GET_CODE (operands[0]) == CONST_INT) { register rtx xfoo; xfoo = operands[1]; operands[0] = operands[1]; operands[1] = xfoo; return cmp_imm_word (INTVAL (operands[1]), operands[0]); } if (signed_flag) return \"cmp.w %0,%1\"; return \"cmpu.w %0,%1\"; } if (signed_flag) { if (GET_CODE (operands[1]) == CONST_INT) return cmp_imm_word (INTVAL (operands[1]), operands[0]); return \"cmp.w %1,%0\"; } else return \"cmpu.w %1,%0\"; }") (define_insn "cmphi" [(set (cc0) (compare (match_operand:HI 0 "nonimmediate_operand" "ri,rm") (match_operand:HI 1 "general_operand" "rm,rmi")))] "" "* { int signed_flag = my_signed_comp (insn); if (which_alternative == 0) { cc_status.flags |= CC_REVERSED; if (signed_flag) return \"cmp.h %0,%1\"; return \"cmpu.h %0,%1\"; } if (signed_flag) return \"cmp.h %1,%0\"; return \"cmpu.h %1,%0\"; }") (define_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "nonimmediate_operand" "ri,rm") (match_operand:QI 1 "general_operand" "rm,rmi")))] "" "* { int signed_flag = my_signed_comp (insn); if (which_alternative == 0) { cc_status.flags |= CC_REVERSED; if (signed_flag) return \"cmp.b %0,%1\"; return \"cmpu.b %0,%1\"; } if (signed_flag) return \"cmp.b %1,%0\"; return \"cmpu.b %1,%0\"; }") (define_insn "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "general_operand" "f,mG") (match_operand:DF 1 "general_operand" "fmG,f")))] "TARGET_FPU" "* { cc_status.flags = CC_IN_FPU; if (FPU_REG_P (operands[0])) return \"fcmp.d %f1,%f0\"; cc_status.flags |= CC_REVERSED; return \"fcmp.d %f0,%f1\"; }") (define_insn "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "general_operand" "f,mG") (match_operand:SF 1 "general_operand" "fmG,f")))] "TARGET_FPU" "* { cc_status.flags = CC_IN_FPU; if (FPU_REG_P (operands[0])) return \"fcmp.s %f1,%0\"; cc_status.flags |= CC_REVERSED; return \"fcmp.s %f0,%1\"; }") ;; Recognizers for btst instructions. (define_insn "" [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:SI 1 "general_operand" "rmi")))] "" "btst %1.w,%0.b") (define_insn "" [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:SI 1 "general_operand" "rmi")))] "" "btst %1.w,%0.h") (define_insn "" [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:SI 1 "general_operand" "rmi")))] "" "btst %1.w,%0.w") ;; The following two patterns are like the previous two ;; except that they use the fact that bit-number operands (offset) ;; are automatically masked to 3 or 5 bits when the base is a register. (define_insn "" [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "r") (const_int 1) (and:SI (match_operand:SI 1 "general_operand" "rmi") (const_int 7))))] "" "btst %1.w,%0.b") (define_insn "" [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "r") (const_int 1) (and:SI (match_operand:SI 1 "general_operand" "rmi") (const_int 31))))] "" "btst %1.w,%0.w") ; More various size-patterns are allowed for btst, but not ; included yet. M.Yuhara (define_insn "" [(set (cc0) (and:SI (sign_extend:SI (sign_extend:HI (match_operand:QI 0 "nonimmediate_operand" "rm"))) (match_operand:SI 1 "general_operand" "i")))] "(GET_CODE (operands[1]) == CONST_INT && (unsigned) INTVAL (operands[1]) < 0x100 && exact_log2 (INTVAL (operands[1])) >= 0)" "* { register int log = exact_log2 (INTVAL (operands[1])); operands[1] = gen_rtx (CONST_INT, VOIDmode, log); return \"btst %1,%0.b\"; }") ; I can add more patterns like above. But not yet. M.Yuhara ; mtst is supported only by G/300. (define_insn "" [(set (cc0) (and:SI (match_operand:SI 0 "general_operand" "%rmi") (match_operand:SI 1 "general_operand" "rm")))] "TARGET_G300" "* { if (GET_CODE (operands[0]) == CONST_INT) return \"mtst.w %0,%1\"; return \"mtst.w %1,%0\"; }") (define_insn "" [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "%rmi") (match_operand:HI 1 "general_operand" "rm")))] "TARGET_G300" "* { if (GET_CODE (operands[0]) == CONST_INT) return \"mtst.h %0,%1\"; return \"mtst.h %1,%0\"; }") (define_insn "" [(set (cc0) (and:QI (match_operand:QI 0 "general_operand" "%rmi") (match_operand:QI 1 "general_operand" "rm")))] "TARGET_G300" "* { if (GET_CODE (operands[0]) == CONST_INT) return \"mtst.b %0,%1\"; return \"mtst.b %1,%0\"; }") ;; move instructions /* added by M.Yuhara */ ;; 1.35.04 89.08.28 modification start ;; register_operand -> general_operand ;; ashift -> mult (define_insn "" [(set (mem:SI (plus:SI (match_operand:SI 0 "general_operand" "r") (ashift:SI (match_operand:SI 1 "general_operand" "r") (const_int 2)))) (match_operand:SI 2 "general_operand" "rmi"))] "" "* { return \"mov.w %2,@(%0:b,%1*4)\"; }") (define_insn "" [(set (mem:SI (plus:SI (ashift:SI (match_operand:SI 0 "general_operand" "r") (const_int 2)) (match_operand:SI 1 "general_operand" "r"))) (match_operand:SI 2 "general_operand" "rmi"))] "" "* { return \"mov.w %2,@(%1:b,%0*4)\"; }") (define_insn "" [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 4)))) (match_operand:SI 2 "general_operand" "rmi"))] "" "* { return \"mov.w %2,@(%0:b,%1*4)\"; }") (define_insn "" [(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") (const_int 4)) (match_operand:SI 1 "register_operand" "r"))) (match_operand:SI 2 "general_operand" "rmi"))] "" "* { return \"mov.w %2,@(%1:b,%0*4)\"; }") (define_insn "" [(set (mem:SI (plus:SI (match_operand:SI 0 "general_operand" "r") (plus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "i")))) (match_operand:SI 3 "general_operand" "rmi"))] "" "* { return \"mov.w %3,@(%c2,%0,%1)\"; }") (define_insn "" [(set (mem:SI (plus:SI (plus:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "general_operand" "i"))) (match_operand:SI 3 "general_operand" "rmi"))] "" "* { return \"mov.w %3,@(%c2,%0,%1)\"; }") (define_insn "" [(set (mem:SI (plus:SI (match_operand:SI 0 "general_operand" "i") (plus:SI (match_operand:SI 1 "register_operand" "r") (mult:SI (match_operand:SI 2 "register_operand" "r") (const_int 4))))) (match_operand:SI 3 "general_operand" "rmi"))] "" "* { return \"mov.w %3,@(%1:b,%0,%2*4)\"; }") ;; 89.08.28 1.35.04 modification end ;; Should add "!" to op2 ?? ;; General move-address-to-operand should handle these. ;; If that does not work, please figure out why. ;(define_insn "" ; [(set (match_operand:SI 0 "push_operand" "=m") ; (plus:SI ; (match_operand:SI 1 "immediate_operand" "i") ; (match_operand:SI 2 "general_operand" "r")))] ; "" ; "mova.w @(%c1,%2),%-") ;(define_insn "" ; [(set (match_operand:SI 0 "push_operand" "=m") ; (plus:SI ; (match_operand:SI 1 "general_operand" "r") ; (match_operand:SI 2 "immediate_operand" "i")))] ; "" ; "mova.w @(%c2,%1),%-") (define_insn "" [(set (match_operand:SI 0 "push_operand" "=m") (minus:SI (match_operand:SI 1 "general_operand" "r") (match_operand:SI 2 "immediate_operand" "i")))] "" "mova.w @(%n2,%1),%-") ;; General case of fullword move. (define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=rm") (match_operand:SI 1 "general_operand" "rmi"))] "" "* { if (GET_CODE (operands[1]) == CONST_INT) return mov_imm_word (INTVAL (operands[1]), operands[0]); /* if (address_operand (operands[1], SImode)) return \"mova.w %1,%0\"; */ if (push_operand (operands[0], SImode)) return \"mov.w %1,%-\"; return \"mov.w %1,%0\"; }") /* pushsi 89.08.10 for test M.Yuhara */ /* (define_insn "" [(set (match_operand:SI 0 "push_operand" "=m") (match_operand:SI 1 "general_operand" "rmi"))] "" "* { if (GET_CODE (operands[1]) == CONST_INT) return mov_imm_word (INTVAL (operands[1]), operands[0]); if (push_operand (operands[0], SImode)) return \"mov.w %1,%-\"; return \"mov.w %1,%0\"; }") */ (define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=rm") (match_operand:HI 1 "general_operand" "rmi"))] "" "* { if (push_operand (operands[0], SImode)) return \"mov.h %1,%-\"; return \"mov.h %1,%0\"; }") ;; Is the operand constraint "+" necessary ???? ;; Should I check push_operand ???? (define_insn "movstricthi" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+rm")) (match_operand:HI 1 "general_operand" "rmi"))] "" "mov.h %1,%0"); (define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=rm") (match_operand:QI 1 "general_operand" "rmi"))] "" "* { if (GREG_P (operands[0])) { if (CONSTANT_P (operands[1])) return \"mov:l %1,%0.w\"; else return \"mov:l %1.b,%0.w\"; } if (GREG_P (operands[1])) return \"mov:s %1.w,%0.b\"; return \"mov.b %1,%0\"; }") (define_insn "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "general_operand" "+rm")) (match_operand:QI 1 "general_operand" "rmi"))] "" "mov.b %1,%0") (define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=f,mf,rm,fr") (match_operand:SF 1 "general_operand" "mfF,f,rmF,fr"))] "" "* { switch (which_alternative) { case 0: if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_single (operands); return \"fmov.s %1,%0\"; case 1: return \"fmov.s %1,%0\"; case 2: if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_single (operands); return \"mov.w %1,%0\"; case 3: if (FPU_REG_P (operands[0])) return \"mov.w %1,%-\\n\\tfmov.s %+,%0\"; return \"fmov.s %1,%-\\n\\tmov.w %+,%0\"; } }") (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=f,mf,rm,fr") (match_operand:DF 1 "general_operand" "mfF,f,rmF,fr"))] "" "* { switch (which_alternative) { case 0: if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); return \"fmov.d %1,%0\"; case 1: return \"fmov.d %1,%0\"; case 2: if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); return output_move_double (operands); case 3: if (FPU_REG_P (operands[0])) { rtx xoperands[2]; xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"mov.w %1,%-\", xoperands); output_asm_insn (\"mov.w %1,%-\", operands); return \"fmov.d %+,%0\"; } else { output_asm_insn (\"fmov.d %f1,%-\", operands); output_asm_insn (\"mov.w %+,%0\", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); return \"mov.w %+,%0\"; } } }") ;; movdi can apply to fp regs in some cases ;; Must check again. you can use fsti/fldi, etc. ;; FPU reg should be included ?? ;; 89.12.13 for test (define_insn "movdi" ;; Let's see if it really still needs to handle fp regs, and, if so, why. [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro") (match_operand:DI 1 "general_operand" "rF,m,roiF"))] "" "* { if (FPU_REG_P (operands[0])) { if (FPU_REG_P (operands[1])) return \"fmov.d %1,%0\"; if (REG_P (operands[1])) { rtx xoperands[2]; xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"mov.w %1,%-\", xoperands); output_asm_insn (\"mov.w %1,%-\", operands); return \"fmov.d %+,%0\"; } if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); return \"fmov.d %f1,%0\"; } else if (FPU_REG_P (operands[1])) { if (REG_P (operands[0])) { output_asm_insn (\"fmov.d %f1,%-\;mov.w %+,%0\", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); return \"mov.w %+,%0\"; } else return \"fmov.d %f1,%0\"; } return output_move_double (operands); } ") ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it won't successfully combine with anything. ;; This is dangerous when %0 and %1 overlapped !!!!! ;; Ugly code... (define_insn "movstrhi" [(set (match_operand:BLK 0 "general_operand" "=m") (match_operand:BLK 1 "general_operand" "m")) (use (match_operand:HI 2 "general_operand" "rmi")) (clobber (reg:SI 0)) (clobber (reg:SI 1)) (clobber (reg:SI 2))] "" "* { int op2const; rtx tmpx; if (CONSTANT_P (operands[1])) { fprintf (stderr, \"smov 1 const err \"); abort (); } else if (GET_CODE (operands[1]) == REG) { fprintf (stderr, \"smov 1 reg err \"); abort (); } else if (GET_CODE (operands[1]) == MEM) { tmpx = XEXP (operands[1], 0); if (CONSTANT_ADDRESS_P (tmpx) || GREG_P (tmpx)) { operands[1] = tmpx; output_asm_insn (\"mov.w %1,r0\", operands); } else { output_asm_insn (\"mova %1,r0\", operands); } } else { fprintf (stderr, \"smov 1 else err \"); abort (); output_asm_insn (\"mova.w %p1,r0\", operands); } if (CONSTANT_P (operands[0])) { fprintf (stderr, \"smov 0 const err \"); abort (); } else if (GET_CODE (operands[0]) == REG) { fprintf (stderr, \"smov 0 reg err \"); abort (); } else if (GET_CODE (operands[0]) == MEM) { tmpx = XEXP (operands[0], 0); if (CONSTANT_ADDRESS_P (tmpx) || GREG_P (tmpx)) { operands[0] = tmpx; output_asm_insn (\"mov.w %0,r1\", operands); } else { output_asm_insn (\"mova %0,r1\", operands); } } else { fprintf (stderr, \"smov 0 else err \"); abort (); } if (GET_CODE (operands[2]) == CONST_INT) { op2const = INTVAL (operands[2]); if (op2const % 4 != 0) { output_asm_insn (\"mov.w %2,r2\", operands); return \"smov/n/f.b\"; } op2const = op2const / 4; if (op2const <= 4) { if (op2const == 0) abort (0); if (op2const == 1) return \"mov.w @r0,@r1\"; output_asm_insn (\"mov.w @r0,@r1\", operands); if (op2const == 2) return \"mov.w @(4,r0),@(4,r1)\"; output_asm_insn (\"mov.w @(4,r0),@(4,r1)\", operands); if (op2const == 3) return \"mov.w @(8,r0),@(8,r1)\"; output_asm_insn (\"mov.w @(8,r0),@(8,r1)\", operands); return \"mov.w @(12,r0),@(12,r1)\"; } operands[2] = gen_rtx (CONST_INT, VOIDmode, op2const); output_asm_insn (\"mov.w %2,r2\", operands); return \"smov/n/f.w\"; } else { fprintf (stderr, \"smov 0 else err \"); abort (); output_asm_insn (\"mov %2.h,r2.w\", operands); return \"smov/n/f.b\"; } }") ;; M.Yuhara 89.08.24 ;; experiment on the built-in strcpy (__builtin_smov) ;; ;; len = 0 means unknown string length. ;; ;; mem:SI is dummy. Necessary so as not to be deleted by optimization. ;; Use of BLKmode would be better... ;; ;; (define_insn "smovsi" [(set (mem:SI (match_operand:SI 0 "general_operand" "=rm")) (mem:SI (match_operand:SI 1 "general_operand" "rm"))) (use (match_operand:SI 2 "general_operand" "i")) (clobber (reg:SI 0)) (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3))] "" "* { int len, wlen, blen, offset; char tmpstr[128]; rtx xoperands[1]; len = INTVAL (operands[2]); output_asm_insn (\"mov.w %1,r0\\t; begin built-in strcpy\", operands); output_asm_insn (\"mov.w %0,r1\", operands); if (len == 0) { output_asm_insn (\"mov:z.w #0,r2\", operands); output_asm_insn (\"mov:z.w #0,r3\", operands); return \"smov/eq/f.b\\t; end built-in strcpy\"; } wlen = len / 4; blen = len - wlen * 4; if (wlen > 0) { if (len <= 40 && !TARGET_FORCE_SMOV) { output_asm_insn (\"mov.w @r0,@r1\", operands); offset = 4; while ( (blen = len - offset) > 0) { if (blen >= 4) { sprintf (tmpstr, \"mov.w @(%d,r0),@(%d,r1)\", offset, offset); output_asm_insn (tmpstr, operands); offset += 4; } else if (blen >= 2) { sprintf (tmpstr, \"mov.h @(%d,r0),@(%d,r1)\", offset, offset); output_asm_insn (tmpstr, operands); offset += 2; } else { sprintf (tmpstr, \"mov.b @(%d,r0),@(%d,r1)\", offset, offset); output_asm_insn (tmpstr, operands); offset++; } } return \"\\t\\t; end built-in strcpy\"; } else { xoperands[0] = gen_rtx (CONST_INT, VOIDmode, wlen); output_asm_insn (\"mov.w %0,r2\", xoperands); output_asm_insn (\"smov/n/f.w\", operands); } } if (blen >= 2) { output_asm_insn (\"mov.h @r0,@r1\", operands); if (blen == 3) output_asm_insn (\"mov.b @(2,r0),@(2,r1)\", operands); } else if (blen == 1) { output_asm_insn (\"mov.b @r0,@r1\", operands); } return \"\\t\\t; end built-in strcpy\"; }") ;; truncation instructions (define_insn "truncsiqi2" [(set (match_operand:QI 0 "general_operand" "=rm") (truncate:QI (match_operand:SI 1 "general_operand" "rmi")))] "" "mov %1.w,%0.b") ; "* ;{ ; if (GET_CODE (operands[0]) == REG) ; return \"mov.w %1,%0\"; ; if (GET_CODE (operands[1]) == MEM) ; operands[1] = adj_offsettable_operand (operands[1], 3); ; return \"mov.b %1,%0\"; ;}") (define_insn "trunchiqi2" [(set (match_operand:QI 0 "general_operand" "=rm") (truncate:QI (match_operand:HI 1 "general_operand" "rmi")))] "" "mov %1.h,%0.b") ; "* ;{ ; if (GET_CODE (operands[0]) == REG) ; return \"mov.h %1,%0\"; ; if (GET_CODE (operands[1]) == MEM) ; operands[1] = adj_offsettable_operand (operands[1], 1); ; return \"mov.b %1,%0\"; ;}") (define_insn "truncsihi2" [(set (match_operand:HI 0 "general_operand" "=rm") (truncate:HI (match_operand:SI 1 "general_operand" "rmi")))] "" "mov %1.w,%0.h") ; "* ;{ ; if (GET_CODE (operands[0]) == REG) ; return \"mov.w %1,%0\"; ; if (GET_CODE (operands[1]) == MEM) ; operands[1] = adj_offsettable_operand (operands[1], 2); ; return \"mov.h %1,%0\"; ;}") ;; zero extension instructions ;; define_expand (68k) -> define_insn (Gmicro) (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "general_operand" "=rm") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] "" "movu %1.h,%0.w") (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "general_operand" "=rm") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))] "" "movu %1.b,%0.h") (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "general_operand" "=rm") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))] "" "movu %1.b,%0.w") ;; sign extension instructions (define_insn "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=rm") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] "" "mov %1.h,%0.w") (define_insn "extendqihi2" [(set (match_operand:HI 0 "general_operand" "=rm") (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))] "" "mov %1.b,%0.h") (define_insn "extendqisi2" [(set (match_operand:SI 0 "general_operand" "=rm") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))] "" "mov %1.b,%0.w") ;; Conversions between float and double. (define_insn "extendsfdf2" [(set (match_operand:DF 0 "general_operand" "=*frm,f") (float_extend:DF (match_operand:SF 1 "general_operand" "f,rmF")))] "TARGET_FPU" "* { if (FPU_REG_P (operands[0])) { if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); if (GREG_P (operands[1])) { output_asm_insn (\"mov.w %1,%-\", operands); return \"fmov %+.s,%0.d\"; } return \"fmov %1.s,%0.d\"; } else { if (GREG_P (operands[0])) { output_asm_insn (\"fmov %1.s,%-.d\", operands); output_asm_insn (\"mov.w %+,%0\", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); return \"mov.w %+,%0\"; } return \"fmov %1.s,%0.d\"; } }") (define_insn "truncdfsf2" [(set (match_operand:SF 0 "general_operand" "=rfm") (float_truncate:SF (match_operand:DF 1 "general_operand" "f")))] "TARGET_FPU" "* { if (GREG_P (operands[0])) { output_asm_insn (\"fmov %1.d,%-.s\", operands); return \"mov.w %+,%0\"; } return \"fmov %1.d,%0.s\"; }") ;; Conversion between fixed point and floating point. ;; Note that among the fix-to-float insns ;; the ones that start with SImode come first. ;; That is so that an operand that is a CONST_INT ;; (and therefore lacks a specific machine mode). ;; will be recognized as SImode (which is always valid) ;; rather than as QImode or HImode. (define_insn "floatsisf2" [(set (match_operand:SF 0 "general_operand" "=f") (float:SF (match_operand:SI 1 "general_operand" "rmi")))] "TARGET_FPU" "fldi %1.w,%0.s") (define_insn "floatsidf2" [(set (match_operand:DF 0 "general_operand" "=f") (float:DF (match_operand:SI 1 "general_operand" "rmi")))] "TARGET_FPU" "fldi %1.w,%0.d") (define_insn "floathisf2" [(set (match_operand:SF 0 "general_operand" "=f") (float:SF (match_operand:HI 1 "general_operand" "rmi")))] "TARGET_FPU" "fldi %1.h,%0.s") (define_insn "floathidf2" [(set (match_operand:DF 0 "general_operand" "=f") (float:DF (match_operand:HI 1 "general_operand" "rmi")))] "TARGET_FPU" "fldi %1.h,%0.d") (define_insn "floatqisf2" [(set (match_operand:SF 0 "general_operand" "=f") (float:SF (match_operand:QI 1 "general_operand" "rmi")))] "TARGET_FPU" "fldi %1.b,%0.s") (define_insn "floatqidf2" [(set (match_operand:DF 0 "general_operand" "=f") (float:DF (match_operand:QI 1 "general_operand" "rmi")))] "TARGET_FPU" "fldi %1.b,%0.d") ;;; Convert a float to a float whose value is an integer. ;;; This is the first stage of converting it to an integer type. ; ;(define_insn "ftruncdf2" ; [(set (match_operand:DF 0 "general_operand" "=f") ; (fix:DF (match_operand:DF 1 "general_operand" "fFm")))] ; "TARGET_FPU" ; "* ;{ ; return \"fintrz.d %f1,%0\"; ;}") ; ;(define_insn "ftruncsf2" ; [(set (match_operand:SF 0 "general_operand" "=f") ; (fix:SF (match_operand:SF 1 "general_operand" "fFm")))] ; "TARGET_FPU" ; "* ;{ ; return \"fintrz.s %f1,%0\"; ;}") ;; Convert a float to an integer. (define_insn "fix_truncsfqi2" [(set (match_operand:QI 0 "general_operand" "=rm") (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "f"))))] "TARGET_FPU" "fsti %1.s,%0.b") (define_insn "fix_truncsfhi2" [(set (match_operand:HI 0 "general_operand" "=rm") (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "f"))))] "TARGET_FPU" "fsti %1.s,%0.h") (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "f"))))] "TARGET_FPU" "fsti %1.s,%0.w") (define_insn "fix_truncdfqi2" [(set (match_operand:QI 0 "general_operand" "=rm") (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "f"))))] "TARGET_FPU" "fsti %1.d,%0.b") (define_insn "fix_truncdfhi2" [(set (match_operand:HI 0 "general_operand" "=rm") (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "f"))))] "TARGET_FPU" "fsti %1.d,%0.h") (define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "f"))))] "TARGET_FPU" "fsti %1.d,%0.w") ;;; Special add patterns ;;; 89.09.28 ;; This should be redundant; please find out why regular addsi3 ;; fails to match this case. ;(define_insn "" ; [(set (mem:SI (plus:SI ; (plus:SI (match_operand 0 "general_operand" "r") ; (match_operand 1 "general_operand" "r")) ; (match_operand 2 "general_operand" "i"))) ; (plus:SI ; (mem:SI (plus:SI ; (plus:SI (match_dup 0) ; (match_dup 1)) ; (match_dup 2))) ; (match_operand 3 "general_operand" "rmi")))] ; "" ; "add.w %3,@(%c2,%0,%1)") ;; add instructions ;; Note that the last two alternatives are near-duplicates ;; in order to handle insns generated by reload. ;; This is needed since they are not themselves reloaded, ;; so commutativity won't apply to them. (define_insn "addsi3" [(set (match_operand:SI 0 "general_operand" "=rm,!r,!r") (plus:SI (match_operand:SI 1 "general_operand" "%0,r,ri") (match_operand:SI 2 "general_operand" "rmi,ri,r")))] "" "* { if (which_alternative == 0) { if (GET_CODE (operands[2]) == CONST_INT) { operands[1] = operands[2]; return add_imm_word (INTVAL (operands[1]), operands[0], &operands[1]); } else return \"add.w %2,%0\"; } else { if (GET_CODE (operands[1]) == REG && REGNO (operands[0]) == REGNO (operands[1])) return \"add.w %2,%0\"; if (GET_CODE (operands[2]) == REG && REGNO (operands[0]) == REGNO (operands[2])) return \"add.w %1,%0\"; if (GET_CODE (operands[1]) == REG) { if (GET_CODE (operands[2]) == REG) return \"mova.w @(%1,%2),%0\"; else return \"mova.w @(%c2,%1),%0\"; } else return \"mova.w @(%c1,%2),%0\"; } }") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") (plus:SI (match_operand:SI 1 "general_operand" "0") (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rmi"))))] "" "* { if (CONSTANT_P (operands[2])) { operands[1] = operands[2]; return add_imm_word (INTVAL (operands[1]), operands[0], &operands[1]); } else return \"add %2.h,%0.w\"; }") (define_insn "addhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (plus:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "general_operand" "rmi")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return \"sub.h #%n2,%0\"; if (GREG_P (operands[0])) { if (CONSTANT_P (operands[2])) return \"add:l %2,%0.w\"; else return \"add:l %2.h,%0.w\"; } return \"add.h %2,%0\"; }") (define_insn "" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+rm")) (plus:HI (match_dup 0) (match_operand:HI 1 "general_operand" "rmi")))] "" "add.h %1,%0") (define_insn "addqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (plus:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "rmi")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return \"sub.b #%n2,%0\"; if (GREG_P (operands[0])) { if (CONSTANT_P (operands[2])) return \"add:l %2,%0.w\"; else return \"add:l %2.b,%0.w\"; } return \"add.b %2,%0\"; }") (define_insn "" [(set (strict_low_part (match_operand:QI 0 "general_operand" "+rm")) (plus:QI (match_dup 0) (match_operand:QI 1 "general_operand" "rmi")))] "" "add.b %1,%0") (define_insn "adddf3" [(set (match_operand:DF 0 "general_operand" "=f") (plus:DF (match_operand:DF 1 "general_operand" "%0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_FPU" "fadd.d %f2,%0") (define_insn "addsf3" [(set (match_operand:SF 0 "general_operand" "=f") (plus:SF (match_operand:SF 1 "general_operand" "%0") (match_operand:SF 2 "general_operand" "fmG")))] "TARGET_FPU" "fadd.s %f2,%0") ;; subtract instructions (define_insn "subsi3" [(set (match_operand:SI 0 "general_operand" "=rm,!r") (minus:SI (match_operand:SI 1 "general_operand" "0,r") (match_operand:SI 2 "general_operand" "rmi,i")))] "" "* { if (which_alternative == 0 || (GET_CODE (operands[1]) == REG && REGNO (operands[0]) == REGNO (operands[1]))) { if (GET_CODE (operands[2]) == CONST_INT) { operands[1] = operands[2]; return sub_imm_word (INTVAL (operands[1]), operands[0], &operands[1]); } else return \"sub.w %2,%0\"; } else return \"mova.w @(%n2,%1),%0\"; }") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") (minus:SI (match_operand:SI 1 "general_operand" "0") (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rmi"))))] "" "sub %2.h,%0.w") (define_insn "subhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (minus:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != 0x8000) return \"add.h #%n2,%0\"; return \"sub.h %2,%0\"; }") (define_insn "" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+rm")) (minus:HI (match_dup 0) (match_operand:HI 1 "general_operand" "rmi")))] "" "sub.h %1,%0") (define_insn "subqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (minus:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != 0x80) return \"add.b #%n2,%0\"; return \"sub.b %2,%0\"; }") (define_insn "" [(set (strict_low_part (match_operand:QI 0 "general_operand" "+rm")) (minus:QI (match_dup 0) (match_operand:QI 1 "general_operand" "rmi")))] "" "sub.b %1,%0") (define_insn "subdf3" [(set (match_operand:DF 0 "general_operand" "=f") (minus:DF (match_operand:DF 1 "general_operand" "0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_FPU" "fsub.d %f2,%0") (define_insn "subsf3" [(set (match_operand:SF 0 "general_operand" "=f") (minus:SF (match_operand:SF 1 "general_operand" "0") (match_operand:SF 2 "general_operand" "fmG")))] "TARGET_FPU" "fsub.s %f2,%0") ;; multiply instructions (define_insn "mulqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (mult:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "rmi")))] "" "mul.b %2,%0") (define_insn "mulhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (mult:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "general_operand" "rmi")))] "" "mul.h %2,%0") ;; define_insn "mulhisi3" (define_insn "mulsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (mult:SI (match_operand:SI 1 "general_operand" "%0") (match_operand:SI 2 "general_operand" "rmi")))] "" "mul.w %2,%0") (define_insn "muldf3" [(set (match_operand:DF 0 "general_operand" "=f") (mult:DF (match_operand:DF 1 "general_operand" "%0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_FPU" "fmul.d %f2,%0") (define_insn "mulsf3" [(set (match_operand:SF 0 "general_operand" "=f") (mult:SF (match_operand:SF 1 "general_operand" "%0") (match_operand:SF 2 "general_operand" "fmG")))] "TARGET_FPU" "fmul.s %f2,%0") ;; divide instructions (define_insn "divqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (div:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "div.b %2,%0") (define_insn "divhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (div:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "div.h %2,%0") (define_insn "divhisi3" [(set (match_operand:HI 0 "general_operand" "=r") (div:HI (match_operand:SI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "div %2.h,%0.w") (define_insn "divsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (div:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" "div.w %2,%0") (define_insn "udivqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (udiv:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "divu.b %2,%0") (define_insn "udivhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (udiv:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "divu.h %2,%0") (define_insn "udivhisi3" [(set (match_operand:HI 0 "general_operand" "=r") (udiv:HI (match_operand:SI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "divu %2.h,%0.w") (define_insn "udivsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (udiv:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" "divu.w %2,%0") (define_insn "divdf3" [(set (match_operand:DF 0 "general_operand" "=f") (div:DF (match_operand:DF 1 "general_operand" "0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_FPU" "fdiv.d %f2,%0") (define_insn "divsf3" [(set (match_operand:SF 0 "general_operand" "=f") (div:SF (match_operand:SF 1 "general_operand" "0") (match_operand:SF 2 "general_operand" "fmG")))] "TARGET_FPU" "fdiv.s %f2,%0") ;; Remainder instructions. (define_insn "modqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (mod:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "rem.b %2,%0") (define_insn "modhisi3" [(set (match_operand:HI 0 "general_operand" "=r") (mod:HI (match_operand:SI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "rem.h %2,%0") (define_insn "umodqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (umod:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "remu.b %2,%0") (define_insn "umodhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (umod:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "remu.h %2,%0") (define_insn "umodhisi3" [(set (match_operand:HI 0 "general_operand" "=r") (umod:HI (match_operand:SI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "remu %2.h,%0.w") ;; define_insn "divmodsi4" (define_insn "udivmodsi4" [(set (match_operand:SI 0 "general_operand" "=rm") (udiv:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi"))) (set (match_operand:SI 3 "general_operand" "=r") (umod:SI (match_dup 1) (match_dup 2)))] "" "mov.w #0,%3;divx.w %2,%0,%3") ;; logical-and instructions (define_insn "andsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (and:SI (match_operand:SI 1 "general_operand" "%0") (match_operand:SI 2 "general_operand" "rmi")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) | 0xffff) == 0xffffffff && (GREG_P (operands[0]) || offsettable_memref_p (operands[0]))) { if (GET_CODE (operands[0]) != REG) operands[0] = adj_offsettable_operand (operands[0], 2); operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); /* Do not delete a following tstl %0 insn; that would be incorrect. */ CC_STATUS_INIT; return \"and.h %2,%0\"; } return \"and.w %2,%0\"; }") (define_insn "andhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (and:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "general_operand" "rmi")))] "" "and.h %2,%0") (define_insn "andqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (and:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "rmi")))] "" "and.b %2,%0") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (and:SI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")) (match_operand:SI 2 "general_operand" "0")))] "" "* { if (GET_CODE (operands[1]) == CONST_INT) return \"and %1,%0.w\"; return \"and %1.h,%0.w\"; }") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (and:SI (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")) (match_operand:SI 2 "general_operand" "0")))] "" "* { if (GET_CODE (operands[1]) == CONST_INT) return \"and %1,%0.w\"; return \"and %1.b,%0.w\"; }") ;; inclusive-or instructions (define_insn "iorsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (ior:SI (match_operand:SI 1 "general_operand" "%0") (match_operand:SI 2 "general_operand" "rmi")))] "" "* { register int logval; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >> 16 == 0 && (GREG_P (operands[0]) || offsettable_memref_p (operands[0]))) { if (GET_CODE (operands[0]) != REG) operands[0] = adj_offsettable_operand (operands[0], 2); /* Do not delete a following tstl %0 insn; that would be incorrect. */ CC_STATUS_INIT; return \"or.h %2,%0\"; } if (GET_CODE (operands[2]) == CONST_INT && (logval = exact_log2 (INTVAL (operands[2]))) >= 0 && (GREG_P (operands[0]) || offsettable_memref_p (operands[0]))) { if (GREG_P (operands[0])) { if (logval < 7) { operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - logval); return \"bset.b %1,%0\"; } operands[1] = gen_rtx (CONST_INT, VOIDmode, 31 - logval); return \"bset.w %1,%0\"; } else { operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8)); operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - (logval % 8)); } return \"bset.b %1,%0\"; } return \"or.w %2,%0\"; }") (define_insn "iorhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (ior:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "general_operand" "rmi")))] "" "or.h %2,%0") (define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (ior:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "rmi")))] "" "or.b %2,%0") ;; xor instructions (define_insn "xorsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (xor:SI (match_operand:SI 1 "general_operand" "%0") (match_operand:SI 2 "general_operand" "rmi")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >> 16 == 0 && (offsettable_memref_p (operands[0]) || GREG_P (operands[0]))) { if (! GREG_P (operands[0])) operands[0] = adj_offsettable_operand (operands[0], 2); /* Do not delete a following tstl %0 insn; that would be incorrect. */ CC_STATUS_INIT; return \"xor.h %2,%0\"; } return \"xor.w %2,%0\"; }") (define_insn "xorhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (xor:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "general_operand" "rmi")))] "" "xor.h %2,%0") (define_insn "xorqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (xor:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "rmi")))] "" "xor.b %2,%0") ;; negation instructions (define_insn "negsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (neg:SI (match_operand:SI 1 "general_operand" "0")))] "" "neg.w %0") (define_insn "neghi2" [(set (match_operand:HI 0 "general_operand" "=rm") (neg:HI (match_operand:HI 1 "general_operand" "0")))] "" "neg.h %0") (define_insn "negqi2" [(set (match_operand:QI 0 "general_operand" "=rm") (neg:QI (match_operand:QI 1 "general_operand" "0")))] "" "neg.b %0") (define_insn "negsf2" [(set (match_operand:SF 0 "general_operand" "=f") (neg:SF (match_operand:SF 1 "general_operand" "fmF")))] "TARGET_FPU" "fneg.s %f1,%0") (define_insn "negdf2" [(set (match_operand:DF 0 "general_operand" "=f") (neg:DF (match_operand:DF 1 "general_operand" "fmF")))] "TARGET_FPU" "fneg.d %f1,%0") ;; Absolute value instructions (define_insn "abssf2" [(set (match_operand:SF 0 "general_operand" "=f") (abs:SF (match_operand:SF 1 "general_operand" "fmF")))] "TARGET_FPU" "fabs.s %f1,%0") (define_insn "absdf2" [(set (match_operand:DF 0 "general_operand" "=f") (abs:DF (match_operand:DF 1 "general_operand" "fmF")))] "TARGET_FPU" "fabs.d %f1,%0") ;; one complement instructions (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (not:SI (match_operand:SI 1 "general_operand" "0")))] "" "not.w %0") (define_insn "one_cmplhi2" [(set (match_operand:HI 0 "general_operand" "=rm") (not:HI (match_operand:HI 1 "general_operand" "0")))] "" "not.h %0") (define_insn "one_cmplqi2" [(set (match_operand:QI 0 "general_operand" "=rm") (not:QI (match_operand:QI 1 "general_operand" "0")))] "" "not.b %0") ;; Optimized special case of shifting. ;; Must precede the general case. (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 24)))] "GET_CODE (XEXP (operands[1], 0)) != POST_INC && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC" "mov:l %1.b,%0.w") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 24)))] "GET_CODE (XEXP (operands[1], 0)) != POST_INC && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC" "movu %1.b,%0.w") (define_insn "" [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i") (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 24))))] "(GET_CODE (operands[0]) == CONST_INT && (INTVAL (operands[0]) & ~0xff) == 0)" "* { cc_status.flags |= CC_REVERSED; if (my_signed_comp (insn)) return \"cmp.b %0,%1\"; return \"cmpu.b %0,%1\"; }") (define_insn "" [(set (cc0) (compare (lshiftrt:SI (match_operand:SI 0 "memory_operand" "m") (const_int 24)) (match_operand:QI 1 "general_operand" "i")))] "(GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & ~0xff) == 0)" "* if (my_signed_comp (insn)) return \"cmp.b %1,%0\"; return \"cmpu.b %1,%0\"; ") (define_insn "" [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i") (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 24))))] "(GET_CODE (operands[0]) == CONST_INT && ((INTVAL (operands[0]) + 0x80) & ~0xff) == 0)" "* cc_status.flags |= CC_REVERSED; if (my_signed_comp (insn)) return \"cmp.b %0,%1\"; return \"cmpu.b %0,%1\"; ") (define_insn "" [(set (cc0) (compare (ashiftrt:SI (match_operand:SI 0 "memory_operand" "m") (const_int 24)) (match_operand:QI 1 "general_operand" "i")))] "(GET_CODE (operands[1]) == CONST_INT && ((INTVAL (operands[1]) + 0x80) & ~0xff) == 0)" "* if (my_signed_comp (insn)) return \"cmp.b %1,%0\"; return \"cmpu.b %1,%0\"; ") ;; arithmetic shift instructions ;; We don't need the shift memory by 1 bit instruction (define_insn "ashlsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (ashift:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" "sha.w %2,%0") (define_insn "ashlhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (ashift:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "sha.h %2,%0") (define_insn "ashlqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (ashift:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "sha.b %2,%0") ;; Arithmetic right shift on the Gmicro works by negating the shift count ;; ashiftrt -> ashift (define_expand "ashrsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (ashift:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" "{ operands[2] = negate_rtx (SImode, operands[2]); }") ;; ashiftrt -> ashift (define_expand "ashrhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (ashift:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (HImode, operands[2]); }") ;; ashiftrt -> ashift (define_expand "ashrqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (ashift:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (QImode, operands[2]); }") ;; logical shift instructions (define_insn "lshlsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (lshift:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" "shl.w %2,%0") (define_insn "lshlhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (lshift:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "shl.h %2,%0") (define_insn "lshlqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (lshift:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "shl.b %2,%0") ;; lshiftrt -> lshift (define_expand "lshrsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (lshift:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (SImode, operands[2]); }") ;; lshiftrt -> lshift (define_expand "lshrhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (lshift:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (HImode, operands[2]); }") ;; lshiftrt -> lshift (define_expand "lshrqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (lshift:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (QImode, operands[2]); }") ;; rotate instructions (define_insn "rotlsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (rotate:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" "rol.w %2,%0") (define_insn "rotlhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (rotate:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" "rol.h %2,%0") (define_insn "rotlqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (rotate:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" "rol.b %2,%0") (define_expand "rotrsi3" [(set (match_operand:SI 0 "general_operand" "=rm") (rotatert:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (SImode, operands[2]); }") (define_expand "rotrhi3" [(set (match_operand:HI 0 "general_operand" "=rm") (rotatert:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (HImode, operands[2]); }") (define_expand "rotrqi3" [(set (match_operand:QI 0 "general_operand" "=rm") (rotatert:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "general_operand" "rmi")))] "" " { operands[2] = negate_rtx (QImode, operands[2]); }") ;; Special cases of bit-field insns which we should ;; recognize in preference to the general case. ;; These handle aligned 8-bit and 16-bit fields, ;; which can usually be done with move instructions. ;; Should I add mode_dependent_address_p ???? (define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+rm") (match_operand:SI 1 "immediate_operand" "i") (match_operand:SI 2 "immediate_operand" "i")) (match_operand:SI 3 "general_operand" "rm"))] "TARGET_BITFIELD && GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) % INTVAL (operands[1]) == 0 && (GET_CODE (operands[0]) != REG || ( INTVAL (operands[1]) + INTVAL (operands[2]) == 32))" "* { if (GET_CODE (operands[3]) == MEM) operands[3] = adj_offsettable_operand (operands[3], (32 - INTVAL (operands[1])) / 8); if (GET_CODE (operands[0]) == REG) { if (INTVAL (operands[1]) == 8) return \"movu %3.b,%0.w\"; return \"movu %3.h,%0.w\"; } else { operands[0] = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8); if (INTVAL (operands[1]) == 8) return \"mov.b %3,%0\"; return \"mov.h %3,%0\"; } }") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=&r") (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "rm") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_BITFIELD && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) % INTVAL (operands[2]) == 0" "* { if (!REG_P (operands[1])) operands[1] = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); if (REG_P (operands[0])) { if (REG_P (operands[1])) { if (INTVAL (operands[2]) == 8) { /* width == 8 */ switch (INTVAL (operands[3])) { case 0: return \"mov.w %1,%0;shl.w #-24,%0\"; break; case 8: return \"mov.w %1,%0;shl.w #8,%0;shl.w #-24,%0\"; break; case 16: return \"mov.w %1,%0;shl.w #16,%0;shl.w #-24,%0\"; break; case 24: return \"movu %1.b,%0.w\"; break; default: myabort (2); } } else { switch (INTVAL (operands[3])) { case 0: return \"mov.w %1,%0;shl.w #-16,%0\"; break; case 16: return \"movu %1.h,%0.w\"; break; default: myabort (3); } } } else { if (INTVAL (operands[2]) == 8) return \"movu %1.h,%0.w\"; else return \"movu %1.b,%0.w\"; } } else { /* op[0] == MEM */ if (INTVAL (operands[2]) == 8) return \"movu %1.b,%0.w\"; return \"movu %1.h,%0.w\"; } }") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_BITFIELD && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) % INTVAL (operands[2]) == 0" "* { if (!REG_P (operands[1])) operands[1] = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); if (REG_P (operands[0])) { if (REG_P (operands[1])) { if (INTVAL (operands[2]) == 8) { /* width == 8 */ switch (INTVAL (operands[3])) { case 0: return \"mov.w %1,%0;sha.w #-24,%0\"; break; case 8: return \"mov.w %1,%0;shl.w #8,%0;sha.w #-24,%0\"; break; case 16: return \"mov.w %1,%0;shl.w #16,%0;sha.w #-24,%0\"; break; case 24: return \"mov %1.b,%0.w\"; break; default: myabort (4); } } else { switch (INTVAL (operands[3])) { case 0: return \"mov.w %1,%0;sha.w #-16,%0\"; break; case 16: return \"mov %1.h,%0.w\"; break; default: myabort (5); } } } else { if (INTVAL (operands[2]) == 8) return \"mov %1.h,%0.w\"; else return \"mov %1.b,%0.w\"; } } else { /* op[0] == MEM */ if (INTVAL (operands[2]) == 8) return \"mov %1.b,%0.w\"; return \"mov %1.h,%0.w\"; } }") ;; Bit field instructions, general cases. ;; "o,d" constraint causes a nonoffsettable memref to match the "o" ;; so that its address is reloaded. ;; extv dest:SI src(:QI/:SI) width:SI pos:SI ;; r.w m r.w/# rmi ;; %0 %1 %2 %3 (define_insn "extv" [(set (match_operand:SI 0 "general_operand" "=r") (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "m") (match_operand:SI 2 "general_operand" "ri") (match_operand:SI 3 "general_operand" "rmi")))] "TARGET_BITFIELD" "bfext %3,%2,%1,%0") (define_insn "extzv" [(set (match_operand:SI 0 "general_operand" "=r") (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "m") (match_operand:SI 2 "general_operand" "ri") (match_operand:SI 3 "general_operand" "rmi")))] "TARGET_BITFIELD" "bfextu %3,%2,%1,%0") ;; There is no insn on the Gmicro to NOT/SET/CLR bitfield. ;; insv dest(BF):QI/SI width:SI pos:SI src:SI ;; m r.w rmi r.w/i ;; 0 1 2 3 (define_insn "insv" [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+m,m") (match_operand:SI 1 "general_operand" "r,i") (match_operand:SI 2 "general_operand" "rmi,i")) (match_operand:SI 3 "general_operand" "ri,ri"))] "TARGET_BITFIELD" "bfinsu %3,%2,%1,%0") ;;; bfins/bfinsu ???????? ;; == == == == == == == == == == == == == ;; Now recognize bit field insns that operate on registers ;; (or at least were intended to do so). ;; On the Gmicro/300, ;; bitfield instructions are not applicable to registers ;-< ;; But I write the register cases, because without them the gcc ;; seems to use "and" instruction with some other instructions ;; instead of using a shift instruction. ;; It is because on many processors shift instructions are slower. ;; On the Gmicro/300 which has a barrel shifter, ;; it is faster to use a shift instruction. ;; ;; Restricts width and offset to be immediates. ;; (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "r") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_BITFIELD" "* { if (REGNO (operands[0]) != REGNO (operands[1])) output_asm_insn (\"mov.w %1,%0\", operands); if (INTVAL (operands[3]) != 0) output_asm_insn (\"shl.w %3,%0\", operands); operands[2] = gen_rtx (CONST_INT, VOIDmode, -(32 - INTVAL (operands[2]))); return \"sha.w %3,%0\"; }") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r") (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "r") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_BITFIELD" "* { if (REGNO (operands[0]) != REGNO (operands[1])) output_asm_insn (\"mov.w %1,%0\", operands); if (INTVAL (operands[3]) != 0) output_asm_insn (\"shl.w %3,%0\", operands); operands[2] = gen_rtx (CONST_INT, VOIDmode, -(32 - INTVAL (operands[2]))); return \"shl.w %3,%0\"; }") ;; There are more descriptions for m68k, but not yet for the Gmicro. ;; ;; Basic conditional jump instructions. (define_insn "beq" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* { OUTPUT_JUMP (\"beq %b0\", \"fbeq %b0\", \"beq %b0\"); }") (define_insn "bne" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* { OUTPUT_JUMP (\"bne %b0\", \"fbne %b0\", \"bne %b0\"); }") (define_insn "bgt" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* OUTPUT_JUMP (\"bgt %b0\", \"fbgt %b0\", 0); ") (define_insn "bgtu" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "bgt %b0") (define_insn "blt" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* OUTPUT_JUMP (\"blt %b0\", \"fblt %b0\", \"bms %b0\"); ") ;; bms ????? ;; (define_insn "bltu" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "blt %b0") (define_insn "bge" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* OUTPUT_JUMP (\"bge %b0\", \"fbge %b0\", \"bmc %b0\"); ") ;; bmc ?? (define_insn "bgeu" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "bge %b0") (define_insn "ble" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "ble %b0") (define_insn "bleu" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "ble %b0") ;; Negated conditional jump instructions. (define_insn "" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* { OUTPUT_JUMP (\"bne %b0\", \"fbne %b0\", \"bne %b0\"); }") (define_insn "" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* { OUTPUT_JUMP (\"beq %b0\", \"fbeq %b0\", \"beq %b0\"); }") (define_insn "" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* OUTPUT_JUMP (\"ble %b0\", \"fbngt %b0\", 0); ") ;; fbngt ??? (define_insn "" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "ble %b0") (define_insn "" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* OUTPUT_JUMP (\"bge %b0\", \"fbnlt %b0\", \"jbmc %b0\"); ") (define_insn "" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "blt %b0") (define_insn "" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* OUTPUT_JUMP (\"blt %b0\", \"fbnge %b0\", \"jbms %b0\"); ") (define_insn "" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "blt %b0") ;; ???? (define_insn "" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* OUTPUT_JUMP (\"bgt %b0\", \"fbnle %b0\", 0); ") (define_insn "" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "bgt %b0") ;; Unconditional and other jump instructions (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "bra %b0") (define_insn "tablejump" [(set (pc) (plus:SI (pc) (match_operand:SI 0 "general_operand" "r"))) (use (label_ref (match_operand 1 "" "")))] "" "jmp @(pc:b,4:4,%0)") ;; ;; Should Add code for "ACB", "SCB". !!! ???? ;; See m68k.h (dbra) ;; ;; Call subroutine with no return value. (define_insn "call" [(call (match_operand:QI 0 "general_operand" "m") (match_operand:SI 1 "general_operand" "rmi"))] ;; Operand 1 not really used on the Gmicro. "" "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0],0)) == SYMBOL_REF) return \"bsr %b0\"; return \"jsr %0\"; }") ;; Call subroutine, returning value in operand 0 ;; (which must be a hard register). (define_insn "call_value" [(set (match_operand 0 "" "=rf") (call (match_operand:QI 1 "general_operand" "m") (match_operand:SI 2 "general_operand" "rmi")))] ;; Operand 2 not really used on the Gmicro. "" "* { if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF) return \"bsr %b1\"; return \"jsr %1\"; }") (define_insn "nop" [(const_int 0)] "" "nop") ;; Turned off because the general move-an-address pattern handles it. ;; ;; Thus goes after the move instructions ;; because the move instructions are better (require no spilling) ;; when they can apply. ;; After add/sub now !! ;(define_insn "pushasi" ; [(set (match_operand:SI 0 "push_operand" "=m") ; (match_operand:SI 1 "address_operand" "p"))] ; "" ; "* ;{ ; if (GET_CODE (operands[1]) == CONST_INT) ; return push_imm_word (INTVAL (operands[1]), operands[0]); ; if (CONSTANT_P (operands[1])) ; return \"mov.w %1,%-\"; ; if (GET_CODE (operands[1]) == REG) ; return \"mov.w %1,%-\"; ; else if (GET_CODE (operands[1]) == MEM) ; { ; return \"mov.w %1,%-\"; ; } ; else ; return \"mova.w %p1,%-\"; ;}") ;; This should not be used unless the add/sub insns can't be. /* mova.[whq] 89.08.11 for test M.Yuhara */ ;(define_insn "" ; [(set (match_operand:SI 0 "general_operand" "=rm") ; (address (match_operand:SI 1 "address_operand" "p")))] ; "" ; "* ;{ ; if (GET_CODE (operands[1]) == CONST_INT) ; return mov_imm_word (INTVAL (operands[1]), operands[0]); ; if (CONSTANT_P (operands[1])) ; return \"mov.w %1,%0\"; ; if (GET_CODE (operands[1]) == REG) ; return \"mov.w %1,%0\"; ; else if (GET_CODE (operands[1]) == MEM) { ; operands[1] = XEXP (operands[1],0); ; return \"mov.w %1,%0\"; ; } ; else ; return \"mova.w %p1,%0\"; ;}") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") (address (match_operand:HI 1 "address_operand" "")))] "" "* { if (GET_CODE (operands[1]) == CONST_INT) return mov_imm_word (INTVAL (operands[1]), operands[0]); if (CONSTANT_P (operands[1])) return \"mov.w %1,%0\"; if (GET_CODE (operands[1]) == REG) return \"mov.w %1,%0\"; else if (GET_CODE (operands[1]) == MEM) { operands[1] = XEXP (operands[1],0); return \"mov.w %1,%0\"; /* OK ? */ } else return \"mova.w %p1,%0\"; }") ;(define_insn "" ; [(set (match_operand:SI 0 "general_operand" "=rm") ; (match_operand:QI 1 "address_operand" "p"))] ; "" ; "* ;{ ; if (push_operand (operands[0], SImode)) ; return \"mova %1,%-\"; ; return \"mova %1,%0\"; ;}") ;(define_insn "" ; [(set (match_operand:SI 0 "general_operand" "=rm") ; (match_operand:QI 1 "address_operand" "p"))] ; "" ; "* ;{ ; if (CONSTANT_P (operands[1])) ; return \"mov.w %1,%0\"; ; else if (GET_CODE (operands[1]) == REG) ; return \"mov.w %1,%0\"; ; else if (GET_CODE (operands[1]) == MEM) ; { ; operands[1] = XEXP (operands[1],0); ; return \"mov.w %1,%0 ; OK?\"; ; } ; else if (GET_CODE (operands[0]) == REG ; && GET_CODE (operands[1]) == PLUS) ; { ; rtx xreg, xdisp; ; ; if (GET_CODE (XEXP (operands[1], 0)) == REG ; && REGNO (XEXP (operands[1], 0)) == REGNO (operands[0])) ; { ; xreg = XEXP (operands[1], 0); ; xdisp = XEXP (operands[1],1); ; } ; else ; { ; xreg = XEXP (operands[1], 1); ; xdisp = XEXP (operands[1],0); ; } ; ; if (GET_CODE (xreg) == REG ; && REGNO (xreg) == REGNO (operands[0]) ; && (CONSTANT_P (xdisp) || GET_CODE (xdisp) == REG)) ; { ; operands[1] = xdisp; ; if (CONSTANT_P (xdisp)) ; return add_imm_word (INTVAL (xdisp), xreg, &operands[1]); ; else ; return \"add.w %1,%0\"; ; } ; } ; return \"mova.w %p1,%0\"; ;}") ;; This is the first machine-dependent peephole optimization. ;; It is useful when a floating value is returned from a function call ;; and then is moved into an FP register. ;; But it is mainly intended to test the support for these optimizations. (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) (set (match_operand:DF 0 "register_operand" "=f") (match_operand:DF 1 "register_operand" "r"))] "FPU_REG_P (operands[0]) && ! FPU_REG_P (operands[1])" "* { rtx xoperands[2]; xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"mov.w %1,@sp\", xoperands); output_asm_insn (\"mov.w %1,%-\", operands); return \"fmov.d %+,%0\"; } ") ;;- Local variables: ;;- mode:emacs-lisp ;;- comment-start: ";;- " ;;- comment-start-skip: ";+- *" ;;- 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: