Subversion Repositories Kolibri OS

Rev

Rev 8097 | Rev 9177 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
2
    BSD 2-Clause License
3
 
8859 leency 4
    Copyright (c) 2019-2021, Anton Krotov
7983 leency 5
    All rights reserved.
6
*)
7
 
8
MODULE MSP430;
9
 
10
IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX,
11
       UTILS, C := CONSOLE, PROG, RTL := MSP430RTL;
12
 
13
 
14
CONST
15
 
8859 leency 16
    chkSTK* = 6;
17
 
7983 leency 18
    minRAM* = 128;  maxRAM* = 2048;
19
    minROM* = 2048; maxROM* = 24576;
20
 
8859 leency 21
    StkReserve = RTL.StkReserve;
7983 leency 22
 
23
    IntVectorSize* = RTL.IntVectorSize;
24
 
25
    PC = 0; SP = 1; SR = 2; CG = 3;
26
 
27
    R4 = 4; R5 = 5; R6 = 6; R7 = 7;
28
 
8859 leency 29
    HP = RTL.HP;
7983 leency 30
 
31
    ACC = R4;
32
 
33
    opRRC  = 1000H;  opSWPB = 1080H;  opRRA  = 1100H;  opSXT = 1180H;
34
    opPUSH = 1200H;  opCALL = 1280H;  opRETI = 1300H;
35
 
36
    opMOV = 04000H;  opADD = 05000H;  opADDC = 06000H;  opSUBC = 07000H;
37
    opSUB = 08000H;  opCMP = 09000H;  opDADD = 0A000H;  opBIT  = 0B000H;
38
    opBIC = 0C000H;  opBIS = 0D000H;  opXOR  = 0E000H;  opAND  = 0F000H;
39
 
40
    opJNE = 2000H;  opJEQ = 2400H;  opJNC = 2800H;  opJC  = 2C00H;
41
    opJN  = 3000H;  opJGE = 3400H;  opJL  = 3800H;  opJMP = 3C00H;
42
 
43
    sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128;
44
 
45
    NOWORD = 10000H;
46
 
47
    RCODE = 0; RDATA = 1; RBSS = 2;
48
 
49
    je  = 0;  jne = je  + 1;
50
    jge = 2;  jl  = jge + 1;
51
    jle = 4;  jg  = jle + 1;
52
    jb  = 6;
53
 
54
 
55
TYPE
56
 
57
    ANYCODE = POINTER TO RECORD (LISTS.ITEM)
58
 
59
        offset: INTEGER
60
 
61
    END;
62
 
63
    WORD = POINTER TO RECORD (ANYCODE)
64
 
65
        val: INTEGER
66
 
67
    END;
68
 
69
    LABEL = POINTER TO RECORD (ANYCODE)
70
 
71
        num: INTEGER
72
 
73
    END;
74
 
75
    JMP = POINTER TO RECORD (ANYCODE)
76
 
77
        cc, label: INTEGER;
78
        short: BOOLEAN
79
 
80
    END;
81
 
82
    CALL = POINTER TO RECORD (ANYCODE)
83
 
84
        label: INTEGER
85
 
86
    END;
87
 
88
    COMMAND = IL.COMMAND;
89
 
90
    RELOC = POINTER TO RECORD (LISTS.ITEM)
91
 
92
        section: INTEGER;
93
        WordPtr: WORD
94
 
95
    END;
96
 
97
 
98
VAR
99
 
100
    R: REG.REGS;
101
 
102
    CodeList: LISTS.LIST;
103
    RelList:  LISTS.LIST;
104
 
105
    mem: ARRAY 65536 OF BYTE;
106
 
107
    Labels: CHL.INTLIST;
108
 
109
    IV: ARRAY RTL.LenIV OF INTEGER;
110
 
111
    IdxWords: RECORD src, dst: INTEGER END;
112
 
8859 leency 113
    StkCnt, MaxStkCnt: INTEGER;
7983 leency 114
 
115
 
8859 leency 116
PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN;
117
    RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize
118
END CheckProcDataSize;
119
 
120
 
7983 leency 121
PROCEDURE EmitLabel (L: INTEGER);
122
VAR
123
    label: LABEL;
124
 
125
BEGIN
126
    NEW(label);
127
    label.num := L;
128
    LISTS.push(CodeList, label)
129
END EmitLabel;
130
 
131
 
132
PROCEDURE EmitWord (val: INTEGER);
133
VAR
134
    word: WORD;
135
 
136
BEGIN
137
    IF val < 0 THEN
138
        ASSERT(val >= -32768);
139
        val := val MOD 65536
140
    ELSE
141
        ASSERT(val <= 65535)
142
    END;
143
    NEW(word);
144
    word.val := val;
145
    LISTS.push(CodeList, word)
146
END EmitWord;
147
 
148
 
149
PROCEDURE EmitJmp (cc, label: INTEGER);
150
VAR
151
    jmp: JMP;
152
 
153
BEGIN
154
    NEW(jmp);
155
    jmp.cc := cc;
156
    jmp.label := label;
157
    jmp.short := FALSE;
158
    LISTS.push(CodeList, jmp)
159
END EmitJmp;
160
 
161
 
162
PROCEDURE EmitCall (label: INTEGER);
163
VAR
164
    call: CALL;
165
 
166
BEGIN
167
    NEW(call);
168
    call.label := label;
169
    LISTS.push(CodeList, call)
170
END EmitCall;
171
 
172
 
8859 leency 173
PROCEDURE IncStk;
174
BEGIN
175
    INC(StkCnt);
176
    MaxStkCnt := MAX(StkCnt, MaxStkCnt)
177
END IncStk;
178
 
179
 
7983 leency 180
PROCEDURE bw (b: BOOLEAN): INTEGER;
181
    RETURN BW * ORD(b)
182
END bw;
183
 
184
 
185
PROCEDURE src_x (x, Rn: INTEGER): INTEGER;
186
VAR
187
    res: INTEGER;
188
 
189
BEGIN
190
    IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN
191
        res := Rn * 256 + sINDIR
192
    ELSE
193
        IdxWords.src := x;
194
        res := Rn * 256 + sIDX
195
    END
196
 
197
    RETURN res
198
END src_x;
199
 
200
 
201
PROCEDURE dst_x (x, Rn: INTEGER): INTEGER;
202
BEGIN
203
    IdxWords.dst := x
204
    RETURN Rn + dIDX
205
END dst_x;
206
 
207
 
208
PROCEDURE indir (Rn: INTEGER): INTEGER;
209
    RETURN Rn * 256 + sINDIR
210
END indir;
211
 
212
 
213
PROCEDURE incr (Rn: INTEGER): INTEGER;
214
    RETURN Rn * 256 + sINCR
215
END incr;
216
 
217
 
218
PROCEDURE imm (x: INTEGER): INTEGER;
219
VAR
220
    res: INTEGER;
221
 
222
BEGIN
223
    CASE x OF
224
    | 0: res := CG * 256
225
    | 1: res := CG * 256 + sIDX
226
    | 2: res := indir(CG)
227
    | 4: res := indir(SR)
228
    | 8: res := incr(SR)
229
    |-1: res := incr(CG)
230
    ELSE
231
        res := incr(PC);
232
        IdxWords.src := x
233
    END
234
 
235
    RETURN res
236
END imm;
237
 
238
 
239
PROCEDURE Op2 (op, src, dst: INTEGER);
240
BEGIN
241
    ASSERT(BITS(op) - {6, 12..15} = {});
242
    ASSERT(BITS(src) - {4, 5, 8..11} = {});
243
    ASSERT(BITS(dst) - {0..3, 7} = {});
244
 
245
    EmitWord(op + src + dst);
246
 
247
    IF IdxWords.src # NOWORD THEN
248
        EmitWord(IdxWords.src);
249
        IdxWords.src := NOWORD
250
    END;
251
 
252
    IF IdxWords.dst # NOWORD THEN
253
        EmitWord(IdxWords.dst);
254
        IdxWords.dst := NOWORD
255
    END
256
END Op2;
257
 
258
 
259
PROCEDURE Op1 (op, reg, As: INTEGER);
260
BEGIN
261
    EmitWord(op + reg + As)
262
END Op1;
263
 
264
 
265
PROCEDURE MovRR (src, dst: INTEGER);
266
BEGIN
267
    Op2(opMOV, src * 256, dst)
268
END MovRR;
269
 
270
 
271
PROCEDURE PushImm (imm: INTEGER);
272
BEGIN
273
    imm := UTILS.Long(imm);
274
    CASE imm OF
275
    | 0: Op1(opPUSH, CG, sREG)
276
    | 1: Op1(opPUSH, CG, sIDX)
277
    | 2: Op1(opPUSH, CG, sINDIR)
278
    |-1: Op1(opPUSH, CG, sINCR)
279
    ELSE
280
        Op1(opPUSH, PC, sINCR);
281
        EmitWord(imm)
282
    END;
8859 leency 283
    IncStk
7983 leency 284
END PushImm;
285
 
286
 
287
PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER);
288
BEGIN
289
    ASSERT(~ODD(adr));
290
    ASSERT((0 <= word) & (word <= 65535));
291
    mem[adr] := word MOD 256;
292
    mem[adr + 1] := word DIV 256;
293
    INC(adr, 2)
294
END PutWord;
295
 
296
 
297
PROCEDURE NewLabel (): INTEGER;
298
BEGIN
299
    CHL.PushInt(Labels, 0)
300
    RETURN IL.NewLabel()
301
END NewLabel;
302
 
303
 
304
PROCEDURE LabelOffs (n: INTEGER): INTEGER;
305
    RETURN CHL.GetInt(Labels, n)
306
END LabelOffs;
307
 
308
 
309
PROCEDURE Fixup (CodeAdr, IntVectorSize: INTEGER): INTEGER;
310
VAR
311
    cmd:      ANYCODE;
312
    adr:      INTEGER;
313
    offset:   INTEGER;
314
    diff:     INTEGER;
315
    cc:       INTEGER;
316
    shorted:  BOOLEAN;
317
 
318
BEGIN
319
    REPEAT
320
        shorted := FALSE;
321
        offset := CodeAdr DIV 2;
322
 
323
        cmd := CodeList.first(ANYCODE);
324
        WHILE cmd # NIL DO
325
            cmd.offset := offset;
326
            CASE cmd OF
327
            |LABEL: CHL.SetInt(Labels, cmd.num, offset)
328
            |JMP:   INC(offset);
329
                    IF ~cmd.short THEN
330
                        INC(offset);
331
                        IF cmd.cc # opJMP THEN
332
                            INC(offset)
333
                        END
334
                    END
335
 
336
            |CALL:  INC(offset, 2)
337
            |WORD:  INC(offset)
338
            END;
339
            cmd := cmd.next(ANYCODE)
340
        END;
341
 
342
        cmd := CodeList.first(ANYCODE);
343
        WHILE cmd # NIL DO
344
            IF (cmd IS JMP) & ~cmd(JMP).short THEN
345
                diff := LabelOffs(cmd(JMP).label) - cmd.offset - 1;
346
                IF ABS(diff) <= 512 THEN
347
                    cmd(JMP).short := TRUE;
348
                    shorted := TRUE
349
                END
350
            END;
351
            cmd := cmd.next(ANYCODE)
352
        END
353
 
354
    UNTIL ~shorted;
355
 
356
    IF offset * 2 > 10000H - IntVectorSize THEN
357
        ERRORS.Error(203)
358
    END;
359
 
360
    adr := CodeAdr;
361
    cmd := CodeList.first(ANYCODE);
362
    WHILE cmd # NIL DO
363
        CASE cmd OF
364
        |LABEL:
365
 
366
        |JMP:   IF ~cmd.short THEN
367
                    CASE cmd.cc OF
368
                    |opJNE: cc := opJEQ
369
                    |opJEQ: cc := opJNE
370
                    |opJNC: cc := opJC
371
                    |opJC:  cc := opJNC
372
                    |opJGE: cc := opJL
373
                    |opJL:  cc := opJGE
374
                    |opJMP: cc := opJMP
375
                    END;
376
 
377
                    IF cc # opJMP THEN
378
                        PutWord(cc + 2, adr)  (* jcc L *)
379
                    END;
380
 
381
                    PutWord(4030H, adr); (* MOV @PC+, PC *)
382
                    PutWord(LabelOffs(cmd.label) * 2, adr)
383
                    (* L: *)
384
                ELSE
385
                    diff := LabelOffs(cmd.label) - cmd.offset - 1;
386
                    ASSERT((-512 <= diff) & (diff <= 511));
387
                    PutWord(cmd.cc + diff MOD 1024, adr)
388
                END
389
 
390
        |CALL:  PutWord(12B0H, adr); (* CALL @PC+ *)
391
                PutWord(LabelOffs(cmd.label) * 2, adr)
392
 
393
        |WORD:  PutWord(cmd.val, adr)
394
 
395
        END;
396
        cmd := cmd.next(ANYCODE)
397
    END
398
 
399
    RETURN adr - CodeAdr
400
END Fixup;
401
 
402
 
403
PROCEDURE Push (reg: INTEGER);
404
BEGIN
405
    Op1(opPUSH, reg, sREG);
8859 leency 406
    IncStk
7983 leency 407
END Push;
408
 
409
 
410
PROCEDURE Pop (reg: INTEGER);
411
BEGIN
412
    Op2(opMOV, incr(SP), reg);
413
    DEC(StkCnt)
414
END Pop;
415
 
416
 
417
PROCEDURE Test (reg: INTEGER);
418
BEGIN
419
    Op2(opCMP, imm(0), reg)
420
END Test;
421
 
422
 
423
PROCEDURE Clear (reg: INTEGER);
424
BEGIN
425
    Op2(opMOV, imm(0), reg)
426
END Clear;
427
 
428
 
429
PROCEDURE mov (dst, src: INTEGER);
430
BEGIN
431
    MovRR(src, dst)
432
END mov;
433
 
434
 
435
PROCEDURE xchg (reg1, reg2: INTEGER);
436
BEGIN
437
    Push(reg1);
8097 maxcodehac 438
    mov(reg1, reg2);
7983 leency 439
    Pop(reg2)
440
END xchg;
441
 
442
 
443
PROCEDURE Reloc (section: INTEGER);
444
VAR
445
    reloc: RELOC;
446
 
447
BEGIN
448
    NEW(reloc);
449
    reloc.section := section;
450
    reloc.WordPtr := CodeList.last(WORD);
451
    LISTS.push(RelList, reloc)
452
END Reloc;
453
 
454
 
455
PROCEDURE CallRTL (proc, params: INTEGER);
456
BEGIN
8859 leency 457
    IncStk;
458
    DEC(StkCnt);
7983 leency 459
    EmitCall(RTL.rtl[proc].label);
460
    RTL.Used(proc);
461
    IF params > 0 THEN
462
        Op2(opADD, imm(params * 2), SP);
463
        DEC(StkCnt, params)
464
    END
465
END CallRTL;
466
 
467
 
468
PROCEDURE UnOp (VAR reg: INTEGER);
469
BEGIN
470
    REG.UnOp(R, reg)
471
END UnOp;
472
 
473
 
474
PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
475
BEGIN
476
    REG.BinOp(R, reg1, reg2)
477
END BinOp;
478
 
479
 
480
PROCEDURE GetRegA;
481
BEGIN
482
    ASSERT(REG.GetReg(R, ACC))
483
END GetRegA;
484
 
485
 
486
PROCEDURE drop;
487
BEGIN
488
    REG.Drop(R)
489
END drop;
490
 
491
 
492
PROCEDURE GetAnyReg (): INTEGER;
493
    RETURN REG.GetAnyReg(R)
494
END GetAnyReg;
495
 
496
 
497
PROCEDURE PushAll (NumberOfParameters: INTEGER);
498
BEGIN
499
    REG.PushAll(R);
500
    DEC(R.pushed, NumberOfParameters)
501
END PushAll;
502
 
503
 
504
PROCEDURE PushAll_1;
505
BEGIN
506
    REG.PushAll_1(R)
507
END PushAll_1;
508
 
509
 
510
PROCEDURE cond (op: INTEGER): INTEGER;
511
VAR
512
    res: INTEGER;
513
 
514
BEGIN
515
    CASE op OF
516
    |IL.opGT, IL.opGTC: res := jg
517
    |IL.opGE, IL.opGEC: res := jge
518
    |IL.opLT, IL.opLTC: res := jl
519
    |IL.opLE, IL.opLEC: res := jle
520
    |IL.opEQ, IL.opEQC: res := je
521
    |IL.opNE, IL.opNEC: res := jne
522
    END
523
 
524
    RETURN res
525
END cond;
526
 
527
 
528
PROCEDURE jcc (cc, label: INTEGER);
529
VAR
530
    L: INTEGER;
531
 
532
BEGIN
533
    CASE cc OF
534
    |jne:
535
        EmitJmp(opJNE, label)
536
    |je:
537
        EmitJmp(opJEQ, label)
538
    |jge:
539
        EmitJmp(opJGE, label)
540
    |jl:
541
        EmitJmp(opJL, label)
542
    |jle:
543
        EmitJmp(opJL, label);
544
        EmitJmp(opJEQ, label)
545
    |jg:
546
        L := NewLabel();
547
        EmitJmp(opJEQ, L);
548
        EmitJmp(opJGE, label);
549
        EmitLabel(L)
550
    |jb:
551
        EmitJmp(opJNC, label)
552
    END
553
END jcc;
554
 
555
 
556
PROCEDURE setcc (cc, reg: INTEGER);
557
VAR
558
    L: INTEGER;
559
 
560
BEGIN
561
    L := NewLabel();
562
    Op2(opMOV, imm(1), reg);
563
    jcc(cc, L);
564
    Clear(reg);
565
    EmitLabel(L)
566
END setcc;
567
 
568
 
569
PROCEDURE Shift2 (op, reg, n: INTEGER);
570
VAR
571
    reg2: INTEGER;
572
 
573
BEGIN
574
    IF n >= 8 THEN
575
        CASE op OF
576
        |IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG)
577
        |IL.opROR2: Op1(opSWPB, reg, sREG)
578
        |IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg)
579
        |IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG)
580
        END;
581
        DEC(n, 8)
582
    END;
583
 
584
    IF (op = IL.opROR2) & (n > 0) THEN
585
        reg2 := GetAnyReg();
586
        MovRR(reg, reg2)
587
    ELSE
588
        reg2 := -1
589
    END;
590
 
591
    WHILE n > 0 DO
592
        CASE op OF
593
        |IL.opASR2: Op1(opRRA, reg, sREG)
594
        |IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG)
595
        |IL.opLSL2: Op2(opADD, reg * 256, reg)
596
        |IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG)
597
        END;
598
        DEC(n)
599
    END;
600
 
601
    IF reg2 # -1 THEN
602
        drop
603
    END
604
 
605
END Shift2;
606
 
607
 
608
PROCEDURE Neg (reg: INTEGER);
609
BEGIN
610
    Op2(opXOR, imm(-1), reg);
611
    Op2(opADD, imm(1), reg)
612
END Neg;
613
 
614
 
615
PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
616
    RETURN (offset + StkCnt - ORD(offset > 0)) * 2
617
END LocalOffset;
618
 
619
 
620
PROCEDURE LocalDst (offset: INTEGER): INTEGER;
621
    RETURN dst_x(LocalOffset(offset), SP)
622
END LocalDst;
623
 
624
 
625
PROCEDURE LocalSrc (offset: INTEGER): INTEGER;
626
    RETURN src_x(LocalOffset(offset), SP)
627
END LocalSrc;
628
 
629
 
8859 leency 630
PROCEDURE translate (chk_stk: BOOLEAN);
7983 leency 631
VAR
632
    cmd, next: COMMAND;
633
 
634
    opcode, param1, param2, L, a, n, c1, c2: INTEGER;
635
 
636
    reg1, reg2: INTEGER;
637
 
638
    cc: INTEGER;
639
 
8859 leency 640
    word: WORD;
641
 
7983 leency 642
BEGIN
643
    cmd := IL.codes.commands.first(COMMAND);
644
 
645
    WHILE cmd # NIL DO
646
 
647
        param1 := cmd.param1;
648
        param2 := cmd.param2;
649
 
650
        opcode := cmd.opcode;
651
 
652
        CASE opcode OF
653
        |IL.opJMP:
654
            EmitJmp(opJMP, param1)
655
 
656
        |IL.opCALL:
8859 leency 657
            IncStk;
658
            DEC(StkCnt);
7983 leency 659
            EmitCall(param1)
660
 
661
        |IL.opCALLP:
8859 leency 662
            IncStk;
663
            DEC(StkCnt);
7983 leency 664
            UnOp(reg1);
665
            Op1(opCALL, reg1, sREG);
666
            drop;
667
            ASSERT(R.top = -1)
668
 
669
        |IL.opPRECALL:
670
            PushAll(0)
671
 
672
        |IL.opLABEL:
673
            EmitLabel(param1)
674
 
675
        |IL.opSADR_PARAM:
676
            Op1(opPUSH, PC, sINCR);
8859 leency 677
            IncStk;
7983 leency 678
            EmitWord(param2);
679
            Reloc(RDATA)
680
 
681
        |IL.opERR:
682
            CallRTL(RTL._error, 2)
683
 
684
        |IL.opPUSHC:
685
            PushImm(param2)
686
 
687
        |IL.opONERR:
8859 leency 688
            DEC(StkCnt);
689
            EmitWord(0C232H); (*  BIC   #8, SR; DINT  *)
690
            EmitWord(4303H);  (*  MOV   R3, R3; NOP   *)
7983 leency 691
            PushImm(param2);
692
            EmitJmp(opJMP, param1)
693
 
694
        |IL.opLEAVEC:
695
            Pop(PC)
696
 
697
        |IL.opENTER:
698
            ASSERT(R.top = -1);
8859 leency 699
            EmitLabel(param1);
700
            n := param2 MOD 65536;
701
            param2 := param2 DIV 65536;
7983 leency 702
            StkCnt := 0;
8859 leency 703
            IF chk_stk THEN
704
                L := NewLabel();
705
                Op2(opMOV, SP * 256, R4);
706
                Op2(opSUB, HP * 256, R4);
707
                Op2(opCMP, imm(StkReserve), R4);
708
                word := CodeList.last(WORD);
709
                jcc(jge, L);
710
                DEC(StkCnt);
711
                EmitWord(0C232H); (*  BIC   #8, SR; DINT  *)
712
                EmitWord(4303H);  (*  MOV   R3, R3; NOP   *)
713
                PushImm(n);
714
                EmitJmp(opJMP, cmd.param3);
715
                EmitLabel(L)
716
            END;
717
 
7983 leency 718
            IF param2 > 8 THEN
719
                Op2(opMOV, imm(param2), R4);
720
                L := NewLabel();
721
                EmitLabel(L);
722
                Push(CG);
723
                Op2(opSUB, imm(1), R4);
724
                jcc(jne, L)
8859 leency 725
            ELSE
726
                FOR n := 1 TO param2 DO
727
                    Push(CG)
7983 leency 728
                END
8859 leency 729
            END;
730
            StkCnt := param2;
731
            MaxStkCnt := StkCnt
7983 leency 732
 
733
        |IL.opLEAVE, IL.opLEAVER:
734
            ASSERT(param2 = 0);
735
            IF opcode = IL.opLEAVER THEN
736
                UnOp(reg1);
737
                IF reg1 # ACC THEN
8859 leency 738
                    mov(ACC, reg1)
7983 leency 739
                END;
740
                drop
741
            END;
742
            ASSERT(R.top = -1);
743
            ASSERT(StkCnt = param1);
8859 leency 744
            IF chk_stk THEN
745
                INC(word.val, MaxStkCnt * 2)
746
            END;
7983 leency 747
            IF param1 > 0 THEN
748
                Op2(opADD, imm(param1 * 2), SP)
749
            END;
750
            Pop(PC)
751
 
752
        |IL.opRES:
753
            ASSERT(R.top = -1);
754
            GetRegA
755
 
756
        |IL.opCLEANUP:
757
            IF param2 # 0 THEN
758
                Op2(opADD, imm(param2 * 2), SP);
759
                DEC(StkCnt, param2)
760
            END
761
 
762
        |IL.opCONST:
763
            next := cmd.next(COMMAND);
764
            IF next.opcode = IL.opCONST THEN
765
                c1 := param2;
766
                c2 := next.param2;
767
                next := next.next(COMMAND);
768
                IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
769
                    Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR));
770
                    cmd := next
771
                ELSE
772
                    Op2(opMOV, imm(param2), GetAnyReg())
773
                END
774
            ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
775
                UnOp(reg1);
776
                Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR));
777
                drop;
778
                cmd := next
779
            ELSE
780
                Op2(opMOV, imm(param2), GetAnyReg())
781
            END
782
 
783
        |IL.opSADR:
784
            Op2(opMOV, incr(PC), GetAnyReg());
785
            EmitWord(param2);
786
            Reloc(RDATA)
787
 
788
        |IL.opGADR:
789
            Op2(opMOV, incr(PC), GetAnyReg());
790
            EmitWord(param2);
791
            Reloc(RBSS)
792
 
793
        |IL.opLADR:
794
            reg1 := GetAnyReg();
795
            n := LocalOffset(param2);
796
            Op2(opMOV, SP * 256, reg1);
797
            IF n # 0 THEN
798
                Op2(opADD, imm(n), reg1)
799
            END
800
 
801
        |IL.opLLOAD8:
802
            Op2(opMOV + BW, LocalSrc(param2), GetAnyReg())
803
 
804
        |IL.opLLOAD16, IL.opVADR:
805
            Op2(opMOV, LocalSrc(param2), GetAnyReg())
806
 
807
        |IL.opGLOAD8:
808
            Op2(opMOV + BW, src_x(param2, SR), GetAnyReg());
809
            Reloc(RBSS)
810
 
811
        |IL.opGLOAD16:
812
            Op2(opMOV, src_x(param2, SR), GetAnyReg());
813
            Reloc(RBSS)
814
 
815
        |IL.opLOAD8:
816
            UnOp(reg1);
817
            Op2(opMOV + BW, indir(reg1), reg1)
818
 
819
        |IL.opLOAD16:
820
            UnOp(reg1);
821
            Op2(opMOV, indir(reg1), reg1)
822
 
823
        |IL.opVLOAD8:
824
            reg1 := GetAnyReg();
825
            Op2(opMOV, LocalSrc(param2), reg1);
826
            Op2(opMOV + BW, indir(reg1), reg1)
827
 
828
        |IL.opVLOAD16:
829
            reg1 := GetAnyReg();
830
            Op2(opMOV, LocalSrc(param2), reg1);
831
            Op2(opMOV, indir(reg1), reg1)
832
 
833
        |IL.opSAVE, IL.opSAVE16:
834
            BinOp(reg2, reg1);
835
            Op2(opMOV, reg2 * 256, dst_x(0, reg1));
836
            drop;
837
            drop
838
 
839
        |IL.opSAVE8:
840
            BinOp(reg2, reg1);
841
            Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
842
            drop;
843
            drop
844
 
845
        |IL.opSAVE8C:
846
            UnOp(reg1);
847
            Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
848
            drop
849
 
850
        |IL.opSAVE16C, IL.opSAVEC:
851
            UnOp(reg1);
852
            Op2(opMOV, imm(param2), dst_x(0, reg1));
853
            drop
854
 
855
        |IL.opUMINUS:
856
            UnOp(reg1);
857
            Neg(reg1)
858
 
859
        |IL.opADD:
860
            BinOp(reg1, reg2);
861
            Op2(opADD, reg2 * 256, reg1);
862
            drop
863
 
8097 maxcodehac 864
        |IL.opADDC:
7983 leency 865
            IF param2 # 0 THEN
866
                UnOp(reg1);
867
                Op2(opADD, imm(param2), reg1)
868
            END
869
 
870
        |IL.opSUB:
871
            BinOp(reg1, reg2);
872
            Op2(opSUB, reg2 * 256, reg1);
873
            drop
874
 
875
        |IL.opSUBR, IL.opSUBL:
876
            UnOp(reg1);
877
            IF param2 # 0 THEN
878
                Op2(opSUB, imm(param2), reg1)
879
            END;
880
            IF opcode = IL.opSUBL THEN
881
                Neg(reg1)
882
            END
883
 
884
        |IL.opLADR_SAVEC:
885
            Op2(opMOV, imm(param2), LocalDst(param1))
886
 
887
        |IL.opLADR_SAVE:
888
            UnOp(reg1);
889
            Op2(opMOV, reg1 * 256, LocalDst(param2));
890
            drop
891
 
892
        |IL.opGADR_SAVEC:
893
            Op2(opMOV, imm(param2), dst_x(param1, SR));
894
            Reloc(RBSS)
895
 
896
        |IL.opCONST_PARAM:
897
            PushImm(param2)
898
 
899
        |IL.opPARAM:
900
            IF param2 = 1 THEN
901
                UnOp(reg1);
902
                Push(reg1);
903
                drop
904
            ELSE
905
                ASSERT(R.top + 1 <= param2);
906
                PushAll(param2)
907
            END
908
 
909
        |IL.opEQ..IL.opGE,
910
         IL.opEQC..IL.opGEC:
911
 
912
            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
913
                BinOp(reg1, reg2);
914
                Op2(opCMP, reg2 * 256, reg1);
915
                drop
916
            ELSE
917
                UnOp(reg1);
918
                Op2(opCMP, imm(param2), reg1)
919
            END;
920
 
921
            drop;
922
            cc := cond(opcode);
923
            next := cmd.next(COMMAND);
924
 
8097 maxcodehac 925
            IF next.opcode = IL.opJNZ THEN
7983 leency 926
                jcc(cc, next.param1);
927
                cmd := next
8097 maxcodehac 928
            ELSIF next.opcode = IL.opJZ THEN
7983 leency 929
                jcc(ORD(BITS(cc) / {0}), next.param1);
930
                cmd := next
931
            ELSE
932
                setcc(cc, GetAnyReg())
933
            END
934
 
8097 maxcodehac 935
        |IL.opNOP, IL.opAND, IL.opOR:
7983 leency 936
 
937
        |IL.opCODE:
938
            EmitWord(param2)
939
 
940
        |IL.opDROP:
941
            UnOp(reg1);
942
            drop
943
 
8097 maxcodehac 944
        |IL.opJNZ1:
7983 leency 945
            UnOp(reg1);
946
            Test(reg1);
947
            jcc(jne, param1)
948
 
949
        |IL.opJG:
950
            UnOp(reg1);
951
            Test(reg1);
952
            jcc(jg, param1)
953
 
8097 maxcodehac 954
        |IL.opJNZ:
7983 leency 955
            UnOp(reg1);
956
            Test(reg1);
957
            jcc(jne, param1);
958
            drop
959
 
8097 maxcodehac 960
        |IL.opJZ:
7983 leency 961
            UnOp(reg1);
962
            Test(reg1);
963
            jcc(je, param1);
964
            drop
965
 
966
        |IL.opNOT:
967
            UnOp(reg1);
968
            Test(reg1);
969
            setcc(je, reg1)
970
 
971
        |IL.opORD:
972
            UnOp(reg1);
973
            Test(reg1);
974
            setcc(jne, reg1)
975
 
976
        |IL.opGET:
977
            BinOp(reg1, reg2);
978
            drop;
979
            drop;
980
            Op2(opMOV + bw(param2 = 1), indir(reg1), dst_x(0, reg2))
981
 
982
        |IL.opGETC:
983
            UnOp(reg2);
984
            drop;
985
            Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2))
986
 
8097 maxcodehac 987
        |IL.opCHKBYTE:
988
            BinOp(reg1, reg2);
989
            Op2(opCMP, imm(256), reg1);
990
            jcc(jb, param1)
991
 
7983 leency 992
        |IL.opCHKIDX:
993
            UnOp(reg1);
994
            Op2(opCMP, imm(param2), reg1);
995
            jcc(jb, param1)
996
 
997
        |IL.opCHKIDX2:
998
            BinOp(reg1, reg2);
999
            IF param2 # -1 THEN
1000
                Op2(opCMP, reg1 * 256, reg2);
1001
                jcc(jb, param1)
1002
            END;
1003
            INCL(R.regs, reg1);
1004
            DEC(R.top);
1005
            R.stk[R.top] := reg2
1006
 
1007
        |IL.opINCC, IL.opINCCB:
1008
            UnOp(reg1);
1009
            Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1));
1010
            drop
1011
 
1012
        |IL.opDECCB:
1013
            UnOp(reg1);
1014
            Op2(opSUB + BW, imm(param2), dst_x(0, reg1));
1015
            drop
1016
 
1017
        |IL.opINC, IL.opINCB:
1018
            BinOp(reg1, reg2);
1019
            Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2));
1020
            drop;
1021
            drop
1022
 
1023
        |IL.opDEC, IL.opDECB:
1024
            BinOp(reg1, reg2);
1025
            Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2));
1026
            drop;
1027
            drop
1028
 
1029
        |IL.opLADR_INCC, IL.opLADR_INCCB:
1030
            Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1))
1031
 
1032
        |IL.opLADR_DECCB:
1033
            Op2(opSUB + BW, imm(param2), LocalDst(param1))
1034
 
1035
        |IL.opLADR_INC, IL.opLADR_INCB:
1036
            UnOp(reg1);
1037
            Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2));
1038
            drop
1039
 
1040
        |IL.opLADR_DEC, IL.opLADR_DECB:
1041
            UnOp(reg1);
1042
            Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2));
1043
            drop
1044
 
1045
        |IL.opPUSHT:
1046
            UnOp(reg1);
1047
            Op2(opMOV, src_x(-2, reg1), GetAnyReg())
1048
 
1049
        |IL.opISREC:
1050
            PushAll(2);
1051
            PushImm(param2);
1052
            CallRTL(RTL._guardrec, 3);
1053
            GetRegA
1054
 
1055
        |IL.opIS:
1056
            PushAll(1);
1057
            PushImm(param2);
1058
            CallRTL(RTL._is, 2);
1059
            GetRegA
1060
 
1061
        |IL.opTYPEGR:
1062
            PushAll(1);
1063
            PushImm(param2);
1064
            CallRTL(RTL._guardrec, 2);
1065
            GetRegA
1066
 
1067
        |IL.opTYPEGP:
1068
            UnOp(reg1);
1069
            PushAll(0);
1070
            Push(reg1);
1071
            PushImm(param2);
1072
            CallRTL(RTL._guard, 2);
1073
            GetRegA
1074
 
1075
        |IL.opTYPEGD:
1076
            UnOp(reg1);
1077
            PushAll(0);
1078
            Op1(opPUSH, reg1, sIDX);
8859 leency 1079
            IncStk;
7983 leency 1080
            EmitWord(-2);
1081
            PushImm(param2);
1082
            CallRTL(RTL._guardrec, 2);
1083
            GetRegA
1084
 
1085
        |IL.opMULS:
1086
            BinOp(reg1, reg2);
1087
            Op2(opAND, reg2 * 256, reg1);
1088
            drop
1089
 
1090
        |IL.opMULSC:
1091
            UnOp(reg1);
1092
            Op2(opAND, imm(param2), reg1)
1093
 
1094
        |IL.opDIVS:
1095
            BinOp(reg1, reg2);
1096
            Op2(opXOR, reg2 * 256, reg1);
1097
            drop
1098
 
1099
        |IL.opDIVSC:
1100
            UnOp(reg1);
1101
            Op2(opXOR, imm(param2), reg1)
1102
 
1103
        |IL.opADDS:
1104
            BinOp(reg1, reg2);
1105
            Op2(opBIS, reg2 * 256, reg1);
1106
            drop
1107
 
1108
        |IL.opSUBS:
1109
            BinOp(reg1, reg2);
1110
            Op2(opBIC, reg2 * 256, reg1);
1111
            drop
1112
 
8097 maxcodehac 1113
        |IL.opADDSC:
7983 leency 1114
            UnOp(reg1);
1115
            Op2(opBIS, imm(param2), reg1)
1116
 
1117
        |IL.opSUBSL:
1118
            UnOp(reg1);
1119
            Op2(opXOR, imm(-1), reg1);
1120
            Op2(opAND, imm(param2), reg1)
1121
 
1122
        |IL.opSUBSR:
1123
            UnOp(reg1);
1124
            Op2(opBIC, imm(param2), reg1)
1125
 
1126
        |IL.opUMINS:
1127
            UnOp(reg1);
1128
            Op2(opXOR, imm(-1), reg1)
1129
 
1130
        |IL.opLENGTH:
1131
            PushAll(2);
1132
            CallRTL(RTL._length, 2);
1133
            GetRegA
1134
 
1135
        |IL.opMAX,IL.opMIN:
1136
            BinOp(reg1, reg2);
1137
            Op2(opCMP, reg2 * 256, reg1);
1138
            IF opcode = IL.opMIN THEN
1139
                cc := opJL + 1
1140
            ELSE
1141
                cc := opJGE + 1
1142
            END;
1143
            EmitWord(cc);        (* jge/jl L *)
1144
            MovRR(reg2, reg1);
1145
                                 (* L: *)
1146
            drop
1147
 
1148
        |IL.opMAXC, IL.opMINC:
1149
            UnOp(reg1);
1150
            Op2(opCMP, imm(param2), reg1);
1151
            L := NewLabel();
1152
            IF opcode = IL.opMINC THEN
1153
                cc := jl
1154
            ELSE
1155
                cc := jge
1156
            END;
1157
            jcc(cc, L);
1158
            Op2(opMOV, imm(param2), reg1);
1159
            EmitLabel(L)
1160
 
1161
        |IL.opSWITCH:
1162
            UnOp(reg1);
1163
            IF param2 = 0 THEN
1164
                reg2 := ACC
1165
            ELSE
1166
                reg2 := R5
1167
            END;
1168
            IF reg1 # reg2 THEN
1169
                ASSERT(REG.GetReg(R, reg2));
1170
                ASSERT(REG.Exchange(R, reg1, reg2));
1171
                drop
1172
            END;
1173
            drop
1174
 
1175
        |IL.opENDSW:
1176
 
1177
        |IL.opCASEL:
1178
            Op2(opCMP, imm(param1), ACC);
1179
            jcc(jl, param2)
1180
 
1181
        |IL.opCASER:
1182
            Op2(opCMP, imm(param1), ACC);
1183
            jcc(jg, param2)
1184
 
1185
        |IL.opCASELR:
1186
            Op2(opCMP, imm(param1), ACC);
8859 leency 1187
            IF param2 = cmd.param3 THEN
1188
                jcc(jne, param2)
1189
            ELSE
1190
                jcc(jl, param2);
1191
                jcc(jg, cmd.param3)
1192
            END
7983 leency 1193
 
1194
        |IL.opSBOOL:
1195
            BinOp(reg2, reg1);
1196
            Test(reg2);
1197
            setcc(jne, reg2);
1198
            Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
1199
            drop;
1200
            drop
1201
 
1202
        |IL.opSBOOLC:
1203
            UnOp(reg1);
1204
            Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
1205
            drop
1206
 
1207
        |IL.opEQS .. IL.opGES:
1208
            PushAll(4);
1209
            PushImm((opcode - IL.opEQS) * 12);
1210
            CallRTL(RTL._strcmp, 5);
1211
            GetRegA
1212
 
1213
        |IL.opLEN:
1214
            UnOp(reg1);
1215
            drop;
1216
            EXCL(R.regs, reg1);
1217
 
1218
            WHILE param2 > 0 DO
1219
                UnOp(reg2);
1220
                drop;
1221
                DEC(param2)
1222
            END;
1223
 
1224
            INCL(R.regs, reg1);
1225
            ASSERT(REG.GetReg(R, reg1))
1226
 
1227
        |IL.opLSL, IL.opASR, IL.opROR, IL.opLSR:
1228
            PushAll(2);
1229
            CASE opcode OF
1230
            |IL.opLSL: CallRTL(RTL._lsl, 2)
1231
            |IL.opASR: CallRTL(RTL._asr, 2)
1232
            |IL.opROR: CallRTL(RTL._ror, 2)
1233
            |IL.opLSR: CallRTL(RTL._lsr, 2)
1234
            END;
1235
            GetRegA
1236
 
1237
        |IL.opLSL1, IL.opASR1, IL.opROR1, IL.opLSR1:
1238
            UnOp(reg1);
1239
            PushAll_1;
1240
            PushImm(param2);
1241
            Push(reg1);
1242
            drop;
1243
            CASE opcode OF
1244
            |IL.opLSL1: CallRTL(RTL._lsl, 2)
1245
            |IL.opASR1: CallRTL(RTL._asr, 2)
1246
            |IL.opROR1: CallRTL(RTL._ror, 2)
1247
            |IL.opLSR1: CallRTL(RTL._lsr, 2)
1248
            END;
1249
            GetRegA
1250
 
1251
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
1252
            param2 := param2 MOD 16;
1253
            IF param2 # 0 THEN
1254
                UnOp(reg1);
1255
                Shift2(opcode, reg1, param2)
1256
            END
1257
 
1258
        |IL.opMUL:
1259
            PushAll(2);
1260
            CallRTL(RTL._mul, 2);
1261
            GetRegA
1262
 
1263
        |IL.opMULC:
1264
            UnOp(reg1);
1265
 
1266
            a := param2;
1267
            IF a > 1 THEN
1268
                n := UTILS.Log2(a)
1269
            ELSIF a < -1 THEN
1270
                n := UTILS.Log2(-a)
1271
            ELSE
1272
                n := -1
1273
            END;
1274
 
1275
            IF a = 1 THEN
1276
 
1277
            ELSIF a = -1 THEN
1278
                Neg(reg1)
1279
            ELSIF a = 0 THEN
1280
                Clear(reg1)
1281
            ELSE
1282
                IF n > 0 THEN
1283
                    IF a < 0 THEN
1284
                        Neg(reg1)
1285
                    END;
1286
                    Shift2(IL.opLSL2, reg1, n)
1287
                ELSE
1288
                    PushAll(1);
1289
                    PushImm(a);
1290
                    CallRTL(RTL._mul, 2);
1291
                    GetRegA
1292
                END
1293
            END
1294
 
1295
        |IL.opDIV:
1296
            PushAll(2);
1297
            CallRTL(RTL._divmod, 2);
1298
            GetRegA
1299
 
1300
        |IL.opDIVR:
1301
            ASSERT(param2 > 0);
1302
 
1303
            IF param2 > 1 THEN
1304
                n := UTILS.Log2(param2);
1305
                IF n > 0 THEN
1306
                    UnOp(reg1);
1307
                    Shift2(IL.opASR2, reg1, n)
1308
                ELSE
1309
                    PushAll(1);
1310
                    PushImm(param2);
1311
                    CallRTL(RTL._divmod, 2);
1312
                    GetRegA
1313
                END
1314
            END
1315
 
1316
        |IL.opDIVL:
1317
            UnOp(reg1);
1318
            PushAll_1;
1319
            PushImm(param2);
1320
            Push(reg1);
1321
            drop;
1322
            CallRTL(RTL._divmod, 2);
1323
            GetRegA
1324
 
1325
        |IL.opMOD:
1326
            PushAll(2);
1327
            CallRTL(RTL._divmod, 2);
1328
            ASSERT(REG.GetReg(R, R5))
1329
 
1330
        |IL.opMODR:
1331
            ASSERT(param2 > 0);
1332
 
1333
            IF param2 = 1 THEN
1334
                UnOp(reg1);
1335
                Clear(reg1)
1336
            ELSE
1337
                IF UTILS.Log2(param2) > 0 THEN
1338
                    UnOp(reg1);
1339
                    Op2(opAND, imm(param2 - 1), reg1)
1340
                ELSE
1341
                    PushAll(1);
1342
                    PushImm(param2);
1343
                    CallRTL(RTL._divmod, 2);
1344
                    ASSERT(REG.GetReg(R, R5))
1345
                END
1346
            END
1347
 
1348
        |IL.opMODL:
1349
            UnOp(reg1);
1350
            PushAll_1;
1351
            PushImm(param2);
1352
            Push(reg1);
1353
            drop;
1354
            CallRTL(RTL._divmod, 2);
1355
            ASSERT(REG.GetReg(R, R5))
1356
 
1357
        |IL.opCOPYS:
1358
            ASSERT(R.top = 3);
1359
            Push(R.stk[2]);
1360
            Push(R.stk[0]);
1361
            Op2(opCMP, R.stk[1] * 256, R.stk[3]);
1362
            EmitWord(3801H); (* JL L1 *)
1363
            MovRR(R.stk[1], R.stk[3]);
1364
                             (* L1:   *)
1365
            Push(R.stk[3]);
1366
            drop;
1367
            drop;
1368
            drop;
1369
            drop;
1370
            CallRTL(RTL._move, 3)
1371
 
1372
        |IL.opCOPY:
1373
            PushAll(2);
1374
            PushImm(param2);
1375
            CallRTL(RTL._move, 3)
1376
 
1377
        |IL.opMOVE:
1378
            PushAll(3);
1379
            CallRTL(RTL._move, 3)
1380
 
1381
        |IL.opCOPYA:
1382
            PushAll(4);
1383
            PushImm(param2);
1384
            CallRTL(RTL._arrcpy, 5);
1385
            GetRegA
1386
 
1387
        |IL.opROT:
1388
            PushAll(0);
1389
            MovRR(SP, ACC);
1390
            Push(ACC);
1391
            PushImm(param2);
1392
            CallRTL(RTL._rot, 2)
1393
 
1394
        |IL.opSAVES:
1395
            UnOp(reg1);
1396
            PushAll_1;
1397
            Op1(opPUSH, PC, sINCR);
8859 leency 1398
            IncStk;
7983 leency 1399
            EmitWord(param2);
1400
            Reloc(RDATA);
1401
            Push(reg1);
1402
            drop;
1403
            PushImm(param1);
1404
            CallRTL(RTL._move, 3)
1405
 
1406
        |IL.opCASET:
1407
            Push(R5);
1408
            Push(R5);
1409
            PushImm(param2);
1410
            CallRTL(RTL._guardrec, 2);
1411
            Pop(R5);
1412
            Test(ACC);
1413
            jcc(jne, param1)
1414
 
1415
        |IL.opCHR:
1416
            UnOp(reg1);
1417
            Op2(opAND, imm(255), reg1)
1418
 
1419
        |IL.opABS:
1420
            UnOp(reg1);
1421
            Test(reg1);
1422
            L := NewLabel();
1423
            jcc(jge, L);
1424
            Neg(reg1);
1425
            EmitLabel(L)
1426
 
1427
        |IL.opEQB, IL.opNEB:
1428
            BinOp(reg1, reg2);
1429
            drop;
1430
 
1431
            Test(reg1);
1432
            L := NewLabel();
1433
            jcc(je, L);
1434
            Op2(opMOV, imm(1), reg1);
1435
            EmitLabel(L);
1436
 
1437
            Test(reg2);
1438
            L := NewLabel();
1439
            jcc(je, L);
1440
            Op2(opMOV, imm(1), reg2);
1441
            EmitLabel(L);
1442
 
1443
            Op2(opCMP, reg2 * 256, reg1);
1444
            IF opcode = IL.opEQB THEN
1445
                setcc(je, reg1)
1446
            ELSE
1447
                setcc(jne, reg1)
1448
            END
1449
 
1450
        |IL.opSAVEP:
1451
            UnOp(reg1);
1452
            Op2(opMOV, incr(PC), reg1 + dIDX);
1453
            EmitWord(param2);
1454
            Reloc(RCODE);
1455
            EmitWord(0);
1456
            drop
1457
 
1458
        |IL.opPUSHP:
1459
            Op2(opMOV, incr(PC), GetAnyReg());
1460
            EmitWord(param2);
1461
            Reloc(RCODE)
1462
 
1463
        |IL.opEQP, IL.opNEP:
1464
            UnOp(reg1);
1465
            Op2(opCMP, incr(PC), reg1);
1466
            EmitWord(param1);
1467
            Reloc(RCODE);
1468
            drop;
1469
            reg1 := GetAnyReg();
1470
 
1471
            IF opcode = IL.opEQP THEN
1472
                setcc(je, reg1)
1473
            ELSIF opcode = IL.opNEP THEN
1474
                setcc(jne, reg1)
1475
            END
1476
 
1477
        |IL.opVADR_PARAM:
1478
            reg1 := GetAnyReg();
1479
            Op2(opMOV, LocalSrc(param2), reg1);
1480
            Push(reg1);
1481
            drop
1482
 
1483
        |IL.opNEW:
1484
            PushAll(1);
1485
            n := param2 + 2;
1486
            ASSERT(UTILS.Align(n, 2));
1487
            PushImm(n);
1488
            PushImm(param1);
1489
            CallRTL(RTL._new, 3)
1490
 
1491
        |IL.opRSET:
1492
            PushAll(2);
1493
            CallRTL(RTL._set, 2);
1494
            GetRegA
1495
 
1496
        |IL.opRSETR:
1497
            PushAll(1);
1498
            PushImm(param2);
1499
            CallRTL(RTL._set, 2);
1500
            GetRegA
1501
 
1502
        |IL.opRSETL:
1503
            UnOp(reg1);
1504
            PushAll_1;
1505
            PushImm(param2);
1506
            Push(reg1);
1507
            drop;
1508
            CallRTL(RTL._set, 2);
1509
            GetRegA
1510
 
1511
        |IL.opRSET1:
1512
            PushAll(1);
1513
            CallRTL(RTL._set1, 1);
1514
            GetRegA
1515
 
1516
        |IL.opINCLC:
1517
            UnOp(reg1);
1518
            Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1));
1519
            drop
1520
 
1521
        |IL.opEXCLC:
1522
            UnOp(reg1);
1523
            Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1));
1524
            drop
1525
 
1526
        |IL.opIN:
1527
            PushAll(2);
1528
            CallRTL(RTL._in, 2);
1529
            GetRegA
1530
 
1531
        |IL.opINR:
1532
            PushAll(1);
1533
            PushImm(param2);
1534
            CallRTL(RTL._in, 2);
1535
            GetRegA
1536
 
1537
        |IL.opINL:
1538
            PushAll(1);
1539
            PushImm(param2);
1540
            CallRTL(RTL._in2, 2);
1541
            GetRegA
1542
 
1543
        |IL.opINCL:
1544
            PushAll(2);
1545
            CallRTL(RTL._incl, 2)
1546
 
1547
        |IL.opEXCL:
1548
            PushAll(2);
1549
            CallRTL(RTL._excl, 2)
1550
 
1551
        |IL.opLADR_INCL, IL.opLADR_EXCL:
1552
            PushAll(1);
1553
            MovRR(SP, ACC);
1554
            n := LocalOffset(param2);
1555
            IF n # 0 THEN
1556
                Op2(opADD, imm(n), ACC)
1557
            END;
1558
            Push(ACC);
1559
            IF opcode = IL.opLADR_INCL THEN
1560
                CallRTL(RTL._incl, 2)
1561
            ELSIF opcode = IL.opLADR_EXCL THEN
1562
                CallRTL(RTL._excl, 2)
1563
            END
1564
 
1565
        |IL.opLADR_INCLC:
1566
            Op2(opBIS, imm(ORD({param2})), LocalDst(param1))
1567
 
1568
        |IL.opLADR_EXCLC:
1569
            Op2(opBIC, imm(ORD({param2})), LocalDst(param1))
1570
 
1571
        END;
1572
 
1573
        cmd := cmd.next(COMMAND)
1574
    END;
1575
 
1576
    ASSERT(R.pushed = 0);
1577
    ASSERT(R.top = -1)
1578
END translate;
1579
 
1580
 
8859 leency 1581
PROCEDURE prolog;
7983 leency 1582
VAR
1583
    i: INTEGER;
1584
 
1585
BEGIN
8859 leency 1586
    RTL.Init(EmitLabel, EmitWord, EmitCall);
7983 leency 1587
    FOR i := 0 TO LEN(RTL.rtl) - 1 DO
1588
        RTL.Set(i, NewLabel())
1589
    END;
1590
 
1591
    IV[LEN(IV) - 1] := NewLabel();
1592
    EmitLabel(IV[LEN(IV) - 1]);
1593
    Op2(opMOV, incr(PC), SP);
1594
    EmitWord(0);
1595
    Op2(opMOV, incr(PC), HP);
1596
    EmitWord(0);
1597
    Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *)
8859 leency 1598
    Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP));
1599
    Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP));
7983 leency 1600
END prolog;
1601
 
1602
 
1603
PROCEDURE epilog;
1604
VAR
8859 leency 1605
    L1, i, n: INTEGER;
7983 leency 1606
 
1607
BEGIN
1608
    Op2(opBIS, imm(10H), SR); (* CPUOFF *)
1609
 
1610
    L1 := NewLabel();
1611
    FOR i := 0 TO LEN(IV) - 2 DO
1612
        IV[i] := NewLabel();
1613
        EmitLabel(IV[i]);
1614
        PushImm(i);
1615
        IF i # LEN(IV) - 2 THEN
1616
            EmitJmp(opJMP, L1)
1617
        END
1618
    END;
1619
 
1620
    EmitLabel(L1);
1621
 
8859 leency 1622
    n := 0;
7983 leency 1623
    FOR i := 0 TO 15 DO
8859 leency 1624
        IF i IN R.regs THEN
1625
            Push(i);
1626
            INC(n)
7983 leency 1627
        END
1628
    END;
1629
 
8859 leency 1630
    MovRR(SP, R4);
1631
    Op2(opADD, imm(n * 2), R4);
1632
 
1633
    Push(R4);
1634
    Op1(opPUSH, R4, sINDIR);
1635
    Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *)
7983 leency 1636
    Op2(opADD, imm(4), SP);
1637
 
1638
    FOR i := 15 TO 0 BY -1 DO
8859 leency 1639
        IF i IN R.regs THEN
7983 leency 1640
            Pop(i)
1641
        END
1642
    END;
1643
 
1644
    Op2(opADD, imm(2), SP);
1645
    Op1(opRETI, 0, 0);
1646
 
1647
    RTL.Gen
1648
END epilog;
1649
 
1650
 
1651
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
1652
VAR
8097 maxcodehac 1653
    i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER;
7983 leency 1654
 
8859 leency 1655
    Code, Data, Bss: RECORD address, size: INTEGER END;
7983 leency 1656
 
1657
    ram, rom: INTEGER;
1658
 
1659
    reloc: RELOC;
1660
 
1661
BEGIN
1662
    IdxWords.src := NOWORD;
1663
    IdxWords.dst := NOWORD;
1664
 
1665
    ram := options.ram;
1666
    rom := options.rom;
1667
 
1668
    IF ODD(ram) THEN DEC(ram) END;
1669
    IF ODD(rom) THEN DEC(rom) END;
1670
 
1671
    ram := MIN(MAX(ram, minRAM), maxRAM);
1672
    rom := MIN(MAX(rom, minROM), maxROM);
1673
 
8859 leency 1674
    IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN
7983 leency 1675
        ERRORS.Error(204)
1676
    END;
1677
 
1678
    Labels := CHL.CreateIntList();
1679
    FOR i := 1 TO IL.codes.lcount DO
1680
        CHL.PushInt(Labels, 0)
1681
    END;
1682
 
1683
    CodeList := LISTS.create(NIL);
1684
    RelList  := LISTS.create(NIL);
8859 leency 1685
    REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7});
7983 leency 1686
 
8859 leency 1687
    prolog;
1688
    translate(chkSTK IN options.checking);
7983 leency 1689
    epilog;
1690
 
8859 leency 1691
    TypesSize := CHL.Length(IL.codes.types) * 2;
1692
    Data.size := CHL.Length(IL.codes.data);
1693
    IF ODD(Data.size) THEN
1694
        CHL.PushByte(IL.codes.data, 0);
1695
        INC(Data.size)
1696
    END;
1697
    Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size);
1698
    Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size);
1699
    IF Code.address < 10000H - rom THEN
1700
        ERRORS.Error(203)
1701
    END;
1702
    Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size);
7983 leency 1703
    Data.address := Code.address + Code.size;
8859 leency 1704
    TextSize := Code.size + Data.size;
7983 leency 1705
 
8859 leency 1706
    IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN
7983 leency 1707
        ERRORS.Error(203)
1708
    END;
1709
 
8859 leency 1710
    stack := RTL.ram + ram;
7983 leency 1711
    Bss.size := IL.codes.bss + IL.codes.bss MOD 2;
8859 leency 1712
    DEC(stack, Bss.size);
1713
    Bss.address := stack;
1714
    DEC(stack, RTL.VarSize);
1715
    heap := RTL.ram;
1716
    ASSERT(stack - heap >= StkReserve);
7983 leency 1717
    adr := Code.address + 2;
1718
    PutWord(stack, adr);
1719
    adr := Code.address + 6;
1720
    PutWord(heap, adr);
1721
 
1722
    reloc := RelList.first(RELOC);
1723
    WHILE reloc # NIL DO
1724
        adr := reloc.WordPtr.offset * 2;
8097 maxcodehac 1725
        val := reloc.WordPtr.val;
7983 leency 1726
        CASE reloc.section OF
8097 maxcodehac 1727
        |RCODE: PutWord(LabelOffs(val) * 2, adr)
1728
        |RDATA: PutWord(val + Data.address, adr)
8859 leency 1729
        |RBSS:  PutWord((val + Bss.address) MOD 65536, adr)
7983 leency 1730
        END;
1731
        reloc := reloc.next(RELOC)
1732
    END;
1733
 
1734
    adr := Data.address;
1735
 
8859 leency 1736
    FOR i := 0 TO Data.size - 1 DO
7983 leency 1737
        mem[adr] := CHL.GetByte(IL.codes.data, i);
1738
        INC(adr)
1739
    END;
1740
 
1741
    FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO
1742
        PutWord(CHL.GetInt(IL.codes.types, i), adr)
1743
    END;
1744
 
1745
    FOR i := 0 TO 15 DO
1746
        PutWord((33 - i) * i, adr);
1747
    END;
1748
 
1749
    FOR n := 0 TO 15 DO
1750
        bits := ORD({0 .. n});
1751
        FOR i := 0 TO 15 - n DO
1752
            PutWord(bits, adr);
1753
            bits := LSL(bits, 1)
1754
        END
1755
    END;
1756
 
1757
    PutWord(4130H, adr); (* RET *)
1758
    PutWord(stack, adr);
1759
    PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *)
1760
 
1761
    FOR i := 0 TO LEN(IV) - 1 DO
1762
        PutWord(LabelOffs(IV[i]) * 2, adr)
1763
    END;
1764
 
8859 leency 1765
    INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16);
1766
    INC(Bss.size, StkReserve + RTL.VarSize);
1767
 
8097 maxcodehac 1768
    WR.Create(outname);
8859 leency 1769
    HEX.Data(mem, Code.address - Code.address MOD 16, TextSize);
8097 maxcodehac 1770
    HEX.End;
1771
    WR.Close;
7983 leency 1772
 
8859 leency 1773
    C.Dashes;
1774
    C.String("  rom:  "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String("  ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)");
7983 leency 1775
    C.Ln;
8859 leency 1776
    C.String("  ram:  "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String("  ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)")
7983 leency 1777
END CodeGen;
1778
 
1779
 
1780
END MSP430.