Shop OBEX P1 Docs P2 Docs Learn Events
CMPX/CMPSX Z flag issue — Parallax Forums

CMPX/CMPSX Z flag issue

ozpropdevozpropdev Posts: 2,791
edited 2016-06-15 06:41 in Propeller 2
Chip
I started a seperate thread for this issue highlighted by garri on another thread.
As garryi points out the Z flag is not being set and returns the previous Z state.

Here's another test snippet.
dat		org

		or	dirb, ##$ffff
		mov	outb,#0

		setcz	#%01 wc,wz	'set z flag = 1 (z)
		cmpx	a,b wz,wc
		setbz	outb,#0		'led0 on

		setcz	#%00 wc,wz	'set z flag = 0 (nz)
		cmpx	a,b wz,wc
		setbz	outb,#1		'led1 off, should be on

me		jmp	#me

a		long	3
b		long	3


Comments

  • cgraceycgracey Posts: 14,133
    edited 2016-06-15 07:43
    Those instructions are working correctly. They are just not documented, yet.

    ADDX
    ADDSX
    SUBX
    SUBSX
    CMPX
    CMPSX

    In the instructions above, the X means 'extended'. These instructions use the carry as an input and they also AND the old Z flag with what would have been the new Z flag in the non-X instruction versions. These are useful for multi-long additions, subtractions, and comparisons, where you'd like both C and Z to be valid at the end of the operation.

    Here is an example where two 64-bit values are compared:
    	cmp	v1+0, v2+0	wc,wz	'compare lower longs
    	cmpx	v1+1, v2+1	wc,wz	'compare upper longs
    
    	'c=1 if v1 < v2
    	'z=1 if v1 = v2
    
  • Thanks Chip

    I see now how I got my wires crossed there.
    Using the P1 manal as a reference I read the following.
    CMPX
    
    Instruction: Compare two unsigned values plus C.
    
    CMPX Value1, <#> Value2
    
    Result: Optionally, equality and greater/lesser status is written to the Z and C flags.
    
    The description of the result led me to believe it operated the same as CMP as the wording is the same.
    It's probably at this point in the manual it should mention the Old Z is ANDed with the New Z and not on the next page.

    I hear the echo of one of my old lecturer's now "READ the manual!"
    <:(

  • @garryi
    Based on my new found knowledge from the P1 docs, does this give you the result you expect.
    Note the CMPX line is preceeded by a SETCZ instruction and the CMPX instruction has it's fields reversed as the comparison is D field aginst S field +C.
    ' Test CMPX Z flag not being written as expected.
    
    dat
    		org
    
    		setword	dirb, ##$ffff, #0	' P123-A9 USER_LED15..0 used for feedback
    		setword	outb, #0, #0
    		mov	flag, #0
    .status
    		mov	d, status		' Fetch rx status
    		setbyte	outb, status, #1	' Show rx status byte on USER_LED15..8
    		shr	d, #8		wc	' Data byte to d, new byte toggle bit into C
    	if_c	or	outb, #$80		' Show state of C on USER_LED7
    		setcz	#1 wz			' <<< set Z = 1
    		cmpx	_1,flag		wz	' flag = 0 + C = 1: CMPX flag, #1 -> Z, toggle flag?
    						' flag = 0 + NC = 0: CPMX flag, #1 -> NZ, flag unchanged?
    						' flag = 1 + C = 2: CMPX flag, #1 -> NZ, flag unchanged?
    						' flag = 1 + NC = 1: CMPX flag, #1 -> Z, toggle flag?
    	if_z	or	outb, #$40		' Show state of Z on USER_LED6
    	if_z	xor	flag, #1		' New byte state change, so toggle flag
    		or	outb, flag		' Show state of flag register
    		waitx	##60_000_000
    		setword	outb, #0, #0
    		notb	status, #7		' Toggle new byte status flag
    		jmp	#.status
    
    _1		long	1
    status		long	$7784
    flag		res	1
    d		res	1
    


  • SeairthSeairth Posts: 2,474
    edited 2016-06-15 11:59
    This reminds me. I need to update the unit tests I had written: https://github.com/Seairth/P2UnitTests. They were for the 2015-10-29 image, so are a little bit out of date. However, for instructions like this, you can still look at the truth table at the end of each unit test. For instance, CMPX contains:
    	'       d           s            cz  r           rcz
    tests	long	$0000_0003, $0000_0002, %00, $0000_0003, %00
    	long	$0000_0003, $0000_0002, %10, $0000_0003, %00
    	long	$0000_0003, $0000_0002, %11, $0000_0003, %01
    	long	$0000_0003, $0000_0003, %00, $0000_0003, %00
    	long	$0000_0003, $0000_0003, %01, $0000_0003, %01	
    	long	$0000_0003, $0000_0003, %10, $0000_0003, %10
    	long	$0000_0003, $0000_0004, %00, $0000_0003, %10
    	long	$0000_0003, $0000_0004, %10, $0000_0003, %10
    	long	$8000_0000, $7FFF_FFFF, %00, $8000_0000, %00
    	long	$7FFF_FFFF, $8000_0000, %00, $7FFF_FFFF, %10
    	long	$FFFF_FFFE, $FFFF_FFFF, %00, $FFFF_FFFE, %10
    	long	$FFFF_FFFE, $FFFF_FFFF, %10, $FFFF_FFFE, %10
    	long	$FFFF_FFFE, $FFFF_FFFE, %00, $FFFF_FFFE, %00
    	long	$FFFF_FFFE, $FFFF_FFFE, %01, $FFFF_FFFE, %01
    	long	$FFFF_FFFE, $FFFF_FFFE, %10, $FFFF_FFFE, %10
    	long	$FFFF_FFFE, $FFFF_FFFD, %00, $FFFF_FFFE, %00
    	long	$FFFF_FFFE, $FFFF_FFFD, %10, $FFFF_FFFE, %00
    	long	$FFFF_FFFE, $FFFF_FFFD, %11, $FFFF_FFFE, %01
    

    where D, S, and CZ are initial values, and R and RCZ are the result values.
  • RaymanRayman Posts: 13,800
    edited 2016-06-15 14:18
    I tried this USB code snippet in the docs also and it didn't seem to work for me either.

    So, maybe docs are wrong or instruction is wrong?
  • Thanks all for the help and education!

    I suspected it might be a doc hiccup. In the context of the example, it looked like the P2 CMPX differed from the P1 and my forum searches missed the link to @Seairth's great work.

    But since it's much easier to change docs than silicon, I thought it would be prudent to ask :smile:
Sign In or Register to comment.