241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
-
+
-
+
+
+
|
### <a id="ralf"></a>RALF
RALF uses more or less the same statement syntax as the PAL family, but it is a very different assembler by nature. We can divide its differences into several groups.
#### Floating Point Processor Support
RALF is the back-end assembler for OS/8's FORTRAN IV compiler, which requires use of a Floating Point Processor (FPP) peripheral, and OS/8 FORTRAN IV delegates all of the FPP handling to RALF. Indeed, Vincent Slyngstad [suggests][smal8] that you think of RALF as an assembler for the FPP rather than for the PDP-8.
RALF is not only an assembler for the PDP-8 processor, it is also an assembler for the [FPP12][fpp12] Floating Point Processor (FPP) peripheral. The OS/8 FORTRAN IV delegates all of the FPP handling to RALF, but at program load time, `FRTS` checks for the existence of an FPP and switches to a software FPP simulator if there is no FPP present. (`FRTS` does the same for the EAE, by the way.)
The first FPP peripheral from DEC was the [FPP12][fpp12]. Although it was introduced with the PDP-12, it is not restricted to the PDP-12: it also works with all of the other PDP-8 family computers contemporaneous with and preceding it, going back to the original PDP-8. This is possible because the FPP is a bus peripheral rather than a feature of the CPU proper. There was also a follow-on peripheral for the PDP-8/a called the [FPP8-A][fpp8a], as well as a later variant called the FPP12A, both of which are instruction-compatible with the original FPP12. The FPP features of RALF allow you to intermix FPP instructions with PDP-8 instructions just as if the FPP were part of the PDP-8 CPU, rather than being a very different external coprocessor.
Although the FPP12 was introduced with the PDP-12, it is not restricted to use with the PDP-12: it also works with all of the other PDP-8 family computers contemporaneous with and preceding it, going back to the original PDP-8. This is possible because the FPP is a bus peripheral rather than a feature of the CPU proper. DEC justified this in their documentation, pointing out that it means that a site can upgrade their existing processors with an FPP rather than buy a whole new machine with integrated FPP features when they find that software FP is taking too much time to run.
There was also a follow-on peripheral for the PDP-8/a called the [FPP8-A][fpp8a], as well as a later variant called the FPP12A, both of which are instruction-compatible with the original FPP12. The FPP features of RALF allow you to intermix FPP instructions with PDP-8 instructions just as if the FPP were part of the PDP-8 CPU, rather than being a very different external coprocessor.
Here is a summary of the FPP-related features of RALF:
* More instructions and pseudo-ops:
* Arithmetic: `FADD`, `FADDM`, `FDIV`, `FLDA`, `FMUL`, `FMULM`, `FSTA`, `FSUB`
* Conditional jumps: `JEQ`, `JGE`, `JLE`, `JA`, `JNE`, `JGT`, `JAL`
* FPP to PDP-8 jumps: `JXN`, `TRAP3`, `TRAP4`
|
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
|
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
|
RALF generates relocatable output code in `*.RL` files rather than absolute-addressed output, which means you cannot simply load its output into core and execute it directly. You must use the OS/8 FORTRAN IV loader (`LOAD.SV`) to load one or more `*.RL` files into core memory, link them to any external libraries, convert relative addresses to fixed addresses, and write out a loader image (`*.LD`) which can then be loaded an run by the OS/8 FORTRAN IV Run Time System, `FRTS.SV`.
The compensation for this complicated scheme is that `LOAD.SV` and `FRTS.SV` provide a powerful overlay and linkage loading scheme which allows for programs up to about 300 kWords in size, nearly 10× the maximum core memory size in a standard PDP-8 family computer. It does this by loading code from disk as needed. This scheme is made possible by the relocatable output code from RALF.
(Do not confuse `LOAD.SV`, the OS/8 FORTRAN IV loader — used by both RALF and F4 — with `LOADER.SV`, the simpler "linking loader" used by the OS/8 FORTRAN II compiler (`FORT.SV`) and by [SABR](#sabr). There's a second cause for confusion: both loaders use `*.RL` as their default input file name extension, so RALF, F4, FORT, and SABR all output files with that extension.)
#### Justifiable Restrictions
There are restrictions in RALF relative to late-generation PAL family assemblers that are justifiable on the grounds that they follow from the requirement that the output code be relocatable:
* It does not understand the `PAGE` pseudo-op: the PAL form of this feature — where the page number is given as an argument to the pseudo-op — inherently goes against the nature of relocatable output. The inability to accept the argument-less version understood by [SABR](#sabr) is harder to justify.
* It does not support current-page literals — `(42` — since allowing it would complicate relocation.
#### Arbitrary Differences
There are additional differences in RALF relative to the PAL family assemblers that seem entirely arbitrary to me:
* Indirect addressing is done differently:
TAD I A / PAL syntax
TAD% A / RALF syntax
* The programmer must tell the assembler when zero-page addressing is needed:
TAD A / PAL syntax: PAL assemblers know when A is on page zero and so set the Z flag in machine code output
TAD Z A / PAL lets you be explicit if you want; space is not optional
TADZ A / RALF syntax: RALF needs to be told; no space can be given
* Its expression syntax has no "and" operator, `&`
* It does not support zero-page literals: `[20`
This restriction does not seem to have a good justification, even in relocatable assembler output, since the nature of the feature at both at the assembly and machine code levels is that the memory reference is inherently absolute. Thus, generation of a zero-page literal cannot affect the ability of the relocating loader to relocate the generated code.
#### Further Improvements
RALF also has many other improvements over late-generation PAL family assemblers such as PAL8 which are not directly tied to driving the FPP or to relocatable code:
* Expressions:
* Multiplication is `*` rather than `^`; this is possible because RALF offers the `ORG` pseudo-op to set the location counter, where PAL family assemblers use `*`
* Division is `/` rather than `%`, achieved by requiring whitespace before `/` if used to start a comment and disallowing spaces in expressions
* Many new and changed pseudo-ops:
* Conditional assembly additions relative to PAL8: `IFPOS`, `IFNEG`, `IFSW`, `IFNSW`, `IFFLAP`, `IFRALF`
* `IFREF`: replaces `IFDEF` pseudo-op, having a superset of its functionality
* `LISTOF`/`LISTON`: stop and start listing output rather than the PAL family's `XLIST` pseudo-op
* `REPEAT`: assemble the following line multiple times
* `ADDR`: define address constant
* `E` and `F`: define floating-point constants
* FORTRAN IV feature support: `COMMON`, `COMMZ`, `ENTRY`, `EXTERN`, `FIELD1`, `SECT`, `SECT8`
There is one regression in RALF relative to PAL8 not mentioned so far: its expression syntax has no "and" operator, `&`.
[fpp8a]: https://archive.org/details/bitsavers_decpdp8pdpUsersManDec76_996770
[fpp12]: https://archive.org/details/bitsavers_decpdp12DE_2606247
### <a id="flap"></a>FLAP
[RALF](#ralf) was based on a simpler assembler called FLAP, which generates absolute-addressed code, just as PAL8 does. This section will simply describe the differences in FLAP relative to RALF. These differences aside, FLAP shares the feature set of RALF.
|