[comp.sys.amiga] Printer drivers and Aztec 3.04a

kaz@cadovax.UUCP (Kerry Zimmerman) (05/04/87)

[]

I ran into a problem this weekend converting an Epson LQ800
printer driver to Manx Aztec 3.04a.  I have read the recent notes
posted by others describing their efforts in this area.  No one
seems to have mentioned what I ran into.

I compiled the driver with no problem using the +BCD compiler options 
and linked it with the cl32.lib.  The driver worked fine until graphic 
printing was finished, at which point the system GURUed.

I eventually isolated the problem by using the +AT option to get
the assembly source for render.c.  What I determined (using DB)
was that register A6 is used by render, but not saved and restored
before and after the routine.  As a result, the printer.device who
calls render, and who expected A6 to be preserved, crashed. 

I solved the problem (with a bandaid) by adding some assembly code
to save and restore A6 at the entrance and exit of render.

My question is shouldn't A6 have been protected automatically by
the compiler?  The compiler does preserve D2 and D3, why not A6?
Is there another option I should have used?  Is there anyway to
make A6 be the frame pointer (like in lattice) instead of A5?
This seems necessary since the printer.device was probably created
with lattice, and assumes A6 will be the frame pointer.

Thanks for any help.

Kerry Zimmerman
#  {ucbvax,ihnp4,decvax}!trwrb!cadovax!kaz
#  cadovax!kaz@ucla-locusre the

dillon@CORY.BERKELEY.EDU.UUCP (05/05/87)

>My question is shouldn't A6 have been protected automatically by
>the compiler?  The compiler does preserve D2 and D3, why not A6?
>Is there another option I should have used?  Is there anyway to
>make A6 be the frame pointer (like in lattice) instead of A5?
>This seems necessary since the printer.device was probably created
>with lattice, and assumes A6 will be the frame pointer.

	Why did they do this?  Simply because you MUST use A6 for your library
base pointer when making AMIGA library calls.  Thus, if one uses A5 as one's
frame pointer, one doesn't have to save and restore it every time one makes
a library call.

	However, I think Aztec was shortsided to simply assume A6 could be
scratch.

					-Matt

jmsynge@sqm.dec.com (James M Synge, DTN 381-1545) (05/10/87)

---------------------Reply to mail dated 4-MAY-1987 19:57---------------------

cardovax!kaz (Kerry Zimmerman) writes
> I eventually isolated the problem by using the +AT option to get
> the assembly source for render.c.  What I determined (using DB)
> was that register A6 is used by render, but not saved and restored
> before and after the routine.  As a result, the printer.device who
> calls render, and who expected A6 to be preserved, crashed. 
...
> My question is shouldn't A6 have been protected automatically by
> the compiler?

Unfortunately this isn't the only register which goes unprotected by Aztec 3.4,
but is nearly always the cause of all problems.  A4 is also not saved, but
even though the docs say that it can be used for storing register variables,
my experience has been that Aztec C never uses A4 for anything other than as
the program base pointer.

SO... If you write any C code, and compile it with Aztec C, which can be
called by any language other than Aztec C, then you will very likely have to
write some assembly language to protect A4/A6.  And great care must be taken
when doing so.  If the arguments are on the stack, then you cannot push the
registers on to the stack because then the args will be in the wrong place.
But!  If your code is to be reentrant, then you can not use a static location
for the resister backup.  If the args are in registers, then you may be able
to push them on to the stack.

For this latter case, the code might look like this:

	public	_sub		; long sub(char *, long) (A0,D0)
	public	__sub

__sub	movem.l	A4/A6,-(sp)	; Save the registers
	move.l	D0,-(sp)	; Push the second arg
	move.l	A0,-(sp)	; Push the first arg

	jsr	_sub		; Call the C routine

	addq.l	#8,sp		; Pop the args (sort of)
	movem.l	(sp)+,A4/A6	; Restore the registers

	rts			; Return

Good luck!

James Synge

USENET:  {decvax, ucbvax, allegra}!decwrl!sqm.dec.com!jmsynge
ARPAnet: jmsynge%sqm.DEC@decwrl.DEC.COM

#include <disclaimer.h>
"Ken Olsen can speak for Digital, not me!"

dillon@CORY.BERKELEY.EDU (Matt Dillon) (05/10/87)

	Aztec uses A4 as its base register for global data ONLY in the small
data model.  BUT (and I think Aztec made the correct decision here), it will
NOT use A4 at all in it's large data model unless you give it a specific
compile-time flag saying it's ok.  This is so small and large data segments
can be mixed freely.

	Aztec uses D0,D1,D2,D3,A0, and A1 as scratch (doesn't bother to save).
You can specify a 'super compatibility mode' flag, +p I believe, which causes
Aztec to save D2/D3 (thus conforming with amiga specs).  However, this is a 
problem only if some external routine calls aztec.  Definately not a problem
when Aztec calls some external routine.

	(P.S. A good guess as to why 4 data registers are 'scratch' is because
most, if not all expressions can be calculated utilizing 4 temporary registers)

	And we all know that Aztec doesn't bother to save A6 when it makes
library calls.  This is a deficiency in the library code to make those calls
rather than in the Aztec compiler.  Frankly, the increase in speed isn't
noticeable and it would have been well worth the effort to save that register.
Of course, those people with the commercial version could simply fixup those
library modules since they have the source, but this is not desireable because
the source would then be incompatible with everybody else's compiler.

				-Matt