The Architecture of Kronos Family Processors

Download PDF Download PDF


        - USSR Academy of Sciences Siberian Division -

                     - Computing Center -


:::::      ::::
:::::      ::::
 :::      :::
 :::     ::
 :::    ::
 ::: : :        ::  :::      :::    ::: :::       :::        ::
 :::    ::      ::::  :::  ::: :::   :::   :::  ::: :::     ::::
 :::     :::    :::       ::     ::  ::     :: ::     ::  ::    ::
 :::      :::   ::        ::     ::  ::     :: ::     ::         ::
:::::      :::: ::         ::: :::   ::     ::  ::: :::    ::   ::
:::::      :::: ::           :::     ::     ::    :::        :::


         The Architecture of KRONOS Family Processors


                      Novosibirsk - 1988


     Copyright (c) 1988 by KRONOS Group.  All rights reserved.
No part of  this document may be  reproduced or transmitted in
any form or by any means without permission.


                         We  hope  information offered in this
                    guide  is  valid. Nevertheless we shall be
                    very   glad   if  user  reads  this  guide
                    critically   and  responds  us  about  all
                    questions,   misses,   disadvantages   and
                    wishes.  Authors  acknowledge  with thanks
                    and pleasure everybody who participated in
                    guide producing.



                    Our address is:

                         Computing       Center,      prospect
                    Lavrentieva, 6, Novosibirsk, 630090, USSR.
                    Phone: 35-50-67.




Version from 16.10.88

                          Contents


Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
Virtual Modula-2 machine  . . . . . . . . . . . . . . . . .  6
M-code interpreter . . . . . . . . . . . . . . . . . . . .  12
Instruction set manual . . . . . . . . . . . . . . . . . .  25
Processors architecture illustrations . . . . . . . . . . . 73
1. Statements . . . . . . . . . . . . . . . . . . . . . . . 74
   1.1. Assignment  . . . . . . . . . . . . . . . . . . . . 74
   1.2. Access to global variables  . . . . . . . . . . . . 74
   1.3. Access to external variables  . . . . . . . . . . . 75
   1.4. IF statement . . . . . . . . . . . . . . . . . . . .75
   1.5. LOOP statement  . . . . . . . . . . . . . . . . . . 75
   1.6. REPEAT statement  . . . . . . . . . . . . . . . . . 76
   1.7. FOR statement  . . . . . . . . . . . . . . . . . . .76
2. Procedures . . . . . . . . . . . . . . . . . . . . . . . 77
   2.1. Procedure declaration and call  . . . . . . . . . . 77
   2.2. Operation over procedure local data . . . . . . . . 78
   2.3. Nested procedures . . . . . . . . . . . . . . . . . 79
   2.4. External procedure call . . . . . . . . . . . . . . 79
   2.5. Multivalues location  . . . . . . . . . . . . . . . 81
   2.6. Return from module initial part  . . . . . . . . .  81
   2.7. Operation over procedure values  . . . . . . . . .  82
   2.8. Parameter passing . . . . . . . . . . . . . . . . . 88
   2.9. Function call over nonempty stack . . . . . . . . . 85
3. Expressions . . . . . . . . . . . . . . . . . . . . . .  87
   3.1. Word-arrays indexation  . . . . . . . . . . . . . . 87
   3.2. Byte-arrays indexation  . . . . . . . . . . . . . . 87
   3.3. Byte-arrays indexation with range check . . . . . . 88
   3.4. Range check . . . . . . . . . . . . . . . . . . . . 89
   3.5. Operation over BITSET type object . . . . . . . . . 89
   3.6. ANDJP and ORJP instructions  . . . . . . . . . . .  89


                         INTRODUCTION


     The  architecture of KRONOS family processors is oriented
to  the  support  of  the  high-level  languages (C, Modula-2,
Pascal,  Occam) and thereby gives possibility to design modern
conceptions  for  computer  application.  32-bit  machine word
allows  one  to  use  processors  of the family for scientific
research.  The  wide  address  space  (2  billion words) gives
possibility    to    use    virtual   memory   for   designing
object-oriented  models  and  artificial intelligence systems.
The  hardware  support  of  the  interruption handler (for the
events and processes synchronization) and compact code give us
surance   that   the   processors  of  KRONOS  family  may  be
successfully used in the real-time systems.
     Any  processor  of  the  family  may  be used in a single
computer or in a multiprocessing system as well.



                      KRONOS processors


     1.  KRONOS-2  is  the  first  implementation of preceding
concepts.  It  is embedded in "Electronica-60" computer and is
compatible   with  its  peripheral  devices  and  memory.  The
processor  is  designed  on  chips  of 1802, 1804, 155 and 531
series.  In  contrast  to  "Electronica-60", the processor has
32-bit  word,  twice  performance,  and  address  space  which
reaches 4Mbyte.
     2.  KRONOS-2.5  is  the development of KRONOS-2 processor
distinguished  by  higher  performance: 1 million instructions
over  stack per second. Interface with the external devices is
performed via MULTIBUS 1.
     3.   In   KRONOS-2.6  the  possibility  of  using  direct
communication  channels  with  high  capacity  for integration
several  processors  is  expected,  thus  providing  usage  of
processors  2.6 extended by emulators of arithmetic operations
as  the  basis of the system MARS-T. High capacity is provided
by  transputer  organization  of  the  system  and servers and
functional  units included. Processors 2.6 may also be used in
workstations of MARS system.
     Now  the  single-chip  variant  of  KRONOS  processor  is
designed.  The  perspective  of  this  work  are  provided  by
simplicity   of   instruction  set  hardware  design  and  the
necessity  in  personal  computers with high power, supporting
high-level  language programming. Modern element base provides
the  creation  of  systems  with  performance  about 5 million
instructions per second for each transputer element.


                 KRONOS-2.X processors family

     KRONOS-2.X   processors  family  consists  of  processors
having  been  designed  over  different element bases with the
usage of different interface buses. All of them have M-code as
the  instruction  set  and  differ  only  by  performance  and
peripheral control methods.

       Engineering characteristics of KRONOS processors

--------------------------------------------------------------
Processor       |  Kronos 2.2   |  Kronos 2.5   |   Kronos 2.6
                |               |               |
Standard        |  Q-22 (c) DEC |  (c) Intel    | EuroCard E-2
                |               |               |
Number of cards |       1       |       2       |      2-8
                |               |               |
Bus             |    Q-bus 22   |   Multibus-1  |     local
                |               |               |
RAM size        |     4 Mbyte   |   2,5 Mbyte   |    8 Gbyte
                |               |               |
Clock           |               |               |
rate, mHz       |       4       |       3       |        3
                |               |               |
Number of op.   |               |               |
over the stack, |      0,6      |       1       |       1,5
m. per sec.     |               |               |
--------------------------------------------------------------


     This guide gives the entire overview of processors of the
KRONOS  family  architecture. The first chapter introduces the
main  notions  of  architecture.  Chapter "M-code interpreter"
gives declaration in Modula-2 of the processor instruction set
followed   by  comments.  The  volume  is  ended  by  examples
illustrating Modula-2 compiler and processing.


                VIRTUAL  MODULA-2  MACHINE

     The Virtual Modula-2 Machine and its interpreters support
the  process  of program execution. This Chapter characterizes
M-code,  defines  semantics  of  its instructions illustrating
some of them.
     The main differencies of VM2M from traditional machines:
     1)  evaluation  of  expressions on quick stack with small
fixed depth. Blasting of this stack (copying in memory) during
a procedure call;
     2) separation of  code and data  areas  for each  process
which  provides  reenterability  for all programs and even for
their constituents (modules);
     3)  refusal  to  use  absolute  addressing even in a code
segment.  Usage  of  displacement tables of subprogram entries
simplifies their invocations;
     4)  advanced  kinds  of  addressing  reflects  notions of
modern  programming  languages. There is addressing for local,
global, external and intermediate objects;
     5) special instructions simplify implementation of loops,
calls, case statements and some other ones;
     6)   a   table  of  separately  loaded  modules  provides
organizing dynamic loading-linking-execution of programs;
     7) there are multivalue operating instructions.

     Futher it is supposed that reader knows followed Modula-2
notions:
     PROGRAM
     MODULE
     IMPORT-EXPORT of OBJECTS
     GLOBAL VARIABLES
     PROCEDURE
     LOCAL PROCEDURE
     LOCAL VARIABLES

     Input/output essentially depend on implementation and are
not considered here.
     VM2M  consists  of  processor,  stack  for the storage of
values and expressions evaluation (further it is designated as
A-stack),  register-pointer  (P-register),  code  segment  and
data.
     VM2M   Processor   serves   for   data   elaboration  and
interpretation of M-code control instructions.
     A-stack is a quick stack of a small depth (whose elements
are   32-bit   machine   words)  over  which  the  traditional
instructions putting on (Push) and taking (with deleting) from
(Pop) the stack top are defined. Hardware supports control for
stack   overflow/underflow   with  corresponding  interruption
raising.
     VM2M  Memory is considered as a linear sequence of 32-bit
words  each related with 32-bit number - its address. Only the
whole  word  may  be  addressed  (i.e.  a  machine word is the
addressing unit).


        address: 0FFFFF             address: 1      address: 0
       _______________        _______________________________
 .... | 3 | 2 | 1 | 0 | .... | 3 | 2 | 1 | 0 | 3 | 2 | 1 | 0 |
       ---------------        -------------------------------


     The  program which is currently being executed is said to
be a process.
     Such  structures  exist in memory during VM2M processing:
separately-compiled   modules,   procedure   stacks   (further
P-stack),  process descriptors and table of pointers on global
domains  of  loaded  modules  (the so-called global Data Frame
Table - DFT).
     Process  descriptor  consists  of  7  machine words which
contain  pointers to the informational data structures related
with  the  process.  These  pointers  determinate  the process
context,  i.  e.  the  whole  information needed for a current
process  execution by virtual machine. The base address of the
current   process   descriptor   lies  in  P-register  of  the
processor.
     In terms of Modula-2 a process descriptor is the record:

     TYPE Process_Descriptor = RECORD
                                 F, PC, G, H, S, L, M: WORD;
                               END;

     Every  descriptor  field  has a special purpose, which is
described  below. Further descriptor fields will be called for
conveniency  as processor registers (e.g. "G-register" instead
of "Process_Descriptor.G").
     Note.  The existing implementation of VM2M (processors of
KRONOS  family)  in  fact  have  specialized  registers  which
contain  copies of corresponding fields of the current process
descriptor  during  the execution time. When process switching
takes  place,  register  contents is copied in memory starting
from the address contained in P-register.
     Module which is loaded in memory and ready for  execution
consists of code segment,  global data area,  constant area of
composite types, i.e. strings, arrays,  records (string pool),
external module link  area - local DFT (if module contains
object import).
     Code  segment  occupies contiguous area and has a complex
structure.  Procedure table (up to 256 words) lies at the top.
It  contains displacements in bytes between a segment base and
the  origin  of  the  corresponding procedure. Thus, the inner
procedure  is precisely identified by its number in the module
procedure  table. During the execution of the inner procedure,
F-register  contains  a  pointer  to the code segment base. PC
(Program  Counter)  contains  offset in bytes between the code
segment base and byte which contains the next instruction.
     Global  data area of module occupies a contiguous area of
words.  The  single-word data are stored there immediately but
composite  variables are represented with the help of pointers
in  special  areas  of memory. G-register points to the global
data  area  base  of  a current module. Thus, access to module
global  variables  is organized as G-register indexation, i.e.
the global word with number 3 is situated in the cell with the
address  [G]+3 ([REG] denotes contents of register "REG"). The
first  two  words  of  the  global  data  area contain special
information: the lower word (its address equals 0) of the area
contains  the  pointer  to the code segment base of the module
(copy of F-register) and the next word contains pointer to the
string pool base.
     String  pool  occupies a contiguous area and contains
literals  of  composite  types (strings, arrays, records). The
first word (it offset equals 1) of the module global data area
points  to  the  string pool base.
     External module link area (local DFT) occupies contiguous
area  and  may  be  represented  as  an  array of words, whose
elements  contain  pointer  to  elements  of  the  global  DFT
referring to the global data area base of the external module.
Thus,  external  modules may be identified by the index in the
module  local  DFT,  i.  e.  DFT[i]  contains the address of a
pointer to the global data area of i-th external module.
     Local  DFT  is  situated  immediately  before  the module
global  data  area,  i.e.  the  element  DFT[i] address equals
[G]-i-1.   Remark:  such  organization  of  information  gives
possibility   to   access   to  statically  existing  entities
(procedures, variables, i.e. external module objects which may
be imported), only knowing the address of the global data area
base.
     P-stack  is  used  for  procedure local data location and
organization  of  procedure  calls and return from them. Three
processor  registers  point to stack: S-register points to the
top  of  the  P-stack,  i.e.  the  first  free  P-stack  word.
H-register  points  to  the  upper  word  in  the storage area
reserved for stack (limit for S increasing). L-register points
to  the  local  data area base of the procedure which is being
executed  (current  procedure). The overlap of the registers S
and  H  (i.e.  situation  when  [S]>=[H]) is determined at the
hardware level with raising corresponding interruption.
     Current  procedure  local  data  area  is  stored  in the
P-stack  and  represents  a  sequence  of  words which contain
either  single-word  local  variables or pointers to a storage
area  base  allocated for variables of composite types. Access
to  the  local  data is performed as indexation of L-register,
i.e.   i-th  word  has  [L]+i  address.  Special  instructions
simplify access to words with numbers from 4 to 255.
     The  first  four  local  words  (with  numbers  0..3) are
reserved for special aims: the lower word points either to the
local  data  area  base  of  the enveloping procedure (i.e.the
procedure  which  immediately contains a current procedure) or
on  a  calling  module  global  data  area if the procedure is
called  from the external module (static chain). The next word
points  to the data area base of the procedure which calls the
current  one (dynamic chain). The next word contains the value
for  PC  returning.  In the last word, the processor interrupt
mask   is   saved  (see  remark  for  scheme  (1)  and  M-code
interpreter).
     Scheme  (1)  illustrates  code and statical and dynamical
data organization of process.


     DFT                                           Scheme 1
|------------|
|            |<------                            <-32 bits->
|------------|       |
|       *----+--     |    |----------|     ___   |--------|
|------------| |      ----+-----*    |  --| F |->|proc0 *-+--
|  Global    | |         :|----------|  |  ---   |--------|  |
:   area     : |        01| Module   |  |        |proc1 *-+--+-
:  tables    : |        00|   DFT    |  |        |--------|  | |
|____________| |   ___    |==========|  |        :  ...   :  | |
                --| G |-->|    *-----+--         |========|  | |
|------------|     ---    |----------|           | proc0  |<-- |
|            |            |    *-----+-----      | code   |    |
|------------|            |==========|     |     |        |    |
:            :         02 |  Module  |     |     |        |    |
:            :         03 |  global  |     |     |--------|    |
|------------|         04 |   data   |     |     | proc1  |<---
|            |          : :          :     |     | code   |
|____________|         FF |__________|     |     |--------|
<-- 32 bits-->            <- 32 bits->     |     :  ...   :
                                           |     |________|
         --------------         ------------     <- 8 bits->
| P |-->|   Process    |       |
 ---    |  descriptor  |       |  |---------------------------|
        | (processor   |        ->| structured type constants |
        |  registers   |          | (arrays, records, strings)|
        |    copy)     |          |___________________________|
        |--------------|
        \/\/\/\/\/\/\/\/
                        <-----
                        <--   |
         /\/\/\/\/\/\/\    |  |
        |--------------|   |  |         |          |  \
| L |-->|   static     |   |  |         |expression|   |
 ---  00|   chain  *---+------          |  stack   |   | 7 words
        |--------------|   |            |          |   |
        |   dynamic    |   |            |          |   |
      01|   chain  *---+---             |__________|  /
        |--------------|                <-32 bits->
        |   Saved      |
      02|    PC      ')|
        |--------------|   ___
      03|  M   mask  ")|  | r | -- Processor registers.
        |--------------|   ---
      04|  Procedure   |     ') -- In case of call from external
      05|   local      |           module, L2 has a mark,and the
       ::    data      :           word  L0  contains G-register
      FF|              |           instead of a static chain.
| S |-->|--------------|
 ---    |              |     ") -- Current  mask is saved in this
        :              :           word   only   when  the  first
 ___    |______________|           change  within procedure takes
| H |--><--- 32 bits--->           place, which is  marked  in L2
 ---                               too.                          *)


     VM2M  code  (M-code)  represents  the  byte  stream, i.e.
opcode  always  occupies a single byte. VM2M instructions have
no  address  fields,  but opcode determines where operands are
situated. The following addressing modes are used in VM2M:

local            : address = [L] + N
global           : address = [G] + N
external         : address = DFT[M]^ + N
intermediate     : address = {[L]^} + N OR [[L]^]^ + N OR ...
indirect         : address = [POP()]^ + N,

where  M  is the external module number, N - object index, "^"
symbol denotes indirection operator.
     Intermediate  addressing  mode  represents  the access to
non-local variables in procedure and realizes the pass through
the procedure static chain.
     Some  instructions  contain  from  4  bits  to 4 bytes of
immediate  operands,  and  opcode  always determines the total
length  of  immediate  addresses following it. Program counter
(PC)  increments  from  1  to  4  bytes  in  dependence on the
instruction mode.
     VM2M  instructions  may  be  divided  into  the groups as
follows:     arithmetical-logical     instructions,    control
organization    instructions,   instructions   over   A-stack,
auxiliary instructions.
     Stack instructions contain constant loading instructions,
instructions of stack exchang with local, global, external and
other data.
     All arithmetical-logical instructions operate over one or
two stack elements and store the result again on the stack.
     Control  organization  instructions  are  represented  by
conventional  conditional and unconditional jump instructions,
special instructions for implementing FOR and CASE statements,
procedure   calling  and  returning  instructions.  They  also
include instructions TRAP and TRANSFER (for process switch).
     There are different modes of procedure parameter passing.
In  this  implementation parameter passing is realized through
the   arithmetical   stack,   which  reduces  consumptions  on
parameter processing during procedure call.
     All  interruptions  are  handled  as  switching  of those
processes  whose  pointers  are contained in the corresponding
interrupt  vector  elements  (i.e. the element index equals to
the interruption number).
     VM2M   has   a   collection   of  auxiliary  instructions
simplifying  processing  of multivalues, procedure parameters,
I/O instructions and so on.
     More comprehensive information about VM2M may be obtained
after  the  search  of  M-code  interpreter program text which
plays  the role of microprogram specification of KRONOS family
processors.


(*            THE  KRONOS  2.X   PROCESSOR  FAMILY

                        INSTRUCTION SET

     00      20      40      60      80      A0      C0      E0

00   LI0     LLW     LXB     LSW0            LSS     MOVE    INCL
01   LI1     LGW     LXW     LSW1    QUIT    LEQ     RDS     EXCL
02   LI2     LEW     LGW2    LSW2    GETM    GTR     LSTA    SLEQ
03   LI3     LSW     LGW3    LSW3    SETM    GEQ     COMP    SGEQ
04   LI4     LLW4    LGW4    LSW4    TRAP    EQU     GB      INC1
05   LI5     LLW5    LGW5    LSW5    TRA     NEQ     GB1     DEC1
06   LI6     LLW6    LGW6    LSW6    TR      ABS     CHK     INC
07   LI7     LLW7    LGW7    LSW7    IDLE    NEG     CHKZ    DEC

08   LI8     LLW8    LGW8    LSW8    ADD     OR      ALLOC   STOT
09   LI9     LLW9    LGW9    LSW9    SUB     AND     ENTR    LODT
0A   LI0A    LLW0A   LGW0A   LSW0A   MUL     XOR     RTN     LXA
0B   LI0B    LLW0B   LGW0B   LSW0B   DIV     BIC     NOP     LPC
0C   LI0C    LLW0C   LGW0C   LSW0C   SHL     IN      CX     *BBU
0D   LI0D    LLW0D   LGW0D   LSW0D   SHR     BIT     CI     *BBP
0E   LI0E    LLW0E   LGW0E   LSW0E   ROL     NOT     CF    **BBLT
0F   LI0F    LLW0F   LGW0F   LSW0F   ROR     MOD     CL

10   LIB     SLW     SXB     SSW0 ***IO0     DECS    CL0     SWAP
11   LID     SGW     SXW     SSW1    IO1     DROP    CL1     LPA
12   LIW     SEW     SGW2    SSW2    IO2     LODFV   CL2     LPW
13   LIN     SSW     SGW3    SSW3    IO3     STORE   CL3     SPW
14   LLA     SLW4    SGW4    SSW4    IO4     STOFV   CL4     SSWU
15   LGA     SLW5    SGW5    SSW5    IO5     COPT    CL5
16   LSA     SLW6    SGW6    SSW6    IO6     CPCOP   CL6
17   LEA     SLW7    SGW7    SSW7    IO7     PCOP    CL7

18   JFLC    SLW8    SGW8    SSW8    FADD    FOR1    CL8
19   JFL     SLW9    SGW9    SSW9    FSUB    FOR2    CL9
1A   JFSC    SLW0A   SGW0A   SSW0A   FMUL    ENTC    CL0A    ACTIV
1B   JFS     SLW0B   SGW0B   SSW0B   FDIV    XIT     CL0B    USR
1C   JBLC    SLW0C   SGW0C   SSW0C   FCMP    ENTS    CL0C    SYS
1D   JBL     SLW0D   SGW0D   SSW0D   FABS            CL0D   *NII
1E   JBSC    SLW0E   SGW0E   SSW0E   FNEG    ORJP    CL0E
1F   JBS     SLW0F   SGW0F   SSW0F   FFCT    ANDJP   CL0F    INVLD


  * -- Not implemented in KRONOS 2.2.
 ** -- Not implemented.
*** -- Instructions IO0..IO7 define the bus-processor interface.

----------------------------------------------------------------
(c) COPYRIGHT KRONOS Research Group      1985,1986,1987

    Last modification                    30-Aug-1987     *)


MODULE Kronos_Interpreter;  (* Leo 27-Nov-85. (c) KRONOS *)
                            (* Ned 30-Aug-87. (c) KRONOS *)

(* This interpreter is hardware specification. *)

FROM SYSTEM    IMPORT  ADDRESS, WORD, ADR;
FROM KRONOS    IMPORT  ROR, ROL, SHR, SHL;

TYPE CPUs = (KRONOS2_2, KRONOS2_5, KRONOS2_6);

VAR cpu: CPUs;

CONST ESdepth = 7; (* Expression stack depth *)

TYPE
  BYTE     = [0..255];
  WORD16   = [0..0FFFFh];
  PC_Range = WORD16;
  CodePtr  = POINTER TO ARRAY PC_Range OF BYTE;

VAR
  PC:    PC_Range;    (* program counter *)
  IR:    [0..0FFh];   (* instruction register *)
  F :    CodePtr;     (* code segment address *)
  G :    ADDRESS;     (* global data segment address *)
  L :    ADDRESS;     (* local data segment address *)
  S :    ADDRESS;     (* P-stack top address *)
  H :    ADDRESS;     (* P-stack bound *)
  P :    ADDRESS;     (* process descriptor address *)
  M :    BITSET;      (* interrupt mask *)
  Ipt:   BOOLEAN;     (* interrupt request *)
  IptNo: WORD16;      (* interrupt number *)

(* Hardware fixed interrupt numbers:

   01h    timer
   02h    processor halt
   03h    memory violation
   04h    power crash
   05h    processor error
   06h    interrupt vector input error
   07h    unimplemented instruction
   08h    on procedure call        (KRONOS 2.2)
   09h    on procedure return      (KRONOS 2.2)

   0Bh    trace (interrupt on each instruction) (KRONOS 2.5,2.6)

   40h    P-stack overflow (S>H)
   41h    integer overflow
   42h    floating overflow
   43h    floating underflow
   44h    address overflow

   49h    instruction INVLD
   4Ah    check bounds error
   4Bh    wrong instruction parameter (hardware ASSERT)
   4Ch    expression stack overflow or underflow

   Note  1.  See  the procedure NotMasked for interrupts masking
   method.

   Note  2.  If  there  are  processor  models in brackets, then
   interrupt raises only for these models.
*)

CONST  (* bit numbers in the word L2 (see fig.) *)
  ExternalBit   = 1Fh;
  ChangeMaskBit = 1Eh;

CONST
  NonVectBit = 1Fh; (* bit masking program interrupts *)

(* Note.  H-register  contains  the  stack  bound decremented on
   ESdepth+1  words  to  save  the  expression  stack on process
   transfer.
*)

VAR Core: ARRAY ADDRESS OF WORD;
    ByteCore: ARRAY OF BYTE; (* combined with Core *)

MODULE InstructionFetch;

  IMPORT F, PC, WORD, WORD16, BYTE, Core, ADDRESS;
  EXPORT Next, Next2, Next4, GetPc;

  PROCEDURE Next(): BYTE;
  BEGIN INC(PC); RETURN INTEGER(F^[PC-1])
  END Next;

  PROCEDURE Next2(): WORD16;
  BEGIN RETURN Next()+Next()*100h
  END Next2;

  PROCEDURE Next4(): WORD;
  BEGIN RETURN Next2()+Next2()*10000h
  END Next4;

  PROCEDURE GetPc(procno: INTEGER): INTEGER;
  (* Gives PC at a procedure entry *)
  BEGIN RETURN Core[ADDRESS(F)+procno]
  END GetPc;

END InstructionFetch;

MODULE Mask;
  IMPORT M, NonVectBit, BYTE;
  EXPORT NotMasked;

  PROCEDURE NotMasked(N: BYTE): BOOLEAN;
  BEGIN
    IF    (N>=0Fh) & (N<3Fh)  THEN RETURN (0 IN M)
    ELSIF (N< 0Fh) & (N>0)    THEN RETURN (0 IN M) & (N IN M)
    ELSIF (N =3Fh)            THEN RETURN (NonVectBit IN M)
    ELSE ASSERT(FALSE)
    END
  END NotMasked;

END Mask;

MODULE ExpressionStack;
  IMPORT WORD, ESdepth, Ipt, IptNo;
  EXPORT Push, Pop, Empty;

  VAR A: ARRAY [0..ESdepth-1] OF WORD;  sp: [0..ESdepth];

  PROCEDURE Push(X: WORD);
  BEGIN A[sp]:=X;
    IF sp<ESdepth THEN INC(sp) ELSE Ipt:=TRUE; IptNo:=4Ch END;
  END Push;

  PROCEDURE Pop(): INTEGER;
  BEGIN
    IF sp=0 THEN Ipt:=TRUE; IptNo:=4Ch ELSE DEC(sp) END;
    RETURN A[sp];
  END Pop;

  PROCEDURE Empty(): BOOLEAN;
  BEGIN RETURN sp=0 END Empty;

BEGIN sp:=0 END ExpressionStack;

MODULE ProcessSupport;
  IMPORT PC,G,F,H,L,S,P,M, Core, NotMasked, ESdepth
       , CodePtr, WORD16, ADDRESS;
  FROM ExpressionStack IMPORT Pop, Push, Empty;

  EXPORT SaveExpStack, RestoreExpStack, Transfer, TRAP;

  PROCEDURE SaveExpStack;
    VAR c: CARDINAL; (* stack depth counter *)
  BEGIN c:=0;
    WHILE NOT Empty() DO Core[S]:=Pop(); INC(S); INC(c) END;
    Core[S]:=c; INC(S);
  END SaveExpStack;

  PROCEDURE RestoreExpStack;
    VAR c: CARDINAL; (* stack depth counter *)
  BEGIN DEC(S); c:=Core[S];
    WHILE c>0 DO DEC(c); DEC(S); Push(Core[S]) END;
  END RestoreExpStack;


  PROCEDURE SaveRegs;
  BEGIN SaveExpStack;
    Core[P+0]:=G;  Core[P+1]:=L;
    Core[P+2]:=PC; Core[P+3]:=CARDINAL(M);
    Core[P+4]:=S;  Core[P+5]:=H+ESdepth+1;  
  END SaveRegs;

  PROCEDURE RestoreRegs;
  BEGIN
    G:=Core[P+0];    F :=CodePtr(Core[G]);
    L:=Core[P+1];    PC:=Core[P+2];  M:=BITSET(Core[P+3]);
    S:=Core[P+4];    H:=Core[P+5]-ESdepth-1;
    RestoreExpStack;
  END RestoreRegs;

  PROCEDURE Transfer(pFrom,pTo: ADDRESS);
    VAR j: CARDINAL;
  BEGIN (* Note: pFrom may be equal to pTo *)
    j:=Core[pTo]; SaveRegs; Core[pFrom]:=P; Core[1]:=P;
    P:=j;         RestoreRegs;              Core[0]:=P;
  END Transfer;

  PROCEDURE TRAP(N: WORD16);
  BEGIN Core[P+6]:=N;
    IF N>3Fh THEN N:=3Fh END;
    IF NotMasked(N) THEN Transfer(N*2,Core[N*2+1]) END;
  END TRAP;

END ProcessSupport;

(* P-stack marking before a procedure call *)

PROCEDURE  Mark(X: ADDRESS; External: BOOLEAN);
  VAR i: ADDRESS;
BEGIN i:=S;
  Core[S]:=X; INC(S); (* static chain *)
  Core[S]:=L; INC(S); (* dynamic chain *)
  IF External THEN Core[S]:=WORD(BITSET(PC)+{ExternalBit})
  ELSE             Core[S]:=PC
  END; INC(S,2); L:=i;
END Mark;

PROCEDURE ioP2_2;
BEGIN ASSERT(IR-90h IN {0..7});
(* See KRONOS 2.2 specification *)
END ioP2_2;

PROCEDURE ioP2_5;
BEGIN ASSERT(IR-90h IN {0..7});
(* Input/output requests transmitted to other processors via the
   common memory.
*)
END ioP2_5;

PROCEDURE ioP2_6;
BEGIN ASSERT(IR-90h IN {0..7});
(* Depends on a bus *)
END ioP2_6;

(* Working variables of interpreter: *)

VAR i,j,k: CARDINAL;   X,Y  : REAL;
    v,w  : BITSET;     a,b  : CHAR;
    adr,adr1,sz,hi,low: CARDINAL;

PROCEDURE ConsolMicroProgram;
BEGIN
(* Consol  microprogram  provides program bootstrap and executes
   Transfer(0,1) by the operator's command "Go".
*)
END ConsolMicroProgram;

PROCEDURE Interpret;
BEGIN
  CASE IR OF
   00h..0Fh:(* LI0..LI0F  Load Immediate *) Push(IR MOD 10h);

  |10h: (* LIB  Load Immediate Byte *) Push(Next())
  |11h: (* LID  Load Immediate Double byte *) Push(Next2())
  |12h: (* LIW  Load Immediate Word *) Push(Next4())
  |13h: (* LIN  Load Immediate NIL  *) Push(NIL)
  |14h: (* LLA  Load Local  Address *) Push(L+Next())
  |15h: (* LGA  Load Global Address *) Push(G+Next())
  |16h: (* LSA  Load Stack  Address *) Push(Pop()+Next())
  |17h: (* LEA  Load External Addres *)
        i:=G-Next()-1; (* Module DFT index *)
        adr:=Core[i]; (* Pointer to a global DFT element *)
        Push(Core[adr]+Next())
  |18h: (* JLFC Jump Long  Forward Condition *)
        IF Pop()=0 THEN PC:=Next2()+PC
        ELSE INC(PC,2) END
  |19h: (* JLF  Jump Long  Forward *) PC:=Next2()+PC;
  |1Ah: (* JSFC Jump Short Forward Condition *)
        IF Pop()=0 THEN PC:=Next()+PC
        ELSE INC(PC) END
  |1Bh: (* JSF  Jump Short Forward *) PC:=Next()+PC;
  |1Ch: (* JLBC Jump Long  Back    Condition *)
        IF Pop()=0 THEN PC:=-Next2()+PC
        ELSE INC(PC,2) END
  |1Dh: (* JLB  Jump Long  Back    *) PC:=-Next2()+PC;
  |1Eh: (* JSBC Jump Short Back    Condition *)
        IF Pop()=0 THEN PC:=-Next()+PC
        ELSE INC(PC) END
  |1Fh: (* JSB  Jump Short Back    *) PC:=-Next()+PC;
  |20h: (* LLW  Load Local  Word *)  Push(Core[L+Next()])
  |21h: (* LGW  Load Global Word *)  Push(Core[G+Next()])
  |22h: (* LEW  Load External Word *)
        i:=G-Next()-1; adr:=Core[Core[i]]; (* external G *)
        Push(Core[adr+Next()])
  |23h: (* LSW  Load Stack addressed Word *)
         Push(Core[Pop()+Next()])
  |24h..2Fh: (* LLW0..LLW0F Load Local Word *)
        Push(Core[L+IR MOD 10h])
  |30h: (* SLW  Store Local  Word *)  Core[L+Next()]:=Pop()
  |31h: (* SLW  Store Global Word *)  Core[G+Next()]:=Pop()
  |32h: (* SEW  Store External Word *)
        i:=G-Next()-1; adr:=Core[Core[i]]; (* external G *)
        Core[adr+Next()]:=Pop()
  |33h: (* SSW  Store Stack addressed Word *)
        i:=Pop(); Core[Pop()+Next()]:=i
  |34h..3Fh: (* SLW0..SLW0F  Store Local Word *)
        Core[L+IR MOD 10h]:=Pop()

  |40h: (* LXB  Load Indexed Byte *)
        i:=Pop(); Push(ByteCore[Pop()*4+i]);
  |41h: (* LXW  Load Indexed Word *)
        i:=Pop(); Push(Core[Pop()+i])
  |42h..4Fh: (* LGW02..LGW0F  Load Global Word *)
        Push(Core[G+IR MOD 10h])
  |50h: (* SXB  Store Indexed Byte *)
        j:=Pop(); i:=Pop(); ByteCore[Pop()*4+i]:=j;
  |51h: (* SXW  Store Indexed Word *)
        j:=Pop(); i:=Pop(); Core[Pop()+i]:=j
  |52h..5Fh: (* SGW02..SGW0F  Store Global Word *)
        Core[G+IR MOD 10h]:=Pop()

  |60h..6Fh: (* LSW00..LSW0F  Load  Stack addressed Word *)
        Push(Core[Pop()+IR MOD 10h])
  |70h..7Fh: (* SSW00..SSW0F  Store Stack addressed Word *)
        i:=Pop(); Core[Pop()+IR MOD 10h]:=i

  |80h: TRAP(7h);
  |81h: (* QUIT   Stop processor *) ConsolMicroProgram
  |82h: (* GETM   Get Mask *) Push(M)
  |83h: (* SETM   Set Mask *)
        IF NOT (ChangeMaskBit IN BITSET(Core[L+2])) THEN
          (* mask is changed the first time *)
          Core[L+2]:=WORD(BITSET(Core[L+2])+{ChangeMaskBit});
          Core[L+3]:=WORD(M)
        END; M:=BITSET(Pop);
  |84h: (* TRAP  interrupt simulation *)  TRAP(Pop())
  |85h: (* TRA   Transfer control between process *)
        i:=Pop(); Transfer(Pop(),i)
  |86h: (* TR    Test & Reset *)
        i:=Pop(); Push(Core[i]); Core[i]:=0
  |87h: (* IDLE  IDLE process *)
        DEC(PC); REPEAT (* not occupying the bus *) UNTIL Ipt

(* In  the  following  six instructions and also in instructions
   MOD,  NEG,  ABS,  FOR2,  INC,  DEC,  INC1, DEC1 the interrupt
   IptNo=41h is raised in case of overflow.
*)
  |88h: (* ADD  integer ADD *) Push(Pop()+Pop())
  |89h: (* SUB  integer SUB *) i:=Pop(); Push(Pop()-i);
  |8Ah: (* MUL  integer MUL *) Push(Pop()*Pop())
  |8Bh: (* DIV  integer DIV *) i:=Pop(); Push(Pop() DIV i)
  |8Ch: (* SHL  integer SHift Left *)
        i:=Pop() MOD 20h; Push(SHL(Pop(),i))
  |8Dh: (* SHR  integer SHift Right *)
        i:=Pop() MOD 20h; Push(SHR(Pop(),i))

  |8Eh: (* ROL  word ROtate Left  *)
        i:=Pop() MOD 20h; Push(ROL(Pop(),i))
  |8Fh: (* ROR  word ROtate Right *)
        i:=Pop() MOD 20h; Push(ROR(Pop(),i))
  |90h..97h: (* io section *)
        CASE cpu OF
          |KRONOS2_2: ioP2_2
          |KRONOS2_5: ioP2_5
          |KRONOS2_6: ioP2_6
        ELSE ASSERT(FALSE);
        END

(* In the following eight instructions the interrupts 42h or 43h
   are   raised  respectively  in  case  of  overflow  or  order
   underflow.
*)
  |98h: (* FADD  Float ADD *) Push(REAL(Pop())+REAL(Pop()))
  |99h: (* FSUB  Float SUB *) X:=REAL(Pop()); Push(REAL(Pop())-X)
  |9Ah: (* FMUL  Float MUL *) Push(REAL(Pop())*REAL(Pop()))
  |9Bh: (* FDIV  Float DIV *) X:=REAL(Pop()); Push(REAL(Pop())/X)
  |9Ch: (* FCMP  Float CoMPare *) X:=REAL(Pop()); Y:=REAL(Pop());
        IF    X<Y THEN Push(1); Push(0)
        ELSIF X>Y THEN Push(0); Push(1)
        ELSE Push(0); Push(0) END
  |9Dh: (* FABS  Float ABS *) X:=REAL(Pop());
        IF X<0.0 THEN Push(-X) ELSE Push(X) END
  |9Eh: (* FNEG  Float NEG *) Push(-REAL(Pop()))
  |9Fh: (* FFCT  Float FunCTions *) i:=Next();
        IF    i=0 THEN Push(FLOAT(INTEGER(Pop())))
        ELSIF i=1 THEN Push(TRUNC(   REAL(Pop())))
        ELSE DEC(PC); TRAP(7h) END;

 |0A0h: (* LSS  int LeSS             *) i:=Pop(); Push(Pop()<i)
 |0A1h: (* LEQ  int Less    or EQual *) i:=Pop(); Push(Pop()<=i)
 |0A2h: (* GTR  int GreaTeR          *) i:=Pop(); Push(Pop()>i)
 |0A3h: (* GEQ  int Greater or EQual *) i:=Pop(); Push(Pop()>=i)
 |0A4h: (* EQU  int EQUal     *) Push(Pop()=Pop())
 |0A5h: (* NEQ  int Not EQual *) Push(Pop()#Pop())
 |0A6h: (* ABS  int ABSolute value *) Push(ABS(Pop()))
 |0A7h: (* NEG  int NEGate         *) Push(-Pop())

 |0A8h: (* OR   logical bit per bit OR *)
        v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w+v)
 |0A9h: (* AND  logical bit per bit AND *)
        v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w*v)
 |0AAh: (* XOR  logical bit per bit XOR *)
        v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w/v)
 |0ABh: (* BIC  logical bit per bit BIt Clear *)
        v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w-v)
 |0ACh: (* IN   membership to bitset *)
        v:=BITSET(Pop()); Push(Pop() IN v)
 |0ADh: (* BIT  setBIT *) i:=Pop();
        IF (i<0) OR (i>=20h) THEN TRAP(4Ah)
        ELSE w:={}; INCL(w,i); Push(w) END

 |0AEh: (* NOT  boolean NOT (not bit per bit!) *) Push(Pop()=0)
 |0AFh: (* MOD  integer MODulo *) i:=Pop(); Push(Pop() MOD i)

 |0B0h: (* DECS  DECriment S register (reverse to ALLOC) *) 
        DEC(S,Pop())
 |0B1h: (* DROP *) i:=Pop();
 |0B2h: (* LODF  reLOaD expr. stack after Function return *)
        i:=Pop(); RestoreExpStack; Push(i)
 |0B3h: (* STORE STORE expr. stack before function call *)
        IF S+ESdepth+1>H THEN DEC(PC); TRAP(40h)
        ELSE SaveExpStack
        END
 |0B4h: (* STOFV STOre expr. stack with Formal function Value
           on top before function call (see instruction CF)
         *)
        IF S+ESdepth+2>H THEN DEC(PC); TRAP(40h)
        ELSE i:=Pop(); SaveExpStack; Core[S]:=i; INC(S) END
 |0B5h: (* COPT  COPy Top of expr. stack *)
        i:=Pop(); Push(i); Push(i)
 |0B6h: (* CPCOP Character array Parameter COPy *)
        i:=Pop(); (* High *) sz:=(i+4) DIV 4;
        IF S+sz>H THEN Push(i); DEC(PC); TRAP(40h)
        ELSE Core[L+Next()]:=S; adr:=Pop();
          WHILE sz>0 DO Core[S]:=Core[adr]; INC(S); INC(adr) END
        END
 |0B7h: (* PCOP  structure Parameter allocate and COPy *)
        i:=Pop(); (* High *) sz:=i+1;
        IF S+sz>H THEN Push(i); DEC(PC); TRAP(40h)
        ELSE Core[L+Next()]:=S; adr:=Pop();
          WHILE sz>0 DO Core[S]:=Core[adr]; INC(S); INC(adr) END
        END
 |0B8h: (* FOR1  enter  FOR statement *)
        IF S+2>H THEN DEC(PC); TRAP(40h)
        ELSE sz:=Next(); (* =0 up; #0 down *)
          hi:=Pop(); low:=Pop(); adr:=Pop(); k:=Next2()+PC;
          IF ((sz=0) & (low<=hi)) OR ((sz#0) & (low>=hi)) THEN
            Core[adr]:=low;
            Core[S]:=adr; INC(S); Core[S]:=hi; INC(S);
          ELSE (* loop isn't executed *) PC:=k
          END
        END
 |0B9h: (* FOR2  end of FOR statment *)
        hi:=Core[S-1]; adr:=Core[S-2]; sz:=Next();
        IF sz>7Fh THEN sz:=7Fh-sz END; (* step [-128..127] *)
        k:=-Next2()+PC;  i:=Core[adr]+sz;
        IF ((sz>=0) & (i>hi)) OR ((sz<0) & (i<hi)) THEN
          DEC(S,2); (* terminate *)
        ELSE Core[adr]:=i; PC:=k (* continue *)
        END
 |0BAh: (* ENTC  ENTer Case statment *)
        IF S+1>H THEN DEC(PC); TRAP(40h)
        ELSE PC:=Next2()+PC; (* jump to case table *)
          k:=Pop(); low:=Next2(); hi:=Next2();
          Core[S]:=PC + 2*(hi-low) + 4; INC(S); (* PC for exit *)
          IF (k>=low) & (k<=hi) THEN
            PC:=PC+2*(k-low+1) (* jump into case table *)
          END;
          PC:=-Next2()+PC (* jump back to variant's code *)
        END
 |0BBh: (* XIT  eXIT from case or control structure *)
        DEC(S); PC:=Core[S]
 |0BCh: (* ENTS ENTer control Structure *)
        IF S+1>H THEN DEC(PC); TRAP(40h)
        ELSE Core[S]:=Next2()+PC; INC(S) END
 |0BEh: (* ORJP   short circuit OR  JumP *)
        IF Pop()#0 THEN Push(1); PC:=Next()+PC
        ELSE INC(PC) END
 |0BFh: (* ANDJP  short circuit AND JumP *)
        IF Pop()=0 THEN Push(0); PC:=Next()+PC
        ELSE INC(PC) END

 |0C0h: (* MOVE   MOVE block *) sz:=Pop();
        i:=Pop(); j:=Pop();
        WHILE sz>0 DO
          Core[j]:=Core[i]; INC(i); INC(j); DEC(sz)
        END
 |0C1h: (* RDS  ReaD String *) sz:=Next();
        IF sz>20h THEN DEC(PC,2); TRAP(4Bh)
        ELSE adr:=Pop();
          WHILE sz>0 DO Core[adr]:=Next4(); INC(adr); DEC(sz) END
        END
 |0C2h: (* LSTA  Load STring Address *) Push(Core[G+1]+Next2());
 |0C3h: (* COMP  COMPare strings *) i:=Pop()*4; j:=Pop()*4;
        REPEAT a:=CHAR(ByteCore[i]); b:=CHAR(ByteCore[j]);
        INC(i); INC(j)
        UNTIL (a=0c) OR (b=0c) OR (a#b); Push(a); Push(b)
 |0C4h: (* GB  Get procedure Base n levels down *)
        i:=L; k:=Next();
        WHILE k>0 DO i:=Core[i]; DEC(k) END; Push(i)
 |0C5h: (* GB1 Get procedure Base 1 level down *) Push(Core[L])
 |0C6h: (* CHK   range bounds CHecK *)
        hi:=Pop(); low:=Pop(); i:=Pop(); Push(i);
        IF (i<low) OR (i>hi) THEN
          Push(low); Push(hi); TRAP(4Ah)
        END
 |0C7h: (* CHKZ  array bounds CHecK (low=Zero) *)
        hi:=Pop(); i:=Pop(); Push(i);
        IF (i<0) OR (i>hi) THEN Push(hi); TRAP(4Ah) END
 |0C8h: (* ALLOC ALLOCate block *) sz:=Pop();
        IF S+sz>H THEN  Push(sz); DEC(PC); TRAP(40h)
        ELSE Push(S); INC(S,sz) END
 |0C9h: (* ENTR  ENTeR procedure *) sz:=Next();
        IF S+sz>H THEN DEC(PC,2); TRAP(40h)
        ELSE INC(S,sz) END
 |0CAh: (* RTN   ReTurN from procedure *)
        S:=L; L:=Core[S+1]; PC:=WORD(BITSET(Core[S+2])*{0..0Fh});
        IF ExternalBit IN BITSET(Core[S+2]) THEN
          (* external called *)
          G:=Core[S]; F:=CodePtr(Core[G])
        END;
        IF ChangeMaskBit IN BITSET(Core[S+2]) THEN
          (* mask was changed *)
          M:=BITSET(Core[S+3])*{0..10h}
        END;
 |0CBh: (* NOP   No OPeration  *)
 |0CCh: (* CX    Call eXternal *)
        IF S+4<=H THEN j:=Core[G-Next()-1]; (* big DFT *)
          i:=Next(); Mark(G,TRUE);
          G:=Core[j]; F:=CodePtr(Core[G]); PC:=GetPc(i);
        ELSE DEC(PC); TRAP(40h) END
 |0CDh: (* CI    Call procedure at Intermediate level *)
        IF S+4<=H THEN
          i:=Next(); Mark(Pop(),FALSE); PC:=GetPc(i);
        ELSE DEC(PC); TRAP(40h) END
 |0CEh: (* CF    Call Formal procedure *)
        IF S+3<=H THEN i:=Core[S-1]; DEC(S); Mark(G,TRUE);
          k:=i DIV 1000000h; i:=i MOD 1000000h;
          G:=Core[i]; F:=CodePtr(Core[G]); PC:=GetPc(k);
        ELSE DEC(PC); TRAP(40h) END
 |0CFh: (* CLN
0CПo LСal procedure *)
        IF S+4<=H THEN i:=Next(); Mark(L,FALSE); PC:=GetPc(i);
        ELSE DEC(PC); TRAP(40h) END
 |0D0h..0DFh: (* CL0..CL0F  Call Local procedure *)
        IF S+4<=H THEN Mark(L,FALSE); PC:=GetPc(IR MOD 10h);
        ELSE DEC(PC); TRAP(40h) END
 |0E0h: (* INCL  INCLude in set *)  i:=Pop();
        IF (i<0) OR (i>1Fh) THEN Push(i); DEC(PC); TRAP(4Ah)
        ELSE j:=Pop(); w:=BITSET(Core[j]); INCL(w,i);
          Core[j]:=CARDINAL(w)
        END
 |0E1h: (* EXCL  EXCLude from set *)  i:=Pop();
        IF (i<0) OR (i>1Fh) THEN Push(i); DEC(PC); TRAP(4Ah)
        ELSE j:=Pop(); w:=BITSET(Core[j]); EXCL(w,i);
          Core[j]:=CARDINAL(w)
        END
 |0E2h: (* SLEQ  bitSet Less    or EQual *)
        w:=BITSET(Pop()); v:=BITSET(Pop()); Push(v<=w)
 |0E3h: (* SGEQ  bitSet Greater or EQual *)
        w:=BITSET(Pop()); v:=BITSET(Pop()); Push(v>=w)
 |0E4h: (* INC1  INCrement by 1 *) INC(Core[Pop()])
 |0E5h: (* DEC1  DECrement by 1 *) DEC(Core[Pop()])
 |0E6h: (* INC   INCrement *) i:=Pop(); INC(Core[Pop()],i)
 |0E7h: ( *)
        IF S+1>H THEN DEC(PC); TRAP(40h)
        ELSE Core[S]:=Pop(); INC(S)
        END
 |0E9h: (* LODT  LOaD   Top of proc stack *)
        DEC(S); Push(Core[S])
 |0EAh: (* LXA   Load indeXed Address *)
        sz:=Pop(); i:=Pop(); adr:=Pop(); Push(adr+i*sz)
 |0EBh: (* LPC   Load Procedure Constant *)
        i:=Next(); j:=Next(); Push(j*1000000h+Core[G-i-1])

(* The  following  3  instructions  deal  with  bit  slices. Bit
   address  is the pair (address, bit offset). Bit offset can be
   greater than 32. The slice may be out of word bounds.
*)
 |0ECh: (* BBU  Bit Block Unpack *)
        sz:=Pop();
        IF (sz<1) OR (sz>32) THEN
          Push(sz); DEC(PC); TRAP(4Ah)
        END;
        i:=Pop(); adr:=Pop();
        (* j  is  a  bit  slice  of  size -sz- beginning from bit
           address (adr,i).
        *)
        Push(j);
 |0EDh: (* BBP  Bit Block Pack *)
        j:=Pop(); sz:=Pop();
        IF (sz<1) OR (sz>32) THEN
          Push(sz); DEC(PC); TRAP(4Ah)
        END;
        i:=Pop(); adr:=Pop();
        (* Packing  up -sz- of least significant bits from j and
           put them to address (adr,i).
        *)
 |0EEh: (* BBLT Bit BLock Transfer *)
        sz:=Pop(); (* size can be greater than 32 *)
        i:=Pop(); adr:=Pop();
        j:=Pop(); adr1:=Pop();
        (* Copies -sz- bits from (adr,i) to (adr1,j) *)
 |0F0h: (* SWAP *)
        i:=Pop(); j:=Pop(); Push(i); Push(j)
 |0F1h: (* LPA Load Parameter Address *)
        Push(L-Next()-1);
 |0F2h: (* LPW Load Parameter WORD *)
        Push(Core[L-Next()-1]);
 |0F3h: (* SPW Store Parameter WORD *)
        Core[L-Next()-1]:=Pop();
 |0F4h: (* SSWU Store Stack Word Undestructive *)
        i:=Pop(); Core[Pop()]:=i; Push(i)
 |0FAh: (* ACTIVe process *) Push(P)
 |0FBh: (* USR User defined functions *) i:=Next(); (*  *)
 |0FCh: (* SYS rare SYStem functions *)
        CASE Next() OF
         |00h: (* PID Processor IDent *)
               (* Push(PID) *)
         |01h..0FFh: (* depends on a processor model *)
        END;
 |0FDh: (* NII Never Implemented Instruction *) TRAP(7h);
 |0FFh: (* INVLD INVaLiD operation *)          TRAP(49h)
  ELSE  (* unimplemented instruction *) TRAP(7h)
  END (*CASE*)
END Interpret;

BEGIN (* "Power On" *)
 (* cpu:=KRONOS2_2 | KRONOS2_5 | KRONOS2_6 *)
 ORIGIN(ByteCore,ADR(Core),SIZE(Core));
 ConsolMicroProgram;
 LOOP
   IF Ipt THEN TRAP(IptNo) END;
   IR:=Next();
   Interpret;
 END (*LOOP*)
END Kronos_Interpreter.


          GENERAL DESCRIPTION OF KRONOS INSTRUCTIONS


     This  description is not an independent document. It must
be  perceived  as  the  detailed,  vast  comments  for "Kronos
Interpreter".  Definitions  of  the  main  concepts  of Kronos
acrhitecture  are  omitted  here.  They  may  be  found in the
section "VIRTUAL MODULA-2 MACHINE".

     The   execution  of  any  instruction  is  starting  from
fetching its code. Instruction code is 8 bit width and treated
as  unique  code  of instruction. It restrictly determines the
algorithm  of  instruction execution. There are not any fields
or   addressation   modes  packed  in  the  instruction  code.
Instruction code is a byte and nothing more. In rare cases the
group  of  instructions  may  have the same code (the so-named
escape instructions). In such cases (as, for example FFCT) the
next  byte  determines  which instruction of the group will be
executed.
     After  instruction  code  fetching,  the algorithm of its
execution is detemined. Some operands of the instruction layed
on  Expression Stack (ES), the other (if necessary) may follow
the  instruction  code,  as a sequence of bytes. The last ones
are  named immediately (constant) operands, but they are never
absolute   addresses.  Some  notions  are  necessary  for  the
instruction description (see, also, "Kronos Interpreter").

     Code Fetching

     Code  fetching  is  performed  by  the procedures "Next",
"Next2" and "Next4". They are fetching a byte, two bytes, or a
word  (four  bytes),  respectively,  and  increase the program
counter  (PC)  by  1,2  or  4.  In  terms  of  Modula-2  these
procedures may be written:

     PROCEDURE Next(): BYTE;
     BEGIN INC(PC); RETURN INTEGER(F^[PC-1]) END Next;

     PROCEDURE Next2(): WORD16;
     BEGIN RETURN Next()+Next()*100h END Next2;

     PROCEDURE Next4(): WORD;
     BEGIN RETURN Next2()+Next2()*10000h END Next4;



     Expression Stack

     Expression  stack  is used for evaluation expressions and
manipulations  with  instruction  arguments.  It  executes two
operations  "Pop"  (take  from the stack) and "Push" (put into
the stack):

     PROCEDURE Push(X: WORD);
     BEGIN
       A[sp]:=X;
       IF sp<ESdepth THEN INC(sp) ELSE Ipt:=TRUE; IptNo:=4Ch END;
     END Push;

     PROCEDURE Pop(): INTEGER;
     BEGIN
       IF sp=0 THEN Ipt:=TRUE; IptNo:=4Ch ELSE DEC(sp) END;
       RETURN A[sp];
     END Pop;

     If  the  stack  is  empty  when "Pop" is executed or full
before "Push" trap 4Ch is raised (this useful feature is added
for compiler debugging).

     Words  "pop  from  the stack" denote following: "take the
value  of  the top element of the stack and then decrement the
stack counter by 1".

     Words  "push  into the stack" denotes following: "put the
value  above  the  top element of the stack and then increment
the stack counter by 1".

     By  default,  the word "stack" without any prefix denotes
"expression stack".

     4-bits Immediate Operands

     Since Kronos instruction set is very small (less than 128
instructions)  it was possible to use 4 least significant bits
in  some  frequently  executed instructions for short (4 bits)
form  of  offset. These instructions may be described as a set
of 16 different instructions (in "Kronos Interpreter") or as a
single  4  bit instruction with 4 bit the immediately followed
operand (in this DESCRIPTION).

Note.
     All  numbers used in the text are hexidecimal, and so are
     postfixed by character 'h' - 'hex'.


LI0..LI0F
Load Immediate

Operation Code:                 4 bits          0h
Immediate Operands:             4 bits          00h..0Fh
Instruction Length:             1 byte
Action:
     Loads  the  value  of  the  least  significant  4 bits of

     instruction  code  (in the range 00h..0Fh), and pushes it
     into  the  stack  as 32 bit words with leadings zeros. PC
     increments by 1.

Interpreter:
     Push(IR MOD 10h);


LIB
Load Immediate Byte

Operation Code:                 1 byte         10h
Immediate Operands:             1 byte         00h..0FFh
Instruction Length:             2 байта
Action:
     Loads  the value of the immediate operand (byte following
     the instruction code) in the range 0..0FFh, and pushes it
     into  the  stack  as 32 bit words with leadings zeros. PC
     increments by 2.

Interpreter:
     Push(Next())


LID
Load Immediate Double Byte

Operation Code:                 1 byte          11h
Immediate Operands:             2 байта         00h..0FFFFh
Instruction Length:             3 bytes
Action:
     Loads  the  value  of  the  immediate  operand  (2  bytes
     following  the  instruction code) in the range 0..0FFFFh,
     and  pushes  it  into  the  stack  as  32  bit words with
     leadings zeros. PC increments by 3.

Interpreter:
     Push(Next2())


LIW
Load Immediate Word

Operation Code:                 1 byte          12h
Immediate Operands:             4 байта        00h..0FFFFFFFFh
Instruction Length:             5 байт
Action:
     Loads  the  value  of  the  immediate  operand  (4  bytes
     following  the  instruction code), and pushes it into the
     stack as 32 bit words. PC increments by 5.

Interpreter:
     Push(Next4())

Note:
     Kronos   used   complement  to  2**32  representaion  for
     negative integer numbers. The integer numbers lies in the
     range:

            MIN(INTEGER)=-2**31 .. MAX(INTEGER)=2**31-1
                 80000000h      ..      7FFFFFFFh

     "-1" reprsents as 0FFFFFFFFh.

     Only  the  instruction  LIW  allows  one to push negative
     numbers into the stack. But there exists the other method
     to  generate  small  negative  numbers  by loading of its
     absolute value using LI,LIB,LID and then change a sign by
     the  instruction NEG. For current models of processors it
     is more effective.


LIN
Load Immediate Nil

Operation Code:                 1 byte          13h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Loads  the  non-existent address (NIL) and pushes it into
     the  stack. PC increments by 1. The NIL value is specific
     and has been changed from one processor model to another,
     without the influence on program portability.

Interpreter:
     Push(NIL)


LLA
Load Local Address

Operation Code:                 1 byte          14h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Adds  contents  of  L_register and the immediate operands
     (byte  following the instruction code) and pushes the sum
     into  the  stack.  PC  increments  by 2. This instruction
     allows  one  to accept the address of a local variable at
     the  top  of  the  stack.  When  offset  of a variable is
     greater  than  0FFh,  the  problem is solved by combining
     LLA, LI,LIB,LID or LIW and ADD instructions.

Interpreter:
     Push(L+Next())


LGA
Load Global Address

Operation Code:                 1 byte          15h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 байта
Action:
     Adds   contents  of  the  G_register  and  the  immediate
     operands (byte following the instruction code) and pushes
     the  sum  into  the  stack.  PC  increments  by  2.  This
     instruction  allows one to accept the address of a global
     variable  at  the  top  of  the  stack.  When offset of a
     variable  is  greater than 0FFh, the problem is solved by
     combining LLA, LI,LIB,LID or LIW and ADD instructions.

Interpreter:
     Push(G+Next())


LSA                             16h
Load Stack Address

Operation Code:                 1 byte          16h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 байта
Action:
     Adds  contents  of the top of the stack and the immediate
     operands  (byte following the instruction code), pops the
     top  of  the  stack and pushes the sum into the stack. PC
     increments  by 2. This instruction allows one to overhead
     the  address  layed  at  the  top of the stack by address
     incremented by offset. It is used for accepting addresses
     of  fields  when  record  address has been already loaded
     into  the stack. When offset of the field is greater than
     0FFh,  the  problem  is solved by combining LI,LIB,LID or
     LIW and ADD instructions.

Note:
     LSA  XX is semantically equivalent to the sequence LIB XX
     ADD. In the RISC model of Kronos this instruction will be
     discarded.

Interpreter:
     Push(Pop()+Next())


LEA
Load External Address

Operation Code:                 1 byte          17h
Immediate Operands:             2 байта         00h..0FFh
Instruction Length:             3 bytes
Action:
     The  first  the  immediate  operand  (byte  following the
     instruction  code)  is the module number (M) and the next
     one  is the word offset (N). Loads the memory word at the
     address  G_register-M-1.  It  is  the  pointer  to module
     global   area   table  (the  so-called  DFT),  and  after
     dereferencing  (see  Note),  it (EA) points to the global
     area of the module M. Pushes the sum of N and EA into the
     stack. PC increments by 3.

Note:
     In   the   RISC   model   of  Kronos  processor  external
     dereferensing will be discarded.

Interpreter:
     i:=G-Next()-1; (* index in local DFT of current module *)
     adr:=Core[i];  (* pointer to DFT                       *)
     Push(Core[adr]+Next())

     For RISC model:

     i:=G-Next()-1; (* index in local DFT of current module *)
     adr:=Core[i];  (* pointer to G-Area of External Module *)
     Push(adr+Next())


JFLC
Jump Forward Long Condition

Operation Code:                 1 byte          18h
Immediate Operands:             2 bytes         00h..0FFFFh
Instruction Length:             3 bytes
Action:
     Takes  2 byte immediate operand - the potential offset to
     the  next  instruction (OFFSET). PC increments by 3. Pops
     the  top of the stack and if it is zero the PC increments
     by OFFSET, otherwise (any nonzero value) goes to the next
     instruction.

Interpreter:
     IF Pop()=0 THEN PC:=Next2()+PC
     ELSE INC(PC,2) END


JFL
Jump Forward Long

Operation Code:                 1 byte          19h
Immediate Operands:             2 bytes         00h..0FFFFh
Instruction Length:             3 bytes
Action:
     Takes  2  byte immediate operand - the offset to the next
     instruction (OFFSET). PC increments by 3+OFFSET.

Interpreter:
     PC:=Next2()+PC;


JFSC
Jump Forward Short Condition

Operation Code:                 1 byte          1Ah
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Takes  1 byte immediate operand - the potential offset to
     the  next  instruction (OFFSET). PC increments by 2. Pops
     the  top  of the stack and if it is zero PC increments by
     OFFSET,  otherwise  (any  nonzero value) goes to the next
     instruction.

Interpreter:
     IF Pop()=0 THEN PC:=Next()+PC
     ELSE INC(PC) END


JFS
Jump Forward Short

Operation Code:                 1 byte          1Bh
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Takes  1  byte immediate operand - the offset to the next
     instruction (OFFSET). PC increments by 2+OFFSET.

Interpreter:
     PC:=Next()+PC;


JBLC
Jump Back Long Condition

Operation Code:                 1 byte          1Ch
Immediate Operands:             2 bytes         00h..0FFFFh
Instruction Length:             3 bytes
Action:
     Takes  2 byte immediate operand - the potential offset to
     the  next  instruction (OFFSET). PC increments by 3. Pops
     the  top of the stack and if it is zero the PC decrements
     by OFFSET, otherwise (any nonzero value) goes to the next
     instruction.

Interpreter:
     IF Pop()=0 THEN PC:=-Next2()+PC
     ELSE INC(PC,2) END


JBL
Jump Back Long

Operation Code:                 1 byte          1Dh
Immediate Operands:             2 bytes         00h..0FFFFh
Instruction Length:             3 bytes
Action:
     Takes  2  byte immediate operand - the offset to the next
     instruction (OFFSET). PC decrements by OFFSET-3.

Interpreter:
     PC:=-Next2()+PC;


JBSC
Jump Back Short Condition

Operation Code:                 1 byte          1Eh
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Takes  1 byte immediate operand - the potential offset to
     the  next  instruction (OFFSET). PC increments by 2. Pops
     the  top of the stack and if it is zero the PC decrements
     by OFFSET, otherwise (any nonzero value) goes to the next
     instruction.

Interpreter:
     IF Pop()=0 THEN PC:=-Next()+PC
     ELSE INC(PC) END


JBS
Jump Back Short

Operation Code:                 1 byte          1Fh
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Takes  1  byte immediate operand - the offset to the next
     instruction (OFFSET). PC decrements by OFFSET-2.

Interpreter:
     PC:=-Next()+PC;


LLW
Load Local Word

Operation Code:                 1 byte         20h
Immediate Operands:             1 byte         00h..0FFh
Instruction Length:             2 bytes
Action:
     Evaluates EA as a sum of the L_register and the immediate
     operand.  Loads a word from EA memory location and pushes
     it  into  the  stack.  PC increments by 2. When offset is
     greater  than  0FFh,  the  problem  may  be solved by the
     combination  of  instructions  LLA 00, LID|LIW offs, ADD,
     LSW0.

Interpreter:
     Push(Core[L+Next()])


LGW
Load Global Word

Operation Code:                 1 byte          21h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Evaluates EA as a sum of the G_register and the immediate
     operand.  Loads a word from EA memory location and pushes
     it  into  the  stack.  PC increments by 2. When offset is
     greater   than   0FFh,  the  problem  may  be  solved  by
     combination  of  instructions  LGA 00, LID|LIW offs, ADD,
     LSW0.

Interpreter:
     Push(Core[G+Next()])


LEW
Load External Word

Operation Code:                 1 byte          22h
Immediate Operands:             2 bytes         00h..0FFFFh
Instruction Length:             3 bytes
Action:
     The   first   immediate   operand   (byte  following  the
     instruction  code)  is the module number (M) and next one
     is  the  word  offset  (N).  Loads the memory word at the
     address  G_register-M-1.  It  is  the  pointer  to module
     global   area   table  (the  so-called  DFT),  and  after
     dereferencing  (see  Note  for LEA) it (EA) points to the
     global area of the module M. Adds N to EA, loads the word
     from memory addressed by EA and pushes it into the stack.
     PC increments by 3.

Interpreter:
     i:=G-Next()-1; adr:=Core[Core[i]]; (* external G *)
     Push(Core[adr+Next()])


LSW                             23h
Load Stack addressed Word

Operation Code:                 1 byte          23h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Evaluates EA as a sum of contents of top of the stack and
     the  immediate  operand  (byte  following the instruction
     code). Pops the top of the stack and pushes a word loaded
     from  EA memory location into the stack. PC increments by
     2.

Interpreter:
     Push(Core[Pop()+Next()])


LLW4..LLW0F
Load Local Word

Operation Code:                 4 bits          2Xh
Immediate Operands:             4 bits          04h..0Fh
Instruction Length:             1 byte
Action:
     Evaluates EA as a sum of the L_register and the immediate
     4  bit operand (the value of the least significant 4 bits
     of  instruction  code).  Loads  a  word  from  EA  memory
     location  and  pushes it into the stack. PC increments by
     1.

Note:
     The  first  4  words  of  the  local  area  are  used for
     call/return  information,  and  can not be used for local
     variables.

Interpreter:
     Push(Core[L+IR MOD 10h])


SLW
Store Local Word

Operation Code:                 1 byte          30h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Evaluates EA as a sum of the L_register and the immediate
     byte operand. Pops a word from the stack and stores it at
     EA memory location. PC increments by 2.

Interpreter:
     Core[L+Next()]:=Pop()


SGW                             31h
Store Global Word

Operation Code:                 1 byte          31h
Immediate Operands:             1 byte          00h..0FFh
Instruction Length:             2 bytes
Action:
     Evaluates  EA  as  a  sum of G_register and the immediate
     byte operand. Pops a word from the stack and stores it at
     EA memory location. PC increments by 2.

Interpreter:
     Core[G+Next()]:=Pop()


SEW
Store  External  Word

Operation Code:                 1 byte          32h
Immediate Operands:             2 bytes         00h..0FFh
Instruction Length:             3 bytes
Action:
     Similar to LEW, but store the popped word in memory.

Interpreter:
     i:=G-Next()-1; adr:=Core[Core[i]]; (* external G *)
     Core[adr+Next()]:=Pop()

SSW
Store Stack addressed Word

Operation Code:                 1 byte
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Pops  the  value from the stack. Evaluates EA as a sum of
     the  address  popped from  the  stack  and  the immediate
     operand (byte following the instruction code). Stores the
     value at EA memory location. PC increments by 2.

Interpreter:
     i:=Pop(); Core[Pop()+Next()]:=i


SLW4..SLW0F
Store Local Word

Operation Code:                 4 bits          3Xh
Immediate Operands:             4 bits          04h..0Fh
Instruction Length:             1 byte
Action:
     Evaluates EA as a sum of the L_register and the immediate
     4  bit operand (the value of the least significant 4 bits
     of the instruction code). Stores the word popped from the
     stack at EA memory location. PC increments by 1.

Interpreter:
     Core[L+IR MOD 10h]:=Pop()


LXB
Load indeXed Byte

Operation Code:                 1 byte          40h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  index  (the upper one) and the base address of
     the  byte  array  from  the  stack.  Loads  addressed  by
     base+index byte from memory, and pushes it into the stack
     as  32 bit word extending by leading zeros. PC increments
     by 1.

Interpreter:
     i:=Pop(); Push(ByteCore[Pop()*4+i]);


LXW
Load indeXed Word

Operation Code:                 1 byte          41h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  index  (the upper one) and the base address of
     the  word  array  from  the  stack.  Loads  addressed  by
     base+index  word  from  memory,  and  pushes  it into the
     stack.  PC increments by 1.

Interpreter:
     i:=Pop(); Push(Core[Pop()+i])


LGW2..LGW0F
Load Global Word

Operation Code:                 4 bits          4*h
Immediate Operands:             4 bits          02h..0Fh
Instruction Length:             1 byte
Action:
     Evaluates EA as a sum of the G_register and the immediate
     4  bit operand (the value of the least significant 4 bits
     of  the  instruction  code).  Loads a word from EA memory
     location  and  pushes it into the stack. PC increments by
     1.

Note:
     The  first  2 words of the global area of module are used
     for  pointers  to code and constant segments, and can not
     be used for global variables.

Interpreter:
     Push(Core[G+IR MOD 10h])


SXB
Store indeXed Byte

Operation Code:                 1 byte          50h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  value  (the  upper  one)  from  the  stack and
     truncate  it to the least significant byte. Then pops the
     index  and  the  base  address of the byte array from the
     stack.  Store  the  value at memory location addressed by
     base+index byte. PC increments by 1.

Interpreter:
     j:=Pop(); i:=Pop(); ByteCore[Pop()*4+i]:=j;


SXW
Store indeXed Word

Operation Code:                 1 byte          51h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the value (the upper one) from the stack. Then pops
     the index and the base address of the word array from the
     stack.  Store  the  value at memory location addressed by
     base+index word. PC increments by 1.

Interpreter:
     j:=Pop(); i:=Pop(); Core[Pop()+i]:=j

SGW2..SGW0F
Store Global Word

Operation Code:                 4 bits          5*h
Immediate Operands:             4 bits          02h..0Fh
Instruction Length:             1 byte
Action:
     Evaluates EA as а sum of the G_register and the immediate
     4  bit operand (the value of the least significant 4 bits
     of  the  instruction  code).  Stores word popped from the
     stack at EA memory location. PC increments by 1.

Interpreter:
     Core[G+IR MOD 10h]:=Pop()


LSW0..LSW0F
Load Stack addressed Word

Operation Code:                 4 bits          6*h
Immediate Operands:             4 bits          00h..0Fh
Instruction Length:             1 byte
Action:
     Evaluates  EA  as  a sum of popped from the stack address
     and  the  immediate 4 bit operand (the value of the least
     significant  4  bits  of the instruction code). Loads the
     word  from  EA  memory  location  and  pushes it into the
     stack. PC increments by 1.

Interpreter:
     Push(Core[Pop()+IR MOD 10h])


SSW0..SSW0F
Store Stack addressed Word

Operation Code:                 4 bits          7*h
Immediate Operands:             4 bits          00h..0Fh
Instruction Length:             1 byte
Action:
     Pops  the  value from the stack. Evaluates EA as a sum of
     popped  from  the  stack  address and the immediate 4 bit
     operand (the value of the least significant 4 bits of the
     instruction   code).   Stores  the  value  at  EA  memory
     location. PC increments by 1.

Interpreter:
     i:=Pop(); Core[Pop()+IR MOD 10h]:=i


QUIT
stop processor

Operation Code:                 1 byte          81h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments by 1. If bit 2 in the M_register (Mask) ON
     then  TRAP(2),  otherwise  stops  processor.  If  console
     microprogram is implemented then control transfers to it.

Note:
     In the RISC model of Kronos the other trap subsystem will
     be implemented and QUIT will be a privileged instruction.

Interpreter:
     ConsolMicroProgram

GETM
GET Mask

Operation Code:                 1 byte          82h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Loads  M_register  and  pushes  it  into  the stack.  PC
     increments by 1.

Note:
     In the RISC model of Kronos the other trap subsystem will
     be  implemented.  Actions  of GETM & SETM will be changed
     and they will be privileged instructions.

Interpreter:
     Push(M)


SETM
SET Mask

Operation Code:                 1 byte      83h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  If  this  is  the first change of
     M_register  in  this  procedure  (30-th bit is OFF in the
     local  word  02h) then the current contents of M_register
     is  saved  in  the local word 03h and 30-th bit is set in
     the local word 02h. (Instruction RTN will restore the old
     mask  after  return.) A new mask value is popped from the
     stack and put into M_register.

Interpreter:
     IF NOT (ChangeMaskBit IN BITSET(Core[L+2])) THEN
       (* Mask is changed first time *)
       Core[L+2]:=WORD(BITSET(Core[L+2])+{ChangeMaskBit});
       Core[L+3]:=WORD(M)
     END; M:=BITSET(Pop);


TRAP
interrupt simulation

Operation Code:                 1 byte    84h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments by 1. Pops the 32 bit trap number from the
     stack and raises trap with this number if it is enabled.

Interpreter:
     TRAP(Pop())


TRA
TRAnsfer control between processes

Operation Code:                 1 byte          85h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC increments by 1.

     The  whole  contents  of the process is determined by the
     whole  contents  of  the processor: registers, expression
     the  stack,  and the state of the process memory (P-stack
     is  the stack for procedure calls). The whole contents of
     the  processor  is  saved at P-stack and into the process
     descriptor  (see  "Kronos Interpreter"). The address of a
     new  pointer  of  the  process  descriptor  pops from the
     expression  the  stack,  then  old pointer to the process
     descriptor  (P_register of the processor) is saved at the
     next  popped  address,  and then P_register is changed by
     the  value  loaded  from memory at new process descriptor
     pointer  location.  After  that  all  the  registers  are
     restored   from  the  new  process  descriptor,  and  the
     expression  stack  is  restored  from  new  P-stack,  and
     control  transfers  to  the  current instruction of a new
     process.

Interpreter:
     i:=Pop(); Transfer(Pop(),i)


TR
Test & Reset

Operation Code:                 1 byte          86h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops the EA from the stack. LOCKs
     memory  to  the  processor  bus. Loads the value from the
     memory  location  EA  and  writes 0 to memory. Pushes the
     value  into  the  stack.  UNLOCKs memory to the processor
     bus. May be used for an exclusive access to the data from
     several processors.

Interpreter:
     i:=Pop(); Push(Core[i]); Core[i]:=0


IDLE
                                IDLE process
Operation Code:                 1 byte          87h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC is not changed. Processor waits for the interrupt not busying the
     bus. The process wich executes this instruction  will be never
     continued.  After the  interrupt  service and continued it it
     will execute IDLE again.

Interpreter:
     DEC(PC); REPEAT (* not busy the bus *) UNTIL Ipt


ADD
integer ADDition

Operation Code:                 1 byte          88h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by 1. Pops two words from the stack, adds
     them  and  pushes  the  result into the stack. If integer
     overflow  happens  and  31-t bit in the M_register is ON,
     raises  trap  41h, elsif it is OFF, puts 41h in 6-th word
     of  the  process  descriptor.  The  result  after integer
     overflow  is undefined. It may not be the module 2**32 of
     addition!

Note:
     All  instructions   of   integer  arithmetics  have  such
     conventions  about  interrupt  raising  and  result after
     overflow.

Interpreter:
     Push(Pop()+Pop())


SUB
integer SUBtraction

Operation Code:                 1 byte          89h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  words  from the stack,
     substracts  the  upper  one from the lower one and pushes
     the result into the stack (see, also, ADD).

Interpreter:
     i:=Pop(); Push(Pop()-i);


MUL
integer MULtiplication
Operation Code:                 1 byte          8Ah
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  words  from the stack,
     multiplies  them  and  pushes  the  result into the stack
     (see, also, ADD).

Interpreter:
     Push(Pop()*Pop())


DIV
integer DIVision

Operation Code:                 1 byte          8Bh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  words  from the stack,
     divides  the  lower  one  by the upper one and pushes the
     result into the stack (see also ADD).

Interpreter:
     i:=Pop(); Push(Pop() DIV i)


SHL
integer SHift Left

Operation Code:                 1 byte          8Ch
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops two words from the stack and
     shifts the lower one arithmetically left by the upper one
     and  pushes  the  result  into  the stack (see also ADD).
     SHL(x,n)  is  semantically equivalent to MULT(x,2**n) and
     so the rules for interrupt raising are the same.

Interpreter:
     i:=Pop() MOD 20h; Push(SHL(Pop(),i))


SHR
integer SHift Right

Operation Code:                 1 byte          8Dh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops two words from the stack and
     shifts the lower one arithmeticaly right by the upper one
     and  pushes  the  result  into  the stack (see also ADD).
     SHR(x,n) is semantically equivalent to DIV(x,2**n) and so
     the rules for interrupt raising are the same.

Note:
     SHR(-1,1) = -1 DIV 2 = 0 !!!

Interpreter:
     i:=Pop() MOD 20h; Push(SHR(Pop(),i))


ROL
word ROate Left

Operation Code:                 1 byte          8Eh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC increments by 1. Pops the shift count and the shifting
     value  from  the  stack.  Rotates  left  the  value until
     count=0  and  then  pushes  the  result  into  the stack.
     Overflow never happens. 31 bit goes directly to 0 bit.

Interpreter:
     i:=Pop() MOD 20h; Push(Pop()<<i)


ROR
word ROate Right

Operation Code:                 1 byte          8Fh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC increments by 1. Pops the shift count and the shifting
     value  from  the  stack.  Rotates  right  the value until
     count=0  and  then  pushes  the  result  into  the stack.
     Overflow never happens. 0 bit goes directly to 31 bit.

Interpreter:
     i:=Pop() MOD 20h; Push(Pop()>>i)


IO0..IO7
Input-Output

Operation Code:                 1 byte          90h..97h
Immediate Operands:             ?
Instruction Length:             ?
Action:
     Instruction  for  I/O  bus communications. Individual for
     each model of processor and I/O bus.

Interpreter:
     CASE cpu OF
       |Kronos2_2: ioP2_2
       |Kronos2_5: ioP2_5
       |Kronos2_6: ioP2_6
     ELSE ASSERT(FALSE);
     END


FADD
Float ADDition

Operation Code:                 1 byte          98h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  32 bits words from the
     stack,  adds them as 32-bits float numbers and pushes the
     result   into   the  stack.  If  real  overflow/underflow
     happened  and  31 bit in the M_register is ON, raise trap
     42h/43h,  elsif  it  is  OFF  puts  42h/43h  in word 6 of
     process descriptor. The result after the real overflow is
     undefined, after underflow 0.0e+00.

Note:

     Overflow/Underflow  discipline  is  common  for all FLOAT
     instructions. Current models of processors use 32-bit DEC
     (tm) real numbers representation.

Interpreter:
     Push(REAL(Pop())+REAL(Pop()))

FSUB
Float SUBtraction

Operation Code:                 1 byte          99h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  32 bits words from the
     stack,  substracts  the  upper  one from the lower one as
     32-bits  float  numbers  and  pushes  the result into the
     stack.

Interpreter:
     X:=REAL(Pop()); Push(REAL(Pop())-X)


FMUL
Float MULtiplication

Operation Code:                 1 byte          9Ah
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  32 bits words from the
     stack,  multiplies  them  as  32-bits  float  numbers and
     pushes the result into the stack.

Interpreter:
     Push(REAL(Pop())*REAL(Pop()))


FDIV
Float DIVision

Operation Code:                 1 byte          9Bh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC  increments  by  1.  Pops  two  32 bits words from the
     stack,  divides the lower one by the upper one as 32-bits
     float numbers and pushes the result into the stack.

Interpreter:
     X:=REAL(Pop()); Push(REAL(Pop())/X)


FCMP
Float CoMPare

Operation Code:                 1 byte          9Ch
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     PC increments by 1.
     Pops  Rigth and Left real values from the stack. Compares
     them  as  a  real  numbers and pushes the results. At the
     place  of the greatest value is 1, at other is 0. If they
     equals pushes 0,0 pair.
      _____              _____         _____          _____
     |  X  |   FCMP     |  0  |       |  1  |        |  0  |
     |  Y  |  ------>   |  1  |       |  0  |        |  0  |

                         X < Y         X > Y          X = Y

     Pair of instructions:
                FCMP EQU        FCMP NEQ
                FCMP LSS        FCMP GTR
                FCMP LEQ        FCMP GEQ
     forms the full system of real comparisons.

Interpreter:
     X:=REAL(Pop()); Y:=REAL(Pop());
     IF    X<Y THEN Push(1); Push(0)
     ELSIF X>Y THEN Push(0); Push(1)
     ELSE Push(0); Push(0) END


FABS
Float ABSolute

Operation Code:                 1 byte          9Dh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops a real number from the stack and pushes its absolute
     value into the stack. PC increments by 1.

Interpreter:
     X:=REAL(Pop());
     IF X<0.0 THEN Push(-X) ELSE Push(X) END


FNEG
Float NEGative

Operation Code:                 1 byte          9Eh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  a real number from the stack, negates it and pushes
     it back into the stack. PC increments by 1.

Interpreter:
     Push(-REAL(Pop()))


FFCT
Float FunCTion

Operation Code:                 1 byte          9Fh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Case of the next byte following the command:

                             next = 0

     pops  an integer number from the stack, transfers it into
     the  appropriate  real number and pushes it back into the
     the stack. PC increments by 1.

                             next = 1

     pops  a real number from the stack, truncates it into the
     appropriate  integer  number  and pushes it back into the
     the  stack.  PC  increments  by  1. (Integer overflow may
     happen).

Interpreter:
     i:=Next();
     IF    i=0 THEN Push(FLOAT(INTEGER(Pop())))
     ELSIF i=1 THEN Push.(TRUNC(   REAL(Pop())))
     ELSE DEC(PC); TRAP(7h) END;


LSS
integer LeSS

Operation Code:                 1 byte          0A0h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  word  and then the Lower word. Compares
     them  and  if  the  Lower integer less than the Upper one
     pushes  1 otherwise 0. PC increments by 1. Overflow never
     happens.

Interpreter:
     i:=Pop(); Push(Pop()<i)


LEQ
integer Less or EQual

Operation Code:                 1 byte          0A1h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  word  and then the Lower word. Compares
     them  and  if the Lower integer <= the Upper one pushes 1
     otherwise 0. PC increments by 1. Overflow never happens.

Interpreter:
     i:=Pop(); Push(Pop()<=i)


GTR
integer GreaTeR

Operation Code:                 1 byte          0A2h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  word  and then the Lower word. Compares
     them  and  if  the Lower integer > the Upper one pushes 1
     otherwise 0. PC increments by 1. Overflow never happens.

Interpreter:
     i:=Pop(); Push(Pop()>i)


GEQ
integer Greater or EQual

Operation Code:                 1 byte          0A3h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  word  and then the Lower word. Compares
     them  and  if the Lower integer >= the Upper one pushes 1
     otherwise 0. PC increments by 1. Overflow never happens.

Interpreter:
     i:=Pop(); Push(Pop()>=i)


EQU
integer EQUal

Operation Code:                 1 byte          0A4h
Immediate Operands:               none
Instruction Length:             1 byte
Action:

     Pops  the  Upper  word  and then the Lower word. Compares
     them  and  if  the  Lower  word = the Upper word pushes 1
     otherwise 0. PC increments by 1. Overflow never happens.

Interpreter:
     Push(Pop()=Pop())


NEQ
integer NOt eQual

Operation Code:                 1 byte          0A5h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  word  and then the Lower word. Compares
     them  and  if  the  Lower word <> the Upper word pushes 1
     otherwise 0. PC increments by 1. Overflow never happens.

Interpreter:
     Push(Pop()#Pop())


ABS
integer ABSolute

Operation Code:                 1 byte          0A6h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops the integer value and pushes its absolute value into
     the  stack.  PC  increments  by  1.  Overflow happens for
     -MIN(INTEGER).

Interpreter:
     Push(ABS(Pop()))


NEG
integer NEGative

Operation Code:                 1 byte          0A7h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  integer  value,  negates  it  and  pushes  its
     absolute  value  into  the  stack.  PC  increments  by 1.
     Overflow happens for -MIN(INTEGER).

Interpreter:
     Push(-Pop())


OR
logical bit per bit OR

Operation Code:                 1 byte          0A8h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  2 words from the stack, executes OR for all 32 bits
     of  these  words and pushes the result into the stack. PC
     increments by 1.

Interpreter:
     v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w+v)


AND
logical bit per bit AND

Operation Code:                 1 byte          0A9h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops 2 words from the stack, executes AND for all 32 bits
     of  these  words and pushes the result into the stack. PC
     increments by 1.

Interpreter:
     v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w*v)


XOR
logical bit per bit XOR

Operation Code:                 1 byte          0AAh
Immediate Operands:               none
Instruction Length:             1 byte
Action:

     Pops 2 words form the stack, executes XOR for all 32 bits
     of  these  words and pushes the result into the stack. PC
     increments by 1.

Interpreter:
     v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w/v)


BIC
logical bit per bit BIt Clear

Operation Code:                 1 byte          0ABh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  word  and  then the Lower word from the
     stack.  Clears  in Lower one all bits which are ON in the
     Upper  word  and  pushes  the  result  into the stack. PC
     increments by 1.

Interpreter:
     v:=BITSET(Pop()); w:=BITSET(Pop()); Push(w-v)


IN
IN bitset

Operation Code:                 1 byte          0ACh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops the Scale (S) word and then the element (N) from the
     stack.  If  N>=0  and N<=31 and bit number N set ON in S,
     then  pushes 1, otherwise 0 into the stack. PC increments
     by 1.

Interpreter:
     v:=BITSET(Pop()); Push(Pop() IN v)


BIT
set BIT

Operation Code:                 1 byte          0ADh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the bit number (N) and pushes the word, in wich all
     bits  are zeros except bit with number N, into the stack.
     If  N<0 or N>31 then trap 4Ah is raised. PC increments by
     1.

Interpreter:
     i:=Pop();
     IF (i<0) OR (i>=20h) THEN TRAP(4Ah)
     ELSE w:={}; INCL(w,i); Push(w) END


NOT
boolean NOT (not bit per bit!)

Operation Code:                 1 byte          0AEh
Immediate Operands:               none
Instruction Length:             1 byte
Action:

     If  the popped value equals 0, pushes 1, otherwise 0 into
     the the stack. PC increments by 1.

Interpreter:
     Push(Pop()=0)

MOD
integer MODule

Operation Code:                 1 byte          0AFh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  Upper  and then the Lower operands. Pushes the
     integer  remainder  from the Lower by the Upper division.
     Integer overflow may happen.

Interpreter:
     i:=Pop(); Push(Pop() MOD i)


DECS
DECrement S_register

Operation Code:                 1 byte          0B0h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Decrements  the  S_register  by the value popped from the
     stack. PC increments by 1.

Interpreter:
     DEC(S,Pop())


DROP
DROP

Operation Code:                 1 byte          0B1h
Immediate Operands:               none
Длина  команды:                 1 byte
Action:
     Ignores the popped value. PC increments by 1.

Interpreter:
     i:=Pop();

LODF
reLOaD the expression stack after Function return

Operation Code:                 1 byte          0B2h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  value  from the stack. Reload the stack by the
     contents  saved  before  at the P-stack. Pushes the value
     over  the  reloaded  stack.  PC  increments  by  1.  This
     instruction  is  used for reloading the saved stack after
     function calls.

Interpreter:
     i:=Pop(); RestoreExpStack; Push(i)


STORE
STORE the expression stack

Operation Code:                 1 byte          0B3h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     If  it  is  possible  (the  free  space  between  S and H
     registers   presents),   saves   the   expression  stack,
     incrementing  S_register.  Puts  the  depth  of the saved
     expression  stack  at  the top of the P-stack (pointed by
     S_register-1).  PC increments by 1. If the free space for
     saving is absent, trap 40h is raised.

Interpreter:
     IF S+ESdepth+1>H THEN DEC(PC); TRAP(40h)
     ELSE SaveExpStack
     END


STOFV
STORE the expression stack with Formal function value at the top

Operation Code:                 1 byte          0B4h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  value from the stack after the stack saving in
     the  same  manner as in the instruction STORE. After that
     the  popped  at the very begining value stores (see STOT)
     at  the top of the P-stack. PC increments by 1. Traps 40h
     may  be  raised. This instruction is useful for the stack
     saving  when the top word is the formal function which is
     called by the CF instruction (see).

Interpreter:
     IF S+ESdepth+2>H THEN DEC(PC); TRAP(40h)
     ELSE i:=Pop(); SaveExpStack; Core[S]:=i; INC(S) END


COPT
COPy Top of expression the stack

Operation Code:                 1 byte          0B5h
Immediate Operands:               none
Instruction Length:             1 byte
Action:

     Pushes twice the popped value. PC increments by 1.

Interpreter:
     i:=Pop(); Push(i); Push(i)


CPCOP
Character array Parameter COPy

Operation Code:                 1 byte          0B6h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Loads  the immediate operand N (the next byte followed by
     the  instruction  code).  A  value  of  the S_register is
     stored   in   the   local  word  N  (at  memory  location
     L_register+N).  Popped  High of array is transformed to a
     word  size. Then array is copied from address popped from
     the stack into the memory pointed by the S_register, with
     incrementing the S_register. PC increments by 2. Trap 40h
     may happen.

Note:
     In  the  RISC  Kronos  processor this instruction will be
     discarded.

Interpreter:
     i:=Pop(); (* High *) sz:=(i+4) DIV 4;
     IF S+sz>H THEN Push(i); DEC(PC); TRAP(40h)
     ELSE Core[L+Next()]:=S; adr:=Pop();
       WHILE sz>0 DO Core[S]:=Core[adr]; INC(S); INC(adr) END
     END


PCOP
structure Parameter allocate and COPy

Operation Code:                 1 byte          0B7h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:

     Loads  the immediate operand N (the next byte followed by
     the  instruction  code).  A  value  of  the S_register is
     stored   in   the   local  word  N  (at  memory  location
     L_register+N).  Loads  High  of  array from the stack and
     increments  it by 1 to transform into size. Then array is
     copied from popped from the stack address into the memory
     pointed   by   the   S_register,  with  incrementing  the
     S_register. PC increments by 2. Trap 40h may happen.

Note:
     In   RISC  Kronos  processor  this  instruction  will  be
     discarded.

Interpreter:
     i:=Pop(); (* High *) sz:=i+1;
     IF S+sz>H THEN Push(i); DEC(PC); TRAP(40h)
     ELSE Core[L+Next()]:=S; adr:=Pop();
       WHILE sz>0 DO Core[S]:=Core[adr]; INC(S); INC(adr) END
     END


FOR1
enter FOR statement

Operation Code:                 1 byte          0B8h
Immediate Operands:             3 bytes
Instruction Length:             4 байта
Action:
     Pops High and Low bounds of FOR loop from the stack, then
     pops  the cycle parameter address. Loads the sign of step
     of cycle from the first immediate operand (byte following
     the   instruction   code).  Loads  Offset  of  the  first
     instruction out of loop from the second immediate operand
     (2  bytes).  PC  increments by 4. Stores Low bound of the
     cycle  in  parameter.  If  conditions of the loop are not
     satisfied  exits  out of loop with incrementing the PC by
     Offset,   else   enters   the  loop  (goes  to  the  next
     instruction).  Address of cycle parameter and High bounds
     of the loop stores at the P-stack. Trap 40h may happen.

Note:
     In  the  RISC  Kronos  processor this instruction will be
     discarded.

Interpreter:
     IF S+2>H THEN DEC(PC); TRAP(40h)
     ELSE sz:=Next(); (* =0 up; #0 down *)
       hi:=Pop(); low:=Pop(); adr:=Pop(); k:=Next2()+PC;
       IF ((sz=0) & (low<=hi)) OR ((sz#0) & (low>=hi)) THEN
         Core[adr]:=low;
         Core[S]:=adr; INC(S); Core[S]:=hi; INC(S);
       ELSE (* цикл не исполняется не разу *) PC:=k
       END
     END


FOR2
end of FOR statement

Operation Code:                 1 byte          0B9h
Immediate Operands:             3 bytes
Instruction Length:             4 байта
Action:
     Loads  the step of cycle from the first immediate operand
     (byte  following the instruction code) and decrements the
     step by 128 to restrict it in the range -128..+127. Loads
     the  Offset  to  the  first  instruction  of the cycle (2
     bytes)  from  the second immediate operand. PC increments
     by  4.  Loads  the High bound and cycle parameter address
     from  the  P-stack. Adds the step to the cycle parameter.
     If  the cycle condition are satisfied, jumps to the first
     instruction  of  the  loop  with  decrementing  the PC by
     Offset, else drops High and address from the P-stack with
     decrementing  the  S_register  by 2 and exits out of loop
     (goes  to the next instruction). Note: FOR1 executes only
     at the first iteration of loop.

Note:
     In  the  RISC  Kronos  processor this instruction will be
     discarded.

Interpreter:
     hi:=Core[S-1];
     adr:=Core[S-2];
     sz:=Next();
     IF sz>7Fh THEN
       sz:=7Fh-sz    (* шаг [-128..127] *)
     END;
     k:=-Next2()+PC;
     i:=Core[adr]+sz;
     IF ((sz>=0) & (i>hi)) OR ((sz<0) & (i<hi)) THEN
       DEC(S,2); (* terminate *)
     ELSE Core[adr]:=i; PC:=k (* continue *)
     END


ENTC
ENTer Case statement

Operation Code:                 1 byte          0BAh
Immediate Operands:             2 bytes         00h..0FFFFh
Instruction Length:             3 bytes +  case table size
Action:
     Selects the needful alternative jump from the case table.
     Trap 40h may happen.

Note:
     In  the  RISC  Kronos  processor this instruction will be
     discarded.


                                        Stacks before ENTC

          ENTC xxxx     ----  (*1*)    E-stack  P-stack
     ---> Alt 0             |
    |     ... XIT           |          |   |   |     |
   -+---> Alt 1             | (*8*)    |   |   |     |    ___
  | |     ... XIT           |          | 1 |   |     |<--| S |
  | |                       |           ~~~    |     |    ~~~
  | |     ...               |
  | |                       |           Stacks after ENTC
 -+-+---> Alt n             |
| | |     ... XIT           |          |   |   |     |    ___
| | |  -> Alt ELSE          |          |   |   |     |<--| S |
| | | |   ... XIT ----------+--------- |   |   | PC' |    ~~~
| | | |                     |        |  ~~~    |     |
| | | |   <Lo><Hi>  <-------  (*2*)  |
| | | |                       (*3,4*)|
| | |  -  <ELSE offset>       (*5*)  |
| |  ----  <Alt0 offset>             |
|  ------  <Alt1 offset>      (*6*)  |
|           ...........              |
 --------  <AltN offset>             |
                                     |
           <Continue code>  <-- PC' --

Interpreter:
     IF S+1>H THEN DEC(PC); TRAP(40h)
     ELSE PC:=Next2()+PC; (* jump to case table *)
       k:=Pop(); low:=Next2(); hi:=Next2();
       Core[S]:=PC + 2*(hi-low) + 4; INC(S);(*PC for exit*)
       IF (k>=low) & (k<=hi) THEN
         PC:=PC+2*(k-low+1) (* jump into case table *)
       END;
       PC:=-Next2()+PC (* jump back to variant's code *)
     END


XIT
eXIT from case

Operation Code:                 1 byte          0BBh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Loads  the  PC  value  from  the  P-stack  and decrements
     S_register. Jumps to the specified PC.

Note:
     In  the  RISC  Kronos  processor this instruction will be
     discarded.

Interpreter:
     DEC(S); PC:=Core[S]


ADDPC
ENTer control Structure

Operation Code:                 1 byte          0BCh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Adds  value  from  the PC_register (after the instruction
     code fetching) to the top of the stack.

Interpreter:
     Push(PC+Pop());


JUMP
ENTer control Structure

Operation Code:                 1 byte          0BDh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Jumps to the instruction wich PC has been popped from the
     top of the stack.

Interpreter:
     PC:=Pop();


ORJP
short circuit OR JumP

Operation Code:                 1 byte          0BEh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Implements the MacCarthy disjunction (conditional OR). If
     the  value  popped  from  the  stack is not equal to zero
     (TRUE)  pushes  1  into the stack and jumps to the end of
     condition   (the   offset  taken  from  the  next  byte),
     otherwise goes to the next instruction.

Interpreter:
     IF Pop()#0 THEN
       Push(1); PC:=Next()+PC
     ELSE
       INC(PC)
     END


ANDJP
short circuit AND JumP

Operation Code:                 1 byte          0BFh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Implements  the  MacCarthy conjunction (conditional AND).
     If  the  value  popped  from  the  stack is equal to zero
     (FALSE)  pushes  0 into the stack and jumps to the end of
     condition  (offset  taken  from the next byte), otherwise
     goes to the next instruction.

Interpreter:
     IF Pop()=0 THEN
       Push(0); PC:=Next()+PC
     ELSE
       INC(PC)
     END


MOVE
MOVE block

Operation Code:                 1 byte          0C0h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  size  (in  words),  source and destinator addresses
     from  the  stack. Moves the sequence of words (in address
     increasing direction) from source to destinator address.

Note:
     May be used to filling area of memory by pattern.

Interpreter:
     sz:=Pop();
     i:=Pop(); j:=Pop();
     WHILE sz>0 DO
       Core[j]:=Core[i]; INC(i); INC(j); DEC(sz)
     END


CHKNIL
ReaD String

Operation Code:                 1 byte          0C1h
Immediate Operands:             none
Instruction Length:             1 byte
Action:
     Checks  the  address  on  the  top of the stack. If it is
     equal to NIL raises the interrupt.

Interpreter:
     adr:=Pop(); Push(adr);
     IF adr=NIL THEN TRAP(3) END;


LSTA
Load STring Address

Operation Code:                 1 byte          0C2h
Immediate Operands:             2 bytes
Instruction Length:             3 bytes
Action:
     Loads  the immediate 2 byte operand and adds its value to
     the  value  of  Global Word 1 (string pointer) and pushes
     sum into the stack.

Note:
     Will be discarded in the RISC Kronos architecture.

Interpreter:
     Push(Core[G+1]+Next2());

COMP
COMPare strings

Operation Code:                 1 byte          0C3h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops from the stack the base addresses of two strings and
     compares them byte after byte until they are not equal or
     one  of  them  is  zero byte (string terminator). In both
     cases  pushes the values of two last bytes into the stack
     in  the  same order as the source strings was. After this
     instruction  any compare instruction (EQU, NEQ, LSS, GTR,
     LEQ, GEQ) may be applied for the string comparison.

Interpreter:
     i:=Pop()*4; j:=Pop()*4;
     REPEAT a:=CHAR(ByteCore[i]); b:=CHAR(ByteCore[j]);
     INC(i); INC(j)
     UNTIL (a=0c) OR (b=0c) OR (a#b); Push(a); Push(b)


GB
Get procedure Base n level down

Operation Code:                 1 byte          0C4h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Takes  the  number  of  levels  N from the byte immediate
     operand.  Goes  through  the  procedure  chain  of  saved
     L_registers  until  the depth N will be extracted. Pushes
     the value on the N'th L_register into the stack.

Note:
     Will be discarded in the RISC Kronos architecture.

Interpreter:
     i:=L; n:=Next();
     WHILE n>0 DO i:=Core[i]; DEC(n) END;
     Push(i)


GB1
Get procedure Base 1 level down

Operation Code:                 1 byte          0C5h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     The short form of the instruction GB 01.

Note:
     Will be discarded in the RISC Kronos architecture.

Interpreter:
     Push(Core[L])


CHK
range bounds CHecK

Operation Code:                 1 byte          0C6h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  high  and  low  bounds and index from the stack and
     checks  whether the index lies in the range low..high. If
     it  is  out of the range raises the interrupt 4Ah else no
     operation.  In  both cases pushes the index backward into
     the stack.

Interpreter:
     hi:=Pop(); low:=Pop(); i:=Pop(); Push(i);
     IF (i<low) OR (i>hi) THEN
       Push(low); Push(hi); TRAP(4Ah)
     END


CHKZ
array bounds CHecK (low=Zero)

Operation Code:                 1 byte          0C7h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  high  bound  and  the index from the stack and
     checks  wheter  index lies in range 0..high. If it is out
     of  range  raises the interrupt 4Ah else no operation. In
     both cases pushes the index backward into the stack.

Interpreter:
     hi:=Pop(); i:=Pop(); Push(i);
     IF (i<0) OR (i>hi) THEN Push(hi); TRAP(4Ah) END


ALLOC
ALLOCate block

Operation Code:                 1 byte          0C8h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the size of structure from the stack, takes a value
     of  the S_register as the start address of the structure,
     increments  the  S_register  by the size. Pushes the base
     address  of allocated area into the stack. If incremented
     S_register   greater   than  the  H_register  raises  the
     interrupt 40h without memory allocation.

Interpreter:
     sz:=Pop();
     IF S+sz>H THEN
       Push(sz); DEC(PC); TRAP(40h)
     ELSE
       Push(S); INC(S,sz)
     END


ENTR
ENTeR procedure

Operation Code:                 1 byte          0C9h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Takes  the  next  byte  immediate  operand as a number of
     necessary  local  variables  for  procedure execution and
     allocates  a local area for them. It is equivalent to the
     sequence  LIB  <n>  ALLOC  DROP. The 40h interrupt may be
     raised.

Interpreter:
     sz:=Next();
     IF S+sz>H THEN
       DEC(PC,2); TRAP(40h)
     ELSE
       INC(S,sz)
     END


RTN
ReTurN from procedure

Operation Code:                 1 byte          0CAh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Restores the previous value of the S_register (to release
     memory  used  for procedure execution) from the procedure
     links  area  (see the instruction CALL), the value of the
     L_register  of  procedure, from wich this one was called,
     the  value  of  the PC_register and, if the external call
     was  performed  (ExternalBit  is  in saved PC_word of the
     links   area),   restores   the   G_register   of  caller
     procedure's module.
     If  processor  mask  (M_register)  was changed during the
     procedure  execution  then the old mask value is restored
     from  the apropriate links area word. So no one procedure
     may change M_register longer than its own execution.

Note:
     Restoring after mask change will be discarded in the RISC
     Kronos architecture.

Interpreter:
     S:=L;
     PC:=WORD(BITSET(Core[S+2])*{0..0Fh});
     L:=Core[S+1];
     IF ExternalBit IN BITSET(Core[S+2]) THEN
       (* external called *)
       G:=Core[S]; F:=CodePtr(Core[G])
     END;
     IF ChangeMaskBit IN BITSET(Core[S+2]) THEN (* mask was changed *)
       M:=BITSET(Core[S+3])*{0..10h}
     END;


NOP
No OPeration

Operation Code:                 1 byte          0CBh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     It is not too hard to understand this instruction.


CX
Call eXternal

Operation Code:                 1 byte          0CCh
Immediate Operands:             2 bytes
Instruction Length:             3 bytes
Action:
     External Call.

     If  there are less than 4 words between S and H registers
     then  raises  the interrupt 40h. Takes the next immediate
     byte  operand  as  a module number and the next immediate
     byte  operand  as  a procedure number. After that a new 4
     words  procedure  links area is constructed. In zero word
     puts  the  current  value of the G_register, in the first
     word  puts  the  current  value of the L_register, in the
     second word puts the current value of the PC_register (16
     bits)  combined  with  the  ExternalBit mark. After that,
     using  module  number,  takes a new G_register from local
     (by indirection through global) DFT. Dereferences the new
     G_register  and  obtains  the  F_register, adds procedure
     number  to  it  and  obtains  a  new  PC  value  from the
     appropriate  word  of  procedure table. And then jumps to
     select the instruction (the begin of called procedure).

Note:
     Extra  dereferencing  through  the  global  DFT  will  be
     discarded in the RISC Kronos architecture.

Interpreter:
     IF S+4<=H THEN j:=Core[G-Next()-1]; (* big DFT *)
       i:=Next(); Mark(G,TRUE);
       G:=Core[j]; F:=CodePtr(Core[G]); PC:=GetPc(i);
     ELSE DEC(PC); TRAP(40h) END


CI
Call procedure at Intermediate level

Operation Code:                 1 byte          0CDh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Similar to CX but obtains PC using own F_register and own
     module  procedure table. Stores in zero word of procedure
     words  a  value  popped from the stack (we assume that it
     may  be  pushed by GB <n> instruction). This value may be
     used  by GB <n> LSW <x> or GB <n> ... SSW <x> to organize
     the access to the intermediate level variables.

Interpreter:
     IF S+4<=H THEN
       i:=Next(); Mark(Pop(),FALSE); PC:=GetPc(i);
     ELSE
       DEC(PC); TRAP(40h)
     END


CF
Call Formal procedure

Operation Code:                 1 byte          0CEh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Takes  a  procedure value from the top of the P-stack and
     decrements   the   S_register   by   1.  Takes  the  most
     significant  byte  of  the procedure value as a procedure
     number  and  three  bytes  as  an address of a global DFT
     entry,  where  the  G_register  of  called procedure host
     module is lied. Then executes similary CX instruction.

Note:
     Extra  dereferencing  through  the  global  DFT  will  be
     discarded in the RISC Kronos architecture.

Interpreter:
     IF S+3<=H THEN i:=Core[S-1]; DEC(S); Mark(G,TRUE);
       k:=i DIV 1000000h; i:=i MOD 1000000h;
       G:=Core[i]; F:=CodePtr(Core[G]); PC:=GetPc(k);
     ELSE DEC(PC); TRAP(40h) END


CL
Call Local procedure

Operation Code:                 1 byte          0CFh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Similar  CI  instruction  but  stores  the  value  of the
     L_register  in  zero word of procedure links area. May be
     used  to  call  the  procedures at the same lexicographic
     level.

Interpreter:
     IF S+4<=H THEN
       i:=Next(); Mark(L,FALSE); PC:=GetPc(i);
     ELSE
       DEC(PC); TRAP(40h)
     END


CL0..CL0E
Call Local procedure

Operation Code:                 4 bits         0D0h
Immediate Operands:             4 bits         00h..0Fh
Instruction Length:             1 byte
Action:
     Equivalent  to  CL instruction but extracts the procedure
     number  from  four  the  least  significant  bits  of the
     instruction code.

Interpreter:
     IF S+4<=H THEN Mark(L,FALSE); PC:=GetPc(IR MOD 10h);
     ELSE DEC(PC); TRAP(40h) END


INCL                            0E0h
INCLude in set

Operation Code:                 1 byte
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  bit number and the destinator address from the
     stack. If the bit number outs of the range 0..31 then the
     interrupt 4Ah is raised. Sets bit with appropriate number
     in the destinator word.

Interpreter:
     i:=Pop();
     IF (i<0) OR (i>1Fh) THEN Push(i); DEC(PC); TRAP(4Ah)
     ELSE j:=Pop(); w:=BITSET(Core[j]); INCL(w,i);
       Core[j]:=CARDINAL(w)
     END


EXCL
EXCLude from set

Operation Code:                 1 byte          0E1h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  bit number and the destinator address from the
     stack.  If  the  bit  number outs of the range 0..31 then
     interrupt  4Ah  is  raised. Sets the bit with appropriate
     number in the destinator word.

Interpreter:
     i:=Pop();
     IF (i<0) OR (i>1Fh) THEN Push(i); DEC(PC); TRAP(4Ah)
     ELSE j:=Pop(); w:=BITSET(Core[j]); EXCL(w,i);
       Core[j]:=CARDINAL(w)
     END


SLEQ                            0E2h
bitSet Less or EQual

Operation Code:                 1 byte
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  bitsets  Top and Under. If bitset Under is the
     subset of Top then pushes 1 (TRUE) else 0 (FALSE).

Note:
     Will be discarded in the RISC Kronos architecture.

Interpreter:
     w:=BITSET(Pop()); v:=BITSET(Pop()); Push(v<=w)


SGEQ
bitSet Greater or EQual

Operation Code:                 1 byte          0E3h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  bitsets  Top  and  Under. If bitset Top is the
     subset of Under then pushes 1 (TRUE) else 0 (FALSE).

Interpreter:
     w:=BITSET(Pop()); v:=BITSET(Pop()); Push(v>=w)


INC1
INCrement by 1

Operation Code:                 1 byte          0E4h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Increments  a  value  at  the  memory  location at popped
     address by 1.

Interpreter:
     INC(Core[Pop()])


DEC1
DECrement by 1

Operation Code:                 1 byte          0E5h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Decrements  a  value  at  the  memory  location at popped
     address by 1.

Interpreter:
     DEC(Core[Pop()])


INC
INCrement

Operation Code:                 1 byte          0E6h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  step from the stack. Increments a value at the
     memory location at popped address by the step.

Interpreter:
     i:=Pop(); INC(Core[Pop()],i)


DEC
DECrement

Operation Code:                 1 byte          0E7h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  a  step  from  the stack. Decrements a value at the
     memory location at popped address by the step.


Interpreter:
     i:=Pop(); DEC(Core[Pop()],i)


STOT
STOre the Top at the procedure stack

Operation Code:                 1 byte          0E8h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Stores  popped  from the stack value at memory located by
     the  L_register. Increments the L_register by 1. If there
     is  less  than  1  word  between S and H registers raises
     interrupt 40h.

Interpreter:
     IF S+1>H THEN DEC(PC); TRAP(40h)
     ELSE Core[S]:=Pop(); INC(S)
     END


LODT
LOaD the Top of the procedure stack

Operation Code:                 1 byte          0E9h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Decrements  the S-register by 1. Pushes value loaded from
     located by S_register.

Interpreter:

     DEC(S); Push(Core[S])


LXA
Load indeXed Address

Operation Code:                 1 byte          0EAh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  a  size  and  an  index of an element and a base of
     structure  array.  Multiplies  the size and the index and
     adds to the base and pushes the result.

Interpreter:
     sz:=Pop(); i:=Pop(); adr:=Pop(); Push(adr+i*sz)


LPC
Load Procedure Constant

Operation Code:                 1 byte          0EBh
Immediate Operands:             2 bytes
Instruction Length:             3 bytes
Action:
     Takes  a  module  number  from  the  next  immediate byte
     operand  and the procedure number from the next immediate
     byte  operand.  Takes  the word with offset equals to the
     module number from the local DFT (the address of entry in
     global  DFT)  and packs it in three the least significant
     bytes  of the resulting procedure value. Procedure number
     is  packed  in  the  most significant byte of the result.
     Pushes the result into the stack.

Interpreter:
     i:=Next(); j:=Next(); Push(j*1000000h+Core[G-i-1])

     The  following  3  instructions deal with bit slices. Bit
     address is the pair (address, bit offset). Bit offset can
     be greater than 32. The slice may out of word bounds.


BBU
Bit Block Unpack

Operation Code:                 1 byte          0ECh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  a  size  of a bit slice (1..32), a bit offset and a
     base address from the stack. Forms bit slice of bits from
     memory located by base address and bit offset, extends it
     by leading zeros and pushes it into the stack.

Interpreter:
     sz:=Pop();
     IF (sz<1) OR (sz>32) THEN
       Push(sz); DEC(PC); TRAP(4Ah)
     END;
     i:=Pop(); adr:=Pop();
     (* j:="sz bits from bit address adr*32+i" *)
     Push(j);


BBP
Bit Block Pack

Operation Code:                 1 byte          0EDh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  value, size of bit slice (sz), offset and base from
     the  the  stack,  truncate  the least significant sz bits
     from  value,  and  packs  it  at  memory  located by base
     address and bit offset.

Interpreter:
     j:=Pop(); sz:=Pop();
     IF (sz<1) OR (sz>32) THEN
       Push(sz); DEC(PC); TRAP(4Ah)
     END;
     i:=Pop(); adr:=Pop();
     (* "pack sz bits from j at bit address adr*32+i *)


BBLT
Bit BLock Transfer

Operation Code:                 1 byte          0EEh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pops  the  size  of  bit slice, the source bit offset and
     base address and destinator offset and base. Transfer bit
     sequence  from  the  soucre bit address to the destinator
     one.  NOTE!  If source and destinator areas are overlaied
     then the instruction result may be unexpected.

Interpreter:
     sz:=Pop();
     i:=Pop(); adr:=Pop();
     j:=Pop(); adr1:=Pop();
     (* "transfer sz bits from bit address
         adr*32+i to bit address adr*32+i"
     *)


SWAP
SWAP

Operation Code:                 1 byte          0F0h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Swaps two top words on the stack.

Interpreter:
     i:=Pop(); j:=Pop(); Push(i); Push(j)


LPA
Load Parameter Address

Operation Code:                 1 byte          0F1h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Substracts the next byte immediate operand and 1 from the
     L_register and pushes the result into the stack.

Interpreter:
     Push(L-Next()-1);


LPW
Load Parameter Word

Operation Code:                 1 byte          0F2h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Substracts the next byte immediate operand and 1 from the
     L_register,  loads a word from the result memory location
     and pushes it into the stack.

Interpreter:
     Push(Core[L-Next()-1]);


SPW
Store Parameter Word

Operation Code:                 1 byte          0F3h
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Pops  a  value  from  the stack. Substracts the next byte
     immediate  operand  and  1  from the L_register, stores a
     value  at  the  result memory location and pushes it into
     the stack.

Interpreter:
     Core[L-Next()-1]:=Pop();


SSWU
Store Stack Word Undistractive

Operation Code:                 1 byte          0F4h
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     The  same  as the instruction SSW but pushes popped value
     backward into the stack.

Interpreter:
     i:=Pop(); Core[Pop()]:=i; Push(i)


ACTIV
ACTIVe process

Operation Code:                 1 byte          0FAh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Pushes  address of the active process descriptor into the
     stack.

Interpreter:
     Push(P)


USR
USeR defined functions

Operation Code:                 1 byte          0FBh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Instruction is reserved for the future extensions.

Interpreter:
     i:=Next(); (*  *)


SYS
SYStem rarely functions

Operation Code:                 1 byte          0FCh
Immediate Operands:             1 byte
Instruction Length:             2 bytes
Action:
     Instruction is reserved for the future extensions.


NII
Never Implemented Instruction

Operation Code:                 1 byte          0FDh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Raises the interrupt 07h.

Interpreter:
     TRAP(7h);


INVLD
INVaLiD command

Operation Code:                 1 byte          0FFh
Immediate Operands:               none
Instruction Length:             1 byte
Action:
     Raises the interrupt 49h.

Interpreter:
     TRAP(49h)


          ILLUSTRATIONS FOR THE PROCESSORS ARCHITECTURE


     Given  partition  may  be used as a manual for the KRONOS
family  processors  architecture,  their  instruction  set and
Modula-2 compiler code generation process.
     The information will be present in the next form:

   __________________________________________________________
   |                          |                             |
   |   Modula-2 source text   | Generated code with comments|
   |__________________________|_____________________________|
   |                          |                             |
   |                          |                             |


     Note  that code will be given only for illustrative needs
and  thereby  may differ from the code really generated by the
current  version  of Modula-2 compiler. The reasons for it are
follows:

     1)  optimizations  which increase the code efficiency but
harm the recognizing are not reflected in examples;
     2)  some  examples  contain  the several variants of code
generation  but  in  the compiler current version only the one
version is of course implemented;
     3)  the  dynamic  control instructions (for example range
check instructions) are omitted.

     The  M-code  instructions mnemonics are used in examples.
The  insructions  formal  description  is  provided  by M-code
interpreter.


                          1. STATEMENTS

     1.1. Assignment


 MODULE M;    (* Global variables assigment *)

 VAR  G: INTEGER;
      B: BITSET;

 BEGIN

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | G:=1;                            LI1 SGW2             |
 | G:=G+255;                        LGW2 LIB FF ADD SGW2 |
 - - - - - - - - - - - - - - - - - - |- - -\-/- -|- -|- --
                                     |      |    |   |
                                     G     255  '+'  G:=


 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | B:={0..31};                      LIW FFFFFFFF SGW3    |
 - - - - - - - - - - - - - - - - - - - \-/- - - - -|- - --
 END M.                                 |          |
                                      {0..31}       B:=


     1.2. Access to global variables

 MODULE M;      (* Greate number of global varialbes *)

 VAR  G2,G3,G4, ... ,G255:INTEGER;
      G256: INTEGER;

 BEGIN
 - - - - - - - - - - - - - - - - - - - - - - -
 | G2  :=  G2;                 LGW02  SGW02  |
 | G15 := G15;                 LGW0F  SGW0F  |
 | G255:=G255;                 LGW FF SGW FF | (1.2.1)
 | G256:=G256;                       ???     | (1.2.2)
 - - - - - - - - - - - - - - - - - - - - - - -
 END M.

Note 1.2.1.  Access  to  the  first  14 global variables (with
     numbers from 2 till 15) has a half-byte (hex) offset and
     for  variables  with  numbers  from  16 till 255 has byte
     offset.

Note 1.2.2.  This is wonder, that a man can generate such much
     number  of  global variables for single module, but if it
     is so, we can generate:

      LGA FF LSW1      LGA FF SSW1

     or something else ...

     1.3. Access to external variables

     The  global  variables  of  another  modules  are  called
"external variables".

 DEFINITION MODULE M;
   (* external module exported variable "i" *)
   VAR i: INTEGER;
 END M.
                           number of module "M" in
                           local DFT of module "N"
 MODULE N;                           |
                                     | the variable "i"
 FROM M IMPORT i;                    | number in module "M"
                                     |  |
 BEGIN  (* read & write  external variable *)
 - - - - - - - - - - - - - - - - - - |- |- - - - - - --
 | i:=i;                         LEW 01 02  SEW 01 02 |
 - - - - - - - - - - - - - - - - - - - - - - - - - - --
 END N.


     More  detail  information about local DFT may be obtained
from procedure call's examples in Chapter 2.

     1.4. IF-statement

 MODULE M;  (* conditional statement *)

 VAR bool : BOOLEAN;                 +--->      LGW2
     G3,G4: INTEGER;                 | (1.4.1) JSFC 04  --+
                                     |                    |
 BEGIN                               |                    |
  - - - - - - - - - - - - - - - - - -          LI3 SGW3   |
 |IF bool THEN G3:=3 ELSE G4:=4 END;                      |
  - - - - - - - - - - - - - - - - - -  (1.4.2) JSF 02   --|--+
 END M.                              |      ______________|  |
                                     |      |-->LI4 SGW4     |
                                     |      _________________|
                                     +--->  +-->

Note 1.4.1.  If E-stack top contains 0 then PC increments 4 to
     omit  THEN  clause  (0  is interpreted as FALSE any other
     value not equal to zero as TRUE).

Note 1.4.2. Unconditional jump to skip ELSE clause.


     1.5. LOOP-statement

     Code  generation  for LOOP-statement implemented with the
help of jump instruction:

MODULE M;

BEGIN                           -->         - - - - - - -
  - - - - - - - - - - - - - - --/         |--> JSF 02  --|--|
  | LOOP   EXIT END;                                     |  |
  - - - - - - - - - - - - - - --\              JSB 04  --   |
END  M.                         -->        - - - - - - - - -
                                          |-->

     If   LOOP-statement   body   is   too  large,  then  jump
instruction  operand  may  consists of two bytes. We hope that
LOOP body less then 65K bytes code.

     1.6. REPEAT-statement

 MODULE M;

   VAR G2:INTEGER; bool: BOOLEAN;

 BEGIN
  - - - - - - - - - - - - - - - - ->   _____________________
  | REPEAT G2:=1 UNTIL bool;           |--> LI1  SGW2      |
  - - - - - - - - - - - - - - - - ->        LGW3 JSBC 05 --|
 END M.

     1.7. FOR-statement

MODULE M;

  VAR i,G3:INTEGER;

BEGIN
                              ____
                             /   LI0              low
                            /    SGW2             =:i
                           /     LIB     7F       high
                          /      SGW4            temporary word
                         /                       for high
 - - - - - - - - - - - -         LGW2    <----    i
  FOR i:=0 TO 127 BY 2 DO        SGW3         |   =:G3
                                 LGW2         |   i
    G3:=i                        LI2          |   step
                                 ADD          |   +
  END;                           COPT         |
 - - - - - - - - - - - - -       SGW2         |   =:i
                          \      LGW4         |   high
                           \     GTR          |   > i ?
                            \    JBSC    -----
                             \___

END M.


                          2. PROCEDURES


     2.1. Procedure declaration and it's call

 MODULE M;

 PROCEDURE P; (* procedure number will be 1 *)


       - - - - - - - - - - - - - - - - - -
 BEGIN | RETURN END P;              RTN  |
       - - - - - - - - - - - - - - - - - -

 BEGIN        (* procedure number will be 0 *)
  - - - - - - - - - - - - - - - - - - - -
  | P;                              CL1 | (2.1.1)
  - - - - - - - - - - - - - - - - - -|- -
 END M.                              |
                        local procedure 1 call


Note 2.1.1. CL1 marks P-stack as follows:

               P-stack--> |          |
                          |__________|
      L in entry point--> |          | <-- S in invocation
                          |    L     |       point
      static          --> |__________| \
         and          --> |    L     |__\ registers values
      dynamic             |__________|  / in invocation points
       links              |    PC    | /
                          |__________|
                          |not change|<-- see instructions
                          |__________|    SETM, RTN
  new S in entry point--> |          |
                          |          |


     After  marking  new  L = old S and new S = old S + 4. The
     offset  of  a  corresponding procedure PC is extracted by
     indexing procedures table (see Note 2.1.2) with procedure
     number.  RTN  takes from the P-stack procedure links area
     values  for  PC and L in the invocation point and restore
     them  in PC and L registers. The L content is assigned to
     S register during the return.


Note 2.1.2. Procedure table is the table which gives procedure
     start  PC  offset  relatively module code frame base F by
     the   procedure   number.  The  module  initial  part  is
     considered as zero procedure (i.e. procedure whith number
     0).

     2.2. Access to procedure's local variables

 MODULE M;

 PROCEDURE P; (* procedure 1 *)

                         procedure local variables quantity
                                         |
       - - - - - - - - - - - - - - - - - |- - - --
 VAR   |L4: INTEGER;                ENTR 01      | (2.2.1)
 BEGIN |L4:=0; RETURN               LI0 SLW4 RTN |
       - - - - - - - - - - - - - - - - - - |- - --
 END P;                                    |
                             first 4 words (with numbers 0..3)
                                 are occupied by links area

 BEGIN        (* procedure 0 *)
 - - - - - - - - - - - - - - - - - - - - - -
 | P                                CL1    |
 - - - - - - - - - - - - - - - - - - - - - -
 END M.

Note 2.2.1. ENTR 01 increments S-register by 1:

        |___________| <-- L                 |__________| <-- L
       0|           |          ENTR 01     0|          |
       1| l i n k s |        ---------->   1|  links   |
       2|           | <-- S                2|          |
       3|___________|                      3|__________|
        |           |                      4|__________| <-- S
                                            |          |


     After  all it is possible to operate with local variables
     by  LLW,  SLW,  LGW  and  SGW  instructions, based on the
     L-register.


     2.3. Nested procedures


 MODULE M;


 PROCEDURE p1;  (* procedure 1*)
   VAR p1L4:INTEGER;


   PROCEDURE p2; (* procedure  2*)

   VAR p2L4:INTEGER;            put embedding procedure p1
                                L-register on A-stack
   BEGIN                             |
      - - - - - - - - - - - - - - - -|- - - - - - - ---
      |p1L4:=12;                    GB1  LI12  SSW4   |
      |p2L4:=11;                    LI11 SLW4  RTN    |
      - - - - - - - - - - - - - - - - - - - - - - - - -
   END p1;
                         procedure number in procedure table
 BEGIN                                         |
   - - - - - - - - - - -- - - - - - - - - - - -|- - -
   |p1L4:=2;                       LI2  SLW4   |     |
   |p2;                            LLA 00  CI 02 RTN | (2.3.1)
   - - - - - - - - - - -- - - - - - - -|- -|- - - - -
 END p1;                               |   |
                        L-register value   |
                intermediate level procedure call instruction

 BEGIN
 - - - - - - - - - - - - - - - - - - - - -
 |p1;                               CL1  |
 - - - - - - - - - - - - - - - - - - - - -
 END M.


Note 2.3.1. CI takes from A-stack base register value, calling
     procedure  and  memorizing  this  value  in  static chain
     (instead   of   L-register   which  is  memorized  by  CL
     instruction).  GB1  passes  procedure  static  chain on 1
     level,  accepts  base  address of low (0) level procedure
     static  chain from which procedure p1 is called, and puts
     it  on  A-stack.  By  this  base  address  the access to
     corresponding  procedure local variables is provided with
     the  help  of  LSW  and SSW instructions. In this example
     compiler  generated CI instead of CL because static chain
     identical the dynamic one.


     2.4. External procedure call


 DEFINITION MODULE N;

 PROCEDURE proc1;

 END N.


 MODULE M;

 FROM N IMPORT proc1;


                                    module number
                                      |
 PROCEDURE p1;                        |
                                      | module's proc number
 BEGIN                                |  |
 - - - - - - - - - - - - - - - - - - -| -|- - -
 |  proc1;                        CX 01 01 RTN |  (2.4.1)
 - - - - - - - - - - - - - - - - - - - - - - - -
 END p1;

 END M.

Note 2.4.1.  In  local  DFT  element with number 1 corresponds
     module  N  and after loading reffers on DFT element which
     points  on  module N G-area. The first area word contains
     module  N  F-register,  thus  providing to reach its code
     segment:


                              D F T
                           +-------+
                     +---->| N *- -|--+   -- DFT element for N
                     |     |-------|  |
                     |     |       |  |
                     |     |_______|  |
                     | +-->| M *- -|  |   -- DFT element for M
                     | |   |_______|  |
                     | |              |
                     | |              |
     module M image  | |              |   module N image
      +---------+    | |              |    +---------+
      | 1 *- - -|- - + |              |    |         |
      |_________|      |              |    |         |
      | 0 *- - -|- - - +              | G  |         |
 G -> |_________|                     +--> |_________|
      | F *- - -|--> on code segment       | F *- - -|-->
      |_________|                          |_________|
      |   *- - -|--> on string pool        |   *- - -|-->
      |_________|                          |_________|
      |module M |                          |module N |
      |G-area   |                          |G-area   |
      |_________|                          |_________|


     CX  puts  G-register in static chain links area and marks
     (putting  flag  in  the  second local word) that call was
     external.  RTN instruction analyses this bit and restores
     G-register value if it's necessary.


     2.5. Multivalues allocation

 MODULE M;

 PROCEDURE p;
     - - - - - - - - - - - - - - - - - - - - - - - - -
 VAR |i: INTEGER;                   ENTR 02           |
     |A: ARRAY [0..15] OF INTEGER;  LIB 10 ALLOC SLW5 |(2.5.1)
     - - - - - - - - - - - - - - - - - - - - - - - - -
 BEGIN
   - - - - - - - - - - - - - - - - - - - - - - - - - -
   |i:=0;                       LI0  SLW4   |        |
   |                                                 |
   |                             A    i              |
   |                             |    |              |
   |A[i]:=1;                    LLW5 LLW4 LI1 SXW    | (2.5.2)
   - - - - - - - - - - - - - - - - - - - - - - - - - - (2.5.3)
END p;

END M.


Note 2.5.1.  ALLOC  takes  from  A-stack multivalue size, puts
     back  S-register value and moves S on the given size thus
     reserving  the  needful  number  of  words on P-stack for
     multivalue.  After all array address is memorized in some
     local word.

Note 2.5.2.  Indexation  without  range  checking. If it's not
     explicitly updated the range check is switched on.

Note 2.5.3. During procedure return RTN instruction transposes
      S in L thus frees all memory (in particular allocated by
      ALLOC instruction on P-stack) for local objects.


     2.6. Return from module initial part

     In  this  Modula-2  programming  system implementation an
initial  procedure  (module  body)  during  returning  puts on
A-stack   memory   size  reserving  on  P-stack  after  module
initialization,  i.e. <multivalues size in words> + 4 words of
initial  procedure  links. This information is used by tasking
initializer:

 MODULE M;
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 |VAR A: ARRAY [0..0Fh] OF INTEGER;    LIB 010 ALLOC SGW2    |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 BEGIN (* procedure 0 *)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 |END M.                                LIB 14 RTN           |
 - - - - - - - - - - - - - - - - - - - - - -|- - - - - - - - -
                                            14h = 10h + 4h


If module hasn't multivalues it must return 0:

 МODULE M;
 - - - - - - - - - - - - - - - - - - - - - - - - -
 |BEGIN END M.                           LI0 RTN |
 - - - - - - - - - - - - - - - - - - - - - - - - -


     2.7. Operation over pocedure values


 MODULE M;

 TYPE proc1=PROCEDURE (INTEGER);

 PROCEDURE P(p1 : proc1); (* procedure # 1 *)


                       to save A-stack on P-stack
                          | load procedure value P1
                          | from procedure P 4-th word
 BEGIN                    |     |  put value on P-stack
                          |     |     | from A-stack
   - - - - - - - - - - - -|- - -|- - -|- - - - - - - - - -
   |p1(1);              SLW4   LLW4  STOT  LI1  CF  RTN  |
   - - - - - - - - - - - - - - - - - - - - -|- -|- - - - -
 END P;                                     |   |
                                       parameter|
                                              formal procedure
                                                     call

 PROCEDURE p(w: INTEGER); (* procedure # 2 *)
 BEGIN
   - - - - - - - - - - - - - - - - - - - - - - - -
   |                                SLW4     RTN |
   - - - - - - - - - - - - - - - - - - - - - - - -
 END p;


 VAR v: proc1;
                              module number equals 0,
                               as procedure is own
                                         |
                                         | procedure number
 BEGIN                                   |  |
   - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   |v:=p;                            LPC 00 02  SGW2      |
   |v(5);                            LGW2  STOT  LI5  CF  |
   |P(v);                            LGW2  CL1            |
   |P(p);                            LPC 00 02  CL1       |
   - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 END M.



                           |<---     single word    --->|
                           |____________________________|
 Procedure value:          | 31..24 | 23 . . . . . . .0 |
                           -----|-------------|----------
                                |             |
                            procedure      module's DFT
                              number       entry point


     Procedure  links  during procedure call by CF instruction
(similarly as CX):

                      L'-->   |          |
                              .          .
                              |----------|
                      S', L-->|G-register|
                              |__________|
                              |    L'    |
                              .----------.
                      S -->   .          .
                              |          |



     2.8. Parameter passing


 MODULE M;

 TYPE String=ARRAY [0..255] OF CHAR;

 PROCEDURE P(i: INTEGER; S: String; VAR w: ARRAY OF CHAR);
   VAR k,j:INTEGER;
 BEGIN

 (* parameter saving and variable allocation *)
 - - - - - - - - - - - - - - - - - - - - - - - - - -
 |                                STORE ENTR 01    |  (2.8.1)
 - - - - - - - - - - - - - - - - - - - - - - - - - -

 (* copying of array S called by value *)

 - - - - - - - - - - - - - - - - - - - - - - - - - -
 |k:=HIGH(S);                       LIB FF  SLW8   |
 |j:=HIGH(w);                       LLW4 SLW9 RTN  |  (2.8.2)
 |                                   |    |        |
 |                                  HIGH  j        |
 - - - - - - - - - - - - - - - - - - - - - - - - - -
 END P;

 VAR
     - - - - - - - - - - - - - -- - - - - - - -  - -
     |str8:ARRAY[0..7] OF CHAR;  LI2 ALLOC SGW2    |
     |str :String;               LIB 40 ALLOC SGW3 |
     - - - - - - - - - - - - - -- - - - - - - - -  -

BEGIN
                     loading 'abc' constant address on A-stack
                               |
 - - - - - - - - -  - - - - - -|- - - - - - - - - - -
 |p(1,'abc',str8);        LI1 LSTA 0001 LGW2 LI7 CL1 |
 |                                                   |
 |str:='def';             LGW3 LSTA *ind* LI1 MOVE   | (2.8.3)
 |                                                   |
 |p(2,str,str);           LI2 LGW3 LGW3 LIB FF CL1   |
 - - - - - - - - -  - - - - - - - - - - - - - - - - -

 END M.


Note 2.8.1. STORE writes A-stack in P-stack, reserving storage
     for local objects in P-stack: 4-th word contains HIGH(w),
     5-th  word  contains  w  address,  6-th  word  contains S
     address,  7-th  word  contains  i, 8-th word contains the
     number  of  parameters.  ENTR  01  instruction terminates
     storage allocation reserving 9-th word for j:



  A-stack before    |__________|       L -----> |__________|
  call of procedure |  HIGH(w) |                |__________|
  p:                |----------|                |__________|
                    |    w     |                |__________|
                    |----------|                |__________|
                    |    S     |          --> 4 | HIGH(w)  |
                    |----------|          |     |----------|
                    |    i     |          |   5 |    w     |
                    |----------|          |     |----------|
                                          |   6 |    S     |
                                  STORE   |     |----------|
                                          |   7 |    i     |
                                          |     |----------|
                                          |   8 |          | k
                                          -->   |----------|
                                  ENTR 1 ---> 9 |          | j
                                                |__________|
                                       S -----> |          |


Note 2.8.2.  The instructions for array S copy which is called
     by value are represented here.


           I)  LIB 40        II)  LLW6           III)  LLW6
               ALLOC              LIB FF               LIB 3F
               COPT               CPCOP 06             PCOP 06
               LLW6
               LIB 40
               MOVE
               SLW6

     The  necessity of introducing instructions CPCOP and PCOP
     is  quite  clear. These instructions serve for allocation
     and copy of multiparameters.

Note 2.8.3.  LSTA  *ind*  by  relative  address in string pool
     loads   on  A-stack  the  corresponding  string  constant
     address.  Designated instruction sequence may be replaced
     by:  LGW3  RDS  01 XYZ0, where X,Y,Z are codes of symbols
     'x', 'y', 'z'.


     2.9. Function call over nonempty stack

 MODULE M;

 PROCEDURE f(i,j: INTEGER): INTEGER;
 BEGIN
 - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | RETURN  i+j               STORE LLW5 LLW4 ADD RTN |
 - - - - - - - - - - - - - - - - - - - - - - - - - - -
 END f;

 PROCEDURE p(i,j: INTEGER);
   VAR k:INTEGER;
 BEGIN
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | k:=i+j;                      STORE LLW5 LLW4 ADD SLW6 RTN |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 END p;
 VAR v: PROCEDURE(INTEGER,INTEGER): INTEGER;
 BEGIN
 - - - - - - - - - - - -- - - - - - - - - - - - - - - -
 | p(1,f(2,3));   LI1     STORE LI2 LI3 CL1 LODFV CL2 |
 | v:=f;          LPC 00 01 SGW2                      |
 | p(1,v(2,3));   LI1 LGW2 STOFV LI2 LI3 CF LODFV CL2 |(2.9.1)
 |                                                    |
 - - - - - - - - - - - - - - - - - - - - -  - - - - - -
 END M.

Note 2.9.1.  Instructions  sequence  LI1  LI2 CL1 CL2 would be
     wrong  because  CL1  takes  all  values from the stack in
     entry  point  and 1 is among them but it's not destinated
     for it.


                          3. EXPRESSIONS


     3.1. Word arrays indexation


MODULE M;

VAR x: ARRAY [0..3] OF INTEGER;
    i: INTEGER;

BEGIN
- - - - - - - - - - - - - - - - - - - - - -
|  x[i]:=1;    LGW2 LGW3 LI3 CHKZ LI1 SXW |-- with range
|  i:=x[1];    LGW2 LI1  LXW SGW2         |   check
- - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - -
|  x[i]:=1;      LGW2 LGW3 LI1 SXW  | -- without range check
|  i:=x[1];      LGW2 LI1  LXW SGW2 |    (3.1.1)
- - - - - - - - - - - - - - - - - - -
END M.


Note 3.1.1.  Compiler uses here constant addressing generating
     next code:

           - - - - - - - - - - - - - - - - - - - - -
           |    i:=x[1]        LGW2 LSW1     SGW2  |
           - - - - - - - - - - - - - - - - - - - - -

     and thereby range checking becomes unnecessary.


     3.2. Byte arrays indexation


 MODULE M;
     - - - - - - - - - - - - - - - - - - - - - - -
 VAR | A:ARRAY [0..0Fh] OF CHAR;  LI4 ALLOC SGW2-|--(3.2.1)
     - - - - - - - - - - - - - - - - - - - - - - -
       i:INTEGER;                                   (3.2.2)


 BEGIN
 - - - - - - - - - - - - - - - - - - - - - - -
 |i:=0;                             LI0 SGW3 |
 - - - - - - - - - - - - - - - - - - - - - - -





                               HIGH    i   '>='
 - - - - - - - - - - - - ->      |     |     |
 | WHILE HIGH(A)>=i DO       |->LI0F  LGW3  GEQ JSFC 014------
 | A[i]:='*';                |  LGW2 LGW3 LIB 2A SXB         |
 | INC(i);                   |  LGA 03 INC1                  |
 | A[i-1]:= A[i-1]; END;     |  LGW2 LGW3 LI1 SUB            |
 - - - - - - - - - - - - ->  |  LGW2 LGW3 LI1 SUB            |
 END M.                      |    |    |   |   |             |
                             |    A[   i   1  '-'            |
                             |   LXB  SXB JSB 019            |
                              \_______________/              |
                                                             |
                                         <--------------------
                                                     (3.2.3)

Note 3.2.1. Second global word contains array address.

Note 3.2.2. Char arrays are always packed.

Note 3.2.3.  LXB  and  SXB are similar LXW and SXW but operate
     over  byte. 0 <byte address> LXB and 0 <byte address> SXB
     realize absolute byte addressing.


     3.3. Byte arrays indexation with range check


 MODULE M;

 VAR A:ARRAY [0..0Fh] OF CHAR;
     i:INTEGER;



 BEGIN i:=0;
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |WHILE  i#HIGH(A) DO -> LIW3 LI0F NEQ JSFC 0E             |
  |  A[i]:=A[i+1];     -> LGW2 LGW3 LI0F CHKZ               |
  |                       LGW2 LGW3 LI1 ADD LI0F            |
  |                        |     |   |   |    |             |
  |                        A     i   1  '+'  HIGH(A)        |
  |                                                         |
  |END (*WHILE *)         CHKZ LXB SXB JSB 013              |
  |                        |                                |
  |                       (3.3.1)                           |
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Note 3.3.1.  CHKZ  checks  whether  the A-stack second element
     lies  between 0 and stack top (which defines a bound). If
     it's  so  instruction  makes  bound  deletion  or  raises
     TRAP(4Ah) otherwise.


     3.4. Range check

 MODULE M;

 VAR x:[10h..20h];
 BEGIN
    - - - - - -  - - - - - - - - - - - - - - - - - - - - - - -
   |x:=13h;                    LIB 13 LIB 10 LIB 20 CHK SGW2 |
   - - - - - - - - - - - - - - - - - - - - - - - - - | - - - -
 END M.                                              |
                                                  (3.4.1)

Note 3.4.1.  CHK  makes range check. This check is made during
     compilation  time  by compiler which generates code LIB13
     SGW2.


     3.5. Operatin over BITSET type object.

 MODULE M;
 VAR b1, b2:BITSET;
 BEGIN
   - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   |b1:={}; b2:={1};                LI0  SGW2  LI2  SGW3 |
   |b1:=b1+b2;                      LGW2  LGW3  OR  SGW3 |
   (*     *                                     AND
          /                                     XOR
          -                                     BIC      *)

   |b1:={1}; INCL(b1,2);            LGA 2  LI2  INCL     |
   |         EXCL(b1.2);            LGA 2  LI2  EXCL     |
  (* 2 IN b1                        LI2  LGW2   IN       *)
   - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 END M.


     3.6. ANDJP and ORJP instructions

 MODULE M;
 .
 .
 BEGIN
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |IF FALSE AND TRUE THEN END;   LI0  ANDJP 1  LI1  JSFC  |
  |IF TRUE OR FALSE  THEN END;   LI1  ORJP 1   LI0  JSFC  |
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 END M.                                                (3.6.1)

Note 3.6.1.  After optimization compiler will generate nothing
     instead of such funny code.