• Please review our updated Terms and Rules here

Turbo pascal...can it be set up to compile into 8080?

Twospruces

Veteran Member
Joined
Dec 9, 2009
Messages
779
Location
Canada
Long shot, but I am wondering if, since a z80 can run 8080 code...is there a way to use turbo pascal on z80 and have it compile to 8080?

Not really cross compiling. Just ignore those extra codes.. ;)

I suppose I could use that earlier post for that Russian simulator with a pascal compiler.
 
Unfortunately not. TP has needed a Z-80 going right back to V1.0 and has no setting to compile to 8080.
There have been various attempts over the years to patch it, but I don't think any of these were successful.
 
Yah ok. I didnt see anything I the manual to suggest it could.

So, I'll use that Russian emulator and pascal compiler.
 
The manual is interesting and the adverts even more so because I don't think it makes it clear that it won't work on an 8080. I wonder how many people bought it only to be disappointed that it wouldn't work on their system.
 
Many moons ago, I bought all three flavors of Turbo Pascal version 3, CP/M-80, CP/M-86 and PC-DOS. Not only did the CP/M-80 version need a Z80 to run, but the programs it generated also required a Z80, leaving out the many systems based on the 8080 or 8085.

I took brief a look at trying to modify it to generate 8080 code, but that effort did not get very far as more of my time was being spent learning to program for the IBM PC.

Recent discussions about simulating an 8080 brought up the incompatibility between Turbo Pascal and the 8080.

I believe that modifying the compiler to directly generate 8080 code to be too difficult. Modifying it to run on an 8080 is out of the question. But much of the same result may be achieved by translating the compiled code to the 8080, then stitching it to a run-time library rewritten for the 8080.

I am happy to be able to report that the prototype for converting the Z80 code produced by the CP/M Turbo Pascal compiler to 8080 code is going well. So far, no Z80 instructions have been encountered. Unfortunately, the same cannot be said for the subroutine library; it makes extensive use of the index and alternate registers as well as instructions like subtract with carry of register pairs.

The original Pascal code:
Code:
  procedure Greet;

    begin
      writeln('Hello world.')
    end;  { Greet }

  begin
    Greet
  end.

The Z80 code generated by the compiler:
Code:
0100 C3E320      jp      20E3
Command? u20e3l23
20E3 310001      ld      SP,0100
20E6 21C2EC      ld      HL,ECC2
20E9 0100FF      ld      BC,FF00
20EC CD6503      call    0365
20EF 212021      ld      HL,2120
20F2 11D0EA      ld      DE,EAD0
20F5 0142ED      ld      BC,ED42
20F8 3E01        ld      A,01
20FA CDD504      call    04D5
20FD C31A21      jp      211A
2100 CD9C14      call    149C
2103 CDBB17      call    17BB
Command? d2106ld
2100                    0C 48-65 6C 6C 6F 20 77 6F 72  '      .Hello wor'
2110  6C 64 2E                                         'ld.             '
Command? u2113
2113 CDCE17      call    17CE
2116 CD1C20      call    201C
2119 C9          ret
211A CD0021      call    2100
211D C3D520      jp      20D5

The 8080 code generated by the recompiler:
Code:
        org     100h

        jmp     L_20E3

        org     20E3h

L_20E3:
        lxi     SP,0100h
        lxi     H,0ECC2h
        lxi     B,0FF00h
        call    R_0365
        lxi     H,2120h
        lxi     D,0EAD0h
        lxi     B,0ED42h
        mvi     A,01h
        call    R_04D5
        jmp     L_211A
L_2100:
        call    R_149C
        call    R_17BB
        db      12,'Hello world.'
        call    R_17CE
        call    R_201C
        ret
L_211A:
        call    L_2100
        jmp     R_20D5

        end     100h
 
Looking at your sample, the compiler generated no Z80-specific code, even though there was opportunity to do so. It simply used the Z80 mnemonics for what is essentially 8080 code.

So, I'm not sure if you're just talking about changing the mnemonics and the syntax, which is a very different matter than converting Z80-specific code.

For example, the JP at 20FD could have been a JR.

So, as you say, "no z80-specific instructions were generated'. After compilation and assembly, what does it matter what syntax was used for the assembly code?
 
That's not what he's showing here.

He's showing a z80 disassembly of what the compiler created, and how he converted that in to 8080 assembly.

The salient points being that so far, apparently the TP compiler does NOT use Z80 codes for the actual compiled code, but only within the actual runtime.

The best route to take, probably, would be to convert the TP runtime library in to 8080 code, and have the converter have a map of the entry points points (for example 0365 and 04D5, one of those is the "writeln" routine). Convert those entry points in to labels, then let the linker sort them out.

The problem there is to make sure that the runtime library "fits" within the space for the compiled code.

For example the initial JP 20E3, that's jumping over the bundled runtime library. TP just bulk copies its entire runtime in to the executable, and sticks the code at the end. Converting the runtime library to Z80 that's not dependent on the actual memory locations, rather just "labels" that can be anywhere, will be laborious, but it's possible.

Then, as shown, instead of memory location 20E3, it's L_20E3 which can be anywhere, and let the linker sort it all out in the end.

Done right, this can reduce the size of TP executables by eliminating chunks of the runtime that are unnecessary for the program.
 
As an old compiler writer, I don't quite understand. Is this just a discussion of assembly language syntax and not of the actual machine code? I've written compilers where one of the output options was a symbolic assembly output, but the compiler generated it for documentation, not for actual use.
 
The original premise (afaict) is to discern if and how to get TP to compile 8080 code instead of Z80 code.

Based on what we seen so far presented, TP already compiles to 8080 code, but the runtime is Z80 dependent.

One potential way to port a Z80 compiled TP program is to decompile it in to 8080 mnemonics, then reassemble it and link it with an 8080 version of the runtime.

This solves a lot of issues with the absolute addresses that are compiled in to the resulting executable that tie directly to internal (Z80) runtime routines.

Another solution is to try and patch the Z80 runtime to an 8080 version, maintain all of the entry points, and the library size, and shove all of the hacks and patches to high memory where the heap normally starts. Then there's no reassembly step, just a swapping of the internal runtime.
 
It seems like I've seen the source around the web somewhere for TP3. Someone could translate it to 8080, but I would think it would be a lot of work.
 
It turns out that the line

Code:
20EF 211921      ld      HL,2119

actually points HL just past the last instruction in the program, I am guessing to initialize the heap, so the generated code is now this:

Code:
        org     100h

        jmp     L_20E3

        org     20E3h

L_20E3:
        lxi     SP,0100h
        lxi     H,0ECC2h
        lxi     B,0FF00h
        call    R_0365
        lxi     H,L_End
        lxi     D,0EAD8h
        lxi     B,0ED42h
        mvi     A,01h
        call    R_04D5
        call    R_149C
        call    R_17BB
        db      12,'Hello world.'
        call    R_17CE
        call    R_201C
        jmp     R_20D5
L_End:

        end     100h
 
As an old compiler writer, I don't quite understand. Is this just a discussion of assembly language syntax and not of the actual machine code? I've written compilers where one of the output options was a symbolic assembly output, but the compiler generated it for documentation, not for actual use.

What you are seeing is the foundation being built. The first steps include building the ability to scan a Z80 binary, writing 8080 code from it in increasing address order and handling special cases such as subroutines and inline string data. I read a .COM program and produce an 8080 assembly language source file. The current intent for the initial version is to be able to build an equivalent 8080 compatible program from the Z80 version using only the tools bundled with CP/M or provided by me.
 
The salient points being that so far, apparently the TP compiler does NOT use Z80 codes for the actual compiled code, but only within the actual runtime.

If only life remained that easy...

Now we see our first Z80 instruction.

Code:
  begin
    I1 := I1 - I2
  end.

Code:
20FD 2AB2EC      ld      HL,(ECB2)
2100 E5          push    HL
2101 2AB0EC      ld      HL,(ECB0)
2104 D1          pop     DE
2105 EB          ex      DE,HL
2106 B7          or      A
2107 ED52        sbc     HL,DE
2109 22B2EC      ld      (ECB2),HL

Code:
        lhld    D_ECB2
        push    H
        lhld    D_ECB0
        pop     D
        xchg
        ora     A
        mov     A,L
        sbb     E
        mov     L,A
        mov     A,H
        sbb     D
        mov     H,A
        shld    D_ECB2
 
This one came pessimized...

Code:
  begin
    I1 := I1 and 1
  end.

Code:
20FD 2AB2EC      ld      HL,(ECB2)
2100 E5          push    HL
2101 210100      ld      HL,0001
2104 D1          pop     DE
2105 7C          ld      A,H
2106 A2          and     D
2107 67          ld      H,A
2108 7D          ld      A,L
2109 A3          and     E
210A 6F          ld      L,A
210B 22B2EC      ld      (ECB2),HL
 
And finally, I have to struggle to resist the urge to try to optimize something like this:

Code:
  begin
    B1 := B1 - 1
  end.

Code:
20FD 2AB7EC      ld      HL,(ECB7)
2100 2600        ld      H,00
2102 E5          push    HL
2103 210100      ld      HL,0001
2106 D1          pop     DE
2107 EB          ex      DE,HL
2108 B7          or      A
2109 ED52        sbc     HL,DE
210B 7D          ld      A,L
210C 32B7EC      ld      (ECB7),A
 
I wonder if this is where the Russian 8080 Pascal compiler would come in handy.
We might be able to grab a bunch of library functions from that, and use that as a starting point.

If in fact the main compiler is truly ignoring Z80 opcodes.
 
I wonder if this is where the Russian 8080 Pascal compiler would come in handy.
We might be able to grab a bunch of library functions from that, and use that as a starting point.

Without knowing whether it was designed to be compatible with Turbo Pascal, verifying its functionality is a chore in itself.

Converting the Turbo library entails rewriting those portions which use Z80 instructions. Most of the time, it is simply substituting a few 8080 instructions for a Z80 one.
 
Most of the time, it is simply substituting a few 8080 instructions for a Z80 one.

Well, can't this just be done mechanically? As sort of demonstrated with the early disassemblies?

That is, "simply(tm)" disassemble in to Z80 code, convert the direct Z80->8080 codes in to 8080 mnemonics, and Z80 codes in to macros. Replace all direct memory references with labels so to adjust to the changes due to macro expansion.

Perhaps reserve a few key memory locations as work areas (such as for the alternate register swap), and detect if any of the actual code conflicts with these spaces.

Dunno, seems like it would work.
 
Many common assemblers of the day, such as M80, could switch assembly syntax, so I'm still wondering what this is about. If you're any kind of x80 assembly programmer, you should be able to switch between the two (Z80, 8080) without even thinking.
 
Back
Top