From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10597 invoked by alias); 8 May 2013 11:50:24 -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 10583 invoked by uid 89); 8 May 2013 11:50:23 -0000 X-Spam-SWARE-Status: No, score=-7.6 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS,TW_KN autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 08 May 2013 11:50:23 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r48BoLoI024284 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 8 May 2013 07:50:21 -0400 Received: from [10.36.5.180] (vpn1-5-180.ams2.redhat.com [10.36.5.180]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r48Bo7Ts010496 (version=TLSv1/SSLv3 cipher=DHE-RSA-CAMELLIA256-SHA bits=256 verify=NO); Wed, 8 May 2013 07:50:13 -0400 Message-ID: <518A3BDE.7090301@redhat.com> Date: Wed, 08 May 2013 11:50:00 -0000 From: nick clifton User-Agent: Mozilla/5.0 (X11; Linux i686; rv:20.0) Gecko/20100101 Firefox/20.0 SeaMonkey/2.17.1 MIME-Version: 1.0 To: DJ Delorie CC: gcc-patches@gcc.gnu.org Subject: Re: RFA: RL78: Improve interrupt function generation References: <8761z2lwvh.fsf@redhat.com> <201305062206.r46M6eu9024672@greed.delorie.com> In-Reply-To: <201305062206.r46M6eu9024672@greed.delorie.com> Content-Type: multipart/mixed; boundary="------------060504010502070105070700" X-Virus-Found: No X-SW-Source: 2013-05/txt/msg00402.txt.bz2 This is a multi-part message in MIME format. --------------060504010502070105070700 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1627 Hi DJ, >> * Uses register bank 3 instead of register bank 0 inside the >> handler. > > I wonder if nested interrupts will cause problems, since the second > interrupt will occur with RB3 already selected. Yes - in fact this appears to be a general problem with RL78 interrupt handlers. There are no instructions to push/pop the current bank selection, so in order for nested interrupt handlers to work they would have to do something like: push ax ; Save AX mov psw, a ; Get the current register bank selection push ax ; Save it. [... rest of interrupt handler code ...] pop ax and a, #0x24 cmp a, #0x24 sknz sel rb3 cmp a, #0x20 sknz sel rb2 cmp a, #0x04 sknz sel rb1 cmp0 a sknz sel rb0 pop ax Which sure seems messy to me. Is it reasonable to say that C based interrupt handlers cannot be nested, or would you like me to extend the current patch to generate prologues/epilogues as suggested above ? > Also, there are some hand-coded routines in libgloss/libgcc that > manually swap banks, they'd have to be checked to see if there are > issues there. Perhaps the G10 work there solved it already. There are ? I did not find any. > Those, plus Vinay's patch, should be OK otherwise. Vinay's patch was based on the RL78 backend supporting the G10 architecture variant, which it currently does not. So I am attaching a revised patch which includes my ISR improvements, Vinay's G10 ISR improvements and the addition of G10 support to the RL78 backend. What do you think of this version ? Cheers Nick --------------060504010502070105070700 Content-Type: application/x-troff-man; name="rl78.intr.patch.2" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="rl78.intr.patch.2" Content-length: 8514 Index: gcc/config/rl78/rl78.c =================================================================== --- gcc/config/rl78/rl78.c (revision 198703) +++ gcc/config/rl78/rl78.c (working copy) @@ -161,11 +161,21 @@ { int i; - for (i = 0; i < 8; i++) + if (TARGET_G10) { - fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i); - fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i); + /* The memory used is 0xffec8 to 0xffedf; real registers are in + 0xffee0 to 0xffee7. */ + for (i = 8; i < 32; i++) + fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i); } + else + { + for (i = 0; i < 8; i++) + { + fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i); + fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i); + } + } register_pass (& rl78_devirt_info); } @@ -373,34 +383,42 @@ return true; } -/* Returns nonzero if the given register needs to be saved by the +/* Returns true if the given register needs to be saved by the current function. */ -static int -need_to_save (int regno) +static bool +need_to_save (unsigned int regno) { if (is_interrupt_func (cfun->decl)) { + /* We don't need to save registers that have + been reserved for interrupt handlers. */ + if (regno > 23) + return false; + + /* If the handler is a non-leaf function then it may call + non-interrupt aware routines which will happily clobber + any call_used registers, so we have to preserve them. */ + if (!crtl->is_leaf && call_used_regs[regno]) + return true; + + /* Interrupt functions do not use register bank 0. */ if (regno < 8) - return 1; /* don't know what devirt will need */ - if (regno > 23) - return 0; /* don't need to save interrupt registers */ - if (crtl->is_leaf) - { - return df_regs_ever_live_p (regno); - } - else - return 1; + return false; + + /* Otherwise we only have to save a register, call_used + or not, if it is used by this handler. */ + return df_regs_ever_live_p (regno); } if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) - return 1; + return true; if (fixed_regs[regno]) - return 0; + return false; if (crtl->calls_eh_return) - return 1; + return true; if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) - return 1; - return 0; + return true; + return false; } /* We use this to wrap all emitted insns in the prologue. */ @@ -499,6 +517,8 @@ false }, { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute, false }, + { "naked", 0, 0, true, false, false, rl78_handle_func_attribute, + false }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -753,8 +773,6 @@ { /* This always works. */ result = gen_reg_rtx (SImode); - debug_rtx(result); - debug_rtx(op); emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op); emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx); return result; @@ -825,6 +843,12 @@ return rv; } +static int +rl78_is_naked_func (void) +{ + return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE); +} + /* Expand the function prologue (from the prologue pattern). */ void rl78_expand_prologue (void) @@ -833,27 +857,45 @@ rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM); int rb = 0; + if (rl78_is_naked_func ()) + return; + + rb = is_interrupt_func (cfun->decl) && ! TARGET_G10 ? -1 : 0; + if (!cfun->machine->computed) rl78_compute_frame_info (); if (flag_stack_usage_info) current_function_static_stack_size = cfun->machine->framesize; - if (is_interrupt_func (cfun->decl)) - emit_insn (gen_sel_rb (GEN_INT (0))); - for (i = 0; i < 16; i++) if (cfun->machine->need_to_push [i]) { - int need_bank = i/4; - if (need_bank != rb) + if (TARGET_G10) { - emit_insn (gen_sel_rb (GEN_INT (need_bank))); - rb = need_bank; + emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2)); + F (emit_insn (gen_push (gen_rtx_REG (HImode, 0)))); } - F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2)))); + else + { + int need_bank = i/4; + + if (need_bank != rb) + { + emit_insn (gen_sel_rb (GEN_INT (need_bank))); + rb = need_bank; + } + F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2)))); + } } - if (rb != 0) + + /* Interrupt functions use rb3 instead of rb0. */ + if (is_interrupt_func (cfun->decl) && ! TARGET_G10) + { + if (rb != 3) + emit_insn (gen_sel_rb (GEN_INT (3))); + } + else if (rb != 0) emit_insn (gen_sel_rb (GEN_INT (0))); if (frame_pointer_needed) @@ -877,6 +919,11 @@ rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM); int rb = 0; + if (rl78_is_naked_func ()) + return; + + rb = is_interrupt_func (cfun->decl) && ! TARGET_G10 ? 3 : 0; + if (frame_pointer_needed) { emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM), @@ -897,14 +944,22 @@ for (i = 15; i >= 0; i--) if (cfun->machine->need_to_push [i]) { - int need_bank = i / 4; - - if (need_bank != rb) + if (TARGET_G10) { - emit_insn (gen_sel_rb (GEN_INT (need_bank))); - rb = need_bank; + emit_insn (gen_pop (gen_rtx_REG (HImode, 0))); + emit_move_insn (gen_rtx_REG (HImode, i * 2), gen_rtx_REG (HImode, 0)); } - emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2))); + else + { + int need_bank = i / 4; + + if (need_bank != rb) + { + emit_insn (gen_sel_rb (GEN_INT (need_bank))); + rb = need_bank; + } + emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2))); + } } if (rb != 0) Index: gcc/config/rl78/rl78.h =================================================================== --- gcc/config/rl78/rl78.h (revision 198703) +++ gcc/config/rl78/rl78.h (working copy) @@ -32,6 +32,8 @@ builtin_define ("__RL78_MUL_RL78__"); \ if (RL78_MUL_G13) \ builtin_define ("__RL78_MUL_G13__"); \ + if (TARGET_G10) \ + builtin_define ("__RL78_G10__"); \ } \ while (0) @@ -41,6 +43,11 @@ #undef ENDFILE_SPEC #define ENDFILE_SPEC "crtend.o%s crtn.o%s" +#undef ASM_SPEC +#define ASM_SPEC "\ +%{mg10} \ +" + #undef LIB_SPEC #define LIB_SPEC " \ --start-group \ Index: gcc/config/rl78/rl78.md =================================================================== --- gcc/config/rl78/rl78.md (revision 198703) +++ gcc/config/rl78/rl78.md (working copy) @@ -141,7 +141,7 @@ (define_insn "sel_rb" [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)] - "" + "!TARGET_G10" "sel\trb%u0" ) Index: gcc/config/rl78/rl78.opt =================================================================== --- gcc/config/rl78/rl78.opt (revision 198703) +++ gcc/config/rl78/rl78.opt (working copy) @@ -41,3 +41,7 @@ EnumValue Enum(rl78_mul_types) String(g13) Value(MUL_G13) + +mg10 +Target Mask(G10) Report +Target the RL78/G10 series Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 198703) +++ gcc/doc/extend.texi (working copy) @@ -3142,7 +3142,7 @@ @item naked @cindex function without a prologue/epilogue code -Use this attribute on the ARM, AVR, MCORE, RX and SPU ports to indicate that +Use this attribute on the ARM, AVR, MCORE, RL78, RX and SPU ports to indicate that the specified function does not need prologue/epilogue sequences generated by the compiler. It is up to the programmer to provide these sequences. The only statements that can be safely included in naked functions are Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 198703) +++ gcc/doc/invoke.texi (working copy) @@ -811,7 +811,7 @@ See RS/6000 and PowerPC Options. @emph{RL78 Options} -@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=rl78} +@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=rl78 -mg10} @emph{RS/6000 and PowerPC Options} @gccoptlist{-mcpu=@var{cpu-type} @gol @@ -17216,6 +17216,10 @@ only on the RL78/G13 targets. The @code{rl78} option is for the standard hardware multiplication defined in the RL78 software manual. +@item -mg10 +@opindex mg10 +Generate code targeted at the RL78/G10 series of microprocessors. + @end table @node RS/6000 and PowerPC Options --------------060504010502070105070700--