|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 108288 (0x1a700)
Types: TextFile
Names: »D173«
└─⟦4b76feb82⟧ Bits:30008865 Diskette med tekster der formodes at være 31-D-163…174
└─⟦this⟧ »D173«
i
P_R_E_F_A_C_E_
PASCAL80 is the common systems programming language for future RC
products, including the RC700 and RC850 product families.
The present manual is aimed at systems programmers writing pro-
grams in the PASCAL80 language intended to run on the PI-1
machine 2 which constitutes the core of RC700 and RC850 pro-
ducts.
The manual has been edited with the purpose of making it -
together with the PASCAL80 Report 1 - sufficient as a collec-
tion of general reference material for a programmer of the
described category.
\f
ii
\f
iii
T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_
1. INTRODUCTION .......................................... 1
2. A SHORT DESCRIPTION OF THE PI-1 MACHINE ............... 3
2.1 Segments ......................................... 4
2.2 The Private Monitor .............................. 5
2.2.1 Wait Functions ............................ 6
2.2.2 Scheduling ................................ 7
2.2.3 CHANNEL Statement ......................... 9
2.3 Standard Processes ............................... 9
3. PASCAL80 ON THE PI-1 MACHINE .......................... 11
3.1 Implementation Details and Language Modifications 11
3.1.1 Parameterized Types ....................... 11
3.1.2 Reals ..................................... 11
3.1.3 Radix ..................................... 12
3.1.4 Bounds of Subrange Types .................. 12
3.1.5 Message Header ............................ 12
3.1.6 LOCK and CHANNEL Statements ............... 12
3.1.7 Pool Initialization ....................... 13
3.1.8 Process Parameters ........................ 13
3.1.9 Incarnation Termination ................... 13
3.1.10 Routine Exit .............................. 13
3.1.11 Exception Handling ........................ 13
3.1.12 Prefix .................................... 14
3.1.13 Character String .......................... 14
3.1.14 Program ................................... 14
3.2 Predefined Types ................................. 14
3.3 Predefined Routines .............................. 15
3.3.1 Shallow Routines .......................... 15
3.3.2 Deep Routines ............................. 16
3.3.3 I/O and CPU Control Routines .............. 19
4. LINKING Z80 ASSEMBLY PROGRAMS INTO PASCAL80 PROGRAMS .. 21
\f
iv
T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _(_c_o_n_t_i_n_u_e_d_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_
5. REPRESENTATION AND LAYOUT OF VARIABLES ................ 25
5.1 Representation of Values ......................... 25
5.1.1 Enumeration Types ......................... 25
5.1.2 Shielded and Pointer Types ................ 25
5.1.3 Structured Types .......................... 26
5.1.4 Type Size ................................. 26
5.2 Memory Layout .................................... 27
5.2.1 Addressing ................................ 27
5.2.2 Stack Frame ............................... 28
5.2.3 Structured Types .......................... 30
5.2.3.1 Arrays and Records, Not Packed ... 30
5.2.3.2 Packed Arrays and Records ........ 31
5.2.3.3 Set Types ........................ 32
A_P_P_E_N_D_I_C_E_S_:
A. REFERENCES ............................................ 35
B. HOW TO USE THE PASCALZ80 COMPILER ..................... 36
B.1 Call of the Compiler ............................. 36
B.2 Contexts ......................................... 38
C. PASCALZ80 ERROR MESSAGES .............................. 39
C.1 Messages from Pass 1 ............................. 39
C.2 Messages from Pass 3 ............................. 42
C.3 Messages from Pass 4 ............................. 48
C.4 Messages from Pass 5 ............................. 49
C.5 Messages from Pass 6 ............................. 50
D. HOW TO BUILD A PI-1 LIBRARY ON THE RC8000.............. 51
D.1 InsertZ80 ........................................ 51
D.2 DeleteZ80 ........................................ 53
D.3 ListZ80 .......................................... 53
\f
v
T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _(_c_o_n_t_i_n_u_e_d_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_
E. HOW TO GENERATE A BOOTSTRAP IMAGE FOR THE PI-1 MACHINE
ON THE RC8000 ......................................... 54
E.1 Error Messages ................................... 56
F. HOW TO TRANSFER BINARY FILES BETWEEN THE RC8000 AND THE
TEKTRONIX 8002A DEVELOPMENT SYSTEM .................... 58
F.1 Tektronix Utility Program >CT> ................... 58
F.2 Tektronix Utility Program >CB> ................... 59
F.3 RC8000 Utility Program >tekmove> ................. 59
F.4 Examples of How to Transfer Programs ............. 60
\f
vi
\f
F_ 1_._ _ _ _ _ _ _ _ _I_N_T_R_O_D_U_C_T_I_O_N_ 1.
The PI-1 implementation of PASCAL80 1 has two main components:
the PI-1 machine based on the Z80 microprocessor and a cross-
compiler which runs on the RC8000 and generates code in the PI-1
machine object code format.
PASCAL80 as defined in 1 presupposes a number of primitive
functions, which in the language are expressed mostly in terms of
predefined routines, particularly in the area of process synchro-
nization, inter-communication, and scheduling. These functions are
provided by the PI-1 basic software, PIBS. The PI-1 machine con-
sists of a Z80 CPU with some amount of memory, PIBS, and an inter-
preter for the PI-1 instruction set which is designed to support
the sequential part of the PASCAL80 language.
A thorough description of the PI-1 machine is given in 2. Chap-
ter 2 of this manual contains a brief introduction which will be
sufficient for most PASCAL80 programmers. Programmers who need to
write Z80 assembly code to be integrated into a PASCAL80 program
(see below) may need to refer to 2 as well as the assembly lan-
guage and assembler manuals 4, 5.
Chapter 3 may be seen as a continuation of 1. The PI-1 version
of a number of language details which have been left in the
report as "implementation dependent" is described, and so are
some modifications and limitations relative to the language
definition given in 1. Chapter 3 contains a complete list of
all predefined routines of PI-1 PASCAL80. The repertoire is
somewhat richer than that described in 1, and all routines
which represent additions or modifications compared to the report
are explained.
In general, the execution by interpretation of compiled PASCAL80
code will be slower than the execution of optimal machine (Z80)
code with similar function by a considerable factor. Commonly,
however, a very small part of a program, typically one containing\f
often repeated loops, accounts for most of the execution time.
Indeed, in applications for which performance on the PI-1 machine
can be foreseen as problematic, we expect to be able easily to
identify the time-critical parts.
The general strategy supported by the PI-1 PASCAL80 compiler to
improve performance for such applications is to locate the cri-
tical part of the program and rewrite it as a Z80 assembler pro-
gram. The available mechanisms for linking such assembler coded
program parts into a PASCAL80 program are described in chapter 4.
Memory allocation and representation of variables of the various
PASCAL80 types are discussed in chapter 5.
Information about practical procedures for compilation, linking,
and loading of PASCAL80 programs is given in appendices.
\f
F_ 2_._ _ _ _ _ _ _ _ _A_ _S_H_O_R_T_ _D_E_S_C_R_I_P_T_I_O_N_ _O_F_ _T_H_E_ _P_I_-_1_ _M_A_C_H_I_N_E_ 2.
The PI-1 machine executes P_A_S_C_A_L_8_0_ _s_y_s_t_e_m_s_. A PASCAL80 system is
defined as the execution of a P_A_S_C_A_L_8_0_ _p_r_o_g_r_a_m_. A PASCAL80 pro-
gram consists of a number of p_r_o_c_e_s_s_e_s_. A process, as defined in
1, is a description of a data structure and some actions on
the data structure. The execution of the actions of a process on
the data structure is called a process i_n_c_a_r_n_a_t_i_o_n_. Each process
incarnation has a private data structure. In general, several
incarnations of a process may share one description of the ac-
tions (reentrant code).
The definition of the PASCAL80 language given in 1 implicitly
presumes the availability of a number of basic system functions
which for the most part are expressed in terms of predefined rou-
tines. In the PI-1 machine these functions are performed by the
PI-1 basic software, PIBS. The most important part of PIBS is the
so-called private monitor, PRIVMON, which is explained in section
2.2 below.
The Z80 microprocessor and its memory, augmented with PIBS, con-
stitutes the b_a_s_i_c_ _l_e_v_e_l_ of the PI-1 machine. The machine at this
level supports the PASCAL80 concepts introduced above, but it
sees process incarnations as executing Z80 machine instructions.
Indeed it is fully possible to write a process at this level,
i.e. in Z80 assembly code, and use the functions of PIBS. The
standard processes in the PI-1 machine (see section 2.3) and a
number of RC850 drivers have been constructed in this way.
Processes written in PASCAL80, however, will execute at the
i_n_t_e_r_p_r_e_t_e_d_ _l_e_v_e_l_ of the PI-1 machine. When compiled, a PASCAL80
program will be transformed into a sequence of PI-1 instructions
which are executed by the second software component of the PI-1
machine, the PI-1 interpreter. Seen from the basic level of the
PI-1 machine the interpreter is merely a reentrant piece of code
shared by many process incarnations.
\f
In the present manual the interpreter and its instruction set is
not discussed in detail. Suffice it to say that the instruction
set is very similar to, in fact derived from, that of the RC3502,
and that it provides direct support for a number of PASCAL80 lan-
guage constructs, such as e.g. FOR-, LOCK-, and CHANNEL-state-
ments and set types.
2_._1_ _ _ _ _ _ _ _S_e_g_m_e_n_t_s_ 2.1
Physically the memory of the PI-1 machine is the memory of the
Z80 microprocessor on which the PI-1 machine is implemented. Logi-
cally this memory is divided into a number of s_e_g_m_e_n_t_s_. A segment
occupies a contiguous area of memory, i.e. locations with conse-
cutive addresses. A segment may be of any size up to 32 K bytes,
and may begin in any location. A PI-1 PASCAL80 system has four
kinds of segments (in addition to special segments containing
basic system information):
- program segment
A program segment contains the executable code of a process, or
of a separately compiled routine. The contents of a program seg-
ment do not change when a system runs. Thus memory for a program
segment can be allocated in ROM. Normally, however, this is not
the case for compiled program segments (see 3). A compiled
program segment which is not bound to absolute addresses of
variables at the process block level (cf. chapter 4 and the abs
option described in appendix B) is reentrant. A separately com-
piled routine is always reentrant. When a process is reentrant
several incarnations may be created sharing the same process
segment.
\f
- incarnation data segment
Each process incarnation has an incarnation data segment which
contains its data structure consisting of the incarnation stack
plus information needed by PIBS. The latter is not visible to the
incarnation itself, i.e. this information cannot be referred to
in the program text. The stack contains all parameters and va-
riables of the incarnation, dynamically organized in a number of
stack frames corresponding to the nest of routine calls generated
by the execution of the process. Messages are not placed in
incarnation data segments, because they can be passed from one
incarnation to another. The incarnation data segment is dynamic
and is always located in RAM.
- message header segment and data buffer segment
A message header segment is allocated for each message header in
a system, and a data buffer segment for each message data part.
Message header and data buffer segments are always located in
RAM.
Memory allocation for the program segments in a bootstrap image
(see 2) is done by the cross-linker (cf. appendix E). Addi-
tional program segments may be loaded by a running system. Allo-
cation of memory for these program segments and for dynamic
segments is performed dynamically as the segments are needed.
However, the PI-1 machine contains no support for deallocation
and re-use of memory within a system. The memory allocation
strategy is therefore of the simplest possible kind: by in-
creasing addresses.
2_._2_ _ _ _ _ _ _ _T_h_e_ _P_r_i_v_a_t_e_ _M_o_n_i_t_o_r_ 2.2
The private monitor, PRIVMON, is responsible for
- scheduling incarnations and switching contexts,
- handling interrupts,
- message exchange between incarnations via semaphores,
- the delay (time-out) function,
- administering entry to and exit from CHANNEL statements,
- starting incarnations.
\f
PRIVMON may be invoked by a call to one of ten predefined routi-
nes: seven wait routines, signal, start, and interrupt. A call of
the latter routine is normally caused by a hardware interrupt. In
addition PRIVMON is invoked when an incarnation enters or leaves
a CHANNEL statement and when the real time clock ticks.
All PRIVMON code is executed with the Z80 interrupt system dis-
abled; thus PRIVMON is indivisible.
2_._2_._1_ _ _ _ _ _W_a_i_t_ _F_u_n_c_t_i_o_n_s_ 2.2.1
PRIVMON provides possibilities for an incarnation to wait for
three kinds of event:
- an interrupt, i.e. actually a call of the PRIVMON routine
interrupt with a parameter specifying a channel from which the
incarnation is expecting an interrupt (see subsection 2.2.3).
- the arrival of a message via a specified semaphore, cf. the
predefined routines signal and wait of 1.
- the expiry of a delay, specified as a number of delay time
units, implemented by means of the delay clock (timer driver).
The delay time unit is 20 msec.
If an incarnation has been started, and if it is not waiting for
any event, it is able to run on the processor and is said to be
a_c_t_i_v_e_. All active incarnations are members of the active queue
(see below).
An incarnation may wait for any combination of the three kinds of
event, but not on more than one semaphore or on more than one
interrupting device simultaneously. Seven PRIVMON wait routines
are available as predefined routines, corresponding to the seven
different combinations of at least one of the three kinds of
event: waitI, waitS, waitD, waitIS, waitID, waitSD, and waitISD,
where I stands for interrupt, S for semaphore, and D for delay.
\f
If an interrupt, i.e. a call of the PRIVMON routine interrupt,
arrives for an incarnation which is not waiting for the inter-
rupt, it is stored as pending. This is analogous to the situation
where a message is signalled to a semaphore before an incarnation
has called a PRIVMON routine to wait for it. In general, if an
incarnation calls a PRIVMON routine to wait for one or more
events, at least one of which has already occurred the routine
returns immediately to the calling incarnation and it continues
to run.
On the other hand, when an incarnation calls a PRIVMON routine to
wait for a combination of one or more events, none of which has
yet occurred, the incarnation is descheduled, removed from the
active queue and tied up with PRIVMON data structures enabling
PRIVMON to reactivate it when one of the desired events event-
ually occurs. Because of the indivisibility of PRIVMON two events
cannot occur simultaneously.
A multiple wait routine always returns a result of type activa-
tion (cf. section 3.2) specifying the kind of event causing reac-
tivation. In case an incarnation calls a PRIVMON routine to wait
for a combination including an interrupt and a message both of
which have already arrived it will receive only the interrupt.
2_._2_._2_ _ _ _ _ _S_c_h_e_d_u_l_i_n_g_ 2.2.2
The incarnations of a PI-1 PASCAL80 system are at any point in
time divided into two priority classes:
Class I: incarnations executing a CHANNEL statement thus
enabling these incarnations to be activated by inter-
rupts. An incarnation of a process containing one or
more CHANNEL statements is called a d_r_i_v_e_r_.
Class II: other incarnations. These behave as coroutines.
This division is not static. It changes as drivers enter and exit
their CHANNEL statements.
\f
A running incarnation may be descheduled for two kinds of
reasons:
- the incarnation explicitly calls a PRIVMON routine which either
deactivates it (a wait routine) or activates an incarnation
with higher priority (signal, start, interrupt), or the incar-
nation leaves a CHANNEL statement thereby lowering its priority
so that another incarnation has higher priority.
- a hardware interrupt occurs, causing a class I incarnation to
be activated and made running.
The scheduling of class I incarnations depends on the hardware
priorities of the attached devices (daisy chain). Nested inter-
rupts may occur so that one driver interrupts another.
Scheduling of class II incarnations is based on priorities.
PRIVMON maintains the a_c_t_i_v_e_ _q_u_e_u_e_ which is at any point in time
a list (not FIFO queue) of all active incarnations, ordered
according to priority.
The running incarnation is always the first incarnation in the
active queue. The presence of the dummy incarnation ensures that
the active queue is never empty.
Class I incarnations all have a priority higher than that of any
class II incarnation. The active class I incarnations, if any,
will therefore always be at the head of the active queue.
When an incarnation is activated, except when activated by inter-
rupt, it is inserted in the active queue after all incarnations
with the same or higher priority and before incarnations with
lower priority. When an incarnation is activated by interrupt it
is inserted as the first incarnation in the active queue and
immediately becomes running.
Class II incarnations must not disable the interrupt system
(incarnations of compiled PASCAL80 processes cannot do this). A
class II incarnation will never be running if a class I incarna-
tion is active.
\f
2_._2_._3_ _ _ _ _ _C_H_A_N_N_E_L_ _S_t_a_t_e_m_e_n_t_ 2.2.3
Executing a CHANNEL statement enables an incarnation (driver) to
interact with a device by receiving the interrupts generated on a
specific channel, i.e. with a particular value of the interrupt
vector (Z80 interrupt model 2).
The reference variable of the CHANNEL statement 1 must refer-
ence a channel message. This channel message (see reservech, sec-
tion 3.3) contains the value of the channel in question. The PI-1
machine has precisely one channel message for each existing
channel.
When an interrupt on the channel occurs, a hardware generated
call of PRIVMON>s interrupt routine causes the incarnation to be
activated, assuming it is waiting for an interrupt.
It is also possible for an incarnation to call interrupt, thereby
generating a software interrupt to a driver.
When a driver enters a CHANNEL statement its priority is adjusted
so that it executes the CHANNEL statement with a high priority.
When it leaves the CHANNEL statement the priority is adjusted
again to the value with which the driver was started. This may
cause it to be descheduled.
2_._3_ _ _ _ _ _ _ _S_t_a_n_d_a_r_d_ _P_r_o_c_e_s_s_e_s_ 2.3
PIBS includes three standard process incarnations which are part
of all PI-1 PASCAL80 systems:
- the initial incarnation (Adam) survives after initializing a
system as a dummy incarnation with lower priority than any
other incarnation.
- the timer driver is activated by regular hardware timer inter-
rupts and causes the d_e_l_a_y_ _c_l_o_c_k_ to tick every delay time unit
(see subsection 2.2.1).
\f
The timer driver is a child of Adam. In addition every system
must include an incarnation of an assembly coded process Eve,
whose program segment is located in the bootstrap image (see
2). Eve is started by Adam as the final action during system
initialization. Eve is the root of the remaining part of the
system.
\f
F_ 3_._ _ _ _ _ _ _ _ _P_A_S_C_A_L_8_0_ _O_N_ _T_H_E_ _P_I_-_1_ _M_A_C_H_I_N_E_ 3.
This chapter together with the PASCAL80 report 1 contains the
precise definition of the programming language PASCAL80 as im-
plemented on the PI-1 machine.
3_._1_ _ _ _ _ _ _ _I_m_p_l_e_m_e_n_t_a_t_i_o_n_ _D_e_t_a_i_l_s_ _a_n_d_ _L_a_n_g_u_a_g_e_ _M_o_d_i_f_i_c_a_t_i_o_n_s_ 3.1
The PASCAL80 report leaves open a number of small parts of the
language. A description of how these parts have been implemented
is given in this section. Included is also information about a
number of aspects of PI-1 PASCAL80 where the implementation de-
viates from what the report prescribes. No indication is given
of which parts of the description are supplementary to the report
and which are alternative. As a rule information which is given
in connection with a predefined routine (section 3.3) is not
found in this section.
The page numbers given in each of the headings below refer to
1.
3_._1_._1_ _ _ _ _ _P_a_r_a_m_e_t_e_r_i_z_e_d_ _T_y_p_e_s_ (p. 9, 10, 36, 41, 42, 50, 51, 52) 3.1.1
Parameterized types are not implemented. In particular the type
string(n) is not defined.
3_._1_._2_ _ _ _ _ _R_e_a_l_s_ (p. 10, 19, 63) 3.1.2
The type real is not implemented. Numeric values can only be
integral, i.e. no decimals or exponents are allowed.
\f
3_._1_._3_ _ _ _ _ _R_a_d_i_x_ (p. 18) 3.1.3
Binary, octal, and hexadecimal numbers are indicated by the pre-
fixes #b, #o, and #h. In hexadecimal numbers the digits a..f may
be used.
3_._1_._4_ _ _ _ _ _B_o_u_n_d_s_ _o_f_ _S_u_b_r_a_n_g_e_ _T_y_p_e_s_ (p. 19) 3.1.4
The bounds min bound and max bound of a subrange type definition
must be given by constant expressions.
3_._1_._5_ _ _ _ _ _M_e_s_s_a_g_e_ _H_e_a_d_e_r_ (p. 21) 3.1.5
The following fields of a message header are accessible:
size: !integer; (* size in bytes of message data *)
kind: !message _kind; (* see section 3.2 *)
u1, u2, u3, u4: byte; (* not present in channel message *)
3_._1_._6_ _ _ _ _ _L_O_C_K_ _a_n_d_ _C_H_A_N_N_E_L_ _S_t_a_t_e_m_e_n_t_s_ (pp. 26-27) 3.1.6
The report specifies certain restrictions on the use of the ref-
erence variable of a LOCK or CHANNEL statement. These restric-
tions are not enforced by PI-1 PASCAL80. However, the reference
variable of a LOCK statement is treated as follows:
- before the statement (after DO) is executed the reference vari-
able is exchanged with an anonymous reference variable and
thereby becomes NIL,
- after the statement the reference variable is again exchanged
with the anonymous variable. If the anonymous reference does
not hereby become NIL an exception occurs.
The substance of the implementation of the CHANNEL statement is
explained in subsection 2.2.3.
\f
3_._1_._7_ _ _ _ _ _P_o_o_l_ _I_n_i_t_i_a_l_i_z_a_t_i_o_n_ (p. 45) 3.1.7
The allocation of memory for messages for a pool variable is per-
formed during the initialization of an incarnation a_f_t_e_r_ it has
been started and scheduled to run. One effect of this is that an
incarnation may in unfortunate cases be successfully created and
yet unable to run due to lack of memory.
3_._1_._8_ _ _ _ _ _P_r_o_c_e_s_s_ _P_a_r_a_m_e_t_e_r_s_ (p. 51) 3.1.8
Process parameters of reference, pool, or shadow types are not
allowed, neither as variables, values, or components of struc-
tured parameters. Pointers may be passed only as values or frozen
variables. Semaphores may be passed as variables, but not as
values. Otherwise, the restrictions mentioned in 1 are not
enforced.
3_._1_._9_ _ _ _ _ _I_n_c_a_r_n_a_t_i_o_n_ _T_e_r_m_i_n_a_t_i_o_n_ (p. 56) 3.1.9
When an incarnation is terminated (by completing its compound
statement) it is permanently descheduled and will not become
running again. However, no garbage collection is performed.
3_._1_._1_0_ _ _ _ _R_o_u_t_i_n_e_ _E_x_i_t_ (p. 57) 3.1.10
The rule stated in 1, that all local reference and shadow vari-
ables must be NIL at exit from a routine block, is not enforced.
3_._1_._1_1_ _ _ _ _E_x_c_e_p_t_i_o_n_ _H_a_n_d_l_i_n_g_ 3.1.11
When an exception occurs the exception routine of the PI-1 ma-
chine is called. It is described in section 3.3. The exception
routine may also be called explicitly.
If a routine with name exception is declared in a program, the
usual scope rules will apply, but the handling of exceptions is
not affected.
\f
3_._1_._1_2_ _ _ _ _P_r_e_f_i_x_ (p. 60) 3.1.12
Prefixes as described in 1 have not been implemented. See the
description of contexts in appendix B for a somewhat similar
mechanism.
A routine may be compiled separately by using the syntax
-'PREFIX -'prefix name -'; -'routine declaration -'
3_._1_._1_3_ _ _ _ _C_h_a_r_a_c_t_e_r_ _S_t_r_i_n_g_ (p. 64) 3.1.13
The type of a one-dimensional array of char is called a string
type. A character string is a value whose type is compatible with
any string type. Thus character strings may be assigned to and
compared with variables of string types, and used as actual para-
meters for formal parameters of string types. Whenever appropri-
ate a character string is truncated to the required number of
characters or extended with spaces.
The predefined type alfa which is used to specify external names
of processes is an example of a string type whose values may be
written as character strings.
3_._1_._1_4_ _ _ _ _P_r_o_g_r_a_m_ (p. 60) 3.1.14
Each compilation of a PASCAL80 program, i.e. a process or a pre-
fix yields an object module 2. The object module name is the
process or prefix name.
3_._2_ _ _ _ _ _ _ _P_r_e_d_e_f_i_n_e_d_ _T_y_p_e_s_ 3.2
The following types are predefined in PI-1 PASCAL80 in addition
to those described in 1.
bit = 0..1;
byte = 0..255;
\f
activation = (a _interrupt, a _semaphore, a _delay);
The type activation is used for results from multiple wait func-
tions to indicate the reason why an incarnation is activated (or
continues to run).
message _kind = (datamsg, channelmsg);
The type message _kind is used in the kind field of a message
header to indicate whether a message is a data message or a
channel message.
alfa = ARRAY(1..12) OF char;
The type alfa is used to specify external process names (see link
in the next section).
3_._3_ _ _ _ _ _ _ _P_r_e_d_e_f_i_n_e_d_ _R_o_u_t_i_n_e_s_ 3.3
The predefined routines supported by PI-1 PASCAL80 are divided
into three groups:
- the s_h_a_l_l_o_w_ routines which are executed without involving PIBS;
these routines are all functions and they may be considered as
operators on their parameter types.
- the d_e_e_p_ routines which involve calls to PIBS, most often to
PRIVMON.
- the i_/_o_ _a_n_d_ _C_P_U_ _c_o_n_t_r_o_l_ routines.
3_._3_._1_ _ _ _ _ _S_h_a_l_l_o_w_ _R_o_u_t_i_n_e_s_ 3.3.1
The following shallow routines are implemented in accordance with
their definition in 1: abs, chr, empty, locked, nil, open, ord,
passive, pred, ref, and succ.
\f
Two shallow routines have been added:
FUNCTION openpool(VAR p: POOL 1): boolean;
A call of openpool returns the value TRUE if the pool is not
empty, FALSE otherwise.
FUNCTION ownertest (VAR p: POOL 1; VAR r: reference): boolean;
A call of ownertest returns the value TRUE if the message
accessed by r has been allocated from p, FALSE otherwise. If r is
NIL an exception occurs.
3_._3_._2_ _ _ _ _ _D_e_e_p_ _R_o_u_t_i_n_e_s_ 3.3.2
All deep routines available in PI-1 PASCAL80 are listed below.
Only those which differ from the definition in 1 are described
in detail.
PROCEDURE alloc(VAR r: reference; VAR p: POOL 1; VAR s: semaphore);
See 1.
PROCEDURE break(VAR sh: shadow; excode: integer);
A call of break causes an exception to occur in the child
(shadow), i.e. the exception routine is called f_r_o_m_ the child.
FUNCTION create(process name (actual parameters);
VAR sh: shadow; size: integer): integer;
See 1. When create is called the shadow variable must be NIL,
and the process name must either be internal, or an external name
must have been linked to it (by link, see below), otherwise an
exception occurs. The size parameter specifies the size in bytes
of the incarnation stack in the data segment allocated for the
incarnation which is created. If a process has not been linked to
the process name it is searched for among the processes which
have been loaded into the memory of the PI-1 machine, and if
found, it is linked to the process name. If not found, the linker
is invoked to search for the process in the object program cata-\f
log (cf. 2). If the process is found in the catalog it is
loaded and linked to the process name, otherwise create fails.
When a program is searched for, both the external name and the
parameter description must match.
The result of create is:
0 - if an incarnation is successfully created,
1 - if the process has not been found,
2 - if sufficient memory cannot be allocated.
PROCEDURE exception (excode: integer);
A call of the exception procedure, which may be caused by the
occurrence of an exception, causes diagnostic information to be
output on a suitable device, if one is present. A stack trace of
the calling incarnation is included. Subsequently the PI-1
machine stops executing the PASCAL80 system.
PROCEDURE interrupt(channel: integer);
A call of interrupt generates a software interrupt to the incar-
nation which is executing a CHANNEL statement with a channel
message containing a channel value equal to the parameter, cf.
subsection 2.2.3. If no such incarnation exists the call has no
effect.
PROCEDURE link(external _name: alfa; process name);
See 1. Note that only the external name, not the actual process
is linked to the process.
PROCEDURE pop(VAR r1, r2: reference);
See 1.
PROCEDURE push(VAR r1, r2: reference);
See 1.
PROCEDURE release(VAR r: reference);
If the parameter is NIL a call of release causes an exception,
otherwise the effect is dependent on the kind of message referred
to by r. If the message is of kind datamsg it is released to its
owner pool, i.e. made available for allocation by a call of\f
alloc. If the message is of kind channelmsg the channel ident-
ified by the message is released, i.e. it becomes free for reser-
vation by a call to reservech. In both cases r is NIL on return
from release.
FUNCTION remdelay : byte;
This function may be called after returning from a multiple wait
function which includes waiting for a delay. The result returned
is the number of time units which remained of the delay when the
incarnation was activated.
PROCEDURE remove(VAR sh : shadow);
The procedure remove is not available in PI-1 PASCAL80.
PROCEDURE reservech(VAR r: reference; channel: integer);
When reservech is called r must be NIL, otherwise an exception
occurs. If the specified channel is free before the call, it is
reserved, and on return r will refer to its channel message. If
the channel is not free the call has no effect, i.e. r is NIL on
return.
PROCEDURE return(VAR r: reference);
See 1.
PROCEDURE sensesem(VAR r: reference; VAR s: semaphore);
If the semaphore s is open, the call sensesem(r,s) is equivalent
to waits(r,s), otherwise the call has no effect.
PROCEDURE signal(VAR r: reference; VAR s: semaphore);
See 1.
PROCEDURE start(VAR sh: shadow; priority: 1..254);
See 1. Notice that the parameter priority is not of type in-
teger as in 1. The priority of the created incarnation with
respect to scheduling is higher, the smaller the value of the
priority parameter.
PROCEDURE stop(VAR sh: shadow);
The procedure stop is not available in PI-1 PASCAL80.
\f
PROCEDURE wait(VAR r: reference; VAR s: semaphore);
Equivalent to waits; see subsection 2.2.1.
PROCEDURE waitd(delay: byte);
See subsection 2.2.1.
PROCEDURE waiti;
See subsection 2.2.1.
FUNCTION waitid(delay: byte): activation;
See subsection 2.2.1.
FUNCTION waitis(VAR r: reference; VAR s: semaphore): activation;
See subsection 2.2.1.
FUNCTION waitisd(VAR r: reference; VAR s: semaphore;
delay: byte); activation;
See subsection 2.2.1.
PROCEDURE waits(VAR r: reference; VAR s: semaphore);
See subsection 2.2.1.
FUNCTION waitsd(VAR r: reference; VAR s: semaphore;
delay: byte): activation;
See subsection 2.2.1.
PROCEDURE unlink(process name);
The procedure unlink is not available in PI-1 PASCAL80.
3_._3_._3_ _ _ _ _ _I_/_O_ _a_n_d_ _C_P_U_ _C_o_n_t_r_o_l_ _R_o_u_t_i_n_e_s_ 3.3.3
The routines described below are available to perform i/o and CPU
control control instructions of the Z80 microprocessor on which
the PI-1 machine is based.
FUNCTION inbyte(inport: byte): byte;
A call of inbyte yields as result a byte read from the input port
specified by the parameter (one Z80 IN instruction).
\f
PROCEDURE inbyteblock(VAR r: reference; first, last: byte;
inport: byte);
This procedure is equivalent to the following:
LOCK r AS buf: ARRAY(0..max) OF byte DO
FOR i:=first TO last DO buf(i):=inbyte(inport);
where max is sufficiently large and i is a byte. The procedure is
executed by means of the Z80 INIR (block input) instruction.
PROCEDURE outbyte(outport, data: byte);
A call of outbyte causes the byte data to be output on the output
port specified by outport (one Z80 OUT instruction).
PROCEDURE outbyteblock(VAR r: reference; first, last: byte;
outport: byte);
This procedure is equivalent to the following:
LOCK r AS buf: ARRAY(0..max) OF byte DO
FOR i:=first TO last DO outbyte(outport,buf(i));
where max is sufficiently large and i is a byte. The procedure is
executed by means of the Z80 OTIR (block output) instruction.
PROCEDURE zenable;
A call of zenable causes the Z80 EI instruction to be executed,
i.e. the interrupt system of the CPU is enabled.
PROCEDURE zreti;
A call of zreti causes the Z80 RETI instruction to be executed,
notifying a peripheral device on the daisy chain that interrupt
service is completed.
\f
4_._ _ _ _ _ _ _ _ _L_I_N_K_I_N_G_ _Z_8_0_ _A_S_S_E_M_B_L_Y_ _P_R_O_G_R_A_M_S_ _I_N_T_O_ _P_A_S_C_A_L_8_0_ _P_R_O_G_R_A_M_S_ 4.
Inclusion of Z80 assembly code into a compiled PASCAL80 program
may be necessary for one of two reasons:
- the need to optimize a time-critical part of the program, or
- the need to use special facilities at the basic level of the
PI-1 machine which are not available at the interpreted
PASCAL80 level, particularly in connection with treatment of
interrupts in drivers.
The procedure for inclusion of an assembly language program in a
compiled PASCAL80 program is as follows:
The program is written in the Z80 assembly language described in
4 and assembled on the Tektronix 8002 microprocessor develop-
ment system 5. Information about how the assembly language pro-
gram interfaces to PIBS and the PI-1 interpreter, and about the
facilities available at the basic level of the PI-1 machine is
found in 2.
The object program produced by the Tektronix assembler is then
transferred to a P_I_-_1_ _l_i_b_r_a_r_y_ on the RC8000 where the compiler
runs. In the PI-1 library the assembler object program is stored
together with a PASCAL80 procedure description, i.e. a name and a
parameter description. The transfer of the assembler object pro-
gram and the specification of the procedure description is done
by means of utility programs which are described in appendices D
and F.
The PI-1 compiler will include an assembler object program from
a PI-1 library specified using the lib option (see appendix B)
into a compiled program if an external procedure declaration
compatible with the procedure description in the library and at
least one call of the declared procedure occurs in the program.
\f
For each call occurring in the PASCAL80 program of a procedure
which has been included from the PI-1 library as described above
the compiler generates code to evaluate the parameters and push
them on the stack of the incarnation executing the call and sub-
sequently transfer control to the entry point of the assembly
language program. Information about the representation of par-
ameters on an incarnation stack is found in chapter 5.
When a program is written in assembly language to replace a
time-critical part of a PASCAL80 program it is necessary, or at
least useful, to be able to access not only the parameters
specified in the external procedure declaration, but also the
variables of the process incarnation in which the assembly
program is executed. For this reason the compiler supports
linking of values exported from a PASCAL80 program to symbols
declared as unbound globals in the assembly language program.
The values to be exported from a PASCAL80 program are defined in
export parts occurring in the declarations of one or more blocks
within the program. The syntax and semantics of an export part
are described below:
export part:
-' EXPORT-'-'export name -' = -'export kind -' simple variable -'
;
Each repetition of the loop yields one e_x_p_o_r_t_ _v_a_l_u_e_ which is
associated with the export name, i.e. the same name must appear
as an unbound global symbol in the assembly language program.
Only the first eight characters of an export name are signifi-
cant.
export kind:
VALUE
DISP
SIZE
ADDRESS
OFFSET
\f
simple variable:
-' simple var name -' -' -'
field name <-.<-
Simple var name can be either a constant name or a variable name.
If it is a constant name, or if the variable is of a packed
record type, field name indexing is not allowed. It follows that
simple variable is either a constant, a variable, or a field of a
record variable which is not packed.
The export value must always be representable in a word (16 bits)
or a byte (8 bits), cf. chapter 5. The export kind determines how
the export value is calculated:
VALUE The simple variable must be a constant. The export
value is the value of the constant.
DISP The simple variable must be a field of a record. The
export value is the displacement of the field relative
to the start of the record.
SIZE The export value is the size in bytes of the type of
the simple variable.
ADDRESS The simple variable must be a variable or a field of a
variable record declared at the process block level of
a separately compiled process. The export value is the
address of the simple variable, and when the object
program resulting from the compilation is loaded and
linked on the PI-1 machine it is relocated as the
absolute Z80 address of the simple variable. Thus the
corresponding global symbol in the assembly language
program may be used directly as a variable address.
Notice that a program which contains exported values of
kind ADDRESS will not be reentrant (see also the abs
option in appendix B).
\f
OFFSET The simple variable must be a variable or field of a
record variable. The export value is the offset of the
simple variable within its local stack frame.
\f
F_ 5_._ _ _ _ _ _ _ _ _R_E_P_R_E_S_E_N_T_A_T_I_O_N_ _A_N_D_ _L_A_Y_O_U_T_ _O_F_ _V_A_R_I_A_B_L_E_S_ 5.
In this chapter it is explained how values of the various types
of PASCAL80 are represented in the PI-1 implementation and how
memory is allocated and laid out to hold the values of the vari-
ables of a process incarnation.
5_._1_ _ _ _ _ _ _ _R_e_p_r_e_s_e_n_t_a_t_i_o_n_ _o_f_ _V_a_l_u_e_s_ 5.1
5_._1_._1_ _ _ _ _ _E_n_u_m_e_r_a_t_i_o_n_ _T_y_p_e_s_ 5.1.1
An enumeration type is defined as consisting of a finite, totally
ordered set of values, corresponding to a set of ordinal values
which is a subset of the integral numbers. The representation of
a value of an enumeration type is the two>s complement represen-
tation of the corresponding ordinal value. If a type includes
negative ordinal values the representation of values of the type
is always in 16 bits (a word). If the type includes only non-
negative ordinal values, and n is the largest of these then the
M_m_m_ representation is in log (n+1) bits (at most 16). Examples:
2
P_p_p_ - integer values (-32768..32767) are represented in 16 bits,
- boolean values (false, true) are represented in 1 bit,
- char values (see 1) are represented in 7 bits,
- values of the subrange type -3..7 are represented in 16 bits,
- values of the scalar type (red, green, blue, orange, pink) are
represented in 3 bits.
5_._1_._2_ _ _ _ _ _S_h_i_e_l_d_e_d_ _a_n_d_ _P_o_i_n_t_e_r_ _T_y_p_e_s_ 5.1.2
The representation of values of shielded and pointer types is not
revealed.
\f
5_._1_._3_ _ _ _ _ _S_t_r_u_c_t_u_r_e_d_ _T_y_p_e_s_ 5.1.3
Values of array or record types are vectors of values of enumer-
ation, shielded, pointer, and set types. The component values are
represented as described for the component types.
The representation of values of a set type uses a bit vector
whose length depends on the base type. The base type must be an
enumeration type which does not include negative ordinal values.
If the ordinal value set of the enumeration type T is the range
m..n (m '_ 0) then values of the type set of T are represented in
a bit vector with indices from 0 to n. The first m (possibly
zero) of these bits are not significant. If the element of T
whose ordinal value is i (m <_ i <_ n) is a member of a particular
value of type set of T then bit i in the representation of that
value is 1, otherwise it is 0. Example:
TYPE
a=set of 3..5;
VAR
b: a:=(.3,5.);
The value of b is represented as shown:
bit 0 1 2 3 4 5
1 0 1 The shaded bits are not significant.
5_._1_._4_ _ _ _ _ _T_y_p_e_ _S_i_z_e_ 5.1.4
The size of a type T, denoted S(T), is the number of bits used to
represent values of type T. The concept of size is only relevant
for types which are affected by packing when used for components
of structured types, and is therefore not defined for all types.
For enumeration types S(T) is computed as described above.
Examples: S(char)=7, S(integer)=16.
\f
5_._2_ _ _ _ _ _ _ _M_e_m_o_r_y_ _L_a_y_o_u_t_ 5.2
The memory requirement of a type T, denoted M(T), is defined as
the number of bytes which are allocated for a variable of type T.
For an enumeration type T, M(T) depends on S(T), as follows:
1 <_ S(T) <_ 8: M(T)=1
9 <_ S(T) <_ 16: M(T)=2
For shielded and pointer types, M(T) is the following:
M(reference)= 2
M(semaphore)= 3
M(shadow) = 2
M(pointer) = 2
M(pool) = 3
Memory requirement for structured types is described in connec-
tion with memory layout for these types in subsections 5.2.3 and
5.2.4.
5_._2_._1_ _ _ _ _ _A_d_r_e_s_s_i_n_g_ 5.2.1
The memory of the PI-1 machine consists of a sequence of eight
bit bytes. Each byte has an address. Two consecutive bytes may be
used as a sixteen bit word.
In Intel fashion a word consists of high byte (most significant
halfword) and low byte (least significant halfword). The low byte
is always the byte with the l_o_w_e_s_t_ address.
An integral number of bytes is allocated for each variable. The
address of a variable is the smallest of the addresses of the
bytes allocated for the variable.
\f
5_._2_._2_ _ _ _ _ _S_t_a_c_k_ _F_r_a_m_e_ 5.2.2
Memory for variables declared in process or routine blocks is
allocated in s_t_a_c_k_ _f_r_a_m_e_s_ in the data segment of the incarnation
to which the variables belong. The general layout of an incarna-
tion stack is shown in fig. 1.
In the portion of a stack frame used for declared variables
memory is allocated from high to low addresses in the order of
declaration of the variables in the program text.
The two bytes allocated for a variable of an enumeration type T
with M(T)=2 are treated as a word, i.e. the most significant
halfword has the highest byte address. A variable of an enumer-
ation type is always right justified, i.e. placed in the least
significant bits of the allocated byte or word.
Example: Corresponding to the declarations:
VAR
a: reference;
b: char;
c,d: 0..7;
e: integer;
memory is allocated within a stack frame as illustrated in fig.
2.
address MSB LSB
7 6 5 4 3 2 1 0
M_m_m_ s-6
e
P_p_p_ s-5
s-4 d the shaded areas are unused
s-3 c
s-2 b
M_m_m_ s-1
a
P_p_p_ s
Figure 2: Memory layout for simple declared variables in stack
frame.
\f
F_
Figure 1: Incarnation stack layout (snapshot).
\f
F_ The layout of actual parameters is similar to that of declared
variables, with a minor modification: since the smallest unit of
memory pushed on the evaluation stack is a word, each actual
parameter of a process or routine stack frame occupies an
integral number of words. Similarly to the case of declared
variables, an actual parameter of an enumeration type of size
less than 16 (bits) is placed in the least significant bits of
the allocated word.
5_._2_._3_ _ _ _ _ _S_t_r_u_c_t_u_r_e_d_ _T_y_p_e_s_ 5.2.3
The memory requirement of a structured type is determined by the
memory requirements of the component type(s). However, the memory
requirement of a packed record or array is always at least two
(bytes).
The memory allocated for a variable of a structured type is sub-
allocated for the components of the variable in a fashion which
depends on whether the type is declared as packed or not.
For an array, memory is allocated from low to high addresses for
the elements in index order, and for a record, memory is allo-
cated from low to high addresses for the fields in the order they
are declared in the record type definition.
5_._2_._3_._1_ _ _ _A_r_r_a_y_s_ _a_n_d_ _R_e_c_o_r_d_s_,_ _N_o_t_ _P_a_c_k_e_d_ 5.2.3.1
For an array or record type which is not packed, memory allocation
for the components takes place in a fashion similar to the allo-
cation of memory for declared variables in a stack frame, except
that increasing address order is used, i.e:
- from low to high addresses,
- an integral number of bytes per component,
- right justification of each enumeration type component
within the allocated byte or word.
\f
Example: With the record type definition below. Fig. 3 shows the
layout of a variable of type r.
TYPE
r=RECORD
a: reference;
b: char;
c,d: 0..7;
e: integer
END;
address 7 6 5 4 3 2 1 0
M_m_m_ s
a
P_p_p_ s+1
s+2 b
s+3 c
s+4 d
M_m_m_ s+5
e
P_p_p_ s+6
Figure 3: Memory layout for record type (not packed).
By summation (or multiplication) the memory requirement of an
array or record type may be determined from the above rules for
sub-allocation of memory for components. For the record type in
the example M(r)=7.
5_._2_._3_._2_ _ _ _P_a_c_k_e_d_ _A_r_r_a_y_s_ _a_n_d_ _R_e_c_o_r_d_s_ 5.2.3.2
When memory is laid out for a packed array or record type compo-
nents of types with size less than 16 (bits) (for arrays: 6 bits)
are packed, if possible. Packing always takes place in a word,
from most to least significant bit, and each component is allo-
cated as many bits as indicated by its size. By this rule unused
space may be left in the least significant bits of a word in
which one or more components are packed.
\f
Notice that in the current implementation only components of
enumeration types are candidates for packing.
Example: The layout of variables of the following packed record
type is shown in fig. 8.
TYPE
q=PACKED RECORD
a: reference;
b: char;
c,d: 0..7;
e: integer
END;
MSB LSB
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
s a
s+2 b c d
s+4 e
Figure 4: Memory layout for record. M(q)=6.
5_._2_._3_._3_ _ _ _S_e_t_ _T_y_p_e_s_ 5.2.3.3
The memory requirement of a set type is always an even number (of
bytes), i.e. an integral number of words is allocated for each
variable of a set type. The number of words used is the smallest
number which will accomodate the bit vector used to represent
values of the set type, cf. subsection 5.1.3. The bit vector is
laid out with index 0 in the most significant bit of the first
word. The last word may contain an unused portion in its least
significant bit positions. Example: see fig. 5.
\f
address 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
s
s+2
s+4
s+6
Figure 5: Layout of a variable of the type set of 0..50;
13 bits are unused. The memory requirement of the type
is 8.
\f
F_\f
F_ A_._ _ _ _ _ _ _ _ _R_E_F_E_R_E_N_C_E_S_ A.
1 RCSL No 52-AA964:
PASCAL80 Report
2 RCSL No 31-D615:
The PI-1 Machine, Reference Manual
3 System User>s Package for
Tektronix 8002A microprocessor development system
4 Z80-Assembly Language Programming Manual,
Zilog, inc.
5 Z80 Assembler and Emulator User>s Manual for
Tektronix 8002A microprocessor development system
\f
F_ B_._ _ _ _ _ _ _ _ _H_O_W_ _T_O_ _U_S_E_ _T_H_E_ _P_A_S_C_A_L_Z_8_0_ _C_O_M_P_I_L_E_R_ B.
B_._1_ _ _ _ _ _ _ _C_a_l_l_ _o_f_ _t_h_e_ _C_o_m_p_i_l_e_r_ B.1
M_m_m_ 1 <s'<options' 1
<bin file'= pascalz80 <s'<source'
0 <s'<context' 0
P_p_p_ 0
list. <yes or no'
stop. <pass no'
<options'::= lib. <lib file'
abs. <yes or no'
index. <yes or no'
M_m_m_ yes
<yes or no'::=
P_p_p_ no
<pass no'::= 1 3 4 5 6
<bin file' is a file descriptor describing the backing
storage area where the object module ends. If
omitted, "pass6code" is assumed.
<context' is a text file containing declarations of types,
constants, and external routines. The syntax is
described in appendix B.2.
<source' is a text file defining a process or a prefix. If
no source is specified, the compiler reads the
source from current input.
list list.yes turns on listing of input on current
output. List.no turns listing off.
\f
stop stop.<pass no' terminates the translation after
the specified pass. The passes perform
1: syntax analysis
3: machine independent semantic analysis
4: storage allocation and machine dependent
semantic analysis
5: code selection
6: code assembly
lib.<lib file' specifies a user defined PI-1 library containing
Z80 assembler routines (see chapter 4 and
appendices D and F).
<lib.file' must be a file descriptor describing
the library.
If the same routine is in the user library and in
the system library, the routine from the user
library is included.
index if index.yes is specified test on values assigned
to subrange variables and test on index in arrays
is included in the object program. If index.no is
specified no test is included.
abs if abs.yes is specified variables declared at the
outermost process block level are addressed by
absolute Z80 addresses; i.e. the program will n_o_t_
be reentrant. Variables declared at inner block
levels and in internal processes are always
addressed specified relative to local stack
frame. If abs.no is all variables are addressed
relative to a stack frame, and the program will
be reentrant.
d_e_f_a_u_l_t_ _v_a_l_u_e_s_
the call: pascalz80 inputfile
is equivalent to:
poss6code = pascalz80 list.no stop.6 abs.no index.yes inputfile
\f
B_._2_ _ _ _ _ _ _ _C_o_n_t_e_x_t_s_ B.2
The context facility allows several input files to be specified
for one compilation. This may be used for inclusion of (common)
contexts (environments), i.e. constant and type definitions and
declaration of external routines. The syntax is:
context:
context name ; context declarations .
context declarations:
P_ constant declaration
type declaration
M_ external declaration
external routine declaration:
P_ procedure heading ; external
M_ function heading
\f
F_ C_._ _ _ _ _ _ _ _ _P_A_S_C_A_L_Z_8_0_ _E_R_R_O_R_ _M_E_S_S_A_G_E_S_ C.
C_._1_ _ _ _ _ _ _ _M_e_s_s_a_g_e_s_ _f_r_o_m_ _P_a_s_s_ _1_ C.1
0 Illegal character or fatal error
1 Context expected
2 Idenfier expected
3 >;> expected
4 Identifier expected
5 >,> or >:> expected
6 Error in declaration
7 Set element or >.)> expected
8 Constant, variable, or >(<expression')> expected
9 Expression expected
10 Actual parameter expected
11 Expression expected
12 >of> expected
13 >(> expected
14 Identifier or >?> expected
15 >)> expected
16 Only >array>, >record>, and >set> can be packed structure
17 >..> expected
18 >)> or >,> expected
19 >)> or >,> expected in array declaration
20 >end> or >;> expected
21 >,> or >.)> expected
22 >;> or >)> expected
23 >:> expected
24 Unsigned integer expected
25 >:> expected
26 >begin> expected
27 Error in for-variable specification
28 >to> or >downto> expected
29 >of> expected
30 Error in channel-variable specification
31 >do> or >,> expected
32 >do> expected
33 >then> expected
34 Label expected (name or integer) \f
35 >,> or >:> expected
36 >else> expected
37 >;>, >end> or >otherwise> expected
38 >until> expected
39 Label definition expected (integer or name)
40 Error in label list (>,> or >;> expected)
41 >=> expected
42 Environment specification expected
43 >process> or >include> expected
44 >.> expected
45 >process> or >prefix> expected
46 Only procedure or function declaration allowed in a prefix
47 End of process expected
100 Error in real constant: digit expected
101 String did not terminate within line
102 Line too long, more than 150 characters
The following messages indicating fatal errors may appear from
pass1 of the PASCAL80 compiler. The message will be preceded by
the line just being parsed with an indication of error number 0
discovered.
E.g.
917 21 if prod = 1305 then
0
*** const >chbufmax> too small
In case no other errors are discovered a fatal error may indicate
that one or more of the compiler tables are insufficient in size.
But most often this kind of fatal errors appear in consequence of
syntactical errors, and after correction of the marked errors the
fatal error may disappear.
\f
The messages are:
***parse stack overflow.const >stackmax> too small
Parsing of a too small syntactical construction.
***end of file encountered
Input exhausted before the process/prefix has been satisfied.
***recovery abandoned
The error recovery was unsuccessful.
***reduction buffer overflow.const >redumax> too small
Parsing of a too complicated syntactical construction.
***const >stringmax> too small
Literal text string too long.
***const >chbufmax> too small
Parsing of a too complicated syntactical construction.
***const >maxnamenodeindex> too small
Too many very long names.
***const >maxnameheads> too small
Too many different names.
***const >typebuffersize> too small
Too complicated type definition.
\f
C_._2_ _ _ _ _ _ _ _M_e_s_s_a_g_e_s_ _f_r_o_m_ _P_a_s_s_ _3_ C.2
Error messages from pass 3 have the format:
***pass 3 line <lineno', <operand no' <text'
where:
<lineno' is the line number where the error is detected
<operand no' gives a hint of where in the line the error was.
Operands are: identifiers and numbers (Note: the empty set
does not count).
First operand in a line has number 1. (Note: if <operand no'
is 0, the error occurred before the first operand in the
line, maybe even in the last part of the previous line).
undeclared,
(*identifier not declared*)
inconsistent _use,
(*identifier used before declaration*)
double _declaration,
(*identifier already declared at this level*)
label _not _declared,
(*label-identification not declared at all*)
not _label _name,
(*other identifier used as label-name*)
multiple _defined _label,
(*label defined several times at this level*)
label _not _locally _declared,
(*label-identifier declared at surrounding level*)
\f
erroneous _label,
(*use of a multiple defined label*)
label _used _from _inner,
(*a label-ident has been used in inner routine*)
label _used _outside _scope,
(*goto leading into control-structure*)
label _defined _outside _lock _or _channel,
(*goto out of lock- or channel statements*)
not _typename,
(*identifier is not a type-identifier*)
recursive _use _of _type,
(*error in record or array etc.*)
recursive _constant _use,
(*constant is used in its own definition-expression*)
illegal _pool _type,
(*pool ... of <illegal type'*)
pool _cardinality _must _be _integer,
(*illegal size>ing of pool type*)
subrange _elems _must _be _enumeration,
(*illegal limit-types in subrange def*)
type _may _only _be _used _at _process _level,
(*nb: semaphore, pool*)
process _only _allowed _at _processlevel,
(*processes inside functions/procedures forbidden*)
external _only _at _processlevel,
(*restriction on >external>*)
\f
illegal _formal _type,
(*formal type may not be used in this context*)
illegal _function _type,
(*functiontype may not contain: semaphore etc.*)
paramlist _changed _since _forwarddecl,
(*>new> paramlist may be empty or exact the same*)
forward _not _solved,
(*forward-declared routine not followed with the real body*)
funcval _not _used,
(*function-value has not been defined at all*)
type _has _pointers,
(*locktype contains pointer-types*)
type _has _systemtypes,
(*locktype contains semaphore, reference, shadow, pool*)
operands _incompatible,
(*operands not of same typename*)
for _incompatible,
(*for-variable/startvalue/endvalue not of compatible types*)
case _incompatible,
(*case-expression/caselabels not of compatible types*)
if _type,
(*if-expression must be boolean type*)
repeat _type,
(*until-expression must be boolean type*)
while _type,
(*while-expression must be boolean type*)
\f
with _type,
(*with-variable must be a record*)
lock _type,
(*lock-variable must be reference type*)
channel _type,
(*channel-variable must be reference type*)
not _index _type,
(*type of operand must be enumeration-type*)
not _variable,
(*operand cannot be used as variable*)
field _must _follow _recordtype,
(*<variable' in front of <.' is not a record*)
name _not _fieldname,
(*<name' after <.' is not a fieldname of <variable'*)
must _be _pointertype _before _uparrow,
(*<variable' in front of <uparrow' is not a pointer*)
mixed _type _in _setlist,
(*elements in set-value may not be mixed*)
relation _error,
(*illegal mixture of types in relation*)
arithmetic _error,
(*illegal mixture of types in term of factor*)
monadic _error,
(*illegal type for monadic operator*)
real _not _implemented,
(*real occuring in expression*)
\f
real _expression _not _implemented,
(*real-division of integers not impl*)
illegal _in _expr,
(*illegal operand kind in expression*)
too _few _parameters,
(*too few actual parameters to routinecall (or strucrecord*)
too _many _actual _params,
(*errors in routinecall*)
too _many _values _in _record _structure,
(*error in structured-record constant*)
type _must _be _record _or _array,
(*typename in front of arglist must be ...*)
double _param _only _in _struc _const,
(*the >***> operator must only occur in structured-array constant*)
subscript _after _nonarray,
(*name in front of arglist is not of array-type*)
incompatible _index,
(*index-expression does not match array-declaration*)
assign _incompatible,
(*incompatible types in assignment*)
exchange _incompatible,
(*incompatible types in exchange*)
not _procedure _call,
(*the statement is not a procedure-call*)
variable _may _not _be _packed,
(*for-variable or actual var-param is packed*)
\f
not _assignable,
(*operand may not be assigned: sem, pool, ref, shadow, frozen*)
not _exchangeable,
(*operand may not be exchanged: sem, pool, frozen*)
exchange _type,
(*type must be: reference or shadow*)
Illegal _var _param _substitution,
(*formal and actual type must match exactly*)
illegal _value _param _substitution,
(*actual and formal types are not compatible*)
actual _may _not _be _frozen,
(*formal is not frozen, therefore ...*)
skipparam _only _in _struc _const,
(*the >?> may only occur in structured constants*)
struc _arr _impossible,
(*incomp. types in structured array-constant*)
struc _rec _incompatible,
(*incomp. types in structured record-constant*)
var _init _incompatible,
(*incomp. types in var-initialization*)
repetition _type,
(*repetition must be integer*)
\f
C_._3_ _ _ _ _ _ _ _M_e_s_s_a_g_e_s_ _f_r_o_m_ _P_a_s_s_ _4_ C.3
All error messages from pass 4 have the format:
xxx pass 4 line <no', <text'
where <no' is the line number where the error is detected.
<text' is one among the following:
subrange def. Error in the definition of subrange type
- lower bound ' upper bound.
set def. Error in the definition of set type -
lower bound of the basis subrange type is
negative.
pool def. Error in the definition of pool type -
number of elements is zero or negative.
record size Record type ' 65536 bytes.
array size Array type ' 65536 bytes.
constant value Value of constant outside interval
bounds.
case label range In a case label interval first ' last.
constant Syntax error in number.
set constant Error in set constant, - negative
constant, or an interval with first value
< last value, or constant ' 1023.
times Wrong number of values in constant of
array type.
\f
not constant Variable, or set constant used in
expression, outside the statement part of
a procedure or process.
stack Variable in a block occupies more than
65536 bytes.
overflow Value of constant or constant expression
outside the interval - 32768, 32767.
export value error Value export of other than constant.
packed field export Export of fields not allowed.
export offset error Address export of variable not declared
at process block level, or declared at
process level of an internal process.
compiler error error in pass 4.
compilation terminated by <error'
where <error' is
operand overflow
too complicated arithmetic expressions.
constant area overflow
too many or too big structured constants.
Other error messages may occur, caused by fatal error in pass 4.
C_._4_ _ _ _ _ _ _ _M_e_s_s_a_g_e_s_ _f_r_o_m_ _P_a_s_s_ _5_
Error messages from poss 5 have the format:
*** pass 5 line <no', <text'
where <no' is the line number where the error is detected.
<text' is among the following:
+decl. caselabel ambiguous caselabel
\f
too many pool buffers max. 127 buffers in pool
too many formal parameters
max. 10 formal parameters in externally
defined routine
routine not implemented
call of routine which is not implemented
export name +decl. ambiguous export name
export name <name' unknown in <routine'
Use of not defined export name.
byte overflow <name' = <value' in <routine'
value of export name ' 255.
library <name' not found
The library lib.<name' in the call, does
not exist.
Other error messages may occur, caused by fatal error in pass 5.
C_._5_ _ _ _ _ _ _ _M_e_s_s_a_g_e_s_ _f_r_o_m_ _P_a_s_s_ _6_ C.5
Only messages caused by fatal error in pass 6.
\f
F_ D_._ _ _ _ _ _ _ _ _H_O_W_ _T_O_ _B_U_I_L_D_ _A_ _P_I_-_1_ _L_I_B_R_A_R_Y_ _O_N_ _T_H_E_ _R_C_8_0_0_0_ D.
With the programs >insertz80>, >listz80>, and >deletez80> it is
possible to maintain PI-1 libraries on the RC8000. A PI-1 library
consists of a number of named entries. The names must be RC8000
names (FP names). There are four kinds of entries:
- Z80 routines in assembler object format
These routines may be included in compiled PASCAL80 programs as
described in chapter 4.
- PASCAL80 object modules
The output from a pascalz80 compilation is a PASCAL80 object
module. In fact the output file is formatted as a PI-1 library
with one entry.
- basic routine
- reserved name
The latter two entry types are used in the basic compiler
library to implement the predefined PASCAL80 routines.
The programs require at least 25000 Hw memory.
D_._1_ _ _ _ _ _ _ _I_n_s_e_r_t_Z_8_0_ D.1
The program inserts an entry in a PI-1 library.
C_a_l_l_:
M_m_m_ 1 10
insertz80 lib.<pascal80 lib' <entry spec' <param spec'
P_p_p_ 0 0
<pascal80 lib' is a file descriptor describing the backing
storage area of the library.
If lib.<pascal80 lib' is omitted the name >pascal80lib> (the
basic compiler library) is assumed. Basic routines and reserved
names can only be inserted in this way.
\f
<entry spec'::= <Z80 spec' <obj spec' <basic spec' <reserve spec'
The <entry spec' specifies the kind and the name of the entry to
be inserted, and if necessary also the file from which to read
the routine or module. It is not checked whether an entry with
the same name is already in the library.
M_m_m_ 1
<Z80 spec'::= <Z80 name' entry.<name'
P_p_p_ 0
The Z80 routine from the file <Z80 name' is inserted as an entry
with name <name' in the library. If the entry parameter is not
present the entry is given the name specified by a NAME assembler
directive which must in this case must have been present during
assembly.
M_m_m_ 1
<obj spec'::= module.<bin file' entry.<name'
P_p_p_ 0
The PASCAL80 object module from the file <bin file' (same as left
hand side of compiler call, cf. appendix B) is inserted as an
entry with name <name'. If the entry parameter is omitted the
entry is given the object module name; see subsection 3.1.14.
<basic spec'::= basic.<no'.<name'
The basic routine number <no' is inserted as an entry with name
<name'.
<reserve spec'::= reserved.<no'.<name'
The entry <name' is inserted as a reserved name.
<param spec'::= <kind'. <type'
The parameters of the inserted routine or process must be
described in the order of declaration.
<kind'::= val var
<type'::= pointer semaphore reference
shadow pool
sysr.<mem req' sysa.<mem req' <mem req'
\f
Shielded and pointer types are called system types. Depending on
the type of each parameter, specify
- for a system type: the type name
- for a record type with system component type(s): sysr
- for an array type with system component type(s): sysa
- for all other types: only <mem req'.
<mem req', when specified, is the memory requirement (in bytes)
of the type (cf. chapter 5).
D_._2_ _ _ _ _ _ _ _D_e_l_e_t_e_Z_8_0_ D.2
The program deletes entries in a PI-1 library.
C_a_l_l_:
M_m_m_ 1
deletez80 lib.<pascal80 lib' <name'
P_p_p_ 0
The entry with name <name' is deleted in the library <pascal80 lib'.
If lib.<pascal80 lib' is omitted the name >pascal80lib> is
assumed.
D_._3_ _ _ _ _ _ _ _L_i_s_t_Z_8_0_ D.3
The program produces a list of entries in the library on current
output including the names and the parameters of the routines.
C_a_l_l_:
M_m_m_ 1 1 1
listz80 lib.<pascal80 lib' <name' .code
P_p_p_ 0 0 0
<name' name of entry, if omitted all entries are listed.
code if present the binary code is listed.
If lib.<pascal80 lib' is omitted the name >pascal80lib> is
assumed.
\f
F_ E_._ _ _ _ _ _ _ _ _H_O_W_ _T_O_ _G_E_N_E_R_A_T_E_ _A_ _B_O_O_T_S_T_R_A_P_ _I_M_A_G_E_ _F_O_R_ _T_H_E_ _P_I_-_1_ _M_A_C_H_I_N_E_ _O_N_ _T_H_E_E.
R_C_8_0_0_0_
With the program >pilink> it is possible to generate a file
containing the specified object modules and the necessary library
routines. The file will be a bootstrap image, i.e. all references
between modules are resolved, except for linking of external
process names, and the image must be located starting from
address 0.
Basic software for the PI-1 machine must always be included in a
bootstrap image. The basic software exists in a number of
versions. A bootstrap image may be a ROM image which is suitable
for blasting in ROM or it may be a RAM image which can be loaded
by a PI-1 machine bootstrap loader. For further details, see 2.
C_a_l_l_ _o_f_ _p_i_l_i_n_k_:
M_m_m_
<objfile' .<process name'.<size'
1 0
<outfile' = pilink lib.<libfile'
0
<params'
P_p_p_ 0
M_m_m_ yes
print.
no
yes
map.
no
<params'::=
yes
rom.
no
P_p_p_ basic.<basic system'
<size'::= integer
<outfile'
<objfile'
<process name' ::= <name'
<libfile'
<basic system'
\f
<outfile'
A file descriptor describing the document where the bootstrap
image is output. If no outfile is specified the bootstrap image
is output to an anonymous work file.
<objfile'
A file descriptor describing a document containing one or more
modules which are all included in the coreimage. The objfile may
be the output from a pascalz80 compilation or a PI-1 library file
created by >insertz80> (see appendix D).
<process name'.<size'
If any of the modules in an objfile are not reentrant processes,
the <objfile' specification must be followed by the names of
these processes, and their stack sizes.
lib. <libfile'
<libfile' is a file descriptor describing a document containing a
PI-1 library (i.e. separately compiled routine). A module boot-
strap from a libfile is included in the image, if it is referen-
ced from an included module.
basis.<basic system'
<basic system must be a file descriptor describing a document
containing PI-1 basic software. There must be precisely one
occurence of this parameter in a call of pilink.
rom.yes
The bootstrap is created as a ROM image.
rom.no
The bootstrap is created as a RAM image. The rom parameter may
occur at most once. Default rom.no.
map.yes
For each module included in the bootstrap, a line is listed, on
current output, containing module name and the addresses of
linker table entry, start, entry, and the date the module is
compiled. For a non-reentrant process the first address of the
stack is also listed.
\f
The map parameter may occur at most once. Default map.no.
print.yes
print.no
Controls printing of the bootstrap image on current output. The
print parameter affects only printing of modules included from
files specified after the print parameter.
The initial setting is print.no.
E_._1_ _ _ _ _ _ _ _E_r_r_o_r_ _M_e_s_s_a_g_e_s_ E.1
***pilink param <illegal parameter'
Illegal parameter syntax. The parameter is ignored.
***pilink too many parameters
Too many parameters in the call.
***pilink <name' unknown
Document with <name' unknown.
***pilink stack size for <name' missing
Stack size for non-reentrant process module missing.
***pilink <name' + declaration
Two modules with same name not allowed.
***pilink byte overflow in <name'
Error in user Z80 assembler routine included in module with
<name'.
***pilink <name' too big
Max module size (20000 bytes) exceeded.
***pilink program too big
Max bootstrap image size (64 K bytes) exceeded.
***pilink stack too big
Stack top for module exceeds 64 K bytes.
\f
***pilink too many modules
Max number of modules in image exceeded (max = 75).
***pilink too many sections in <name'
Too many user Z80 assembler routines in module <name'
(max = 30).
***pilink too many externals in <name'
Max number of externals in module <name' exceeded (max = 50).
***pilink fatal error
Program error.
Other error messages may occur, caused by fatal error in pilink.
\f
F_ F_._ _ _ _ _ _ _ _ _H_O_W_ _T_O_ _T_R_A_N_S_F_E_R_ _B_I_N_A_R_Y_ _F_I_L_E_S_ _B_E_T_W_E_E_N_ _T_H_E_ _R_C_8_0_0_0_ _A_N_D_ _T_H_E_ _T_E_K_T_R_O_N_I_X_F.
8_0_0_2_A_ _D_E_V_E_L_O_P_M_E_N_T_ _S_Y_S_T_E_M_
The object code is transferred between the two computers in the
Tekhex textformat 3. This format represents binary code as
ASCII-encoded hexadecimal digits (two digits per byte of code).
Each block is identified with a header character, a slash charac-
ter, and includes two checksums.
Transferring data between RC8000 and Tektronix is done with
Tektronix in the COMM operation mode 3.
To convert object code between Tektex and binary two utility
programs are available on the Tektronix development system called
>CB> (convert to binary) and >CT> (convert to Tektex).
On the RC8000 the program >tekmove> takes care of receiving
Tektex blocks from Tektronix and converting them to binary, as
well as converting binary to Tektex blocks and transmitting them
to Tektronix.
F_._1_ _ _ _ _ _ _ _T_e_k_t_r_o_n_i_x_ _U_t_i_l_i_t_y_ _P_r_o_g_r_a_m_ _>_C_T_>_ F.1
The program converts a binary file on the Tektronix development
system to a file in the Tekhex format.
C_a_l_l_:
XEQ CT <binfile' <tektexfile'
<binfile'::= name of the binary file (input)
<tektexfile'::= name of the Tekhex file (output)
\f
F_._2_ _ _ _ _ _ _ _T_e_k_t_r_o_n_i_x_ _U_t_i_l_i_t_y_ _P_r_o_g_r_a_m_ _>_C_B_>_ F.2
The program converts a file in the Tekhex textformat, (transfer-
red from RC8000) to a binary file.
C_a_l_l_:
XEQ CB <tektexfile' <binfile'
<tektexfile'::= name of the Tekhex file (input)
<binfile' ::= name of the binary file (output)
F_._3_ _ _ _ _ _ _ _R_C_8_0_0_0_ _U_t_i_l_i_t_y_ _P_r_o_g_r_a_m_ _>_t_e_k_m_o_v_e_>_ F.3
The program performs conversion and transfer of files between
RC8000 and Tektronix.
C_a_l_l_:
M_m_m_ to 1
tekmove <file' block.<size'
P_p_p_ from 0
to The program reads Tekhex blocks from the file with
descriptor >v>, (terminal input, i.e. the Tektronix system
in the COMM mode) and converts them into the bs area with
the name <file'.
from The program reads from the bs area <file', converts the
contents to Tekhex blocks and writes these into the file
with descriptor >v> (terminal output, i.e. the Tektronix
system).
block The blocks transferred from RC8000 to Tektronix contain
<size' hexadecimal bytes of data. Default block length is
58 hexadecimal bytes.
The program can run under the operating systems >s> and >sos>.
\f
F_._4_ _ _ _ _ _ _ _E_x_a_m_p_l_e_s_ _o_f_ _H_o_w_ _t_o_ _T_r_a_n_s_f_e_r_ _P_r_o_g_r_a_m_s_ F.4
The RC8000 is supposed to be connected to the 8002A via the
remote input/output (jack J101), and commands are entered on the
8002A system terminal (jack J100).
a_)_ _T_r_a_n_s_f_e_r_r_i_n_g_ _p_r_o_g_r_a_m_s_ _f_r_o_m_ _8_0_0_2_A_ _t_o_ _R_C_8_0_0_0_
In the example a program >TEST> on the 8002A is transferred to a
file >test> on RC8000.
The program is converted to Tekhex format by typing:
XEQ CT TEST TESTH <CR'
Now the file TESTH contains the file TEST in Tekhex format.
The COMM terminal level is entered by typing:
COMM M=0 T=1 P=7 <CR'
After enrolling by the operating system on RC8000 (>sos> or >s>)
the program >tekmove> is called:
tekmove to test CNTRL@<TESTH <CR'
The command makes the 8002A enter the transfer level and >TESTH>
is transferred to the file >test> on RC8000.
After a successful transfer the 8002A automatically re-enters the
terminal level.
By typing CNTRL@ ESC you exit from COMM and get back in normal
mode.
\f
b_)_ _T_r_a_n_s_f_e_r_r_i_n_g_ _p_r_o_g_r_a_m_s_ _f_r_o_m_ _R_C_8_0_0_0_ _t_o_ _8_0_0_2_A_
COMM is entered as described in a). After enrolling by the
operating system the transfer is performed by typing:
tekmove from test CNTRL@'TESTH<CR'
The file >test> on RC8000 is transferred to the file >TESTH>
(Tekhex format) on 8002A. After exit from COMM the Tektex file is
converted to binary by typing:
XEQ CB TESTH TEST
\f
\f
«eof»