Subversion Repositories Kolibri OS

Rev

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