QL / PASCAL

Anything QL Software or Programming Related.
Derek_Stewart
Font of All Knowledge
Posts: 3900
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: QL / PASCAL

Post by Derek_Stewart »

NormanDunbar wrote:Back onto the Pascal topic! ;)

I've updated the "How to" document with the following changes:
  • The bits about the linker error message have been removed as Chain-Q has fixed that.
  • I've added a section on how to create a new unit and, if necessary, a new example for same;
  • I've added a section on updating the version control (Subversion) so that it will look at your new files when creating a patch file.
Version 1.4 of the document is here: https://github.com/NormanDunbar/FPC-Cro ... ses/latest.


Cheers,
Norm.
Hi Norman,

I have downloaded the updated document and will work through it from the start.

One point, can you insert the document version in the filename, as I end up with many different versions of the same documents with varying version numbers.

Life is confusing enough without added tedium.


Regards,

Derek
User avatar
NormanDunbar
Forum Moderator
Posts: 2249
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: QL / PASCAL

Post by NormanDunbar »

derek_Stewart wrote:One point, can you insert the document version in the filename, as I end up with many different versions of the same documents with varying version numbers.
I will do Derek. If I forget, poke me with a sharp stick!


Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
pjw
QL Wafer Drive
Posts: 1280
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: QL / PASCAL

Post by pjw »

NormanDunbar wrote:<>any chance you can take the emulator/68000/etc stuff to a new thread please? I keep seeing new posts on my (it's mine now even though I didn't start it) Pascal thread, only to find then off topic.
Sure. Sorry. Its just how normal, human conversations run, though. My
excuse for my part in this is that this discussion is tangential to
the main topic: namely how might FPC (etc) look if it werent
constrained by the olde 68008? Its sometimes hard to know when to
split off.
NormanDunbar wrote:Much obliged, and apologies for being a grump. ;)
Cant say I detect any untoward grumpiness, Norm :) And your efforts with FPC are
much appreciated!


Per
dont be happy. worry
- ?
User avatar
NormanDunbar
Forum Moderator
Posts: 2249
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: QL / PASCAL

Post by NormanDunbar »

Thanks Per.

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
Chain-Q
Chuggy Microdrive
Posts: 62
Joined: Mon Nov 16, 2020 1:10 pm
Location: Berlin, DE, EU
Contact:

Re: QL / PASCAL

Post by Chain-Q »

pjw wrote: My excuse for my part in this is that this discussion is tangential to the main topic: namely how might FPC (etc) look if it werent constrained by the olde 68008? Its sometimes hard to know when to split off.
You mean generated code wise? Well, FPC on the m68k is mainly a 68020 compiler, and it was written with such code in mind. For example it prefers 32bit integers and pointers. The runtime library also follows this trend when it comes to parameters and handles. This is admittedly not too effective on an original 68000. But my priorities were: first make it work, then maybe work to make it fast... However, FPC does several smaller things when set to target a plain 68000. The most obvious is that it avoids generating addressing modes and instructions not available on the 68000. This means for example using helper functions for long multiplication and division, however it can also generate shit+add code sequences when the long multiplication is with a constant. It also tries to detect code which might lead to unaligned accesses and compile special (slower) code there to avoid alignment exceptions. (Sometimes this cannot be done w/o modifying the code, and you have to mark the unaligned accesses using the unaligned() keyword, but in several cases it's automatic.)

On a 68020+, FPC will use long displacements, scaled indexing, will rely on the CPU to be able to handle unaligned accesses, and of course generate several 68020+ instructions, for example TST Ax, RTD, long and even long long MULU/MULS/DIVU/DIVS, among others. There's ongoing work to utilize 020+ bitfield instructions better in some cases, for example when working with sets and bitpacked records. Probably more, this is just from the top of my head. And of course it can use the 68881/2 FPU for floating point math, when so told. (Or when the platform ABI dictates this, for example on Linux/BSD.)

If one is feeling like improving the 68000 support, I can give some pointers where to start. For example the memory copy/fill functions need some overhaul. A better (maybe assembly optimized) version of the mul/div helpers would be nice. And there's some more. Most of this is not even QL specific, and will improve FPC on all 68k systems.


User avatar
Chain-Q
Chuggy Microdrive
Posts: 62
Joined: Mon Nov 16, 2020 1:10 pm
Location: Berlin, DE, EU
Contact:

Re: QL / PASCAL

Post by Chain-Q »

So, because earlier there was some discussion on how QLGCC/C68 addresses the console opening, and makes it possible to override via some struct which can be injected using weak linking, I enabled weak linking for the QL, and added two "hooks", where the user code can open a console the way it wants, then fill out the stdin/stdout/stderr channel ID handles in a struct for the RTL. This is documented here. I also wanted to add an example code, but I had no time yet.

On a related note, I think there's some trouble on how FPC handles and shares a single channel as stdin/stdout handle. For example a write('enter your name:'); readln(name); won't work, the "enter your name" text will not appear, and then all sorts of weird things will happen depending on the length of your input. Someone with better QL knowledge might be able to tell me there what's going on, and how to fix it. The most obvious would be to have two separate channels as stdout and stdin. But how can I achieve that? Just one "con_" twice? Once for reading and once for writing? C68 libc seems to use con_ only for input? But the code is complicated because it's mixed with standard channels handling and whatnot. But I only looked at the code briefly.


User avatar
Chain-Q
Chuggy Microdrive
Posts: 62
Joined: Mon Nov 16, 2020 1:10 pm
Location: Berlin, DE, EU
Contact:

Re: QL / PASCAL

Post by Chain-Q »

NormanDunbar wrote:Another patch to the Free Pascal stuff. In this one, I have modified the qdos unit to:
  • Include a file qdos_sysvars.inc which has a new record type, SystemVariables, and a pointer to it, PSystemVariables.
  • Remove the existing offsets from the base of the system variables, superceeded by the above.
This is great work, and very useful, however, I didn't merge it yet, because I found a couple of things I didn't like:

First, you used {$PACKRECORDS 1} for this SystemVariables type. Instead of the compiler directive, you could have used SystemVariables = packed record, which has the same effect, and it's cleaner. But anyway, both are quite bad on the 68000, because it will make FPC think this is a completely unaligned record, used for example for I/O, so regardless of the offsets inside the record, it will generate unaligned access code for the fields longer than a byte. (move.b (a0)+,d0; lsl.w #8, d0; move.b (a0)+,d0; swap d0; move.b (a0)+,d0; lsl.w #8,d0; move.b (a0)+,d0 just to load a longword... Not ideal. Yes, I know one can make it faster via some stack pointer trickery, but I decided to go against that for now, for several reasons.) So this must not be a packed record, I think. On the QL, FPC guarantees a two byte alignment, , so you can calculate with that. (Well, unless someone is messing with $PACKRECORDS in their own code, but that shouldn't affect the OS package.) FPC's unaligned access support on m68k is documented here. (OK, to be honest, I just added PACKRECORDS 1 to this section in the documentation, because internally it's really just the same as setting all records to "packed", but of course to someone without knowledge of the compiler internals this might not be obvious.)

The above problem is related to this, I'd prefer to keep the offset constants you removed, for various reasons. For example having them makes porting/reading of C examples when you port them over to Pascal, as C68 libc has similar constants. Or you can actually use them to write test code to verify the record offsets. I think an OS API unit shouldn't make too much effort to direct what kind of code one should write, and just provide as many tools as possible. One can still build a "helper" layer on top of it for "best practices", and I consider this new struct to be part of that. The example code of course is for best practices, so it can still use the new record, of course.


User avatar
NormanDunbar
Forum Moderator
Posts: 2249
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: QL / PASCAL

Post by NormanDunbar »

Chain-Q wrote:First, you used {$PACKRECORDS 1} for this SystemVariables type.
Hmm. Usually I code in C/C++ and not Pascal. However, when I'm coding on the PC to read QL structures, I always have to pack the structures to get the correct offsets. I suspect this was simply "muscle memory" in action. I've commented out the packing lines and recompiled the QDOS and SMS examples (in packages/qlunits/examples) and they appear to work fine. However, I'm on QPC which is impersonating/emulating a 68020 and I have fallen foul of that in the past with misaligned words/longwords on byte addresses -- the original QL with its 68008 would have barfed but the 68020 just did what was needed and carried on.

So I then compiled my own example program which displays all the QDOS System Variables on 5 or so pages. That also worked, so the good news is, unless I'm being 68020'd, is that I didn't need the packing after all. Famous last words?
Chain-Q wrote: I'd prefer to keep the offset constants you removed, for various reasons.
No worries, I've edited them back in.
Chain-q wrote:... I think there's some trouble on how FPC handles and shares a single channel as stdin/stdout handle. For example a write('enter your name:'); readln(name); won't work, the "enter your name" text will not appear, and then all sorts of weird things will happen depending on the length of your input.
I noticed this. When I was doing my "list all the system variables" program, I needed to prompt the user to "press any key to continue or ESC to quit" and weird things did indeed happen. I resolved this as follows but the user doesn't have to press ENTER:

Code: Select all

  Write('Press Any key (except ESC) to continue,  ESC to Quit....');
  Flush(output);
  Enter := char(io_fbyte(stdInputHandle, -1));
  if Enter = chr(27) then
    Pause := false;
  Writeln;
In a test program, It works fine like this:

Code: Select all

program test;

var
   name: array[0..49] of char;

begin
  write('enter your name:'); 
  flush(output);
  readln(name);
  writeln('your name is: ', name);
end.
The prompt gets printed if I flush, If I forget to flush, there's no prompt and it acts weird.


The QL defaults to three channels being open -- C68 may do other things, other (SuperBASIC) compilers allow the programmer to select how many windows to copy from SuperBASIC or whether the code opens its own windows etc -- Depending on TV or Monitor mode. The input channel (#0) is a con channel at the bottom of the screen and is about 3 lines deep. The other two are at the top of the screen, one is used for program output without a channel id, the other for listings etc. Those are both also con channels as input is permitted, but only by explicitly specifying the channel number (#1 or #2).

At the moment, I would leave the console opening as is, and note, perhaps, that between a write and a read, a flush may be required?

This file is a replacement for FPC.patch.8.zip and contains the changes/reversions above. It has been tested with the latest updates -- Revision: 49374 -- as per svn info.
FPC.patch.8a.zip
(6.36 KiB) Downloaded 76 times
Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
Chain-Q
Chuggy Microdrive
Posts: 62
Joined: Mon Nov 16, 2020 1:10 pm
Location: Berlin, DE, EU
Contact:

Re: QL / PASCAL

Post by Chain-Q »

Yes, flushing works, but I consider it a workaround, read/write is platform agnostic API, so it shouldn't really behave differently and need code changes on a specific platform. I'll look into this where this problem comes from.


User avatar
tofro
Font of All Knowledge
Posts: 2679
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: QL / PASCAL

Post by tofro »

There's actually nothing in QDOS that would delay the output and there shouldn't be the need to flush output to see anything - I'd suspect the buffering, if any, happens inside the RTL.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Post Reply