Subject: asm() bugs
To: None <port-mac68k@NetBSD.ORG>
From: Taras Ivanenko <ivanenko@ctpa03.mit.edu>
List: port-mac68k
Date: 05/14/1996 07:59:15
When was the last time you checked the *assembler* output of the
compiler? Here is the simple example:

void f(int A, int B)
{
	int C;

	/* some code */

	asm("movel %0, a0
	movel %1, a1
	jsr _some_external_function:
	: "=g"(A), "=g"(C) );

	/* more code */
}

How it is supposed to be executed? The value of A will be put into
"a0", the value of C into "a1" and then call ... But what if C was assigned
to the register "a0"? Then the compiler will produce the code

movel A, a0
movel a0, a1 <--- so that some_external_function is called with
arguments (A,A) instead of (A,C). Saving the registers inside asm()
would not help either as the problem is related to the variables
external to the asm() block.

Here is the real example (from the file macrom.c)

int
mrg_NewPtr()
{
	int result = noErr;
	u_int numbytes;
	u_int32_t trapword;
	caddr_t ptr;

	asm("	movl	d1, %0
		movl	d0, %1"
!		: "=g" (trapword), "=g" (numbytes)
+	    :: "d0", "d1");

#if defined(MRG_SHOWTRAPS)
	printf("mrg: NewPtr(%d bytes, %sclear, %ssys)", numbytes,
		TRAP_SYS(trapword) ? "" : "no ",
		TRAP_CLEAR(trapword) ? "" : "no ");
#endif

and here is the assembler output for this function:

_mrg_NewPtr:
	link a6,#0
	moveml #0x2030,sp@-
	clrl d2
#APP
		movl	d1, d0
		movl	d0, a3
#NO_APP

The variable trapword was assigned from d1 and the variable numbytes
got it's value from trapword. I doubt that was the original intention.
The solution: for each asm() statement specify the "bashed registers"
as I did for this example (after the second colon) I can do the
context diff, but it is easier just to search through the code and fix
asm() statements then apply diffs (my sources are significantly
different from -current)

	Taras Ivanenko