Re: A89: Re: porting Z80 to 68k.....possible?? (yes, but not easy)
[Prev][Next][Index][Thread]
Re: A89: Re: porting Z80 to 68k.....possible?? (yes, but not easy)
I have only 3 points to make:
1) What about a routine like this to access data?
ld a,(level)
ld b,a
ld de,49 ;Size of a level
ld hl,levelSet+1-49 ;levelSet-48
lvlAddLoop:
add hl,de
djnz lvlAddLoop
49 is a odd number... and this is a program that will eventually be on
83s
2) What about people who write self-modifying code like this:
.db $FE; cp n
levelCountCheck .db 0
3) What about actual data that is accessed by (label+1)?
Patrick Davidson wrote:
>
> > Why is it crazy?? There are similar instructions on both processors,
> > the 68k has more registers so you don't have to worry about running
> > out, and the languages are pretty much the same (I've programmed in
> > both and they are very similar). I don't see any difficulties except
> > for the memory locations which would be easily switched between calcs.
> > I dunno, maybe I'm just stupid and I don't know anything about this,
> > but from my POV, it looks like a good idea.
>
> Actually, I have been working on this very problem myself; I am making
> a computer program to automatically convert TI-85 programs to run on
> the 68K calculators. I do think I have (more or less) solved most of
> the problems involved, but it's much more difficult than you seem to
> suggest. My program will only work from Z80 source code, and should do
> both ZShell and Usgard programs. Since it's just a simple translator,
> the output won't be as efficient as code written for the 68K, but since
> the 68K is a faster processor it should allow programs to run somewhere
> near the correct speed. Anyway, here's a list of the things the program
> needs to do:
>
> 1) Parse Z80 source code. Recognize instructions, directives,
> registers, etc. This part is straightforward.
>
> 2) Basic code translation. I'm only referring to the basic instructions
> here, and not memory access or control stuff which is addressed later.
> This means to take a Z80 instruction and write out a 68K equivalent.
> This is not as easy as you make it seem, as the registers are not that
> similar. The difficulty has to do with the fact that registers can be
> split and combined (e.g. B, C, and BC). Anyway, this is my plan for
> dealing with this:
>
> The register equivalencies will be this (there is a reason for these
> particular choices: D0 and D1 are scratch since library calls may
> change them, and the address registers are in D2 to D6 so they can be
> conveniently mirrored in A2 to A6, as is explained later).
>
> D7 = A
> D2 = BC
> D3 = DE
> D4 = HL
> D5 = IX
> D6 = IY
>
> In these registers, I do plan to keep them in big-endian order as is
> normal in the 68K, and will just reverse the order (with ror.w #8,dn)
> when storing them to memory.
>
> The 68K can deal with the low word and low byte of a register as
> seperate values, but not so with the second byte.
>
> For example, the one instruction
>
> ld c,a
>
> becomes the one instruction
>
> move.b d7,d2
>
> while the one instruction
>
> ld b,a
>
> must become multiple instructions, such as
>
> move.b d7,d0
> lsl.w #8,d0
> and.w #$ff,d2
> or.w d0,d2
>
> However, some special cases such as the instruction
>
> dec b
>
> can still work in one instruction
>
> sub.w #$100,d2
>
> I have considered some systems in which each component of a
> register would have its own 68K equivalent, in which case only
> word operations would need special tricks, but I decided not to do
> this in the first version of the translator (though I might make it
> an option later).
>
> Of course, alignment is also a problem as the 68K needs instructions
> on even addresses. This is not, however, a huge problem. As a
> temporary solution, I'll just write "EVEN" whenever there is a change
> from data to instructions. As far as loading words from memory, I'll
> simply load each byte a time to avoid trouble.
>
> 3) Memory access - Unfortunately, this is not simply a matter of
> finding equivalent addresses. Most addresses on the TI-85 have no
> equivalent on the 68K calcs (and the situation is much worse on the
> TI-86). The solution I have come up with is as follows:
>
> Z80 memory addresses Where they go
>
> $0000-$7FFF nowhere
> $8000-$8FFF Temporary 4K buffer
> $9000-$EFFF program's code
> $F000-$FFFF Temporary 4K buffer
>
> This memory arrangement allows all low memory variables to work,
> and also allows tricks with the stack. In addition, programs that
> allocate memory from the top of the VAT (e.g. grayscale buffers)
> could still work. Mapping another area to the program's code
> allows the program to reference data in itself (which is very
> common) and allows a possibilty to get self-modifying code to work.
> This does have the downside that any program which is larger than
> 24K when converted will fail.
>
> (If you're wondering, I did consider other memory systems before
> coming to conclude that this one is best. At first I thought I
> would just try to convert addresses, but realized that this couldn't
> work. The fact that addresses are different sizes, can be part of
> data structures, and can be "built" byte by byte (e.g. calculating
> H and L seperately, then combining to get a pixel address) and the
> fact that a value like $FFFF could easily used in calculations as
> -1 or the lower right corner of the LCD, or both, and other things
> led me to think against simple translations).
>
> I'd also need to do something with labels to get the fake addresses.
> I'd have to labels corresponding to each original; one that's its
> real 68K address (for program branches) and another that's the fake
> virtual address for other references.
>
> This virtual addressing isn't 100% perfect, so converted programs
> need to be extensively tested befor they are considered stable, even
> when the original is reliable. I'm of course trusting that programs
> won't try to write to the ROM.
>
> This also is a major performance drain, but I think that memory
> references are not used so much that this will be unacceptable. I
> have come up with several different methods of determining addresses
> that have somewhat different performance issues:
>
> a) Calculate-on-demand. Whenever you reference a memory address, the
> real address will be determined. This is more efficient if the
> program uses the address registers as data a lot, but will waste time
> when the same address is accessed repeatedly.
>
> b) Calculate-on-change. Whenever the address register is changed,
> you re-do the address conversion. The real addresses would be
> shadowed in address registers. If the register is simply incremented
> or decrementing, you only need to increment or decrement it instead
> of the whole recalculation. This is faster if the same address is
> used a lot, or the program steps through addresses.
>
> c) Validity flags. In this method, I'd have some sort of flag
> indicating which registers had valid shadows. When a register is
> changed, it's set to invalid. Then any memory access would check
> the flag, and if invalid, recalculate and set the flag.
>
> d) Some combination of the above, such as (b) for IX and IY which are
> almost always addresses, with (a) for the others which are often data.
>
> In the first release, I've decided to use method (a) though I may
> make the others options later, depending on how well it turns out to
> work.
>
> 4) "Emulation" library - ROM calls, display, ports
>
> These features would go together in an emulation library that the
> converted program uses.
>
> The display handling would be fairly simple: just an interrupt that
> copies data from the simulated memory area to the actual screen
> periodically.
>
> The port handler would most importantly handle keyboard reads.
> Other ports could mostly be ignored for most programs, though at
> some point the display address port could be activated to allow
> grayscale.
>
> The ROM call emulation is possibly the hardest. However, it is
> survivable. Since the converter has the program's source code it
> can easily identify ROM calls. The library would need to simulate
> their action. Some, like UNPACK_HL would be easy (and actually
> faster than on the original TI-85). The display routines would be
> more difficult; in addition to reading the coordinates from the
> virtual address space, you'd have to somehow put the letters back
> over the virtual screen area (I haven't thought about this in
> detail yet, but it shouldn't be too bad).
>
> The most important feature of the library, of course, would be to
> display a message warning the user that a converted program may be
> unstable before the program begins, allowing a safe exit for people
> who unknowingly run such a program.
>
> 5) Program flow control - For the most part, this one is actually
> easier than it seems. Conditional branches and stuff within the
> code are easily converted to 68K equivalents in most cases. A jump
> to a computed address could be dealt with by the normal memory
> handling system. For example, this jump table would work fine:
>
> ld a,(hl)
> add a,a
> ld e,a
> ld d,0
> ld hl,&address_table
> add hl,de
> call LD_HL_MHL
> ld de,(PROGRAM_ADDR)
> add hl,de
> jp (hl)
> address_table:
> .dw addr0
> .dw addr1
> .dw addr2
>
> Unfortunately, this one would fail miserably:
>
> ld a,(hl)
> ld l,a
> add a,a
> add a,l
> ld e,a
> ld d,0
> ld hl,&address_table
> add hl,de
> jp (hl)
> address_table:
> jp &addr0
> jp &addr1
> jp &addr2
>
> This is very bad, since something is multiplied by 3 to get an
> address, while instructions on the 68K can't be at odd addresses.
> Even if it could, it would still fail as the addresses aren't lined
> up properly. This would require the following *hideous kluge*
>
> - Jump table detector in the converter which notices any string of
> three or more jumps
> - Jump table list at the end of the code, which holds the addresses
> each jump table covers
> - A much uglier memory address handler for computed jumps: It would
> need to check the address you jump to against these tables, and do
> the appropriate conversion if its present. That is, if it's in
> the jump table's range, subtract the start address, divide by three,
> and then compute the real address with the offset value.
> - Even the "kinder, gentler" jump tables with JR instructions would
> still need this kluge, since the instructions might expand enough
> that the branches wouldn't fit in two bytes.
>
> As you may have guessed by now, I'm not going to put this capability
> in the first release of the converter, as it's a mess and not that
> useful.
>
> 6) Self-modifying code.
>
> Self-modifying code is common in Z80 programs, so it needs to be
> dealt with. This is actually, easier than it seems, as most of it
> is in the form of stuff like "ld (&label+1),a" which is simply used
> to change the constant data of an instruction. This can be detected
> by looking for writes to 1 beyond a code label. Then the converter
> simply needs to determine the real offset into the new code, and
> replace it.
>
> However, this is not the only self-modifying code that's ever been
> used, even though it's the most common. For example, in Z-Kart 3D,
> I change the an opcode between a RET and a NEG. Since this sort of
> thing is probably rare, I'll deal with it by implementing specific
> handling for each of the few cases of it I see. Of course, the
> first release will only do the standard stuff above.
>
> 7) The hard part. Once everything above has been done and tested,
> then I can release a "workable" version of the program. However,
> the above is only the easy part. Difficult stuff includes:
>
> - Interrupts/grayscale (actually, this one isn't too bad)
> - Variables
> - Dynamically constructed jump tables (Orzunoid uses this to help
> with external levels; the first converted release of Orzunoid
> will be from an older version of the game which doesn't do this)
> - Programs that throw code around (e.g. Z-Kart 3D which copies its
> code to the graph screen)
> - Dealing with multiple calculators: the TI-82 and TI-83 probably
> wouldn't be that hard to implement, but TI-86 is a real mess due to
> its memory swapping and such
> - And there's probably more stuff that's so horrible I can't even
> think of it...
--
Scott "_Wrath_" Dial
wrath@calc.org
ICQ#3608935
TimeCity AI Guy II - www.timecity.org
Member of TCPA - tcpa.calc.org
__________________________________________
NetZero - Defenders of the Free World
Get your FREE Internet Access and Email at
http://www.netzero.net/download/index.html
Follow-Ups:
References: