6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 1:31 pm

All times are UTC




Post new topic Reply to topic  [ 62 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
PostPosted: Tue Mar 30, 2021 9:19 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
Nice. If you'd like to share, I would be interested.
I would like to add it to my collection of languages.

So far have Applesoft Basic, Integer Basic, Forth, Pascal, Logo, 9 advanced basics, 8 compilers and Aztec C, all working under Prodos on the Apple II.

Would like to add MSBasic to that list and try to port over Cobol, Fortran and Turbo Pascal as well. And even try to emulate the TRS80.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 30, 2021 12:49 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BigEd wrote:
Great progress!

Thanks.

That was the easy part though.

When I start an emulator project, the infrastructure is built first. That includes the memory layout, the loading of a binary image, memory examine and change, virtual processor register examine and change, code disassembly.

I wrote one a couple of years ago to run 6800 FLEX programs on a 6809 FLEX system. Some of that code was reused for the 6800 version of the 8080 one. Part of the 6502 code came from a debugger/monitor I have been working on.

Only then do I start implementing machine instructions. Instead of coding up everything and having a monstrous pile of code to debug, I start with a bare execution engine in which every instruction is invalid. Then implement an instruction at a time as I try to run code.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 30, 2021 1:12 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
IamRob wrote:
Nice. If you'd like to share, I would be interested.
I would like to add it to my collection of languages.

So far have Applesoft Basic, Integer Basic, Forth, Pascal, Logo, 9 advanced basics, 8 compilers and Aztec C, all working under Prodos on the Apple II.

Would like to add MSBasic to that list and try to port over Cobol, Fortran and Turbo Pascal as well. And even try to emulate the TRS80.


ProDOS, huh? I have looked at it but have not done much with it other than a little bit of using a IIGS.

I will admit to considering the Apple II as a possible platform to run my FLEX operating system for the 6502. Besides Corsham, it and the OSI line are the best candidates despite both having physical disk hardware totally incompatible with a majority of existing FLEX machines. Atari I/O is very complex and too many memory locations are reserved on the C64.

The biggest problem with Fortran and Cobol is going to be the amount of memory they require. I do not know how much at this time. CP/M is well known for allowing for quite a large memory environment for its programs. There is also a PL/I compiler for CP/M and knowing Digital Research, it will not require a full boat system.

Turbo Pascal is around 30K, but worse, it requires a Z80 processor for both the compiler and the programs it generates. I found that out the hard way when trying to produce something for a CP/M users group many moons ago.

MBASIC weighs in at just under 24K and that is pretty tight within both of these emulators as I have them configured today. Versions for the 6809 and 6502 have some room to grow. The 6800 one is essentially maxed out because the I/O space is right in the middle of the address space at $8000.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 04, 2021 5:41 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
IamRob wrote:
Would like to add MSBasic to that list and try to port over Cobol, Fortran and Turbo Pascal as well. And even try to emulate the TRS80.


Your post made me decide to implement Z80 instructions as needed to try to get Turbo Pascal to run.

A long time ago, I wanted to modify Turbo Pascal to generate 8080-compatible programs. That effort did not get very far. Borland's code is very tricky and reverse engineering it is not easy.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 04, 2021 6:16 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
The emulator, specifically the 6800 version, now has limited disk support when built to run as a FLEX program.

It can now load and run the CP/M DUMP utility:
Quote:
3.run8080 2.dump c:hello.hex

FLEX uses numbers to identify disk drives. My emulated system has four. Drive 0 corresponds to drive A:, 1 to B:, 2 to C: and 3 to D:.

In this example, the emulator resides on drive 3; the DUMP utility and HELLO.HEX reside on drive 2.

The command line following the name of the CP/M program honors CP/M syntax; everything before that is in FLEX lingo.

The one gotcha is that the FLEX command interpreter allows more than one command to be typed on one line. The "end of line" character denotes where a command ends and the next begins. By default, the EOL character is a colon; it can be changed using the TTYSET utility. If the EOL character is a colon, the emulator treats the rest of the command line as one; in other words, if the EOL character is a colon, the multiple command feature is disabled for the rest of the line.

The emulator can also run the DDT debugger; I have not tried every command, but I can enter a simple "Hello world." program in assembly language and trace through it.

It also loads and runs the MBASIC interpreter. I can enter and run simple programs; only a small subset of the language has been tried so far. There remains a problem loading a BASIC program from disk.

Performance is not fast, but not as bad as I was fearing except for a few isolated spots.

Other issues:

* CP/M file names are 8.3 format, uncoincidentally very similar to DOS. FLEX names are also 8.3, but more restrictive as to what characters are accepted.

* CP/M text files use CR/LF to separate lines. FLEX uses a lone CR.

* CP/M text files may contain hard TAB characters; FLEX uses the TAB character as part of its space compression method so that text files must use spaces.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 05, 2021 3:29 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
I seem to recall there being a DOS 3.3 program on the Apple II that can load text files directly from a CPM disk. For the most part then, the 6502 code is already out there for reading cpm directories and loading files.

But there are two different ways to describe CPM. CPM code vs CPM disk information.

I think saying CPM textfiles would be like saying 6502 text files, would it not?


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 05, 2021 3:43 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
Well, that's a day I will not get back...

The journey to getting Turbo Pascal working has begun.

Since programs compiled with Turbo Pascal use the same run-time library code as the compiler itself, the best place to start is writing a simple "Hello world" program and getting that running.

There were only a few Z80 specific instructions encountered, but the program quit with a not enough memory error message. What? My emulated environment provides around 28K for the TPA. After some disassembly of the startup code, a test for the amount of memory surfaced. The program was expecting something like 59K in the TPA. Huh? How can that be? Most CP/M 2.2 systems do not have that much!

The problem turned out to be the brain-damaged way in which Turbo Pascal handles memory. The compiler offers two memory size options: start address and end address.

The start address sets the location where the compiler starts putting the code it generates for the program. The stated purpose is to allow setting aside some memory between the end of the run-time library code and the base of the generated program. The manual suggests using this to reserve memory to be shared with chained programs. Fair enough. I see that feature useful to have a place to put configuration data which an external program can easily locate.

"The End address specifies the highest address available to the program," says the manual. The next paragraph suggests setting this value "relatively low" if it is anticipated that the program will be "run on a range of different computers." But it never explicitly states that the end address is also the minimum acceptable.

I am using the 22NICE emulator to run the compiler. Because it does not actually boot and run CP/M, 22NICE provides an unnaturally large TPA. Which causes the default value for the end address to also be unreasonably high.

A better way of doing this would be for the end address to set an absolute limit which will not be crossed. Separate stack and minimum heap sizes determine the minimum memory needed to run the program. I guess that Borland did not expect the compiler will be used very much for generating software to be distributed to the community at large. I stopped using the CP/M version of the compiler for distributables after discovering that the programs it generated required a Z80 processor.

Anyway, the hello program now runs. Getting the compiler and its only slightly smaller installation program to work will not happen with the 6800 version of the emulator as it does not provide a large enough TPA. The quickest way there is probably to reassemble it for the 6809 where more memory is available.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 05, 2021 3:50 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
IamRob wrote:
I seem to recall there being a DOS 3.3 program on the Apple II that can load text files directly from a CPM disk. For the most part then, the 6502 code is already out there for reading cpm directories and loading files.

What are the Apple II conventions for text files?

I know the Mac uses a single carriage return character to terminate a line like FLEX does. It must go back to a Motorola standard predating the two.

Are hard TAB characters allowed?


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 05, 2021 4:32 pm 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
BillG wrote:
IamRob wrote:
I seem to recall there being a DOS 3.3 program on the Apple II that can load text files directly from a CPM disk. For the most part then, the 6502 code is already out there for reading cpm directories and loading files.

What are the Apple II conventions for text files?

I know the Mac uses a single carriage return character to terminate a line like FLEX does. It must go back to a Motorola standard predating the two.

Are hard TAB characters allowed?

For the most part, the Apple II supports the first 128 characters of the Unicode character set. There are just very few software programs on the Apple II that take advantage of it. A tab character is defined as a non-printable character translated by software to a variable width spacing. It won't hurt anything if the Apple software tries to print it, but all Control characters are usually filtered out before printing and translated accordingly.

For simplicity, Apple ROM is hard coded to only recognize a carriage return. That might have more to do with the space restriction of ROM than actual programming decision. Apple was trying to make the Apple computer like your everyday typewriter. As a side effect benefit though, double spacing can be performed by leaving the line feed character in a file.

With the right software, there could even be limited support to display .rtf files and .html files on the Apple II as well.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 25, 2021 11:09 am 
Offline
User avatar

Joined: Tue Aug 11, 2020 3:45 am
Posts: 311
Location: A magnetic field
In the specific case of decimal adjust, is it possible to use look-up tables?

In the general case, I've not considered lazy evaluation of flags within 8080 on 6502 simulation. However, I have considered:-

  • Simplified 8080 as 65816 virtual machine.
  • 6502 on 6502 simulation.
  • 6502 on Z80 simulation; possibly cross-assembled to AVR. (So I never have to write Z80 or AVR assembly.)
  • 6502 with 64 bit extensions and lazy flag evaluation in C with AVR as the primary target.

The short answer is don't do lazy flag evaluation. The problem is complicated by the skewed execution frequency of opcodes which varies by application. Attempts to save clock cycles in one place often incur additional clock cycles elsewhere. At best, you'll have huge amounts of action-at-a-distance and marginal or illusionary gains.

I've considered the technique of splitting 6502 opcodes into micro-ops. This should apply equally to other processor architectures. Essentially, address mode computation, register transfer, ALU operation and computation/preservation of flags would be split into separate operations. I hoped to apply this to straight runs of instructions of up to 64 bytes on the assumption that they would be unlikely to decompose into more than 256 micro-ops. This allows flag operations to be stripped from a sequence of instructions. It also allows other operations to occur. For example, stack operations may replaced with shadow register transfers.

Unfortunately, this technique has several disadvantages. Most obviously, it greatly increases the number of virtual instruction dispatch operations. It is also possible to inadvertently devise "optimizations" which are O(n^2). Stripping flag operations is likely to fall into this case. I also hoped to fit such optimization around the memory cycles of a device very much like MCL65+. Again, this leads to marginal or illusionary gains. It also complicates or is highly detrimental to interrupt response. I hoped to use change of program flow as a natural check-point for polling interrupts; in part because a stack should be balanced when iterating a loop and therefore shadow stack locations do not require flushing. In aggregate, on a fast system, control flow should change more one million times per second. However, jitter may be terrible.

A preferable technique may be to consider difficult instruction sequences as arbitrarily large instruction prefixes. This incurs no overhead when running common opcodes and incurs minimal overhead when partial matches occur. However, when an instruction sequence triggers a specific state, the semantics are implemented as a special case. Unfortunately, useful sequences have to be found empirically from legacy binaries and sequences are highly dependent upon programming style. In the general case, it should be useful to look for operations such as 16 bit addition or block copying. Both of these rely upon flags and they may be freely implemented without regard for intermediate flag values.

You have the displeasure of handling mismatched flags. I've had success holding comparable flags on top of stack. This works exceedingly well for 6502 on 6502 simulation but I originally considered it for 6502 on Z80 simulation. It should work equally well for 8080 on 6502 simulation. Very few programs poke about with flags directly. Acorn's OS is a notable exception. In the general case, it is possible to hold flags in arbitrary order and with arbitrary polarity. I haven't investigated closely but I suspect that Klaus Dormann's 6502 on AVR simulation works because AVR provides Z80 style flags in 6502 order. In particular, carry is in the bottom bit and don't look too closely at the polarity of the zero flag. I also suspect that Klaus Dormann's test suite doesn't delve too deeply into such discrepancy.

I highly recommend holding comparable flags on top of stack and flags such as parity in zero page. You'll have to split and join flags when they are pulled or pushed. However, it is otherwise quite pleasant to write PLP // ... // PHP around the critical step and handle minor discrepancies as separate cases.

_________________
Modules | Processors | Boards | Boxes | Beep, Beep! I'm a sheep!


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 26, 2021 1:18 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
I have never experimented with delaying flag evaluation, but have thought about it because the effects of most instructions on the flags are not used, that is, not followed by something like a conditional branch, addition with carry, subtraction with borrow, shift or rotate, push flags or servicing an interrupt before another instruction modifies the flag.

Some amount of overhead is needed to save enough context to enable evaluating the flags later; for some instructions, that overhead may be greater than actually evaluating the flags.

My thought at this time is that two tactics may be fruitful:

* Keep the flags in the form of the host processor instead of the simulated one and doing a translation only before something like push flags or an interrupt.

* On host processors like the 6502 without an aux carry or half carry flag, delay evaluating that flag until it is actually needed by a decimal adjust, push flags or interrupt.

For maximum performance, dynamically converting frequently executed code from the instruction set of the simulated processor to that of the host can pay off, but there is overhead in doing that as well. I do not believe that a machine with only 64K of address space can do that effectively.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 26, 2021 3:18 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
The first tactic seems to be an excellent idea, but I have a feeling that delaying the evaluation of the parity and half-carry flags is going to be tricky, unless you cache the op-code, previous flags and all operands of the last relevant instruction and re-run it more carefully when necessary (only four bytes per flag for the 8080, so not so expensive storage-wise). It's conceivable that this instruction-caching technique could be used for the other flags as well ... even other register contents in some cases.

JIT compiling is a well-studied topic, but I believe it takes more talent than most of us possess to make it a worthwhile effort on a limited host.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Thu Apr 29, 2021 1:59 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
Delaying the evaluation of the parity flag is simple: instructions which affect this flag set it if there is an even number of "1" bits in the result of the instruction. So those instructions store a copy of the result into a variable; the lone exception is "pop psw" which stores an inverted copy of the popped flag into the variable.

The parity flag is currently being evaluated by lookup table along with the sign and zero flags, so there is nothing to be gained by doing that later.


Top
 Profile  
Reply with quote  
PostPosted: Mon May 10, 2021 9:00 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BillG wrote:
IamRob wrote:
Would like to add MSBasic to that list and try to port over Cobol, Fortran and Turbo Pascal as well. And even try to emulate the TRS80.

A long time ago, I wanted to modify Turbo Pascal to generate 8080-compatible programs. That effort did not get very far. Borland's code is very tricky and reverse engineering it is not easy.

I have disassembled most of the Turbo Pascal run-time library and commented much of it.  I still believe that creating a version of the compiler to run on an 8080 system is not feasible, but it now seems very doable to:

* write an 8080 version of the run-time library
* write a post-compiler to translate Z80 code generated by the compiler to 8080 assembly language
* write a tool to stitch the two together

If that can be done, it is not a huge stretch to

* write enough of a Z80 simulator to run the Turbo Pascal compiler on processor X
* write a version of the run-time library for processor X
* write a version of a converter to translate Z80 code to processor X

I believe this can be done with substantially less effort than writing a new Turbo compatible compiler to run natively on processor X


Top
 Profile  
Reply with quote  
PostPosted: Wed May 12, 2021 5:02 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
I didn't realize the Turbo Pascal compiler converted its code to Z80. That might be too much of stretch to convert to 6502.

I hadn't played with KIX much since not a fan of the interface, but after delving into it more realized that the Pascal compiler that comes with it is already 6502 based. KIX's Pascal compiler creates P-code and might be a better fit for the 6502.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 62 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 19 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: