;;- Machine description for GNU compiler ;;- MIL-STD-1750A version. ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc. ;; Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de). ;; This file is part of GNU CC. ;; GNU CC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 1, or (at your option) ;; any later version. ;; GNU CC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, 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. ;; MIL-STD-1750 specific remarks: ;; ;; 1) BITS_PER_UNIT = 16 ;; ;; 2) GCC to MIL-STD-1750 data type mappings: ;; QImode => single integer (16 bits or 1 reg). ;; HImode => double integer (32 bits or 2 regs). ;; HFmode => single precision float (32 bits or 2 regs). ;; TQFmode => extended precision float (48 bits or 3 regs). ;; ;; 3) Immediate integer operands Constraints: ;; 'I' 1 .. 16 ;; 'J' -1 ..-16 ;; 'K' 0 .. 15 ;; 'L' 0 .. 255 ;; 'M' -32768 .. 32767 ;; 'O' => 0 (for optimizations and GCC quirks) ;; ;; Further notes: ;;- Assembly output ending in ".M" are macros in file M1750.INC ;; stackpush (define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "general_operand" "r"))] "" "pshm r%1,r%1 ; stackptr = R%0") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "general_operand" "r"))] "" "* { rtx new_operands[3]; new_operands[2] = operands[0]; new_operands[0] = operands[1]; new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+1); output_asm_insn(\"pshm r%0,r%1 ; stackptr = r%2\",new_operands); return \";\"; } ") (define_insn "" [(set (match_operand:HF 0 "push_operand" "=<") (match_operand:HF 1 "general_operand" "r"))] "" "* { rtx new_operands[3]; new_operands[2] = operands[0]; new_operands[0] = operands[1]; new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+1); output_asm_insn(\"pshm r%0,r%1 ; stackptr = r%2\",new_operands); return \";\"; } ") (define_insn "" [(set (match_operand:TQF 0 "push_operand" "=<") (match_operand:TQF 1 "general_operand" "r"))] "" "* { rtx new_operands[3]; new_operands[2] = operands[0]; new_operands[0] = operands[1]; new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+2); output_asm_insn(\"pshm r%0,r%1 ; stackptr = r%2\",new_operands); return \";\"; } ") ;; stackpop (define_insn "" [(set (match_operand:QI 0 "general_operand" "=r") (match_operand:QI 1 "push_operand" ">"))] "" "popm r%1,r%1") (define_insn "" [(set (match_operand:HI 0 "general_operand" "=r") (match_operand:HI 1 "push_operand" ">"))] "" "* { rtx new_operands[2]; new_operands[0] = operands[0]; new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+1); output_asm_insn(\"popm r%0,r%1\",new_operands); return \";\"; } ") (define_insn "" [(set (match_operand:HF 0 "general_operand" "=r") (match_operand:HF 1 "push_operand" ">"))] "" "* { rtx new_operands[2]; new_operands[0] = operands[0]; new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+1); output_asm_insn(\"popm r%0,r%1\",new_operands); return \";\"; } ") (define_insn "" [(set (match_operand:TQF 0 "general_operand" "=r") (match_operand:TQF 1 "push_operand" ">"))] "" "* { rtx new_operands[2]; new_operands[0] = operands[0]; new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+2); output_asm_insn(\"popm r%0,r%1\",new_operands); return \";\"; } ") ;; Test operations. These shouldn't really occur for 1750: ;; all important instructions set the cc's (see NOTICE_UPDATE_CC) (define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "register_operand" "r"))] "" "lr r%0,r%0 ; from tstqi") (define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "register_operand" "r"))] "" "dlr r%0,r%0 ; from tsthi") (define_insn "tsthf" [(set (cc0) (match_operand:HF 0 "register_operand" "r"))] "" "dlr r%0,r%0 ; from tsthf") ;; This one is happy with "roughly zero" :-) (should be improved) (define_insn "tsttqf" [(set (cc0) (match_operand:TQF 0 "register_operand" "r"))] "" "dlr r%0,r%0 ; from tsttqf") ;; block move. ; there is a problem with this insn in gcc-2.2.3 ; (clobber (match_dup 2)) does not prevent use of this operand later ; (define_insn "movstrqi" [(set (mem:BLK (match_operand:QI 0 "register_operand" "r")) (mem:BLK (match_operand:QI 1 "register_operand" "r"))) (use (match_operand:QI 2 "register_operand" "r")) (use (match_operand:QI 3 "immediate_operand" "")) (clobber (match_dup 0)) (clobber (match_dup 1)) (clobber (match_dup 2))] "" "* return (char *)movcnt_regno_adjust(operands); ") ;; compare instructions. (define_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "register_operand" "r,r,r,r,r") (match_operand:QI 1 "general_operand" "I,J,i,r,m")))] "" "* { if (next_cc_user_is_unsigned (insn)) switch (which_alternative) { case 0: case 1: case 2: return \"ucim.m %0,%1\"; case 3: return \"ucr.m %0,%1\"; case 4: return \"uc.m %0,%1\"; } else switch (which_alternative) { case 0: return \"cisp r%0,%1\"; case 1: return \"cisn r%0,%J1\"; case 2: return \"cim r%0,%1\"; case 3: return \"cr r%0,r%1\"; case 4: return \"c r%0,%1\"; } } ") (define_insn "cmphi" [(set (cc0) (compare (match_operand:HI 0 "general_operand" "r,r") (match_operand:HI 1 "general_operand" "r,m")))] "" "@ dcr r%0,r%1 dc r%0,%1 ") (define_insn "cmphf" [(set (cc0) (compare (match_operand:HF 0 "general_operand" "r,z,r") (match_operand:HF 1 "general_operand" "r,Q,m")))] "" "@ fcr r%0,r%1 fcb %Q1 fc r%0,%1 ") (define_insn "cmptqf" [(set (cc0) (compare (match_operand:TQF 0 "general_operand" "r,r") (match_operand:TQF 1 "general_operand" "r,m")))] "" "@ efcr r%0,r%1 efc r%0,%1 ") ;; truncation instructions ;;- 1750: any needed? (define_insn "trunchiqi2" [(set (match_operand:QI 0 "register_operand" "=r") (truncate:QI (match_operand:HI 1 "register_operand" "r")))] "" "* { rtx new_operands[2]; new_operands[0] = operands[0]; new_operands[1] = gen_rtx (REG, HImode, REGNO(operands[1]) + 1); output_asm_insn(\"lr r%0,r%1 ;trunchiqi2\",new_operands); return \";\"; } ") ;; zero extension instructions (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (zero_extend:HI (match_operand:QI 1 "general_operand" "r,m,i")))] "" "* { rtx new_opnds[2]; output_asm_insn(\"xorr r%0,r%0 ;zero_extendqihi2\",operands); new_opnds[0] = gen_rtx (REG, HImode, REGNO(operands[0]) + 1); new_opnds[1] = operands[1]; switch (which_alternative) { case 0: output_asm_insn(\"lr r%0,r%1\",new_opnds); break; case 1: output_asm_insn(\"l r%0,%1\",new_opnds); break; case 2: output_asm_insn(\"lim r%0,%1\",new_opnds); break; } return \";\"; } ") ;; sign extension instructions (define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (sign_extend:HI (match_operand:QI 1 "general_operand" "r,m,i")) )] "" "@ lr r%0,r%1 ;extendqihi2\;dsra r%0,16 l r%0,%1 ;extendqihi2\;dsra r%0,16 lim r%0,%1 ;extendqihi2\;dsra r%0,16 ") ;; Conversions between float and double. ; 1750 HF-to-TQF extend: just append 16 bits (least signif.) with all bits zero (define_insn "extendhftqf2" [(set (match_operand:TQF 0 "register_operand" "=r,r") (float_extend:TQF (match_operand:HF 1 "general_operand" "r,m")))] "" "* { rtx new_opnds[2]; new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]) + 2); new_opnds[1] = operands[1]; output_asm_insn(\"xorr r%0,r%0 ;extendhftqf2\",new_opnds); if (which_alternative == 0) return \"dlr r%0,r%1 ; put condition codes back on track\"; else return \"dl r%0,%1 ; put condition codes back on track\"; } ") ; 1750 TQF-to-HF truncate is a no-op: just leave away the least signif. 16 bits (define_insn "trunctqfhf2" [(set (match_operand:HF 0 "register_operand" "=r,r") (float_truncate:HF (match_operand:TQF 1 "general_operand" "r,m")))] "" "@ dlr r%0,r%1 ;trunctqfhf2 dl r%0,%1 ;trunctqfhf2 ") ;; Conversion between fixed point and floating point. (define_insn "floatqihf2" [(set (match_operand:HF 0 "register_operand" "=r") (float:HF (match_operand:QI 1 "register_operand" "r")))] "" "flt r%0,r%1") (define_insn "floathitqf2" [(set (match_operand:TQF 0 "register_operand" "=r") (float:TQF (match_operand:HI 1 "register_operand" "r")))] "" "eflt r%0,r%1") ;; Convert floats to ints (define_insn "fix_trunchfqi2" [(set (match_operand:QI 0 "register_operand" "=r") (fix:QI (fix:HF (match_operand:HF 1 "register_operand" "r"))))] "" "fix r%0,r%1") (define_insn "fix_trunctqfhi2" [(set (match_operand:HI 0 "register_operand" "=r") (fix:HI (fix:TQF (match_operand:TQF 1 "register_operand" "r"))))] "" "efix r%0,r%1") ;; Move instructions ;; We can't deal with normal byte-size characters, only with WIDE characters! ;; This may appear as a serious restriction, but it also opens the doors ;; for ISO 10646 :-) ;; 16-bit moves (define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,r,t,r,Q,m,m") (match_operand:QI 1 "general_operand" "O,I,J,M,i,r,Q,m,t,r,K"))] "" "@ xorr r%0,r%0 lisp r%0,%1 lisn r%0,%J1 lim r%0,%1 ; 'M' constraint lim r%0,%1 ; 'i' constraint lr r%0,r%1 lb %Q1 l r%0,%1 stb %Q0 st r%1,%0 stc %1,%0 ") ;; 32-bit moves ; Set HIreg to constant (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (match_operand:HI 1 "immediate_operand" "i"))] "" "* { rtx new_opnds[2]; int val = INTVAL(operands[1]); if (val >= 0) { if (val <= 65535) { new_opnds[0] = gen_rtx(REG,QImode,REGNO(operands[0])); new_opnds[1] = operands[1]; output_asm_insn(\"xorr r%0,r%0 ;movhi cst->reg\",new_opnds); REGNO(new_opnds[0]) += 1; if (val == 0) output_asm_insn(\"xorr r%0,r%0\",new_opnds); else if (val <= 16) output_asm_insn(\"lisp r%0,%1\",new_opnds); else output_asm_insn(\"lim r%0,%1\",new_opnds); return \";\"; } } else if (val >= -16) return \"lisn r%0,%J1\;dsra r%0,16 ;movhi cst\"; new_opnds[0] = gen_rtx(REG, QImode, REGNO(operands[0])); new_opnds[1] = gen_rtx(CONST_INT,VOIDmode,(INTVAL(operands[1])) >> 16); output_asm_insn(\"lim r%0,%1 ;movhi cst->reg\",new_opnds); INTVAL(new_opnds[1]) = val & 0xFFFF; REGNO(new_opnds[0]) += 1; output_asm_insn(\"lim r%0,%1\",new_opnds); return \";\"; } ") (define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=r,z,r,Q,m") (match_operand:HI 1 "general_operand" "r,Q,m,z,r"))] "" "@ dlr r%0,r%1 dlb %Q1 dl r%0,%1 dstb %Q0 dst r%1,%0 ") ;; Single-Float moves are *same* as HImode moves: ;(define_insn "movhf" ; [(set (match_operand:HF 0 "general_operand" "=r,r,r,m") ; (match_operand:HF 1 "general_operand" "F,r,m,r"))] ; "" ; "@ ; %D1\;dl r%0,%F1 ; dlr r%0,r%1 ; dl r%0,%1 ; dst r%1,%0 ") (define_insn "movhf" [(set (match_operand:HF 0 "general_operand" "=r,z,r,Q,m") (match_operand:HF 1 "general_operand" "r,Q,m,z,r"))] "" "@ dlr r%0,r%1 dlb %Q1 dl r%0,%1 dstb %Q0 dst r%1,%0 ") ;; Longfloat moves ;(define_insn "movtqf" ; [(set (match_operand:TQF 0 "general_operand" "=r,r,r,m") ; (match_operand:TQF 1 "general_operand" "F,r,m,r"))] ; "" ; "@ ; %E1\;efl r%0,%G1 ; eflr.m %0,%1 ; efl r%0,%1 ; efst r%1,%0 ") (define_insn "movtqf" [(set (match_operand:TQF 0 "general_operand" "=r,r,m") (match_operand:TQF 1 "general_operand" "r,m,r"))] "" "@ eflr.m %0,%1 efl r%0,%1 efst r%1,%0 ") ;; add instructions ;; single integer (define_insn "addqi3" [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,t,r,m,m") (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0,0,0") (match_operand:QI 2 "general_operand" "I,J,i,r,Q,m,I,J")))] "" "* switch (which_alternative) { case 0: return \"aisp r%0,%2\"; case 1: return \"sisp r%0,%J2\"; case 2: if (INTVAL(operands[2]) < 0) return \"sim r%0,%J2\"; else return \"aim r%0,%2\"; case 3: return \"ar r%0,r%2\"; case 4: return \"ab %Q2\"; case 5: return \"a r%0,%2\"; case 6: return \"incm %2,%0\"; case 7: return \"decm %J2,%0\"; } ") ;; double integer (define_insn "addhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (plus:HI (match_operand:HI 1 "register_operand" "%0,0") (match_operand:HI 2 "general_operand" "r,m")))] "" "@ dar r%0,r%2 da r%0,%2 ") (define_insn "addhf3" [(set (match_operand:HF 0 "register_operand" "=r,z,r") (plus:HF (match_operand:HF 1 "register_operand" "%0,0,0") (match_operand:HF 2 "general_operand" "r,Q,m")))] "" "@ far r%0,r%2 fab %Q2 fa r%0,%2 ") (define_insn "addtqf3" [(set (match_operand:TQF 0 "register_operand" "=r,r") (plus:TQF (match_operand:TQF 1 "register_operand" "%0,0") (match_operand:TQF 2 "general_operand" "r,m")))] "" "@ efar r%0,r%2 efa r%0,%2 ") ;; subtract instructions ;; single integer (define_insn "subqi3" [(set (match_operand:QI 0 "general_operand" "=r,r,r,t,r,m") (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0,0,0") (match_operand:QI 2 "general_operand" "I,i,r,Q,m,I")))] "" "@ sisp r%0,%2 sim r%0,%2 sr r%0,r%2 sbb %Q2 s r%0,%2 decm %2,%0 ") ;; double integer (define_insn "subhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (minus:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "general_operand" "r,m")))] "" "@ dsr r%0,r%2 ds r%0,%2 ") (define_insn "subhf3" [(set (match_operand:HF 0 "register_operand" "=r,z,r") (minus:HF (match_operand:HF 1 "register_operand" "0,0,0") (match_operand:HF 2 "general_operand" "r,Q,m")))] "" "@ fsr r%0,r%2 fsb %Q2 fs r%0,%2 ") (define_insn "subtqf3" [(set (match_operand:TQF 0 "register_operand" "=r,r") (minus:TQF (match_operand:TQF 1 "register_operand" "0,0") (match_operand:TQF 2 "general_operand" "r,m")))] "" "@ efsr r%0,r%2 efs r%0,%2 ") ;; multiply instructions (define_insn "mulqi3" [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r") (mult:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0") (match_operand:QI 2 "general_operand" "I,J,M,r,m")))] "" "@ misp r%0,%2 misn r%0,%J2 msim r%0,%2 msr r%0,r%2 ms r%0,%2 ") ; 32-bit product (define_insn "mulqihi3" [(set (match_operand:HI 0 "register_operand" "=r,r,t,r") (mult:HI (match_operand:QI 1 "register_operand" "%0,0,0,0") (match_operand:QI 2 "general_operand" "M,r,Q,m")))] "" "@ mim r%0,%1 mr r%0,r%2 mb %Q2 m r%0,%2 ") (define_insn "mulhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (mult:HI (match_operand:HI 1 "register_operand" "%0,0") (match_operand:HI 2 "general_operand" "r,m")))] "" "@ dmr r%0,r%2 dm r%0,%2 ") ; not available on 1750: "umulhi3","umulhisi3","umulsi3" (unsigned multiply's) (define_insn "mulhf3" [(set (match_operand:HF 0 "register_operand" "=r,z,r") (mult:HF (match_operand:HF 1 "register_operand" "%0,0,0") (match_operand:HF 2 "general_operand" "r,Q,m")))] "" "@ fmr r%0,r%2 fmb %Q2 fm r%0,%2 ") (define_insn "multqf3" [(set (match_operand:TQF 0 "register_operand" "=r,r") (mult:TQF (match_operand:TQF 1 "register_operand" "%0,0") (match_operand:TQF 2 "general_operand" "r,m")))] "" "@ efmr r%0,r%2 efm r%0,%2 ") ;; divide instructions ;; The 1750 16bit integer division instructions deliver a 16-bit ;; quotient and a 16-bit remainder, where the remainder is in the next higher ;; register number above the quotient. For now, we haven't found a way ;; to give the reload pass knowledge of this property. So we make do with ;; whatever registers the allocator wants, and willy-nilly output a pair of ;; register-copy ops when needed. (See mod_regno_adjust() in file aux-output.c) ;; A comment in the description of `divmodM4' suggests that one leave the divM3 ;; undefined when there is a divmodM4 available. (define_insn "divmodqi4" [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r") (div:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0") (match_operand:QI 2 "general_operand" "I,J,M,r,m"))) (set (match_operand:QI 3 "register_operand" "=r,r,r,r,r") (mod:QI (match_dup 1) (match_dup 2)))] "" "* { char *istr; switch(which_alternative) { case 0: istr = \"disp\"; break; case 1: { rtx new_opnds[4]; new_opnds[0] = operands[0]; new_opnds[1] = operands[1]; new_opnds[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL(operands[2])); new_opnds[3] = operands[3]; istr = \"disn\"; return (char *)mod_regno_adjust(istr,new_opnds); } break; case 2: istr = \"dvim\"; break; case 3: istr = \"dvr \"; break; case 4: istr = \"dv \"; break; } return (char *)mod_regno_adjust(istr,operands); }") ;; Division for other types is straightforward. (define_insn "divhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (div:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "general_operand" "r,m")))] "" "@ ddr r%0,r%2 dd r%0,%2 ") (define_insn "divhf3" [(set (match_operand:HF 0 "register_operand" "=r,z,r") (div:HF (match_operand:HF 1 "register_operand" "0,0,0") (match_operand:HF 2 "general_operand" "r,Q,m")))] "" "@ fdr r%0,r%2 fdb %Q2 fd r%0,%2 ") (define_insn "divtqf3" [(set (match_operand:TQF 0 "register_operand" "=r,r") (div:TQF (match_operand:TQF 1 "register_operand" "0,0") (match_operand:TQF 2 "general_operand" "r,m")))] "" "@ efdr r%0,r%2 efd r%0,%2 ") ;; Other arithmetic instructions: ;; Absolute value (define_insn "absqi2" [(set (match_operand:QI 0 "register_operand" "=r") (abs:QI (match_operand:QI 1 "register_operand" "r")))] "" "abs r%0,r%1") (define_insn "abshi2" [(set (match_operand:HI 0 "register_operand" "=r") (abs:HI (match_operand:HI 1 "register_operand" "r")))] "" "dabs r%0,r%1") (define_insn "abshf2" [(set (match_operand:HF 0 "register_operand" "=r") (abs:HF (match_operand:HF 1 "register_operand" "r")))] "" "fabs r%0,r%1") ;; Negation (define_insn "negqi2" [(set (match_operand:QI 0 "register_operand" "=r") (neg:QI (match_operand:QI 1 "register_operand" "r")))] "" "neg r%0,r%1") (define_insn "neghi2" [(set (match_operand:HI 0 "register_operand" "=r") (neg:HI (match_operand:HI 1 "register_operand" "r")))] "" "dneg r%0,r%1") (define_insn "neghf2" [(set (match_operand:HF 0 "register_operand" "=r") (neg:HF (match_operand:HF 1 "register_operand" "r")))] "" "fneg r%0,r%1") ; The 1750A does not have an extended float negate instruction, so simulate. (define_expand "negtqf2" [(set (match_operand:TQF 0 "register_operand" "=&r") (neg:TQF (match_operand:TQF 1 "register_operand" "r")))] "" " emit_insn(gen_rtx(SET,VOIDmode,operands[0],CONST0_RTX(TQFmode))); emit_insn(gen_rtx(SET,VOIDmode,operands[0], gen_rtx(MINUS,TQFmode,operands[0],operands[1]))); DONE; ") ;; bit-logical instructions ;; AND (define_insn "andqi3" [(set (match_operand:QI 0 "general_operand" "=r,r,t,r") (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0") (match_operand:QI 2 "general_operand" "M,r,Q,m")))] "" "@ andm r%0,%2 andr r%0,r%2 andb %Q2 and r%0,%2 ") ; This sets incorrect condition codes. See notice_update_cc() (define_insn "andhi3" [(set (match_operand:HI 0 "register_operand" "=r") (and:HI (match_operand:HI 1 "register_operand" "%0") (match_operand:HI 2 "register_operand" "r")))] "" "danr.m %0,%2") ;; OR (define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=r,r,t,r") (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0") (match_operand:QI 2 "general_operand" "M,r,Q,m")))] "" "@ orim r%0,%2 orr r%0,r%2 orb %Q2 or r%0,%2 ") ; This sets incorrect condition codes. See notice_update_cc() (define_insn "iorhi3" [(set (match_operand:HI 0 "register_operand" "=r") (ior:HI (match_operand:HI 1 "register_operand" "%0") (match_operand:HI 2 "register_operand" "r")))] "" "dorr.m %0,%2") ;; XOR (define_insn "xorqi3" [(set (match_operand:QI 0 "register_operand" "=r,r,r") (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "M,r,m")))] "" "@ xorm r%0,%2 xorr r%0,r%2 xor r%0,%2 ") ; This sets incorrect condition codes. See notice_update_cc() (define_insn "xorhi3" [(set (match_operand:HI 0 "register_operand" "=r") (xor:HI (match_operand:HI 1 "register_operand" "%0") (match_operand:HI 2 "register_operand" "r")))] "" "dxrr.m %0,%2") ;; NAND (define_insn "" [(set (match_operand:QI 0 "register_operand" "=r,r,r") (ior:QI (not:QI (match_operand:QI 1 "register_operand" "%0,0,0")) (not:QI (match_operand:QI 2 "general_operand" "M,r,m"))))] "" "@ nim r%0,%2 nr r%0,r%2 n r%0,%2 ") ; This sets incorrect condition codes. See notice_update_cc() (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (ior:HI (not:HI (match_operand:HI 1 "register_operand" "%0")) (not:HI (match_operand:HI 2 "register_operand" "r"))))] "" "dnr.m %0,%2") ;; NOT (define_insn "one_cmplqi2" [(set (match_operand:QI 0 "register_operand" "=r") (not:QI (match_operand:QI 1 "register_operand" "0")))] "" "nr r%0,r%0") ; This sets incorrect condition codes. See notice_update_cc() (define_insn "one_cmplhi2" [(set (match_operand:HI 0 "register_operand" "=r") (not:HI (match_operand:HI 1 "register_operand" "0")))] "" "dnr.m %0,%0") ;; Shift instructions ; (What to the 1750 is logical-shift-left, GCC likes to call "arithmetic") (define_insn "ashlqi3" [(set (match_operand:QI 0 "register_operand" "=r,r") (ashift:QI (match_operand:QI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,r")))] "" "@ sll r%0,%2 slr r%0,r%2 ") (define_insn "ashlhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (ashift:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "L,r")))] "" ; the 'L' constraint is a slight imprecise... "* if (which_alternative == 1) return \"dslr r%0,r%2\"; else if (INTVAL(operands[2]) <= 16) return \"dsll r%0,%2\"; else { rtx new_opnds[2]; new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0])); new_opnds[1] = gen_rtx (REG, QImode, REGNO(operands[0]) + 1); output_asm_insn(\"lr r%0,r%1 ; ashlhi3 shiftcount > 16\",new_opnds); new_opnds[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL(operands[2]) - 16); output_asm_insn(\"sll r%0,%1\",new_opnds); return \";\"; } ") ;; Right shift by a variable shiftcount works by negating the shift count, ;; then emitting a right shift with the shift count negated. This means ;; that all actual shift counts in the RTL will be positive. This ;; prevents converting shifts to ZERO_EXTRACTs with negative positions, ;; which isn't valid. (define_expand "lshrqi3" [(set (match_operand:QI 0 "general_operand" "=r") (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "nonmemory_operand" "g")))] "" " { if (GET_CODE (operands[2]) != CONST_INT) operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); }") (define_insn "" [(set (match_operand:QI 0 "register_operand" "=r") (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "immediate_operand" "I")))] "" "srl r%0,%2") (define_insn "" [(set (match_operand:QI 0 "register_operand" "=r") (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") (neg:QI (match_operand:QI 2 "register_operand" "r"))))] "" "slr r%0,r%2 ") ;; Same thing for HImode. (define_expand "lshrhi3" [(set (match_operand:HI 0 "register_operand" "=r") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (match_operand:QI 2 "nonmemory_operand" "g")))] "" " { if (GET_CODE (operands[2]) != CONST_INT) operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); }") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (match_operand:QI 2 "immediate_operand" "L")))] "" "* { rtx new_opnds[2]; int amount = INTVAL(operands[2]); if (amount <= 16) return \"dsrl r%0,%2\"; output_asm_insn(\"dsrl r%0,16 ; lshrhi3 shiftcount > 16\",operands); new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]) + 1); new_opnds[1] = gen_rtx (CONST_INT, VOIDmode, amount - 16); output_asm_insn(\"srl r%0,%1\",new_opnds); return \";\"; } ") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (neg:QI (match_operand:QI 2 "register_operand" "r"))))] "" "dslr r%0,r%2 ") ;; Same applies for arithmetic shift right. (define_expand "ashrqi3" [(set (match_operand:QI 0 "general_operand" "=r") (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") (match_operand:QI 2 "nonmemory_operand" "g")))] "" " { if (GET_CODE (operands[2]) != CONST_INT) operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); }") (define_insn "" [(set (match_operand:QI 0 "register_operand" "=r") (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "immediate_operand" "I")))] "" "sra r%0,%2") (define_insn "" [(set (match_operand:QI 0 "register_operand" "=r") (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (neg:QI (match_operand:QI 2 "register_operand" "r"))))] "" "sar r%0,r%2 ") ;; HImode arithmetic shift right. (define_expand "ashrhi3" [(set (match_operand:HI 0 "general_operand" "=r") (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") (match_operand:QI 2 "nonmemory_operand" "g")))] "" " { if (GET_CODE (operands[2]) != CONST_INT) operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); }") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") (match_operand:QI 2 "immediate_operand" "L")))] "" "* { rtx new_opnds[2]; int amount = INTVAL(operands[2]); if (amount <= 16) return \"dsra r%0,%2\"; output_asm_insn(\"dsra r%0,16 ; ashrhi3 shiftcount > 16\",operands); new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]) + 1); new_opnds[1] = gen_rtx (CONST_INT, VOIDmode, amount - 16); output_asm_insn(\"sra r%0,%1\",new_opnds); return \";\"; } ") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") (neg:QI (match_operand:QI 2 "register_operand" "r"))))] "" "dsar r%0,r%2 ") ;; rotate instructions (define_insn "rotlqi3" [(set (match_operand:QI 0 "register_operand" "=r,r") (rotate:QI (match_operand:QI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,r")))] "" "@ slc r%0,%2 scr r%0,r%2 ") (define_insn "rotlhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (rotate:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "I,r")))] "" "@ dslc r%0,%2 dscr r%0,r%2 ") (define_insn "rotrqi3" [(set (match_operand:QI 0 "register_operand" "=r") (rotatert:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "register_operand" "r")))] "" "neg r%2,r%2\;scr r%0,r%2 ") (define_insn "rotrhi3" [(set (match_operand:HI 0 "register_operand" "=r") (rotatert:HI (match_operand:HI 1 "register_operand" "0") (match_operand:QI 2 "nonmemory_operand" "r")))] "" "neg r%2,r%2\;dscr r%0,r%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. ; 1750: t.b.d. ;******************** ;; Bit field instructions, general cases. ;; "o,d" constraint causes a nonoffsetable memref to match the "o" ;; so that its address is reloaded. ;; (define_insn "extv" ... ;; (define_insn "extzv" ... ;; (define_insn "insv" ... ;; Now recognize bit field insns that operate on registers ;; (or at least were intended to do so). ;[unnamed only] ;; Special patterns for optimizing bit-field instructions. ;************************************** ; cc status test ops n.a. on 1750 ......... e.g. "sleu" on 68k: ; [(set (match_operand:QI 0 "general_operand" "=d") ; (leu (cc0) (const_int 0)))] ; "" ; "* cc_status = cc_prev_status; ; return \"sls %0\"; ") ;; Basic conditional jump instructions. (define_insn "beq" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return (char *)branch_or_jump(\"ez\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "bne" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return (char *)branch_or_jump(\"nz\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "bgt" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return (char *)branch_or_jump(\"gt\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "blt" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return (char *)branch_or_jump(\"lt\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "bge" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return (char *)branch_or_jump(\"ge\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "ble" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return (char *)branch_or_jump(\"le\",CODE_LABEL_NUMBER(operands[0])); ") ; no unsigned branches available on 1750. But GCC still needs them, so faking: (define_insn "bgtu" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jc gt,%l0 ; Warning: this should be an *unsigned* test!") (define_insn "bltu" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jc lt,%l0 ; Warning: this should be an *unsigned* test!") (define_insn "bgeu" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jc ge,%l0 ; Warning: this should be an *unsigned* test!") (define_insn "bleu" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jc le,%l0 ; Warning: this should be an *unsigned* test!") ;; Negated conditional jump instructions. (define_insn "" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return (char *)branch_or_jump(\"nz\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return (char *)branch_or_jump(\"ez\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return (char *)branch_or_jump(\"le\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return (char *)branch_or_jump(\"ge\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return (char *)branch_or_jump(\"lt\",CODE_LABEL_NUMBER(operands[0])); ") (define_insn "" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return (char *)branch_or_jump(\"gt\",CODE_LABEL_NUMBER(operands[0])); ") ;; Negated unsigned conditional jump instructions (faked for 1750). (define_insn "" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jc le,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") (define_insn "" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jc ge,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") (define_insn "" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jc lt,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") (define_insn "" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jc gt,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") ;; Tablejump ;; 1750 note: CASE_VECTOR_PC_RELATIVE is not defined (define_insn "tablejump" [(set (pc) (match_operand:QI 0 "register_operand" "b")) (use (label_ref (match_operand 1 "" "")))] "" "jc 15,0,r%0 ; tablejump label_ref=%1") ;; Unconditional jump (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "jc 15,%0") ;; Call subroutine, returning value in operand 0 ;; (which must be a hard register). (define_insn "call_value" [(set (match_operand 0 "register_operand" "r") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g")))] ;; Operand 2 not really used for 1750. "" "sjs r15,%1 ; return value in R0") ;; Call subroutine with no return value. ;; Operand 1 not really used in MIL-STD-1750. (define_insn "" [(call (match_operand:QI 0 "memory_operand" "mp") (match_operand:QI 1 "general_operand" ""))] "" "sjs r15,%0 ; no return value") ;;;;;;;;;;;; 1750: NOT READY YET. (define_insn "call" [(call (match_operand:QI 0 "" "") (match_operand:QI 1 "" ""))] "" "ANYCALL %0") ; (define_insn "return" ; [(return)] ; "" ; "* ; { ; rtx oprnd = gen_rtx(CONST_INT,VOIDmode,get_frame_size()); ; output_asm_insn(\"ret.m %0\",&oprnd); ; return \"\;\"; ; } ") (define_insn "indirect_jump" [(set (pc) (match_operand:QI 0 "address_operand" "p"))] "" "jci 15,%0") (define_insn "nop" [(const_int 0)] "" "nop") ;; Subtract One and Jump (if non-zero) (define_peephole [(set (match_operand:QI 0 "register_operand" "=r") (plus:QI (match_operand:QI 1 "register_operand" "%0") (match_operand:QI 2 "immediate_operand" "J"))) (set (cc0) (match_dup 0)) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 3 "" "")) (pc))) ] "INTVAL(operands[2]) == -1" "soj r%0,%3") ;; Combine a Load Register with subsequent increment/decrement into a LIM (define_peephole [(set (match_operand:QI 0 "register_operand" "=r") (match_operand:QI 1 "register_operand" "b")) (set (match_dup 0) (plus:QI (match_dup 0) (match_operand:QI 2 "immediate_operand" "i")))] "REGNO(operands[1]) > 0" "lim r%0,%2,r%1 ; LR,inc/dec peephole") ;; Eliminate the redundant load in a store/load sequence (define_peephole [(set (mem:QI (plus:QI (match_operand:QI 0 "register_operand" "r") (match_operand:QI 1 "immediate_operand" "i"))) (match_operand:QI 2 "register_operand" "r")) (set (match_operand:QI 3 "register_operand" "=r") (mem:QI (plus:QI (match_dup 0) (match_dup 1)))) ] "REGNO(operands[2]) == REGNO(operands[3])" "st r%2,%1,r%0 ; eliminated previous redundant load") ;;;End.