

Z80 Code Converter Documentation1


MC68000 Applications Group  - Motorola Semiconductor Products - Austin
 
             CNVZ80 -  Z80 SOURCE TO MC68000 SOURCE UTILITY
 
                   (C) COPYRIGHT 1982 BY MOTOROLA INC.
 
                     ***** VERSION 1.0  9/21/82*****
 
 
This describes the CNVZ80 utility which converts Z80 source code to MC68000
 
source code.  Additional information is given to assist customizing of the
 
package.
 
 
Version 1.0 is the first tested release of this product.  It has succesfully
 
translated a complete BASIC Z80 interpreter of over 4,000 lines of code.
 
The only areas left untested were the Z80 string instructions, since the
 
interpreter did not utilize instructions of this type.
 
 
Motorola does not assume any liability arising out of the application or use
 
use of this product.
 
 
 
 
                    WHAT THE CNVZ80 PROGRAM DOES
 
The CNVZ80 PASCAL program utility takes as input a file consisting of
 
Z80 source assembler language statements and produces an output file 

  containing MC68000 instructions representing the converted code.  This 
  
  output file is structured such that it directly assembles on a MC68000             
  assembler when preceeded by a special file (FRONTZ80.SA) containing run-time 
  
  support and a small initialization stub.  The input file must follow 

  Mostek conventions for statement syntax and directives, plus it must 
 
  be "clean" (i.e. must assemble on a native Z80 assembler or cross-assembler 

  without errors.)  The converter does not handle macros or more than the most 

  basic assembler directives.  This is because there is not a general 
consensus 

  on how to implement these on the various Z80 assemblers around, and thus 

  customizing will be requiredin most cases anyway.
 
 
Since there exists several assemblers for the Z80 it was necessary to choose
 
one implementation's directive statements for support.  A Mostek assembler
 
definition of psuedo-ops has been implemented.  Users must custom code any
 
difference or extensions to this basic set.  This utility is written in PASCAL
 
for easy customization.  The converter is written as two PASCAL programs, a
 
main PASCAL program and a separate subroutine section.  Standard PASCAL was
 
used except for the string extensions defined by Motorola PASCAL.  A later
 
section defines the Z80 assembly language syntax and directives processed
 
by the stock converter.
 
 
                   EFFECIENCY OF THE CONVERTED PROGRAM
 
Comparing a random sampling of forty-five Z80 statments with their converted
 
MC68000 counterparts resulted in the following statistics:
 
            The average bytes per Z80 instruction was 2.04
            The average bytes per MC68000 translation was 6.00
 
            The average cycle time per Z80 instruction was 11.22 cycles
            The average cycle time per MC68000 translation was 20.53 cycles
 
What this indicates is an almost exact ratio of 3 to 1 for program code size
 
and two to one for cycle time.  Thus, the standard 8 Mhz MC68000 will execute
 
a converted Z80 program with roughly the same performance as a 4 Mhz Z80
 
in about 3 times the memory space.
 
 
                       HOW TO USE THE CNVZ80 SYSTEM
 
  Step 1:  Execute the CNVZ80 command with the Z80 source input file and
           MC68000 source output file as parameters.  The output file will
           be either created or overwritten.
 
                   Example (VersaDOS):    =CNVZ80  INZ80,OUT68K
 
  Step 2:  If any diagnostics are given, the Z80 source may have to be
           carefully examined and treated for possible incompatibilities.
           A later section describes all possible diagnostics and suggests
           what action to take for each.  The first two steps are rerun until
           an acceptable conversion is obtained.
 
  Step 3:  Assemble the file FRONTZ80.SA with the output from the CNVZ80
           utility to produce the MC68000 program.  On Motorola's VERSAdos
           this is done as follows:
 
                Example:    =ASM  FRONTZ80/OUT68K,OUT68K,#PR
 
 
             SUPPORTED Z80 ASSEMBLER SYNTAX AND DIRECTIVES
 
The stock converter assumes Z80 assembler formats and directives as defined
 
by Mostek.  Statement labels must start in column one unless followed by a
 
colon.  No macro support is provided.  All lower-case characters are converted
 
to upper case (except within string constants.)  The logical operators
 
supported are .AND. and .OR..  Constant numbers are defined by a trailing
 
base identifier as follows:
 
                    D or nothing    -   Decimal
                    O or Q          -   Octal
                    B               -   Binary
                    H               -   Hexadecimal
 
The Mostek assembler directives supported by the converter are as follows:
 
  DEFB   exp(,exp...)          Define byte memory
  DEFW   exp(,exp...)          Define reversed word memory (LSByte first)
  DEFM   'string...'           Define message character string
  DEFS   exp                   Reserve bytes of memory storage
  DEFL   exp                   Define resetable symbol (label required)
  EJECT                        Force page eject
  END    (exp)                 END with optional start address
  EQU                          Equate non-resetable symbol (label required)
  ORG    exp                   Program counter forced placement
 
 
 
               CONVERSION THOROUGHNESS AND INCOMPATIBILITES
 
In some cases there are major differences between the execution of a Z80
 
instruction and the same instruction on the MC68000.  For example, Z80
 
load instructions do not set the condition code whereas the MC68000 move
 
instruction does for most instances.  The CNVZ80 utility handles this
 
 incompatibility by actually carrying a simulated copy of the Z80 flag 
register.
 
The net effect is that the final execution remains identical.
 
 
Most incompatibilites are properly and completely handled by the CNVZ80
 
utility.  Even the "reversed byte" syndrome of the Z80 architecture where
 
word data is stored least significant byte first is acknowledged by the
 
converter.  However, there are a few things that are not practical or 
important
 
enough to warrant complete conversion.  These are explained now in detail.
 
  1) The P/V bit in the Z80 flag byte indicates the parity of 8-bit results
     after certain boolean operations.  This flag is not simulated.  However,
     there is a small subroutine in the run-time front end module FRONTZ80
     which accepts an 8-bit value in register D2 and properly sets the
     Z80 P/V bit to indicate the proper parity.  If parity is desired a
     simple statement can be added to call this routine.
 
  2) Interrupt enter and exit code along with the enabling and disabling of
     interrupts will most likely need some modifications due to differences
     in the hardware specifications of the two processors.  For example,
     it may be desirable to run the converted program in user state only
     which would invalidate any privilidged instructions such as the changing
     of interrupt status via the Z80 DI or EI instructions.  All Z80 I/O
     instructions must be changed for the same reasons.
 
  3) Whenever the Z80 flag is transfered to or from memory via POP and PUSH
     instructions it remains in MC68000 condition code format.  This causes
    problems only when programs examine or alter the flag byte in memory. Such
    code should be manually changed.  A simple subroutine could be provided to
    to convert from one format to the other to solve this problem if it occurs
     excessively.  A warning message is given whenever the Z80 flag byte
     is stored in memory.
 
  4) The Z80 DAA instruction (decimal adjust) is not simulated.  Since the
     MC68000 has complete decimal arithmetic capability built-in, these
     code sequences should be recoded.  Just such an example is given later
     in this document.
 
 
 
                 CODE SEQUENCES WHICH REQUIRE SPECIAL CARE
 
Even though most instructions translate properly on a one for one
 
basis the "meaning behind" the instructions may not come through.  This occurs
 
only rarely and is usually tied into the fact that a programmer has made use
 
of a special artifact of the microprocessor architecture.
 
For example, Z80 instructions carry 16-bit immediate values
 
least-significant byte first.  An instruction which loads an immediate
 
value into a register will convert to the standard MC68000 MOVE instruction
 
which will not have the bytes "reversed".  Normally this is perfectly
 
acceptable.  However, if a Z80 programmer points a register at such an
 
embedded swapped immediate residing in an instruction and loads it, this is
 
an error because the execution assumes a reversed word at such a location.
 
(Remember that the converter DOES know about swapped bytes but generates
 
immediate data in standard Motorola format since it is assumed that
 
only the instruction which contains the immediate field will use it.)
 
There is a similar problem related to a program counter reference.  If a
 
Z80 program references the program counter ($) then that reference will
 
be in error if it depends on any Z80 architectural features such as the
 
length of an instruction.  The converter will flag all suspect usage of the
 
program counter.
 
 
Since the Z80 architecture assumes 16-bit data constants (DEFW) to be in
 
reverse order, the CNVZ80 utility generates a paired byte DC with
 
the bytes reversed.  The Motorola EXORmacs assembler properly accepts such
 
expressions produced unless the item contains an external reference.
 
 
 
                             MEMORY LAYOUT
 
As described earlier, there is an auxilliary module FRONTZ80.SA which is
 
combined during the assembly process with the converted code.  This module
 
obtains initial control to establish the Z80 simluation environment and then
 
branches to the label found on the converted END statement directive, or
 
if no label was found branches to the first converted Z80 statement.  The
 
FRONTZ80 code and the converted program should reside in the lower 32K or
 
upper 32K of the MC68000's memory map for proper execution.
 
 
One minor problem concerns the location of the resulting code.  Due to the
 
fact that the MC68000 sign-extends addresses it must be insured that no
 
code or data structure lays directly across the 32K address boundary ($7FFF to
 
$8000)  Note that this will never occur unless the converted program is larger
 
than 32K bytes or has ORG statements forcing a portion of its location.
 
This can usually be rectified by examining the resultant linkage editor
 
memory map and including linkage editor control statements to force such
 
an offending code or data segment to start immediately above the boundary
 
(or elsewhere.)  At worst an ORG statement may have to be placed in the
 
assembly.
 
 
                      MAKING SOURCE CODE ADJUSTMENTS
 
Some Z80 instructions or assembler directives lead to warning or error
 
diagnostics.  Warnings require that the Z80 source be checked for possible
 
incompatabilities.  Errors indicate that a statement or directive cannot be
 
converted and therefore must be handled by overt code changes.  Code changes
 
may be done in one of two ways: 1) altering the original Z80 source and
 
re-running the CNVZ80 utility, or 2) altering the converted source.  The
 
first alternative above is by far the best procedure since the second
 
requires that if a re-translation is ever done the complete set of
 
changes would have to be re-applied again on the newly converted source.
 
 
If desired, MC68000 instructions may be mixed with the Z80 instructions
 
by framing the inserted statements with  **PASS and **PASSOFF statements.
 
The CNVZ80 utility automatically passes statements sandwiched between
 
these without translation.  See the section on runtime environment
 
below for guidelines on register usage and other conventions.
 
 
As an example, take the DAA Z80 instruction which will not translate.
 
The following Z80 loop and its MC68000 replacement is shown:
 
         Z80 SOURCE                       MC6800 SOURCE REPLACEMENT
 
         LD     IX,TOTAL+1                **PASS
         LD     HL,RESULT+1               LEA    TOTAL+2,A3
         LD     A,(HL)                    LEA    RESULT+2,A4
         ADD    A,(IX+0)                  MOVE.W #0,CCR       (CLEAR X BIT)
         DAA                              ABCD.B -(A3),-(A4)
         LD     (HL),A                    ABCD.B -(A3),-(A4)
         DEC    HL                        **PASSOFF
         LD     A,(HL)
         ADC    A,(IX+-1)
         DAA
         LD     (HL),A
 
 
 
                   THE CONVERTED Z80 RUNTIME ENVIRONMENT
 
To properly simulate Z80 instruction execution several conventions
 
are followed by the converted code and the runtime subroutines included
 
in FRONTZ80.SA.  Any MC68000 code added by the user must follow these
 
same conventions.  Dedicated register usage is as follows:
 
         D0   - Z80 A register and A' register
         D1   - Z80 flag register and flag' register
         D4   - constant $0F (condition code X bit mask)
         D5   - constant $10 (condition code X bit mask)
         D6   - IX
         D7   - IY
         A1   - pointer to B and BC on stack
         A2   - pointer to C on stack
         A3   - pointer to D and DE on stack
         A4   - pointer to E on stack
         A5   - pointer to L on stack
         A6   - Z80 SP register
         A7   - pointer to H and HL on stack
 
The contents of the registers B, C, D, E, H and L reside in memory (actually
 
the MC68000's stack) and are each pointed to by an address register.  The
 
so-called prime (') registers are stored in a special area in the FRONTZ80
 
front-end assembly module except for the A' and flag' registers which are
 
stored in the upper half of the MC68000 registers used for their simulation.
 
Registers D2, D3 and A0 are used at any time as scratch registers.  The
 
current version of CNVZ80 never depends on the value of a scratch register
 
left from the conversion of one Z80 instruction to the next
 
(i.e. no intrastatement optimization is done.)   Due to the sign extending
 
nature of MC68000 address registers there is a restriction that any addressed
 
object should not extend across the 32K midpoint in the address map (i.e. from
 
$7FFF to $8000.)  This can be guaranteed via use of linkage editor control
 
statements or by the insertion of an ORG statement in the offending code or
 
before the offending data structure.
 
 
The Z80 flag register is actually kept in the MC68000 condition code image
 
in register D1.  Only the P/V, Z, C and S Z80 flag bits are simulated.
 
These are associated with the MC68000 V, Z, X and M condition code bits
 
respectively.  Note that the Z80 flag bits H and N are used only by the
 
DAA instruction which is not directly supported by the conversion program
 
and therefore these flags are not supported either.
 
 
The Z80 stack is simulated by using A6 as the stack pointer.
 
If the user adds MC68000 code it must
 
be remembered that the Z80 stack is not based on the system stack pointer
 
(A7 or SP).  The true system stack is size limited and normally used only
 
for internal calls to the run-time support subroutines.  The code in
 
FRONTZ80.SA contains the run-time system and default user stacks with 30
 
bytes allocated to each.  This may be changed for customization.  Remember
 
that most Z80 programs will setup their own stack area
 
and therefore the default psuedo stack provided will never be used.
 
 
 
 
 
             DIAGNOSTIC MESSAGES AND THEIR REQUIRED RESPONSE
 
When CNVZ80 runs it may produce errors and warnings giving both the input
 
text line and output text line count.  Errors will also cause the insertion
 
of an added assembler statement consisting of the text of the error and which
 
will force an assembler diagnostic when assembly reaches that point.  Warnings
 
require investigation to insure that possible incapatabilities are not
 
produced.  Errors absolutely require that the source code be amended since
 
a condition or opcode has been found which cannot be directly converted.
 
As explained earlier, new Z80 and/or MC68000 code may be inserted at these
 
positions.  Here are all the possible diagnostics and explanations:
 
 
WARNING - P/V branch test unsupported if for parity
         The parity flag setting for boolean functions is not overtly
         handled during conversions.  If parity checking is desired
         a run-time subroutine can be called to set the Z80 parity flag
         as explained in documentation above.
 
WARNING - HALT simulated with STOP instruction
         The translation simulates a Z80 HALT with the MC68000 STOP.  However,
         the stop instruction is privilidged and assumes that a level seven
         is entered.
 
WARNING - FLAG stored in MC68000 condition code format
WARNING - FLAG read in MC68000 condition code format
         Converted programs assume the Z80 flag in MC68000 condition code
         format.  If the flag is manipulated in memory other than to merely
         restore the byte as a flag then code must be hand altered.
 
WARNING - ORG encountered
         Any ORG statement is passed as is, however, this may indicate
         a specific hardware address or a forced location of code which
         could be incompatible with the size of the converted program.
 
WARNING - Label may need word alignment
         A label only statement has been translated.  If the next converted
         code is an instruction, then there is a possibility of an odd byte
         alignment being generated.
 
ERROR - RETI/RETN interrupt returns need checking
        The Z80 architecture requires these instructions to terminate
        an interrupt sequence at a device.  Interrupt handling may
        require alterations for running in a MC68000 environment.
 
ERROR - '$' location counter use may be invalid
         The reference of the Z80 location counter may result in incorrect
         conversions if Z80 architectural dependences are relied upon.
 
ERROR - fixed address untranslatable
         The Z80 source code has an END directive with a constant number
         for the initial program execution start value.  This is probably
         in error.  An instruction label or empty field only is proper here.
 
ERROR - EI/DI interrupts require rewrite
         Interrupt processing probably requires some rewrite due to the nature
         of the differences between the Z80 and MC68000 architectures.
 
ERROR - IM - set interrupt mode not convertable
         The IM instruction has no counterpart in the MC68000 architecture.
 
ERROR - IN instruction unconvertable
         I/O instructions are handled differently with MC68000 architecture.
 
ERROR - IND/INDR/INI/INIR I/O untranslatable
         I/O instructions are handled differently with MC68000 architecture.
 
ERROR - absolute branch displacements untranslatable
         The Z80 assemblers force the programmer to subtract the program
         counter to generate a relative branch.  This subtraction has not
         been detected and probably indicates that an absolute branch
         displacement has been used.  This most likely will not convert
         properly if any Z80 architecture artifacts are used.
 
ERROR - OUT I/O untranslatable
         I/O instructions are handled differently with MC68000 architecture.
 
ERROR - OUTD/OTDR/OUTI/OTIR I/O untranslatable
         I/O instructions are handled differently with MC68000 architecture.
 
ERROR - RST restart untranslatable
         Since the Z80 RST is used for operating system calls or hardware I/O
         dependent operations this statement is flagged as needing 
translating.
 
ERROR - this statement unidentified
         This statement does not match any known by the converter utility and
         thus it cannot be translated.
 
ERROR - DAA instruction untranslatable
         Since the half-carry condition code bit is not simulated and the
         MC68000 has built-in BCD arithmetic this instruction is not
         translated.  The BCD algorithm should be rewritten to use the
         native MC68000 BCD operations.  Follow the conventions for
         register usage detailed elsewhere in this document.  An example
         of a BCD conversion is also given.
 
 
                     BUILDING THE CNVZ80 UTILITY
 
The CNVZ80 utility consists of a main Pascal program segment and a subroutine
 
Pascal program segment.  Diagnostic messages are placed both in the resultant
 
converted output file and the standard output file.  The following steps
 
for program compilation and linking are given for the Motorola EXORmacs system
 
and will build the CNVZ80 utility:
 
                     =PASCAL   CNVZ80
                     =PASCAL2  CNVZ80
                     =PASCAL   CNVZ80B
                     =PASCAL2  CNVZ80B
                     =LINK     CNVZ80/CNVZ80B
 
The result of the above processes will be the file CNVZ80.LO which is the
 
CNVZ80 command utility.
 
 
 
                             END OF DOCUMENT
