Hi there.  The machine I'm working is part accumulator based, part
register based.  I'm having trouble figuring out how best to tell the
compiler how ACC is affected and when.

For example, the add instruction is two operand with the destination
being a general register:
  ADD, R11 is equivalent to R11 = R11 + ACC

This works fine using a rule like
(define_insn "addsi3_insn"
  [(set (match_operand:SI 0 "register_operand"  "=r")
        (plus:SI
         (match_operand:SI 1 "register_operand" "0")
         (match_operand:SI 2 "register_operand" "b")))]

(b is the constraint that the register comes from the ACC_REGS class)

The logical right shift instruction only works on the accumulator:
  LSR1 is equivalent to ACC = ACC >> 1

This works fine using:
(define_insn "lshrsi3_const"
  [(set (match_operand:SI 0 "register_operand" "=b")
        (lshiftrt:SI
         (match_operand:SI 1 "register_operand" "0")
         (match_operand:SI 2 "immediate_operand" "")))]

The problem is when I have to clobber ACC such as when moving between
registers.  The output should be:
 LOADACC, R10; STOREACC, R11 (equivalent to ACC = R10; R11 = ACC)

I've tried a parallel clobber like:
(define_insn "movsi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=b,   dam,dam")
        (match_operand:SI 1 "general_operand"       "dami,b,  dam"))
  (clobber (reg:SI TREG_ACC))

 but this causes trouble when setting up ACC for the likes of the add
above.  The compiler runs but the code is incorrect

I've tried a parallel with a match_scratch like:
(define_insn "movsi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=b,   rm,rm")
        (match_operand:SI 1 "general_operand"       "rmi,b,  rm"))
  (clobber (match_scratch:SI 2 "=X,X,b"))
  ]
  ""
  "@
  LOADACC, %1
  STOREACC, %0
  LOADACC, %1\;STOREACC, %0"

This uses a 'b' constraint to put the scratch into ACC when moving
between registers and a 'X' constraint to ignore the scratch when
moving to or from ACC directly.

This basically works but fails when mixed with other instructions.
For example, the code:

  return left + right

fails with a 'movsi does not meet constraints' as ACC was already
allocated to one of the operands of the addsi, was not available for
the scratch register, and as such something else was given to the
movsi which didn't match the 'b' constraint.

All of the other instructions are OK as I can clobber or mark ACC as
an output reload to mark it as dirty.

Even the 68hc11 is better off as it can directly move between any two
registers :)

Any ideas?  Am I going about this the wrong way?  My first port
treated ACC as a fixed register which avoided all of this but
generated too many loads and stores.  Is there a way of using a
register only if a chain of instructions use it?  Can I peephole it in
someway instead?

-- Michael

Reply via email to