Mohamed Shafi wrote:
> Hello Omar,
>
> I saw your mail to gcc mailing list regarding splitting of HImode
> patterns into QImode patterns. I am also involved in porting. My
> problem is similar to yours. But i have to split SImode patterns into
> HImode patterns.
>
> I am sure that you have modified your define_split patterns after
> receiving the suggestions from the mailing list. Could you just mail
> me the finalized define_split pattern of HImode.
>
> One thing that i noticed in your split pattern is that you are not
> handling cases where operand[0] is memory, i.e store patterns.  How
> are you handling this? Do you have a define_insn for this case?
>
> I hope you don't mind me asking these questions.
>
> Thank you for your time.
>
> Regards,
> Shafi
>
>

Hi Mohamed,
  I added the gcc mailing list to the threat.

My current implementation looks like this:
;; movhi
(define_expand "movhi"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
         (match_operand:HI 1 "general_operand"      ""))]
""
{
   if (c816_expand_move (HImode, operands)) {
       DONE;
   }
})

;; =&r creates an early clobber.
;; It prevent insn where the target register
;; is the same as the base register used for memory addressing...
;; This is needed so that the split produce correct code.
(define_insn "*movhi"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=&r,m")
         (match_operand:HI 1 "general_operand"      "g,r"))]
""
"#")

(define_split
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
         (match_operand:HI 1 "general_operand"      ""))]
   "reload_completed"
[(set (match_dup 2) (match_dup 4))
  (set (match_dup 3) (match_dup 5))]
  "{
   gcc_assert (REG_P (operands[0]) || MEM_P (operands[0]));

#ifdef DEBUG_OVERLAP
   if (reg_overlap_mentioned_p(operands[0], operands[1])){
       fprintf (stderr, \"\nOperands Overlap:\n\");
       debug_rtx (curr_insn);
   }
#endif

   if (REG_P (operands[0])) {
       operands[2] = gen_highpart(QImode, operands[0]);
       operands[3] = gen_lowpart (QImode, operands[0]);
   }
   else if (MEM_P (operands[0])) {
       operands[2] = adjust_address (operands[0], QImode, 0);
       operands[3] = adjust_address (operands[0], QImode, 1);
   }

   if (MEM_P (operands[1])) {// || CONST == GET_CODE (operands[1])) {
       operands[4] = adjust_address (operands[1], QImode, 0);
       operands[5] = adjust_address (operands[1], QImode, 1);
   }
   else if (LABEL_REF == GET_CODE (operands[1])
          || SYMBOL_REF == GET_CODE (operands[1])) {//
       operands[4] = simplify_gen_subreg(QImode, operands[1], HImode, 0);
       operands[5] = simplify_gen_subreg(QImode, operands[1], HImode, 1);
   }
   else if (CONST_INT == GET_CODE (operands[1])
          || REG_P (operands[1])) {
       operands[4] = simplify_gen_subreg(QImode, operands[1], HImode, 0);
       operands[5] = simplify_gen_subreg(QImode, operands[1], HImode, 1);
   }
   else {
       error(\"Unrecognized code in operands[1]\");
       fputs(\"\nrtx code is: \", stderr);
       debug_rtx(curr_insn);
       abort();
   }
  }")


The purpose of the expand is to load Label or Symbol references into
base registers for index addressing. I decided to use the expand since
the force_reg() was failing when I called from the split.

The c816_expand_move() is implemented as follows:
bool
c816_expand_move (enum machine_mode mode, rtx *operands) {
   if (!no_new_pseudos) {
     int i;
     for (i = 0; i < 2; i++) {
       if (MEM_P (operands[i]) || CONST == GET_CODE (operands[i])) {
        rtx base = XEXP (operands[i],0);
        if (CONST == GET_CODE(base)) {
          base = XEXP (base,0);
        }
        if (PLUS == GET_CODE (base)) {
          rtx off = XEXP (base,1);
          base = XEXP (base,0);
          if (SYMBOL_REF == GET_CODE (base)
              || LABEL_REF == GET_CODE (base)) {
            rtx newreg = force_reg (Pmode, base);
            operands[i] = gen_rtx_MEM (mode,
                                       gen_rtx_PLUS (Pmode,
                                                     newreg,
                                                     off));
          }
        }
        else if (SYMBOL_REF == GET_CODE (base)
                 || LABEL_REF == GET_CODE(base)) {
          rtx newreg = force_reg (Pmode, base);
          operands[i] = gen_rtx_MEM (mode, newreg);
        }
       }// if MEM_P
     }// for
   }// if !no_new_pseudos
   return false;
}

In your case, you might want to look at other gcc ports for 16-bit
machines. One I have look from time to time is the MSP430 port
(http://mspgcc.sourceforge.net/).

Hope this helps.
Good Luck,
-Omar

Reply via email to