[comp.os.cpm] System use of Z80 registers

bridger%monty@RAND.ORG (Bridger Mitchell) (11/27/90)

Mitch Mlinar wrote:
>> Regarding BIOS:  Kaypro assumed that you were in an 8080 world AND interrupts
>> do not exist.  (They wrote their BIOS in Z80 code, though, and used the
>> "back-side" Z80 registers.)  Bridger Mitchell (TurboROM) is better here in
>> that he understands that interrupts might exist, but ALSO assumes that one
>> lives in an 8080 world only.  In other words, the assumption is that IX and
>> IY registers are unchanged outside of your program.  KayPLUS does not make
>> any of those assumptions, especially since 90% of the CP/M computers are
>> Z80 and replacement operating systems (like QP/M or ZCPR) all exploit the
>> Z80 instruction set.
>> 
>> 

Not many people are writing Z80 operating systems today (although
interesting applications such as background reminder calendars
continue to appear).  However, I think some clarification of Mitch's
comments is desirable.

I (and others) have long argued strenuously for strict adherence to
the following systems-programming guideline:

				 ****
  SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
  UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
				 ****

This rule ensures that an application that uses Z80 opcodes can run on
any z80 system without having to save and restore any of those
registers before every BIOS and BDOS call.

Note that system code can indeed *use* the Z80 registers (the TurboRom,
BackGrounder ii, and ZSDOS, for example, do so extensively).  The code
must just push/pop or save/restore from memory any registers that it
needs to use.

A flagrant violations of this guideline is found in an early
version of the Osborne Executive rom, which used an index register
(probably IY) in a service interrupt routine.  Not even the smartest
application can safely use IY, since the interrupt is asynchronous,
and until a corrected rom was issued early owners were baffled to find
that some programs would simply not run correctly.

Another egregious case is the BIOS in the ON! computer, which uses af'
without preserving it.

This topic -- appropriate use of registers -- is part of the larger
subject I have called "environmental programming" and discussed at
greater length in a column in The Computer Journal.  Each programmer
needs to be aware of the computer environment in which his/her code
may be executing, and take appropriate steps to preserve that
environment.  Systems code has an especially heavy obligation to allow
applications to thrive; hence the abvove guideline.  But applications
also have responsibilities -- for example, to verify that the host has
the necessary resources (devices, type of BIOS, etc.) before executing
code that can crash or do damage on the wrong platform.

-- bridger

tilmann@cosmo.UUCP (Tilmann Reh) (12/02/90)

Hello world,

Bridger Mitchell writes:
> I (and others) have long argued strenuously for strict adherence to
> the following systems-programming guideline:
>
>				 ****
>   SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
>   UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
>				 ****
>
> This rule ensures that an application that uses Z80 opcodes can run on
> any z80 system without having to save and restore any of those
> registers before every BIOS and BDOS call.

That's a guideline I don't agree with.
Why should the system care about which registers the application program uses?
The responsibility for register contents is *only* at the application
program! So, before each and every system call it has to save those registers
it want's to use afterwards (assuming with unchanged contents). This also
reduces system overhead (thus increasing performance, though slightly) as
not every register that *might* be used has to be saved, but only those
that *are* used.
The above guideline opens the door to very improper application programming.
The only way to ensure that a program runs on *every* CP/M machine is to
save all registers which must stay valid prior to any system call. BTW, I
don't see why this should be so hard...

Of course, interrupt routines must also save all registers they use, as this
are asynchronous events.

When will programmers (system *and* application) finally understand that
everything should be programmed as portable and universal as possible ?

Tilmann Reh			tilmann@mcshh.uucp
				tilmann@mcshh.hanse.de

floyd@ims.alaska.edu (Floyd Davidson) (12/04/90)

In article <6209@balu.UUCP> tilmann@cosmo.UUCP (Tilmann Reh) writes:
>Bridger Mitchell writes:
>>   SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
>>   UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
>>				 ****
>>
>> This rule ensures that an application that uses Z80 opcodes can run on
>> any z80 system without having to save and restore any of those
>> registers before every BIOS and BDOS call.
>
>That's a guideline I don't agree with.
>Why should the system care about which registers the application program uses?
>The responsibility for register contents is *only* at the application
[...]
>
>When will programmers (system *and* application) finally understand that
>everything should be programmed as portable and universal as possible ?
>

You're last statement does not follow from the first.  For maximum
portability both should assume the other did it wrong.  Both
applications programmer and system programmer should protect the
registers.  I think the performance cost is small if a little
thought is given to register use.

Floyd


-- 
Floyd L. Davidson                             floyd@hayes.ims.alaska.edu
Salcha, AK 99714                    paycheck connection to Alascom, Inc.
 When I speak for them, one of us will be *out* of business in a hurry.

pl@news.funet.fi.tut.fi (Lehtinen Pertti) (12/04/90)

From article <6209@balu.UUCP>, by tilmann@cosmo.UUCP (Tilmann Reh):
> Hello world,
> 
> Bridger Mitchell writes:
>> I (and others) have long argued strenuously for strict adherence to
>> the following systems-programming guideline:
>>
>>				 ****
>>   SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
>>   UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
>>				 ****
>>
>> This rule ensures that an application that uses Z80 opcodes can run on
>> any z80 system without having to save and restore any of those
>> registers before every BIOS and BDOS call.
> 
> That's a guideline I don't agree with.
> Why should the system care about which registers the application program uses?

	The point is, that CP/M is specified to 8080 and first Z80 versions
	didn't use Z80-specific registers, so it appeared, that applications
	were free to use those registers without saving/restoring.

	Now, if new versions of CP/M take those registers in use, it
	could break old applications.

> The responsibility for register contents is *only* at the application
> program! So, before each and every system call it has to save those registers
> it want's to use afterwards (assuming with unchanged contents). This also
> reduces system overhead (thus increasing performance, though slightly) as
> not every register that *might* be used has to be saved, but only those
> that *are* used.

	System routine usually saves only those registers it really uses,
	so I don't really see, if it matters, who saves the registers,
	as long as it is clearly specified somewhere.
	
> The above guideline opens the door to very improper application programming.
> The only way to ensure that a program runs on *every* CP/M machine is to
> save all registers which must stay valid prior to any system call. BTW, I
> don't see why this should be so hard...
>
	Yes, this is sure way to do that. But what is needed, is clear
	specification, which registers should be preserved and which not,
	just as in every subroutine calling standard.

> Of course, interrupt routines must also save all registers they use, as this
> are asynchronous events.
> 
> When will programmers (system *and* application) finally understand that
> everything should be programmed as portable and universal as possible ?
>
	If system specification says which registers are to be preserved,
	it would be very easy.

	Up to that point there is always possibility to argue,
	who is brain damaged and who not.
>
> Tilmann Reh			tilmann@mcshh.uucp
> 				tilmann@mcshh.hanse.de
pl@tut.fi				! All opinions expressed above are
Pertti Lehtinen				! purely offending and in subject
Tampere University of Technology	! to change without any further
Software Systems Laboratory		! notice

tom@afthree.as.arizona.edu (Thomas J. Trebisky) (12/06/90)

>Bridger Mitchell writes:
>> I (and others) have long argued strenuously for strict adherence to
>> the following systems-programming guideline:
>>
>>				 ****
>>   SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
>>   UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
>>				 ****
>
> Tilmann Reh writes
>The above guideline opens the door to very improper application programming.
>The only way to ensure that a program runs on *every* CP/M machine is to
>save all registers which must stay valid prior to any system call. BTW, I
>don't see why this should be so hard...

Sorry to take exception with this. I don't think it is the applications
programmers responsibility to guard against all manner of stupidity on the
part of those writing systems code. Believe me, every modern OS puts the
burden of saving and restoring machine state on the OS -- on a Unix system
a system call is commonly implemented by a TRAP or INT, and the first thing
the OS will do is save all the registers and whatever else is involved with
the user context so it can restore it transparently.  As you point out there
is no possible way that user code can "guard against" what is done with
registers in interrupt routines since they are completely asynchronous.

The sad reality of things though is that you are right in a way,
due to the abundance of funky systems software in the CPM realm.
In the hey-day of CPM every Tom, Dick, and Harry was in a rush to port CPM
to this or that platform, and some of the work was poorly done.
This forces you and I to go to lengths we shouldn't have to, if we really
want "portability" to every sleaze-ball system.  However if the above 
guidelines for SYSTEMS code were followed, we would not have to do this.
Another case could be made perhaps for efficiency, the applications
programmer knows at any time exactly what he needs to save, whereas a
systems call handler must necessarily save everything to be general.
In the Z80 realm where every machine cycle is precious, this might have
merit, but I would rather save the code space (and my keystrokes :-) ).

tilmann@mcshh.hanse.de (Tilmann Reh) (12/09/90)

In article <1990Dec4.131328.15594@ims.alaska.edu>
  floyd@ims.alaska.edu (Floyd Davidson) writes:

> You're last statement does not follow from the first.  For maximum
> portability both should assume the other did it wrong.

Of course, that is the safest way. But then, system behaviour is very
well specified (see below). So I especially wanted to emphasize the
responsibility of the application programmers (not to blame it all on
the system programmers!).

In article <1990Dec4.134833.17783@funet.fi>
  pl@news.funet.fi.tut.fi (Lehtinen Pertti) writes:

>	The point is, that CP/M is specified to 8080 and first Z80 versions
>	didn't use Z80-specific registers, so it appeared, that applications
>	were free to use those registers without saving/restoring.

Sorry, but that's not logical. If one uses Z80 opcodes in an application, he
must be aware that at least the BIOS also uses these instructions.

>	System routine usually saves only those registers it really uses,
>	so I don't really see, if it matters, who saves the registers,
>	as long as it is clearly specified somewhere.
	
Of course, in fact it doesn't matter *who* saves. Just that the system may
save registers which aren't used by the application at all.
As for the spec's: see below.

>	Yes, this is sure way to do that. But what is needed, is clear
>	specification, which registers should be preserved and which not,
>	just as in every subroutine calling standard.
>	If system specification says which registers are to be preserved,
>	it would be very easy.

I wonder if anyone of you ever read the CP/M Programmers Guide. In this
(original DRI) document there is the clear specification. The CP/M-Plus
Programmers Guide (as I use CP/M-Plus) tells me on page 27:

	When a transient program makes a BDOS function call, the BDOS does
	not restore registers to their entry values before returning to the
	calling program. The responsiblity for saving and restoring any
	critical register values rests with the calling program.

So everyone who writes (or wants to write) applications programs should
please read the specifications before doing so.

Of course, that quotation doesn't mention Z80 registers. But if you think
logically and carefully look at the sentence, it is absolutely clear that
*every* register may be changed after returning from a system call.

BTW, even commercial programs may have bugs: In Turbo-Pascal 3.0, the IX
and IY registers aren't saved before calling the Console Input routine, but
used afterwards. So be careful. (every other Char I/O is ok!)

Tilmann Reh			tilmann@mcshh.uucp
				tilmann@mcshh.hanse.de

bandy@catnip.berkeley.ca.us (Gun Control is Hitting Your Target) (12/10/90)

I agree with Bridger, disagree with Tilmann and give my take on the
situation, plus official word from DRI.  

Bridger Mitchell writes:
>> I (and others) have long argued strenuously for strict adherence to
>> the following systems-programming guideline:
>>
>>				 ****
>>   SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
>>   UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
>>				 ****
>>
>> This rule ensures that an application that uses Z80 opcodes can run on
>> any z80 system without having to save and restore any of those
>> registers before every BIOS and BDOS call.

tilmann@cosmo.UUCP (Tilmann Reh) writes:
>That's a guideline I don't agree with.
>Why should the system care about which registers the application program uses?

Why?  "Because CP/M is an **8080** operating system - thus it may only use
8080 registers."  I got this reply back from Digital Research back in '80
when I asked them about the Z/80 registers.

>Of course, interrupt routines must also save all registers they use, as this
>are asynchronous events.

That's right, but the silly people who did the Osborne-1 roms didn't. 
Hence perfectly valid Z80 applications that ran on other folks' systems
would crash on the Osborne. 

>When will programmers (system *and* application) finally understand that
>everything should be programmed as portable and universal as possible ?

Exactly.

Yes, it would make an application even more bullet proof to have it save
all the Z80 registers [or don't use them :-)] before it called into
BDOS/BIOS, but folks who write BIOS software should preserve the Z80
registers to help maintain compatibility with "incorrect" software.
-- 
real address: bandy@catnip.berkeley.ca.us
last choice:  lll-winken!catnip.berkeley.ca.us!bandy

fzsitvay@techbook.com (Frank Zsitvay) (12/12/90)

In article <663@catnip.berkeley.ca.us> bandy@catnip.berkeley.ca.us (Gun Control is Hitting Your Target) writes:
>>> I (and others) have long argued strenuously for strict adherence to
>>> the following systems-programming guideline:
>>>
>>>				 ****
>>>   SYSTEM CODE (BIOS, BDOS, INTERRUPT-SERVICE ROUTINES, AND BACKGROUND
>>>   UTILITIES)  SHOULD *ALWAYS PRESERVE* THE NON-8080 REGISTERS.
>>>				 ****
>>>
>>> This rule ensures that an application that uses Z80 opcodes can run on
>>> any z80 system without having to save and restore any of those
>>> registers before every BIOS and BDOS call.

>>That's a guideline I don't agree with.
>>Why should the system care about which registers the application program uses?
>
>Why?  "Because CP/M is an **8080** operating system - thus it may only use
>8080 registers."  I got this reply back from Digital Research back in '80
>when I asked them about the Z/80 registers.

well, CP/M itself doesn't use the special registers, but the BIOS might,
since that was supplied from the manufacturer of the machine.  there is 
another problem, though, in that some z-80 BIOS' were written in such way
that the index registers of the z-80 as well as the alternate register
set were used as temporary storage between calls, and applications that
used these registers would bomb on machines that expected those values
to still be there.
 
CP/M itself (for BDOS calls) doesn't preserve any registers.  (which led to
programs being littered with  PUSH B! PUSH D! PUSH H and corresponding
pops after each BDOS call)  perhaps it would be best to assume the bios
doesn't save the special registers in the z-80.   but an unacceptable
situation is where the BIOS requires the application to not change the 
value of those registers.
 
sure, CP/M is an 8080 operating system, but since most CP/M machines still
working these days are Z-80 based, then perhaps it should be considered a
z-80 operating system.  writing applications to run under z-80 CP/M should
be free to use those registers, but not expect the operating system to
preserve the contents.  (exception - interrupt handlers.)
 
people who own machines with a BIOS that does store values in special z80
registers would probably have to hack their BIOS so that it doesn't.  those
writing programs that use special z80 registers should PUSH them before
a BDOS call and POP them after the call, assuming they need to save the 
contents of those registers.

-- 
fzsitvay@techbook.COM - but don't quote me on that....

American Oil Company motto - Bend over, We'll pump!!!