[comp.sys.encore] word in registers

reeder@ut-emx.UUCP (William P. Reeder) (07/15/89)

Boy, this one makes my head hurt.  I have tried reading the "Series 32000
Programmer's Reference Manual" from Prentice-Hall to find the answer to
this question:  When I reference a word in a register, is it the least
significant word, or the most significant word?

Here is why I ask:  I have a FORTRAN program in which 1000 is greater
than 3.  I look at the assembly instructions generated by the Encore
f77 compiler and don't understand why things are busted.

Here is the subroutine which produces the problem.
      SUBROUTINE SUB ( PTR )
      INTEGER*2 PTR, LKEY, THOU

      LKEY = 2
      PTR = 1

      PTR = PTR + 1

      IF ( 1000 .LT. PTR+LKEY-1 ) THEN
      PRINT *, '1000 is less than 3'
      ELSE
      PRINT *, '1000 is greater than 3'
      ENDIF

      RETURN

      END

Here is the relevant assembler code (produced with f77 -S):
_sub_:
	enter	[],$24

	movd	8(fp),r1	# R1 contains address of ptr
	movqw	$2,r2		# R2 contains word value 2 (lkey)
	movqw	$1,0(r1)	# store 1 in word addressed in R1 (ptr=1)
	movxwd	0(r1),r0	# bring ptr into R0 as double
	addqd	$1,r0		# add (as doubles) 1 to contents of R0 (ptr+=1)
	movw	r0,0(r1)	# store low word back in memory
	movxwd	0(r1),r0	# bring it back
	addd	r2,r0		# add R2 to R0 as doubles (ptr+lkey)
	addqd	$-1,r0		# subtract 1 from R0 as doubles (ptr+lkey-1)
	cmpd	r0,$1000	# compare double in R0 with 1000 (clear N?)
	ble	.L15		# branch if N flag clear

I added the comments and deleted the code which followed the conditional
branch.

Now, when we get to the cmpd instruction, R0 *should* contain the value
3.  The binary in R0, most significant bit on the left, should be
	000000000000000000000000000000011
while 1000 as a double (the manual says it is sign extended to the size
of the compare) is
	000000000000000000000001111101000
Clearly, 1000 is greater than 3, so "cmpd  ro,$1000" should clear the N
flag in PSR, and the ble instruction should cause a jump to .L15 -- but
it doesn't.  The really sick part is that if I edit the .s file produced
by f77 -S and change the cmpd to cmpw, but change NOTHING else, then
run as and ld, the "proper" behavior is observed.

Can anyone explain what is going on with the this assembler?  And
can anyone from Encore tell me why f77 is generating this apparently
incorrect code?  I will be submitting a bug report to Encore about
this soon.  For those who care, I have an Encore Multimax 320 with
APC's, running Umax 4.2 Release 3.2.1, and with f77 release 2.0.r051.
-- 
William "Wills" Reeder, The University of Texas at Austin, Computation Center
reeder@emx.utexas.edu, uunet!cs.utexas.edu!ut-emx!reeder, (512)471-3241

DISCLAIMER:     Opinions expressed above are those of the author and do
not necessarily reflect the opinions of The University of Texas at Austin,
or those of the manufacturer of the wires which carried this message.

simpson@xenna.UUCP (Rich Simpson,Look for the plant on the pole.,x2609,5082636474) (07/17/89)

From article <15266@ut-emx.UUCP>, by reeder@ut-emx.UUCP (William P. Reeder):
-- 
-- Here is why I ask:  I have a FORTRAN program in which 1000 is greater
-- than 3.  I look at the assembly instructions generated by the Encore
-- f77 compiler and don't understand why things are busted.

-- Here is the relevant assembler code (produced with f77 -S):
-- 	movd	8(fp),r1	# R1 contains address of ptr
-- 	movqw	$2,r2		# R2 contains word value 2 (lkey)
-- 	movqw	$1,0(r1)	# store 1 in word addressed in R1 (ptr=1)
-- 	movxwd	0(r1),r0	# bring ptr into R0 as double
-- 	addqd	$1,r0		# add (as doubles) 1 to contents of R0 (ptr+=1)
-- 	movw	r0,0(r1)	# store low word back in memory
-- 	movxwd	0(r1),r0	# bring it back
-- 	addd	r2,r0		# add R2 to R0 as doubles (ptr+lkey)
The problem is here. The value in r2 is a word and the value in r0 is a
double. Either the compiler should have not done the movxwd into r0,
done an addw and then widened the result, or it should have widened
the value in r2 to double before the addd. The net effect is that
the addd picks up noise from the top half of r2 which throws the
cmpd off.
-- 	addqd	$-1,r0		# subtract 1 from R0 as doubles (ptr+lkey-1)
-- 	cmpd	r0,$1000	# compare double in R0 with 1000 (clear N?)
-- 	ble	.L15		# branch if N flag clear

-- Can anyone explain what is going on with the this assembler?  And
-- can anyone from Encore tell me why f77 is generating this apparently
-- incorrect code?  I will be submitting a bug report to Encore about
-- this soon.  For those who care, I have an Encore Multimax 320 with
-- APC's, running Umax 4.2 Release 3.2.1, and with f77 release 2.0.r051.
-- -- 
-- William "Wills" Reeder, The University of Texas at Austin, Computation Center
-- reeder@emx.utexas.edu, uunet!cs.utexas.edu!ut-emx!reeder, (512)471-3241

This problem is fixed in the 2.1 version of f77 which is currently in final
release testing and should be available within a month. There were a variety
of problems with handling INTEGER*2 expressions which have been fixed in 
this release. 

Rich Simpson
Encore Computer