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