8sa1-gcc/gcc/config/gmicro/gmicro.md
Torbjorn Granlund d12a2c91ca Initial revision
From-SVN: r474
1992-03-14 05:15:35 +00:00

66 KiB
Raw Blame History

;;- 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: