This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Destructive comparison


Hi there.  I'm having trouble figuring out how to represent a
destructive comparison on the port I'm attempting.  The ISA is very
simple and accumulator based, so to generate a compare of two
registers you would do:

; Compare R10 and R11, destroying R11 and setting C

LOADACC, R10
XOR, R11

Note that the XOR instruction leaves the result in R11, i.e. R11 = R11 ^ ACC

; Greater than or equals, unsigned:

LOADACC, R10
NOTACC ; Ones complement the accumulator
ADD, R11 ; R11 = R11 + ACC, set C

The C flag is equivalent to a zero flag in many cases and a carry flag
in others so I've followed docs and defined different carry modes.
Setting C is done similar to MMIX and bfin where you finally emit a
set compare instruction such as:

(define_insn "cmpcc_insn"
  [(set (match_operand:CC 0 "register_operand" "=C")
	(compare:CC
	 (match_operand:SI 1 "register_operand" "d")
	 (match_operand:SI 2 "register_operand" "b")))
  ]
  ""
  "XOR, %1"
)

Note here the 'b' constraint is for registers in the ACC_REGS class
and 'd' is for registers in the DATA_REGS class.  This seems to work
fine, properly reloading the right operand into the accumulator.

How should I represent the destruction/clobbering of operand 1?  I've tried:

 * Setting the constraint to '=d' or '+d' to mark it as written
 * Using a (clobber (match_dup 1)) in the insn form, such as:

(define_insn "cmpcc_insn"
  [(set (match_operand:CC 0 "register_operand" "=C")
	(compare:CC
	 (match_operand:SI 1 "register_operand" "d")
	 (match_operand:SI 2 "register_operand" "b")))
  ]
  ""
  "XOR, %1"
)

 * Using a define_expand to clobber operand 1 later (outside the
insn's implicit parallel)
 * Using a define_insn to mark it as both a destructive xor and
compare in parallel, such as:

(define_insn "cmpcc_insn"
  [
  (set (match_operand:SI 0 "register_operand" "=d")
       (xor:SI
	(match_operand:SI 1 "register_operand" "%0")
	(match_operand:SI 2 "register_operand" "b")))
  (set (match_operand:CC 3 "register_operand" "=C")
       (compare:CC
	(match_dup 1)
	(match_dup 2)
	))

I'd rather not use a scratch register as the moving between registers
involves ACC, which would mean I'd need to save the right hand operand
before doing the move.  I'd rather have the reload do the move earlier
if required if the left operand lives past this instruction.

Thanks for any help,

-- Michael


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]