Просмотр исходного кода

SVI Начало переделок

SVI 2 лет назад
Родитель
Сommit
687daaae22
5 измененных файлов с 2350 добавлено и 2367 удалено
  1. 2 0
      .gitignore
  2. 3 1
      Makefile
  3. 1920 1927
      source/AMD64.ob07
  4. 1 8
      source/Compiler.ob07
  5. 424 431
      source/SCAN.ob07

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+bin
+compiler_new

+ 3 - 1
Makefile

@@ -1,5 +1,7 @@
 lin64:
-	./compiler ./source/Compiler.ob07 linux64exe -out ./bin/compiler -stk 2
+	./compiler ./source/Compiler.ob07 linux64exe -out ./bin/compiler_new -stk 2
+	upx -f ./bin/compiler_new
+	cp ./bin/compiler_new ./compiler_new
 lin32:
 	./compiler ./source/Compiler.ob07 linux32exe -out ./bin/compiler32 -stk 2
 lin64sample1:

+ 1920 - 1927
source/AMD64.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2023, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE AMD64;
+MODULE AMD64;
 
 IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, TARGETS,
        REG, UTILS, S := STRINGS, PE32, ELF, X86, ERRORS;
@@ -75,2350 +68,2350 @@ VAR
 
 
 PROCEDURE OutByte (b: BYTE);
-BEGIN
-    X86.OutByte(b)
-END OutByte;
+    BEGIN
+        X86.OutByte(b)
+    END OutByte;
 
 
 PROCEDURE OutByte2 (a, b: BYTE);
-BEGIN
-    X86.OutByte(a);
-    X86.OutByte(b)
-END OutByte2;
+    BEGIN
+        X86.OutByte(a);
+        X86.OutByte(b)
+    END OutByte2;
 
 
 PROCEDURE OutByte3 (a, b, c: BYTE);
-BEGIN
-    X86.OutByte(a);
-    X86.OutByte(b);
-    X86.OutByte(c)
-END OutByte3;
+    BEGIN
+        X86.OutByte(a);
+        X86.OutByte(b);
+        X86.OutByte(c)
+    END OutByte3;
 
 
 PROCEDURE OutInt (n: INTEGER);
-BEGIN
-    X86.OutByte(n MOD 256);
-    X86.OutByte(UTILS.Byte(n, 1));
-    X86.OutByte(UTILS.Byte(n, 2));
-    X86.OutByte(UTILS.Byte(n, 3))
-END OutInt;
+    BEGIN
+        X86.OutByte(n MOD 256);
+        X86.OutByte(UTILS.Byte(n, 1));
+        X86.OutByte(UTILS.Byte(n, 2));
+        X86.OutByte(UTILS.Byte(n, 3))
+    END OutInt;
 
 
 PROCEDURE short (n: INTEGER): INTEGER;
-    RETURN 2 * ORD(X86.isByte(n))
-END short;
+        RETURN 2 * ORD(X86.isByte(n))
+    END short;
 
 
 PROCEDURE long (n: INTEGER): INTEGER;
-    RETURN 40H * ORD(~X86.isByte(n))
-END long;
+        RETURN 40H * ORD(~X86.isByte(n))
+    END long;
 
 
 PROCEDURE OutIntByte (n: INTEGER);
-BEGIN
-    IF X86.isByte(n) THEN
-        OutByte(n MOD 256)
-    ELSE
-        OutInt(n)
-    END
-END OutIntByte;
+    BEGIN
+        IF X86.isByte(n) THEN
+            OutByte(n MOD 256)
+        ELSE
+            OutInt(n)
+        END
+    END OutIntByte;
 
 
 PROCEDURE isLong (n: INTEGER): BOOLEAN;
-    RETURN (n > UTILS.max32) OR (n < UTILS.min32)
-END isLong;
+        RETURN (n > UTILS.max32) OR (n < UTILS.min32)
+    END isLong;
 
 
 PROCEDURE NewNumber (value: INTEGER);
-VAR
-    number: Number;
+    VAR
+        number: Number;
 
-BEGIN
-    NEW(number);
-    number.value := value;
-    LISTS.push(Numbers, number);
-    INC(Numbers_Count)
-END NewNumber;
+    BEGIN
+        NEW(number);
+        number.value := value;
+        LISTS.push(Numbers, number);
+        INC(Numbers_Count)
+    END NewNumber;
 
 
 PROCEDURE NewLabel (): INTEGER;
-BEGIN
-    BIN.NewLabel(prog)
-    RETURN IL.NewLabel()
-END NewLabel;
+    BEGIN
+        BIN.NewLabel(prog)
+        RETURN IL.NewLabel()
+    END NewLabel;
 
 
 PROCEDURE Rex (reg1, reg2: INTEGER);
-BEGIN
-    OutByte(48H + reg1 DIV 8 + 4 * (reg2 DIV 8))
-END Rex;
+    BEGIN
+        OutByte(48H + reg1 DIV 8 + 4 * (reg2 DIV 8))
+    END Rex;
 
 
 PROCEDURE lea (reg, offset, section: INTEGER);
-BEGIN
-    Rex(0, reg);
-    OutByte2(8DH, 05H + 8 * (reg MOD 8)); (* lea reg, [rip + offset] *)
-    X86.Reloc(section, offset)
-END lea;
+    BEGIN
+        Rex(0, reg);
+        OutByte2(8DH, 05H + 8 * (reg MOD 8)); (* lea reg, [rip + offset] *)
+        X86.Reloc(section, offset)
+    END lea;
 
 
 PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
-BEGIN
-    Rex(reg1, reg2);
-    OutByte2(op, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
-END oprr;
+    BEGIN
+        Rex(reg1, reg2);
+        OutByte2(op, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
+    END oprr;
 
 
 PROCEDURE oprr2 (op1, op2: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
-BEGIN
-    Rex(reg1, reg2);
-    OutByte3(op1, op2, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
-END oprr2;
+    BEGIN
+        Rex(reg1, reg2);
+        OutByte3(op1, op2, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
+    END oprr2;
 
 
 PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *)
-BEGIN
-    oprr(89H, reg1, reg2)
-END mov;
+    BEGIN
+        oprr(89H, reg1, reg2)
+    END mov;
 
 
 PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *)
-BEGIN
-    oprr(31H, reg1, reg2)
-END xor;
+    BEGIN
+        oprr(31H, reg1, reg2)
+    END xor;
 
 
 PROCEDURE and (reg1, reg2: INTEGER); (* and reg1, reg2 *)
-BEGIN
-    oprr(21H, reg1, reg2)
-END and;
+    BEGIN
+        oprr(21H, reg1, reg2)
+    END and;
 
 
 PROCEDURE _or (reg1, reg2: INTEGER); (* or reg1, reg2 *)
-BEGIN
-    oprr(09H, reg1, reg2)
-END _or;
+    BEGIN
+        oprr(09H, reg1, reg2)
+    END _or;
 
 
 PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *)
-BEGIN
-    oprr(01H, reg1, reg2)
-END add;
+    BEGIN
+        oprr(01H, reg1, reg2)
+    END add;
 
 
 PROCEDURE sub (reg1, reg2: INTEGER); (* sub reg1, reg2 *)
-BEGIN
-    oprr(29H, reg1, reg2)
-END sub;
+    BEGIN
+        oprr(29H, reg1, reg2)
+    END sub;
 
 
 PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *)
-BEGIN
-    IF rax IN {reg1, reg2} THEN
-        Rex(reg1 + reg2, 0);
-        OutByte(90H + (reg1 + reg2) MOD 8)
-    ELSE
-        oprr(87H, reg1, reg2)
-    END
-END xchg;
+    BEGIN
+        IF rax IN {reg1, reg2} THEN
+            Rex(reg1 + reg2, 0);
+            OutByte(90H + (reg1 + reg2) MOD 8)
+        ELSE
+            oprr(87H, reg1, reg2)
+        END
+    END xchg;
 
 
 PROCEDURE cmprr (reg1, reg2: INTEGER);  (* cmp reg1, reg2 *)
-BEGIN
-    oprr(39H, reg1, reg2)
-END cmprr;
+    BEGIN
+        oprr(39H, reg1, reg2)
+    END cmprr;
 
 
 PROCEDURE pop (reg: INTEGER); (* pop reg *)
-BEGIN
-    IF reg >= 8 THEN
-        OutByte(41H)
-    END;
-    OutByte(58H + reg MOD 8)
-END pop;
+    BEGIN
+        IF reg >= 8 THEN
+            OutByte(41H)
+        END;
+        OutByte(58H + reg MOD 8)
+    END pop;
 
 
 PROCEDURE push (reg: INTEGER); (* push reg *)
-BEGIN
-    IF reg >= 8 THEN
-        OutByte(41H)
-    END;
-    OutByte(50H + reg MOD 8)
-END push;
+    BEGIN
+        IF reg >= 8 THEN
+            OutByte(41H)
+        END;
+        OutByte(50H + reg MOD 8)
+    END push;
 
 
 PROCEDURE decr (reg: INTEGER);
-BEGIN
-    Rex(reg, 0);
-    OutByte2(0FFH, 0C8H + reg MOD 8) (* dec reg1 *)
-END decr;
+    BEGIN
+        Rex(reg, 0);
+        OutByte2(0FFH, 0C8H + reg MOD 8) (* dec reg1 *)
+    END decr;
 
 
 PROCEDURE incr (reg: INTEGER);
-BEGIN
-    Rex(reg, 0);
-    OutByte2(0FFH, 0C0H + reg MOD 8) (* inc reg1 *)
-END incr;
+    BEGIN
+        Rex(reg, 0);
+        OutByte2(0FFH, 0C0H + reg MOD 8) (* inc reg1 *)
+    END incr;
 
 
 PROCEDURE drop;
-BEGIN
-    REG.Drop(R)
-END drop;
+    BEGIN
+        REG.Drop(R)
+    END drop;
 
 
 PROCEDURE GetAnyReg (): INTEGER;
-    RETURN REG.GetAnyReg(R)
-END GetAnyReg;
+        RETURN REG.GetAnyReg(R)
+    END GetAnyReg;
 
 
 PROCEDURE callimp (label: INTEGER);
-BEGIN
-    OutByte2(0FFH, 15H);    (* call qword[rip + label + IMP] *)
-    X86.Reloc(sIMP, label)
-END callimp;
+    BEGIN
+        OutByte2(0FFH, 15H);    (* call qword[rip + label + IMP] *)
+        X86.Reloc(sIMP, label)
+    END callimp;
 
 
 PROCEDURE pushDA (offs: INTEGER);
-VAR
-    reg: INTEGER;
+    VAR
+        reg: INTEGER;
 
-BEGIN
-    reg := GetAnyReg();
-    lea(reg, offs, sDATA);
-    push(reg);
-    drop
-END pushDA;
+    BEGIN
+        reg := GetAnyReg();
+        lea(reg, offs, sDATA);
+        push(reg);
+        drop
+    END pushDA;
 
 
 PROCEDURE CallRTL (proc: INTEGER);
-VAR
-    label: INTEGER;
+    VAR
+        label: INTEGER;
 
-BEGIN
-    label := IL.codes.rtl[proc];
-    IF label < 0 THEN
-        callimp(-label)
-    ELSE
-        X86.call(label)
-    END
-END CallRTL;
+    BEGIN
+        label := IL.codes.rtl[proc];
+        IF label < 0 THEN
+            callimp(-label)
+        ELSE
+            X86.call(label)
+        END
+    END CallRTL;
 
 
 PROCEDURE UnOp (VAR reg: INTEGER);
-BEGIN
-    REG.UnOp(R, reg)
-END UnOp;
+    BEGIN
+        REG.UnOp(R, reg)
+    END UnOp;
 
 
 PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
-BEGIN
-    REG.BinOp(R, reg1, reg2)
-END BinOp;
+    BEGIN
+        REG.BinOp(R, reg1, reg2)
+    END BinOp;
 
 
 PROCEDURE PushAll (NumberOfParameters: INTEGER);
-BEGIN
-    REG.PushAll(R);
-    DEC(R.pushed, NumberOfParameters)
-END PushAll;
+    BEGIN
+        REG.PushAll(R);
+        DEC(R.pushed, NumberOfParameters)
+    END PushAll;
 
 
 PROCEDURE movabs (reg, n: INTEGER);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    Rex(reg, 0);
-    OutByte(0B8H + reg MOD 8); (* movabs reg, n *)
-    FOR i := 0 TO 7 DO
-        OutByte(UTILS.Byte(n, i))
-    END
-END movabs;
+    BEGIN
+        Rex(reg, 0);
+        OutByte(0B8H + reg MOD 8); (* movabs reg, n *)
+        FOR i := 0 TO 7 DO
+            OutByte(UTILS.Byte(n, i))
+        END
+    END movabs;
 
 
 PROCEDURE movrc (reg, n: INTEGER); (* mov reg, n *)
-BEGIN
-    IF isLong(n) THEN
-        movabs(reg, n)
-    ELSIF n = 0 THEN
-        xor(reg, reg)
-    ELSE
-        Rex(reg, 0);
-        OutByte2(0C7H, 0C0H + reg MOD 8);
-        OutInt(n)
-    END
-END movrc;
+    BEGIN
+        IF isLong(n) THEN
+            movabs(reg, n)
+        ELSIF n = 0 THEN
+            xor(reg, reg)
+        ELSE
+            Rex(reg, 0);
+            OutByte2(0C7H, 0C0H + reg MOD 8);
+            OutInt(n)
+        END
+    END movrc;
 
 
 PROCEDURE test (reg: INTEGER); (* test reg, reg *)
-BEGIN
-    oprr(85H, reg, reg)
-END test;
+    BEGIN
+        oprr(85H, reg, reg)
+    END test;
 
 
 PROCEDURE oprlongc (reg, n: INTEGER; oprr: OPRR);
-VAR
-    reg2: INTEGER;
+    VAR
+        reg2: INTEGER;
 
-BEGIN
-    reg2 := GetAnyReg();
-    ASSERT(reg2 # reg);
-    movabs(reg2, n);
-    oprr(reg, reg2);
-    drop
-END oprlongc;
+    BEGIN
+        reg2 := GetAnyReg();
+        ASSERT(reg2 # reg);
+        movabs(reg2, n);
+        oprr(reg, reg2);
+        drop
+    END oprlongc;
 
 
 PROCEDURE oprc (op, reg, n: INTEGER; oprr: OPRR);
-BEGIN
-    IF isLong(n) THEN
-        oprlongc(reg, n, oprr)
-    ELSE
-        Rex(reg, 0);
-        X86.oprc(op, reg, n)
-    END
-END oprc;
+    BEGIN
+        IF isLong(n) THEN
+            oprlongc(reg, n, oprr)
+        ELSE
+            Rex(reg, 0);
+            X86.oprc(op, reg, n)
+        END
+    END oprc;
 
 
 PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *)
-BEGIN
-    IF n = 0 THEN
-        test(reg)
-    ELSE
-        oprc(0F8H, reg, n, cmprr)
-    END
-END cmprc;
+    BEGIN
+        IF n = 0 THEN
+            test(reg)
+        ELSE
+            oprc(0F8H, reg, n, cmprr)
+        END
+    END cmprc;
 
 
 PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *)
-BEGIN
-    oprc(0C0H, reg, n, add)
-END addrc;
+    BEGIN
+        oprc(0C0H, reg, n, add)
+    END addrc;
 
 
 PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *)
-BEGIN
-    oprc(0E8H, reg, n, sub)
-END subrc;
+    BEGIN
+        oprc(0E8H, reg, n, sub)
+    END subrc;
 
 
 PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *)
-BEGIN
-    oprc(0E0H, reg, n, and)
-END andrc;
+    BEGIN
+        oprc(0E0H, reg, n, and)
+    END andrc;
 
 
 PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *)
-BEGIN
-    oprc(0C8H, reg, n, _or)
-END orrc;
+    BEGIN
+        oprc(0C8H, reg, n, _or)
+    END orrc;
 
 
 PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *)
-BEGIN
-    oprc(0F0H, reg, n, xor)
-END xorrc;
+    BEGIN
+        oprc(0F0H, reg, n, xor)
+    END xorrc;
 
 
 PROCEDURE pushc (n: INTEGER);
-VAR
-    reg2: INTEGER;
+    VAR
+        reg2: INTEGER;
 
-BEGIN
-    IF isLong(n) THEN
-        reg2 := GetAnyReg();
-        movabs(reg2, n);
-        push(reg2);
-        drop
-    ELSE
-        X86.pushc(n)
-    END
-END pushc;
+    BEGIN
+        IF isLong(n) THEN
+            reg2 := GetAnyReg();
+            movabs(reg2, n);
+            push(reg2);
+            drop
+        ELSE
+            X86.pushc(n)
+        END
+    END pushc;
 
 
 PROCEDURE not (reg: INTEGER); (* not reg *)
-BEGIN
-    Rex(reg, 0);
-    OutByte2(0F7H, 0D0H + reg MOD 8)
-END not;
+    BEGIN
+        Rex(reg, 0);
+        OutByte2(0F7H, 0D0H + reg MOD 8)
+    END not;
 
 
 PROCEDURE neg (reg: INTEGER); (* neg reg *)
-BEGIN
-    Rex(reg, 0);
-    OutByte2(0F7H, 0D8H + reg MOD 8)
-END neg;
+    BEGIN
+        Rex(reg, 0);
+        OutByte2(0F7H, 0D8H + reg MOD 8)
+    END neg;
 
 
 PROCEDURE movzx (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *)
-BEGIN
-    Rex(reg2, reg1);
-    X86.movzx(reg1, reg2, offs, word)
-END movzx;
+    BEGIN
+        Rex(reg2, reg1);
+        X86.movzx(reg1, reg2, offs, word)
+    END movzx;
 
 
 PROCEDURE movmr32 (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2_32 *)
-BEGIN
-    X86._movrm(reg2, reg1, offs, 32, TRUE)
-END movmr32;
+    BEGIN
+        X86._movrm(reg2, reg1, offs, 32, TRUE)
+    END movmr32;
 
 
 PROCEDURE movrm32 (reg1, reg2, offs: INTEGER); (* mov reg1_32, dword[reg2+offs] *)
-BEGIN
-    X86._movrm(reg1, reg2, offs, 32, FALSE)
-END movrm32;
+    BEGIN
+        X86._movrm(reg1, reg2, offs, 32, FALSE)
+    END movrm32;
 
 
 PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov qword[reg1+offs], reg2 *)
-BEGIN
-    X86._movrm(reg2, reg1, offs, 64, TRUE)
-END movmr;
+    BEGIN
+        X86._movrm(reg2, reg1, offs, 64, TRUE)
+    END movmr;
 
 
 PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, qword[reg2+offs] *)
-BEGIN
-    X86._movrm(reg1, reg2, offs, 64, FALSE)
-END movrm;
+    BEGIN
+        X86._movrm(reg1, reg2, offs, 64, FALSE)
+    END movrm;
 
 
 PROCEDURE comisd (xmm1, xmm2: INTEGER); (* comisd xmm1, xmm2 *)
-BEGIN
-    OutByte(66H);
-    IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
-        OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
-    END;
-    OutByte3(0FH, 2FH, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
-END comisd;
+    BEGIN
+        OutByte(66H);
+        IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
+            OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
+        END;
+        OutByte3(0FH, 2FH, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
+    END comisd;
 
 
 PROCEDURE _movsdrm (xmm, reg, offs: INTEGER; mr: BOOLEAN);
-VAR
-    b: BYTE;
-
-BEGIN
-    OutByte(0F2H);
-    IF (xmm >= 8) OR (reg >= 8) THEN
-        OutByte(40H + (xmm DIV 8) * 4 + reg DIV 8)
-    END;
-    OutByte2(0FH, 10H + ORD(mr));
-    IF (offs = 0) & (reg # rbp) THEN
-        b := 0
-    ELSE
-        b := 40H + long(offs)
-    END;
-    OutByte(b + (xmm MOD 8) * 8 + reg MOD 8);
-    IF reg = rsp THEN
-        OutByte(24H)
-    END;
-    IF b # 0 THEN
-        OutIntByte(offs)
-    END
-END _movsdrm;
+    VAR
+        b: BYTE;
+
+    BEGIN
+        OutByte(0F2H);
+        IF (xmm >= 8) OR (reg >= 8) THEN
+            OutByte(40H + (xmm DIV 8) * 4 + reg DIV 8)
+        END;
+        OutByte2(0FH, 10H + ORD(mr));
+        IF (offs = 0) & (reg # rbp) THEN
+            b := 0
+        ELSE
+            b := 40H + long(offs)
+        END;
+        OutByte(b + (xmm MOD 8) * 8 + reg MOD 8);
+        IF reg = rsp THEN
+            OutByte(24H)
+        END;
+        IF b # 0 THEN
+            OutIntByte(offs)
+        END
+    END _movsdrm;
 
 
 PROCEDURE movsdrm (xmm, reg, offs: INTEGER); (* movsd xmm, qword[reg+offs] *)
-BEGIN
-    _movsdrm(xmm, reg, offs, FALSE)
-END movsdrm;
+    BEGIN
+        _movsdrm(xmm, reg, offs, FALSE)
+    END movsdrm;
 
 
 PROCEDURE movsdmr (reg, offs, xmm: INTEGER); (* movsd qword[reg+offs], xmm *)
-BEGIN
-    _movsdrm(xmm, reg, offs, TRUE)
-END movsdmr;
+    BEGIN
+        _movsdrm(xmm, reg, offs, TRUE)
+    END movsdmr;
 
 
 PROCEDURE opxx (op, xmm1, xmm2: INTEGER);
-BEGIN
-    OutByte(0F2H);
-    IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
-        OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
-    END;
-    OutByte3(0FH, op, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
-END opxx;
+    BEGIN
+        OutByte(0F2H);
+        IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
+            OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
+        END;
+        OutByte3(0FH, op, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
+    END opxx;
 
 
 PROCEDURE jcc (cc, label: INTEGER); (* jcc label *)
-BEGIN
-    X86.jcc(cc, label)
-END jcc;
+    BEGIN
+        X86.jcc(cc, label)
+    END jcc;
 
 
 PROCEDURE shiftrc (op, reg, n: INTEGER);
-BEGIN
-    Rex(reg, 0);
-    IF n = 1 THEN
-        OutByte(0D1H)
-    ELSE
-        OutByte(0C1H)
-    END;
-    X86.shift(op, reg MOD 8);
-    IF n # 1 THEN
-        OutByte(n)
-    END
-END shiftrc;
+    BEGIN
+        Rex(reg, 0);
+        IF n = 1 THEN
+            OutByte(0D1H)
+        ELSE
+            OutByte(0C1H)
+        END;
+        X86.shift(op, reg MOD 8);
+        IF n # 1 THEN
+            OutByte(n)
+        END
+    END shiftrc;
 
 
 PROCEDURE GetRegA;
-BEGIN
-    ASSERT(REG.GetReg(R, rax))
-END GetRegA;
+    BEGIN
+        ASSERT(REG.GetReg(R, rax))
+    END GetRegA;
 
 
 PROCEDURE Win64Passing (params: INTEGER);
-VAR
-    n, i: INTEGER;
-
-BEGIN
-    n := params MOD 32;
-    params := params DIV 32;
-    FOR i := 0 TO n - 1 DO
-        IF i IN BITS(params) THEN
-            movsdrm(i, rsp, i * 8)
-        ELSE
-            movrm(Win64RegPar[i], rsp, i * 8)
-        END
-    END
-END Win64Passing;
-
+    VAR
+        n, i: INTEGER;
 
-PROCEDURE SysVPassing (params: INTEGER);
-VAR
-    n, i, s, p, ofs: INTEGER;
-    i_count, f_count: INTEGER;
-    reg: BOOLEAN;
-
-BEGIN
-    ASSERT(r11 IN R.regs);
-    n := params MOD 32;
-    params := params DIV 32;
-    s := 0;
-
-    i_count := 0;
-    f_count := 0;
-    FOR i := 0 TO n - 1 DO
-        IF i IN BITS(params) THEN
-            INC(f_count)
-        ELSE
-            INC(i_count)
+    BEGIN
+        n := params MOD 32;
+        params := params DIV 32;
+        FOR i := 0 TO n - 1 DO
+            IF i IN BITS(params) THEN
+                movsdrm(i, rsp, i * 8)
+            ELSE
+                movrm(Win64RegPar[i], rsp, i * 8)
+            END
         END
-    END;
+    END Win64Passing;
 
-    s := MAX(0, f_count - 8) + MAX(0, i_count - 6);
-    p := 0;
 
-    subrc(rsp, s * 8);
+PROCEDURE SysVPassing (params: INTEGER);
+    VAR
+        n, i, s, p, ofs: INTEGER;
+        i_count, f_count: INTEGER;
+        reg: BOOLEAN;
 
-    i_count := 0;
-    f_count := 0;
-    FOR i := 0 TO n - 1 DO
-        ofs := (i + s) * 8;
-        IF i IN BITS(params) THEN
-            reg := f_count <= 7;
-            IF reg THEN
-                movsdrm(f_count, rsp, ofs);
+    BEGIN
+        ASSERT(r11 IN R.regs);
+        n := params MOD 32;
+        params := params DIV 32;
+        s := 0;
+
+        i_count := 0;
+        f_count := 0;
+        FOR i := 0 TO n - 1 DO
+            IF i IN BITS(params) THEN
                 INC(f_count)
-            END
-        ELSE
-            reg := i_count <= 5;
-            IF reg THEN
-                movrm(SystemVRegPar[i_count], rsp, ofs);
+            ELSE
                 INC(i_count)
             END
         END;
 
-        IF ~reg THEN
-            movrm(r11, rsp, ofs);
-            movmr(rsp, p, r11);
-            INC(p, 8)
+        s := MAX(0, f_count - 8) + MAX(0, i_count - 6);
+        p := 0;
+
+        subrc(rsp, s * 8);
+
+        i_count := 0;
+        f_count := 0;
+        FOR i := 0 TO n - 1 DO
+            ofs := (i + s) * 8;
+            IF i IN BITS(params) THEN
+                reg := f_count <= 7;
+                IF reg THEN
+                    movsdrm(f_count, rsp, ofs);
+                    INC(f_count)
+                END
+            ELSE
+                reg := i_count <= 5;
+                IF reg THEN
+                    movrm(SystemVRegPar[i_count], rsp, ofs);
+                    INC(i_count)
+                END
+            END;
+
+            IF ~reg THEN
+                movrm(r11, rsp, ofs);
+                movmr(rsp, p, r11);
+                INC(p, 8)
+            END
         END
-    END
-END SysVPassing;
+    END SysVPassing;
 
 
 PROCEDURE fcmp (op: INTEGER; xmm: INTEGER);
-VAR
-    cc, reg: INTEGER;
-
-BEGIN
-    reg := GetAnyReg();
-    xor(reg, reg);
-    CASE op OF
-    |IL.opEQF:
-        comisd(xmm - 1, xmm);
-        cc := sete
-
-    |IL.opNEF:
-        comisd(xmm - 1, xmm);
-        cc := setne
-
-    |IL.opLTF:
-        comisd(xmm - 1, xmm);
-        cc := setc
-
-    |IL.opGTF:
-        comisd(xmm, xmm - 1);
-        cc := setc
-
-    |IL.opLEF:
-        comisd(xmm, xmm - 1);
-        cc := setnc
-
-    |IL.opGEF:
-        comisd(xmm - 1, xmm);
-        cc := setnc
-    END;
-    OutByte2(7AH, 3 + reg DIV 8); (* jp L *)
-    X86.setcc(cc, reg)
-    (* L: *)
-END fcmp;
+    VAR
+        cc, reg: INTEGER;
+
+    BEGIN
+        reg := GetAnyReg();
+        xor(reg, reg);
+        CASE op OF
+        |IL.opEQF:
+            comisd(xmm - 1, xmm);
+            cc := sete
+
+        |IL.opNEF:
+            comisd(xmm - 1, xmm);
+            cc := setne
+
+        |IL.opLTF:
+            comisd(xmm - 1, xmm);
+            cc := setc
+
+        |IL.opGTF:
+            comisd(xmm, xmm - 1);
+            cc := setc
+
+        |IL.opLEF:
+            comisd(xmm, xmm - 1);
+            cc := setnc
+
+        |IL.opGEF:
+            comisd(xmm - 1, xmm);
+            cc := setnc
+        END;
+        OutByte2(7AH, 3 + reg DIV 8); (* jp L *)
+        X86.setcc(cc, reg)
+        (* L: *)
+    END fcmp;
 
 
 PROCEDURE translate (commands: LISTS.LIST; stroffs: INTEGER);
-VAR
-    cmd, next: COMMAND;
+    VAR
+        cmd, next: COMMAND;
 
-    opcode, param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER;
+        opcode, param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER;
 
-    reg1, reg2, reg3, xmm: INTEGER;
+        reg1, reg2, reg3, xmm: INTEGER;
 
-    float: REAL;
+        float: REAL;
 
-BEGIN
-    xmm := -1;
-    cmd := commands.first(COMMAND);
-    WHILE cmd # NIL DO
+    BEGIN
+        xmm := -1;
+        cmd := commands.first(COMMAND);
+        WHILE cmd # NIL DO
 
-        param1 := cmd.param1;
-        param2 := cmd.param2;
+            param1 := cmd.param1;
+            param2 := cmd.param2;
 
-        opcode := cmd.opcode;
+            opcode := cmd.opcode;
 
-        CASE opcode OF
+            CASE opcode OF
 
-        |IL.opJMP:
-            X86.jmp(param1)
+            |IL.opJMP:
+                X86.jmp(param1)
 
-        |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL:
-            CASE opcode OF
-            |IL.opCALL:
-            |IL.opWIN64CALL: Win64Passing(param2)
-            |IL.opSYSVCALL:  SysVPassing(param2)
-            END;
-            X86.call(param1)
+            |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL:
+                CASE opcode OF
+                |IL.opCALL:
+                |IL.opWIN64CALL: Win64Passing(param2)
+                |IL.opSYSVCALL:  SysVPassing(param2)
+                END;
+                X86.call(param1)
 
-        |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP:
-            UnOp(reg1);
-            IF reg1 # rax THEN
-                mov(rax, reg1)
-            END;
-            drop;
-            CASE opcode OF
-            |IL.opCALLP:
-            |IL.opWIN64CALLP: Win64Passing(param2)
-            |IL.opSYSVCALLP:  SysVPassing(param2)
-            END;
-            OutByte2(0FFH, 0D0H); (* call rax *)
-            ASSERT(R.top = -1)
+            |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP:
+                UnOp(reg1);
+                IF reg1 # rax THEN
+                    mov(rax, reg1)
+                END;
+                drop;
+                CASE opcode OF
+                |IL.opCALLP:
+                |IL.opWIN64CALLP: Win64Passing(param2)
+                |IL.opSYSVCALLP:  SysVPassing(param2)
+                END;
+                OutByte2(0FFH, 0D0H); (* call rax *)
+                ASSERT(R.top = -1)
+
+            |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI:
+                CASE opcode OF
+                |IL.opCALLI:
+                |IL.opWIN64CALLI: Win64Passing(param2)
+                |IL.opSYSVCALLI:  SysVPassing(param2)
+                END;
+                callimp(param1)
 
-        |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI:
-            CASE opcode OF
-            |IL.opCALLI:
-            |IL.opWIN64CALLI: Win64Passing(param2)
-            |IL.opSYSVCALLI:  SysVPassing(param2)
-            END;
-            callimp(param1)
+            |IL.opLABEL:
+                X86.SetLabel(param1)
 
-        |IL.opLABEL:
-            X86.SetLabel(param1)
+            |IL.opERR:
+                CallRTL(IL._error)
 
-        |IL.opERR:
-            CallRTL(IL._error)
+            |IL.opONERR:
+                pushc(param2);
+                X86.jmp(param1)
 
-        |IL.opONERR:
-            pushc(param2);
-            X86.jmp(param1)
+            |IL.opPUSHC:
+                pushc(param2)
 
-        |IL.opPUSHC:
-            pushc(param2)
+            |IL.opPRECALL:
+                PushAll(0);
+                IF (param2 # 0) & (xmm >= 0) THEN
+                    subrc(rsp, 8)
+                END;
+                INC(Xmm[0]);
+                Xmm[Xmm[0]] := xmm + 1;
+                WHILE xmm >= 0 DO
+                    subrc(rsp, 8);
+                    movsdmr(rsp, 0, xmm);
+                    DEC(xmm)
+                END;
+                ASSERT(xmm = -1)
+
+            |IL.opWIN64ALIGN16:
+                ASSERT(rax IN R.regs);
+                mov(rax, rsp);
+                andrc(rsp, -16);
+                push(rax);
+                subrc(rsp, (MAX(param2 - 4, 0) MOD 2 + MAX(4 - param2, 0) + 1) * 8)
+
+            |IL.opSYSVALIGN16:
+                ASSERT(rax IN R.regs);
+                mov(rax, rsp);
+                andrc(rsp, -16);
+                push(rax);
+                IF ~ODD(param2) THEN
+                    push(rax)
+                END
 
-        |IL.opPRECALL:
-            PushAll(0);
-            IF (param2 # 0) & (xmm >= 0) THEN
-                subrc(rsp, 8)
-            END;
-            INC(Xmm[0]);
-            Xmm[Xmm[0]] := xmm + 1;
-            WHILE xmm >= 0 DO
-                subrc(rsp, 8);
-                movsdmr(rsp, 0, xmm);
-                DEC(xmm)
-            END;
-            ASSERT(xmm = -1)
-
-        |IL.opWIN64ALIGN16:
-            ASSERT(rax IN R.regs);
-            mov(rax, rsp);
-            andrc(rsp, -16);
-            push(rax);
-            subrc(rsp, (MAX(param2 - 4, 0) MOD 2 + MAX(4 - param2, 0) + 1) * 8)
-
-        |IL.opSYSVALIGN16:
-            ASSERT(rax IN R.regs);
-            mov(rax, rsp);
-            andrc(rsp, -16);
-            push(rax);
-            IF ~ODD(param2) THEN
-                push(rax)
-            END
+            |IL.opRESF, IL.opRES:
+                ASSERT(R.top = -1);
+                ASSERT(xmm = -1);
+                n := Xmm[Xmm[0]]; DEC(Xmm[0]);
 
-        |IL.opRESF, IL.opRES:
-            ASSERT(R.top = -1);
-            ASSERT(xmm = -1);
-            n := Xmm[Xmm[0]]; DEC(Xmm[0]);
+                IF opcode = IL.opRESF THEN
+                    INC(xmm);
+                    IF n > 0 THEN
+                        movsdmr(rsp, n * 8, 0);
+                        DEC(xmm);
+                        INC(n)
+                    END;
 
-            IF opcode = IL.opRESF THEN
-                INC(xmm);
-                IF n > 0 THEN
-                    movsdmr(rsp, n * 8, 0);
-                    DEC(xmm);
-                    INC(n)
+                    IF xmm + n > MAX_XMM THEN
+                        ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
+                    END
+                ELSE
+                    GetRegA
                 END;
 
-                IF xmm + n > MAX_XMM THEN
-                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
+                WHILE n > 0 DO
+                    INC(xmm);
+                    movsdrm(xmm, rsp, 0);
+                    addrc(rsp, 8);
+                    DEC(n)
                 END
-            ELSE
-                GetRegA
-            END;
 
-            WHILE n > 0 DO
-                INC(xmm);
-                movsdrm(xmm, rsp, 0);
-                addrc(rsp, 8);
-                DEC(n)
-            END
-
-        |IL.opENTER:
-            ASSERT(R.top = -1);
+            |IL.opENTER:
+                ASSERT(R.top = -1);
 
-            X86.SetLabel(param1);
+                X86.SetLabel(param1);
 
-            param3 := cmd.param3;
+                param3 := cmd.param3;
 
-            IF param3 > 0 THEN
-                push(rbp);
-                mov(rbp, rsp);
+                IF param3 > 0 THEN
+                    push(rbp);
+                    mov(rbp, rsp);
 
-                n := param3 MOD 32;
-                param3 := param3 DIV 32;
+                    n := param3 MOD 32;
+                    param3 := param3 DIV 32;
 
-                FOR i := 0 TO n - 1 DO
-                    IF i IN BITS(param3) THEN
-                        movsdmr(rbp, i * 8 + 16, i)
-                    ELSE
-                        movmr(rbp, i * 8 + 16, Win64RegPar[i])
-                    END
-                END
-            ELSIF param3 < 0 THEN
-                param3 := -param3;
-                n := (param3 MOD 32) * 8;
-                param3 := param3 DIV 32;
-                pop(r11);
-                subrc(rsp, n);
-                push(r11);
-                push(rbp);
-                mov(rbp, rsp);
-
-                a := 0;
-                b := 0;
-                c := 0;
-
-                INC(n, 16);
-
-                FOR i := 16 TO n - 8 BY 8 DO
-                    IF ODD(param3) THEN
-                        IF b <= 7 THEN
-                            movsdmr(rbp, i, b);
-                            INC(b)
+                    FOR i := 0 TO n - 1 DO
+                        IF i IN BITS(param3) THEN
+                            movsdmr(rbp, i * 8 + 16, i)
                         ELSE
-                            movrm(r11, rbp, n + c);
-                            movmr(rbp, i, r11);
-                            INC(c, 8)
+                            movmr(rbp, i * 8 + 16, Win64RegPar[i])
                         END
-                    ELSE
-                        IF a <= 5 THEN
-                            movmr(rbp, i, SystemVRegPar[a]);
-                            INC(a)
+                    END
+                ELSIF param3 < 0 THEN
+                    param3 := -param3;
+                    n := (param3 MOD 32) * 8;
+                    param3 := param3 DIV 32;
+                    pop(r11);
+                    subrc(rsp, n);
+                    push(r11);
+                    push(rbp);
+                    mov(rbp, rsp);
+
+                    a := 0;
+                    b := 0;
+                    c := 0;
+
+                    INC(n, 16);
+
+                    FOR i := 16 TO n - 8 BY 8 DO
+                        IF ODD(param3) THEN
+                            IF b <= 7 THEN
+                                movsdmr(rbp, i, b);
+                                INC(b)
+                            ELSE
+                                movrm(r11, rbp, n + c);
+                                movmr(rbp, i, r11);
+                                INC(c, 8)
+                            END
                         ELSE
-                            movrm(r11, rbp, n + c);
-                            movmr(rbp, i, r11);
-                            INC(c, 8)
-                        END
-                    END;
-                    param3 := param3 DIV 2
-                END
-            ELSE
-                push(rbp);
-                mov(rbp, rsp)
-            END;
+                            IF a <= 5 THEN
+                                movmr(rbp, i, SystemVRegPar[a]);
+                                INC(a)
+                            ELSE
+                                movrm(r11, rbp, n + c);
+                                movmr(rbp, i, r11);
+                                INC(c, 8)
+                            END
+                        END;
+                        param3 := param3 DIV 2
+                    END
+                ELSE
+                    push(rbp);
+                    mov(rbp, rsp)
+                END;
 
-            n := param2;
-            IF n > 4 THEN
-                movrc(rcx, n);
-                                     (* L: *)
-                pushc(0);
-                OutByte2(0E2H, 0FCH) (* loop L *)
-            ELSE
-                WHILE n > 0 DO
+                n := param2;
+                IF n > 4 THEN
+                    movrc(rcx, n);
+                                        (* L: *)
                     pushc(0);
-                    DEC(n)
+                    OutByte2(0E2H, 0FCH) (* loop L *)
+                ELSE
+                    WHILE n > 0 DO
+                        pushc(0);
+                        DEC(n)
+                    END
                 END
-            END
 
-        |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
-            IF opcode = IL.opLEAVER THEN
-                UnOp(reg1);
-                IF reg1 # rax THEN
-                    mov(rax, reg1)
+            |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
+                IF opcode = IL.opLEAVER THEN
+                    UnOp(reg1);
+                    IF reg1 # rax THEN
+                        mov(rax, reg1)
+                    END;
+                    drop
                 END;
-                drop
-            END;
 
-            ASSERT(R.top = -1);
+                ASSERT(R.top = -1);
 
-            IF opcode = IL.opLEAVEF THEN
-                DEC(xmm)
-            END;
+                IF opcode = IL.opLEAVEF THEN
+                    DEC(xmm)
+                END;
 
-            ASSERT(xmm = -1);
+                ASSERT(xmm = -1);
 
-            IF param1 > 0 THEN
-                mov(rsp, rbp)
-            END;
+                IF param1 > 0 THEN
+                    mov(rsp, rbp)
+                END;
 
-            pop(rbp);
-            IF param2 > 0 THEN
-                OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2*8 *)
-            ELSE
-                X86.ret
-            END
+                pop(rbp);
+                IF param2 > 0 THEN
+                    OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2*8 *)
+                ELSE
+                    X86.ret
+                END
 
-        |IL.opSAVES:
-            UnOp(reg1);
-            REG.PushAll_1(R);
-            pushDA(stroffs + param2);
-            push(reg1);
-            drop;
-            pushc(param1);
-            CallRTL(IL._move)
-
-        |IL.opSADR:
-            lea(GetAnyReg(), stroffs + param2, sDATA)
-
-        |IL.opLOAD8:
-            UnOp(reg1);
-            movzx(reg1, reg1, 0, FALSE)
-
-        |IL.opLOAD16:
-            UnOp(reg1);
-            movzx(reg1, reg1, 0, TRUE)
-
-        |IL.opLOAD32:
-            UnOp(reg1);
-            movrm32(reg1, reg1, 0);
-            shiftrc(shl, reg1, 32);
-            shiftrc(shr, reg1, 32)
-
-        |IL.opLOAD64:
-            UnOp(reg1);
-            movrm(reg1, reg1, 0)
-
-        |IL.opLLOAD64:
-            reg1 := GetAnyReg();
-            movrm(reg1, rbp, param2 * 8)
-
-        |IL.opLLOAD8,
-         IL.opLLOAD16:
-            reg1 := GetAnyReg();
-            movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16)
-
-        |IL.opLLOAD32:
-            reg1 := GetAnyReg();
-            movrm32(reg1, rbp, param2 * 8);
-            shiftrc(shl, reg1, 32);
-            shiftrc(shr, reg1, 32)
-
-        |IL.opGLOAD64:
-            reg1 := GetAnyReg();
-            Rex(0, reg1);  (* mov reg1, qword[rip + param2 + BSS] *)
-            OutByte2(8BH, 05H + 8 * (reg1 MOD 8));
-            X86.Reloc(sBSS, param2)
-
-        |IL.opGLOAD8, IL.opGLOAD16:
-            reg1 := GetAnyReg();
-            Rex(0, reg1);  (* movzx reg1, byte/word[rip + param2 + BSS] *)
-            OutByte3(0FH, 0B6H + ORD(opcode = IL.opGLOAD16), 05H + 8 * (reg1 MOD 8));
-            X86.Reloc(sBSS, param2)
-
-        |IL.opGLOAD32:
-            reg1 := GetAnyReg();
-            lea(reg1, param2, sBSS);
-            movrm32(reg1, reg1, 0);
-            shiftrc(shl, reg1, 32);
-            shiftrc(shr, reg1, 32)
-
-        |IL.opVLOAD64:
-            reg1 := GetAnyReg();
-            movrm(reg1, rbp, param2 * 8);
-            movrm(reg1, reg1, 0)
-
-        |IL.opVLOAD8,
-         IL.opVLOAD16:
-            reg1 := GetAnyReg();
-            movrm(reg1, rbp, param2 * 8);
-            movzx(reg1, reg1, 0, opcode = IL.opVLOAD16)
-
-        |IL.opVLOAD32:
-            reg1 := GetAnyReg();
-            reg2 := GetAnyReg();
-            movrm(reg2, rbp, param2 * 8);
-            movrm32(reg1, reg2, 0);
-            shiftrc(shl, reg1, 32);
-            shiftrc(shr, reg1, 32);
-            drop
+            |IL.opSAVES:
+                UnOp(reg1);
+                REG.PushAll_1(R);
+                pushDA(stroffs + param2);
+                push(reg1);
+                drop;
+                pushc(param1);
+                CallRTL(IL._move)
 
-        |IL.opLADR:
-            n := param2 * 8;
-            next := cmd.next(COMMAND);
-            IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN
-                ASSERT(xmm >= 0);
-                movsdmr(rbp, n, xmm);
-                DEC(xmm);
-                cmd := next
-            ELSIF next.opcode = IL.opLOADF THEN
-                INC(xmm);
-                IF xmm > MAX_XMM THEN
-                    ERRORS.ErrorMsg(fname, next.param1, next.param2, FPR_ERR)
-                END;
-                movsdrm(xmm, rbp, n);
-                cmd := next
-            ELSE
-                IF (next.opcode = IL.opADDC) & ~isLong(n + next.param2) THEN
-                    INC(n, next.param2);
-                    cmd := next
-                END;
-                reg1 := GetAnyReg();
-                Rex(0, reg1);
-                OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *)
-                OutIntByte(n)
-            END
+            |IL.opSADR:
+                lea(GetAnyReg(), stroffs + param2, sDATA)
 
-        |IL.opGADR:
-            next := cmd.next(COMMAND);
-            IF (next.opcode = IL.opADDC) & ~isLong(param2 + next.param2) THEN
-                INC(param2, next.param2);
-                cmd := next
-            END;
-            lea(GetAnyReg(), param2, sBSS)
+            |IL.opLOAD8:
+                UnOp(reg1);
+                movzx(reg1, reg1, 0, FALSE)
 
-        |IL.opVADR:
-            movrm(GetAnyReg(), rbp, param2 * 8)
+            |IL.opLOAD16:
+                UnOp(reg1);
+                movzx(reg1, reg1, 0, TRUE)
 
-        |IL.opSAVE8C:
-            UnOp(reg1);
-            IF reg1 >= 8 THEN
-                OutByte(41H)
-            END;
-            OutByte3(0C6H, reg1 MOD 8, param2); (* mov byte[reg1], param2 *)
-            drop
+            |IL.opLOAD32:
+                UnOp(reg1);
+                movrm32(reg1, reg1, 0);
+                shiftrc(shl, reg1, 32);
+                shiftrc(shr, reg1, 32)
 
-        |IL.opSAVE16C:
-            UnOp(reg1);
-            OutByte(66H);
-            IF reg1 >= 8 THEN
-                OutByte(41H)
-            END;
-            OutByte2(0C7H, reg1 MOD 8);
-            OutByte2(param2 MOD 256, param2 DIV 256); (* mov word[reg1], param2 *)
-            drop
+            |IL.opLOAD64:
+                UnOp(reg1);
+                movrm(reg1, reg1, 0)
+
+            |IL.opLLOAD64:
+                reg1 := GetAnyReg();
+                movrm(reg1, rbp, param2 * 8)
+
+            |IL.opLLOAD8,
+            IL.opLLOAD16:
+                reg1 := GetAnyReg();
+                movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16)
+
+            |IL.opLLOAD32:
+                reg1 := GetAnyReg();
+                movrm32(reg1, rbp, param2 * 8);
+                shiftrc(shl, reg1, 32);
+                shiftrc(shr, reg1, 32)
+
+            |IL.opGLOAD64:
+                reg1 := GetAnyReg();
+                Rex(0, reg1);  (* mov reg1, qword[rip + param2 + BSS] *)
+                OutByte2(8BH, 05H + 8 * (reg1 MOD 8));
+                X86.Reloc(sBSS, param2)
+
+            |IL.opGLOAD8, IL.opGLOAD16:
+                reg1 := GetAnyReg();
+                Rex(0, reg1);  (* movzx reg1, byte/word[rip + param2 + BSS] *)
+                OutByte3(0FH, 0B6H + ORD(opcode = IL.opGLOAD16), 05H + 8 * (reg1 MOD 8));
+                X86.Reloc(sBSS, param2)
 
-        |IL.opSAVEC:
-            UnOp(reg1);
-            IF isLong(param2) THEN
+            |IL.opGLOAD32:
+                reg1 := GetAnyReg();
+                lea(reg1, param2, sBSS);
+                movrm32(reg1, reg1, 0);
+                shiftrc(shl, reg1, 32);
+                shiftrc(shr, reg1, 32)
+
+            |IL.opVLOAD64:
+                reg1 := GetAnyReg();
+                movrm(reg1, rbp, param2 * 8);
+                movrm(reg1, reg1, 0)
+
+            |IL.opVLOAD8,
+            IL.opVLOAD16:
+                reg1 := GetAnyReg();
+                movrm(reg1, rbp, param2 * 8);
+                movzx(reg1, reg1, 0, opcode = IL.opVLOAD16)
+
+            |IL.opVLOAD32:
+                reg1 := GetAnyReg();
                 reg2 := GetAnyReg();
-                movrc(reg2, param2);
-                movmr(reg1, 0, reg2);
+                movrm(reg2, rbp, param2 * 8);
+                movrm32(reg1, reg2, 0);
+                shiftrc(shl, reg1, 32);
+                shiftrc(shr, reg1, 32);
                 drop
-            ELSE
-                Rex(reg1, 0);
-                OutByte2(0C7H, reg1 MOD 8); (* mov qword[reg1], param2 *)
-                OutInt(param2)
-            END;
-            drop
 
-        |IL.opRSET:
-            PushAll(2);
-            CallRTL(IL._set);
-            GetRegA
-
-        |IL.opRSETR:
-            PushAll(1);
-            pushc(param2);
-            CallRTL(IL._set);
-            GetRegA
-
-        |IL.opRSETL:
-            UnOp(reg1);
-            REG.PushAll_1(R);
-            pushc(param2);
-            push(reg1);
-            drop;
-            CallRTL(IL._set);
-            GetRegA
-
-        |IL.opRSET1:
-            PushAll(1);
-            CallRTL(IL._set1);
-            GetRegA
-
-        |IL.opINCL, IL.opEXCL:
-            BinOp(reg1, reg2);
-            cmprc(reg1, 64);
-            OutByte2(73H, 04H); (* jnb L *)
-            Rex(reg2, reg1);
-            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); (* bts/btr qword[reg2], reg1 *)
-            (* L: *)
-            drop;
-            drop
+            |IL.opLADR:
+                n := param2 * 8;
+                next := cmd.next(COMMAND);
+                IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN
+                    ASSERT(xmm >= 0);
+                    movsdmr(rbp, n, xmm);
+                    DEC(xmm);
+                    cmd := next
+                ELSIF next.opcode = IL.opLOADF THEN
+                    INC(xmm);
+                    IF xmm > MAX_XMM THEN
+                        ERRORS.ErrorMsg(fname, next.param1, next.param2, FPR_ERR)
+                    END;
+                    movsdrm(xmm, rbp, n);
+                    cmd := next
+                ELSE
+                    IF (next.opcode = IL.opADDC) & ~isLong(n + next.param2) THEN
+                        INC(n, next.param2);
+                        cmd := next
+                    END;
+                    reg1 := GetAnyReg();
+                    Rex(0, reg1);
+                    OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *)
+                    OutIntByte(n)
+                END
 
-        |IL.opINCLC, IL.opEXCLC:
-            UnOp(reg1);
-            Rex(reg1, 0);
-            OutByte2(0FH, 0BAH); (* bts/btr qword[reg1], param2 *)
-            OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2);
-            drop
+            |IL.opGADR:
+                next := cmd.next(COMMAND);
+                IF (next.opcode = IL.opADDC) & ~isLong(param2 + next.param2) THEN
+                    INC(param2, next.param2);
+                    cmd := next
+                END;
+                lea(GetAnyReg(), param2, sBSS)
 
-        |IL.opEQS .. IL.opGES:
-            PushAll(4);
-            pushc(opcode - IL.opEQS);
-            CallRTL(IL._strcmp);
-            GetRegA
+            |IL.opVADR:
+                movrm(GetAnyReg(), rbp, param2 * 8)
 
-        |IL.opEQSW .. IL.opGESW:
-            PushAll(4);
-            pushc(opcode - IL.opEQSW);
-            CallRTL(IL._strcmpw);
-            GetRegA
+            |IL.opSAVE8C:
+                UnOp(reg1);
+                IF reg1 >= 8 THEN
+                    OutByte(41H)
+                END;
+                OutByte3(0C6H, reg1 MOD 8, param2); (* mov byte[reg1], param2 *)
+                drop
 
-        |IL.opCONST:
-            movrc(GetAnyReg(), param2)
+            |IL.opSAVE16C:
+                UnOp(reg1);
+                OutByte(66H);
+                IF reg1 >= 8 THEN
+                    OutByte(41H)
+                END;
+                OutByte2(0C7H, reg1 MOD 8);
+                OutByte2(param2 MOD 256, param2 DIV 256); (* mov word[reg1], param2 *)
+                drop
 
-        |IL.opEQ..IL.opGE,
-         IL.opEQC..IL.opGEC:
+            |IL.opSAVEC:
+                UnOp(reg1);
+                IF isLong(param2) THEN
+                    reg2 := GetAnyReg();
+                    movrc(reg2, param2);
+                    movmr(reg1, 0, reg2);
+                    drop
+                ELSE
+                    Rex(reg1, 0);
+                    OutByte2(0C7H, reg1 MOD 8); (* mov qword[reg1], param2 *)
+                    OutInt(param2)
+                END;
+                drop
+
+            |IL.opRSET:
+                PushAll(2);
+                CallRTL(IL._set);
+                GetRegA
+
+            |IL.opRSETR:
+                PushAll(1);
+                pushc(param2);
+                CallRTL(IL._set);
+                GetRegA
+
+            |IL.opRSETL:
+                UnOp(reg1);
+                REG.PushAll_1(R);
+                pushc(param2);
+                push(reg1);
+                drop;
+                CallRTL(IL._set);
+                GetRegA
+
+            |IL.opRSET1:
+                PushAll(1);
+                CallRTL(IL._set1);
+                GetRegA
 
-            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
+            |IL.opINCL, IL.opEXCL:
                 BinOp(reg1, reg2);
-                cmprr(reg1, reg2);
+                cmprc(reg1, 64);
+                OutByte2(73H, 04H); (* jnb L *)
+                Rex(reg2, reg1);
+                OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); (* bts/btr qword[reg2], reg1 *)
+                (* L: *)
+                drop;
                 drop
-            ELSE
+
+            |IL.opINCLC, IL.opEXCLC:
                 UnOp(reg1);
-                cmprc(reg1, param2)
-            END;
+                Rex(reg1, 0);
+                OutByte2(0FH, 0BAH); (* bts/btr qword[reg1], param2 *)
+                OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2);
+                drop
 
-            drop;
-            cc := X86.cond(opcode);
-
-            next := cmd.next(COMMAND);
-            IF next.opcode = IL.opJNZ THEN
-                jcc(cc, next.param1);
-                cmd := next
-            ELSIF next.opcode = IL.opJZ THEN
-                jcc(X86.inv0(cc), next.param1);
-                cmd := next
-            ELSE
+            |IL.opEQS .. IL.opGES:
+                PushAll(4);
+                pushc(opcode - IL.opEQS);
+                CallRTL(IL._strcmp);
+                GetRegA
+
+            |IL.opEQSW .. IL.opGESW:
+                PushAll(4);
+                pushc(opcode - IL.opEQSW);
+                CallRTL(IL._strcmpw);
+                GetRegA
+
+            |IL.opCONST:
+                movrc(GetAnyReg(), param2)
+
+            |IL.opEQ..IL.opGE,
+            IL.opEQC..IL.opGEC:
+
+                IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
+                    BinOp(reg1, reg2);
+                    cmprr(reg1, reg2);
+                    drop
+                ELSE
+                    UnOp(reg1);
+                    cmprc(reg1, param2)
+                END;
+
+                drop;
+                cc := X86.cond(opcode);
+
+                next := cmd.next(COMMAND);
+                IF next.opcode = IL.opJNZ THEN
+                    jcc(cc, next.param1);
+                    cmd := next
+                ELSIF next.opcode = IL.opJZ THEN
+                    jcc(X86.inv0(cc), next.param1);
+                    cmd := next
+                ELSE
+                    reg1 := GetAnyReg();
+                    X86.setcc(cc + 16, reg1);
+                    andrc(reg1, 1)
+                END
+
+            |IL.opCODE:
+                OutByte(param2)
+
+            |IL.opPUSHIP:
                 reg1 := GetAnyReg();
-                X86.setcc(cc + 16, reg1);
-                andrc(reg1, 1)
-            END
+                lea(reg1, param2, sIMP);
+                movrm(reg1, reg1, 0)
+
+            |IL.opPARAM:
+                IF param2 = 1 THEN
+                    UnOp(reg1);
+                    push(reg1);
+                    drop
+                ELSE
+                    ASSERT(R.top + 1 <= param2);
+                    PushAll(param2)
+                END
 
-        |IL.opCODE:
-            OutByte(param2)
+            |IL.opJNZ1:
+                UnOp(reg1);
+                test(reg1);
+                jcc(jne, param1)
 
-        |IL.opPUSHIP:
-            reg1 := GetAnyReg();
-            lea(reg1, param2, sIMP);
-            movrm(reg1, reg1, 0)
+            |IL.opJG:
+                UnOp(reg1);
+                test(reg1);
+                jcc(jg, param1)
 
-        |IL.opPARAM:
-            IF param2 = 1 THEN
+            |IL.opJNZ:
                 UnOp(reg1);
-                push(reg1);
+                test(reg1);
+                jcc(jne, param1);
                 drop
-            ELSE
-                ASSERT(R.top + 1 <= param2);
-                PushAll(param2)
-            END
-
-        |IL.opJNZ1:
-            UnOp(reg1);
-            test(reg1);
-            jcc(jne, param1)
 
-        |IL.opJG:
-            UnOp(reg1);
-            test(reg1);
-            jcc(jg, param1)
+            |IL.opJZ:
+                UnOp(reg1);
+                test(reg1);
+                jcc(je, param1);
+                drop
 
-        |IL.opJNZ:
-            UnOp(reg1);
-            test(reg1);
-            jcc(jne, param1);
-            drop
+            |IL.opIN, IL.opINR:
+                IF opcode = IL.opINR THEN
+                    reg2 := GetAnyReg();
+                    movrc(reg2, param2)
+                END;
+                label := NewLabel();
+                L := NewLabel();
+                BinOp(reg1, reg2);
+                cmprc(reg1, 64);
+                jcc(jb, L);
+                xor(reg1, reg1);
+                X86.jmp(label);
+                X86.SetLabel(L);
+                Rex(reg2, reg1);
+                OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *)
+                X86.setcc(setc, reg1);
+                andrc(reg1, 1);
+                X86.SetLabel(label);
+                drop
 
-        |IL.opJZ:
-            UnOp(reg1);
-            test(reg1);
-            jcc(je, param1);
-            drop
+            |IL.opINL:
+                UnOp(reg1);
+                Rex(reg1, 0);
+                OutByte2(0FH, 0BAH); (* bt reg1, param2 *)
+                OutByte2(0E0H + reg1 MOD 8, param2);
+                X86.setcc(setc, reg1);
+                andrc(reg1, 1)
 
-        |IL.opIN, IL.opINR:
-            IF opcode = IL.opINR THEN
-                reg2 := GetAnyReg();
-                movrc(reg2, param2)
-            END;
-            label := NewLabel();
-            L := NewLabel();
-            BinOp(reg1, reg2);
-            cmprc(reg1, 64);
-            jcc(jb, L);
-            xor(reg1, reg1);
-            X86.jmp(label);
-            X86.SetLabel(L);
-            Rex(reg2, reg1);
-            OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *)
-            X86.setcc(setc, reg1);
-            andrc(reg1, 1);
-            X86.SetLabel(label);
-            drop
+            |IL.opNOT:
+                UnOp(reg1);
+                test(reg1);
+                X86.setcc(sete, reg1);
+                andrc(reg1, 1)
 
-        |IL.opINL:
-            UnOp(reg1);
-            Rex(reg1, 0);
-            OutByte2(0FH, 0BAH); (* bt reg1, param2 *)
-            OutByte2(0E0H + reg1 MOD 8, param2);
-            X86.setcc(setc, reg1);
-            andrc(reg1, 1)
-
-        |IL.opNOT:
-            UnOp(reg1);
-            test(reg1);
-            X86.setcc(sete, reg1);
-            andrc(reg1, 1)
-
-        |IL.opORD:
-            UnOp(reg1);
-            test(reg1);
-            X86.setcc(setne, reg1);
-            andrc(reg1, 1)
-
-        |IL.opABS:
-            UnOp(reg1);
-            test(reg1);
-            OutByte2(7DH, 03H); (* jge L *)
-            neg(reg1)
-            (* L: *)
-
-        |IL.opEQB, IL.opNEB:
-            BinOp(reg1, reg2);
-            drop;
-            test(reg1);
-            label := NewLabel();
-            jcc(je, label);
-            movrc(reg1, 1);
-            X86.SetLabel(label);
-            test(reg2);
-            label := NewLabel();
-            jcc(je, label);
-            movrc(reg2, 1);
-            X86.SetLabel(label);
-            cmprr(reg1, reg2);
-            IF opcode = IL.opEQB THEN
-                X86.setcc(sete, reg1)
-            ELSE
-                X86.setcc(setne, reg1)
-            END;
-            andrc(reg1, 1)
+            |IL.opORD:
+                UnOp(reg1);
+                test(reg1);
+                X86.setcc(setne, reg1);
+                andrc(reg1, 1)
 
-        |IL.opMULSC:
-            UnOp(reg1);
-            andrc(reg1, param2)
+            |IL.opABS:
+                UnOp(reg1);
+                test(reg1);
+                OutByte2(7DH, 03H); (* jge L *)
+                neg(reg1)
+                (* L: *)
 
-        |IL.opDIVSC:
-            UnOp(reg1);
-            xorrc(reg1, param2)
+            |IL.opEQB, IL.opNEB:
+                BinOp(reg1, reg2);
+                drop;
+                test(reg1);
+                label := NewLabel();
+                jcc(je, label);
+                movrc(reg1, 1);
+                X86.SetLabel(label);
+                test(reg2);
+                label := NewLabel();
+                jcc(je, label);
+                movrc(reg2, 1);
+                X86.SetLabel(label);
+                cmprr(reg1, reg2);
+                IF opcode = IL.opEQB THEN
+                    X86.setcc(sete, reg1)
+                ELSE
+                    X86.setcc(setne, reg1)
+                END;
+                andrc(reg1, 1)
 
-        |IL.opADDSC:
-            UnOp(reg1);
-            orrc(reg1, param2)
+            |IL.opMULSC:
+                UnOp(reg1);
+                andrc(reg1, param2)
 
-        |IL.opSUBSL:
-            UnOp(reg1);
-            not(reg1);
-            andrc(reg1, param2)
+            |IL.opDIVSC:
+                UnOp(reg1);
+                xorrc(reg1, param2)
 
-        |IL.opSUBSR:
-            UnOp(reg1);
-            andrc(reg1, ORD(-BITS(param2)))
+            |IL.opADDSC:
+                UnOp(reg1);
+                orrc(reg1, param2)
 
-        |IL.opMULS:
-            BinOp(reg1, reg2);
-            and(reg1, reg2);
-            drop
+            |IL.opSUBSL:
+                UnOp(reg1);
+                not(reg1);
+                andrc(reg1, param2)
 
-        |IL.opDIVS:
-            BinOp(reg1, reg2);
-            xor(reg1, reg2);
-            drop
+            |IL.opSUBSR:
+                UnOp(reg1);
+                andrc(reg1, ORD(-BITS(param2)))
 
-        |IL.opUMINS:
-            UnOp(reg1);
-            not(reg1)
+            |IL.opMULS:
+                BinOp(reg1, reg2);
+                and(reg1, reg2);
+                drop
 
-        |IL.opCOPY:
-            IF (0 < param2) & (param2 <= 256) THEN
+            |IL.opDIVS:
                 BinOp(reg1, reg2);
-                reg3 := GetAnyReg();
-                FOR n := 0 TO param2 - param2 MOD 8 - 1 BY 8 DO
-                    movrm(reg3, reg1, n);
-                    movmr(reg2, n, reg3)
-                END;
-                n := param2 - param2 MOD 8;
-                IF param2 MOD 8 >= 4 THEN
-                    movrm32(reg3, reg1, n);
-                    movmr32(reg2, n, reg3);
-                    INC(n, 4);
-                    DEC(param2, 4)
-                END;
-                IF param2 MOD 8 >= 2 THEN
-                    X86.movrm16(reg3, reg1, n);
-                    X86.movmr16(reg2, n, reg3);
-                    INC(n, 2);
-                    DEC(param2, 2)
-                END;
-                IF param2 MOD 8 = 1 THEN
-                    X86.movrm8(reg3, reg1, n);
-                    X86.movmr8(reg2, n, reg3);
-                END;
-                drop;
-                drop;
+                xor(reg1, reg2);
                 drop
-            ELSE
-                PushAll(2);
-                pushc(param2);
+
+            |IL.opUMINS:
+                UnOp(reg1);
+                not(reg1)
+
+            |IL.opCOPY:
+                IF (0 < param2) & (param2 <= 256) THEN
+                    BinOp(reg1, reg2);
+                    reg3 := GetAnyReg();
+                    FOR n := 0 TO param2 - param2 MOD 8 - 1 BY 8 DO
+                        movrm(reg3, reg1, n);
+                        movmr(reg2, n, reg3)
+                    END;
+                    n := param2 - param2 MOD 8;
+                    IF param2 MOD 8 >= 4 THEN
+                        movrm32(reg3, reg1, n);
+                        movmr32(reg2, n, reg3);
+                        INC(n, 4);
+                        DEC(param2, 4)
+                    END;
+                    IF param2 MOD 8 >= 2 THEN
+                        X86.movrm16(reg3, reg1, n);
+                        X86.movmr16(reg2, n, reg3);
+                        INC(n, 2);
+                        DEC(param2, 2)
+                    END;
+                    IF param2 MOD 8 = 1 THEN
+                        X86.movrm8(reg3, reg1, n);
+                        X86.movmr8(reg2, n, reg3);
+                    END;
+                    drop;
+                    drop;
+                    drop
+                ELSE
+                    PushAll(2);
+                    pushc(param2);
+                    CallRTL(IL._move)
+                END
+
+            |IL.opMOVE:
+                PushAll(3);
                 CallRTL(IL._move)
-            END
 
-        |IL.opMOVE:
-            PushAll(3);
-            CallRTL(IL._move)
+            |IL.opCOPYA:
+                PushAll(4);
+                pushc(param2);
+                CallRTL(IL._arrcpy);
+                GetRegA
 
-        |IL.opCOPYA:
-            PushAll(4);
-            pushc(param2);
-            CallRTL(IL._arrcpy);
-            GetRegA
+            |IL.opCOPYS:
+                PushAll(4);
+                pushc(param2);
+                CallRTL(IL._strcpy)
 
-        |IL.opCOPYS:
-            PushAll(4);
-            pushc(param2);
-            CallRTL(IL._strcpy)
+            |IL.opROT:
+                PushAll(0);
+                push(rsp);
+                pushc(param2);
+                CallRTL(IL._rot)
 
-        |IL.opROT:
-            PushAll(0);
-            push(rsp);
-            pushc(param2);
-            CallRTL(IL._rot)
-
-        |IL.opNEW:
-            PushAll(1);
-            n := param2 + 16;
-            ASSERT(UTILS.Align(n, 16));
-            pushc(n);
-            pushc(param1);
-            CallRTL(IL._new)
-
-        |IL.opDISP:
-            PushAll(1);
-            CallRTL(IL._dispose)
-
-        |IL.opPUSHT:
-            UnOp(reg1);
-            movrm(GetAnyReg(), reg1, -8)
-
-        |IL.opISREC:
-            PushAll(2);
-            pushc(param2 * tcount);
-            CallRTL(IL._isrec);
-            GetRegA
-
-        |IL.opIS:
-            PushAll(1);
-            pushc(param2 * tcount);
-            CallRTL(IL._is);
-            GetRegA
-
-        |IL.opTYPEGR:
-            PushAll(1);
-            pushc(param2 * tcount);
-            CallRTL(IL._guardrec);
-            GetRegA
-
-        |IL.opTYPEGP:
-            UnOp(reg1);
-            PushAll(0);
-            push(reg1);
-            pushc(param2 * tcount);
-            CallRTL(IL._guard);
-            GetRegA
-
-        |IL.opTYPEGD:
-            UnOp(reg1);
-            PushAll(0);
-            X86.pushm(reg1, -8);
-            pushc(param2 * tcount);
-            CallRTL(IL._guardrec);
-            GetRegA
-
-        |IL.opCASET:
-            push(rcx);
-            push(rcx);
-            pushc(param2 * tcount);
-            CallRTL(IL._guardrec);
-            pop(rcx);
-            test(rax);
-            jcc(jne, param1)
+            |IL.opNEW:
+                PushAll(1);
+                n := param2 + 16;
+                ASSERT(UTILS.Align(n, 16));
+                pushc(n);
+                pushc(param1);
+                CallRTL(IL._new)
 
-        |IL.opSAVEP:
-            UnOp(reg1);
-            reg2 := GetAnyReg();
-            lea(reg2, param2, sCODE);
-            movmr(reg1, 0, reg2);
-            drop;
-            drop
+            |IL.opDISP:
+                PushAll(1);
+                CallRTL(IL._dispose)
 
-        |IL.opPUSHP:
-            lea(GetAnyReg(), param2, sCODE)
+            |IL.opPUSHT:
+                UnOp(reg1);
+                movrm(GetAnyReg(), reg1, -8)
 
-        |IL.opINC, IL.opDEC:
-            BinOp(reg1, reg2);
-            (* add/sub qword[reg2], reg1 *)
-            Rex(reg2, reg1);
-            OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8);
-            drop;
-            drop
+            |IL.opISREC:
+                PushAll(2);
+                pushc(param2 * tcount);
+                CallRTL(IL._isrec);
+                GetRegA
+
+            |IL.opIS:
+                PushAll(1);
+                pushc(param2 * tcount);
+                CallRTL(IL._is);
+                GetRegA
+
+            |IL.opTYPEGR:
+                PushAll(1);
+                pushc(param2 * tcount);
+                CallRTL(IL._guardrec);
+                GetRegA
+
+            |IL.opTYPEGP:
+                UnOp(reg1);
+                PushAll(0);
+                push(reg1);
+                pushc(param2 * tcount);
+                CallRTL(IL._guard);
+                GetRegA
 
-        |IL.opINCC:
-            UnOp(reg1);
-            IF isLong(param2) THEN
+            |IL.opTYPEGD:
+                UnOp(reg1);
+                PushAll(0);
+                X86.pushm(reg1, -8);
+                pushc(param2 * tcount);
+                CallRTL(IL._guardrec);
+                GetRegA
+
+            |IL.opCASET:
+                push(rcx);
+                push(rcx);
+                pushc(param2 * tcount);
+                CallRTL(IL._guardrec);
+                pop(rcx);
+                test(rax);
+                jcc(jne, param1)
+
+            |IL.opSAVEP:
+                UnOp(reg1);
                 reg2 := GetAnyReg();
-                movrc(reg2, param2);
-                (* add qword[reg1], reg2 *)
-                Rex(reg1, reg2);
-                OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8);
+                lea(reg2, param2, sCODE);
+                movmr(reg1, 0, reg2);
+                drop;
                 drop
-            ELSIF ABS(param2) = 1 THEN
-                Rex(reg1, 0);
-                OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *)
-            ELSE
-                (* add qword[reg1], param2 *)
-                Rex(reg1, 0);
-                OutByte2(81H + short(param2), reg1 MOD 8);
-                OutIntByte(param2)
-            END;
-            drop
 
-        |IL.opDROP:
-            UnOp(reg1);
-            drop
+            |IL.opPUSHP:
+                lea(GetAnyReg(), param2, sCODE)
 
-        |IL.opSAVE, IL.opSAVE64:
-            BinOp(reg2, reg1);
-            movmr(reg1, 0, reg2);
-            drop;
-            drop
+            |IL.opINC, IL.opDEC:
+                BinOp(reg1, reg2);
+                (* add/sub qword[reg2], reg1 *)
+                Rex(reg2, reg1);
+                OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8);
+                drop;
+                drop
 
-        |IL.opSAVE8:
-            BinOp(reg2, reg1);
-            X86.movmr8(reg1, 0, reg2);
-            drop;
-            drop
+            |IL.opINCC:
+                UnOp(reg1);
+                IF isLong(param2) THEN
+                    reg2 := GetAnyReg();
+                    movrc(reg2, param2);
+                    (* add qword[reg1], reg2 *)
+                    Rex(reg1, reg2);
+                    OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8);
+                    drop
+                ELSIF ABS(param2) = 1 THEN
+                    Rex(reg1, 0);
+                    OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *)
+                ELSE
+                    (* add qword[reg1], param2 *)
+                    Rex(reg1, 0);
+                    OutByte2(81H + short(param2), reg1 MOD 8);
+                    OutIntByte(param2)
+                END;
+                drop
 
-        |IL.opSAVE16:
-            BinOp(reg2, reg1);
-            X86.movmr16(reg1, 0, reg2);
-            drop;
-            drop
+            |IL.opDROP:
+                UnOp(reg1);
+                drop
 
-        |IL.opSAVE32:
-            BinOp(reg2, reg1);
-            movmr32(reg1, 0, reg2);
-            drop;
-            drop
+            |IL.opSAVE, IL.opSAVE64:
+                BinOp(reg2, reg1);
+                movmr(reg1, 0, reg2);
+                drop;
+                drop
 
-        |IL.opMAX, IL.opMIN:
-            BinOp(reg1, reg2);
-            cmprr(reg1, reg2);
-            OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *)
-            mov(reg1, reg2);
-            (* L: *)
-            drop
+            |IL.opSAVE8:
+                BinOp(reg2, reg1);
+                X86.movmr8(reg1, 0, reg2);
+                drop;
+                drop
 
-        |IL.opMAXC, IL.opMINC:
-            UnOp(reg1);
-            cmprc(reg1, param2);
-            label := NewLabel();
-            IF opcode = IL.opMINC THEN
-                cc := jle
-            ELSE
-                cc := jge
-            END;
-            jcc(cc, label);
-            movrc(reg1, param2);
-            X86.SetLabel(label)
-
-        |IL.opSBOOL:
-            BinOp(reg2, reg1);
-            test(reg2);
-            IF reg1 >= 8 THEN
-                OutByte(41H)
-            END;
-            OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *)
-            drop;
-            drop
+            |IL.opSAVE16:
+                BinOp(reg2, reg1);
+                X86.movmr16(reg1, 0, reg2);
+                drop;
+                drop
 
-        |IL.opSBOOLC:
-            UnOp(reg1);
-            IF reg1 >= 8 THEN
-                OutByte(41H)
-            END;
-            OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
-            drop
+            |IL.opSAVE32:
+                BinOp(reg2, reg1);
+                movmr32(reg1, 0, reg2);
+                drop;
+                drop
 
-        |IL.opUMINUS:
-            UnOp(reg1);
-            neg(reg1)
+            |IL.opMAX, IL.opMIN:
+                BinOp(reg1, reg2);
+                cmprr(reg1, reg2);
+                OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *)
+                mov(reg1, reg2);
+                (* L: *)
+                drop
 
-        |IL.opADD:
-            BinOp(reg1, reg2);
-            add(reg1, reg2);
-            drop
+            |IL.opMAXC, IL.opMINC:
+                UnOp(reg1);
+                cmprc(reg1, param2);
+                label := NewLabel();
+                IF opcode = IL.opMINC THEN
+                    cc := jle
+                ELSE
+                    cc := jge
+                END;
+                jcc(cc, label);
+                movrc(reg1, param2);
+                X86.SetLabel(label)
 
-        |IL.opSUB:
-            BinOp(reg1, reg2);
-            sub(reg1, reg2);
-            drop
+            |IL.opSBOOL:
+                BinOp(reg2, reg1);
+                test(reg2);
+                IF reg1 >= 8 THEN
+                    OutByte(41H)
+                END;
+                OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *)
+                drop;
+                drop
 
-        |IL.opSUBR, IL.opSUBL:
-            UnOp(reg1);
-            IF param2 = 1 THEN
-                decr(reg1)
-            ELSIF param2 = -1 THEN
-                incr(reg1)
-            ELSIF param2 # 0 THEN
-                subrc(reg1, param2)
-            END;
-            IF opcode = IL.opSUBL THEN
+            |IL.opSBOOLC:
+                UnOp(reg1);
+                IF reg1 >= 8 THEN
+                    OutByte(41H)
+                END;
+                OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
+                drop
+
+            |IL.opUMINUS:
+                UnOp(reg1);
                 neg(reg1)
-            END
 
-        |IL.opADDC:
-            IF (param2 # 0) & ~isLong(param2) THEN
+            |IL.opADD:
+                BinOp(reg1, reg2);
+                add(reg1, reg2);
+                drop
+
+            |IL.opSUB:
+                BinOp(reg1, reg2);
+                sub(reg1, reg2);
+                drop
+
+            |IL.opSUBR, IL.opSUBL:
                 UnOp(reg1);
-                next := cmd.next(COMMAND);
-                CASE next.opcode OF
-                |IL.opLOAD64:
-                    movrm(reg1, reg1, param2);
-                    cmd := next
-                |IL.opLOAD32:
-                    movrm32(reg1, reg1, param2);
-                    shiftrc(shl, reg1, 32);
-                    shiftrc(shr, reg1, 32);
-                    cmd := next
-                |IL.opLOAD16:
-                    movzx(reg1, reg1, param2, TRUE);
-                    cmd := next
-                |IL.opLOAD8:
-                    movzx(reg1, reg1, param2, FALSE);
-                    cmd := next
-                |IL.opLOAD64_PARAM:
-                    X86.pushm(reg1, param2);
-                    drop;
-                    cmd := next
-                ELSE
-                    IF param2 = 1 THEN
-                        incr(reg1)
-                    ELSIF param2 = -1 THEN
-                        decr(reg1)
+                IF param2 = 1 THEN
+                    decr(reg1)
+                ELSIF param2 = -1 THEN
+                    incr(reg1)
+                ELSIF param2 # 0 THEN
+                    subrc(reg1, param2)
+                END;
+                IF opcode = IL.opSUBL THEN
+                    neg(reg1)
+                END
+
+            |IL.opADDC:
+                IF (param2 # 0) & ~isLong(param2) THEN
+                    UnOp(reg1);
+                    next := cmd.next(COMMAND);
+                    CASE next.opcode OF
+                    |IL.opLOAD64:
+                        movrm(reg1, reg1, param2);
+                        cmd := next
+                    |IL.opLOAD32:
+                        movrm32(reg1, reg1, param2);
+                        shiftrc(shl, reg1, 32);
+                        shiftrc(shr, reg1, 32);
+                        cmd := next
+                    |IL.opLOAD16:
+                        movzx(reg1, reg1, param2, TRUE);
+                        cmd := next
+                    |IL.opLOAD8:
+                        movzx(reg1, reg1, param2, FALSE);
+                        cmd := next
+                    |IL.opLOAD64_PARAM:
+                        X86.pushm(reg1, param2);
+                        drop;
+                        cmd := next
                     ELSE
-                        addrc(reg1, param2)
+                        IF param2 = 1 THEN
+                            incr(reg1)
+                        ELSIF param2 = -1 THEN
+                            decr(reg1)
+                        ELSE
+                            addrc(reg1, param2)
+                        END
                     END
+                ELSIF isLong(param2) THEN
+                    UnOp(reg1);
+                    addrc(reg1, param2)
                 END
-            ELSIF isLong(param2) THEN
-                UnOp(reg1);
-                addrc(reg1, param2)
-            END
 
-        |IL.opDIV:
-            PushAll(2);
-            CallRTL(IL._divmod);
-            GetRegA
+            |IL.opDIV:
+                PushAll(2);
+                CallRTL(IL._divmod);
+                GetRegA
 
-        |IL.opDIVR:
-            n := UTILS.Log2(param2);
-            IF n > 0 THEN
+            |IL.opDIVR:
+                n := UTILS.Log2(param2);
+                IF n > 0 THEN
+                    UnOp(reg1);
+                    shiftrc(sar, reg1, n)
+                ELSIF n < 0 THEN
+                    PushAll(1);
+                    pushc(param2);
+                    CallRTL(IL._divmod);
+                    GetRegA
+                END
+
+            |IL.opDIVL:
                 UnOp(reg1);
-                shiftrc(sar, reg1, n)
-            ELSIF n < 0 THEN
-                PushAll(1);
+                REG.PushAll_1(R);
                 pushc(param2);
+                push(reg1);
+                drop;
                 CallRTL(IL._divmod);
                 GetRegA
-            END
 
-        |IL.opDIVL:
-            UnOp(reg1);
-            REG.PushAll_1(R);
-            pushc(param2);
-            push(reg1);
-            drop;
-            CallRTL(IL._divmod);
-            GetRegA
-
-        |IL.opMOD:
-            PushAll(2);
-            CallRTL(IL._divmod);
-            mov(rax, rdx);
-            GetRegA
-
-        |IL.opMODR:
-            n := UTILS.Log2(param2);
-            IF n > 0 THEN
-                UnOp(reg1);
-                andrc(reg1, param2 - 1);
-            ELSIF n < 0 THEN
-                PushAll(1);
-                pushc(param2);
+            |IL.opMOD:
+                PushAll(2);
                 CallRTL(IL._divmod);
                 mov(rax, rdx);
                 GetRegA
-            ELSE
-                UnOp(reg1);
-                xor(reg1, reg1)
-            END
 
-        |IL.opMODL:
-            UnOp(reg1);
-            REG.PushAll_1(R);
-            pushc(param2);
-            push(reg1);
-            drop;
-            CallRTL(IL._divmod);
-            mov(rax, rdx);
-            GetRegA
+            |IL.opMODR:
+                n := UTILS.Log2(param2);
+                IF n > 0 THEN
+                    UnOp(reg1);
+                    andrc(reg1, param2 - 1);
+                ELSIF n < 0 THEN
+                    PushAll(1);
+                    pushc(param2);
+                    CallRTL(IL._divmod);
+                    mov(rax, rdx);
+                    GetRegA
+                ELSE
+                    UnOp(reg1);
+                    xor(reg1, reg1)
+                END
 
-        |IL.opMUL:
-            BinOp(reg1, reg2);
-            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
-            drop
+            |IL.opMODL:
+                UnOp(reg1);
+                REG.PushAll_1(R);
+                pushc(param2);
+                push(reg1);
+                drop;
+                CallRTL(IL._divmod);
+                mov(rax, rdx);
+                GetRegA
 
-        |IL.opMULC:
-            IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
+            |IL.opMUL:
                 BinOp(reg1, reg2);
-                OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *)
-                reg1 := reg1 MOD 8;
-                reg2 := reg2 MOD 8;
-                OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2));
-                drop;
-                cmd := cmd.next(COMMAND)
-            ELSE
-                UnOp(reg1);
+                oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
+                drop
 
-                a := param2;
-                IF a > 1 THEN
-                    n := UTILS.Log2(a)
-                ELSIF a < -1 THEN
-                    n := UTILS.Log2(-a)
+            |IL.opMULC:
+                IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
+                    BinOp(reg1, reg2);
+                    OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *)
+                    reg1 := reg1 MOD 8;
+                    reg2 := reg2 MOD 8;
+                    OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2));
+                    drop;
+                    cmd := cmd.next(COMMAND)
                 ELSE
-                    n := -1
-                END;
+                    UnOp(reg1);
 
-                IF a = 1 THEN
+                    a := param2;
+                    IF a > 1 THEN
+                        n := UTILS.Log2(a)
+                    ELSIF a < -1 THEN
+                        n := UTILS.Log2(-a)
+                    ELSE
+                        n := -1
+                    END;
 
-                ELSIF a = -1 THEN
-                    neg(reg1)
-                ELSIF a = 0 THEN
-                    xor(reg1, reg1)
-                ELSE
-                    IF n > 0 THEN
-                        IF a < 0 THEN
-                            neg(reg1)
-                        END;
-                        shiftrc(shl, reg1, n)
+                    IF a = 1 THEN
+
+                    ELSIF a = -1 THEN
+                        neg(reg1)
+                    ELSIF a = 0 THEN
+                        xor(reg1, reg1)
                     ELSE
-                        IF isLong(a) THEN
-                            reg2 := GetAnyReg();
-                            movabs(reg2, a);
-                            ASSERT(reg1 # reg2);
-                            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
-                            drop
+                        IF n > 0 THEN
+                            IF a < 0 THEN
+                                neg(reg1)
+                            END;
+                            shiftrc(shl, reg1, n)
                         ELSE
-                            (* imul reg1, a *)
-                            Rex(reg1, reg1);
-                            OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9);
-                            OutIntByte(a)
+                            IF isLong(a) THEN
+                                reg2 := GetAnyReg();
+                                movabs(reg2, a);
+                                ASSERT(reg1 # reg2);
+                                oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
+                                drop
+                            ELSE
+                                (* imul reg1, a *)
+                                Rex(reg1, reg1);
+                                OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9);
+                                OutIntByte(a)
+                            END
                         END
                     END
                 END
-            END
 
-        |IL.opADDS:
-            BinOp(reg1, reg2);
-            _or(reg1, reg2);
-            drop
+            |IL.opADDS:
+                BinOp(reg1, reg2);
+                _or(reg1, reg2);
+                drop
+
+            |IL.opSUBS:
+                BinOp(reg1, reg2);
+                not(reg2);
+                and(reg1, reg2);
+                drop
+
+            |IL.opNOP, IL.opAND, IL.opOR:
+
+            |IL.opSWITCH:
+                UnOp(reg1);
+                IF param2 = 0 THEN
+                    reg2 := rax
+                ELSE
+                    reg2 := rcx
+                END;
+                IF reg1 # reg2 THEN
+                    ASSERT(REG.GetReg(R, reg2));
+                    ASSERT(REG.Exchange(R, reg1, reg2));
+                    drop
+                END;
+                drop
+
+            |IL.opENDSW:
+
+            |IL.opCASEL:
+                GetRegA;
+                cmprc(rax, param1);
+                jcc(jl, param2);
+                drop
+
+            |IL.opCASER:
+                GetRegA;
+                cmprc(rax, param1);
+                jcc(jg, param2);
+                drop
+
+            |IL.opCASELR:
+                GetRegA;
+                cmprc(rax, param1);
+                IF param2 = cmd.param3 THEN
+                    jcc(jne, param2)
+                ELSE
+                    jcc(jl, param2);
+                    jcc(jg, cmd.param3)
+                END;
+                drop
+
+            |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
+                UnOp(reg1);
+                IF reg1 # rcx THEN
+                    ASSERT(REG.GetReg(R, rcx));
+                    ASSERT(REG.Exchange(R, reg1, rcx));
+                    drop
+                END;
+
+                BinOp(reg1, reg2);
+                ASSERT(reg2 = rcx);
+                Rex(reg1, 0);
+                OutByte(0D3H);
+                X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *)
+                drop
+
+            |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
+                UnOp(reg1);
+                IF reg1 # rcx THEN
+                    ASSERT(REG.GetReg(R, rcx));
+                    ASSERT(REG.Exchange(R, reg1, rcx));
+                    drop
+                END;
+
+                reg1 := GetAnyReg();
+                movrc(reg1, param2);
+                BinOp(reg1, reg2);
+                ASSERT(reg1 = rcx);
+                Rex(reg2, 0);
+                OutByte(0D3H);
+                X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *)
+                drop;
+                drop;
+                ASSERT(REG.GetReg(R, reg2))
+
+            |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
+                UnOp(reg1);
+                shiftrc(opcode, reg1, param2 MOD 64)
+
+            |IL.opGET, IL.opGETC:
+                IF opcode = IL.opGET THEN
+                    BinOp(reg1, reg2)
+                ELSIF opcode = IL.opGETC THEN
+                    UnOp(reg2);
+                    reg1 := GetAnyReg();
+                    movrc(reg1, param1)
+                END;
+                drop;
+                drop;
+                X86._movrm(reg1, reg1, 0, param2 * 8, FALSE);
+                X86._movrm(reg1, reg2, 0, param2 * 8, TRUE)
+
+            |IL.opCHKIDX:
+                UnOp(reg1);
+                cmprc(reg1, param2);
+                jcc(jb, param1)
+
+            |IL.opCHKIDX2:
+                BinOp(reg1, reg2);
+                IF param2 # -1 THEN
+                    cmprr(reg2, reg1);
+                    jcc(jb, param1);
+                END;
+                INCL(R.regs, reg1);
+                DEC(R.top);
+                R.stk[R.top] := reg2
+
+            |IL.opLENGTH:
+                PushAll(2);
+                CallRTL(IL._length);
+                GetRegA
+
+            |IL.opLENGTHW:
+                PushAll(2);
+                CallRTL(IL._lengthw);
+                GetRegA
+
+            |IL.opLEN:
+                n := param2;
+                UnOp(reg1);
+                drop;
+                EXCL(R.regs, reg1);
 
-        |IL.opSUBS:
-            BinOp(reg1, reg2);
-            not(reg2);
-            and(reg1, reg2);
-            drop
+                WHILE n > 0 DO
+                    UnOp(reg2);
+                    drop;
+                    DEC(n)
+                END;
 
-        |IL.opNOP, IL.opAND, IL.opOR:
+                INCL(R.regs, reg1);
+                ASSERT(REG.GetReg(R, reg1))
 
-        |IL.opSWITCH:
-            UnOp(reg1);
-            IF param2 = 0 THEN
-                reg2 := rax
-            ELSE
-                reg2 := rcx
-            END;
-            IF reg1 # reg2 THEN
-                ASSERT(REG.GetReg(R, reg2));
-                ASSERT(REG.Exchange(R, reg1, reg2));
-                drop
-            END;
-            drop
+            |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
+                UnOp(reg1);
+                reg2 := GetAnyReg();
 
-        |IL.opENDSW:
+                CASE opcode OF
+                |IL.opEQP, IL.opNEP:
+                    lea(reg2, param1, sCODE)
 
-        |IL.opCASEL:
-            GetRegA;
-            cmprc(rax, param1);
-            jcc(jl, param2);
-            drop
+                |IL.opEQIP, IL.opNEIP:
+                    lea(reg2, param1, sIMP);
+                    movrm(reg2, reg2, 0)
+                END;
 
-        |IL.opCASER:
-            GetRegA;
-            cmprc(rax, param1);
-            jcc(jg, param2);
-            drop
+                cmprr(reg1, reg2);
+                drop;
+                drop;
+                reg1 := GetAnyReg();
 
-        |IL.opCASELR:
-            GetRegA;
-            cmprc(rax, param1);
-            IF param2 = cmd.param3 THEN
-                jcc(jne, param2)
-            ELSE
-                jcc(jl, param2);
-                jcc(jg, cmd.param3)
-            END;
-            drop
+                CASE opcode OF
+                |IL.opEQP, IL.opEQIP: X86.setcc(sete,  reg1)
+                |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1)
+                END;
+
+                andrc(reg1, 1)
 
-        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
-            UnOp(reg1);
-            IF reg1 # rcx THEN
-                ASSERT(REG.GetReg(R, rcx));
-                ASSERT(REG.Exchange(R, reg1, rcx));
+            |IL.opINCCB, IL.opDECCB:
+                UnOp(reg1);
+                IF reg1 >= 8 THEN
+                    OutByte(41H)
+                END;
+                OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *)
                 drop
-            END;
 
-            BinOp(reg1, reg2);
-            ASSERT(reg2 = rcx);
-            Rex(reg1, 0);
-            OutByte(0D3H);
-            X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *)
-            drop
+            |IL.opINCB, IL.opDECB:
+                BinOp(reg1, reg2);
+                IF (reg1 >= 8) OR (reg2 >= 8) THEN
+                    OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8))
+                END;
+                OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *)
+                drop;
+                drop
 
-        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
-            UnOp(reg1);
-            IF reg1 # rcx THEN
-                ASSERT(REG.GetReg(R, rcx));
-                ASSERT(REG.Exchange(R, reg1, rcx));
+            |IL.opSAVEIP:
+                UnOp(reg1);
+                reg2 := GetAnyReg();
+                lea(reg2, param2, sIMP);
+                movrm(reg2, reg2, 0);
+                push(reg2);
+                drop;
+                IF reg1 >= 8 THEN
+                    OutByte(41H)
+                END;
+                OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *)
                 drop
-            END;
 
-            reg1 := GetAnyReg();
-            movrc(reg1, param2);
-            BinOp(reg1, reg2);
-            ASSERT(reg1 = rcx);
-            Rex(reg2, 0);
-            OutByte(0D3H);
-            X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *)
-            drop;
-            drop;
-            ASSERT(REG.GetReg(R, reg2))
+            |IL.opCLEANUP:
+                IF param2 # 0 THEN
+                    addrc(rsp, param2 * 8)
+                END
 
-        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
-            UnOp(reg1);
-            shiftrc(opcode, reg1, param2 MOD 64)
+            |IL.opPOPSP:
+                pop(rsp)
 
-        |IL.opGET, IL.opGETC:
-            IF opcode = IL.opGET THEN
-                BinOp(reg1, reg2)
-            ELSIF opcode = IL.opGETC THEN
-                UnOp(reg2);
-                reg1 := GetAnyReg();
-                movrc(reg1, param1)
-            END;
-            drop;
-            drop;
-            X86._movrm(reg1, reg1, 0, param2 * 8, FALSE);
-            X86._movrm(reg1, reg2, 0, param2 * 8, TRUE)
-
-        |IL.opCHKIDX:
-            UnOp(reg1);
-            cmprc(reg1, param2);
-            jcc(jb, param1)
-
-        |IL.opCHKIDX2:
-            BinOp(reg1, reg2);
-            IF param2 # -1 THEN
-                cmprr(reg2, reg1);
-                jcc(jb, param1);
-            END;
-            INCL(R.regs, reg1);
-            DEC(R.top);
-            R.stk[R.top] := reg2
-
-        |IL.opLENGTH:
-            PushAll(2);
-            CallRTL(IL._length);
-            GetRegA
-
-        |IL.opLENGTHW:
-            PushAll(2);
-            CallRTL(IL._lengthw);
-            GetRegA
-
-        |IL.opLEN:
-            n := param2;
-            UnOp(reg1);
-            drop;
-            EXCL(R.regs, reg1);
+            |IL.opLOADF:
+                UnOp(reg1);
+                INC(xmm);
+                IF xmm > MAX_XMM THEN
+                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
+                END;
+                movsdrm(xmm, reg1, 0);
+                drop
 
-            WHILE n > 0 DO
-                UnOp(reg2);
-                drop;
-                DEC(n)
-            END;
+            |IL.opPUSHF:
+                ASSERT(xmm >= 0);
+                subrc(rsp, 8);
+                movsdmr(rsp, 0, xmm);
+                DEC(xmm)
 
-            INCL(R.regs, reg1);
-            ASSERT(REG.GetReg(R, reg1))
+            |IL.opCONSTF:
+                float := cmd.float;
+                INC(xmm);
+                IF xmm > MAX_XMM THEN
+                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
+                END;
+                (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *)
+                OutByte(0F2H);
+                IF xmm >= 8 THEN
+                    OutByte(44H)
+                END;
+                OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
+                X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8);
+                NewNumber(UTILS.splitf(float, a, b))
 
-        |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
-            UnOp(reg1);
-            reg2 := GetAnyReg();
+            |IL.opSAVEF, IL.opSAVEFI:
+                ASSERT(xmm >= 0);
+                UnOp(reg1);
+                movsdmr(reg1, 0, xmm);
+                DEC(xmm);
+                drop
 
-            CASE opcode OF
-            |IL.opEQP, IL.opNEP:
-                lea(reg2, param1, sCODE)
+            |IL.opADDF:
+                ASSERT(xmm >= 1);
+                opxx(58H, xmm - 1, xmm);
+                DEC(xmm)
 
-            |IL.opEQIP, IL.opNEIP:
-                lea(reg2, param1, sIMP);
-                movrm(reg2, reg2, 0)
-            END;
+            |IL.opSUBF:
+                ASSERT(xmm >= 1);
+                opxx(5CH, xmm - 1, xmm);
+                DEC(xmm)
 
-            cmprr(reg1, reg2);
-            drop;
-            drop;
-            reg1 := GetAnyReg();
+            |IL.opSUBFI:
+                ASSERT(xmm >= 1);
+                opxx(5CH, xmm, xmm - 1);
+                opxx(10H, xmm - 1, xmm);
+                DEC(xmm)
 
-            CASE opcode OF
-            |IL.opEQP, IL.opEQIP: X86.setcc(sete,  reg1)
-            |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1)
-            END;
+            |IL.opMULF:
+                ASSERT(xmm >= 1);
+                opxx(59H, xmm - 1, xmm);
+                DEC(xmm)
 
-            andrc(reg1, 1)
+            |IL.opDIVF:
+                ASSERT(xmm >= 1);
+                opxx(5EH, xmm - 1, xmm);
+                DEC(xmm)
 
-        |IL.opINCCB, IL.opDECCB:
-            UnOp(reg1);
-            IF reg1 >= 8 THEN
-                OutByte(41H)
-            END;
-            OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *)
-            drop
+            |IL.opDIVFI:
+                ASSERT(xmm >= 1);
+                opxx(5EH, xmm, xmm - 1);
+                opxx(10H, xmm - 1, xmm);
+                DEC(xmm)
 
-        |IL.opINCB, IL.opDECB:
-            BinOp(reg1, reg2);
-            IF (reg1 >= 8) OR (reg2 >= 8) THEN
-                OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8))
-            END;
-            OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *)
-            drop;
-            drop
+            |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *)
+                ASSERT(xmm >= 0);
+                OutByte(66H);
+                IF xmm >= 8 THEN
+                    OutByte(44H)
+                END;
+                OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8);
+                X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS))
 
-        |IL.opSAVEIP:
-            UnOp(reg1);
-            reg2 := GetAnyReg();
-            lea(reg2, param2, sIMP);
-            movrm(reg2, reg2, 0);
-            push(reg2);
-            drop;
-            IF reg1 >= 8 THEN
-                OutByte(41H)
-            END;
-            OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *)
-            drop
+            |IL.opFLT:
+                UnOp(reg1);
+                INC(xmm);
+                IF xmm > MAX_XMM THEN
+                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
+                END;
+                OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *)
+                OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8);
+                drop
 
-        |IL.opCLEANUP:
-            IF param2 # 0 THEN
-                addrc(rsp, param2 * 8)
-            END
+            |IL.opFLOOR:
+                ASSERT(xmm >= 0);
+                reg1 := GetAnyReg();
+                subrc(rsp, 8);
+                OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H);                       (* stmxcsr dword[rsp+4];                              *)
+                OutByte2(00FH, 0AEH); OutByte2(01CH, 024H);                             (* stmxcsr dword[rsp];                                *)
+                OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b;  *)
+                OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b;   *)
+                OutByte2(00FH, 0AEH); OutByte2(014H, 024H);                             (* ldmxcsr dword[rsp];                                *)
+                OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH);                            (* cvtsd2si reg1, xmm                                 *)
+                OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8);
+                OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H);                       (* ldmxcsr dword[rsp+4];                              *)
+                addrc(rsp, 8);
+                DEC(xmm)
 
-        |IL.opPOPSP:
-            pop(rsp)
+            |IL.opEQF .. IL.opGEF:
+                ASSERT(xmm >= 1);
+                fcmp(opcode, xmm);
+                DEC(xmm, 2)
 
-        |IL.opLOADF:
-            UnOp(reg1);
-            INC(xmm);
-            IF xmm > MAX_XMM THEN
-                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
-            END;
-            movsdrm(xmm, reg1, 0);
-            drop
+            |IL.opINF:
+                INC(xmm);
+                IF xmm > MAX_XMM THEN
+                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
+                END;
+                (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *)
+                OutByte(0F2H);
+                IF xmm >= 8 THEN
+                    OutByte(44H)
+                END;
+                OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
+                X86.Reloc(sDATA, Numbers_Offs + 32)
 
-        |IL.opPUSHF:
-            ASSERT(xmm >= 0);
-            subrc(rsp, 8);
-            movsdmr(rsp, 0, xmm);
-            DEC(xmm)
-
-        |IL.opCONSTF:
-            float := cmd.float;
-            INC(xmm);
-            IF xmm > MAX_XMM THEN
-                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
-            END;
-            (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *)
-            OutByte(0F2H);
-            IF xmm >= 8 THEN
-                OutByte(44H)
-            END;
-            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
-            X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8);
-            NewNumber(UTILS.splitf(float, a, b))
-
-        |IL.opSAVEF, IL.opSAVEFI:
-            ASSERT(xmm >= 0);
-            UnOp(reg1);
-            movsdmr(reg1, 0, xmm);
-            DEC(xmm);
-            drop
+            |IL.opPACK, IL.opPACKC:
+                IF opcode = IL.opPACK THEN
+                    BinOp(reg1, reg2)
+                ELSE
+                    UnOp(reg1);
+                    reg2 := GetAnyReg();
+                    movrc(reg2, param2)
+                END;
+                push(reg1);
+                movrm(reg1, reg1, 0);
+                shiftrc(shl, reg1, 1);
+                shiftrc(shr, reg1, 53);
+                add(reg1, reg2);
+                andrc(reg1, ORD({0..10}));
+                shiftrc(shl, reg1, 52);
+                movrm(reg2, rsp, 0);
+                movrm(reg2, reg2, 0);
 
-        |IL.opADDF:
-            ASSERT(xmm >= 1);
-            opxx(58H, xmm - 1, xmm);
-            DEC(xmm)
-
-        |IL.opSUBF:
-            ASSERT(xmm >= 1);
-            opxx(5CH, xmm - 1, xmm);
-            DEC(xmm)
-
-        |IL.opSUBFI:
-            ASSERT(xmm >= 1);
-            opxx(5CH, xmm, xmm - 1);
-            opxx(10H, xmm - 1, xmm);
-            DEC(xmm)
-
-        |IL.opMULF:
-            ASSERT(xmm >= 1);
-            opxx(59H, xmm - 1, xmm);
-            DEC(xmm)
-
-        |IL.opDIVF:
-            ASSERT(xmm >= 1);
-            opxx(5EH, xmm - 1, xmm);
-            DEC(xmm)
-
-        |IL.opDIVFI:
-            ASSERT(xmm >= 1);
-            opxx(5EH, xmm, xmm - 1);
-            opxx(10H, xmm - 1, xmm);
-            DEC(xmm)
-
-        |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *)
-            ASSERT(xmm >= 0);
-            OutByte(66H);
-            IF xmm >= 8 THEN
-                OutByte(44H)
-            END;
-            OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8);
-            X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS))
-
-        |IL.opFLT:
-            UnOp(reg1);
-            INC(xmm);
-            IF xmm > MAX_XMM THEN
-                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
-            END;
-            OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *)
-            OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8);
-            drop
+                push(reg1);
+                lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *)
+                movrm(reg1, reg1, 0);
+                and(reg2, reg1);
+                pop(reg1);
 
-        |IL.opFLOOR:
-            ASSERT(xmm >= 0);
-            reg1 := GetAnyReg();
-            subrc(rsp, 8);
-            OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H);                       (* stmxcsr dword[rsp+4];                              *)
-            OutByte2(00FH, 0AEH); OutByte2(01CH, 024H);                             (* stmxcsr dword[rsp];                                *)
-            OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b;  *)
-            OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b;   *)
-            OutByte2(00FH, 0AEH); OutByte2(014H, 024H);                             (* ldmxcsr dword[rsp];                                *)
-            OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH);                            (* cvtsd2si reg1, xmm                                 *)
-            OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8);
-            OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H);                       (* ldmxcsr dword[rsp+4];                              *)
-            addrc(rsp, 8);
-            DEC(xmm)
-
-        |IL.opEQF .. IL.opGEF:
-            ASSERT(xmm >= 1);
-            fcmp(opcode, xmm);
-            DEC(xmm, 2)
-
-        |IL.opINF:
-            INC(xmm);
-            IF xmm > MAX_XMM THEN
-                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
-            END;
-            (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *)
-            OutByte(0F2H);
-            IF xmm >= 8 THEN
-                OutByte(44H)
-            END;
-            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
-            X86.Reloc(sDATA, Numbers_Offs + 32)
+                _or(reg2, reg1);
+                pop(reg1);
+                movmr(reg1, 0, reg2);
+                drop;
+                drop
 
-        |IL.opPACK, IL.opPACKC:
-            IF opcode = IL.opPACK THEN
-                BinOp(reg1, reg2)
-            ELSE
-                UnOp(reg1);
-                reg2 := GetAnyReg();
-                movrc(reg2, param2)
-            END;
-            push(reg1);
-            movrm(reg1, reg1, 0);
-            shiftrc(shl, reg1, 1);
-            shiftrc(shr, reg1, 53);
-            add(reg1, reg2);
-            andrc(reg1, ORD({0..10}));
-            shiftrc(shl, reg1, 52);
-            movrm(reg2, rsp, 0);
-            movrm(reg2, reg2, 0);
-
-            push(reg1);
-            lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *)
-            movrm(reg1, reg1, 0);
-            and(reg2, reg1);
-            pop(reg1);
-
-            _or(reg2, reg1);
-            pop(reg1);
-            movmr(reg1, 0, reg2);
-            drop;
-            drop
+            |IL.opUNPK, IL.opLADR_UNPK:
 
-        |IL.opUNPK, IL.opLADR_UNPK:
+                IF opcode = IL.opLADR_UNPK THEN
+                    n := param2 * 8;
+                    UnOp(reg1);
+                    reg2 := GetAnyReg();
+                    Rex(0, reg2);
+                    OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *)
+                    OutIntByte(n)
+                ELSE
+                    BinOp(reg1, reg2)
+                END;
 
-            IF opcode = IL.opLADR_UNPK THEN
-                n := param2 * 8;
-                UnOp(reg1);
-                reg2 := GetAnyReg();
-                Rex(0, reg2);
-                OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *)
-                OutIntByte(n)
-            ELSE
-                BinOp(reg1, reg2)
-            END;
+                push(reg1);
+                movrm(reg1, reg1, 0);
+                shiftrc(shl, reg1, 1);
+                shiftrc(shr, reg1, 53);
+                subrc(reg1, 1023);
 
-            push(reg1);
-            movrm(reg1, reg1, 0);
-            shiftrc(shl, reg1, 1);
-            shiftrc(shr, reg1, 53);
-            subrc(reg1, 1023);
+                movmr(reg2, 0, reg1);
 
-            movmr(reg2, 0, reg1);
+                pop(reg2);
+                movrm(reg1, reg2, 0);
 
-            pop(reg2);
-            movrm(reg1, reg2, 0);
+                push(reg2);
+                lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *)
+                movrm(reg2, reg2, 0);
+                _or(reg1, reg2);
+                pop(reg2);
 
-            push(reg2);
-            lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *)
-            movrm(reg2, reg2, 0);
-            _or(reg1, reg2);
-            pop(reg2);
-
-            Rex(reg1, 0);
-            OutByte2(0FH, 0BAH);
-            OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *)
-            movmr(reg2, 0, reg1);
-            drop;
-            drop
+                Rex(reg1, 0);
+                OutByte2(0FH, 0BAH);
+                OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *)
+                movmr(reg2, 0, reg1);
+                drop;
+                drop
 
-        |IL.opSADR_PARAM:
-            pushDA(stroffs + param2)
+            |IL.opSADR_PARAM:
+                pushDA(stroffs + param2)
 
-        |IL.opVADR_PARAM:
-            X86.pushm(rbp, param2 * 8)
+            |IL.opVADR_PARAM:
+                X86.pushm(rbp, param2 * 8)
 
-        |IL.opLOAD64_PARAM:
-            UnOp(reg1);
-            X86.pushm(reg1, 0);
-            drop
+            |IL.opLOAD64_PARAM:
+                UnOp(reg1);
+                X86.pushm(reg1, 0);
+                drop
+
+            |IL.opLLOAD64_PARAM:
+                X86.pushm(rbp, param2 * 8)
 
-        |IL.opLLOAD64_PARAM:
-            X86.pushm(rbp, param2 * 8)
+            |IL.opGLOAD64_PARAM:
+                OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *)
+                X86.Reloc(sBSS, param2)
 
-        |IL.opGLOAD64_PARAM:
-            OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *)
-            X86.Reloc(sBSS, param2)
+            |IL.opCONST_PARAM:
+                pushc(param2)
 
-        |IL.opCONST_PARAM:
-            pushc(param2)
+            |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM:
+                IF opcode = IL.opGLOAD32_PARAM THEN
+                    reg1 := GetAnyReg();
+                    lea(reg1, param2, sBSS)
+                ELSE
+                    UnOp(reg1)
+                END;
+                movrm32(reg1, reg1, 0);
+                shiftrc(shl, reg1, 32);
+                shiftrc(shr, reg1, 32);
+                push(reg1);
+                drop
 
-        |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM:
-            IF opcode = IL.opGLOAD32_PARAM THEN
+            |IL.opLLOAD32_PARAM:
                 reg1 := GetAnyReg();
-                lea(reg1, param2, sBSS)
-            ELSE
-                UnOp(reg1)
-            END;
-            movrm32(reg1, reg1, 0);
-            shiftrc(shl, reg1, 32);
-            shiftrc(shr, reg1, 32);
-            push(reg1);
-            drop
+                movrm32(reg1, rbp, param2 * 8);
+                shiftrc(shl, reg1, 32);
+                shiftrc(shr, reg1, 32);
+                push(reg1);
+                drop
 
-        |IL.opLLOAD32_PARAM:
-            reg1 := GetAnyReg();
-            movrm32(reg1, rbp, param2 * 8);
-            shiftrc(shl, reg1, 32);
-            shiftrc(shr, reg1, 32);
-            push(reg1);
-            drop
+            |IL.opLADR_SAVEC:
+                n := param1 * 8;
+                IF isLong(param2) THEN
+                    reg2 := GetAnyReg();
+                    movrc(reg2, param2);
+                    movmr(rbp, n, reg2);
+                    drop
+                ELSE
+                    OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *)
+                    OutIntByte(n);
+                    OutInt(param2)
+                END
 
-        |IL.opLADR_SAVEC:
-            n := param1 * 8;
-            IF isLong(param2) THEN
-                reg2 := GetAnyReg();
-                movrc(reg2, param2);
-                movmr(rbp, n, reg2);
+            |IL.opGADR_SAVEC:
+                IF isLong(param2) THEN
+                    reg1 := GetAnyReg();
+                    movrc(reg1, param2);
+                    reg2 := GetAnyReg();
+                    lea(reg2, param1, sBSS);
+                    movmr(reg2, 0, reg1);
+                    drop;
+                    drop
+                ELSE
+                    (* mov qword[rip + param1 - 4 + BSS], param2 *)
+                    OutByte3(48H, 0C7H, 05H);
+                    X86.Reloc(sBSS, param1 - 4);
+                    OutInt(param2)
+                END
+
+            |IL.opLADR_SAVE:
+                UnOp(reg1);
+                movmr(rbp, param2 * 8, reg1);
                 drop
-            ELSE
-                OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *)
+
+            |IL.opLADR_INCC:
+                IF isLong(param2) THEN
+                    reg2 := GetAnyReg();
+                    movrc(reg2, param2);
+                    n := param1 * 8;
+                    Rex(0, reg2);
+                    OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8);
+                    OutIntByte(n); (* add qword[rbp+n], reg2 *)
+                    drop
+                ELSIF ABS(param2) = 1 THEN
+                    n := param1 * 8;
+                    OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *)
+                    OutIntByte(n)
+                ELSE
+                    n := param1 * 8;
+                    OutByte3(48H, 81H + short(param2), 45H + long(n));
+                    OutIntByte(n);
+                    OutIntByte(param2) (* add qword[rbp+n], param2 *)
+                END
+
+            |IL.opLADR_INCCB, IL.opLADR_DECCB:
+                param2 := param2 MOD 256;
+                n := param1 * 8;
+                OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB));
                 OutIntByte(n);
-                OutInt(param2)
-            END
+                OutByte(param2) (* add/sub byte[rbp+n], param2 *)
 
-        |IL.opGADR_SAVEC:
-            IF isLong(param2) THEN
-                reg1 := GetAnyReg();
-                movrc(reg1, param2);
-                reg2 := GetAnyReg();
-                lea(reg2, param1, sBSS);
-                movmr(reg2, 0, reg1);
-                drop;
+            |IL.opLADR_INC, IL.opLADR_DEC:
+                UnOp(reg1);
+                n := param2 * 8;
+                Rex(0, reg1);
+                OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8);
+                OutIntByte(n); (* add/sub qword[rbp+n], reg1 *)
                 drop
-            ELSE
-                (* mov qword[rip + param1 - 4 + BSS], param2 *)
-                OutByte3(48H, 0C7H, 05H);
-                X86.Reloc(sBSS, param1 - 4);
-                OutInt(param2)
-            END
 
-        |IL.opLADR_SAVE:
-            UnOp(reg1);
-            movmr(rbp, param2 * 8, reg1);
-            drop
+            |IL.opLADR_INCB, IL.opLADR_DECB:
+                UnOp(reg1);
+                n := param2 * 8;
+                IF reg1 >= 8 THEN
+                    OutByte(44H)
+                END;
+                OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8));
+                OutIntByte(n); (* add/sub byte[rbp+n], reg1_8 *)
+                drop
 
-        |IL.opLADR_INCC:
-            IF isLong(param2) THEN
-                reg2 := GetAnyReg();
-                movrc(reg2, param2);
-                n := param1 * 8;
-                Rex(0, reg2);
-                OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8);
-                OutIntByte(n); (* add qword[rbp+n], reg2 *)
+            |IL.opLADR_INCL, IL.opLADR_EXCL:
+                UnOp(reg1);
+                cmprc(reg1, 64);
+                n := param2 * 8;
+                OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *)
+                Rex(0, reg1);
+                OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8));
+                OutIntByte(n); (* bts/btr qword[rbp+n], reg1 *)
+                (* L: *)
                 drop
-            ELSIF ABS(param2) = 1 THEN
-                n := param1 * 8;
-                OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *)
-                OutIntByte(n)
-            ELSE
+
+            |IL.opLADR_INCLC, IL.opLADR_EXCLC:
                 n := param1 * 8;
-                OutByte3(48H, 81H + short(param2), 45H + long(n));
+                OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *)
+                OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC));
                 OutIntByte(n);
-                OutIntByte(param2) (* add qword[rbp+n], param2 *)
-            END
+                OutByte(param2)
 
-        |IL.opLADR_INCCB, IL.opLADR_DECCB:
-            param2 := param2 MOD 256;
-            n := param1 * 8;
-            OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB));
-            OutIntByte(n);
-            OutByte(param2) (* add/sub byte[rbp+n], param2 *)
-
-        |IL.opLADR_INC, IL.opLADR_DEC:
-            UnOp(reg1);
-            n := param2 * 8;
-            Rex(0, reg1);
-            OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8);
-            OutIntByte(n); (* add/sub qword[rbp+n], reg1 *)
-            drop
+            |IL.opFNAME:
+                fname := cmd(IL.FNAMECMD).fname
 
-        |IL.opLADR_INCB, IL.opLADR_DECB:
-            UnOp(reg1);
-            n := param2 * 8;
-            IF reg1 >= 8 THEN
-                OutByte(44H)
             END;
-            OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8));
-            OutIntByte(n); (* add/sub byte[rbp+n], reg1_8 *)
-            drop
 
-        |IL.opLADR_INCL, IL.opLADR_EXCL:
-            UnOp(reg1);
-            cmprc(reg1, 64);
-            n := param2 * 8;
-            OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *)
-            Rex(0, reg1);
-            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8));
-            OutIntByte(n); (* bts/btr qword[rbp+n], reg1 *)
-            (* L: *)
-            drop
+            cmd := cmd.next(COMMAND)
+        END;
 
-        |IL.opLADR_INCLC, IL.opLADR_EXCLC:
-            n := param1 * 8;
-            OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *)
-            OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC));
-            OutIntByte(n);
-            OutByte(param2)
+        ASSERT(R.pushed = 0);
+        ASSERT(R.top = -1);
+        ASSERT(xmm = -1)
+    END translate;
 
-        |IL.opFNAME:
-            fname := cmd(IL.FNAMECMD).fname
 
-        END;
+PROCEDURE prolog (modname: ARRAY OF CHAR; target, stack_size: INTEGER);
+    VAR
+        ModName_Offs, entry, L: INTEGER;
 
-        cmd := cmd.next(COMMAND)
-    END;
+    BEGIN
+        ModName_Offs := tcount * 8 + CHL.Length(IL.codes.data);
+        Numbers_Offs := ModName_Offs + LENGTH(modname) + 1;
+        ASSERT(UTILS.Align(Numbers_Offs, 16));
 
-    ASSERT(R.pushed = 0);
-    ASSERT(R.top = -1);
-    ASSERT(xmm = -1)
-END translate;
+        entry := NewLabel();
+        X86.SetLabel(entry);
 
+        IF target = TARGETS.Win64DLL THEN
+            dllret := NewLabel();
+            push(r8);
+            push(rdx);
+            push(rcx);
+            CallRTL(IL._dllentry);
+            test(rax);
+            jcc(je, dllret);
+            pushc(0)
+        ELSIF target = TARGETS.Linux64 THEN
+            push(rsp)
+        ELSE
+            pushc(0)
+        END;
 
-PROCEDURE prolog (modname: ARRAY OF CHAR; target, stack_size: INTEGER);
-VAR
-    ModName_Offs, entry, L: INTEGER;
-
-BEGIN
-    ModName_Offs := tcount * 8 + CHL.Length(IL.codes.data);
-    Numbers_Offs := ModName_Offs + LENGTH(modname) + 1;
-    ASSERT(UTILS.Align(Numbers_Offs, 16));
-
-    entry := NewLabel();
-    X86.SetLabel(entry);
-
-    IF target = TARGETS.Win64DLL THEN
-        dllret := NewLabel();
-        push(r8);
-        push(rdx);
-        push(rcx);
-        CallRTL(IL._dllentry);
-        test(rax);
-        jcc(je, dllret);
-        pushc(0)
-    ELSIF target = TARGETS.Linux64 THEN
-        push(rsp)
-    ELSE
-        pushc(0)
-    END;
-
-    lea(rax, entry, sCODE);
-    push(rax);
-    pushDA(0); (* TYPES *)
-    pushc(tcount);
-    pushDA(ModName_Offs); (* MODNAME *)
-    CallRTL(IL._init);
-
-    IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN
-        L := NewLabel();
-        pushc(0);
-        push(rsp);
-        pushc(1024 * 1024 * stack_size);
-        pushc(0);
-        CallRTL(IL._new);
-        pop(rax);
-        test(rax);
-        jcc(je, L);
-        GetRegA;
-        addrc(rax, 1024 * 1024 * stack_size - 8);
-        drop;
-        mov(rsp, rax);
-        X86.SetLabel(L)
-    END
-END prolog;
+        lea(rax, entry, sCODE);
+        push(rax);
+        pushDA(0); (* TYPES *)
+        pushc(tcount);
+        pushDA(ModName_Offs); (* MODNAME *)
+        CallRTL(IL._init);
+
+        IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN
+            L := NewLabel();
+            pushc(0);
+            push(rsp);
+            pushc(1024 * 1024 * stack_size);
+            pushc(0);
+            CallRTL(IL._new);
+            pop(rax);
+            test(rax);
+            jcc(je, L);
+            GetRegA;
+            addrc(rax, 1024 * 1024 * stack_size - 8);
+            drop;
+            mov(rsp, rax);
+            X86.SetLabel(L)
+        END
+    END prolog;
 
 
 PROCEDURE epilog (modname: ARRAY OF CHAR; target: INTEGER);
-VAR
-    i, n: INTEGER;
-    number: Number;
-    exp: IL.EXPORT_PROC;
+    VAR
+        i, n: INTEGER;
+        number: Number;
+        exp: IL.EXPORT_PROC;
 
 
-    PROCEDURE _import (imp: LISTS.LIST);
-    VAR
-        lib:  IL.IMPORT_LIB;
-        proc: IL.IMPORT_PROC;
+        PROCEDURE _import (imp: LISTS.LIST);
+        VAR
+            lib:  IL.IMPORT_LIB;
+            proc: IL.IMPORT_PROC;
+
+        BEGIN
+
+            lib := imp.first(IL.IMPORT_LIB);
+            WHILE lib # NIL DO
+                BIN.Import(prog, lib.name, 0);
+                proc := lib.procs.first(IL.IMPORT_PROC);
+                WHILE proc # NIL DO
+                    BIN.Import(prog, proc.name, proc.label);
+                    proc := proc.next(IL.IMPORT_PROC)
+                END;
+                lib := lib.next(IL.IMPORT_LIB)
+            END
+
+        END _import;
+
 
     BEGIN
+        IF target = TARGETS.Win64DLL THEN
+            X86.SetLabel(dllret);
+            X86.ret
+        ELSIF target = TARGETS.Linux64SO THEN
+            sofinit := NewLabel();
+            X86.ret;
+            X86.SetLabel(sofinit);
+            CallRTL(IL._sofinit);
+            X86.ret
+        ELSE
+            pushc(0);
+            CallRTL(IL._exit)
+        END;
 
-        lib := imp.first(IL.IMPORT_LIB);
-        WHILE lib # NIL DO
-            BIN.Import(prog, lib.name, 0);
-            proc := lib.procs.first(IL.IMPORT_PROC);
-            WHILE proc # NIL DO
-                BIN.Import(prog, proc.name, proc.label);
-                proc := proc.next(IL.IMPORT_PROC)
-            END;
-            lib := lib.next(IL.IMPORT_LIB)
-        END
+        X86.fixup;
+
+        i := 0;
+        WHILE i < tcount DO
+            BIN.PutData64LE(prog, CHL.GetInt(IL.codes.types, i));
+            INC(i)
+        END;
+
+        i := 0;
+        WHILE i < CHL.Length(IL.codes.data) DO
+            BIN.PutData(prog, CHL.GetByte(IL.codes.data, i));
+            INC(i)
+        END;
 
-    END _import;
-
-
-BEGIN
-    IF target = TARGETS.Win64DLL THEN
-        X86.SetLabel(dllret);
-        X86.ret
-    ELSIF target = TARGETS.Linux64SO THEN
-        sofinit := NewLabel();
-        X86.ret;
-        X86.SetLabel(sofinit);
-        CallRTL(IL._sofinit);
-        X86.ret
-    ELSE
-        pushc(0);
-        CallRTL(IL._exit)
-    END;
-
-    X86.fixup;
-
-    i := 0;
-    WHILE i < tcount DO
-        BIN.PutData64LE(prog, CHL.GetInt(IL.codes.types, i));
-        INC(i)
-    END;
-
-    i := 0;
-    WHILE i < CHL.Length(IL.codes.data) DO
-        BIN.PutData(prog, CHL.GetByte(IL.codes.data, i));
-        INC(i)
-    END;
-
-    BIN.PutDataStr(prog, modname);
-    BIN.PutData(prog, 0);
-    n := CHL.Length(prog.data);
-    ASSERT(UTILS.Align(n, 16));
-    i := n - CHL.Length(prog.data);
-    WHILE i > 0 DO
+        BIN.PutDataStr(prog, modname);
         BIN.PutData(prog, 0);
-        DEC(i)
-    END;
-    number := Numbers.first(Number);
-    FOR i := 0 TO Numbers_Count - 1 DO
-        BIN.PutData64LE(prog, number.value);
-        number := number.next(Number)
-    END;
+        n := CHL.Length(prog.data);
+        ASSERT(UTILS.Align(n, 16));
+        i := n - CHL.Length(prog.data);
+        WHILE i > 0 DO
+            BIN.PutData(prog, 0);
+            DEC(i)
+        END;
+        number := Numbers.first(Number);
+        FOR i := 0 TO Numbers_Count - 1 DO
+            BIN.PutData64LE(prog, number.value);
+            number := number.next(Number)
+        END;
 
-    exp := IL.codes.export.first(IL.EXPORT_PROC);
-    WHILE exp # NIL DO
-        BIN.Export(prog, exp.name, exp.label);
-        exp := exp.next(IL.EXPORT_PROC)
-    END;
+        exp := IL.codes.export.first(IL.EXPORT_PROC);
+        WHILE exp # NIL DO
+            BIN.Export(prog, exp.name, exp.label);
+            exp := exp.next(IL.EXPORT_PROC)
+        END;
 
-    _import(IL.codes._import)
-END epilog;
+        _import(IL.codes._import)
+    END epilog;
 
 
 PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
-VAR
-    path, modname, ext: PATHS.PATH;
-
-BEGIN
-    Xmm[0] := 0;
-    X86.align16(TRUE);
-    tcount := CHL.Length(IL.codes.types);
-
-    Win64RegPar[0] := rcx;
-    Win64RegPar[1] := rdx;
-    Win64RegPar[2] := r8;
-    Win64RegPar[3] := r9;
-
-    SystemVRegPar[0] := rdi;
-    SystemVRegPar[1] := rsi;
-    SystemVRegPar[2] := rdx;
-    SystemVRegPar[3] := rcx;
-    SystemVRegPar[4] := r8;
-    SystemVRegPar[5] := r9;
-
-    PATHS.split(outname, path, modname, ext);
-    S.append(modname, ext);
-
-    REG.Init(R, push, pop, mov, xchg, {rax, rcx, rdx, r8, r9, r10, r11});
-
-    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8)));
-
-    Numbers := LISTS.create(NIL);
-    Numbers_Count := 0;
-    NewNumber(ROR(1, 1));      (* 8000000000000000H *)
-    NewNumber(0);
-    NewNumber(ROR(-2, 1));     (* 7FFFFFFFFFFFFFFFH *)
-    NewNumber(-1);
-    NewNumber(ROR(7FFH, 12));  (* +Infinity *)
-    NewNumber(ORD(-BITS(LSR(ASR(ROR(1, 1), 10), 1))));  (* {0..51, 63} *)
-    NewNumber(LSR(ASR(ROR(1, 1), 9), 2));  (* {52..61} *)
-
-    prog := BIN.create(IL.codes.lcount);
-    BIN.SetParams(prog, IL.codes.bss, 1, WCHR(1), WCHR(0));
-
-    X86.SetProgram(prog);
-
-    prolog(modname, target, options.stack);
-    translate(IL.codes.commands, tcount * 8);
-    epilog(modname, target);
-
-    BIN.fixup(prog);
-    IF TARGETS.OS = TARGETS.osWIN64 THEN
-        PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE, options.PE32FileAlignment)
-    ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
-        ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE)
-    END
-END CodeGen;
+    VAR
+        path, modname, ext: PATHS.PATH;
+
+    BEGIN
+        Xmm[0] := 0;
+        X86.align16(TRUE);
+        tcount := CHL.Length(IL.codes.types);
+
+        Win64RegPar[0] := rcx;
+        Win64RegPar[1] := rdx;
+        Win64RegPar[2] := r8;
+        Win64RegPar[3] := r9;
+
+        SystemVRegPar[0] := rdi;
+        SystemVRegPar[1] := rsi;
+        SystemVRegPar[2] := rdx;
+        SystemVRegPar[3] := rcx;
+        SystemVRegPar[4] := r8;
+        SystemVRegPar[5] := r9;
+
+        PATHS.split(outname, path, modname, ext);
+        S.append(modname, ext);
+
+        REG.Init(R, push, pop, mov, xchg, {rax, rcx, rdx, r8, r9, r10, r11});
+
+        IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8)));
+
+        Numbers := LISTS.create(NIL);
+        Numbers_Count := 0;
+        NewNumber(ROR(1, 1));      (* 8000000000000000H *)
+        NewNumber(0);
+        NewNumber(ROR(-2, 1));     (* 7FFFFFFFFFFFFFFFH *)
+        NewNumber(-1);
+        NewNumber(ROR(7FFH, 12));  (* +Infinity *)
+        NewNumber(ORD(-BITS(LSR(ASR(ROR(1, 1), 10), 1))));  (* {0..51, 63} *)
+        NewNumber(LSR(ASR(ROR(1, 1), 9), 2));  (* {52..61} *)
+
+        prog := BIN.create(IL.codes.lcount);
+        BIN.SetParams(prog, IL.codes.bss, 1, WCHR(1), WCHR(0));
+
+        X86.SetProgram(prog);
+
+        prolog(modname, target, options.stack);
+        translate(IL.codes.commands, tcount * 8);
+        epilog(modname, target);
+
+        BIN.fixup(prog);
+        IF TARGETS.OS = TARGETS.osWIN64 THEN
+            PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE, options.PE32FileAlignment)
+        ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
+            ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE)
+        END
+    END CodeGen;
 
 
 END AMD64.

+ 1 - 8
source/Compiler.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2023, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE Compiler;
+MODULE Compiler;
 
 IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE,
        ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS, SCAN, TEXTDRV;

+ 424 - 431
source/SCAN.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2021, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE SCAN;
+MODULE SCAN;
 
 IMPORT TXT := TEXTDRV, ARITH, S := STRINGS, ERRORS, LISTS;
 
@@ -115,587 +108,587 @@ END enterKW;
 
 
 PROCEDURE checkKW (ident: IDENT): INTEGER;
-VAR
-    i, res: INTEGER;
+    VAR
+        i, res: INTEGER;
 
-BEGIN
-    res := lxIDENT;
-    i := 0;
-    WHILE i < LEN(KW) DO
-        IF (KW[i].uhash = ident.hash) & (KW[i].upper = ident.s)
-        OR LowerCase & (KW[i].lhash = ident.hash) & (KW[i].lower = ident.s) THEN
-            res := i + lxKW;
-            i := LEN(KW)
-        END;
-        INC(i)
-    END
+    BEGIN
+        res := lxIDENT;
+        i := 0;
+        WHILE i < LEN(KW) DO
+            IF (KW[i].uhash = ident.hash) & (KW[i].upper = ident.s)
+            OR LowerCase & (KW[i].lhash = ident.hash) & (KW[i].lower = ident.s) THEN
+                res := i + lxKW;
+                i := LEN(KW)
+            END;
+            INC(i)
+        END
 
-    RETURN res
+        RETURN res
 END checkKW;
 
 
 PROCEDURE enterStr* (s: TEXTSTR): STRING;
-VAR
-    str, res: STRING;
-    hash: INTEGER;
+    VAR
+        str, res: STRING;
+        hash: INTEGER;
 
-BEGIN
-    hash := S.HashStr(s);
-    str := strings.first(STRING);
-    res := NIL;
-    WHILE str # NIL DO
-        IF (str.hash = hash) & (str.s = s) THEN
-            res := str;
-            str := NIL
-        ELSE
-            str := str.next(STRING)
+    BEGIN
+        hash := S.HashStr(s);
+        str := strings.first(STRING);
+        res := NIL;
+        WHILE str # NIL DO
+            IF (str.hash = hash) & (str.s = s) THEN
+                res := str;
+                str := NIL
+            ELSE
+                str := str.next(STRING)
+            END
+        END;
+        IF res = NIL THEN
+            NEW(res);
+            res.s := s;
+            res.offset  := -1;
+            res.offsetW := -1;
+            res.hash := hash;
+            LISTS.push(strings, res)
         END
-    END;
-    IF res = NIL THEN
-        NEW(res);
-        res.s := s;
-        res.offset  := -1;
-        res.offsetW := -1;
-        res.hash := hash;
-        LISTS.push(strings, res)
-    END
-
-    RETURN res
+
+        RETURN res
 END enterStr;
 
 
 PROCEDURE nextc (text: TXT.TEXT): CHAR;
-BEGIN
-    TXT.next(text)
-    RETURN text.peak
+    BEGIN
+        TXT.next(text)
+        RETURN text.peak
 END nextc;
 
 
 PROCEDURE setIdent* (VAR ident: IDENT; s: IDSTR);
-BEGIN
-    ident.s := s;
-    ident.hash := S.HashStr(s)
+    BEGIN
+        ident.s := s;
+        ident.hash := S.HashStr(s)
 END setIdent;
 
 
 PROCEDURE ident (text: TXT.TEXT; VAR lex: LEX);
-VAR
-    c: CHAR;
-    i: INTEGER;
-
-BEGIN
-    c := text.peak;
-    ASSERT(S.letter(c));
-
-    i := 0;
-    WHILE (i < IDLEN - 1) & (S.letter(c) OR S.digit(c)) DO
-        lex.ident.s[i] := c;
-        INC(i);
-        c := nextc(text)
-    END;
+    VAR
+        c: CHAR;
+        i: INTEGER;
 
-    lex.ident.s[i] := 0X;
-    lex.ident.hash := S.HashStr(lex.ident.s);
-    lex.sym := checkKW(lex.ident);
+    BEGIN
+        c := text.peak;
+        ASSERT(S.letter(c));
 
-    IF S.letter(c) OR S.digit(c) THEN
-        ERRORS.WarningMsg(lex.pos.line, lex.pos.col, 2);
-        WHILE S.letter(c) OR S.digit(c) DO
+        i := 0;
+        WHILE (i < IDLEN - 1) & (S.letter(c) OR S.digit(c)) DO
+            lex.ident.s[i] := c;
+            INC(i);
             c := nextc(text)
+        END;
+
+        lex.ident.s[i] := 0X;
+        lex.ident.hash := S.HashStr(lex.ident.s);
+        lex.sym := checkKW(lex.ident);
+
+        IF S.letter(c) OR S.digit(c) THEN
+            ERRORS.WarningMsg(lex.pos.line, lex.pos.col, 2);
+            WHILE S.letter(c) OR S.digit(c) DO
+                c := nextc(text)
+            END
         END
-    END
 END ident;
 
 
 PROCEDURE number (text: TXT.TEXT; VAR lex: LEX);
-TYPE
-    NUMSTR = ARRAY NUMLEN OF CHAR;
-
-VAR
-    c: CHAR;
-    hex: BOOLEAN;
-    error, sym, i: INTEGER;
-    num: NUMSTR;
+    TYPE
+        NUMSTR = ARRAY NUMLEN OF CHAR;
 
-
-    PROCEDURE push (VAR num: NUMSTR; VAR i: INTEGER; c: CHAR);
-    BEGIN
-        IF i < NUMLEN - 1 THEN
-            num[i] := c;
-            INC(i)
-        END
-    END push;
+    VAR
+        c: CHAR;
+        hex: BOOLEAN;
+        error, sym, i: INTEGER;
+        num: NUMSTR;
 
 
-BEGIN
-    c := text.peak;
-    ASSERT(S.digit(c));
+        PROCEDURE push (VAR num: NUMSTR; VAR i: INTEGER; c: CHAR);
+        BEGIN
+            IF i < NUMLEN - 1 THEN
+                num[i] := c;
+                INC(i)
+            END
+        END push;
 
-    i := 0;
 
-    error := 0;
+    BEGIN
+        c := text.peak;
+        ASSERT(S.digit(c));
 
-    sym := lxINTEGER;
-    hex := FALSE;
+        i := 0;
 
-    WHILE S.digit(c) DO
-        push(num, i, c);
-        c := nextc(text)
-    END;
+        error := 0;
 
-    WHILE S.hexdigit(c) OR LowerCase & ("a" <= c) & (c <= "f") DO
-        S.cap(c);
-        push(num, i, c);
-        c := nextc(text);
-        hex := TRUE
-    END;
+        sym := lxINTEGER;
+        hex := FALSE;
 
-    IF (c = "H") OR LowerCase & (c = "h") THEN
-        push(num, i, c);
-        TXT.next(text);
-        sym := lxHEX
+        WHILE S.digit(c) DO
+            push(num, i, c);
+            c := nextc(text)
+        END;
 
-    ELSIF (c = "X") OR LowerCase & (c = "x") THEN
-        push(num, i, c);
-        TXT.next(text);
-        sym := lxCHAR
+        WHILE S.hexdigit(c) OR LowerCase & ("a" <= c) & (c <= "f") DO
+            S.cap(c);
+            push(num, i, c);
+            c := nextc(text);
+            hex := TRUE
+        END;
 
-    ELSIF c = "." THEN
+        IF (c = "H") OR LowerCase & (c = "h") THEN
+            push(num, i, c);
+            TXT.next(text);
+            sym := lxHEX
 
-        IF hex THEN
-            sym := lxERROR01
-        ELSE
+        ELSIF (c = "X") OR LowerCase & (c = "x") THEN
+            push(num, i, c);
+            TXT.next(text);
+            sym := lxCHAR
 
-            c := nextc(text);
+        ELSIF c = "." THEN
 
-            IF c # "." THEN
-                push(num, i, ".");
-                sym := lxFLOAT
+            IF hex THEN
+                sym := lxERROR01
             ELSE
-                sym := lxINTEGER;
-                text.peak := 7FX;
-                upto := TRUE
-            END;
 
-            WHILE S.digit(c) DO
-                push(num, i, c);
-                c := nextc(text)
-            END;
+                c := nextc(text);
 
-            IF (c = "E") OR LowerCase & (c = "e") THEN
+                IF c # "." THEN
+                    push(num, i, ".");
+                    sym := lxFLOAT
+                ELSE
+                    sym := lxINTEGER;
+                    text.peak := 7FX;
+                    upto := TRUE
+                END;
 
-                push(num, i, c);
-                c := nextc(text);
-                IF (c = "+") OR (c = "-") THEN
+                WHILE S.digit(c) DO
                     push(num, i, c);
                     c := nextc(text)
                 END;
 
-                IF S.digit(c) THEN
-                    WHILE S.digit(c) DO
+                IF (c = "E") OR LowerCase & (c = "e") THEN
+
+                    push(num, i, c);
+                    c := nextc(text);
+                    IF (c = "+") OR (c = "-") THEN
                         push(num, i, c);
                         c := nextc(text)
+                    END;
+
+                    IF S.digit(c) THEN
+                        WHILE S.digit(c) DO
+                            push(num, i, c);
+                            c := nextc(text)
+                        END
+                    ELSE
+                        sym := lxERROR02
                     END
-                ELSE
-                    sym := lxERROR02
+
                 END
 
             END
 
-        END
-
-    ELSIF hex THEN
-        sym := lxERROR01
+        ELSIF hex THEN
+            sym := lxERROR01
 
-    END;
+        END;
 
-    IF (i = NUMLEN - 1) & (sym >= 0) THEN
-        sym := lxERROR07
-    END;
+        IF (i = NUMLEN - 1) & (sym >= 0) THEN
+            sym := lxERROR07
+        END;
 
-    num[i] := 0X;
+        num[i] := 0X;
 
-    IF sym = lxINTEGER THEN
-        ARITH.iconv(num, lex.value, error)
-    ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN
-        ARITH.hconv(num, lex.value, error)
-    ELSIF sym = lxFLOAT THEN
-        ARITH.fconv(num, lex.value, error)
-    END;
+        IF sym = lxINTEGER THEN
+            ARITH.iconv(num, lex.value, error)
+        ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN
+            ARITH.hconv(num, lex.value, error)
+        ELSIF sym = lxFLOAT THEN
+            ARITH.fconv(num, lex.value, error)
+        END;
 
-    CASE error OF
-    |0:
-    |1: sym := lxERROR08
-    |2: sym := lxERROR09
-    |3: sym := lxERROR10
-    |4: sym := lxERROR11
-    |5: sym := lxERROR12
-    END;
+        CASE error OF
+        |0:
+        |1: sym := lxERROR08
+        |2: sym := lxERROR09
+        |3: sym := lxERROR10
+        |4: sym := lxERROR11
+        |5: sym := lxERROR12
+        END;
 
-    lex.sym := sym
+        lex.sym := sym
 END number;
 
 
 PROCEDURE string (text: TXT.TEXT; VAR lex: LEX; quot: CHAR);
-VAR
-    c: CHAR;
-    i: INTEGER;
-    str: TEXTSTR;
+    VAR
+        c: CHAR;
+        i: INTEGER;
+        str: TEXTSTR;
 
-BEGIN
-    c  := nextc(text);
+    BEGIN
+        c  := nextc(text);
 
-    i := 0;
-    WHILE (i < LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO
-        str[i] := c;
-        c := nextc(text);
-        INC(i)
-    END;
+        i := 0;
+        WHILE (i < LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO
+            str[i] := c;
+            c := nextc(text);
+            INC(i)
+        END;
 
-    str[i] := 0X;
+        str[i] := 0X;
 
-    IF (i = LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof THEN
-        lex.sym := lxERROR05
-    END;
+        IF (i = LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof THEN
+            lex.sym := lxERROR05
+        END;
 
-    IF c = quot THEN
-        TXT.next(text);
-        IF i # 1 THEN
-            lex.sym := lxSTRING
-        ELSE
-            lex.sym := lxCHAR;
-            ARITH.setChar(lex.value, ORD(str[0]))
-        END
-    ELSIF lex.sym # lxERROR05 THEN
-        lex.sym := lxERROR03
-    END;
+        IF c = quot THEN
+            TXT.next(text);
+            IF i # 1 THEN
+                lex.sym := lxSTRING
+            ELSE
+                lex.sym := lxCHAR;
+                ARITH.setChar(lex.value, ORD(str[0]))
+            END
+        ELSIF lex.sym # lxERROR05 THEN
+            lex.sym := lxERROR03
+        END;
 
-    IF lex.sym = lxSTRING THEN
-        lex.string := enterStr(str);
-        lex.value.typ := ARITH.tSTRING;
-        lex.value.string := lex.string
-    END
+        IF lex.sym = lxSTRING THEN
+            lex.string := enterStr(str);
+            lex.value.typ := ARITH.tSTRING;
+            lex.value.string := lex.string
+        END
 
 END string;
 
 
 PROCEDURE comment (text: TXT.TEXT);
-VAR
-    c: CHAR;
-    cond, depth: INTEGER;
+    VAR
+        c: CHAR;
+        cond, depth: INTEGER;
 
-BEGIN
-    cond  := 0;
-    depth := 1;
+    BEGIN
+        cond  := 0;
+        depth := 1;
 
-    REPEAT
+        REPEAT
 
-        c := text.peak;
-        TXT.next(text);
+            c := text.peak;
+            TXT.next(text);
 
-        IF c = "*" THEN
-            IF cond = 1 THEN
-                cond := 0;
-                INC(depth)
+            IF c = "*" THEN
+                IF cond = 1 THEN
+                    cond := 0;
+                    INC(depth)
+                ELSE
+                cond := 2
+                END
+            ELSIF c = ")" THEN
+                IF cond = 2 THEN
+                    DEC(depth)
+                END;
+                cond := 0
+            ELSIF c = "(" THEN
+                cond := 1
             ELSE
-               cond := 2
+                cond := 0
             END
-        ELSIF c = ")" THEN
-            IF cond = 2 THEN
-                DEC(depth)
-            END;
-            cond := 0
-        ELSIF c = "(" THEN
-            cond := 1
-        ELSE
-            cond := 0
-        END
 
-    UNTIL (depth = 0) OR text.eof
+        UNTIL (depth = 0) OR text.eof
 
 END comment;
 
 
 PROCEDURE delimiter (text: TXT.TEXT; c: CHAR): INTEGER;
-VAR
-    sym: INTEGER;
-    c0:  CHAR;
+    VAR
+        sym: INTEGER;
+        c0:  CHAR;
 
-BEGIN
-    c0 := c;
-    c := nextc(text);
+    BEGIN
+        c0 := c;
+        c := nextc(text);
 
-    CASE c0 OF
-    |"+":
-        sym := lxPLUS
+        CASE c0 OF
+        |"+":
+            sym := lxPLUS
 
-    |"-":
-        sym := lxMINUS
+        |"-":
+            sym := lxMINUS
 
-    |"*":
-        sym := lxMUL
+        |"*":
+            sym := lxMUL
 
-    |"/":
-        sym := lxSLASH;
+        |"/":
+            sym := lxSLASH;
 
-        IF c = "/" THEN
-            sym := lxCOMMENT;
-            REPEAT
-                TXT.next(text)
-            UNTIL text.eol OR text.eof
-        END
+            IF c = "/" THEN
+                sym := lxCOMMENT;
+                REPEAT
+                    TXT.next(text)
+                UNTIL text.eol OR text.eof
+            END
 
-    |"~":
-        sym := lxNOT
+        |"~":
+            sym := lxNOT
 
-    |"&":
-        sym := lxAND
+        |"&":
+            sym := lxAND
 
-    |".":
-        sym := lxPOINT;
+        |".":
+            sym := lxPOINT;
 
-        IF c = "." THEN
-            sym := lxRANGE;
-            TXT.next(text)
-        END
+            IF c = "." THEN
+                sym := lxRANGE;
+                TXT.next(text)
+            END
 
-    |",":
-        sym := lxCOMMA
+        |",":
+            sym := lxCOMMA
 
-    |";":
-        sym := lxSEMI
+        |";":
+            sym := lxSEMI
 
-    |"|":
-        sym := lxBAR
+        |"|":
+            sym := lxBAR
 
-    |"(":
-        sym := lxLROUND;
+        |"(":
+            sym := lxLROUND;
 
-        IF c = "*" THEN
-            sym := lxCOMMENT;
-            TXT.next(text);
-            comment(text)
-        END
+            IF c = "*" THEN
+                sym := lxCOMMENT;
+                TXT.next(text);
+                comment(text)
+            END
 
-    |"[":
-        sym := lxLSQUARE
+        |"[":
+            sym := lxLSQUARE
 
-    |"{":
-        sym := lxLCURLY
+        |"{":
+            sym := lxLCURLY
 
-    |"^":
-        sym := lxCARET
+        |"^":
+            sym := lxCARET
 
-    |"=":
-        sym := lxEQ
+        |"=":
+            sym := lxEQ
 
-    |"#":
-        sym := lxNE
+        |"#":
+            sym := lxNE
 
-    |"<":
-        sym := lxLT;
+        |"<":
+            sym := lxLT;
 
-        IF c = "=" THEN
-            sym := lxLE;
-            TXT.next(text)
-        END
+            IF c = "=" THEN
+                sym := lxLE;
+                TXT.next(text)
+            END
 
-    |">":
-        sym := lxGT;
+        |">":
+            sym := lxGT;
 
-        IF c = "=" THEN
-            sym := lxGE;
-            TXT.next(text)
-        END
+            IF c = "=" THEN
+                sym := lxGE;
+                TXT.next(text)
+            END
 
-    |":":
-        sym := lxCOLON;
+        |":":
+            sym := lxCOLON;
 
-        IF c = "=" THEN
-            sym := lxASSIGN;
-            TXT.next(text)
-        END
+            IF c = "=" THEN
+                sym := lxASSIGN;
+                TXT.next(text)
+            END
 
-    |")":
-        sym := lxRROUND
+        |")":
+            sym := lxRROUND
 
-    |"]":
-        sym := lxRSQUARE
+        |"]":
+            sym := lxRSQUARE
 
-    |"}":
-        sym := lxRCURLY
+        |"}":
+            sym := lxRCURLY
 
-    END
+        END
 
-    RETURN sym
+        RETURN sym
 END delimiter;
 
 
 PROCEDURE Next* (text: SCANNER; VAR lex: LEX);
-VAR
-    c: CHAR;
+    VAR
+        c: CHAR;
 
 
-    PROCEDURE check (cond: BOOLEAN; text: SCANNER; lex: LEX; errno: INTEGER);
-    BEGIN
-        IF ~cond THEN
-            ERRORS.ErrorMsg(text.fname, lex.pos.line, lex.pos.col, errno)
-        END
-    END check;
+        PROCEDURE check (cond: BOOLEAN; text: SCANNER; lex: LEX; errno: INTEGER);
+            BEGIN
+                IF ~cond THEN
+                    ERRORS.ErrorMsg(text.fname, lex.pos.line, lex.pos.col, errno)
+                END
+        END check;
 
 
-    PROCEDURE IsDef (str: ARRAY OF CHAR): BOOLEAN;
-    VAR
-        cur: DEF;
+        PROCEDURE IsDef (str: ARRAY OF CHAR): BOOLEAN;
+            VAR
+                cur: DEF;
 
-    BEGIN
-        cur := def.first(DEF);
-        WHILE (cur # NIL) & (cur.ident # str) DO
-            cur := cur.next(DEF)
-        END
+            BEGIN
+                cur := def.first(DEF);
+                WHILE (cur # NIL) & (cur.ident # str) DO
+                    cur := cur.next(DEF)
+                END
 
-        RETURN cur # NIL
-    END IsDef;
+                RETURN cur # NIL
+        END IsDef;
 
 
-    PROCEDURE Skip (text: SCANNER);
-    VAR
-        i: INTEGER;
+        PROCEDURE Skip (text: SCANNER);
+        VAR
+            i: INTEGER;
 
-    BEGIN
-        i := 0;
-        WHILE (i <= text.ifc) & ~text._skip[i] DO
-            INC(i)
-        END;
-        text.skip := i <= text.ifc
-    END Skip;
+        BEGIN
+            i := 0;
+            WHILE (i <= text.ifc) & ~text._skip[i] DO
+                INC(i)
+            END;
+            text.skip := i <= text.ifc
+        END Skip;
 
 
-    PROCEDURE prep_if (text: SCANNER; VAR lex: LEX);
-    VAR
-        skip: BOOLEAN;
+        PROCEDURE prep_if (text: SCANNER; VAR lex: LEX);
+        VAR
+            skip: BOOLEAN;
 
-    BEGIN
-        INC(text.ifc);
-        text._elsif[text.ifc] := lex.sym = lxELSIF;
-        IF lex.sym = lxIF THEN
-            INC(text.elsec);
-            text._else[text.elsec] := FALSE
-        END;
-        _if := TRUE;
-        skip := TRUE;
-        text.skip := FALSE;
+        BEGIN
+            INC(text.ifc);
+            text._elsif[text.ifc] := lex.sym = lxELSIF;
+            IF lex.sym = lxIF THEN
+                INC(text.elsec);
+                text._else[text.elsec] := FALSE
+            END;
+            _if := TRUE;
+            skip := TRUE;
+            text.skip := FALSE;
 
-        Next(text, lex);
-        check(lex.sym = lxLROUND, text, lex, 64);
+            Next(text, lex);
+            check(lex.sym = lxLROUND, text, lex, 64);
 
-        Next(text, lex);
-        check(lex.sym = lxIDENT, text, lex, 22);
+            Next(text, lex);
+            check(lex.sym = lxIDENT, text, lex, 22);
 
-        REPEAT
-            IF IsDef(lex.ident.s) THEN
-                skip := FALSE
-            END;
+            REPEAT
+                IF IsDef(lex.ident.s) THEN
+                    skip := FALSE
+                END;
 
-            Next(text, lex);
-            IF lex.sym = lxBAR THEN
                 Next(text, lex);
-                check(lex.sym = lxIDENT, text, lex, 22)
-            ELSE
-                check(lex.sym = lxRROUND, text, lex, 33)
-            END
-        UNTIL lex.sym = lxRROUND;
+                IF lex.sym = lxBAR THEN
+                    Next(text, lex);
+                    check(lex.sym = lxIDENT, text, lex, 22)
+                ELSE
+                    check(lex.sym = lxRROUND, text, lex, 33)
+                END
+            UNTIL lex.sym = lxRROUND;
 
-        _if := FALSE;
-        text._skip[text.ifc] := skip;
-        Skip(text);
-        Next(text, lex)
-    END prep_if;
+            _if := FALSE;
+            text._skip[text.ifc] := skip;
+            Skip(text);
+            Next(text, lex)
+        END prep_if;
 
 
-    PROCEDURE prep_end (text: SCANNER; VAR lex: LEX);
-    BEGIN
-        check(text.ifc > 0, text, lex, 118);
-        IF lex.sym = lxEND THEN
-            WHILE text._elsif[text.ifc] DO
-                DEC(text.ifc)
+        PROCEDURE prep_end (text: SCANNER; VAR lex: LEX);
+        BEGIN
+            check(text.ifc > 0, text, lex, 118);
+            IF lex.sym = lxEND THEN
+                WHILE text._elsif[text.ifc] DO
+                    DEC(text.ifc)
+                END;
+                DEC(text.ifc);
+                DEC(text.elsec)
+            ELSIF (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
+                check(~text._else[text.elsec], text, lex, 118);
+                text._skip[text.ifc] := ~text._skip[text.ifc];
+                text._else[text.elsec] := lex.sym = lxELSE
             END;
-            DEC(text.ifc);
-            DEC(text.elsec)
-        ELSIF (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
-            check(~text._else[text.elsec], text, lex, 118);
-            text._skip[text.ifc] := ~text._skip[text.ifc];
-            text._else[text.elsec] := lex.sym = lxELSE
-        END;
-        Skip(text);
-        IF lex.sym = lxELSIF THEN
-            prep_if(text, lex)
-        ELSE
-            Next(text, lex)
-        END
-    END prep_end;
+            Skip(text);
+            IF lex.sym = lxELSIF THEN
+                prep_if(text, lex)
+            ELSE
+                Next(text, lex)
+            END
+        END prep_end;
 
 
-BEGIN
+    BEGIN
 
-    REPEAT
-        c := text.peak;
+        REPEAT
+            c := text.peak;
 
-        WHILE S.space(c) DO
-            c := nextc(text)
-        END;
+            WHILE S.space(c) DO
+                c := nextc(text)
+            END;
 
-        lex.pos.line := text.line;
-        lex.pos.col  := text.col;
-
-        IF S.letter(c) THEN
-            ident(text, lex)
-        ELSIF S.digit(c) THEN
-            number(text, lex)
-        ELSIF (c = '"') OR (c = "'") THEN
-            string(text, lex, c)
-        ELSIF delimiters[ORD(c)] THEN
-            lex.sym := delimiter(text, c)
-        ELSIF c = "$" THEN
-            IF S.letter(nextc(text)) THEN
-                ident(text, lex);
-                IF lex.sym = lxIF THEN
-                    IF ~_if THEN
-                        prep_if(text, lex)
-                    END
-                ELSIF (lex.sym = lxEND) OR (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
-                    IF ~_if THEN
-                        prep_end(text, lex)
+            lex.pos.line := text.line;
+            lex.pos.col  := text.col;
+
+            IF S.letter(c) THEN
+                ident(text, lex)
+            ELSIF S.digit(c) THEN
+                number(text, lex)
+            ELSIF (c = '"') OR (c = "'") THEN
+                string(text, lex, c)
+            ELSIF delimiters[ORD(c)] THEN
+                lex.sym := delimiter(text, c)
+            ELSIF c = "$" THEN
+                IF S.letter(nextc(text)) THEN
+                    ident(text, lex);
+                    IF lex.sym = lxIF THEN
+                        IF ~_if THEN
+                            prep_if(text, lex)
+                        END
+                    ELSIF (lex.sym = lxEND) OR (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
+                        IF ~_if THEN
+                            prep_end(text, lex)
+                        END
+                    ELSE
+                        check(FALSE, text, lex, 119)
                     END
                 ELSE
                     check(FALSE, text, lex, 119)
                 END
+            ELSIF c = 0X THEN
+                lex.sym := lxEOF;
+                text.skip := FALSE;
+                IF text.eof THEN
+                    INC(lex.pos.col)
+                END
+            ELSIF (c = 7FX) & upto THEN
+                upto := FALSE;
+                lex.sym := lxRANGE;
+                DEC(lex.pos.col);
+                TXT.next(text)
             ELSE
-                check(FALSE, text, lex, 119)
-            END
-        ELSIF c = 0X THEN
-            lex.sym := lxEOF;
-            text.skip := FALSE;
-            IF text.eof THEN
-                INC(lex.pos.col)
-            END
-        ELSIF (c = 7FX) & upto THEN
-            upto := FALSE;
-            lex.sym := lxRANGE;
-            DEC(lex.pos.col);
-            TXT.next(text)
-        ELSE
-            TXT.next(text);
-            lex.sym := lxERROR04
-        END;
+                TXT.next(text);
+                lex.sym := lxERROR04
+            END;
 
-        IF lex.sym < 0 THEN
-            lex.error := -lex.sym
-        ELSE
-            lex.error := 0
-        END
+            IF lex.sym < 0 THEN
+                lex.error := -lex.sym
+            ELSE
+                lex.error := 0
+            END
 
-    UNTIL (lex.sym # lxCOMMENT) & ~text.skip
+        UNTIL (lex.sym # lxCOMMENT) & ~text.skip
 
 END Next;