From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 37862 invoked by alias); 27 Jun 2018 22:01:55 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 37825 invoked by uid 89); 27 Jun 2018 22:01:54 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_LOW,SPF_PASS,TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=oo, nn, lives, bis X-HELO: resqmta-po-05v.sys.comcast.net Received: from resqmta-po-05v.sys.comcast.net (HELO resqmta-po-05v.sys.comcast.net) (96.114.154.164) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 27 Jun 2018 22:01:43 +0000 Received: from resomta-po-01v.sys.comcast.net ([96.114.154.225]) by resqmta-po-05v.sys.comcast.net with ESMTP id YHkXf6QQ6LBozYIVRf9lWB; Wed, 27 Jun 2018 22:01:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcast.net; s=q20161114; t=1530136901; bh=p5b3eAwYdIsSBucr/UjOjXsz7PM61GuCAAec0Xxgdu8=; h=Received:Received:From:Content-Type:Mime-Version:Subject: Message-Id:Date:To; b=gE0r/QGr0RZeyFPTSS7umGHXaVhdNS1T3OOLTToLgVWmG5MgC/1cKORym312an18/ pi3JEbq0TLwj97tJXrTXJnQTJxC0FYoFQRg1snA7ij241/enaIfWwBu3J4OSJCtrhv Z/xIr0oz6BWcR22JaJWwThWtLYlYwwIcQNOPh+UBTtZpTR3jbIZWeQ7rrihGB0iXEW U9Q8a0jrP2CLXMc14af+kcXUgJBHZe8fCahAwtbmtjhlPgtjixltgK7u3ioPUsjCI0 cRqzuKZa1hsTmsOy3VEMNnmqYaTW13Z/z61zPcnz0oSpPkvhpTDzFm7WWd9PVcj4dO Zq75eqHVqsUPA== Received: from [192.168.10.125] ([73.60.223.101]) by resomta-po-01v.sys.comcast.net with ESMTPA id YIVQfs2RIVGSOYIVRfIMRU; Wed, 27 Jun 2018 22:01:41 +0000 From: Paul Koning Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 11.4 \(3445.8.2\)) Subject: [PATCH, committed] Convert pdp11 back end to CCmode Message-Id: <687E4329-7FAF-4DA5-9580-B9B927C2263F@comcast.net> Date: Wed, 27 Jun 2018 22:01:00 -0000 To: GCC Patches X-SW-Source: 2018-06/txt/msg01729.txt.bz2 This change converts the pdp11 back end to use CCmode rather than cc0. It = is functional and the testsuite compile sections runs at least as well as b= efore. There is additional work left to be done; for example, the compare eliminat= ion pass, which this target uses, does not know how to deal with a machine = that has two condition code registers. Committed. paul ChangeLog: 2018-06-27 Paul Koning * common/config/pdp11/pdp11-common.c (pdp11_handle_option): Handle mutually exclusive options. * config/pdp11/constraints.md (h): New constraint. (O): Update definition to match shift code generation. (D): New constraint. * config/pdp11/pdp11-modes.def (CCNZ): Define mode. (CCFP): Remove. * config/pdp11/pdp11-protos.h (int_no_side_effect_operand): New function. (output_jump): Change arguments. (pdp11_fixed_cc_regs): New function. (pdp11_cc_mode): Ditto. (pdp11_expand_shift): Ditto. (pdp11_assemble_shift): Ditto. (pdp11_small_shift): Ditto. (pdp11_branch_cost): Remove. * config/pdp11/pdp11.c (pdp11_assemble_integer): Remove comments from output. (pdp11_register_move_cost): Update for CC registers. (pdp11_rtx_costs): Add case for LSHIFTRT. (pdp11_output_jump): Add CCNZ mode conditional branches. (notice_update_cc_on_set): Remove. (pdp11_cc_mode): New function. (simple_memory_operand): Correct pre/post decrement case. (no_side_effect_operand): New function. (pdp11_regno_reg_class): Add CC_REGS class. (pdp11_fixed_cc_regs): New function. (pdp11_small_shift): New function. (pdp11_expand_shift): New function to expand shift insns. (pdp11_assemble_shift): New function to output shifts. (pdp11_branch_cost): Remove. (pdp11_modes_tieable_p): Make QI/HI modes tieable. * config/pdp11/pdp11.h (SIZE_TYPE): Ensure 16-bit type. (WCHAR_TYPE): Ditto. (PTRDIFF_TYPE): Ditto. (ADJUST_INSN_LENGTH): New macro. (FIXED_REGISTERS): Add CC registers. (CALL_USED_REGISTERS): Ditto. (reg_class): Ditto. (REG_CLASS_NAMES): Ditto. (REG_CLASS_CONTENTS): Ditto. (SELECT_CC_MODE): Use new function. (TARGET_FLAGS_REGNUM): New macro. (TARGET_FIXED_CONDITION_CODE_REGS): Ditto. (cc0_reg_rtx): Remove. (CC_STATUS_MDEP): Remove. (CC_STATUS_MDEFP_INIT): Remove. (CC_IN_FPU): Remove. (NOTICE_UPDATE_CC): Remove. (REGISTER_NAMES): Add CC registers. (BRANCH_COST): Change to constant 1. * config/pdp11/pdp11.md: Rewrite for CCmode condition code handling. * config/pdp11/pdp11.opt (mbcopy): Remove. (mbcopy-builtin): Remove. (mbranch-cheap): Remove. (mbranch-expensive): Remove. * config/pdp11/predicates.md (expand_shift_operand): Update to match shift code generation. (ccnz_operator): New predicate. * doc/invoke.texi (PDP-11 Options): Remove deleted options -mbcopy, -mbcopy-builtin, -mbranch-cheap, -mbranch-expensive. Remove non-existent option -mabshi, -mno-abshi. Document mutually exclusive options. * doc/md.texi (PDP-11): Document new D and h constraints. Update description of O constraint. Index: common/config/pdp11/pdp11-common.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- common/config/pdp11/pdp11-common.c (revision 262195) +++ common/config/pdp11/pdp11-common.c (working copy) @@ -39,9 +39,27 @@ pdp11_handle_option (struct gcc_options *opts, switch (code) { case OPT_m10: - opts->x_target_flags &=3D ~(MASK_40 | MASK_45); + opts->x_target_flags &=3D ~(MASK_40 | MASK_45 | MASK_FPU | MASK_AC0 = | MASK_SPLIT); return true; =20 + case OPT_m40: + opts->x_target_flags &=3D ~(MASK_45 | MASK_FPU | MASK_AC0 | MASK_SPL= IT); + return true; + + case OPT_mfpu: + opts->x_target_flags &=3D ~MASK_40; + opts->x_target_flags |=3D MASK_45; + return true; +=20=20=20=20=20=20 + case OPT_msoft_float: + opts->x_target_flags &=3D ~MASK_AC0; + return true; + + case OPT_msplit: + opts->x_target_flags &=3D ~MASK_40; + opts->x_target_flags |=3D MASK_45; + return true; +=20=20=20=20=20=20 default: return true; } Index: config/pdp11/constraints.md =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/constraints.md (revision 262195) +++ config/pdp11/constraints.md (working copy) @@ -18,11 +18,14 @@ ;; along with GCC; see the file COPYING3. If not see ;; . =20 +(define_register_constraint "a" "LOAD_FPU_REGS" + "FPU register that can be directly loaded from memory") + (define_register_constraint "f" "FPU_REGS" "Any FPU register") =20 -(define_register_constraint "a" "LOAD_FPU_REGS" - "FPU register that can be directly loaded from memory") +(define_register_constraint "h" "NO_LOAD_FPU_REGS" + "FPU register that cannot be directly loaded from memory") =20 (define_register_constraint "d" "MUL_REGS" "General register that can be used for 16-bit multiply (odd numbered)") @@ -60,7 +63,7 @@ (define_constraint "O" "Integer constant for which several individual shifts are better than on= e big one" (and (match_code "const_int") - (match_test "abs (ival) > 1 && abs (ival) <=3D 4"))) + (match_test "pdp11_small_shift (ival)"))) =20 (define_constraint "G" "Defines a real zero constant." @@ -79,3 +82,9 @@ (match_test "memory_address_p (GET_MODE (op), XEXP (op, 0)) && simple_memory_operand (op, GET_MODE (op))"))) =20 +(define_constraint "D" + "Memory reference that is encoded within the opcode, and not push or pop" + (and (match_code "mem") + (match_test "memory_address_p (GET_MODE (op), XEXP (op, 0)) + && no_side_effect_operand (op, GET_MODE (op))"))) + Index: config/pdp11/pdp11-modes.def =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/pdp11-modes.def (revision 262195) +++ config/pdp11/pdp11-modes.def (working copy) @@ -19,8 +19,26 @@ along with GCC; see the file COPYING3. If not see . */ =20 /* Add any extra modes needed to represent the condition code. - CCFPmode is used for FPU, but should we use a separate reg? */ =20 -CC_MODE (CCFP); + The default CCmode is the CPU condition codes, as set by compare; + all conditional branches are valid with this. + + CCNZmode is the CPU condition code as a side effect of arithmetic + or logic operations where N and Z reflect sign and zero status of + the result, but the V bit is not meaningful. Unsigned conditional + branches don't apply then (no such thing when comparing with zero) + and signed branches that use V need to clear V first if they are to + be used. CCNZ mode appears in side effects (implicit compare with + zero) if V is not forced to 0 by the instruction. In such cases, V + often reflects signed overflow of the operation, which means a + signed branch will get the sign backwards. This applies both to + some float and integer operations. + + These modes are used both in the FPU and the CPU, since they have + the same meaning, and also because the FPU condition codes are + copied to the CPU before being used in conditional branches. */ + +CC_MODE (CCNZ); + RESET_FLOAT_FORMAT (SF, pdp11_f_format); RESET_FLOAT_FORMAT (DF, pdp11_d_format); Index: config/pdp11/pdp11-protos.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/pdp11-protos.h (revision 262195) +++ config/pdp11/pdp11-protos.h (working copy) @@ -21,21 +21,27 @@ along with GCC; see the file COPYING3. If not see /* declarations */ #ifdef RTX_CODE extern int simple_memory_operand (rtx, machine_mode); - +extern int no_side_effect_operand (rtx, machine_mode); extern int legitimate_const_double_p (rtx); extern void notice_update_cc_on_set (rtx, rtx); extern void output_addr_const_pdp11 (FILE *, rtx); extern const char *output_move_multiple (rtx *); extern const char *output_block_move (rtx *); -extern const char *output_jump (enum rtx_code, int, int); +extern const char *output_jump (rtx *, int, int); extern void print_operand_address (FILE *, rtx); typedef enum { no_action, dec_before, inc_after } pdp11_action; typedef enum { little, either, big } pdp11_partorder; -extern bool pdp11_expand_operands (rtx *, rtx [][2], int,=20 +extern bool pdp11_expand_operands (rtx *, rtx [][2], int, pdp11_action *, pdp11_partorder); extern int pdp11_sp_frame_offset (void); extern int pdp11_initial_elimination_offset (int, int); extern enum reg_class pdp11_regno_reg_class (int); +extern bool pdp11_fixed_cc_regs (unsigned int *, unsigned int *); +extern machine_mode pdp11_cc_mode (enum rtx_code, rtx, rtx); +extern bool pdp11_expand_shift (rtx *, rtx (*) (rtx, rtx, rtx), + rtx (*) (rtx, rtx, rtx)); +extern const char * pdp11_assemble_shift (rtx *, machine_mode, int); +extern bool pdp11_small_shift (int); =20 #endif /* RTX_CODE */ =20 @@ -43,5 +49,4 @@ extern void output_ascii (FILE *, const char *, in extern void pdp11_asm_output_var (FILE *, const char *, int, int, bool); extern void pdp11_expand_prologue (void); extern void pdp11_expand_epilogue (void); -extern int pdp11_branch_cost (void); extern poly_int64 pdp11_push_rounding (poly_int64); Index: config/pdp11/pdp11.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/pdp11.c (revision 262195) +++ config/pdp11/pdp11.c (working copy) @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "builtins.h" #include "dbxout.h" +#include "expmed.h" =20 /* This file should be included last. */ #include "target-def.h" @@ -146,9 +147,6 @@ decode_pdp11_d (const struct real_format *fmt ATTR (*vax_d_format.decode) (fmt, r, tbuf); } =20 -/* This is where the condition code register lives. */ -/* rtx cc0_reg_rtx; - no longer needed? */ - static const char *singlemove_string (rtx *); static bool pdp11_assemble_integer (rtx, unsigned int, int); static bool pdp11_rtx_costs (rtx, machine_mode, int, int, int *, bool); @@ -384,7 +382,7 @@ pdp11_expand_epilogue (void) emit_move_insn (reg, x); else { - emit_move_insn (via_ac, x); + emit_move_insn (via_ac, x); emit_move_insn (reg, via_ac); } } @@ -872,14 +870,13 @@ pdp11_assemble_integer (rtx x, unsigned int size, case 1: fprintf (asm_out_file, "\t.byte\t"); output_addr_const_pdp11 (asm_out_file, GEN_INT (INTVAL (x) & 0xff)); -; - fprintf (asm_out_file, " /* char */\n"); + fputs ("\n", asm_out_file); return true; =20 case 2: fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t"); output_addr_const_pdp11 (asm_out_file, x); - fprintf (asm_out_file, " /* short */\n"); + fputs ("\n", asm_out_file); return true; } return default_assemble_integer (x, size, aligned_p); @@ -886,34 +883,27 @@ pdp11_assemble_integer (rtx x, unsigned int size, } =20 =20 -/* register move costs, indexed by regs */ - -static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =3D=20 -{ - /* NO MUL GEN LFPU NLFPU FPU ALL */ - -/* NO */ { 0, 0, 0, 0, 0, 0, 0}, -/* MUL */ { 0, 2, 2, 22, 22, 22, 22}, -/* GEN */ { 0, 2, 2, 22, 22, 22, 22}, -/* LFPU */ { 0, 22, 22, 2, 2, 2, 22}, -/* NLFPU */ { 0, 22, 22, 2, 10, 10, 22}, -/* FPU */ { 0, 22, 22, 2, 10, 10, 22}, -/* ALL */ { 0, 22, 22, 22, 22, 22, 22} -} ; - - -/* -- note that some moves are tremendously expensive,=20 - because they require lots of tricks! do we have to=20 - charge the costs incurred by secondary reload class=20 - -- as we do here with 10 -- or not ? */ - +/* Register to register moves are cheap if both are general registers. + The same is true for FPU, but there we return cost of 3 rather than + 2 to make reload look at the constraints. The raeson is that + load/store double require extra care since load touches condition + codes and store doesn't, which is (partly anyway) described by + constraints. */ static int=20 pdp11_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, reg_class_t c1, reg_class_t c2) { - return move_costs[(int)c1][(int)c2]; + if (((c1 =3D=3D MUL_REGS || c1 =3D=3D GENERAL_REGS) && + (c2 =3D=3D MUL_REGS || c2 =3D=3D GENERAL_REGS))) + return 2; + else if ((c1 >=3D LOAD_FPU_REGS && c1 <=3D FPU_REGS && c2 =3D=3D LOAD_FP= U_REGS) || + (c2 >=3D LOAD_FPU_REGS && c2 <=3D FPU_REGS && c1 =3D=3D LOAD_FPU_REGS)) + return 3; + else + return 22; } =20 + static bool pdp11_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED, int opno ATTRIBUTE_UNUSED, int *total, @@ -988,7 +978,6 @@ pdp11_rtx_costs (rtx x, machine_mode mode, int out return false; =20 case ASHIFT: - case LSHIFTRT: case ASHIFTRT: if (optimize_size) *total =3D COSTS_N_INSNS (1); @@ -1020,6 +1009,37 @@ pdp11_rtx_costs (rtx x, machine_mode mode, int out } return false; =20 + case LSHIFTRT: + if (optimize_size) + *total =3D COSTS_N_INSNS (2); + else if (mode =3D=3D QImode) + { + if (GET_CODE (XEXP (x, 1)) !=3D CONST_INT) + *total =3D COSTS_N_INSNS (12); /* worst case */ + else + *total =3D COSTS_N_INSNS (1 + INTVAL (XEXP (x, 1))); + } + else if (mode =3D=3D HImode) + { + if (GET_CODE (XEXP (x, 1)) =3D=3D CONST_INT) + { + if (abs (INTVAL (XEXP (x, 1))) =3D=3D 1) + *total =3D COSTS_N_INSNS (2); + else + *total =3D COSTS_N_INSNS (3.5 + 0.5 * INTVAL (XEXP (x, 1))); + } + else + *total =3D COSTS_N_INSNS (12); /* worst case */ + } + else if (mode =3D=3D SImode) + { + if (GET_CODE (XEXP (x, 1)) =3D=3D CONST_INT) + *total =3D COSTS_N_INSNS (3.5 + 0.5 * INTVAL (XEXP (x, 1))); + else /* worst case */ + *total =3D COSTS_N_INSNS (20); + } + return false; + default: return false; } @@ -1026,108 +1046,97 @@ pdp11_rtx_costs (rtx x, machine_mode mode, int out } =20 const char * -output_jump (enum rtx_code code, int inv, int length) +output_jump (rtx *operands, int ccnz, int length) { - static int x =3D 0; -=20=20=20=20 - static char buf[1000]; - const char *pos, *neg; + rtx tmpop[1]; + static char buf[100]; + const char *pos, *neg; + enum rtx_code code =3D GET_CODE (operands[0]); =20 - if (cc_prev_status.flags & CC_NO_OVERFLOW) - { - switch (code) - { - case GTU: code =3D GT; break; - case LTU: code =3D LT; break; - case GEU: code =3D GE; break; - case LEU: code =3D LE; break; - default: ; - } - } - switch (code) - { - case EQ: pos =3D "beq", neg =3D "bne"; break; - case NE: pos =3D "bne", neg =3D "beq"; break; - case GT: pos =3D "bgt", neg =3D "ble"; break; - case GTU: pos =3D "bhi", neg =3D "blos"; break; - case LT: pos =3D "blt", neg =3D "bge"; break; - case LTU: pos =3D "blo", neg =3D "bhis"; break; - case GE: pos =3D "bge", neg =3D "blt"; break; - case GEU: pos =3D "bhis", neg =3D "blo"; break; - case LE: pos =3D "ble", neg =3D "bgt"; break; - case LEU: pos =3D "blos", neg =3D "bhi"; break; - default: gcc_unreachable (); - } - -#if 0 -/* currently we don't need this, because the tstdf and cmpdf=20 - copy the condition code immediately, and other float operations are not= =20 - yet recognized as changing the FCC - if so, then the length-cost of all - jump insns increases by one, because we have to potentially copy the=20 - FCC! */ - if (cc_status.flags & CC_IN_FPU) - output_asm_insn("cfcc", NULL); -#endif -=09 - switch (length) + if (ccnz) { - case 2: -=09 - sprintf(buf, "%s %%l1", inv ? neg : pos); -=09 - return buf; -=09 - case 6: -=09 - sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x); -=09 - x++; -=09 - return buf; -=09 - default: -=09 - gcc_unreachable (); + /* These are the branches valid for CCNZmode, i.e., a comparison + with zero where the V bit is not set to zero. These cases + occur when CC or FCC are set as a side effect of some data + manipulation, such as the ADD instruction. */ + switch (code) + { + case EQ: pos =3D "beq", neg =3D "bne"; break; + case NE: pos =3D "bne", neg =3D "beq"; break; + case LT: pos =3D "bmi", neg =3D "bpl"; break; + case GE: pos =3D "bpl", neg =3D "bmi"; break; + default: gcc_unreachable (); + } } -=20=20=20=20 + else + { + switch (code) + { + case EQ: pos =3D "beq", neg =3D "bne"; break; + case NE: pos =3D "bne", neg =3D "beq"; break; + case GT: pos =3D "bgt", neg =3D "ble"; break; + case GTU: pos =3D "bhi", neg =3D "blos"; break; + case LT: pos =3D "blt", neg =3D "bge"; break; + case LTU: pos =3D "blo", neg =3D "bhis"; break; + case GE: pos =3D "bge", neg =3D "blt"; break; + case GEU: pos =3D "bhis", neg =3D "blo"; break; + case LE: pos =3D "ble", neg =3D "bgt"; break; + case LEU: pos =3D "blos", neg =3D "bhi"; break; + default: gcc_unreachable (); + } + } + switch (length) + { + case 2: + sprintf (buf, "%s %%l1", pos); + return buf; + case 6: + tmpop[0] =3D gen_label_rtx (); + sprintf (buf, "%s %%l0", neg); + output_asm_insn (buf, tmpop); + output_asm_insn ("jmp %l1", operands); + output_asm_label (tmpop[0]); + fputs (":\n", asm_out_file); + return ""; + default: + gcc_unreachable (); + } } =20 -void -notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED) +/* Select the CC mode to be used for the side effect compare with + zero, given the compare operation code in op and the compare + operands in x in and y. */ +machine_mode +pdp11_cc_mode (enum rtx_code op, rtx x, rtx y) { - if (GET_CODE (SET_DEST (exp)) =3D=3D CC0) - {=20 - cc_status.flags =3D 0;=09=09=09=09=09 - cc_status.value1 =3D SET_DEST (exp);=09=09=09 - cc_status.value2 =3D SET_SRC (exp);=09=09=09 - }=09=09=09=09=09=09=09 - else if (GET_CODE (SET_SRC (exp)) =3D=3D CALL)=09=09 - {=20 - CC_STATUS_INIT;=20 + if (FLOAT_MODE_P (GET_MODE (x))) + { + switch (GET_CODE (x)) + { + case ABS: + case NEG: + case REG: + case MEM: + return CCmode; + default: + return CCNZmode; + } } - else if (SET_DEST(exp) =3D=3D pc_rtx) - {=20 - /* jump */ - }=09 - else if (GET_MODE (SET_DEST(exp)) =3D=3D HImode=09=09 - || GET_MODE (SET_DEST(exp)) =3D=3D QImode) - {=20 - cc_status.flags =3D GET_CODE (SET_SRC(exp)) =3D=3D MINUS ? 0 : CC_NO= _OVERFLOW; - cc_status.value1 =3D SET_SRC (exp);=20=20=20=09=09=09 - cc_status.value2 =3D SET_DEST (exp);=09=09=09 -=09 - if (cc_status.value1 && GET_CODE (cc_status.value1) =3D=3D REG=09 - && cc_status.value2=09=09=09=09=09 - && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) - cc_status.value2 =3D 0;=09=09=09=09=09 - if (cc_status.value1 && GET_CODE (cc_status.value1) =3D=3D MEM=09 - && cc_status.value2=09=09=09=09=09 - && GET_CODE (cc_status.value2) =3D=3D MEM)=09=09=09 - cc_status.value2 =3D 0;=20=09=09=09=09=09 - }=09=09=20=20=20=20=20=20=20=20 - else - {=20 - CC_STATUS_INIT;=20 + else + { + switch (GET_CODE (x)) + { + case XOR: + case AND: + case IOR: + case MULT: + case NOT: + case REG: + case MEM: + return CCmode; + default: + return CCNZmode; + } } } =20 @@ -1135,62 +1144,115 @@ const char * int simple_memory_operand(rtx op, machine_mode mode ATTRIBUTE_UNUSED) { - rtx addr; + rtx addr; =20 - /* Eliminate non-memory operations */ - if (GET_CODE (op) !=3D MEM) - return FALSE; + /* Eliminate non-memory operations */ + if (GET_CODE (op) !=3D MEM) + return FALSE; =20 -#if 0 - /* dword operations really put out 2 instructions, so eliminate them. = */ - if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4)) - return FALSE; -#endif + /* Decode the address now. */ =20 - /* Decode the address now. */ - - indirection: + indirection: =20=20=20=20=20 - addr =3D XEXP (op, 0); + addr =3D XEXP (op, 0); =20 - switch (GET_CODE (addr)) + switch (GET_CODE (addr)) { - case REG: - /* (R0) - no extra cost */ - return 1; + case REG: + /* (R0) - no extra cost */ + return 1; =20=09 - case PRE_DEC: - case POST_INC: - /* -(R0), (R0)+ - cheap! */ + case PRE_DEC: + case POST_INC: + case PRE_MODIFY: + case POST_MODIFY: + /* -(R0), (R0)+ - cheap! */ + return 1; +=09 + case MEM: + /* cheap - is encoded in addressing mode info!=20 + + -- except for @(R0), which has to be @0(R0) !!! */ + + if (GET_CODE (XEXP (addr, 0)) =3D=3D REG) return 0; =20=09 - case MEM: - /* cheap - is encoded in addressing mode info!=20 + op=3Daddr; + goto indirection; +=09 + case CONST_INT: + case LABEL_REF:=09=20=20=20=20=20=20=20 + case CONST: + case SYMBOL_REF: + /* @#address - extra cost */ + return 0; =20 - -- except for @(R0), which has to be @0(R0) !!! */ + case PLUS: + /* X(R0) - extra cost */ + return 0; =20 - if (GET_CODE (XEXP (addr, 0)) =3D=3D REG) - return 0; + default: + break; + } +=20=20=20=20 + return FALSE; +} + +/* Similar to simple_memory_operand but doesn't match push/pop. */ +int +no_side_effect_operand(rtx op, machine_mode mode ATTRIBUTE_UNUSED) +{ + rtx addr; + + /* Eliminate non-memory operations */ + if (GET_CODE (op) !=3D MEM) + return FALSE; + + /* Decode the address now. */ + + indirection: +=20=20=20=20 + addr =3D XEXP (op, 0); + + switch (GET_CODE (addr)) + { + case REG: + /* (R0) - no extra cost */ + return 1; =20=09 - op=3Daddr; - goto indirection; + case PRE_DEC: + case POST_INC: + case PRE_MODIFY: + case POST_MODIFY: + return 0; =20=09 - case CONST_INT: - case LABEL_REF:=09=20=20=20=20=20=20=20 - case CONST: - case SYMBOL_REF: - /* @#address - extra cost */ - return 0; + case MEM: + /* cheap - is encoded in addressing mode info!=20 =20 - case PLUS: - /* X(R0) - extra cost */ + -- except for @(R0), which has to be @0(R0) !!! */ + + if (GET_CODE (XEXP (addr, 0)) =3D=3D REG) return 0; +=09 + op=3Daddr; + goto indirection; +=09 + case CONST_INT: + case LABEL_REF:=09=20=20=20=20=20=20=20 + case CONST: + case SYMBOL_REF: + /* @#address - extra cost */ + return 0; =20 - default: - break; + case PLUS: + /* X(R0) - extra cost */ + return 0; + + default: + break; } =20=20=20=20=20 - return FALSE; + return FALSE; } =20 =20 @@ -1446,7 +1508,7 @@ pdp11_preferred_output_reload_class (rtx x, reg_cl =20 FPU registers AC4 and AC5 (class NO_LOAD_FPU_REGS) require an=20 intermediate register (AC0-AC3: LOAD_FPU_REGS). Everything else - can be loade/stored directly. */ + can be loaded/stored directly. */ static reg_class_t=20 pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, @@ -1463,9 +1525,8 @@ pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED =20 /* Implement TARGET_SECONDARY_MEMORY_NEEDED. =20 - The answer is yes if we're going between general register and FPU=20 - registers. The mode doesn't matter in making this check. -*/ + The answer is yes if we're going between general register and FPU + registers. The mode doesn't matter in making this check. */ static bool pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c= 2) { @@ -1594,6 +1655,8 @@ pdp11_regno_reg_class (int regno) {=20 if (regno =3D=3D FRAME_POINTER_REGNUM || regno =3D=3D ARG_POINTER_REGNUM) return GENERAL_REGS; + else if (regno =3D=3D CC_REGNUM || regno =3D=3D FCC_REGNUM) + return CC_REGS; else if (regno > AC3_REGNUM) return NO_LOAD_FPU_REGS; else if (regno >=3D AC0_REGNUM) @@ -1604,6 +1667,14 @@ pdp11_regno_reg_class (int regno) return GENERAL_REGS; } =20 +/* Return the regnums of the CC registers. */ +bool +pdp11_fixed_cc_regs (unsigned int *p1, unsigned int *p2) +{ + *p1 =3D CC_REGNUM; + *p2 =3D FCC_REGNUM; + return true; +} =20 int pdp11_sp_frame_offset (void) @@ -1804,6 +1875,151 @@ pdp11_function_value_regno_p (const unsigned int r return (regno =3D=3D RETVAL_REGNUM) || (TARGET_AC0 && (regno =3D=3D AC0_= REGNUM)); } =20 +/* Used for O constraint, matches if shift count is "small". */ +bool +pdp11_small_shift (int n) +{ + return (unsigned) n < 4; +} + +/* Expand a shift insn. Returns true if the expansion was done, + false if it needs to be handled by the caller. */ +bool +pdp11_expand_shift (rtx *operands, rtx (*shift_sc) (rtx, rtx, rtx), + rtx (*shift_base) (rtx, rtx, rtx)) +{ + rtx dest, n, r, test; + rtx_code_label *lb, *lb2; +=20=20 + if (CONSTANT_P (operands[2]) && pdp11_small_shift (INTVAL (operands[2]))) + emit_insn ((*shift_sc) (operands[0], operands[1], operands[2])); + else if (TARGET_40_PLUS) + return false; + else + { + lb =3D gen_label_rtx (); + r =3D gen_reg_rtx (HImode); + emit_move_insn (operands[0], operands[1]); + emit_move_insn (r, operands[2]); + if (!CONSTANT_P (operands[2])) + { + test =3D gen_rtx_LE (HImode, r, const0_rtx); + emit_jump_insn (gen_cbranchhi4 (test, r, const0_rtx, lb)); + } + /* It would be nice to expand the loop here, but that's not + possible because shifts may be generated by the loop unroll + optimizer and it doesn't appreciate flow changes happening + while it's doing things. */ + emit_insn ((*shift_base) (operands[0], operands[1], r)); + if (!CONSTANT_P (operands[2])) + { + emit_label (lb); + + /* Allow REG_NOTES to be set on last insn (labels don't have enough + fields, and can't be used for REG_NOTES anyway). */ + emit_use (stack_pointer_rtx); + } + } + return true; +} + +/* Emit the instructions needed to produce a shift by a small constant + amount (unrolled), or a shift made from a loop for the base machine + case. */ +const char * +pdp11_assemble_shift (rtx *operands, machine_mode m, int code) +{ + int i, n; + rtx exops[4][2]; + rtx lb[1]; + pdp11_action action[2]; + const bool small =3D CONSTANT_P (operands[2]) && pdp11_small_shift (INTV= AL (operands[2])); + + gcc_assert (small || !TARGET_40_PLUS); + + if (m =3D=3D E_SImode) + pdp11_expand_operands (operands, exops, 1, action, either); + + if (!small) + { + /* Loop case, generate the top of loop label. */ + lb[0] =3D gen_label_rtx (); + output_asm_label (lb[0]); + fputs (":\n", asm_out_file); + n =3D 1; + } + else + n =3D INTVAL (operands[2]); + if (code =3D=3D LSHIFTRT) + { + output_asm_insn ("clc", NULL); + switch (m) + { + case E_QImode: + output_asm_insn ("rorb %0", operands); + break; + case E_HImode: + output_asm_insn ("ror %0", operands); + break; + case E_SImode: + output_asm_insn ("ror %0", exops[0]); + output_asm_insn ("ror %0", exops[1]); + break; + default: + gcc_unreachable (); + } + n--; + } + for (i =3D 0; i < n; i++) + { + switch (code) + { + case LSHIFTRT: + case ASHIFTRT: + switch (m) + { + case E_QImode: + output_asm_insn ("asrb %0", operands); + break; + case E_HImode: + output_asm_insn ("asr %0", operands); + break; + case E_SImode: + output_asm_insn ("asr %0", exops[0]); + output_asm_insn ("ror %0", exops[1]); + break; + default: + gcc_unreachable (); + } + break; + case ASHIFT: + switch (m) + { + case E_QImode: + output_asm_insn ("aslb %0", operands); + break; + case E_HImode: + output_asm_insn ("asl %0", operands); + break; + case E_SImode: + output_asm_insn ("asl %0", exops[1]); + output_asm_insn ("rol %0", exops[0]); + break; + default: + gcc_unreachable (); + } + break; + } + } + if (!small) + { + /* Loop case, emit the count-down and branch if not done. */ + output_asm_insn ("dec %2", operands); + output_asm_insn ("bne %l0", lb); + } + return ""; +} + /* Worker function for TARGET_TRAMPOLINE_INIT. =20 trampoline - how should i do it in separate i+d ?=20 @@ -1814,7 +2030,6 @@ pdp11_function_value_regno_p (const unsigned int r MOV #STATIC, $4 01270Y 0x0000 <- STATIC; Y =3D STATIC_CHAIN_REGNUM JMP @#FUNCTION 000137 0x0000 <- FUNCTION */ - static void pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) { @@ -1934,12 +2149,6 @@ pdp11_scalar_mode_supported_p (scalar_mode mode) return default_scalar_mode_supported_p (mode); } =20 -int -pdp11_branch_cost () -{ - return (TARGET_BRANCH_CHEAP ? 0 : 1); -} - /* Implement TARGET_HARD_REGNO_NREGS. */ =20 static unsigned int @@ -1972,9 +2181,9 @@ pdp11_hard_regno_mode_ok (unsigned int regno, mach /* Implement TARGET_MODES_TIEABLE_P. */ =20 static bool -pdp11_modes_tieable_p (machine_mode, machine_mode) +pdp11_modes_tieable_p (machine_mode mode1, machine_mode mode2) { - return false; + return mode1 =3D=3D HImode && mode2 =3D=3D QImode; } =20 /* Implement PUSH_ROUNDING. On the pdp11, the stack is on an even Index: config/pdp11/pdp11.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/pdp11.h (revision 262195) +++ config/pdp11/pdp11.h (working copy) @@ -65,11 +65,11 @@ along with GCC; see the file COPYING3. If not see #define LONG_DOUBLE_TYPE_SIZE 64 =20 /* machine types from ansi */ -#define SIZE_TYPE "unsigned int" /* definition of size_t */ -#define WCHAR_TYPE "int" /* or long int???? */ +#define SIZE_TYPE "short unsigned int" /* definition of size_t */ +#define WCHAR_TYPE "short int" /* or long int???? */ #define WCHAR_TYPE_SIZE 16 =20 -#define PTRDIFF_TYPE "int" +#define PTRDIFF_TYPE "short int" =20 /* target machine storage layout */ =20 @@ -99,8 +99,7 @@ along with GCC; see the file COPYING3. If not see extern const struct real_format pdp11_f_format; extern const struct real_format pdp11_d_format; =20 -/* Maximum sized of reasonable data type=20 - DImode or Dfmode ...*/ +/* Maximum sized of reasonable data type -- DImode ...*/ #define MAX_FIXED_MODE_SIZE 64=09 =20 /* Allocation boundary (in *bits*) for storing pointers in memory. */ @@ -124,6 +123,22 @@ extern const struct real_format pdp11_d_format; /* Define this if move instructions will actually fail to work when given unaligned data. */ #define STRICT_ALIGNMENT 1 + +/* Adjust the length of shifts by small constant amounts. The base + value (in "length" on input) is the length of a shift by one, not + including the CLC in logical shifts. */ +#define ADJUST_INSN_LENGTH(insn, length) \ + if ((GET_CODE (insn) =3D=3D ASHIFT || \ + GET_CODE (insn) =3D=3D ASHIFTRT || \ + GET_CODE (insn) =3D=3D LSHIFTRT) && \ + GET_CODE (XEXP (insn, 2)) =3D=3D CONST_INT && \ + pdp11_small_shift (XINT (insn, 2))) \ + { \ + if (GET_CODE (insn) =3D=3D LSHIFTRT) \ + length =3D (length * XINT (insn, 2)) + 2; \ + else \ + length *=3D XINT (insn, 2); \ + } =0C /* Standard register usage. */ =20 @@ -147,7 +162,8 @@ extern const struct real_format pdp11_d_format; =20 #define FIXED_REGISTERS \ {0, 0, 0, 0, 0, 0, 1, 1, \ - 0, 0, 0, 0, 0, 0, 1, 1 } + 0, 0, 0, 0, 0, 0, 1, 1, \ + 1, 1 } =20 =20 =20 @@ -161,7 +177,8 @@ extern const struct real_format pdp11_d_format; /* don't know about fp */ #define CALL_USED_REGISTERS \ {1, 1, 0, 0, 0, 0, 1, 1, \ - 0, 0, 0, 0, 0, 0, 1, 1 } + 0, 0, 0, 0, 0, 0, 1, 1, \ + 1, 1 } =20 =20 /* Specify the registers used for certain standard purposes. @@ -203,27 +220,47 @@ NO_LOAD_FPU_REGS is ac4 and ac5, currently - diffi FPU_REGS is all fpu regs=20 */ =20 -enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_F= PU_REGS, FPU_REGS, ALL_REGS, LIM_REG_CLASSES }; +enum reg_class + { NO_REGS, + MUL_REGS, + GENERAL_REGS, + LOAD_FPU_REGS, + NO_LOAD_FPU_REGS, + FPU_REGS, + CC_REGS, + ALL_REGS, + LIM_REG_CLASSES }; =20 -#define N_REG_CLASSES (int) LIM_REG_CLASSES +#define N_REG_CLASSES ((int) LIM_REG_CLASSES) =20 /* have to allow this till cmpsi/tstsi are fixed in a better way !! */ #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true =20 -/* 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. */ =20 -#define REG_CLASS_NAMES {"NO_REGS", "MUL_REGS", "GENERAL_REGS", "LOAD_FPU_= REGS", "NO_LOAD_FPU_REGS", "FPU_REGS", "ALL_REGS" } +#define REG_CLASS_NAMES \ + { "NO_REGS", \ + "MUL_REGS", \ + "GENERAL_REGS", \ + "LOAD_FPU_REGS", \ + "NO_LOAD_FPU_REGS", \ + "FPU_REGS", \ + "CC_REGS", \ + "ALL_REGS" } =20 /* Define which registers fit in which classes. This is an initializer for a vector of HARD_REG_SET of length N_REG_CLASSES. */ =20 -#define REG_CLASS_CONTENTS {{0}, {0x00aa}, {0xc0ff}, {0x0f00}, {0x3000}, {= 0x3f00}, {0xffff}} +#define REG_CLASS_CONTENTS \ + { {0x00000}, /* NO_REGS */ \ + {0x000aa}, /* MUL_REGS */ \ + {0x0c0ff}, /* GENERAL_REGS */ \ + {0x00f00}, /* LOAD_FPU_REGS */ \ + {0x03000}, /* NO_LOAD_FPU_REGS */ \ + {0x03f00}, /* FPU_REGS */ \ + {0x30000}, /* CC_REGS */ \ + {0x3ffff}} /* ALL_REGS */ =20 /* The same information, inverted: Return the class number of the smallest class containing @@ -331,7 +368,7 @@ extern int may_call_alloca; {{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} =20 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ ((OFFSET) =3D pdp11_initial_elimination_offset ((FROM), (TO))) @@ -424,12 +461,19 @@ extern int may_call_alloca; #define DBX_CONTIN_LENGTH 0 =20 /* Give a comparison code (EQ, NE etc) and the first operand of a COMPARE, - return the mode to be used for the comparison. For floating-point, CCF= Pmode - should be used. */ + return the mode to be used for the comparison. */ =20 -#define SELECT_CC_MODE(OP,X,Y) \ -(GET_MODE_CLASS(GET_MODE(X)) =3D=3D MODE_FLOAT? CCFPmode : CCmode) +#define SELECT_CC_MODE(OP,X,Y) pdp11_cc_mode (OP, X, Y) =20 +/* Enable compare elimination pass. + FIXME: how can this be enabled for two registers? */ +#undef TARGET_FLAGS_REGNUM +#define TARGET_FLAGS_REGNUM CC_REGNUM + +/* Specify the CC registers. TODO: is this for "type 1" CC handling only?= */ +#undef TARGET_FIXED_CONDITION_CODE_REGS +#define TARGET_FIXED_CONDITION_CODE_REGS pdp11_fixed_cc_regs + /* 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. */ @@ -447,54 +491,6 @@ extern int may_call_alloca; /* #define NO_FUNCTION_CSE */ =20 =0C -/* Tell emit-rtl.c how to initialize special values on a per-function base= . */ -extern rtx cc0_reg_rtx; - -#define CC_STATUS_MDEP rtx - -#define CC_STATUS_MDEP_INIT (cc_status.mdep =3D 0) -=0C -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). */ - -#define CC_IN_FPU 04000=20 - -/* Do UPDATE_CC if EXP is a set, used in - NOTICE_UPDATE_CC=20 - - floats only do compare correctly, else nullify ... - - get cc0 out soon ... -*/ - -/* 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) \ -{ if (GET_CODE (EXP) =3D=3D SET) \ - { \ - notice_update_cc_on_set(EXP, INSN); \ - } \ - else if (GET_CODE (EXP) =3D=3D PARALLEL \ - && GET_CODE (XVECEXP (EXP, 0, 0)) =3D=3D SET) \ - { \ - notice_update_cc_on_set(XVECEXP (EXP, 0, 0), INSN); \ - } \ - else if (GET_CODE (EXP) =3D=3D CALL) \ - { /* all bets are off */ CC_STATUS_INIT; } \ - if (cc_status.value1 && GET_CODE (cc_status.value1) =3D=3D REG \ - && cc_status.value2 \ - && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \ - { \ - printf ("here!\n"); \ - cc_status.value2 =3D 0; \ - } \ -} -=0C /* Control the assembler format that we output. */ =20 /* Output to assembler file text saying following lines @@ -520,7 +516,8 @@ extern int may_call_alloca; =20 #define REGISTER_NAMES \ {"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc", \ - "ac0", "ac1", "ac2", "ac3", "ac4", "ac5", "fp", "ap" } + "ac0", "ac1", "ac2", "ac3", "ac4", "ac5", "fp", "ap", \ + "cc", "fcc" } =20 /* Globalizing directive for a label. */ #define GLOBAL_ASM_OP "\t.globl " @@ -603,10 +600,7 @@ extern int may_call_alloca; #define TRAMPOLINE_SIZE 8 #define TRAMPOLINE_ALIGNMENT 16 =20 -/* there is no point in avoiding branches on a pdp,=20 - since branches are really cheap - I just want to find out - how much difference the BRANCH_COST macro makes in code */ -#define BRANCH_COST(speed_p, predictable_p) pdp11_branch_cost () +#define BRANCH_COST(speed_p, predictable_p) 1 =20 #define COMPARE_FLAG_MODE HImode =20 Index: config/pdp11/pdp11.md =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/pdp11.md (revision 262195) +++ config/pdp11/pdp11.md (working copy) @@ -44,7 +44,12 @@ ;; arguments. (FRAME_POINTER_REGNUM 14) (ARG_POINTER_REGNUM 15) - (FIRST_PSEUDO_REGISTER 16) + ;; Condition code registers + (CC_REGNUM 16) + (FCC_REGNUM 17) + ;; End of hard registers + (FIRST_PSEUDO_REGISTER 18) +=20=20=20 ;; Branch offset limits, as byte offsets from instruction address (MIN_BRANCH -254) (MAX_BRANCH 256) @@ -51,21 +56,68 @@ (MIN_SOB -126) (MAX_SOB 0)]) =20 +;; DF is 64 bit +;; SF is 32 bit +;; SI is 32 bit ;; HI is 16 bit ;; QI is 8 bit=20 =20 ;; Integer modes supported on the PDP11, with a mapping from machine mode -;; to mnemonic suffix. SImode and DImode always are special cases. +;; to mnemonic suffix. SImode and DImode are usually special cases. (define_mode_iterator PDPint [QI HI]) (define_mode_attr isfx [(QI "b") (HI "")]) +(define_mode_attr mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "D= Imode")]) +(define_mode_attr e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode"= ) (DI "E_DImode")]) +(define_mode_attr hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")]) =20 +;; These are analogous for use in splitters and expanders. +(define_mode_iterator HSint [HI SI]) +(define_mode_iterator QHSint [QI HI SI]) +(define_mode_iterator QHSDint [QI HI SI DI]) + +(define_code_iterator SHF [ashift ashiftrt lshiftrt]) + +;; Substitution to turn a CC clobber into a CC setter. We have four of +;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM. +(define_subst "cc_cc" + [(set (match_operand 0 "") (match_operand 1 "")) + (clobber (reg CC_REGNUM))] + "" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (const_int 0))) + (set (match_dup 0) (match_dup 1))]) + +(define_subst "cc_ccnz" + [(set (match_operand 0 "") (match_operand 1 "")) + (clobber (reg CC_REGNUM))] + "" + [(set (reg:CCNZ CC_REGNUM) + (compare:CCNZ (match_dup 1) (const_int 0))) + (set (match_dup 0) (match_dup 1))]) + +(define_subst "fcc_cc" + [(set (match_operand 0 "") (match_operand 1 "")) + (clobber (reg FCC_REGNUM))] + "" + [(set (reg:CC FCC_REGNUM) + (compare:CC (match_dup 1) (const_int 0))) + (set (match_dup 0) (match_dup 1))]) + +(define_subst "fcc_ccnz" + [(set (match_operand 0 "") (match_operand 1 "")) + (clobber (reg FCC_REGNUM))] + "" + [(set (reg:CCNZ FCC_REGNUM) + (compare:CCNZ (match_dup 1) (const_int 0))) + (set (match_dup 0) (match_dup 1))]) + +(define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc") +(define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc") +(define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc") +(define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc") + ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. =20 -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. - -;;- Operand classes for the register allocator: -=0C ;; Compare instructions. =20 ;; currently we only support df floats, which saves us quite some @@ -82,16 +134,6 @@ ;; and ucmp_optab for mode SImode, because we don't have that!!! ;; - yet since no libfunc is there, we abort () =20 -;; The only thing that remains to be done then is output=20 -;; the floats in a way the assembler can handle it (and=20 -;; if you're really into it, use a PDP11 float emulation -;; library to do floating point constant folding - but=20 -;; I guess you'll get reasonable results even when not -;; doing this) -;; the last thing to do is fix the UPDATE_CC macro to check -;; for floating point condition codes, and set cc_status -;; properly, also setting the CC_IN_FCCR flag.=20 - ;; define attributes ;; currently type is only fpu or arith or unknown, maybe branch later ? ;; default is arith @@ -163,24 +205,31 @@ =20 ;; compare (define_insn "*cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF") - (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))] - "TARGET_FPU" + [(set (reg:CC FCC_REGNUM) + (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF") + (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))] + "TARGET_FPU && reload_completed" "* { - cc_status.flags =3D CC_IN_FPU; if (which_alternative =3D=3D 0 || which_alternative =3D=3D 2) - return \"{tstd|tstf} %0\;cfcc\"; + return \"{tstd|tstf} %0\"; else - return \"{cmpd|cmpf} %0, %1\;cfcc\"; + return \"{cmpd|cmpf} %0, %1\"; }" - [(set_attr "length" "4,4,6,6")])=20 + [(set_attr "length" "2,2,4,4") + (set_attr "type" "fp")])=20 =20 -(define_insn "*cmp" - [(set (cc0) - (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") - (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] +;; Copy floating point processor condition code register to main CPU +;; condition code register. +(define_insn "*cfcc" + [(set (reg CC_REGNUM) (reg FCC_REGNUM))] + "TARGET_FPU && reload_completed" + "cfcc") + +(define_insn "cmp" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") + (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] "" "@ tst %0 @@ -191,8 +240,7 @@ cmp %0,%1" [(set_attr "length" "2,2,4,4,4,6")]) =20 -;; sob instruction - we need an assembler which can make this instruction -;; valid under _all_ circumstances! +;; sob instruction - FIXME: this doesn't do anything, need to use doloop_e= nd. =20 (define_insn "" [(set (pc) @@ -208,22 +256,17 @@ "TARGET_40_PLUS" "* { - static int labelcount =3D 0; - static char buf[1000]; - if (get_attr_length (insn) =3D=3D 2) return \"sob %0, %l1\"; =20 /* emulate sob */ + operands[2] =3D gen_label_rtx (); output_asm_insn (\"dec %0\", operands); -=20 - sprintf (buf, \"bge LONG_SOB%d\", labelcount); - output_asm_insn (buf, NULL); - + output_asm_insn (\"beq %l2\", operands); output_asm_insn (\"jmp %l1\", operands); =20=20 - sprintf (buf, \"LONG_SOB%d:\", labelcount++); - output_asm_insn (buf, NULL); + output_asm_label (operands[2]); + fputs (\":\\n\", asm_out_file); =20 return \"\"; }" @@ -238,46 +281,73 @@ =20 ;; These control RTL generation for conditional jump insns ;; and match them for register allocation. - -(define_expand "cbranchdf4" - [(set (cc0) - (compare (match_operand:DF 1 "general_operand") - (match_operand:DF 2 "register_or_const0_operand"))) - (set (pc) +;; Post reload these get expanded into insns that actually +;; manipulate the condition code registers. We can't do that before +;; because instructions generated by reload clobber condition codes (new +;; CC design, type #2). +(define_insn_and_split "cbranchdf4" + [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) (const_int 0)]) + [(match_operand:DF 1 "general_operand" "fg") + (match_operand:DF 2 "general_operand" "a")]) (label_ref (match_operand 3 "" "")) (pc)))] "TARGET_FPU" + "#" + "&& reload_completed" + [(set (reg:CC FCC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC FCC_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] "") =20 -(define_expand "cbranch4" - [(set (cc0) - (compare (match_operand:PDPint 1 "general_operand") - (match_operand:PDPint 2 "general_operand"))) - (set (pc) +(define_insn_and_split "cbranch4" + [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) (const_int 0)]) + [(match_operand:PDPint 1 "general_operand" "g") + (match_operand:PDPint 2 "general_operand" "g")]) (label_ref (match_operand 3 "" "")) (pc)))] "" + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC CC_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] "") =20 -;; problem with too short jump distance! we need an assembler which can=20 -;; make this valid for all jump distances! -;; e.g. gas! +;; This splitter turns a branch on float condition into a branch on +;; CPU condition, by adding a CFCC. +(define_split + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(reg:CC FCC_REGNUM) (const_int 0)]) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_FPU && reload_completed" + [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM)) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC CC_REGNUM) (const_int 0)]) + (label_ref (match_dup 1)) + (pc)))] + "") =20 -;; these must be changed to check for CC_IN_FCCR if float is to be=20 -;; enabled - -(define_insn "*branch" +(define_insn "cond_branch" [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) (const_int 0)]) + [(reg:CC CC_REGNUM) (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] - "" - "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));" + "reload_completed" + "* return output_jump (operands, 0, get_attr_length (insn));" [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1) (pc)) (const_int MIN_BRANCH)) @@ -287,17 +357,14 @@ (const_int 6) (const_int 2)))]) =20 - -;; These match inverted jump insns for register allocation. - -(define_insn "*branch_inverted" +(define_insn "*branch" [(set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));" + (if_then_else (match_operator 0 "ccnz_operator" + [(reg:CCNZ CC_REGNUM) (const_int 0)]) + (label_ref (match_operand 1 "" "")) + (pc)))] + "reload_completed" + "* return output_jump (operands, 1, get_attr_length (insn));" [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1) (pc)) (const_int MIN_BRANCH)) @@ -306,6 +373,7 @@ (const_int MAX_BRANCH))) (const_int 6) (const_int 2)))]) + =0C ;; Move instructions =20 @@ -313,6 +381,14 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=3D&r,g") (match_operand:DI 1 "general_operand" "rN,g"))] "" + "") + + +(define_insn "*movdi_nocc" + [(set (match_operand:DI 0 "nonimmediate_operand" "=3D&r,g") + (match_operand:DI 1 "general_operand" "rN,g")) + (clobber (reg:CC CC_REGNUM))] + "" "* return output_move_multiple (operands);" [(set_attr "length" "16,32")]) =20 @@ -320,6 +396,13 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,r,g,g") (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))] "" + "") + +(define_insn "*movsi_nocc" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,r,g,g") + (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g")) + (clobber (reg:CC CC_REGNUM))] + "" "* return output_move_multiple (operands);" [(set_attr "length" "4,6,8,16")]) =20 @@ -327,6 +410,25 @@ [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))] "" + "") + +;; This splits all the integer moves: DI and SI modes as well as +;; the simple machine operations. +(define_split=20 + [(set (match_operand:QHSDint 0 "nonimmediate_operand" "") + (match_operand:QHSDint 1 "general_operand" ""))] + "reload_completed" + [(parallel [(set (match_dup 0) + (match_dup 1)) + (clobber (reg:CC CC_REGNUM))])] + "") +=20=20 +;; MOV clears V +(define_insn "*mov_" + [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") + (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi")) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "* { if (operands[1] =3D=3D const0_rtx) @@ -336,32 +438,88 @@ }" [(set_attr "length" "2,4,4,6")]) =20 -(define_insn "movdf" - [(set (match_operand:DF 0 "float_nonimm_operand" "=3Da,fR,a,Q,g") - (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))] +;; movdf has unusually complicated condition code handling, because +;; load (into float register) updates the FCC, while store (from +;; float register) leaves it untouched. +;; +;; 1. Loads are: ac4, ac5, or non-register into load-register +;; 2. Stores are: load-register to non-register, ac4, or ac5 +;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled +;; either as loads or as stores. + +(define_expand "movdf" + [(set (match_operand:DF 0 "float_nonimm_operand" "") + (match_operand:DF 1 "float_operand" ""))] "TARGET_FPU" - "* if (which_alternative =3D=3D0 || which_alternative =3D=3D 2) - return \"ldd %1, %0\"; - else if (which_alternative =3D=3D 1 || which_alternative =3D=3D 3) - return \"std %1, %0\"; - else=20 - return output_move_multiple (operands); " -;; last one is worst-case - [(set_attr "length" "2,2,4,4,24")]) + "") =20 -(define_insn "movsf" - [(set (match_operand:SF 0 "float_nonimm_operand" "=3Da,fR,a,Q,g") - (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))] +;; Splitter for all these cases. Store is the first two +;; alternatives, which are not split. Note that case 3 +;; is treated as a store, i.e., not split. +(define_insn_and_split "movdf_split" + [(set (match_operand:DF 0 "float_nonimm_operand" "=3DfR,FQ,a,a,a") + (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))] "TARGET_FPU" - "* if (which_alternative =3D=3D0 || which_alternative =3D=3D 2) - return \"{ldcfd|movof} %1, %0\"; - else if (which_alternative =3D=3D 1 || which_alternative =3D=3D 3) - return \"{stcdf|movfo} %1, %0\"; - else=20 - return output_move_multiple (operands); " -;; last one is worst-case - [(set_attr "length" "2,2,4,4,12")]) + "* + gcc_assert (which_alternative < 2); + return \"std %1, %0\"; + " + "&& reload_completed" + [(parallel [(set (match_dup 0) + (match_dup 1)) + (clobber (reg:CC FCC_REGNUM))])] + "{ + if (GET_CODE (operands[1]) =3D=3D REG &&=20 + REGNO_REG_CLASS (REGNO (operands[1])) =3D=3D LOAD_FPU_REGS) + FAIL; + }" + [(set_attr "length" "2,4,0,0,0")]) =20 +;; Loads (case 1).=20=20 +(define_insn "*ldd" + [(set (match_operand:DF 0 "float_nonimm_operand" "=3Da,a,a") + (match_operand:DF 1 "float_operand" "hR,FQ,G")) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" + "@ + ldd %1, %0 + ldd %1, %0 + clrd %0" + [(set_attr "length" "2,4,2")]) + +;; SFmode is easier because that uses convert load/store, which +;; always change condition codes. +;; Note that these insns are cheating a bit. We actually have +;; DFmode operands in the FPU registers, which is why the +;; ldcfd and stcdf instructions appear. But GCC likes to think +;; of these as SFmode loads and does the conversion once in the +;; register, at least in many cases. So we pretend to do this, +;; but then extend and truncate register-to-register are NOP and +;; generate no code. +(define_insn_and_split "movsf" + [(set (match_operand:SF 0 "float_nonimm_operand" "=3Da,fR,a,Q") + (match_operand:SF 1 "float_operand" "fRG,a,FQ,a"))] + "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (match_dup 1)) + (clobber (reg:CC FCC_REGNUM))])] + "") +=20=20 +(define_insn "*movsf" + [(set (match_operand:SF 0 "float_nonimm_operand" "=3Da,fR,a,Q,a") + (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G")) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" + "@ + {ldcfd|movof} %1, %0 + {stcdf|movfo} %1, %0 + {ldcfd|movof} %1, %0 + {stcdf|movfo} %1, %0 + clrf %0" + [(set_attr "length" "2,2,4,4,2")]) + ;; maybe fiddle a bit with move_ratio, then=20 ;; let constraints only accept a register ... =20 @@ -374,7 +532,7 @@ (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 2))])] - "(TARGET_BCOPY_BUILTIN)" + "" " { operands[0] @@ -389,7 +547,7 @@ }") =20 =20 -(define_insn "movmemhi1" +(define_insn "*movmemhi1" [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r")) (mem:BLK (match_operand:HI 1 "register_operand" "r,r"))) (use (match_operand:HI 2 "general_operand" "n,r")) @@ -398,7 +556,7 @@ (clobber (match_dup 0)) (clobber (match_dup 1)) (clobber (match_dup 2))] - "(TARGET_BCOPY_BUILTIN)" + "" "* return output_block_move (operands);" ;;; just a guess [(set_attr "length" "80")]) @@ -407,29 +565,56 @@ =0C ;;- truncation instructions =20 -(define_insn "truncdfsf2" +;; We sometimes end up doing a register to register truncate, +;; which isn't right because we actually load registers always +;; with a DFmode value. But even with PROMOTE the compiler +;; doesn't always get that (so we don't use it). That means +;; a register to register truncate is a NOP. +(define_insn_and_split "truncdfsf2" [(set (match_operand:SF 0 "float_nonimm_operand" "=3Df,R,Q") - (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))] + (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))] "TARGET_FPU" - "* if (which_alternative =3D=3D0) - { - return \"\"; - } - else if (which_alternative =3D=3D 1) - return \"{stcdf|movfo} %1, %0\"; - else=20 - return \"{stcdf|movfo} %1, %0\"; - " - [(set_attr "length" "0,2,4")]) + { + gcc_assert (which_alternative =3D=3D 0); + return ""; + }=09=20=20=20=20=20=20 + "&& reload_completed" + [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1))) + (clobber (reg:CC FCC_REGNUM))])] + "{ + if (GET_CODE (operands[0]) =3D=3D REG &&=20 + GET_CODE (operands[1]) =3D=3D REG &&=20 + REGNO (operands[0]) =3D=3D REGNO (operands[1])) + FAIL; + }" + [(set_attr "length" "0,0,0")]) =20 +(define_insn "*truncdfsf2_" + [(set (match_operand:SF 0 "float_nonimm_operand" "=3DR,Q") + (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" + "{stcdf|movfo} %1, %0" + [(set_attr "length" "2,4")]) =20 =0C ;;- zero extension instructions =20 -(define_insn "zero_extendqihi2" +(define_insn_and_split "zero_extendqihi2" [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*zero_extendqihi2" + [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") + (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0"))) + (clobber (reg:CC CC_REGNUM))])] + "reload_completed" "bic $0177400, %0" [(set_attr "length" "4,6")]) =20=09=09=09=20 @@ -448,56 +633,73 @@ =0C ;;- sign extension instructions =20 -(define_insn "extendsfdf2" +;; We sometimes end up doing a register to register extend, +;; which isn't right because we actually load registers always +;; with a DFmode value. But even with PROMOTE the compiler +;; doesn't always get that (so we don't use it). That means +;; a register to register truncate is a NOP. +(define_insn_and_split "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=3Df,a,a") - (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))] + (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))] "TARGET_FPU" - "@ - /* nothing */ - {ldcfd|movof} %1, %0 - {ldcfd|movof} %1, %0" - [(set_attr "length" "0,2,4")]) + { + gcc_assert (which_alternative =3D=3D 0); + return ""; + }=09=20=20=20=20=20=20 + "&& reload_completed" + [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1))) + (clobber (reg:CC FCC_REGNUM))])] + "{ + if (GET_CODE (operands[0]) =3D=3D REG &&=20 + GET_CODE (operands[1]) =3D=3D REG &&=20 + REGNO (operands[0]) =3D=3D REGNO (operands[1])) + FAIL; + }" + [(set_attr "length" "0,0,0")]) =20 -;; does movb sign extend in register-to-register move? -(define_insn "extendqihi2" +(define_insn "*extendsfdf2_" + [(set (match_operand:DF 0 "register_operand" "=3Da,a") + (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" + "{ldcfd|movof} %1, %0" + [(set_attr "length" "2,4")]) + +;; movb sign extends if destination is a register +(define_insn_and_split "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=3Dr,r") (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") + +;; MOVB clears V +(define_insn "*extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=3Dr,r") + (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "movb %1, %0" [(set_attr "length" "2,4")]) =20 -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=3Dr,r") - (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))] +(define_insn_and_split "extendhisi2" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3Do,<,r") + (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))] "TARGET_40_PLUS" - "* -{ - rtx latehalf[2]; + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") =20 - /* make register pair available */ - latehalf[0] =3D operands[0]; - operands[0] =3D gen_rtx_REG (HImode, REGNO (operands[0])+ 1); - - output_asm_insn(\"movb %1, %0\", operands); - output_asm_insn(\"sxt %0\", latehalf); -=20=20=20=20 - return \"\"; -}" - [(set_attr "length" "4,6")]) - -;; maybe we have to use define_expand to say that we have the instruction, -;; unconditionally, and then match dependent on CPU type: - -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dg") - (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))] - "" - "") -=20=20 -(define_insn "" ; "extendhisi2" +(define_insn "*extendhisi2_nocc" [(set (match_operand:SI 0 "nonimmediate_operand" "=3Do,<,r") - (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))] - "TARGET_40_PLUS" + (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g"))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_40_PLUS && reload_completed" "* { rtx latehalf[2]; @@ -542,52 +744,33 @@ }" [(set_attr "length" "10,6,6")]) =20 - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=3Dr") - (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))] - "(! TARGET_40_PLUS)" - "* -{ - static int count =3D 0; - char buf[100]; - rtx lateoperands[2]; - - lateoperands[0] =3D operands[0]; - operands[0] =3D gen_rtx_REG (HImode, REGNO (operands[0]) + 1); - - output_asm_insn(\"tst %0\", operands); - sprintf(buf, \"bge extendhisi%d\", count); - output_asm_insn(buf, NULL); - output_asm_insn(\"mov -1, %0\", lateoperands); - sprintf(buf, \"bne extendhisi%d\", count+1); - output_asm_insn(buf, NULL); - sprintf(buf, \"\\nextendhisi%d:\", count); - output_asm_insn(buf, NULL); - output_asm_insn(\"clr %0\", lateoperands); - sprintf(buf, \"\\nextendhisi%d:\", count+1); - output_asm_insn(buf, NULL); - - count +=3D 2; - - return \"\"; -}" - [(set_attr "length" "12")]) - ;; make float to int and vice versa=20 -;; using the cc_status.flag field we could probably cut down -;; on seti and setl ;; assume that we are normally in double and integer mode - ;; what do pdp library routines do to fpu mode ? =20 -(define_insn "floatsidf2" +;; Note: the hardware treats register source as +;; a 16-bit (high order only) source, which isn't +;; what we want. But we do need to support register +;; dest because gcc asks for it. +(define_insn_and_split "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=3Da,a,a") (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (float:DF (match_dup 1))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +(define_insn "*floatsidf2" + [(set (match_operand:DF 0 "register_operand" "=3Da,a,a") + (float:DF (match_operand:SI 1 "general_operand" "r,R,Q"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "* if (which_alternative =3D=3D0) { rtx latehalf[2]; - +=20 latehalf[0] =3D NULL;=20 latehalf[1] =3D gen_rtx_REG (HImode, REGNO (operands[1]) + 1); output_asm_insn(\"mov %1, -(sp)\", latehalf); @@ -598,25 +781,53 @@ output_asm_insn(\"seti\", operands); return \"\"; } - else if (which_alternative =3D=3D 1) - return \"setl\;{ldcld|movif} %1, %0\;seti\"; else=20 return \"setl\;{ldcld|movif} %1, %0\;seti\"; " [(set_attr "length" "10,6,8")]) =20 -(define_insn "floathidf2" +(define_insn_and_split "floathidf2" [(set (match_operand:DF 0 "register_operand" "=3Da,a") (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (float:DF (match_dup 1))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +(define_insn "*floathidf2" + [(set (match_operand:DF 0 "register_operand" "=3Da,a") + (float:DF (match_operand:HI 1 "general_operand" "rR,Qi"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{ldcid|movif} %1, %0" [(set_attr "length" "2,4")]) =20=09 ;; cut float to int -(define_insn "fix_truncdfsi2" + +;; Note: the hardware treats register destination as +;; a 16-bit (high order only) destination, which isn't +;; what we want. But we do need to support register +;; dest because gcc asks for it. +(define_insn_and_split "fix_truncdfsi2" [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,R,Q") (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1)))) + (clobber (reg:CC CC_REGNUM)) + (clobber (reg:CC FCC_REGNUM))])] + "") + +;; Note: this clobbers both sets of condition codes! +(define_insn "*fix_truncdfsi2_nocc" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,R,Q") + (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a")))) + (clobber (reg:CC CC_REGNUM)) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "* if (which_alternative =3D=3D0) { output_asm_insn(\"setl\", operands); @@ -627,17 +838,29 @@ output_asm_insn(\"mov (sp)+, %0\", operands); return \"\"; } - else if (which_alternative =3D=3D 1) - return \"setl\;{stcdl|movfi} %1, %0\;seti\"; else=20 return \"setl\;{stcdl|movfi} %1, %0\;seti\"; " [(set_attr "length" "10,6,8")]) =20 -(define_insn "fix_truncdfhi2" +(define_insn_and_split "fix_truncdfhi2" [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1)))) + (clobber (reg:CC CC_REGNUM)) + (clobber (reg:CC FCC_REGNUM))])] + "") + +;; Note: this clobbers both sets of condition codes! +(define_insn "*fix_truncdfhi2_nocc" + [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") + (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a")))) + (clobber (reg:CC CC_REGNUM)) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{stcdi|movfi} %1, %0" [(set_attr "length" "2,4")]) =20 @@ -645,19 +868,45 @@ ;;- arithmetic instructions ;;- add instructions =20 -(define_insn "adddf3" +(define_insn_and_split "adddf3" [(set (match_operand:DF 0 "register_operand" "=3Da,a") (plus:DF (match_operand:DF 1 "register_operand" "%0,0") (match_operand:DF 2 "general_operand" "fR,QF")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (plus:DF (match_dup 1) (match_dup 2))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +;; Float add sets V if overflow from add +(define_insn "*adddf3" + [(set (match_operand:DF 0 "register_operand" "=3Da,a") + (plus:DF (match_operand:DF 1 "register_operand" "%0,0") + (match_operand:DF 2 "general_operand" "fR,QF"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{addd|addf} %2, %0" [(set_attr "length" "2,4")]) =20 -(define_insn "adddi3" +(define_insn_and_split "adddi3" [(set (match_operand:DI 0 "nonimmediate_operand" "=3D&r,r,o,o") (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0") (match_operand:DI 2 "general_operand" "r,on,r,on")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*adddi3_nocc" + [(set (match_operand:DI 0 "nonimmediate_operand" "=3D&r,r,o,o") + (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0") + (match_operand:DI 2 "general_operand" "r,on,r,on"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed"=20=20 "* { rtx inops[2]; @@ -701,11 +950,23 @@ ;; high word is added at the end, so the adding of the high parts ;; will always used the original high part and not a high part ;; modified by carry (which would amount to double carry). -(define_insn "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,r,o,o") +(define_insn_and_split "addsi3" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3D&r,r,o,o") (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0") (match_operand:SI 2 "general_operand" "r,on,r,on")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*addsi3_nocc" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3D&r,r,o,o") + (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0") + (match_operand:SI 2 "general_operand" "r,on,r,on"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "* { rtx inops[2]; @@ -727,11 +988,25 @@ }" [(set_attr "length" "6,10,12,16")]) =20 -(define_insn "addhi3" +(define_insn_and_split "addhi3" [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0") (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (plus:HI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +;; Add sets V if overflow from the add +(define_insn "*addhi3" + [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") + (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0") + (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "* { if (GET_CODE (operands[2]) =3D=3D CONST_INT) @@ -752,19 +1027,44 @@ ;; args, since they are canonical plus:xx now! ;; also for minus:DF ?? =20 -(define_insn "subdf3" +(define_insn_and_split "subdf3" [(set (match_operand:DF 0 "register_operand" "=3Da,a") (minus:DF (match_operand:DF 1 "register_operand" "0,0") (match_operand:DF 2 "general_operand" "fR,Q")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (minus:DF (match_dup 1) (match_dup 2))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +(define_insn "*subdf3" + [(set (match_operand:DF 0 "register_operand" "=3Da,a") + (minus:DF (match_operand:DF 1 "register_operand" "0,0") + (match_operand:DF 2 "general_operand" "fR,QF"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{subd|subf} %2, %0" [(set_attr "length" "2,4")]) =20 -(define_insn "subdi3" +(define_insn_and_split "subdi3" [(set (match_operand:DI 0 "nonimmediate_operand" "=3D&r,r,o,o") (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") (match_operand:DI 2 "general_operand" "r,on,r,on")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*subdi3_nocc" + [(set (match_operand:DI 0 "nonimmediate_operand" "=3D&r,r,o,o") + (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") + (match_operand:DI 2 "general_operand" "r,on,r,on"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "* { rtx inops[2]; @@ -799,11 +1099,23 @@ }" [(set_attr "length" "20,28,40,48")]) =20 -(define_insn "subsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,r,o,o") +(define_insn_and_split "subsi3" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3D&r,r,o,o") (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0") (match_operand:SI 2 "general_operand" "r,on,r,on")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*subsi3_nocc" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3D&r,r,o,o") + (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0") + (match_operand:SI 2 "general_operand" "r,on,r,on"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "* { rtx inops[2]; @@ -825,14 +1137,37 @@ }" [(set_attr "length" "6,10,12,16")]) =20 -(define_insn "subhi3" +(define_insn_and_split "subhi3" [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") - (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))] + (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (minus:HI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +;; Note: the manual says that (minus m (const_int n)) is converted +;; to (plus m (const_int -n)) but that does not appear to be +;; the case when it's wrapped in a PARALLEL. So instead we handle +;; that case here, which is easy enough. +(define_insn "*subhi3" + [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") + (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") + (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "* { - gcc_assert (GET_CODE (operands[2]) !=3D CONST_INT); + if (GET_CODE (operands[2]) =3D=3D CONST_INT) + { + if (INTVAL(operands[2]) =3D=3D 1) + return \"dec %0\"; + else if (INTVAL(operands[2]) =3D=3D -1) + return \"inc %0\"; + } =20 return \"sub %2, %0\"; }" @@ -867,121 +1202,149 @@ operands[1] =3D expand_unop (mode, one_cmpl_optab, op1, 0, 1); }") =20 -(define_insn "*bic" +(define_insn_and_split "*bic" [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") (and:PDPint (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"= )) (match_operand:PDPint 2 "general_operand" "0,0,0,0")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*bic" + [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") + (and:PDPint + (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"= )) + (match_operand:PDPint 2 "general_operand" "0,0,0,0"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "bic %1, %0" [(set_attr "length" "2,4,4,6")]) =20 ;;- Bit set (inclusive or) instructions -(define_insn "ior3" +(define_insn_and_split "ior3" [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0") - (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))] + (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (ior:PDPint (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "ior3" + [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,rR,Q,Q") + (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0") + (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "bis %2, %0" [(set_attr "length" "2,4,4,6")]) =20 ;;- xor instructions -(define_insn "xorhi3" +(define_insn_and_split "xorhi3" [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") (xor:HI (match_operand:HI 1 "general_operand" "%0,0") (match_operand:HI 2 "register_operand" "r,r")))] "TARGET_40_PLUS" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (xor:HI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*xorhi3" + [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") + (xor:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "register_operand" "r,r"))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_40_PLUS && reload_completed" "xor %2, %0" [(set_attr "length" "2,4")]) =20 ;;- one complement instructions =20 -(define_insn "one_cmpl2" +(define_insn_and_split "one_cmpl2" [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,Q") (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (not:PDPint (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "*one_cmpl2" + [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,Q") + (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" "com %0" [(set_attr "length" "2,4")]) =20 ;;- arithmetic shift instructions -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=3Dr,r") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:HI 2 "general_operand" "rR,Qi")))] - "TARGET_40_PLUS" - "ashc %2,%0" +;; +;; There is a fair amount of complexity here because with -m10 +;; (pdp-11/10, /20) we only have shift by one bit. Iterators are +;; used to reduce the amount of very similar code. +;; +;; First the insns used for small constant shifts. +; +;; The "length" attribute values are modified by the ADJUST_INSN_LENGTH +;; macro for the small constant shift case (first two alternatives). +;; For those, the value coded in the length attribute is the cost of just +;; the shift for a single shift. +(define_insn "_sc" + [(set (match_operand:QHSint 0 "nonimmediate_operand" "=3DrD,Q") + (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0") + (match_operand:HI 2 "expand_shift_operand" "O,O")))] + "" + "* return pdp11_assemble_shift (operands, , );" [(set_attr "length" "2,4")]) =20 -;; Arithmetic right shift on the pdp works by negating the shift count. -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=3Dr") - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] +;; Next, shifts that are done as a loop on base (11/10 class) machines. +;; This applies to shift counts too large to unroll, or variable shift +;; counts. The check for count <=3D 0 is done before we get here. +(define_insn "_base" + [(set (match_operand:QHSint 0 "nonimmediate_operand" "=3DrD,Q") + (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0") + (match_operand:HI 2 "register_operand" "r,r"))) + (clobber (match_dup 2))] "" - " -{ - operands[2] =3D negate_rtx (HImode, operands[2]); -}") - -;; define asl aslb asr asrb - ashc missing! - -;; asl=20 -(define_insn ""=20 - [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") - (ashift:HI (match_operand:HI 1 "general_operand" "0,0") - (const_int 1)))] - "" - "asl %0" + "* return pdp11_assemble_shift (operands, , );" [(set_attr "length" "2,4")]) =20 -;; and another possibility for asr is << -1 -;; might cause problems since -1 can also be encoded as 65535! -;; not in gcc2 ???=20 - -;; asr -(define_insn ""=20 - [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") +;; Next the insns that use the extended instructions ash and ashc. +;; Note that these are just left shifts, and HI/SI only. (Right shifts +;; are done by shifting by a negative amount.) +(define_insn "aslhi_op" + [(set (match_operand:HI 0 "nonimmediate_operand" "=3Dr,r") (ashift:HI (match_operand:HI 1 "general_operand" "0,0") - (const_int -1)))] - "" - "asr %0" + (match_operand:HI 2 "general_operand" "rR,Q")))] + "TARGET_40_PLUS" + "ash %2, %0" [(set_attr "length" "2,4")]) =20 -;; lsr -(define_insn "lsrhi1"=20 - [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0") - (const_int 1)))] - "" - "clc\;ror %0" +(define_insn "aslsi_op" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,r") + (ashift:SI (match_operand:SI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "rR,Q")))] + "TARGET_40_PLUS" + "ashc %2, %0" [(set_attr "length" "2,4")]) =20 -(define_insn "lsrsi1" - [(set (match_operand:SI 0 "register_operand" "=3Dr") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") - (const_int 1)))] - "" -{ - - rtx lateoperands[2]; - - lateoperands[0] =3D operands[0]; - operands[0] =3D gen_rtx_REG (HImode, REGNO (operands[0]) + 1); - - lateoperands[1] =3D operands[1]; - operands[1] =3D gen_rtx_REG (HImode, REGNO (operands[1]) + 1); - - output_asm_insn (\"clc\", operands); - output_asm_insn (\"ror %0\", lateoperands); - output_asm_insn (\"ror %0\", operands); - - return \"\"; -} - [(set_attr "length" "10")]) - -(define_expand "lshrsi3" - [(match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "register_operand" "0") +;; Now the expanders that produce the insns defined above.=20 +(define_expand "ashl3" + [(match_operand:QHSint 0 "nonimmediate_operand" "") + (match_operand:QHSint 1 "general_operand" "") (match_operand:HI 2 "general_operand" "")] "" " @@ -988,196 +1351,139 @@ { rtx r; =20 - if (!TARGET_40_PLUS && - (GET_CODE (operands[2]) !=3D CONST_INT || - (unsigned) INTVAL (operands[2]) > 3)) - FAIL; - emit_insn (gen_lsrsi1 (operands[0], operands[1])); - if (GET_CODE (operands[2]) !=3D CONST_INT) + if (!pdp11_expand_shift (operands, gen_ashift_sc, gen_ashift= _base)) { - r =3D gen_reg_rtx (HImode); - emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1))); - emit_insn (gen_ashrsi3 (operands[0], operands[0], r)); + if ( =3D=3D E_QImode) + { + r =3D copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, ope= rands[1])); + emit_insn (gen_aslhi_op (r, r, operands[2])); + emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)= )); + } + else + { + emit_insn (gen_asl_op (operands[0], operands[1], o= perands[2])); + } } - else if ((unsigned) INTVAL (operands[2]) !=3D 1) - { - emit_insn (gen_ashlsi3 (operands[0], operands[0], - GEN_INT (1 - INTVAL (operands[2])))); - } DONE; -} -" -) +}") =20 -;; shift is by arbitrary count is expensive,=20 -;; shift by one cheap - so let's do that, if -;; space doesn't matter -(define_insn ""=20 - [(set (match_operand:HI 0 "nonimmediate_operand" "=3Dr") - (ashift:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "expand_shift_operand" "O")))] - "! optimize_size" - "* +(define_expand "ashr3" + [(match_operand:QHSint 0 "nonimmediate_operand" "") + (match_operand:QHSint 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")] + "" + " { - register int i; + rtx r; =20 - for (i =3D 1; i <=3D abs(INTVAL(operands[2])); i++) - if (INTVAL(operands[2]) < 0) - output_asm_insn(\"asr %0\", operands); - else - output_asm_insn(\"asl %0\", operands); -=20=20=20=20=20=20 - return \"\"; -}" -;; longest is 4 - [(set (attr "length") (const_int 8))]) - -;; aslb -(define_insn ""=20 - [(set (match_operand:QI 0 "nonimmediate_operand" "=3Dr,o") - (ashift:QI (match_operand:QI 1 "general_operand" "0,0") - (match_operand:HI 2 "const_int_operand" "n,n")))] - "" - "* -{ /* allowing predec or post_inc is possible, but hairy! */ - int i, cnt; - - cnt =3D INTVAL(operands[2]) & 0x0007; - - for (i=3D0 ; i < cnt ; i++) - output_asm_insn(\"aslb %0\", operands); - - return \"\"; -}" -;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!! - [(set_attr_alternative "length"=20 - [(const_int 14) - (const_int 28)])]) - -;;; asr=20 -;(define_insn ""=20 -; [(set (match_operand:HI 0 "nonimmediate_operand" "=3DrR,Q") -; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0") -; (const_int 1)))] -; "" -; "asr %0" -; [(set_attr "length" "2,4")]) - -;; asrb -(define_insn ""=20 - [(set (match_operand:QI 0 "nonimmediate_operand" "=3Dr,o") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0") - (match_operand:HI 2 "const_int_operand" "n,n")))] - "" - "* -{ /* allowing predec or post_inc is possible, but hairy! */ - int i, cnt; - - cnt =3D INTVAL(operands[2]) & 0x0007; - - for (i=3D0 ; i < cnt ; i++) - output_asm_insn(\"asrb %0\", operands); - - return \"\"; -}" - [(set_attr_alternative "length"=20 - [(const_int 14) - (const_int 28)])]) - -;; the following is invalid - too complex!!! - just say 14 !!! -; [(set (attr "length") (plus (and (match_dup 2) -; (const_int 14)) -; (and (match_dup 2) -; (const_int 14))))]) - - - -;; can we get +-1 in the next pattern? should=20 -;; have been caught by previous patterns! - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=3Dr,r") - (ashift:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "general_operand" "rR,Qi")))] - "TARGET_40_PLUS" - "* -{ - if (GET_CODE(operands[2]) =3D=3D CONST_INT) + if (!pdp11_expand_shift (operands, gen_ashiftrt_sc, gen_ashiftrt_base)) { - if (INTVAL(operands[2]) =3D=3D 1) - return \"asl %0\"; - else if (INTVAL(operands[2]) =3D=3D -1) - return \"asr %0\"; + operands[2] =3D negate_rtx (HImode, operands[2]); + if ( =3D=3D E_QImode) + { + r =3D copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, ope= rands[1])); + emit_insn (gen_aslhi_op (r, r, operands[2])); + emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)= )); + } + else + { + emit_insn (gen_asl_op (operands[0], operands[1], o= perands[2])); + } } - - return \"ash %2,%0\"; -}" - [(set_attr "length" "2,4")]) - -;; Arithmetic right shift on the pdp works by negating the shift count. -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "register_operand" "=3Dr") - (ashift:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - " -{ - operands[2] =3D negate_rtx (HImode, operands[2]); + DONE; }") =20 -(define_expand "lshrhi3" - [(match_operand:HI 0 "register_operand" "") - (match_operand:HI 1 "register_operand" "") +(define_expand "lshr3" + [(match_operand:QHSint 0 "nonimmediate_operand" "") + (match_operand:QHSint 1 "general_operand" "") (match_operand:HI 2 "general_operand" "")] "" " { - rtx r; + rtx r, n; =20 - if (!TARGET_40_PLUS && - (GET_CODE (operands[2]) !=3D CONST_INT || - (unsigned) INTVAL (operands[2]) > 3)) - FAIL; - emit_insn (gen_lsrhi1 (operands[0], operands[1])); - if (GET_CODE (operands[2]) !=3D CONST_INT) + if (!pdp11_expand_shift (operands, gen_lshiftrt_sc, gen_lshiftrt_base)) { - r =3D gen_reg_rtx (HImode); - emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1))); - emit_insn (gen_ashrhi3 (operands[0], operands[0], r)); + if ( =3D=3D E_QImode) + { + r =3D copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, ope= rands[1])); + emit_insn (gen_aslhi_op (r, r, operands[2])); + emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)= )); + } + else + { + r =3D gen_reg_rtx (); + emit_insn (gen_lshiftrt_sc (r, operands[1], const1_rtx)); + if (GET_CODE (operands[2]) !=3D CONST_INT) + { + n =3D gen_reg_rtx (HImode); + emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1))); + emit_insn (gen_ashr3 (operands[0], r, n)); + } + else + emit_insn (gen_asl_op (operands[0], r, + GEN_INT (1 - INTVAL (operands[2])))); + } } - else if ((unsigned) INTVAL (operands[2]) !=3D 1) - { - emit_insn (gen_ashlhi3 (operands[0], operands[0], - GEN_INT (1 - INTVAL (operands[2])))); - } DONE; -} -" -) +}") =20 ;; absolute=20 =20 -(define_insn "absdf2" +(define_insn_and_split "absdf2" [(set (match_operand:DF 0 "nonimmediate_operand" "=3DfR,Q") (abs:DF (match_operand:DF 1 "general_operand" "0,0")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (abs:DF (match_dup 1))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +(define_insn "absdf2" + [(set (match_operand:DF 0 "nonimmediate_operand" "=3DfR,Q") + (abs:DF (match_operand:DF 1 "general_operand" "0,0"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{absd|absf} %0" [(set_attr "length" "2,4")]) =20 - ;; negate insns =20 -(define_insn "negdf2" - [(set (match_operand:DF 0 "float_nonimm_operand" "=3DfR,Q") - (neg:DF (match_operand:DF 1 "register_operand" "0,0")))] +(define_insn_and_split "negdf2" + [(set (match_operand:DF 0 "nonimmediate_operand" "=3DfR,Q") + (neg:DF (match_operand:DF 1 "general_operand" "0,0")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (neg:DF (match_dup 1))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +(define_insn "negdf2" + [(set (match_operand:DF 0 "nonimmediate_operand" "=3DfR,Q") + (neg:DF (match_operand:DF 1 "general_operand" "0,0"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{negd|negf} %0" [(set_attr "length" "2,4")]) =20 -(define_insn "negdi2" +(define_insn_and_split "negdi2" [(set (match_operand:DI 0 "nonimmediate_operand" "=3Dr,o") (neg:DI (match_operand:DI 1 "general_operand" "0,0")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (neg:DI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") +=20=20 +;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word. +(define_insn "negdi2_nocc" + [(set (match_operand:DI 0 "nonimmediate_operand" "=3Dr,o") + (neg:DI (match_operand:DI 1 "general_operand" "0,0"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" { rtx exops[4][2]; =20=20=20 @@ -1196,10 +1502,22 @@ } [(set_attr "length" "18,34")]) =20 -(define_insn "negsi2" +(define_insn_and_split "negsi2" [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,o") (neg:SI (match_operand:SI 1 "general_operand" "0,0")))] "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (neg:SI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") +=20=20 +;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word. +(define_insn "negsi2_nocc" + [(set (match_operand:SI 0 "nonimmediate_operand" "=3Dr,o") + (neg:SI (match_operand:SI 1 "general_operand" "0,0"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" { rtx exops[2][2]; =20=20=20 @@ -1212,13 +1530,24 @@ =20 return \"\"; } -[(set_attr "length" "12,20")]) +[(set_attr "length" "10,18")]) =20 -(define_insn "neg2" +(define_insn_and_split "neg2" [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,Q") (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))] "" - "neg %0" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])] + "") +=20=20 +(define_insn "neg2" + [(set (match_operand:PDPint 0 "nonimmediate_operand" "=3DrR,Q") + (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0"))) + (clobber (reg:CC CC_REGNUM))] + "" + "neg %0" [(set_attr "length" "2,4")]) =20 =20 @@ -1229,9 +1558,9 @@ "" "* { - if (get_attr_length (insn) =3D=3D 2) + if (get_attr_length (insn) =3D=3D 2) return \"br %l0\"; - return \"jmp %l0\"; + return \"jmp %l0\"; }" [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0) (pc)) @@ -1242,14 +1571,6 @@ (const_int 4) (const_int 2)))]) =20 -(define_insn "" - [(set (pc) - (label_ref (match_operand 0 "" ""))) - (clobber (const_int 1))] - "" - "jmp %l0" - [(set_attr "length" "4")]) - (define_insn "tablejump" [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q")) (use (label_ref (match_operand 1 "" "")))] @@ -1260,22 +1581,20 @@ jmp %@%0" [(set_attr "length" "2,2,4")]) =20 -;; indirect jump - let's be conservative! -;; allow only register_operand, even though we could also=20 -;; allow labels etc. - +;; indirect jump. TODO: this needs a constraint that allows memory +;; references but not indirection, since we add a level of indirection +;; in the generated code. (define_insn "indirect_jump" - [(set (pc) (match_operand:HI 0 "register_operand" "r"))] + [(set (pc) (match_operand:HI 0 "general_operand" "r"))] "" - "jmp (%0)") + "jmp @%0" + [(set_attr "length" "2")]) =20 ;;- jump to subroutine =20 (define_insn "call" [(call (match_operand:HI 0 "general_operand" "rR,Q") - (match_operand:HI 1 "general_operand" "g,g")) -;; (use (reg:HI 0)) what was that ??? - ] + (match_operand:HI 1 "general_operand" "g,g"))] ;;- Don't use operand 1 for most machines. "" "jsr pc, %0" @@ -1285,14 +1604,38 @@ (define_insn "call_value" [(set (match_operand 0 "" "") (call (match_operand:HI 1 "general_operand" "rR,Q") - (match_operand:HI 2 "general_operand" "g,g"))) -;; (use (reg:HI 0)) - what was that ???? - ] + (match_operand:HI 2 "general_operand" "g,g")))] ;;- Don't use operand 2 for most machines. "" "jsr pc, %1" [(set_attr "length" "2,4")]) =20 +(define_expand "untyped_call" + [(parallel [(call (match_operand 0 "" "") + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] + "" +{ + int i; + + emit_call_insn (gen_call (operands[0], const0_rtx)); + + for (i =3D 0; i < XVECLEN (operands[2], 0); i++) + { + rtx set =3D XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); + } + + /* The optimizer does not know that the call sets the function value + registers we stored in the result block. We avoid problems by + claiming that all hard registers are used and clobbered at this + point. */ + emit_insn (gen_blockage ()); + + DONE; +}) + ;;- nop instruction (define_insn "nop" [(const_int 0)] @@ -1302,124 +1645,134 @@ =20 ;;- multiply=20 =20 -(define_insn "muldf3" +(define_insn_and_split "muldf3" [(set (match_operand:DF 0 "register_operand" "=3Da,a") (mult:DF (match_operand:DF 1 "register_operand" "%0,0") (match_operand:DF 2 "float_operand" "fR,QF")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2))) + (clobber (reg:CC FCC_REGNUM))])] + "") + +(define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=3Da,a") + (mult:DF (match_operand:DF 1 "register_operand" "%0,0") + (match_operand:DF 2 "float_operand" "fR,QF"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{muld|mulf} %2, %0" [(set_attr "length" "2,4")]) =20 -;; 16 bit result multiply: -;; currently we multiply only into odd registers, so we don't use two=20 -;; registers - but this is a bit inefficient at times. If we define=20 -;; a register class for each register, then we can specify properly=20 -;; which register need which scratch register .... +;; 16 bit result multiply. This uses odd numbered registers. =20 -(define_insn "mulhi3" +(define_insn_and_split "mulhi3" [(set (match_operand:HI 0 "register_operand" "=3Dd,d") ; multiply regs (mult:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "float_operand" "rR,Qi")))] + (match_operand:HI 2 "general_operand" "rR,Qi")))] "TARGET_40_PLUS" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "") + +(define_insn "mulhi3" + [(set (match_operand:HI 0 "register_operand" "=3Dd,d") + (mult:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "general_operand" "rR,Qi"))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_40_PLUS && reload_completed" "mul %2, %0" [(set_attr "length" "2,4")]) =20 -;; 32 bit result -(define_expand "mulhisi3" - [(set (match_dup 3) - (match_operand:HI 1 "nonimmediate_operand" "g,g")) - (set (match_operand:SI 0 "register_operand" "=3Dr,r") ; even numbered! - (mult:SI (truncate:HI=20 - (match_dup 0)) - (match_operand:HI 2 "general_operand" "rR,Qi")))] +;; 32 bit result from 16 bit operands +(define_insn_and_split "mulhisi3" + [(set (match_operand:SI 0 "register_operand" "=3Dr,r") + (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0")) + (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi")))= )] "TARGET_40_PLUS" - "operands[3] =3D gen_lowpart(HImode, operands[1]);") + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (mult:SI (sign_extend:SI (match_dup 1)) + (sign_extend:SI (match_dup 2)))) + (clobber (reg:CC CC_REGNUM))])] + "") =20 -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=3Dr,r") ; even numbered! - (mult:SI (truncate:HI=20 - (match_operand:SI 1 "register_operand" "%0,0")) - (match_operand:HI 2 "general_operand" "rR,Qi")))] - "TARGET_40_PLUS" +(define_insn "mulhisi3" + [(set (match_operand:SI 0 "register_operand" "=3Dr,r") + (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0")) + (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi")))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_40_PLUS && reload_completed" "mul %2, %0" [(set_attr "length" "2,4")]) =20 -;(define_insn "mulhisi3" -; [(set (match_operand:SI 0 "register_operand" "=3Dr,r") ; even numbered! -; (mult:SI (truncate:HI=20 -; (match_operand:SI 1 "register_operand" "%0,0")) -; (match_operand:HI 2 "general_operand" "rR,Qi")))] -; "TARGET_40_PLUS" -; "mul %2, %0" -; [(set_attr "length" "2,4")]) - ;;- divide -(define_insn "divdf3" +(define_insn_and_split "divdf3" [(set (match_operand:DF 0 "register_operand" "=3Da,a") (div:DF (match_operand:DF 1 "register_operand" "0,0") (match_operand:DF 2 "general_operand" "fR,QF")))] "TARGET_FPU" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2))) + (clobber (reg:CC FCC_REGNUM))])] + "") +=20=20 +(define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=3Da,a") + (div:DF (match_operand:DF 1 "register_operand" "0,0") + (match_operand:DF 2 "general_operand" "fR,QF"))) + (clobber (reg:CC FCC_REGNUM))] + "TARGET_FPU && reload_completed" "{divd|divf} %2, %0" [(set_attr "length" "2,4")]) =20 -=09=20 -(define_expand "divhi3" - [(set (subreg:HI (match_dup 1) 0) +(define_expand "divmodhi4" + [(parallel + [(set (subreg:HI (match_dup 1) 0) (div:HI (match_operand:SI 1 "register_operand" "0") (match_operand:HI 2 "general_operand" "g"))) + (set (subreg:HI (match_dup 1) 2) + (mod:HI (match_dup 1) (match_dup 2)))]) (set (match_operand:HI 0 "register_operand" "=3Dr") - (subreg:HI (match_dup 1) 0))] + (subreg:HI (match_dup 1) 0)) + (set (match_operand:HI 3 "register_operand" "=3Dr") + (subreg:HI (match_dup 1) 2))] "TARGET_40_PLUS" "") =20 -(define_insn "" - [(set (subreg:HI (match_operand:SI 0 "register_operand" "=3Dr") 0) - (div:HI (match_operand:SI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] +(define_insn_and_split "*divmodhi4" + [(set (subreg:HI (match_operand:SI 0 "register_operand" "=3Dr,r") 0) + (div:HI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:HI 2 "general_operand" "rR,Qi"))) + (set (subreg:HI (match_dup 1) 2) + (mod:HI (match_dup 1) (match_dup 2)))] "TARGET_40_PLUS" - "div %2,%0" - [(set_attr "length" "4")]) - -(define_expand "modhi3" - [(set (subreg:HI (match_dup 1) 2) - (mod:HI (match_operand:SI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "g"))) - (set (match_operand:HI 0 "register_operand" "=3Dr") - (subreg:HI (match_dup 1) 2))] - "TARGET_40_PLUS" + "#" + "&& reload_completed" + [(parallel [(set (subreg:HI (match_dup 0) 0) + (div:HI (match_dup 1) (match_dup 2))) + (set (subreg:HI (match_dup 1) 2) + (mod:HI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] "") =20 -(define_insn "" - [(set (subreg:HI (match_operand:SI 0 "register_operand" "=3Dr") 2) - (mod:HI (match_operand:SI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] +;; Note that there is no corresponding CC setter pattern. +;; The reason is that it won't be generated, because +;; compare-elim.c only does the transformation on input +;; insns that have a two-element PARALLEL, as opposed to +;; the three-element one we have here.=20=20=20=20=20 +(define_insn "divmodhi4_nocc" + [(set (subreg:HI (match_operand:SI 0 "register_operand" "=3Dr,r") 0) + (div:HI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:HI 2 "general_operand" "rR,Qi"))) + (set (subreg:HI (match_dup 1) 2) + (mod:HI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))] "TARGET_40_PLUS" - "div %2,%0" - [(set_attr "length" "4")]) - -;(define_expand "divmodhi4" -; [(parallel [(set (subreg:HI (match_dup 1) 0) -; (div:HI (match_operand:SI 1 "register_operand" "0") -; (match_operand:HI 2 "general_operand" "g"))) -; (set (subreg:HI (match_dup 1) 2) -; (mod:HI (match_dup 1) -; (match_dup 2)))]) -; (set (match_operand:HI 3 "register_operand" "=3Dr") -; (subreg:HI (match_dup 1) 2)) -; (set (match_operand:HI 0 "register_operand" "=3Dr") -; (subreg:HI (match_dup 1) 0))] -; "TARGET_40_PLUS" -; "") -; -;(define_insn "" -; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=3Dr") 0) -; (div:HI (match_operand:SI 1 "general_operand" "0") -; (match_operand:HI 2 "general_operand" "g"))) -; (set (subreg:HI (match_dup 0) 2) -; (mod:HI (match_dup 1) -; (match_dup 2)))] -; "TARGET_40_PLUS" -; "div %2, %0") -; -=20=20=20 -;; is rotate doing the right thing to be included here ???? + "div %2,%0" + [(set_attr "length" "2,4")]) Index: config/pdp11/pdp11.opt =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/pdp11.opt (revision 262195) +++ config/pdp11/pdp11.opt (working copy) @@ -34,22 +34,6 @@ mac0 Target Report Mask(AC0) Return floating-point results in ac0 (fr0 in Unix assembler syntax). =20 -mbcopy -Target RejectNegative Report Mask(BCOPY) -Do not use inline patterns for copying memory. - -mbcopy-builtin -Target RejectNegative Report InverseMask(BCOPY, BCOPY_BUILTIN) -Use inline patterns for copying memory. - -mbranch-cheap -Target RejectNegative Report InverseMask(BRANCH_EXPENSIVE, BRANCH_CHEAP) -Do not pretend that branches are expensive. - -mbranch-expensive -Target RejectNegative Report Mask(BRANCH_EXPENSIVE) -Pretend that branches are expensive. - mdec-asm Target RejectNegative Report InverseMask(UNIX_ASM) Use the DEC assembler syntax. Index: config/pdp11/predicates.md =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- config/pdp11/predicates.md (revision 262195) +++ config/pdp11/predicates.md (working copy) @@ -23,18 +23,13 @@ (ior (match_operand 0 "register_operand") (match_test "op =3D=3D CONST0_RTX (GET_MODE (op))"))) =20 -;; Accept integer arguments in the range -4..-2 and 2..4, which are the +;; Accept integer arguments in the range 1..3, which are the ;; shift counts for which we unroll a shift. This matches the rule for ;; the "O" constraint. (define_predicate "expand_shift_operand" - (match_code "const_int") -{ - int sh; + (and (match_code "const_int") + (match_test "(unsigned) INTVAL (op) < 4"))) =20 - sh =3D INTVAL (op); - return (abs (sh) > 1 && abs (sh) <=3D 4); -}) - ;; Accept anything general_operand accepts, except that registers must ;; be FPU registers. (define_predicate "float_operand" @@ -52,3 +47,7 @@ (match_test "REGNO_REG_CLASS (REGNO (op)) =3D=3D LOAD_FPU_REGS") (match_test "REGNO_REG_CLASS (REGNO (op)) =3D=3D NO_LOAD_FPU_REGS")) (match_operand 0 "nonimmediate_operand"))) + +;; Accept any comparison valid for CCNZmode +(define_predicate "ccnz_operator" + (match_code "eq,ne,ge,lt")) Index: doc/invoke.texi =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- doc/invoke.texi (revision 262195) +++ doc/invoke.texi (working copy) @@ -969,11 +969,9 @@ Objective-C and Objective-C++ Dialects}. =20 @emph{PDP-11 Options} @gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol --mbcopy -mbcopy-builtin -mint32 -mno-int16 @gol --mint16 -mno-int32 -mfloat32 -mno-float64 @gol --mfloat64 -mno-float32 -mabshi -mno-abshi @gol --mbranch-expensive -mbranch-cheap @gol --munix-asm -mdec-asm} +-mint32 -mno-int16 -mint16 -mno-int32 @gol +-mfloat32 -mno-float64 -mfloat64 -mno-float32 @gol +-msplit -munix-asm -mdec-asm} =20 @emph{picoChip Options} @gccoptlist{-mae=3D@var{ae_type} -mvliw-lookahead=3D@var{N} @gol @@ -22018,7 +22016,7 @@ These options are defined for the PDP-11: @item -mfpu @opindex mfpu Use hardware FPP floating point. This is the default. (FIS floating -point on the PDP-11/40 is not supported.) +point on the PDP-11/40 is not supported.) Implies -m45. =20 @item -msoft-float @opindex msoft-float @@ -22034,7 +22032,7 @@ Return floating-point results in memory. This is =20 @item -m40 @opindex m40 -Generate code for a PDP-11/40. +Generate code for a PDP-11/40. Implies -msoft-float -mno-split. =20 @item -m45 @opindex m45 @@ -22042,17 +22040,8 @@ Generate code for a PDP-11/45. This is the defaul =20 @item -m10 @opindex m10 -Generate code for a PDP-11/10. +Generate code for a PDP-11/10. Implies -msoft-float -mno-split. =20 -@item -mbcopy-builtin -@opindex mbcopy-builtin -Use inline @code{movmemhi} patterns for copying memory. This is the -default. - -@item -mbcopy -@opindex mbcopy -Do not use inline @code{movmemhi} patterns for copying memory. - @item -mint16 @itemx -mno-int32 @opindex mint16 @@ -22077,32 +22066,17 @@ Use 64-bit @code{float}. This is the default. @opindex mno-float64 Use 32-bit @code{float}. =20 -@item -mabshi -@opindex mabshi -Use @code{abshi2} pattern. This is the default. +@item -msplit +@opindex msplit +Target has split instruction and data space. Implies -m45. =20 -@item -mno-abshi -@opindex mno-abshi -Do not use @code{abshi2} pattern. - -@item -mbranch-expensive -@opindex mbranch-expensive -Pretend that branches are expensive. This is for experimenting with -code generation only. - -@item -mbranch-cheap -@opindex mbranch-cheap -Do not pretend that branches are expensive. This is the default. - @item -munix-asm @opindex munix-asm -Use Unix assembler syntax. This is the default when configured for -@samp{pdp11-*-bsd}. +Use Unix assembler syntax. =20 @item -mdec-asm @opindex mdec-asm -Use DEC assembler syntax. This is the default when configured for any -PDP-11 target other than @samp{pdp11-*-bsd}. +Use DEC assembler syntax. This is the default. @end table =20 @node picoChip Options Index: doc/md.texi =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- doc/md.texi (revision 262195) +++ doc/md.texi (working copy) @@ -2966,6 +2966,10 @@ memory with a single instruction. Odd numbered general registers (R1, R3, R5). These are used for 16-bit multiply operations. =20 +@item D +A memory reference that is encoded within the opcode, but not +auto-increment or auto-decrement. + @item f Any of the floating point registers (AC0 through AC5). =20 @@ -2972,6 +2976,10 @@ Any of the floating point registers (AC0 through A @item G Floating point constant 0. =20 +@item h +Floating point registers AC4 and AC5. These cannot be loaded from/to +memory with a single instruction. + @item I An integer constant that fits in 16 bits. =20 @@ -2992,7 +3000,7 @@ The integer constant @minus{}1. The integer constant 0. =20 @item O -Integer constants @minus{}4 through @minus{}1 and 1 through 4; shifts by t= hese +Integer constants 0 through 3; shifts by these amounts are handled as multiple single-bit shifts rather than a single variable-length shift. =20