Commit | Line | Data |
---|---|---|
1662094b BJ |
1 | .de mD |
2 | .ta 8n 16n 24n | |
3 | .. | |
4 | .if !\n(xx .so tmac.p | |
5 | .nr H1 1 | |
6 | .if n .ND | |
7 | .NH | |
8 | Operations | |
9 | .NH 2 | |
10 | Naming conventions and operation summary | |
11 | .PP | |
12 | As discussed in section 1.10, | |
13 | the main interpreter loop decodes the first word of the interpreter | |
14 | instruction, | |
15 | using the first byte as an operation code, | |
16 | and places the second byte, | |
17 | the ``subop'', | |
18 | in register 3. | |
19 | The subop may be used to index the display, | |
20 | as a small constant, | |
21 | or to indicate one of several relational operators. | |
22 | In the cases where a constant is needed, but it | |
23 | is not small enough to fit in the byte sub-operator, | |
24 | a zero is placed there and the constant follows in the next word. | |
25 | Zero is easily tested for, | |
26 | as the instruction which places the | |
27 | subop in r3 sets the condition code flags, | |
28 | and this condition code is still available after the transfer | |
29 | to an operation code sequence. | |
30 | A construction like | |
31 | .DS | |
32 | .mD | |
33 | _OPER: | |
34 | \fBbne\fR 1f | |
35 | \fBmov\fR (lc)+,r3 | |
36 | 1: | |
37 | ... | |
38 | .DE | |
39 | .IP | |
40 | is all that is needed to effect this packing of data. | |
41 | This technique saves a great deal of space in the Pascal | |
42 | .I obj | |
43 | object code. | |
44 | .PP | |
45 | Table 2.1 gives the codes used in the instruction descriptions | |
46 | to indicate the kind of inline data expected by each instruction. | |
47 | .KF | |
48 | .TS | |
49 | box center; | |
50 | c s | |
51 | l | l | |
52 | ci | aw(3.25i). | |
53 | Table 2.1 \- Inline data type codes | |
54 | _ | |
55 | Code Description | |
56 | = | |
57 | a T{ | |
58 | .fi | |
59 | An address offset is given in the word | |
60 | following the instruction. | |
61 | T} | |
62 | _ | |
63 | l T{ | |
64 | An index into the display, ready as an offset or a guaranteeably small integer, | |
65 | is given in the sub-operation code. | |
66 | T} | |
67 | _ | |
68 | r T{ | |
69 | A relational operator encoded as described | |
70 | in section 2.3 is given in the subop. | |
71 | T} | |
72 | _ | |
73 | s T{ | |
74 | A small integer is | |
75 | placed in the subop, or in the next word | |
76 | if it is zero or too large. | |
77 | T} | |
78 | _ | |
79 | v T{ | |
80 | Variable length inline data. | |
81 | T} | |
82 | _ | |
83 | w T{ | |
84 | A word value in the following word. | |
85 | T} | |
86 | _ | |
87 | " T{ | |
88 | An inline constant string. | |
89 | T} | |
90 | .TE | |
91 | .KE | |
92 | .PP | |
93 | Before giving a list of the machine opcodes, | |
94 | it is useful to note the naming conventions in the interpreter for typed | |
95 | operations. | |
96 | Machine instructions which have numeric operands use a simple and uniform | |
97 | naming convention in which a suffix on the root operation name indicates | |
98 | the type of operands expected. | |
99 | These are given in Table 2.2. | |
100 | Here the expression ``a above b'' means that `a' is on top of the | |
101 | stack with `b' below it. | |
102 | Short integers are 2 byte integers, | |
103 | and long integers are 4 byte integers. | |
104 | .TS | |
105 | box center; | |
106 | c s s | |
107 | c s s | |
108 | l l l | |
109 | c ap-2 a. | |
110 | Table 2.2 \- Operator Suffices | |
111 | .sp | |
112 | Unary operator suffices | |
113 | .sp .1i | |
114 | Suffix Example Argument type | |
115 | 2 NEG2 Short integer | |
116 | 4 SQR4 Long integer | |
117 | 8 ABS8 Real | |
118 | .sp | |
119 | .T& | |
120 | c s s | |
121 | l l l | |
122 | c ap-2 a. | |
123 | Binary operator suffices | |
124 | .sp .1i | |
125 | Suffix Example Argument type | |
126 | 2 ADD2 Two short integers | |
127 | 24 MUL24 Short above long integer | |
128 | 42 REL42 Long above short integer | |
129 | 4 DIV4 Two long integers | |
130 | 28 DVD28 Short integer above real | |
131 | 48 REL48 Long integer above real | |
132 | 82 SUB82 Real above short integer | |
133 | 84 MUL84 Real above long integer | |
134 | .sp | |
135 | .T& | |
136 | c s s | |
137 | l l l | |
138 | c ap-2 a. | |
139 | Other Suffices | |
140 | .sp .1i | |
141 | Suffix Example Argument types | |
142 | T ADDT Sets | |
143 | G RELG Strings | |
144 | .TE | |
145 | .PP | |
146 | We now give the list of machine operations with a reference | |
147 | to the appropriate sections and a short description of each. | |
148 | The character `*' at the end of a name indicates that all | |
149 | operations with the root prefix before the `*' are summarized by | |
150 | the one entry. | |
151 | .br | |
152 | .ne 15 | |
153 | .TS H | |
154 | box center; | |
155 | c s s | |
156 | lw(14) | lw(12) | lw(40) | |
157 | lp-2 | a | l. | |
158 | Table 2.3 \- Machine operations | |
159 | _ | |
160 | Mnemonic Reference Description | |
161 | = | |
162 | .TH | |
163 | .so fig2.1.n | |
164 | .TE | |
165 | .bp | |
166 | .NH 2 | |
167 | Basic control operations | |
168 | .LP | |
169 | .SH | |
170 | ABORT | |
171 | .IP | |
172 | This operator is used to halt execution immediately with an IOT process | |
173 | fault. | |
174 | It is used only for debugging | |
175 | .I px | |
176 | and is never generated by the translator | |
177 | .I pi. | |
178 | .SH | |
179 | HALT | |
180 | .IP | |
181 | Corresponds to the Pascal procedure | |
182 | .I halt ; | |
183 | causes execution to terminate with a post-mortem backtrace as if a run-time | |
184 | error had occurred. | |
185 | .SH | |
186 | BEG w1,w2," | |
187 | .IP | |
188 | Causes the second part of the block mark to be created, and | |
189 | .I w1 | |
190 | bytes of local variable space to be allocated and cleared to zero. | |
191 | Stack overflow is detected here. | |
192 | .I W2 | |
193 | is the first line of the body of this section for error traceback, | |
194 | and he inline string (length 8) the character representation of its name. | |
195 | .SH | |
196 | NODUMP w | |
197 | .IP | |
198 | Equivalent to | |
199 | .SM BEG , | |
200 | and used to begin the main program when the ``p'' | |
201 | option is disabled so that the post-mortem backtrace will be inhibited. | |
202 | .SH | |
203 | END | |
204 | .IP | |
205 | Complementary to the operators | |
206 | .SM CALL | |
207 | and | |
208 | .SM BEG , | |
209 | exits the current block, calling the procedure | |
210 | .I blkexit | |
211 | to flush buffers for and release any local files. | |
212 | Restores the environment of the caller from the block mark. | |
213 | If this is the end for the main program, all files are | |
214 | .I flushed, | |
215 | the profile data file is written if necessary, and | |
216 | the routine | |
217 | .I psexit | |
218 | which prints the statistics if desired (and does not return) is called. | |
219 | .SH | |
220 | CALL l,a | |
221 | .IP | |
222 | Saves the current line number, return address, and active display entry pointer | |
223 | .I dp | |
224 | in the first part of the block mark, then transfers to the entry point | |
225 | given by the relative address | |
226 | .I a , | |
227 | which is the beginning of a | |
228 | .B procedure | |
229 | or | |
230 | .B function | |
231 | at level | |
232 | .I l. | |
233 | .SH | |
234 | PUSH s | |
235 | .IP | |
236 | Clears | |
237 | .I s | |
238 | bytes on the stack for, e.g., the return value of a | |
239 | .B function | |
240 | just before calling the function. | |
241 | .SH | |
242 | POP s | |
243 | .IP | |
244 | Pop | |
245 | .I s | |
246 | bytes off the stack. | |
247 | Used, e.g., after a | |
248 | .B function | |
249 | or | |
250 | .B procedure | |
251 | returns to remove the arguments from the stack. | |
252 | .SH | |
253 | TRA a | |
254 | .IP | |
255 | Transfer control to relative address | |
256 | .I a | |
257 | as a local | |
258 | .B goto | |
259 | or part of a structured statement. | |
260 | .SH | |
261 | LINO s | |
262 | .IP | |
263 | Set current line number to | |
264 | .I s. | |
265 | For consistency, check that the expression stack is empty | |
266 | as it should be (as this is the start of a statement.) | |
267 | This consistency check will fail only if there is a bug in the | |
268 | interpreter or the interpreter code has somehow been damaged. | |
269 | Increment the statement count and if it exceeds the statement limit, | |
270 | generate a fault. | |
271 | .SH | |
272 | GOTO l,a | |
273 | .IP | |
274 | Transfer conrol to address | |
275 | .I a | |
276 | which is in the block at level | |
277 | .I l | |
278 | of the display. | |
279 | This is a non-local | |
280 | .B goto. | |
281 | Causes each block to be exited as if with | |
282 | .SM END , | |
283 | flushing and freeing files with | |
284 | .I blkexit, | |
285 | until the current display entry is at level | |
286 | .I l. | |
287 | .SH | |
288 | SDUP | |
289 | .IP | |
290 | Duplicate the one word integer on the top of | |
291 | the stack. | |
292 | This is used mostly for constructing sets. | |
293 | See section 2.11. | |
294 | .NH 2 | |
295 | If and relational operators | |
296 | .SH | |
297 | IF a | |
298 | .IP | |
299 | The interpreter conditional transfers all take place using this operator | |
300 | which examines the Boolean value on the top of the stack. | |
301 | If the value is | |
302 | .I true , | |
303 | the subsequent code is executed, | |
304 | otherwise control transfers to the specified address. | |
305 | .SH | |
306 | REL* r | |
307 | .IP | |
308 | These take two arguments on the stack, | |
309 | and the sub-operation code indicates which relational operation is to | |
310 | be performed, coded as follows with `a' above `b' on the stack: | |
311 | .DS | |
312 | .mD | |
313 | .TS | |
314 | lb lb | |
315 | c a. | |
316 | Code Operation | |
317 | _ | |
318 | 0 a = b | |
319 | 2 a <> b | |
320 | 4 a < b | |
321 | 6 a > b | |
322 | 8 a <= b | |
323 | 10 a >= b | |
324 | .TE | |
325 | .DE | |
326 | .IP | |
327 | Each operation does a number of tests to set the condition code | |
328 | appropriately and then does an indexed branch based on the | |
329 | sub-operation code to a test of the condition here specified, | |
330 | pushing a Boolean value on the stack. | |
331 | .IP | |
332 | Consider the statement fragment: | |
333 | .DS | |
334 | .mD | |
335 | \*bif\fR a = b \*bthen\fR | |
336 | .DE | |
337 | .IP | |
338 | If | |
339 | .I a | |
340 | and | |
341 | .I b | |
342 | are integers this generates the following code: | |
343 | .DS | |
344 | .TS | |
345 | lp-2w(8) l. | |
346 | RV4 \fIa\fR | |
347 | RV4 \fIb\fR | |
348 | REL4 \&= | |
349 | IF \fIElse part offset\fR | |
350 | .sp | |
351 | .T& | |
352 | c s. | |
353 | \fI\&... Then part code ...\fR | |
354 | .TE | |
355 | .DE | |
356 | .NH 2 | |
357 | Boolean operators | |
358 | .IP | |
359 | The Boolean operators | |
360 | .SM AND , | |
361 | .SM OR , | |
362 | and | |
363 | .SM NOT | |
364 | manipulate values on the top of the stack. | |
365 | All Boolean values are kept in single bytes in memory, | |
366 | or in single words on the stack. | |
367 | Zero represents a Boolean \fIfalse\fP, and one a Boolean \fItrue\fP. | |
368 | .NH 2 | |
369 | Rvalue, constant, and assignment operators | |
370 | .SH | |
371 | RV* l,a | |
372 | .IP | |
373 | The rvalue operators load values on the stack. | |
374 | They take a block number as a subop and load the appropriate | |
375 | number of bytes from that block at the offset specified | |
376 | in the following word onto the stack. As an example, consider | |
377 | .SM RV4 : | |
378 | .DS | |
379 | .mD | |
380 | _RV4: | |
381 | \fBmov\fR _display(r3),r0 | |
382 | \fBadd\fR (lc)+,r0 | |
383 | \fBsub\fR $4,sp | |
384 | \fBmov\fR sp,r2 | |
385 | \fBmov\fR (r0)+,(r2)+ | |
386 | \fBmov\fR (r0)+,(r2)+ | |
387 | \fBreturn\fR | |
388 | .DE | |
389 | .IP | |
390 | Here the interpreter first generates the source address in r0 by adding the | |
391 | display entry to the offset in the next instruction word. | |
392 | It then reserves a long integer space on the stack (4 bytes) | |
393 | and moves the data from the source onto the stack. | |
394 | The pseudo-operation ``return'' | |
395 | takes the interpreter back to the main interpreter loop. | |
396 | Note that the sub-operation code is already in | |
397 | r3 and multiplied by 2 to be immediately usable as a word index | |
398 | into the display. | |
399 | .SH | |
400 | CON* r | |
401 | .IP | |
402 | The constant operators load a value onto the stack from inline code. | |
403 | Small integer values are condensed and loaded by the | |
404 | .SM CON1 | |
405 | operator, which is given by | |
406 | .DS | |
407 | .mD | |
408 | _CON1: | |
409 | \fBmov\fR r3,-(sp) | |
410 | \fBreturn\fR | |
411 | .DE | |
412 | .IP | |
413 | Here note that little work was required as the required constant | |
414 | had already been placed in register 3. | |
415 | For longer constants, more work is required; | |
416 | the operator | |
417 | .SM CON | |
418 | takes a length specification in the subop and can be used to load | |
419 | strings and other variable length data onto the stack. | |
420 | .SH | |
421 | AS* | |
422 | .IP | |
423 | The assignment operators are similar to arithmetic and relational operators | |
424 | in that they take two operands, both in the stack, | |
425 | but the lengths given for them indicate | |
426 | first the length of the value on the stack and then the length | |
427 | of the target in memory. | |
428 | The target address in memory is under the value to be stored. | |
429 | Thus the statement | |
430 | .DS | |
431 | i := 1 | |
432 | .DE | |
433 | .IP | |
434 | where | |
435 | .I i | |
436 | is a full-length, 4 byte, integer, | |
437 | will generate the code sequence | |
438 | .DS | |
439 | .TS | |
440 | lp-2w(8) l. | |
441 | LV \fIi\fP | |
442 | CON1 1 | |
443 | AS24 | |
444 | .TE | |
445 | .DE | |
446 | .IP | |
447 | Here | |
448 | .SM LV | |
449 | will load the address of | |
450 | .I i, | |
451 | which is actually given as a block number in the subop and an | |
452 | offest in the following word, | |
453 | onto the stack, occupying a single word. | |
454 | .SM CON1 , | |
455 | which is a single word instruction, | |
456 | then loads the constant 1, | |
457 | which is in its subop, | |
458 | onto the stack. | |
459 | Since there are not one byte constants on the stack, | |
460 | this becomes a 2 byte, single word integer. | |
461 | The interpreter then assigns a length 2 integer to a length 4 integer using | |
462 | .SM AS24 \&. | |
463 | The code sequence for | |
464 | .SM AS24 | |
465 | is given by: | |
466 | .DS | |
467 | .mD | |
468 | _AS24: | |
469 | \fBmov\fR (sp)+,r1 | |
470 | \fBsxt\fR r0 | |
471 | \fBmov\fR (sp)+,r2 | |
472 | \fBmov\fR r0,(r2)+ | |
473 | \fBmov\fR r1,(r2) | |
474 | \fBreturn\fR | |
475 | .DE | |
476 | .IP | |
477 | Thus the interpreter gets the single word off the stack, | |
478 | extends it to be a 4 byte integer in two registers, | |
479 | gets the target address off the stack, | |
480 | and finally stores the parts of the value in the target. | |
481 | This is a typical use of the constant and assignment operators. | |
482 | .NH 2 | |
483 | Addressing operations | |
484 | .SH | |
485 | LV l,w | |
486 | .IP | |
487 | The most common operation performed by the interpreter | |
488 | is the ``lvalue'' or ``address of'' operation. | |
489 | It is given by: | |
490 | .DS | |
491 | .mD | |
492 | _LV: | |
493 | \fBmov\fR _display(r3),r0 | |
494 | \fBadd\fR (lc)+,r0 | |
495 | \fBmov\fR r0,-(sp) | |
496 | \fBreturn | |
497 | .DE | |
498 | .IP | |
499 | It calculates an address in the block specified in the subop | |
500 | by adding the associated display entry to the | |
501 | offset which appears in the following word. | |
502 | .SH | |
503 | OFF s | |
504 | .IP | |
505 | The offset operator is used in field names. | |
506 | Thus to get the address of | |
507 | .LS | |
508 | p^.f1 | |
509 | .LE | |
510 | .IP | |
511 | .I pi | |
512 | would generate the sequence | |
513 | .DS | |
514 | .mD | |
515 | .TS | |
516 | lp-2w(8) l. | |
517 | RV \fIp\fP | |
518 | OFF \fIf1\fP | |
519 | .TE | |
520 | .DE | |
521 | .IP | |
522 | where the | |
523 | .SM RV | |
524 | loads the value of | |
525 | .I p, | |
526 | given its block in the subop and offset in the following word, | |
527 | and the interpreter then adds the offset of the field | |
528 | .I f1 | |
529 | in its record to get the correct address. | |
530 | .SM OFF | |
531 | takes its argument in the subop if it is small enough. | |
532 | .SH | |
533 | NIL | |
534 | .IP | |
535 | The example above is incomplete, lacking a check for a | |
536 | .B nil | |
537 | pointer. | |
538 | The code generated would, in fact, be | |
539 | .DS | |
540 | .TS | |
541 | lp-2w(8) l. | |
542 | RV \fIp\fP | |
543 | NIL | |
544 | OFF \fIf1\fP | |
545 | .TE | |
546 | .DE | |
547 | .IP | |
548 | where the | |
549 | .SM NIL | |
550 | operation checks for a | |
551 | .I nil | |
552 | pointer and generates the appropriate runtime error if it is. | |
553 | .SH | |
554 | INX* s,w,w | |
555 | .IP | |
556 | The operators | |
557 | .SM INX2 | |
558 | and | |
559 | .SM INX4 | |
560 | perform subscripting. | |
561 | For example, the statement | |
562 | .DS | |
563 | a[i] := 2.0 | |
564 | .DE | |
565 | .IP | |
566 | with | |
567 | .I i | |
568 | a short integer, such as a subrange ``1..1000'', | |
569 | and | |
570 | .I a | |
571 | an | |
572 | ``array [1..1000] of real'' | |
573 | would generate | |
574 | .DS | |
575 | .TS | |
576 | lp-2w(8) l. | |
577 | LV \fIa\fP | |
578 | RV2 \fIi\fP | |
579 | INX2 8,1,999 | |
580 | CON8 2.0 | |
581 | AS8 | |
582 | .TE | |
583 | .DE | |
584 | .IP | |
585 | Here the | |
586 | .SM LV | |
587 | operation takes the address of | |
588 | .I a | |
589 | and places it on the stack. | |
590 | The value of | |
591 | .I i | |
592 | is then placed on top of this on the stack. | |
593 | We then perform an indexing of the array address by the | |
594 | length 2 index (a length 4 index would use | |
595 | .SM INX4 ) | |
596 | where the individual elements have a size of 8 bytes. | |
597 | The code for | |
598 | .SM INX2 | |
599 | is: | |
600 | .DS | |
601 | .mD | |
602 | _INX2: | |
603 | \fBtst\fR r3 | |
604 | \fBbne\fR 1f | |
605 | \fBmov\fR (lc)+,r3 | |
606 | 1: | |
607 | \fBmov\fR (sp)+,r1 | |
608 | \fBsub\fR (lc)+,r1 | |
609 | \fBbmi\fR 1f | |
610 | \fBcmp\fR r1,(lc)+ | |
611 | \fBbgt\fR 1f | |
612 | \fBmul\fR r3,r1 | |
613 | \fBadd\fR r1,(sp) | |
614 | \fBreturn | |
615 | 1: | |
616 | \fBerror\fR ESUBSCR | |
617 | .DE | |
618 | .IP | |
619 | Here the index operation subtracts the constant value 1 from the | |
620 | supplied subscript, | |
621 | this being the low bound of the range of permissible subscripts. | |
622 | If the result is negative, | |
623 | or if the normalized subscript then exceeds 999, which | |
624 | is the maximum permissible subscript if the first is numbered 0, | |
625 | the interpreter generates a subscript error. | |
626 | Otherwise, the interpreter multiplies the offset by 8 and adds it to the address | |
627 | which is already on the stack for | |
628 | .I a , | |
629 | to address ``a[i]''. | |
630 | Multi-dimension subscripts are translated as a sequence of single subscriptings. | |
631 | .SH | |
632 | IND* | |
633 | .IP | |
634 | For indirect references through | |
635 | .B var | |
636 | parameters and pointers, | |
637 | the interpreter has a set of indirection operators which convert a pointer | |
638 | on the stack into a value on the stack from that address. | |
639 | different | |
640 | .SM IND | |
641 | operators are necessary because of the possibility of different | |
642 | length operands. | |
643 | .NH 2 | |
644 | Arithmetic operators | |
645 | .IP | |
646 | The interpreter has a large number of arithmetic operators. | |
647 | All operators produce results long enough to prevent overflow | |
648 | unless the bounds of the base type are exceeded. | |
649 | No overflow checking is done on arithmetic, but divide by zero | |
650 | and mod by zero are detected. | |
651 | .NH 2 | |
652 | Range checking | |
653 | .IP | |
654 | The interpreter has a number of range checking operators. | |
655 | The important distinction among these operators is between values whose | |
656 | legal range begins at 0 and those which do not begin at 0, i.e. with | |
657 | a subrange variable whose values range from 45 to 70. | |
658 | For those which begin at 0, a simpler ``logical'' comparison against | |
659 | the upper bound suffices. | |
660 | For others, both the low and upper bounds must be checked independently, | |
661 | requiring two comparisons. | |
662 | .NH 2 | |
663 | Case operators | |
664 | .IP | |
665 | The interpreter includes three operators for | |
666 | .B case | |
667 | statements which are used depending on the width of the | |
668 | .B case | |
669 | label type. | |
670 | For each width, the structure of the case data is the same, and | |
671 | is represented in the following figure. | |
672 | .sp 1 | |
673 | .KF | |
674 | .so fig2.2.n | |
675 | .KE | |
676 | .sp 1 | |
677 | .IP | |
678 | The | |
679 | .SM CASEOP | |
680 | case statement operators do a sequential search through the | |
681 | case label values. | |
682 | If they find the label value, they take the corresponding entry | |
683 | from the transfer table and cause the interpreter to branch to the | |
684 | indicated statement. | |
685 | If the specified label is not found, an error results. | |
686 | .IP | |
687 | The | |
688 | .SM CASE | |
689 | operators take the number of cases as a subop | |
690 | if possible. | |
691 | Three different operators are needed to handle single byte, | |
692 | word, and double word case transfer table values. | |
693 | For example, the | |
694 | .SM CASEOP1 | |
695 | operator has the following code sequence: | |
696 | .DS | |
697 | .mD | |
698 | _CASEOP1: | |
699 | \fBbne\fR 1f | |
700 | \fBmov\fR (lc)+,r3 | |
701 | 1: | |
702 | \fBmov\fR lc,r0 | |
703 | \fBadd\fR r3,r0 | |
704 | \fBadd\fR r3,r0 | |
705 | \fBmov\fR r3,r2 | |
706 | \fBtst\fR (sp)+ | |
707 | 1: | |
708 | \fBcmpb\fR (r0)+,-2(sp) | |
709 | \fBbeq\fR 5f | |
710 | \fBsob\fR r3,1b | |
711 | \fBerror\fR ECASE | |
712 | 5: | |
713 | \fBsub\fR r3,r2 | |
714 | \fBadd\fR r2,r2 | |
715 | \fBadd\fR lc,r2 | |
716 | \fBadd\fR (r2),lc | |
717 | \fBreturn | |
718 | .DE | |
719 | .IP | |
720 | Here the interpreter first computes the address of the beginning | |
721 | of the case label value area by adding twice the number of case label | |
722 | values to the address of the transfer table, since the transfer | |
723 | table entries are full word, 2 byte, address offsets. | |
724 | It then searches through the label values, and generates an ECASE | |
725 | error if the label is not found. | |
726 | If the label is found, we calculate the index of the entry in | |
727 | the transfer table which is desired and then add that offset | |
728 | to the interpreter location counter. | |
729 | .NH 2 | |
730 | Operations supporting pxp | |
731 | .IP | |
732 | For the purpose of execution profiling the following operations | |
733 | are defined. | |
734 | .SH | |
735 | PXPBUF w | |
736 | .IP | |
737 | Causes the interpreter to allocate a count buffer | |
738 | with | |
739 | .I w | |
740 | counters, each of which is a 4 byte integer, | |
741 | and to clear the counters to 0. | |
742 | The count buffer is placed within an image of the | |
743 | .I pmon.out | |
744 | file as described in the | |
745 | .I "PXP Implementation Notes." | |
746 | The contents of this buffer will be written to the file | |
747 | .I pmon.out | |
748 | when the program terminates. | |
749 | .SH | |
750 | COUNT s | |
751 | .IP | |
752 | Increments the counter specified by | |
753 | .I s. | |
754 | .SH | |
755 | TRACNT w,a | |
756 | .IP | |
757 | Used at the entry point to procedures and functions, | |
758 | combining a transfer to the entry point of the block with | |
759 | an incrementing of its entry count. | |
760 | .NH 2 | |
761 | Set operations | |
762 | .IP | |
763 | The set operations | |
764 | set union | |
765 | .SM ADDT, | |
766 | intersection | |
767 | .SM MULT, | |
768 | and the set relationals | |
769 | .SM RELT | |
770 | are straightforward. | |
771 | The following operations are more interesting. | |
772 | .SH | |
773 | CARD s | |
774 | .IP | |
775 | Takes the cardinality of a set of size | |
776 | .I s | |
777 | bytes on top of the stack, leaving a 2 byte integer count. | |
778 | .SM CARD | |
779 | uses a table of 4-bit population counts to count set bits | |
780 | in each 4-bit nibble of each byte in the set. | |
781 | .SH | |
782 | CTTOT s,w,w | |
783 | .IP | |
784 | Constructs a set. | |
785 | This operation requires a non-trivial amount of work, | |
786 | checking bounds and setting individual bits or ranges of bits. | |
787 | This operation sequence is very slow, | |
788 | and motivates the presence of the operator | |
789 | .SM INCT | |
790 | below. | |
791 | The arguments to | |
792 | .SM CTTOT | |
793 | include the number of elements | |
794 | .I s | |
795 | in the constructed set, | |
796 | the lower and upper bounds of the set, | |
797 | the two | |
798 | .I w | |
799 | values, | |
800 | and a pair of values on the stack for each range in the set, single | |
801 | elements in constructed sets being duplicated with | |
802 | .SM SDUP | |
803 | to form degenerate ranges. | |
804 | .SH | |
805 | IN s,w,w | |
806 | .IP | |
807 | The operator | |
808 | .B in | |
809 | for sets. | |
810 | The value | |
811 | .I s | |
812 | specifies the size of the set, | |
813 | the two | |
814 | .I w | |
815 | values the lower and upper bounds of the set. | |
816 | The value on the stack is checked to be in the set on the stack, | |
817 | and a Boolean value of | |
818 | .I true | |
819 | or | |
820 | .I false | |
821 | replaces the operands. | |
822 | .SH | |
823 | INCT | |
824 | .IP | |
825 | The operator | |
826 | .B in | |
827 | on a constructed set without constructing it. | |
828 | The left operand of | |
829 | .B in | |
830 | is on top of the stack followed by the number of pairs in the | |
831 | constructed set, | |
832 | and then the pairs themselves, all as single word integers. | |
833 | Pairs designate runs of values and single values are represented by | |
834 | a degenerate pair with both value equal. | |
835 | A typical situation for this operator to be generated is | |
836 | .LS | |
837 | \fBif\fR ch \fBin\fR ['+', '-', '*', '/'] | |
838 | .LE | |
839 | .IP | |
840 | or | |
841 | .LS | |
842 | \fBif\fR ch \fBin\fR ['a'..'z', '$', '_'] | |
843 | .LE | |
844 | .IP | |
845 | These situations are very common in Pascal, and | |
846 | .SM INCT | |
847 | makes them run much faster in the interpreter, | |
848 | as if they were written as an efficient series of | |
849 | .B if | |
850 | statements. | |
851 | .NH 2 | |
852 | Miscellaneous | |
853 | .IP | |
854 | Other miscellaneous operators which are present in the interpreter | |
855 | are | |
856 | .SM ASRT | |
857 | which causes termination if the Boolean value on the stack is not | |
858 | .I true, | |
859 | and | |
860 | .SM STOI , | |
861 | .SM STOD , | |
862 | .SM ITOD , | |
863 | and | |
864 | .SM ITOS | |
865 | which convert between different length arithmetic operands for | |
866 | use in aligning the arguments in | |
867 | .B procedure | |
868 | and | |
869 | .B function | |
870 | calls, and with some untyped built-ins, such as | |
871 | .SM SIN | |
872 | and | |
873 | .SM COS \&. | |
874 | .IP | |
875 | Finally, if the program is run with the run-time testing disabled, there | |
876 | are special operators for | |
877 | .B for | |
878 | statements | |
879 | and special indexing operators for arrays | |
880 | which have individual element size which is a power of 2. | |
881 | The code can run significantly faster using these operators. | |
882 | .NH 2 | |
883 | Functions and procedures | |
884 | .IP | |
885 | .I Px | |
886 | has a large number of built-in procedures and functions. | |
887 | The mathematical functions are taken from the standard | |
888 | system library. | |
889 | The linear congruential random number generator is described in | |
890 | the | |
891 | .I "Berkeley Pascal User Manual" | |
892 | .IP | |
893 | The procedures | |
894 | .I linelimit | |
895 | and | |
896 | .I dispose | |
897 | are included here but currently ignored. | |
898 | One surprise is that the built-ins | |
899 | .I pack | |
900 | and | |
901 | .I unpack | |
902 | are here and quite complex, functioning as a memory to memory | |
903 | move with a number of semantic checks. | |
904 | They do no ``unpacking'' or ``packing'' in the true sense, however, | |
905 | as the interpreter supports no packed data types. |