Hello all,

The target that i am working on is 16bit, big endian and with 16 registers.
It has this particular addressing mode

load Rd, Ra[offset]
store Rs, Ra[offset]

where the offset should be positive, base register Ra should be an
even register and for the source or the destination register Rd/Ra,
the restriction is
that it should be one more than the base register . So the following
instructions are valid:

load R5, R4[4]
store R11, R10[2]

while the following ones are wrong:

load R8, R6[4]
store R3, R8[2]

What i did to implement this is to have eight register classes with
each class having two registers, an even register and an odd register
then in define expand look for the register indirect with offset
addressing mode and emit gen_store_offset or gen_load_offset pattern
if the addressing mode is found. In the pattern i will have the 8
similar constraints for the base register and the source/destination
register. But this didn't work out properly, probably because i had
many patterns for movhi operations. So i tired what Jim Wilson
suggested to me when i posted this question earlier. What he suggested
was:

"One thing you could try is generating a double-word pseudo-reg at RTL
expand time, and then using subreg 0 for the source and subreg 1 for
the dest (or vice versa depending on endianness/word order).  This
will get you a register pair you can use from the register allocator.
This doesn't help at reload time though.

You probably have to define a constraint for every register, and then
write an alternative for every register pair matching the correct even
register with the correct odd register.  That gets you past reload."

So i did the following to implement his suggestion.
I have single define_expand and define_insn for movhi patterns. In
define_expand for movhi i have the folllowing

    offset = INTVAL(XEXP(XEXP(mem_op, 0), 1));
    dword = gen_reg_rtx (SImode);
    base = simplify_gen_subreg (HImode, dword, SImode, 0);

    if (mode == Pmode) {
      reg_op = simplify_gen_subreg (HImode, dword, SImode, 2);
      mem_op1 = gen_rtx_MEM (Pmode, plus_constant (base, offset));
    }
    else {
      reg_op = simplify_gen_subreg (QImode, dword, SImode, 3);
      mem_op1 = gen_rtx_MEM (QImode, plus_constant (base, offset));
    }

    if (GET_CODE (operands[0]) == MEM) {
        operands[0] = mem_op1;
        operands[1] = reg_op;
      }
    else if (GET_CODE (operands[1]) == MEM) {
        operands[1] = mem_op1;
        operands[0] = reg_op;
      }


and in define_insn i have the following pattern:

(define_insn "*movhi_internal"
  [(set (match_operand:HI 0 "nonimmediate_operand"
"=r,R01,R03,R05,R07,R09,R13,R15,r,U00,U02,U04,U06,U08,U12,U14,m,r")
        (match_operand:HI 1 "general_operand"
"r,U00,U02,U04,U06,U08,U12,U14,m,R01,R03,R05,R07,R09,R13,R15,r,i"))]

where Uxx is memory constraints and Rxx is register constraints.
After implementing this i came across this problem:


(insn 12 11 13 1 (set (reg/f:HI 24)
        (mem/c/i:HI (reg/f:HI 25) [0 m+0 S2 A16])) -1 (nil)
    (nil))

(insn 13 12 14 1 (set (subreg:QI (reg:SI 28) 3)
        (mem:QI (plus:HI (subreg:HI (reg:SI 28) 0)
                (const_int 1 [0x1])) [0 S1 A8])) -1 (nil)
    (nil))

(insn 14 13 15 1 (set (reg:HI 26)
        (zero_extend:HI (reg:QI 27))) -1 (nil)
    (nil))

For zero-extend both operands should be in registers. So one operand
which was previously in memory is moved to reg27 through load
operations(insn 13). Since for this offset addressing mode is used
define_expand for movqi will generate SImode register, reg28 and does
the operations. But this is not reflected in the subsequent
instructions (insn 14). And hence insn 13 is getting deleted as its
operands are never used.

What i am i doing wrong? Am i implementing the addressing mode properly?

Any help is appreciated.

Regards,
Shafi

Reply via email to