public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Destructive comparison
@ 2009-05-17 16:33 Michael Hope
  2009-05-17 18:28 ` Jim Wilson
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Hope @ 2009-05-17 16:33 UTC (permalink / raw)
  To: gcc

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-05-18 19:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-17 16:33 Destructive comparison Michael Hope
2009-05-17 18:28 ` Jim Wilson
2009-05-18 12:34   ` Michael Hope
2009-05-19  0:02     ` Jim Wilson
2009-05-19  0:38       ` Michael Hope

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).