Page 2 of 4
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 3:14 am
by BillG
You also might want to look at the
ISO 7185 Standard Pascal website. It has several versions of the portable Pascal-P compiler/interpreter. I believe Pascal-P2 served as the basis for UCSD Pascal.
I looked at the interpreters for P2 and P4. Neither resembled LUCIDATA.
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 3:18 am
by BillG
Thanks!
Some of that information should apply to all P-code implementations.
Data Becker published some GREAT technical books in their time. One of my favorites is Turbo Pascal 6 System Programming.
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 3:49 am
by BillG
I'd be interested in seeing if this might run on my Ruby system - but one big issue might well be what sort of underlying operating system it needs to handle e.g. files and so-on.
The LUCIDATA system switches into "paging" mode when a program is too large to load into available memory. Theoretically, a version for the 65816 may be possible to use an entire 64K bank for data (the stack) and other memory above the base 64K for the program. The question then would be internal size limits of the compiler. For instance, the "program counter" is 16-bits as are offsets into the stack.
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 4:19 am
by Sean
You also might want to look at the
ISO 7185 Standard Pascal website. It has several versions of the portable Pascal-P compiler/interpreter. I believe Pascal-P2 served as the basis for UCSD Pascal.
I looked at the interpreters for P2 and P4. Neither resembled LUCIDATA.
Interesting. Since it doesn't look like P2 or P4, and it doesn't look like UCSD, you make me wonder if the developer of LUCIDATA went for a fresh implementation from the language spec.
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 6:22 am
by BillG
The manual says the compiler was written by David R. Gibby and the run-time system by Nigel W. Bennee.
A web search does not reveal much except possibly versions for CP/M and Heathkit DOS. I have heard of neither of these before.
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 11:18 am
by BigEd
Which disassembler are you using BillG? Just possibly py8dis will be of interest.
https://stardot.org.uk/forums/viewtopic ... 55&t=23335
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 11:28 am
by drogon
I'd be interested in seeing if this might run on my Ruby system - but one big issue might well be what sort of underlying operating system it needs to handle e.g. files and so-on.
The LUCIDATA system switches into "paging" mode when a program is too large to load into available memory. Theoretically, a version for the 65816 may be possible to use an entire 64K bank for data (the stack) and other memory above the base 64K for the program. The question then would be internal size limits of the compiler. For instance, the "program counter" is 16-bits as are offsets into the stack.
Hm. I was half hoping I may be able to run it like I run the cintcode VM - which is is 32-bit mode with no bank/page restrictions, but if that's effectively built into the system then it might be awkward.
I'll get Pascal going one day, even if I have to finish off the compiler I started writing - with the intention of having it compile into the bcpl cintcode, then it can directly work on the system with the possibility of cross calling from Pascal to BCPL and back.... Back to Jack Crenshaws papers!
Cheers,
-Gordon
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 14, 2021 1:13 pm
by BillG
None. I start with the hex dump, manually group the bytes into clumps of four for each instruction and add a comment if I know the meaning.
Unless LUCIDATA had an internal tool, I doubt anyone knows the instruction set to write one.
Re: LUCIDATA Pascal for 6502
Posted: Sun Oct 17, 2021 5:04 am
by BillG
So I morphed the debugger from the 8080 simulator into a P-code debugger.
Now to build a foundation below it to execute those instructions...
Re: LUCIDATA Pascal for 6502
Posted: Tue Oct 19, 2021 11:23 am
by BillG
Re: LUCIDATA Pascal for 6502
Posted: Tue Oct 19, 2021 1:06 pm
by drogon
Looks like good progress!
Things I found tricky about Pascal were sets/ranges but with this sort of incremental approach it might not be too hard to work out what's going on under the bonnet...
Cheers,
-Gordon
Re: LUCIDATA Pascal for 6502
Posted: Wed Oct 20, 2021 12:01 pm
by BillG
This has been but a few bites of a rather large elephant.
Without an understanding of the frame pointer and activation records, there will be little further progress as everything else keys on that.
Re: LUCIDATA Pascal for 6502
Posted: Thu Oct 28, 2021 11:36 am
by BillG
Still trying to gain an understanding of the stack frames and activation records. In pursuit thereof, I came up with this test program:
Code: Select all
PROGRAM TEST;
VAR
I : INTEGER;
PROCEDURE DEEP;
VAR
J : INTEGER;
PROCEDURE DEEPER;
VAR
K : INTEGER;
PROCEDURE DEEPEST;
VAR
L : INTEGER;
BEGIN
L := 4;
WRITE(I);
WRITE(J);
WRITE(K);
WRITELN(L)
END;
BEGIN
K := 3;
DEEPEST
END;
BEGIN
J := 2;
DEEPER
END;
BEGIN
I := 1;
DEEP
END.
It's P-code is:
Code: Select all
Hexadecimal dump of nested.bin
00000000: 00 2E 00 7C 00 01 00 01-00 06 01 00 00 68 01 00 |...|.........h..|
00000010: 00 54 01 00 00 40 06 00-00 02 07 02 00 04 27 00 |.T...@........'.|
00000020: 00 08 26 03 00 08 2E 02-06 01 26 02 00 08 2E 02 |..&.......&.....|
00000030: 06 01 26 01 00 08 2E 02-06 01 26 00 00 08 2E 02 |..&.......&.....|
00000040: 06 01 1C 02 00 00 05 00-00 00 06 00 00 02 07 02 |................|
00000050: 00 03 27 00 00 08 04 80-00 0C 05 00 00 00 06 00 |..'.............|
00000060: 00 02 07 02 00 02 27 00-00 08 04 80 00 40 05 00 |......'......@..|
00000070: 00 00 06 00 00 08 07 02-00 01 27 00 00 08 04 80 |..........'.....|
00000080: 00 54 00 00 00 00 00 00-00 00 00 00 00 00 00 00 |.T..............|
0000: 01 00 00 68 ; Jump $0068
0004: 01 00 00 54 ; Jump $0054
0008: 01 00 00 40 ; Jump $0040
000C: 06 00 00 02 ; SP := SP + 2
0010: 07 02 00 04 ; Push integer "0004"
0014: 27 00 00 08 ; Pop L
0018: 26 03 00 08 ; Push I
001C: 2E 02 06 01 ; Write integer
0020: 26 02 00 08 ; Push J
0024: 2E 02 06 01 ; Write integer
0028: 26 01 00 08 ; Push K
002C: 2E 02 06 01 ; Write integer
0030: 26 00 00 08 ; Push L
0034: 2E 02 06 01 ; Write integer
0038: 1C 02 00 00 ; Writeln
003C: 05 00 00 00 ; Return
0040: 06 00 00 02 ; SP := SP + 2
0044: 07 02 00 03 ; Push integer "0003"
0048: 27 00 00 08 ; Pop K
004C: 04 80 00 0C ; Call DEEPEST
0050: 05 00 00 00 ; Return
0054: 06 00 00 02 ; SP := SP + 2
0058: 07 02 00 02 ; Push integer "0002"
005C: 27 00 00 08 ; Pop J
0060: 04 80 00 40 ; Call DEEPER
0064: 05 00 00 00 ; Return
0068: 06 00 00 08 ; SP := SP + 8
006C: 07 02 00 01 ; Push integer "0001"
0070: 27 00 00 08 ; Pop I
0074: 04 80 00 54 ; Call DEEP
0078: 00 00 00 00 ; Halt
P-code instructions are a multiple of four bytes; all except for pushing a constant string are only four bytes.
The first byte is an opcode identifying the instruction. The second byte often serves as a "mode" indicator to allow for variations of an operation or for multiple operations to share an opcode. The third and fourth bytes are extra information.
From the posted test program, the second byte of a push variable instruction appears to be the procedure nesting level. The "main program" is treated as just another enveloping procedure, so there are no physical global variables. The logical global variables of a program are allocated in the activation record of the main program. This is what the SP := SP + 6 (or more) instruction which starts every program allocates.
In the meantime, other P-code instructions may be exercised solely by pushing constants onto the stack and operating on them. About a half of the instructions have been done. The dispatch table now looks like this:
Code: Select all
2B33 02211 Instructions
2B33 2AAB 02212 fdb I_Halt ; $00
2B35 2AD2 02213 fdb I_Jump ; $01
2B37 2AE5 02214 fdb I_IfFalse ; $02
2B39 2BB3 02215 fdb Unimplemented ; $03
2B3B 2BB3 02216 fdb Unimplemented ; $04
2B3D 2BB3 02217 fdb Unimplemented ; $05
2B3F 2E8A 02218 fdb I_ManageStack ; $06
2B41 2EC7 02219 fdb I_PushConstant ; $07
2B43 2BB3 02220 fdb Unimplemented ; $08
2B45 2F20 02221 fdb I_IfNotAndOr ; $09
2B47 2BB3 02222 fdb Unimplemented ; $0A
2B49 2BB3 02223 fdb Unimplemented ; $0B
2B4B 2BB3 02224 fdb Unimplemented ; $0C
2B4D 2BB3 02225 fdb Unimplemented ; $0D
2B4F 2BB3 02226 fdb Unimplemented ; $0E
2B51 2BB3 02227 fdb Unimplemented ; $0F
2B53 2F4A 02228 fdb I_CompareBytesForEQ ; $10
2B55 2F78 02229 fdb I_CompareBytesForNE ; $11
2B57 2BB3 02230 fdb Unimplemented ; $12
2B59 2BB3 02231 fdb Unimplemented ; $13
2B5B 2BB3 02232 fdb Unimplemented ; $14
2B5D 2BB3 02233 fdb Unimplemented ; $15
2B5F 2BB3 02234 fdb Unimplemented ; $16
2B61 2BB3 02235 fdb Unimplemented ; $17
2B63 2BB3 02236 fdb Unimplemented ; $18
2B65 2F91 02237 fdb I_ConvertIntegerToByte ; $19
2B67 2FCD 02238 fdb I_Convert ; $1A
2B69 2BB3 02239 fdb Unimplemented ; $1B
2B6B 3010 02240 fdb I_Writeln ; $1C
2B6D 301D 02241 fdb I_Readln ; $1D
2B6F 3073 02242 fdb I_WriteString ; $1E
2B71 2BB3 02243 fdb Unimplemented ; $1F
2B73 310B 02244 fdb I_CompareIntegersForEQ ; $20
2B75 312E 02245 fdb I_CompareIntegersForNE ; $21
2B77 313C 02246 fdb I_CompareIntegersForLT ; $22
2B79 315A 02247 fdb I_CompareIntegersForGT ; $23
2B7B 317B 02248 fdb I_CompareIntegersForLE ; $24
2B7D 319C 02249 fdb I_CompareIntegersForGE ; $25
2B7F 2BB3 02250 fdb Unimplemented ; $26
2B81 2BB3 02251 fdb Unimplemented ; $27
2B83 2BB3 02252 fdb Unimplemented ; $28
2B85 2BB3 02253 fdb Unimplemented ; $29
2B87 2BB3 02254 fdb Unimplemented ; $2A
2B89 2BB3 02255 fdb Unimplemented ; $2B
2B8B 2BB3 02256 fdb Unimplemented ; $2C
2B8D 2BB3 02257 fdb Unimplemented ; $2D
2B8F 31BB 02258 fdb I_WriteInteger ; $2E
2B91 2BB3 02259 fdb Unimplemented ; $2F
2B93 2BB3 02260 fdb Unimplemented ; $30
2B95 2BB3 02261 fdb Unimplemented ; $31
2B97 32EB 02262 fdb I_CreateAddMemberToSet ; $32
2B99 3334 02263 fdb I_SetOperations ; $33
2B9B 3373 02264 fdb I_DetermineSetMembership ; $34
2B9D 33AB 02265 fdb I_CompareSets ; $35
2B9F 33F8 02266 fdb I_CompareAlfaForEQ ; $36
2BA1 3412 02267 fdb I_CompareAlfaForNE ; $37
2BA3 3421 02268 fdb I_CompareAlfaForLT ; $38
2BA5 3440 02269 fdb I_CompareAlfaForGT ; $39
2BA7 3460 02270 fdb I_CompareAlfaForLE ; $3A
2BA9 347F 02271 fdb I_CompareAlfaForGE ; $3B
2BAB 2BB3 02272 fdb Unimplemented ; $3C
2BAD 2BB3 02273 fdb Unimplemented ; $3D
2BAF 2BB3 02274 fdb Unimplemented ; $3E
2BB1 2BB3 02275 fdb Unimplemented ; $3F
Re: LUCIDATA Pascal for 6502
Posted: Sun Oct 31, 2021 12:57 pm
by BillG
After many tricks, I finally get a treat. This program runs:
Code: Select all
PROGRAM TEST;
VAR
C : CHAR;
I : INTEGER;
BEGIN
WRITE("Enter a character ");
READLN(C);
WRITELN;
WRITELN("'",C,"'");
REPEAT
WRITE("Enter an integer (0 or <CR> to quit) ");
READLN(I);
WRITELN(I)
UNTIL I = 0
END.
Access to variables work within the current activation record, in this case, program global variables.
The big pieces of functionality still left to do include:
* arrays
* add, subtract, multiply, divide
* subroutine call and return
* files on disk
* paged mode
The last one is not needed to try running the compiler.
Re: LUCIDATA Pascal for 6502
Posted: Sun Oct 31, 2021 5:59 pm
by Sean
After many tricks, I finally get a treat. This program runs:
Congratulations on your progress. That's an important milestone.