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 required˙in 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