|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T U
Length: 802706 (0xc3f92) Types: TextFile Notes: Uncompressed file
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦f718c2795⟧ »./gcc.diff-1.32-1.33.Z« └─⟦this⟧
Changes for GNU CC version 1.33, from 1.32. Changes in files that can be rebuilt with etags, tex, bison or M-x texinfo-format-buffer have been omitted. diff -rc2N gcc-1.32/ChangeLog gcc-1.33/ChangeLog *** gcc-1.32/ChangeLog Thu Dec 22 01:09:45 1988 --- gcc-1.33/ChangeLog Wed Feb 1 20:20:01 1989 *************** *** 1,2 **** --- 1,763 ---- + Wed Feb 1 20:01:54 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Version 1.33 released. + + * reload1.c (reload_as_needed): On entering new basic block, + if it didn't need reload regs, forget all inherited contents of those. + + * tm-alliant.h (NOTICE_UPDATE_CC): Floating moves don't set the cc's. + Also delete the clauses and tests for FPA regs. + + Tue Jan 31 21:51:05 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * config.gcc: Handle convex-c1, convex-c2. + * tm-convex1.h, tm-convex2.h: New files that include tm-convex.h. + * tm-convex.h: Define switches -mnoc1, -mnoc2. + + * config.gcc: rename `nofp' to `nfp', to match the file names. + + Mon Jan 30 22:12:15 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * output-sparc.c (output_delay_insn): Extract the operands, + call alter_subreg, constrain_operands and NOTICE_UPDATE_CC. + So callers other than output_eager_then_insn don't lose. + (output_eager_then_insn): No need to do that stuff. + + * symout.c (symout_block_symbols): Handle (MEM (REG)) for + variable-sized arrays. + + * tm-encore.h (ASM_SPEC): Always pass -j; avoid jump-range lossage. + + Sun Jan 29 17:06:26 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * alliant.md: Fix refs to CONST_DOUBLEs to use CONST_DOUBLE_{HIGH,LOW}. + + * combine.c (subst): (minus (zero_extend ...) (const_int ...)) opt. + now limited to within the context of (set (cc0) ...). + + Sat Jan 28 14:26:08 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * cse.c (fold_cc0): Missing `&' extracting CONST_DOUBLEs. + (fold_rtx): Don't put CONST_DOUBLEs together into a (CONST (PLUS...)). + + * output-convex.c (gen_cmp): Recognize CONST_DOUBLE as a constant. + + * tree.c (build_real_from_int_cst): Typo in REAL_ARITHMETIC case. + + * Makefile (bootstrap2): Don't use bootstrap3 as subroutine. + + * varasm.c (force_const_mem): Put the CONST_DOUBLE on the chain + if its MEM is stored in it; so it can be cleared at end of function. + + * stmt.c (emit_case_nodes): Put a compare before each cond-jump. + Two cond-jumps after one cond is invalid and makes cse produce garbage. + + Fri Jan 27 01:05:01 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * tm-sun2.h (CPP_SPEC): Define __HAVE_68881__ only if -m68881. + + * c-decl.c (start_decl): Don't expand_decl if DECL already has rtl. + (grokparms): If just declaring fcn, incomplete parm type is just + a warning, and don't discard the specified type. + + * expmed.c (expand_divmod): Be smarter about not clobbering args + with intermediate results; one mem can clobber another, and a reg + can clobber a mem. + + * tm-i386.h (FUNCTION_PROFILER): Use LPREFIX. May actually work now. + * tm-i386gas.h: Include tm-bsd386.h, not tm-att386.h. + This means changing asm syntax. + #undef DBX_NO_XREFS and DBX_CONTIN_LENGTH. + + * sparc.md (eager branch peepholes): Don't forget 2nd arg to + safe_insn_src_p. + Don't print warnings. + * output-sparc.c: (strict_single_insn_op_p): Return 0 for floating + REG or MEM, since copying that may take 2 insns. + (operands_satisfy_eager_branch_peephole): require delay insn to + be strict_single_insn_op_p as well as safe_insn_src_p. + (operand_clobbered_before_used_after): Don't print warnings. + + * varasm.c (decode_rtx_const): Clear entire structure incl. gaps. + Avoids spurious hash mismatches. + (force_const_mem): If CONST_DOUBLE, store its CONST_DOUBLE_MEM field. + Also look in that field rather than hashing, to save time. + + * c-typeck.c (build_c_cast): If value is literal, mark NOP_EXPR as so. + (store_init_value): Change error msg. + + * c-decl.c (duplicate_decls): Classify prototype vs nonprototype + mismatches better. + + * tm-3b1.h: Fix comment. + + Wed Jan 25 12:46:50 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Makefile (cleanlinks): Use -f. + + Tue Jan 24 17:54:16 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * cse.c (canon_hash): Fix paren error in last change. + + * varasm.c (immed_real_const_1): Missing arg to bcmp. + + Mon Jan 23 02:43:45 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * stor-layout.c (layout_type): BLKmode elts force array to be BLKmode. + + * genpeep.c, genoutput.c, genemit.c: Put `#include "real.h"' in output. + + * stmt.c (expand_expr_stmt): No "no effect" warning for error-mark. + + * varargs.h: Rename implicit arg name to __builtin_va_alist + which triggers code in assign_parms. Does this really matter? + + * sparc.md (sne): New define_expand. + (seq recognizers): Handle sne as well. + * output-sparc.c ({strict_,}single_insn_src_p): + Some NEG and MINUS insns are actually 2 asm insns. + (safe_insn_src_p): No floating arith is safe; they can trap. + (eq_or_neq): New fn, for seq/sne recognizers. + + * c-decl.c (grokdeclarator, size of array type): + Strip from SIZE any NOP_EXPRs that don't change anything. + + * reload.c, recog.c: Include real.h so constraint macros can examine + CONST_DOUBLEs. + + Sun Jan 22 04:12:54 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * c-decl.c (init_decl_processing): Define __builtin_saveregs. + * tree.h: likewise. + * expr.c (expand_builtin): Handle it. + + * tm-sparc.h: Define TARGET_EAGER and -meager. + * sparc.md (eager branch peepholes): Reenable, but test TARGET_EAGER. + Change fb insns to use %F. Delete `,a' from some of them. + * jump.c (jump_optimize): Don't delete USE and CLOBBER insns. + + * xm-vms.h (const): Define it as empty. + + * make-cccp.com: Move the rename of cexp_tab.c. + Compile cccp.c with no macro definitions. + + * cccp.c (main): VMS conditional for setting max_include_len. + + Sat Jan 21 12:53:00 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * varargs.h (va_start): On sparc, call __builtin_saveregs. + Delete the old conditional that used va-sparc.h. + Rename macros and locals to start with two underscores. + * va-sparc.h: File deleted. + + * c-decl.c (store_parm_decls): Initialize OTHERS. + + * stmt.c (assign_parms): Obey layout_decl. + + Fri Jan 20 02:19:32 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * cse.c (fold_rtx): For SYMBOL_REF and LABEL_REF, mask address + to 16 bits. + + * tree.h (NUM_TREE_CODES): NUM_TREE_CODE renamed. + + Thu Jan 19 13:53:24 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * c-typeck.c (mark_addressable): For global reg var, report error. + Now returns an int; value of 0 means caller should fail. + All calls (in this file) changed. + + * stor-layout.c (layout_decl): Don't let an more than 1 word + of any aggregate go in any 1 register. (Needed for machines whose + integer regs are 64 bits). + + * tm-convex.h, xm-convex.h, convex.md, output-convex.c: new files. + + * expr.c (convert_move): Use extendqidi2, etc. for converting + small ints to double ints. Use zero_extendsidi2 rather than + clearing the high half. + + Wed Jan 18 01:20:52 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * varasm.c (make_decl_rtl): If global `register' decl is invalid, + make ordinary non-register rtl. + + * output-sparc.c (operand_clobbered_before_used_after): new fn. + (reg_clobbered_p, safe_insn_src_p): New fns. + (single_insn_src_p): Treat constants all as ok, even though not + always literally so. Also accept some SIGN_EXTENDs and ZERO_EXTENDs. + (strict_single_insn_src_p): New fn, like above but is strict + about constants and constant memory addresses. + (relop): New fn. + (output_move_double): Don't make a MEM, and don't use %m. + (output_delayed_branch): New name for output_delay_insn. + Now handle non-small constant operands. + Avoid duplicate loads of g1 for constant addresses. + Use recog_operand directly for output of the delay insn. + (output_delay_insn): Now a completely new fn. + (output_eager_then_insn, next_real_insn_no_labels): New fns. + (operands_satisfy_eager_branch_peephole): New fn. + + * sparc.md: New peepholes for testing a recently used operand. + New peepholes for delayed branches, incl. conditional ones. + ** Some of them commented out because they seem not to work. + (andcc recognizer): Fix typo, missing %. + (bgt): Change bgt to bg in output. + (reversed jumps): Replace with one pattern using match_operand. + It uses %F to output the condition. + (movsi): For round-valued immed const, use just a sethi. + For other immed, use explicit sethi and or. + (movhi, movqi): use `move' for reg source or small int source. + For other immed, use explicit sethi and or. + (movsi, etc.): Handle all constant addresses like SYMBOL_REFs. + (movsf): Delete never-used duplicate code for constant addresses. + (addsi3, subsi3, cse'd multiply): Use sethi and or, rather than set. + (andsi3, iorsi3, xorsi3): Likewise. + (jump): Make an annulled branch. + + * tm-sparc.h (PROMOTE_PROTOTYPES): Define this. + (GO_IF_LEGITIMATE_ADDRESS): Now accept all constant addresses; + also cleaned up. + (NOTICE_UPDATE_CC): Don't change the G1 status when storing in memory. + Assume all PARALLEL insns are peepholes. + (PRINT_OPERAND): New codes C and N for outputting conditions, + either forward or reversed. Also F for reversed floating. + + * jump.c (delete_for_peephole): New function to delete range of insns. + * genpeep.c (gen_peephole): Output code to use this. + + * Makefile (install): Fix typo, had $${name} for $${file}. + + Tue Jan 17 00:00:12 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * i386.md (ashlsi3): Use addl or leal for special cases. + + * c-decl.c (grokdeclarator): Make a non-global VAR_DECL public + if it is external. + + * masm386.c: Clean up formatting. + + * cse.c (fold_rtx): Typo simplifying x|0 or x^0 + when the 0 comes second. + + * expmed.c (store_fixed_bit_field): For halfwords, verify that + the field fits in an *aligned* halfword. + (extract_fixed_bit_field): likewise. + + * expmed.c (store_split_bit_field): New arg align, passed in from + store_fixed_bit_field and passed back to it. + (extract_split_bit_field): likewise. + + * expr.c: Reinsert changes from Jan 2, mysteriously deleted Jan 3. + Also changes from Dec 23, Dec 28 and Dec 29. + + * tm-i386.h: Likewise for changes from Dec 30. + + * c-typeck.c (build_component_ref): If field's type is error-mark, + return an error-mark. + + Mon Jan 16 14:16:54 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * genpeep.c (main): Output code to exit early if insn is followed + by a barrier. + (gen_peephole): Reject barriers just like labels. + + * stmt.c (do_jump_if_equal): New arg UNSIGNEDP, for emit_cmp_insn. + Caller changed. Now static. + + * final.c (final): Set INSN_DELETED_P in insns when output. + + * final.c (final): Re-set BODY if peephole does anything. + + * c-decl.c (grokparms): Ignore anything but PARM_DECLs in the list. + (store_parm_decls): If we had a prototype, separate out anything other + than a PARM_DECL declared in it, and pushdecl those at the end, + after DECL_ARGUMENTS is set. + + * stmt.c (expand_end_case): Do stack adjusts after computing index. + + * expr.c (store_one_arg): Handle padding for case of BLKmode + for which space was preallocated. + + * integrate.c (copy_rtx_and_substitute): When copying asm insn, + preserve sharing of the input-operand vectors. + (expand_inline_function): Clear {orig,copy}_asm_operands_vector + to make that mechanism work. + (save_for_inline, copy_for_inline): Likewise. + + * stmt.c (expand_asm_operands): Reject `+' in constraints. + Every output constraint requires `='; inputs reject it. + + * stmt.c (expand_function_end): Arg to fixup_gotos was missing. + + Sun Jan 15 00:28:23 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * cccp.c, gcc.c (main): Handle SIGPIPE. + (pipe_closed): New fn; report suitable fatal error. + + * loop.c (loop_optimize): Initialize moved_once. + + * gcc.c (do_spec): Don't call `execute' if value != 0. + Delete redundant second call to do_spec_1. + + * toplev.c (compile_file): Make declared-but-not-defined warnings + only if -Wunused. + + * stmt.c (emit_case_nodes): Fix typo setting gen_ble_pat. + + * tm-sparc.h ({U,}MODSI3_LIBCALL): Name was wrong. + + * gcc.c (env_exec_prefix refs): Don't try to open via it if it's null. + + * output-sparc.c (output_store, output_load_{fixed,floating}): + Fixed confusions between the mem ref and its address. + + * cse.c (canon_hash): global_regs has entries only for hard regs. + * flow.c (insn_dead_p, mark_set_p, mark_used_regs): Likewise. + + * cse.c (fold_rtx): More simplifications for MULT, IOR, AND, XOR + DIV and shifts with one arg 0 or 1. + + Sat Jan 14 11:41:11 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * c-typeck.c (build_array_ref): If pedantic, check for regdecl arrays. + + * fixincludes: Make all subdirs in advance, so no need for `dirname'. + + * genpeep.c (gen_peephole): Delete code to increment LABEL_NUSES; + instead, clear JUMP_LABEL for any jumps being deleted. + No need to test INSN1 for being a label, since not called then. + [If any of the matched insns is a JUMP_INSN, set want_jump, + and in that case make the matched peephole a JUMP_INSN itself.] + That's in an #if 0 now; it's good in jump, but not in final. + + * jump.c (jump_optimize): Don't do peepholes here. + * final.c (final): Do them here. + + * jump.c (jump_optimize): In optimizing `if (foo) bar; else break;', + don't try to invert anything but a standard-looking conditional jump. + + * jump.c (jump_optimize): Do peepholes on ALL BUT the first pass. + + * gcc.c (env_exec_prefix): New var used like user_exec_prefix + but set from envvar GCC_EXEC_PREFIX. + + Fri Jan 13 13:21:59 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * genpeep.c (gen_peephole): Test INSN1 for a label at the very start, + then test following insns at the end of the loop. + + * sparc.md (call recognizers): do CC_STATUS_INIT, for %g1. + + Thu Jan 12 02:13:49 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * varasm.c (make_decl_rtl): Recognize more error cases for reg vars: + BLKmode, or initializer given. + Distinguisn missing asm from invalid name. + + * expr.c (expand_call): Never return 0; return const0_rtx instead. + This makes expand_expr more uniform. + + * c-decl.c (grokparms): For ptr to incomplete type, just warn; + don't change the parm's type. + + * stmt.c (expand_return): Set RETVAL_RHS so as to recognize + tail-recursive fcn returning void. + Unconditionally test value of expand_expr for being a REG. + + * reload.c (find_reloads): Don't process insns that have + no constraint alternatives. No more need for have_constraints. + + * recog.c (constrain_operands): New local var nalternatives. + Don't bother checking the insn if nalternatives is 0. + + Wed Jan 11 01:27:48 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Implement global register decls. + + * varasm.c (make_decl_rtl): Handle global register vars. + (make_function_rtl): Set function_defined: after 1st function dfn. + (assemble_variable): Ignore global register vars. + + * c-decl.c (grokdeclarator): Don't reject global register decls. + (builtin_function): Use make_decl_rtl, not make_function_rtl, + to avoid setting function_defined. + + * regclass.c (init_reg_class{,_1}): Init and process global_regs. + They are fixed, and call-clobbered. + + * flow.c (insn_dead_p): Storing one of global_regs is never dead. + (mark_used_regs, mark_set_1): A global reg is never dead. + + * cse.c (canon_hash): Consider global regs volatile. + + + * expr.c (do_jump): Know how to invert jumps which are sequences. + + * dbxout.c, symout.c, final.c: On USG, use our own stab.h. + + * tm-i386gas.h: New file for GAS on sysV (with DBX debugging info). + + * m68k.md (bfchg and bfins patterns): Make # alternatives uniform. + * alliant.md: Likewise; also in movdf patterns. + + * genoutput.c (output_epilogue): Spurious `break' disabled + error check for mismatched # of alternatives. + (output_epilogue, scan_operands): Errors in input are not fatal. + + * flow.c (regno_uninitialized): Avoid crash if no basic blocks. + + * sparc.md (move insns): Delete special patterns that handled + symbolic constant addresses. The main move patterns now do this. + * output-sparc.c (output_store, output_load_{fixed,floating}): + Subroutines to do the work for this; has the code from those + special patterns. Also fixed bugs in testing against cc_status.mdep. + + * output-sparc.c (output_delay_insn): Clear the CC status. + This is necessary for %g1 in the case of a call insn. + + * tm-i386.h (REG_CLASS_CONTENTS): INDEX_REGS is now all but ESP. + (REGNO_REG_CLASS): Corresponding change. + (REG_CLASS_FROM_LETTER): Eliminate `x' letter since not used. + + * optabs.c (emit_cmp_insn): New arg ALIGN, used for BLKmode. + All callers changed. + Pass alignment (as rtx) as 4th arg to cmpstr gen functions. + Use cmpstrhi if available. + * expr.c (compare): Only this call passes a nonzero ALIGN. + + * expr.c (emit_push_insn, emit_block_move): Pass alignment (as rtx) + as 4th arg to movstr gen functions. + + Tue Jan 10 23:43:05 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * stor-layout.c (layout_type): Use BLKmode, if a struct isn't + aligned well enough for a scalar mode. + + * expr.c (expand_expr): For static CONSTRUCTOR, ensure memory + address is made valid. + + * genpeep.c (match_rtx): For MATCH_OPERATOR, set max_opno, n_operands. + + Mon Jan 9 17:07:56 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * varasm.c (output_constant): Split strings every 2000 chars. + + * stmt.c (expand_end_case): Test bkwds, handling constant switch arg. + + Fri Jan 6 09:11:20 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * output-sparc.c (output_delay_insn): Add parens to first if test. + (output_move_double): Turn addr for `sethi' into MEM for %m. + + * c-typeck.c (convert_for_assignment): move test for ERROR_MARK. + + * c-parse.y (unary_expr): Allow cast_expr as arg of unary op. + + * stmt.c (expand_decl): Don't abort if FUNCTION_DECL lacks rtl; + assemble_variable is called after this. + + * c-parse.y (primary -> identifier): Separate case for undeclared + identifier outside of functions; avoids confusing error msgs. + + Thu Jan 5 01:24:47 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Makefile (install): Ignore errors in all `if' commands. + Create $(libdir) if nec. + + * Makefile (insn-*.[ch]): Put in empty commands. May help Ultrix Make. + + * stmt.c (emit_case_nodes): New arg UNSIGNEDP says do unsigned jumps. + Arg INDEX is an rtx, not a tree. + (expand_end_case): Pass that arg. + (node_has_{low,high}_bound): check for overflow, avoid confusion. + + Wed Jan 4 02:24:21 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * sparc.md (movdi, movdf): Use `&' constraint when loading reg from; + otherwise can lose on (set (reg X) (mem (plus (reg X) (reg X+1)))). + + * expr.c (emit_push_insn): For memory scalar partially going in regs, + copy each word to reg before pushing. Avoids memory-to-memory move. + Make the displaced address valid. + Also delete unfinished STACK_OFFSET variable. + + * c-parse.y (check_newline): Read just one #-directive and return. + This prevents lossage when toplev.c calls it to get the main input file + name, and it gets a following #ident as well. + + * c-decl.c (lang_decode_option): Set warn_cast_qual for -Wcast-qual. + * c-typeck.c (build_c_cast): Issue some warnings if set. + + * tm-3b1.h (ASM_OUTPUT_CASE_LABEL): Missing `;'. + + Tue Jan 3 18:07:31 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * expr.c (emit_library_call): Do force_operand on each operand + if it isn't a REG, MEM or constant. + Do this, or mode conversions, earlier, before loading any hard regs. + + * m68k.md (addsi3) [SGS]: Put a zero displacement in the `lea'. + + * c-typeck.c (default_conversion): Don't lose `const' or `volatile' + when converting array type to pointer. + + Mon Jan 2 01:18:01 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * expmed.c (store_bit_field, store_fixed_bit_field): New arg, + alignment in bytes the structure is known to have. + (store_fixed_bit_field): Handle working in halfwords, + in case the pointer isn't known to have fullword alignment. + * expmed.c (extract_bit_field, extract_fixed_bit_field): likewise. + (extract_bit_field): fix unsignedp arg to extract_fixed_bit_field. + * expr.c (store_field): New arg, passed to {store,extract}_bit_field + (expand_assignment, store_constructor): Pass that arg. + (expand_expr): Pass new arg to extract_bit_field. + + * m68k.md (casesi_2 recognizer): Offset always 6 for 3b1. + + * c-typeck.c (convert_for_assignment): Strip from rhs no-op NOP_EXPRs + put on by build_c_cast (to make the result not an lvalue). + (build_modify_expr, build_compound_expr): likewise. + (build_conditional_expr): likewise. + (actualparameterlist, build_function_call): likewise. + (default_conversion, truthvalue_conversion): likewise. + + * loop.c (move_movables): If reg has moved out of one loop, + divide `savings' by 2. + + Sun Jan 1 03:00:07 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * c-typeck.c (truthvalue_conversion): Distribute the conversion + into the arms of a COND_EXPR. + + * cse.c (fold_rtx): Don't fold a MINUS with VOIDmode + into a symbolic constant--it's incorrect. + + * cse.c (cse_insn): If SRC is a subreg with known value, simplify it. + + * integrate.c (copy_rtx_and_substitute): Allow a ref to a part of + MEM parm whose actual parm is a reg, provided it refs + the low part of the MEM. + (function_cannot_inline_p): Don't inline functions which have + aggregate parameters and take their addresses. This could produce + refs to non-low-parts, which copy_rtx_and_substitute can't handle. + + * c-typeck.c (build_modify_expr): If lhs is COND_EXPR, + make a COMPOUND_EXPR to ensure the rhs is computed before the branch. + + * Implement -pipe. + * gcc.c (do_spec_1): `|' is now a special delimiter + which goes in the argbuf. + When a newline is preceded by a `|', delete it if no -pipe. + Otherwise, don't execute yet, and keep scanning. + (do_spec): At end, if we have stuff with no newline, execute it. + (handle_braces): Implement %{|foo:...}. + (execute): If argbuf contains some `|'s, run several processes + and pipe them together. + (pexecute): new subroutine to make one of the processes. + (find_exec_file): new fn to search for program to execute. + (record_temp_file): new arg FAIL_ONLY. + (store_arg): 2nd arg == 3 means delete file on failure. + This is used for output files. + (delete_temp_files): delete certain files only if fail. + + * cccp.c (include_defaults): /usr/include before /usr/local/include. + + * recog.c (asm_noperands): 1-off in loop checking CLOBBERS + when no output operands and PARALLEL. + + * expmed.c (negate_rtx): Sign-extend the high bits rather than clear. + + * cse.c (fold_rtx): fold negation of real values. + (fold_cc0): fold comparisons on real values. + + * Makefile (install): Use $(INSTALL) for gcc.1 and files in USER_H. + + * Handle floating-point problems for cross-compilation. + + * real.h (CONST_DOUBLE_LOW, etc.): new macros to access CONST_DOUBLE. + * varasm.c (immed_double_const, decode_rtx_const): Use these. + ({force,clear}_const_double_mem): Likewise. + * output-*.c (output_move_double): Use these. + * output-m68k.c (standard_{68881,sun_fpa}_constant_p): Likewise. + * tm-*.h (PRINT_OPERAND): Use these. + * output-i386.c (print_operand): Use these. + * final.c (output_addr_const): Likewise. + * emit-rtl.c (gen_rtx): Delete special code for CONST_DOUBLE. + + * real.h (union real_extract): Portable type for storing real as ints. + * varasm.c (immed_double_const, decode_rtx_const): Use these. + + * varasm.c (immed_real_const_1, decode_rtx_const): + Don't assume REAL_VALUE_TYPE is 2 ints long. + * emit-rtl.c (init_emit_once): Likewise. + + * real.h (REAL_VALUE_TYPE): Define as `double' if not defined. + (REAL_IS_NOT_DOUBLE): Define this if default REAL_VALUE_TYPE not used. + (REAL_VALUES_EQUAL, REAL_VALUES_LESS): Define, if not already defined. + (REAL_VALUE_LDEXP, REAL_VALUE_ATOF): Likewise. + * tree.h (struct tree_real_cst): Use REAL_VALUE_TYPE for the value. + + * rtl.c (init_rtl): Increase length of CONST_DOUBLE if REAL_VALUE_TYPE + needs more space. Change the rtx_format element to match. + * varasm.c (immed_real_const_1): 1st arg now has REAL_VALUE_TYPE. + (force_const_mem): Assume a CONST_DOUBLE contains REAL_VALUE_TYPE. + * emit-rtl.c (init_emit_once): Likewise. + And use REAL_VALUE_ATOF to get a floating zero. + * optabs.c (expand_float): Use REAL_VALUE_TYPE, REAL_VALUE_LDEXP. + * c-parse.y (yylex): Likewise, and use REAL_VALUE_ATOF. + * fold-const.c (split_tree): Don't accept REAL_CSTs. + (combine, fold_convert, fold): Use REAL_ARITHMETIC if defined; + else don't fold reals if they are not doubles. + * tree.c (build_real_from_int_cst): Likewise. + * print-tree.c (dump) [REAL_IS_NOT_DOUBLE]: output float value + in hex, since we don't know how to do it right. + + Sat Dec 31 14:15:13 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * optabs.c (init_optabs): Handle new macros {U,}MULSI3_LIBCALL, + DIVSI3_LIBCALL, MODSI3_LIBCALL. + * tm-sparc.h: Define {,U}{MUL,DIV,MOD}SI3 to call Sun's library direct. + + * tm-sun3-nfp.h, tm-sun3-fpa.h: New files. + + Fri Dec 30 00:14:36 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * cccp.c (main): Certain envvars specify a file to write deps info to. + + * toplev.c (compile_file): Warn about undefined fns declared static. + + * m68k.md (casesi_2 recognizer) [SGS] RTX_INTEGRATED_P test backwards. + * tm-3b1.h (ASM_OUTPUT_CASE_LABEL): Likewise. Also missing `\'. + + * reload1.c (count_occurrences): New function. + (choose_reload_targets): Don't delete a reload if the same reg + is used elsewhere in the current insn. + (delete_output_reload): code split out from choose_reload_targets. + + * c-typeck.c (build_c_cast): Always put on some operator, + so the cast is never an lvalue for strict ANSI. + + * c-typeck.c (initializer_constant_valid_p): Don't depend on + distinction between NOP_EXPR and CONVERT_EXPR. + + * c-convert.c: Fns reordered; new comments. + + * fold-const.c (fold): If simplifying a NOP_EXPR within a BIT_AND_EXPR, + return a NOP_EXPR. + New var TYPE holds type of expr. + + * c-parse.y (expr_no_commas): Split off cast_expr and unary_expr, + to reject `sizeof (int) foo'. + + * toplev.c (main): Treat plain `-' as input filename. + + * final.c (final): If an insn's output routine returns 0, + it means to output the deleted compare insn immediately preceding. + + * m68k.md (branch insns): Use 0 as 3rd arg for OUTPUT_JUMP + rather than explicitly clearing the overflow flag. + + * tm-i386.h (OUTPUT_JUMP): Really use NO_OV; don't abort. + * i386.md (branch insns): Put real data (sometimes 0) in 3rd arg + of OUTPUT_JUMP. 0 means preceding test may not be deleted. + (lea pattern): Clear the cc's. + * output-i386.c (notice_update_cc): various arith insns set the cc's. + + Thu Dec 29 13:22:01 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * stmt.c (expand_decl_init): Do nothing for static decls. + + * reload.c (find_reloads_address{,_1}): Return 1 iff entire arg + was reloaded as a whole, else 0. + (find_reload): If find_reloads_address returns 1, don't let that MEM + satisfy a `>' or `<' constraint. + + * m68k.md (cmpmb): Delete special pattern, make cmpqi handle it. + The special pattern couldn't handle reloading the incremented register. + + * integrate.c (copy_rtx_and_substitute): Test BYTES_BIG_ENDIAN, + not BITS... + + * combine.c (subst): Consider big-endian correction + when simplifying (subreg (mem ...) ...). + + * reload.c (find_reloads): Don't crash if matching operands in `asm' + are both read or both write. + + * expr.c (emit_push_insn): Address for movstr must be XINNER, not X. + + * toplev.c (main): Typo parsing `-fno...'. + + Wed Dec 28 13:07:21 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * toplev.c (rest_of_compilation): `volatile' fns need jump_optimize + for warnings, as if -Wreturn-type. + * c-typeck.c (c_expand_return): Warn about `return' in a `volatile' fn. + * c-decl.c (finish_function): Warn if `volatile' fn can drop thru end. + + * cse.c (canon_reg): Handle nulls as subexpressions. + (fold_rtx, canon_hash, mention_regs, exp_equiv_p): Likewise. + * loop.c (invariant_p, replace_regs, replace_call_address, may_trap_p, + {basic,general}_induction_var): Likewise. + + * expr.c (expand_call): Handle `const' functions: + Local IS_CONST is 1 if function is const. + Attach REG_RETVAL and REG_LIBCALL notes around the call. + Copy fn address to register outside of those notes. + Likewise precompute all parms outside them. + + * expr.c (expand_call): If fn is volatile, emit barrier after the call. + + * c-decl.c (grokdeclarator): Allow function declared const or volatile. + + Sat Dec 24 18:40:12 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * integrate.c (function_cannot_inline_p): If STRUCT_VALUE_INCOMING + or STRUCT_VALUE is defined, can't inline functions returning BLKmode. + + Fri Dec 23 13:26:26 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * expr.c (store_constructor): Compute array's size + with int_size_in_bytes. + + * varasm.c (assemble_variable): If shared data, go to data section + before outputting an uninitialized symbol. + + * tm-sequent.h (ASM_OUTPUT_ALIGN_CODE): Missing backslash. + (SHARED_SECTION_ASM_OP): Macro defined. + * tm-seq386.h (SHARED_SECTION_ASM_OP): Macro defined. + + * c-typeck.c (c_expand_asm_operands): Warn if output op is `const'. + + * Fix problem where a stmt expr in an initialization + refers to the variable it is initializing. + * stmt.c (expand_decl_init): New fn split out from `expand_decl'. + * c-decl.c (finish_decl): Call that. + Don't call expand_decl if already done. + (start_decl): Call expand_decl if type is complete already. + + * Makefile (install): Typo in ranlib command. + + Thu Dec 22 15:57:12 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * tree.h (tree_identifier): New field. + (IDENTIFIER_ERROR_LOCUS): Accessor for it. + * c-parse.y (primary => IDENTIFIER): + Undeclared variable gets one err msg per function it appears in. + + * ns32k.md (andsi3): Delete extra brace. + + * alliant.md, xm-alliant.h, tm-alliant.h, output-alliant.c: New files. + + * combine.c (SUBST, SUBST_INT): Store new field `is_int'. + (copy_substitutions): Don't copy an int as an rtx. + + * Makefile (INSTALL): Install gcc.1 properly. + + * tm-ns32k.h (FUNCTION_PROLOGUE, ASM_OUTPUT_ALIGN_CODE): + Add missing backslashes. + Wed Dec 21 02:46:34 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) *************** *** 607,611 **** now needed in expr.c. ! * output-sparc.md (reg_or_0_operand): new function, returns nonzero if operand is const0_rtx or a register of specified mode. (hardreg): deleted. --- 1368,1372 ---- now needed in expr.c. ! * output-sparc.c (reg_or_0_operand): new function, returns nonzero if operand is const0_rtx or a register of specified mode. (hardreg): deleted. *************** *** 1117,1121 **** SImode SUBREGs are possible and ok in extzv, extv. ! * tm-ns32k.md (REGISTER_NAMES): Had two excess elements; deleted. Mon Oct 3 01:15:51 1988 Richard Stallman (rms at corn-chex.ai.mit.edu) --- 1878,1882 ---- SImode SUBREGs are possible and ok in extzv, extv. ! * tm-ns32k.h (REGISTER_NAMES): Had two excess elements; deleted. Mon Oct 3 01:15:51 1988 Richard Stallman (rms at corn-chex.ai.mit.edu) *************** *** 1818,1822 **** * Version 1.27 released. ! * tm-i386.md (PREFERRED_RELOAD_REG): When reloading a QImode, make sure the class doesn't include %esi or %edi. * i386.md (movqi): Eliminate only use of the class `x', --- 2579,2583 ---- * Version 1.27 released. ! * tm-i386.h (PREFERRED_RELOAD_REG): When reloading a QImode, make sure the class doesn't include %esi or %edi. * i386.md (movqi): Eliminate only use of the class `x', *************** *** 1824,1828 **** (In next version, get rid of INDEX_CLASS). Also use `*' to cause preferencing of Q_REGS. ! * tm-m68k.md (PREFERRED_RELOAD_REG): When reloading a QImode, use DATA_REGS. --- 2585,2589 ---- (In next version, get rid of INDEX_CLASS). Also use `*' to cause preferencing of Q_REGS. ! * tm-m68k.h (PREFERRED_RELOAD_REG): When reloading a QImode, use DATA_REGS. diff -rc2N gcc-1.32/INSTALL gcc-1.33/INSTALL *** gcc-1.32/INSTALL Wed Dec 21 23:32:37 1988 --- gcc-1.33/INSTALL Wed Feb 1 01:06:07 1989 *************** *** 7,12 **** TeX source gcc.texinfo - File: gcc.info, Node: Installation, Next: Trouble, Prev: Options, Up: Top - Installing GNU CC ***************** --- 7,10 ---- *************** *** 42,45 **** --- 40,47 ---- Intel 386 PCs running system V. + `i386-sysv-gas' + Intel 386 PCs running system V, using the GNU assembler and + GNU linker. + `sequent-386' Sequent with Intel 386 processors. *************** *** 49,53 **** `sun3' ! Sun 3 running system version 2 or 3. `sun4' --- 51,61 ---- `sun3' ! Sun 3 running system version 2 or 3, with 68881. ! ! `sun3-nfp' ! Sun 3 running system version 2 or 3, without 68881. ! ! `sun3-fpa' ! Sun 3 running system version 2 or 3, with 68881 and fpa. `sun4' *************** *** 58,63 **** `sun3-os4' ! Sun 3 running system version 4. `sun4-os4' Sun 4 running system version 4. --- 66,77 ---- `sun3-os4' ! Sun 3 running system version 4, with 68881. + `sun3-nfp-os4' + Sun 3 running system version 4, without 68881. + + `sun3-fpa-os4' + Sun 3 running system version 4, with 68881 and fpa. + `sun4-os4' Sun 4 running system version 4. *************** *** 66,69 **** --- 80,95 ---- Sun 386 (``roadrunner''). + `alliant' + Alliant FX/8 computer. Currently, there are bugs in the + support for floating point. Also note that Alliant's + version of dbx does not manage to work with the output from + GNU CC. + + `convex-c1' + Convex C1 computer. + + `convex-c2' + Convex C2 computer. + `hp9k320' HP 9000 series 300 using HPUX assembler. *************** *** 72,76 **** HP 9000 series 300 using GNU assembler, linker and debugger. This requires the HP-adapt package which is or will soon be ! available in the same places as GNU CC. `isi68' --- 98,102 ---- HP 9000 series 300 using GNU assembler, linker and debugger. This requires the HP-adapt package which is or will soon be ! available along with the linker. `isi68' *************** *** 141,145 **** `tm-sun3.h' ! for Sun 3 machines. `tm-sun2.h' --- 167,177 ---- `tm-sun3.h' ! for Sun 3 machines with 68881. ! ! `tm-sun3-fpa.h' ! for Sun 3 machines with floating point accelerator. ! ! `tm-sun3-nfp.h' ! for Sun 3 machines with no hardware floating point. `tm-sun2.h' *************** *** 177,182 **** For the 80386, don't use `tm-i386.h' directly. Use `tm-i386v.h' if the target machine is running system V, ! `tm-seq386.h' for a Sequent 386 system, or `tm-compaq.h' ! for a Compaq, or `tm-sun386i.h' for a Sun 386 system. For the 32000, use `tm-sequent.h' if you are using a --- 209,216 ---- For the 80386, don't use `tm-i386.h' directly. Use `tm-i386v.h' if the target machine is running system V, ! `tm-i386gas.h' if it is running system V but you are using ! the GNU assembler and linker, `tm-seq386.h' for a Sequent ! 386 system, or `tm-compaq.h' for a Compaq, or ! `tm-sun386i.h' for a Sun 386 system. For the 32000, use `tm-sequent.h' if you are using a *************** *** 222,226 **** Bugs::.). ! 7. Move the first-stage object files and executables into a subdirectory with this command: --- 256,265 ---- Bugs::.). ! 7. If you are using COFF-encapsulation, you must convert `gnulib' ! to a GNU-format library at this point. See the file ! `README-ENCAP' in the directory containing the GNU binary file ! utilities, for directions. ! ! 8. Move the first-stage object files and executables into a subdirectory with this command: *************** *** 231,235 **** with `rm -r stage1'. ! 8. Recompile the compiler with itself, with this command: make CC=stage1/gcc CFLAGS="-g -O -Bstage1/" --- 270,274 ---- with `rm -r stage1'. ! 9. Recompile the compiler with itself, with this command: make CC=stage1/gcc CFLAGS="-g -O -Bstage1/" *************** *** 241,245 **** make CC=stage1/gcc CFLAGS="-g -O -Bstage1/ -msoft-float" ! 9. If you wish to test the compiler by compiling it with itself one more time, do this: --- 280,284 ---- make CC=stage1/gcc CFLAGS="-g -O -Bstage1/ -msoft-float" ! 10. If you wish to test the compiler by compiling it with itself one more time, do this: *************** *** 259,263 **** when you made stage 2. ! 10. Install the compiler driver, the compiler's passes and run-time support. You can use the following command: --- 298,302 ---- when you made stage 2. ! 11. Install the compiler driver, the compiler's passes and run-time support. You can use the following command: *************** *** 309,312 **** --- 348,352 ---- + ▶1f◀ File: gcc.info, Node: VMS Install, Prev: Installation, Up: Installation *************** *** 327,330 **** --- 367,377 ---- 2. Type `@make' to do recompile everything. + If you are compiling with a version of GCC older than 1.33, + specify `/DEFINE=("inline=")' as an option in all the + compilations. This requires editing all the `gcc' commands in + `make-cc1.com'. (The older versions had problems supporting + `inline'.) Once you have a working 1.33 or newer GCC, you can + change this file back. + To install the `GCC' command so you can use the compiler easily, in the same manner as you use the VMS C compiler, you must install the *************** *** 350,351 **** --- 397,402 ---- /verbose file.c', which is equivalent to the command `gcc -v -c file.c' in Unix. + + There is a known problem on VMS: `const' global variables don't work + compatibly with the VMS C compiler; we don't know a way to get them + to the linker properly. diff -rc2N gcc-1.32/Makefile gcc-1.33/Makefile *** gcc-1.32/Makefile Fri Dec 16 18:28:29 1988 --- gcc-1.33/Makefile Sat Jan 28 19:28:26 1989 *************** *** 37,43 **** --- 37,47 ---- # Directory in which to put man pages. mandir = $(prefix)/usr/local/man/man1 + # Number to put in man-page filename. + manext = 1 # These are what you would need on HPUX: # CFLAGS = -Wc,-Ns2000 -Wc,-Ne700 -Wc,-Np300 + # If you are using the GNU assembler and linker on HPUX, + # add -I../hp-include to CFLAGS. # -g is desirable in CFLAGS, but a compiler bug in HPUX version 5 # bites whenever tree.def, rtl.def or machmode.def is included *************** *** 47,54 **** # forces only 68000 instructions to be used. - # If you are using gas on hp-ux you need the following to fake up some - # system file definitions: - # CFLAGS = -g -I../hp-include - # If you are making gcc for the first time, and if you are compiling it with # a non-gcc compiler, and if your system doesn't have a working alloca() in any --- 51,54 ---- *************** *** 122,126 **** CONFIG_H = RTL_H = rtl.h rtl.def machmode.def ! TREE_H = tree.h tree.def machmode.def CPLUS_TREE_H = $(TREE_H) cplus-tree.h c-tree.h --- 122,126 ---- CONFIG_H = RTL_H = rtl.h rtl.def machmode.def ! TREE_H = tree.h real.h tree.def machmode.def CPLUS_TREE_H = $(TREE_H) cplus-tree.h c-tree.h *************** *** 166,173 **** if [ -f /usr/bin/ranlib ] ; then ranlib gnulib ;fi # On HPUX, if you are working with the GNU assembler and linker, ! # the previous line must be replaced with # No change is needed here if you are using the HPUX assembler and linker. # mv gnulib gnulib-hp ! # hpxt gnulib-hp gnulib --- 166,173 ---- if [ -f /usr/bin/ranlib ] ; then ranlib gnulib ;fi # On HPUX, if you are working with the GNU assembler and linker, ! # the previous line must be replaced with the following two lines. # No change is needed here if you are using the HPUX assembler and linker. # mv gnulib gnulib-hp ! # ../hp-bin/hpxt gnulib-hp gnulib *************** *** 211,215 **** rtl.o : rtl.c $(CONFIG_H) $(RTL_H) ! varasm.o : varasm.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h expr.h insn-codes.h stmt.o : stmt.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \ insn-flags.h expr.h insn-config.h regs.h insn-codes.h --- 211,216 ---- rtl.o : rtl.c $(CONFIG_H) $(RTL_H) ! varasm.o : varasm.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h expr.h \ ! insn-codes.h hard-reg-set.h stmt.o : stmt.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \ insn-flags.h expr.h insn-config.h regs.h insn-codes.h *************** *** 225,229 **** sdbout.o : sdbout.c $(CONFIG_H) $(TREE_H) $(RTL_H) c-tree.h ! emit-rtl.o : emit-rtl.c $(CONFIG_H) $(RTL_H) regs.h insn-config.h integrate.o : integrate.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h expr.h \ --- 226,230 ---- sdbout.o : sdbout.c $(CONFIG_H) $(TREE_H) $(RTL_H) c-tree.h ! emit-rtl.o : emit-rtl.c $(CONFIG_H) $(RTL_H) regs.h insn-config.h real.h integrate.o : integrate.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h expr.h \ *************** *** 233,238 **** stupid.o : stupid.c $(CONFIG_H) $(RTL_H) regs.h hard-reg-set.h ! cse.o : cse.c $(CONFIG_H) $(RTL_H) regs.h hard-reg-set.h flags.h ! loop.o : loop.c $(CONFIG_H) $(RTL_H) insn-config.h regs.h recog.h flags.h expr.h flow.o : flow.c $(CONFIG_H) $(RTL_H) basic-block.h regs.h hard-reg-set.h combine.o : combine.c $(CONFIG_H) $(RTL_H) flags.h \ --- 234,240 ---- stupid.o : stupid.c $(CONFIG_H) $(RTL_H) regs.h hard-reg-set.h ! cse.o : cse.c $(CONFIG_H) $(RTL_H) regs.h hard-reg-set.h flags.h real.h ! loop.o : loop.c $(CONFIG_H) $(RTL_H) insn-config.h insn-codes.h \ ! regs.h recog.h flags.h expr.h flow.o : flow.c $(CONFIG_H) $(RTL_H) basic-block.h regs.h hard-reg-set.h combine.o : combine.c $(CONFIG_H) $(RTL_H) flags.h \ *************** *** 250,254 **** reload.h regs.h hard-reg-set.h insn-config.h basic-block.h final.o : final.c $(CONFIG_H) $(RTL_H) regs.h recog.h conditions.h gdbfiles.h \ ! insn-config.h recog.o : recog.c $(CONFIG_H) $(RTL_H) \ regs.h recog.h hard-reg-set.h insn-config.h --- 252,256 ---- reload.h regs.h hard-reg-set.h insn-config.h basic-block.h final.o : final.c $(CONFIG_H) $(RTL_H) regs.h recog.h conditions.h gdbfiles.h \ ! insn-config.h real.h recog.o : recog.c $(CONFIG_H) $(RTL_H) \ regs.h recog.h hard-reg-set.h insn-config.h *************** *** 273,277 **** # Each of the other insn-* files is handled by a similar pair of rules. ! insn-config.h: stamp-config.h stamp-config.h : md genconfig ./genconfig md > tmp-insn-config.h --- 275,279 ---- # Each of the other insn-* files is handled by a similar pair of rules. ! insn-config.h: stamp-config.h ; stamp-config.h : md genconfig ./genconfig md > tmp-insn-config.h *************** *** 279,283 **** touch stamp-config.h ! insn-flags.h: stamp-flags.h stamp-flags.h : md genflags ./genflags md > tmp-insn-flags.h --- 281,285 ---- touch stamp-config.h ! insn-flags.h: stamp-flags.h ; stamp-flags.h : md genflags ./genflags md > tmp-insn-flags.h *************** *** 285,289 **** touch stamp-flags.h ! insn-codes.h: stamp-codes.h stamp-codes.h : md gencodes ./gencodes md > tmp-insn-codes.h --- 287,291 ---- touch stamp-flags.h ! insn-codes.h: stamp-codes.h ; stamp-codes.h : md gencodes ./gencodes md > tmp-insn-codes.h *************** *** 291,298 **** touch stamp-codes.h ! insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) expr.h insn-config.h $(CC) $(CFLAGS) -c insn-emit.c ! insn-emit.c: stamp-emit.c stamp-emit.c : md genemit ./genemit md > tmp-insn-emit.c --- 293,300 ---- touch stamp-codes.h ! insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) expr.h insn-config.h real.h $(CC) $(CFLAGS) -c insn-emit.c ! insn-emit.c: stamp-emit.c ; stamp-emit.c : md genemit ./genemit md > tmp-insn-emit.c *************** *** 303,307 **** $(CC) $(CFLAGS) -c insn-recog.c ! insn-recog.c: stamp-recog.c stamp-recog.c : md genrecog ./genrecog md > tmp-insn-recog.c --- 305,309 ---- $(CC) $(CFLAGS) -c insn-recog.c ! insn-recog.c: stamp-recog.c ; stamp-recog.c : md genrecog ./genrecog md > tmp-insn-recog.c *************** *** 312,316 **** $(CC) $(CFLAGS) -c insn-extract.c ! insn-extract.c: stamp-extract.c stamp-extract.c : md genextract ./genextract md > tmp-insn-extract.c --- 314,318 ---- $(CC) $(CFLAGS) -c insn-extract.c ! insn-extract.c: stamp-extract.c ; stamp-extract.c : md genextract ./genextract md > tmp-insn-extract.c *************** *** 318,325 **** touch stamp-extract.c ! insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) regs.h $(CC) $(CFLAGS) -c insn-peep.c ! insn-peep.c: stamp-peep.c stamp-peep.c : md genpeep ./genpeep md > tmp-insn-peep.c --- 320,327 ---- touch stamp-extract.c ! insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) regs.h real.h $(CC) $(CFLAGS) -c insn-peep.c ! insn-peep.c: stamp-peep.c ; stamp-peep.c : md genpeep ./genpeep md > tmp-insn-peep.c *************** *** 327,334 **** touch stamp-peep.c ! insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) regs.h insn-config.h insn-flags.h conditions.h output.h aux-output.c $(CC) $(CFLAGS) -c insn-output.c ! insn-output.c: stamp-output.c stamp-output.c : md genoutput ./genoutput md > tmp-insn-output.c --- 329,337 ---- touch stamp-peep.c ! insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) regs.h real.h conditions.h \ ! insn-config.h insn-flags.h output.h aux-output.c $(CC) $(CFLAGS) -c insn-output.c ! insn-output.c: stamp-output.c ; stamp-output.c : md genoutput ./genoutput md > tmp-insn-output.c *************** *** 428,439 **** # Like realclean but also delete the links made to configure gcc. cleanlinks: realclean ! -rm tm.h aux-output.c config.h md config.status # Copy the files into directories where they will be run. install: all ! if [ -f cc1 ] ; then $(INSTALL) cc1 $(libdir)/gcc-cc1 ;fi ! if [ -f cc1plus ] ; then $(INSTALL) cc1plus $(libdir)/gcc-cc1plus ;fi $(INSTALL) gnulib $(libdir)/gcc-gnulib ! if [ -f /usr/bin/ranlib ] ; then (cd $(libdir); ranlib /gcc-gnulib) ;fi $(INSTALL) cpp $(libdir)/gcc-cpp $(INSTALL) gcc $(bindir) --- 431,443 ---- # Like realclean but also delete the links made to configure gcc. cleanlinks: realclean ! -rm -f tm.h aux-output.c config.h md config.status # Copy the files into directories where they will be run. install: all ! -mkdir $(libdir) ! -if [ -f cc1 ] ; then $(INSTALL) cc1 $(libdir)/gcc-cc1 ;fi ! -if [ -f cc1plus ] ; then $(INSTALL) cc1plus $(libdir)/gcc-cc1plus ;fi $(INSTALL) gnulib $(libdir)/gcc-gnulib ! -if [ -f /usr/bin/ranlib ] ; then (cd $(libdir); ranlib gcc-gnulib) ;fi $(INSTALL) cpp $(libdir)/gcc-cpp $(INSTALL) gcc $(bindir) *************** *** 440,446 **** -mkdir $(libdir)/gcc-include chmod ugo+rx $(libdir)/gcc-include ! cd $(libdir)/gcc-include; rm -f $(USER_H) ! cp $(USER_H) $(libdir)/gcc-include ! cp gcc.1 mandir # do make -f ../gcc/Makefile maketest DIR=../gcc --- 444,449 ---- -mkdir $(libdir)/gcc-include chmod ugo+rx $(libdir)/gcc-include ! for file in $(USER_H); do $(INSTALL) $${file} $(libdir)/gcc-include; done ! $(INSTALL) gcc.1 $(mandir)/gcc.$(manext) # do make -f ../gcc/Makefile maketest DIR=../gcc *************** *** 464,467 **** --- 467,478 ---- $(MAKE) CC="stage1/gcc -Bstage1/" CFLAGS="-O $(CFLAGS)" $(MAKE) stage2 + $(MAKE) CC="stage2/gcc -Bstage2/" CFLAGS="-O $(CFLAGS)" + + bootstrap2: force + $(MAKE) CC="stage1/gcc -Bstage1/" CFLAGS="-O $(CFLAGS)" + $(MAKE) stage2 + $(MAKE) CC="stage2/gcc -Bstage2/" CFLAGS="-O $(CFLAGS)" + + bootstrap3: force $(MAKE) CC="stage2/gcc -Bstage2/" CFLAGS="-O $(CFLAGS)" diff -rc2N gcc-1.32/PROBLEMS gcc-1.33/PROBLEMS *** gcc-1.32/PROBLEMS Thu Sep 15 11:48:36 1988 --- gcc-1.33/PROBLEMS Fri Dec 30 17:54:40 1988 *************** *** 124,125 **** --- 124,128 ---- being able to specify "push this" as a target for expand_expr. + 124. On the 386, bad code results from foo (bar ()) when bar + returns a double, because the pseudo used fails to get preferenced + into an fp reg because of the distinction between regs 8 and 9. diff -rc2N gcc-1.32/PROJECTS gcc-1.33/PROJECTS *** gcc-1.32/PROJECTS Sat Dec 17 02:37:35 1988 --- gcc-1.33/PROJECTS Tue Jan 24 02:33:14 1989 *************** *** 1,4 **** --- 1,14 ---- 1. Better optimization. + * Constants in unused inline functions + + It would be nice to delay output of string constants so that string + constants mentioned in unused inline functions are never generated. + Perhaps this would also take care of string constants in dead code. + + The difficulty is in finding a clean way for the RTL which refers + to the constant (currently, only by an assembler symbol name) + to point to the constant and cause it to be output. + * More cse *************** *** 191,201 **** 4. Generalize the machine model. ! Some new compiler features may be needed to do a good job on machines where static data needs to be addressed using base registers. ! Some machines have two stacks in different areas of memory, one used for scalars and another for large objects. The compiler does not now have a way to understand this. 5. Precompilation of header files. --- 201,246 ---- 4. Generalize the machine model. ! * Some new compiler features may be needed to do a good job on machines where static data needs to be addressed using base registers. ! * Some machines have two stacks in different areas of memory, one used for scalars and another for large objects. The compiler does not now have a way to understand this. + * Some machines use a caller-saves convention for saving registers over + function calls. Here is a design for how to handle such a convention. + + Classify all the hard registers as call-clobbered, then teach the + compiler how to put call-crossing pseudo-regs in call-clobbered hard + registers by generating save/restore insns around the call. Generate + the save/restores somewhere around the reload pass; this avoids + getting confused by cross jumping which happens after. Actually put + the save/restore insns into the RTL chain, so that cross-jumping and + peephole opt. will work on them. + + The time to generate these insns is when you can still tell what regs + are live at each call, but late enough to know exactly where the + pseudos have been allocated. Perhaps the best time is just before + reload_as_needed. + + This requires changes in local-alloc.c and global-alloc.c to be willing + to allocate call-crossing pseudos to call-clobbered registers. + That isn't hard if you do it with a special flag macro that simply says to + ignore (in those passes) whether a register is call-clobbered. + This macro would be defined if the target machine uses caller-saves. + + To get the best output, it is necessary to count the cost (in + additional save/restores) for each pseudo register of putting it in a + call-clobbered hard reg. This means counting *how many times* each + pseudo crosses a call. Depending on that value, it might be better to + put the pseudo in memory than in a call-clobbered register. Cost + counting would be done in flow.c, perhaps, and costs would affect + allocation decisions in local-alloc and global-alloc. Perhaps each + pseudo should have one priority for getting a call-saved reg and + another, lower (in general) priority for a call-clobbered reg. + + Then there would no longer be a need for the flag: the changes would + improve the output, on all machines. + 5. Precompilation of header files. *************** *** 266,267 **** --- 311,387 ---- some unconditional. This division is done without changing the order of the text being divided up. + + 6. Other possibly nice features. + + * cpp could have a #provide directive. + #provide would have the same syntax as #include, + and it would nullify any future #include directive + with the same argument. Thus, the file foo.h + could contain #provide <foo> to prevent itself from + being included twice. + + This is much cleaner than the alternative sometimes implemented, + which is to require the user to use something other than #include + in order to ensure inclusion only once. + + 7. Better documentation of how GCC works and how to port it. + + Here is an outline proposed by Allan Adler. + + I. Overview of this document + II. The machines on which GCC is implemented + A. Prose description of those characteristics of target machines and + their operating systems which are pertinent to the implementation + of GCC. + i. target machine characteristics + ii. comparison of this system of machine characteristics with + other systems of machine specification currently in use + B. Tables of the characteristics of the target machines on which + GCC is implemented. + C. A priori restrictions on the values of characteristics of target + machines, with special reference to those parts of the source code + which entail those restrictions + i. restrictions on individual characteristics + ii. restrictions involving relations between various characteristics + D. The use of GCC as a cross-compiler + i. cross-compilation to existing machines + ii. cross-compilation to non-existent machines + E. Assumptions which are made regarding the target machine + i. assumptions regarding the architecture of the target machine + ii. assumptions regarding the operating system of the target machine + iii. assumptions regarding software resident on the target machine + iv. where in the source code these assumptions are in effect made + III. A systematic approach to writing the files tm.h and xm.h + A. Macros which require special care or skill + B. Examples, with special reference to the underlying reasoning + IV. A systematic approach to writing the machine description file md + A. Minimal viable sets of insn descriptions + B. Examples, with special reference to the underlying reasoning + V. Uses of the file aux-output.c + VI. Specification of what constitutes correct performance of an + implementation of GCC + A. The components of GCC + B. The itinerary of a C program through GCC + C. A system of benchmark programs + D. What your RTL and assembler look should like with these benchmarks + E. Fine tuning for speed and size of compiled code + VII. A systematic procedure for debugging an implementation of GCC + A. Use of GDB + i. the macros in the file .gdbinit for GCC + ii. obstacles to the use of GDB + a. functions implemented as macros can't be called in GDB + B. Debugging without GDB + i. How to turn off the normal operation of GCC and access specific + parts of GCC + C. Debugging tools + D. Debugging the parser + i. how machine macros and insn definitions affect the parser + E. Debugging the recognizer + i. how machine macros and insn definitions affect the recognizer + + ditto for other components + + VIII. Data types used by GCC, with special reference to restrictions not + specified in the formal definition of the data type + IX. References to the literature for the algorithms used in GCC + diff -rc2N gcc-1.32/README gcc-1.33/README *** gcc-1.32/README Wed Dec 21 23:17:56 1988 --- gcc-1.33/README Wed Feb 1 21:34:57 1989 *************** *** 1,3 **** ! This directory contains the version 1.32 test release of the GNU C compiler. All bugs reported for previous test releases have been fixed. Some bugs surely remain. --- 1,3 ---- ! This directory contains the version 1.33 test release of the GNU C compiler. All bugs reported for previous test releases have been fixed. Some bugs surely remain. diff -rc2N gcc-1.32/alliant.md gcc-1.33/alliant.md *** gcc-1.32/alliant.md Wed Dec 31 19:00:00 1969 --- gcc-1.33/alliant.md Sun Jan 29 20:25:07 1989 *************** *** 0 **** --- 1,2994 ---- + ;;- Machine description for GNU compiler + ;;- Alliant FX Version (Based on Motorola 68000) + ;; Copyright (C) 1988 Free Software Foundation, Inc. + + ;; This file is part of GNU CC. + + ;; GNU CC is distributed in the hope that it will be useful, + ;; but WITHOUT ANY WARRANTY. No author or distributor + ;; accepts responsibility to anyone for the consequences of using it + ;; or for whether it serves any particular purpose or works at all, + ;; unless he says so in writing. Refer to the GNU CC General Public + ;; License for full details. + + ;; Everyone is granted permission to copy, modify and redistribute + ;; GNU CC, but only under the conditions described in the + ;; GNU CC General Public License. A copy of this license is + ;; supposed to have been given to you along with GNU CC so you + ;; can know your rights and responsibilities. It should be in a + ;; file named COPYING. Among other things, the copyright notice + ;; and this notice must be preserved on all copies. + + + ;;- instruction definitions + + ;;- @@The original PO technology requires these to be ordered by speed, + ;;- @@ so that assigner will pick the fastest. + + ;;- 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 in file tm.h handles condition code + ;;- updates for most instructions. + + ;;- Operand classes for the register allocator: + ;;- 'a' one of the address registers can be used. + ;;- 'd' one of the data registers can be used. + ;;- 'f' one of the m68881 registers can be used + ;;- 'r' either a data or an address register can be used. + ;;- 'x' if one of the Sun FPA registers + ;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15). + + ;;- Immediate Floating point operator constraints + ;;- 'G' a floating point constant that is *NOT* one of the standard + ;; 68881 constant values (to force calling output_move_const_double + ;; to get it from rom if it is a 68881 constant). + ;;- 'H' one of the standard FPA constant values + ;; + ;; See the functions standard_XXX_constant_p in output-m68k.c for more + ;; info. + + ;;- Immedidate integer operands Constrains: + ;;- 'I' 1 .. 8 + ;;- 'J' -32768 .. 32767 + ;;- 'K' -128 .. 127 + ;;- 'L' -8 .. -1 + + ;;- Some of these insn's are composites of several m68000 op codes. + ;;- The assembler (or final @@??) insures that the appropriate one is + ;;- selected. + + \f + (define_insn "" + [(set (match_operand:DF 0 "push_operand" "=m") + (match_operand:DF 1 "general_operand" "ro<>fyF"))] + "" + "* + { + if (FP_REG_P (operands[1])) + return \"fmoved %1,%0\"; + return output_move_double (operands); + }") + + (define_insn "" + [(set (match_operand:DI 0 "push_operand" "=m") + (match_operand:DI 1 "general_operand" "ro<>Fy"))] + "" + "* + { + return output_move_double (operands); + }") + \f + (define_insn "tstsi" + [(set (cc0) + (match_operand:SI 0 "general_operand" "rm"))] + "" + "* + { + if (TARGET_68020 || ! ADDRESS_REG_P (operands[0])) + return \"tstl %0\"; + /* If you think that the 68020 does not support tstl a0, + reread page B-167 of the 68020 manual more carefully. */ + /* On an address reg, cmpw may replace cmpl. */ + return \"cmpw %#0,%0\"; + }") + + (define_insn "tsthi" + [(set (cc0) + (match_operand:HI 0 "general_operand" "rm"))] + "" + "* + { + if (TARGET_68020 || ! ADDRESS_REG_P (operands[0])) + return \"tstw %0\"; + return \"cmpw %#0,%0\"; + }") + + (define_insn "tstqi" + [(set (cc0) + (match_operand:QI 0 "general_operand" "dm"))] + "" + "tstb %0") + + (define_expand "tstsf" + [(set (cc0) + (match_operand:SF 0 "general_operand" ""))] + "TARGET_68881" + "") + + + (define_insn "" + [(set (cc0) + (match_operand:SF 0 "general_operand" "fdm"))] + "TARGET_68881" + "* + { + cc_status.flags = CC_IN_68881; + if (FP_REG_P (operands[0])) + return \"ftests %0\"; + return \"ftests %0\"; + }") + + (define_expand "tstdf" + [(set (cc0) + (match_operand:DF 0 "general_operand" ""))] + "TARGET_68881" + "") + + (define_insn "" + [(set (cc0) + (match_operand:DF 0 "general_operand" "fm"))] + "TARGET_68881" + "* + { + cc_status.flags = CC_IN_68881; + if (FP_REG_P (operands[0])) + return \"ftestd %0\"; + return \"ftestd %0\"; + }") + \f + ;; compare instructions. + + ;; A composite of the cmp, cmpa, & cmpi m68000 op codes. + (define_insn "cmpsi" + [(set (cc0) + (minus (match_operand:SI 0 "general_operand" "rKs,mr") + (match_operand:SI 1 "general_operand" "mr,Ksr")))] + "" + "* + { + if (REG_P (operands[1]) + || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) + { cc_status.flags |= CC_REVERSED; + return \"cmpl %0,%1\"; + } + return \"cmpl %1,%0\"; + }") + + (define_insn "cmphi" + [(set (cc0) + (minus (match_operand:HI 0 "general_operand" "rn,mr") + (match_operand:HI 1 "general_operand" "mr,nr")))] + "" + "* + { + if (REG_P (operands[1]) + || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) + { cc_status.flags |= CC_REVERSED; + return \"cmpw %0,%1\"; + } + return \"cmpw %1,%0\"; + }") + + ;; + ;; This seems to cause problems -- PMP + ;; + ;;(define_insn "" + ;; [(set (cc0) + ;; (minus (match_operand:QI 0 "memory_operand" ">") + ;; (match_operand:QI 1 "memory_operand" ">")))] + ;; "GET_CODE (XEXP (operands[0], 0)) == POST_INC + ;; && GET_CODE (XEXP (operands[1], 0)) == POST_INC" + ;; "cmpmb %1,%0") + + (define_insn "cmpqi" + [(set (cc0) + (minus (match_operand:QI 0 "general_operand" "dn,md") + (match_operand:QI 1 "general_operand" "dm,nd")))] + "" + "* + { + if (REG_P (operands[1]) + || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) + { cc_status.flags |= CC_REVERSED; + return \"cmpb %0,%1\"; + } + return \"cmpb %1,%0\"; + }") + + (define_expand "cmpdf" + [(set (cc0) + (minus:DF (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (cc0) + (minus:DF (match_operand:DF 0 "general_operand" "f,m") + (match_operand:DF 1 "general_operand" "fm,f")))] + "TARGET_68881" + "* + { + cc_status.flags = CC_IN_68881; + if (REG_P (operands[0])) + { + if (REG_P (operands[1])) + return \"fcmpd %1,%0\"; + else + return \"fcmpd %1,%0\"; + } + cc_status.flags |= CC_REVERSED; + return \"fcmpd %0,%1\"; + }") + + (define_expand "cmpsf" + [(set (cc0) + (minus:SF (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (cc0) + (minus:SF (match_operand:SF 0 "general_operand" "f,md") + (match_operand:SF 1 "general_operand" "fmd,f")))] + "TARGET_68881" + "* + { + cc_status.flags = CC_IN_68881; + if (FP_REG_P (operands[0])) + { + if (FP_REG_P (operands[1])) + return \"fcmps %1,%0\"; + else + return \"fcmps %1,%0\"; + } + cc_status.flags |= CC_REVERSED; + return \"fcmps %0,%1\"; + }") + \f + ;; Recognizers for btst instructions. + + (define_insn "" + [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do") + (const_int 1) + (minus:SI (const_int 7) + (match_operand:SI 1 "general_operand" "di"))))] + "" + "* { return output_btst (operands, operands[1], operands[0], insn, 7); }") + + (define_insn "" + [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d") + (const_int 1) + (minus:SI (const_int 31) + (match_operand:SI 1 "general_operand" "di"))))] + "" + "* { return output_btst (operands, operands[1], operands[0], insn, 31); }") + + ;; The following two patterns are like the previous two + ;; except that they use the fact that bit-number operands + ;; are automatically masked to 3 or 5 bits. + + (define_insn "" + [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do") + (const_int 1) + (minus:SI (const_int 7) + (and:SI + (match_operand:SI 1 "general_operand" "d") + (const_int 7)))))] + "" + "* { return output_btst (operands, operands[1], operands[0], insn, 7); }") + + (define_insn "" + [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d") + (const_int 1) + (minus:SI (const_int 31) + (and:SI + (match_operand:SI 1 "general_operand" "d") + (const_int 31)))))] + "" + "* { return output_btst (operands, operands[1], operands[0], insn, 31); }") + + (define_insn "" + ;; The constraint "o,d" here means that a nonoffsetable memref + ;; will match the first alternative, and its address will be reloaded. + ;; Copying the memory contents into a reg would be incorrect if the + ;; bit position is over 7. + [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "o,d") + (const_int 1) + (match_operand:SI 1 "general_operand" "i,i")))] + "GET_CODE (operands[1]) == CONST_INT" + "* + { operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1])); + return output_btst (operands, operands[1], operands[0], insn, 7); }") + + (define_insn "" + [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "o,d") + (const_int 1) + (match_operand:SI 1 "general_operand" "i,i")))] + "GET_CODE (operands[1]) == CONST_INT" + "* + { + if (GET_CODE (operands[0]) == MEM) + { + operands[0] = adj_offsetable_operand (operands[0], + INTVAL (operands[1]) / 8); + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 7 - INTVAL (operands[1]) % 8); + return output_btst (operands, operands[1], operands[0], insn, 7); + } + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 15 - INTVAL (operands[1])); + return output_btst (operands, operands[1], operands[0], insn, 15); + }") + + (define_insn "" + [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do") + (const_int 1) + (match_operand:SI 1 "general_operand" "i")))] + "GET_CODE (operands[1]) == CONST_INT" + "* + { + if (GET_CODE (operands[0]) == MEM) + { + operands[0] = adj_offsetable_operand (operands[0], + INTVAL (operands[1]) / 8); + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 7 - INTVAL (operands[1]) % 8); + return output_btst (operands, operands[1], operands[0], insn, 7); + } + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 31 - INTVAL (operands[1])); + return output_btst (operands, operands[1], operands[0], insn, 31); + }") + + (define_insn "" + [(set (cc0) (subreg:SI (lshiftrt:QI (match_operand:QI 0 "nonimmediate_operand" "dm") + (const_int 7)) + 0))] + "" + "* + { + cc_status.flags = CC_Z_IN_NOT_N | CC_NOT_NEGATIVE; + return \"tstb %0\"; + }") + + (define_insn "" + [(set (cc0) (and:SI (sign_extend:SI (sign_extend:HI (match_operand:QI 0 "nonimmediate_operand" "dm"))) + (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 output_btst (operands, operands[1], operands[0], insn, 7); + }") + \f + ;; move instructions + (define_insn "swapsi" + [(set (match_operand:SI 0 "general_operand" "r") + (match_operand:SI 1 "general_operand" "r")) + (set (match_dup 1) (match_dup 0))] + "" + "exg %1,%0") + + ;; Special case of fullword move when source is zero. + ;; The reason this is special is to avoid loading a zero + ;; into a data reg with moveq in order to store it elsewhere. + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (const_int 0))] + "" + "* + { + if (ADDRESS_REG_P (operands[0])) + return \"subl %0,%0\"; + return \"clrl %0\"; + }") + + ;; Another special case in which it is not desirable + ;; to reload the constant into a data register. + (define_insn "" + [(set (match_operand:SI 0 "push_operand" "=m") + (match_operand:SI 1 "general_operand" "J"))] + "GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) >= -0x8000 + && INTVAL (operands[1]) < 0x8000" + "pea %a1") + + ;; General case of fullword move. The register constraints + ;; force integer constants in range for a moveq to be reloaded + ;; if they are headed for memory. + (define_insn "movsi" + ;; Notes: make sure no alternative allows g vs g. + ;; We don't allow f-regs since fixed point cannot go in them. + ;; We do allow y and x regs since fixed point is allowed in them. + [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m") + (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))] + "" + "* + { + if (GET_CODE (operands[1]) == CONST_INT) + { + if (operands[1] == const0_rtx + && (DATA_REG_P (operands[0]) + || GET_CODE (operands[0]) == MEM)) + return \"clrl %0\"; + else if (DATA_REG_P (operands[0]) + && INTVAL (operands[1]) < 128 + && INTVAL (operands[1]) >= -128) + { + return \"moveq %1,%0\"; + } + else if (ADDRESS_REG_P (operands[0]) + && INTVAL (operands[1]) < 0x8000 + && INTVAL (operands[1]) >= -0x8000) + return \"movw %1,%0\"; + else if (push_operand (operands[0], SImode) + && INTVAL (operands[1]) < 0x8000 + && INTVAL (operands[1]) >= -0x8000) + return \"pea %a1\"; + } + else if ((GET_CODE (operands[1]) == SYMBOL_REF + || GET_CODE (operands[1]) == CONST) + && push_operand (operands[0], SImode)) + return \"pea %a1\"; + else if ((GET_CODE (operands[1]) == SYMBOL_REF + || GET_CODE (operands[1]) == CONST) + && ADDRESS_REG_P (operands[0])) + return \"lea %a1,%0\"; + return \"movl %1,%0\"; + }") + + (define_insn "movhi" + [(set (match_operand:HI 0 "general_operand" "=g") + (match_operand:HI 1 "general_operand" "g"))] + "" + "* + { + if (GET_CODE (operands[1]) == CONST_INT) + { + if (operands[1] == const0_rtx + && (DATA_REG_P (operands[0]) + || GET_CODE (operands[0]) == MEM)) + return \"clrw %0\"; + else if (DATA_REG_P (operands[0]) + && INTVAL (operands[1]) < 128 + && INTVAL (operands[1]) >= -128) + { + return \"moveq %1,%0\"; + } + else if (INTVAL (operands[1]) < 0x8000 + && INTVAL (operands[1]) >= -0x8000) + return \"movw %1,%0\"; + } + else if (CONSTANT_P (operands[1])) + return \"movl %1,%0\"; + /* Recognize the insn before a tablejump, one that refers + to a table of offsets. Such an insn will need to refer + to a label on the insn. So output one. Use the label-number + of the table of offsets to generate this label. */ + if (GET_CODE (operands[1]) == MEM + && GET_CODE (XEXP (operands[1], 0)) == PLUS + && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF + || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF) + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS + && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS) + { + rtx labelref; + if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF) + labelref = XEXP (XEXP (operands[1], 0), 0); + else + labelref = XEXP (XEXP (operands[1], 0), 1); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\", + CODE_LABEL_NUMBER (XEXP (labelref, 0))); + } + return \"movw %1,%0\"; + }") + + (define_insn "movstricthi" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) + (match_operand:HI 1 "general_operand" "rmn"))] + "" + "* + { + if (GET_CODE (operands[1]) == CONST_INT) + { + if (operands[1] == const0_rtx + && (DATA_REG_P (operands[0]) + || GET_CODE (operands[0]) == MEM)) + return \"clrw %0\"; + } + return \"movw %1,%0\"; + }") + + (define_insn "movqi" + [(set (match_operand:QI 0 "general_operand" "=d,*a,m") + (match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi"))] + "" + "* + { + if (operands[1] == const0_rtx) + return \"clrb %0\"; + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) == -1) + return \"st %0\"; + if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1])) + return \"movl %1,%0\"; + if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1])) + return \"movw %1,%0\"; + return \"movb %1,%0\"; + }") + + (define_insn "movstrictqi" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) + (match_operand:QI 1 "general_operand" "dmn"))] + "" + "* + { + if (operands[1] == const0_rtx) + return \"clrb %0\"; + return \"movb %1,%0\"; + }") + + (define_insn "movsf" + [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm") + (match_operand:SF 1 "general_operand" "rmfF,x,rmF,y,rm,x"))] + "" + "* + { + if (FP_REG_P (operands[0])) + { + if (FP_REG_P (operands[1])) + return \"fmoves %1,%0\"; + else if (ADDRESS_REG_P (operands[1]) || DATA_REG_P (operands[1])) + return \"movl %1,%-\;fmoves %+,%0\"; + else if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + rtx xoperands[2]; + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_HIGH (operands[1])); + output_asm_insn (\"movl %1,%-\", xoperands); + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_LOW (operands[1])); + output_asm_insn (\"movl %1,%-\", xoperands); + return \"fmoveds %+,%0\"; + } + return \"fmoves %1,%0\"; + } + if (FP_REG_P (operands[1])) + { + if (ADDRESS_REG_P (operands[0]) || DATA_REG_P (operands[0])) + return \"fmoves %1,%-\;movl %+,%0\"; + return \"fmoves %1,%0\"; + } + return \"movl %1,%0\"; + }") + + ;; This pattern forces (set (reg:DF ...) (const_double ...)) + ;; to be reloaded by putting the constant into memory. + ;; It must come before the more general movdf pattern. + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f,f,f") + (match_operand:DF 1 "" "mF,m,F"))] + "GET_CODE (operands[1]) == CONST_DOUBLE" + "* + { + rtx xoperands[2]; + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_HIGH (operands[1])); + output_asm_insn (\"movl %1,%-\", xoperands); + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_LOW (operands[1])); + output_asm_insn (\"movl %1,%-\", xoperands); + return \"fmoved %+,%0\"; + } + ") + + (define_insn "movdf" + [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>,y,rm,x,!x,!rm") + (match_operand:DF 1 "general_operand" "rf,m,rof<>,rm,y,x,rm,x"))] + "" + "* + { + if (FP_REG_P (operands[0])) + { + if (FP_REG_P (operands[1])) + return \"fmoved %1,%0\"; + if (REG_P (operands[1])) + { + rtx xoperands[2]; + xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + output_asm_insn (\"movl %1,%-\", xoperands); + output_asm_insn (\"movl %1,%-\", operands); + return \"fmoved %+,%0\"; + } + if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + rtx xoperands[2]; + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_HIGH (operands[1])); + output_asm_insn (\"movl %1,%-\", xoperands); + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_LOW (operands[1])); + output_asm_insn (\"movl %1,%-\", xoperands); + return \"fmoved %+,%0\"; + } + return \"fmoved %1,%0\"; + } + else if (FP_REG_P (operands[1])) + { + if (REG_P (operands[0])) + { + output_asm_insn (\"fmoved %1,%-\;movl %+,%0\", operands); + operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + return \"movl %+,%0\"; + } + else + return \"fmoved %1,%0\"; + } + return output_move_double (operands); + } + ") + + ;; movdi can apply to fp regs in some cases + (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<>,y,rm,!*x,!rm") + (match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))] + "" + "* + { + if (FP_REG_P (operands[0])) + { + if (FP_REG_P (operands[1])) + return \"fmoved %1,%0\"; + if (REG_P (operands[1])) + { + rtx xoperands[2]; + xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + output_asm_insn (\"movl %1,%-\", xoperands); + output_asm_insn (\"movl %1,%-\", operands); + return \"fmoved %+,%0\"; + } + if (GET_CODE (operands[1]) == CONST_DOUBLE) + return output_move_const_double (operands); + return \"fmoved %1,%0\"; + } + else if (FP_REG_P (operands[1])) + { + if (REG_P (operands[0])) + { + output_asm_insn (\"fmove.d %1,%-\;movl %+,%0\", operands); + operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + return \"movl %+,%0\"; + } + else + return \"fmoved %1,%0\"; + } + return output_move_double (operands); + } + ") + + ;; These go after the move instructions + ;; because the move instructions are better (require no spilling) + ;; when they can apply. But these go before the add and subtract insns + ;; because it is often shorter to use these when both apply. + (define_insn "pushasi" + [(set (match_operand:SI 0 "push_operand" "=m") + (match_operand:SI 1 "address_operand" "p"))] + "" + "pea %a1") + + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=a") + (match_operand:QI 1 "address_operand" "p"))] + "" + "lea %a1,%0") + \f + ;; truncation instructions + (define_insn "truncsiqi2" + [(set (match_operand:QI 0 "general_operand" "=dm,d") + (truncate:QI + (match_operand:SI 1 "general_operand" "doJ,i")))] + "" + "* + { + if (GET_CODE (operands[0]) == REG) + return \"movl %1,%0\"; + if (GET_CODE (operands[1]) == MEM) + operands[1] = adj_offsetable_operand (operands[1], 3); + return \"movb %1,%0\"; + }") + + (define_insn "trunchiqi2" + [(set (match_operand:QI 0 "general_operand" "=dm,d") + (truncate:QI + (match_operand:HI 1 "general_operand" "doJ,i")))] + "" + "* + { + if (GET_CODE (operands[0]) == REG) + return \"movl %1,%0\"; + if (GET_CODE (operands[1]) == MEM) + operands[1] = adj_offsetable_operand (operands[1], 1); + return \"movb %1,%0\"; + }") + + (define_insn "truncsihi2" + [(set (match_operand:HI 0 "general_operand" "=dm,d") + (truncate:HI + (match_operand:SI 1 "general_operand" "roJ,i")))] + "" + "* + { + if (GET_CODE (operands[0]) == REG) + return \"movl %1,%0\"; + if (GET_CODE (operands[1]) == MEM) + operands[1] = adj_offsetable_operand (operands[1], 2); + return \"movw %1,%0\"; + }") + \f + ;; zero extension instructions + + (define_expand "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (const_int 0)) + (set (strict_low_part (subreg:HI (match_dup 0) 0)) + (match_operand:HI 1 "general_operand" ""))] + "" + "operands[1] = make_safe_from (operands[1], operands[0]);") + + (define_expand "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "") + (const_int 0)) + (set (strict_low_part (subreg:QI (match_dup 0) 0)) + (match_operand:QI 1 "general_operand" ""))] + "" + "operands[1] = make_safe_from (operands[1], operands[0]);") + + (define_expand "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "") + (const_int 0)) + (set (strict_low_part (subreg:QI (match_dup 0) 0)) + (match_operand:QI 1 "general_operand" ""))] + "" + " operands[1] = make_safe_from (operands[1], operands[0]); ") + \f + ;; Patterns to recognize zero-extend insns produced by the combiner. + + ;; Note that the one starting from HImode comes before those for QImode + ;; so that a constant operand will match HImode, not QImode. + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=do<>") + (zero_extend:SI + (match_operand:HI 1 "general_operand" "rmn")))] + "" + "* + { + if (DATA_REG_P (operands[0])) + { + if (GET_CODE (operands[1]) == REG + && REGNO (operands[0]) == REGNO (operands[1])) + return \"andl %#0xFFFF,%0\"; + if (reg_mentioned_p (operands[0], operands[1])) + return \"movw %1,%0\;andl %#0xFFFF,%0\"; + return \"clrl %0\;movw %1,%0\"; + } + else if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + return \"movw %1,%0\;clrw %0\"; + else if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == POST_INC) + return \"clrw %0\;movw %1,%0\"; + else + { + output_asm_insn (\"clrw %0\", operands); + operands[0] = adj_offsetable_operand (operands[0], 2); + return \"movw %1,%0\"; + } + }") + + (define_insn "" + [(set (match_operand:HI 0 "general_operand" "=do<>") + (zero_extend:HI + (match_operand:QI 1 "general_operand" "dmn")))] + "" + "* + { + if (DATA_REG_P (operands[0])) + { + if (GET_CODE (operands[1]) == REG + && REGNO (operands[0]) == REGNO (operands[1])) + return \"andw %#0xFF,%0\"; + if (reg_mentioned_p (operands[0], operands[1])) + return \"movb %1,%0\;andw %#0xFF,%0\"; + return \"clrw %0\;movb %1,%0\"; + } + else if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + { + if (REGNO (XEXP (XEXP (operands[0], 0), 0)) + == STACK_POINTER_REGNUM) + return \"clrw %-\;movb %1,%0\"; + else + return \"movb %1,%0\;clrb %0\"; + } + else if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == POST_INC) + return \"clrb %0\;movb %1,%0\"; + else + { + output_asm_insn (\"clrb %0\", operands); + operands[0] = adj_offsetable_operand (operands[0], 1); + return \"movb %1,%0\"; + } + }") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=do<>") + (zero_extend:SI + (match_operand:QI 1 "general_operand" "dmn")))] + "" + "* + { + if (DATA_REG_P (operands[0])) + { + if (GET_CODE (operands[1]) == REG + && REGNO (operands[0]) == REGNO (operands[1])) + return \"andl %#0xFF,%0\"; + if (reg_mentioned_p (operands[0], operands[1])) + return \"movb %1,%0\;andl %#0xFF,%0\"; + return \"clrl %0\;movb %1,%0\"; + } + else if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + { + operands[0] = XEXP (XEXP (operands[0], 0), 0); + return \"clrl %0@-\;movb %1,%0@(3)\"; + } + else if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == POST_INC) + { + operands[0] = XEXP (XEXP (operands[0], 0), 0); + return \"clrl %0@+\;movb %1,%0@(-1)\"; + } + else + { + output_asm_insn (\"clrl %0\", operands); + operands[0] = adj_offsetable_operand (operands[0], 3); + return \"movb %1,%0\"; + } + }") + \f + ;; sign extension instructions + ;; Note that the one starting from HImode comes before those for QImode + ;; so that a constant operand will match HImode, not QImode. + + (define_insn "extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=*d,a") + (sign_extend:SI + (match_operand:HI 1 "general_operand" "0,rmn")))] + "" + "* + { + if (ADDRESS_REG_P (operands[0])) + return \"movw %1,%0\"; + return \"extl %0\"; + }") + + (define_insn "extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=d") + (sign_extend:HI + (match_operand:QI 1 "general_operand" "0")))] + "" + "extw %0") + + (define_insn "extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=d") + (sign_extend:SI + (match_operand:QI 1 "general_operand" "0")))] + "TARGET_68020" + "extbl %0") + \f + ;; Conversions between float and double. + + (define_expand "extendsfdf2" + [(set (match_operand:DF 0 "general_operand" "") + (float_extend:DF + (match_operand:SF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (float_extend:DF + (match_operand:SF 1 "general_operand" "fm")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0]) && FP_REG_P (operands[1])) + return \"fmovesd %1,%0\"; + if (FP_REG_P (operands[0])) + return \"fmovesd %1,%0\"; + if (DATA_REG_P (operands[0]) && FP_REG_P (operands[1])) + { + output_asm_insn (\"fmovesd %1,%-\;movl %+,%0\", operands); + operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + return \"movl %+,%0\"; + } + return \"fmovesd %1,%0\"; + }") + + ;; This cannot output into an f-reg because there is no way to be + ;; sure of truncating in that case. + + (define_expand "truncdfsf2" + [(set (match_operand:SF 0 "general_operand" "") + (float_truncate:SF + (match_operand:DF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=fm") + (float_truncate:SF + (match_operand:DF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[1])) { + if (FP_REG_P (operands[0])) + return \"fmoveds %1,%0\"; + else { + output_asm_insn (\"fmoveds %1,%-\", operands); + return \"movl %+,%0\"; + } + } + if (FP_REG_P (operands[0])) + return \"fmoveds %1,%0\"; + return \"fmoveds %1,%0\"; + }") + + \f + ;; 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_expand "floatsisf2" + [(set (match_operand:SF 0 "general_operand" "") + (float:SF (match_operand:SI 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (float:SF (match_operand:SI 1 "general_operand" "dmi")))] + "TARGET_68881" + "fmovels %1,%0") + + (define_expand "floatsidf2" + [(set (match_operand:DF 0 "general_operand" "") + (float:DF (match_operand:SI 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (float:DF (match_operand:SI 1 "general_operand" "dmi")))] + "TARGET_68881" + "fmoveld %1,%0") + + (define_insn "floathisf2" + [(set (match_operand:SF 0 "general_operand" "=f") + (float:SF (match_operand:HI 1 "general_operand" "dmn")))] + "TARGET_68881" + "fmovews %1,%0") + + (define_insn "floathidf2" + [(set (match_operand:DF 0 "general_operand" "=f") + (float:DF (match_operand:HI 1 "general_operand" "dmn")))] + "TARGET_68881" + "fmovewd %1,%0") + + (define_insn "floatqisf2" + [(set (match_operand:SF 0 "general_operand" "=f") + (float:SF (match_operand:QI 1 "general_operand" "dmn")))] + "TARGET_68881" + "fmovebs %1,%0") + + (define_insn "floatqidf2" + [(set (match_operand:DF 0 "general_operand" "=f") + (float:DF (match_operand:QI 1 "general_operand" "dmn")))] + "TARGET_68881" + "fmovebd %1,%0") + + ;; 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" "=fm") + (fix:DF (match_operand:DF 1 "general_operand" "fm")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[1])) { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovedl %1,%-\", operands); + return \"fmoveld %+,%0\"; + } + return \"fmovedl %1,%0\"; + } + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmoved %1,%0\", operands); + output_asm_insn (\"fmovedl %0,%-\", operands); + return \"fmoveld %+,%0\"; + } + return \"fmovedl %1,%0\"; + }") + + (define_insn "ftruncsf2" + [(set (match_operand:SF 0 "general_operand" "=fm") + (fix:SF (match_operand:SF 1 "general_operand" "fm")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[1])) { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovesl %1,%-\", operands); + return \"fmovels %+,%0\"; + } + return \"fmovesl %1,%0\"; + } + return \"fmovesl %1,%0\"; + }") + + ;; Convert a float whose value is an integer + ;; to an actual integer. Second stage of converting float to integer type. + (define_insn "fixsfqi2" + [(set (match_operand:QI 0 "general_operand" "=m") + (fix:QI (match_operand:SF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovesb %1,%-\", operands); + return \"fmovebs %+,%0\"; + } + if (DATA_REG_P (operands[0])) { + output_asm_insn (\"fmovesb %1,%-\", operands); + return \"movb% %+,%0\"; + } + return \"fmovesb %1,%0\"; + }") + + (define_insn "fixsfhi2" + [(set (match_operand:HI 0 "general_operand" "=m") + (fix:HI (match_operand:SF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovesw %1,%-\", operands); + return \"fmovews %+,%0\"; + } + if (DATA_REG_P (operands[0])) { + output_asm_insn (\"fmovesw %1,%-\", operands); + return \"movw% %+,%0\"; + } + return \"fmovesw %1,%0\"; + }") + + (define_insn "fixsfsi2" + [(set (match_operand:SI 0 "general_operand" "=fdm") + (fix:SI (match_operand:SF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovesl %1,%-\", operands); + return \"fmovels %+,%0\"; + } + if (DATA_REG_P (operands[0])) { + output_asm_insn (\"fmovesl %1,%-\", operands); + return \"movl %+,%0\"; + } + return \"fmovesl %1,%0\"; + }") + + (define_insn "fixdfqi2" + [(set (match_operand:QI 0 "general_operand" "=fdm") + (fix:QI (match_operand:DF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovedb %1,%-\", operands); + return \"fmovebd %+,%0\"; + } + if (DATA_REG_P (operands[0])) { + output_asm_insn (\"fmovedb %1,%-\", operands); + return \"movb% %+,%0\"; + } + return \"fmovedb %1,%0\"; + }") + + (define_insn "fixdfhi2" + [(set (match_operand:HI 0 "general_operand" "=fdm") + (fix:HI (match_operand:DF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovedw %1,%-\", operands); + return \"fmovewd %+,%0\"; + } + if (DATA_REG_P (operands[0])) { + output_asm_insn (\"fmovedw %1,%-\", operands); + return \"movw% %+,%0\"; + } + return \"fmovedw %1,%0\"; + }") + + (define_insn "fixdfsi2" + [(set (match_operand:SI 0 "general_operand" "=fdm") + (fix:SI (match_operand:DF 1 "general_operand" "f")))] + "TARGET_68881" + "* + { + if (FP_REG_P (operands[0])) { + output_asm_insn (\"fmovedl %1,%-\", operands); + return \"fmoveld %+,%0\"; + } + if (DATA_REG_P (operands[0])) { + output_asm_insn (\"fmovedl %1,%-\", operands); + return \"movl %+,%0\"; + } + return \"fmovedl %1,%0\"; + }") + + \f + ;; add instructions + + (define_insn "addsi3" + [(set (match_operand:SI 0 "general_operand" "=m,r,!a") + (plus:SI (match_operand:SI 1 "general_operand" "%0,0,a") + (match_operand:SI 2 "general_operand" "dIKLs,mrIKLs,rJK")))] + "" + "* + { + if (! operands_match_p (operands[0], operands[1])) + { + /* These insns can result from reloads to access + stack slots over 64k from the frame pointer. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000) + return \"movl %2,%0\;addl %1,%0\"; + if (GET_CODE (operands[2]) == REG) + return \"lea %1@[%2:L:B],%0\"; + else + return \"lea %1@(%c2),%0\"; + } + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) > 0 + && INTVAL (operands[2]) <= 8) + return (ADDRESS_REG_P (operands[0]) + ? \"addqw %2,%0\" + : \"addql %2,%0\"); + if (INTVAL (operands[2]) < 0 + && INTVAL (operands[2]) >= -8) + { + operands[2] = gen_rtx (CONST_INT, VOIDmode, + - INTVAL (operands[2])); + return (ADDRESS_REG_P (operands[0]) + ? \"subqw %2,%0\" + : \"subql %2,%0\"); + } + if (ADDRESS_REG_P (operands[0]) + && INTVAL (operands[2]) >= -0x8000 + && INTVAL (operands[2]) < 0x8000) + return \"addw %2,%0\"; + } + return \"addl %2,%0\"; + }") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=a") + (plus:SI (match_operand:SI 1 "general_operand" "0") + (sign_extend:SI (match_operand:HI 2 "general_operand" "rmn"))))] + "" + "addw %2,%0") + + (define_insn "addhi3" + [(set (match_operand:HI 0 "general_operand" "=m,r") + (plus:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "general_operand" "dn,rmn")))] + "" + "* + { + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) > 0 + && INTVAL (operands[2]) <= 8) + return \"addqw %2,%0\"; + } + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) < 0 + && INTVAL (operands[2]) >= -8) + { + operands[2] = gen_rtx (CONST_INT, VOIDmode, + - INTVAL (operands[2])); + return \"subqw %2,%0\"; + } + } + return \"addw %2,%0\"; + }") + + (define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (plus:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dn,rmn")))] + "" + "addw %1,%0") + + (define_insn "addqi3" + [(set (match_operand:QI 0 "general_operand" "=m,d") + (plus:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "general_operand" "dn,dmn")))] + "" + "* + { + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) > 0 + && INTVAL (operands[2]) <= 8) + return \"addqb %2,%0\"; + } + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8) + { + operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2])); + return \"subqb %2,%0\"; + } + } + return \"addb %2,%0\"; + }") + + (define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (plus:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dn,dmn")))] + "" + "addb %1,%0") + + (define_expand "adddf3" + [(set (match_operand:DF 0 "general_operand" "") + (plus:DF (match_operand:DF 1 "general_operand" "") + (match_operand:DF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (plus:DF (match_operand:DF 1 "general_operand" "%f") + (match_operand:DF 2 "general_operand" "fm")))] + "TARGET_68881" + "faddd %2,%1,%0") + + (define_expand "addsf3" + [(set (match_operand:SF 0 "general_operand" "") + (plus:SF (match_operand:SF 1 "general_operand" "") + (match_operand:SF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (plus:SF (match_operand:SF 1 "general_operand" "%f") + (match_operand:SF 2 "general_operand" "fm")))] + "TARGET_68881" + "fadds %2,%1,%0") + \f + ;; subtract instructions + + (define_insn "subsi3" + [(set (match_operand:SI 0 "general_operand" "=m,r,!a,?d") + (minus:SI (match_operand:SI 1 "general_operand" "0,0,a,mrIKs") + (match_operand:SI 2 "general_operand" "dIKs,mrIKs,J,0")))] + "" + "* + { + if (! operands_match_p (operands[0], operands[1])) + { + if (operands_match_p (operands[0], operands[2])) + { + if (GET_CODE (operands[1]) == CONST_INT) + { + if (INTVAL (operands[1]) > 0 + && INTVAL (operands[1]) <= 8) + return \"subql %1,%0\;negl %0\"; + } + return \"subl %1,%0\;negl %0\"; + } + /* This case is matched by J, but negating -0x8000 + in an lea would give an invalid displacement. + So do this specially. */ + if (INTVAL (operands[2]) == -0x8000) + return \"movl %1,%0\;subl %2,%0\"; + return \"lea %1@(%n2),%0\"; + } + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) > 0 + && INTVAL (operands[2]) <= 8) + return \"subql %2,%0\"; + if (ADDRESS_REG_P (operands[0]) + && INTVAL (operands[2]) >= -0x8000 + && INTVAL (operands[2]) < 0x8000) + return \"subw %2,%0\"; + } + return \"subl %2,%0\"; + }") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=a") + (minus:SI (match_operand:SI 1 "general_operand" "0") + (sign_extend:SI (match_operand:HI 2 "general_operand" "rmn"))))] + "" + "subw %2,%0") + + (define_insn "subhi3" + [(set (match_operand:HI 0 "general_operand" "=m,r") + (minus:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "dn,rmn")))] + "" + "subw %2,%0") + + (define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (minus:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dn,rmn")))] + "" + "subw %1,%0") + + (define_insn "subqi3" + [(set (match_operand:QI 0 "general_operand" "=m,d") + (minus:QI (match_operand:QI 1 "general_operand" "0,0") + (match_operand:QI 2 "general_operand" "dn,dmn")))] + "" + "subb %2,%0") + + (define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (minus:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dn,dmn")))] + "" + "subb %1,%0") + + (define_expand "subdf3" + [(set (match_operand:DF 0 "general_operand" "") + (minus:DF (match_operand:DF 1 "general_operand" "") + (match_operand:DF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (minus:DF (match_operand:DF 1 "general_operand" "f") + (match_operand:DF 2 "general_operand" "fm")))] + "TARGET_68881" + "fsubd %2,%1,%0") + + (define_expand "subsf3" + [(set (match_operand:SF 0 "general_operand" "") + (minus:SF (match_operand:SF 1 "general_operand" "") + (match_operand:SF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (minus:SF (match_operand:SF 1 "general_operand" "f") + (match_operand:SF 2 "general_operand" "fm")))] + "TARGET_68881" + "fsubs %2,%1,%0") + \f + ;; multiply instructions + + (define_insn "mulhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (mult:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "muls %2,%0") + + (define_insn "mulhisi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (mult:SI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "muls %2,%0") + + (define_insn "mulsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (mult:SI (match_operand:SI 1 "general_operand" "%0") + (match_operand:SI 2 "general_operand" "dmsK")))] + "TARGET_68020" + "mulsl %2,%0") + + (define_insn "umulhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (umult:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "mulu %2,%0") + + (define_insn "umulhisi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (umult:SI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "mulu %2,%0") + + (define_insn "umulsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (umult:SI (match_operand:SI 1 "general_operand" "%0") + (match_operand:SI 2 "general_operand" "dmsK")))] + "TARGET_68020" + "mulul %2,%0") + + (define_expand "muldf3" + [(set (match_operand:DF 0 "general_operand" "") + (mult:DF (match_operand:DF 1 "general_operand" "") + (match_operand:DF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (mult:DF (match_operand:DF 1 "general_operand" "%f") + (match_operand:DF 2 "general_operand" "fm")))] + "TARGET_68881" + "fmuld %2,%1,%0") + + (define_expand "mulsf3" + [(set (match_operand:SF 0 "general_operand" "") + (mult:SF (match_operand:SF 1 "general_operand" "") + (match_operand:SF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (mult:SF (match_operand:SF 1 "general_operand" "%f") + (match_operand:SF 2 "general_operand" "fm")))] + "TARGET_68881" + "fmuls %2,%1,%0") + \f + ;; divide instructions + + (define_insn "divhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (div:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "extl %0\;divs %2,%0") + + (define_insn "divhisi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (div:HI (match_operand:SI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "divs %2,%0") + + (define_insn "divsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (div:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dmsK")))] + "TARGET_68020" + "divsl %2,%0,%0") + + (define_insn "udivhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (udiv:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "andl %#0xFFFF,%0\;divu %2,%0") + + (define_insn "udivhisi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (udiv:HI (match_operand:SI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "divu %2,%0") + + (define_insn "udivsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (udiv:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dmsK")))] + "TARGET_68020" + "divul %2,%0,%0") + + (define_expand "divdf3" + [(set (match_operand:DF 0 "general_operand" "") + (div:DF (match_operand:DF 1 "general_operand" "") + (match_operand:DF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (div:DF (match_operand:DF 1 "general_operand" "f") + (match_operand:DF 2 "general_operand" "fm")))] + "TARGET_68881" + "fdivd %2,%1,%0") + + (define_expand "divsf3" + [(set (match_operand:SF 0 "general_operand" "") + (div:SF (match_operand:SF 1 "general_operand" "") + (match_operand:SF 2 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (div:SF (match_operand:SF 1 "general_operand" "0") + (match_operand:SF 2 "general_operand" "fm")))] + "TARGET_68881" + "fdivs %2,%0,%0") + \f + ;; Remainder instructions. + + (define_insn "modhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (mod:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "* + { + /* The swap insn produces cc's that don't correspond to the result. */ + CC_STATUS_INIT; + return \"extl %0\;divs %2,%0\;swap %0\"; + }") + + (define_insn "modhisi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (mod:HI (match_operand:SI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "* + { + /* The swap insn produces cc's that don't correspond to the result. */ + CC_STATUS_INIT; + return \"divs %2,%0\;swap %0\"; + }") + + (define_insn "umodhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (umod:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "* + { + /* The swap insn produces cc's that don't correspond to the result. */ + CC_STATUS_INIT; + return \"andl %#0xFFFF,%0\;divu %2,%0\;swap %0\"; + }") + + (define_insn "umodhisi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (umod:HI (match_operand:SI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmn")))] + "" + "* + { + /* The swap insn produces cc's that don't correspond to the result. */ + CC_STATUS_INIT; + return \"divu %2,%0\;swap %0\"; + }") + + (define_insn "divmodsi4" + [(set (match_operand:SI 0 "general_operand" "=d") + (div:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dmsK"))) + (set (match_operand:SI 3 "general_operand" "=d") + (mod:SI (match_dup 1) (match_dup 2)))] + "TARGET_68020" + "divsl %2,%0,%3") + + (define_insn "udivmodsi4" + [(set (match_operand:SI 0 "general_operand" "=d") + (udiv:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dmsK"))) + (set (match_operand:SI 3 "general_operand" "=d") + (umod:SI (match_dup 1) (match_dup 2)))] + "TARGET_68020" + "divul %2,%0,%3") + \f + ;; logical-and instructions + + (define_insn "andsi3" + [(set (match_operand:SI 0 "general_operand" "=m,d") + (and:SI (match_operand:SI 1 "general_operand" "%0,0") + (match_operand:SI 2 "general_operand" "dKs,dmKs")))] + "" + "* + { + if (GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) | 0xffff) == 0xffffffff + && (DATA_REG_P (operands[0]) + || offsetable_memref_p (operands[0]))) + { + if (GET_CODE (operands[0]) != REG) + operands[0] = adj_offsetable_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; + if (operands[2] == const0_rtx) + return \"clrw %0\"; + return \"andw %2,%0\"; + } + return \"andl %2,%0\"; + }") + + (define_insn "andhi3" + [(set (match_operand:HI 0 "general_operand" "=m,d") + (and:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "general_operand" "dn,dmn")))] + "" + "andw %2,%0") + + (define_insn "andqi3" + [(set (match_operand:QI 0 "general_operand" "=m,d") + (and:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "general_operand" "dn,dmn")))] + "" + "andb %2,%0") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (and:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "dm")) + (match_operand:SI 2 "general_operand" "0")))] + "GET_CODE (operands[2]) == CONST_INT + && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))" + "andw %1,%0") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (and:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "dm")) + (match_operand:SI 2 "general_operand" "0")))] + "GET_CODE (operands[2]) == CONST_INT + && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" + "andb %1,%0") + \f + ;; inclusive-or instructions + + (define_insn "iorsi3" + [(set (match_operand:SI 0 "general_operand" "=m,d") + (ior:SI (match_operand:SI 1 "general_operand" "%0,0") + (match_operand:SI 2 "general_operand" "dKs,dmKs")))] + "" + "* + { + register int logval; + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) >> 16 == 0 + && (DATA_REG_P (operands[0]) + || offsetable_memref_p (operands[0]))) + { + if (GET_CODE (operands[0]) != REG) + operands[0] = adj_offsetable_operand (operands[0], 2); + /* Do not delete a following tstl %0 insn; that would be incorrect. */ + CC_STATUS_INIT; + return \"orw %2,%0\"; + } + if (GET_CODE (operands[2]) == CONST_INT + && (logval = exact_log2 (INTVAL (operands[2]))) >= 0 + && (DATA_REG_P (operands[0]) + || offsetable_memref_p (operands[0]))) + { + if (DATA_REG_P (operands[0])) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, logval); + } + else + { + operands[0] = adj_offsetable_operand (operands[0], 3 - (logval / 8)); + operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8); + } + return \"bset %1,%0\"; + } + return \"orl %2,%0\"; + }") + + (define_insn "iorhi3" + [(set (match_operand:HI 0 "general_operand" "=m,d") + (ior:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "general_operand" "dn,dmn")))] + "" + "orw %2,%0") + + (define_insn "iorqi3" + [(set (match_operand:QI 0 "general_operand" "=m,d") + (ior:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "general_operand" "dn,dmn")))] + "" + "orb %2,%0") + \f + ;; xor instructions + + (define_insn "xorsi3" + [(set (match_operand:SI 0 "general_operand" "=do,m") + (xor:SI (match_operand:SI 1 "general_operand" "%0,0") + (match_operand:SI 2 "general_operand" "di,dKs")))] + "" + "* + { + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) >> 16 == 0 + && (offsetable_memref_p (operands[0]) || DATA_REG_P (operands[0]))) + { + if (! DATA_REG_P (operands[0])) + operands[0] = adj_offsetable_operand (operands[0], 2); + /* Do not delete a following tstl %0 insn; that would be incorrect. */ + CC_STATUS_INIT; + return \"eorw %2,%0\"; + } + return \"eorl %2,%0\"; + }") + + (define_insn "xorhi3" + [(set (match_operand:HI 0 "general_operand" "=dm") + (xor:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "dn")))] + "" + "eorw %2,%0") + + (define_insn "xorqi3" + [(set (match_operand:QI 0 "general_operand" "=dm") + (xor:QI (match_operand:QI 1 "general_operand" "%0") + (match_operand:QI 2 "general_operand" "dn")))] + "" + "eorb %2,%0") + \f + ;; negation instructions + + (define_insn "negsi2" + [(set (match_operand:SI 0 "general_operand" "=dm") + (neg:SI (match_operand:SI 1 "general_operand" "0")))] + "" + "negl %0") + + (define_insn "neghi2" + [(set (match_operand:HI 0 "general_operand" "=dm") + (neg:HI (match_operand:HI 1 "general_operand" "0")))] + "" + "negw %0") + + (define_insn "negqi2" + [(set (match_operand:QI 0 "general_operand" "=dm") + (neg:QI (match_operand:QI 1 "general_operand" "0")))] + "" + "negb %0") + + (define_expand "negsf2" + [(set (match_operand:SF 0 "general_operand" "") + (neg:SF (match_operand:SF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (neg:SF (match_operand:SF 1 "general_operand" "fdm")))] + "TARGET_68881" + "* + { + if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) + return \"fnegs %1,%0\"; + return \"fnegs %1,%0\"; + }") + + (define_expand "negdf2" + [(set (match_operand:DF 0 "general_operand" "") + (neg:DF (match_operand:DF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (neg:DF (match_operand:DF 1 "general_operand" "fm")))] + "TARGET_68881" + "* + { + if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) + return \"fnegd %1,%0\"; + return \"fnegd %1,%0\"; + }") + \f + ;; Absolute value instructions + + (define_expand "abssf2" + [(set (match_operand:SF 0 "general_operand" "") + (abs:SF (match_operand:SF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (abs:SF (match_operand:SF 1 "general_operand" "fdm")))] + "TARGET_68881" + "* + { + if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) + return \"fabss %1,%0\"; + return \"fabss %1,%0\"; + }") + + (define_expand "absdf2" + [(set (match_operand:DF 0 "general_operand" "") + (abs:DF (match_operand:DF 1 "general_operand" "")))] + "TARGET_68881" + "") + + (define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (abs:DF (match_operand:DF 1 "general_operand" "fm")))] + "TARGET_68881" + "* + { + if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) + return \"fabsd %1,%0\"; + return \"fabsd %1,%0\"; + }") + \f + ;; one complement instructions + + (define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "general_operand" "=dm") + (not:SI (match_operand:SI 1 "general_operand" "0")))] + "" + "notl %0") + + (define_insn "one_cmplhi2" + [(set (match_operand:HI 0 "general_operand" "=dm") + (not:HI (match_operand:HI 1 "general_operand" "0")))] + "" + "notw %0") + + (define_insn "one_cmplqi2" + [(set (match_operand:QI 0 "general_operand" "=dm") + (not:QI (match_operand:QI 1 "general_operand" "0")))] + "" + "notb %0") + \f + ;; Optimized special case of shifting. + ;; Must precede the general case. + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (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" + "* + { + if (TARGET_68020) + return \"movb %1,%0\;extbl %0\"; + return \"movb %1,%0\;extw %0\;extl %0\"; + }") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (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" + "* + { + if (reg_mentioned_p (operands[0], operands[1])) + return \"movb %1,%0\;andl %#0xFF,%0\"; + return \"clrl %0\;movb %1,%0\"; + }") + + (define_insn "" + [(set (cc0) (minus (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; + return \"cmpb %0,%1\"; + ") + + (define_insn "" + [(set (cc0) (minus (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)" + "* + return \"cmpb %1,%0\"; + ") + + (define_insn "" + [(set (cc0) (minus (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; + return \"cmpb %0,%1\"; + ") + + (define_insn "" + [(set (cc0) (minus (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)" + "* + return \"cmpb %1,%0\"; + ") + \f + ;; arithmetic shift instructions + ;; We don't need the shift memory by 1 bit instruction + + (define_insn "ashlsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (ashift:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dI")))] + "" + "asll %2,%0") + + (define_insn "ashlhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (ashift:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dI")))] + "" + "aslw %2,%0") + + (define_insn "ashlqi3" + [(set (match_operand:QI 0 "general_operand" "=d") + (ashift:QI (match_operand:QI 1 "general_operand" "0") + (match_operand:QI 2 "general_operand" "dI")))] + "" + "aslb %2,%0") + + (define_insn "ashrsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dI")))] + "" + "asrl %2,%0") + + (define_insn "ashrhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dI")))] + "" + "asrw %2,%0") + + (define_insn "ashrqi3" + [(set (match_operand:QI 0 "general_operand" "=d") + (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") + (match_operand:QI 2 "general_operand" "dI")))] + "" + "asrb %2,%0") + \f + ;; logical shift instructions + + (define_insn "lshlsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (lshift:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dI")))] + "" + "lsll %2,%0") + + (define_insn "lshlhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (lshift:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dI")))] + "" + "lslw %2,%0") + + (define_insn "lshlqi3" + [(set (match_operand:QI 0 "general_operand" "=d") + (lshift:QI (match_operand:QI 1 "general_operand" "0") + (match_operand:QI 2 "general_operand" "dI")))] + "" + "lslb %2,%0") + + (define_insn "lshrsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dI")))] + "" + "lsrl %2,%0") + + (define_insn "lshrhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dI")))] + "" + "lsrw %2,%0") + + (define_insn "lshrqi3" + [(set (match_operand:QI 0 "general_operand" "=d") + (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") + (match_operand:QI 2 "general_operand" "dI")))] + "" + "lsrb %2,%0") + \f + ;; rotate instructions + + (define_insn "rotlsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (rotate:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dI")))] + "" + "roll %2,%0") + + (define_insn "rotlhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (rotate:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dI")))] + "" + "rolw %2,%0") + + (define_insn "rotlqi3" + [(set (match_operand:QI 0 "general_operand" "=d") + (rotate:QI (match_operand:QI 1 "general_operand" "0") + (match_operand:QI 2 "general_operand" "dI")))] + "" + "rolb %2,%0") + + (define_insn "rotrsi3" + [(set (match_operand:SI 0 "general_operand" "=d") + (rotatert:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "dI")))] + "" + "rorl %2,%0") + + (define_insn "rotrhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (rotatert:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dI")))] + "" + "rorw %2,%0") + + (define_insn "rotrqi3" + [(set (match_operand:QI 0 "general_operand" "=d") + (rotatert:QI (match_operand:QI 1 "general_operand" "0") + (match_operand:QI 2 "general_operand" "dI")))] + "" + "rorb %2,%0") + \f + ;; 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. + + (define_insn "" + [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do") + (match_operand:SI 1 "immediate_operand" "i") + (match_operand:SI 2 "immediate_operand" "i")) + (match_operand:SI 3 "general_operand" "d"))] + "TARGET_68020 && 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 + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" + "* + { + if (REG_P (operands[0])) + { + if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32) + return \"bfins %3,[%c2,%c1]%0\"; + } + else + operands[0] + = adj_offsetable_operand (operands[0], INTVAL (operands[2]) / 8); + + if (GET_CODE (operands[3]) == MEM) + operands[3] = adj_offsetable_operand (operands[3], + (32 - INTVAL (operands[1])) / 8); + if (INTVAL (operands[1]) == 8) + return \"movb %3,%0\"; + return \"movw %3,%0\"; + }") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=&d") + (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do") + (match_operand:SI 2 "immediate_operand" "i") + (match_operand:SI 3 "immediate_operand" "i")))] + "TARGET_68020 && 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 + && (GET_CODE (operands[1]) == REG + || ! mode_dependent_address_p (XEXP (operands[1], 0)))" + "* + { + if (REG_P (operands[1])) + { + if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32) + return \"bfextu [%c3,%c2]%1,%0\"; + } + else + operands[1] + = adj_offsetable_operand (operands[1], INTVAL (operands[3]) / 8); + + output_asm_insn (\"clrl %0\", operands); + if (GET_CODE (operands[0]) == MEM) + operands[0] = adj_offsetable_operand (operands[0], + (32 - INTVAL (operands[1])) / 8); + if (INTVAL (operands[2]) == 8) + return \"movb %1,%0\"; + return \"movw %1,%0\"; + }") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do") + (match_operand:SI 2 "immediate_operand" "i") + (match_operand:SI 3 "immediate_operand" "i")))] + "TARGET_68020 && 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 + && (GET_CODE (operands[1]) == REG + || ! mode_dependent_address_p (XEXP (operands[1], 0)))" + "* + { + if (REG_P (operands[1])) + { + if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32) + return \"bfexts [%c3,%c2]%1,%0\"; + } + else + operands[1] + = adj_offsetable_operand (operands[1], INTVAL (operands[3]) / 8); + + if (INTVAL (operands[2]) == 8) + return \"movb %1,%0\;extbl %0\"; + return \"movw %1,%0\;extl %0\"; + }") + \f + ;; 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" + [(set (match_operand:SI 0 "general_operand" "=d,d") + (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d") + (match_operand:SI 2 "general_operand" "di,di") + (match_operand:SI 3 "general_operand" "di,di")))] + "TARGET_68020 && TARGET_BITFIELD" + "bfexts [%c3,%c2]%1,%0") + + (define_insn "extzv" + [(set (match_operand:SI 0 "general_operand" "=d,d") + (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d") + (match_operand:SI 2 "general_operand" "di,di") + (match_operand:SI 3 "general_operand" "di,di")))] + "TARGET_68020 && TARGET_BITFIELD" + "bfextu [%c3,%c2]%1,%0") + + (define_insn "" + [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") + (match_operand:SI 1 "general_operand" "di,di") + (match_operand:SI 2 "general_operand" "di,di")) + (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) + (match_operand 3 "immediate_operand" "i,i")))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[3]) == CONST_INT + && (INTVAL (operands[3]) == -1 + || (GET_CODE (operands[1]) == CONST_INT + && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))" + "bfchg [%c2,%c1]%0") + + (define_insn "" + [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") + (match_operand:SI 1 "general_operand" "di,di") + (match_operand:SI 2 "general_operand" "di,di")) + (const_int 0))] + "TARGET_68020 && TARGET_BITFIELD" + "bfclr [%c2,%c1]%0") + + (define_insn "" + [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") + (match_operand:SI 1 "general_operand" "di,di") + (match_operand:SI 2 "general_operand" "di,di")) + (const_int -1))] + "TARGET_68020 && TARGET_BITFIELD" + "bfset [%c2,%c1]%0") + + (define_insn "insv" + [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") + (match_operand:SI 1 "general_operand" "di,di") + (match_operand:SI 2 "general_operand" "di,di")) + (match_operand:SI 3 "general_operand" "d,d"))] + "TARGET_68020 && TARGET_BITFIELD" + "bfins %3,[%c2,%c1]%0") + + ;; Now recognize bit field insns that operate on registers + ;; (or at least were intended to do so). + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d") + (match_operand:SI 2 "general_operand" "di") + (match_operand:SI 3 "general_operand" "di")))] + "TARGET_68020 && TARGET_BITFIELD" + "bfexts [%c3,%c2]%1,%0") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d") + (match_operand:SI 2 "general_operand" "di") + (match_operand:SI 3 "general_operand" "di")))] + "TARGET_68020 && TARGET_BITFIELD" + "bfextu [%c3,%c2]%1,%0") + + (define_insn "" + [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + (const_int 0))] + "TARGET_68020 && TARGET_BITFIELD" + "bfclr [%c2,%c1]%0") + + (define_insn "" + [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + (const_int -1))] + "TARGET_68020 && TARGET_BITFIELD" + "bfset [%c2,%c1]%0") + + (define_insn "" + [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + (match_operand:SI 3 "general_operand" "d"))] + "TARGET_68020 && TARGET_BITFIELD" + "* + { + return \"bfins %3,[%c2,%c1]%0\"; + }") + \f + ;; Special patterns for optimizing bit-field instructions. + + (define_insn "" + [(set (cc0) + (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[1]) == CONST_INT" + "* + { + if (operands[1] == const1_rtx + && GET_CODE (operands[2]) == CONST_INT) + { + int width = GET_CODE (operands[0]) == REG ? 31 : 7; + return output_btst (operands, + gen_rtx (CONST_INT, VOIDmode, + width - INTVAL (operands[2])), + operands[0], + insn, 1000); + /* Pass 1000 as SIGNPOS argument so that btst will + not think we are testing the sign bit for an `and' + and assume that nonzero implies a negative result. */ + } + if (INTVAL (operands[1]) != 32) + cc_status.flags = CC_NOT_NEGATIVE; + return \"bftst [%c2,%c1]%0\"; + }") + + (define_insn "" + [(set (cc0) + (subreg:QI + (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + 0))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[1]) == CONST_INT" + "* + { + if (operands[1] == const1_rtx + && GET_CODE (operands[2]) == CONST_INT) + { + int width = GET_CODE (operands[0]) == REG ? 31 : 7; + return output_btst (operands, + gen_rtx (CONST_INT, VOIDmode, + width - INTVAL (operands[2])), + operands[0], + insn, 1000); + /* Pass 1000 as SIGNPOS argument so that btst will + not think we are testing the sign bit for an `and' + and assume that nonzero implies a negative result. */ + } + if (INTVAL (operands[1]) != 32) + cc_status.flags = CC_NOT_NEGATIVE; + return \"bftst [%c2,%c1]%0\"; + }") + + (define_insn "" + [(set (cc0) + (subreg:HI + (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + 0))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[1]) == CONST_INT" + "* + { + if (operands[1] == const1_rtx + && GET_CODE (operands[2]) == CONST_INT) + { + int width = GET_CODE (operands[0]) == REG ? 31 : 7; + return output_btst (operands, + gen_rtx (CONST_INT, VOIDmode, + width - INTVAL (operands[2])), + operands[0], + insn, 1000); + /* Pass 1000 as SIGNPOS argument so that btst will + not think we are testing the sign bit for an `and' + and assume that nonzero implies a negative result. */ + } + if (INTVAL (operands[1]) != 32) + cc_status.flags = CC_NOT_NEGATIVE; + return \"bftst [%c2,%c1]%0\"; + }") + + ;;; now handle the register cases + (define_insn "" + [(set (cc0) + (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[1]) == CONST_INT" + "* + { + if (operands[1] == const1_rtx + && GET_CODE (operands[2]) == CONST_INT) + { + int width = GET_CODE (operands[0]) == REG ? 31 : 7; + return output_btst (operands, + gen_rtx (CONST_INT, VOIDmode, + width - INTVAL (operands[2])), + operands[0], + insn, 1000); + /* Pass 1000 as SIGNPOS argument so that btst will + not think we are testing the sign bit for an `and' + and assume that nonzero implies a negative result. */ + } + if (INTVAL (operands[1]) != 32) + cc_status.flags = CC_NOT_NEGATIVE; + return \"bftst [%c2,%c1]%0\"; + }") + + (define_insn "" + [(set (cc0) + (subreg:QI + (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + 0))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[1]) == CONST_INT" + "* + { + if (operands[1] == const1_rtx + && GET_CODE (operands[2]) == CONST_INT) + { + int width = GET_CODE (operands[0]) == REG ? 31 : 7; + return output_btst (operands, + gen_rtx (CONST_INT, VOIDmode, + width - INTVAL (operands[2])), + operands[0], + insn, 1000); + /* Pass 1000 as SIGNPOS argument so that btst will + not think we are testing the sign bit for an `and' + and assume that nonzero implies a negative result. */ + } + if (INTVAL (operands[1]) != 32) + cc_status.flags = CC_NOT_NEGATIVE; + return \"bftst [%c2,%c1]%0\"; + }") + + (define_insn "" + [(set (cc0) + (subreg:HI + (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d") + (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 2 "general_operand" "di")) + 0))] + "TARGET_68020 && TARGET_BITFIELD + && GET_CODE (operands[1]) == CONST_INT" + "* + { + if (operands[1] == const1_rtx + && GET_CODE (operands[2]) == CONST_INT) + { + int width = GET_CODE (operands[0]) == REG ? 31 : 7; + return output_btst (operands, + gen_rtx (CONST_INT, VOIDmode, + width - INTVAL (operands[2])), + operands[0], + insn, 1000); + /* Pass 1000 as SIGNPOS argument so that btst will + not think we are testing the sign bit for an `and' + and assume that nonzero implies a negative result. */ + } + if (INTVAL (operands[1]) != 32) + cc_status.flags = CC_NOT_NEGATIVE; + return \"bftst [%c2,%c1]%0\"; + }") + \f + (define_insn "seq" + [(set (match_operand:QI 0 "general_operand" "=d") + (eq (cc0) (const_int 0)))] + "" + "* + cc_status = cc_prev_status; + OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\"); + ") + + (define_insn "sne" + [(set (match_operand:QI 0 "general_operand" "=d") + (ne (cc0) (const_int 0)))] + "" + "* + cc_status = cc_prev_status; + OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\"); + ") + + (define_insn "sgt" + [(set (match_operand:QI 0 "general_operand" "=d") + (gt (cc0) (const_int 0)))] + "" + "* + cc_status = cc_prev_status; + OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", \"andb %#0xc,%!\;sgt %0\"); + ") + + (define_insn "sgtu" + [(set (match_operand:QI 0 "general_operand" "=d") + (gtu (cc0) (const_int 0)))] + "" + "* cc_status = cc_prev_status; + return \"shi %0\"; ") + + (define_insn "slt" + [(set (match_operand:QI 0 "general_operand" "=d") + (lt (cc0) (const_int 0)))] + "" + "* cc_status = cc_prev_status; + OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ") + + (define_insn "sltu" + [(set (match_operand:QI 0 "general_operand" "=d") + (ltu (cc0) (const_int 0)))] + "" + "* cc_status = cc_prev_status; + return \"scs %0\"; ") + + (define_insn "sge" + [(set (match_operand:QI 0 "general_operand" "=d") + (ge (cc0) (const_int 0)))] + "" + "* cc_status = cc_prev_status; + OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ") + + (define_insn "sgeu" + [(set (match_operand:QI 0 "general_operand" "=d") + (geu (cc0) (const_int 0)))] + "" + "* cc_status = cc_prev_status; + return \"scc %0\"; ") + + (define_insn "sle" + [(set (match_operand:QI 0 "general_operand" "=d") + (le (cc0) (const_int 0)))] + "" + "* + cc_status = cc_prev_status; + OUTPUT_JUMP (\"sle %0\", \"fsle %0\", \"andb %#0xc,%!\;sle %0\"); + ") + + (define_insn "sleu" + [(set (match_operand:QI 0 "general_operand" "=d") + (leu (cc0) (const_int 0)))] + "" + "* cc_status = cc_prev_status; + return \"sls %0\"; ") + \f + ;; 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 (\"jeq %l0\", \"fbeq %l0\", \"jeq %l0\"); + }") + + (define_insn "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + { + OUTPUT_JUMP (\"jne %l0\", \"fbneq %l0\", \"jne %l0\"); + }") + + (define_insn "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + OUTPUT_JUMP (\"jgt %l0\", \"fbgt %l0\", \"andb %#0xc,%!\;jgt %l0\"); + ") + + (define_insn "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + return \"jhi %l0\"; + ") + + (define_insn "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + OUTPUT_JUMP (\"jlt %l0\", \"fblt %l0\", \"jmi %l0\"); + ") + + (define_insn "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + return \"jcs %l0\"; + ") + + (define_insn "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + OUTPUT_JUMP (\"jge %l0\", \"fbge %l0\", \"jpl %l0\"); + ") + + (define_insn "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + return \"jcc %l0\"; + ") + + (define_insn "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + OUTPUT_JUMP (\"jle %l0\", \"fble %l0\", \"andb %#0xc,%!\;jle %l0\"); + ") + + (define_insn "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + return \"jls %l0\"; + ") + \f + ;; Negated conditional jump instructions. + + (define_insn "" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + { + OUTPUT_JUMP (\"jne %l0\", \"fbneq %l0\", \"jne %l0\"); + }") + + (define_insn "" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + { + OUTPUT_JUMP (\"jeq %l0\", \"fbeq %l0\", \"jeq %l0\"); + }") + + (define_insn "" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + OUTPUT_JUMP (\"jle %l0\", \"fbngt %l0\", \"andb %#0xc,%!\;jle %l0\"); + ") + + (define_insn "" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + return \"jls %l0\"; + ") + + (define_insn "" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + OUTPUT_JUMP (\"jge %l0\", \"fbnlt %l0\", \"jpl %l0\"); + ") + + (define_insn "" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + return \"jcc %l0\"; + ") + + (define_insn "" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + OUTPUT_JUMP (\"jlt %l0\", \"fbnge %l0\", \"jmi %l0\"); + ") + + (define_insn "" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + return \"jcs %l0\"; + ") + + (define_insn "" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + OUTPUT_JUMP (\"jgt %l0\", \"fbnle %l0\", \"andb %#0xc,%!\;jgt %l0\"); + ") + + (define_insn "" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* + return \"jhi %l0\"; + ") + \f + ;; Subroutines of "casesi". + + (define_expand "casesi_1" + [(set (match_operand:SI 3 "general_operand" "") + (plus:SI (match_operand:SI 0 "general_operand" "") + ;; Note operand 1 has been negated! + (match_operand:SI 1 "immediate_operand" ""))) + (set (cc0) (minus (match_operand:SI 2 "general_operand" "") + (match_dup 3))) + (set (pc) (if_then_else (ltu (cc0) (const_int 0)) + (label_ref (match_operand 4 "" "")) (pc)))] + "" + "") + + (define_expand "casesi_2" + [(set (match_operand:SI 0 "" "") (mem:HI (match_operand:SI 1 "" ""))) + ;; The USE here is so that at least one jump-insn will refer to the label, + ;; to keep it alive in jump_optimize. + (parallel [(set (pc) + (plus:SI (pc) (match_dup 0))) + (use (label_ref (match_operand 2 "" "")))])] + "" + "") + + ;; Operand 0 is index (in bytes); operand 1 is minimum, operand 2 the maximum; + ;; operand 3 is CODE_LABEL for the table; + ;; operand 4 is the CODE_LABEL to go to if index out of range. + (define_expand "casesi" + ;; We don't use these for generating the RTL, but we must describe + ;; the operands here. + [(match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "immediate_operand" "") + (match_operand:SI 2 "general_operand" "") + (match_operand 3 "" "") + (match_operand 4 "" "")] + "" + " + { + rtx table_elt_addr; + rtx index_diff; + + operands[1] = negate_rtx (SImode, operands[1]); + index_diff = gen_reg_rtx (SImode); + /* Emit the first few insns. */ + emit_insn (gen_casesi_1 (operands[0], operands[1], operands[2], + index_diff, operands[4])); + /* Construct a memory address. This may emit some insns. */ + table_elt_addr + = memory_address_noforce + (HImode, + gen_rtx (PLUS, Pmode, + gen_rtx (MULT, Pmode, index_diff, + gen_rtx (CONST_INT, VOIDmode, 2)), + gen_rtx (LABEL_REF, VOIDmode, operands[3]))); + /* Emit the last few insns. */ + emit_insn (gen_casesi_2 (gen_reg_rtx (HImode), table_elt_addr, operands[3])); + DONE; + }") + + ;; Recognize one of the insns resulting from casesi_2. + (define_insn "" + [(set (pc) + (plus:SI (pc) (match_operand:HI 0 "general_operand" "r"))) + (use (label_ref (match_operand 1 "" "")))] + "" + "* + return \"jmp pc@(2:B)[%0:W:B]\"; + ") + \f + ;; Unconditional and other jump instructions + (define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "* + return \"jra %l0\"; + ") + + (define_insn "" + [(set (pc) + (if_then_else + (ne (minus (plus:HI (match_operand:HI 0 "general_operand" "g") + (const_int -1)) + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) + (const_int -1)))] + "" + "* + { + if (DATA_REG_P (operands[0])) + return \"dbra %0,%l1\"; + if (GET_CODE (operands[0]) == MEM) + { + return \"subqw %#1,%0\;jcc %l1\"; + } + return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\"; + }") + + (define_insn "" + [(set (pc) + (if_then_else + (ne (minus (plus:SI (match_operand:SI 0 "general_operand" "g") + (const_int -1)) + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* + { + if (DATA_REG_P (operands[0])) + return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\"; + if (GET_CODE (operands[0]) == MEM) + return \"subql %#1,%0\;jcc %l1\"; + return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\"; + }") + + ;; dbra patterns that use REG_NOTES info generated by strength_reduce. + + (define_insn "" + [(set (pc) + (if_then_else + (ge (plus:SI (match_operand:SI 0 "general_operand" "g") + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "find_reg_note (insn, REG_NONNEG, 0)" + "* + { + if (DATA_REG_P (operands[0])) + return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\"; + if (GET_CODE (operands[0]) == MEM) + return \"subql %#1,%0\;jcc %l1\"; + return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\"; + }") + + ;; Call subroutine with no return value. + (define_insn "call" + [(call (match_operand:QI 0 "general_operand" "o") + (match_operand:SI 1 "general_operand" "g"))] + ;; Operand 1 not really used on the m68000. + + "" + "* + { + rtx xoperands[2]; + int size = XINT(operands[1],0); + + if (size == 0) + return \"subl a0,a0\;jsr %0\;movl a6@(-4),a0\"; + else { + xoperands[1] = gen_rtx (CONST_INT, VOIDmode, size/4 ); + output_asm_insn (\"movl sp,a0\;movl %1,%-\", xoperands ); + return \"jsr %0\;movl a6@(-4),a0\;addqw #4,sp\"; + } + }") + + ;; 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" "o") + (match_operand:SI 2 "general_operand" "g")))] + ;; Operand 2 not really used on the m68000. + "" + "* + { + rtx xoperands[3]; + int size = XINT(operands[2],0); + + if (size == 0) + return \"subl a0,a0\;jsr %1\;movl a6@(-4),a0\"; + else { + xoperands[2] = gen_rtx (CONST_INT, VOIDmode, size/4 ); + output_asm_insn (\"movl sp,a0\;movl %2,%-\", xoperands ); + return \"jsr %1\;movl a6@(-4),a0\;addqw #4,sp\"; + } + }") + + (define_insn "return" + [(return)] + "0" + "ret 0") + \f + ;; 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" "ad"))] + "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" + "* + { + rtx xoperands[2]; + xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + output_asm_insn (\"movl %1,%s\", xoperands); + output_asm_insn (\"movl %1,%-\", operands); + return \"fmoved %+,%0\"; + } + ") + \f + + ;;- 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: diff -rc2N gcc-1.32/c-convert.c gcc-1.33/c-convert.c *** gcc-1.32/c-convert.c Fri Dec 9 16:00:46 1988 --- gcc-1.33/c-convert.c Fri Dec 30 16:07:45 1988 *************** *** 28,33 **** #include "tree.h" - /* Subroutines of `convert'. */ - /* Change of width--truncation and extension of integers or reals-- is represented with NOP_EXPR. Proper functioning of many things --- 28,31 ---- *************** *** 36,40 **** Conversion between integer and pointer is represented with CONVERT_EXPR. Converting integer to real uses FLOAT_EXPR ! and real to integer uses FIX_TRUNC_EXPR. */ static tree --- 34,49 ---- Conversion between integer and pointer is represented with CONVERT_EXPR. Converting integer to real uses FLOAT_EXPR ! and real to integer uses FIX_TRUNC_EXPR. ! ! Here is a list of all the functions that assume that widening and ! narrowing is always done with a NOP_EXPR: ! In c-convert.c, convert_to_integer. ! In c-typeck.c, build_binary_op_nodefault (boolean ops), ! and truthvalue_conversion. ! In expr.c: expand_expr, for operands of a MULT_EXPR. ! In fold-const.c: fold. ! In tree.c: get_narrower and get_unwidened. */ ! \f ! /* Subroutines of `convert'. */ static tree *************** *** 72,75 **** --- 81,111 ---- } + static tree + convert_to_real (type, expr) + tree type, expr; + { + register enum tree_code form = TREE_CODE (TREE_TYPE (expr)); + extern int flag_float_store; + + if (form == REAL_TYPE) + return build (flag_float_store ? CONVERT_EXPR : NOP_EXPR, + type, expr); + + if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) + return build (FLOAT_EXPR, type, expr); + + if (form == POINTER_TYPE) + error ("pointer value used where a float was expected"); + else + error ("aggregate value used where a float was expected"); + + { + register tree tem = make_node (REAL_CST); + TREE_TYPE (tem) = type; + TREE_REAL_CST (tem) = 0; + return tem; + } + } + \f /* The result of this is always supposed to be a newly created tree node not in use in any existing structure. */ *************** *** 293,323 **** register tree tem = build_int_2 (0, 0); TREE_TYPE (tem) = type; - return tem; - } - } - - static tree - convert_to_real (type, expr) - tree type, expr; - { - register enum tree_code form = TREE_CODE (TREE_TYPE (expr)); - extern int flag_float_store; - - if (form == REAL_TYPE) - return build (flag_float_store ? CONVERT_EXPR : NOP_EXPR, - type, expr); - - if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) - return build (FLOAT_EXPR, type, expr); - - if (form == POINTER_TYPE) - error ("pointer value used where a float was expected"); - else - error ("aggregate value used where a float was expected"); - - { - register tree tem = make_node (REAL_CST); - TREE_TYPE (tem) = type; - TREE_REAL_CST (tem) = 0; return tem; } --- 329,332 ---- diff -rc2N gcc-1.32/c-decl.c gcc-1.33/c-decl.c *** gcc-1.32/c-decl.c Tue Dec 20 18:48:35 1988 --- gcc-1.33/c-decl.c Fri Jan 27 23:37:33 1989 *************** *** 215,218 **** --- 215,223 ---- int warn_write_strings; + /* Nonzero means warn about pointer casts that can drop a type qualifier + from the pointer target type. */ + + int warn_cast_qual; + /* Nonzero means `$' can be in an identifier. See cccp.c for reasons why this breaks some obscure ANSI C programs. */ *************** *** 260,263 **** --- 265,270 ---- else if (!strcmp (p, "-Wwrite-strings")) warn_write_strings = 1; + else if (!strcmp (p, "-Wcast-qual")) + warn_cast_qual = 1; else if (!strcmp (p, "-Wcomment")) ; /* cpp handles this one. */ *************** *** 637,648 **** && DECL_INITIAL (old) == 0 && DECL_INITIAL (new) == 0) { ! /* It's a parm type mismatch ! between a prototype and a non-prototype *declaration*. ! This is always due to an argument type ! that doesn't self-promote. */ ! error ("an argument type that has a default promotion"); ! error ("can't match an empty parameter list declaration"); } ! error_with_decl (old, "here is the previous declaration of `%s'"); } else --- 644,673 ---- && DECL_INITIAL (old) == 0 && DECL_INITIAL (new) == 0) { ! /* Classify the problem. */ ! register tree t = TYPE_ARG_TYPES (TREE_TYPE (old)); ! if (t == 0) ! t = TYPE_ARG_TYPES (TREE_TYPE (new)); ! for (; t; t = TREE_CHAIN (t)) ! { ! register tree type = TREE_VALUE (t); ! ! if (TREE_CHAIN (t) == 0 && type != void_type_node) ! { ! error ("A parameter list with an ellipsis can't match"); ! error ("an empty parameter name list declaration."); ! break; ! } ! ! if (type == float_type_node ! || (TREE_CODE (type) == INTEGER_TYPE ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) ! { ! error ("An argument type that has a default promotion"); ! error ("can't match an empty parameter name list declaration."); ! break; ! } ! } } ! error_with_decl (old, "previous declaration of `%s'"); } else *************** *** 894,898 **** if (oldlocal == 0 && IDENTIFIER_GLOBAL_VALUE (name) == 0 ! && TREE_EXTERNAL (x)) { TREE_PUBLIC (name) = 1; --- 919,924 ---- if (oldlocal == 0 && IDENTIFIER_GLOBAL_VALUE (name) == 0 ! && TREE_EXTERNAL (x) ! && TREE_PUBLIC (x)) { TREE_PUBLIC (name) = 1; *************** *** 1420,1423 **** --- 1446,1450 ---- builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS); builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS); + builtin_function ("__builtin_saveregs", default_function_type, BUILT_IN_SAVEREGS); #if 0 /* Support for these has not been written in either expand_builtin *************** *** 1452,1456 **** TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; ! make_function_rtl (decl); pushdecl (decl); DECL_SET_FUNCTION_CODE (decl, function_code); --- 1479,1483 ---- TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; ! make_decl_rtl (decl, 0, 1); pushdecl (decl); DECL_SET_FUNCTION_CODE (decl, function_code); *************** *** 1598,1601 **** --- 1625,1641 ---- tem = pushdecl (decl); + /* For a local variable, define the RTL now. */ + if (current_binding_level != global_binding_level + /* But not if this is a duplicate decl + and we prefer the previous decl. */ + && DECL_RTL (decl) == 0) + { + if (TYPE_SIZE (TREE_TYPE (decl)) != 0) + expand_decl (decl, NULL_TREE); + else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && DECL_INITIAL (decl) != 0) + expand_decl (decl, NULL_TREE); + } + if (init_written) { *************** *** 1620,1623 **** --- 1660,1664 ---- { register tree type = TREE_TYPE (decl); + int was_incomplete = (DECL_SIZE (decl) == 0); /* If `start_decl' didn't like having an initialization, ignore it now. */ *************** *** 1719,1726 **** current_binding_level == global_binding_level, 0); ! if (TYPE_SIZE (TREE_TYPE (decl)) != 0 ! || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) ! if (current_binding_level != global_binding_level) ! expand_decl (decl, NULL_TREE); } --- 1760,1780 ---- current_binding_level == global_binding_level, 0); ! if (current_binding_level != global_binding_level) ! { ! /* Recompute the RTL of a local array now ! if it used to be an incomplete type. */ ! if (was_incomplete ! && ! TREE_STATIC (decl) && ! TREE_EXTERNAL (decl)) ! { ! /* If we used it already as memory, it must stay in memory. */ ! TREE_ADDRESSABLE (decl) = TREE_USED (decl); ! /* If it's still incomplete now, no init will save it. */ ! if (DECL_SIZE (decl) == 0) ! DECL_INITIAL (decl) = 0; ! expand_decl (decl, NULL_TREE); ! } ! /* Compute and store the initial value. */ ! expand_decl_init (decl); ! } } *************** *** 2079,2084 **** if (specbits & (1 << (int) RID_AUTO)) error ("top-level declaration of `%s' specifies `auto'", name); - if (specbits & (1 << (int) RID_REGISTER)) - error ("top-level declaration of `%s' specifies `register'", name); } } --- 2133,2136 ---- *************** *** 2143,2146 **** --- 2195,2203 ---- if (size) { + /* might be a cast */ + if (TREE_CODE (size) == NOP_EXPR + && TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0))) + size = TREE_OPERAND (size, 0); + if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE) *************** *** 2188,2196 **** continue; ! /* Is this an error? Should they be merged into TYPE here? */ ! if (constp || volatilep) warning ("function declared to return const or volatile result"); - constp = 0; - volatilep = 0; /* Warn about some types functions can't return. */ --- 2245,2250 ---- continue; ! if (pedantic && (constp || volatilep)) warning ("function declared to return const or volatile result"); /* Warn about some types functions can't return. */ *************** *** 2436,2439 **** --- 2490,2494 ---- { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; + TREE_PUBLIC (decl) = TREE_EXTERNAL (decl); /* `extern' with initialization is invalid if not at top level. */ if ((specbits & (1 << (int) RID_EXTERN)) && initialized) *************** *** 2518,2555 **** for (parm = last_function_parms, typelt = first_parm; parm; ! parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt)) ! { ! /* Barf if the parameter itself has an incomplete type. */ ! tree type = TREE_VALUE (typelt); ! if (TYPE_SIZE (type) == 0) ! { ! TREE_VALUE (typelt) = error_mark_node; ! if (parm != 0 && DECL_NAME (parm) != 0) ! error ("parameter `%s' has incomplete type", ! IDENTIFIER_POINTER (DECL_NAME (parm))); ! else ! error ("parameter has incomplete type"); ! if (parm != 0) ! TREE_TYPE (parm) = error_mark_node; ! } ! else ! { ! /* Now warn if is a pointer to an incomplete type. */ ! while (TREE_CODE (type) == POINTER_TYPE ! || TREE_CODE (type) == REFERENCE_TYPE) ! type = TREE_TYPE (type); ! if (TYPE_SIZE (type) == 0) ! { ! TREE_VALUE (typelt) = error_mark_node; ! if (parm != 0 && DECL_NAME (parm) != 0) ! warning ("parameter `%s' points to incomplete type", ! IDENTIFIER_POINTER (DECL_NAME (parm))); ! else ! warning ("parameter points to incomplete type"); ! if (parm != 0) ! TREE_TYPE (parm) = error_mark_node; ! } ! } ! } return first_parm; --- 2573,2613 ---- for (parm = last_function_parms, typelt = first_parm; parm; ! parm = TREE_CHAIN (parm)) ! /* Skip over any enumeration constants declared here. */ ! if (TREE_CODE (parm) == PARM_DECL) ! { ! /* Barf if the parameter itself has an incomplete type. */ ! tree type = TREE_VALUE (typelt); ! if (TYPE_SIZE (type) == 0) ! { ! if (funcdef_flag && parm != 0 && DECL_NAME (parm) != 0) ! error ("parameter `%s' has incomplete type", ! IDENTIFIER_POINTER (DECL_NAME (parm))); ! else ! warning ("parameter has incomplete type"); ! if (funcdef_flag) ! { ! TREE_VALUE (typelt) = error_mark_node; ! if (parm != 0) ! TREE_TYPE (parm) = error_mark_node; ! } ! } ! else ! { ! /* Now warn if is a pointer to an incomplete type. */ ! while (TREE_CODE (type) == POINTER_TYPE ! || TREE_CODE (type) == REFERENCE_TYPE) ! type = TREE_TYPE (type); ! if (TYPE_SIZE (type) == 0) ! { ! if (parm != 0 && DECL_NAME (parm) != 0) ! warning ("parameter `%s' points to incomplete type", ! IDENTIFIER_POINTER (DECL_NAME (parm))); ! else ! warning ("parameter points to incomplete type"); ! } ! } ! typelt = TREE_CHAIN (typelt); ! } return first_parm; *************** *** 3194,3197 **** --- 3252,3256 ---- register tree next; + tree others = 0; if (parmdecls != 0) *************** *** 3199,3203 **** "parm types given both in parmlist and separately"); ! for (parm = nreverse (specparms); parm; parm = next) { next = TREE_CHAIN (parm); --- 3258,3263 ---- "parm types given both in parmlist and separately"); ! specparms = nreverse (specparms); ! for (parm = specparms; parm; parm = next) { next = TREE_CHAIN (parm); *************** *** 3206,3211 **** else if (TREE_TYPE (parm) == void_type_node) error_with_decl (parm, "parameter `%s' declared void"); ! else pushdecl (parm); } --- 3266,3277 ---- else if (TREE_TYPE (parm) == void_type_node) error_with_decl (parm, "parameter `%s' declared void"); ! else if (TREE_CODE (parm) == PARM_DECL) pushdecl (parm); + else + { + /* If we find an enum constant, put it aside for the moment. */ + TREE_CHAIN (parm) = 0; + others = chainon (others, parm); + } } *************** *** 3214,3217 **** --- 3280,3295 ---- DECL_ARGUMENTS (fndecl) = getdecls (); + /* Now pushdecl the enum constants. */ + for (parm = others; parm; parm = next) + { + next = TREE_CHAIN (parm); + if (DECL_NAME (parm) == 0) + ; + else if (TREE_TYPE (parm) == void_type_node) + ; + else if (TREE_CODE (parm) != PARM_DECL) + pushdecl (parm); + } + storetags (chainon (parmtags, gettags ())); } *************** *** 3423,3429 **** expand_function_end (input_filename, lineno); ! if (warn_return_type) ! /* So we can tell if jump_optimize sets it to 1. */ ! current_function_returns_null = 0; /* Run the optimizers and output the assembler code for this function. */ --- 3501,3506 ---- expand_function_end (input_filename, lineno); ! /* So we can tell if jump_optimize sets it to 1. */ ! current_function_returns_null = 0; /* Run the optimizers and output the assembler code for this function. */ *************** *** 3430,3435 **** rest_of_compilation (fndecl); ! if (warn_return_type && current_function_returns_null ! && TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node) /* If this function returns non-void and control can drop through, complain. */ --- 3507,3514 ---- rest_of_compilation (fndecl); ! if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) ! warning ("`volatile' function does return"); ! else if (warn_return_type && current_function_returns_null ! && TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node) /* If this function returns non-void and control can drop through, complain. */ diff -rc2N gcc-1.32/c-parse.y gcc-1.33/c-parse.y *** gcc-1.32/c-parse.y Wed Dec 7 13:56:14 1988 --- gcc-1.33/c-parse.y Mon Jan 9 18:43:12 1989 *************** *** 60,64 **** /* Cause the `yydebug' variable to be defined. */ ! #define YYDEBUG %} --- 60,64 ---- /* Cause the `yydebug' variable to be defined. */ ! #define YYDEBUG 1 %} *************** *** 126,130 **** %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist ! %type <ttype> expr_no_commas primary string STRING %type <ttype> typed_declspecs reserved_declspecs %type <ttype> typed_typespecs reserved_typespecquals --- 126,130 ---- %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist ! %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING %type <ttype> typed_declspecs reserved_declspecs %type <ttype> typed_typespecs reserved_typespecquals *************** *** 160,165 **** static void reinit_parse_for_function (); - extern double atof (); - /* List of types and structure classes of the current declaration */ tree current_declspecs; --- 160,163 ---- *************** *** 168,171 **** --- 166,171 ---- char *main_input_filename; /* top-level source file */ + int undeclared_variable_notice; /* 1 if we explained undeclared var errors. */ + static int yylex (); %} *************** *** 285,295 **** ; ! expr_no_commas: primary ! | '*' expr_no_commas %prec UNARY { $$ = build_indirect_ref ($2, "unary *"); } ! | unop expr_no_commas %prec UNARY { $$ = build_unary_op ($1, $2, 0); } ! | '(' typename ')' expr_no_commas %prec UNARY { tree type = groktypename ($2); $$ = build_c_cast (type, $4); } --- 285,313 ---- ; ! unary_expr: primary ! | '*' cast_expr %prec UNARY { $$ = build_indirect_ref ($2, "unary *"); } ! | unop cast_expr %prec UNARY { $$ = build_unary_op ($1, $2, 0); } ! | SIZEOF unary_expr %prec UNARY ! { if (TREE_CODE ($2) == COMPONENT_REF ! && TREE_PACKED (TREE_OPERAND ($2, 1))) ! error ("`sizeof' applied to a bit-field"); ! $$ = c_sizeof (TREE_TYPE ($2)); } ! | SIZEOF '(' typename ')' %prec HYPERUNARY ! { $$ = c_sizeof (groktypename ($3)); } ! | ALIGNOF unary_expr %prec UNARY ! { if (TREE_CODE ($2) == COMPONENT_REF ! && TREE_PACKED (TREE_OPERAND ($2, 1))) ! error ("`__alignof' applied to a bit-field"); ! $$ = c_alignof (TREE_TYPE ($2)); } ! | ALIGNOF '(' typename ')' %prec HYPERUNARY ! { $$ = c_alignof (groktypename ($3)); } ! ; ! ! cast_expr: ! unary_expr ! | '(' typename ')' cast_expr %prec UNARY { tree type = groktypename ($2); $$ = build_c_cast (type, $4); } *************** *** 297,301 **** { tree type = groktypename ($2); if (pedantic) ! warning ("ANSI C forbids constructor-expressions"); $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) --- 315,319 ---- { tree type = groktypename ($2); if (pedantic) ! warning ("ANSI C forbids constructor expressions"); $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) *************** *** 306,323 **** } } ! | SIZEOF expr_no_commas %prec UNARY ! { if (TREE_CODE ($2) == COMPONENT_REF ! && TREE_PACKED (TREE_OPERAND ($2, 1))) ! error ("sizeof applied to a bit-field"); ! $$ = c_sizeof (TREE_TYPE ($2)); } ! | SIZEOF '(' typename ')' %prec HYPERUNARY ! { $$ = c_sizeof (groktypename ($3)); } ! | ALIGNOF expr_no_commas %prec UNARY ! { if (TREE_CODE ($2) == COMPONENT_REF ! && TREE_PACKED (TREE_OPERAND ($2, 1))) ! error ("__alignof applied to a bit-field"); ! $$ = c_alignof (TREE_TYPE ($2)); } ! | ALIGNOF '(' typename ')' %prec HYPERUNARY ! { $$ = c_alignof (groktypename ($3)); } | expr_no_commas '+' expr_no_commas { $$ = build_binary_op ($2, $1, $3); } --- 324,331 ---- } } ! ; ! ! expr_no_commas: ! cast_expr | expr_no_commas '+' expr_no_commas { $$ = build_binary_op ($2, $1, $3); } *************** *** 359,363 **** IDENTIFIER { $$ = lastiddecl; ! if (!$$) { if (yychar == YYEMPTY) --- 367,371 ---- IDENTIFIER { $$ = lastiddecl; ! if (!$$ || $$ == error_mark_node) { if (yychar == YYEMPTY) *************** *** 369,380 **** TREE_USED ($$) = 1; } else { ! if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node) ! error ("undeclared variable `%s' (first use here)", ! IDENTIFIER_POINTER ($1)); $$ = error_mark_node; /* Prevent repeated error messages. */ IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node; } } --- 377,405 ---- TREE_USED ($$) = 1; } + else if (current_function_decl == 0) + { + error ("`%s' undeclared, outside of functions", + IDENTIFIER_POINTER ($1)); + $$ = error_mark_node; + } else { ! if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node ! || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl) ! { ! error ("`%s' undeclared (first use this function)", ! IDENTIFIER_POINTER ($1)); ! ! if (! undeclared_variable_notice) ! { ! error ("(Each undeclared identifier is reported only once"); ! error ("for each function it appears in.)"); ! undeclared_variable_notice = 1; ! } ! } $$ = error_mark_node; /* Prevent repeated error messages. */ IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node; + IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl; } } *************** *** 1544,1549 **** \f /* At the beginning of a line, increment the line number ! and handle a #line directive immediately following. ! Return first nonwhite char of first non-# line following. */ int --- 1569,1575 ---- \f /* At the beginning of a line, increment the line number ! and process any #-directive on this line. ! If the line is a #-directive, read the entire line and return a newline. ! Otherwise, return the line's first non-whitespace character. */ int *************** *** 1553,1724 **** register int token; ! while (1) ! { ! lineno++; ! /* Read first nonwhite char on the line. */ ! c = getc (finput); ! while (c == ' ' || c == '\t') ! c = getc (finput); ! if (c != '#') ! { ! /* If not #, return it so caller will use it. */ ! return c; ! } ! /* Read first nonwhite char after the `#'. */ ! c = getc (finput); ! while (c == ' ' || c == '\t') ! c = getc (finput); ! /* If a letter follows, then if the word here is `line', skip ! it and ignore it; otherwise, ignore the line, with an error ! if the word isn't `pragma'. */ ! if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) ! { ! if (c == 'p') ! { ! if (getc (finput) == 'r' ! && getc (finput) == 'a' ! && getc (finput) == 'g' ! && getc (finput) == 'm' ! && getc (finput) == 'a' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! goto noerror; ! } ! ! else if (c == 'l') ! { ! if (getc (finput) == 'i' ! && getc (finput) == 'n' ! && getc (finput) == 'e' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! goto linenum; ! } #ifdef IDENT_DIRECTIVE ! else if (c == 'i') ! { ! if (getc (finput) == 'd' ! && getc (finput) == 'e' ! && getc (finput) == 'n' ! && getc (finput) == 't' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! { ! extern FILE *asm_out_file; ! ! if (pedantic) ! error ("ANSI C does not allow #ident"); ! /* Here we have just seen `#ident '. ! A string constant should follow. */ ! while (c == ' ' || c == '\t') ! c = getc (finput); ! /* If no argument, ignore the line. */ ! if (c == '\n') ! continue; ! ungetc (c, finput); ! token = yylex (); ! if (token != STRING ! || TREE_CODE (yylval.ttype) != STRING_CST) ! { ! error ("invalid #ident"); ! return getc (finput); ! } #ifdef ASM_OUTPUT_IDENT ! ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype)); #else ! fprintf (asm_out_file, "\t.ident \"%s\"\n", ! TREE_STRING_POINTER (yylval.ttype)); #endif ! /* Skip the rest of this line. */ ! while ((c = getc (finput)) && c != '\n'); ! if (c == 0) ! return 0; ! continue; ! } ! } ! #endif ! ! error ("undefined or invalid # directive"); ! noerror: ! ! while ((c = getc (finput)) && c != '\n'); ! ! if (c == 0) ! return 0; ! continue; ! } ! linenum: ! /* Here we have either `#line' or `# <nonletter>'. ! In either case, it should be a line number; a digit should follow. */ while (c == ' ' || c == '\t') c = getc (finput); - - /* If the # is the only nonwhite char on the line, - just ignore it. Check the new newline. */ if (c == '\n') ! continue; ! /* Something follows the #; read a token. */ - ungetc (c, finput); token = yylex (); ! ! if (token == CONSTANT ! && TREE_CODE (yylval.ttype) == INTEGER_CST) { ! /* subtract one, because it is the following line that ! gets the specified number */ ! ! int l = TREE_INT_CST_LOW (yylval.ttype) - 1; ! ! /* Is this the last nonwhite stuff on the line? */ ! c = getc (finput); ! while (c == ' ' || c == '\t') ! c = getc (finput); ! if (c == '\n') ! { ! /* No more: store the line number and check following line. */ ! lineno = l; ! continue; ! } ! ungetc (c, finput); ! ! /* More follows: it must be a string constant (filename). */ ! ! token = yylex (); ! if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) ! { ! error ("invalid #line"); ! return getc (finput); ! } ! ! input_filename ! = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1); ! strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype)); ! lineno = l; ! ! if (main_input_filename == 0) ! main_input_filename = input_filename; } ! else ! error ("invalid #line"); ! ! /* skip the rest of this line. */ ! while ((c = getc (finput)) && c != '\n'); ! if (c == 0) ! return 0; } } \f --- 1579,1738 ---- register int token; ! lineno++; ! /* Read first nonwhite char on the line. */ ! c = getc (finput); ! while (c == ' ' || c == '\t') ! c = getc (finput); ! if (c != '#') ! { ! /* If not #, return it so caller will use it. */ ! return c; ! } ! /* Read first nonwhite char after the `#'. */ ! c = getc (finput); ! while (c == ' ' || c == '\t') ! c = getc (finput); ! /* If a letter follows, then if the word here is `line', skip ! it and ignore it; otherwise, ignore the line, with an error ! if the word isn't `pragma'. */ ! if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) ! { ! if (c == 'p') ! { ! if (getc (finput) == 'r' ! && getc (finput) == 'a' ! && getc (finput) == 'g' ! && getc (finput) == 'm' ! && getc (finput) == 'a' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! goto skipline; ! } ! ! else if (c == 'l') ! { ! if (getc (finput) == 'i' ! && getc (finput) == 'n' ! && getc (finput) == 'e' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! goto linenum; ! } #ifdef IDENT_DIRECTIVE ! else if (c == 'i') ! { ! if (getc (finput) == 'd' ! && getc (finput) == 'e' ! && getc (finput) == 'n' ! && getc (finput) == 't' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! { ! extern FILE *asm_out_file; ! ! if (pedantic) ! error ("ANSI C does not allow #ident"); ! /* Here we have just seen `#ident '. ! A string constant should follow. */ ! while (c == ' ' || c == '\t') ! c = getc (finput); ! /* If no argument, ignore the line. */ ! if (c == '\n') ! return c; ! ungetc (c, finput); ! token = yylex (); ! if (token != STRING ! || TREE_CODE (yylval.ttype) != STRING_CST) ! { ! error ("invalid #ident"); ! goto skipline; ! } #ifdef ASM_OUTPUT_IDENT ! ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype)); #else ! fprintf (asm_out_file, "\t.ident \"%s\"\n", ! TREE_STRING_POINTER (yylval.ttype)); #endif ! /* Skip the rest of this line. */ ! goto skipline; ! } ! } ! #endif ! ! error ("undefined or invalid # directive"); ! goto skipline; ! } ! ! linenum: ! /* Here we have either `#line' or `# <nonletter>'. ! In either case, it should be a line number; a digit should follow. */ ! ! while (c == ' ' || c == '\t') ! c = getc (finput); ! ! /* If the # is the only nonwhite char on the line, ! just ignore it. Check the new newline. */ ! if (c == '\n') ! return c; ! ! /* Something follows the #; read a token. */ ! ! ungetc (c, finput); ! token = yylex (); ! ! if (token == CONSTANT ! && TREE_CODE (yylval.ttype) == INTEGER_CST) ! { ! /* subtract one, because it is the following line that ! gets the specified number */ ! int l = TREE_INT_CST_LOW (yylval.ttype) - 1; + /* Is this the last nonwhite stuff on the line? */ + c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); if (c == '\n') ! { ! /* No more: store the line number and check following line. */ ! lineno = l; ! return c; ! } ! ungetc (c, finput); ! /* More follows: it must be a string constant (filename). */ token = yylex (); ! if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) { ! error ("invalid #line"); ! goto skipline; } ! ! input_filename ! = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1); ! strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype)); ! lineno = l; ! ! if (main_input_filename == 0) ! main_input_filename = input_filename; } + else + error ("invalid #line"); + + /* skip the rest of this line. */ + skipline: + while ((c = getc (finput)) && c != '\n'); + return c; } \f *************** *** 2139,2143 **** char f_seen = 0; char l_seen = 0; ! double value; /* Read explicit exponent if any, and put it in tokenbuf. */ --- 2153,2157 ---- char f_seen = 0; char l_seen = 0; ! REAL_VALUE_TYPE value; /* Read explicit exponent if any, and put it in tokenbuf. */ *************** *** 2167,2171 **** *p = 0; errno = 0; ! value = atof (token_buffer); #ifdef ERANGE if (errno == ERANGE && !flag_traditional) --- 2181,2185 ---- *p = 0; errno = 0; ! value = REAL_VALUE_ATOF (token_buffer); #ifdef ERANGE if (errno == ERANGE && !flag_traditional) diff -rc2N gcc-1.32/c-tree.h gcc-1.33/c-tree.h *** gcc-1.32/c-tree.h Sun Aug 28 16:19:24 1988 --- gcc-1.33/c-tree.h Wed Jan 4 03:24:50 1989 *************** *** 120,123 **** --- 120,128 ---- extern int warn_write_strings; + /* Nonzero means warn about pointer casts that can drop a type qualifier + from the pointer target type. */ + + extern int warn_cast_qual; + /* Nonzero means do some things the same way PCC does. */ diff -rc2N gcc-1.32/c-typeck.c gcc-1.33/c-typeck.c *** gcc-1.32/c-typeck.c Thu Dec 15 18:57:03 1988 --- gcc-1.33/c-typeck.c Sat Jan 28 20:37:00 1989 *************** *** 1,4 **** /* Build expressions with type checking for C compiler. ! Copyright (C) 1987, 1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Build expressions with type checking for C compiler. ! Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 37,41 **** ! static void mark_addressable (); static tree convert_for_assignment (); static int compparms (); --- 37,41 ---- ! static int mark_addressable (); static tree convert_for_assignment (); static int compparms (); *************** *** 617,620 **** --- 617,626 ---- exp = DECL_INITIAL (exp); + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs, since EXP is being used in non-lvalue context. */ + if (TREE_CODE (exp) == NOP_EXPR + && TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))) + exp = TREE_OPERAND (exp, 0); + if (form == ENUMERAL_TYPE || (form == INTEGER_TYPE *************** *** 641,646 **** { register tree adr; if (TREE_CODE (exp) == INDIRECT_REF) ! return convert (TYPE_POINTER_TO (TREE_TYPE (dt)), TREE_OPERAND (exp, 0)); --- 647,655 ---- { register tree adr; + tree restype = TREE_TYPE (dt); + tree ptrtype; + if (TREE_CODE (exp) == INDIRECT_REF) ! return convert (TYPE_POINTER_TO (restype), TREE_OPERAND (exp, 0)); *************** *** 659,662 **** --- 668,677 ---- } + if (TREE_READONLY (exp) || TREE_VOLATILE (exp)) + restype = build_type_variant (restype, TREE_READONLY (exp), + TREE_VOLATILE (exp)); + + ptrtype = build_pointer_type (restype); + if (TREE_CODE (exp) == VAR_DECL) { *************** *** 665,670 **** is not the target type of the type of the ADDR_EXPR itself. Question is, can this lossage be avoided? */ ! adr = build (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (dt)), exp); ! mark_addressable (exp); TREE_LITERAL (adr) = staticp (exp); TREE_VOLATILE (adr) = 0; /* Default would be, same as EXP. */ --- 680,686 ---- is not the target type of the type of the ADDR_EXPR itself. Question is, can this lossage be avoided? */ ! adr = build (ADDR_EXPR, ptrtype, exp); ! if (mark_addressable (exp) == 0) ! return error_mark_node; TREE_LITERAL (adr) = staticp (exp); TREE_VOLATILE (adr) = 0; /* Default would be, same as EXP. */ *************** *** 674,678 **** simplify the offset for a component. */ adr = build_unary_op (ADDR_EXPR, exp, 1); ! return convert (TYPE_POINTER_TO (TREE_TYPE (dt)), adr); } return exp; --- 690,694 ---- simplify the offset for a component. */ adr = build_unary_op (ADDR_EXPR, exp, 1); ! return convert (ptrtype, adr); } return exp; *************** *** 718,721 **** --- 734,739 ---- return error_mark_node; } + if (TREE_TYPE (field) == error_mark_node) + return error_mark_node; ref = build (COMPONENT_REF, TREE_TYPE (field), basename, field); *************** *** 806,810 **** if (TREE_CODE (index) != INTEGER_CST || TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST) ! mark_addressable (array); if (pedantic && !lvalue_p (array)) --- 824,831 ---- if (TREE_CODE (index) != INTEGER_CST || TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST) ! { ! if (mark_addressable (array) == 0) ! return error_mark_node; ! } if (pedantic && !lvalue_p (array)) *************** *** 811,814 **** --- 832,844 ---- warning ("ANSI C forbids subscripting non-lvalue array"); + if (pedantic) + { + tree foo = array; + while (TREE_CODE (foo) == COMPONENT_REF) + foo = TREE_OPERAND (foo, 0); + if (TREE_CODE (foo) == VAR_DECL && TREE_REGDECL (foo)) + warning ("ANSI C forbids subscripting non-lvalue array"); + } + rval = build (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)), array, index); /* Array ref is const/volatile if the array elements are. */ *************** *** 852,855 **** --- 882,891 ---- tree actualparameterlist (); + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */ + if (TREE_CODE (function) == NOP_EXPR + && TREE_TYPE (function) == TREE_TYPE (TREE_OPERAND (function, 0))) + function = TREE_OPERAND (function, 0); + /* Convert anything with function type to a pointer-to-function. */ if (TREE_CODE (function) == FUNCTION_DECL) *************** *** 952,955 **** --- 988,997 ---- } + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */ + if (TREE_CODE (val) == NOP_EXPR + && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0))) + val = TREE_OPERAND (val, 0); + if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE) *************** *** 2133,2137 **** if (TREE_CODE (arg) == ARRAY_REF) { ! mark_addressable (TREE_OPERAND (arg, 0)); return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); --- 2175,2180 ---- if (TREE_CODE (arg) == ARRAY_REF) { ! if (mark_addressable (TREE_OPERAND (arg, 0)) == 0) ! return error_mark_node; return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); *************** *** 2180,2184 **** argtype = build_pointer_type (argtype); ! mark_addressable (arg); { --- 2223,2228 ---- argtype = build_pointer_type (argtype); ! if (mark_addressable (arg) == 0) ! return error_mark_node; { *************** *** 2333,2338 **** tree expr; { ! register enum tree_code form = TREE_CODE (expr); if (form == EQ_EXPR && integer_zerop (TREE_OPERAND (expr, 1))) return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0); --- 2377,2390 ---- tree expr; { ! register enum tree_code form; ! ! /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. ! Strip such NOP_EXPRs, since EXPR is being used in non-lvalue context. */ ! if (TREE_CODE (expr) == NOP_EXPR ! && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) ! expr = TREE_OPERAND (expr, 0); + form = TREE_CODE (expr); + if (form == EQ_EXPR && integer_zerop (TREE_OPERAND (expr, 1))) return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0); *************** *** 2358,2361 **** --- 2410,2420 ---- return truthvalue_conversion (TREE_OPERAND (expr, 0)); + /* Distribute the conversion into the arms of a COND_EXPR. */ + if (form == COND_EXPR) + return build (COND_EXPR, TREE_TYPE (expr), + TREE_OPERAND (expr, 0), + truthvalue_conversion (TREE_OPERAND (expr, 1)), + truthvalue_conversion (TREE_OPERAND (expr, 2))); + /* Sign-extension and zero-extension has no effect. */ if (form == NOP_EXPR *************** *** 2437,2443 **** /* Mark EXP saying that we need to be able to take the ! address of it; it should not be allocated in a register. */ ! static void mark_addressable (exp) tree exp; --- 2496,2503 ---- /* Mark EXP saying that we need to be able to take the ! address of it; it should not be allocated in a register. ! Value is 1 if successful. */ ! static int mark_addressable (exp) tree exp; *************** *** 2458,2463 **** case RESULT_DECL: if (TREE_REGDECL (x) && !TREE_ADDRESSABLE (x)) ! warning ("address requested for `%s', which is declared `register'", ! IDENTIFIER_POINTER (DECL_NAME (x))); put_var_into_stack (x); --- 2518,2530 ---- case RESULT_DECL: if (TREE_REGDECL (x) && !TREE_ADDRESSABLE (x)) ! { ! if (DECL_CONTEXT (x) == 0) ! { ! error ("address of global register variable requested"); ! return 0; ! } ! warning ("address requested for `%s', which is declared `register'", ! IDENTIFIER_POINTER (DECL_NAME (x))); ! } put_var_into_stack (x); *************** *** 2468,2472 **** default: ! return; } } --- 2535,2539 ---- default: ! return 1; } } *************** *** 2660,2664 **** if (TREE_CHAIN (list) == 0) ! return TREE_VALUE (list); rest = build_compound_expr (TREE_CHAIN (list)); --- 2727,2739 ---- if (TREE_CHAIN (list) == 0) ! { ! /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. ! Strip such NOP_EXPRs, since LIST is used in non-lvalue context. */ ! if (TREE_CODE (list) == NOP_EXPR ! && TREE_TYPE (list) == TREE_TYPE (TREE_OPERAND (list, 0))) ! list = TREE_OPERAND (list, 0); ! ! return TREE_VALUE (list); ! } rest = build_compound_expr (TREE_CHAIN (list)); *************** *** 2677,2686 **** tree expr; { ! register tree value; if (type == error_mark_node) return error_mark_node; ! if (type == TREE_TYPE (expr)) { if (pedantic) --- 2752,2768 ---- tree expr; { ! register tree value = expr; if (type == error_mark_node) return error_mark_node; + type = TYPE_MAIN_VARIANT (type); ! /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. ! Strip such NOP_EXPRs, since VALUE is being used in non-lvalue context. */ ! if (TREE_CODE (value) == NOP_EXPR ! && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) ! value = TREE_OPERAND (value, 0); ! ! if (type == TREE_TYPE (value)) { if (pedantic) *************** *** 2690,2704 **** warning ("ANSI C forbids casting nonscalar to the same type"); } - return expr; } ! value = convert (TYPE_MAIN_VARIANT (type), default_conversion (expr)); ! /* As far as I know, it is not meaningful to cast something ! to a const or volatile type, because those are meaningful ! only for lvalues. ! But if it is meaningful, we must somehow return something ! whose TREE_READONLY or TREE_VOLATILE is set. ! That is not trivial because it is possible that VALUE == EXPR ! or is a shared constant. */ return value; } --- 2772,2807 ---- warning ("ANSI C forbids casting nonscalar to the same type"); } } + else + { + tree otype; + value = default_conversion (value); + otype = TREE_TYPE (value); ! /* Optionally warn about potentially worrysome casts. */ ! ! if (warn_cast_qual ! && TREE_CODE (type) == POINTER_TYPE ! && TREE_CODE (otype) == POINTER_TYPE) ! { ! if (TREE_VOLATILE (TREE_TYPE (otype)) ! && ! TREE_VOLATILE (TREE_TYPE (type))) ! warning ("cast discards `volatile' from pointer target type"); ! if (TREE_READONLY (TREE_TYPE (otype)) ! && ! TREE_READONLY (TREE_TYPE (type))) ! warning ("cast discards `const' from pointer target type"); ! } ! ! value = convert (type, value); ! } ! ! if (value == expr) ! { ! /* Always produce some operator for an explicit cast, ! so we can tell (for -pedantic) that the cast is no lvalue. */ ! tree nvalue = build (NOP_EXPR, type, value); ! TREE_LITERAL (nvalue) = TREE_LITERAL (value); ! return nvalue; ! } return value; } *************** *** 2715,2719 **** { register tree result; ! tree newrhs = rhs; tree lhstype = TREE_TYPE (lhs); tree olhstype = lhstype; --- 2818,2822 ---- { register tree result; ! tree newrhs; tree lhstype = TREE_TYPE (lhs); tree olhstype = lhstype; *************** *** 2726,2729 **** --- 2829,2840 ---- return error_mark_node; + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs, since RHS is being used in non-lvalue context. */ + if (TREE_CODE (rhs) == NOP_EXPR + && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0))) + rhs = TREE_OPERAND (rhs, 0); + + newrhs = rhs; + /* Handle control structure constructs used as "lvalues". */ *************** *** 2741,2748 **** case COND_EXPR: rhs = save_expr (rhs); ! return (build_conditional_expr ! (TREE_OPERAND (lhs, 0), ! build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs), ! build_modify_expr (TREE_OPERAND (lhs, 2), modifycode, rhs))); } --- 2852,2870 ---- case COND_EXPR: rhs = save_expr (rhs); ! { ! /* Produce (a ? (b = rhs) : (c = rhs)) ! except that the RHS goes through a save-expr ! so the code to compute it is only emitted once. */ ! tree cond ! = build_conditional_expr ! (TREE_OPERAND (lhs, 0), ! build_modify_expr (TREE_OPERAND (lhs, 1), ! modifycode, rhs), ! build_modify_expr (TREE_OPERAND (lhs, 2), ! modifycode, rhs)); ! /* Make sure the code to compute the rhs comes out ! before the split. */ ! return build (COMPOUND_EXPR, TREE_TYPE (lhs), rhs, cond); ! } } *************** *** 2859,2867 **** { register enum tree_code codel = TREE_CODE (type); ! register tree rhstype = datatype (rhs); ! register enum tree_code coder = TREE_CODE (rhstype); ! if (coder == ERROR_MARK) ! return rhs; if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE --- 2981,2992 ---- { register enum tree_code codel = TREE_CODE (type); ! register tree rhstype; ! register enum tree_code coder; ! /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. ! Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */ ! if (TREE_CODE (rhs) == NOP_EXPR ! && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0))) ! rhs = TREE_OPERAND (rhs, 0); if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE *************** *** 2869,2872 **** --- 2994,3003 ---- rhs = default_conversion (rhs); + rhstype = TREE_TYPE (rhs); + coder = TREE_CODE (rhstype); + + if (coder == ERROR_MARK) + return rhs; + if (type == rhstype) return rhs; *************** *** 2961,2964 **** --- 3092,3100 ---- case CONVERT_EXPR: + case NOP_EXPR: + /* Allow conversions between types of the same kind. */ + if (TREE_CODE (TREE_TYPE (value)) + == TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0)))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0)); /* Allow (int) &foo. */ if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE *************** *** 2966,2972 **** return initializer_constant_valid_p (TREE_OPERAND (value, 0)); return 0; - - case NOP_EXPR: - return initializer_constant_valid_p (TREE_OPERAND (value, 0)); case PLUS_EXPR: --- 3102,3105 ---- *************** *** 3037,3041 **** warning ("aggregate initializer is not constant"); else if (! TREE_STATIC (value)) ! warning ("aggregate initializer uses complex arithmetic"); } } --- 3170,3174 ---- warning ("aggregate initializer is not constant"); else if (! TREE_STATIC (value)) ! warning ("aggregate initializer uses complicated arithmetic"); } } *************** *** 3394,3400 **** /* Copy all the intermediate outputs into the specified outputs. */ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) ! if (o[i] != TREE_VALUE (tail)) ! expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), ! 0, VOIDmode, 0); /* Those MODIFY_EXPRs could do autoincrements. */ --- 3527,3546 ---- /* Copy all the intermediate outputs into the specified outputs. */ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) ! { ! if (o[i] != TREE_VALUE (tail)) ! expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), ! 0, VOIDmode, 0); ! /* Detect modification of read-only values. ! (Otherwise done by build_modify_expr.) */ ! else ! { ! tree type = TREE_TYPE (o[i]); ! if (TREE_READONLY (o[i]) ! || ((TREE_CODE (type) == RECORD_TYPE ! || TREE_CODE (type) == UNION_TYPE) ! && C_TYPE_FIELDS_READONLY (type))) ! readonly_warning (o[i], "modification by `asm'"); ! } ! } /* Those MODIFY_EXPRs could do autoincrements. */ *************** *** 3411,3414 **** --- 3557,3563 ---- { tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + + if (TREE_THIS_VOLATILE (current_function_decl)) + warning ("function declared `volatile' has a `return' statement"); if (!retval) diff -rc2N gcc-1.32/cccp.c gcc-1.33/cccp.c *** gcc-1.32/cccp.c Sun Dec 11 13:04:19 1988 --- gcc-1.33/cccp.c Sun Jan 22 04:13:18 1989 *************** *** 130,133 **** --- 130,134 ---- #include <ctype.h> #include <stdio.h> + #include <signal.h> #ifndef VMS *************** *** 164,167 **** --- 165,169 ---- void bcopy (), bzero (); int bcmp (); + extern char *getenv (); extern char *version_string; *************** *** 316,321 **** #ifndef VMS { &include_defaults[1], GCC_INCLUDE_DIR }, ! { &include_defaults[2], "/usr/local/include" }, ! { 0, "/usr/include" } #else { &include_defaults[1], "GNU_CC_INCLUDE:" }, /* GNU includes */ --- 318,323 ---- #ifndef VMS { &include_defaults[1], GCC_INCLUDE_DIR }, ! { &include_defaults[2], "/usr/include" }, ! { 0, "/usr/local/include" } #else { &include_defaults[1], "GNU_CC_INCLUDE:" }, /* GNU includes */ *************** *** 568,571 **** --- 570,581 ---- int ignore_srcdir; \f + /* Handler for SIGPIPE. */ + + static void + pipe_closed () + { + fatal ("output pipe has been closed"); + } + int main (argc, argv) *************** *** 584,587 **** --- 594,605 ---- int no_standard_includes = 0; + /* Non-0 means don't output the preprocessed program. */ + int inhibit_output = 0; + + /* Stream on which to print the dependency information. */ + FILE *deps_stream = 0; + /* Target-name to write with the dependency information. */ + char *deps_target = 0; + #ifdef RLIMIT_STACK /* Get rid of any avoidable limit on stack size. */ *************** *** 615,618 **** --- 633,639 ---- #endif + signal (SIGPIPE, pipe_closed); + + #ifndef VMS max_include_len = max (max (sizeof (GCC_INCLUDE_DIR), *************** *** 619,622 **** --- 640,647 ---- sizeof (GPLUSPLUS_INCLUDE_DIR)), sizeof ("/usr/include/CC")); + #else /* VMS */ + max_include_len + = sizeof("SYS$SYSROOT:[SYSLIB.]"); + #endif /* VMS */ bzero (pend_files, argc * sizeof (char *)); *************** *** 684,693 **** else if (!strcmp (argv[i], "-MM")) print_deps = 1; ! deps_allocated_size = 200; ! deps_buffer = (char *) xmalloc (deps_allocated_size); ! deps_buffer[0] = 0; ! deps_size = 0; ! deps_column = 0; ! break; --- 709,713 ---- else if (!strcmp (argv[i], "-MM")) print_deps = 1; ! inhibit_output = 1; break; *************** *** 874,881 **** goto perror; /* For -M, print the expected object file name as the target of this Make-rule. */ if (print_deps) { ! if (*in_fname == 0) deps_output ("-: ", 0); else { --- 894,956 ---- goto perror; + /* Either of two environment variables can specify output of deps. + Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET", + where OUTPUT_FILE is the file to write deps info to + and DEPS_TARGET is the target to mention in the deps. */ + + if (print_deps == 0 + && (getenv ("SUNPRO_DEPENDENCIES") != 0 + || getenv ("DEPENDENCIES_OUTPUT") != 0)) + { + char *spec = getenv ("DEPENDENCIES_OUTPUT"); + char *s; + char *output_file; + + if (spec == 0) + { + spec = getenv ("SUNPRO_DEPENDENCIES"); + print_deps = 2; + } + else + print_deps = 1; + + s = spec; + /* Find the space before the DEPS_TARGET, if there is one. */ + /* Don't use `index'; that causes trouble on USG. */ + while (*s != 0 && *s != ' ') s++; + if (*s != 0) + { + deps_target = s + 1; + output_file = (char *) xmalloc (s - spec + 1); + bcopy (spec, output_file, s - spec); + output_file[s - spec] = 0; + } + else + { + deps_target = 0; + output_file = spec; + } + + deps_stream = fopen (output_file, "a"); + if (deps_stream == 0) + pfatal_with_name (output_file); + } + /* If the -M option was used, output the deps to standard output. */ + else if (print_deps) + deps_stream = stdout; + /* For -M, print the expected object file name as the target of this Make-rule. */ if (print_deps) { ! deps_allocated_size = 200; ! deps_buffer = (char *) xmalloc (deps_allocated_size); ! deps_buffer[0] = 0; ! deps_size = 0; ! deps_column = 0; ! ! if (deps_target) { ! deps_output (deps_target, 0); ! deps_output (":", 0); ! } else if (*in_fname == 0) deps_output ("-: ", 0); else { *************** *** 986,993 **** if (dump_macros) dump_all_macros (); ! else if (print_deps) ! puts (deps_buffer); ! else if (write (fileno (stdout), outbuf.buf, outbuf.bufp - outbuf.buf) < 0) ! fatal ("I/O error on output"); if (ferror (stdout)) --- 1061,1076 ---- if (dump_macros) dump_all_macros (); ! else if (print_deps) { ! fputs (deps_buffer, deps_stream); ! putc ('\n', deps_stream); ! if (deps_stream != stdout) { ! fclose (deps_stream); ! if (ferror (deps_stream)) ! fatal ("I/O error on output"); ! } ! } else if (! inhibit_output) { ! if (write (fileno (stdout), outbuf.buf, outbuf.bufp - outbuf.buf) < 0) ! fatal ("I/O error on output"); ! } if (ferror (stdout)) diff -rc2N gcc-1.32/combine.c gcc-1.33/combine.c *** gcc-1.32/combine.c Tue Dec 20 15:41:01 1988 --- gcc-1.33/combine.c Sun Jan 29 17:06:11 1989 *************** *** 143,147 **** /* Record one modification to rtl structure ! to be undone by storing old_contents into *where. */ struct undo --- 143,148 ---- /* Record one modification to rtl structure ! to be undone by storing old_contents into *where. ! is_int is 1 if the contents are an int. */ struct undo *************** *** 149,152 **** --- 150,154 ---- rtx *where; rtx old_contents; + int is_int; }; *************** *** 155,158 **** --- 157,161 ---- int *where; int old_contents; + int is_int; }; *************** *** 192,196 **** static void remove_links (); static void add_incs (); - static int insn_has_inc_p (); static int adjacent_insns_p (); static int check_asm_operands (); --- 195,198 ---- *************** *** 715,719 **** { for (i = undobuf.num_undo - 1; i >= 1; i--) ! *undobuf.undo[i].where = copy_rtx (*undobuf.undo[i].where); } } --- 717,722 ---- { for (i = undobuf.num_undo - 1; i >= 1; i--) ! if (! undobuf.undo[i].is_int) ! *undobuf.undo[i].where = copy_rtx (*undobuf.undo[i].where); } } *************** *** 747,750 **** --- 750,754 ---- undobuf.undo[undobuf.num_undo].where = &INTO; \ undobuf.undo[undobuf.num_undo].old_contents = INTO; \ + undobuf.undo[undobuf.num_undo].is_int = 0; \ INTO = NEWVAL; \ } \ *************** *** 757,760 **** --- 761,765 ---- u->where = &INTO; \ u->old_contents = INTO; \ + u->is_int = 1; \ INTO = NEWVAL; \ } \ *************** *** 880,883 **** --- 885,895 ---- && GET_CODE (to) == MEM) { + int endian_offset = 0; + #ifdef BYTES_BIG_ENDIAN + if (GET_MODE_SIZE (GET_MODE (x)) < UNITS_PER_WORD) + endian_offset += UNITS_PER_WORD - GET_MODE_SIZE (GET_MODE (x)); + if (GET_MODE_SIZE (GET_MODE (to)) < UNITS_PER_WORD) + endian_offset -= UNITS_PER_WORD - GET_MODE_SIZE (GET_MODE (to)); + #endif if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); *************** *** 886,890 **** return gen_rtx (MEM, GET_MODE (x), plus_constant (XEXP (to, 0), ! SUBREG_WORD (x) * UNITS_PER_WORD)); } break; --- 898,903 ---- return gen_rtx (MEM, GET_MODE (x), plus_constant (XEXP (to, 0), ! (SUBREG_WORD (x) * UNITS_PER_WORD ! + endian_offset))); } break; *************** *** 1033,1055 **** break; - case MINUS: - /* Can simplify (minus:VOIDmode (zero/sign_extend FOO) CONST) - (which is a compare instruction, not a subtract instruction) - to (minus FOO CONST) if CONST fits in FOO's mode - and we are only testing equality. - In fact, this is valid for zero_extend if what follows is an - unsigned comparison, and for sign_extend with a signed comparison. */ - if (GET_MODE (x) == VOIDmode - && was_replaced[0] - && (GET_CODE (to) == ZERO_EXTEND || GET_CODE (to) == SIGN_EXTEND) - && next_insn_tests_no_inequality (subst_insn) - && GET_CODE (XEXP (x, 1)) == CONST_INT - /* This is overly cautious by one bit, but saves worrying about - whether it is zero-extension or sign extension. */ - && ((unsigned) INTVAL (XEXP (x, 1)) - < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (to, 0))) - 1)))) - SUBST (XEXP (x, 0), XEXP (to, 0)); - break; - case EQ: case NE: --- 1046,1049 ---- *************** *** 1322,1325 **** --- 1316,1336 ---- : 0)))); } + /* Can simplify (set (cc0) (minus:VOIDmode (zero/sign_extend FOO) CONST)) + to (set (cc0) (minus:VOIDmode FOO CONST)) if CONST fits in FOO's mode + and we are only testing equality. + In fact, this is valid for zero_extend if what follows is an + unsigned comparison, and for sign_extend with a signed comparison. */ + if (SET_DEST (x) == cc0_rtx + && GET_CODE (SET_SRC (x)) == MINUS + && GET_MODE (SET_SRC (x)) == VOIDmode + && (GET_CODE (XEXP (SET_SRC (x), 0)) == ZERO_EXTEND + || GET_CODE (XEXP (SET_SRC (x), 0)) == SIGN_EXTEND) + && next_insn_tests_no_inequality (subst_insn) + && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT + /* This is overly cautious by one bit, but saves worrying about + whether it is zero-extension or sign extension. */ + && ((unsigned) INTVAL (XEXP (SET_SRC (x), 1)) + < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (SET_SRC (x), 0), 0))) - 1)))) + SUBST (XEXP (SET_SRC (x), 0), XEXP (XEXP (SET_SRC (x), 0), 0)); break; diff -rc2N gcc-1.32/config.gcc gcc-1.33/config.gcc *** gcc-1.32/config.gcc Tue Dec 6 18:08:42 1988 --- gcc-1.33/config.gcc Tue Jan 31 21:55:26 1989 *************** *** 79,82 **** --- 79,87 ---- target_machine=tm-${machine}.h ;; + i386-sysv-gas | i386g) + cpu_type=i386 + configuration_file=xm-i386v.h + target_machine=tm-i386gas.h + ;; sun4 | sun-4) cpu_type=sparc *************** *** 89,92 **** --- 94,107 ---- target_machine=tm-sun3.h ;; + sun3-nfp | sun-3-nfp) + cpu_type=m68k + configuration_file=xm-m68k.h + target_machine=tm-sun3-nfp.h + ;; + sun3-fpa | sun-3-fpa) + cpu_type=m68k + configuration_file=xm-m68k.h + target_machine=tm-sun3-fpa.h + ;; sun2 | sun-2) cpu_type=m68k *************** *** 102,106 **** cpu_type=sparc configuration_file=xm-sunos4.h ! target_machine=tm-${cpu_type}.h ;; sun3-os4 | sun-3-os4) --- 117,121 ---- cpu_type=sparc configuration_file=xm-sunos4.h ! target_machine=tm-sparc.h ;; sun3-os4 | sun-3-os4) *************** *** 109,112 **** --- 124,137 ---- target_machine=tm-sun3.h ;; + sun3-nfp-os4 | sun-3-nfp-os4) + cpu_type=m68k + configuration_file=xm-sunos4.h + target_machine=tm-sun3-nfp.h + ;; + sun3-fpa-os4 | sun-3-fpa-os4) + cpu_type=m68k + configuration_file=xm-sunos4.h + target_machine=tm-sun3-fpa.h + ;; sun2-os4 |sun-2-os4) cpu_type=m68k *************** *** 148,151 **** --- 173,184 ---- cpu_type=m88k target_machine=tm-${cpu_type}.h + ;; + alliant) # Alliant FX/8 + ;; + convex-c1) # Convex C1 + cpu_type = convex + ;; + convex-c2) # Convex C2 + cpu_type = convex ;; # 370) diff -rc2N gcc-1.32/convex.md gcc-1.33/convex.md *** gcc-1.32/convex.md Wed Dec 31 19:00:00 1969 --- gcc-1.33/convex.md Mon Jan 23 02:53:07 1989 *************** *** 0 **** --- 1,1264 ---- + ;;- Machine description for GNU compiler + ;;- Convex Version + ;; Copyright (C) 1989 Free Software Foundation, Inc. + + ;; This file is part of GNU CC. + + ;; GNU CC is distributed in the hope that it will be useful, + ;; but WITHOUT ANY WARRANTY. No author or distributor + ;; accepts responsibility to anyone for the consequences of using it + ;; or for whether it serves any particular purpose or works at all, + ;; unless he says so in writing. Refer to the GNU CC General Public + ;; License for full details. + + ;; Everyone is granted permission to copy, modify and redistribute + ;; GNU CC, but only under the conditions described in the + ;; GNU CC General Public License. A copy of this license is + ;; supposed to have been given to you along with GNU CC so you + ;; can know your rights and responsibilities. It should be in a + ;; file named COPYING. Among other things, the copyright notice + ;; and this notice must be preserved on all copies. + + + ;;- Instruction patterns. When multiple patterns apply, + ;;- the first one in the file is chosen. + ;;- + ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. + ;;- + ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code + ;;- updates for most instructions. + + (define_insn "tstsi" + [(set (cc0) + (match_operand:SI 0 "register_operand" "r"))] + "" + "* return set_cmp (operands[0], const0_rtx, 'w');") + + (define_insn "tsthi" + [(set (cc0) + (match_operand:HI 0 "register_operand" "r"))] + "" + "* return set_cmp (operands[0], const0_rtx, 'h');") + + (define_expand "tstqi" + [(set (match_dup 1) + (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))) + (set (cc0) + (match_dup 1))] + "" + "operands[1] = gen_reg_rtx (SImode);") + + (define_expand "tstdi" + [(set (cc0) + (minus (match_operand:DI 0 "register_operand" "d") + (match_dup 1)))] + "" + " + { + operands[1] = gen_rtx (CONST_DOUBLE, DImode); + CONST_DOUBLE_MEM (operands[1]) = cc0_rtx; + CONST_DOUBLE_HIGH (operands[1]) = 0; + CONST_DOUBLE_LOW (operands[1]) = 0; + operands[1] = force_reg (DImode, operands[1]); + }") + + (define_expand "tstdf" + [(set (cc0) + (minus (match_operand:DF 0 "register_operand" "d") + (match_dup 1)))] + "" + "operands[1] = force_reg (DFmode, dconst0_rtx);") + + (define_insn "tstsf" + [(set (cc0) + (match_operand:SF 0 "register_operand" "d"))] + "" + "* return set_cmp (operands[0], fconst0_rtx, 's');") + + (define_insn "cmpdi" + [(set (cc0) + (minus (match_operand:DI 0 "register_operand" "d") + (match_operand:DI 1 "register_operand" "d")))] + "" + "* return set_cmp (operands[0], operands[1], 'l');") + + (define_insn "cmpsi" + [(set (cc0) + (minus (match_operand:SI 0 "nonmemory_operand" "d,a,i,r") + (match_operand:SI 1 "nonmemory_operand" "d,a,r,i")))] + "" + "* return set_cmp (operands[0], operands[1], 'w');") + + (define_insn "cmphi" + [(set (cc0) + (minus (match_operand:HI 0 "nonmemory_operand" "d,a,r,i") + (match_operand:HI 1 "nonmemory_operand" "d,a,i,r")))] + "" + "* return set_cmp (operands[0], operands[1], 'h');") + + (define_insn "" + [(set (cc0) + (minus (sign_extend:SI (match_operand:QI 0 "register_operand" "d")) + (sign_extend:SI (match_operand:QI 1 "register_operand" "d"))))] + "" + "* return set_cmp (operands[0], operands[1], 'b');") + + (define_insn "cmpdf" + [(set (cc0) + (minus (match_operand:DF 0 "register_operand" "d") + (match_operand:DF 1 "register_operand" "d")))] + "" + "* return set_cmp (operands[0], operands[1], 'd');") + + (define_insn "cmpsf" + [(set (cc0) + (minus (match_operand:SF 0 "nonmemory_operand" "dF,d") + (match_operand:SF 1 "nonmemory_operand" "d,F")))] + "" + "* return set_cmp (operands[0], operands[1], 's');") + \f + (define_insn "movdf" + [(set (match_operand:DF 0 "general_operand" "=d,m<") + (match_operand:DF 1 "general_operand" "gG,d"))] + "" + "* + { + if (push_operand (operands[0], DFmode)) + return \"psh.l %1\"; + else if (which_alternative) + return \"st.l %1,%0\"; + else if (GET_CODE (operands[1]) == REG) + return \"mov %1,%0\"; + else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_D_P (operands[1])) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_LOW (operands[1])); + return \"ld.d %1,%0\"; + } + else + return \"ld.l %1,%0\"; + }") + + (define_insn "movsf" + [(set (match_operand:SF 0 "general_operand" "=d,m") + (match_operand:SF 1 "general_operand" "gF,d"))] + "" + "* + { + if (which_alternative) + return \"st.s %1,%0\"; + else if (GET_CODE (operands[1]) == REG) + return \"mov.s %1,%0\"; + else + return \"ld.s %1,%0\"; + }") + + (define_insn "movdi" + [(set (match_operand:DI 0 "general_operand" "=d,m<") + (match_operand:DI 1 "general_operand" "gG,d"))] + "" + "* + { + if (push_operand (operands[0], DImode)) + return \"psh.l %1\"; + else if (which_alternative) + return \"st.l %1,%0\"; + else if (GET_CODE (operands[1]) == REG) + return \"mov %1,%0\"; + else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_D_P (operands[1])) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_LOW (operands[1])); + return \"ld.d %1,%0\"; + } + else + return \"ld.l %1,%0\"; + }") + + (define_insn "movsi" + [(set (match_operand:SI 0 "general_operand" "=r,m,<") + (match_operand:SI 1 "general_operand" "g,r,i"))] + "" + "* + { + if (push_operand (operands[0], SImode)) + { + if (GET_CODE (operands[1]) == REG) + return \"psh.w %1\"; + else + return \"pshea %a1\"; + } + if (GET_CODE (operands[0]) == MEM) + return \"st.w %1,%0\"; + if (GET_CODE (operands[1]) != REG) + return \"ld.w %1,%0\"; + if (S_REGNO_P (REGNO (operands[0])) && S_REGNO_P (REGNO (operands[1]))) + return \"mov.w %1,%0\"; + return \"mov %1,%0\"; + }") + + (define_insn "movhi" + [(set (match_operand:HI 0 "general_operand" "=r,m") + (match_operand:HI 1 "general_operand" "g,r"))] + "" + "* + { + if (which_alternative) + return \"st.h %1,%0\"; + else if (GET_CODE (operands[1]) == REG) + { + if (S_REGNO_P (REGNO (operands[0])) && S_REGNO_P (REGNO (operands[1]))) + return \"mov.w %1,%0\"; + else + return \"mov %1,%0\"; + } + else if (GET_CODE (operands[1]) == CONST_INT) + return \"ld.w %1,%0\"; + else + return \"ld.h %1,%0\"; + }") + + (define_insn "movqi" + [(set (match_operand:QI 0 "general_operand" "=r,m") + (match_operand:QI 1 "general_operand" "g,r"))] + "" + "* + { + if (which_alternative) + return \"st.b %1,%0\"; + else if (GET_CODE (operands[1]) == REG) + { + if (S_REGNO_P (REGNO (operands[0])) && S_REGNO_P (REGNO (operands[1]))) + return \"mov.w %1,%0\"; + else + return \"mov %1,%0\"; + } + else if (GET_CODE (operands[1]) == CONST_INT) + return \"ld.w %1,%0\"; + else + return \"ld.b %1,%0\"; + }") + \f + ;;- push effective address + + (define_insn "" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:QI 1 "address_operand" "p"))] + "" + "pshea %a1") + + (define_insn "" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:HI 1 "address_operand" "p"))] + "" + "pshea %a1") + + (define_insn "" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:SI 1 "address_operand" "p"))] + "" + "pshea %a1") + + (define_insn "" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:SF 1 "address_operand" "p"))] + "" + "pshea %a1") + + (define_insn "" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:DF 1 "address_operand" "p"))] + "" + "pshea %a1") + \f + ;; Extension and truncation insns. + ;; Those for integer source operand + ;; are ordered widest source type first. + + (define_insn "truncsiqi2" + [(set (match_operand:QI 0 "register_operand" "=d,a") + (truncate:QI (match_operand:SI 1 "register_operand" "d,a")))] + "" + "cvtw.b %1,%0") + + (define_insn "truncsihi2" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (truncate:HI (match_operand:SI 1 "register_operand" "d,a")))] + "" + "cvtw.h %1,%0") + + (define_insn "trunchiqi2" + [(set (match_operand:QI 0 "register_operand" "=d,a") + (truncate:QI (match_operand:HI 1 "register_operand" "d,a")))] + "" + "cvth.b %1,%0") + + (define_insn "truncdisi2" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI (match_operand:DI 1 "register_operand" "d")))] + "" + "cvtl.w %1,%0") + + (define_insn "extendsidi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (sign_extend:DI (match_operand:SI 1 "register_operand" "d")))] + "" + "cvtw.l %1,%0") + + (define_insn "extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (sign_extend:SI (match_operand:HI 1 "register_operand" "d,a")))] + "" + "cvth.w %1,%0") + + (define_insn "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (sign_extend:HI (match_operand:QI 1 "register_operand" "d,a")))] + "" + "cvtb.w %1,%0") + + (define_insn "extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (sign_extend:SI (match_operand:QI 1 "register_operand" "d,a")))] + "" + "cvtb.w %1,%0") + + (define_insn "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=d") + (float_extend:DF (match_operand:SF 1 "register_operand" "d")))] + "" + "cvts.d %1,%0") + + (define_insn "truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=d") + (float_truncate:SF (match_operand:DF 1 "register_operand" "d")))] + "" + "cvtd.s %1,%0") + + (define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))] + "" + "and #0xffff,%0") + + (define_insn "zero_extendhidi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (zero_extend:DI (match_operand:HI 1 "register_operand" "0")))] + "" + "and #0xffff,%0") + + (define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r") + (zero_extend:HI (match_operand:QI 1 "register_operand" "0")))] + "" + "and #0xff,%0") + + (define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))] + "" + "and #0xff,%0") + + (define_insn "zero_extendqidi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (zero_extend:DI (match_operand:QI 1 "register_operand" "0")))] + "" + "and #0xff,%0") + + (define_insn "zero_extendsidi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (zero_extend:DI (match_operand:SI 1 "register_operand" "0")))] + "" + "ld.u #0,%0") + \f + ;; Fix-to-float conversion insns. + ;; Note that 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 "register_operand" "=d") + (float:SF (match_operand:SI 1 "register_operand" "d")))] + "" + "cvtw.s %1,%0") + + (define_insn "floatdisf2" + [(set (match_operand:SF 0 "register_operand" "=d") + (float:SF (match_operand:DI 1 "register_operand" "d")))] + "" + "cvtl.s %1,%0") + + (define_insn "floatsidf2" + [(set (match_operand:DF 0 "register_operand" "=d") + (float:DF (match_operand:SI 1 "register_operand" "d")))] + "TARGET_C2" + "cvtw.d %1,%0") + + (define_insn "floatdidf2" + [(set (match_operand:DF 0 "register_operand" "=d") + (float:DF (match_operand:DI 1 "register_operand" "d")))] + "" + "cvtl.d %1,%0") + \f + ;; Float-to-fix conversion insns. + + (define_insn "fix_truncsfsi2" + [(set (match_operand:SI 0 "register_operand" "=d") + (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "d"))))] + "" + "cvts.w %1,%0") + + (define_insn "fix_truncsfdi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "d"))))] + "" + "cvts.l %1,%0") + + (define_insn "fix_truncdfsi2" + [(set (match_operand:SI 0 "register_operand" "=d") + (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "d"))))] + "" + "* + { + if (TARGET_C2) + return \"cvtd.w %1,%0\"; + return \"cvtd.l %1,%0\"; + }") + + (define_insn "fix_truncdfdi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "d"))))] + "" + "cvtd.l %1,%0") + \f + ;;- All kinds of add instructions. + + (define_insn "adddf3" + [(set (match_operand:DF 0 "register_operand" "=d") + (plus:DF (match_operand:DF 1 "register_operand" "%0") + (match_operand:DF 2 "register_operand" "d")))] + "" + "add.d %2,%0") + + (define_insn "addsf3" + [(set (match_operand:SF 0 "register_operand" "=d") + (plus:SF (match_operand:SF 1 "register_operand" "%0") + (match_operand:SF 2 "nonmemory_operand" "dF")))] + "" + "add.s %2,%0") + + (define_insn "adddi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (plus:DI (match_operand:DI 1 "register_operand" "%0") + (match_operand:DI 2 "register_operand" "d")))] + "" + "add.l %2,%0") + + (define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a,r,a,a,a,a") + (plus:SI (match_operand:SI 1 "nonmemory_operand" "0,0,i,0,r,a,i") + (match_operand:SI 2 "nonmemory_operand" "di,ai,0,d,0,i,a")))] + "" + "* switch (which_alternative) + { + default: + return \"add.w %2,%0\"; + case 2: case 4: + return \"add.w %1,%0\"; + case 5: + return \"ldea %a2(%1),%0\"; + case 6: + return \"ldea %a1(%2),%0\"; + }") + + (define_insn "addhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (plus:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "add.h %2,%0") + + (define_insn "addqi3" + [(set (match_operand:QI 0 "register_operand" "=d") + (plus:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "register_operand" "d")))] + "" + "add.b %2,%0") + \f + ;;- All kinds of subtract instructions. + + (define_insn "subdf3" + [(set (match_operand:DF 0 "register_operand" "=d") + (minus:DF (match_operand:DF 1 "register_operand" "0") + (match_operand:DF 2 "register_operand" "d")))] + "" + "sub.d %2,%0") + + (define_insn "subsf3" + [(set (match_operand:SF 0 "register_operand" "=d") + (minus:SF (match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "nonmemory_operand" "dF")))] + "" + "sub.s %2,%0") + + (define_insn "subdi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (minus:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "register_operand" "d")))] + "" + "sub.l %2,%0") + + (define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (minus:SI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "sub.w %2,%0") + + (define_insn "subhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (minus:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "sub.h %2,%0") + + (define_insn "subqi3" + [(set (match_operand:QI 0 "register_operand" "=d") + (minus:QI (match_operand:QI 1 "register_operand" "0") + (match_operand:QI 2 "register_operand" "d")))] + "" + "sub.b %2,%0") + \f + ;;- Multiply instructions. + + (define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=d") + (mult:DF (match_operand:DF 1 "register_operand" "%0") + (match_operand:DF 2 "register_operand" "d")))] + "" + "mul.d %2,%0") + + (define_insn "mulsf3" + [(set (match_operand:SF 0 "register_operand" "=d") + (mult:SF (match_operand:SF 1 "register_operand" "%0") + (match_operand:SF 2 "nonmemory_operand" "dF")))] + "" + "mul.s %2,%0") + + (define_insn "muldi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (mult:DI (match_operand:DI 1 "register_operand" "%0") + (match_operand:DI 2 "register_operand" "d")))] + "" + "mul.l %2,%0") + + (define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (mult:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "mul.w %2,%0") + + (define_insn "mulhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (mult:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "mul.h %2,%0") + + (define_insn "mulqi3" + [(set (match_operand:QI 0 "register_operand" "=d") + (mult:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "register_operand" "d")))] + "" + "mul.b %2,%0") + \f + ;;- Divide instructions. + + (define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=d") + (div:DF (match_operand:DF 1 "register_operand" "0") + (match_operand:DF 2 "register_operand" "d")))] + "" + "div.d %2,%0") + + (define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=d") + (div:SF (match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "nonmemory_operand" "dF")))] + "" + "div.s %2,%0") + + (define_insn "divdi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (div:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "register_operand" "d")))] + "" + "div.l %2,%0") + + (define_insn "udivdi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (udiv:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "d")))] + "" + "psh.l %2\;psh.l %1\;callq udiv64\;pop.l %0\;add.w #8,sp") + + ;; do not define this, it causes all unsigned mods to promote to DI + ;; (at least, don't define it without also defining umodsi3) + + ;(define_insn "umoddi3" + ; [(set (match_operand:DI 0 "register_operand" "=d") + ; (umod:DI (match_operand:DI 1 "register_operand" "d") + ; (match_operand:DI 2 "register_operand" "d")))] + ; "" + ; "psh.l %2\;psh.l %1\;callq urem64\;pop.l %0\;add.w #8,sp") + + (define_insn "divsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (div:SI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "div.w %2,%0") + + ; unfortunately, udivsi3 must be defined if udivdi3 is, otherwise + ; every unsigned divide promotes to unsigned DI + + (define_insn "udivsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (udiv:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "+d")))] + "" + "ld.u #0,%2\;ld.u #0,%0\;div.l %2,%0") + + (define_insn "divhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (div:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "div.h %2,%0") + + (define_expand "udivhi3" + [(set (subreg:SI (match_operand:HI 0 "register_operand" "=d") 0) + (zero_extend:SI (match_operand:HI 1 "register_operand" "d"))) + (set (match_dup 3) + (zero_extend:SI (match_operand:HI 2 "register_operand" "d"))) + (set (subreg:SI (match_operand:HI 0 "register_operand" "=d") 0) + (div:SI (subreg:SI (match_operand:HI 0 "register_operand" "=d") 0) + (match_dup 3)))] + "" + " + { + operands[3] = gen_reg_rtx (SImode); + }") + + (define_insn "divqi3" + [(set (match_operand:QI 0 "register_operand" "=d") + (div:QI (match_operand:QI 1 "register_operand" "0") + (match_operand:QI 2 "register_operand" "d")))] + "" + "div.b %2,%0") + + (define_expand "udivqi3" + [(set (subreg:SI (match_operand:QI 0 "register_operand" "=d") 0) + (zero_extend:SI (match_operand:QI 1 "register_operand" "d"))) + (set (match_dup 3) + (zero_extend:SI (match_operand:QI 2 "register_operand" "d"))) + (set (subreg:SI (match_operand:QI 0 "register_operand" "=d") 0) + (div:SI (subreg:SI (match_operand:QI 0 "register_operand" "=d") 0) + (match_dup 3)))] + "" + " + { + operands[3] = gen_reg_rtx (SImode); + }") + \f + ;; - and, or, xor + + (define_insn "anddi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (and:DI (match_operand:DI 1 "register_operand" "%0") + (match_operand:DI 2 "nonmemory_operand" "dI")))] + "" + "and %2,%0") + + (define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (and:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "and %2,%0") + + (define_insn "andhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (and:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "and %2,%0") + + (define_insn "andqi3" + [(set (match_operand:QI 0 "register_operand" "=d,a") + (and:QI (match_operand:QI 1 "register_operand" "%0,0") + (match_operand:QI 2 "nonmemory_operand" "di,ai")))] + "" + "and %2,%0") + + ;;- Bit set instructions. + + (define_insn "iordi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (ior:DI (match_operand:DI 1 "register_operand" "%0") + (match_operand:DI 2 "register_operand" "dI")))] + "" + "or %2,%0") + + (define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "or %2,%0") + + (define_insn "iorhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (ior:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "or %2,%0") + + (define_insn "iorqi3" + [(set (match_operand:QI 0 "register_operand" "=d,a") + (ior:QI (match_operand:QI 1 "register_operand" "%0,0") + (match_operand:QI 2 "nonmemory_operand" "di,ai")))] + "" + "or %2,%0") + + ;;- xor instructions. + + (define_insn "xordi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (xor:DI (match_operand:DI 1 "register_operand" "%0") + (match_operand:DI 2 "register_operand" "dI")))] + "" + "xor %2,%0") + + (define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "xor %2,%0") + + (define_insn "xorhi3" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (xor:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "di,ai")))] + "" + "xor %2,%0") + + (define_insn "xorqi3" + [(set (match_operand:QI 0 "register_operand" "=d,a") + (xor:QI (match_operand:QI 1 "register_operand" "%0,0") + (match_operand:QI 2 "nonmemory_operand" "di,ai")))] + "" + "xor %2,%0") + \f + (define_insn "negdf2" + [(set (match_operand:DF 0 "register_operand" "=d") + (neg:DF (match_operand:DF 1 "register_operand" "d")))] + "" + "neg.d %1,%0") + + (define_insn "negsf2" + [(set (match_operand:SF 0 "register_operand" "=d") + (neg:SF (match_operand:SF 1 "register_operand" "d")))] + "" + "neg.s %1,%0") + + (define_insn "negdi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (neg:DI (match_operand:DI 1 "register_operand" "d")))] + "" + "neg.l %1,%0") + + (define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (neg:SI (match_operand:SI 1 "register_operand" "d,a")))] + "" + "neg.w %1,%0") + + (define_insn "neghi2" + [(set (match_operand:HI 0 "register_operand" "=d,a") + (neg:HI (match_operand:HI 1 "register_operand" "d,a")))] + "" + "neg.h %1,%0") + + (define_insn "negqi2" + [(set (match_operand:QI 0 "register_operand" "=d") + (neg:QI (match_operand:QI 1 "register_operand" "d")))] + "" + "neg.b %1,%0") + \f + (define_insn "one_cmpldi2" + [(set (match_operand:DI 0 "register_operand" "=d") + (not:DI (match_operand:DI 1 "register_operand" "d")))] + "" + "not %1,%0") + + (define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (not:SI (match_operand:SI 1 "register_operand" "d,a")))] + "" + "not %1,%0") + \f + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (ashift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "immediate_operand" "i")))] + "INTVAL (operands[2]) >= 0" + "* + { + if (operands[2] == const1_rtx) + return \"add.w %0,%0\"; + else if (TARGET_C2 && S_REGNO_P (REGNO (operands[0]))) + return \"shf.w %2,%0\"; + else + return \"shf %2,%0\"; + }") + + (define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (ashift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "* + { + if (operands[2] == const1_rtx) + return \"add.w %0,%0\"; + else if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) >= 0) + { + if (TARGET_C2) + return \"shf.w %2,%0\"; + else + return \"shf %2,%0\"; + } + else + return \"cvtw.l %0,%0\;shf %2,%0\"; + }") + + (define_expand "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (ashift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "operands[2] = negate_rtx (SImode, operands[2]);") + + (define_insn "lshlsi3" + [(set (match_operand:SI 0 "register_operand" "=d,a") + (lshift:SI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "di,ai")))] + "" + "* + { + if (operands[2] == const1_rtx) + return \"add.w %0,%0\"; + if (S_REGNO_P (REGNO (operands[0]))) + { + if (TARGET_C2) + return \"shf.w %2,%0\"; + else if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) >= 0) + return \"shf %2,%0\"; + else + return \"ld.u #0,%0\;shf %2,%0\"; + } + return \"shf %2,%0\"; + }") + + (define_expand "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (lshift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "operands[2] = negate_rtx (SImode, operands[2]);") + + (define_expand "ashldi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (lshift:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + " + { + if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 0) + FAIL; + }") + + (define_insn "lshldi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (lshift:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "shf %2,%0") + + (define_expand "lshrdi3" + [(set (match_operand:DI 0 "register_operand" "=d") + (lshift:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "operands[2] = negate_rtx (SImode, operands[2]);") + \f + ;; __builtin instructions + + (define_insn "sqrtdf2" + [(set (match_operand:DF 0 "register_operand" "d") + (sqrt:DF (match_operand:DF 1 "register_operand" "0")))] + "" + "sqrt.d %0") + + (define_insn "sqrtsf2" + [(set (match_operand:SF 0 "register_operand" "d") + (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] + "" + "sqrt.s %0") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "d") + (minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d")) + (const_int 1)))] + "" + "tzc %1,%0\;le.w #32,%0\;jbrs.f .+6\;ld.w #-1,%0") + + (define_expand "ffssi2" + [(set (match_operand:SI 0 "register_operand" "d") + (minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d")) + (const_int 1))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "") + \f + (define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jbr %l0") + + (define_insn "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"eq\", 't'); ") + + (define_insn "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"eq\", 'f'); ") + + (define_insn "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"le\", 'f'); ") + + (define_insn "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"leu\", 'f'); ") + + (define_insn "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"lt\", 't'); ") + + (define_insn "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"ltu\", 't'); ") + + (define_insn "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"lt\", 'f'); ") + + (define_insn "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"ltu\", 'f'); ") + + (define_insn "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"le\", 't'); ") + + (define_insn "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return gen_cmp (operands[0], \"leu\", 't'); ") + \f + (define_insn "" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"eq\", 'f'); ") + + (define_insn "" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"eq\", 't'); ") + + (define_insn "" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"le\", 't'); ") + + (define_insn "" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"leu\", 't'); ") + + (define_insn "" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"lt\", 'f'); ") + + (define_insn "" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"ltu\", 'f'); ") + + (define_insn "" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"lt\", 't'); ") + + (define_insn "" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"ltu\", 't'); ") + + (define_insn "" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"le\", 'f'); ") + + (define_insn "" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return gen_cmp (operands[0], \"leu\", 'f'); ") + \f + ;; - Calls + ;; + ;; arg count word may be omitted to save a push and let gcc try to + ;; combine the arg list pop. RETURN_POPS_ARGS from tm.h decides this. + + (define_insn "call" + [(call (match_operand:QI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g"))] + "" + "* + { + if (! RETURN_POPS_ARGS ()) + { + if (operands[1] == const0_rtx) + { + if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN + && GET_CODE (PATTERN (NEXT_INSN (insn))) == RETURN) + return \"jmp %0\"; + else + return \"calls %0\"; + } + else if (! call_ap_check (operands[0])) + return \"mov sp,ap\;calls %0\;ld.w 12(fp),ap\"; + operands[0] = XEXP (operands[0], 0); + return \"ld.w %0,a1\;mov sp,ap\;calls (a1)\;ld.w 12(fp),ap\"; + } + operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 3)/ 4); + if (! call_ap_check (operands[0])) + return \"mov sp,ap\;pshea %a1\;calls %0\;ld.w 12(fp),ap\;add.w #4*%a1+4,sp\"; + operands[0] = XEXP (operands[0], 0); + return \"ld.w %0,a1\;mov sp,ap\;pshea %a1\;calls (a1)\;ld.w 12(fp),ap\;add.w #4*%a1+4,sp\"; + }") + + (define_insn "call_value" + [(set (match_operand 0 "" "g") + (call (match_operand:QI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* + { + if (! RETURN_POPS_ARGS ()) + { + if (operands[1] == const0_rtx) + { + if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN + && GET_CODE (PATTERN (NEXT_INSN (insn))) == RETURN) + return \"jmp %1\"; + else + return \"calls %1\"; + } + else if (! call_ap_check (operands[1])) + return \"mov sp,ap\;calls %1\;ld.w 12(fp),ap\"; + operands[1] = XEXP (operands[1], 0); + return \"ld.w %1,a1\;mov sp,ap\;calls (a1)\;ld.w 12(fp),ap\"; + } + operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 3)/ 4); + if (! call_ap_check (operands[1])) + return \"mov sp,ap\;pshea %a2\;calls %1\;ld.w 12(fp),ap\;add.w #4*%a2+4,sp\"; + operands[1] = XEXP (operands[1], 0); + return \"ld.w %1,a1\;mov sp,ap\;pshea %a2\;calls (a1)\;ld.w 12(fp),ap\;add.w #4*%a2+4,sp\"; + }") + + (define_insn "return" + [(return)] + "" + "rtn") + + (define_insn "tablejump" + [(set (pc) (match_operand:SI 0 "address_operand" "p")) + (use (label_ref (match_operand 1 "" "")))] + "" + "jmp %a0") + \f + ;; - fix up the code generated for bit field tests + + ;; cc0 = (x >> k1) & k2 --> cc0 = x & (k2 << k1) + ;; cc0 = (x << k1) & k2 --> cc0 = x & (k2 >> k1) + ;; provided k2 and (k2 << k1) don't include the sign bit + + (define_peephole + [(set (match_operand:SI 0 "register_operand" "r") + (lshift:SI (match_dup 0) + (match_operand 1 "immediate_operand" "i"))) + (set (match_dup 0) + (and:SI (match_dup 0) + (match_operand 2 "immediate_operand" "i"))) + (set (cc0) (match_dup 0))] + "dead_or_set_p (insn, operands[0]) + && GET_CODE (operands[1]) == CONST_INT + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) >= 0 + && (INTVAL (operands[2]) << INTVAL (operands[1])) >= 0" + "* + { + operands[2] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[2]) >> INTVAL (operands[1])); + output_asm_insn (\"and %2,%0\", operands); + return set_cmp (operands[0], const0_rtx, 'w'); + }") + + ;; same as above where x is (y & 0xff...) caused by a zero extend + + (define_peephole + [(set (match_operand:SI 0 "register_operand" "r") + (zero_extend:SI (match_operand 1 "register_operand" "0"))) + (set (match_dup 0) + (lshift:SI (match_dup 0) + (match_operand 2 "immediate_operand" "i"))) + (set (match_dup 0) + (and:SI (match_dup 0) + (match_operand 3 "immediate_operand" "i"))) + (set (cc0) (match_dup 0))] + "dead_or_set_p (insn, operands[0]) + && REGNO (operands[0]) == REGNO (operands[1]) + && GET_CODE (operands[2]) == CONST_INT + && GET_CODE (operands[3]) == CONST_INT + && (INTVAL (operands[3]) << INTVAL (operands[2])) >= 0" + "* + { + operands[3] = gen_rtx (CONST_INT, VOIDmode, + (INTVAL (operands[3]) >> INTVAL (operands[2])) & + ~((-1) << GET_MODE_BITSIZE (GET_MODE (operands[1])))); + output_asm_insn (\"and %3,%0\", operands); + return set_cmp (operands[0], const0_rtx, 'w'); + }") + \f + ;;- Local variables: + ;;- mode:emacs-lisp + ;;- comment-start: ";;- " + ;;- eval: (set-syntax-table (copy-sequence (syntax-table))) + ;;- eval: (modify-syntax-entry ?[ "(]") + ;;- eval: (modify-syntax-entry ?] ")[") + ;;- eval: (modify-syntax-entry ?{ "(}") + ;;- eval: (modify-syntax-entry ?} "){") + ;;- End: + diff -rc2N gcc-1.32/cse.c gcc-1.33/cse.c *** gcc-1.32/cse.c Tue Dec 20 17:56:27 1988 --- gcc-1.33/cse.c Sat Jan 28 22:07:33 1989 *************** *** 1,4 **** /* Common subexpression elimination for GNU compiler. ! Copyright (C) 1987, 1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Common subexpression elimination for GNU compiler. ! Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 25,28 **** --- 25,29 ---- #include "hard-reg-set.h" #include "flags.h" + #include "real.h" /* The basic idea of common subexpression elimination is to go *************** *** 413,420 **** { register int i, j; ! register RTX_CODE code = GET_CODE (x); register char *fmt; register int total; switch (code) { --- 414,425 ---- { register int i, j; ! register enum rtx_code code; register char *fmt; register int total; + if (x == 0) + return 0; + + code = GET_CODE (x); switch (code) { *************** *** 597,604 **** rtx x; { ! register RTX_CODE code = GET_CODE (x); register int i, j; register char *fmt; if (code == REG) { --- 602,613 ---- rtx x; { ! register enum rtx_code code; register int i, j; register char *fmt; + if (x == 0) + return; + + code = GET_CODE (x); if (code == REG) { *************** *** 950,954 **** elt->first_same_value = elt; ! if ((CONSTANT_P (x) || FIXED_BASE_PLUS_P (x)) && GET_CODE (elt->first_same_value->exp) == REG) { --- 959,963 ---- elt->first_same_value = elt; ! if ((CONSTANT_P (x) || GET_CODE (x) == CONST_DOUBLE || FIXED_BASE_PLUS_P (x)) && GET_CODE (elt->first_same_value->exp) == REG) { *************** *** 961,964 **** --- 970,974 ---- if (elt->next_same_value != 0 && (CONSTANT_P (elt->next_same_value->exp) + || GET_CODE (elt->next_same_value->exp) == CONST_DOUBLE || FIXED_BASE_PLUS_P (elt->next_same_value->exp))) { *************** *** 967,970 **** --- 977,981 ---- } if (CONSTANT_P (elt->first_same_value->exp) + || GET_CODE (elt->first_same_value->exp) == CONST_DOUBLE || FIXED_BASE_PLUS_P (elt->first_same_value->exp)) { *************** *** 1270,1274 **** register int i, j; register int hash = 0; ! register RTX_CODE code; register char *fmt; --- 1281,1285 ---- register int i, j; register int hash = 0; ! register enum rtx_code code; register char *fmt; *************** *** 1275,1278 **** --- 1286,1292 ---- /* repeat is used to turn tail-recursion into iteration. */ repeat: + if (x == 0) + return hash; + code = GET_CODE (x); switch (code) *************** *** 1286,1290 **** register int regno = REGNO (x); ! if (regno == STACK_POINTER_REGNUM) { do_not_record = 1; --- 1300,1305 ---- register int regno = REGNO (x); ! if (regno == STACK_POINTER_REGNUM ! || (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])) { do_not_record = 1; *************** *** 1304,1311 **** hash += (int) code + (int) GET_MODE (x); { ! int tem = XINT (x, 0); ! hash += ((1 << HASHBITS) - 1) & (tem + (tem >> HASHBITS)); ! tem = XINT (x, 1); ! hash += ((1 << HASHBITS) - 1) & (tem + (tem >> HASHBITS)); } return hash; --- 1319,1328 ---- hash += (int) code + (int) GET_MODE (x); { ! int i; ! for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++) ! { ! int tem = XINT (x, i); ! hash += ((1 << HASHBITS) - 1) & (tem + (tem >> HASHBITS)); ! } } return hash; *************** *** 1313,1320 **** /* Assume there is only one rtx object for any given label. */ case LABEL_REF: ! return hash + ((int) LABEL_REF << 7) + (int) XEXP (x, 0); case SYMBOL_REF: ! return hash + ((int) SYMBOL_REF << 7) + (int) XEXP (x, 0); case MEM: --- 1330,1340 ---- /* Assume there is only one rtx object for any given label. */ case LABEL_REF: ! /* Use `and' to ensure a positive number. */ ! return (hash + ((int) LABEL_REF << 7) ! + ((int) XEXP (x, 0) & ((1 << HASHBITS) - 1))); case SYMBOL_REF: ! return (hash + ((int) SYMBOL_REF << 7) ! + ((int) XEXP (x, 0) & ((1 << HASHBITS) - 1))); case MEM: *************** *** 1421,1425 **** { register int i; ! register RTX_CODE code = GET_CODE (x); register char *fmt; --- 1441,1445 ---- { register int i; ! register enum rtx_code code; register char *fmt; *************** *** 1428,1431 **** --- 1448,1454 ---- if (x == y && !validate) return 1; + if (x == 0 || y == 0) + return x == y; + code = GET_CODE (x); if (code != GET_CODE (y)) return 0; *************** *** 1496,1500 **** { register int i; ! register RTX_CODE code; register char *fmt; --- 1519,1523 ---- { register int i; ! register enum rtx_code code; register char *fmt; *************** *** 1557,1561 **** { register int i; ! register RTX_CODE code; register char *fmt; --- 1580,1584 ---- { register int i; ! register enum rtx_code code; register char *fmt; *************** *** 1640,1646 **** { register int i; ! register RTX_CODE code = GET_CODE (x); register char *fmt; switch (code) { --- 1663,1673 ---- { register int i; ! register enum rtx_code code; register char *fmt; + if (x == 0) + return x; + + code = GET_CODE (x); switch (code) { *************** *** 1707,1711 **** int copyflag; { ! register RTX_CODE code = GET_CODE (x); register char *fmt; register int i, val; --- 1734,1738 ---- int copyflag; { ! register enum rtx_code code; register char *fmt; register int i, val; *************** *** 1712,1716 **** rtx new = 0; int copied = ! copyflag; ! int width = GET_MODE_BITSIZE (GET_MODE (x)); /* Constant equivalents of first three operands of X; --- 1739,1743 ---- rtx new = 0; int copied = ! copyflag; ! int width; /* Constant equivalents of first three operands of X; *************** *** 1720,1723 **** --- 1747,1755 ---- rtx const_arg2; + if (x == 0) + return x; + + width = GET_MODE_BITSIZE (GET_MODE (x)); + code = GET_CODE (x); switch (code) { *************** *** 1730,1733 **** --- 1762,1769 ---- case CC0: case REG: + /* No use simplifying an EXPR_LIST + since they are used only for lists of args + in a function call's REG_EQUAL note. */ + case EXPR_LIST: return x; *************** *** 1841,1845 **** /* Now decode the kind of rtx X is ! and either return X (if nothing can be done) or store a value in VAL and drop through (to return a CONST_INT for the integer VAL). */ --- 1877,1882 ---- /* Now decode the kind of rtx X is ! and then return X (if nothing can be done) ! or return a folded rtx or store a value in VAL and drop through (to return a CONST_INT for the integer VAL). */ *************** *** 1847,1902 **** if (GET_RTX_LENGTH (code) == 1) { ! register int arg0; ! ! if (const_arg0 == 0 || GET_CODE (const_arg0) != CONST_INT) return x; ! arg0 = INTVAL (const_arg0); ! ! switch (GET_CODE (x)) { ! case NOT: ! val = ~ arg0; ! break; ! ! case NEG: ! val = - arg0; ! break; ! ! case TRUNCATE: ! val = arg0; ! break; ! case ZERO_EXTEND: ! { ! enum machine_mode mode = GET_MODE (XEXP (x, 0)); ! if (mode == VOIDmode) ! return x; ! if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) ! val = arg0 & ~((-1) << GET_MODE_BITSIZE (mode)); ! else ! return x; ! break; ! } ! case SIGN_EXTEND: ! { ! enum machine_mode mode = GET_MODE (XEXP (x, 0)); ! if (mode == VOIDmode) ! return x; ! if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) { ! val = arg0 & ~((-1) << GET_MODE_BITSIZE (mode)); ! if (val & (1 << (GET_MODE_BITSIZE (mode) - 1))) ! val -= 1 << GET_MODE_BITSIZE (mode); } ! else return x; ! break; ! } ! default: ! return x; } } else if (GET_RTX_LENGTH (code) == 2) --- 1884,1955 ---- if (GET_RTX_LENGTH (code) == 1) { ! if (const_arg0 == 0) return x; ! if (GET_CODE (const_arg0) == CONST_INT) { ! register int arg0 = INTVAL (const_arg0); ! switch (GET_CODE (x)) ! { ! case NOT: ! val = ~ arg0; ! break; ! ! case NEG: ! val = - arg0; ! break; ! case TRUNCATE: ! val = arg0; ! break; ! ! case ZERO_EXTEND: { ! enum machine_mode mode = GET_MODE (XEXP (x, 0)); ! if (mode == VOIDmode) ! return x; ! if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) ! val = arg0 & ~((-1) << GET_MODE_BITSIZE (mode)); ! else ! return x; ! break; } ! ! case SIGN_EXTEND: ! { ! enum machine_mode mode = GET_MODE (XEXP (x, 0)); ! if (mode == VOIDmode) ! return x; ! if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) ! { ! val = arg0 & ~((-1) << GET_MODE_BITSIZE (mode)); ! if (val & (1 << (GET_MODE_BITSIZE (mode) - 1))) ! val -= 1 << GET_MODE_BITSIZE (mode); ! } ! else ! return x; ! break; ! } ! ! default: return x; ! } ! } ! #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) ! else if (GET_CODE (const_arg0) == CONST_DOUBLE ! && GET_CODE (x) == NEG) ! { ! union real_extract u; ! register REAL_VALUE_TYPE arg0; ! bcopy (&CONST_DOUBLE_LOW (const_arg0), &u, sizeof u); ! arg0 = u.d; ! u.d = REAL_VALUE_NEGATE (arg0); ! return immed_real_const_1 (u.d, GET_MODE (x)); } + #endif + else + return x; } else if (GET_RTX_LENGTH (code) == 2) *************** *** 1961,1965 **** /* Handle both-operands-constant cases. */ ! if (const_arg0 != 0 && const_arg1 != 0) { if (GET_CODE (const_arg1) == CONST_INT) --- 2014,2021 ---- /* Handle both-operands-constant cases. */ ! if (const_arg0 != 0 && const_arg1 != 0 ! && GET_CODE (const_arg0) != CONST_DOUBLE ! && GET_CODE (const_arg1) != CONST_DOUBLE ! && GET_MODE_CLASS (GET_MODE (x))) { if (GET_CODE (const_arg1) == CONST_INT) *************** *** 2002,2007 **** } /* Change subtraction from zero into negation. */ ! if (GET_MODE (x) != VOIDmode && const_arg0 == const0_rtx) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 1)); --- 2058,2070 ---- } + /* MINUS with VOIDmode is an overflowless subtraction + for comparison purposes. It's incorrect to fold it + at all unless we can determine the comparison results. + Leave that to fold_cc0. */ + if (GET_MODE (x) == VOIDmode) + return x; + /* Change subtraction from zero into negation. */ ! if (const_arg0 == const0_rtx) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 1)); *************** *** 2019,2026 **** && GET_MODE (XEXP (x, 0)) == GET_MODE (x)) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 0)); ! if (const_arg1 == const0_rtx) new = const0_rtx; if (const_arg1 == const1_rtx) return XEXP (x, 0); break; --- 2082,2091 ---- && GET_MODE (XEXP (x, 0)) == GET_MODE (x)) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 0)); ! if (const_arg1 == const0_rtx || const_arg0 == const0_rtx) new = const0_rtx; if (const_arg1 == const1_rtx) return XEXP (x, 0); + if (const_arg0 == const1_rtx) + return XEXP (x, 1); break; *************** *** 2028,2031 **** --- 2093,2098 ---- if (const_arg1 == const0_rtx) return XEXP (x, 0); + if (const_arg0 == const0_rtx) + return XEXP (x, 1); if (const_arg1 && GET_CODE (const_arg1) == CONST_INT && (INTVAL (const_arg1) & GET_MODE_MASK (GET_MODE (x))) *************** *** 2037,2040 **** --- 2104,2109 ---- if (const_arg1 == const0_rtx) return XEXP (x, 0); + if (const_arg0 == const0_rtx) + return XEXP (x, 1); if (const_arg1 && GET_CODE (const_arg1) == CONST_INT && (INTVAL (const_arg1) & GET_MODE_MASK (GET_MODE (x))) *************** *** 2044,2048 **** case AND: ! if (const_arg1 == const0_rtx) new = const0_rtx; if (const_arg1 && GET_CODE (const_arg1) == CONST_INT --- 2113,2117 ---- case AND: ! if (const_arg1 == const0_rtx || const_arg0 == const0_rtx) new = const0_rtx; if (const_arg1 && GET_CODE (const_arg1) == CONST_INT *************** *** 2074,2077 **** --- 2143,2148 ---- if (const_arg1 == const0_rtx) return XEXP (x, 0); + if (const_arg0 == const0_rtx) + new = const_arg0; break; } *************** *** 2369,2373 **** y0 = tem; ! if (y0 == 0 || GET_CODE (y0) != CONST_INT) return 0; --- 2440,2444 ---- y0 = tem; ! if (y0 == 0) return 0; *************** *** 2376,2382 **** y1 = tem; ! if (y1 == 0 || GET_CODE (y1) != CONST_INT) return 0; s0 = u0 = INTVAL (y0); s1 = u1 = INTVAL (y1); --- 2447,2474 ---- y1 = tem; ! if (y1 == 0) ! return 0; ! ! /* Compare floats; report the result only for signed compares ! since that's all there are for floats. */ ! if (GET_CODE (y0) == CONST_DOUBLE ! && GET_CODE (y1) == CONST_DOUBLE ! && GET_MODE_CLASS (GET_MODE (y0)) == MODE_FLOAT) ! { ! union real_extract u0, u1; ! bcopy (&CONST_DOUBLE_LOW (y0), &u0, sizeof u0); ! bcopy (&CONST_DOUBLE_LOW (y1), &u1, sizeof u1); ! return 0100 + (REAL_VALUES_LESS (u0.d, u1.d) ? 7 << 3 ! : REAL_VALUES_LESS (u1.d, u0.d) ? 1 << 3 : 0); ! } ! ! /* Aside from that, demand explicit integers. */ ! ! if (GET_CODE (y0) != CONST_INT) return 0; + if (GET_CODE (y1) != CONST_INT) + return 0; + s0 = u0 = INTVAL (y0); s1 = u1 = INTVAL (y1); *************** *** 2766,2769 **** --- 2858,2869 ---- hash_arg_in_struct = 0; src = fold_rtx (src, 0); + /* If SRC is a subreg of a reg with a known value, + perform the truncation now. */ + if (GET_CODE (src) == SUBREG) + { + rtx temp = equiv_constant (src); + if (temp) + src = temp; + } /* If we have (NOT Y), see if Y is known to be (NOT Z). If so, (NOT Y) simplifies to Z. */ *************** *** 3471,3475 **** for (insn = from; insn != to; insn = NEXT_INSN (insn)) { ! register RTX_CODE code = GET_CODE (insn); if (code == INSN || code == JUMP_INSN || code == CALL_INSN) cse_insn (insn); --- 3571,3575 ---- for (insn = from; insn != to; insn = NEXT_INSN (insn)) { ! register enum rtx_code code = GET_CODE (insn); if (code == INSN || code == JUMP_INSN || code == CALL_INSN) cse_insn (insn); diff -rc2N gcc-1.32/dbxout.c gcc-1.33/dbxout.c *** gcc-1.32/dbxout.c Tue Dec 6 21:36:45 1988 --- gcc-1.33/dbxout.c Wed Jan 11 21:40:53 1989 *************** *** 85,89 **** #endif ! #include <stab.h> /* Stream for writing to assembler file. */ --- 85,93 ---- #endif ! #ifdef USG ! #include "stab.h" /* If doing DBX on sysV, use our own stab.h. */ ! #else ! #include <stab.h> /* On BSD, use the system's stab.h. */ ! #endif /* not USG */ /* Stream for writing to assembler file. */ diff -rc2N gcc-1.32/emit-rtl.c gcc-1.33/emit-rtl.c *** gcc-1.32/emit-rtl.c Mon Dec 5 17:21:57 1988 --- gcc-1.33/emit-rtl.c Sun Jan 1 17:13:23 1989 *************** *** 41,44 **** --- 41,45 ---- #include "regs.h" #include "insn-config.h" + #include "real.h" #define max(A,B) ((A) > (B) ? (A) : (B)) *************** *** 190,212 **** INTVAL (rt_val) = arg; } - else if (code == CONST_DOUBLE) - { - int arg0 = va_arg (p, int); - int arg1 = va_arg (p, int); - if (arg0 == XINT (fconst0_rtx, 0) - && arg1 == XINT (fconst0_rtx, 1)) - { - if (mode == DFmode) - return dconst0_rtx; - if (mode == SFmode) - return fconst0_rtx; - if (mode == DImode) - return const0_rtx; - } - rt_val = rtx_alloc (code); - rt_val->mode = mode; - XINT (rt_val, 0) = arg0; - XINT (rt_val, 1) = arg1; - } else { --- 191,194 ---- *************** *** 1550,1571 **** fconst0_rtx = rtx_alloc (CONST_DOUBLE); - { - union { double d; int i[2]; } u; - u.d = 0; - XINT (fconst0_rtx, 0) = u.i[0]; - XINT (fconst0_rtx, 1) = u.i[1]; - XEXP (fconst0_rtx, 2) = cc0_rtx; - } - PUT_MODE (fconst0_rtx, SFmode); - dconst0_rtx = rtx_alloc (CONST_DOUBLE); { ! union { double d; int i[2]; } u; u.d = 0; ! XINT (dconst0_rtx, 0) = u.i[0]; ! XINT (dconst0_rtx, 1) = u.i[1]; ! XEXP (dconst0_rtx, 2) = cc0_rtx; } - PUT_MODE (dconst0_rtx, DFmode); stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); --- 1532,1553 ---- fconst0_rtx = rtx_alloc (CONST_DOUBLE); dconst0_rtx = rtx_alloc (CONST_DOUBLE); { ! union real_extract u; ! #ifdef REAL_IS_NOT_DOUBLE ! bzero (&u, sizeof u); ! u.d = REAL_VALUE_ATOF ("0"); ! #else u.d = 0; ! #endif ! ! bcopy (&u, &CONST_DOUBLE_LOW (fconst0_rtx), sizeof u); ! CONST_DOUBLE_MEM (fconst0_rtx) = cc0_rtx; ! PUT_MODE (fconst0_rtx, SFmode); ! ! bcopy (&u, &CONST_DOUBLE_LOW (dconst0_rtx), sizeof u); ! CONST_DOUBLE_MEM (dconst0_rtx) = cc0_rtx; ! PUT_MODE (dconst0_rtx, DFmode); } stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); diff -rc2N gcc-1.32/expmed.c gcc-1.33/expmed.c *** gcc-1.32/expmed.c Wed Dec 7 14:09:52 1988 --- gcc-1.33/expmed.c Sat Jan 28 19:48:11 1989 *************** *** 1,5 **** /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. ! Copyright (C) 1987, 1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,5 ---- /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. ! Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 48,54 **** { int val = - INTVAL (x); - /* Avoid setting an extraneous bits. */ if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) ! val &= (1 << GET_MODE_BITSIZE (mode)) - 1; return gen_rtx (CONST_INT, VOIDmode, val); } --- 48,59 ---- { int val = - INTVAL (x); if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) ! { ! /* Sign extend the value from the bits that are significant. */ ! if (val & (1 << (GET_MODE_BITSIZE (mode) - 1))) ! val |= (-1) << GET_MODE_BITSIZE (mode); ! else ! val &= (1 << GET_MODE_BITSIZE (mode)) - 1; ! } return gen_rtx (CONST_INT, VOIDmode, val); } *************** *** 60,64 **** into a bit-field within structure STR_RTX containing BITSIZE bits starting at bit BITNUM. ! FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */ /* ??? This should really have the ability to copy a word into a register --- 65,70 ---- into a bit-field within structure STR_RTX containing BITSIZE bits starting at bit BITNUM. ! FIELDMODE is the machine-mode of the FIELD_DECL node for this field. ! ALIGN is the alignment that STR_RTX is known to have, measured in bytes. */ /* ??? This should really have the ability to copy a word into a register *************** *** 67,71 **** rtx ! store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value) rtx str_rtx; register int bitsize; --- 73,77 ---- rtx ! store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align) rtx str_rtx; register int bitsize; *************** *** 73,76 **** --- 79,83 ---- enum machine_mode fieldmode; rtx value; + int align; { int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD; *************** *** 225,229 **** { delete_insns_since (last); ! store_fixed_bit_field (op0, offset, bitsize, bitpos, value); } } --- 232,236 ---- { delete_insns_since (last); ! store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align); } } *************** *** 231,235 **** #endif /* Insv is not available; store using shifts and boolean ops. */ ! store_fixed_bit_field (op0, offset, bitsize, bitpos, value); return value; } --- 238,242 ---- #endif /* Insv is not available; store using shifts and boolean ops. */ ! store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align); return value; } *************** *** 243,246 **** --- 250,254 ---- but BITPOS still counts within a full word, which is significant on bigendian machines.) + STRUCT_ALIGN is the alignment the structure is known to have (in bytes). Note that protect_from_queue has already been done on OP0 and VALUE. */ *************** *** 247,254 **** static void ! store_fixed_bit_field (op0, offset, bitsize, bitpos, value) register rtx op0; register int offset, bitsize, bitpos; register rtx value; { register enum machine_mode mode; --- 255,263 ---- static void ! store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align) register rtx op0; register int offset, bitsize, bitpos; register rtx value; + int struct_align; { register enum machine_mode mode; *************** *** 262,265 **** --- 271,281 ---- change OP0 to a byte. */ + /* There is a case not handled here: + a structure with a known alignment of just a halfword + and a field split across two aligned halfwords within the structure. + Or likewise a structure with a known alignment of just a byte + and a field split across two bytes. + Such cases are not supposed to be able to occur. */ + if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) { *************** *** 269,273 **** if (bitsize + bitpos > BITS_PER_WORD) { ! store_split_bit_field (op0, bitsize, bitpos, value); return; } --- 285,289 ---- if (bitsize + bitpos > BITS_PER_WORD) { ! store_split_bit_field (op0, bitsize, bitpos, value, BITS_PER_WORD); return; } *************** *** 274,279 **** } else if (bitsize + bitpos <= BITS_PER_UNIT ! && ! SLOW_BYTE_ACCESS) { total_bits = BITS_PER_UNIT; op0 = change_address (op0, QImode, --- 290,299 ---- } else if (bitsize + bitpos <= BITS_PER_UNIT ! && (! SLOW_BYTE_ACCESS ! || (struct_align == 1 ! && BIGGEST_ALIGNMENT > 1))) { + /* It fits in one byte, and either bytes are fast + or the alignment won't let us use anything bigger. */ total_bits = BITS_PER_UNIT; op0 = change_address (op0, QImode, *************** *** 280,286 **** plus_constant (XEXP (op0, 0), offset)); } else { ! /* Get ref to word containing the field. */ /* Adjust BITPOS to be position within a word, and OFFSET to be the offset of that word. --- 300,325 ---- plus_constant (XEXP (op0, 0), offset)); } + else if ((bitsize + bitpos + (offset % GET_MODE_SIZE (HImode)) * BITS_PER_UNIT + <= GET_MODE_BITSIZE (HImode)) + /* If halfwords are fast, use them whenever valid. */ + && (! SLOW_BYTE_ACCESS + /* Use halfwords if larger is invalid due to alignment. */ + || (struct_align == GET_MODE_SIZE (HImode) + && BIGGEST_ALIGNMENT > GET_MODE_SIZE (HImode)))) + { + /* It fits in an aligned halfword within the structure, + and either halfwords are fast + or the alignment won't let us use anything bigger. */ + total_bits = GET_MODE_BITSIZE (HImode); + + /* Get ref to halfword containing the field. */ + bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT; + offset -= (offset % (total_bits / BITS_PER_UNIT)); + op0 = change_address (op0, HImode, + plus_constant (XEXP (op0, 0), offset)); + } else { ! /* Get ref to an aligned word containing the field. */ /* Adjust BITPOS to be position within a word, and OFFSET to be the offset of that word. *************** *** 290,297 **** op0 = change_address (op0, SImode, plus_constant (XEXP (op0, 0), offset)); ! /* Special treatment for a bit field split across two words. */ if (bitsize + bitpos > BITS_PER_WORD) { ! store_split_bit_field (op0, bitsize, bitpos, value); return; } --- 329,337 ---- op0 = change_address (op0, SImode, plus_constant (XEXP (op0, 0), offset)); ! ! /* Special treatment for a bit field split across two aligned words. */ if (bitsize + bitpos > BITS_PER_WORD) { ! store_split_bit_field (op0, bitsize, bitpos, value, struct_align); return; } *************** *** 300,311 **** mode = GET_MODE (op0); ! /* Now OP0 is either a byte or a word, and the bit field is contained ! entirely within it. TOTAL_BITS and MODE say which one (byte or word). ! BITPOS is the starting bit number within the byte or word. ! (If OP0 is a word, it may actually have a mode narrower than SImode.) */ #ifdef BYTES_BIG_ENDIAN /* BITPOS is the distance between our msb ! and that of the containing byte or word. Convert it to the distance from the lsb. */ --- 340,352 ---- mode = GET_MODE (op0); ! /* Now MODE is either QImode, HImode or SImode for a MEM as OP0, ! or is SImode for a REG as OP0. TOTAL_BITS corresponds. ! The bit field is contained entirely within OP0. ! BITPOS is the starting bit number within OP0. ! (OP0's mode may actually be narrower than MODE.) */ #ifdef BYTES_BIG_ENDIAN /* BITPOS is the distance between our msb ! and that of the containing datum. Convert it to the distance from the lsb. */ *************** *** 313,317 **** #endif /* Now BITPOS is always the distance between our lsb ! and that of the containing byte or word. */ /* Shift VALUE left by BITPOS bits. If VALUE is not constant, --- 354,358 ---- #endif /* Now BITPOS is always the distance between our lsb ! and that of OP0. */ /* Shift VALUE left by BITPOS bits. If VALUE is not constant, *************** *** 339,343 **** { if ((GET_CODE (value) == REG || GET_CODE (value) == SUBREG) ! && mode == QImode) value = gen_lowpart (mode, value); else --- 380,384 ---- { if ((GET_CODE (value) == REG || GET_CODE (value) == SUBREG) ! && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (value))) value = gen_lowpart (mode, value); else *************** *** 387,394 **** static void ! store_split_bit_field (op0, bitsize, bitpos, value) rtx op0; int bitsize, bitpos; rtx value; { /* BITSIZE_1 is size of the part in the first word. */ --- 428,436 ---- static void ! store_split_bit_field (op0, bitsize, bitpos, value, align) rtx op0; int bitsize, bitpos; rtx value; + int align; { /* BITSIZE_1 is size of the part in the first word. */ *************** *** 439,443 **** /* Store PART1 into the first word. */ ! store_fixed_bit_field (op0, 0, bitsize_1, bitpos, part1); /* Offset op0 to get to the following word. */ --- 481,485 ---- /* Store PART1 into the first word. */ ! store_fixed_bit_field (op0, 0, bitsize_1, bitpos, part1, align); /* Offset op0 to get to the following word. */ *************** *** 451,455 **** /* Store PART2 into the second word. */ ! store_fixed_bit_field (op0, 0, bitsize_2, 0, part2); } \f --- 493,497 ---- /* Store PART2 into the second word. */ ! store_fixed_bit_field (op0, 0, bitsize_2, 0, part2, align); } \f *************** *** 466,469 **** --- 508,513 ---- but the value may be returned with type MODE instead. + ALIGN is the alignment that STR_RTX is known to have, measured in bytes. + If a TARGET is specified and we can store in it at no extra cost, we do so, and return TARGET. *************** *** 472,476 **** rtx ! extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, target, mode, tmode) rtx str_rtx; register int bitsize; --- 516,521 ---- rtx ! extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, ! target, mode, tmode, align) rtx str_rtx; register int bitsize; *************** *** 479,482 **** --- 524,528 ---- rtx target; enum machine_mode mode, tmode; + int align; { int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD; *************** *** 644,648 **** delete_insns_since (last); target = extract_fixed_bit_field (tmode, op0, offset, bitsize, ! bitpos, target, 1); } } --- 690,694 ---- delete_insns_since (last); target = extract_fixed_bit_field (tmode, op0, offset, bitsize, ! bitpos, target, 1, align); } } *************** *** 650,654 **** #endif target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! target, 1); } else --- 696,700 ---- #endif target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! target, 1, align); } else *************** *** 735,739 **** delete_insns_since (last); target = extract_fixed_bit_field (tmode, op0, offset, bitsize, ! bitpos, target, 1); } } --- 781,785 ---- delete_insns_since (last); target = extract_fixed_bit_field (tmode, op0, offset, bitsize, ! bitpos, target, 0, align); } } *************** *** 741,745 **** #endif target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! target, 0); } if (target == spec_target) --- 787,791 ---- #endif target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! target, 0, align); } if (target == spec_target) *************** *** 766,773 **** If TARGET is nonzero, attempts to store the value there and return TARGET, but this is not guaranteed. ! If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */ static rtx ! extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, target, unsignedp) enum machine_mode tmode; register rtx op0, target; --- 812,822 ---- If TARGET is nonzero, attempts to store the value there and return TARGET, but this is not guaranteed. ! If TARGET is not used, create a pseudo-reg of mode TMODE for the value. + ALIGN is the alignment that STR_RTX is known to have, measured in bytes. */ + static rtx ! extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! target, unsignedp, align) enum machine_mode tmode; register rtx op0, target; *************** *** 774,777 **** --- 823,827 ---- register int offset, bitsize, bitpos; int unsignedp; + int align; { int total_bits = BITS_PER_WORD; *************** *** 782,807 **** /* Special treatment for a bit field split across two registers. */ if (bitsize + bitpos > BITS_PER_WORD) ! return extract_split_bit_field (op0, bitsize, bitpos, unsignedp); } ! else if (bitsize + bitpos <= BITS_PER_UNIT && ! SLOW_BYTE_ACCESS) { ! /* If the bit field fits entirely in one byte of memory, ! let OP0 be that byte. We must add OFFSET to its address. */ total_bits = BITS_PER_UNIT; ! op0 = change_address (op0, QImode, plus_constant (XEXP (op0, 0), offset)); } else { - #ifdef STRICT_ALIGNMENT - #ifndef STRUCTURE_SIZE_BOUNDARY - /* The following code assumes that OP0 is aligned - such that a word can be fetched there. - This could be because words don't need to be aligned, - or because all structures are suitably aligned. */ - abort (); - #endif - #endif - /* Get ref to word containing the field. */ /* Adjust BITPOS to be position within a word, --- 832,869 ---- /* Special treatment for a bit field split across two registers. */ if (bitsize + bitpos > BITS_PER_WORD) ! return extract_split_bit_field (op0, bitsize, bitpos, ! unsignedp, align); } ! else if (bitsize + bitpos <= BITS_PER_UNIT ! && (! SLOW_BYTE_ACCESS ! || (align == 1 ! && BIGGEST_ALIGNMENT > 1))) { ! /* It fits in one byte, and either bytes are fast ! or the alignment won't let us use anything bigger. */ total_bits = BITS_PER_UNIT; ! op0 = change_address (op0, QImode, plus_constant (XEXP (op0, 0), offset)); } + else if ((bitsize + bitpos + (offset % GET_MODE_SIZE (HImode)) * BITS_PER_UNIT + <= GET_MODE_BITSIZE (HImode)) + /* If halfwords are fast, use them whenever valid. */ + && (! SLOW_BYTE_ACCESS + /* Use halfwords if larger is invalid due to alignment. */ + || (align == GET_MODE_SIZE (HImode) + && BIGGEST_ALIGNMENT > GET_MODE_SIZE (HImode)))) + { + /* It fits in an aligned halfword, and either halfwords are fast + or the alignment won't let us use anything bigger. */ + total_bits = GET_MODE_BITSIZE (HImode); + + /* Get ref to halfword containing the field. */ + bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT; + offset -= (offset % (total_bits / BITS_PER_UNIT)); + op0 = change_address (op0, HImode, + plus_constant (XEXP (op0, 0), offset)); + } else { /* Get ref to word containing the field. */ /* Adjust BITPOS to be position within a word, *************** *** 814,818 **** /* Special treatment for a bit field split across two words. */ if (bitsize + bitpos > BITS_PER_WORD) ! return extract_split_bit_field (op0, bitsize, bitpos, unsignedp); } --- 876,881 ---- /* Special treatment for a bit field split across two words. */ if (bitsize + bitpos > BITS_PER_WORD) ! return extract_split_bit_field (op0, bitsize, bitpos, ! unsignedp, align); } *************** *** 820,825 **** #ifdef BYTES_BIG_ENDIAN ! /* BITPOS is the distance between our msb ! and that of the containing byte or word. Convert it to the distance from the lsb. */ --- 883,887 ---- #ifdef BYTES_BIG_ENDIAN ! /* BITPOS is the distance between our msb and that of OP0. Convert it to the distance from the lsb. */ *************** *** 826,831 **** bitpos = total_bits - bitsize - bitpos; #endif ! /* Now BITPOS is always the distance between our lsb ! and that of the containing byte or word. We have reduced the big-endian case to the little-endian case. */ --- 888,892 ---- bitpos = total_bits - bitsize - bitpos; #endif ! /* Now BITPOS is always the distance between the field's lsb and that of OP0. We have reduced the big-endian case to the little-endian case. */ *************** *** 904,910 **** static rtx ! extract_split_bit_field (op0, bitsize, bitpos, unsignedp) rtx op0; ! int bitsize, bitpos, unsignedp; { /* BITSIZE_1 is size of the part in the first word. */ --- 965,971 ---- static rtx ! extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align) rtx op0; ! int bitsize, bitpos, unsignedp, align; { /* BITSIZE_1 is size of the part in the first word. */ *************** *** 915,919 **** /* Get the part of the bit field from the first word. */ ! part1 = extract_fixed_bit_field (SImode, op0, 0, bitsize_1, bitpos, 0, 1); /* Offset op0 by 1 word to get to the following one. */ --- 976,981 ---- /* Get the part of the bit field from the first word. */ ! part1 = extract_fixed_bit_field (SImode, op0, 0, bitsize_1, bitpos, ! 0, 1, align); /* Offset op0 by 1 word to get to the following one. */ *************** *** 927,931 **** /* Get the part of the bit field from the second word. */ ! part2 = extract_fixed_bit_field (SImode, op0, 0, bitsize_2, 0, 0, 1); /* Shift the more significant part up to fit above the other part. */ --- 989,993 ---- /* Get the part of the bit field from the second word. */ ! part2 = extract_fixed_bit_field (SImode, op0, 0, bitsize_2, 0, 0, 1, align); /* Shift the more significant part up to fit above the other part. */ *************** *** 1261,1270 **** target = 0; - if (target == 0) - target = gen_reg_rtx (mode); - /* Don't clobber an operand while doing a multi-step calculation. */ ! if ((rem_flag && rtx_equal_p (target, op0)) ! || rtx_equal_p (target, op1)) target = gen_reg_rtx (mode); --- 1323,1335 ---- target = 0; /* Don't clobber an operand while doing a multi-step calculation. */ ! if (target) ! if ((rem_flag && (reg_mentioned_p (target, op0) ! || (GET_CODE (op0) == MEM && GET_CODE (target) == MEM))) ! || reg_mentioned_p (target, op1) ! || (GET_CODE (op1) == MEM && GET_CODE (target) == MEM)) ! target = 0; ! ! if (target == 0) target = gen_reg_rtx (mode); *************** *** 1292,1296 **** if (! can_clobber_op0) adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0); emit_jump_insn (gen_bge (label)); expand_inc (adjusted_op0, plus_constant (op1, -1)); --- 1357,1361 ---- if (! can_clobber_op0) adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0, 0); emit_jump_insn (gen_bge (label)); expand_inc (adjusted_op0, plus_constant (op1, -1)); *************** *** 1307,1311 **** if (! can_clobber_op0) adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0); emit_jump_insn (gen_bge (label)); expand_dec (adjusted_op0, op1); --- 1372,1376 ---- if (! can_clobber_op0) adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0, 0); emit_jump_insn (gen_bge (label)); expand_dec (adjusted_op0, op1); *************** *** 1326,1330 **** { label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0); emit_jump_insn (gen_ble (label)); } --- 1391,1395 ---- { label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0, 0); emit_jump_insn (gen_ble (label)); } *************** *** 1353,1357 **** { rtx label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0); emit_jump_insn (gen_bge (label)); expand_unop (mode, neg_optab, op1, op1, 0); --- 1418,1422 ---- { rtx label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0, 0); emit_jump_insn (gen_bge (label)); expand_unop (mode, neg_optab, op1, op1, 0); diff -rc2N gcc-1.32/expr.c gcc-1.33/expr.c *** gcc-1.32/expr.c Thu Dec 15 17:24:08 1988 --- gcc-1.33/expr.c Mon Jan 23 03:19:44 1989 *************** *** 340,350 **** if (unsignedp) { ! emit_insn (gen_rtx (CLOBBER, VOIDmode, to)); ! convert_move (gen_lowpart (SImode, to), from, unsignedp); ! emit_clr_insn (gen_highpart (SImode, to)); } #ifdef HAVE_extendsidi2 else if (HAVE_extendsidi2) ! emit_insn (gen_extendsidi2 (to, from)); #endif #ifdef HAVE_slt --- 340,390 ---- if (unsignedp) { ! #ifdef HAVE_zero_extendsidi2 ! if (HAVE_zero_extendsidi2 && from_mode == SImode) ! emit_unop_insn (CODE_FOR_zero_extendsidi2, to, from, ZERO_EXTEND); ! else ! #endif ! #ifdef HAVE_zero_extendhidi2 ! if (HAVE_zero_extendhidi2 && from_mode == HImode) ! emit_unop_insn (CODE_FOR_zero_extendhidi2, to, from, ZERO_EXTEND); ! else ! #endif ! #ifdef HAVE_zero_extendqidi2 ! if (HAVE_zero_extendqidi2 && from_mode == QImode) ! emit_unop_insn (CODE_FOR_zero_extendqidi2, to, from, ZERO_EXTEND); ! else ! #endif ! #ifdef HAVE_zero_extendsidi2 ! if (HAVE_zero_extendsidi2) ! { ! convert_move (gen_lowpart (SImode, to), from, unsignedp); ! emit_unop_insn (CODE_FOR_zero_extendsidi2, to, to, ZERO_EXTEND); ! } ! else ! #endif ! { ! emit_insn (gen_rtx (CLOBBER, VOIDmode, to)); ! convert_move (gen_lowpart (SImode, to), from, unsignedp); ! emit_clr_insn (gen_highpart (SImode, to)); ! } } #ifdef HAVE_extendsidi2 + else if (HAVE_extendsidi2 && from_mode == SImode) + emit_unop_insn (CODE_FOR_extendsidi2, to, from, SIGN_EXTEND); + #endif + #ifdef HAVE_extendhidi2 + else if (HAVE_extendhidi2 && from_mode == HImode) + emit_unop_insn (CODE_FOR_extendhidi2, to, from, SIGN_EXTEND); + #endif + #ifdef HAVE_extendqidi2 + else if (HAVE_extendqidi2 && from_mode == QImode) + emit_unop_insn (CODE_FOR_extendqidi2, to, from, SIGN_EXTEND); + #endif + #ifdef HAVE_extendsidi2 else if (HAVE_extendsidi2) ! { ! convert_move (gen_lowpart (SImode, to), from, unsignedp); ! emit_unop_insn (CODE_FOR_extendsidi2, to, to, SIGN_EXTEND); ! } #endif #ifdef HAVE_slt *************** *** 365,369 **** emit_cmp_insn (gen_lowpart (SImode, to), gen_rtx (CONST_INT, VOIDmode, 0), ! 0, 0); NO_DEFER_POP; emit_jump_insn (gen_bge (label)); --- 405,409 ---- emit_cmp_insn (gen_lowpart (SImode, to), gen_rtx (CONST_INT, VOIDmode, 0), ! 0, 0, 0); NO_DEFER_POP; emit_jump_insn (gen_bge (label)); *************** *** 853,857 **** < (1 << (GET_MODE_BITSIZE (QImode) - 1)))) { ! emit_insn (gen_movstrqi (x, y, size)); return; } --- 893,898 ---- < (1 << (GET_MODE_BITSIZE (QImode) - 1)))) { ! emit_insn (gen_movstrqi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); return; } *************** *** 863,867 **** < (1 << (GET_MODE_BITSIZE (HImode) - 1)))) { ! emit_insn (gen_movstrhi (x, y, size)); return; } --- 904,909 ---- < (1 << (GET_MODE_BITSIZE (HImode) - 1)))) { ! emit_insn (gen_movstrhi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); return; } *************** *** 870,874 **** if (HAVE_movstrsi) { ! emit_insn (gen_movstrsi (x, y, size)); return; } --- 912,917 ---- if (HAVE_movstrsi) { ! emit_insn (gen_movstrsi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); return; } *************** *** 1246,1250 **** { emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp), ! x, size)); return; } --- 1289,1294 ---- { emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); return; } *************** *** 1257,1261 **** { emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp), ! x, size)); return; } --- 1301,1306 ---- { emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); return; } *************** *** 1264,1268 **** if (HAVE_movstrsi) { ! emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), x, size)); return; } --- 1309,1315 ---- if (HAVE_movstrsi) { ! emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); return; } *************** *** 1309,1312 **** --- 1356,1361 ---- else if (partial > 0) { + /* Scalar partly in registers. */ + int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD; int i; *************** *** 1316,1322 **** int skip = partial % (PARM_BOUNDARY / BITS_PER_WORD); int args_offset = INTVAL (args_so_far); - int stack_offset; - - stack_offset = 0; /* This is a placeholder for a questionable change. */ /* If we make space by pushing it, we might as well push --- 1365,1368 ---- *************** *** 1334,1337 **** --- 1380,1385 ---- /* Loop over all the words allocated on the stack for this arg. */ + /* We can do it by words, because any scalar bigger than a word + has a size a multiple of a word. */ #ifndef PUSH_ARGS_REVERSED for (i = not_stack; i < size; i++) *************** *** 1341,1363 **** if (i >= not_stack + skip) { if (GET_CODE (x) == MEM) ! emit_push_insn (gen_rtx (MEM, SImode, ! plus_constant (XEXP (x, 0), ! stack_offset + i * UNITS_PER_WORD)), ! SImode, 0, align, 0, 0, 0, args_addr, ! gen_rtx (CONST_INT, VOIDmode, ! args_offset + i * UNITS_PER_WORD)); else if (GET_CODE (x) == REG) ! emit_push_insn (gen_rtx (SUBREG, SImode, x, i), ! SImode, 0, align, 0, 0, 0, args_addr, ! gen_rtx (CONST_INT, VOIDmode, ! args_offset + i * UNITS_PER_WORD)); else if (x == dconst0_rtx) ! emit_push_insn (const0_rtx, ! SImode, 0, align, 0, 0, 0, args_addr, ! gen_rtx (CONST_INT, VOIDmode, ! args_offset + i * UNITS_PER_WORD)); else abort (); } } --- 1389,1417 ---- if (i >= not_stack + skip) { + rtx wd; + rtx addr; + /* Get the next word of the value in WD. */ if (GET_CODE (x) == MEM) ! { ! rtx addr = memory_address (SImode, ! plus_constant (XEXP (x, 0), ! i * UNITS_PER_WORD)); ! /* Copy to a reg, since machine may lack ! memory-to-memory move insns. */ ! wd = copy_to_reg (gen_rtx (MEM, SImode, addr)); ! } else if (GET_CODE (x) == REG) ! wd = gen_rtx (SUBREG, SImode, x, i); else if (x == dconst0_rtx) ! wd = const0_rtx; else abort (); + + emit_push_insn (wd, + SImode, 0, align, 0, 0, 0, args_addr, + gen_rtx (CONST_INT, VOIDmode, + args_offset + i * UNITS_PER_WORD)); + + } } *************** *** 1423,1428 **** for (count = 0; count < nargs; count++) { ! argvec[count].value = va_arg (p, rtx); ! argvec[count].mode = va_arg (p, enum machine_mode); } va_end (p); --- 1477,1503 ---- for (count = 0; count < nargs; count++) { ! rtx val = va_arg (p, rtx); ! enum machine_mode mode = va_arg (p, enum machine_mode); ! ! argvec[count].value = val; ! ! /* Convert the arg value to the mode the library wants. ! Also make sure it is a reasonable operand ! for a move or push insn. */ ! /* ??? It is wrong to do it here; must do it earlier ! where we know the signedness of the arg. */ ! if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode) ! { ! val = gen_reg_rtx (mode); ! convert_move (val, argvec[argnum].value, 0); ! } ! else if (GET_CODE (val) != REG && GET_CODE (val) != MEM ! ! && ! ((CONSTANT_P (val) || GET_CODE (val) == CONST_DOUBLE) ! && LEGITIMATE_CONSTANT_P (val))) ! val = force_operand (val, 0); ! ! argvec[count].value = val; ! argvec[count].mode = mode; } va_end (p); *************** *** 1475,1486 **** int arg_size; - /* Convert the arg value to the mode the library wants. */ - /* ??? It is wrong to do it here; must do it earlier - where we know the signedness of the arg. */ - if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode) - { - val = gen_reg_rtx (mode); - convert_move (val, argvec[argnum].value, 0); - } reg = FUNCTION_ARG (args_so_far, mode, 0, 1); regvec[argnum] = reg; --- 1550,1553 ---- *************** *** 1633,1637 **** ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to)) : VOIDmode), ! unsignedp); } --- 1700,1705 ---- ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to)) : VOIDmode), ! unsignedp, ! TYPE_ALIGN (TREE_TYPE (to))); } *************** *** 1793,1797 **** store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt), ! VOIDmode, 0); } } --- 1861,1865 ---- store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt), ! VOIDmode, 0, TYPE_ALIGN (TREE_TYPE (elt))); } } *************** *** 1848,1855 **** Otherwise, return an rtx for the value stored. This rtx has mode VALUE_MODE if that is convenient to do. ! In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. */ static rtx ! store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp) rtx target; int bitsize, bitpos; --- 1916,1925 ---- Otherwise, return an rtx for the value stored. This rtx has mode VALUE_MODE if that is convenient to do. ! In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. + ALIGN is the alignment that TARGET is known to have, measured in bytes. */ + static rtx ! store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, align) rtx target; int bitsize, bitpos; *************** *** 1858,1861 **** --- 1928,1932 ---- enum machine_mode value_mode; int unsignedp; + int align; { /* If the structure is in a register or if the component *************** *** 1868,1875 **** store_bit_field (target, bitsize, bitpos, mode, ! expand_expr (exp, 0, VOIDmode, 0)); if (value_mode != VOIDmode) return extract_bit_field (target, bitsize, bitpos, unsignedp, ! 0, value_mode, 0); return const0_rtx; } --- 1939,1947 ---- store_bit_field (target, bitsize, bitpos, mode, ! expand_expr (exp, 0, VOIDmode, 0), ! align); if (value_mode != VOIDmode) return extract_bit_field (target, bitsize, bitpos, unsignedp, ! 0, value_mode, 0, align); return const0_rtx; } *************** *** 1950,1954 **** \f /* expand_expr: generate code for computing expression EXP. ! An rtx for the computed value is returned. The value may be stored in TARGET if TARGET is nonzero. --- 2022,2027 ---- \f /* expand_expr: generate code for computing expression EXP. ! An rtx for the computed value is returned. The value is never null. ! In the case of a void EXP, const0_rtx is returned. The value may be stored in TARGET if TARGET is nonzero. *************** *** 2072,2075 **** --- 2145,2155 ---- if (DECL_RTL (exp) == 0) abort (); + /* This is the case of an array whose size is to be determined + from its initializer, while the initializer is still being parsed. + See expand_decl. */ + if (GET_CODE (DECL_RTL (exp)) == MEM + && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG) + return change_address (DECL_RTL (exp), BLKmode, + XEXP (DECL_RTL (exp), 0)); if (GET_CODE (DECL_RTL (exp)) == MEM && modifier != EXPAND_CONST_ADDRESS) *************** *** 2149,2153 **** /* For aggregate types with non-BLKmode modes, this should ideally construct a CONST_INT. */ ! return output_constant_def (exp); if (ignore) --- 2229,2240 ---- /* For aggregate types with non-BLKmode modes, this should ideally construct a CONST_INT. */ ! { ! rtx constructor = output_constant_def (exp); ! if (! memory_address_p (GET_MODE (constructor), ! XEXP (constructor, 0))) ! constructor = change_address (constructor, VOIDmode, ! XEXP (constructor, 0)); ! return constructor; ! } if (ignore) *************** *** 2318,2322 **** { return extract_bit_field (op0, bitsize, bitpos, unsignedp, ! target, mode, tmode); } /* Get a reference to just this component. */ --- 2405,2410 ---- { return extract_bit_field (op0, bitsize, bitpos, unsignedp, ! target, mode, tmode, ! TYPE_ALIGN (TREE_TYPE (tem))); } /* Get a reference to just this component. */ *************** *** 2670,2674 **** expand_expr (convert (TREE_TYPE (exp), integer_zero_node), 0, VOIDmode, 0), ! 0, 0); NO_DEFER_POP; emit_jump_insn (gen_bge (temp)); --- 2758,2762 ---- expand_expr (convert (TREE_TYPE (exp), integer_zero_node), 0, VOIDmode, 0), ! 0, 0, 0); NO_DEFER_POP; emit_jump_insn (gen_bge (temp)); *************** *** 2795,2799 **** temp = copy_to_reg (temp); op1 = gen_label_rtx (); ! emit_cmp_insn (temp, const0_rtx, 0, TREE_UNSIGNED (type)); emit_jump_insn (gen_beq (op1)); emit_move_insn (temp, const1_rtx); --- 2883,2887 ---- temp = copy_to_reg (temp); op1 = gen_label_rtx (); ! emit_cmp_insn (temp, const0_rtx, 0, TREE_UNSIGNED (type), 0); emit_jump_insn (gen_beq (op1)); emit_move_insn (temp, const1_rtx); *************** *** 3055,3058 **** --- 3143,3158 ---- abort (); + case BUILT_IN_SAVEREGS: + { + /* When this function is called, it means that registers must be + saved on entry to this function. So we migrate the + call to the first insn of this function. */ + rtx last = get_last_insn (); + /* Now really call the function. `expand_call' does not call + expand_builtin, so there is no danger of infinite recursion here. */ + expand_call (exp, target, 1); + reorder_insns (last, get_last_insn (), get_insns ()); + } + case BUILT_IN_ALLOCA: if (arglist == 0 *************** *** 3557,3560 **** --- 3657,3662 ---- /* Nonzero if this is a call to __builtin_new. */ int is_builtin_new; + /* Nonzero if this is a call to a `const' function. */ + int is_const = 0; /* Nonzero if there are BLKmode args whose data types require them *************** *** 3571,3574 **** --- 3673,3680 ---- rtx protected_stack = 0; + /* The last insn before the things that are intrinsically part of the call. + The beginning reg-note goes on the insn after this one. */ + rtx insn_before; + rtx old_stack_level = 0; int old_pending_adj; *************** *** 3602,3605 **** --- 3708,3714 ---- TREE_ADDRESSABLE (DECL_NAME (fndecl)) = 1; } + + if (TREE_READONLY (fndecl) && ! TREE_THIS_VOLATILE (fndecl)) + is_const = 1; } } *************** *** 3886,3889 **** --- 3995,4040 ---- } + /* Precompute all register parameters. It isn't safe to compute anything + once we have started filling any specific hard regs. + If this function call is cse'able, precompute all the parameters. */ + + reg_parm_seen = 0; + for (i = 0; i < num_actuals; i++) + if (args[i].reg != 0 || is_const) + { + if (args[i].reg != 0) + reg_parm_seen = 1; + args[i].value = expand_expr (args[i].tree_value, 0, VOIDmode, 0); + if (GET_CODE (args[i].value) != MEM + && ! CONSTANT_P (args[i].value) + && GET_CODE (args[i].value) != CONST_DOUBLE) + args[i].value + = force_reg (TYPE_MODE (TREE_TYPE (args[i].tree_value)), + args[i].value); + /* ANSI doesn't require a sequence point here, + but PCC has one, so this will avoid some problems. */ + emit_queue (); + } + + /* Get the function to call, in the form of RTL, if it is a constant. */ + if (fndecl && is_const) + { + /* Get a SYMBOL_REF rtx for the function address. */ + funexp = XEXP (DECL_RTL (fndecl), 0); + + #ifndef NO_FUNCTION_CSE + /* Pass the address through a pseudoreg, if desired, + before the "beginning" of the library call. + So this insn isn't "part of" the library call, in case that + is deleted, or cse'd. */ + if (! flag_no_function_cse) + funexp = copy_to_mode_reg (Pmode, funexp); + #endif + } + + /* Now we are about to start emitting insns that can be deleted + if the libcall is deleted. */ + insn_before = get_last_insn (); + /* If we have no actual push instructions, or shouldn't use them, or we need a variable amount of space, make space for all args right now. *************** *** 3962,3985 **** #endif /* STACK_GROWS_DOWNWARD */ - /* Precompute all register parameters. It isn't safe to compute anything - once we have started filling any specific hard regs. */ - - reg_parm_seen = 0; - for (i = 0; i < num_actuals; i++) - if (args[i].reg != 0) - { - reg_parm_seen = 1; - args[i].value = expand_expr (args[i].tree_value, 0, VOIDmode, 0); - if (GET_CODE (args[i].value) != MEM - && ! CONSTANT_P (args[i].value) - && GET_CODE (args[i].value) != CONST_DOUBLE) - args[i].value - = force_reg (TYPE_MODE (TREE_TYPE (args[i].tree_value)), - args[i].value); - /* ANSI doesn't require a sequence point here, - but PCC has one, so this will avoid some problems. */ - emit_queue (); - } - /* Get the function to call, in the form of RTL. */ if (fndecl) --- 4113,4116 ---- *************** *** 4089,4092 **** --- 4220,4231 ---- } + /* Notice functions that cannot return. + If optimizing, insns emitted below will be dead. + If not optimizing, they will exist, which is useful + if the user uses the `return' command in the debugger. */ + + if (fndecl && TREE_THIS_VOLATILE (fndecl)) + emit_barrier (); + /* For calls to __builtin_new, note that it can never return 0. This is because a new handler will be called, and 0 it not *************** *** 4108,4112 **** || ignore) { ! target = 0; } else if (structure_value_addr) --- 4247,4251 ---- || ignore) { ! target = const0_rtx; } else if (structure_value_addr) *************** *** 4143,4146 **** --- 4282,4309 ---- } + /* If call is cse'able, make appropriate pair of reg-notes around it. */ + if (is_const) + { + rtx insn_first = NEXT_INSN (insn_before); + rtx insn_last = get_last_insn (); + rtx note = 0; + + /* Construct an "equal form" for the value + which mentions all the arguments in order + as well as the function name. */ + for (i = 0; i < num_actuals; i++) + if (args[i].reg != 0 || is_const) + note = gen_rtx (EXPR_LIST, VOIDmode, args[i].value, note); + note = gen_rtx (EXPR_LIST, VOIDmode, XEXP (DECL_RTL (fndecl), 0), note); + + REG_NOTES (insn_last) + = gen_rtx (EXPR_LIST, REG_EQUAL, note, + gen_rtx (INSN_LIST, REG_RETVAL, insn_first, + REG_NOTES (insn_last))); + REG_NOTES (insn_first) + = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last, + REG_NOTES (insn_first)); + } + return target; } *************** *** 4271,4274 **** --- 4434,4478 ---- else if (arg->stack != 0) { + /* BLKmode parm, not entirely passed in registers, + and with space already allocated. */ + + tree sizetree = size_in_bytes (TREE_TYPE (pval)); + /* Round the size up to multiple of PARM_BOUNDARY bits. */ + tree s1 = convert_units (sizetree, BITS_PER_UNIT, PARM_BOUNDARY); + tree s2 = convert_units (s1, PARM_BOUNDARY, BITS_PER_UNIT); + + /* Find out if the parm needs padding, and whether above or below. */ + enum direction where_pad + = FUNCTION_ARG_PADDING (TYPE_MODE (TREE_TYPE (pval)), + expand_expr (sizetree, 0, VOIDmode, 0)); + + /* If it is padded below, adjust the stack address + upward over the padding. */ + + if (where_pad == downward) + { + rtx offset_rtx; + rtx address = XEXP (arg->stack, 0); + struct args_size stack_offset; + + stack_offset.constant = 0; + stack_offset.var = 0; + + /* Compute amount of padding. */ + ADD_PARM_SIZE (stack_offset, s2); + SUB_PARM_SIZE (stack_offset, sizetree); + offset_rtx = ARGS_SIZE_RTX (stack_offset); + + /* Adjust the address to store at. */ + if (GET_CODE (offset_rtx) == CONST_INT) + address = plus_constant (address, INTVAL (offset_rtx)); + else + { + address = gen_rtx (PLUS, Pmode, address, offset_rtx); + address = memory_address (QImode, address); + } + arg->stack = change_address (arg->stack, VOIDmode, address); + } + /* ARG->stack probably refers to the stack-pointer. If so, stabilize it, in case stack-pointer changes during evaluation. */ *************** *** 4298,4302 **** else { ! /* No place on the stack waiting for it, so just push. */ register rtx tem = arg->value ? arg->value : expand_expr (pval, 0, VOIDmode, 0); --- 4502,4507 ---- else { ! /* BLKmode, at least partly to be pushed. */ ! register rtx tem = arg->value ? arg->value : expand_expr (pval, 0, VOIDmode, 0); *************** *** 4538,4542 **** of each IF_THEN_ELSE. Note that inverting the condition would be incorrect for IEEE floating point with nans! */ ! invert_exp (pat, 0, 0); emit_jump_insn (pat); } --- 4743,4758 ---- of each IF_THEN_ELSE. Note that inverting the condition would be incorrect for IEEE floating point with nans! */ ! if (GET_CODE (pat) == SEQUENCE) ! { ! int i; ! /* We can invert a sequence if the only jump is at the end. */ ! for (i = 0; i < XVECLEN (pat, 0) - 1; i++) ! if (GET_CODE (XVECEXP (pat, 0, i)) == JUMP_INSN) ! abort (); ! invert_exp (PATTERN (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1))); ! } ! else ! invert_exp (pat, 0, 0); ! emit_jump_insn (pat); } *************** *** 4663,4667 **** emit_cmp_insn (op0, op1, (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0, ! unsignedp); return gen_rtx ((unsignedp ? unsigned_forward : signed_forward), --- 4879,4884 ---- emit_cmp_insn (op0, op1, (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0, ! unsignedp, ! TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); return gen_rtx ((unsignedp ? unsigned_forward : signed_forward), *************** *** 4703,4707 **** GET_MODE_BITSIZE (mode)); ! emit_cmp_insn (op0, op1, 0, unsignedp); return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx); --- 4920,4924 ---- GET_MODE_BITSIZE (mode)); ! emit_cmp_insn (op0, op1, 0, unsignedp, 0); return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx); *************** *** 4823,4827 **** register rtx temp; ! emit_cmp_insn (range, index, 0); emit_jump_insn (gen_bltu (default_label)); /* If flag_force_addr were to affect this address --- 5040,5044 ---- register rtx temp; ! emit_cmp_insn (range, index, 0, 0, 0); emit_jump_insn (gen_bltu (default_label)); /* If flag_force_addr were to affect this address diff -rc2N gcc-1.32/final.c gcc-1.33/final.c *** gcc-1.32/final.c Tue Dec 20 01:50:32 1988 --- gcc-1.33/final.c Mon Jan 16 23:41:07 1989 *************** *** 54,62 **** #include "gdbfiles.h" #include "flags.h" /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ #ifdef DBX_DEBUGGING_INFO ! #include <stab.h> ! #endif /* .stabd code for line number. */ --- 54,67 ---- #include "gdbfiles.h" #include "flags.h" + #include "real.h" /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ #ifdef DBX_DEBUGGING_INFO ! #ifdef USG ! #include "stab.h" /* If doing DBX on sysV, use our own stab.h. */ ! #else ! #include <stab.h> /* On BSD, use the system's stab.h. */ ! #endif /* not USG */ ! #endif /* DBX_DEBUGGING_INFO */ /* .stabd code for line number. */ *************** *** 400,403 **** --- 405,409 ---- register rtx insn; register int i; + rtx last_ignored_compare = 0; init_recog (); *************** *** 656,664 **** /* or if anything in it is volatile. */ && ! volatile_refs_p (PATTERN (insn))) ! /* We don't really delete the insn; just ignore it. */ ! break; } } /* If this is a conditional branch, maybe modify it if the cc's are in a nonstandard state --- 662,675 ---- /* or if anything in it is volatile. */ && ! volatile_refs_p (PATTERN (insn))) ! { ! /* We don't really delete the insn; just ignore it. */ ! last_ignored_compare = insn; ! break; ! } } } + reinsert_compare: + /* If this is a conditional branch, maybe modify it if the cc's are in a nonstandard state *************** *** 736,739 **** --- 747,760 ---- #endif /* STORE_FLAG_VALUE */ + /* Do machine-specific peephole optimizations if desired. */ + + if (optimize && !flag_no_peephole) + { + peephole (insn); + + /* PEEPHOLE might have changed this. */ + body = PATTERN (insn); + } + /* Try to recognize the instruction. If successful, verify that the operands satisfy the *************** *** 776,780 **** template = insn_template[insn_code_number]; if (template == 0) ! template = (*insn_outfun[insn_code_number]) (recog_operand, insn); if (prescan > 0) --- 797,815 ---- template = insn_template[insn_code_number]; if (template == 0) ! { ! template = (*insn_outfun[insn_code_number]) (recog_operand, insn); ! ! /* If the C code returns 0, it means that it is a jump insn ! which follows a deleted test insn, and that test insn ! needs to be reinserted. */ ! if (template == 0) ! { ! if (PREV_INSN (insn) != last_ignored_compare) ! abort (); ! insn = PREV_INSN (insn); ! body = PATTERN (insn); ! goto reinsert_compare; ! } ! } if (prescan > 0) *************** *** 784,787 **** --- 819,825 ---- output_asm_insn (template, recog_operand); + + /* Mark this insn as having been output. */ + INSN_DELETED_P (insn) = 1; } } *************** *** 1323,1330 **** { /* We can use %d if the number is <32 bits and positive. */ ! if (XINT (x, 1) || XINT (x, 0) < 0) ! fprintf (file, "0x%x%08x", XINT (x, 1), XINT (x, 0)); else ! fprintf (file, "%d", XINT (x, 0)); } else --- 1361,1369 ---- { /* We can use %d if the number is <32 bits and positive. */ ! if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) ! fprintf (file, "0x%x%08x", ! CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); else ! fprintf (file, "%d", CONST_DOUBLE_LOW (x)); } else diff -rc2N gcc-1.32/fixincludes gcc-1.33/fixincludes *** gcc-1.32/fixincludes Tue Dec 13 17:46:52 1988 --- gcc-1.33/fixincludes Sat Jan 14 16:03:23 1989 *************** *** 9,13 **** LIB=/usr/local/lib/gcc-include ! mkdir $LIB > /dev/null 2>&1 echo 'Finding header files:' --- 9,18 ---- LIB=/usr/local/lib/gcc-include ! echo 'Making directories:' ! cd /usr/include ! files=`find . -type d -print` ! for file in $files; do ! mkdir $LIB/$file > /dev/null 2>&1 ! done echo 'Finding header files:' *************** *** 20,25 **** if [ -r $file ]; then cp $file ${LIB}/$file >/dev/null 2>&1 \ - || (mkdir `dirname ${LIB}/$file` \ - && cp $file ${LIB}/$file) \ || echo "Can't copy $file" chmod +w ${LIB}/$file --- 25,28 ---- *************** *** 45,50 **** if [ ! -r ${LIB}/$file ]; then cp $file ${LIB}/$file >/dev/null 2>&1 \ - || (mkdir `dirname ${LIB}/$file` \ - && cp $file ${LIB}/$file) \ || echo "Can't copy $file" chmod +w ${LIB}/$file --- 48,51 ---- diff -rc2N gcc-1.32/flow.c gcc-1.33/flow.c *** gcc-1.32/flow.c Sun Dec 18 15:19:37 1988 --- gcc-1.33/flow.c Sun Jan 15 01:19:31 1989 *************** *** 1188,1192 **** register int offset = regno / REGSET_ELT_BITS; register int bit = 1 << (regno % REGSET_ELT_BITS); ! return (needed[offset] & bit) == 0; } } --- 1188,1193 ---- register int offset = regno / REGSET_ELT_BITS; register int bit = 1 << (regno % REGSET_ELT_BITS); ! return (! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]) ! && (needed[offset] & bit) == 0); } } *************** *** 1251,1254 **** --- 1252,1258 ---- int regno; { + if (n_basic_blocks == 0) + return 0; + return (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] & (1 << (regno % REGSET_ELT_BITS))); *************** *** 1332,1336 **** if (GET_CODE (reg) == REG && (regno = REGNO (reg), regno != FRAME_POINTER_REGNUM) ! && regno != ARG_POINTER_REGNUM) /* && regno != STACK_POINTER_REGNUM) -- let's try without this. */ { --- 1336,1341 ---- if (GET_CODE (reg) == REG && (regno = REGNO (reg), regno != FRAME_POINTER_REGNUM) ! && regno != ARG_POINTER_REGNUM ! && ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])) /* && regno != STACK_POINTER_REGNUM) -- let's try without this. */ { *************** *** 1674,1678 **** if (GET_CODE (testreg) == REG && (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM) ! && regno != ARG_POINTER_REGNUM) #if 0 /* This was added in 1.25, but screws up death notes for hard regs. It probably isn't really needed anyway. */ --- 1679,1684 ---- if (GET_CODE (testreg) == REG && (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM) ! && regno != ARG_POINTER_REGNUM ! && ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])) #if 0 /* This was added in 1.25, but screws up death notes for hard regs. It probably isn't really needed anyway. */ diff -rc2N gcc-1.32/fold-const.c gcc-1.33/fold-const.c *** gcc-1.32/fold-const.c Tue Dec 6 21:21:29 1988 --- gcc-1.33/fold-const.c Sun Jan 1 03:46:07 1989 *************** *** 682,686 **** { enum tree_code code = TREE_CODE (TREE_OPERAND (in, 0)); ! if (code == INTEGER_CST || code == REAL_CST) { *conp = TREE_OPERAND (in, 0); --- 682,686 ---- { enum tree_code code = TREE_CODE (TREE_OPERAND (in, 0)); ! if (code == INTEGER_CST) { *conp = TREE_OPERAND (in, 0); *************** *** 705,710 **** It could also be the address of a static variable. We cannot negate that, so give up. */ ! if (TREE_CODE (*conp) == INTEGER_CST ! || TREE_CODE (*conp) == REAL_CST) *conp = combine (MINUS_EXPR, integer_zero_node, *conp); else --- 705,709 ---- It could also be the address of a static variable. We cannot negate that, so give up. */ ! if (TREE_CODE (*conp) == INTEGER_CST) *conp = combine (MINUS_EXPR, integer_zero_node, *conp); else *************** *** 844,852 **** return t; } if (TREE_CODE (arg1) == REAL_CST) { ! register double d1 = TREE_REAL_CST (arg1); ! register double d2 = TREE_REAL_CST (arg2); ! register double value; if (setjmp (combine_error)) --- 843,852 ---- return t; } + #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) if (TREE_CODE (arg1) == REAL_CST) { ! register REAL_VALUE_TYPE d1 = TREE_REAL_CST (arg1); ! register REAL_VALUE_TYPE d2 = TREE_REAL_CST (arg2); ! register REAL_VALUE_TYPE value; if (setjmp (combine_error)) *************** *** 854,857 **** --- 854,860 ---- set_float_handler (combine_error); + #ifdef REAL_ARITHMETIC + REAL_ARITHMETIC (value, code, d1, d2); + #else switch (code) { *************** *** 886,892 **** --- 889,897 ---- abort (); } + #endif /* no REAL_ARITHMETIC */ set_float_handler (0); return build_real (TREE_TYPE (arg1), value); } + #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ if (TREE_CODE (arg1) == COMPLEX_CST) { *************** *** 969,975 **** force_fit_type (t); } else if (TREE_CODE (arg1) == REAL_CST) ! t = build_int_2 ((int) TREE_REAL_CST (arg1), ! (int) (TREE_REAL_CST (arg1) / 0x10000 / 0x10000)); TREE_TYPE (t) = type; } --- 974,990 ---- force_fit_type (t); } + #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) else if (TREE_CODE (arg1) == REAL_CST) ! { ! #ifndef REAL_ARITHMETIC ! t = build_int_2 ((int) TREE_REAL_CST (arg1), ! (int) (TREE_REAL_CST (arg1) / 0x10000 / 0x10000)); ! #else ! int low, high; ! REAL_VALUE_TO_INT (low, high, TREE_REAL_CST (arg1)); ! t = build_int_2 (low, high); ! #endif ! } ! #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ TREE_TYPE (t) = type; } *************** *** 976,982 **** else if (TREE_CODE (type) == REAL_TYPE) { if (TREE_CODE (arg1) == INTEGER_CST) return build_real_from_int_cst (type, arg1); ! else if (TREE_CODE (arg1) == REAL_CST) return build_real (type, TREE_REAL_CST (arg1)); } --- 991,999 ---- else if (TREE_CODE (type) == REAL_TYPE) { + #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) if (TREE_CODE (arg1) == INTEGER_CST) return build_real_from_int_cst (type, arg1); ! #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ ! if (TREE_CODE (arg1) == REAL_CST) return build_real (type, TREE_REAL_CST (arg1)); } *************** *** 1022,1025 **** --- 1039,1043 ---- { register tree t = expr; + tree type = TREE_TYPE (expr); register tree arg0, arg1; register enum tree_code code = TREE_CODE (t); *************** *** 1056,1060 **** continue; /* Valid for CALL_EXPR, at least. */ if (TREE_CODE (TREE_OPERAND (t, i)) != INTEGER_CST ! && TREE_CODE (TREE_OPERAND (t, i)) != REAL_CST) /* Note that TREE_LITERAL isn't enough: static var addresses are constant but we can't --- 1074,1081 ---- continue; /* Valid for CALL_EXPR, at least. */ if (TREE_CODE (TREE_OPERAND (t, i)) != INTEGER_CST ! #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) ! && TREE_CODE (TREE_OPERAND (t, i)) != REAL_CST ! #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ ! ) /* Note that TREE_LITERAL isn't enough: static var addresses are constant but we can't *************** *** 1111,1120 **** t = build_int_2 (- TREE_INT_CST_LOW (arg0), ~ TREE_INT_CST_HIGH (arg0)); ! TREE_TYPE (t) = TREE_TYPE (expr); force_fit_type (t); } else if (TREE_CODE (arg0) == REAL_CST) ! t = build_real (TREE_TYPE (expr), - TREE_REAL_CST (arg0)); ! TREE_TYPE (t) = TREE_TYPE (expr); } return t; --- 1132,1141 ---- t = build_int_2 (- TREE_INT_CST_LOW (arg0), ~ TREE_INT_CST_HIGH (arg0)); ! TREE_TYPE (t) = type; force_fit_type (t); } else if (TREE_CODE (arg0) == REAL_CST) ! t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0))); ! TREE_TYPE (t) = type; } return t; *************** *** 1125,1129 **** if (TREE_CODE (arg0) == INTEGER_CST) { ! if (! TREE_UNSIGNED (TREE_TYPE (expr)) || TREE_INT_CST_HIGH (arg0) < 0) { --- 1146,1150 ---- if (TREE_CODE (arg0) == INTEGER_CST) { ! if (! TREE_UNSIGNED (type) || TREE_INT_CST_HIGH (arg0) < 0) { *************** *** 1138,1144 **** { if (TREE_REAL_CST (arg0) < 0) ! t = build_real (TREE_TYPE (expr), - TREE_REAL_CST (arg0)); } ! TREE_TYPE (t) = TREE_TYPE (expr); } return t; --- 1159,1166 ---- { if (TREE_REAL_CST (arg0) < 0) ! t = build_real (type, ! REAL_VALUE_NEGATE (TREE_REAL_CST (arg0))); } ! TREE_TYPE (t) = type; } return t; *************** *** 1150,1154 **** t = build_int_2 (~ TREE_INT_CST_LOW (arg0), ~ TREE_INT_CST_HIGH (arg0)); ! TREE_TYPE (t) = TREE_TYPE (expr); force_fit_type (t); } --- 1172,1176 ---- t = build_int_2 (~ TREE_INT_CST_LOW (arg0), ~ TREE_INT_CST_HIGH (arg0)); ! TREE_TYPE (t) = type; force_fit_type (t); } *************** *** 1157,1163 **** case PLUS_EXPR: if (integer_zerop (arg0)) ! return convert (TREE_TYPE (expr), arg1); if (integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg0); associate: /* In most languages, can't associate operations on floats --- 1179,1185 ---- case PLUS_EXPR: if (integer_zerop (arg0)) ! return convert (type, arg1); if (integer_zerop (arg1)) ! return convert (type, arg0); associate: /* In most languages, can't associate operations on floats *************** *** 1164,1168 **** through parentheses. Rather than remember where the parentheses were, we don't associate floats at all. It shouldn't matter much. */ ! if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) goto binary; /* The varsign == -1 cases happen only for addition and subtraction. --- 1186,1190 ---- through parentheses. Rather than remember where the parentheses were, we don't associate floats at all. It shouldn't matter much. */ ! if (TREE_CODE (type) == REAL_TYPE) goto binary; /* The varsign == -1 cases happen only for addition and subtraction. *************** *** 1248,1254 **** case MINUS_EXPR: if (! wins && integer_zerop (arg0)) ! return build (NEGATE_EXPR, TREE_TYPE (expr), arg1); if (integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg0); /* Fold &x - &x. This can happen from &x.foo - &x. */ if (operand_equal_p (arg0, arg1)) --- 1270,1276 ---- case MINUS_EXPR: if (! wins && integer_zerop (arg0)) ! return build (NEGATE_EXPR, type, arg1); if (integer_zerop (arg1)) ! return convert (type, arg0); /* Fold &x - &x. This can happen from &x.foo - &x. */ if (operand_equal_p (arg0, arg1)) *************** *** 1258,1268 **** case MULT_EXPR: if (!loses && integer_zerop (arg0)) ! return convert (TREE_TYPE (expr), arg0); if (!loses && integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg1); if (integer_onep (arg0)) ! return convert (TREE_TYPE (expr), arg1); if (integer_onep (arg1)) ! return convert (TREE_TYPE (expr), arg0); goto associate; --- 1280,1290 ---- case MULT_EXPR: if (!loses && integer_zerop (arg0)) ! return convert (type, arg0); if (!loses && integer_zerop (arg1)) ! return convert (type, arg1); if (integer_onep (arg0)) ! return convert (type, arg1); if (integer_onep (arg1)) ! return convert (type, arg0); goto associate; *************** *** 1269,1280 **** case BIT_IOR_EXPR: if (!loses && integer_all_onesp (arg0)) ! return convert (TREE_TYPE (expr), arg0); if (!loses && integer_all_onesp (arg1)) ! return convert (TREE_TYPE (expr), arg1); case BIT_XOR_EXPR: if (integer_zerop (arg0)) ! return convert (TREE_TYPE (expr), arg1); if (integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg0); goto associate; --- 1291,1302 ---- case BIT_IOR_EXPR: if (!loses && integer_all_onesp (arg0)) ! return convert (type, arg0); if (!loses && integer_all_onesp (arg1)) ! return convert (type, arg1); case BIT_XOR_EXPR: if (integer_zerop (arg0)) ! return convert (type, arg1); if (integer_zerop (arg1)) ! return convert (type, arg0); goto associate; *************** *** 1281,1292 **** case BIT_AND_EXPR: if (integer_all_onesp (arg0)) ! return convert (TREE_TYPE (expr), arg1); if (integer_all_onesp (arg1)) ! return convert (TREE_TYPE (expr), arg0); if (!loses && integer_zerop (arg0)) ! return convert (TREE_TYPE (expr), arg0); if (!loses && integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg1); ! /* Simplify (int)((unsigned char)x & 0x377) into (int)(unsigned char)x. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == NOP_EXPR && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))) --- 1303,1314 ---- case BIT_AND_EXPR: if (integer_all_onesp (arg0)) ! return convert (type, arg1); if (integer_all_onesp (arg1)) ! return convert (type, arg0); if (!loses && integer_zerop (arg0)) ! return convert (type, arg0); if (!loses && integer_zerop (arg1)) ! return convert (type, arg1); ! /* Simplify ((int)c & 0x377) into (int)c, if c is unsigned char. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == NOP_EXPR && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))) *************** *** 1295,1299 **** if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT && (~TREE_INT_CST_LOW (arg0) & ((1 << prec) - 1)) == 0) ! return convert (TREE_TYPE (expr), arg1); } if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR --- 1317,1321 ---- if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT && (~TREE_INT_CST_LOW (arg0) & ((1 << prec) - 1)) == 0) ! return build (NOP_EXPR, type, TREE_OPERAND (arg1, 0)); } if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR *************** *** 1303,1307 **** if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT && (~TREE_INT_CST_LOW (arg1) & ((1 << prec) - 1)) == 0) ! return convert (TREE_TYPE (expr), arg0); } goto associate; --- 1325,1329 ---- if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT && (~TREE_INT_CST_LOW (arg1) & ((1 << prec) - 1)) == 0) ! return build (NOP_EXPR, type, TREE_OPERAND (arg0, 0)); } goto associate; *************** *** 1309,1317 **** case BIT_ANDTC_EXPR: if (integer_all_onesp (arg0)) ! return convert (TREE_TYPE (expr), arg1); if (integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg0); if (!loses && integer_zerop (arg0)) ! return convert (TREE_TYPE (expr), arg0); if (!loses && integer_all_onesp (arg1)) return combine (code, arg1, arg1); --- 1331,1339 ---- case BIT_ANDTC_EXPR: if (integer_all_onesp (arg0)) ! return convert (type, arg1); if (integer_zerop (arg1)) ! return convert (type, arg0); if (!loses && integer_zerop (arg0)) ! return convert (type, arg0); if (!loses && integer_all_onesp (arg1)) return combine (code, arg1, arg1); *************** *** 1324,1328 **** case RDIV_EXPR: if (integer_onep (arg1)) ! return convert (TREE_TYPE (expr), arg0); goto binary; --- 1346,1350 ---- case RDIV_EXPR: if (integer_onep (arg1)) ! return convert (type, arg0); goto binary; *************** *** 1340,1344 **** case RROTATE_EXPR: if (integer_zerop (arg1)) ! return convert (TREE_TYPE (expr), arg0); goto binary; --- 1362,1366 ---- case RROTATE_EXPR: if (integer_zerop (arg1)) ! return convert (type, arg0); goto binary; *************** *** 1377,1381 **** t = build_int_2 ((TREE_REAL_CST (arg0) && TREE_REAL_CST (arg1)), 0); ! TREE_TYPE (t) = TREE_TYPE (expr); } return t; --- 1399,1403 ---- t = build_int_2 ((TREE_REAL_CST (arg0) && TREE_REAL_CST (arg1)), 0); ! TREE_TYPE (t) = type; } return t; *************** *** 1393,1397 **** t = build_int_2 ((TREE_REAL_CST (arg0) || TREE_REAL_CST (arg1)), 0); ! TREE_TYPE (t) = TREE_TYPE (expr); } return t; --- 1415,1419 ---- t = build_int_2 ((TREE_REAL_CST (arg0) || TREE_REAL_CST (arg1)), 0); ! TREE_TYPE (t) = type; } return t; *************** *** 1555,1561 **** { if (code == EQ_EXPR || code == NE_EXPR) ! t = build_int_2 (TREE_REAL_CST (arg0) == TREE_REAL_CST (arg1), 0); else ! t = build_int_2 (TREE_REAL_CST (arg0) < TREE_REAL_CST (arg1), 0); } else --- 1577,1587 ---- { if (code == EQ_EXPR || code == NE_EXPR) ! t = build_int_2 (REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), ! TREE_REAL_CST (arg1)), ! 0); else ! t = build_int_2 (REAL_VALUES_LESS (TREE_REAL_CST (arg0), ! TREE_REAL_CST (arg1)), ! 0); } else *************** *** 1565,1569 **** if (code == GE_EXPR || code == LE_EXPR || code == NE_EXPR) TREE_INT_CST_LOW (t) ^= 1; ! TREE_TYPE (t) = TREE_TYPE (expr); return t; --- 1591,1595 ---- if (code == GE_EXPR || code == LE_EXPR || code == NE_EXPR) TREE_INT_CST_LOW (t) ^= 1; ! TREE_TYPE (t) = type; return t; diff -rc2N gcc-1.32/gcc.1 gcc-1.33/gcc.1 *** gcc-1.32/gcc.1 Sun Nov 13 10:30:15 1988 --- gcc-1.33/gcc.1 Fri Jan 20 01:41:28 1989 *************** *** 1,6 **** .\ " ====================== ! .\ " This version is 1.24. .\ " ====================== ! .TH GCC 1 "8 July 1988" "Version 1.24" .SH NAME gcc \- GNU project C Compiler --- 1,6 ---- .\ " ====================== ! .\ " This version is 1.33. .\ " ====================== ! .TH GCC 1 "19 January 1989" "Version 1.33" .SH NAME gcc \- GNU project C Compiler *************** *** 14,22 **** occasionally, because the GNU project does not use nroff. For complete, current documentation, refer to the Info file ! .B internals or the DVI file ! .B internals.dvi which are made from the Texinfo source file ! .B internals.texinfo \. .SH DESCRIPTION --- 14,22 ---- occasionally, because the GNU project does not use nroff. For complete, current documentation, refer to the Info file ! .B gcc or the DVI file ! .B gcc.dvi which are made from the Texinfo source file ! .B gcc.texinfo \. .SH DESCRIPTION *************** *** 210,213 **** --- 210,219 ---- promote to \fBunsigned int\fR. .br + \(** Out-of-range floating point literals are not an error. + .br + \(** All automatic variables not declared \fBregister\fR are preserved by + \fBlongjmp\fR. Ordinarily, GNU C follows ANSI C: automatic variables + not declared \fBvolatile\fR may be clobbered. + .br \(** In the preprocessor, comments convert to nothing at all, rather than to a space. *************** *** 214,233 **** This allows traditional token concatenation. .br ! \(** In the preprocessor, single and double quote characters are ! ignored when scanning macro definitions, so that macro arguments ! can be replaced even within a string or character constant. ! Quote characters are also ignored when skipping text inside ! a failing conditional directive. ! .TP ! .B \-pedantic ! Issue all the warnings demanded by strict ANSI standard C; ! reject all programs that use forbidden extensions. ! Valid ANSI standard C programs should compile properly with or ! without this option (though a rare few will require `\fB\-ansi\fR'. ! However, without this option, certain GNU extensions and ! traditional C features are supported as well. ! With this option, they are rejected. ! There is no reason to \fIuse\fR ! this option; it exists only to satisfy pedants. .TP .B \-O --- 220,237 ---- This allows traditional token concatenation. .br ! \(** In the preprocessor, macro arguments are recognized within string ! constants in a macro definition (and their values are stringified, ! though without additional quote marks, when they appear in such a ! context). The preprocessor also considers a string constant to end ! at a newline. ! .br ! \(** The predefined macro \fB__STDC__\fR is not defined when you ! use `\fB\-traditional\fR', but \fB__GNUC__\fR is (since the GNU extensions ! which \fB__GNUC__\fR indicates are not affected by `\fB\-traditional\fR'). ! If you need to write header files that work ! differently depending on whether `\fB\-traditional\fR' is in use, by ! testing both of these predefined macros you can distinguish four ! situations: GNU C, traditional GNU C, other ANSI C compilers, and ! other old C compilers. .TP .B \-O *************** *** 234,237 **** --- 238,242 ---- Optimize. Optimizing compilation takes somewhat more time, and a lot more memory for a large function. + .br Without `\fB\-O\fR', the compiler's goal is to reduce the cost of compilation and to make debugging produce the expected results. *************** *** 244,247 **** --- 249,253 ---- The resulting compiled code is a little worse than produced by PCC without `\fB\-O\fR'. + .br With `\fB\-O\fR', the compiler tries to reduce code size and execution time. Some of the `\fB\-f\fR' options described below turn specific *************** *** 249,256 **** .TP .B \-g ! Produce debugging information in DBX format. ! Unlike most other C compilers, ! GNU CC allows you to use `\fB\-g\fR' with `\fB\-O\fR'. ! The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; --- 255,264 ---- .TP .B \-g ! Produce debugging information in the operating system's native format ! (for DBX or SDB). GDB also can work with this debugging information. ! Unlike most other C compilers, GNU CC allows you to use `\fB\-g\fR' ! with`\fB\-O\fR'. ! .br ! The short cuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; *************** *** 266,269 **** --- 274,283 ---- This requires the GNU assembler and linker in order to work. + This feature will probably be eliminated. It was intended to enable + GDB to read the symbol table faster, but it doesn't result in enough + of a speedup to be worth the larger object files and executables. We + are working on other ways of making GDB start even faster, which work + with DBX format debugging information and could be made to work with + SDB format. .TP .B \-w *************** *** 308,314 **** certain functions (including \fBabort\fR and \fBlongjmp\fR) will never return. ! .TP ! .B \-Wunused ! Warn whenever a local variable is unused aside from its declaration. .TP .B \-Wimplicit --- 322,327 ---- certain functions (including \fBabort\fR and \fBlongjmp\fR) will never return. ! .br ! \(** An expression-statement contains no side effects. .TP .B \-Wimplicit *************** *** 321,327 **** --- 334,355 ---- is not \fBvoid\fR. .TP + .B \-Wunused + Warn whenever a local variable is unused aside from its declaration. + .TP .B \-Wcomment Warn whenever a comment-start sequence `/*' appears in a comment. .TP + .B \-Wall + All of the above \fB\-W\fR options combined. + .TP + .B \-Wwrite-strings + Give string constants the type \fBconst char[\fIlength\fB]\fR so that + copying the address of one into a non-\fBconst char *\fR + pointer will get a warning. These warnings will help you find at + compile time code that can try to write into a string constant, but + only if you have been very careful about using \fBconst\fR in + declarations and prototypes. Otherwise, it will just be a nuisance; + this is why we did not make \fB\-Wall\fR request these warnings. + .TP .B \-p Generate extra code to write profile information suitable for the *************** *** 364,367 **** --- 392,397 ---- .TP 10 .B \ \ \ \ \ \ \ \ \-m68020 + .TP 10 + .B \ \ \ \ \ \ \ \ \-mc68020 Generate output for a 68020 (rather than a 68000). This is the default if you use the unmodified sources. *************** *** 368,371 **** --- 398,403 ---- .TP 10 .B \ \ \ \ \ \ \ \ \-m68000 + .TP 10 + .B \ \ \ \ \ \ \ \ \-mc68000 Generate output for a 68000 (rather than a 68020). .TP 10 *************** *** 374,377 **** --- 406,412 ---- This is the default if you use the unmodified sources. .TP 10 + .B \ \ \ \ \ \ \ \ \-mfpa + Generate output containing Sun FPA instructions for floating point. + .TP 10 .B \ \ \ \ \ \ \ \ \-msoft-float Generate output containing library calls for floating point. *************** *** 411,419 **** instruction is supported by the 68010 and 68020 processors, but not by the 68000. ! .IP ! These are the `\fB\-m\fR' options defined in the VAX machine description: .TP 10 .B \ \ \ \ \ \ \ \ \-munix ! Do not output certain jump instructions (\fBaobleq\fP and so on) that the Unix assembler for the VAX cannot handle across long ranges. --- 446,455 ---- instruction is supported by the 68010 and 68020 processors, but not by the 68000. ! .IP ! These are the `\fB\-m\fR' options defined in the VAX ! machine description: .TP 10 .B \ \ \ \ \ \ \ \ \-munix ! Do not output certain jump instructions (\fBaobleq\fR and so on) that the Unix assembler for the VAX cannot handle across long ranges. *************** *** 422,428 **** Do output those jump instructions, on the assumption that you will assemble with the GNU assembler. .TP 5 .BI \-f "flag" ! Specify machine-independent flags. These are the flags: .TP 10 .B \ \ \ \ \ \ \ \ \-ffloat-store --- 458,471 ---- Do output those jump instructions, on the assumption that you will assemble with the GNU assembler. + .TP 10 + .B \ \ \ \ \ \ \ \ \-mg + Output code for g-format floating point numbers instead of d-format. .TP 5 .BI \-f "flag" ! Specify machine-independent flags. Most flags have both positive and ! negative forms; the negative form of `\fB\-ffoo\fR' would ! be `\fB\-fno-foo\fR'. In the table below, only one of the forms is ! listed---the one which is not the default. You can figure out the ! other form by either removing `\fBno-\fR' or adding it. .TP 10 .B \ \ \ \ \ \ \ \ \-ffloat-store *************** *** 501,504 **** --- 544,551 ---- is a very bad idea; ``constants'' should be constant. .TP 10 + .B \ \ \ \ \ \ \ \ \-fcond-mismatch + Allow conditional expressions with mismatched types in the second and + third arguments. The value of such an expression is void. + .TP 10 .B \ \ \ \ \ \ \ \ \-fno-function-cse Do not put function addresses in registers; make each instruction that *************** *** 511,514 **** --- 558,568 ---- Consider all memory references through pointers to be volatile. .TP 10 + .B \ \ \ \ \ \ \ \ \-fshared-data + Requests that the data and non-\fBconst\fR variables of this + compilation be shared data rather than private data. The distinction + makes sense only on certain operating systems, where shared data is + shared between processes running the same program, while private data + exists in one copy per process. + .TP 10 .B \ \ \ \ \ \ \ \ \-funsigned-char Let the type \fBchar\f be the unsigned, like \fBunsigned char\fR. *************** *** 521,527 **** --- 575,585 ---- or \fBunsigned char\fR, even though its behavior is always just like one of those two. + Note that this is equivalent to `\fB\-fno-signed-char\fR', which is the + negative form of `\fB\-fsigned-char\fR'. .TP 10 .B \ \ \ \ \ \ \ \ \-fsigned-char Let the type \fBchar\fR be the same as \fBsigned char\fR. + Note that this is equivalent to `\fB\-fno-unsigned-char\fR', which is + the negative form of `\fB\-funsigned-char\fR'. .TP 10 .B \ \ \ \ \ \ \ \ \-ffixed-\fIreg\fR *************** *** 533,536 **** --- 591,596 ---- the \fBREGISTER_NAMES\fR macro in the machine description macro file. + This flag does not have a negative form, because it specifies a + three-way choice. .TP 10 .B \ \ \ \ \ \ \ \ \-fcall-used-\fIreg\fR *************** *** 544,547 **** --- 604,609 ---- in the machine's execution model, such as the stack pointer or frame pointer, will produce disastrous results. + This flag does not have a negative form, because it specifies a + three-way choice. .TP 10 .B \ \ \ \ \ \ \ \ \-fcall-saved-\fIreg\fR *************** *** 555,559 **** frame pointer, will produce disastrous results. A different sort of disaster will result from the use of this ! flag for a register in which function values are may be returned. .TP .BI \-d "letters" --- 617,623 ---- frame pointer, will produce disastrous results. A different sort of disaster will result from the use of this ! flag for a register in which function values may be returned. ! This flag does not have a negative form, because it specifies a ! three-way choice. .TP .BI \-d "letters" *************** *** 591,594 **** --- 655,669 ---- .B \ \ \ \ \ \ \ \ m Print statistics on memory usage, at the end of the run. + .TP + .B \-pedantic + Issue all the warnings demanded by strict ANSI standard C; + reject all programs that use forbidden extensions. + Valid ANSI standard C programs should compile properly with or + without this option (though a rare few will require `\fB\-ansi\fR'. + However, without this option, certain GNU extensions and + traditional C features are supported as well. + With this option, they are rejected. + There is no reason to \fIuse\fR + this option; it exists only to satisfy pedants. .SH FILES .ta \w'/usr/local/lib/gcc-gnulib 'u *************** *** 614,617 **** --- 689,694 ---- /usr/include standard directory for `#include' files .br + /usr/include/gcc-include standard gcc directory for `#include' files + .br .SH "SEE ALSO" adb(1), ld(1), dbx(1), as(1) *************** *** 621,625 **** in such a way that they can be easily reproduced. .SH COPYING ! Copyright (C) 1988 Richard M. Stallman. .br Permission is granted to make and distribute verbatim copies of --- 698,702 ---- in such a way that they can be easily reproduced. .SH COPYING ! Copyright (c) 1988 Free Software Foundation, Inc. .br Permission is granted to make and distribute verbatim copies of *************** *** 632,637 **** permission notice identical to this one. .br ! Permission is granted to copy and distribute translations of this manual ! into another language, under the above conditions for modified versions. .SH AUTHORS See the GNU CC Manual for the contributors to GNU CC. --- 709,717 ---- permission notice identical to this one. .br ! Permission is granted to copy and distribute translations of this ! manual into another language, under the above conditions for modified ! versions, except that this permission notice may be included in ! translations approved by the Free Software Foundation instead of in ! the original English. .SH AUTHORS See the GNU CC Manual for the contributors to GNU CC. diff -rc2N gcc-1.32/gcc.c gcc-1.33/gcc.c *** gcc-1.32/gcc.c Sat Dec 3 23:41:11 1988 --- gcc-1.33/gcc.c Thu Jan 19 02:26:35 1989 *************** *** 1,4 **** /* Compiler driver program that can handle many languages. ! Copyright (C) 1987 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Compiler driver program that can handle many languages. ! Copyright (C) 1987,1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 91,94 **** --- 91,96 ---- %{S:X} substitutes X, but only if the -S switch was given to CC. %{!S:X} substitutes X, but only if the -S switch was NOT given to CC. + %{|S:X} like %{S:X}, but if no S switch, substitute `-'. + %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'. The conditional text X in a %{S:X} or %{!S:X} construct may contain *************** *** 130,134 **** #define X_OK 1 #define vfork fork ! #endif #define obstack_chunk_alloc xmalloc --- 132,136 ---- #define X_OK 1 #define vfork fork ! #endif /* USG */ #define obstack_chunk_alloc xmalloc *************** *** 152,155 **** --- 154,158 ---- int do_spec_1 (); char *find_file (); + static char *find_exec_file (); /* config.h can define ASM_SPEC to provide extra args to the assembler *************** *** 214,225 **** %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\ %{Wcomment} %{Wtrigraphs} %{Wall} %C\ ! %i %{!M*:%{!E:%g.cpp}}%{E:%{o*}}%{M*:%{o*}}\n\ ! %{!M*:%{!E:cc1 %g.cpp %1 %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*}\ %{g} %{O} %{W*} %{w} %{pedantic} %{ansi} %{traditional}\ %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ ! %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %g.s}\n\ %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! %g.s %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"}, {".cc", "cpp -+ %{nostdinc} %{C} %{v} %{D*} %{U*} %{I*} %{M*} %{T} \ --- 217,230 ---- %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\ %{Wcomment} %{Wtrigraphs} %{Wall} %C\ ! %i %{!M*:%{!E:%{!pipe:%g.cpp}}}%{E:%{o*}}%{M*:%{o*}} |\n\ ! %{!M*:%{!E:cc1 %{!pipe:%g.cpp} %1 \ ! %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*}\ %{g} %{O} %{W*} %{w} %{pedantic} %{ansi} %{traditional}\ %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ ! %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! %{!pipe:%g.s}\ ! %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"}, {".cc", "cpp -+ %{nostdinc} %{C} %{v} %{D*} %{U*} %{I*} %{M*} %{T} \ *************** *** 227,238 **** %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\ %{Wcomment} %{Wtrigraphs} %{Wall} %C\ ! %i %{!M*:%{!E:%g.cpp}}%{E:%{o*}}%{M*:%{o*}}\n\ ! %{!M*:%{!E:cc1plus %g.cpp %1 %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*}\ %{g} %{O} %{W*} %{w} %{pedantic} %{traditional}\ %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ ! %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %g.s}\n\ %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! %g.s %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"}, {".i", "cc1 %i %1 %{!Q:-quiet} %{Y*} %{d*} %{m*} %{f*}\ --- 232,245 ---- %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\ %{Wcomment} %{Wtrigraphs} %{Wall} %C\ ! %i %{!M*:%{!E:%{!pipe:%g.cpp}}}%{E:%{o*}}%{M*:%{o*}} |\n\ ! %{!M*:%{!E:cc1plus %{!pipe:%g.cpp} %1\ ! %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*}\ %{g} %{O} %{W*} %{w} %{pedantic} %{traditional}\ %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ ! %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! %{!pipe:%g.s}\ ! %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"}, {".i", "cc1 %i %1 %{!Q:-quiet} %{Y*} %{d*} %{m*} %{f*}\ *************** *** 239,248 **** %{g} %{O} %{W*} %{w} %{pedantic} %{ansi} %{traditional}\ %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\ ! %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %g.s}\n\ %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! %g.s %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }"}, {".s", "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ %i %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }"}, /* Mark end of table */ {0, 0} --- 246,263 ---- %{g} %{O} %{W*} %{w} %{pedantic} %{ansi} %{traditional}\ %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\ ! %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! %{!pipe:%g.s} %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }"}, {".s", "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ %i %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }"}, + {".S", + "cpp %{nostdinc} %{C} %{v} %{D*} %{U*} %{I*} %{M*} %{T} \ + -undef -D__GNUC__ -$ %p %P\ + %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\ + %{Wcomment} %{Wtrigraphs} %{Wall} %C\ + %i %{!M*:%{!E:%{!pipe:%g.cpp}}}%{E:%{o*}}%{M*:%{o*}} |\n\ + %{!M*:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{!pipe:%g.s} \ + %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"}, /* Mark end of table */ {0, 0} *************** *** 279,282 **** --- 294,299 ---- int success_only; /* Nonzero means delete this file only if compilation succeeds fully. */ + int fail_only; /* Nonzero means delete this file + only if compilation fails. */ }; *************** *** 285,294 **** /* Record FILENAME as a file to be deleted automatically. SUCCESS_ONLY nonzero means delete it only if all compilation succeeds; otherwise delete it in any case. */ void ! record_temp_file (filename, success_only) char *filename; int success_only; { register struct temp_file *temp; --- 302,314 ---- /* Record FILENAME as a file to be deleted automatically. SUCCESS_ONLY nonzero means delete it only if all compilation succeeds; + otherwise delete it in any case. + FAIL_ONLY nonzero means delete it only if a compilation step fails; otherwise delete it in any case. */ void ! record_temp_file (filename, success_only, fail_only) char *filename; int success_only; + int fail_only; { register struct temp_file *temp; *************** *** 300,303 **** --- 320,324 ---- temp->name = name; temp->success_only = success_only; + temp->fail_only = fail_only; temp_file_queue = temp; } *************** *** 304,308 **** /* Delete all the temporary files whose names we previously recorded. ! SUCCESS nonzero means "delete on success only" files should be deleted. */ void --- 325,331 ---- /* Delete all the temporary files whose names we previously recorded. ! SUCCESS nonzero means "delete on success only" files should be deleted. ! When we use -pipe option, delete all tempoarry ! without checking of success flag. */ void *************** *** 312,316 **** register struct temp_file *temp; for (temp = temp_file_queue; temp; temp = temp->next) ! if (success || ! temp->success_only) { #ifdef DEBUG --- 335,339 ---- register struct temp_file *temp; for (temp = temp_file_queue; temp; temp = temp->next) ! if (success ? !temp->fail_only : !temp->success_only) { #ifdef DEBUG *************** *** 359,363 **** unsigned char vflag; ! /* User-specified prefix to attach to command names, or 0 if none specified. */ --- 382,386 ---- unsigned char vflag; ! /* User-specified -B prefix to attach to command names, or 0 if none specified. */ *************** *** 364,367 **** --- 387,395 ---- char *user_exec_prefix = 0; + /* Environment-specified prefix to attach to command names, + or 0 if none specified. */ + + char *env_exec_prefix = 0; + /* Default prefixes to attach to command names. */ *************** *** 391,396 **** This is done when a space is seen or at the end of the line. If TEMPNAMEP is nonzero, this arg is a file that should be deleted ! at the end of compilation. (If TEMPNAMEP is 2, delete the file ! only if compilation is fully successful.) */ void --- 419,427 ---- This is done when a space is seen or at the end of the line. If TEMPNAMEP is nonzero, this arg is a file that should be deleted ! at the end of compilation. ! If TEMPNAMEP is 2, delete the file ! only if compilation is fully successful. ! If TEMPNAMEP is 3, delete the file ! only if a compilation step fails. */ void *************** *** 408,425 **** if (tempnamep) ! record_temp_file (arg, tempnamep == 2); } ! ! /* Execute the command specified by the arguments on the current line of spec. ! Returns 0 if successful, -1 if failed. */ ! int ! execute () { - int pid; - int status; - int size; - char *temp; int win = 0; size = strlen (standard_exec_prefix); --- 439,455 ---- if (tempnamep) ! record_temp_file (arg, tempnamep == 2, tempnamep == 3); } ! \f ! /* Search for an execute file through our search path. ! Return 0 if not found, otherwise return its name, allocated with malloc. */ ! static char * ! find_exec_file (prog) ! char *prog; { int win = 0; + char *temp; + int size; size = strlen (standard_exec_prefix); *************** *** 426,433 **** if (user_exec_prefix != 0 && strlen (user_exec_prefix) > size) size = strlen (user_exec_prefix); if (strlen (standard_exec_prefix_1) > size) size = strlen (standard_exec_prefix_1); ! size += strlen (argbuf[0]) + 1; ! temp = (char *) alloca (size); /* Determine the filename to execute. */ --- 456,465 ---- if (user_exec_prefix != 0 && strlen (user_exec_prefix) > size) size = strlen (user_exec_prefix); + if (env_exec_prefix != 0 && strlen (env_exec_prefix) > size) + size = strlen (env_exec_prefix); if (strlen (standard_exec_prefix_1) > size) size = strlen (standard_exec_prefix_1); ! size += strlen (prog) + 1; ! temp = (char *) xmalloc (size); /* Determine the filename to execute. */ *************** *** 436,440 **** { strcpy (temp, user_exec_prefix); ! strcat (temp, argbuf[0]); win = (access (temp, X_OK) == 0); } --- 468,479 ---- { strcpy (temp, user_exec_prefix); ! strcat (temp, prog); ! win = (access (temp, X_OK) == 0); ! } ! ! if (!win && env_exec_prefix) ! { ! strcpy (temp, env_exec_prefix); ! strcat (temp, prog); win = (access (temp, X_OK) == 0); } *************** *** 443,447 **** { strcpy (temp, standard_exec_prefix); ! strcat (temp, argbuf[0]); win = (access (temp, X_OK) == 0); } --- 482,486 ---- { strcpy (temp, standard_exec_prefix); ! strcat (temp, prog); win = (access (temp, X_OK) == 0); } *************** *** 454,468 **** } if (vflag) { ! int i; ! for (i = 0; argbuf[i]; i++) { ! if (i == 0 && win) ! fprintf (stderr, " %s", temp); ! else ! fprintf (stderr, " %s", argbuf[i]); } - fprintf (stderr, "\n"); fflush (stderr); #ifdef DEBUG --- 493,666 ---- } + if (win) + return temp; + else + return 0; + } + \f + /* stdin file number. */ + #define STDIN_FILE_NO 0 + + /* stdout file number. */ + #define STDOUT_FILE_NO 1 + + /* value of `pipe': port index for reading. */ + #define READ_PORT 0 + + /* value of `pipe': port index for writing. */ + #define WRITE_PORT 1 + + /* Pipe waiting from last process, to be used as input for the next one. + Value is STDIN_FILE_NO if no pipe is waiting + (i.e. the next command is the first of a group). */ + + int last_pipe_input; + + /* Fork one piped subcommand. FUNC is the system call to use + (either execv or execvp). ARGV is the arg vector to use. + NOT_LAST is nonzero if this is not the last subcommand + (i.e. its output should be piped to the next one.) */ + + static int + pexecute (func, program, argv, not_last) + char *program; + int (*func)(); + char *argv[]; + int not_last; + { + int pid; + int pdes[2]; + int input_desc = last_pipe_input; + int output_desc = STDOUT_FILE_NO; + + /* If this isn't the last process, make a pipe for its output, + and record it as waiting to be the input to the next process. */ + + if (not_last) + { + if (pipe (pdes) < 0) + pfatal_with_name ("pipe"); + output_desc = pdes[WRITE_PORT]; + last_pipe_input = pdes[READ_PORT]; + } + else + last_pipe_input = STDIN_FILE_NO; + + pid = vfork (); + + switch (pid) + { + case -1: + pfatal_with_name ("vfork"); + break; + + case 0: /* child */ + /* Move the input and output pipes into place, if nec. */ + if (input_desc != STDIN_FILE_NO) + { + close (STDIN_FILE_NO); + dup (input_desc); + close (input_desc); + } + if (output_desc != STDOUT_FILE_NO) + { + close (STDOUT_FILE_NO); + dup (output_desc); + close (output_desc); + } + + /* Close the parent's descs that aren't wanted here. */ + if (last_pipe_input != STDIN_FILE_NO) + close (last_pipe_input); + + /* Exec the program. */ + (*func) (program, argv); + exit (-1); + /* NOTREACHED */ + + default: + /* In the parent, after forking. + Close the descriptors that we made for this child. */ + if (input_desc != STDIN_FILE_NO) + close (input_desc); + if (output_desc != STDOUT_FILE_NO) + close (output_desc); + + /* Return child's process number. */ + return pid; + } + } + \f + /* Execute the command specified by the arguments on the current line of spec. + When using pipes, this includes several piped-together commands + with `|' between them. + + Return 0 if successful, -1 if failed. */ + + int + execute () + { + int i, j; + int n_commands; /* # of command. */ + char *string; + struct command + { + char *prog; /* program name. */ + char **argv; /* vector of args. */ + int pid; /* pid of process for this command. */ + }; + + struct command *commands; /* each command buffer with above info. */ + + /* Count # of piped commands. */ + for (n_commands = 1, i = 0; i < argbuf_index; i++) + if (strcmp (argbuf[i], "|") == 0) + n_commands++; + + /* Get storage for each command. */ + commands + = (struct command *) alloca (n_commands * sizeof (struct command)); + + /* Split argbuf into its separate piped processes, + and record info about each one. + Also search for the programs that are to be run. */ + + commands[0].prog = argbuf[0]; /* first command. */ + commands[0].argv = &argbuf[0]; + string = find_exec_file (commands[0].prog); + if (string) + commands[0].argv[0] = string; + + for (n_commands = 1, i = 0; i < argbuf_index; i++) + if (strcmp (argbuf[i], "|") == 0) + { /* each command. */ + argbuf[i] = 0; /* termination of command args. */ + commands[n_commands].prog = argbuf[i + 1]; + commands[n_commands].argv = &argbuf[i + 1]; + string = find_exec_file (commands[n_commands].prog); + if (string) + commands[n_commands].argv[0] = string; + n_commands++; + } + + argbuf[argbuf_index] = 0; + + /* If -v, print what we are about to do, and maybe query. */ + if (vflag) { ! /* Print each piped command as a separate line. */ ! for (i = 0; i < n_commands ; i++) { ! char **j; ! ! for (j = commands[i].argv; *j; j++) ! fprintf (stderr, " %s", *j); ! ! /* Print a pipe symbol after all but the last command. */ ! if (i + 1 != n_commands) ! fprintf (stderr, " |"); ! fprintf (stderr, "\n"); } fflush (stderr); #ifdef DEBUG *************** *** 469,504 **** fprintf (stderr, "\nGo ahead? (y or n) "); fflush (stderr); ! i = getchar (); ! if (i != '\n') while (getchar () != '\n') ; ! if (i != 'y' && i != 'Y') return 0; ! #endif /* DEBUG */ } ! #ifdef USG ! pid = fork (); ! if (pid < 0) ! pfatal_with_name ("fork"); ! #else ! pid = vfork (); ! if (pid < 0) ! pfatal_with_name ("vfork"); ! #endif ! if (pid == 0) { ! if (win) ! execv (temp, argbuf); ! else ! execvp (argbuf[0], argbuf); ! perror_with_name (argbuf[0]); ! _exit (65); ! } ! wait (&status); ! if ((status & 0x7F) != 0) ! fatal ("Program %s got fatal signal %d.", argbuf[0], (status & 0x7F)); ! if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS) ! return -1; ! return 0; } \f --- 667,726 ---- fprintf (stderr, "\nGo ahead? (y or n) "); fflush (stderr); ! j = getchar (); ! if (j != '\n') while (getchar () != '\n') ; ! if (j != 'y' && j != 'Y') return 0; ! #endif /* DEBUG */ } ! /* Run each piped subprocess. */ ! ! last_pipe_input = STDIN_FILE_NO; ! for (i = 0; i < n_commands; i++) { ! extern int execv(), execvp(); ! char *string = commands[i].argv[0]; ! ! commands[i].pid = pexecute ((string != commands[i].prog ? execv : execvp), ! string, commands[i].argv, ! i + 1 < n_commands); ! ! if (string != commands[i].prog) ! free (string); ! } ! ! /* Wait for all the subprocesses to finish. ! We don't care what order they finish in; ! we know that N_COMMANDS waits will get them all. */ ! ! { ! int ret_code = 0; ! ! for (i = 0; i < n_commands; i++) ! { ! int status; ! int pid; ! char *prog; ! ! pid = wait (&status); ! if (pid < 0) ! abort (); ! ! if (status != 0) ! { ! int j; ! for (j = 0; j < n_commands; j++) ! if (commands[j].pid == pid) ! prog = commands[j].prog; ! ! if ((status & 0x7F) != 0) ! fatal ("Program %s got fatal signal %d.", prog, (status & 0x7F)); ! if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS) ! ret_code = -1; ! } ! } ! return ret_code; ! } } \f *************** *** 558,561 **** --- 780,784 ---- char **argv; { + extern char *getenv (); register int i; n_switches = 0; *************** *** 562,565 **** --- 785,790 ---- n_infiles = 0; + env_exec_prefix = getenv ("GCC_EXEC_PREFIX"); + /* Scan argv twice. Here, the first time, just count how many switches there will be in their vector, and how many input files in theirs. *************** *** 681,686 **** value = do_spec_1 (spec, 0); if (value == 0) ! value = do_spec_1 ("\n", 0); return value; } --- 906,921 ---- value = do_spec_1 (spec, 0); + + /* Force out any unfinished command. + If -pipe, this forces out the last command if it ended in `|'. */ if (value == 0) ! { ! if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) ! argbuf_index--; ! ! if (argbuf_index > 0) ! value = execute (); ! } ! return value; } *************** *** 721,725 **** if (this_is_library_file) string = find_file (string); ! store_arg (string, delete_this_arg); if (this_is_output_file) outfiles[input_file_number] = string; --- 956,963 ---- if (this_is_library_file) string = find_file (string); ! if (this_is_output_file) ! store_arg (string, 3); ! else ! store_arg (string, delete_this_arg); if (this_is_output_file) outfiles[input_file_number] = string; *************** *** 726,730 **** } arg_going = 0; ! if (argbuf_index) { int value = execute (); --- 964,985 ---- } arg_going = 0; ! ! if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) ! { ! int i; ! for (i = 0; i < n_switches; i++) ! if (!strcmp (switches[i].part1, "pipe")) ! break; ! ! /* A `|' before the newline means use a pipe here, ! but only if -pipe was specified. ! Otherwise, execute now and don't pass the `|' as an arg. */ ! if (i < n_switches) ! break; ! else ! argbuf_index--; ! } ! ! if (argbuf_index > 0) { int value = execute (); *************** *** 740,743 **** --- 995,1019 ---- break; + case '|': + /* End any pending argument. */ + if (arg_going) + { + obstack_1grow (&obstack, 0); + string = obstack_finish (&obstack); + if (this_is_library_file) + string = find_file (string); + if (this_is_output_file) + store_arg (string, 3); + else + store_arg (string, delete_this_arg); + if (this_is_output_file) + outfiles[input_file_number] = string; + } + + /* Use pipe */ + obstack_1grow (&obstack, c); + arg_going = 1; + break; + case '\t': case ' ': *************** *** 749,753 **** if (this_is_library_file) string = find_file (string); ! store_arg (string, delete_this_arg); if (this_is_output_file) outfiles[input_file_number] = string; --- 1025,1032 ---- if (this_is_library_file) string = find_file (string); ! if (this_is_output_file) ! store_arg (string, 3); ! else ! store_arg (string, delete_this_arg); if (this_is_output_file) outfiles[input_file_number] = string; *************** *** 917,924 **** { register char *q; - int negate = *p == '!'; char *filter; ! if (negate) ++p; filter = p; --- 1196,1213 ---- { register char *q; char *filter; + int pipe = 0; + int negate = 0; ! if (*p == '|') ! /* A `|' after the open-brace means, ! if the test fails, output a single minus sign rather than nothing. ! This is used in %{|!pipe:...}. */ ! pipe = 1, ++p; ! ! if (*p == '!') ! /* A `!' after the open-brace negates the condition: ! succeed if the specified switch is not present. */ ! negate = 1, ++p; filter = p; *************** *** 1001,1004 **** --- 1290,1299 ---- } } + else if (pipe) + { + /* Here if a %{|...} conditional fails: output a minus sign, + which means "standard output" or "standard input". */ + do_spec_1 ("-"); + } } *************** *** 1042,1045 **** --- 1337,1342 ---- if (user_exec_prefix != 0 && strlen (user_exec_prefix) > size) size = strlen (user_exec_prefix); + if (env_exec_prefix != 0 && strlen (env_exec_prefix) > size) + size = strlen (env_exec_prefix); if (strlen (standard_exec_prefix_1) > size) size = strlen (standard_exec_prefix_1); *************** *** 1059,1062 **** --- 1356,1366 ---- } + if (!win && env_exec_prefix) + { + strcpy (temp, env_exec_prefix); + strcat (temp, name); + win = (access (temp, R_OK) == 0); + } + if (!win) { *************** *** 1156,1160 **** if (n_infiles == 0) ! fatal ("No source or object files specified."); /* Make a place to record the compiler output file names --- 1460,1464 ---- if (n_infiles == 0) ! fatal ("No input files specified."); /* Make a place to record the compiler output file names diff -rc2N gcc-1.32/gcc.texinfo gcc-1.33/gcc.texinfo *** gcc-1.32/gcc.texinfo Wed Dec 21 23:07:46 1988 --- gcc-1.33/gcc.texinfo Tue Jan 31 22:09:15 1989 *************** *** 7,11 **** This file documents the use and the internals of the GNU compiler. ! Copyright (C) 1988 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 7,11 ---- This file documents the use and the internals of the GNU compiler. ! Copyright (C) 1988, 1989 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of *************** *** 40,49 **** @center Richard M. Stallman @sp 3 ! @center last updated 21 December 1988 @sp 1 ! @center for version 1.32 @page @vskip 0pt plus 1filll ! Copyright @copyright{} 1988 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 40,49 ---- @center Richard M. Stallman @sp 3 ! @center last updated 24 Jan 1989 @sp 1 ! @center for version 1.33 @page @vskip 0pt plus 1filll ! Copyright @copyright{} 1988, 1989 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of *************** *** 307,310 **** --- 307,316 ---- @item William Schelter did most of the work on the Intel 80386 support. + + @item + Christopher Smith did the port for Convex machines. + + @item + Paul Petersen wrote the machine description for the Alliant FX/8. @end itemize *************** *** 319,326 **** When you invoke GNU CC, it normally does preprocessing, compilation, assembly and linking. File names which end in @samp{.c} are taken as C ! source to be preprocessed and compiled; compiler output files plus any ! input files with names ending in @samp{.s} are assembled; then the ! resulting object files, plus any other input files, are linked together to ! produce an executable. Command options allow you to stop this process at an intermediate stage. --- 325,333 ---- When you invoke GNU CC, it normally does preprocessing, compilation, assembly and linking. File names which end in @samp{.c} are taken as C ! source to be preprocessed and compiled; file names ending in @samp{.i} ! are taken as preprocessor output to be compiled; compiler output files ! plus any input files with names ending in @samp{.s} are assembled; then ! the resulting object files, plus any other input files, are linked ! together to produce an executable. Command options allow you to stop this process at an intermediate stage. *************** *** 328,335 **** output consists of object files output by the assembler. ! Other command options are passed on to one stage. Some options control ! the preprocessor and others the compiler itself. Yet other options ! control the assembler and linker; these are not documented here because the ! GNU assembler and linker are not yet released. Here are the options to control the overall compilation process, including --- 335,342 ---- output consists of object files output by the assembler. ! Other command options are passed on to one stage of processing. Some ! options control the preprocessor and others the compiler itself. Yet ! other options control the assembler and linker; these are not documented ! here, but you rarely need to use any of them. Here are the options to control the overall compilation process, including *************** *** 368,371 **** --- 375,384 ---- these are directed to print their own version numbers. + @item -pipe + Use pipes rather than temporary files for communication between the + various stages of compilation. This fails to work on some systems + where the assembler is unable to read from a pipe; but the GNU + assembler has no trouble. + @item -B@var{prefix} Compiler driver program tries @var{prefix} as a prefix for each *************** *** 386,389 **** --- 399,408 ---- out of the link if it is not found by those means. Most of the time, on most machines, you can do without it. + + You can get a similar result from the environment variable; + @code{GCC_EXEC_PREFIX} if it is defined, its value is used as a prefix + in the same way. If both the @samp{-B} option and the + @code{GCC_EXEC_PREFIX} variable are present, the @samp{-B} option is + used first and the environment variable value second. @end table *************** *** 568,571 **** --- 587,594 ---- This has no bug because @code{save_y} is used only if it is set. + Some spurious warnings can be avoided if you declare as + @code{volatile} all the functions you use that never return. + @xref{Function Attributes}. + @item A nonvolatile automatic variable might be changed by a call to *************** *** 613,617 **** @item -Wunused ! Warn whenever a local variable is unused aside from its declaration. @item -Wcomment --- 636,641 ---- @item -Wunused ! Warn whenever a local variable is unused aside from its declaration, ! and whenever a function is declared static but never defined. @item -Wcomment *************** *** 746,749 **** --- 770,819 ---- @end table + These @samp{-m} switches are supported on the Sparc: + + @table @samp + @item -mfpu + Generate output containing floating point instructions. This is the + default if you use the unmodified sources. + + @item -msoft-float + Generate output containing library calls for floating point. + + @item -mno-epilogue + Nonzero to generate separate return instructions for @code{return} + statements. This has both advantages and disadvantages; I don't + recall what they are. + + @item -meager + Do eager conditional branch scheduling to fill no-op slots. This + optimization is new, so we suspect it has bugs; some day it will be + done by default, but it is optional now so you can test it when you + are ready. + + @emph{Test it now}, and report the bugs; otherwise we won't find them, + and this option may become the default with bugs still in it! + @end table + + These @samp{-m} options are defined in the Convex machine description: + + @table @samp + @item -mc1 + Generate output for a C1. This is the default when the compiler is + configured for a C1. + + @item -mc2 + Generate output for a C2. This is the default when the compiler is + configured for a C2. + + @item -margcount + Generate code which puts an argument count in the word preceding each + argument list. Some nonportable Convex and Vax programs need this + word. (Debuggers don't; this info is in the symbol table.) + + @item -mnoargcount + Omit the argument count word. This is the default if you use the + unmodified sources. + @end table + @item -f@var{flag} Specify machine-independent flags. Most flags have both positive and *************** *** 956,959 **** --- 1026,1033 ---- are supported as well. With this option, they are rejected. There is no reason to @i{use} this option; it exists only to satisfy pedants. + + @item -static + On Suns running version 4, this prevents linking with the shared + libraries. (@samp{-g} has the same effect.) @end table *************** *** 1065,1068 **** --- 1139,1145 ---- @item i386-sysv Intel 386 PCs running system V. + @item i386-sysv-gas + Intel 386 PCs running system V, using the GNU assembler and GNU + linker. @item sequent-386 Sequent with Intel 386 processors. *************** *** 1070,1074 **** Sun 2 running system version 2 or 3. @item sun3 ! Sun 3 running system version 2 or 3. @item sun4 Sun 4 running system version 2 or 3. --- 1147,1155 ---- Sun 2 running system version 2 or 3. @item sun3 ! Sun 3 running system version 2 or 3, with 68881. ! @item sun3-nfp ! Sun 3 running system version 2 or 3, without 68881. ! @item sun3-fpa ! Sun 3 running system version 2 or 3, with 68881 and fpa. @item sun4 Sun 4 running system version 2 or 3. *************** *** 1076,1080 **** Sun 2 running system version 4. @item sun3-os4 ! Sun 3 running system version 4. @item sun4-os4 Sun 4 running system version 4. --- 1157,1165 ---- Sun 2 running system version 4. @item sun3-os4 ! Sun 3 running system version 4, with 68881. ! @item sun3-nfp-os4 ! Sun 3 running system version 4, without 68881. ! @item sun3-fpa-os4 ! Sun 3 running system version 4, with 68881 and fpa. @item sun4-os4 Sun 4 running system version 4. *************** *** 1081,1084 **** --- 1166,1177 ---- @item sun386 Sun 386 (``roadrunner''). + @item alliant + Alliant FX/8 computer. Currently, there are bugs in the support for + floating point. Also note that Alliant's version of dbx does not + manage to work with the output from GNU CC. + @item convex-c1 + Convex C1 computer. + @item convex-c2 + Convex C2 computer. @item hp9k320 HP 9000 series 300 using HPUX assembler. *************** *** 1086,1090 **** HP 9000 series 300 using GNU assembler, linker and debugger. This requires the HP-adapt package which is or will soon be ! available in the same places as GNU CC. @item isi68 ISI 68000 or 68020 system. --- 1179,1183 ---- HP 9000 series 300 using GNU assembler, linker and debugger. This requires the HP-adapt package which is or will soon be ! available along with the linker. @item isi68 ISI 68000 or 68020 system. *************** *** 1147,1151 **** @table @file @item tm-sun3.h ! for Sun 3 machines. @item tm-sun2.h for Sun 2 machines. --- 1240,1248 ---- @table @file @item tm-sun3.h ! for Sun 3 machines with 68881. ! @item tm-sun3-fpa.h ! for Sun 3 machines with floating point accelerator. ! @item tm-sun3-nfp.h ! for Sun 3 machines with no hardware floating point. @item tm-sun2.h for Sun 2 machines. *************** *** 1177,1182 **** For the 80386, don't use @file{tm-i386.h} directly. Use @file{tm-i386v.h} if the target machine is running system V, ! @file{tm-seq386.h} for a Sequent 386 system, or @file{tm-compaq.h} for ! a Compaq, or @file{tm-sun386i.h} for a Sun 386 system. For the 32000, use @file{tm-sequent.h} if you are using a Sequent --- 1274,1281 ---- For the 80386, don't use @file{tm-i386.h} directly. Use @file{tm-i386v.h} if the target machine is running system V, ! @file{tm-i386gas.h} if it is running system V but you are using the ! GNU assembler and linker, @file{tm-seq386.h} for a Sequent 386 system, ! or @file{tm-compaq.h} for a Compaq, or @file{tm-sun386i.h} for a Sun ! 386 system. For the 32000, use @file{tm-sequent.h} if you are using a Sequent *************** *** 1228,1231 **** --- 1327,1336 ---- @item + If you are using COFF-encapsulation, you must convert @file{gnulib} to + a GNU-format library at this point. See the file @file{README-ENCAP} + in the directory containing the GNU binary file utilities, for + directions. + + @item Move the first-stage object files and executables into a subdirectory with this command: *************** *** 1347,1350 **** --- 1452,1461 ---- @item Type @samp{@@make} to do recompile everything. + + If you are compiling with a version of GCC older than 1.33, specify + @samp{/DEFINE=("inline=")} as an option in all the compilations. This + requires editing all the @code{gcc} commands in @file{make-cc1.com}. + (The older versions had problems supporting @code{inline}.) Once you + have a working 1.33 or newer GCC, you can change this file back. @end enumerate *************** *** 1383,1386 **** --- 1494,1501 ---- @end enumerate + There is a known problem on VMS: @code{const} global variables don't + work compatibly with the VMS C compiler; we don't know a way to get + them to the linker properly. + @node Trouble, Incompatibilities, Installation, Top @chapter Known Causes of Trouble with GNU CC. *************** *** 1406,1413 **** even a different byte-ordering. ! It is possible to fix this by writing machine-independent code which ! understands the floating point representation of the target machine. ! I am not interested in doing that much work to compensate for bugs ! in assemblers. @item --- 1521,1532 ---- even a different byte-ordering. ! In addition, correct constant folding of floating point values ! requires representing them in the target machine's format. ! (The C standard does not quite require this, but in practice ! it is the only way to win.) ! ! It is now possible to overcome these problems by defining macros such ! as @code{REAL_VALUE_TYPE}. But doing so is a substantial amount of ! work for each target machine. @xref{Cross-compilation}. @item *************** *** 1642,1645 **** --- 1761,1769 ---- @samp{-traditional}, so that the ANSI antirecursion rules for macro expansions are effective.) + + On some machines, PCC uses a reentrant convention. Then GNU CC uses + the same convention except for structures of 1, 2, 4 or 8 bytes. For + such machines, there is no problem when returning structures of other + sizes; the problem is insoluble for structures of those sizes. @end itemize *************** *** 1663,1668 **** --- 1787,1795 ---- * Subscripting:: Any array can be subscripted, even if not an lvalue. * Pointer Arith:: Arithmetic on @code{void}-pointers and function pointers. + * Initializers:: Non-constant initializers. * Constructors:: Constructor expressions give structures, unions or arrays as values. + * Function Attributes:: Declaring that functions have no side effects, + or that they can never return. * Dollar Signs:: Dollar sign is allowed in identifiers. * Alignment:: Inquiring about the alignment of a type or variable. *************** *** 1671,1674 **** --- 1798,1802 ---- (With them you can define ``built-in'' functions.) * Asm Labels:: Specifying the assembler name to use for a C symbol. + * Global Reg Vars:: Defining global variables which reside in registers. @end menu *************** *** 2055,2059 **** @end example ! @node Constructors, Dollar Signs, Initializers, Extensions @section Constructor Expressions --- 2183,2187 ---- @end example ! @node Constructors, Function Attributes, Initializers, Extensions @section Constructor Expressions *************** *** 2105,2109 **** @end example ! @node Dollar Signs, Alignment, Constructors, Extensions @section Dollar Signs in Identifier Names --- 2233,2289 ---- @end example ! @node Function Attributes, Dollar Signs, Constructors ! @section Declaring Attributes of Functions ! ! In GNU C, you declare certain things about functions called in your program ! which help the compiler optimize function calls. ! ! A few functions, such as @code{abort} and @code{exit}, cannot return. ! These functions should be declared @code{volatile}. For example, ! ! @example ! extern volatile void abort (); ! @end example ! ! @noindent ! tells the compiler that it can assume that @code{abort} will not return. ! This makes slightly better code, but more importantly it helps avoid ! spurious warnings of uninitialized variables. ! ! Many functions do not examine any values except their arguments, and ! have no effects except the return value. Such a function can be subject ! to common subexpression elimination and loop optimization just as an ! arithmetic operator would be. These functions should be declared ! @code{const}. For example, ! ! @example ! extern const void square (); ! @end example ! ! @noindent ! says that the hypothetical function @code{square} is safe to call ! fewer times than the program says. ! ! Note that a function that has pointer arguments and examines the data ! pointed to must @emph{not} be declared @code{const}. Likewise, a ! function that calls a non-@code{const} function must not be ! @code{const}. ! ! Some people object to this feature, claiming that ANSI C's @code{#pragma} ! should be used instead. There are two reasons I did not do this. ! ! @enumerate ! @item ! It is impossible to generate @code{#pragma} commands from a macro. ! ! @item ! The @code{#pragma} command is just as likely as these keywords to mean ! something else in another compiler. ! @end enumerate ! ! These two reasons apply to @emph{any} application whatever: as far as ! I can see, @code{#pragma} is never useful. ! ! @node Dollar Signs, Alignment, Function Attributes, Extensions @section Dollar Signs in Identifier Names *************** *** 2206,2210 **** @code{result} is that of the output operand. Each has @samp{"f"} as its operand constraint, saying that a floating-point register is required. The ! @samp{=} in @samp{=r} indicates that the operand is an output; all output operands' constraints must use @samp{=}. The constraints use the same language used in the machine description (@pxref{Constraints}). --- 2386,2390 ---- @code{result} is that of the output operand. Each has @samp{"f"} as its operand constraint, saying that a floating-point register is required. The ! @samp{=} in @samp{=f} indicates that the operand is an output; all output operands' constraints must use @samp{=}. The constraints use the same language used in the machine description (@pxref{Constraints}). *************** *** 2247,2251 **** @noindent The constraint @samp{"0"} for operand 1 says that it must occupy the same ! location as operand 0. Only a digit in the constraint can guarantee that one operand will be in --- 2427,2432 ---- @noindent The constraint @samp{"0"} for operand 1 says that it must occupy the same ! location as operand 0. A digit in constraint is allowed only in an input ! operand, and it must refer to an output operand. Only a digit in the constraint can guarantee that one operand will be in *************** *** 2354,2358 **** ``compare'' instructions because they don't have any output operands. ! @node Asm Labels,,Extended Asm, Extensions @section Controlling Names Used in Assembler Code --- 2535,2539 ---- ``compare'' instructions because they don't have any output operands. ! @node Asm Labels, Global Reg Vars, Extended Asm, Extensions @section Controlling Names Used in Assembler Code *************** *** 2392,2395 **** --- 2573,2658 ---- Perhaps that will be added. + @node Global Reg Vars,, Asm Labels, Extensions + @section Global Variables in Registers + + A few programs, such as programming language interpreters, may have a + couple of global variables that are accessed so often that it is worth + while to reserve registers throughout the program just for them. + + You can define a global register variable in GNU C like this: + + @example + register int *foo asm ("a5"); + @end example + + @noindent + Here @code{a5} is the name of the register which should be used. Choose a + register which is normally saved and restored by function calls on your + machine, so that library routines will not clobber it. + + Naturally the register name is cpu-dependent, so you would need to + conditionalize your program according to cpu type. The register + @code{a5} would be a good choice on a 68000 for a variable of pointer + type. On machines with register windows, be sure to choose a ``global'' + register that is not affected by the function call mechanism. + + In addition, operating systems on one type of cpu may differ in how they + name the registers; then you would need additional conditionals. For + example, some 68000 operating systems call this register @code{%a5}. + + Eventually there may be a way of asking the compiler to choose a register + automatically, but first we need to figure out how it should choose and + how to enable you to guide the choice. + + Defining a global register variable in a certain register reserves that + register entirely for this use, at least within the current compilation. + The register will not be allocated for any other purpose in the functions + in the current compilation. The register will not be saved and restored by + these functions. Stores into this register are never deleted even if they + would appear to be dead, but references may be deleted or moved or + simplified. + + It is not safe to access the global register variables from signal + handlers, or from more than one thread of control, because the system + library routines may temporarily use the register for other things (unless + you recompile them specially for the task at hand). + + It is not safe for one function that uses a global register variable to + call another such function @code{foo} by way of a third function + @code{lose} that was compiled without knowledge of this variable (i.e. in a + different source file in which the variable wasn't declared). This is + because @code{lose} might save the register and put some other value there. + For example, you can't expect a global register variable to be available in + the comparison-function that you pass to @code{qsort}, since @code{qsort} + might have put something else in that register. (If you are prepared to + recompile @code{qsort} with the same global register variable, you can + solve this problem.) + + If you want to recompile @code{qsort} or other source files which do not + actually use your global register variable, so that they will not use that + register for any other purpose, then it suffices to specify the compiler + option @samp{-ffixed-@var{reg}}. You need not actually add a global + register declaration to their source code. + + A function which can alter the value of a global register variable cannot + safely be called from a function compiled without this variable, because it + could clobber the value the caller expects to find there on return. + Therefore, the function which is the entry point into the part of the + program that uses the global register variable must explicitly save and + restore the value which belongs to its caller. + + On most machines, @code{longjmp} will restore to each global register + variable the value it had at the time of the @code{setjmp}. On some + machines, however, @code{longjmp} will not change the value of global + register variables. To be portable, the function that called @code{setjmp} + should make other arrangements to save the values of the global register + variables, and to restore them if a @code{longjmp}. This way, the the same + thing will happen regardless of what @code{longjmp} does. + + All global register variable declarations must precede all function + definitions. If such a declaration could appear after function + definitions, the declaration would be too late to prevent the register from + being used for other purposes in the preceding functions. + @node Bugs, Portability, Extensions, Top @chapter Reporting Bugs *************** *** 3014,3019 **** @item Jump optimization is repeated, this time including cross-jumping ! and deletion of no-op move instructions. Machine-specific peephole ! optimizations are performed at the same time. The option @samp{-dJ} causes a debugging dump of the RTL code after --- 3277,3281 ---- @item Jump optimization is repeated, this time including cross-jumping ! and deletion of no-op move instructions. The option @samp{-dJ} causes a debugging dump of the RTL code after *************** *** 3024,3028 **** Final. This pass outputs the assembler code for the function. It is also responsible for identifying spurious test and compare ! instructions. The function entry and exit sequences are generated directly as assembler code in this pass; they never exist as RTL. --- 3286,3291 ---- Final. This pass outputs the assembler code for the function. It is also responsible for identifying spurious test and compare ! instructions. Machine-specific peephole optimizations are performed ! at the same time. The function entry and exit sequences are generated directly as assembler code in this pass; they never exist as RTL. *************** *** 3638,3642 **** with the specified one. ! Such multi-word hardware register @samp{reg} expressions may not be live across the boundary of a basic block. The lifetime analysis pass does not know how to record properly that several consecutive registers are --- 3901,3905 ---- with the specified one. ! Such multi-word hardware register @samp{reg} expressions must not be live across the boundary of a basic block. The lifetime analysis pass does not know how to record properly that several consecutive registers are *************** *** 3757,3761 **** support one but not the other.@refill ! @samp{mult} may be used for floating point division as well. Then @var{m} is a floating point machine mode. --- 4020,4024 ---- support one but not the other.@refill ! @samp{mult} may be used for floating point multiplication as well. Then @var{m} is a floating point machine mode. *************** *** 4182,4187 **** new value that is set by this instruction. ! Peephole optimization, which takes place in the last jump-optimization ! pass, can produce insns whose patterns consist of a @samp{parallel} whose elements are the operands needed to output the resulting assembler code--often @samp{reg}, @samp{mem} or constant expressions. --- 4445,4450 ---- new value that is set by this instruction. ! Peephole optimization, which takes place in together with final assembly ! code output, can produce insns whose patterns consist of a @samp{parallel} whose elements are the operands needed to output the resulting assembler code--often @samp{reg}, @samp{mem} or constant expressions. *************** *** 4467,4476 **** The @code{REG_NOTES} field of an insn is a similar chain but of ! @samp{expr_list} expressions instead of @samp{insn_list}. There are four ! kinds of register notes, which are distinguished by the machine mode of the ! @samp{expr_list}, which a register note is really understood as being an ! @code{enum reg_note}. The first operand @var{op} of the @samp{expr_list} ! is data whose meaning depends on the kind of note. Here are the four ! kinds: @table @code --- 4730,4739 ---- The @code{REG_NOTES} field of an insn is a similar chain but of ! @samp{expr_list} expressions instead of @samp{insn_list}. There are ! several kinds of register notes, which are distinguished by the machine ! mode of the @samp{expr_list}, which in a register note is really ! understood as being an @code{enum reg_note}. The first operand @var{op} ! of the @samp{expr_list} is data whose meaning depends on the kind of ! note. Here are the kinds of register note: @table @code *************** *** 4660,4663 **** --- 4923,4934 ---- @item + When a single @code{asm} statement has multiple output operands, + a distinct @code{asm_operands} RTX is made for each output operand. + However, these all share the vector which contains the sequence of + input operands. Because this sharing is used later on to test whether + two @code{asm_operands} RTX's come from the same statement, the sharing + must be guaranteed to be preserved. + + @item No RTL object appears in more than one place in the RTL structure except as described above. Many passes of the compiler rely on this *************** *** 4922,4926 **** When this pattern does match, the two operands of the commutative operator are recorded as operands 3 and 4 of the insn. (This is done ! by the two instances of @samp{match_operator}.) Operand 2 of the insn will be the entire commutative expression: use @code{GET_CODE (operands[2])} to see which commutative operator was used. --- 5193,5197 ---- When this pattern does match, the two operands of the commutative operator are recorded as operands 3 and 4 of the insn. (This is done ! by the two instances of @samp{match_operand}.) Operand 2 of the insn will be the entire commutative expression: use @code{GET_CODE (operands[2])} to see which commutative operator was used. *************** *** 5054,5058 **** When an insn pattern has multiple alternatives in its constraints, often ! the appearance of the assembler code determined mostly by which alternative was matched. When this is so, the C code can test the variable @code{which_alternative}, which is the ordinal number of the alternative --- 5325,5329 ---- When an insn pattern has multiple alternatives in its constraints, often ! the appearance of the assembler code is determined mostly by which alternative was matched. When this is so, the C code can test the variable @code{which_alternative}, which is the ordinal number of the alternative *************** *** 5220,5224 **** More precisely, the matching constraint must appear in an input-only operand and the operand that it matches must be an output-only operand ! with a lower number. For operands to match in a particular case usually means that they --- 5491,5496 ---- More precisely, the matching constraint must appear in an input-only operand and the operand that it matches must be an output-only operand ! with a lower number. Thus, operand @var{n} must have @samp{=} in its ! constraint. For operands to match in a particular case usually means that they *************** *** 5317,5321 **** provided its constraints include the letter @samp{i}. If any possible constant value is accepted, then nothing less than @samp{i} will do; ! if the predicate is more selective, than the constraints may also be more selective. --- 5589,5593 ---- provided its constraints include the letter @samp{i}. If any possible constant value is accepted, then nothing less than @samp{i} will do; ! if the predicate is more selective, then the constraints may also be more selective. *************** *** 5394,5403 **** @end table ! When an insn pattern has multiple alternatives in its constraints, ! often the appearance of the assembler code determined mostly by which alternative was matched. When this is so, the C code for writing the assembler code can use the variable @code{which_alternative}, which is ! the ordinal number of the alternative that was actually satisfied ! (0 for the first, 1 for the second alternative, etc.). For example: @example --- 5666,5675 ---- @end table ! When an insn pattern has multiple alternatives in its constraints, often ! the appearance of the assembler code is determined mostly by which alternative was matched. When this is so, the C code for writing the assembler code can use the variable @code{which_alternative}, which is ! the ordinal number of the alternative that was actually satisfied (0 for ! the first, 1 for the second alternative, etc.). For example: @example *************** *** 5689,5692 **** --- 5961,5966 ---- strings are the first two operands, and both are in mode @code{Pmode}. The number of bytes to move is the third operand, in mode @var{m}. + The fourth operand is the known shared alignment of the source and + destination, in the form of a @code{const_int} rtx. @item @samp{cmpstr@var{m}} *************** *** 6062,6066 **** It also works to define patterns for compare-and-branch instructions. In optimizing compilation, the pair of compare and branch instructions ! will be combined accoprding to these patterns. But this does not happen if optimization is not requested. So you must use one of the solutions above in addition to any special patterns you define. --- 6336,6340 ---- It also works to define patterns for compare-and-branch instructions. In optimizing compilation, the pair of compare and branch instructions ! will be combined according to these patterns. But this does not happen if optimization is not requested. So you must use one of the solutions above in addition to any special patterns you define. *************** *** 6097,6103 **** In this skeleton, @var{insn-pattern-1} and so on are patterns to match ! consecutive instructions. The optimization applies to a sequence of ! instructions when @var{insn-pattern-1} matches the first one, ! @var{insn-pattern-2} matches the next, and so on.@refill @var{insn-pattern-1} and so on look @emph{almost} like the second operand --- 6371,6377 ---- In this skeleton, @var{insn-pattern-1} and so on are patterns to match ! consecutive insns. The optimization applies to a sequence of insns when ! @var{insn-pattern-1} matches the first one, @var{insn-pattern-2} matches ! the next, and so on.@refill @var{insn-pattern-1} and so on look @emph{almost} like the second operand *************** *** 6109,6117 **** @code{parallel} RTX.@refill ! The operands of the instructions are matched with @code{match_operands} and ! @code{match_dup}, as usual). What is not usual is that the operand numbers ! apply to all the instruction patterns in the definition. So, you can check ! for identical operands in two instructions by using @code{match_operand} ! in one instruction and @code{match_dup} in the other. The operand constraints used in @code{match_operand} patterns do not have --- 6383,6391 ---- @code{parallel} RTX.@refill ! The operands of the insns are matched with @code{match_operands} and ! @code{match_dup}, as usual. What is not usual is that the operand numbers ! apply to all the insn patterns in the definition. So, you can check for ! identical operands in two insns by using @code{match_operand} in one insn ! and @code{match_dup} in the other. The operand constraints used in @code{match_operand} patterns do not have *************** *** 6121,6134 **** operand. ! Once a sequence of instructions matches the patterns, the @var{condition} ! is checked. This is a C expression which makes the final decision whether ! to perform the optimization (do so if the expression is nonzero). If @var{condition} is omitted (in other words, the string is empty) then the ! optimization is applied to every sequence of instructions that matches the patterns. ! The defined peephole optimizations are applied after register allocation is ! complete. Therefore, the optimizer can check which operands have ended up ! in which kinds of registers, just by looking at the operands. The way to refer to the operands in @var{condition} is to write --- 6395,6409 ---- operand. ! Once a sequence of insns matches the patterns, the @var{condition} is ! checked. This is a C expression which makes the final decision whether to ! perform the optimization (we do so if the expression is nonzero). If @var{condition} is omitted (in other words, the string is empty) then the ! optimization is applied to every sequence of insns that matches the patterns. ! The defined peephole optimizations are applied after register allocation ! is complete. Therefore, the peephole definition can check which ! operands have ended up in which kinds of registers, just by looking at ! the operands. The way to refer to the operands in @var{condition} is to write *************** *** 6147,6164 **** @code{operands[@var{i}]}).@refill ! Applying the optimization means replacing the sequence of instructions with ! one new instruction. The @var{template} controls ultimate output of ! assembler code for this combined instruction. It works exactly like the ! template of a @code{define_insn}. Operand numbers in this template are the ! same ones used in matching the original sequence of instructions. The result of a defined peephole optimizer does not need to match any of ! the instruction patterns, and it does not have an opportunity to match ! them. The peephole optimizer definition itself serves as the instruction ! pattern to control how the instruction is output. ! Defined peephole optimizers are run in the last jump optimization pass, so ! the instructions they produce are never combined or rearranged ! automatically in any way. Here is an example, taken from the 68000 machine description: --- 6422,6438 ---- @code{operands[@var{i}]}).@refill ! Applying the optimization means replacing the sequence of insns with one ! new insn. The @var{template} controls ultimate output of assembler code ! for this combined insn. It works exactly like the template of a ! @code{define_insn}. Operand numbers in this template are the same ones ! used in matching the original sequence of insns. The result of a defined peephole optimizer does not need to match any of ! the insn patterns in the machine description; it does not even have an ! opportunity to match them. The peephole optimizer definition itself serves ! as the insn pattern to control how the insn is output. ! Defined peephole optimizers are run as assembler code is being output, ! so the insns they produce are never combined or rearranged in any way. Here is an example, taken from the 68000 machine description: *************** *** 6207,6210 **** --- 6481,6496 ---- @end example + @ignore + If a peephole matches a sequence including one or more jump insns, you must + take account of the flags such as @code{CC_REVERSED} which specify that the + condition codes are represented in an unusual manner. The compiler + automatically alters any ordinary conditional jumps which occur in such + situations, but the compiler cannot alter jumps which have been replaced by + peephole optimizations. So it is up to you to alter the assembler code + that the peephole produces. Supply C code to write the assembler output, + and in this C code check the condition code status flags and change the + assembler code as appropriate. + @end ignore + @node Expander Definitions,, Peephole Definitions, Machine Desc @section Defining RTL Sequences for Code Generation *************** *** 6382,6385 **** --- 6668,6672 ---- * Condition Code:: Defining how insns update the condition code. * Assembler Format:: Defining how to write insns and pseudo-ops to output. + * Cross-compilation:: Handling floating point for cross-compilers. * Misc:: Everything else. @end menu *************** *** 6406,6410 **** @end example ! The result is to define the macros @samp{__Dmc68000__}, @samp{__sun__} and @samp{__unix__} unconditionally, and the macros @samp{mc68000}, @samp{sun} and @samp{unix} provided @samp{-ansi} is not specified. --- 6693,6697 ---- @end example ! The result is to define the macros @samp{__mc68000__}, @samp{__sun__} and @samp{__unix__} unconditionally, and the macros @samp{mc68000}, @samp{sun} and @samp{unix} provided @samp{-ansi} is not specified. *************** *** 6627,6633 **** If the usage of an entire class of registers depends on the target ! flags, you may indicate this to gcc by using this macro to modify @code{fixed_regs} and @code{call_used_regs} to 1 for each of the ! registers in the classes which should not be used by gcc. Also define the macro @code{REG_CLASS_FROM_LETTER} to return @code{NO_REGS} if it is called with a letter for a class that shouldn't be used. --- 6914,6920 ---- If the usage of an entire class of registers depends on the target ! flags, you may indicate this to GCC by using this macro to modify @code{fixed_regs} and @code{call_used_regs} to 1 for each of the ! registers in the classes which should not be used by GCC. Also define the macro @code{REG_CLASS_FROM_LETTER} to return @code{NO_REGS} if it is called with a letter for a class that shouldn't be used. *************** *** 6639,6651 **** @item OVERLAPPING_REGNO_P (@var{regno}) ! If defined, this is a C expression whose value is @var{regno} is ! nonzero if hard register number @var{regno} is an overlapping ! register. This means a hard register which overlaps a hard register ! with a different number. (Such overlap is undesirable, but ! occasionally it allows a machine to be supported which otherwise could ! not be.) This macro must return nonzero for @emph{all} the registers ! which overlap each other. GNU CC can use an overlapping register only ! in certain limited ways. It can be used for allocation within a basic ! block, and may be spilled for reloading; that is all. If this macro is not defined, it means that none of the hard registers --- 6926,6938 ---- @item OVERLAPPING_REGNO_P (@var{regno}) ! If defined, this is a C expression whose value is nonzero if hard ! register number @var{regno} is an overlapping register. This means a ! hard register which overlaps a hard register with a different number. ! (Such overlap is undesirable, but occasionally it allows a machine to ! be supported which otherwise could not be.) This macro must return ! nonzero for @emph{all} the registers which overlap each other. GNU CC ! can use an overlapping register only in certain limited ways. It can ! be used for allocation within a basic block, and may be spilled for ! reloading; that is all. If this macro is not defined, it means that none of the hard registers *************** *** 6778,6784 **** advantage to avoiding a frame pointer. ! In certain cases, the compiler does not know how to do without a frame ! pointer. The compiler recognizes those cases and automatically gives ! the function a frame pointer regardless of what @code{FRAME_POINTER_REQUIRED} says. You don't need to worry about them.@refill --- 7065,7071 ---- advantage to avoiding a frame pointer. ! In certain cases, the compiler does not know how to produce valid code ! without a frame pointer. The compiler recognizes those cases and ! automatically gives the function a frame pointer regardless of what @code{FRAME_POINTER_REQUIRED} says. You don't need to worry about them.@refill *************** *** 7417,7431 **** @table @code @item UDIVSI3_LIBCALL A C string constant giving the name of the function to call for ! division of a full-word by a full-word. If you do not define this ! macro, the default name is used, which is @code{_udivsi3}, a function ! defined in @file{gnulib}. @item UMODSI3_LIBCALL A C string constant giving the name of the function to call for the ! remainder in division of a full-word by a full-word. If you do not ! define this macro, the default name is used, which is @code{_umodsi3}, ! a function defined in @file{gnulib}. @item TARGET_MEM_FUNCTIONS --- 7704,7742 ---- @table @code + @item MULSI3_LIBCALL + A C string constant giving the name of the function to call for + multiplication of one signed full-word by another. If you do not + define this macro, the default name is used, which is @code{__mulsi3}, + a function defined in @file{gnulib}. + + @item UMULSI3_LIBCALL + A C string constant giving the name of the function to call for + multiplication of one unsigned full-word by another. If you do not + define this macro, the default name is used, which is + @code{__umulsi3}, a function defined in @file{gnulib}. + + @item DIVSI3_LIBCALL + A C string constant giving the name of the function to call for + division of one signed full-word by another. If you do not define + this macro, the default name is used, which is @code{__divsi3}, a + function defined in @file{gnulib}. + @item UDIVSI3_LIBCALL A C string constant giving the name of the function to call for ! division of one unsigned full-word by another. If you do not define ! this macro, the default name is used, which is @code{__udivsi3}, a ! function defined in @file{gnulib}. + @item MODSI3_LIBCALL + A C string constant giving the name of the function to call for the + remainder in division of one signed full-word by another. If you do + not define this macro, the default name is used, which is + @code{__modsi3}, a function defined in @file{gnulib}. + @item UMODSI3_LIBCALL A C string constant giving the name of the function to call for the ! remainder in division of one unsigned full-word by another. If you do ! not define this macro, the default name is used, which is ! @code{__umodsi3}, a function defined in @file{gnulib}. @item TARGET_MEM_FUNCTIONS *************** *** 7435,7439 **** @end table ! @node Addressing Modes, Misc, Library Names, Machine Macros @section Addressing Modes --- 7746,7750 ---- @end table ! @node Addressing Modes, Cross-compilation, Library Names, Machine Macros @section Addressing Modes *************** *** 7494,7498 **** @item REG_OK_FOR_BASE_P (@var{x}) ! A C expression that is nonzero if @var{x} (asumed to be a @code{reg} RTX) is valid for use as a base register. For hard registers, it should always accept those which the hardware permits and reject the --- 7805,7809 ---- @item REG_OK_FOR_BASE_P (@var{x}) ! A C expression that is nonzero if @var{x} (assumed to be a @code{reg} RTX) is valid for use as a base register. For hard registers, it should always accept those which the hardware permits and reject the *************** *** 7503,7507 **** @item REG_OK_FOR_INDEX_P (@var{x}) ! A C expression that is nonzero if @var{x} (asumed to be a @code{reg} RTX) is valid for use as an index register. --- 7814,7818 ---- @item REG_OK_FOR_INDEX_P (@var{x}) ! A C expression that is nonzero if @var{x} (assumed to be a @code{reg} RTX) is valid for use as an index register. *************** *** 7562,7566 **** @end table ! @node Misc, Condition Code, Addressing Modes, Machine Macros @section Miscellaneous Parameters --- 7873,7976 ---- @end table ! @node Cross-compilation, Misc, Addressing Modes, Machine Macros ! @section Cross Compilation and Floating-Point Format ! ! While all modern machines use 2's compliment representation for integers, ! there are a variety of representations for floating point numbers. This ! means that in a cross-compiler the representation of floating point numbers ! in the compiled program may be different from that used in the machine ! doing the compilation. ! ! Because different representation systems may offer different amounts of ! range and precision, the cross compiler cannot safely use the host ! machine's floating point arithmetic. Therefore, floating point constants ! must be represented in the target machine's format. This means that the ! cross compiler cannot use @code{atof} to parse a floating point constant; ! it must have its own special routine to use instead. Also, constant ! folding must emulate the target machine's arithmetic (or must not be done ! at all). ! ! The macros in the following table should be defined only if you are cross ! compiling between different floating point formats. ! ! Otherwise, don't define them. Then default definitions will be set up which ! use @code{double} as the data type, @code{==} to test for equality, etc. ! ! You don't need to worry about how many times you use an operand of any ! of these macros. The compiler never uses operands which have side effects. ! ! @table @code ! @item REAL_VALUE_TYPE ! A macro for the C data type to be used to hold a floating point value ! in the target machine's format. Typically this would be a ! @code{struct} containing an array of @code{int}. ! ! @item REAL_VALUES_EQUAL (@var{x}, @var{y}) ! A macro for a C expression which compares for equality the two values, ! @var{x} and @var{y}, both of type @code{REAL_VALUE_TYPE}. ! ! @item REAL_VALUES_LESS (@var{x}, @var{y}) ! A macro for a C expression which tests whether @var{x} is less than ! @var{y}, both values being of type @code{REAL_VALUE_TYPE} and ! interpreted as floating point numbers in the target machine's ! representation. ! ! @item REAL_VALUE_LDEXP (@var{x}, @var{scale}) ! A macro for a C expression which performs the standard library ! function @code{ldexp}, but using the target machine's floating point ! representation. Both @var{x} and the value of the expression have ! type @code{REAL_VALUE_TYPE}. The second argument, @var{scale}, is an ! integer. ! ! @item REAL_VALUE_ATOF (@var{string}) ! A macro for a C expression which converts @var{string}, an expression ! of type @code{char *}, into a floating point number in the target ! machine's representation. The value has type @code{REAL_VALUE_TYPE}. ! @end table ! ! Define the following additional macros if you want to make floating ! point constant folding work while cross compiling. If you don't ! define them, cross compilation is still possible, but constant folding ! will not happen for floating point values. ! ! @table @code ! @item REAL_ARITHMETIC (@var{output}, @var{code}, @var{x}, @var{y}) ! A macro for a C statement which calculates an arithmetic operation of ! the two floating point values @var{x} and @var{y}, both of type ! @code{REAL_VALUE_TYPE} in the target machine's representation, to ! produce a result of the same type and representation which is stored ! in @var{output} (which will be a variable). ! ! The operation to be performed is specified by @var{code}, a tree code ! which will always be one of the following: @code{PLUS_EXPR}, ! @code{MINUS_EXPR}, @code{MULT_EXPR}, @code{RDIV_EXPR}, ! @code{MAX_EXPR}, @code{MIN_EXPR}.@refill ! ! The expansion of this macro is responsible for checking for overflow. ! If overflow happens, the macro expansion should execute the statement ! @code{return 0;}, which indicates the inability to perform the ! arithmetic operation requested. ! ! @item REAL_VALUE_NEGATE (@var{x}) ! A macro for a C expression which returns the negative of the floating ! point value @var{x}. Both @var{x} and the value of the expression ! have type @code{REAL_VALUE_TYPE} and are in the target machine's ! floating point representation. ! ! There is no way for this macro to report overflow, since overflow ! can't happen in the negation operation. ! ! @item REAL_VALUE_TO_INT (@var{low}, @var{high}, @var{x}) ! A macro for a C expression which converts a floating point value ! @var{x} into a double-precision integer which is then stored into ! @var{low} and @var{high}, two variables of type @var{int}. ! ! @item REAL_VALUE_FROM_INT (@var{x}, @var{low}, @var{high}) ! A macro for a C expression which converts a double-precision integer ! found in @var{low} and @var{high}, two variables of type @var{int}, ! into a floating point value which is then stored into @var{x}. ! @end table ! ! @node Misc, Condition Code, Cross-compilation, Machine Macros @section Miscellaneous Parameters diff -rc2N gcc-1.32/genemit.c gcc-1.33/genemit.c *** gcc-1.32/genemit.c Mon Dec 5 21:49:31 1988 --- gcc-1.33/genemit.c Mon Jan 23 15:03:42 1989 *************** *** 431,434 **** --- 431,435 ---- printf ("#include \"rtl.h\"\n"); printf ("#include \"expr.h\"\n"); + printf ("#include \"real.h\"\n"); printf ("#include \"insn-config.h\"\n\n"); printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n"); diff -rc2N gcc-1.32/genoutput.c gcc-1.33/genoutput.c *** gcc-1.32/genoutput.c Thu Dec 15 21:53:46 1988 --- gcc-1.33/genoutput.c Wed Jan 11 20:49:10 1989 *************** *** 112,115 **** --- 112,116 ---- void fatal (); + void error (); void mybcopy (); void mybzero (); *************** *** 169,172 **** --- 170,174 ---- printf ("#include \"rtl.h\"\n"); printf ("#include \"regs.h\"\n"); + printf ("#include \"real.h\"\n"); printf ("#include \"conditions.h\"\n"); printf ("#include \"insn-flags.h\"\n"); *************** *** 251,257 **** n = d->op_n_alternatives[start]; else if (n != d->op_n_alternatives[start]) ! fatal ("wrong number of alternatives in operand %d of insn number %d", start, d->code_number); - break; } /* Record the insn's overall number of alternatives. */ --- 253,258 ---- n = d->op_n_alternatives[start]; else if (n != d->op_n_alternatives[start]) ! error ("wrong number of alternatives in operand %d of insn number %d", start, d->code_number); } /* Record the insn's overall number of alternatives. */ *************** *** 386,390 **** max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) ! fatal ("Too many operands (%d) in one instruction pattern.\n", max_opno + 1); modes[opno] = GET_MODE (part); --- 387,391 ---- max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) ! error ("Too many operands (%d) in one instruction pattern.\n", max_opno + 1); modes[opno] = GET_MODE (part); *************** *** 407,411 **** max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) ! fatal ("Too many operands (%d) in one instruction pattern.\n", max_opno + 1); modes[opno] = GET_MODE (part); --- 408,412 ---- max_opno = opno; if (max_opno >= MAX_MAX_OPERANDS) ! error ("Too many operands (%d) in one instruction pattern.\n", max_opno + 1); modes[opno] = GET_MODE (part); *************** *** 699,702 **** --- 700,711 ---- fprintf (stderr, "\n"); exit (FATAL_EXIT_CODE); + } + + void + error (s, a1, a2) + { + fprintf (stderr, "genoutput: "); + fprintf (stderr, s, a1, a2); + fprintf (stderr, "\n"); } \f diff -rc2N gcc-1.32/genpeep.c gcc-1.33/genpeep.c *** gcc-1.32/genpeep.c Mon Dec 5 18:19:02 1988 --- gcc-1.33/genpeep.c Mon Jan 23 15:12:21 1989 *************** *** 75,78 **** --- 75,81 ---- printf (" insn = ins1;\n"); + #if 0 + printf (" want_jump = 0;\n"); + #endif for (i = 0; i < ninsns; i++) *************** *** 84,93 **** insn_code_number); printf (" while (GET_CODE (insn) == NOTE);\n"); } ! printf (" if (GET_CODE (insn) == CODE_LABEL) goto L%d;\n", ! insn_code_number); printf (" pat = PATTERN (insn);\n"); /* Walk the insn's pattern, remembering at all times the path down to the walking point. */ --- 87,103 ---- insn_code_number); printf (" while (GET_CODE (insn) == NOTE);\n"); + + printf (" if (GET_CODE (insn) == CODE_LABEL\n\ + || GET_CODE (insn) == BARRIER)\n goto L%d;\n", + insn_code_number); } ! #if 0 ! printf (" if (GET_CODE (insn) == JUMP_INSN)\n"); ! printf (" want_jump = JUMP_LABEL (insn);\n"); ! #endif printf (" pat = PATTERN (insn);\n"); + /* Walk the insn's pattern, remembering at all times the path down to the walking point. */ *************** *** 110,133 **** printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands); - printf (" insn = ins1;\n"); ! /* Make sure that labels referred to by the insns ! don't get deleted because of their counts' going to zero. */ ! printf (" for (i = 0; i < %d; i++)\n", n_operands); ! printf (" if (GET_CODE (operands[i]) == CODE_LABEL)\n"); ! printf (" LABEL_NUSES (operands[i])++;\n"); /* Record this define_peephole's insn code in the insn, as if it had been recognized to match this. */ ! printf (" INSN_CODE (insn) = %d;\n", insn_code_number); /* Delete the remaining insns. */ ! for (i = 1; i < ninsns; i++) ! { ! printf (" do insn = NEXT_INSN (insn);\n"); ! printf (" while (GET_CODE (insn) == NOTE);\n"); ! printf (" delete_insn (insn);\n"); ! } printf (" return 1;\n"); --- 120,141 ---- printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands); ! #if 0 ! printf (" if (want_jump && GET_CODE (ins1) != JUMP_INSN)\n"); ! printf (" {\n"); ! printf (" rtx insn2 = emit_jump_insn_before (PATTERN (ins1), ins1);\n"); ! printf (" delete_insn (ins1);\n"); ! printf (" ins1 = ins2;\n"); ! printf (" }\n"); ! #endif /* Record this define_peephole's insn code in the insn, as if it had been recognized to match this. */ ! printf (" INSN_CODE (ins1) = %d;\n", insn_code_number); /* Delete the remaining insns. */ ! if (ninsns > 1) ! printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n"); printf (" return 1;\n"); *************** *** 182,185 **** --- 190,198 ---- case MATCH_OPERATOR: + if (XINT (x, 0) > max_opno) + max_opno = XINT (x, 0); + if (XINT (x, 0) >= n_operands) + n_operands = 1 + XINT (x, 0); + printf (" x = (rtx)"); print_path (path); *************** *** 357,363 **** from the machine description file `md'. */\n\n"); ! printf ("#include \"config.h\"\n\n"); ! printf ("#include \"rtl.h\"\n\n"); ! printf ("#include \"regs.h\"\n\n"); printf ("extern rtx peep_operand[];\n\n"); --- 370,377 ---- from the machine description file `md'. */\n\n"); ! printf ("#include \"config.h\"\n"); ! printf ("#include \"rtl.h\"\n"); ! printf ("#include \"regs.h\"\n"); ! printf ("#include \"real.h\"\n\n"); printf ("extern rtx peep_operand[];\n\n"); *************** *** 366,370 **** printf ("int\npeephole (ins1)\n rtx ins1;\n{\n"); printf (" rtx insn, x, pat;\n"); ! printf (" int i;\n"); /* Read the machine description. */ --- 380,389 ---- printf ("int\npeephole (ins1)\n rtx ins1;\n{\n"); printf (" rtx insn, x, pat;\n"); ! printf (" int i;\n\n"); ! ! /* Early out: no peepholes for insns followed by barriers. */ ! printf (" if (NEXT_INSN (ins1)\n"); ! printf (" && GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n"); ! printf (" return 0;\n\n"); /* Read the machine description. */ diff -rc2N gcc-1.32/hard-reg-set.h gcc-1.33/hard-reg-set.h *** gcc-1.32/hard-reg-set.h Sat Jul 16 14:41:16 1988 --- gcc-1.33/hard-reg-set.h Thu Jan 12 02:15:38 1989 *************** *** 185,188 **** --- 185,195 ---- extern HARD_REG_SET call_used_reg_set; + /* Indexed by hard register number, contains 1 for registers + that are being used for global register decls. + These must be exempt from ordinary flow analysis + and are also considered fixed. */ + + extern char global_regs[FIRST_PSEUDO_REGISTER]; + /* Table of register numbers in the order in which to try to use them. */ diff -rc2N gcc-1.32/i386.md gcc-1.33/i386.md *** gcc-1.32/i386.md Mon Dec 12 14:39:25 1988 --- gcc-1.33/i386.md Tue Jan 17 22:17:30 1989 *************** *** 325,329 **** (match_operand:QI 1 "general_operand" "q"))] "" ! "push%W %1") (define_insn "movqi" --- 325,333 ---- (match_operand:QI 1 "general_operand" "q"))] "" ! "* ! { ! operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); ! return \"push%W %1\"; ! }") (define_insn "movqi" *************** *** 509,513 **** (match_operand:QI 1 "address_operand" "p"))] "" ! "lea%L %a1,%0") \f ;;- conversion instructions --- 513,521 ---- (match_operand:QI 1 "address_operand" "p"))] "" ! "* ! { ! CC_STATUS_INIT; ! return \"lea%L %a1,%0\"; ! }") \f ;;- conversion instructions *************** *** 1198,1203 **** if (REG_P (operands[2])) return AS2 (sal%L,%Rcl,%0); ! else ! return AS2 (sal%L,%2,%1); }") --- 1206,1222 ---- if (REG_P (operands[2])) return AS2 (sal%L,%Rcl,%0); ! else if (REG_P (operands[1]) && GET_CODE (operands[2]) == CONST_INT) ! switch (INTVAL (operands[2])) ! { ! case 1: ! return AS2 (add%L,%1,%1); ! case 2: ! CC_STATUS_INIT; ! return \"lea%L (,%1,4),%1\"; ! case 3: ! CC_STATUS_INIT; ! return \"lea%L (,%1,8),%1\"; ! } ! return AS2 (sal%L,%2,%1); }") *************** *** 1430,1437 **** \f ;; Basic conditional jump instructions. ! ! ;; ??? The third operand of OUTPUT_JUMP is incorrect, in each case. ! ;; It is supposed to ignore the overflow flag. ! ;; It isn't obvious how to do this in certain cases. (define_insn "beq" --- 1449,1459 ---- \f ;; Basic conditional jump instructions. ! ;; We ignore the overflow flag for signed branch instructions. ! ;; We accomplish this through the code in notice_update_cc in output-i386.c. ! ;; Based on '(cc_status.flags & CC_NO_OVERFLOW)' and '(cc_status.value2)' ! ;; (the rtx for the destination of the insn setting cc_status) we clear ! ;; the overflow flag (if necessary). ! ;; For register destinations we do this by 'or%z1 <reg>, <reg>'; ! ;; for memory destinations we do this by 'cmp%z1 $0, <mem>'. (define_insn "beq" *************** *** 1460,1464 **** (pc)))] "" ! "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", \"jg %l0\")") (define_insn "bgtu" --- 1482,1486 ---- (pc)))] "" ! "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)") (define_insn "bgtu" *************** *** 1478,1482 **** (pc)))] "" ! "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"jl %l0\")") (define_insn "bltu" --- 1500,1504 ---- (pc)))] "" ! "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")") (define_insn "bltu" *************** *** 1496,1500 **** (pc)))] "" ! "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jge %l0\")") (define_insn "bgeu" --- 1518,1522 ---- (pc)))] "" ! "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")") (define_insn "bgeu" *************** *** 1514,1518 **** (pc)))] "" ! "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", \"jle %l0\") ") (define_insn "bleu" --- 1536,1540 ---- (pc)))] "" ! "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ") (define_insn "bleu" *************** *** 1552,1556 **** (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", \"jle %l0\") ") (define_insn "" --- 1574,1578 ---- (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ") (define_insn "" *************** *** 1570,1574 **** (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jge %l0\") ") --- 1592,1596 ---- (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\") ") *************** *** 1589,1593 **** (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"jl %l0\")") (define_insn "" --- 1611,1615 ---- (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")") (define_insn "" *************** *** 1607,1611 **** (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", \"jg %l0\")") (define_insn "" --- 1629,1633 ---- (label_ref (match_operand 0 "" ""))))] "" ! "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)") (define_insn "" diff -rc2N gcc-1.32/integrate.c gcc-1.33/integrate.c *** gcc-1.32/integrate.c Tue Dec 20 01:26:47 1988 --- gcc-1.33/integrate.c Mon Jan 16 16:05:38 1989 *************** *** 82,85 **** --- 82,97 ---- static int fp_delta; + /* When an insn is being copied by copy_rtx_and_substitute, + this is nonzero if we have copied an ASM_OPERANDS. + In that case, it is the original input-operand vector. + Likewise in copy_for_inline. */ + static rtvec orig_asm_operands_vector; + + /* When an insn is being copied by copy_rtx_and_substitute, + this is nonzero if we have copied an ASM_OPERANDS. + In that case, it is the copied input-operand vector. + Likewise in copy_for_inline. */ + static rtvec copy_asm_operands_vector; + /* Return a copy of an rtx (as needed), substituting pseudo-register, labels, and frame-pointer offsets as necessary. */ *************** *** 123,126 **** --- 135,145 ---- return "function too large to be inline"; + /* If the structure value address comes in the stack, + we can't handle it. */ + #if defined (STRUCT_VALUE) || defined (STRUCT_VALUE_INCOMING) + if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode) + return "function returning large aggregate cannot be inline"; + #endif + /* Don't inline functions which have BLKmode arguments. Don't inline functions that take the address of *************** *** 132,135 **** --- 151,163 ---- if (last == NULL_TREE && TREE_ADDRESSABLE (parms)) return "no prototype, and parameter address used; cannot be inline"; + /* If an aggregate is thought of as "in memory" + then its components are referred to by narrower memory refs. + If the actual parameter is a reg, these refs can't be translated, + esp. since copy_rtx_and_substitute doesn't know whether it is + reading or writing. */ + if ((TREE_CODE (TREE_TYPE (parms)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (parms)) == UNION_TYPE) + && GET_CODE (DECL_RTL (parms)) == MEM) + return "address of an aggregate parameter is used; cannot be inline"; } *************** *** 316,319 **** --- 344,350 ---- for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) { + orig_asm_operands_vector = 0; + copy_asm_operands_vector = 0; + switch (GET_CODE (insn)) { *************** *** 402,405 **** --- 433,452 ---- return x; + case ASM_OPERANDS: + /* If a single asm insn contains multiple output operands + then it contains multiple ASM_OPERANDS rtx's that share operand 3. + We must make sure that the copied insn continues to share it. */ + if (orig_asm_operands_vector == XVEC (orig, 3)) + { + x = rtx_alloc (ASM_OPERANDS); + XSTR (x, 0) = XSTR (orig, 0); + XSTR (x, 1) = XSTR (orig, 1); + XINT (x, 2) = XINT (orig, 2); + XVEC (x, 3) = copy_asm_operands_vector; + XVEC (x, 4) = XVEC (orig, 4); + return x; + } + break; + case MEM: /* A MEM is allowed to be shared if its address is constant *************** *** 485,488 **** --- 532,542 ---- } } + + if (code == ASM_OPERANDS && orig_asm_operands_vector == 0) + { + orig_asm_operands_vector = XVEC (orig, 3); + copy_asm_operands_vector = XVEC (x, 3); + } + return x; } *************** *** 749,752 **** --- 803,809 ---- rtx copy, pattern, next = 0; + orig_asm_operands_vector = 0; + copy_asm_operands_vector = 0; + switch (GET_CODE (insn)) { *************** *** 1070,1073 **** --- 1127,1146 ---- return orig; + case ASM_OPERANDS: + /* If a single asm insn contains multiple output operands + then it contains multiple ASM_OPERANDS rtx's that share operand 3. + We must make sure that the copied insn continues to share it. */ + if (orig_asm_operands_vector == XVEC (orig, 3)) + { + copy = rtx_alloc (ASM_OPERANDS); + XSTR (copy, 0) = XSTR (orig, 0); + XSTR (copy, 1) = XSTR (orig, 1); + XINT (copy, 2) = XINT (orig, 2); + XVEC (copy, 3) = copy_asm_operands_vector; + XVEC (copy, 4) = XVEC (orig, 4); + return copy; + } + break; + case CALL: /* This is given special treatment because the first *************** *** 1229,1233 **** copy = parm_map[index]; ! #ifdef BITS_BIG_ENDIAN /* Subtract from OFFSET the offset of where the actual parm value would start. */ --- 1302,1306 ---- copy = parm_map[index]; ! #ifdef BYTES_BIG_ENDIAN /* Subtract from OFFSET the offset of where the actual parm value would start. */ *************** *** 1243,1251 **** && GET_MODE (copy) != VOIDmode)) { ! if (GET_CODE (copy) != MEM) ! abort (); ! return change_address (copy, mode, ! plus_constant (XEXP (copy, 0), ! offset)); } return copy; --- 1316,1342 ---- && GET_MODE (copy) != VOIDmode)) { ! if (GET_CODE (copy) == MEM) ! return change_address (copy, mode, ! plus_constant (XEXP (copy, 0), ! offset)); ! if (GET_CODE (copy) == REG) ! { ! /* Crash if the portion of the arg wanted ! is not the least significant. ! Functions with refs to other parts of a ! parameter should not be inline-- ! see function_cannot_inline_p. */ ! #ifdef BYTES_BIG_ENDIAN ! if (offset + GET_MODE_SIZE (mode) ! != GET_MODE_SIZE (GET_MODE (copy))) ! abort (); ! #else ! if (offset != 0) ! abort (); ! #endif ! return gen_rtx (SUBREG, mode, copy, 0); ! } ! ! abort (); } return copy; *************** *** 1357,1360 **** --- 1448,1458 ---- } } + + if (code == ASM_OPERANDS && orig_asm_operands_vector == 0) + { + orig_asm_operands_vector = XVEC (orig, 3); + copy_asm_operands_vector = XVEC (copy, 3); + } + return copy; } diff -rc2N gcc-1.32/jump.c gcc-1.33/jump.c *** gcc-1.32/jump.c Wed Dec 7 12:22:02 1988 --- gcc-1.33/jump.c Sat Jan 28 19:51:34 1989 *************** *** 1,4 **** /* Optimize jump instructions, for GNU compiler. ! Copyright (C) 1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Optimize jump instructions, for GNU compiler. ! Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 104,110 **** If CROSS_JUMP is nonzero, detect matching code before a jump and its destination and unify them. ! If NOOP_MOVES is nonzero, also delete no-op move insns ! and perform machine-specific peephole optimizations ! (but flag_no_peephole inhibits the latter). If `optimize' is zero, don't change any code, --- 104,108 ---- If CROSS_JUMP is nonzero, detect matching code before a jump and its destination and unify them. ! If NOOP_MOVES is nonzero, also delete no-op move insns. If `optimize' is zero, don't change any code, *************** *** 277,280 **** --- 275,280 ---- register rtx body = PATTERN (insn); + #if 0 /* Keep these, since they are used for conditional branch + scheduling peepholes on the sparc. */ /* Delete insns that existed just to advise flow-analysis. */ *************** *** 282,285 **** --- 282,287 ---- || GET_CODE (body) == CLOBBER) delete_insn (insn); + else + #endif /* Detect and delete no-op move instructions *************** *** 286,290 **** resulting from not allocating a parameter in a register. */ ! else if (GET_CODE (body) == SET && (SET_DEST (body) == SET_SRC (body) || (GET_CODE (SET_DEST (body)) == MEM --- 288,292 ---- resulting from not allocating a parameter in a register. */ ! if (GET_CODE (body) == SET && (SET_DEST (body) == SET_SRC (body) || (GET_CODE (SET_DEST (body)) == MEM *************** *** 337,346 **** for (insn = f; insn; insn = next) { ! /* On the first iteration, if this is the last jump pass ! (just before final), do the special peephole optimizations. */ ! if (noop_moves && first && !flag_no_peephole) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) peephole (insn); /* That could have deleted some insns after INSN, so check now --- 339,352 ---- for (insn = f; insn; insn = next) { ! #if 0 ! /* If NOT the first iteration, if this is the last jump pass ! (just before final), do the special peephole optimizations. ! Avoiding the first iteration gives ordinary jump opts ! a chance to work before peephole opts. */ ! if (noop_moves && !first && !flag_no_peephole) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) peephole (insn); + #endif /* That could have deleted some insns after INSN, so check now *************** *** 367,371 **** if this is the last jump-optimization before final and we need to have a frame pointer. */ ! #if 0 #ifdef EXIT_IGNORE_STACK if (noop_moves && frame_pointer_needed && EXIT_IGNORE_STACK --- 373,377 ---- if this is the last jump-optimization before final and we need to have a frame pointer. */ ! #if 0 /* These are now deleted by flow.c as dead stores. */ #ifdef EXIT_IGNORE_STACK if (noop_moves && frame_pointer_needed && EXIT_IGNORE_STACK *************** *** 468,471 **** --- 474,479 ---- whether a jump is unconditional. */ if (! first + /* Make sure INSN is something we can invert. */ + && condjump_p (insn) && JUMP_LABEL (insn) == label1 && LABEL_NUSES (label1) == 1 *************** *** 1162,1166 **** } } ! /* Delete insn INSN from the chain of insns and update label ref counts. May delete some following insns as a consequence; may even delete --- 1170,1174 ---- } } ! \f /* Delete insn INSN from the chain of insns and update label ref counts. May delete some following insns as a consequence; may even delete *************** *** 1266,1269 **** --- 1274,1318 ---- insn = NEXT_INSN (insn); return insn; + } + \f + /* Delete a range of insns from FROM to TO, inclusive. + This is for the sake of peephole optimization, so assume + that whatever these insns do will still be done by a new + peephole insn that will replace them. */ + + void + delete_for_peephole (from, to) + register rtx from, to; + { + register rtx insn = from; + + while (1) + { + register rtx next = NEXT_INSN (insn); + register rtx prev = PREV_INSN (insn); + + if (GET_CODE (insn) != NOTE) + { + INSN_DELETED_P (insn) = 1; + + /* Patch this insn out of the chain. */ + /* We don't do this all at once, because we + must preserve all NOTEs. */ + if (prev) + NEXT_INSN (prev) = next; + + if (next) + PREV_INSN (next) = prev; + } + + if (insn == to) + break; + insn = next; + } + + /* Note that if TO is an unconditional jump + we *do not* delete the BARRIER that follows, + since the peephole that replaces this sequence + is also an unconditional jump in that case. */ } \f diff -rc2N gcc-1.32/loop.c gcc-1.33/loop.c *** gcc-1.32/loop.c Sat Dec 17 13:26:33 1988 --- gcc-1.33/loop.c Sun Jan 15 16:46:33 1989 *************** *** 117,120 **** --- 117,125 ---- static short *n_times_used; + /* Nonzero means reg N has already been moved out of one loop. + This reduces the desire to move it out of another. */ + + static char *moved_once; + /* Array of fixed memory addresses that are stored in this loop. If there are too many to fit here, *************** *** 221,224 **** --- 226,232 ---- old_max_reg = max_reg_num (); + moved_once = (char *) alloca (old_max_reg); + bzero (moved_once, old_max_reg); + /* First find the last real insn, and count the number of insns, and assign insns their suids. */ *************** *** 798,801 **** --- 806,817 ---- fprintf (loop_dump_stream, "savings %d ", savings); + if (moved_once[regno]) + { + insn_count *= 2; + + if (loop_dump_stream) + fprintf (loop_dump_stream, "halved since already moved "); + } + /* An insn MUST be moved if we already moved something else which is safe only if this one is moved too: that is, *************** *** 921,924 **** --- 937,943 ---- already_moved[regno] = 1; + /* This reg has been moved out of one loop. */ + moved_once[regno] = 1; + /* The reg set here is now invariant. */ if (! m->partial) *************** *** 1056,1063 **** int nregs; { ! register RTX_CODE code = GET_CODE (x); register int i; register char *fmt; switch (code) { --- 1075,1086 ---- int nregs; { ! register enum rtx_code code; register int i; register char *fmt; + if (x == 0) + return x; + + code = GET_CODE (x); switch (code) { *************** *** 1100,1107 **** rtx x, reg, addr; { ! register RTX_CODE code = GET_CODE (x); register int i; register char *fmt; switch (code) { --- 1123,1133 ---- rtx x, reg, addr; { ! register enum rtx_code code; register int i; register char *fmt; + if (x == 0) + return; + code = GET_CODE (x); switch (code) { *************** *** 1301,1305 **** int beg, end; { ! register RTX_CODE code = GET_CODE (x); register int i; register char *fmt; --- 1327,1331 ---- int beg, end; { ! register enum rtx_code code = GET_CODE (x); register int i; register char *fmt; *************** *** 1398,1405 **** { register int i; ! register RTX_CODE code = GET_CODE (x); register char *fmt; int conditional = 0; switch (code) { --- 1424,1434 ---- { register int i; ! register enum rtx_code code; register char *fmt; int conditional = 0; + if (x == 0) + return 1; + code = GET_CODE (x); switch (code) { *************** *** 1765,1771 **** { int i; ! enum rtx_code code = GET_CODE (x); char *fmt; switch (code) { --- 1794,1803 ---- { int i; ! enum rtx_code code; char *fmt; + if (x == 0) + return 0; + code = GET_CODE (x); switch (code) { *************** *** 3004,3010 **** rtx *mult_val; { ! register RTX_CODE code = GET_CODE (x); rtx arg; switch (code) { --- 3036,3045 ---- rtx *mult_val; { ! register enum rtx_code code; rtx arg; + if (x == 0) + return 0; + code = GET_CODE (x); switch (code) { *************** *** 3095,3099 **** struct induction **forces2; { ! register RTX_CODE code = GET_CODE (x); rtx arg; struct induction *g = 0; --- 3130,3134 ---- struct induction **forces2; { ! register enum rtx_code code; rtx arg; struct induction *g = 0; *************** *** 3102,3105 **** --- 3137,3144 ---- int tem; + if (x == 0) + return 0; + + code = GET_CODE (x); switch (code) { diff -rc2N gcc-1.32/m68k.md gcc-1.33/m68k.md *** gcc-1.32/m68k.md Wed Dec 14 13:51:28 1988 --- gcc-1.33/m68k.md Wed Jan 11 20:51:06 1989 *************** *** 412,430 **** }") - (define_insn "" - [(set (cc0) - (minus (match_operand:QI 0 "memory_operand" ">") - (match_operand:QI 1 "memory_operand" ">")))] - "GET_CODE (XEXP (operands[0], 0)) == POST_INC - && GET_CODE (XEXP (operands[1], 0)) == POST_INC" - "cmpm%.b %1,%0") - (define_insn "cmpqi" [(set (cc0) ! (minus (match_operand:QI 0 "general_operand" "dn,md") ! (match_operand:QI 1 "general_operand" "dm,nd")))] "" "* { if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) --- 412,424 ---- }") (define_insn "cmpqi" [(set (cc0) ! (minus (match_operand:QI 0 "general_operand" "dn,md,>") ! (match_operand:QI 1 "general_operand" "dm,nd,>")))] "" "* { + if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) + return \"cmpm%.b %1,%0\"; if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) *************** *** 690,694 **** { if (operands[1] == const0_rtx) ! return \"clrl %0\"; return \"pea %a1\"; }") --- 684,688 ---- { if (operands[1] == const0_rtx) ! return \"clr%.l %0\"; return \"pea %a1\"; }") *************** *** 1492,1496 **** #ifdef SGS if (GET_CODE (operands[2]) == REG) ! return \"lea (%1,%2.l),%0\"; else return \"lea %c2(%1),%0\"; --- 1486,1490 ---- #ifdef SGS if (GET_CODE (operands[2]) == REG) ! return \"lea 0(%1,%2.l),%0\"; else return \"lea %c2(%1),%0\"; *************** *** 2836,2840 **** (match_operand:SI 2 "general_operand" "di,di")) (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) ! (match_operand 3 "immediate_operand" "i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[3]) == CONST_INT --- 2830,2834 ---- (match_operand:SI 2 "general_operand" "di,di")) (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) ! (match_operand 3 "immediate_operand" "i,i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[3]) == CONST_INT *************** *** 2864,2868 **** (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) ! (match_operand:SI 3 "general_operand" "d"))] "TARGET_68020 && TARGET_BITFIELD" "bfins %3,%0{%b2:%b1}") --- 2858,2862 ---- (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) ! (match_operand:SI 3 "general_operand" "d,d"))] "TARGET_68020 && TARGET_BITFIELD" "bfins %3,%0{%b2:%b1}") *************** *** 3120,3124 **** "* cc_status = cc_prev_status; ! OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", \"and%.b %#0xc,%!\;sgt %0\"); ") --- 3114,3118 ---- "* cc_status = cc_prev_status; ! OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0); ") *************** *** 3164,3168 **** "* cc_status = cc_prev_status; ! OUTPUT_JUMP (\"sle %0\", \"fsle %0\", \"and%.b %#0xc,%!\;sle %0\"); ") --- 3158,3162 ---- "* cc_status = cc_prev_status; ! OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0); ") *************** *** 3217,3223 **** "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jbgt %l0\", \"fbgt %l0\", \"and%.b %#0xc,%!\;jbgt %l0\"); #else ! OUTPUT_JUMP (\"jgt %l0\", \"fjgt %l0\", \"andb %#0xc,%!\;jgt %l0\"); #endif ") --- 3211,3217 ---- "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jbgt %l0\", \"fbgt %l0\", 0); #else ! OUTPUT_JUMP (\"jgt %l0\", \"fjgt %l0\", 0); #endif ") *************** *** 3307,3313 **** "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jble %l0\", \"fble %l0\", \"and%.b %#0xc,%!\;jble %l0\"); #else ! OUTPUT_JUMP (\"jle %l0\", \"fjle %l0\", \"and%.b %#0xc,%!\;jle %l0\"); #endif ") --- 3301,3307 ---- "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jble %l0\", \"fble %l0\", 0); #else ! OUTPUT_JUMP (\"jle %l0\", \"fjle %l0\", 0); #endif ") *************** *** 3371,3377 **** "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jble %l0\", \"fbngt %l0\", \"and%.b %#0xc,%!\;jble %l0\"); #else ! OUTPUT_JUMP (\"jle %l0\", \"fjngt %l0\", \"and%.b %#0xc,%!\;jle %l0\"); #endif ") --- 3365,3371 ---- "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jble %l0\", \"fbngt %l0\", 0); #else ! OUTPUT_JUMP (\"jle %l0\", \"fjngt %l0\", 0); #endif ") *************** *** 3461,3467 **** "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jbgt %l0\", \"fbnle %l0\", \"and%.b %#0xc,%!\;jbgt %l0\"); #else ! OUTPUT_JUMP (\"jgt %l0\", \"fjnle %l0\", \"and%.b %#0xc,%!\;jgt %l0\"); #endif ") --- 3455,3461 ---- "* #ifdef MOTOROLA ! OUTPUT_JUMP (\"jbgt %l0\", \"fbnle %l0\", 0); #else ! OUTPUT_JUMP (\"jgt %l0\", \"fjnle %l0\", 0); #endif ") *************** *** 3550,3558 **** #ifdef SGS #ifdef ASM_OUTPUT_CASE_LABEL ! if (! RTX_INTEGRATED_P (operands[1])) ! return \"jmp 6(%%pc,%0.w)\"; ! #endif ! return \"jmp 2(%%pc,%0.w)\"; #else #ifdef MOTOROLA return \"jmp (2,pc,%0.w)\"; --- 3544,3552 ---- #ifdef SGS #ifdef ASM_OUTPUT_CASE_LABEL ! return \"jmp 6(%%pc,%0.w)\"; #else + return \"jmp 2(%%pc,%0.w)\"; + #endif + #else /* not SGS */ #ifdef MOTOROLA return \"jmp (2,pc,%0.w)\"; diff -rc2N gcc-1.32/make-cccp.com gcc-1.33/make-cccp.com *** gcc-1.32/make-cccp.com Wed Dec 14 23:02:20 1988 --- gcc-1.33/make-cccp.com Sun Jan 22 04:59:57 1989 *************** *** 3,8 **** $! $ if "''p1'" .eqs. "LINK" then goto Link ! ! $ gcc /define=("GCC_INCLUDE_DIR=""gnu_cc:[000000]""",- ! ! "GPLUSPLUS_INCLUDE_DIR=""gnu_cc:[000000]""","IDENT_DIRECTIVE") cccp.c $ t1:='f$search("CEXP.C")' $ if "''t1'" .eqs. "" then goto 10$ --- 3,7 ---- $! $ if "''p1'" .eqs. "LINK" then goto Link ! $ gcc/debug cccp.c $ t1:='f$search("CEXP.C")' $ if "''t1'" .eqs. "" then goto 10$ *************** *** 14,20 **** $ 10$: $ bison cexp.y $ 20$: $! - $ rename cexp_tab.c cexp.c $ gcc/debug cexp.c $ gcc/debug version.c --- 13,19 ---- $ 10$: $ bison cexp.y + $ rename cexp_tab.c cexp.c $ 20$: $! $ gcc/debug cexp.c $ gcc/debug version.c diff -rc2N gcc-1.32/masm386.c gcc-1.33/masm386.c *** gcc-1.32/masm386.c Sat Jul 16 17:53:40 1988 --- gcc-1.33/masm386.c Tue Jan 17 19:36:00 1989 *************** *** 23,107 **** static tree *implicit_declares; ! int implicit_declares_max=0; ! int implicit_declares_fillp=0; ! add_to_implicit_list(t) ! tree t; { if (implicit_declares_max > implicit_declares_fillp) ! {implicit_declares [implicit_declares_fillp++]=t;return;} ! else ! {tree *new; int i; ! implicit_declares_max=2*(implicit_declares_max+10); ! new=(tree *)(xmalloc(implicit_declares_max*sizeof(tree *))); ! for (i=0; i<implicit_declares_fillp; i++) ! new[i]=implicit_declares[i]; ! implicit_declares=new; ! implicit_declares [implicit_declares_fillp++]=t;return;}} ! ! ! write_implicit_declares() ! {int i; ! for(i=0;i<implicit_declares_fillp;i++) ! {tree t; ! t=implicit_declares[i]; ! if (!IDENTIFIER_GLOBAL_VALUE(t) && IDENTIFIER_IMPLICIT_DECL(t)) ! { /* avoid repeats */ ! IDENTIFIER_IMPLICIT_DECL(t)=0; ! fprintf(aux_asm_out_file,"EXTRN "); ! assemble_name(aux_asm_out_file,IDENTIFIER_POINTER(t)); ! fprintf(aux_asm_out_file,":NEAR ; implicit\n");}}} void ! asm_write_decls(decls,toplevel) ! int toplevel; ! tree decls; ! { tree tr,t; ! char *type,*size; ! tr=nreverse(decls); ! for (t=tr; t ;t=TREE_CHAIN(t)) ! { type=0; ! size=0; ! if (TREE_CODE(t)==FUNCTION_DECL ! &&(!toplevel || TREE_ASM_WRITTEN(t))) ! { if (!toplevel && IDENTIFIER_IMPLICIT_DECL(DECL_NAME(t)) ) ! { add_to_implicit_list(DECL_NAME(t)); ! continue;} ! if (TREE_PUBLIC(t) ! && (DECL_INITIAL(t))) ! type="PUBLIC "; ! else {if (TREE_PUBLIC(t) || TREE_EXTERNAL(t)) ! {type="EXTRN "; ! size="NEAR";}}} else ! if (TREE_CODE(t)==VAR_DECL) ! {if (TREE_PUBLIC(t) && DECL_INITIAL(t)) ! type="PUBLIC "; ! else if (TREE_EXTERNAL(t)) ! {type="EXTRN "; ! switch(int_size_in_bytes(TREE_TYPE(t))){ ! case 1: size="BYTE"; break; ! case 2: size="WORD"; break; ! case 4: size="DWORD"; break; ! case 8: size="QWORD"; break; ! default: size="BYTE"; break; ! } ! }} if (type) ! { fputs(type,aux_asm_out_file); ! putc(' ',aux_asm_out_file); ! assemble_name(aux_asm_out_file,IDENTIFIER_POINTER(DECL_NAME(t))); ! if(size) ! fprintf(aux_asm_out_file,":%s",size); ! fprintf(aux_asm_out_file,"\t\t; %d,%d,%d,%d,%d", ! TREE_EXTERNAL(t),TREE_PUBLIC(t),TREE_STATIC(t), ! DECL_INITIAL(t),TREE_CODE(t)); ! putc('\n',aux_asm_out_file); } } - nreverse(tr); - } /* If we are using a library which does not follow the underscore convention, --- 23,134 ---- static tree *implicit_declares; ! int implicit_declares_max = 0; ! int implicit_declares_fillp = 0; ! add_to_implicit_list (t) ! tree t; { if (implicit_declares_max > implicit_declares_fillp) ! { ! implicit_declares[implicit_declares_fillp++] = t; ! } ! else ! { ! tree *new; ! int i; ! ! implicit_declares_max = 2 * (implicit_declares_max + 10); ! new = (tree *)(xmalloc (implicit_declares_max * sizeof (tree *))); ! for (i = 0; i < implicit_declares_fillp; i++) ! new[i] = implicit_declares[i]; ! implicit_declares = new; ! implicit_declares[implicit_declares_fillp++] = t; ! } ! } ! ! ! write_implicit_declares () ! { ! int i; ! for (i = 0; i < implicit_declares_fillp; i++) ! { ! tree t; ! t = implicit_declares[i]; ! if (!IDENTIFIER_GLOBAL_VALUE (t) && IDENTIFIER_IMPLICIT_DECL (t)) ! { /* avoid repeats */ ! IDENTIFIER_IMPLICIT_DECL (t) = 0; ! fprintf (aux_asm_out_file, "EXTRN "); ! assemble_name (aux_asm_out_file, IDENTIFIER_POINTER (t)); ! fprintf (aux_asm_out_file, ":NEAR ; implicit\n"); ! } ! } ! } void ! asm_write_decls (decls, toplevel) ! int toplevel; ! tree decls; ! { ! tree tr, t; ! char *type, *size; ! tr = nreverse (decls); ! for (t = tr; t; t = TREE_CHAIN (t)) ! { ! type = 0; ! size = 0; ! if (TREE_CODE (t) == FUNCTION_DECL ! && (!toplevel || TREE_ASM_WRITTEN (t))) ! { ! if (!toplevel && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (t))) ! { ! add_to_implicit_list (DECL_NAME (t)); ! continue; ! } ! if (TREE_PUBLIC (t) ! && (DECL_INITIAL (t))) ! type = "PUBLIC "; ! else { ! if (TREE_PUBLIC (t) || TREE_EXTERNAL (t)) ! { ! type = "EXTRN "; ! size = "NEAR"; ! } ! } ! } else ! if (TREE_CODE (t) == VAR_DECL) ! { ! if (TREE_PUBLIC (t) && DECL_INITIAL (t)) ! type = "PUBLIC "; ! else if (TREE_EXTERNAL (t)) ! { ! type = "EXTRN "; ! switch (int_size_in_bytes (TREE_TYPE (t))) ! { ! case 1: size = "BYTE"; break; ! case 2: size = "WORD"; break; ! case 4: size = "DWORD"; break; ! case 8: size = "QWORD"; break; ! default: size = "BYTE"; break; ! } ! } ! } if (type) ! { ! fputs (type, aux_asm_out_file); ! putc (' ', aux_asm_out_file); ! assemble_name (aux_asm_out_file, IDENTIFIER_POINTER (DECL_NAME (t))); ! if (size) ! fprintf (aux_asm_out_file, ":%s", size); ! fprintf (aux_asm_out_file, "\t\t; %d,%d,%d,%d,%d", ! TREE_EXTERNAL (t), TREE_PUBLIC (t), TREE_STATIC (t), ! DECL_INITIAL (t), TREE_CODE (t)); ! putc ('\n', aux_asm_out_file); } + } + nreverse (tr); } /* If we are using a library which does not follow the underscore convention, *************** *** 116,126 **** /* #include <string.h> */ ! char *no_prefix_names[]={ #include "masm-lib.h" }; ! static int node_compare(a,b) ! char **a,**b; ! {return strcmp(*a,*b);} /* Masm needs extrn references for ALL symbols written, --- 143,156 ---- /* #include <string.h> */ ! char *no_prefix_names[] = { #include "masm-lib.h" }; ! static int ! node_compare (a, b) ! char **a, **b; ! { ! return strcmp (*a, *b); ! } /* Masm needs extrn references for ALL symbols written, *************** *** 133,180 **** void ! mark_name_used(name) char *name; ! {tree t=get_identifier(name); ! if ((IDENTIFIER_GLOBAL_VALUE(t)) ! && TREE_CODE((IDENTIFIER_GLOBAL_VALUE(t)))==FUNCTION_DECL) ! TREE_ASM_WRITTEN(IDENTIFIER_GLOBAL_VALUE(t))=1; } ! static int number_no_prefix_names=0; ! int use_prefix=1; ! asm_output_labelref(file,name) char *name; ! {int i; ! char *ans; ! char *test[1]; ! mark_name_used(name); ! ans=0; ! test[0]=name; ! if (!number_no_prefix_names) ! { for (i=0;;i++) ! if(*(no_prefix_names[i]) == 0) ! {number_no_prefix_names=i; break;}} ! if (use_prefix) ! ans= ! (char *) ! bsearch(test,no_prefix_names,number_no_prefix_names, ! sizeof(char *),node_compare); ! if (ans || !use_prefix) fprintf(file,name); ! else fprintf(file, "_%s",name); ! } void ! asm_library_declare(fun) ! rtx fun; ! { tree iden; ! iden=get_identifier(XSTR(fun,0)); ! if (!TREE_ASM_WRITTEN(iden)) ! {fprintf(aux_asm_out_file,"EXTRN "); ! assemble_name(aux_asm_out_file,XSTR(fun,0)); ! fprintf(aux_asm_out_file,":NEAR ; library\n"); ! TREE_ASM_WRITTEN(iden)=1;}} ! /* list of implicit declares identifier_node uid's --- 163,223 ---- void ! mark_name_used (name) char *name; ! { ! tree t = get_identifier (name); ! if (IDENTIFIER_GLOBAL_VALUE (t) ! && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (t)) == FUNCTION_DECL) ! TREE_ASM_WRITTEN (IDENTIFIER_GLOBAL_VALUE (t)) = 1; } ! static int number_no_prefix_names = 0; ! int use_prefix = 1; ! asm_output_labelref (file, name) ! int file; char *name; ! { ! int i; ! char *ans; ! char *test[1]; ! ! mark_name_used (name); ! ans = 0; ! test[0] = name; ! if (!number_no_prefix_names) ! { ! for (i = 0;; i++) ! if (*(no_prefix_names[i]) == 0) ! { ! number_no_prefix_names = i; ! break; ! } ! } ! if (use_prefix) ! ans = ! (char *) ! bsearch (test, no_prefix_names, number_no_prefix_names, ! sizeof (char *), node_compare); ! if (ans || !use_prefix) ! fprintf (file, name); ! else ! fprintf (file, "_%s", name); } void ! asm_library_declare (fun) ! rtx fun; ! { ! tree iden; ! iden = get_identifier (XSTR (fun, 0)); ! if (!TREE_ASM_WRITTEN (iden)) ! { ! fprintf (aux_asm_out_file, "EXTRN "); ! assemble_name (aux_asm_out_file, XSTR (fun, 0)); ! fprintf (aux_asm_out_file, ":NEAR ; library\n"); ! TREE_ASM_WRITTEN (iden) = 1; ! } ! } /* list of implicit declares identifier_node uid's diff -rc2N gcc-1.32/ns32k.md gcc-1.33/ns32k.md *** gcc-1.32/ns32k.md Tue Dec 20 01:40:43 1988 --- gcc-1.33/ns32k.md Thu Dec 22 17:27:23 1988 *************** *** 1109,1113 **** } } - } return \"andd %2,%0\"; }") --- 1109,1112 ---- diff -rc2N gcc-1.32/optabs.c gcc-1.33/optabs.c *** gcc-1.32/optabs.c Wed Dec 7 18:11:13 1988 --- gcc-1.33/optabs.c Wed Jan 11 13:13:49 1989 *************** *** 636,646 **** /* Generate code to compare X with Y so that the condition codes are set. - If they have mode BLKmode, then SIZE specifies the size of block. */ void ! emit_cmp_insn (x, y, size, unsignedp) rtx x, y; rtx size; int unsignedp; { enum machine_mode mode = GET_MODE (x); --- 636,652 ---- /* Generate code to compare X with Y so that the condition codes are set. + UNSIGNEDP nonzero says that X and Y are unsigned; + this matters if they need to be widened. + + If they have mode BLKmode, then SIZE specifies the size of both X and Y, + and ALIGN specifies the known shared alignment of X and Y. */ + void ! emit_cmp_insn (x, y, size, unsignedp, align) rtx x, y; rtx size; int unsignedp; + int align; { enum machine_mode mode = GET_MODE (x); *************** *** 669,673 **** && GET_CODE (size) == CONST_INT && INTVAL (size) < (1 << BITS_PER_UNIT)) ! emit_insn (gen_cmpstrqi (x, y, size)); else #endif --- 675,688 ---- && GET_CODE (size) == CONST_INT && INTVAL (size) < (1 << BITS_PER_UNIT)) ! emit_insn (gen_cmpstrqi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); ! else ! #endif ! #ifdef HAVE_cmpstrhi ! if (HAVE_cmpstrhi ! && GET_CODE (size) == CONST_INT ! && INTVAL (size) < (1 << BITS_PER_UNIT)) ! emit_insn (gen_cmpstrhi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); else #endif *************** *** 674,678 **** #ifdef HAVE_cmpstrsi if (HAVE_cmpstrsi) ! emit_insn (gen_cmpstrsi (x, y, convert_to_mode (SImode, size, 1))); else #endif --- 689,694 ---- #ifdef HAVE_cmpstrsi if (HAVE_cmpstrsi) ! emit_insn (gen_cmpstrsi (x, y, convert_to_mode (SImode, size, 1), ! gen_rtx (CONST_INT, VOIDmode, align))); else #endif *************** *** 685,689 **** SImode, 3, x, Pmode, y, Pmode, size, Pmode); #endif ! emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0); } } --- 701,705 ---- SImode, 3, x, Pmode, y, Pmode, size, Pmode); #endif ! emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0); } } *************** *** 728,732 **** x = convert_to_mode (SImode, x, unsignedp); y = convert_to_mode (SImode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp); } else if ((mode == QImode || mode == HImode || mode == SImode) --- 744,748 ---- x = convert_to_mode (SImode, x, unsignedp); y = convert_to_mode (SImode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp, 0); } else if ((mode == QImode || mode == HImode || mode == SImode) *************** *** 735,739 **** x = convert_to_mode (DImode, x, unsignedp); y = convert_to_mode (DImode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp); } else if (mode == SFmode --- 751,755 ---- x = convert_to_mode (DImode, x, unsignedp); y = convert_to_mode (DImode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp, 0); } else if (mode == SFmode *************** *** 742,746 **** x = convert_to_mode (DFmode, x, unsignedp); y = convert_to_mode (DFmode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp); } else if (cmp_optab->handlers[(int) mode].lib_call) --- 758,762 ---- x = convert_to_mode (DFmode, x, unsignedp); y = convert_to_mode (DFmode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp, 0); } else if (cmp_optab->handlers[(int) mode].lib_call) *************** *** 759,765 **** there is still a value that can represent the result "less than". */ if (GET_MODE_CLASS (mode) == MODE_INT) ! emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, 0, unsignedp); else ! emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0); } else if (mode == SFmode --- 775,781 ---- there is still a value that can represent the result "less than". */ if (GET_MODE_CLASS (mode) == MODE_INT) ! emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, 0, unsignedp, 0); else ! emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0); } else if (mode == SFmode *************** *** 769,773 **** x = convert_to_mode (DFmode, x, unsignedp); y = convert_to_mode (DFmode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp); } else --- 785,789 ---- x = convert_to_mode (DFmode, x, unsignedp); y = convert_to_mode (DFmode, y, unsignedp); ! emit_cmp_insn (x, y, 0, unsignedp, 0); } else *************** *** 1113,1124 **** rtx label = gen_label_rtx (); rtx temp; ! double offset; ! double ldexp (); do_pending_stack_adjust (); emit_cmp_insn (to, GET_MODE (to) == DFmode ? dconst0_rtx : fconst0_rtx, ! 0, 0); emit_jump_insn (gen_bge (label)); ! offset = ldexp (1.0, GET_MODE_BITSIZE (GET_MODE (from))); temp = expand_binop (GET_MODE (to), add_optab, to, immed_real_const_1 (offset, GET_MODE (to)), --- 1129,1139 ---- rtx label = gen_label_rtx (); rtx temp; ! REAL_VALUE_TYPE offset; do_pending_stack_adjust (); emit_cmp_insn (to, GET_MODE (to) == DFmode ? dconst0_rtx : fconst0_rtx, ! 0, 0, 0); emit_jump_insn (gen_bge (label)); ! offset = REAL_VALUE_LDEXP (1.0, GET_MODE_BITSIZE (GET_MODE (from))); temp = expand_binop (GET_MODE (to), add_optab, to, immed_real_const_1 (offset, GET_MODE (to)), *************** *** 1366,1370 **** --- 1381,1390 ---- smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3; #endif + + #ifdef MULSI3_LIBCALL + smul_optab->handlers[(int) SImode].lib_call = MULSI3_LIBCALL; + #else smul_optab->handlers[(int) SImode].lib_call = "__mulsi3"; + #endif smul_optab->handlers[(int) DImode].lib_call = "__muldi3"; smul_optab->handlers[(int) SFmode].lib_call = "__mulsf3"; *************** *** 1408,1412 **** --- 1428,1437 ---- umul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_umuldf3; #endif + + #ifdef UMULSI3_LIBCALL + umul_optab->handlers[(int) SImode].lib_call = UMULSI3_LIBCALL; + #else umul_optab->handlers[(int) SImode].lib_call = "__umulsi3"; + #endif umul_optab->handlers[(int) DImode].lib_call = "__umuldi3"; umul_optab->handlers[(int) SFmode].lib_call = "__umulsf3"; *************** *** 1442,1446 **** --- 1467,1476 ---- sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3; #endif + + #ifdef DIVSI3_LIBCALL + sdiv_optab->handlers[(int) SImode].lib_call = DIVSI3_LIBCALL; + #else sdiv_optab->handlers[(int) SImode].lib_call = "__divsi3"; + #endif sdiv_optab->handlers[(int) DImode].lib_call = "__divdi3"; *************** *** 1461,1464 **** --- 1491,1495 ---- udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3; #endif + #ifdef UDIVSI3_LIBCALL udiv_optab->handlers[(int) SImode].lib_call = UDIVSI3_LIBCALL; *************** *** 1518,1522 **** --- 1549,1558 ---- smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3; #endif + + #ifdef MODSI3_LIBCALL + smod_optab->handlers[(int) SImode].lib_call = MODSI3_LIBCALL; + #else smod_optab->handlers[(int) SImode].lib_call = "__modsi3"; + #endif smod_optab->handlers[(int) DImode].lib_call = "__moddi3"; *************** *** 1537,1540 **** --- 1573,1577 ---- umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3; #endif + #ifdef UMODSI3_LIBCALL umod_optab->handlers[(int) SImode].lib_call = UMODSI3_LIBCALL; diff -rc2N gcc-1.32/output-alliant.c gcc-1.33/output-alliant.c *** gcc-1.32/output-alliant.c Wed Dec 31 19:00:00 1969 --- gcc-1.33/output-alliant.c Sun Jan 1 16:10:57 1989 *************** *** 0 **** --- 1,304 ---- + /* Subroutines for insn-output.c for Alliant computers. + Copyright (C) 1988 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + + /* Some output-actions in m68k.md need these. */ + #include <stdio.h> + + extern FILE *asm_out_file; + + /* Index into this array by (register number >> 3) to find the + smallest class which contains that register. */ + enum reg_class regno_reg_class[] + = { DATA_REGS, ADDR_REGS, FP_REGS, + LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS }; + + static rtx find_addr_reg (); + + char * + output_btst (operands, countop, dataop, insn, signpos) + rtx *operands; + rtx countop, dataop; + rtx insn; + int signpos; + { + operands[0] = countop; + operands[1] = dataop; + if (GET_CODE (countop) == CONST_INT) + { + register int count = INTVAL (countop); + if (count == signpos) + cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N; + else + cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N; + + if (count == 31 + && next_insns_test_no_inequality (insn)) + return "tst%.l %1"; + if (count == 15 + && next_insns_test_no_inequality (insn)) + return "tst%.w %1"; + if (count == 7 + && next_insns_test_no_inequality (insn)) + return "tst%.b %1"; + + cc_status.flags = CC_NOT_NEGATIVE; + } + return "btst %0,%1"; + } + \f + /* Return the best assembler insn template + for moving operands[1] into operands[0] as a fullword. */ + + static char * + singlemove_string (operands) + rtx *operands; + { + if (operands[1] != const0_rtx) + return "mov%.l %1,%0"; + if (! ADDRESS_REG_P (operands[0])) + return "clr%.l %0"; + return "sub%.l %0,%0"; + } + + /* Output assembler code to perform a doubleword move insn + with operands OPERANDS. */ + + char * + output_move_double (operands) + rtx *operands; + { + enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; + rtx latehalf[2]; + rtx addreg0 = 0, addreg1 = 0; + + /* First classify both operands. */ + + if (REG_P (operands[0])) + optype0 = REGOP; + else if (offsetable_memref_p (operands[0])) + optype0 = OFFSOP; + else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) + optype0 = POPOP; + else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + optype0 = PUSHOP; + else if (GET_CODE (operands[0]) == MEM) + optype0 = MEMOP; + else + optype0 = RNDOP; + + if (REG_P (operands[1])) + optype1 = REGOP; + else if (CONSTANT_P (operands[1]) + || GET_CODE (operands[1]) == CONST_DOUBLE) + optype1 = CNSTOP; + else if (offsetable_memref_p (operands[1])) + optype1 = OFFSOP; + else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC) + optype1 = POPOP; + else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) + optype1 = PUSHOP; + else if (GET_CODE (operands[1]) == MEM) + optype1 = MEMOP; + else + optype1 = RNDOP; + + /* Check for the cases that the operand constraints are not + supposed to allow to happen. Abort if we get one, + because generating code for these cases is painful. */ + + if (optype0 == RNDOP || optype1 == RNDOP) + abort (); + + /* If one operand is decrementing and one is incrementing + decrement the former register explicitly + and change that operand into ordinary indexing. */ + + if (optype0 == PUSHOP && optype1 == POPOP) + { + operands[0] = XEXP (XEXP (operands[0], 0), 0); + output_asm_insn ("subq%.l %#8,%0", operands); + operands[0] = gen_rtx (MEM, DImode, operands[0]); + optype0 = OFFSOP; + } + if (optype0 == POPOP && optype1 == PUSHOP) + { + operands[1] = XEXP (XEXP (operands[1], 0), 0); + output_asm_insn ("subq%.l %#8,%1", operands); + operands[1] = gen_rtx (MEM, DImode, operands[1]); + optype1 = OFFSOP; + } + + /* If an operand is an unoffsettable memory ref, find a register + we can increment temporarily to make it refer to the second word. */ + + if (optype0 == MEMOP) + addreg0 = find_addr_reg (operands[0]); + + if (optype1 == MEMOP) + addreg1 = find_addr_reg (operands[1]); + + /* Ok, we can do one word at a time. + Normally we do the low-numbered word first, + but if either operand is autodecrementing then we + do the high-numbered word first. + + In either case, set up in LATEHALF the operands to use + for the high-numbered word and in some cases alter the + operands in OPERANDS to be suitable for the low-numbered word. */ + + if (optype0 == REGOP) + latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else if (optype0 == OFFSOP) + latehalf[0] = adj_offsetable_operand (operands[0], 4); + else + latehalf[0] = operands[0]; + + if (optype1 == REGOP) + latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + else if (optype1 == OFFSOP) + latehalf[1] = adj_offsetable_operand (operands[1], 4); + else if (optype1 == CNSTOP) + { + if (CONSTANT_P (operands[1])) + latehalf[1] = const0_rtx; + else if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + latehalf[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_HIGH (operands[1])); + operands[1] = gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_LOW (operands[1])); + } + } + else + latehalf[1] = operands[1]; + + /* If insn is effectively movd N(sp),-(sp) then we will do the + high word first. We should use the adjusted operand 1 (which is N+4(sp)) + for the low word as well, to compensate for the first decrement of sp. */ + if (optype0 == PUSHOP + && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM + && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) + operands[1] = latehalf[1]; + + /* If one or both operands autodecrementing, + do the two words, high-numbered first. */ + + /* Likewise, the first move would clobber the source of the second one, + do them in the other order. This happens only for registers; + such overlap can't happen in memory unless the user explicitly + sets it up, and that is an undefined circumstance. */ + + if (optype0 == PUSHOP || optype1 == PUSHOP + || (optype0 == REGOP && optype1 == REGOP + && REGNO (operands[0]) == REGNO (latehalf[1]))) + { + /* Make any unoffsetable addresses point at high-numbered word. */ + if (addreg0) + output_asm_insn ("addql %#4,%0", &addreg0); + if (addreg1) + output_asm_insn ("addql %#4,%0", &addreg1); + + /* Do that word. */ + output_asm_insn (singlemove_string (latehalf), latehalf); + + /* Undo the adds we just did. */ + if (addreg0) + output_asm_insn ("subql %#4,%0", &addreg0); + if (addreg1) + output_asm_insn ("subql %#4,%0", &addreg1); + + /* Do low-numbered word. */ + return singlemove_string (operands); + } + + /* Normal case: do the two words, low-numbered first. */ + + output_asm_insn (singlemove_string (operands), operands); + + /* Make any unoffsetable addresses point at high-numbered word. */ + if (addreg0) + output_asm_insn ("addql %#4,%0", &addreg0); + if (addreg1) + output_asm_insn ("addql %#4,%0", &addreg1); + + /* Do that word. */ + output_asm_insn (singlemove_string (latehalf), latehalf); + + /* Undo the adds we just did. */ + if (addreg0) + output_asm_insn ("subql %#4,%0", &addreg0); + if (addreg1) + output_asm_insn ("subql %#4,%0", &addreg1); + + return ""; + } + + /* Return a REG that occurs in ADDR with coefficient 1. + ADDR can be effectively incremented by incrementing REG. */ + + static rtx + find_addr_reg (addr) + rtx addr; + { + while (GET_CODE (addr) == PLUS) + { + if (GET_CODE (XEXP (addr, 0)) == REG) + addr = XEXP (addr, 0); + if (GET_CODE (XEXP (addr, 1)) == REG) + addr = XEXP (addr, 1); + if (CONSTANT_P (XEXP (addr, 0))) + addr = XEXP (addr, 1); + if (CONSTANT_P (XEXP (addr, 1))) + addr = XEXP (addr, 0); + } + if (GET_CODE (addr) == REG) + return addr; + return 0; + } + \f + char * + output_move_const_double (operands) + rtx *operands; + { + return "fmove%.d %1,%0"; + } + + char * + output_move_const_single (operands) + rtx *operands; + { + return "fmove%.s %1,%0"; + } + + int + standard_68881_constant_p (x) + rtx x; + { + return 0; + } + + int + standard_SunFPA_constant_p (x) + rtx x; + { + return( 0 ); + } + diff -rc2N gcc-1.32/output-convex.c gcc-1.33/output-convex.c *** gcc-1.32/output-convex.c Wed Dec 31 19:00:00 1969 --- gcc-1.33/output-convex.c Sun Jan 29 01:21:48 1989 *************** *** 0 **** --- 1,195 ---- + /* Subroutines for insn-output.c for Convex. + Copyright (C) 1989 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + /* + * set_cmp (left_rtx, right_rtx, [bhwlsd]) + * gen_cmp (label_rtx, cmpop, [tf]) + * + * set_cmp saves the operands of a "cmp" insn, + * along with the type character to be used in the compare instruction. + * + * gen_cmp finds out what comparison is to be performed and + * outputs the necessary instructions, eg, + * "eq.w a1,a2 ! jbra.t L5" + * for (cmpsi a1 a2) (beq L5) + * if necessary, it reverses the order of the operands to put a constant first + * the operands of eq can be swapped without changing the sense + * of the test; swapping the operands of lt changes it to le with + * the branch sense reversed, and similarly for le. + */ + + static rtx xop0, xop1; + static char typech, regch; + + char * + set_cmp (op0, op1, typechr) + rtx op0, op1; + char typechr; + { + xop0 = op0; + xop1 = op1; + typech = typechr; + if (GET_CODE (op0) == REG) + regch = REGNO_OK_FOR_BASE_P (REGNO (op0)) ? 'a' : 's'; + else if (GET_CODE (op1) == REG) + regch = REGNO_OK_FOR_BASE_P (REGNO (op1)) ? 'a' : 's'; + else abort (); + return ""; + } + + char * + gen_cmp (label, cmpop, tf) + rtx label; + char *cmpop; + char tf; + { + char buf[80]; + char revop[4]; + rtx ops[3]; + + ops[2] = label; + + /* constant must be first; swap operands if necessary + if lt, le, ltu, leu are swapped, change to le, lt, leu, ltu + and reverse the sense of the jump */ + + if (CONSTANT_P (xop1) || GET_CODE (xop1) == CONST_DOUBLE) + { + ops[0] = xop1; + ops[1] = xop0; + if (cmpop[0] == 'l') + { + bcopy (cmpop, revop, 4); + revop[1] ^= 'e' ^ 't'; + tf ^= 't' ^ 'f'; + cmpop = revop; + } + } + else + { + ops[0] = xop0; + ops[1] = xop1; + } + + sprintf (buf, "%s.%c %%0,%%1! jbr%c.%c %%l2", cmpop, typech, regch, tf); + output_asm_insn (buf, ops); + return ""; + } + \f + /* + * set_section -- arg is a section name, like ".text". + * Remembers it and returns it + * + * align_section -- returns a string to align current section, + * something like ".text 2" or ".align 8". Arg is log2 of boundary. + */ + + static char *prevsect = ""; + static char *cursect = ""; + + char * + set_section (p) + char *p; + { + if (p == 0) + p = prevsect; + prevsect = cursect; + cursect = p; + return p; + } + + char * + align_section (n) + int n; + { + static char buf[20]; + + if (n < 0) + { + /* -n is a size; align to that size */ + if ((n & 7) == 0) n = 3; + else if ((n & 3) == 0) n = 2; + else if ((n & 1) == 0) n = 1; + else n = 0; + } + + if (!strcmp (cursect, ".text")) + { + if (n > 1) + sprintf (buf, "%s %d\n", cursect, n); + else + sprintf (buf, "%s\n.align %d\n", cursect, 1 << n); + return buf; + } + else + { + if (n == 0) return ""; + sprintf (buf, ".align %d\n", 1 << n); + return buf; + } + } + \f + /* + * calls like (*f)() generate calls @n(ap) -- invalid, since ap + * has been changed for the call. Detect this case so the instruction + * pattern can deal with it. + */ + + call_ap_check (addr) + rtx addr; + { + if (GET_CODE (addr) != MEM) + return 0; + addr = XEXP (addr, 0); + if (GET_CODE (addr) != MEM) + return 0; + addr = XEXP (addr, 0); + if (REG_P (addr) && REGNO (addr) == ARG_POINTER_REGNUM) + return 1; + if (GET_CODE (addr) != PLUS) + return 0; + addr = XEXP (addr, 0); + if (REG_P (addr) && REGNO (addr) == ARG_POINTER_REGNUM) + return 1; + return 0; + } + \f + /* + * pick target machine if not specified, the same as the host + */ + + extern int target_flags; + + override_options () + { + #ifdef convex + #include <sys/sysinfo.h> + if (! (TARGET_C1 || TARGET_C2)) + { + struct system_information sysinfo; + getsysinfo (sizeof sysinfo, &sysinfo); + if (sysinfo.cpu_type >= SI_CPUTYPE_C2MP) + target_flags |= 2; + else + target_flags |= 1; + } + #endif + } + diff -rc2N gcc-1.32/output-i386.c gcc-1.33/output-i386.c *** gcc-1.32/output-i386.c Sat Nov 19 11:19:43 1988 --- gcc-1.33/output-i386.c Sun Jan 1 16:10:39 1989 *************** *** 522,527 **** else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); } } --- 522,529 ---- else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_HIGH (operands[1])); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_LOW (operands[1])); } } *************** *** 604,607 **** --- 606,613 ---- if (d == 1) return 2; + /* Note that on the 80387, other constants, such as pi, + are much slower to load as standard constants + than to load from doubles in memory! */ + return 0; } *************** *** 646,651 **** union { int i[2]; double d;} u1; union { int i; float f;} u2; ! u1.i[0] = XINT (operands[1], 0); ! u1.i[1] = XINT (operands[1], 1); u2.f = u1.d; operands[1] = gen_rtx (CONST_INT, VOIDmode, u2.i); --- 652,657 ---- union { int i[2]; double d;} u1; union { int i; float f;} u2; ! u1.i[0] = CONST_DOUBLE_LOW (operands[1]); ! u1.i[1] = CONST_DOUBLE_HIGH (operands[1]); u2.f = u1.d; operands[1] = gen_rtx (CONST_INT, VOIDmode, u2.i); *************** *** 957,962 **** union { double d; int i[2]; } u; union { float f; int i; } u1; ! u.i[0] = XINT (x, 0); ! u.i[1] = XINT (x, 1); u1.f = u.d; if (code == 'f') --- 963,968 ---- union { double d; int i[2]; } u; union { float f; int i; } u1; ! u.i[0] = CONST_DOUBLE_LOW (x); ! u.i[1] = CONST_DOUBLE_HIGH (x); u1.f = u.d; if (code == 'f') *************** *** 971,976 **** { union { double d; int i[2]; } u; ! u.i[0] = XINT (x, 0); ! u.i[1] = XINT (x, 1); fprintf (file, "%.22e", u.d); } --- 977,982 ---- { union { double d; int i[2]; } u; ! u.i[0] = CONST_DOUBLE_LOW (x); ! u.i[1] = CONST_DOUBLE_HIGH (x); fprintf (file, "%.22e", u.d); } *************** *** 1101,1116 **** \f /* Set the cc_status for the results of an insn whose pattern is EXP. ! On the 80386, we assume that only test and compare insns ! set the condition codes usefully, ! and that all other insns except for jumps and moves ! clobber the condition codes unpredictably. ! In fact, it would be legitimate to detect certain arithmetic ! instructions and record what they do to the cc's, ! but it would be necessary to be careful: ! for example, some fixed-point add insns generate code that ! doesn't set them. In addition, correct handling of arith insn ! cc's requires setting CC_NO_OVERFLOW; but i386.md's jump insns ! don't make correct output in this case. */ notice_update_cc (exp) --- 1107,1118 ---- \f /* Set the cc_status for the results of an insn whose pattern is EXP. ! On the 80386, we assume that only test and compare insns, as well ! as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT, ! ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully. ! Also, we assume that jumps and moves don't affect the condition codes. ! All else, clobbers the condition codes, by assumption. ! We assume that ALL add, minus, etc. instructions effect the condition ! codes. This MUST be consistent with i386.md. */ notice_update_cc (exp) *************** *** 1135,1138 **** --- 1137,1141 ---- && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) cc_status.value2 = 0; + return; } /* Moving register into memory doesn't alter the cc's. *************** *** 1146,1149 **** --- 1149,1158 ---- return; } + /* Function calls clobber the cc's. */ + else if (GET_CODE (SET_SRC (exp)) == CALL) + { + CC_STATUS_INIT; + return; + } /* Tests and compares set the cc's in predictable ways. */ else if (SET_DEST (exp) == cc0_rtx) *************** *** 1153,1156 **** --- 1162,1193 ---- return; } + /* Certain instructions effect the condition codes. */ + else if (GET_MODE (SET_SRC (exp)) == SImode + || GET_MODE (SET_SRC (exp)) == HImode + || GET_MODE (SET_SRC (exp)) == QImode) + switch (GET_CODE (SET_SRC (exp))) + { + case ASHIFTRT: case LSHIFTRT: + case ASHIFT: case LSHIFT: + /* Shifts on the 386 don't set the condition codes if the + shift count is zero. */ + if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT) + { + CC_STATUS_INIT; + break; + } + /* We assume that the CONST_INT is non-zero (this rtx would + have been deleted if it were zero. */ + + case PLUS: case MINUS: case NEG: + case AND: case IOR: case XOR: + cc_status.flags |= CC_NO_OVERFLOW; + cc_status.value1 = SET_SRC (exp); + cc_status.value2 = SET_DEST (exp); + break; + + default: + CC_STATUS_INIT; + } else { diff -rc2N gcc-1.32/output-m68k.c gcc-1.33/output-m68k.c *** gcc-1.32/output-m68k.c Sun Dec 18 14:13:06 1988 --- gcc-1.33/output-m68k.c Sun Jan 1 17:37:50 1989 *************** *** 183,188 **** else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); } } --- 183,190 ---- else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_HIGH (operands[1])); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_LOW (operands[1])); } } *************** *** 349,354 **** union {double d; int i[2];} u; register double d; ! u.i[0] = XINT (x, 0); ! u.i[1] = XINT (x, 1); d = u.d; --- 351,356 ---- union {double d; int i[2];} u; register double d; ! u.i[0] = CONST_DOUBLE_LOW (x); ! u.i[1] = CONST_DOUBLE_HIGH (x); d = u.d; *************** *** 405,410 **** union {double d; int i[2];} u; register double d; ! u.i[0] = XINT (x, 0); ! u.i[1] = XINT (x, 1); d = u.d; --- 407,412 ---- union {double d; int i[2];} u; register double d; ! u.i[0] = CONST_DOUBLE_LOW (x); ! u.i[1] = CONST_DOUBLE_HIGH (x); d = u.d; diff -rc2N gcc-1.32/output-m88k.c gcc-1.33/output-m88k.c *** gcc-1.32/output-m88k.c Tue Nov 15 23:19:52 1988 --- gcc-1.33/output-m88k.c Sun Jan 1 16:09:54 1989 *************** *** 254,259 **** else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); } } --- 254,261 ---- else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_HIGH (operands[1])); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_LOW (operands[1])); } } diff -rc2N gcc-1.32/output-ns32k.c gcc-1.33/output-ns32k.c *** gcc-1.32/output-ns32k.c Sun Dec 4 15:37:20 1988 --- gcc-1.33/output-ns32k.c Sun Jan 1 16:09:41 1989 *************** *** 150,155 **** else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); } } --- 150,157 ---- else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_HIGH (operands[1])); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_LOW (operands[1])); } } diff -rc2N gcc-1.32/output-sparc.c gcc-1.33/output-sparc.c *** gcc-1.32/output-sparc.c Sat Dec 17 12:55:36 1988 --- gcc-1.33/output-sparc.c Tue Jan 31 02:50:45 1989 *************** *** 1,4 **** /* Subroutines for insn-output.c for Sun SPARC. ! Copyright (C) 1987, 1988 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@mcc.com) --- 1,4 ---- /* Subroutines for insn-output.c for Sun SPARC. ! Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@mcc.com) *************** *** 29,32 **** --- 29,34 ---- static rtx find_addr_reg (); + rtx next_real_insn_no_labels (); + /* Return non-zero only if OP is a register of mode MODE, or const0_rtx. */ *************** *** 39,42 **** --- 41,287 ---- } + /* Return non-zero if this pattern, can be evaluated safely, even if it + was not asked for. */ + int + safe_insn_src_p (op, mode) + rtx op; + enum machine_mode mode; + { + /* Just experimenting. */ + + /* No floating point src is safe if it contains an arithmetic + operation, since that operation may trap. */ + switch (GET_CODE (op)) + { + case CONST_INT: + case LABEL_REF: + case SYMBOL_REF: + case CONST: + return 1; + + case REG: + return 1; + + case MEM: + return CONSTANT_ADDRESS_P (XEXP (op, 0)); + + /* We never need to negate or complement constants. */ + case NEG: + return (mode != SFmode && mode != DFmode); + case NOT: + return 1; + + case MINUS: + case PLUS: + return (mode != SFmode && mode != DFmode); + case AND: + case IOR: + case XOR: + case LSHIFT: + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0))) + || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1)))) + return 0; + return 1; + + default: + return 0; + } + } + + /* Return 1 if REG is clobbered in IN. + Return 0 if REG is used in IN (other than being clobbered). + Return 2 if REG does not appear in IN. */ + + static int + reg_clobbered_p (reg, in) + rtx reg; + rtx in; + { + register char *fmt; + register int i, result = 0; + + register enum rtx_code code; + + if (in == 0) + return 2; + + code = GET_CODE (in); + + switch (code) + { + /* Let these fail out quickly. */ + case CONST_INT: + case SYMBOL_REF: + case CONST: + return 2; + + case SUBREG: + if (SUBREG_WORD (in) != 0) + in = gen_rtx (REG, SImode, REGNO (SUBREG_REG (in)) + SUBREG_WORD (in)); + else + in = SUBREG_REG (in); + + case REG: + if (in == reg + || refers_to_regno_p (REGNO (reg), + REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), + in, 0)) + return 0; + return 2; + + case SET: + if (SET_SRC (in) == reg + || refers_to_regno_p (REGNO (reg), + REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), + SET_SRC (in), 0)) + return 0; + + if (SET_DEST (in) == reg) + return 1; + + if (refers_to_regno_p (REGNO (reg), + REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), + SET_DEST (in), 0)) + if (GET_CODE (SET_DEST (in)) == REG + || GET_CODE (SET_DEST (in)) == SUBREG) + return 1; + else + return 0; + return 2; + + case USE: + if (XEXP (in, 0) == reg + || refers_to_regno_p (REGNO (reg), + REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), + XEXP (in, 0), 0)) + return 0; + return 2; + + case CLOBBER: + if (XEXP (in, 0) == reg) + return 1; + /* If the CLOBBER expression is a SUBREG, accept that as a + clobber. But if it is some expression based on this register, + that is like a USE as far as this register is concerned, + so we won't take it. */ + if (refers_to_regno_p (REGNO (reg), + REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), + XEXP (in, 0), 0)) + if (GET_CODE (XEXP (in, 0)) == REG + || GET_CODE (XEXP (in, 0)) == SUBREG) + return 1; + else + return 0; + return 2; + } + + fmt = GET_RTX_FORMAT (code); + + result = 2; + + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'E') + { + register int j; + for (j = XVECLEN (in, i) - 1; j >= 0; j--) + switch (reg_clobbered_p (reg, XVECEXP (in, i, j))) + { + case 0: + return 0; + case 2: + continue; + case 1: + result = 1; + break; + } + } + else if (fmt[i] == 'e') + switch (reg_clobbered_p (reg, XEXP (in, i))) + { + case 0: + return 0; + case 2: + continue; + case 1: + result = 1; + break; + } + } + return result; + } + + /* Return non-zero if OP can be written to without screwing up + GCC's model of what's going on. It is assumed that this operand + appears in the dest position of a SET insn in a conditional + branch's delay slot. AFTER is the label to start looking from. */ + int + operand_clobbered_before_used_after (op, after) + rtx op; + rtx after; + { + extern char call_used_regs[]; + + /* Just experimenting. */ + if (GET_CODE (op) == CC0) + return 1; + if (GET_CODE (op) == REG) + { + rtx insn; + + if (op == stack_pointer_rtx) + return 0; + + for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn)) + { + if (GET_CODE (insn) == NOTE) + continue; + if (GET_CODE (insn) == INSN + || GET_CODE (insn) == JUMP_INSN + || GET_CODE (insn) == CALL_INSN) + { + switch (reg_clobbered_p (op, PATTERN (insn))) + { + case 0: + return 0; + case 2: + break; + case 1: + return 1; + } + if (dead_or_set_p (insn, op)) + return 1; + } + else if (GET_CODE (insn) == CODE_LABEL) + return 0; + if (GET_CODE (insn) == JUMP_INSN) + { + if (condjump_p (insn)) + return 0; + /* This is a jump insn which has already + been mangled. We can't tell what it does. */ + if (GET_CODE (PATTERN (insn)) == PARALLEL) + return 0; + if (! JUMP_LABEL (insn)) + return 0; + /* Keep following jumps. */ + insn = JUMP_LABEL (insn); + } + } + return 1; + } + + /* In both of these cases, the first insn executed + for this op will be a sethi %hi(whatever),%g1, + which is tolerable. */ + if (GET_CODE (op) == MEM) + return (CONSTANT_ADDRESS_P (XEXP (op, 0))); + + return 0; + } + /* Return non-zero if this pattern, as a source to a "SET", is known to yield an instruction of unit size. */ *************** *** 49,55 **** --- 294,322 ---- { case CONST_INT: + #if 1 + /* This is not always a single insn src, technically, + but output_delayed_branch knows how to deal with it. */ + return 1; + #else if (SMALL_INT (op)) return 1; + /* We can put this set insn into delay slot, because this is one + insn; 'sethi'. */ + if ((INTVAL (op) & 0x3ff) == 0) + return 1; + + /* This is not a single insn src, technically, + but output_delayed_branch knows how to deal with it. */ + return 1; + #endif + + #if 1 + case SYMBOL_REF: + /* This is not a single insn src, technically, + but output_delayed_branch knows how to deal with it. */ + return 1; + #else return 0; + #endif case REG: *************** *** 59,63 **** #if 0 /* This is not a single insn src, technically, ! but output_delay_insn knows how to deal with it. */ if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF) return 0; --- 326,330 ---- #if 0 /* This is not a single insn src, technically, ! but output_delayed_branch knows how to deal with it. */ if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF) return 0; *************** *** 66,75 **** /* We never need to negate or complement constants. */ - case NOT: case NEG: return 1; - case PLUS: case MINUS: case AND: case IOR: --- 333,346 ---- /* We never need to negate or complement constants. */ case NEG: + return (mode != DFmode); + case NOT: return 1; case MINUS: + /* If the target is cc0, then these insns will take + two insns (one being a nop). */ + return (mode != SFmode && mode != DFmode); + case PLUS: case AND: case IOR: *************** *** 91,95 **** case SIGN_EXTEND: case ZERO_EXTEND: ! /* Lazy... could check for these. */ return 0; --- 362,453 ---- case SIGN_EXTEND: case ZERO_EXTEND: ! /* Lazy... could check for more cases. */ ! if (GET_CODE (XEXP (op, 0)) == MEM ! && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0))) ! return 1; ! return 0; ! ! /* Not doing floating point, since they probably ! take longer than the branch slot they might fill. */ ! case FLOAT_EXTEND: ! case FLOAT_TRUNCATE: ! case FLOAT: ! case FIX: ! case UNSIGNED_FLOAT: ! case UNSIGNED_FIX: ! return 0; ! ! default: ! return 0; ! } ! } ! ! /* Nonzero only if this *really* is a single insn operand. */ ! int ! strict_single_insn_op_p (op, mode) ! rtx op; ! enum machine_mode mode; ! { ! if (mode == VOIDmode) ! mode = GET_MODE (op); ! ! switch (GET_CODE (op)) ! { ! case CC0: ! return 1; ! ! case CONST_INT: ! if (SMALL_INT (op)) ! return 1; ! /* We can put this set insn into delay slot, because this is one ! insn; 'sethi'. */ ! if ((INTVAL (op) & 0x3ff) == 0) ! return 1; ! return 0; ! ! case SYMBOL_REF: ! return 0; ! ! case REG: ! return (mode != DFmode && mode != DImode); ! ! case MEM: ! if (! CONSTANT_ADDRESS_P (XEXP (op, 0))) ! return (mode != DFmode && mode != DImode); ! return 0; ! ! /* We never need to negate or complement constants. */ ! case NEG: ! return (mode != DFmode); ! case NOT: ! return 1; ! ! case MINUS: ! /* If the target is cc0, then these insns will take ! two insns (one being a nop). */ ! return (mode != SFmode && mode != DFmode); ! case PLUS: ! case AND: ! case IOR: ! case XOR: ! case LSHIFT: ! case ASHIFT: ! case ASHIFTRT: ! case LSHIFTRT: ! if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0))) ! || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1)))) ! return 0; ! return 1; ! ! case SUBREG: ! if (SUBREG_WORD (op) != 0) ! return 0; ! return strict_single_insn_op_p (SUBREG_REG (op), mode); ! ! case SIGN_EXTEND: ! case ZERO_EXTEND: ! if (GET_CODE (XEXP (op, 0)) == MEM ! && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0))) ! return 1; return 0; *************** *** 109,112 **** --- 467,502 ---- } \f + /* Return truth value of whether OP is a relational operator. */ + int + relop (op, mode) + rtx op; + enum machine_mode mode; + { + switch (GET_CODE (op)) + { + case EQ: + case NE: + case GT: + case GE: + case LT: + case LE: + case GTU: + case GEU: + case LTU: + case LEU: + return 1; + } + return 0; + } + + /* Return truth value of wheterh OP is EQ or NE. */ + int + eq_or_neq (op, mode) + rtx op; + enum machine_mode mode; + { + return (GET_CODE (op) == EQ || GET_CODE (op) == NE); + } + \f /* Return truth value of whether OP can be used as an operands in a three address arithmetic insn (such as add %o1,7,%l2) of mode MODE. */ *************** *** 270,275 **** else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); } } --- 660,667 ---- else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_HIGH (operands[1])); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_LOW (operands[1])); } } *************** *** 313,323 **** if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) && cc_prev_status.mdep == op2)) ! output_asm_insn ("sethi %%hi(%m1),%%g1", operands); cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = op2; if (op1 == operands[0]) ! return "ldd [%%lo(%m1)+%%g1],%0"; else ! return "std [%%lo(%m1)+%%g1],%0"; } --- 705,715 ---- if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) && cc_prev_status.mdep == op2)) ! output_asm_insn ("sethi %%hi(%1),%%g1", operands); cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = op2; if (op1 == operands[0]) ! return "ldd [%%lo(%1)+%%g1],%0"; else ! return "std [%%lo(%1)+%%g1],%0"; } *************** *** 548,552 **** --- 940,1079 ---- fprintf (asm_out_file, "\t%s%s", opname, modename); } + \f + /* Output a store-in-memory whose operands are OPERANDS[0,1]. + OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero. */ + + char * + output_store (operands) + rtx *operands; + { + enum machine_mode mode = GET_MODE (operands[0]); + rtx address = XEXP (operands[0], 0); + + cc_status.flags |= CC_KNOW_HI_G1; + cc_status.mdep = address; + + if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) + && address == cc_prev_status.mdep)) + { + output_asm_insn ("sethi %%hi(%m0),%%g1", operands); + cc_prev_status.mdep = address; + } + + /* Store zero in two parts when appropriate. */ + if (mode == DFmode && operands[1] == dconst0_rtx) + { + /* We can't cross a page boundary here because the + SYMBOL_REF must be double word aligned, and for this + to be the case, SYMBOL_REF+4 cannot cross. */ + output_sized_memop ("st", SImode); + output_asm_insn ("%r1,[%%g1+%%lo(%m0)]", operands); + output_sized_memop ("st", SImode); + return "%r1,[%%g1+%%lo(%m0)+4]"; + } + + /* Code below isn't smart enough to move a doubleword in two parts, + so use output_move_double to do that in the cases that require it. */ + if ((mode == DImode || mode == DFmode) + && (GET_CODE (operands[1]) == REG + && (REGNO (operands[1]) & 1))) + return output_move_double (operands); + + output_sized_memop ("st", mode); + return "%r1,[%%g1+%%lo(%m0)]"; + } + + /* Output a fixed-point load-from-memory whose operands are OPERANDS[0,1]. + OPERANDS[0] is a reg, and OPERANDS[1] is a mem. */ + + char * + output_load_fixed (operands) + rtx *operands; + { + enum machine_mode mode = GET_MODE (operands[0]); + rtx address = XEXP (operands[1], 0); + + /* We don't bother trying to see if we know %hi(address). + This is because we are doing a load, and if we know the + %hi value, we probably also know that value in memory. */ + cc_status.flags |= CC_KNOW_HI_G1; + cc_status.mdep = address; + + if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) + && address == cc_prev_status.mdep + && cc_prev_status.mdep == cc_status.mdep)) + { + output_asm_insn ("sethi %%hi(%m1),%%g1", operands); + cc_prev_status.mdep = address; + } + + /* Code below isn't smart enough to do a doubleword in two parts. + So handle that case the slow way. */ + if (mode == DImode + && GET_CODE (operands[0]) == REG /* Moving to nonaligned reg pair */ + && (REGNO (operands[0]) & 1)) + return output_move_double (operands); + + output_sized_memop ("ld", mode); + if (GET_CODE (operands[0]) == REG) + return "[%%g1+%%lo(%m1)],%0"; + abort (); + } + + /* Output a floating-point load-from-memory whose operands are OPERANDS[0,1]. + OPERANDS[0] is a reg, and OPERANDS[1] is a mem. + We also handle the case where OPERANDS[0] is a mem. */ + + char * + output_load_floating (operands) + rtx *operands; + { + enum machine_mode mode = GET_MODE (operands[0]); + rtx address = XEXP (operands[1], 0); + + /* We don't bother trying to see if we know %hi(address). + This is because we are doing a load, and if we know the + %hi value, we probably also know that value in memory. */ + cc_status.flags |= CC_KNOW_HI_G1; + cc_status.mdep = address; + + if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) + && address == cc_prev_status.mdep + && cc_prev_status.mdep == cc_status.mdep)) + { + output_asm_insn ("sethi %%hi(%m1),%%g1", operands); + cc_prev_status.mdep = address; + } + + if (mode == DFmode) + { + if (REG_P (operands[0])) + { + if (REGNO (operands[0]) & 1) + return output_move_double (operands); + else + return "ldd [%%g1+%%lo(%m1)],%0"; + } + cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0); + output_asm_insn ("ldd [%%g1+%%lo(%m1)],%%f0", operands); + operands[1] = gen_rtx (REG, DFmode, 32); + return output_fp_move_double (operands); + } + if (GET_CODE (operands[0]) == MEM) + { + cc_status.flags &= ~CC_F1_IS_0; + output_asm_insn ("ld [%%g1+%%lo(%1)],%%f1", operands); + if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) + { + cc_status.mdep = XEXP (operands[0], 0); + return "sethi %%hi(%m0),%%g1\n\tst %%f1,[%%g1+%%lo(%m0)]"; + } + else + return "st %%f1,%0"; + } + return "ld [%%g1+%%lo(%m1)],%0"; + } + \f /* Load the address specified by OPERANDS[3] into the register specified by OPERANDS[0]. *************** *** 1073,1080 **** ld/st [%g1+%lo(x)],... */ char * ! output_delay_insn (template, operands, insn) char *template; rtx *operands; --- 1600,1614 ---- ld/st [%g1+%lo(x)],... + As another special case, we handle loading (SYMBOL_REF ...) and + other large constants around branches as well: + + sethi %hi(x),%0 + b ... + or %0,%lo(x),%1 + */ char * ! output_delayed_branch (template, operands, insn) char *template; rtx *operands; *************** *** 1081,1091 **** rtx insn; { rtx src = XVECEXP (PATTERN (insn), 0, 1); rtx dest = XVECEXP (PATTERN (insn), 0, 0); ! if (GET_CODE (src) == MEM ! && CONSTANT_ADDRESS_P (XEXP (src, 0)) ! || GET_CODE (dest) == MEM ! && CONSTANT_ADDRESS_P (XEXP (dest, 0))) { rtx xoperands[2]; --- 1615,1643 ---- rtx insn; { + extern rtx recog_operand[]; rtx src = XVECEXP (PATTERN (insn), 0, 1); rtx dest = XVECEXP (PATTERN (insn), 0, 0); ! if (GET_CODE (src) == SYMBOL_REF ! || (GET_CODE (src) == CONST_INT ! && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0))) ! { ! rtx xoperands[2]; ! xoperands[0] = dest; ! xoperands[1] = src; ! ! /* Output the `sethi' insn. */ ! output_asm_insn ("sethi %%hi(%1),%0", xoperands); ! ! /* Output the branch instruction next. */ ! output_asm_insn (template, operands); ! ! /* Now output the `or' insn. */ ! output_asm_insn ("or %0,%%lo(%1),%0", xoperands); ! } ! else if ((GET_CODE (src) == MEM ! && CONSTANT_ADDRESS_P (XEXP (src, 0))) ! || (GET_CODE (dest) == MEM ! && CONSTANT_ADDRESS_P (XEXP (dest, 0)))) { rtx xoperands[2]; *************** *** 1097,1101 **** if (GET_CODE (src) == MEM) { ! output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands); split_template = "ld [%%g1+%%lo(%m1)],%0"; } --- 1649,1655 ---- if (GET_CODE (src) == MEM) { ! if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) ! && cc_prev_status.mdep == XEXP (operands[1], 0))) ! output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands); split_template = "ld [%%g1+%%lo(%m1)],%0"; } *************** *** 1102,1106 **** else { ! output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands); split_template = "st %r1,[%%g1+%%lo(%m0)]"; } --- 1656,1662 ---- else { ! if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) ! && cc_prev_status.mdep == XEXP (operands[0], 0))) ! output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands); split_template = "st %r1,[%%g1+%%lo(%m0)]"; } *************** *** 1126,1130 **** /* Now recognize the insn which we put in its delay slot. We must do this after outputing the branch insn, ! since operands may just be a pointer to `recog_operands'. */ insn_code_number = recog (pat, delay_insn); if (insn_code_number == -1) --- 1682,1686 ---- /* Now recognize the insn which we put in its delay slot. We must do this after outputing the branch insn, ! since operands may just be a pointer to `recog_operand'. */ insn_code_number = recog (pat, delay_insn); if (insn_code_number == -1) *************** *** 1137,1143 **** template = insn_template[insn_code_number]; if (template == 0) ! template = (*insn_outfun[insn_code_number]) (operands, delay_insn); ! output_asm_insn (template, operands); } return ""; } --- 1693,1900 ---- template = insn_template[insn_code_number]; if (template == 0) ! template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn); ! output_asm_insn (template, recog_operand); ! } ! CC_STATUS_INIT; ! return ""; ! } ! ! /* Output a newly constructed insn DELAY_INSN. */ ! char * ! output_delay_insn (delay_insn) ! rtx delay_insn; ! { ! char *template; ! extern rtx recog_operand[]; ! extern char call_used_regs[]; ! extern char *insn_template[]; ! extern int insn_n_operands[]; ! extern char *(*insn_outfun[])(); ! extern rtx alter_subreg(); ! int insn_code_number; ! extern int insn_n_operands[]; ! int i; ! ! /* Now recognize the insn which we put in its delay slot. ! We must do this after outputing the branch insn, ! since operands may just be a pointer to `recog_operand'. */ ! insn_code_number = recog_memoized (delay_insn); ! if (insn_code_number == -1) ! abort (); ! ! /* Extract the operands of this delay insn. */ ! INSN_CODE (delay_insn) = insn_code_number; ! insn_extract (delay_insn); ! ! /* It is possible that this insn has not been properly scaned by final ! yet. If this insn's operands don't appear in the peephole's ! actual operands, then they won't be fixed up by final, so we ! make sure they get fixed up here. -- This is a kludge. */ ! for (i = 0; i < insn_n_operands[insn_code_number]; i++) ! { ! if (GET_CODE (recog_operand[i]) == SUBREG) ! recog_operand[i] = alter_subreg (recog_operand[i]); } + + #ifdef REGISTER_CONSTRAINTS + if (! constrain_operands (insn_code_number)) + abort (); + #endif + + cc_prev_status = cc_status; + + /* Update `cc_status' for this instruction. + The instruction's output routine may change it further. + If the output routine for a jump insn needs to depend + on the cc status, it should look at cc_prev_status. */ + + NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn); + + /* Now get the template for what this insn would + have been, without the branch. */ + + template = insn_template[insn_code_number]; + if (template == 0) + template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn); + output_asm_insn (template, recog_operand); return ""; } + + /* Output the insn HEAD, keeping OPERANDS protected (wherever they are). + HEAD comes from the target of some branch, so before we output it, + we delete it from the target, lest we execute it twice. The caller + of this function promises that such code motion is permissable. */ + char * + output_eager_then_insn (head, operands) + rtx head; + rtx *operands; + { + extern rtx alter_subreg (); + extern int insn_n_operands[]; + extern rtx recog_operand[]; + rtx xoperands[MAX_RECOG_OPERANDS]; + int insn_code_number, i, nbytes; + rtx nhead; + + /* Micro-hack: run peephole on head if it looks like a good idea. + Right now there's only one such case worth doing... + + This could be made smarter if the peephole for ``2-insn combine'' + were also made smarter. */ + if (GET_CODE (PATTERN (head)) == SET + && REG_P (SET_SRC (PATTERN (head))) + && REG_P (SET_DEST (PATTERN (head))) + && (nhead = next_real_insn_no_labels (head)) + && GET_CODE (nhead) == INSN + && GET_CODE (PATTERN (nhead)) == SET + && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0 + && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head)) + || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head)))) + /* Something's wrong if this does not fly. */ + if (! peephole (head)) + abort (); + + /* Save our contents of `operands', since output_delay_insn sets them. */ + insn_code_number = recog_memoized (head); + nbytes = insn_n_operands[insn_code_number] * sizeof (rtx); + bcopy (operands, xoperands, nbytes); + + /* Output the delay insn, and prevent duplication later. */ + delete_insn (head); + output_delay_insn (head); + + /* Restore this insn's operands. */ + bcopy (xoperands, operands, nbytes); + } + + /* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL; + or 0, if there is none. Also return 0 if we cross a label. */ + + rtx + next_real_insn_no_labels (label) + rtx label; + { + register rtx insn = NEXT_INSN (label); + register RTX_CODE code; + + while (insn) + { + code = GET_CODE (insn); + if (code == INSN) + { + if (GET_CODE (PATTERN (insn)) != CLOBBER + && GET_CODE (PATTERN (insn)) != USE) + return insn; + } + if (code == CALL_INSN || code == JUMP_INSN) + return insn; + if (code == CODE_LABEL) + return 0; + insn = NEXT_INSN (insn); + } + + return 0; + } + + int + operands_satisfy_eager_branch_peephole (operands, conditional) + rtx *operands; + int conditional; + { + rtx label; + + if (conditional) + { + if (GET_CODE (operands[0]) != IF_THEN_ELSE) + return 0; + + if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF) + label = XEXP (XEXP (operands[0], 1), 0); + else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF) + label = XEXP (XEXP (operands[0], 2), 0); + else return 0; + } + else + { + label = operands[0]; + } + + if (LABEL_NUSES (label) == 1) + { + rtx prev = PREV_INSN (label); + while (prev && GET_CODE (prev) == NOTE) + prev = PREV_INSN (prev); + if (prev == 0 + || GET_CODE (prev) == BARRIER) + { + rtx head = next_real_insn_no_labels (label); + + if (head + && ! INSN_DELETED_P (head) + && GET_CODE (head) == INSN + && GET_CODE (PATTERN (head)) == SET + && strict_single_insn_op_p (SET_SRC (PATTERN (head)), + GET_MODE (SET_DEST (PATTERN (head)))) + && strict_single_insn_op_p (SET_DEST (PATTERN (head)), + GET_MODE (SET_DEST (PATTERN (head))))) + { + if (conditional == 2) + return (GET_CODE (operands[1]) != PC + && safe_insn_src_p (operands[2], VOIDmode) + && strict_single_insn_op_p (operands[2], VOIDmode) + && operand_clobbered_before_used_after (operands[1], label)); + return 1; + } + } + } + + if (conditional == 1 + && GET_CODE (operands[1]) != PC + && safe_insn_src_p (operands[2], VOIDmode) + && strict_single_insn_op_p (operands[2], VOIDmode) + && operand_clobbered_before_used_after (operands[1], label)) + return 1; + + return 0; + } + diff -rc2N gcc-1.32/output-spur.c gcc-1.33/output-spur.c *** gcc-1.32/output-spur.c Mon Sep 26 18:36:46 1988 --- gcc-1.33/output-spur.c Sun Jan 1 16:09:03 1989 *************** *** 145,150 **** else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); } } --- 145,152 ---- else if (GET_CODE (operands[1]) == CONST_DOUBLE) { ! latehalf[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_HIGH (operands[1])); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! CONST_DOUBLE_LOW (operands[1])); } } diff -rc2N gcc-1.32/print-tree.c gcc-1.33/print-tree.c *** gcc-1.32/print-tree.c Wed Nov 30 06:21:53 1988 --- gcc-1.33/print-tree.c Sat Dec 31 19:30:34 1988 *************** *** 565,569 **** --- 565,580 ---- case REAL_CST: + #ifndef REAL_IS_NOT_DOUBLE fprintf (outfile, " = %e;", TREE_REAL_CST (node)); + #else + { + int i; + fprintf (outfile, " = 0x"); + char *p = (char *) &TREE_REAL_CST (node); + for (i = 0; i < sizeof TREE_REAL_CST (node); i++) + fprintf (outfile, "%02x", *p++); + fprintf (outfile, ";"); + } + #endif /* REAL_IS_NOT_DOUBLE */ break; diff -rc2N gcc-1.32/real.h gcc-1.33/real.h *** gcc-1.32/real.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/real.h Sun Jan 1 17:21:49 1989 *************** *** 0 **** --- 1,84 ---- + /* Front-end tree definitions for GNU compiler. + Copyright (C) 1989 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + /* If we are not cross-compiling, use a `double' to represent the + floating-point value. Otherwise, use some other type + (probably a struct containing an array of longs). */ + #ifndef REAL_VALUE_TYPE + #define REAL_VALUE_TYPE double + #else + #define REAL_IS_NOT_DOUBLE + #endif + + /* Compare two floating-point values for equality. */ + #ifndef REAL_VALUES_EQUAL + #define REAL_VALUES_EQUAL(x,y) ((x) == (y)) + #endif + + /* Compare two floating-point values for less than. */ + #ifndef REAL_VALUES_LESS + #define REAL_VALUES_LESS(x,y) ((x) < (y)) + #endif + + /* Scale X by Y powers of 2. */ + #ifndef REAL_VALUE_LDEXP + #define REAL_VALUE_LDEXP(x,y) ldexp (x, y) + extern double ldexp (); + #endif + + /* Convert the string X to a floating-point value. */ + #ifndef REAL_VALUE_ATOF + #define REAL_VALUE_ATOF(x) atof (x) + extern double atof (); + #endif + + /* Negate the floating-point value X. */ + #ifndef REAL_VALUE_NEGATE + #define REAL_VALUE_NEGATE(x) (- (x)) + #endif + + /* Truncate the floating-point value X to single-precision. */ + #ifndef REAL_VALUE_TRUNCATE + #define REAL_VALUE_TRUNCATE(x) ((float) (x)) + #endif + + /* Union type used for extracting real values from CONST_DOUBLEs + or putting them in. */ + + union real_extract + { + REAL_VALUE_TYPE d; + int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)]; + }; + + /* For a CONST_DOUBLE: + The usual two ints that hold the value. + For a DImode, that is all there are. + For a float, the number of ints varies, + so use &CONST_DOUBLE_LOW(r) as the address of an array of them. */ + #define CONST_DOUBLE_LOW(r) XINT (r, 2) + #define CONST_DOUBLE_HIGH(r) XINT (r, 3) + + /* Link for chain of all CONST_DOUBLEs in use in current function. */ + #define CONST_DOUBLE_CHAIN(r) XEXP (r, 1) + /* The MEM which represents this CONST_DOUBLE's value in memory, + or const0_rtx if no MEM has been made for it yet, + or cc0_rtx if it is not on the chain. */ + #define CONST_DOUBLE_MEM(r) XEXP (r, 0) diff -rc2N gcc-1.32/recog.c gcc-1.33/recog.c *** gcc-1.32/recog.c Tue Dec 20 15:32:26 1988 --- gcc-1.33/recog.c Mon Jan 23 02:43:41 1989 *************** *** 27,31 **** --- 27,33 ---- #include "regs.h" #include "hard-reg-set.h" + #include "real.h" + static int inequality_comparisons_p (); *************** *** 453,458 **** /* Count backwards through CLOBBERs to determine number of SETs. */ for (i = XVECLEN (body, 0); i > 0; i--) ! if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET) ! break; /* N_SETS is now number of output operands. */ --- 455,464 ---- /* Count backwards through CLOBBERs to determine number of SETs. */ for (i = XVECLEN (body, 0); i > 0; i--) ! { ! if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET) ! break; ! if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER) ! return -1; ! } /* N_SETS is now number of output operands. */ *************** *** 487,491 **** /* Make sure all the other parallel things really are clobbers. */ for (i = XVECLEN (body, 0) - 1; i > 0; i--) ! if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER) return -1; --- 493,497 ---- /* Make sure all the other parallel things really are clobbers. */ for (i = XVECLEN (body, 0) - 1; i > 0; i--) ! if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) return -1; *************** *** 871,876 **** struct funny_match funny_match[MAX_RECOG_OPERANDS]; int funny_match_index; ! if (noperands == 0) return 1; --- 877,883 ---- struct funny_match funny_match[MAX_RECOG_OPERANDS]; int funny_match_index; + int nalternatives = insn_n_alternatives[insn_code_num]; ! if (noperands == 0 || nalternatives == 0) return 1; *************** *** 880,884 **** which_alternative = 0; ! while (which_alternative < insn_n_alternatives[insn_code_num]) { register int opno; --- 887,891 ---- which_alternative = 0; ! while (which_alternative < nalternatives) { register int opno; diff -rc2N gcc-1.32/regclass.c gcc-1.33/regclass.c *** gcc-1.32/regclass.c Tue Dec 20 01:50:20 1988 --- gcc-1.33/regclass.c Thu Jan 19 00:04:04 1989 *************** *** 67,70 **** --- 67,77 ---- static char initial_call_used_regs[] = CALL_USED_REGISTERS; + + /* Indexed by hard register number, contains 1 for registers + that are being used for global register decls. + These must be exempt from ordinary flow analysis + and are also considered fixed. */ + + char global_regs[FIRST_PSEUDO_REGISTER]; /* Table of register numbers in the order in which to try to use them. */ *************** *** 109,112 **** --- 116,120 ---- bcopy (initial_fixed_regs, fixed_regs, sizeof fixed_regs); bcopy (initial_call_used_regs, call_used_regs, sizeof call_used_regs); + bzero (global_regs, sizeof global_regs); /* Compute number of hard regs in each class. */ *************** *** 199,202 **** --- 207,220 ---- CONDITIONAL_REGISTER_USAGE; #endif + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (global_regs[i]) + { + if (call_used_regs[i] && ! fixed_regs[i]) + warning ("call-clobbered register used for global register variable"); + fixed_regs[i] = 1; + /* Prevent saving/restoring of this reg. */ + call_used_regs[i] = 1; + } /* Initialize "constant" tables. */ diff -rc2N gcc-1.32/reload.c gcc-1.33/reload.c *** gcc-1.32/reload.c Tue Dec 20 01:50:25 1988 --- gcc-1.33/reload.c Mon Jan 23 02:44:08 1989 *************** *** 77,80 **** --- 77,81 ---- #include "hard-reg-set.h" #include "flags.h" + #include "real.h" \f /* The variables set up by `find_reloads' are: *************** *** 180,185 **** static rtx find_dummy_reload (); static rtx find_reloads_toplev (); ! static void find_reloads_address (); ! static void find_reloads_address_1 (); static int hard_reg_set_here_p (); static rtx forget_volatility (); --- 181,186 ---- static rtx find_dummy_reload (); static rtx find_reloads_toplev (); ! static int find_reloads_address (); ! static int find_reloads_address_1 (); static int hard_reg_set_here_p (); static rtx forget_volatility (); *************** *** 390,394 **** #if 0 ! /* This was replaced by changes in find_reloads_addr_1 and the new function inc_for_reload, which go with a new meaning of reload_inc. */ --- 391,395 ---- #if 0 ! /* This was replaced by changes in find_reloads_address_1 and the new function inc_for_reload, which go with a new meaning of reload_inc. */ *************** *** 870,873 **** --- 871,876 ---- and they are chewed up as we consider alternatives. */ char *constraints[MAX_RECOG_OPERANDS]; + /* Nonzero for a MEM operand whose entire address needs a reload. */ + int address_reloaded[MAX_RECOG_OPERANDS]; int n_alternatives; int this_alternative[MAX_RECOG_OPERANDS]; *************** *** 971,992 **** noperands = insn_n_operands[insn_code_number]; n_alternatives = insn_n_alternatives[insn_code_number]; insn_extract (insn); ! { ! /* Nonzero if some operand has a nonnull constraint. ! If none has, we have no work to do. ! Even a general_operand should have `g' in its constraint. */ ! int have_constraints = 0; ! ! for (i = 0; i < noperands; i++) ! { ! constraints[i] = constraints1[i] ! = insn_operand_constraint[insn_code_number][i]; ! operand_mode[i] = insn_operand_mode[insn_code_number][i]; ! if (constraints[i] != 0) ! have_constraints = 1; ! } ! if (!have_constraints) ! return; ! } } --- 974,987 ---- noperands = insn_n_operands[insn_code_number]; n_alternatives = insn_n_alternatives[insn_code_number]; + /* Just return "no reloads" if insn has no operands with constraints. */ + if (n_alternatives == 0) + return; insn_extract (insn); ! for (i = 0; i < noperands; i++) ! { ! constraints[i] = constraints1[i] ! = insn_operand_constraint[insn_code_number][i]; ! operand_mode[i] = insn_operand_mode[insn_code_number][i]; ! } } *************** *** 1053,1056 **** --- 1048,1052 ---- register RTX_CODE code = GET_CODE (recog_operand[i]); modified[i] = RELOAD_READ; + address_reloaded[i] = 0; if (constraints[i][0] == 'p') { *************** *** 1061,1068 **** else if (code == MEM) { ! find_reloads_address (GET_MODE (recog_operand[i]), ! recog_operand_loc[i], ! XEXP (recog_operand[i], 0), ! &XEXP (recog_operand[i], 0)); substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]; } --- 1057,1065 ---- else if (code == MEM) { ! if (find_reloads_address (GET_MODE (recog_operand[i]), ! recog_operand_loc[i], ! XEXP (recog_operand[i], 0), ! &XEXP (recog_operand[i], 0))) ! address_reloaded[i] = 1; substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]; } *************** *** 1289,1292 **** --- 1286,1290 ---- case '<': if (GET_CODE (operand) == MEM + && ! address_reloaded[i] && (GET_CODE (XEXP (operand, 0)) == PRE_DEC || GET_CODE (XEXP (operand, 0)) == POST_DEC)) *************** *** 1296,1299 **** --- 1294,1298 ---- case '>': if (GET_CODE (operand) == MEM + && ! address_reloaded[i] && (GET_CODE (XEXP (operand, 0)) == PRE_INC || GET_CODE (XEXP (operand, 0)) == POST_INC)) *************** *** 1679,1683 **** operand_reloadnum[i] = output_reloadnum; } ! else abort (); } else if (goal_alternative_matched[i] < 0 --- 1678,1691 ---- operand_reloadnum[i] = output_reloadnum; } ! else if (insn_code_number >= 0) ! abort (); ! else ! { ! error_for_asm (insn, "inconsistent operand constraints in an `asm'"); ! /* Avoid further trouble with this insn. */ ! PATTERN (insn) = gen_rtx (USE, VOIDmode, const0_rtx); ! n_reloads = 0; ! return; ! } } else if (goal_alternative_matched[i] < 0 *************** *** 1987,1993 **** (MEMREFLOC may be zero, meaning don't ever bother to copy the memref.) Note that we take shortcuts assuming that no multi-reg machine mode ! occurs as part of an address. */ ! static void find_reloads_address (mode, memrefloc, ad, loc) enum machine_mode mode; --- 1995,2004 ---- (MEMREFLOC may be zero, meaning don't ever bother to copy the memref.) Note that we take shortcuts assuming that no multi-reg machine mode ! occurs as part of an address. ! Value is nonzero if this address is reloaded or replaced as a whole. ! This is interesting to the caller if the address is an autoincrement. */ ! ! static int find_reloads_address (mode, memrefloc, ad, loc) enum machine_mode mode; *************** *** 2008,2012 **** { *loc = ad = reg_equiv_constant[regno]; ! return; } } --- 2019,2023 ---- { *loc = ad = reg_equiv_constant[regno]; ! return 1; } } *************** *** 2018,2022 **** { *loc = ad = reg_equiv_mem[regno]; ! return; } } --- 2029,2033 ---- { *loc = ad = reg_equiv_mem[regno]; ! return 1; } } *************** *** 2030,2034 **** push_reload (tem, 0, loc, 0, BASE_REG_CLASS, GET_MODE (ad), 0, VOIDmode, 0); ! return; } if (! (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 --- 2041,2045 ---- push_reload (tem, 0, loc, 0, BASE_REG_CLASS, GET_MODE (ad), 0, VOIDmode, 0); ! return 1; } if (! (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 *************** *** 2035,2041 **** ? indirect_ok : REGNO_OK_FOR_BASE_P (regno))) ! push_reload (ad, 0, loc, 0, BASE_REG_CLASS, ! GET_MODE (ad), 0, VOIDmode, 0); ! return; } --- 2046,2055 ---- ? indirect_ok : REGNO_OK_FOR_BASE_P (regno))) ! { ! push_reload (ad, 0, loc, 0, BASE_REG_CLASS, ! GET_MODE (ad), 0, VOIDmode, 0); ! return 1; ! } ! return 0; } *************** *** 2054,2058 **** && GET_CODE (XEXP (ad, 0)) == REG && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0) ! return; subst_reg_equivs_changed = 0; --- 2068,2072 ---- && GET_CODE (XEXP (ad, 0)) == REG && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0) ! return 0; subst_reg_equivs_changed = 0; *************** *** 2060,2068 **** if (! subst_reg_equivs_changed) ! return; /* Check result for validity after substitution. */ if (strict_memory_address_p (mode, ad)) ! return; } --- 2074,2082 ---- if (! subst_reg_equivs_changed) ! return 0; /* Check result for validity after substitution. */ if (strict_memory_address_p (mode, ad)) ! return 0; } *************** *** 2085,2089 **** push_reload (ad, 0, loc, 0, BASE_REG_CLASS, GET_MODE (ad), 0, VOIDmode, 0); ! return; } --- 2099,2103 ---- push_reload (ad, 0, loc, 0, BASE_REG_CLASS, GET_MODE (ad), 0, VOIDmode, 0); ! return 1; } *************** *** 2107,2111 **** { *loc = tem; ! return; } } --- 2121,2125 ---- { *loc = tem; ! return 0; } } *************** *** 2118,2125 **** BASE_REG_CLASS, Pmode, 0, VOIDmode, 0); ! return; } ! find_reloads_address_1 (ad, 0, loc); } \f --- 2132,2139 ---- BASE_REG_CLASS, Pmode, 0, VOIDmode, 0); ! return 1; } ! return find_reloads_address_1 (ad, 0, loc); } \f *************** *** 2247,2252 **** = 0 means we are considering them as base regs. ! We return X, whose operands may have been altered, ! or perhaps a RELOAD rtx if X itself was a REG that must be reloaded. */ /* Note that we take shortcuts assuming that no multi-reg machine mode --- 2261,2265 ---- = 0 means we are considering them as base regs. ! We return nonzero if X, as a whole, is reloaded or replaced. */ /* Note that we take shortcuts assuming that no multi-reg machine mode *************** *** 2256,2260 **** could have addressing modes that this does not handle right. */ ! static void find_reloads_address_1 (x, context, loc) rtx x; --- 2269,2273 ---- could have addressing modes that this does not handle right. */ ! static int find_reloads_address_1 (x, context, loc) rtx x; *************** *** 2329,2333 **** { register int regno = REGNO (XEXP (x, 0)); ! int reloadnum; /* A register that is incremented cannot be constant! */ --- 2342,2346 ---- { register int regno = REGNO (XEXP (x, 0)); ! int value = 0; /* A register that is incremented cannot be constant! */ *************** *** 2369,2373 **** register rtx link; ! reloadnum = push_reload (x, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, --- 2382,2386 ---- register rtx link; ! int reloadnum = push_reload (x, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, *************** *** 2376,2379 **** --- 2389,2394 ---- = find_inc_amount (PATTERN (this_insn), XEXP (x, 0)); + value = 1; + /* Update the REG_INC notes. */ *************** *** 2384,2388 **** push_replacement (&XEXP (link, 0), reloadnum, VOIDmode); } ! return; } } --- 2399,2403 ---- push_replacement (&XEXP (link, 0), reloadnum, VOIDmode); } ! return value; } } *************** *** 2396,2400 **** context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), 0, VOIDmode, 0); ! return; } --- 2411,2415 ---- context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), 0, VOIDmode, 0); ! return 1; } *************** *** 2426,2430 **** context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), 0, VOIDmode, 0); ! return; } } --- 2441,2445 ---- context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), 0, VOIDmode, 0); ! return 1; } } *************** *** 2439,2442 **** --- 2454,2459 ---- } } + + return 0; } \f diff -rc2N gcc-1.32/reload1.c gcc-1.33/reload1.c *** gcc-1.32/reload1.c Tue Dec 20 01:50:38 1988 --- gcc-1.33/reload1.c Wed Feb 1 20:03:17 1989 *************** *** 179,182 **** --- 179,183 ---- static int spill_hard_reg (); static void choose_reload_targets (); + static void delete_output_reload (); static void forget_old_reloads (); static void order_regs_for_reload (); *************** *** 184,187 **** --- 185,189 ---- static void inc_for_reload (); static int constraint_accepts_reg_p (); + static int count_occurrences (); extern void remove_death (); *************** *** 1349,1353 **** if (basic_block_needs && this_block + 1 < n_basic_blocks && insn == basic_block_head[this_block+1]) ! ++this_block; if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN --- 1351,1363 ---- if (basic_block_needs && this_block + 1 < n_basic_blocks && insn == basic_block_head[this_block+1]) ! { ! ++this_block; ! /* When we enter a basic block which had no spilling, ! forget any inherited reloads, since we might use those ! same registers for allocated pseudos. */ ! if (basic_block_needs != 0 ! && basic_block_needs[this_block] == 0) ! bzero (reg_last_reload_reg, max_regno * sizeof (rtx)); ! } if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN *************** *** 2027,2030 **** --- 2037,2043 ---- && constraint_accepts_reg_p (insn_operand_constraint[recog_memoized (insn)][0], reloadreg) + /* This is unsafe if operand occurs more than once in current + insn. Perhaps some occurrences aren't reloaded. */ + && count_occurrences (PATTERN (insn), old) == 1 /* Don't risk splitting a matching pair of operands. */ && ! reg_mentioned_p (old, SET_SRC (PATTERN (temp)))) *************** *** 2103,2178 **** && REGNO (reload_in[j]) >= FIRST_PSEUDO_REGISTER && spill_reg_store[reload_spill_index[j]] != 0 ! && dead_or_set_p (insn, reload_in[j])) ! { ! register rtx i1; ! /* If the pseudo-reg we are reloading is no longer referenced ! anywhere between the store into it and here, ! and no jumps or labels intervene, then the value can get ! here through the reload reg alone. */ ! for (i1 = NEXT_INSN (spill_reg_store[reload_spill_index[j]]); ! i1 != insn; i1 = NEXT_INSN (i1)) ! { ! if (GET_CODE (i1) == CODE_LABEL || GET_CODE (i1) == JUMP_INSN) ! break; ! if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN) ! && reg_mentioned_p (reload_in[j], PATTERN (i1))) ! break; ! } ! if (i1 == insn) ! { ! /* If this insn will store in the pseudo again, ! the previous store can be removed. */ ! if (reload_out[j] == reload_in[j]) ! delete_insn (spill_reg_store[reload_spill_index[j]]); ! ! /* See if the pseudo reg has been completely replaced ! with reload regs. If so, delete the store insn ! and forget we had a stack slot for the pseudo. */ ! else if (reg_n_deaths[REGNO (reload_in[j])] == 1 ! && reg_basic_block[REGNO (reload_in[j])] >= 0 ! && find_regno_note (insn, REG_DEAD, REGNO (reload_in[j]))) ! { ! rtx i2; ! /* We know that it was used only between here ! and the beginning of the current basic block. ! Search that range; see if any ref remains. */ ! for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2)) ! { ! /* if (i2 == spill_reg_store[reload_spill_index[j]]) */ ! /* Uses which just store in the pseudo don't count, ! since if they are the only uses, they are dead. */ ! if (GET_CODE (i2) == INSN ! && GET_CODE (PATTERN (i2)) == SET ! && SET_DEST (PATTERN (i2)) == reload_in[j]) ! continue; ! if (GET_CODE (i2) == CODE_LABEL ! || GET_CODE (i2) == JUMP_INSN) ! break; ! if ((GET_CODE (i2) == INSN || GET_CODE (i2) == CALL_INSN) ! && reg_mentioned_p (reload_in[j], PATTERN (i2))) ! goto still_used; ! } ! /* Delete the now-dead stores into this pseudo. */ ! /* delete_insn (spill_reg_store[reload_spill_index[j]]); */ ! for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2)) ! { ! /* Uses which just store in the pseudo don't count, ! since if they are the only uses, they are dead. */ ! if (GET_CODE (i2) == INSN ! && GET_CODE (PATTERN (i2)) == SET ! && SET_DEST (PATTERN (i2)) == reload_in[j]) ! delete_insn (i2); ! if (GET_CODE (i2) == CODE_LABEL ! || GET_CODE (i2) == JUMP_INSN) ! break; ! } ! /* For the debugging info, ! say the pseudo lives in this reload reg. */ ! reg_renumber[REGNO (old)] = REGNO (reload_reg_rtx[j]); ! alter_reg (REGNO (old), -1); ! still_used: ; ! } ! } ! } /* Input-reloading is done. Now do output-reloading, --- 2116,2124 ---- && REGNO (reload_in[j]) >= FIRST_PSEUDO_REGISTER && spill_reg_store[reload_spill_index[j]] != 0 ! && dead_or_set_p (insn, reload_in[j]) ! /* This is unsafe if operand occurs more than once in current ! insn. Perhaps some occurrences weren't reloaded. */ ! && count_occurrences (PATTERN (insn), reload_in[j]) == 1) ! delete_output_reload (insn, j, reload_spill_index[j]); /* Input-reloading is done. Now do output-reloading, *************** *** 2238,2241 **** --- 2184,2284 ---- } \f + /* Delete a previously made output-reload + whose result we now believe is not needed. + First we double-check. + + INSN is the insn now being processed. + J is the reload-number for this insn, + and SPILL_INDEX is the index in spill_regs of the reload-reg + being used for the reload. */ + + static void + delete_output_reload (insn, j, spill_index) + rtx insn; + int j; + int spill_index; + { + register rtx i1; + + /* Get the raw pseudo-register referred to. */ + + rtx reg = reload_in[j]; + while (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + + /* If the pseudo-reg we are reloading is no longer referenced + anywhere between the store into it and here, + and no jumps or labels intervene, then the value can get + here through the reload reg alone. + Otherwise, give up--return. */ + for (i1 = NEXT_INSN (spill_reg_store[spill_index]); + i1 != insn; i1 = NEXT_INSN (i1)) + { + if (GET_CODE (i1) == CODE_LABEL || GET_CODE (i1) == JUMP_INSN) + return; + if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN) + && reg_mentioned_p (reg, PATTERN (i1))) + return; + } + + /* If this insn will store in the pseudo again, + the previous store can be removed. */ + if (reload_out[j] == reload_in[j]) + delete_insn (spill_reg_store[spill_index]); + + /* See if the pseudo reg has been completely replaced + with reload regs. If so, delete the store insn + and forget we had a stack slot for the pseudo. */ + else if (reg_n_deaths[REGNO (reg)] == 1 + && reg_basic_block[REGNO (reg)] >= 0 + && find_regno_note (insn, REG_DEAD, REGNO (reg))) + { + rtx i2; + + /* We know that it was used only between here + and the beginning of the current basic block. + (We also know that the last use before INSN was + the output reload we are thinking of deleting, but never mind that.) + Search that range; see if any ref remains. */ + for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2)) + { + /* Uses which just store in the pseudo don't count, + since if they are the only uses, they are dead. */ + if (GET_CODE (i2) == INSN + && GET_CODE (PATTERN (i2)) == SET + && SET_DEST (PATTERN (i2)) == reg) + continue; + if (GET_CODE (i2) == CODE_LABEL + || GET_CODE (i2) == JUMP_INSN) + break; + if ((GET_CODE (i2) == INSN || GET_CODE (i2) == CALL_INSN) + && reg_mentioned_p (reg, PATTERN (i2))) + /* Some other ref remains; + we can't do anything. */ + return; + } + + /* Delete the now-dead stores into this pseudo. */ + for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2)) + { + /* Uses which just store in the pseudo don't count, + since if they are the only uses, they are dead. */ + if (GET_CODE (i2) == INSN + && GET_CODE (PATTERN (i2)) == SET + && SET_DEST (PATTERN (i2)) == reg) + delete_insn (i2); + if (GET_CODE (i2) == CODE_LABEL + || GET_CODE (i2) == JUMP_INSN) + break; + } + + /* For the debugging info, + say the pseudo lives in this reload reg. */ + reg_renumber[REGNO (reg)] = REGNO (reload_reg_rtx[j]); + alter_reg (REGNO (reg), -1); + } + } + + \f /* Output reload-insns around INSN to reload VALUE into RELOADREG. VALUE is a autoincrement or autodecrement RTX whose operand *************** *** 2366,2368 **** --- 2409,2465 ---- value = 1; } + } + \f + /* Return the number of places FIND appears within X. */ + + static int + count_occurrences (x, find) + register rtx x, find; + { + register int i, j; + register enum rtx_code code; + register char *format_ptr; + int count; + + if (x == find) + return 1; + if (x == 0) + return 0; + + code = GET_CODE (x); + + switch (code) + { + case REG: + case QUEUED: + case CONST_INT: + case CONST_DOUBLE: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + return 0; + } + + format_ptr = GET_RTX_FORMAT (code); + count = 0; + + for (i = 0; i < GET_RTX_LENGTH (code); i++) + { + switch (*format_ptr++) + { + case 'e': + count += count_occurrences (XEXP (x, i), find); + break; + + case 'E': + if (XVEC (x, i) != NULL) + { + for (j = 0; j < XVECLEN (x, i); j++) + count += count_occurrences (XVECEXP (x, i, j), find); + } + break; + } + } + return count; } diff -rc2N gcc-1.32/rtl.c gcc-1.33/rtl.c *** gcc-1.32/rtl.c Fri Dec 16 18:23:51 1988 --- gcc-1.33/rtl.c Sun Jan 1 16:16:25 1989 *************** *** 50,54 **** /* Indexed by rtx code, gives number of operands for an rtx with that code. Does NOT include rtx header data (code and links). ! This array is initialized in init_rtx. */ int rtx_length[NUM_RTX_CODE + 1]; --- 50,54 ---- /* Indexed by rtx code, gives number of operands for an rtx with that code. Does NOT include rtx header data (code and links). ! This array is initialized in init_rtl. */ int rtx_length[NUM_RTX_CODE + 1]; *************** *** 1275,1277 **** --- 1275,1298 ---- for (i = 0; i < NUM_RTX_CODE; i++) rtx_length[i] = strlen (rtx_format[i]); + + /* Make CONST_DOUBLE bigger, if real values are bigger than + it normally expects to have room for. + Note that REAL_VALUE_TYPE is not defined by default, + since tree.h is not included. But the default dfn as `double' + would do no harm. */ + #ifdef REAL_VALUE_TYPE + i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2; + if (rtx_length[(int) CONST_DOUBLE] < i) + { + char *s = (char *) permalloc (i + 1); + rtx_length[(int) CONST_DOUBLE] = i; + *s++ = 'e'; + *s++ = '0'; + /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string + of as many `i's as we now have elements. */ + for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++) + *s++ = 'i'; + *s++ = 0; + } + #endif } diff -rc2N gcc-1.32/rtl.def gcc-1.33/rtl.def *** gcc-1.32/rtl.def Mon Dec 5 18:54:39 1988 --- gcc-1.33/rtl.def Sun Jan 1 16:16:10 1989 *************** *** 301,308 **** /* numeric double constant. ! The double is stored in two "integer" operands. ! The third operand is the MEM that stores this constant in memory. ! The fourth is used to chain together these rtx's for uniquization. */ ! DEF_RTL_EXPR(CONST_DOUBLE, "const_double", "iie00") /* This is used to encapsulate an expression whose value is constant --- 301,311 ---- /* numeric double constant. ! Operand 0 is the MEM that stores this constant in memory, ! or various other things (see comments at immed_double_const in varasm.c). ! Operand 1 is a chain of all CONST_DOUBLEs in use in the current function. ! Remaining operands hold the actual value. ! The number of operands may be more than 2 if cross-compiling; ! see init_rtl. */ ! DEF_RTL_EXPR(CONST_DOUBLE, "const_double", "e0ii") /* This is used to encapsulate an expression whose value is constant diff -rc2N gcc-1.32/rtl.h gcc-1.33/rtl.h *** gcc-1.32/rtl.h Wed Nov 30 06:22:08 1988 --- gcc-1.33/rtl.h Sun Jan 1 23:02:24 1989 *************** *** 433,436 **** --- 433,437 ---- extern rtx output_constant_def (); extern rtx immed_real_const (); + extern rtx immed_real_const_1 (); extern rtx immed_double_const (); extern rtx force_const_double_mem (); diff -rc2N gcc-1.32/sparc.md gcc-1.33/sparc.md *** gcc-1.32/sparc.md Fri Dec 16 17:24:50 1988 --- gcc-1.33/sparc.md Sat Jan 28 19:45:37 1989 *************** *** 1,4 **** ;;- Machine description for SPARC chip for GNU C compiler ! ;; Copyright (C) 1988 Free Software Foundation, Inc. ;; Contributed by Michael Tiemann (tiemann@mcc.com) --- 1,4 ---- ;;- Machine description for SPARC chip for GNU C compiler ! ;; Copyright (C) 1988, 1989 Free Software Foundation, Inc. ;; Contributed by Michael Tiemann (tiemann@mcc.com) *************** *** 114,117 **** --- 114,191 ---- "set %0,%%g1\;tst %%g1") + ;; Optimize the case of following a reg-reg move with a test + ;; of reg just moved. + + (define_peephole + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "register_operand" "r")) + (set (cc0) (match_operand:SI 2 "register_operand" "r"))] + "operands[2] == operands[0] + || operands[2] == operands[1]" + "orcc %1,%%g0,%0 ! 2-insn combine") + + ;; Optimize 5(6) insn sequence to 3(4) insns. + ;; These patterns could also optimize more complicated sets + ;; before conditional branches. + + (define_peephole + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "general_operand" "g")) + (set (match_operand:SI 2 "register_operand" "=r") + (match_operand:SI 3 "reg_or_0_operand" "rJ")) + (set (cc0) (match_operand:SI 4 "register_operand" "r")) + (set (pc) (match_operand 5 "" ""))] + "GET_CODE (operands[5]) == IF_THEN_ELSE + && operands[0] != operands[3] + && ! reg_mentioned_p (operands[2], operands[1]) + && (operands[4] == operands[0] + || operands[4] == operands[2] + || operands[4] == operands[3])" + "* + { + rtx xoperands[2]; + int parity; + xoperands[0] = XEXP (operands[5], 0); + if (GET_CODE (XEXP (operands[5], 1)) == PC) + { + parity = 1; + xoperands[1] = XEXP (XEXP (operands[5], 2), 0); + } + else + { + parity = 0; + xoperands[1] = XEXP (XEXP (operands[5], 1), 0); + } + + if (operands[4] == operands[0]) + { + /* Although the constraints for operands[1] permit a general + operand (and hence possibly a const_int), we know that + in this branch it cannot be a CONST_INT, since that would give + us a fixed condition, and those should have been optimized away. */ + if (REG_P (operands[1])) + output_asm_insn (\"orcc %1,%%g0,%0 ! 3-insn reorder\", operands); + else if (GET_CODE (operands[1]) != MEM) + abort (); + else + { + if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) + output_asm_insn (\"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;tst %0 ! 4-insn reorder\", operands); + else + output_asm_insn (\"ld %1,%0\;tst %0 ! 3.5-insn reorder\", operands); + } + XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 2); + XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 3); + } + else + { + output_asm_insn (\"orcc %3,%%g0,%2 ! 3-insn reorder\", operands); + } + if (parity) + return output_delayed_branch (\"b%N0 %l1\", xoperands, insn); + else + return output_delayed_branch (\"b%C0 %l1\", xoperands, insn); + }") + ;; By default, operations don't set the condition codes. ;; These patterns allow cc's to be set, while doing some work *************** *** 121,125 **** (zero_extend:SI (subreg:QI (match_operand:SI 0 "register_operand" "r"))))] "" ! "andcc %0,0xff,%g0") (define_insn "" --- 195,199 ---- (zero_extend:SI (subreg:QI (match_operand:SI 0 "register_operand" "r"))))] "" ! "andcc %0,0xff,%%g0") (define_insn "" *************** *** 291,343 **** "gen_scc_insn (EQ, VOIDmode, operands); DONE;") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r") ! (eq (minus (match_operand:SI 1 "general_operand" "r,rI") ! (match_operand:SI 2 "general_operand" "I,r")) ! (const_int 0)))] "" "* { ! if (! REG_P (operands[1])) { ! output_asm_insn (\"cmp %2,%1\", operands); cc_status.flags |= CC_REVERSED; } else ! output_asm_insn (\"cmp %1,%2\", operands); ! return output_scc_insn (EQ, operands[0]); }") (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=r") ! (eq (match_operand:SI 1 "general_operand" "r") (const_int 0)))] "" ! "* output_asm_insn (\"tst %1\", operands); ! return output_scc_insn (EQ, operands[0]);") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r") ! (eq (minus:DF (match_operand:DF 1 "general_operand" "f,fG") ! (match_operand:DF 2 "general_operand" "G,f")) ! (const_int 0)))] "" "* { ! if (GET_CODE (operands[1]) == CONST_DOUBLE ! || GET_CODE (operands[2]) == CONST_DOUBLE) make_f0_contain_0 (2); cc_status.flags |= CC_IN_FCCR; ! if (GET_CODE (operands[1]) == CONST_DOUBLE) ! output_asm_insn (\"fcmped %%f0,%2\;nop\", operands); ! else if (GET_CODE (operands[2]) == CONST_DOUBLE) ! output_asm_insn (\"fcmped %1,%%f0\;nop\", operands); ! else output_asm_insn (\"fcmped %1,%2\;nop\", operands); ! return output_scc_insn (EQ, operands[0]); ! }") ! ! (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=r") ! (eq (match_operand:DF 1 "general_operand" "f") (const_int 0)))] "" "* --- 365,429 ---- "gen_scc_insn (EQ, VOIDmode, operands); DONE;") + (define_expand "sne" + [(set (match_operand:SI 0 "general_operand" "=r") + (ne (cc0) (const_int 0)))] + "" + "gen_scc_insn (NE, VOIDmode, operands); DONE;") + (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r") ! (match_operator 1 "eq_or_neq" ! [(minus (match_operand:SI 2 "general_operand" "r,rI") ! (match_operand:SI 3 "general_operand" "I,r")) ! (const_int 0)]))] "" "* { ! if (! REG_P (operands[2])) { ! output_asm_insn (\"cmp %3,%2\", operands); cc_status.flags |= CC_REVERSED; } else ! output_asm_insn (\"cmp %2,%3\", operands); ! return output_scc_insn (GET_CODE (operands[1]), operands[0]); }") (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=r") ! (match_operator 1 "eq_or_neq" ! [(match_operand:SI 2 "general_operand" "r") ! (const_int 0)]))] "" ! "* output_asm_insn (\"tst %2\", operands); ! return output_scc_insn (GET_CODE (operands[1]), operands[0]);") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r") ! (match_operator 1 "eq_or_neq" ! [(minus:DF (match_operand:DF 2 "general_operand" "f,fG") ! (match_operand:DF 3 "general_operand" "G,f")) ! (const_int 0)]))] "" "* { ! if (GET_CODE (operands[2]) == CONST_DOUBLE ! || GET_CODE (operands[3]) == CONST_DOUBLE) make_f0_contain_0 (2); cc_status.flags |= CC_IN_FCCR; ! if (GET_CODE (operands[2]) == CONST_DOUBLE) ! output_asm_insn (\"fcmped %%f0,%3\;nop\", operands); ! else if (GET_CODE (operands[3]) == CONST_DOUBLE) ! output_asm_insn (\"fcmped %2,%%f0\;nop\", operands); ! else output_asm_insn (\"fcmped %2,%3\;nop\", operands); ! return output_scc_insn (GET_CODE (operands[1]), operands[0]); ! }") ! ! (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=r") ! (match_operator 1 "eq_or_neq" ! [(match_operand:DF 2 "general_operand" "f") ! (const_int 0)]))] "" "* *************** *** 345,350 **** make_f0_contain_0 (2); cc_status.flags |= CC_IN_FCCR; ! output_asm_insn (\"fcmped %1,%%f0\;nop\", operands); ! return output_scc_insn (EQ, operands[0]); }") --- 431,436 ---- make_f0_contain_0 (2); cc_status.flags |= CC_IN_FCCR; ! output_asm_insn (\"fcmped %2,%%f0\;nop\", operands); ! return output_scc_insn (GET_CODE (operands[1]), operands[0]); }") *************** *** 351,376 **** (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r") ! (eq (minus:SF (match_operand:SF 1 "general_operand" "f,fG") ! (match_operand:SF 2 "general_operand" "G,f")) ! (const_int 0)))] "" "* { ! if (GET_CODE (operands[1]) == CONST_DOUBLE ! || GET_CODE (operands[2]) == CONST_DOUBLE) make_f0_contain_0 (1); cc_status.flags |= CC_IN_FCCR; ! if (GET_CODE (operands[1]) == CONST_DOUBLE) ! output_asm_insn (\"fcmpes %%f0,%2\;nop\", operands); ! else if (GET_CODE (operands[2]) == CONST_DOUBLE) ! output_asm_insn (\"fcmpes %1,%%f0\;nop\", operands); ! else output_asm_insn (\"fcmpes %1,%2\;nop\", operands); ! return output_scc_insn (EQ, operands[0]); ! }") ! ! (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=r") ! (eq (match_operand:SF 1 "general_operand" "f") (const_int 0)))] "" "* --- 437,465 ---- (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r") ! (match_operator 1 "eq_or_neq" ! [(minus:SF (match_operand:SF 2 "general_operand" "f,fG") ! (match_operand:SF 3 "general_operand" "G,f")) ! (const_int 0)]))] "" "* { ! if (GET_CODE (operands[2]) == CONST_DOUBLE ! || GET_CODE (operands[3]) == CONST_DOUBLE) make_f0_contain_0 (1); cc_status.flags |= CC_IN_FCCR; ! if (GET_CODE (operands[2]) == CONST_DOUBLE) ! output_asm_insn (\"fcmpes %%f0,%3\;nop\", operands); ! else if (GET_CODE (operands[3]) == CONST_DOUBLE) ! output_asm_insn (\"fcmpes %2,%%f0\;nop\", operands); ! else output_asm_insn (\"fcmpes %2,%3\;nop\", operands); ! return output_scc_insn (GET_CODE (operands[1]), operands[0]); ! }") ! ! (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=r") ! (match_operator 1 "eq_or_neq" ! [(match_operand:SF 2 "general_operand" "f") ! (const_int 0)]))] "" "* *************** *** 378,383 **** make_f0_contain_0 (1); cc_status.flags |= CC_IN_FCCR; ! output_asm_insn (\"fcmpes %1,%%f0\;nop\", operands); ! return output_scc_insn (EQ, operands[0]); }") \f --- 467,472 ---- make_f0_contain_0 (1); cc_status.flags |= CC_IN_FCCR; ! output_asm_insn (\"fcmpes %2,%%f0\;nop\", operands); ! return output_scc_insn (GET_CODE (operands[1]), operands[0]); }") \f *************** *** 424,428 **** if (cc_prev_status.flags & CC_IN_FCCR) return \"fbg %l0\;nop\"; ! return \"bgt %l0\;nop\"; }") --- 513,517 ---- if (cc_prev_status.flags & CC_IN_FCCR) return \"fbg %l0\;nop\"; ! return \"bg %l0\;nop\"; }") *************** *** 525,662 **** }") \f ! ;; These match inverted jump insns for register allocation. ! ! (define_insn "" ! [(set (pc) ! (if_then_else (eq (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fbne %l0\;nop\"; ! return \"bne %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (ne (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fbe %l0\;nop\"; ! return \"be %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (gt (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fble %l0\;nop\"; ! return \"ble %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (gtu (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! abort (); ! return \"bleu %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (lt (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fbge %l0\;nop\"; ! return \"bge %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (ltu (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! abort (); ! return \"bgeu %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (ge (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fbl %l0\;nop\"; ! return \"bl %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (geu (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! abort (); ! return \"blu %l0\;nop\"; ! }") ! ! (define_insn "" ! [(set (pc) ! (if_then_else (le (cc0) ! (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] ! "" ! "* ! { ! if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fbg %l0\;nop\"; ! return \"bg %l0\;nop\"; ! }") (define_insn "" [(set (pc) ! (if_then_else (leu (cc0) ! (const_int 0)) (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 614,624 ---- }") \f ! ;; This matches inverted jump insns for register allocation. (define_insn "" [(set (pc) ! (if_then_else (match_operator 0 "relop" [(cc0) (const_int 0)]) (pc) ! (label_ref (match_operand 1 "" ""))))] "" "* *************** *** 663,668 **** { if (cc_prev_status.flags & CC_IN_FCCR) ! abort (); ! return \"bgu %l0\;nop\"; }") \f --- 625,630 ---- { if (cc_prev_status.flags & CC_IN_FCCR) ! return \"fb%F0 %l1\;nop\"; ! return \"b%N0 %l1\;nop\"; }") \f *************** *** 699,845 **** }") - ;; These three patterns pick up all cases dealing with SYMBOL_REFS - ;; Can't do any special casing on modes if we want to use a modeless - ;; catch-all pattern, since taht pattern will win ahead of these patterns, - ;; despite the order they appear in the file. - - (define_insn "" - [(set (match_operand 0 "general_operand" "=fg") - (mem (match_operand:SI 1 "" "i")))] - "(GET_MODE (operands[0]) == SFmode - || GET_MODE (operands[0]) == DFmode) - && CONSTANT_ADDRESS_P (operands[1])" - "* - { - enum machine_mode mode = GET_MODE (SET_SRC (PATTERN (insn))); - - /* We don't bother trying to see if we know %hi(operands[1]). - This is because we are doing a load, and if we know the - %hi value, we probably also know that value in memory. */ - cc_status.flags |= CC_KNOW_HI_G1; - cc_status.mdep = operands[1]; - - if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) - && XEXP (operands[1], 0) == cc_prev_status.mdep - && cc_prev_status.mdep == cc_status.mdep)) - { - output_asm_insn (\"sethi %%hi(%1),%%g1\", operands); - cc_prev_status.mdep = operands[1]; - } - - if (mode == DFmode) - { - if (REG_P (operands[0])) - if (REGNO (operands[0]) & 1) - { - operands[1] = gen_rtx (MEM, mode, operands[1]); - return output_move_double (operands); - } - else - return \"ldd [%%g1+%%lo(%1)],%0\"; - cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0); - output_asm_insn (\"ldd [%%g1+%%lo(%1)],%%f0\", operands); - operands[1] = gen_rtx (REG, DFmode, 32); - return output_fp_move_double (operands); - } - - if (GET_CODE (operands[0]) == MEM) - { - cc_status.flags &= ~CC_F1_IS_0; - output_asm_insn (\"ld [%%g1+%%lo(%1)],%%f1\", operands); - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - cc_status.mdep = XEXP (operands[0], 0); - return \"sethi %%hi(%m0),%%g1\;st %%f1,[%%g1+%%lo(%m0)]\"; - } - else - return \"st %%f1,%0\"; - } - return \"ld [%%g1+%%lo(%1)],%0\"; - }") - - (define_insn "" - [(set (match_operand 0 "general_operand" "=r") - (mem (match_operand:SI 1 "" "i")))] - "GET_MODE (operands[0]) != SFmode - && GET_MODE (operands[0]) != DFmode - && CONSTANT_ADDRESS_P (operands[1])" - "* - { - enum machine_mode mode = GET_MODE (SET_SRC (PATTERN (insn))); - - /* We don't bother trying to see if we know %hi(operands[1]). - This is because we are doing a load, and if we know the - %hi value, we probably also know that value in memory. */ - cc_status.flags |= CC_KNOW_HI_G1; - cc_status.mdep = operands[1]; - - if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) - && XEXP (operands[1], 0) == cc_prev_status.mdep - && cc_prev_status.mdep == cc_status.mdep)) - { - output_asm_insn (\"sethi %%hi(%1),%%g1\", operands); - cc_prev_status.mdep = operands[1]; - } - - /* Code below isn't smart enough to do a doubleword in two parts. - So handle that case the slow way. */ - if (mode == DImode - && GET_CODE (operands[0]) == REG /* Moving to nonaligned reg pair */ - && (REGNO (operands[0]) & 1)) - { - operands[1] = gen_rtx (MEM, mode, operands[1]); - return output_move_double (operands); - } - output_sized_memop (\"ld\", mode); - if (GET_CODE (operands[0]) == REG) - return \"[%%g1+%%lo(%1)],%0\"; - abort (); - }") - - (define_insn "" - [(set (mem (match_operand:SI 0 "" "i")) - (match_operand 1 "reg_or_0_operand" "frGJ"))] - "CONSTANT_ADDRESS_P (operands[0])" - "* - { - enum machine_mode mode = GET_MODE (SET_DEST (PATTERN (insn))); - - cc_status.flags |= CC_KNOW_HI_G1; - cc_status.mdep = operands[0]; - - if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) - && operands[0] == cc_prev_status.mdep)) - { - output_asm_insn (\"sethi %%hi(%0),%%g1\", operands); - cc_prev_status.mdep = operands[0]; - } - - /* Store zero in two parts when appropriate. */ - if (mode == DFmode && operands[1] == dconst0_rtx) - { - /* We can't cross a page boundary here because the - SYMBOL_REF must be double word aligned, and for this - to be the case, SYMBOL_REF+4 cannot cross. */ - output_sized_memop (\"st\", SImode); - output_asm_insn (\"%r1,[%%g1+%%lo(%0)]\", operands); - output_sized_memop (\"st\", SImode); - return \"%r1,[%%g1+%%lo(%0)+4]\"; - } - - /* Code below isn't smart enough to move a doubleword in two parts, - so use output_move_double to do that in the cases that require it. */ - if ((mode == DImode || mode == DFmode) - && (GET_CODE (operands[1]) == REG - && (REGNO (operands[1]) & 1))) - { - operands[0] = gen_rtx (MEM, mode, operands[0]); - return output_move_double (operands); - } - - output_sized_memop (\"st\", mode); - return \"%r1,[%%g1+%%lo(%0)]\"; - }") - (define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=r,m") --- 661,664 ---- *************** *** 849,855 **** { if (GET_CODE (operands[0]) == MEM) ! return \"st %r1,%0\"; if (GET_CODE (operands[1]) == MEM) ! return \"ld %1,%0\"; if (FP_REG_P (operands[1])) return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\"; --- 668,682 ---- { if (GET_CODE (operands[0]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) ! return output_store (operands); ! return \"st %r1,%0\"; ! } if (GET_CODE (operands[1]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) ! return output_load_fixed (operands); ! return \"ld %1,%0\"; ! } if (FP_REG_P (operands[1])) return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\"; *************** *** 858,862 **** && SMALL_INT (operands[1]))) return \"mov %1,%0\"; ! return \"set %1,%0\"; }") --- 685,692 ---- && SMALL_INT (operands[1]))) return \"mov %1,%0\"; ! if (GET_CODE (operands[1]) == CONST_INT ! && (INTVAL (operands[1]) & 0x3ff) == 0) ! return \"sethi %%hi(%1),%0\"; ! return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\"; }") *************** *** 868,874 **** { if (GET_CODE (operands[0]) == MEM) ! return \"sth %r1,%0\"; if (GET_CODE (operands[1]) == MEM) ! return \"ldsh %1,%0\"; if (REG_P (operands[1]) || (GET_CODE (operands[1]) == CONST_INT --- 698,712 ---- { if (GET_CODE (operands[0]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) ! return output_store (operands); ! return \"sth %r1,%0\"; ! } if (GET_CODE (operands[1]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) ! return output_load_fixed (operands); ! return \"ldsh %1,%0\"; ! } if (REG_P (operands[1]) || (GET_CODE (operands[1]) == CONST_INT *************** *** 875,879 **** && SMALL_INT (operands[1]))) return \"mov %1,%0\"; ! return \"set %1,%0\"; }") --- 713,717 ---- && SMALL_INT (operands[1]))) return \"mov %1,%0\"; ! return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\"; }") *************** *** 885,892 **** { if (GET_CODE (operands[0]) == MEM) ! return \"stb %r1,%0\"; if (GET_CODE (operands[1]) == MEM) ! return \"ldsb %1,%0\"; ! return \"mov %1,%0\"; }") --- 723,742 ---- { if (GET_CODE (operands[0]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) ! return output_store (operands); ! return \"stb %r1,%0\"; ! } if (GET_CODE (operands[1]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) ! return output_load_fixed (operands); ! return \"ldsb %1,%0\"; ! } ! if (REG_P (operands[1]) ! || (GET_CODE (operands[1]) == CONST_INT ! && SMALL_INT (operands[1]))) ! return \"mov %1,%0\"; ! return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\"; }") *************** *** 958,966 **** (define_insn "movdf" ! [(set (match_operand:DF 0 "general_operand" "=r,m,?f,?rm") ! (match_operand:DF 1 "general_operand" "rm,r,rfm,f"))] "" "* { if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return output_fp_move_double (operands); --- 808,823 ---- (define_insn "movdf" ! [(set (match_operand:DF 0 "general_operand" "=rm,&r,?f,?rm") ! (match_operand:DF 1 "general_operand" "r,m,rfm,f"))] "" "* { + if (GET_CODE (operands[0]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) + return output_store (operands); + if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) + return output_load_floating (operands); + if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return output_fp_move_double (operands); *************** *** 969,977 **** (define_insn "movdi" ! [(set (match_operand:DI 0 "general_operand" "=r,m,?f,?rm") ! (match_operand:DI 1 "general_operand" "rmi,r,rfm,f"))] "" "* { if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return output_fp_move_double (operands); --- 826,841 ---- (define_insn "movdi" ! [(set (match_operand:DI 0 "general_operand" "=rm,&r,?f,?rm") ! (match_operand:DI 1 "general_operand" "r,mi,rfm,f"))] "" "* { + if (GET_CODE (operands[0]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) + return output_store (operands); + if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) + return output_load_fixed (operands); + if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return output_fp_move_double (operands); *************** *** 985,988 **** --- 849,858 ---- "* { + if (GET_CODE (operands[0]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) + return output_store (operands); + if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) + return output_load_floating (operands); if (FP_REG_P (operands[0])) { *************** *** 1017,1044 **** } if (GET_CODE (operands[0]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) ! { ! if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) ! && XEXP (operands[0], 0) == cc_prev_status.mdep)) ! { ! cc_status.flags |= CC_KNOW_HI_G1; ! cc_status.mdep = XEXP (operands[0], 0); ! output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands); ! } ! return \"st %r1,[%%g1+%%lo(%m0)]\"; ! } ! return \"st %r1,%0\"; ! } if (GET_CODE (operands[1]) == MEM) ! { ! if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) ! { ! cc_status.flags |= CC_KNOW_HI_G1; ! cc_status.mdep = XEXP (operands[1], 0); ! return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\"; ! } ! return \"ld %1,%0\"; ! } return \"mov %1,%0\"; }") --- 887,893 ---- } if (GET_CODE (operands[0]) == MEM) ! return \"st %r1,%0\"; if (GET_CODE (operands[1]) == MEM) ! return \"ld %1,%0\"; return \"mov %1,%0\"; }") *************** *** 1502,1506 **** return \"add %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"set %2,%%g1\;add %1,%%g1,%0\"; }") --- 1351,1355 ---- return \"add %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;add %1,%%g1,%0\"; }") *************** *** 1517,1521 **** return \"sub %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"set %2,%%g1\;sub %1,%%g1,%0\"; }") --- 1366,1370 ---- return \"sub %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;sub %1,%%g1,%0\"; }") *************** *** 1649,1653 **** "* return (GET_CODE (operands[1]) == CONST_INT ! ? \"set %1,%0\" : \"mov %1,%0\"); ") --- 1498,1502 ---- "* return (GET_CODE (operands[1]) == CONST_INT ! ? \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\" : \"mov %1,%0\"); ") *************** *** 1664,1668 **** return \"and %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"set %2,%%g1\;and %1,%%g1,%0\"; }") --- 1513,1517 ---- return \"and %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;and %1,%%g1,%0\"; }") *************** *** 1684,1688 **** return \"or %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"set %2,%%g1\;or %1,%%g1,%0\"; }") --- 1533,1537 ---- return \"or %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;or %1,%%g1,%0\"; }") *************** *** 1704,1708 **** return \"xor %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"set %2,%%g1\;xor %1,%%g1,%0\"; }") --- 1553,1557 ---- return \"xor %1,%2,%0\"; cc_status.flags &= ~CC_KNOW_HI_G1; ! return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;xor %1,%%g1,%0\"; }") *************** *** 1910,1920 **** \f ;; Unconditional and other jump instructions (define_insn "jump" ! [(set (pc) ! (label_ref (match_operand 0 "" "")))] "" ! "b %l0\;nop") ;; Peephole optimizers recognize a few simple cases when delay insns are safe. (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") --- 1759,1976 ---- \f ;; Unconditional and other jump instructions + ;; Note that for the Sparc, by setting the annul bit on an unconditional + ;; branch, the following insn is never executed. This saves us a nop, + ;; but requires a debugger which can handle annuled branches. (define_insn "jump" ! [(set (pc) (label_ref (match_operand 0 "" "")))] "" ! "* ! { ! extern int optimize; ! extern int flag_no_peephole; ! ! if (optimize && !flag_no_peephole) ! return \"b,a %l0\"; ! return \"b %l0\;nop\"; ! }") ;; Peephole optimizers recognize a few simple cases when delay insns are safe. + ;; Complex ones are up front. Simple ones after. + + ;; This pattern is just like the following one, but matches when there + ;; is a jump insn after the "delay" insn. Without this pattern, we + ;; de-optimize that case. + + (define_peephole + [(set (pc) (match_operand 0 "" "")) + (set (match_operand:SI 1 "" "") + (match_operand:SI 2 "" "")) + (set (pc) (label_ref (match_operand 3 "" "")))] + "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 2)" + "* + { + rtx xoperands[2]; + rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]); + rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0); + rtx label, head; + int parity; + + if (GET_CODE (XEXP (operands[0], 1)) == PC) + { + parity = 1; + label = XEXP (XEXP (operands[0], 2), 0); + } + else + { + parity = 0; + label = XEXP (XEXP (operands[0], 1), 0); + } + xoperands[0] = XEXP (operands[0], 0); + xoperands[1] = label; + + head = next_real_insn_no_labels (label); + + /* If at the target of this label we set the condition codes, + and the condition codes are already set for that value, + advance, if we can, to the following insn. */ + if (GET_CODE (PATTERN (head)) == SET + && GET_CODE (SET_DEST (PATTERN (head))) == CC0 + && cc_status.value2 == SET_SRC (PATTERN (head))) + { + rtx nhead = next_real_insn_no_labels (head); + if (nhead + && GET_CODE (nhead) == INSN + && GET_CODE (PATTERN (nhead)) == SET + && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)), + GET_MODE (SET_DEST (PATTERN (nhead)))) + && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode)) + { + head = nhead; + } + } + + /* Output the branch instruction first. */ + if (cc_prev_status.flags & CC_IN_FCCR) + { + if (parity) + output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands); + else + output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands); + } + else + { + if (parity) + output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands); + else + output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands); + } + + /* Now steal the first insn of the target. */ + output_eager_then_insn (head, operands); + + XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 1); + XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 2); + + return output_delayed_branch (\"b %l3 ! eager2\", operands, insn); + }") + + ;; Here is a peephole which recognizes where delay insns can be made safe: + ;; (1) following a conditional branch, if the target of the conditional branch + ;; has only one user (this insn), move the first insn into our delay slot + ;; and emit an annulled branch. + ;; (2) following a conditional branch, if we can execute the fall-through + ;; insn without risking any evil effects, then do that instead of a nop. + + (define_peephole + [(set (pc) (match_operand 0 "" "")) + (set (match_operand:SI 1 "" "") + (match_operand:SI 2 "" ""))] + "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 1)" + "* + { + rtx xoperands[2]; + rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]); + rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0); + rtx label, head, prev = (rtx)1; + int parity; + + if (GET_CODE (XEXP (operands[0], 1)) == PC) + { + parity = 1; + label = XEXP (XEXP (operands[0], 2), 0); + } + else + { + parity = 0; + label = XEXP (XEXP (operands[0], 1), 0); + } + xoperands[0] = XEXP (operands[0], 0); + xoperands[1] = label; + + if (LABEL_NUSES (label) == 1) + { + prev = PREV_INSN (label); + while (prev + && (GET_CODE (prev) == NOTE + || (GET_CODE (prev) == INSN + && (GET_CODE (PATTERN (prev)) == CLOBBER + || GET_CODE (PATTERN (prev)) == USE)))) + prev = PREV_INSN (prev); + if (prev == 0 + || GET_CODE (prev) == BARRIER) + { + prev = 0; + head = next_real_insn_no_labels (label); + } + } + if (prev == 0 + && head != 0 + && ! INSN_DELETED_P (head) + && GET_CODE (head) == INSN + && GET_CODE (PATTERN (head)) == SET + && strict_single_insn_op_p (SET_SRC (PATTERN (head)), + GET_MODE (SET_DEST (PATTERN (head)))) + && strict_single_insn_op_p (SET_DEST (PATTERN (head)), VOIDmode)) + { + /* If at the target of this label we set the condition codes, + and the condition codes are already set for that value, + advance, if we can, to the following insn. */ + if (GET_CODE (PATTERN (head)) == SET + && GET_CODE (SET_DEST (PATTERN (head))) == CC0 + && cc_status.value2 == SET_SRC (PATTERN (head))) + { + rtx nhead = next_real_insn_no_labels (head); + if (nhead + && GET_CODE (nhead) == INSN + && GET_CODE (PATTERN (nhead)) == SET + && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)), + GET_MODE (SET_DEST (nhead))) + && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode)) + head = nhead; + } + + /* Output the branch instruction first. */ + if (cc_prev_status.flags & CC_IN_FCCR) + { + if (parity) + output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands); + else + output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands); + } + else + { + if (parity) + output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands); + else + output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands); + } + + /* Now steal the first insn of the target. */ + output_eager_then_insn (head, operands); + } + else + { + /* Output the branch instruction first. */ + if (cc_prev_status.flags & CC_IN_FCCR) + { + if (parity) + output_asm_insn (\"fb%F0 %l1 ! eager\", xoperands); + else + output_asm_insn (\"fb%C0 %l1 ! eager\", xoperands); + } + else + { + if (parity) + output_asm_insn (\"b%N0 %l1 ! eager\", xoperands); + else + output_asm_insn (\"b%C0 %l1 ! eager\", xoperands); + } + } + return output_delay_insn (delay_insn); + }") + + ;; Here are two simple peepholes which fill the delay slot of + ;; an unconditional branch. + (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") *************** *** 1922,1926 **** (set (pc) (label_ref (match_operand 2 "" "")))] "" ! "* return output_delay_insn (\"b %l2\", operands, insn);") (define_peephole --- 1978,1982 ---- (set (pc) (label_ref (match_operand 2 "" "")))] "" ! "* return output_delayed_branch (\"b %l2\", operands, insn);") (define_peephole *************** *** 1929,1933 **** (set (pc) (label_ref (match_operand 2 "" "")))] "" ! "* return output_delay_insn (\"b %l2\", operands, insn);") (define_insn "tablejump" --- 1985,1989 ---- (set (pc) (label_ref (match_operand 2 "" "")))] "" ! "* return output_delayed_branch (\"b %l2\", operands, insn);") (define_insn "tablejump" *************** *** 1943,1947 **** (use (label_ref (match_operand 3 "" "")))] "REGNO (operands[0]) != REGNO (operands[2])" ! "* return output_delay_insn (\"jmp %2\", operands, insn);") (define_peephole --- 1999,2003 ---- (use (label_ref (match_operand 3 "" "")))] "REGNO (operands[0]) != REGNO (operands[2])" ! "* return output_delayed_branch (\"jmp %2\", operands, insn);") (define_peephole *************** *** 1951,1955 **** (use (label_ref (match_operand 3 "" "")))] "" ! "* return output_delay_insn (\"jmp %2\", operands, insn);") ;;- jump to subroutine --- 2007,2011 ---- (use (label_ref (match_operand 3 "" "")))] "" ! "* return output_delayed_branch (\"jmp %2\", operands, insn);") ;;- jump to subroutine *************** *** 2000,2003 **** --- 2056,2060 ---- /* strip the MEM. */ operands[0] = XEXP (operands[0], 0); + CC_STATUS_INIT; if (TARGET_SUN_ASM && GET_CODE (operands[0]) == REG) return \"jmpl %a0,%%o7\;nop\"; *************** *** 2018,2023 **** operands[2] = XEXP (operands[2], 0); if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG) ! return output_delay_insn (\"jmpl %a2,%%o7\", operands, insn); ! return output_delay_insn (\"call %a2,%3\", operands, insn); }") --- 2075,2080 ---- operands[2] = XEXP (operands[2], 0); if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG) ! return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn); ! return output_delayed_branch (\"call %a2,%3\", operands, insn); }") *************** *** 2035,2040 **** operands[2] = XEXP (operands[2], 0); if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG) ! return output_delay_insn (\"jmpl %a2,%%o7\", operands, insn); ! return output_delay_insn (\"call %a2,%3\", operands, insn); }") --- 2092,2097 ---- operands[2] = XEXP (operands[2], 0); if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG) ! return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn); ! return output_delayed_branch (\"call %a2,%3\", operands, insn); }") *************** *** 2088,2091 **** --- 2145,2149 ---- /* strip the MEM. */ operands[1] = XEXP (operands[1], 0); + CC_STATUS_INIT; if (TARGET_SUN_ASM && GET_CODE (operands[1]) == REG) return \"jmpl %a1,%%o7\;nop\"; *************** *** 2107,2112 **** operands[3] = XEXP (operands[3], 0); if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG) ! return output_delay_insn (\"jmpl %a3,%%o7\", operands, insn); ! return output_delay_insn (\"call %a3,%4\", operands, insn); }") --- 2165,2170 ---- operands[3] = XEXP (operands[3], 0); if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG) ! return output_delayed_branch (\"jmpl %a3,%%o7\", operands, insn); ! return output_delayed_branch (\"call %a3,%4\", operands, insn); }") *************** *** 2125,2130 **** operands[3] = XEXP (operands[3], 0); if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG) ! return output_delay_insn (\"jmpl %a3,%%o7\", operands, insn); ! return output_delay_insn (\"call %a3,%4\", operands, insn); }") \f --- 2183,2188 ---- operands[3] = XEXP (operands[3], 0); if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG) ! return output_delayed_branch (\"jmpl %a3,%%o7\", operands, insn); ! return output_delayed_branch (\"call %a3,%4\", operands, insn); }") \f *************** *** 2166,2167 **** --- 2224,2226 ---- ;;- eval: (modify-syntax-entry ?} "){") ;;- End: + diff -rc2N gcc-1.32/stab.def gcc-1.33/stab.def *** gcc-1.32/stab.def Wed Dec 31 19:00:00 1969 --- gcc-1.33/stab.def Tue Sep 13 17:59:23 1988 *************** *** 0 **** --- 1,201 ---- + /* Table of DBX symbol codes for the GNU system. + Copyright (C) 1988 Free Software Foundation, Inc. + + NO WARRANTY + + BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY + NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, + RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY + AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE + DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR + CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. + STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY + WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE + LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR + OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR + DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR + A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS + PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. + + GENERAL PUBLIC LICENSE TO COPY + + 1. You may copy and distribute verbatim copies of this source file + as you receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy a valid copyright notice "Copyright + (C) 1988 Free Software Foundation, Inc."; and include following the + copyright notice a verbatim copy of the above disclaimer of warranty + and of this License. You may charge a distribution fee for the + physical act of transferring a copy. + + 2. You may modify your copy or copies of this source file or + any portion of it, and copy and distribute such modifications under + the terms of Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + that you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of this + program or any part thereof, to be licensed at no charge to all + third parties on terms identical to those contained in this + License Agreement (except that you may choose to grant more extensive + warranty protection to some or all third parties, at your option). + + c) You may charge a distribution fee for the physical act of + transferring a copy, and you may at your option offer warranty + protection in exchange for a fee. + + Mere aggregation of another unrelated program with this program (or its + derivative) on a volume of a storage or distribution medium does not bring + the other program under the scope of these terms. + + 3. You may copy and distribute this program or any portion of it in + compiled, executable or object code form under the terms of Paragraphs + 1 and 2 above provided that you do the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal + shipping charge) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + + For an executable file, complete source code means all the source code for + all modules it contains; but, as a special exception, it need not include + source code for modules which are standard libraries that accompany the + operating system on which the executable file runs. + + 4. You may not copy, sublicense, distribute or transfer this program + except as expressly provided under this License Agreement. Any attempt + otherwise to copy, sublicense, distribute or transfer this program is void and + your rights to use the program under this License agreement shall be + automatically terminated. However, parties who have received computer + software programs from you with this License Agreement will not have + their licenses terminated so long as such parties remain in full compliance. + + 5. If you wish to incorporate parts of this program into other free + programs whose distribution conditions are different, write to the Free + Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet + worked out a simple rule that can be stated here, but we will often permit + this. We will be guided by the two goals of preserving the free status of + all derivatives our free software and of promoting the sharing and reuse of + software. + + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + \f + /* Global variable. Only the name is significant. + To find the address, look in the corresponding external symbol. */ + __define_stab (N_GSYM, 0x20, "GSYM") + + /* Function name for BSD Fortran. Only the name is significant. + To find the address, look in the corresponding external symbol. */ + __define_stab (N_FNAME, 0x22, "FNAME") + + /* Function name or text-segment variable for C. Value is its address. + Desc is supposedly starting line number, but GCC doesn't set it + and DBX seems not to miss it. */ + __define_stab (N_FUN, 0x24, "FUN") + + /* Data-segment variable with internal linkage. Value is its address. */ + __define_stab (N_STSYM, 0x26, "STSYM") + + /* BSS-segment variable with internal linkage. Value is its address. */ + __define_stab (N_LCSYM, 0x28, "LCSYM") + + /* Name of main routine. Only the name is significant. + This is not used in C. */ + __define_stab (N_MAIN, 0x2a, "MAIN") + + /* Register variable. Value is number of register. */ + __define_stab (N_RSYM, 0x40, "RSYM") + + /* Structure or union element. Value is offset in the structure. */ + __define_stab (N_SSYM, 0x60, "SSYM") + + /* Parameter variable. Value is offset from argument pointer. + (On most machines the argument pointer is the same as the frame pointer. */ + __define_stab (N_PSYM, 0xa0, "PSYM") + + /* Automatic variable in the stack. Value is offset from frame pointer. */ + __define_stab (N_LSYM, 0x80, "LSYM") + + /* Alternate entry point. Value is its address. */ + __define_stab (N_ENTRY, 0xa4, "ENTRY") + + /* Name of main source file. + Value is starting text address of the compilation. */ + __define_stab (N_SO, 0x64, "SO") + + /* Name of sub-source file. + Value is starting text address of the compilation. */ + __define_stab (N_SOL, 0x84, "SOL") + + /* Line number in text segment. Desc is the line number; + value is corresponding address. */ + __define_stab (N_SLINE, 0x44, "SLINE") + /* Similar, for data segment. */ + __define_stab (N_DSLINE, 0x46, "DSLINE") + /* Similar, for bss segment. */ + __define_stab (N_BSLINE, 0x48, "BSLINE") + + /* Beginning of an include file. Only Sun uses this. + In an object file, only the name is significant. + The Sun linker puts data into some of the other fields. */ + __define_stab (N_BINCL, 0x82, "BINCL") + /* End of an include file. No name. + These two act as brackets around the file's output. + In an object file, there is no significant data in this entry. + The Sun linker puts data into some of the fields. */ + __define_stab (N_EINCL, 0xa2, "EINCL") + /* Place holder for deleted include file. + This appears only in output from the Sun linker. */ + __define_stab (N_EXCL, 0xc2, "EXCL") + + /* Beginning of lexical block. + The desc is the nesting level in lexical blocks. + The value is the address of the start of the text for the block. + The variables declared inside the block *precede* the N_LBRAC symbol. */ + __define_stab (N_LBRAC, 0xc0, "LBRAC") + /* End of a lexical block. Desc matches the N_LBRAC's desc. + The value is the address of the end of the text for the block. */ + __define_stab (N_RBRAC, 0xe0, "RBRAC") + + /* Begin named common block. Only the name is significant. */ + __define_stab (N_BCOMM, 0xe2, "BCOMM") + /* Begin named common block. Only the name is significant + (and it should match the N_BCOMM). */ + __define_stab (N_ECOMM, 0xe4, "ECOMM") + /* End common (local name): value is address. + I'm not sure how this is used. */ + __define_stab (N_ECOML, 0xe8, "ECOML") + /* Second symbol entry containing a length-value for the preceding entry. + The value is the length. */ + __define_stab (N_LENG, 0xfe, "LENG") + + /* Global symbol in Pascal. + Supposedly the value is its line number; I'm skeptical. */ + __define_stab (N_PC, 0x30, "PC") + + /* Modula-2 compilation unit. Can someone say what info it contains? */ + __define_stab (N_M2C, 0x42, "M2C") + /* Modula-2 scope information. Can someone say what info it contains? */ + __define_stab (N_SCOPE, 0xc4, "SCOPE") diff -rc2N gcc-1.32/stab.h gcc-1.33/stab.h *** gcc-1.32/stab.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/stab.h Tue Sep 13 17:51:21 1988 *************** *** 0 **** --- 1,16 ---- + #ifndef __GNU_STAB__ + + /* Indicate the GNU stab.h is in use. */ + + #define __GNU_STAB__ + + #define __define_stab(NAME, CODE, STRING) NAME=CODE, + + enum __stab_debug_code + { + #include "stab.def" + }; + + #undef __define_stab + + #endif /* __GNU_STAB_ */ diff -rc2N gcc-1.32/stmt.c gcc-1.33/stmt.c *** gcc-1.32/stmt.c Wed Dec 21 02:42:05 1988 --- gcc-1.33/stmt.c Sat Jan 28 19:49:49 1989 *************** *** 1,4 **** /* Expands front end tree to back end RTL for GNU C-Compiler ! Copyright (C) 1987,1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Expands front end tree to back end RTL for GNU C-Compiler ! Copyright (C) 1987,1988, 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 162,166 **** static rtx parm_stack_loc (); static void optimize_bit_field (); ! void do_jump_if_equal (); \f /* Functions and data structures for expanding case statements. */ --- 162,166 ---- static rtx parm_stack_loc (); static void optimize_bit_field (); ! static void do_jump_if_equal (); \f /* Functions and data structures for expanding case statements. */ *************** *** 739,742 **** --- 739,744 ---- { tree val = TREE_VALUE (tail); + int j; + int found_equal; /* If there's an erroneous arg, emit no insn. */ *************** *** 744,747 **** --- 746,768 ---- return; + /* Make sure constraint has `=' and does not have `+'. */ + + found_equal = 0; + for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)); j++) + { + if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+') + { + error ("input operand constraint contains `+'"); + return; + } + if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '=') + found_equal = 1; + } + if (! found_equal) + { + error ("output operand constraint lacks `='"); + return; + } + /* If an output operand is not a variable or indirect ref, create a SAVE_EXPR which is a pseudo-reg *************** *** 786,789 **** --- 807,812 ---- for (tail = inputs; tail; tail = TREE_CHAIN (tail)) { + int j; + /* If there's an erroneous arg, emit no insn, because the ASM_INPUT would get VOIDmode *************** *** 798,801 **** --- 821,835 ---- } + /* Make sure constraint has neither `=' nor `+'. */ + + for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)); j++) + if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '=' + || TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+') + { + error ("input operand constraint contains `%c'", + TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]); + return; + } + XVECEXP (body, 3, i) /* argvec */ = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0); *************** *** 912,916 **** /* If -W, warn about statements with no side effects, except inside a ({...}) where they may be useful. */ ! if (extra_warnings && expr_stmts_for_value == 0 && !TREE_VOLATILE (exp)) warning ("statement with no effect"); last_expr_type = TREE_TYPE (exp); --- 946,951 ---- /* If -W, warn about statements with no side effects, except inside a ({...}) where they may be useful. */ ! if (extra_warnings && expr_stmts_for_value == 0 && !TREE_VOLATILE (exp) ! && exp != error_mark_node) warning ("statement with no effect"); last_expr_type = TREE_TYPE (exp); *************** *** 1305,1308 **** --- 1340,1346 ---- && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL) retval_rhs = TREE_OPERAND (retval, 1); + else if (TREE_TYPE (retval) == void_type_node) + /* Recognize tail-recursive call to void function. */ + retval_rhs = retval; else retval_rhs = NULL_TREE; *************** *** 1323,1327 **** DECL_ARGUMENTS (this_function))) { - ; if (tail_recursion_label == 0) { --- 1361,1364 ---- *************** *** 1371,1375 **** emit_queue (); ! if (retval_rhs && GET_CODE (val) == REG) emit_insn (gen_rtx (USE, VOIDmode, val)); --- 1408,1412 ---- emit_queue (); ! if (GET_CODE (val) == REG) emit_insn (gen_rtx (USE, VOIDmode, val)); *************** *** 1679,1695 **** type = TREE_TYPE (decl); - /* External function declarations are supposed to have been - handled in assemble_variable. Verify this. */ - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (DECL_RTL (decl) == 0) - abort (); - return; - } - /* Aside from that, only automatic variables need any expansion done. ! Static and external variables were handled by `assemble_variable' ! (called from finish_decl). TYPE_DECL and CONST_DECL require nothing; PARM_DECLs are handled in `assign_parms'. */ --- 1716,1723 ---- type = TREE_TYPE (decl); /* Aside from that, only automatic variables need any expansion done. ! Static and external variables, and external functions, ! will be handled by `assemble_variable' (called from finish_decl). ! TYPE_DECL and CONST_DECL require nothing. PARM_DECLs are handled in `assign_parms'. */ *************** *** 1703,1706 **** --- 1731,1745 ---- if (type == error_mark_node) DECL_RTL (decl) = gen_rtx (MEM, BLKmode, const0_rtx); + else if (DECL_SIZE (decl) == 0) + /* Variable with incomplete type. */ + { + if (DECL_INITIAL (decl) == 0) + /* Error message was already done; now avoid a crash. */ + DECL_RTL (decl) = assign_stack_local (DECL_MODE (decl), 0); + else + /* An initializer is going to decide the size of this array. + Until we know the size, represent its address with a reg. */ + DECL_RTL (decl) = gen_rtx (MEM, BLKmode, gen_reg_rtx (Pmode)); + } else if (DECL_MODE (decl) != BLKmode /* If -ffloat-store, don't put explicit float vars *************** *** 1718,1727 **** REG_USERVAR_P (DECL_RTL (decl)) = 1; } - else if (DECL_SIZE (decl) == 0) - /* Variable with incomplete type. */ - /* Error message was already done; now avoid a crash. */ - DECL_RTL (decl) = assign_stack_local (DECL_MODE (decl), 0); else if (TREE_LITERAL (DECL_SIZE (decl))) { /* Variable of fixed size that goes on the stack. */ DECL_RTL (decl) --- 1757,1777 ---- REG_USERVAR_P (DECL_RTL (decl)) = 1; } else if (TREE_LITERAL (DECL_SIZE (decl))) { + rtx oldaddr = 0; + rtx addr; + + /* If we previously made RTL for this decl, it must be an array + whose size was determined by the initializer. + The old address was a register; set that register now + to the proper address. */ + if (DECL_RTL (decl) != 0) + { + if (GET_CODE (DECL_RTL (decl)) != MEM + || GET_CODE (XEXP (DECL_RTL (decl), 0)) != REG) + abort (); + oldaddr = XEXP (DECL_RTL (decl), 0); + } + /* Variable of fixed size that goes on the stack. */ DECL_RTL (decl) *************** *** 1731,1734 **** --- 1781,1790 ---- + BITS_PER_UNIT - 1) / BITS_PER_UNIT); + if (oldaddr) + { + addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr); + emit_move_insn (oldaddr, addr); + } + /* If this is a memory ref that contains aggregate components, mark it as such for cse and loop optimize. */ *************** *** 1802,1809 **** register variable starts here, at the start of its scope. */ ! if (obey_regdecls ! && TREE_CODE (decl) == VAR_DECL ! && DECL_RTL (decl) != 0) use_variable (DECL_RTL (decl)); /* Compute and store the initial value now. */ --- 1858,1873 ---- register variable starts here, at the start of its scope. */ ! if (obey_regdecls) use_variable (DECL_RTL (decl)); + } + \f + /* Emit code to perform the initialization of a declaration DECL. */ + + void + expand_decl_init (decl) + tree decl; + { + if (TREE_STATIC (decl)) + return; /* Compute and store the initial value now. */ *************** *** 2061,2065 **** for (l = &case_stack->data.case_stmt.case_list; /* Keep going past elements distinctly less than VALUE. */ ! *l != 0 && !tree_int_cst_lt (value, (*l)->high); l = &(*l)->right) ; --- 2125,2129 ---- for (l = &case_stack->data.case_stmt.case_list; /* Keep going past elements distinctly less than VALUE. */ ! *l != 0 && tree_int_cst_lt ((*l)->high, value); l = &(*l)->right) ; *************** *** 2145,2149 **** for (l = &case_stack->data.case_stmt.case_list; /* Keep going past elements distinctly less than this range. */ ! *l != 0 && !tree_int_cst_lt (value1, (*l)->high); l = &(*l)->right) ; --- 2209,2213 ---- for (l = &case_stack->data.case_stmt.case_list; /* Keep going past elements distinctly less than this range. */ ! *l != 0 && tree_int_cst_lt ((*l)->high, value1); l = &(*l)->right) ; *************** *** 2278,2281 **** --- 2342,2346 ---- index = expand_expr (index_expr, 0, VOIDmode, 0); emit_queue (); + do_pending_stack_adjust (); index = protect_from_queue (index, 0); *************** *** 2282,2287 **** if (GET_CODE (index) == MEM) index = copy_to_reg (index); ! if (TREE_CODE (index_expr) == INTEGER_CST) { /* For constant index expressions we need only issue a unconditional branch to the appropriate --- 2347,2361 ---- if (GET_CODE (index) == MEM) index = copy_to_reg (index); ! if (GET_CODE (index) == CONST_INT ! || TREE_CODE (index_expr) == INTEGER_CST) { + /* Make a tree node with the proper constant value + if we don't already have one. */ + if (TREE_CODE (index_expr) != INTEGER_CST) + { + index_expr = build_int_2 (INTVAL (index), 0); + index_expr = convert (TREE_TYPE (index_expr), index_expr); + } + /* For constant index expressions we need only issue a unconditional branch to the appropriate *************** *** 2298,2304 **** } if (n) - emit_jump (default_label); - else emit_jump (label_rtx (n->code_label)); } else --- 2372,2378 ---- } if (n) emit_jump (label_rtx (n->code_label)); + else + emit_jump (default_label); } else *************** *** 2319,2323 **** balance_case_nodes (&thiscase->data.case_stmt.case_list, 0); emit_case_nodes (index, thiscase->data.case_stmt.case_list, ! default_label); emit_jump_if_reachable (default_label); } --- 2393,2398 ---- balance_case_nodes (&thiscase->data.case_stmt.case_list, 0); emit_case_nodes (index, thiscase->data.case_stmt.case_list, ! default_label, ! TREE_UNSIGNED (TREE_TYPE (index_expr))); emit_jump_if_reachable (default_label); } *************** *** 2415,2423 **** /* Generate code to jump to LABEL if OP1 and OP2 are equal. */ - /* ??? This may need an UNSIGNEDP argument to work properly ??? */ ! void ! do_jump_if_equal (op1, op2, label) rtx op1, op2, label; { if (GET_CODE (op1) == CONST_INT --- 2490,2498 ---- /* Generate code to jump to LABEL if OP1 and OP2 are equal. */ ! static void ! do_jump_if_equal (op1, op2, label, unsignedp) rtx op1, op2, label; + int unsignedp; { if (GET_CODE (op1) == CONST_INT *************** *** 2429,2433 **** else { ! emit_cmp_insn (op1, op2, 0, 0); emit_jump_insn (gen_beq (label)); } --- 2504,2508 ---- else { ! emit_cmp_insn (op1, op2, 0, unsignedp, 0); emit_jump_insn (gen_beq (label)); } *************** *** 2567,2580 **** { low_minus_one = combine (MINUS_EXPR, node->low, build_int_2 (1, 0)); ! for (pnode = node->parent; pnode; pnode = pnode->parent) ! { ! if (tree_int_cst_equal (low_minus_one, pnode->high)) ! return 1; ! /* If a parent node has a left branch we know that none ! of its parents can have a high bound of our target ! minus one so we abort the search. */ ! if (node->left) ! break; ! } } return 0; --- 2642,2657 ---- { low_minus_one = combine (MINUS_EXPR, node->low, build_int_2 (1, 0)); ! /* Avoid the screw case of overflow where low_minus_one is > low. */ ! if (tree_int_cst_lt (low_minus_one, node->low)) ! for (pnode = node->parent; pnode; pnode = pnode->parent) ! { ! if (tree_int_cst_equal (low_minus_one, pnode->high)) ! return 1; ! /* If a parent node has a left branch we know that none ! of its parents can have a high bound of our target ! minus one so we abort the search. */ ! if (node->left) ! break; ! } } return 0; *************** *** 2600,2613 **** { high_plus_one = combine (PLUS_EXPR, node->high, build_int_2 (1, 0)); ! for (pnode = node->parent; pnode; pnode = pnode->parent) ! { ! if (tree_int_cst_equal (high_plus_one, pnode->low)) ! return 1; ! /* If a parent node has a right branch we know that none ! of its parents can have a low bound of our target ! plus one so we abort the search. */ ! if (node->right) ! break; ! } } return 0; --- 2677,2692 ---- { high_plus_one = combine (PLUS_EXPR, node->high, build_int_2 (1, 0)); ! /* Avoid the screw case of overflow where high_plus_one is > high. */ ! if (tree_int_cst_lt (node->high, high_plus_one)) ! for (pnode = node->parent; pnode; pnode = pnode->parent) ! { ! if (tree_int_cst_equal (high_plus_one, pnode->low)) ! return 1; ! /* If a parent node has a right branch we know that none ! of its parents can have a low bound of our target ! plus one so we abort the search. */ ! if (node->right) ! break; ! } } return 0; *************** *** 2642,2645 **** --- 2721,2725 ---- The thus generated decision tree follows the form of the case-node binary tree NODE, whose nodes represent test conditions. + UNSIGNEDP is nonzero if we should do unsigned comparisons. Care is taken to prune redundant tests from the decision tree *************** *** 2657,2665 **** static void ! emit_case_nodes (index, node, default_label) ! tree index; case_node_ptr node; tree default_label; { if (node->test_label) { --- 2737,2753 ---- static void ! emit_case_nodes (index, node, default_label, unsignedp) ! rtx index; case_node_ptr node; tree default_label; + int unsignedp; { + /* If INDEX has an unsigned type, we must make unsigned branches. */ + typedef rtx rtx_function (); + rtx_function *gen_bgt_pat = unsignedp ? gen_bgtu : gen_bgt; + rtx_function *gen_bge_pat = unsignedp ? gen_bgeu : gen_bge; + rtx_function *gen_blt_pat = unsignedp ? gen_bltu : gen_blt; + rtx_function *gen_ble_pat = unsignedp ? gen_bleu : gen_ble; + if (node->test_label) { *************** *** 2675,2679 **** /* Node is single valued. */ do_jump_if_equal (index, expand_expr (node->low, 0, VOIDmode, 0), ! label_rtx (node->code_label)); if (node->right) { --- 2763,2767 ---- /* Node is single valued. */ do_jump_if_equal (index, expand_expr (node->low, 0, VOIDmode, 0), ! label_rtx (node->code_label), unsignedp); if (node->right) { *************** *** 2681,2692 **** { /* This node has children on either side. */ if (node_is_bounded (node->right)) { ! emit_jump_insn (gen_bgt (label_rtx (node->right->code_label))); if (node_is_bounded (node->left)) emit_jump (label_rtx (node->left->code_label)); else ! emit_case_nodes (index, node->left, default_label); } else --- 2769,2782 ---- { /* This node has children on either side. */ + emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0, 0); if (node_is_bounded (node->right)) { ! emit_jump_insn (gen_bgt_pat (label_rtx (node->right->code_label))); if (node_is_bounded (node->left)) emit_jump (label_rtx (node->left->code_label)); else ! emit_case_nodes (index, node->left, ! default_label, unsignedp); } else *************** *** 2693,2697 **** { if (node_is_bounded (node->left)) ! emit_jump_insn (gen_blt (label_rtx (node->left->code_label))); else { --- 2783,2787 ---- { if (node_is_bounded (node->left)) ! emit_jump_insn (gen_blt_pat (label_rtx (node->left->code_label))); else { *************** *** 2698,2705 **** node->right->test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ! emit_jump_insn (gen_bgt (label_rtx (node->right->test_label))); ! emit_case_nodes (index, node->left, default_label); } ! emit_case_nodes (index, node->right, default_label); } } --- 2788,2797 ---- node->right->test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ! emit_jump_insn (gen_bgt_pat (label_rtx (node->right->test_label))); ! emit_case_nodes (index, node->left, ! default_label, unsignedp); } ! emit_case_nodes (index, node->right, ! default_label, unsignedp); } } *************** *** 2714,2722 **** it costs too much space to save so little time. */ if (node->right->right && !node_has_low_bound (node)) ! emit_jump_insn (gen_blt (default_label)); if (node_is_bounded (node->right)) emit_jump (label_rtx (node->right->code_label)); else ! emit_case_nodes (index, node->right, default_label); } } --- 2806,2817 ---- it costs too much space to save so little time. */ if (node->right->right && !node_has_low_bound (node)) ! { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_blt_pat (default_label)); ! } if (node_is_bounded (node->right)) emit_jump (label_rtx (node->right->code_label)); else ! emit_case_nodes (index, node->right, default_label, unsignedp); } } *************** *** 2726,2730 **** emit_jump (label_rtx (node->left->code_label)); else ! emit_case_nodes (index, node->left, default_label); } } --- 2821,2825 ---- emit_jump (label_rtx (node->left->code_label)); else ! emit_case_nodes (index, node->left, default_label, unsignedp); } } *************** *** 2736,2740 **** if (node->left) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0); if (node_is_bounded (node->right)) { --- 2831,2835 ---- if (node->left) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0, 0); if (node_is_bounded (node->right)) { *************** *** 2742,2746 **** eliminate any testing and branch directly to the target code. */ ! emit_jump_insn (gen_bgt (label_rtx (node->right->code_label))); } else --- 2837,2841 ---- eliminate any testing and branch directly to the target code. */ ! emit_jump_insn (gen_bgt_pat (label_rtx (node->right->code_label))); } else *************** *** 2750,2757 **** node->right->test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ! emit_jump_insn (gen_bgt (label_rtx (node->right->test_label))); } ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_bge (label_rtx (node->code_label))); if (node_is_bounded (node->left)) { --- 2845,2852 ---- node->right->test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ! emit_jump_insn (gen_bgt_pat (label_rtx (node->right->test_label))); } ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_bge_pat (label_rtx (node->code_label))); if (node_is_bounded (node->left)) { *************** *** 2762,2770 **** } else ! emit_case_nodes (index, node->left, default_label); /* If right node has been given a test label above we must process it now. */ if (node->right->test_label) ! emit_case_nodes (index, node->right, default_label); } else --- 2857,2865 ---- } else ! emit_case_nodes (index, node->left, default_label, unsignedp); /* If right node has been given a test label above we must process it now. */ if (node->right->test_label) ! emit_case_nodes (index, node->right, default_label, unsignedp); } else *************** *** 2772,2780 **** if (!node_has_low_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_blt (default_label)); } ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_ble (label_rtx (node->code_label))); if (node_is_bounded (node->right)) { --- 2867,2875 ---- if (!node_has_low_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_blt_pat (default_label)); } ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_ble_pat (label_rtx (node->code_label))); if (node_is_bounded (node->right)) { *************** *** 2785,2789 **** } else ! emit_case_nodes (index, node->right, default_label); } } --- 2880,2884 ---- } else ! emit_case_nodes (index, node->right, default_label, unsignedp); } } *************** *** 2792,2800 **** if (!node_has_high_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_bgt (default_label)); } ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_bge (label_rtx (node->code_label))); if (node_is_bounded (node->left)) { --- 2887,2895 ---- if (!node_has_high_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_bgt_pat (default_label)); } ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_bge_pat (label_rtx (node->code_label))); if (node_is_bounded (node->left)) { *************** *** 2805,2809 **** } else ! emit_case_nodes (index, node->left, default_label); } else --- 2900,2904 ---- } else ! emit_case_nodes (index, node->left, default_label, unsignedp); } else *************** *** 2815,2825 **** if (!node_has_high_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_bgt (default_label)); } if (!node_has_low_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0); ! emit_jump_insn (gen_bge (label_rtx (node->code_label))); } /* We allow the default case to drop through since --- 2910,2920 ---- if (!node_has_high_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_bgt_pat (default_label)); } if (!node_has_low_bound (node)) { ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, 0, 0); ! emit_jump_insn (gen_bge_pat (label_rtx (node->code_label))); } /* We allow the default case to drop through since *************** *** 3793,3796 **** --- 3888,3893 ---- else if (! ((obey_regdecls && ! TREE_REGDECL (parm) && ! TREE_INLINE (fndecl)) + /* layout_decl may set this. */ + || TREE_ADDRESSABLE (parm) /* If -ffloat-store specified, don't put explicit float variables into registers. */ *************** *** 4207,4211 **** and they need to create temporary variables, then you will lose. */ ! fixup_gotos (0, 0, get_insns (), 0); } --- 4304,4308 ---- and they need to create temporary variables, then you will lose. */ ! fixup_gotos (0, 0, 0, get_insns (), 0); } diff -rc2N gcc-1.32/stor-layout.c gcc-1.33/stor-layout.c *** gcc-1.32/stor-layout.c Tue Dec 6 21:36:57 1988 --- gcc-1.33/stor-layout.c Mon Jan 23 17:37:08 1989 *************** *** 282,285 **** --- 282,286 ---- register enum tree_code code = TREE_CODE (decl); int spec_size = DECL_SIZE_UNIT (decl); + int bitsize; if (code == CONST_DECL) *************** *** 329,332 **** --- 330,336 ---- DECL_ALIGN (decl) = TYPE_ALIGN (type); + if (DECL_SIZE (decl)) + bitsize = TREE_INT_CST_LOW (DECL_SIZE (decl)) * DECL_SIZE_UNIT (decl); + /* See if we can use a scalar mode such as QImode or SImode in place of BLKmode or a packed byte mode. */ *************** *** 340,346 **** && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { ! register unsigned packed_size ! = TREE_INT_CST_LOW (DECL_SIZE (decl)) * DECL_SIZE_UNIT (decl); ! register enum machine_mode xmode = agg_mode (packed_size); if (xmode != BLKmode --- 344,348 ---- && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { ! register enum machine_mode xmode = agg_mode (bitsize); if (xmode != BLKmode *************** *** 352,358 **** --- 354,379 ---- DECL_SIZE (decl) = build_int (GET_MODE_SIZE (xmode)); DECL_SIZE_UNIT (decl) = BITS_PER_UNIT; + bitsize = GET_MODE_BITSIZE (xmode); } } + /* Don't let more than one word of an aggregate occupy one register, + since then the SUBREG used to access the high part would malfunction. + Check that the expected # of registers is big enough that they + seem to hold this variable with just a word per register. */ + if (DECL_SIZE (decl) != 0 + && (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == ARRAY_TYPE)) + { + /* This test is not exactly right, since we really want the minimum + number of regs in any class that can hold this mode. + But it does distinguish the machines we need to distinguish, + for now. */ + if (CLASS_MAX_NREGS (ALL_REGS, TYPE_MODE (type)) * BITS_PER_WORD + < bitsize) + TREE_ADDRESSABLE (decl) = 1; + } + /* Evaluate nonconstant size only once, either now or as soon as safe. */ if (DECL_SIZE (decl) != 0 && ! TREE_LITERAL (DECL_SIZE (decl))) *************** *** 754,758 **** TYPE_MODE (type) = BLKmode; if (TYPE_SIZE (type) != 0 ! && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { TYPE_MODE (type) --- 775,782 ---- TYPE_MODE (type) = BLKmode; if (TYPE_SIZE (type) != 0 ! && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST ! /* BLKmode elements force BLKmode aggregate; ! else extract/store fields may lose. */ ! && TYPE_MODE (TREE_TYPE (type)) != BLKmode) { TYPE_MODE (type) *************** *** 766,770 **** layout_record (type); TYPE_MODE (type) = BLKmode; ! if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { tree field; --- 790,803 ---- layout_record (type); TYPE_MODE (type) = BLKmode; ! if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST ! /* If structure's known alignment is less than ! what the scalar mode would need, and it matters, ! then stick with BLKmode. */ ! #ifdef STRICT_ALIGNMENT ! && (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT ! || TYPE_ALIGN (type) >= (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! * TYPE_SIZE_UNIT (type))) ! #endif ! ) { tree field; *************** *** 785,789 **** layout_union (type); TYPE_MODE (type) = BLKmode; ! if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { tree field; --- 818,831 ---- layout_union (type); TYPE_MODE (type) = BLKmode; ! if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST ! /* If structure's known alignment is less than ! what the scalar mode would need, and it matters, ! then stick with BLKmode. */ ! #ifdef STRICT_ALIGNMENT ! && (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT ! || TYPE_ALIGN (type) >= (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! * TYPE_SIZE_UNIT (type))) ! #endif ! ) { tree field; diff -rc2N gcc-1.32/symout.c gcc-1.33/symout.c *** gcc-1.32/symout.c Tue Dec 6 23:03:00 1988 --- gcc-1.33/symout.c Tue Jan 31 03:15:45 1989 *************** *** 31,35 **** /* Get N_SO from stab.h if we can expect the file to exist. */ #ifdef DBX_DEBUGGING_INFO ! #include <stab.h> #endif --- 31,39 ---- /* Get N_SO from stab.h if we can expect the file to exist. */ #ifdef DBX_DEBUGGING_INFO ! #ifdef USG ! #include "stab.h" /* If doing DBX on sysV, use our own stab.h. */ ! #else ! #include <stab.h> /* On BSD, use the system's stab.h. */ ! #endif /* not USG */ #endif *************** *** 764,767 **** --- 768,813 ---- if (buffer.value.value == -1) buffer.class = LOC_CONST; + } + else if (GET_CODE (DECL_RTL (decl)) == MEM + && (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM + || (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG + && REGNO (XEXP (DECL_RTL (decl), 0)) != FRAME_POINTER_REGNUM))) + /* If the value is indirect by memory or by a register + that isn't the frame pointer + then it means the object is variable-sized and address through + that register or stack slot. + If we have a pointer-type (which we should, for an array), + output the variable as a pointer. + Otherwise ignore it, since it is hard to create the ptr + type now and output it, and -gg is being retired. */ + { + tree ptype = TYPE_POINTER_TO (TREE_TYPE (TREE_TYPE (decl))); + if (ptype == 0 + || TYPE_OUTPUT_ADDRESS (ptype) == 0) + continue; + + buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (ptype); + + + if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG) + { + buffer.class = LOC_REGISTER; + buffer.value.value = REGNO (DECL_RTL (decl)); + /* Detect vars that were optimized entirely away. */ + if (buffer.value.value == -1) + buffer.class = LOC_CONST; + } + else + { + register rtx addr = XEXP (DECL_RTL (decl), 0); + if (GET_CODE (addr) != PLUS && GET_CODE (addr) != MINUS) + abort (); + if (GET_CODE (XEXP (addr, 1)) != CONST_INT) + abort (); + buffer.class = LOC_LOCAL; + buffer.value.value = INTVAL (XEXP (addr, 1)); + if (GET_CODE (addr) == MINUS) + buffer.value.value = - buffer.value.value; + } } /* Locals in memory are expected to be addressed as diff -rc2N gcc-1.32/texinfo.tex gcc-1.33/texinfo.tex *** gcc-1.32/texinfo.tex Mon Dec 5 22:01:00 1988 --- gcc-1.33/texinfo.tex Tue Jan 31 00:00:37 1989 *************** *** 1,5 **** %% TeX macros to handle texinfo files ! % Copyright (C) 1985, 1986, 1988 Richard M. Stallman % NO WARRANTY --- 1,5 ---- %% TeX macros to handle texinfo files ! % Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc. % NO WARRANTY *************** *** 102,106 **** %what you give them. Help stamp out software-hoarding! ! \def\texinfoversion{1.18} \message{Loading texinfo package [Version \texinfoversion]:} \message{} --- 102,106 ---- %what you give them. Help stamp out software-hoarding! ! \def\texinfoversion{1.21} \message{Loading texinfo package [Version \texinfoversion]:} \message{} *************** *** 458,470 **** \let\secbf=\secrm ! \font\ssecrm=cmbx10 scaled \magstep1 ! \font\ssecit=cmti10 scaled \magstep1 ! \font\ssecsl=cmsl10 scaled \magstep1 ! \font\ssectt=cmtt10 scaled \magstep1 ! \font\ssecsf=cmss10 scaled \magstep1 \let\ssecbf=\ssecrm \def\textfonts{\let\rm=\tenrm\let\it=\tenit\let\sl=\tensl\let\bf=\tenbf% ! \let\sc=\tensc\let\sf=\tensf} \def\chapfonts{\let\rm=\chaprm\let\it=\chapit\let\sl=\chapsl\let\bf=\chapbf\let\tt=\chaptt\let\sf=\chapsf} \def\secfonts{\let\rm=\secrm\let\it=\secit\let\sl=\secsl\let\bf=\secbf\let\tt=\sectt\let\sf=\secsf} --- 458,477 ---- \let\secbf=\secrm ! % \font\ssecrm=cmbx10 scaled \magstep1 % This size an fontlooked bad. ! % \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded. ! % \font\ssecsl=cmsl10 scaled \magstep1 ! % \font\ssectt=cmtt10 scaled \magstep1 ! % \font\ssecsf=cmss10 scaled \magstep1 ! ! \font\ssecrm=cmb10 at 13pt % Note the use of cmb rather than cmbx. ! \font\ssecit=cmti10 at 13pt % Also, the size is a little larger than ! \font\ssecsl=cmsl10 at 13pt % being scaled magstep1. ! \font\ssectt=cmtt10 at 13pt ! \font\ssecsf=cmss10 at 13pt ! \let\ssecbf=\ssecrm \def\textfonts{\let\rm=\tenrm\let\it=\tenit\let\sl=\tensl\let\bf=\tenbf% ! \let\smallcaps=\tensc\let\sf=\tensf} \def\chapfonts{\let\rm=\chaprm\let\it=\chapit\let\sl=\chapsl\let\bf=\chapbf\let\tt=\chaptt\let\sf=\chapsf} \def\secfonts{\let\rm=\secrm\let\it=\secit\let\sl=\secsl\let\bf=\secbf\let\tt=\sectt\let\sf=\secsf} *************** *** 495,503 **** \let\file=\samp ! \def\l#1{{\li #1}\null} ! \def\r#1{{\rm #1}} ! \def\s#1{{\sc #1}} ! \def\ii#1{{\it #1}} \def\titlefont#1{{\titlerm #1}} --- 502,510 ---- \let\file=\samp ! \def\l#1{{\li #1}\null} % ! \def\r#1{{\rm #1}} % roman font ! \def\sc#1{{\\smallcaps #1}} % smallcaps font ! \def\ii#1{{\it #1}} % italic font \def\titlefont#1{{\titlerm #1}} *************** *** 1194,1201 **** \outer\def\majorheading #1{% {\advance\chapheadingskip by 10pt \chapbreak }% ! {\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 200} \outer\def\chapheading #1{\chapbreak % ! {\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 200} \let\heading=\secheadingi --- 1201,1208 ---- \outer\def\majorheading #1{% {\advance\chapheadingskip by 10pt \chapbreak }% ! {\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200} \outer\def\chapheading #1{\chapbreak % ! {\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200} \let\heading=\secheadingi *************** *** 1243,1247 **** \def\chfplain #1#2{% \pchapsepmacro % ! {\chapfonts \line{\chaprm #2.\enspace #1\hfill}}\bigskip \par\penalty 5000 % } --- 1250,1254 ---- \def\chfplain #1#2{% \pchapsepmacro % ! {\chapfonts \line{\rm #2.\enspace #1\hfill}}\bigskip \par\penalty 5000 % } *************** *** 1248,1252 **** \def\unnchfplain #1{% \pchapsepmacro % ! {\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 10000 % } \CHAPFplain % The default --- 1255,1259 ---- \def\unnchfplain #1{% \pchapsepmacro % ! {\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 % } \CHAPFplain % The default *************** *** 1253,1257 **** \def\unnchfopen #1{% ! \chapoddpage {\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 10000 % } --- 1260,1264 ---- \def\unnchfopen #1{% ! \chapoddpage {\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 % } *************** *** 1273,1276 **** --- 1280,1287 ---- \def\secheadingbreak{\dobreak \secheadingskip {-1000}} + + % Section fonts are the base font at magstep2, which produces + % a size a bit more than 14 points in the default situation. + \def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} \def\plainsecheading #1{\secheadingi {#1}} *************** *** 1277,1293 **** \def\secheadingi #1{{\advance \secheadingskip by \parskip % \secheadingbreak}% ! {\secfonts \line{\secrm #1\hfill}}% \ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } \def\subsecheading #1#2#3#4{{\advance \subsecheadingskip by \parskip % \subsecheadingbreak}% ! {\secfonts \line{\secrm#2.#3.#4\enspace #1\hfill}}% \ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } ! \def\subsubsecfonts{\subsecfonts} % Maybe this should change ! \def\subsubsecheading #1#2#3#4#5{{\advance \subsecheadingskip by \parskip % \subsecheadingbreak}% ! {\secfonts \line{\secrm#2.#3.#4.#5\enspace #1\hfill}}% \ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} --- 1288,1309 ---- \def\secheadingi #1{{\advance \secheadingskip by \parskip % \secheadingbreak}% ! {\secfonts \line{\rm #1\hfill}}% \ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + % Subsection fonts are the base font at magstep1, + % which produces a size of 12 points. + \def\subsecheading #1#2#3#4{{\advance \subsecheadingskip by \parskip % \subsecheadingbreak}% ! {\subsecfonts \line{\rm#2.#3.#4\enspace #1\hfill}}% \ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } ! \def\subsubsecfonts{\subsecfonts} % Maybe this should change: ! % Perhaps make sssec fonts scaled ! % magstep half \def\subsubsecheading #1#2#3#4#5{{\advance \subsecheadingskip by \parskip % \subsecheadingbreak}% ! {\subsubsecfonts \line{\rm#2.#3.#4.#5\enspace #1\hfill}}% \ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} *************** *** 1442,1446 **** \let\par=\lisppar \def\Elisp{\endgroup\afterenvbreak}% ! \parskip=0pt \advance \rightskip by \lispnarrowing \advance \leftskip by \lispnarrowing \parindent=0pt --- 1458,1462 ---- \let\par=\lisppar \def\Elisp{\endgroup\afterenvbreak}% ! \parskip=0pt \advance \leftskip by \lispnarrowing \parindent=0pt *************** *** 1471,1475 **** \let\par=\lisppar \def\Esmalllisp{\endgroup\afterenvbreak}% ! \parskip=0pt \advance \rightskip by \lispnarrowing \advance \leftskip by \lispnarrowing \parindent=0pt --- 1487,1491 ---- \let\par=\lisppar \def\Esmalllisp{\endgroup\afterenvbreak}% ! \parskip=0pt \advance \leftskip by \lispnarrowing \parindent=0pt *************** *** 1490,1494 **** \let\par=\lisppar \def\Edisplay{\endgroup\afterenvbreak}% ! \parskip=0pt \advance \rightskip by \lispnarrowing \advance \leftskip by \lispnarrowing \parindent=0pt --- 1506,1510 ---- \let\par=\lisppar \def\Edisplay{\endgroup\afterenvbreak}% ! \parskip=0pt \advance \leftskip by \lispnarrowing \parindent=0pt diff -rc2N gcc-1.32/tm-3b1.h gcc-1.33/tm-3b1.h *** gcc-1.32/tm-3b1.h Mon Dec 12 13:31:28 1988 --- gcc-1.33/tm-3b1.h Fri Jan 27 03:20:15 1989 *************** *** 28,32 **** #include "tm-hp9k320.h" ! /* See tm-m68k.h. 7 means 680[01]0 with no 68881. */ #undef TARGET_DEFAULT --- 28,32 ---- #include "tm-hp9k320.h" ! /* See tm-m68k.h. 0 means 680[01]0 with no 68881. */ #undef TARGET_DEFAULT *************** *** 346,353 **** `short L%nn-L%nn' supposedly works. */ #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ ! if (RTX_INTEGRATED_P (TABLE)) \ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \ ! XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)) ! else fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \ XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \ --- 346,353 ---- `short L%nn-L%nn' supposedly works. */ #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ ! if (! RTX_INTEGRATED_P (TABLE)) \ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \ ! XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \ ! else \ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \ XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \ diff -rc2N gcc-1.32/tm-alliant.h gcc-1.33/tm-alliant.h *** gcc-1.32/tm-alliant.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-alliant.h Wed Feb 1 20:18:21 1989 *************** *** 0 **** --- 1,1511 ---- + /* Definitions of target machine for GNU compiler. Alliant FX/8 version. + Copyright (C) 1987, 1988 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + + /* Note that some other tm- files include this one and then override + many of the definitions that relate to assembler syntax. */ + + + /* Names to predefine in the preprocessor for this target machine. */ + + /* See tm-sun3.h, tm-sun2.h, tm-isi68.h for different CPP_PREDEFINES. */ + + /* Print subsidiary information on the compiler version in use. */ + #ifdef MOTOROLA + #define TARGET_VERSION printf (" (68k, Motorola syntax)"); + #else + #define TARGET_VERSION printf (" (68k, MIT syntax)"); + #endif + + /* Run-time compilation parameters selecting different hardware subsets. */ + + extern int target_flags; + + /* Macros used in the machine description to test the flags. */ + + /* Compile for a 68020 (not a 68000 or 68010). */ + #define TARGET_68020 (target_flags & 1) + /* Compile 68881 insns for floating point (not library calls). */ + #define TARGET_68881 (target_flags & 2) + /* Compile using 68020 bitfield insns. */ + #define TARGET_BITFIELD (target_flags & 4) + /* Compile using rtd insn calling sequence. + This will not work unless you use prototypes at least + for all functions that can take varying numbers of args. */ + #define TARGET_RTD (target_flags & 8) + /* Compile passing first two args in regs 0 and 1. + This exists only to test compiler features that will + be needed for RISC chips. It is not usable + and is not intended to be usable on this cpu. */ + #define TARGET_REGPARM (target_flags & 020) + /* Compile with 16-bit `int'. */ + #define TARGET_SHORT (target_flags & 040) + + /* Compile with special insns for Sun FPA. */ + #define TARGET_FPA (target_flags & 0100) + + /* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + + #define TARGET_SWITCHES \ + { { "68020", 5}, \ + { "c68020", 5}, \ + { "68881", 2}, \ + { "bitfield", 4}, \ + { "68000", -5}, \ + { "c68000", -5}, \ + { "soft-float", -0102}, \ + { "nobitfield", -4}, \ + { "rtd", 8}, \ + { "nortd", -8}, \ + { "short", 040}, \ + { "noshort", -040}, \ + { "fpa", 0100}, \ + { "nofpa", -0100}, \ + { "", TARGET_DEFAULT}} + + /* TARGET_DEFAULT is defined in tm-sun*.h and tm-isi68.h, etc. */ + + /* Blow away 68881 flag silently on TARGET_FPA (since we can't clear + any bits in TARGET_SWITCHES above) */ + #define OVERRIDE_OPTIONS \ + { \ + if (TARGET_FPA) target_flags &= ~2; \ + } + \f + /* target machine storage layout */ + + /* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. + This is true for 68020 insns such as bfins and bfexts. + We make it true always by avoiding using the single-bit insns + except in special cases with constant bit numbers. */ + #define BITS_BIG_ENDIAN + + /* Define this if most significant byte of a word is the lowest numbered. */ + /* That is true on the 68000. */ + #define BYTES_BIG_ENDIAN + + /* Define this if most significant word of a multiword number is numbered. */ + /* For 68000 we can decide arbitrarily + since there are no machine instructions for them. */ + /* #define WORDS_BIG_ENDIAN */ + + /* number of bits in an addressible storage unit */ + #define BITS_PER_UNIT 8 + + /* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ + #define BITS_PER_WORD 32 + + /* Width of a word, in units (bytes). */ + #define UNITS_PER_WORD 4 + + /* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ + #define POINTER_SIZE 32 + + /* Allocation boundary (in *bits*) for storing pointers in memory. */ + #define POINTER_BOUNDARY 16 + + /* Allocation boundary (in *bits*) for storing arguments in argument list. */ + #define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32) + + /* Boundary (in *bits*) on which stack pointer should be aligned. */ + #define STACK_BOUNDARY 16 + + /* Allocation boundary (in *bits*) for the code of a function. */ + #define FUNCTION_BOUNDARY 16 + + /* Alignment of field after `int : 0' in a structure. */ + #define EMPTY_FIELD_BOUNDARY 16 + + /* No data type wants to be aligned rounder than this. */ + #define BIGGEST_ALIGNMENT 16 + + /* Define this if move instructions will actually fail to work + when given unaligned data. */ + #define STRICT_ALIGNMENT + + /* Define number of bits in most basic integer type. + (If undefined, default is BITS_PER_WORD). */ + + #define INT_TYPE_SIZE (TARGET_SHORT ? 16 : 32) + \f + /* Standard register usage. */ + + /* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. + For the 68000, we give the data registers numbers 0-7, + the address registers numbers 010-017, + and the 68881 floating point registers numbers 020-027. */ + #define FIRST_PSEUDO_REGISTER 56 + + /* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + On the 68000, only the stack pointer is such. */ + /* fpa0 is also reserved so that it can be used to move shit back and + forth between high fpa regs and everything else. */ + #define FIXED_REGISTERS \ + {0, 0, 0, 0, 0, 0, 0, 0, \ + 1, 0, 0, 0, 0, 0, 1, 1, \ + 0, 0, 0, 0, 0, 0, 0, 0 } + + /* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. */ + + #define CALL_USED_REGISTERS \ + {1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1 } + + /* Make sure everything's fine if we *don't* have a given processor. + This assumes that putting a register in fixed_regs will keep the + compilers mitt's completely off it. We don't bother to zero it out + of register classes. If neither TARGET_FPA or TARGET_68881 is set, + the compiler won't touch since no instructions that use these + registers will be valid. */ + #define CONDITIONAL_REGISTER_USAGE \ + { \ + int i; \ + HARD_REG_SET x; \ + if (!TARGET_FPA) \ + { \ + COPY_HARD_REG_SET (x, reg_class_contents[(int)FPA_REGS]); \ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \ + if (TEST_HARD_REG_BIT (x, i)) \ + fixed_regs[i] = call_used_regs[i] = 1; \ + } \ + } + + /* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. + + On the 68000, ordinary registers hold 32 bits worth; + for the 68881 registers, a single register is always enough for + anything that can be stored in them at all. */ + #define HARD_REGNO_NREGS(REGNO, MODE) \ + ((REGNO) >= 16 ? 1 \ + : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + + /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. + On the 68000, the cpu registers can hold any mode but the 68881 registers + can hold only SFmode or DFmode. And the 68881 registers can't hold anything + if 68881 use is disabled. However, the Sun FPA register can + (apparently) hold whatever you feel like putting in them. */ + #define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((REGNO) < 16 \ + || ((REGNO) < 24 \ + ? TARGET_68881 && ((MODE) == SFmode || (MODE) == DFmode) \ + : ((REGNO) < 56 \ + ? TARGET_FPA : 0))) + + /* Value is 1 if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ + #define MODES_TIEABLE_P(MODE1, MODE2) \ + (! TARGET_68881 \ + || (((MODE1) == SFmode || (MODE1) == DFmode) \ + == ((MODE2) == SFmode || (MODE2) == DFmode))) + + /* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + + /* m68000 pc isn't overloaded on a register. */ + /* #define PC_REGNUM */ + + /* Register to use for pushing function arguments. */ + #define STACK_POINTER_REGNUM 15 + + /* Base register for access to local variables of the function. */ + #define FRAME_POINTER_REGNUM 14 + + /* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms + may be accessed via the stack pointer) in functions that seem suitable. + This is computed in `reload', in reload1.c. */ + #define FRAME_POINTER_REQUIRED 1 + + /* Base register for access to arguments of the function. */ + #define ARG_POINTER_REGNUM 8 + + /* Register in which static-chain is passed to a function. */ + #define STATIC_CHAIN_REGNUM 8 + + /* Register in which address to store a structure value + is passed to a function. */ + #define STRUCT_VALUE_REGNUM 9 + \f + /* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + + /* The 68000 has three kinds of registers, so eight classes would be + a complete set. One of them is not needed. */ + + /* + * Notes on final choices: + * + * 1) Didn't feel any need to union-ize LOW_FPA_REGS with anything + * else. + * 2) Removed all unions that involve address registers with + * floating point registers (left in unions of address and data with + * floating point). + * 3) Defined GENERAL_REGS as ADDR_OR_DATA_REGS. + * 4) Defined ALL_REGS as FPA_OR_FP_OR_GENERAL_REGS. + * 4) Left in everything else. + */ + enum reg_class { NO_REGS, LO_FPA_REGS, FPA_REGS, FP_REGS, + FP_OR_FPA_REGS, DATA_REGS, DATA_OR_FPA_REGS, DATA_OR_FP_REGS, + DATA_OR_FP_OR_FPA_REGS, ADDR_REGS, GENERAL_REGS, + GENERAL_OR_FPA_REGS, GENERAL_OR_FP_REGS, ALL_REGS, + LIM_REG_CLASSES }; + + #define N_REG_CLASSES (int) LIM_REG_CLASSES + + /* Give names of register classes as strings for dump file. */ + + #define REG_CLASS_NAMES \ + { "NO_REGS", "LO_FPA_REGS", "FPA_REGS", "FP_REGS", \ + "FP_OR_FPA_REGS", "DATA_REGS", "DATA_OR_FPA_REGS", "DATA_OR_FP_REGS", \ + "DATA_OR_FP_OR_FPA_REGS", "ADDR_REGS", "GENERAL_REGS", \ + "GENERAL_OR_FPA_REGS", "GENERAL_OR_FP_REGS", "ALL_REGS" } + + /* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + + #define REG_CLASS_CONTENTS \ + { \ + {0, 0}, /* NO_REGS */ \ + {0xff000000, 0x000000ff}, /* LO_FPA_REGS */ \ + {0xff000000, 0x00ffffff}, /* FPA_REGS */ \ + {0x00ff0000, 0x00000000}, /* FP_REGS */ \ + {0xffff0000, 0x00ffffff}, /* FP_OR_FPA_REGS */ \ + {0x000000ff, 0x00000000}, /* DATA_REGS */ \ + {0xff0000ff, 0x00ffffff}, /* DATA_OR_FPA_REGS */ \ + {0x00ff00ff, 0x00000000}, /* DATA_OR_FP_REGS */ \ + {0xffff00ff, 0x00ffffff}, /* DATA_OR_FP_OR_FPA_REGS */\ + {0x0000ff00, 0x00000000}, /* ADDR_REGS */ \ + {0x0000ffff, 0x00000000}, /* GENERAL_REGS */ \ + {0xff00ffff, 0x00ffffff}, /* GENERAL_OR_FPA_REGS */\ + {0x00ffffff, 0x00000000}, /* GENERAL_OR_FP_REGS */\ + {0xffffffff, 0x00ffffff} /* ALL_REGS */ \ + } + + /* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + + extern enum reg_class regno_reg_class[]; + #define REGNO_REG_CLASS(REGNO) (regno_reg_class[(REGNO)>>3]) + + /* The class value for index registers, and the one for base regs. */ + + #define INDEX_REG_CLASS GENERAL_REGS + #define BASE_REG_CLASS ADDR_REGS + + /* Get reg_class from a letter such as appears in the machine description. + We do a trick here to modify the effective constraints on the + machine description; we zorch the constraint letters that aren't + appropriate for a specific target. This allows us to guarrantee + that a specific kind of register will not be used for a given taget + without fiddling with the register classes above. */ + + #define REG_CLASS_FROM_LETTER(C) \ + ((C) == 'a' ? ADDR_REGS : \ + ((C) == 'd' ? DATA_REGS : \ + ((C) == 'f' ? (TARGET_68881 ? FP_REGS : \ + NO_REGS) : \ + ((C) == 'x' ? (TARGET_FPA ? FPA_REGS : \ + NO_REGS) : \ + ((C) == 'y' ? (TARGET_FPA ? LO_FPA_REGS : \ + NO_REGS) : \ + NO_REGS))))) + + /* The letters I, J, K, L and M in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. + + For the 68000, `I' is used for the range 1 to 8 + allowed as immediate shift counts and in addq. + `J' is used for the range of signed numbers that fit in 16 bits. + `K' is for numbers that moveq can't handle. + `L' is for range -8 to -1, range of values that can be added with subq. */ + + #define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? (VALUE) > 0 && (VALUE) <= 8 : \ + (C) == 'J' ? (VALUE) >= -0x8000 && (VALUE) <= 0x7FFF : \ + (C) == 'K' ? (VALUE) < -0x80 || (VALUE) >= 0x80 : \ + (C) == 'L' ? (VALUE) < 0 && (VALUE) >= -8 : 0) + + /* + * A small bit of explanation: + * "G" defines all of the floating constants that are *NOT* 68881 + * constants. this is so 68881 constants get reloaded and the + * fpmovecr is used. "H" defines *only* the class of constants that + * the fpa can use, because these can be gotten at in any fpa + * instruction and there is no need to force reloads. + */ + + #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 + + /* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. + On the 68000 series, use a data reg if possible when the + value is a constant in the range where moveq could be used + and we ensure that QImodes are reloaded into data regs. */ + + #define PREFERRED_RELOAD_CLASS(X,CLASS) \ + ((GET_CODE (X) == CONST_INT \ + && (unsigned) (INTVAL (X) + 0x80) < 0x100 \ + && (CLASS) != ADDR_REGS) \ + ? DATA_REGS \ + : GET_MODE (X) == QImode \ + ? DATA_REGS \ + : (CLASS)) + + /* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ + /* On the 68000, this is the size of MODE in words, + except in the FP regs, where a single reg is always enough. */ + #define CLASS_MAX_NREGS(CLASS, MODE) \ + ((CLASS) == FP_REGS || (CLASS) == FPA_REGS || (CLASS) == LO_FPA_REGS ? 1 \ + : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + \f + /* Stack layout; function entry, exit and calling. */ + + /* Define this if pushing a word on the stack + makes the stack pointer a smaller address. */ + #define STACK_GROWS_DOWNWARD + + /* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ + #define FRAME_GROWS_DOWNWARD + + /* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ + #define STARTING_FRAME_OFFSET -4 + + /* If we generate an insn to push BYTES bytes, + this says how many the stack pointer really advances by. + On the 68000, sp@- in a byte insn really pushes a word. */ + #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1) + + /* Offset of first parameter from the argument pointer register value. */ + #define FIRST_PARM_OFFSET(FNDECL) 0 + + /* Value is 1 if returning from a function call automatically + pops the arguments described by the number-of-args field in the call. + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + + On the 68000, the RTS insn cannot pop anything. + On the 68010, the RTD insn may be used to pop them if the number + of args is fixed, but if the number is variable then the caller + must pop them all. RTD can't be used for library calls now + because the library is compiled with the Unix compiler. + Use of RTD is a selectable option, since it is incompatible with + standard Unix calling sequences. If the option is not selected, + the caller must always pop the args. */ + + #define RETURN_POPS_ARGS(FUNTYPE) \ + (TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \ + && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ + || TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) == void_type_node)) + + /* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + + /* On the 68000 the return value is in D0 regardless. */ + + #define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), 0) + + /* Define how to find the value returned by a library function + assuming the value has mode MODE. */ + + /* On the 68000 the return value is in D0 regardless. */ + + #define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + + /* 1 if N is a possible register number for a function value. + On the 68000, d0 is the only register thus used. */ + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + + /* 1 if N is a possible register number for function argument passing. + On the 68000, no registers are used in this way. */ + + #define FUNCTION_ARG_REGNO_P(N) 0 + \f + /* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. + + On the m68k, this is a single integer, which is a number of bytes + of arguments scanned so far. */ + + #define CUMULATIVE_ARGS int + + /* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. + + On the m68k, the offset starts at 0. */ + + #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \ + ((CUM) = 0) + + /* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + + #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM) += ((MODE) != BLKmode \ + ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ + : (int_size_in_bytes (TYPE) + 3) & ~3)) + + /* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + + /* On the 68000 all args are pushed, except if -mregparm is specified + then the first two words of arguments are passed in d0, d1. + *NOTE* -mregparm does not work. + It exists only to test register calling conventions. */ + + #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ + ((TARGET_REGPARM && (CUM) < 8) ? gen_rtx(REG, (MODE), (CUM)/4) : 0) + + /* For an arg passed partly in registers and partly in memory, + this is the number of registers used. + For args passed entirely in registers or entirely in memory, zero. */ + + #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ + ((TARGET_REGPARM && (CUM) < 8 \ + && 8 < ((CUM) + ((MODE) == BLKmode \ + ? int_size_in_bytes (TYPE) \ + : GET_MODE_SIZE (MODE)))) \ + ? 2 - (CUM) / 4 : 0) + + /* This macro generates the assembly code for function entry. + FILE is a stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. */ + + /* Note that the order of the bit mask for fmovem is the opposite + of the order for movem! */ + + #define FUNCTION_PROLOGUE(FILE, SIZE) \ + { int fsize = ((SIZE) + 3) & -4; \ + if (frame_pointer_needed) { \ + if (TARGET_68020 || fsize < 0x8000) \ + fprintf(FILE,"\tlink a6,#%d\n", -fsize); \ + else \ + fprintf(FILE,"\tlink a6,#0\n\tsubl #%d,sp\n", fsize); } \ + fprintf(FILE, "\tmovl a0,a6@(-4)\n" ); } + + /* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + + #define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "\tlea LP%d,a0\n\tjsr mcount\n", (LABELNO)) + + /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ + + #define EXIT_IGNORE_STACK 1 + + /* This macro generates the assembly code for function exit, + on machines that need it. If FUNCTION_EPILOGUE is not defined + then individual return instructions are generated for each + return statement. Args are same as for FUNCTION_PROLOGUE. + + The function epilogue should not depend on the current stack pointer! + It should use the frame pointer only. This is mandatory because + of alloca; we also take advantage of it to omit stack adjustments + before returning. */ + + #define FUNCTION_EPILOGUE(FILE, SIZE) \ + { extern int current_function_pops_args; \ + extern int current_function_args_size; \ + if (frame_pointer_needed) \ + fprintf (FILE, "\tunlk a6\n"); \ + if (current_function_pops_args && current_function_args_size) \ + fprintf (FILE, "\trtd #%d\n", current_function_args_size); \ + else fprintf (FILE, "\trts\n"); } + + /* If the memory address ADDR is relative to the frame pointer, + correct it to be relative to the stack pointer instead. + This is for when we don't use a frame pointer. + ADDR should be a variable name. */ + + #define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \ + { int offset = -1; \ + rtx regs = stack_pointer_rtx; \ + if (ADDR == frame_pointer_rtx) \ + offset = 0; \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \ + && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \ + offset = INTVAL (XEXP (ADDR, 1)); \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \ + { rtx other_reg = XEXP (ADDR, 1); \ + offset = 0; \ + regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \ + { rtx other_reg = XEXP (ADDR, 0); \ + offset = 0; \ + regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ + else if (GET_CODE (ADDR) == PLUS \ + && GET_CODE (XEXP (ADDR, 0)) == PLUS \ + && XEXP (XEXP (ADDR, 0), 0) == frame_pointer_rtx \ + && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \ + { rtx other_reg = XEXP (XEXP (ADDR, 0), 1); \ + offset = INTVAL (XEXP (ADDR, 1)); \ + regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ + else if (GET_CODE (ADDR) == PLUS \ + && GET_CODE (XEXP (ADDR, 0)) == PLUS \ + && XEXP (XEXP (ADDR, 0), 1) == frame_pointer_rtx \ + && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \ + { rtx other_reg = XEXP (XEXP (ADDR, 0), 0); \ + offset = INTVAL (XEXP (ADDR, 1)); \ + regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ + if (offset >= 0) \ + { int regno; \ + extern char call_used_regs[]; \ + for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \ + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ + offset += 12; \ + for (regno = 0; regno < 16; regno++) \ + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ + offset += 4; \ + offset -= 4; \ + ADDR = plus_constant (regs, offset + (DEPTH)); } } \ + \f + /* Addressing modes, and classification of registers for them. */ + + #define HAVE_POST_INCREMENT + /* #define HAVE_POST_DECREMENT */ + + #define HAVE_PRE_DECREMENT + /* #define HAVE_PRE_INCREMENT */ + + /* Macros to check register numbers against specific register classes. */ + + /* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ + + #define REGNO_OK_FOR_INDEX_P(REGNO) \ + ((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16) + #define REGNO_OK_FOR_BASE_P(REGNO) \ + (((REGNO) ^ 010) < 8 || (unsigned) (reg_renumber[REGNO] ^ 010) < 8) + #define REGNO_OK_FOR_DATA_P(REGNO) \ + ((REGNO) < 8 || (unsigned) reg_renumber[REGNO] < 8) + #define REGNO_OK_FOR_FP_P(REGNO) \ + (((REGNO) ^ 020) < 8 || (unsigned) (reg_renumber[REGNO] ^ 020) < 8) + + #define REGNO_OK_FOR_FPA_P(REGNO) 0 + + /* Now macros that check whether X is a register and also, + strictly, whether it is in a specified class. + + These macros are specific to the 68000, and may be used only + in code for printing assembler insns and in conditions for + define_optimization. */ + + /* 1 if X is a data register. */ + + #define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X))) + + /* 1 if X is an fp register. */ + + #define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X))) + + /* 1 if X is an address register */ + + #define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) + + /* 1 if X is a register in the Sun FPA. */ + #define FPA_REG_P(X) 0 + \f + /* Maximum number of registers that can appear in a valid memory address. */ + + #define MAX_REGS_PER_ADDRESS 2 + + /* Recognize any constant value that is a valid address. */ + + #define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) + + /* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + + #define LEGITIMATE_CONSTANT_P(X) 1 + + /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + + #ifndef REG_OK_STRICT + + /* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ + #define REG_OK_FOR_INDEX_P(X) ((REGNO (X) ^ 020) >= 8) + /* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ + #define REG_OK_FOR_BASE_P(X) ((REGNO (X) & ~027) != 0) + + #else + + /* Nonzero if X is a hard reg that can be used as an index. */ + #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) + /* Nonzero if X is a hard reg that can be used as a base reg. */ + #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) + + #endif + \f + /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */ + + #define INDIRECTABLE_1_ADDRESS_P(X) \ + (CONSTANT_ADDRESS_P (X) \ + || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ + || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ + && REG_P (XEXP (X, 0)) \ + && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ + || (GET_CODE (X) == PLUS \ + && REG_P (XEXP (X, 0)) && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ + && GET_CODE (XEXP (X, 1)) == CONST_INT \ + && ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000)) + + #define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ + { if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; } + + #define GO_IF_INDEXABLE_BASE(X, ADDR) \ + { if (GET_CODE (X) == LABEL_REF) goto ADDR; \ + if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; } + + #define GO_IF_INDEXING(X, ADDR) \ + { if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \ + { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \ + if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \ + { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } } + + #define GO_IF_INDEXED_ADDRESS(X, ADDR) \ + { GO_IF_INDEXING (X, ADDR); \ + if (GET_CODE (X) == PLUS) \ + { if (GET_CODE (XEXP (X, 1)) == CONST_INT \ + && (unsigned) INTVAL (XEXP (X, 1)) + 0x80 < 0x100) \ + { rtx go_temp = XEXP (X, 0); GO_IF_INDEXING (go_temp, ADDR); } \ + if (GET_CODE (XEXP (X, 0)) == CONST_INT \ + && (unsigned) INTVAL (XEXP (X, 0)) + 0x80 < 0x100) \ + { rtx go_temp = XEXP (X, 1); GO_IF_INDEXING (go_temp, ADDR); } } } + + #define LEGITIMATE_INDEX_REG_P(X) \ + ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ + || (GET_CODE (X) == SIGN_EXTEND \ + && GET_CODE (XEXP (X, 0)) == REG \ + && GET_MODE (XEXP (X, 0)) == HImode \ + && REG_OK_FOR_INDEX_P (XEXP (X, 0)))) + + #define LEGITIMATE_INDEX_P(X) \ + (LEGITIMATE_INDEX_REG_P (X) \ + || (TARGET_68020 && GET_CODE (X) == MULT \ + && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \ + && GET_CODE (XEXP (X, 1)) == CONST_INT \ + && (INTVAL (XEXP (X, 1)) == 2 \ + || INTVAL (XEXP (X, 1)) == 4 \ + || INTVAL (XEXP (X, 1)) == 8))) + + #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ + { GO_IF_NONINDEXED_ADDRESS (X, ADDR); \ + GO_IF_INDEXED_ADDRESS (X, ADDR); } + \f + /* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. + + For the 68000, we handle X+REG by loading X into a register R and + using R+REG. R will go in an address reg and indexing will be used. + However, if REG is a broken-out memory address or multiplication, + nothing needs to be done because REG can certainly go in an address reg. */ + + #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ + { register int ch = (X) != (OLDX); \ + if (GET_CODE (X) == PLUS) \ + { if (GET_CODE (XEXP (X, 0)) == MULT) \ + ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \ + if (GET_CODE (XEXP (X, 1)) == MULT) \ + ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \ + if (ch && GET_CODE (XEXP (X, 1)) == REG \ + && GET_CODE (XEXP (X, 0)) == REG) \ + return X; \ + if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \ + if (GET_CODE (XEXP (X, 0)) == REG \ + || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \ + && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \ + { register rtx temp = gen_reg_rtx (Pmode); \ + register rtx val = force_operand (XEXP (X, 1), 0); \ + emit_move_insn (temp, val); \ + XEXP (X, 1) = temp; \ + return X; } \ + else if (GET_CODE (XEXP (X, 1)) == REG \ + || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \ + && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \ + && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \ + { register rtx temp = gen_reg_rtx (Pmode); \ + register rtx val = force_operand (XEXP (X, 0), 0); \ + emit_move_insn (temp, val); \ + XEXP (X, 0) = temp; \ + return X; }}} + + /* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. + On the 68000, only predecrement and postincrement address depend thus + (the amount of decrement or increment being the length of the operand). */ + + #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ + if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) goto LABEL + \f + /* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ + #define CASE_VECTOR_MODE HImode + + /* Define this if the tablejump instruction expects the table + to contain offsets from the address of the table. + Do not define this if the table should contain absolute addresses. */ + #define CASE_VECTOR_PC_RELATIVE + + /* Specify the tree operation to be used to convert reals to integers. */ + #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + + /* This is the kind of divide that is easiest to do in the general case. */ + #define EASY_DIV_EXPR TRUNC_DIV_EXPR + + /* Define this as 1 if `char' should by default be signed; else as 0. */ + #define DEFAULT_SIGNED_CHAR 1 + + /* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ + #define MOVE_MAX 4 + + /* Define this if zero-extension is slow (more than one real instruction). */ + #define SLOW_ZERO_EXTEND + + /* Nonzero if access to memory by bytes is slow and undesirable. */ + #define SLOW_BYTE_ACCESS 0 + + /* Define if shifts truncate the shift count + which implies one can omit a sign-extension or zero-extension + of a shift count. */ + #define SHIFT_COUNT_TRUNCATED + + /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ + #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + + /* We assume that the store-condition-codes instructions store 0 for false + and some other value for true. This is the value stored for true. */ + + #define STORE_FLAG_VALUE -1 + + /* When a prototype says `char' or `short', really pass an `int'. */ + #define PROMOTE_PROTOTYPES + + /* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ + #define Pmode SImode + + /* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ + #define FUNCTION_MODE QImode + + /* Compute the cost of computing a constant rtl expression RTX + whose rtx-code is CODE. The body of this macro is a portion + of a switch statement. If the code is computed here, + return it with a return statement. Otherwise, break from the switch. */ + + #define CONST_COSTS(RTX,CODE) \ + case CONST_INT: \ + /* Constant zero is super cheap due to clr instruction. */ \ + if (RTX == const0_rtx) return 0; \ + if ((unsigned) INTVAL (RTX) < 077) return 1; \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 3; \ + case CONST_DOUBLE: \ + return 5; + \f + /* Tell final.c how to eliminate redundant test instructions. */ + + /* Here we define machine-dependent flags and fields in cc_status + (see `conditions.h'). */ + + /* On the Alliant, floating-point instructions do not modify the + ordinary CC register. Only fcmp and ftest instructions modify the + floating-point CC register. We should actually keep track of what + both kinds of CC registers contain, but for now we only consider + the most recent instruction that has set either register. */ + + /* Set if the cc value came from a floating point test, so a floating + point conditional branch must be output. */ + #define CC_IN_68881 04000 + + /* Store in cc_status the expressions + that the condition codes will describe + after execution of an instruction whose pattern is EXP. + Do not alter them if the instruction would not alter the cc's. */ + + /* On the 68000, all the insns to store in an address register + fail to set the cc's. However, in some cases these instructions + can make it possibly invalid to use the saved cc's. In those + cases we clear out some or all of the saved cc's so they won't be used. */ + + #define NOTICE_UPDATE_CC(EXP, INSN) \ + { \ + if (GET_CODE (EXP) == SET) \ + { if (ADDRESS_REG_P (XEXP (EXP, 0))) \ + { if (cc_status.value1 \ + && reg_overlap_mentioned_p (XEXP (EXP, 0), cc_status.value1)) \ + cc_status.value1 = 0; \ + if (cc_status.value2 \ + && reg_overlap_mentioned_p (XEXP (EXP, 0), cc_status.value2)) \ + cc_status.value2 = 0; } \ + else if (FP_REG_P (XEXP (EXP,0)) \ + || (FP_REG_P (XEXP (EXP,1)) \ + && XEXP (EXP, 0) != cc0_rtx)) \ + { } \ + else if (!FP_REG_P (XEXP (EXP, 0)) \ + && XEXP (EXP, 0) != cc0_rtx \ + && (FP_REG_P (XEXP (EXP, 1)) \ + || GET_CODE (XEXP (EXP, 1)) == FIX \ + || GET_CODE (XEXP (EXP, 1)) == FLOAT_TRUNCATE \ + || GET_CODE (XEXP (EXP, 1)) == FLOAT_EXTEND)) \ + { CC_STATUS_INIT; } \ + else if (GET_CODE (SET_SRC (EXP)) == CALL) \ + { CC_STATUS_INIT; } \ + else if (XEXP (EXP, 0) != pc_rtx) \ + { cc_status.flags = 0; \ + cc_status.value1 = XEXP (EXP, 0); \ + cc_status.value2 = XEXP (EXP, 1); } } \ + else if (GET_CODE (EXP) == PARALLEL \ + && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \ + { \ + if (ADDRESS_REG_P (XEXP (XVECEXP (EXP, 0, 0), 0))) \ + CC_STATUS_INIT; \ + else if (XEXP (XVECEXP (EXP, 0, 0), 0) != pc_rtx) \ + { cc_status.flags = 0; \ + cc_status.value1 = XEXP (XVECEXP (EXP, 0, 0), 0); \ + cc_status.value2 = XEXP (XVECEXP (EXP, 0, 0), 1); } } \ + else CC_STATUS_INIT; \ + if (cc_status.value2 != 0 \ + && ADDRESS_REG_P (cc_status.value2) \ + && GET_MODE (cc_status.value2) == QImode) \ + CC_STATUS_INIT; \ + if (cc_status.value2 != 0 \ + && !(cc_status.value1 && FPA_REG_P (cc_status.value1))) \ + switch (GET_CODE (cc_status.value2)) \ + { case PLUS: case MINUS: case MULT: case UMULT: \ + case DIV: case UDIV: case MOD: case UMOD: case NEG: \ + case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT: \ + case ROTATE: case ROTATERT: \ + if (GET_MODE (cc_status.value2) != VOIDmode) \ + cc_status.flags |= CC_NO_OVERFLOW; \ + break; \ + case ZERO_EXTEND: \ + /* (SET r1 (ZERO_EXTEND r2)) on this machine + ends with a move insn moving r2 in r2's mode. + Thus, the cc's are set for r2. + This can set N bit spuriously. */ \ + cc_status.flags |= CC_NOT_NEGATIVE; } \ + if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \ + && cc_status.value2 \ + && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \ + cc_status.value2 = 0; \ + if ((cc_status.value1 && FP_REG_P (cc_status.value1)) \ + || (cc_status.value2 && FP_REG_P (cc_status.value2))) \ + cc_status.flags = CC_IN_68881; } + + #define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ + { if (cc_prev_status.flags & CC_IN_68881) \ + return FLOAT; \ + if (cc_prev_status.flags & CC_NO_OVERFLOW) \ + return NO_OV; \ + return NORMAL; } + \f + /* Control the assembler format that we output. */ + + /* Output at beginning of assembler file. */ + + #define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n"); + + /* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ + + #define ASM_APP_ON "#APP\n" + + /* Output to assembler file text saying following lines + no longer contain unusual constructs. */ + + #define ASM_APP_OFF "#NO_APP\n" + + /* Output before read-only data. */ + + #define TEXT_SECTION_ASM_OP "\t.text" + + /* Output before writable data. */ + + #define DATA_SECTION_ASM_OP "\t.data" + + /* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ + + #define REGISTER_NAMES \ + {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \ + "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7" } + + /* How to renumber registers for dbx and gdb. + On the Sun-3, the floating point registers have numbers + 18 to 25, not 16 to 23 as they do in the compiler. */ + + #define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2) + + /* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ + + #define ASM_OUTPUT_LABEL(FILE,NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + + /* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ + + #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + do { fputs ("\t.globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + + /* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. */ + + #define ASM_OUTPUT_LABELREF(FILE,NAME) \ + fprintf (FILE, "_%s", NAME) + + /* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + + #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, "%s%d:\n", PREFIX, NUM) + + /* This is how to store into the string LABEL + the symbol_ref name of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. + This is suitable for output with `assemble_name'. */ + + #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*%s%d", PREFIX, NUM) + + /* This is how to output an assembler line defining a `double' constant. */ + + #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + do { union { double d; long v[2];} tem; \ + tem.d = (VALUE); \ + fprintf (FILE, "\t.long 0x%x,0x%x\n", tem.v[0], tem.v[1]); \ + } while (0) + + /* This is how to output an assembler line defining a `float' constant. */ + + #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + do { union { float f; long l;} tem; \ + tem.f = (VALUE); \ + fprintf (FILE, "\t.long 0x%x\n", tem.l); \ + } while (0) + + /* This is how to output an assembler line defining an `int' constant. */ + + #define ASM_OUTPUT_INT(FILE,VALUE) \ + ( fprintf (FILE, "\t.long "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + /* Likewise for `char' and `short' constants. */ + + #define ASM_OUTPUT_SHORT(FILE,VALUE) \ + ( fprintf (FILE, "\t.word "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + #define ASM_OUTPUT_CHAR(FILE,VALUE) \ + ( fprintf (FILE, "\t.byte "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + #define ASM_OUTPUT_ASCII(FILE,PTR,SIZE) \ + { int i; unsigned char *pp = (unsigned char *) PTR; \ + fprintf(FILE, "\t.byte %d", (unsigned int)*pp++); \ + for (i = 1; i < SIZE; ++i, ++pp) { \ + if ((i % 8) == 0) \ + fprintf(FILE, "\n\t.byte %d", (unsigned int) *pp); \ + else \ + fprintf(FILE, ",%d", (unsigned int) *pp); } \ + fprintf (FILE, "\n"); } + + /* This is how to output an assembler line for a numeric constant byte. */ + + #define ASM_OUTPUT_BYTE(FILE,VALUE) \ + fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) + + /* This is how to output an insn to push a register on the stack. + It need not be very fast code. */ + + #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ + fprintf (FILE, "\tmovl %s,sp@-\n", reg_names[REGNO]) + + /* This is how to output an insn to pop a register from the stack. + It need not be very fast code. */ + + #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ + fprintf (FILE, "\tmovl sp@+,%s\n", reg_names[REGNO]) + + /* This is how to output an element of a case-vector that is absolute. + (The 68000 does not use such vectors, + but we must define this macro anyway.) */ + + #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\t.long L%d\n", VALUE) + + /* This is how to output an element of a case-vector that is relative. */ + + #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL) + + /* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + + #define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG) == 1) \ + fprintf (FILE, "\t.even\n"); \ + else if ((LOG) != 0) \ + fprintf (FILE, "\t.align %dn", (LOG)); + + #define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t. = . + %d\n", (SIZE)) + + /* This says how to output an assembler line + to define a global common symbol. */ + + #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ + ( fputs ("\t.comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d\n", (ROUNDED))) + + /* This says how to output an assembler line + to define a local common symbol. */ + + #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ + ( fputs ("\t.lcomm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d\n", (ROUNDED))) + + /* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + + #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ + ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) + + /* Define the parentheses used to group arithmetic operations + in assembler code. */ + + #define ASM_OPEN_PAREN "(" + #define ASM_CLOSE_PAREN ")" + + /* Define results of standard character escape sequences. */ + #define TARGET_BELL 007 + #define TARGET_BS 010 + #define TARGET_TAB 011 + #define TARGET_NEWLINE 012 + #define TARGET_VT 013 + #define TARGET_FF 014 + #define TARGET_CR 015 + + /* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. + + On the 68000, we use several CODE characters: + 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) + 'b' for byte insn (no effect, on the Sun; this is for the ISI). + '.' for dot needed in Motorola-style opcode names. + '-' for an operand pushing on the stack: + sp@-, -(sp) or -(%sp) depending on the style of syntax. + '+' for an operand pushing on the stack: + sp@+, (sp)+ or (%sp)+ depending on the style of syntax. + 's' for a reference to the top word on the stack: + sp@, (sp) or (%sp) depending on the style of syntax. + '#' for an immediate operand prefix (# in MIT and Motorola syntax + but & in SGS syntax). + '!' for the cc register (used in an `and to cc' insn). + + 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather + than directly). Second part of 'y' below. + 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), + or print pair of registers as rx:ry. + 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs + CONST_DOUBLE's as SunFPA constant RAM registers if + possible, so it should not be used except for the SunFPA. */ + + #define PRINT_OPERAND(FILE, X, CODE) \ + { int i; \ + if (CODE == '.') ; \ + else if (CODE == '#') fprintf (FILE, "#"); \ + else if (CODE == '-') fprintf (FILE, "sp@-"); \ + else if (CODE == '+') fprintf (FILE, "sp@+"); \ + else if (CODE == 's') fprintf (FILE, "sp@"); \ + else if (CODE == '!') fprintf (FILE, "cc"); \ + else if ((X) == 0 ) ; \ + else if (GET_CODE (X) == REG) \ + { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \ + fprintf (FILE, "%s,%s", reg_name [REGNO (X)], reg_name [REGNO (X)+1]); \ + else \ + fprintf (FILE, "%s", reg_name[REGNO (X)]); \ + } \ + else if (GET_CODE (X) == MEM) \ + output_address (XEXP (X, 0)); \ + else if ((CODE == 'y' || CODE == 'w') \ + && GET_CODE(X) == CONST_DOUBLE \ + && (i = standard_SunFPA_constant_p (X))) \ + fprintf(FILE, "%%%d", i & 0x1ff); \ + else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ + { union { double d; int i[2]; } u; \ + union { float f; int i; } u1; \ + u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ + u1.f = u.d; \ + if (CODE == 'f') \ + fprintf (FILE, "#0r%.9g", u1.f); \ + else \ + fprintf (FILE, "#0x%x", u1.i[0]); } \ + else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ + { union { double d; int i[2]; } u; \ + u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ + fprintf (FILE, "#0r%.20g", u.d); } \ + else { putc ('#', FILE); output_addr_const (FILE, X); }} + \f + /* Note that this contains a kludge that knows that the only reason + we have an address (plus (label_ref...) (reg...)) + is in the insn before a tablejump, and we know that m68k.md + generates a label LInnn: on such an insn. */ + #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ + { register rtx reg1, reg2, breg, ireg; \ + register rtx addr = ADDR; \ + static char *sz = ".BW.L...D"; \ + rtx offset; \ + switch (GET_CODE (addr)) \ + { \ + case REG: \ + fprintf (FILE, "%s@", reg_name [REGNO (addr)]); \ + break; \ + case PRE_DEC: \ + fprintf (FILE, "%s@-", reg_name [REGNO (XEXP (addr, 0))]); \ + break; \ + case POST_INC: \ + fprintf (FILE, "%s@+", reg_name [REGNO (XEXP (addr, 0))]); \ + break; \ + case PLUS: \ + reg1 = 0; reg2 = 0; \ + ireg = 0; breg = 0; \ + offset = 0; \ + if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \ + { \ + offset = XEXP (addr, 0); \ + addr = XEXP (addr, 1); \ + } \ + else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \ + { \ + offset = XEXP (addr, 1); \ + addr = XEXP (addr, 0); \ + } \ + if (GET_CODE (addr) != PLUS) ; \ + else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \ + { \ + reg1 = XEXP (addr, 0); \ + addr = XEXP (addr, 1); \ + } \ + else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \ + { \ + reg1 = XEXP (addr, 1); \ + addr = XEXP (addr, 0); \ + } \ + else if (GET_CODE (XEXP (addr, 0)) == MULT) \ + { \ + reg1 = XEXP (addr, 0); \ + addr = XEXP (addr, 1); \ + } \ + else if (GET_CODE (XEXP (addr, 1)) == MULT) \ + { \ + reg1 = XEXP (addr, 1); \ + addr = XEXP (addr, 0); \ + } \ + else if (GET_CODE (XEXP (addr, 0)) == REG) \ + { \ + reg1 = XEXP (addr, 0); \ + addr = XEXP (addr, 1); \ + } \ + else if (GET_CODE (XEXP (addr, 1)) == REG) \ + { \ + reg1 = XEXP (addr, 1); \ + addr = XEXP (addr, 0); \ + } \ + if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \ + || GET_CODE (addr) == SIGN_EXTEND) \ + { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \ + /* for OLD_INDEXING \ + else if (GET_CODE (addr) == PLUS) \ + { \ + if (GET_CODE (XEXP (addr, 0)) == REG) \ + { \ + reg2 = XEXP (addr, 0); \ + addr = XEXP (addr, 1); \ + } \ + else if (GET_CODE (XEXP (addr, 1)) == REG) \ + { \ + reg2 = XEXP (addr, 1); \ + addr = XEXP (addr, 0); \ + } \ + } \ + */ \ + if (offset != 0) { if (addr != 0) abort (); addr = offset; } \ + if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \ + || GET_CODE (reg1) == MULT)) \ + || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \ + { breg = reg2; ireg = reg1; } \ + else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \ + { breg = reg1; ireg = reg2; } \ + if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \ + { int scale = 1; \ + if (GET_CODE (ireg) == MULT) \ + { scale = INTVAL (XEXP (ireg, 1)); \ + ireg = XEXP (ireg, 0); } \ + if (GET_CODE (ireg) == SIGN_EXTEND) \ + fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:W", \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + reg_name[REGNO (XEXP (ireg, 0))]); \ + else \ + fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:L", \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + reg_name[REGNO (ireg)]); \ + fprintf (FILE, ":%c", sz[scale]); \ + putc (']', FILE); \ + break; } \ + if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \ + { fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:L:B]", \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + reg_name[REGNO (breg)]); \ + break; } \ + if (ireg != 0 || breg != 0) \ + { int scale = 1; \ + if (breg == 0) \ + abort (); \ + if (addr && GET_CODE (addr) == LABEL_REF) abort (); \ + fprintf (FILE, "%s@", reg_name[REGNO (breg)]); \ + if (addr != 0) { \ + putc( '(', FILE ); \ + output_addr_const (FILE, addr); \ + if (ireg != 0) { \ + if (GET_CODE(addr) == CONST_INT) { \ + int size_of = 1, val = INTVAL(addr); \ + if (val < -0x8000 || val >= 0x8000) \ + size_of = 4; \ + else if (val < -0x80 || val >= 0x80) \ + size_of = 2; \ + fprintf(FILE, ":%c", sz[size_of]); \ + } \ + else \ + fprintf(FILE, ":L"); } \ + putc( ')', FILE ); } \ + if (ireg != 0) { \ + putc ('[', FILE); \ + if (ireg != 0 && GET_CODE (ireg) == MULT) \ + { scale = INTVAL (XEXP (ireg, 1)); \ + ireg = XEXP (ireg, 0); } \ + if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \ + fprintf (FILE, "%s:W", reg_name[REGNO (XEXP (ireg, 0))]); \ + else if (ireg != 0) \ + fprintf (FILE, "%s:L", reg_name[REGNO (ireg)]); \ + fprintf (FILE, ":%c", sz[scale]); \ + putc (']', FILE); \ + } \ + break; \ + } \ + else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \ + { fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:L:B]", \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ + reg_name[REGNO (reg1)]); \ + break; } \ + default: \ + if (GET_CODE (addr) == CONST_INT \ + && INTVAL (addr) < 0x8000 \ + && INTVAL (addr) >= -0x8000) \ + fprintf (FILE, "%d:W", INTVAL (addr)); \ + else \ + output_addr_const (FILE, addr); \ + }} + \f + /* + Local variables: + version-control: t + End: + */ + /* See tm-m68k.h. 3 means 68020 with 68881. */ + + #define TARGET_DEFAULT 3 + + /* Define __HAVE_FPA__ or __HAVE_68881__ in preprocessor, + according to the -m flags. + This will control the use of inline 68881 insns in certain macros. + Also inform the program which CPU this is for. */ + + #if TARGET_DEFAULT & 02 + + /* -m68881 is the default */ + #define CPP_SPEC \ + "%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}\ + %{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}" + + #else + #if TARGET_DEFAULT & 0100 + + /* -mfpa is the default */ + #define CPP_SPEC \ + "%{!msoft-float:%{m68881:-D__HAVE_68881__ }%{!m68881:-D__HAVE_FPA__ }}\ + %{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}" + + #else + + /* -msoft-float is the default */ + #define CPP_SPEC \ + "%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\ + %{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}" + + #endif + #endif + + /* Names to predefine in the preprocessor for this target machine. */ + + #define CPP_PREDEFINES "-Dmc68000 -Dalliant -Dunix" + + /* Every structure or union's size must be a multiple of 2 bytes. */ + + #define STRUCTURE_SIZE_BOUNDARY 16 + + /* This is BSD, so it wants DBX format. */ + + #define DBX_DEBUGGING_INFO diff -rc2N gcc-1.32/tm-convex.h gcc-1.33/tm-convex.h *** gcc-1.32/tm-convex.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-convex.h Tue Jan 31 21:55:58 1989 *************** *** 0 **** --- 1,968 ---- + /* Definitions of target machine for GNU compiler. Convex version. + Copyright (C) 1989 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + + /* Names to predefine in the preprocessor for this target machine. */ + + #define CPP_PREDEFINES "-Dconvex -Dunix" + + /* Print subsidiary information on the compiler version in use. */ + + #define TARGET_VERSION fprintf (stderr, " (convex)"); + + /* Run-time compilation parameters selecting different hardware subsets. */ + + extern int target_flags; + + /* Macros used in the machine description to test the flags. */ + + /* + -mc1 avoid C2-only instructions; default on C1 host + -mc2 use C2-only instructions; default on C2 host + -margcount use standard calling sequence, with arg count word + -mnoargcount don't push arg count (it's in the symbol table) (usually) + */ + + #define TARGET_C1 (target_flags & 1) + #define TARGET_C2 (target_flags & 2) + #define TARGET_ARGCOUNT (target_flags & 4) + + /* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + + #define TARGET_SWITCHES \ + { { "c1", 1 }, \ + { "c2", 2 }, \ + { "noc1", -1 }, \ + { "noc2", -2 }, \ + { "argcount", 4 }, \ + { "noargcount", -4 }, \ + { "", TARGET_DEFAULT }} + + /* Default target_flags if no switches specified. */ + + #define TARGET_DEFAULT 0 + + /* Pick a target if none was specified */ + + #define OVERRIDE_OPTIONS override_options (); + + /* Allow $ in identifiers */ + + #define DOLLARS_IN_IDENTIIFERS 1 + \f + /* Target machine storage layout */ + + /* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. */ + #define BITS_BIG_ENDIAN + + /* Define this if most significant byte of a word is the lowest numbered. */ + #define BYTES_BIG_ENDIAN + + /* Define this if most significant word of a multiword number is numbered. */ + /* #define WORDS_BIG_ENDIAN */ + + /* Number of bits in an addressible storage unit */ + #define BITS_PER_UNIT 8 + + /* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ + #define BITS_PER_WORD 32 + + /* Width of a word, in units (bytes). */ + #define UNITS_PER_WORD 4 + + /* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ + #define POINTER_SIZE 32 + + /* Allocation boundary (in *bits*) for storing pointers in memory. */ + #define POINTER_BOUNDARY 32 + + /* Allocation boundary (in *bits*) for storing arguments in argument list. */ + #define PARM_BOUNDARY 32 + + /* Boundary (in *bits*) on which stack pointer should be aligned. */ + #define STACK_BOUNDARY 32 + + /* Allocation boundary (in *bits*) for the code of a function. */ + #define FUNCTION_BOUNDARY 16 + + /* Alignment of field after `int : 0' in a structure. */ + #define EMPTY_FIELD_BOUNDARY 32 + + /* Every structure's size must be a multiple of this. */ + #define STRUCTURE_SIZE_BOUNDARY 8 + + /* No data type wants to be aligned rounder than this. */ + /* beware of doubles in structs -- 64 is incompatible with pcc */ + #define BIGGEST_ALIGNMENT 32 + + /* Define this if move instructions will actually fail to work + when given unaligned data. */ + /* #define STRICT_ALIGNMENT */ + \f + /* Standard register usage. */ + + /* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ + #define FIRST_PSEUDO_REGISTER 16 + + /* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + For Convex, these are AP, FP, and SP. */ + #define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1} + + /* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. */ + #define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + + /* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. + On Convex, all values fit in one register. */ + #define HARD_REGNO_NREGS(REGNO, MODE) 1 + + /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. + On Convex, S registers can hold any type, A registers can any nonfloat */ + #define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((REGNO) < 8 || ((MODE) != SFmode && (MODE) != DFmode && (MODE) != DImode)) + + /* Value is 1 if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ + #define MODES_TIEABLE_P(MODE1, MODE2) \ + (((MODE1) == SFmode || (MODE1) == DFmode || (MODE1) == DImode) \ + == ((MODE2) == SFmode || (MODE2) == DFmode || (MODE2) == DImode)) + + /* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + + /* Register to use for pushing function arguments. */ + #define STACK_POINTER_REGNUM 8 + + /* Base register for access to local variables of the function. */ + #define FRAME_POINTER_REGNUM 15 + + /* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms + may be accessed via the stack pointer) in functions that seem suitable. + This is computed in `reload', in reload1.c. */ + #define FRAME_POINTER_REQUIRED 1 + + /* Base register for access to arguments of the function. */ + #define ARG_POINTER_REGNUM 14 + + /* Register in which static-chain is passed to a function. */ + #define STATIC_CHAIN_REGNUM 10 + + /* Register in which address to store a structure value + is passed to a function. */ + #define STRUCT_VALUE_REGNUM 9 + \f + /* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + + /* Convex has classes A (address) and S (scalar). Seems to work + better to put S first, here and in the md. */ + + enum reg_class { NO_REGS, S_REGS, A_REGS, ALL_REGS, LIM_REG_CLASSES }; + + #define N_REG_CLASSES (int) LIM_REG_CLASSES + + /* Since GENERAL_REGS is the same class as ALL_REGS, + don't give it a different class number; just make it an alias. */ + + #define GENERAL_REGS ALL_REGS + + /* Give names of register classes as strings for dump file. */ + + #define REG_CLASS_NAMES \ + {"NO_REGS", "S_REGS", "A_REGS", "ALL_REGS" } + + /* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + + #define REG_CLASS_CONTENTS {0, 0x00ff, 0xff00, 0xffff} + + /* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + + #define S_REGNO_P(REGNO) ((REGNO) < 8) + #define A_REGNO_P(REGNO) ((REGNO) >= 8) + + #define REGNO_REG_CLASS(REGNO) \ + (S_REGNO_P (REGNO) ? S_REGS : A_REGS) + + /* The class value for index registers, and the one for base regs. */ + + #define INDEX_REG_CLASS A_REGS + #define BASE_REG_CLASS A_REGS + + /* Get reg_class from a letter such as appears in the machine description. */ + /* S regs use the letter 'd' because 's' is taken. */ + + #define REG_CLASS_FROM_LETTER(C) \ + ((C) == 'a' ? A_REGS : (C) == 'd' ? S_REGS : NO_REGS) + + /* The letters I, J, K, L and M in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ + + /* Convex uses only I: + 32-bit value with sign bit off, usable as immediate in DImode logical + instructions and, or, xor */ + + #define CONST_OK_FOR_LETTER_P(VALUE, C) ((VALUE) >= 0) + + /* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. */ + /* Convex uses only G: + value usable in ld.d (low word 0) or ld.l (high word all sign) */ + + #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ + (LD_D_P (VALUE) || LD_L_P (VALUE)) + + #define LD_D_P(X) (CONST_DOUBLE_HIGH (X) == 0) + #define LD_L_P(X) (CONST_DOUBLE_HIGH (X) >= 0 ? \ + CONST_DOUBLE_LOW (X) == 0 : CONST_DOUBLE_LOW (X) == -1) + + /* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. */ + + #define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS) + + /* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ + #define CLASS_MAX_NREGS(CLASS, MODE) 1 + \f + /* Stack layout; function entry, exit and calling. */ + + /* Define this if pushing a word on the stack + makes the stack pointer a smaller address. */ + #define STACK_GROWS_DOWNWARD + + /* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ + #define FRAME_GROWS_DOWNWARD + + /* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ + #define STARTING_FRAME_OFFSET 0 + + /* If we generate an insn to push BYTES bytes, + this says how many the stack pointer really advances by. */ + #define PUSH_ROUNDING(BYTES) (BYTES) + + /* Offset of first parameter from the argument pointer register value. */ + #define FIRST_PARM_OFFSET(FNDECL) 0 + + /* Value is 1 if returning from a function call automatically + pops the arguments described by the number-of-args field in the call. + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. */ + /* The standard Convex call, with arg count word, includes popping the + args as part of the call template. We optionally omit the arg count + word and let gcc combine the arg pops. */ + #define RETURN_POPS_ARGS(FUNTYPE) TARGET_ARGCOUNT + + /* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + + /* On Convex the return value is in S0 regardless. */ + + #define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), 0) + + /* Define how to find the value returned by a library function + assuming the value has mode MODE. */ + + /* On Convex the return value is in S0 regardless. */ + + #define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + + /* 1 if N is a possible register number for a function value. + On the Convex, S0 is the only register thus used. */ + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + + /* 1 if N is a possible register number for function argument passing. */ + + #define FUNCTION_ARG_REGNO_P(N) 0 + \f + /* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. + + On the vax, this is a single integer, which is a number of bytes + of arguments scanned so far. */ + + #define CUMULATIVE_ARGS int + + /* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. + + On Convex, the offset starts at 0. */ + + #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \ + ((CUM) = 0) + + /* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + + #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM) += ((MODE) != BLKmode \ + ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ + : (int_size_in_bytes (TYPE) + 3) & ~3)) + + /* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + + /* On Convex, all args are pushed. */ + + #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 + + /* This macro generates the assembly code for function entry. + FILE is a stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. */ + + #define FUNCTION_PROLOGUE(FILE, SIZE) \ + { if ((SIZE) != 0) fprintf (FILE, "\tsub.w #%d,sp\n", (SIZE));} + + /* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + + #define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "\tldea LP%d,a1\n\tcallq mcount\n", (LABELNO)); + + /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ + + #define EXIT_IGNORE_STACK 1 + + /* This macro generates the assembly code for function exit, + on machines that need it. If FUNCTION_EPILOGUE is not defined + then individual return instructions are generated for each + return statement. Args are same as for FUNCTION_PROLOGUE. */ + + /* #define FUNCTION_EPILOGUE(FILE, SIZE) */ + + /* If the memory address ADDR is relative to the frame pointer, + correct it to be relative to the stack pointer instead. + This is for when we don't use a frame pointer. + ADDR should be a variable name. */ + + #define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) abort (); + \f + /* Addressing modes, and classification of registers for them. */ + + /* #define HAVE_POST_INCREMENT */ + /* #define HAVE_POST_DECREMENT */ + + /* #define HAVE_PRE_DECREMENT */ + /* #define HAVE_PRE_INCREMENT */ + + /* Macros to check register numbers against specific register classes. */ + + /* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ + + #define REGNO_OK_FOR_INDEX_P(regno) \ + (((regno) ^ 010) < 8 || ((reg_renumber[regno] ^ 010) & -8) == 0) + #define REGNO_OK_FOR_BASE_P(regno) \ + (((regno) ^ 010) < 8 || ((reg_renumber[regno] ^ 010) & -8) == 0) + \f + /* Maximum number of registers that can appear in a valid memory address. */ + + #define MAX_REGS_PER_ADDRESS 1 + + /* 1 if X is an rtx for a constant that is a valid address. */ + + #define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) + + /* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + + /* For convex, any single-word constant is ok; the only contexts + allowing general_operand of mode DI or DF are movdi and movdf. */ + + #define LEGITIMATE_CONSTANT_P(X) \ + (GET_CODE (X) != CONST_DOUBLE ? 1 : (LD_D_P (X) || LD_L_P (X))) + + /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + + #ifndef REG_OK_STRICT + + /* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ + #define REG_OK_FOR_INDEX_P(X) (REGNO (X) >= 8) + /* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ + #define REG_OK_FOR_BASE_P(X) (REGNO (X) >= 8) + + #else + + /* Nonzero if X is a hard reg that can be used as an index. */ + #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) + /* Nonzero if X is a hard reg that can be used as a base reg. */ + #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) + + #endif + \f + /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + For Convex, valid addresses are + indirectable or (MEM indirectable) + where indirectable is + const, reg, (PLUS reg const) */ + + /* 1 if X is an address that we could indirect through. */ + #define INDIRECTABLE_ADDRESS_P(X) \ + (CONSTANT_ADDRESS_P (X) \ + || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ + || (GET_CODE (X) == PLUS \ + && GET_CODE (XEXP (X, 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ + && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ + || (GET_CODE (X) == PLUS \ + && GET_CODE (XEXP (X, 1)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 1)) \ + && CONSTANT_ADDRESS_P (XEXP (X, 0)))) + + /* Go to ADDR if X is a valid address. */ + #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ + { register rtx xfoob = (X); \ + if (GET_CODE (xfoob) == REG) goto ADDR; \ + if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \ + xfoob = XEXP (X, 0); \ + if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \ + goto ADDR; \ + if (GET_CODE (X) == PRE_DEC && REG_P (xfoob) \ + && REGNO (xfoob) == STACK_POINTER_REGNUM) \ + goto ADDR; } + \f + /* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. + + For Convex, nothing needs to be done. */ + + #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} + + /* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. */ + + #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} + \f + /* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ + #define CASE_VECTOR_MODE SImode + + /* Define this if the case instruction expects the table + to contain offsets from the address of the table. + Do not define this if the table should contain absolute addresses. */ + /* #define CASE_VECTOR_PC_RELATIVE */ + + /* Define this if the case instruction drops through after the table + when the index is out of range. Don't define it if the case insn + jumps to the default label instead. */ + /* #define CASE_DROPS_THROUGH */ + + /* Specify the tree operation to be used to convert reals to integers. */ + #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + + /* This is the kind of divide that is easiest to do in the general case. */ + #define EASY_DIV_EXPR TRUNC_DIV_EXPR + + /* Define this as 1 if `char' should by default be signed; else as 0. */ + #define DEFAULT_SIGNED_CHAR 1 + + /* This flag, if defined, says the same insns that convert to a signed fixnum + also convert validly to an unsigned one. */ + #define FIXUNS_TRUNC_LIKE_FIX_TRUNC + + /* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ + #define MOVE_MAX 8 + + /* Define this if zero-extension is slow (more than one real instruction). */ + /* #define SLOW_ZERO_EXTEND */ + + /* Nonzero if access to memory by bytes is slow and undesirable. */ + #define SLOW_BYTE_ACCESS 0 + + /* Define if shifts truncate the shift count + which implies one can omit a sign-extension or zero-extension + of a shift count. */ + #define SHIFT_COUNT_TRUNCATED + + /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ + #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + + /* On Convex, it is as good to call a constant function address as to + call an address kept in a register. */ + #define NO_FUNCTION_CSE + + /* When a prototype says `char' or `short', really pass an `int'. */ + #define PROMOTE_PROTOTYPES + + /* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ + #define Pmode SImode + + /* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ + #define FUNCTION_MODE QImode + + /* Compute the cost of computing a constant rtl expression RTX + whose rtx-code is CODE. The body of this macro is a portion + of a switch statement. If the code is computed here, + return it with a return statement. Otherwise, break from the switch. */ + + #define CONST_COSTS(RTX,CODE) \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + case CONST_INT: \ + return 0; \ + case CONST_DOUBLE: \ + return 2; + + /* Check a `double' value for validity for a particular machine mode. */ + + #define CHECK_FLOAT_VALUE(mode, d) \ + if ((mode) == SFmode) \ + { \ + if ((d) > 1.7014117331926443e+38) \ + { error ("magnitude of constant too large for `float'"); \ + (d) = 1.7014117331926443e+38; } \ + else if ((d) < -1.7014117331926443e+38) \ + { error ("magnitude of constant too large for `float'"); \ + (d) = -1.7014117331926443e+38; } \ + else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \ + { warning ("`float' constant truncated to zero"); \ + (d) = 0.0; } \ + else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \ + { warning ("`float' constant truncated to zero"); \ + (d) = 0.0; } \ + } + \f + /* Tell final.c how to eliminate redundant test instructions. */ + + /* Here we define machine-dependent flags and fields in cc_status + (see `conditions.h'). No extra ones are needed for convex. */ + + /* Store in cc_status the expressions + that the condition codes will describe + after execution of an instruction whose pattern is EXP. + Do not alter them if the instruction would not alter the cc's. */ + + #define NOTICE_UPDATE_CC(EXP,INSN) {CC_STATUS_INIT;} + \f + /* Control the assembler format that we output. */ + + /* Output at beginning of assembler file. */ + + #define ASM_FILE_START(FILE) fprintf (FILE, ";NO_APP\n") + + /* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ + + #define ASM_APP_ON ";APP\n" + + /* Output to assembler file text saying following lines + no longer contain unusual constructs. */ + + #define ASM_APP_OFF ";NO_APP\n" + + /* Alignment with Convex's assembler goes like this: + .text will allow .align 1 or .align 2 + .data allows 1,2,4,8 (at least; but those are all we need). + there is no .lcomm, must use explicit decls in .bss instead. + .text and .data have subsections, each starts on an 8-byte boundary. + So, since alignment is worth having, + use ".text <n>" for 2**<n>-byte aligned text section -- + this assumes that all lengths are multiples of their alignment. + use .align in .text if possible, and it's always possible in .data. + gcc arranges that everything in .bss is a multiple of 8, so it + stays aligned. + This is all handled in two routines in output-convex.c. */ + + extern char *set_section (); + extern char *align_section (); + + /* Output before read-only data. */ + + #define TEXT_SECTION_ASM_OP set_section (".text") + + /* Output before writable data. */ + + #define DATA_SECTION_ASM_OP set_section (".data") + + /* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ + + #define REGISTER_NAMES \ + {"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \ + "sp", "a1", "a2", "a3", "a4", "a5", "ap", "fp"} + + /* This is BSD, so it wants DBX format. */ + + #define DBX_DEBUGGING_INFO + + /* How to renumber registers for dbx and gdb. */ + + #define DBX_REGISTER_NUMBER(REGNO) (REGNO) + + /* Do not break .stabs pseudos into continuations. */ + + #define DBX_CONTIN_LENGTH 0 + + /* This is the char to use for continuation (in case we need to turn + continuation back on). */ + + #define DBX_CONTIN_CHAR '?' + + /* Don't use the `xsfoo;' construct in DBX output; this system + doesn't support it. */ + + #define DBX_NO_XREFS + + /* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ + + #define ASM_OUTPUT_LABEL(FILE,NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + + /* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ + + #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + + /* This is how to output a reference to a user-level label named NAME. */ + + #define ASM_OUTPUT_LABELREF(FILE,NAME) \ + fprintf (FILE, "_%s", NAME) + + /* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + + #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, "%s%d:\n", PREFIX, NUM) + + /* Put case tables in .text 2, where they will be word-aligned */ + + #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + fprintf (FILE, ".text 2\n"); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM) + + #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \ + fprintf (FILE, ".text\n"); + + /* This is how to store into the string LABEL + the symbol_ref name of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. + This is suitable for output with `assemble_name'. */ + + #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*%s%d", PREFIX, NUM) + + /* This is how to output an assembler line defining a `double' constant. + USE HEX until gcc is modified not to call this with DImode constants. */ + + #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + fprintf (FILE, "\tds.l 0x%016llx\n", (VALUE)) + + /* This is how to output an assembler line defining a `float' constant. */ + + #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + fprintf (FILE, "\tds.s %.9#g\n", (VALUE)) + + /* This is how to output an assembler line defining an `int' constant. */ + + #define ASM_OUTPUT_INT(FILE,VALUE) \ + ( fprintf (FILE, "\tds.w "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + /* Likewise for `char' and `short' constants. */ + + #define ASM_OUTPUT_SHORT(FILE,VALUE) \ + ( fprintf (FILE, "\tds.h "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + #define ASM_OUTPUT_CHAR(FILE,VALUE) \ + ( fprintf (FILE, "\tds.b "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + /* This is how to output an assembler line for a numeric constant byte. */ + + #define ASM_OUTPUT_BYTE(FILE,VALUE) \ + fprintf (FILE, "\tds.b %#x\n", (VALUE)) + + /* This is how to output a string */ + + #define ASM_OUTPUT_ASCII(FILE,STR,SIZE) do { \ + int i; \ + fprintf (FILE, "\tds.b \""); \ + for (i = 0; i < (SIZE); i++) { \ + register int c = (STR)[i] & 0377; \ + if (c >= ' ' && c < 0177 && c != '\\' && c != '"') \ + putc (c, FILE); \ + else \ + fprintf (FILE, "\\%03o", c);} \ + fprintf (FILE, "\"\n");} while (0) + + /* This is how to output an insn to push a register on the stack. + It need not be very fast code. */ + + #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ + fprintf (FILE, "\tpsh.%c %s\n", \ + S_REGNO_P (REGNO) ? 'l' : 'w', \ + reg_names[REGNO]) + + /* This is how to output an insn to pop a register from the stack. + It need not be very fast code. */ + + #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ + fprintf (FILE, "\tpop.%c %s\n", \ + S_REGNO_P (REGNO) ? 'l' : 'w', \ + reg_names[REGNO]) + + /* This is how to output an element of a case-vector that is absolute. */ + + #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\tds.w L%d\n", VALUE) + + /* This is how to output an element of a case-vector that is relative. + (not used on Convex) */ + + #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\tds.w L%d-L%d\n", VALUE, REL) + + /* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + + #define ASM_OUTPUT_ALIGN(FILE,LOG) \ + fprintf (FILE, align_section (LOG)); + + /* This is how to output an assembler line + that says to advance the location counter by SIZE bytes. */ + + #define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\tds.b %d(0)\n", (SIZE)) + + /* This says how to output an assembler line + to define a global common symbol. */ + + #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ + ( fputs (".comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d\n", (ROUNDED))) + + /* This says how to output an assembler line + to define a local common symbol. */ + + #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ + ( fprintf ((FILE), "%s\n", set_section (".bss")), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ":\tbs.b %d\n", (ROUNDED)), \ + fprintf ((FILE), "%s\n", set_section (0))) + + /* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + + #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ + ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) + + /* Define the parentheses used to group arithmetic operations + in assembler code. */ + + #define ASM_OPEN_PAREN "(" + #define ASM_CLOSE_PAREN ")" + + /* Define results of standard character escape sequences. */ + #define TARGET_BELL 007 + #define TARGET_BS 010 + #define TARGET_TAB 011 + #define TARGET_NEWLINE 012 + #define TARGET_VT 013 + #define TARGET_FF 014 + #define TARGET_CR 015 + + /* Print an instruction operand X on file FILE. + CODE is the code from the %-spec that requested printing this operand; + if `%z3' was used to print operand 3, then CODE is 'z'. */ + + #define PRINT_OPERAND(FILE, X, CODE) \ + { if (GET_CODE (X) == REG) \ + fprintf (FILE, "%s", reg_name [REGNO (X)]); \ + else if (GET_CODE (X) == MEM) \ + output_address (XEXP (X, 0)); \ + else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ + { union { double d; int i[2]; } u; \ + u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ + fprintf (FILE, "#%.20#g", u.d); } \ + else { putc ('#', FILE); output_addr_const (FILE, X); }} + + /* Print a memory operand whose address is X, on file FILE. */ + + #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ + { \ + register rtx addr = ADDR; \ + register rtx index = 0; \ + register rtx offset = 0; \ + \ + if (GET_CODE (addr) == MEM) \ + { \ + fprintf (FILE, "@"); \ + addr = XEXP (addr, 0); \ + } \ + \ + switch (GET_CODE (addr)) \ + { \ + case REG: \ + index = addr; \ + break; \ + \ + case PLUS: \ + index = XEXP (addr, 0); \ + if (REG_P (index)) \ + offset = XEXP (addr, 1); \ + else \ + { \ + offset = XEXP (addr, 0); \ + index = XEXP (addr, 1); \ + if (! REG_P (index)) abort (); \ + } \ + break; \ + \ + default: \ + offset = addr; \ + break; \ + } \ + \ + if (offset) \ + output_addr_const (FILE, offset); \ + \ + if (index) \ + fprintf (FILE, "(%s)", reg_name[REGNO (index)]); \ + } + diff -rc2N gcc-1.32/tm-convex1.h gcc-1.33/tm-convex1.h *** gcc-1.32/tm-convex1.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-convex1.h Tue Jan 31 21:53:33 1989 *************** *** 0 **** --- 1,7 ---- + /* tm.h file for a Convex C1. */ + + #include "tm-convex.h" + + #define TARGET_DEFAULT 1 + + #define CC1_SPEC "%{mc2:-mnoc1}" diff -rc2N gcc-1.32/tm-convex2.h gcc-1.33/tm-convex2.h *** gcc-1.32/tm-convex2.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-convex2.h Tue Jan 31 21:53:44 1989 *************** *** 0 **** --- 1,7 ---- + /* tm.h file for a Convex C2. */ + + #include "tm-convex.h" + + #define TARGET_DEFAULT 2 + + #define CC1_SPEC "%{mc1:-mnoc2}" diff -rc2N gcc-1.32/tm-encore.h gcc-1.33/tm-encore.h *** gcc-1.32/tm-encore.h Sun Dec 4 13:03:49 1988 --- gcc-1.33/tm-encore.h Mon Jan 30 22:12:33 1989 *************** *** 32,35 **** --- 32,39 ---- #define SDB_DEBUGGING_INFO + /* Cause long-jump assembler to be used, + since otherwise some files fail to be assembled right. */ + #define ASM_SPEC "-j" + #undef ASM_FILE_START #undef ASM_GENERATE_INTERNAL_LABEL *************** *** 180,187 **** if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0l%.20e", u.d); } \ else { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0f%.20e", u.d); } \ else if (GET_CODE (X) == CONST) \ --- 184,191 ---- if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0l%.20e", u.d); } \ else { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0f%.20e", u.d); } \ else if (GET_CODE (X) == CONST) \ diff -rc2N gcc-1.32/tm-genix.h gcc-1.33/tm-genix.h *** gcc-1.32/tm-genix.h Mon Dec 5 18:24:14 1988 --- gcc-1.33/tm-genix.h Sun Jan 1 16:08:28 1989 *************** *** 146,153 **** if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0l%.20e", u.d); } \ else { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0f%.20e", u.d); } \ else if (GET_CODE (X) == CONST) \ --- 146,153 ---- if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0l%.20e", u.d); } \ else { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0f%.20e", u.d); } \ else if (GET_CODE (X) == CONST) \ diff -rc2N gcc-1.32/tm-hp9k320.h gcc-1.33/tm-hp9k320.h *** gcc-1.32/tm-hp9k320.h Sun Dec 4 13:03:45 1988 --- gcc-1.33/tm-hp9k320.h Sun Jan 1 16:08:26 1989 *************** *** 337,341 **** { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ u1.f = u.d; \ if (CODE == 'f') \ --- 337,341 ---- { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ u1.f = u.d; \ if (CODE == 'f') \ *************** *** 345,349 **** else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "&0f%.20g", u.d); } \ else { putc ('&', FILE); output_addr_const (FILE, X); }} --- 345,349 ---- else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "&0f%.20g", u.d); } \ else { putc ('&', FILE); output_addr_const (FILE, X); }} diff -rc2N gcc-1.32/tm-i386.h gcc-1.33/tm-i386.h *** gcc-1.32/tm-i386.h Tue Dec 6 21:00:12 1988 --- gcc-1.33/tm-i386.h Fri Jan 27 03:50:10 1989 *************** *** 261,265 **** #define REG_CLASS_CONTENTS {0, 0x1, 0x2, 0x3, 0x4, 0x8, 0xf,\ ! 0x30, 0xff, 0x300, 0x3ff} /* The same information, inverted: --- 261,265 ---- #define REG_CLASS_CONTENTS {0, 0x1, 0x2, 0x3, 0x4, 0x8, 0xf,\ ! 0x7f, 0xff, 0x300, 0x3ff} /* The same information, inverted: *************** *** 273,279 **** (REGNO) == 2 ? CREG : \ (REGNO) == 3 ? BREG : \ ! (REGNO) == 4 ? INDEX_REGS : \ ! (REGNO) == 5 ? INDEX_REGS : \ ! (REGNO) < 8 ? GENERAL_REGS : \ FLOAT_REGS) --- 273,278 ---- (REGNO) == 2 ? CREG : \ (REGNO) == 3 ? BREG : \ ! (REGNO) == 7 ? GENERAL_REGS : \ ! (REGNO) < 8 ? INDEX_REGS : \ FLOAT_REGS) *************** *** 307,311 **** (C) == 'q' ? Q_REGS : \ (C) == 'f' ? FLOAT_REGS : \ - (C) == 'x' ? INDEX_REGS : \ (C) == 'a' ? AREG : (C) == 'b' ? BREG : \ (C) == 'c' ? CREG : (C) == 'd' ? DREG : \ --- 306,309 ---- *************** *** 500,504 **** #define FUNCTION_PROFILER(FILE, LABELNO) \ ! fprintf (FILE, "\tlea LP%d,%%eax\n\tcall mcount\n", (LABELNO)); /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, --- 498,502 ---- #define FUNCTION_PROFILER(FILE, LABELNO) \ ! fprintf (FILE, "\tlea %sP%d,%%eax\n\tcall mcount\n", LPREFIX, (LABELNO)); /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, *************** *** 857,871 **** /* Output a signed jump insn. Use template NORMAL ordinarily, or FLOAT following a floating point comparison. ! We ought to use NO_OV if following an arithmetic insn that set the ! cc's based on its result; but (1) the NO_OV templates written ! in i386.md are incorrect and (2) notice_update_cc never records ! cc settings from arithmetic insns. */ ! #define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ ! { if (cc_status.flags & CC_IN_80387) \ return FLOAT; \ if (cc_status.flags & CC_NO_OVERFLOW) \ ! abort (); \ ! return NORMAL; } \f /* Control the assembler format that we output. */ --- 855,871 ---- /* Output a signed jump insn. Use template NORMAL ordinarily, or FLOAT following a floating point comparison. ! Use NO_OV following an arithmetic insn that set the cc's ! before a test insn that was deleted. ! NO_OV may be zero, meaning final should reinsert the test insn ! because the jump cannot be handled properly without it. */ ! #define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ ! { \ ! if (cc_status.flags & CC_IN_80387) \ return FLOAT; \ if (cc_status.flags & CC_NO_OVERFLOW) \ ! return NO_OV; \ ! return NORMAL; \ ! } \f /* Control the assembler format that we output. */ diff -rc2N gcc-1.32/tm-i386gas.h gcc-1.33/tm-i386gas.h *** gcc-1.32/tm-i386gas.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-i386gas.h Fri Jan 27 03:53:04 1989 *************** *** 0 **** --- 1,88 ---- + /* Definitions for Intel 386 running system V with gnu tools + Copyright (C) 1988 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + + #include "tm-i386.h" + /* Use the bsd assembler syntax. */ + /* we need to do this because gas is really a bsd style assembler, + * and so doesn't work well this these att-isms: + * + * ASM_OUTPUT_SKIP is .set .,.+N, which isn't implemented in gas + * ASM_OUTPUT_LOCAL is done with .set .,.+N, but that can't be + * used to define bss static space + * ASM_OUTPUT_ALIGN's arg is N instead of log(N) for att + * + * Next is the question of whether to uses underscores. RMS didn't + * like this idea at first, but since it is now obvious that we + * need this separate tm file for use with gas, at least to get + * dbx debugging info, I think we should also switch to underscores. + * We can keep tm-i386v for real att style output, and the few + * people who want both form will have to compile twice. + */ + + #include "tm-bsd386.h" + + /* these come from tm-bsd386.h, but are specific to sequent */ + #undef DBX_NO_XREFS + #undef DBX_CONTIN_LENGTH + + /* By default, target has a 80387. */ + + #define TARGET_DEFAULT 1 + + /* Specify predefined symbols in preprocessor. */ + + #define CPP_PREDEFINES "-Dunix -Di386" + + /* Allow #ident and #sccs in preprocessor. */ + + #define IDENT_DIRECTIVE + #define SCCS_DIRECTIVE + + /* We do not want to output SDB debugging information. */ + + #undef SDB_DEBUGGING_INFO + + /* We want to output DBX debugging information. */ + + #define DBX_DEBUGGING_INFO + + /* Implicit library calls should use memcpy, not bcopy, etc. */ + + #define TARGET_MEM_FUNCTIONS + + \f + /* Machines that use the AT&T assembler syntax + also return floating point values in an FP register. */ + /* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + + #define VALUE_REGNO(MODE) \ + (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0) + + /* 1 if N is a possible register number for a function value. */ + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) + + #undef ASM_FILE_START + #define ASM_FILE_START(FILE) \ + fprintf (FILE, "\t.file\t\"%s\"\n", dump_base_name); diff -rc2N gcc-1.32/tm-m68k.h gcc-1.33/tm-m68k.h *** gcc-1.32/tm-m68k.h Tue Dec 20 15:10:48 1988 --- gcc-1.33/tm-m68k.h Sun Jan 1 16:08:23 1989 *************** *** 1408,1412 **** { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ u1.f = u.d; \ if (CODE == 'f') \ --- 1408,1412 ---- { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ u1.f = u.d; \ if (CODE == 'f') \ *************** *** 1416,1420 **** else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ ASM_OUTPUT_DOUBLE_OPERAND (FILE, u.d); } \ else { putc ('#', FILE); output_addr_const (FILE, X); }} --- 1416,1420 ---- else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ ASM_OUTPUT_DOUBLE_OPERAND (FILE, u.d); } \ else { putc ('#', FILE); output_addr_const (FILE, X); }} diff -rc2N gcc-1.32/tm-m88k.h gcc-1.33/tm-m88k.h *** gcc-1.32/tm-m88k.h Sun Dec 4 13:03:12 1988 --- gcc-1.33/tm-m88k.h Sun Jan 1 16:08:19 1989 *************** *** 1075,1079 **** { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ u1.f = u.d; \ if (CODE == 'f') \ --- 1075,1079 ---- { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ u1.f = u.d; \ if (CODE == 'f') \ *************** *** 1083,1087 **** else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "0r%.20g", u.d); } \ else if ((CODE) == 'r' && (X) == const0_rtx) \ --- 1083,1087 ---- else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "0r%.20g", u.d); } \ else if ((CODE) == 'r' && (X) == const0_rtx) \ diff -rc2N gcc-1.32/tm-news800.h gcc-1.33/tm-news800.h *** gcc-1.32/tm-news800.h Sun Dec 4 13:07:48 1988 --- gcc-1.33/tm-news800.h Sun Jan 1 16:08:17 1989 *************** *** 227,231 **** { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ u1.f = u.d; \ if (CODE == 'f') \ --- 227,231 ---- { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ u1.f = u.d; \ if (CODE == 'f') \ *************** *** 235,239 **** else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "#0d%.20e", u.d); } \ else if (CODE == 'b') output_addr_const (FILE, X); \ --- 235,239 ---- else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "#0d%.20e", u.d); } \ else if (CODE == 'b') output_addr_const (FILE, X); \ diff -rc2N gcc-1.32/tm-ns32k.h gcc-1.33/tm-ns32k.h *** gcc-1.32/tm-ns32k.h Sun Dec 4 16:38:29 1988 --- gcc-1.33/tm-ns32k.h Sun Jan 1 16:08:15 1989 *************** *** 472,476 **** } \ fprintf (FILE, "],%d\n", SIZE); \ ! } else while (*bufp >= 0) \ fprintf (FILE, "\tmovd r%d,tos\n", *bufp++); \ --- 472,476 ---- } \ fprintf (FILE, "],%d\n", SIZE); \ ! } \ else while (*bufp >= 0) \ fprintf (FILE, "\tmovd r%d,tos\n", *bufp++); \ *************** *** 1070,1074 **** /* This is how to align the code that follows an unconditional branch. */ ! #define ASM_OUTPUT_ALIGN_CODE(FILE) fprintf (FILE, "\t.align 4\n") --- 1070,1074 ---- /* This is how to align the code that follows an unconditional branch. */ ! #define ASM_OUTPUT_ALIGN_CODE(FILE) \ fprintf (FILE, "\t.align 4\n") *************** *** 1196,1204 **** if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0d%.20e", u.d); } \ else \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0f%.20e", u.d); } \ else { putc ('$', FILE); output_addr_const (FILE, X); }} --- 1196,1204 ---- if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0d%.20e", u.d); } \ else \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0f%.20e", u.d); } \ else { putc ('$', FILE); output_addr_const (FILE, X); }} diff -rc2N gcc-1.32/tm-seq386.h gcc-1.33/tm-seq386.h *** gcc-1.32/tm-seq386.h Wed Nov 30 08:47:17 1988 --- gcc-1.33/tm-seq386.h Fri Dec 23 22:19:47 1988 *************** *** 56,57 **** --- 56,60 ---- #define FUNCTION_PROFILER(FILE, LABELNO) \ fprintf (FILE, "\tmovl $LP%d,%%eax\n\tcall mcount\n", (LABELNO)); + + /* Assember pseudo-op for shared data segment. */ + #define SHARED_SECTION_ASM_OP ".shdata" diff -rc2N gcc-1.32/tm-sequent.h gcc-1.33/tm-sequent.h *** gcc-1.32/tm-sequent.h Sun Dec 4 13:03:31 1988 --- gcc-1.33/tm-sequent.h Thu Jan 5 18:12:40 1989 *************** *** 44,53 **** #define CPP_PREDEFINES "-Dns32000 -Dsequent -Dunix" ! /* This is how to align the code that follows an unconditional branch. */ #undef ASM_OUTPUT_ALIGN_CODE - #define ASM_OUTPUT_ALIGN_CODE(FILE) - fprintf (FILE, "\t.align 2\n") /* %$ means print the prefix for an immediate operand. On the sequent, no prefix is used for such. */ --- 44,55 ---- #define CPP_PREDEFINES "-Dns32000 -Dsequent -Dunix" ! /* This is how to align the code that follows an unconditional branch. ! Don't define it, since it confuses the assembler (we hear). */ #undef ASM_OUTPUT_ALIGN_CODE + /* Assember pseudo-op for shared data segment. */ + #define SHARED_SECTION_ASM_OP ".shdata" + /* %$ means print the prefix for an immediate operand. On the sequent, no prefix is used for such. */ *************** *** 96,103 **** if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "0d%.20e", u.d); } \ else { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "0f%.20e", u.d); } \ else output_addr_const (FILE, X); } --- 98,105 ---- if (GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "0d%.20e", u.d); } \ else { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "0f%.20e", u.d); } \ else output_addr_const (FILE, X); } diff -rc2N gcc-1.32/tm-sparc.h gcc-1.33/tm-sparc.h *** gcc-1.32/tm-sparc.h Fri Dec 16 17:33:41 1988 --- gcc-1.33/tm-sparc.h Sun Jan 22 04:34:40 1989 *************** *** 54,57 **** --- 54,61 ---- #define TARGET_SUN_ASM (target_flags & 4) + /* Nonzero if we should do eager peepholes for conditional branch + scheduling. */ + #define TARGET_EAGER (target_flags & 8) + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, *************** *** 66,69 **** --- 70,74 ---- {"no-epilogue", -2}, \ {"sun-asm", 4}, \ + {"eager", 8}, \ { "", TARGET_DEFAULT}} *************** *** 779,817 **** be output as REG+SMALLINT. ! Try making SYMBOL_REF a legitimate address, regardless. Because the ! only insns which can use memory are load or store insns, the ! added hair in the machine description is not that bad. It should ! also speed up the compiler by halving the number of insns it must ! manage for each (MEM (SYMBOL_REF ...)) involved. */ #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ ! { if (GET_CODE (X) == REG \ ! && REG_OK_FOR_BASE_P (X)) \ ! goto ADDR; \ ! if (GET_CODE (X) == SYMBOL_REF /* && CONSTANT_POOL_ADDRESS_P(X) */) \ goto ADDR; \ - if (GET_CODE (X) == PLUS) \ - if (GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ - { \ - if (GET_CODE (XEXP (X, 1)) == REG \ - && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \ - goto ADDR; \ - if (GET_CODE (XEXP (X, 1)) == CONST_INT \ - && INTVAL (XEXP (X, 1)) >= -0x1000 \ - && INTVAL (XEXP (X, 1)) < 0x1000) \ - goto ADDR; \ - } \ - else if (GET_CODE (XEXP (X, 1)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ - { \ - if (GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \ - goto ADDR; \ - if (GET_CODE (XEXP (X, 0)) == CONST_INT \ - && INTVAL (XEXP (X, 0)) >= -0x1000 \ - && INTVAL (XEXP (X, 0)) < 0x1000) \ - goto ADDR; \ - } \ } \f --- 784,823 ---- be output as REG+SMALLINT. ! Try making SYMBOL_REF (and other things which are CONSTANT_ADDRESS_P) ! a legitimate address, regardless. Because the only insns which can use ! memory are load or store insns, the added hair in the machine description ! is not that bad. It should also speed up the compiler by halving the number ! of insns it must manage for each (MEM (SYMBOL_REF ...)) involved. */ #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ ! { if (GET_CODE (X) == REG) \ ! { if (REG_OK_FOR_BASE_P (X)) goto ADDR; } \ ! else if (GET_CODE (X) == PLUS) \ ! { \ ! if (GET_CODE (XEXP (X, 0)) == REG \ ! && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ ! { \ ! if (GET_CODE (XEXP (X, 1)) == REG \ ! && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \ ! goto ADDR; \ ! if (GET_CODE (XEXP (X, 1)) == CONST_INT \ ! && INTVAL (XEXP (X, 1)) >= -0x1000 \ ! && INTVAL (XEXP (X, 1)) < 0x1000) \ ! goto ADDR; \ ! } \ ! else if (GET_CODE (XEXP (X, 1)) == REG \ ! && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ ! { \ ! if (GET_CODE (XEXP (X, 0)) == REG \ ! && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \ ! goto ADDR; \ ! if (GET_CODE (XEXP (X, 0)) == CONST_INT \ ! && INTVAL (XEXP (X, 0)) >= -0x1000 \ ! && INTVAL (XEXP (X, 0)) < 0x1000) \ ! goto ADDR; \ ! } \ ! } \ ! else if (CONSTANT_ADDRESS_P (X)) \ goto ADDR; \ } \f *************** *** 880,887 **** #define SLOW_BYTE_ACCESS 0 - /* On Sun 4, this limit is 2048. We use 1500 to be safe, - since the length can run past this up to a continuation point. */ - #define DBX_CONTIN_LENGTH 1500 - /* We assume that the store-condition-codes instructions store 0 for false and some other value for true. This is the value stored for true. */ --- 886,889 ---- *************** *** 889,892 **** --- 891,897 ---- #define STORE_FLAG_VALUE 1 + /* When a prototype says `char' or `short', really pass an `int'. */ + #define PROMOTE_PROTOTYPES + /* Define if shifts truncate the shift count which implies one can omit a sign-extension or zero-extension *************** *** 914,917 **** --- 919,933 ---- #define NO_FUNCTION_CSE + /* Define subroutines to call to handle multiply and divide. + Use the subroutines that Sun's library provides. + The `*' prevents an underscore from being prepended by the compiler. */ + + #define DIVSI3_LIBCALL "*.div" + #define UDIVSI3_LIBCALL "*.udiv" + #define MODSI3_LIBCALL "*.rem" + #define UMODSI3_LIBCALL "*.urem" + #define MULSI3_LIBCALL "*.mul" + #define UMULSI3_LIBCALL "*.umul" + /* Compute the cost of computing a constant rtl expression RTX whose rtx-code is CODE. The body of this macro is a portion *************** *** 981,985 **** } \ else if (GET_CODE (SET_DEST (EXP)) == MEM) \ ! { CC_STATUS_INIT; } \ } \ else if (GET_CODE (EXP) == PARALLEL \ --- 997,1005 ---- } \ else if (GET_CODE (SET_DEST (EXP)) == MEM) \ ! { rtx x = cc_status.mdep; int know = cc_status.flags & CC_KNOW_HI_G1; \ ! CC_STATUS_INIT; \ ! if (x && know) \ ! { cc_status.mdep = x; cc_status.flags |= CC_KNOW_HI_G1; } \ ! } \ } \ else if (GET_CODE (EXP) == PARALLEL \ *************** *** 1001,1008 **** } \ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == MEM) \ ! { CC_STATUS_INIT; } \ } \ ! else if (GET_CODE (EXP) == PARALLEL \ ! && GET_CODE (XVECEXP (EXP, 0, 0)) == REG) \ /* insn-peep has changed this insn beyond recognition by NOTICE_UPDATE_CC. However, we know it is either --- 1021,1031 ---- } \ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == MEM) \ ! { rtx x = cc_status.mdep; int know = cc_status.flags & CC_KNOW_HI_G1; \ ! CC_STATUS_INIT; \ ! if (x && know) \ ! { cc_status.mdep = x; cc_status.flags |= CC_KNOW_HI_G1; } \ ! } \ } \ ! else if (GET_CODE (EXP) == PARALLEL) \ /* insn-peep has changed this insn beyond recognition by NOTICE_UPDATE_CC. However, we know it is either *************** *** 1055,1058 **** --- 1078,1085 ---- #define DBX_REGISTER_NUMBER(REGNO) (REGNO) + /* On Sun 4, this limit is 2048. We use 1500 to be safe, + since the length can run past this up to a continuation point. */ + #define DBX_CONTIN_LENGTH 1500 + /* This is how to output a note to DBX telling it the line number to which the following sequence of instructions corresponds. *************** *** 1222,1225 **** --- 1249,1288 ---- else if ((CODE) == 'r' && (X) == const0_rtx) \ fprintf (FILE, "%%g0"); \ + else if ((CODE) == 'C') switch (GET_CODE (X)) \ + { \ + case EQ: fputs ("e", FILE); break; \ + case NE: fputs ("ne", FILE); break; \ + case GT: fputs ("g", FILE); break; \ + case GE: fputs ("ge", FILE); break; \ + case LT: fputs ("l", FILE); break; \ + case LE: fputs ("le", FILE); break; \ + case GTU: fputs ("gu", FILE); break; \ + case GEU: fputs ("geu", FILE); break; \ + case LTU: fputs ("lu", FILE); break; \ + case LEU: fputs ("leu", FILE); break; \ + } \ + else if ((CODE) == 'N') switch (GET_CODE (X)) \ + { \ + case EQ: fputs ("ne", FILE); break; \ + case NE: fputs ("e", FILE); break; \ + case GT: fputs ("le", FILE); break; \ + case GE: fputs ("l", FILE); break; \ + case LT: fputs ("ge", FILE); break; \ + case LE: fputs ("g", FILE); break; \ + case GTU: fputs ("leu", FILE); break; \ + case GEU: fputs ("lu", FILE); break; \ + case LTU: fputs ("geu", FILE); break; \ + case LEU: fputs ("gu", FILE); break; \ + } \ + else if ((CODE) == 'F') switch (GET_CODE (X)) \ + { \ + case EQ: fputs ("ne", FILE); break; \ + case NE: fputs ("e", FILE); break; \ + case GT: fputs ("ule", FILE); break; \ + case GE: fputs ("ul", FILE); break; \ + case LT: fputs ("uge", FILE); break; \ + case LE: fputs ("ug", FILE); break; \ + default: abort (); \ + } \ else { output_addr_const (FILE, X); }} \f *************** *** 1253,1254 **** --- 1316,1318 ---- } \ } + diff -rc2N gcc-1.32/tm-sun2.h gcc-1.33/tm-sun2.h *** gcc-1.32/tm-sun2.h Tue Dec 6 11:43:14 1988 --- gcc-1.33/tm-sun2.h Fri Jan 27 21:15:36 1989 *************** *** 26,34 **** #define TARGET_DEFAULT 0 ! /* Define __HAVE_FPU__ in preprocessor, unless -msoft-float is specified. This will control the use of inline 68881 insns in certain macros. Also inform the program which CPU this is for. */ ! #define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__} \ %{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}" --- 26,34 ---- #define TARGET_DEFAULT 0 ! /* Define __HAVE_68881 in preprocessor only if -m68881 is specified. This will control the use of inline 68881 insns in certain macros. Also inform the program which CPU this is for. */ ! #define CPP_SPEC "%{m68881:-D__HAVE_68881__} \ %{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}" diff -rc2N gcc-1.32/tm-sun3-fpa.h gcc-1.33/tm-sun3-fpa.h *** gcc-1.32/tm-sun3-fpa.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-sun3-fpa.h Sat Dec 31 14:13:10 1988 *************** *** 0 **** --- 1,5 ---- + /* Define target machine as a Sun 3 with an FPA. */ + + #define TARGET_DEFAULT 0107 + + #include "tm-sun3.h" diff -rc2N gcc-1.32/tm-sun3-nfp.h gcc-1.33/tm-sun3-nfp.h *** gcc-1.32/tm-sun3-nfp.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/tm-sun3-nfp.h Sat Dec 31 14:12:03 1988 *************** *** 0 **** --- 1,5 ---- + /* Define target machine as a Sun 3 with no 68881. */ + + #define TARGET_DEFAULT 5 + + #include "tm-sun3.h" diff -rc2N gcc-1.32/tm-sun3.h gcc-1.33/tm-sun3.h *** gcc-1.32/tm-sun3.h Tue Dec 6 11:43:05 1988 --- gcc-1.33/tm-sun3.h Sat Dec 31 14:11:32 1988 *************** *** 24,28 **** --- 24,30 ---- /* See tm-m68k.h. 7 means 68020 with 68881. */ + #ifndef TARGET_DEFAULT #define TARGET_DEFAULT 7 + #endif /* Define __HAVE_FPA__ or __HAVE_68881__ in preprocessor, diff -rc2N gcc-1.32/tm-vax.h gcc-1.33/tm-vax.h *** gcc-1.32/tm-vax.h Mon Dec 12 14:20:51 1988 --- gcc-1.33/tm-vax.h Sun Jan 1 16:08:09 1989 *************** *** 999,1003 **** else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = XINT (X, 0); u.i[1] = XINT (X, 1); \ fprintf (FILE, "$0%c%.20e", ASM_DOUBLE_CHAR, u.d); } \ else { putc ('$', FILE); output_addr_const (FILE, X); }} --- 999,1003 ---- else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ fprintf (FILE, "$0%c%.20e", ASM_DOUBLE_CHAR, u.d); } \ else { putc ('$', FILE); output_addr_const (FILE, X); }} diff -rc2N gcc-1.32/toplev.c gcc-1.33/toplev.c *** gcc-1.32/toplev.c Wed Dec 21 14:14:46 1988 --- gcc-1.33/toplev.c Sun Jan 15 20:16:52 1989 *************** *** 721,724 **** --- 721,732 ---- longjmp (float_handler, 1); } + + /* Handler for SIGPIPE. */ + + static void + pipe_closed () + { + fatal ("output pipe has been closed"); + } \f /* Compile an entire file of output from cpp, named NAME. *************** *** 988,991 **** --- 996,1005 ---- && TREE_ADDRESSABLE (decl)) output_inline_function (decl); + if (warn_unused + && TREE_CODE (decl) == FUNCTION_DECL + && DECL_INITIAL (decl) == 0 + && TREE_EXTERNAL (decl) + && ! TREE_PUBLIC (decl)) + warning_with_decl (decl, "`%s' declared but never defined"); } } *************** *** 1221,1225 **** it only computes whether control can drop off the end of the function. */ ! if (optimize || extra_warnings || warn_return_type) TIMEVAR (jump_time, jump_optimize (insns, 0, 0)); --- 1235,1241 ---- it only computes whether control can drop off the end of the function. */ ! if (optimize || extra_warnings || warn_return_type ! /* If function is `volatile', we should warn if it tries to return. */ ! || TREE_THIS_VOLATILE (decl)) TIMEVAR (jump_time, jump_optimize (insns, 0, 0)); *************** *** 1509,1512 **** --- 1525,1530 ---- signal (SIGFPE, float_signal); + signal (SIGPIPE, pipe_closed); + /* Initialize whether `char' is signed. */ flag_signed_char = DEFAULT_SIGNED_CHAR; *************** *** 1522,1526 **** for (i = 1; i < argc; i++) ! if (argv[i][0] == '-') { register char *str = argv[i] + 1; --- 1540,1544 ---- for (i = 1; i < argc; i++) ! if (argv[i][0] == '-' && argv[i][1] != 0) { register char *str = argv[i] + 1; *************** *** 1596,1600 **** found = 1; } ! if (p[0] == 'n' && p[1] == 'o' && p[3] == '-' && ! strcmp (p+3, f_options[j].string)) { --- 1614,1618 ---- found = 1; } ! if (p[0] == 'n' && p[1] == 'o' && p[2] == '-' && ! strcmp (p+3, f_options[j].string)) { diff -rc2N gcc-1.32/tree.c gcc-1.33/tree.c *** gcc-1.32/tree.c Wed Nov 30 06:22:49 1988 --- gcc-1.33/tree.c Sat Jan 28 22:00:35 1989 *************** *** 567,571 **** build_real (type, d) tree type; ! double d; { tree v; --- 567,571 ---- build_real (type, d) tree type; ! REAL_VALUE_TYPE d; { tree v; *************** *** 586,589 **** --- 586,593 ---- and whose value is the integer value of the INTEGER_CST node I. */ + #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) + /* This function can't be implemented if we can't do arithmetic + on the float representation. */ + tree build_real_from_int_cst (type, i) *************** *** 597,600 **** --- 601,607 ---- TREE_TYPE (v) = type; + #ifdef REAL_ARITHMETIC + REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i)); + #else /* not REAL_ARITHMETIC */ if (TREE_INT_CST_HIGH (i) < 0) { *************** *** 612,615 **** --- 619,623 ---- d += (double) (unsigned) TREE_INT_CST_LOW (i); } + #endif /* not REAL_ARITHMETIC */ /* Check for valid float value for this type on this target machine; *************** *** 623,626 **** --- 631,636 ---- } + #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ + /* Return a newly constructed STRING_CST node whose value is the LEN characters at STR. *************** *** 1612,1616 **** case REAL_CST: ! return TREE_REAL_CST (t1) == TREE_REAL_CST (t2); case STRING_CST: --- 1622,1626 ---- case REAL_CST: ! return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2)); case STRING_CST: diff -rc2N gcc-1.32/tree.def gcc-1.33/tree.def *** gcc-1.32/tree.def Fri Dec 2 13:56:52 1988 --- gcc-1.33/tree.def Thu Dec 22 21:31:26 1988 *************** *** 46,50 **** There is only one IDENTIFIER_NODE ever made for any particular name. Use `get_identifier' to get it (or create it, the first time). */ ! DEFTREECODE (IDENTIFIER_NODE, "identifier_node", "x", 6) /* Used to hold information to identify an operator (or combination --- 46,50 ---- There is only one IDENTIFIER_NODE ever made for any particular name. Use `get_identifier' to get it (or create it, the first time). */ ! DEFTREECODE (IDENTIFIER_NODE, "identifier_node", "x", 7) /* Used to hold information to identify an operator (or combination diff -rc2N gcc-1.32/tree.h gcc-1.33/tree.h *** gcc-1.32/tree.h Sat Dec 3 17:52:40 1988 --- gcc-1.33/tree.h Mon Jan 23 03:21:24 1989 *************** *** 1,4 **** /* Front-end tree definitions for GNU compiler. ! Copyright (C) 1987 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Front-end tree definitions for GNU compiler. ! Copyright (C) 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 34,38 **** /* Number of tree codes. */ ! #define NUM_TREE_CODE ((int)LAST_AND_UNUSED_TREE_CODE) /* Indexed by enum tree_code, contains a character which is --- 34,38 ---- /* Number of tree codes. */ ! #define NUM_TREE_CODES ((int)LAST_AND_UNUSED_TREE_CODE) /* Indexed by enum tree_code, contains a character which is *************** *** 89,92 **** --- 89,93 ---- BUILT_IN_GETEXP, BUILT_IN_GETMAN, + BUILT_IN_SAVEREGS, /* C++ extensions */ *************** *** 312,317 **** --- 313,324 ---- /* In a REAL_CST node. */ + /* We can represent a real value as either a `double' or a string. + Strings don't allow for any optimization, but they do allow + for cross-compilation. */ + #define TREE_REAL_CST(NODE) ((NODE)->real_cst.real_cst) + #include "real.h" + struct tree_real_cst { *************** *** 319,323 **** struct rtx_def *rtl; /* acts as link to register transfer language (rtl) info */ ! double real_cst; }; --- 326,330 ---- struct rtx_def *rtl; /* acts as link to register transfer language (rtl) info */ ! REAL_VALUE_TYPE real_cst; }; *************** *** 356,359 **** --- 363,367 ---- #define IDENTIFIER_LABEL_VALUE(NODE) ((NODE)->identifier.label_value) #define IDENTIFIER_IMPLICIT_DECL(NODE) ((NODE)->identifier.implicit_decl) + #define IDENTIFIER_ERROR_LOCUS(NODE) ((NODE)->identifier.error_locus) struct tree_identifier *************** *** 366,369 **** --- 374,378 ---- union tree_node *label_value; union tree_node *implicit_decl; + union tree_node *error_locus; }; *************** *** 511,515 **** int frame_size; /* For FUNCTION_DECLs: size of stack frame */ struct rtx_def *saved_insns; /* For FUNCTION_DECLs: points to insn that ! constitute its definition on the permanent obstack. */ int block_symtab_address; --- 520,524 ---- int frame_size; /* For FUNCTION_DECLs: size of stack frame */ struct rtx_def *saved_insns; /* For FUNCTION_DECLs: points to insn that ! constitutes its definition on the permanent obstack. */ int block_symtab_address; diff -rc2N gcc-1.32/va-sparc.h gcc-1.33/va-sparc.h *** gcc-1.32/va-sparc.h Tue Dec 6 18:10:15 1988 --- gcc-1.33/va-sparc.h Wed Dec 31 19:00:00 1969 *************** *** 1,40 **** - /* varargs.h for SPARC. */ - - /* NB. This is NOT the definition needed for the new ANSI proposed - standard */ - - - struct __va_struct { char regs[24]; }; - - #define va_alist __va_regs, __va_stack - - #define va_dcl struct __va_struct __va_regs; int __va_stack; - - typedef int va_list; - - #define va_start(pvar) ((pvar) = 0) - - #define va_arg(pvar,type) \ - ({ type __va_result; \ - if ((pvar) >= 24) { \ - __va_result = *( (type *) (&__va_stack + ((pvar) - 24)/4)); \ - (pvar) += (sizeof(type) + 3) & ~3; \ - } \ - else if ((pvar) + sizeof(type) > 24) { \ - __va_result = * (type *) &__va_stack; \ - (pvar) = 24 + ( (sizeof(type) + 3) & ~3); \ - } \ - else if (sizeof(type) == 8) { \ - union {double d; int i[2];} __u; \ - __u.i[0] = *(int *) (__va_regs.regs + (pvar)); \ - __u.i[1] = *(int *) (__va_regs.regs + (pvar) + 4); \ - __va_result = * (type *) &__u; \ - (pvar) += (sizeof(type) + 3) & ~3; \ - } \ - else { \ - __va_result = * (type *) (__va_regs.regs + (pvar)); \ - (pvar) += (sizeof(type) + 3) & ~3; \ - } \ - __va_result; }) - - #define va_end(pvar) (pvar) --- 0 ---- diff -rc2N gcc-1.32/varargs.h gcc-1.33/varargs.h *** gcc-1.32/varargs.h Fri Aug 5 17:38:40 1988 --- gcc-1.33/varargs.h Mon Jan 23 03:48:21 1989 *************** *** 3,10 **** #include <varargs.h> #else ! #ifdef sparc ! #include "va-sparc.h" ! #else ! #ifdef spur #include "va-spur.h" #else --- 3,7 ---- #include <varargs.h> #else ! #ifdef __spur__ #include "va-spur.h" #else *************** *** 13,31 **** for GNU C. */ ! #define va_alist _varargs ! #define va_dcl int _varargs; #define va_list char * ! #define va_start(AP) AP=(char *) &_varargs #define va_end(AP) ! #define _va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) #define va_arg(AP, TYPE) \ ! (AP += _va_rounded_size (TYPE), \ ! *((TYPE *) (AP - _va_rounded_size (TYPE)))) #endif /* not spur */ - #endif /* not sparc */ #endif /* __GNUC__ */ --- 10,33 ---- for GNU C. */ ! #define va_alist __builtin_va_alist ! #define va_dcl int __builtin_va_alist; #define va_list char * ! #ifdef __sparc__ ! #define va_start(AP) \ ! (__builtin_saveregs (), \ ! AP = ((void *) &__builtin_va_alist)) ! #else ! #define va_start(AP) AP=(char *) &__builtin_va_alist ! #endif #define va_end(AP) ! #define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) #define va_arg(AP, TYPE) \ ! (AP += __va_rounded_size (TYPE), \ ! *((TYPE *) (AP - __va_rounded_size (TYPE)))) #endif /* not spur */ #endif /* __GNUC__ */ diff -rc2N gcc-1.32/varasm.c gcc-1.33/varasm.c *** gcc-1.32/varasm.c Tue Dec 6 21:36:47 1988 --- gcc-1.33/varasm.c Sat Jan 28 19:51:58 1989 *************** *** 1,4 **** /* Output variables, constants and external declarations, for GNU compiler. ! Copyright (C) 1987, 1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Output variables, constants and external declarations, for GNU compiler. ! Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 34,37 **** --- 34,38 ---- #include "flags.h" #include "expr.h" + #include "hard-reg-set.h" #include "obstack.h" *************** *** 59,62 **** --- 60,66 ---- int var_labelno; + /* Nonzero if at least one function definition has been seen. */ + static int function_defined; + extern FILE *asm_out_file; *************** *** 117,125 **** gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (DECL_NAME (decl)))); } ! /* Create the DECL_RTL for a declaration (either variable or function). ! ASMSPEC, if not 0, is the string ! which the user specified as the assembler symbol name. TOP_LEVEL is nonzero if this is a file-scope variable. */ --- 121,133 ---- gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (DECL_NAME (decl)))); + + /* Record at least one function has been defined. */ + function_defined = 1; } ! /* Create the DECL_RTL for a declaration for a static or external variable ! or static or external function. ! ASMSPEC, if not 0, is the string which the user specified ! as the assembler symbol name. TOP_LEVEL is nonzero if this is a file-scope variable. */ *************** *** 131,145 **** { register char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); if (asmspec != 0) { if (TREE_CODE (asmspec) != STRING_CST) abort (); ! name = (char *) obstack_alloc (saveable_obstack, ! strlen (TREE_STRING_POINTER (asmspec)) + 2); ! name[0] = '*'; ! strcpy (&name[1], TREE_STRING_POINTER (asmspec)); ! } /* For a duplicate declaration, we can be called twice on the same DECL node. Don't alter the RTL already made --- 139,168 ---- { register char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); + int reg_number = -1; if (asmspec != 0) { + int i; + extern char *reg_names[]; + if (TREE_CODE (asmspec) != STRING_CST) abort (); ! for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! if (!strcmp (TREE_STRING_POINTER (asmspec), ! reg_names[i])) ! break; + if (i < FIRST_PSEUDO_REGISTER) + reg_number = i; + else + { + name = (char *) obstack_alloc (saveable_obstack, + strlen (TREE_STRING_POINTER (asmspec)) + 2); + name[0] = '*'; + strcpy (&name[1], TREE_STRING_POINTER (asmspec)); + reg_number = -2; + } + } + /* For a duplicate declaration, we can be called twice on the same DECL node. Don't alter the RTL already made *************** *** 149,177 **** || GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl)) { ! if (DECL_RTL (decl) && asmspec == 0) ! name = XSTR (XEXP (DECL_RTL (decl), 0), 0); ! /* Can't use just the variable's own name for a variable ! whose scope is less than the whole file. ! Concatenate a distinguishing number. */ ! else if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0) ! { ! char *label; ! ! ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); ! name = obstack_copy0 (saveable_obstack, label, strlen (label)); ! var_labelno++; ! } ! ! DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), ! gen_rtx (SYMBOL_REF, Pmode, name)); ! if (TREE_VOLATILE (decl)) ! MEM_VOLATILE_P (DECL_RTL (decl)) = 1; ! if (TREE_READONLY (decl)) ! RTX_UNCHANGING_P (DECL_RTL (decl)) = 1; ! MEM_IN_STRUCT_P (DECL_RTL (decl)) ! = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE ! || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE ! || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE); } } --- 172,243 ---- || GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl)) { ! DECL_RTL (decl) = 0; ! ! /* First detect errors in declaring global registers. */ ! if (TREE_REGDECL (decl) && reg_number == -1) ! error_with_decl (decl, ! "register name not specified for `%s'"); ! if (TREE_REGDECL (decl) && reg_number == -2) ! error_with_decl (decl, ! "invalid register name for `%s'"); ! else if (reg_number >= 0 && ! TREE_REGDECL (decl)) ! error_with_decl (decl, ! "register name given for non-register variable `%s'"); ! else if (TREE_REGDECL (decl) && TREE_CODE (decl) == FUNCTION_DECL) ! error ("function declared `register'"); ! else if (TREE_REGDECL (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode) ! error_with_decl (decl, "data type of `%s' isn't suitable for a register"); ! /* Now handle properly declared static register variables. */ ! else if (TREE_REGDECL (decl)) ! { ! int nregs; ! if (pedantic) ! warning ("ANSI C forbids global register variables"); ! if (DECL_INITIAL (decl) != 0) ! { ! DECL_INITIAL (decl) = 0; ! error ("global register variable has initial value"); ! } ! if (fixed_regs[reg_number] == 0 ! && function_defined) ! error ("global register variable follows a function definition"); ! DECL_RTL (decl) = gen_rtx (REG, DECL_MODE (decl), reg_number); ! /* Make this register fixed, so not usable for anything else. */ ! nregs = HARD_REGNO_NREGS (reg_number, DECL_MODE (decl)); ! while (nregs > 0) ! global_regs[reg_number + --nregs] = 1; ! init_reg_sets_1 (); ! } ! ! /* Now handle ordinary static variables and functions (in memory). ! Also handle vars declared register invalidly. */ ! if (DECL_RTL (decl) == 0) ! { ! if (DECL_RTL (decl) && asmspec == 0) ! name = XSTR (XEXP (DECL_RTL (decl), 0), 0); ! ! /* Can't use just the variable's own name for a variable ! whose scope is less than the whole file. ! Concatenate a distinguishing number. */ ! else if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0) ! { ! char *label; ! ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); ! name = obstack_copy0 (saveable_obstack, label, strlen (label)); ! var_labelno++; ! } ! ! DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), ! gen_rtx (SYMBOL_REF, Pmode, name)); ! if (TREE_VOLATILE (decl)) ! MEM_VOLATILE_P (DECL_RTL (decl)) = 1; ! if (TREE_READONLY (decl)) ! RTX_UNCHANGING_P (DECL_RTL (decl)) = 1; ! MEM_IN_STRUCT_P (DECL_RTL (decl)) ! = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE ! || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE ! || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE); ! } } } *************** *** 271,277 **** int at_end; { ! register char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); register int i; /* Normally no need to say anything for external references, since assembler considers all undefined symbols external. */ --- 337,348 ---- int at_end; { ! register char *name; register int i; + /* Do nothing for global register variables. */ + + if (GET_CODE (DECL_RTL (decl)) == REG) + return; + /* Normally no need to say anything for external references, since assembler considers all undefined symbols external. */ *************** *** 335,338 **** --- 406,411 ---- app_disable (); + name = XSTR (XEXP (DECL_RTL (decl), 0), 0); + /* Handle uninitialized definitions. */ *************** *** 347,350 **** --- 420,425 ---- / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); + if (flag_shared_data) + data_section (); if (TREE_PUBLIC (decl)) ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded); *************** *** 440,446 **** /* Chain of all CONST_DOUBLE rtx's constructed for the current function. ! They are chained through the third operand slot, XEXP (r, 3). ! A CONST_DOUBLE rtx has XEXP (r, 2) != cc0_rtx iff it is on this chain. ! XEXP (r, 2) is either a MEM, or const0_rtx if no MEM has been made. */ static rtx real_constant_chain; --- 515,522 ---- /* Chain of all CONST_DOUBLE rtx's constructed for the current function. ! They are chained through the CONST_DOUBLE_CHAIN. ! A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain. ! In that case, CONST_DOUBLE_MEM is either a MEM, ! or const0_rtx if no MEM has been made for this CONST_DOUBLE yet. */ static rtx real_constant_chain; *************** *** 455,463 **** register rtx r; /* Search the chain for an existing CONST_DOUBLE with the right value. If one is found, return it. */ ! for (r = real_constant_chain; r; r = XEXP (r, 3)) ! if (XINT (r, 0) == i0 && XINT (r, 1) == i1 && GET_MODE (r) == mode) return r; --- 531,542 ---- register rtx r; + if (mode == DImode && i0 == 0 && i1 == 0) + return const0_rtx; + /* Search the chain for an existing CONST_DOUBLE with the right value. If one is found, return it. */ ! for (r = real_constant_chain; r; r = CONST_DOUBLE_CHAIN (r)) ! if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1 && GET_MODE (r) == mode) return r; *************** *** 465,482 **** /* No; make a new one and add it to the chain. */ ! r = gen_rtx (CONST_DOUBLE, mode, i0, i1, 0); ! ! /* If a one-word int was allocated for the value, ! just return it. */ ! if (GET_CODE (r) == CONST_INT) ! return r; ! XEXP (r, 3) = real_constant_chain; real_constant_chain = r; ! /* Store const0_rtx in slot 2 since this CONST_DOUBLE is on the chain. ! Actual use of slot 2 is only through force_const_double_mem. */ ! XEXP (r, 2) = const0_rtx; return r; --- 544,556 ---- /* No; make a new one and add it to the chain. */ ! r = gen_rtx (CONST_DOUBLE, mode, 0, i0, i1); ! CONST_DOUBLE_CHAIN (r) = real_constant_chain; real_constant_chain = r; ! /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain. ! Actual use of mem-slot is only through force_const_double_mem. */ ! CONST_DOUBLE_MEM (r) = const0_rtx; return r; *************** *** 488,497 **** rtx immed_real_const_1 (d, mode) ! double d; enum machine_mode mode; { ! union {double d; int i[2];} u; ! /* Get the desired `double' value as two ints since that is how they are stored in a CONST_DOUBLE. */ --- 562,573 ---- rtx immed_real_const_1 (d, mode) ! REAL_VALUE_TYPE d; enum machine_mode mode; { ! union real_extract u; ! register rtx r; ! REAL_VALUE_TYPE negated; ! /* Get the desired `double' value as a sequence of ints since that is how they are stored in a CONST_DOUBLE. */ *************** *** 498,502 **** u.d = d; ! return immed_double_const (u.i[0], u.i[1], mode); } --- 574,613 ---- u.d = d; ! /* Detect zero. */ ! ! negated = REAL_VALUE_NEGATE (d); ! if (REAL_VALUES_EQUAL (negated, d)) ! return (mode == DFmode ? dconst0_rtx : fconst0_rtx); ! ! if (sizeof u == 2 * sizeof (int)) ! return immed_double_const (u.i[0], u.i[1], mode); ! ! /* The rest of this function handles the case where ! a float value requires more than 2 ints of space. ! It will be deleted as dead code on machines that don't need it. */ ! ! /* Search the chain for an existing CONST_DOUBLE with the right value. ! If one is found, return it. */ ! ! for (r = real_constant_chain; r; r = CONST_DOUBLE_CHAIN (r)) ! if (! bcmp (&CONST_DOUBLE_LOW (r), &u, sizeof u) ! && GET_MODE (r) == mode) ! return r; ! ! /* No; make a new one and add it to the chain. */ ! ! r = rtx_alloc (CONST_DOUBLE); ! PUT_MODE (r, mode); ! bcopy (&u, &CONST_DOUBLE_LOW (r), sizeof u); ! ! CONST_DOUBLE_CHAIN (r) = real_constant_chain; ! real_constant_chain = r; ! ! /* Store const0_rtx in slot 2 since this CONST_DOUBLE is on the chain. ! Actual use of slot 2 is only through force_const_double_mem. */ ! ! CONST_DOUBLE_MEM (r) = const0_rtx; ! ! return r; } *************** *** 520,540 **** rtx r; { ! if (XEXP (r, 2) == cc0_rtx) { ! XEXP (r, 3) = real_constant_chain; real_constant_chain = r; ! XEXP (r, 2) = const0_rtx; } ! if (XEXP (r, 2) == const0_rtx) { ! XEXP (r, 2) = force_const_mem (GET_MODE (r), r); } ! /* XEXP (r, 2) is now a MEM with a constant address. If that is legitimate, return it. Othewise it will need reloading, so return a copy of it. */ ! if (memory_address_p (GET_MODE (r), XEXP (XEXP (r, 2), 0))) ! return XEXP (r, 2); ! return gen_rtx (MEM, GET_MODE (r), XEXP (XEXP (r, 2), 0)); } --- 631,651 ---- rtx r; { ! if (CONST_DOUBLE_MEM (r) == cc0_rtx) { ! CONST_DOUBLE_CHAIN (r) = real_constant_chain; real_constant_chain = r; ! CONST_DOUBLE_MEM (r) = const0_rtx; } ! if (CONST_DOUBLE_MEM (r) == const0_rtx) { ! CONST_DOUBLE_MEM (r) = force_const_mem (GET_MODE (r), r); } ! /* CONST_DOUBLE_MEM (r) is now a MEM with a constant address. If that is legitimate, return it. Othewise it will need reloading, so return a copy of it. */ ! if (memory_address_p (GET_MODE (r), XEXP (CONST_DOUBLE_MEM (r), 0))) ! return CONST_DOUBLE_MEM (r); ! return gen_rtx (MEM, GET_MODE (r), XEXP (CONST_DOUBLE_MEM (r), 0)); } *************** *** 550,556 **** for (r = real_constant_chain; r; r = next) { ! next = XEXP (r, 3); ! XEXP (r, 3) = 0; ! XEXP (r, 2) = cc0_rtx; } real_constant_chain = 0; --- 661,667 ---- for (r = real_constant_chain; r; r = next) { ! next = CONST_DOUBLE_CHAIN (r); ! CONST_DOUBLE_CHAIN (r) = 0; ! CONST_DOUBLE_MEM (r) = cc0_rtx; } real_constant_chain = 0; *************** *** 1016,1020 **** enum machine_mode mode : 16; union { ! int d[2]; struct addr_const addr; } un; --- 1127,1131 ---- enum machine_mode mode : 16; union { ! union real_extract du; struct addr_const addr; } un; *************** *** 1031,1038 **** struct rtx_const *value; { value->kind = RTX_INT; /* Most usual kind. */ value->mode = mode; - value->un.addr.base = 0; - value->un.addr.offset = 0; switch (GET_CODE (x)) --- 1142,1156 ---- struct rtx_const *value; { + /* Clear the whole structure, including any gaps. */ + + { + int *p = (int *) value; + int *end = (int *) (value + 1); + while (p < end) + *p++ = 0; + } + value->kind = RTX_INT; /* Most usual kind. */ value->mode = mode; switch (GET_CODE (x)) *************** *** 1041,1046 **** value->kind = RTX_DOUBLE; value->mode = GET_MODE (x); ! value->un.d[0] = XINT (x, 0); ! value->un.d[1] = XINT (x, 1); break; --- 1159,1163 ---- value->kind = RTX_DOUBLE; value->mode = GET_MODE (x); ! bcopy (&CONST_DOUBLE_LOW (x), &value->un.du, sizeof value->un.du); break; *************** *** 1178,1181 **** --- 1295,1302 ---- rtx def; + if (GET_CODE (x) == CONST_DOUBLE + && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM) + return CONST_DOUBLE_MEM (x); + /* Compute hash code of X. Search the descriptors for that hash code to see if any of them describes X. If yes, the descriptor records *************** *** 1223,1230 **** if (GET_CODE (x) == CONST_DOUBLE) { ! union {double d; int i[2];} u; ! u.i[0] = XINT (x, 0); ! u.i[1] = XINT (x, 1); switch (mode) { --- 1344,1350 ---- if (GET_CODE (x) == CONST_DOUBLE) { ! union real_extract u; ! bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u); switch (mode) { *************** *** 1278,1281 **** --- 1398,1411 ---- CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1; + if (GET_CODE (x) == CONST_DOUBLE) + { + if (CONST_DOUBLE_MEM (x) == cc0_rtx) + { + CONST_DOUBLE_CHAIN (x) = real_constant_chain; + real_constant_chain = x; + } + CONST_DOUBLE_MEM (x) = def; + } + return def; } *************** *** 1459,1462 **** --- 1589,1594 ---- = (unsigned char *) TREE_STRING_POINTER (exp); int excess = 0; + int pos = 0; + int maximum = 2000; if (size > TREE_STRING_LENGTH (exp)) *************** *** 1466,1496 **** } #ifdef ASM_OUTPUT_ASCII ! ASM_OUTPUT_ASCII (asm_out_file, p, size); #else ! fprintf (asm_out_file, "\t.ascii \""); ! for (i = 0; i < size; i++) ! { ! register int c = p[i]; ! if (c == '\"' || c == '\\') ! putc ('\\', asm_out_file); ! if (c >= ' ' && c < 0177) ! putc (c, asm_out_file); ! else { ! fprintf (asm_out_file, "\\%o", c); ! /* After an octal-escape, if a digit follows, ! terminate one string constant and start another. ! The Vax assembler fails to stop reading the escape ! after three digits, so this is the only way we ! can get it to parse the data properly. */ ! if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9') ! fprintf (asm_out_file, "\"\n\t.ascii \""); } ! } ! fprintf (asm_out_file, "\"\n"); #endif /* no ASM_OUTPUT_ASCII */ size = excess; } --- 1598,1640 ---- } + /* If the string is very long, split it up. */ + + while (pos < size) + { + int thissize = size - pos; + if (thissize > maximum) + thissize = maximum; + #ifdef ASM_OUTPUT_ASCII ! ASM_OUTPUT_ASCII (asm_out_file, p, thissize); #else ! fprintf (asm_out_file, "\t.ascii \""); ! for (i = 0; i < thissize; i++) { ! register int c = p[i]; ! if (c == '\"' || c == '\\') ! putc ('\\', asm_out_file); ! if (c >= ' ' && c < 0177) ! putc (c, asm_out_file); ! else ! { ! fprintf (asm_out_file, "\\%o", c); ! /* After an octal-escape, if a digit follows, ! terminate one string constant and start another. ! The Vax assembler fails to stop reading the escape ! after three digits, so this is the only way we ! can get it to parse the data properly. */ ! if (i < thissize - 1 ! && p[i + 1] >= '0' && p[i + 1] <= '9') ! fprintf (asm_out_file, "\"\n\t.ascii \""); ! } } ! fprintf (asm_out_file, "\"\n"); #endif /* no ASM_OUTPUT_ASCII */ + pos += thissize; + p += thissize; + } size = excess; } diff -rc2N gcc-1.32/version.c gcc-1.33/version.c *** gcc-1.32/version.c Wed Dec 21 23:17:57 1988 --- gcc-1.33/version.c Wed Feb 1 21:34:59 1989 *************** *** 1,1 **** ! char *version_string = "1.32"; --- 1,1 ---- ! char *version_string = "1.33"; diff -rc2N gcc-1.32/xm-alliant.h gcc-1.33/xm-alliant.h *** gcc-1.32/xm-alliant.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/xm-alliant.h Thu Dec 22 16:25:38 1988 *************** *** 0 **** --- 1,43 ---- + /* Configuration for GNU C-compiler for Alliant computer. + Copyright (C) 1987 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + + /* #defines that need visibility everywhere. */ + #define FALSE 0 + #define TRUE 1 + + /* This describes the machine the compiler is hosted on. */ + #define HOST_BITS_PER_CHAR 8 + #define HOST_BITS_PER_SHORT 16 + #define HOST_BITS_PER_INT 32 + #define HOST_BITS_PER_LONG 32 + + /* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + #include "tm.h" + + /* Arguments to use with `exit'. */ + #define SUCCESS_EXIT_CODE 0 + #define FATAL_EXIT_CODE 33 + + /* If compiled with GNU C, use the built-in alloca */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #endif diff -rc2N gcc-1.32/xm-convex.h gcc-1.33/xm-convex.h *** gcc-1.32/xm-convex.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/xm-convex.h Thu Jan 19 13:43:24 1989 *************** *** 0 **** --- 1,43 ---- + /* Configuration for GNU C-compiler for Convex. + Copyright (C) 1987 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + /* #defines that need visibility everywhere. */ + #define FALSE 0 + #define TRUE 1 + + /* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + #include "tm.h" + + /* This describes the machine the compiler is hosted on. */ + #define HOST_BITS_PER_CHAR 8 + #define HOST_BITS_PER_SHORT 16 + #define HOST_BITS_PER_INT 32 + #define HOST_BITS_PER_LONG 32 + + /* Arguments to use with `exit'. */ + #define SUCCESS_EXIT_CODE 0 + #define FATAL_EXIT_CODE 33 + + /* If compiled with GNU C, use the built-in alloca */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #endif + diff -rc2N gcc-1.32/xm-mips.h gcc-1.33/xm-mips.h *** gcc-1.32/xm-mips.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/xm-mips.h Sat Jan 21 16:20:34 1989 *************** *** 0 **** --- 1,34 ---- + /* Configuration for GNU C-compiler for MIPS Rx000 family + Copyright (C) 1987 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + + /* #defines that need visibility everywhere. */ + #define FALSE 0 + #define TRUE 1 + + /* This describes the machine the compiler is hosted on. */ + #define HOST_BITS_PER_CHAR 8 + #define HOST_BITS_PER_SHORT 16 + #define HOST_BITS_PER_INT 32 + #define HOST_BITS_PER_LONG 32 + + /* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + #include "tm.h" diff -rc2N gcc-1.32/xm-umips.h gcc-1.33/xm-umips.h *** gcc-1.32/xm-umips.h Wed Dec 31 19:00:00 1969 --- gcc-1.33/xm-umips.h Sat Jan 21 16:21:06 1989 *************** *** 0 **** --- 1,45 ---- + /* Configuration for GNU C-compiler for UMIPS operating system + Copyright (C) 1987 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU CC General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU CC, but only under the conditions described in the + GNU CC General Public License. A copy of this license is + supposed to have been given to you along with GNU CC so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + + /* + * Notes for compiling gcc on umips (v3.0) + * - change the -g in the CFLAGS to a -g3 or take it out all together. + * - do not define DBX_DEBUGGING_INFO in tm.h, it doesn't exist (unless + * you get one from a bsd system) + */ + #include "xm-mips.h" + + /* Arguments to use with `exit'. */ + #define SUCCESS_EXIT_CODE 0 + #define FATAL_EXIT_CODE 33 + + /* If compiled with GNU C, use the built-in alloca */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #endif + + #define USG + + /* for the emacs version of alloca */ + #define STACK_DIRECTION -1 + + #define bcopy(a,b,c) memcpy((b),(a),(c)) + #define bzero(a,b) memset((a),0,(b)) + #define bcmp(a,b,c) memcmp((a),(b),(c)) diff -rc2N gcc-1.32/xm-vms.h gcc-1.33/xm-vms.h *** gcc-1.32/xm-vms.h Sat Jul 2 10:53:16 1988 --- gcc-1.33/xm-vms.h Sun Jan 22 16:18:11 1989 *************** *** 50,51 **** --- 50,55 ---- #define unlink delete #endif + + /* global const variables don't work, + so turn off const-ness to prevent trouble with insn-output.c. */ + #define const