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 THUMB;
9
 
10
IMPORT PROG, LISTS, CHL := CHUNKLISTS, BIN, REG, IL, C := CONSOLE,
11
       UTILS, WR := WRITER, HEX, ERRORS, TARGETS;
12
 
13
 
14
CONST
15
 
16
    R0 = 0; R1 = 1; R2 = 2; R3 = 3; R4 = 4;
17
 
18
    SP = 13; LR = 14; PC = 15;
19
 
20
    ACC = R0;
21
 
22
    je = 0; jne = 1; jnb = 2; jb = 3; jge = 10; jl = 11; jg = 12; jle = 13;
23
 
24
    inf = 7F800000H;
25
 
8859 leency 26
    minROM* = 16; maxROM* = 65536;
27
    minRAM* = 4;  maxRAM* = 65536;
7983 leency 28
 
29
    maxIVT* = 1023;
30
 
8859 leency 31
    _THUMB2 = 0; _IT = 1; _SDIV = 2; _CBXZ = 3;
7983 leency 32
 
8859 leency 33
    CortexM0  = {};
34
    CortexM1  = {};
35
    CortexM3  = {_THUMB2, _IT, _SDIV, _CBXZ};
36
    CortexM23 = {_SDIV, _CBXZ};
37
 
38
 
7983 leency 39
TYPE
40
 
41
    COMMAND = IL.COMMAND;
42
 
43
    ANYCODE = POINTER TO RECORD (LISTS.ITEM)
44
 
45
        offset: INTEGER
46
 
47
    END;
48
 
49
    CODE = POINTER TO RECORD (ANYCODE)
50
 
51
        code: INTEGER
52
 
53
    END;
54
 
55
    LABEL = POINTER TO RECORD (ANYCODE)
56
 
57
        label: INTEGER
58
 
59
    END;
60
 
61
    JUMP = POINTER TO RECORD (ANYCODE)
62
 
63
        label, diff, len, cond: INTEGER;
64
        short: BOOLEAN
65
 
66
    END;
67
 
68
    JMP = POINTER TO RECORD (JUMP)
69
 
70
    END;
71
 
72
    JCC = POINTER TO RECORD (JUMP)
73
 
74
    END;
75
 
76
    CBXZ = POINTER TO RECORD (JUMP)
77
 
78
        reg: INTEGER
79
 
80
    END;
81
 
82
    CALL = POINTER TO RECORD (JUMP)
83
 
84
    END;
85
 
86
    RELOC = POINTER TO RECORD (ANYCODE)
87
 
88
        reg, rel, value: INTEGER
89
 
90
    END;
91
 
92
    RELOCCODE = ARRAY 7 OF INTEGER;
93
 
94
 
95
VAR
96
 
97
    R: REG.REGS;
98
 
99
    tcount: INTEGER;
100
 
101
    CodeList: LISTS.LIST;
102
 
103
    program: BIN.PROGRAM;
104
 
105
    StkCount: INTEGER;
106
 
107
    Target: RECORD
108
        FlashAdr,
109
        SRAMAdr,
110
        IVTLen,
111
        MinStack,
112
        Reserved: INTEGER;
8859 leency 113
        InstrSet: SET;
114
        isNXP: BOOLEAN
7983 leency 115
    END;
116
 
117
    IVT: ARRAY maxIVT + 1 OF INTEGER;
118
 
119
    sdivProc, trap, genTrap, entry, emptyProc, int0, genInt: INTEGER;
120
 
121
 
122
PROCEDURE Code (code: INTEGER);
123
VAR
124
    c: CODE;
125
 
126
BEGIN
127
    NEW(c);
128
    c.code := code;
129
    LISTS.push(CodeList, c)
130
END Code;
131
 
132
 
133
PROCEDURE Label (label: INTEGER);
134
VAR
135
    L: LABEL;
136
 
137
BEGIN
138
    NEW(L);
139
    L.label := label;
140
    LISTS.push(CodeList, L)
141
END Label;
142
 
143
 
144
PROCEDURE jcc (cond, label: INTEGER);
145
VAR
146
    j: JCC;
147
 
148
BEGIN
149
    NEW(j);
150
    j.label := label;
151
    j.cond  := cond;
152
    j.short := FALSE;
153
    j.len   := 3;
154
    LISTS.push(CodeList, j)
155
END jcc;
156
 
157
 
158
PROCEDURE cbxz (cond, reg, label: INTEGER);
159
VAR
160
    j: CBXZ;
161
 
162
BEGIN
163
    NEW(j);
164
    j.label := label;
165
    j.cond  := cond;
166
    j.reg   := reg;
167
    j.short := FALSE;
168
    j.len   := 4;
169
    LISTS.push(CodeList, j)
170
END cbxz;
171
 
172
 
173
PROCEDURE jmp (label: INTEGER);
174
VAR
175
    j: JMP;
176
 
177
BEGIN
178
    NEW(j);
179
    j.label := label;
180
    j.short := FALSE;
181
    j.len   := 2;
182
    LISTS.push(CodeList, j)
183
END jmp;
184
 
185
 
186
PROCEDURE call (label: INTEGER);
187
VAR
188
    c: CALL;
189
 
190
BEGIN
191
    NEW(c);
192
    c.label := label;
193
    c.short := FALSE;
194
    c.len   := 2;
195
    LISTS.push(CodeList, c)
196
END call;
197
 
198
 
199
PROCEDURE reloc (reg, rel, value: INTEGER);
200
VAR
201
    r: RELOC;
202
 
203
BEGIN
204
    NEW(r);
205
    r.reg := reg;
206
    r.rel := rel;
207
    r.value := value;
208
    LISTS.push(CodeList, r)
209
END reloc;
210
 
211
 
212
PROCEDURE NewLabel (): INTEGER;
213
BEGIN
214
    BIN.NewLabel(program)
215
    RETURN IL.NewLabel()
216
END NewLabel;
217
 
218
 
219
PROCEDURE range (x, n: INTEGER): BOOLEAN;
220
    RETURN (0 <= x) & (x < LSL(1, n))
221
END range;
222
 
223
 
224
PROCEDURE srange (x, n: INTEGER): BOOLEAN;
225
    RETURN (-LSL(1, n - 1) <= x) & (x < LSL(1, n - 1))
226
END srange;
227
 
228
 
229
PROCEDURE gen1 (op, imm, rs, rd: INTEGER);
230
BEGIN
231
    ASSERT(op IN {0..2});
232
    ASSERT(range(imm, 5));
233
    ASSERT(range(rs, 3));
234
    ASSERT(range(rd, 3));
235
    Code(LSL(op, 11) + LSL(imm, 6) + LSL(rs, 3) + rd)
236
END gen1;
237
 
238
 
239
PROCEDURE gen2 (i, op: BOOLEAN; imm, rs, rd: INTEGER);
240
BEGIN
241
    ASSERT(range(imm, 3));
242
    ASSERT(range(rs, 3));
243
    ASSERT(range(rd, 3));
244
    Code(1800H + LSL(ORD(i), 10) + LSL(ORD(op), 9) + LSL(imm, 6) + LSL(rs, 3) + rd)
245
END gen2;
246
 
247
 
248
PROCEDURE gen3 (op, rd, imm: INTEGER);
249
BEGIN
250
    ASSERT(range(op, 2));
251
    ASSERT(range(rd, 3));
252
    ASSERT(range(imm, 8));
253
    Code(2000H + LSL(op, 11) + LSL(rd, 8) + imm)
254
END gen3;
255
 
256
 
257
PROCEDURE gen4 (op, rs, rd: INTEGER);
258
BEGIN
259
    ASSERT(range(op, 4));
260
    ASSERT(range(rs, 3));
261
    ASSERT(range(rd, 3));
262
    Code(4000H + LSL(op, 6) + LSL(rs, 3) + rd)
263
END gen4;
264
 
265
 
266
PROCEDURE gen5 (op: INTEGER; h1, h2: BOOLEAN; rs, rd: INTEGER);
267
BEGIN
268
    ASSERT(range(op, 2));
269
    ASSERT(range(rs, 3));
270
    ASSERT(range(rd, 3));
271
    Code(4400H + LSL(op, 8) + LSL(ORD(h1), 7) + LSL(ORD(h2), 6) + LSL(rs, 3) + rd)
272
END gen5;
273
 
274
 
275
PROCEDURE gen7 (l, b: BOOLEAN; ro, rb, rd: INTEGER);
276
BEGIN
277
    ASSERT(range(ro, 3));
278
    ASSERT(range(rb, 3));
279
    ASSERT(range(rd, 3));
280
    Code(5000H + LSL(ORD(l), 11) + LSL(ORD(b), 10) + LSL(ro, 6) + LSL(rb, 3) + rd)
281
END gen7;
282
 
283
 
284
PROCEDURE gen8 (h, s: BOOLEAN; ro, rb, rd: INTEGER);
285
BEGIN
286
    ASSERT(range(ro, 3));
287
    ASSERT(range(rb, 3));
288
    ASSERT(range(rd, 3));
289
    Code(5200H + LSL(ORD(h), 11) + LSL(ORD(s), 10) + LSL(ro, 6) + LSL(rb, 3) + rd)
290
END gen8;
291
 
292
 
293
PROCEDURE gen9 (b, l: BOOLEAN; imm, rb, rd: INTEGER);
294
BEGIN
295
    ASSERT(range(imm, 5));
296
    ASSERT(range(rb, 3));
297
    ASSERT(range(rd, 3));
298
    Code(6000H + LSL(ORD(b), 12) + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd)
299
END gen9;
300
 
301
 
302
PROCEDURE gen10 (l: BOOLEAN; imm, rb, rd: INTEGER);
303
BEGIN
304
    ASSERT(range(imm, 5));
305
    ASSERT(range(rb, 3));
306
    ASSERT(range(rd, 3));
307
    Code(8000H + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd)
308
END gen10;
309
 
310
 
311
PROCEDURE gen11 (l: BOOLEAN; rd, imm: INTEGER);
312
BEGIN
313
    ASSERT(range(rd, 3));
314
    ASSERT(range(imm, 8));
315
    Code(9000H + LSL(ORD(l), 11) + LSL(rd, 8) + imm)
316
END gen11;
317
 
318
 
319
PROCEDURE gen12 (sp: BOOLEAN; rd, imm: INTEGER);
320
BEGIN
321
    ASSERT(range(rd, 3));
322
    ASSERT(range(imm, 8));
323
    Code(0A000H + LSL(ORD(sp), 11) + LSL(rd, 8) + imm)
324
END gen12;
325
 
326
 
327
PROCEDURE gen14 (l, r: BOOLEAN; rlist: SET);
328
VAR
329
    i, n: INTEGER;
330
 
331
BEGIN
332
    ASSERT(range(ORD(rlist), 8));
333
 
334
    n := ORD(r);
335
    FOR i := 0 TO 7 DO
336
        IF i IN rlist THEN
337
            INC(n)
338
        END
339
    END;
340
 
341
    IF l THEN
342
        n := -n
343
    END;
344
 
345
    INC(StkCount, n);
346
 
347
    Code(0B400H + LSL(ORD(l), 11) + LSL(ORD(r), 8) + ORD(rlist))
348
END gen14;
349
 
350
 
351
PROCEDURE split16 (imm16: INTEGER; VAR imm4, imm1, imm3, imm8: INTEGER);
352
BEGIN
353
    ASSERT(range(imm16, 16));
354
    imm8 := imm16 MOD 256;
355
    imm4 := LSR(imm16, 12);
356
    imm3 := LSR(imm16, 8) MOD 8;
357
    imm1 := LSR(imm16, 11) MOD 2;
358
END split16;
359
 
360
 
361
PROCEDURE LslImm (r, imm5: INTEGER);
362
BEGIN
363
    gen1(0, imm5, r, r)
364
END LslImm;
365
 
366
 
367
PROCEDURE LsrImm (r, imm5: INTEGER);
368
BEGIN
369
    gen1(1, imm5, r, r)
370
END LsrImm;
371
 
372
 
373
PROCEDURE AsrImm (r, imm5: INTEGER);
374
BEGIN
375
    gen1(2, imm5, r, r)
376
END AsrImm;
377
 
378
 
379
PROCEDURE AddReg (rd, rs, rn: INTEGER);
380
BEGIN
381
    gen2(FALSE, FALSE, rn, rs, rd)
382
END AddReg;
383
 
384
 
385
PROCEDURE SubReg (rd, rs, rn: INTEGER);
386
BEGIN
387
    gen2(FALSE, TRUE, rn, rs, rd)
388
END SubReg;
389
 
390
 
391
PROCEDURE AddImm8 (rd, imm8: INTEGER);
392
BEGIN
393
    IF imm8 # 0 THEN
394
        gen3(2, rd, imm8)
395
    END
396
END AddImm8;
397
 
398
 
399
PROCEDURE SubImm8 (rd, imm8: INTEGER);
400
BEGIN
401
    IF imm8 # 0 THEN
402
        gen3(3, rd, imm8)
403
    END
404
END SubImm8;
405
 
406
 
407
PROCEDURE AddSubImm12 (r, imm12: INTEGER; sub: BOOLEAN);
408
VAR
409
    imm4, imm1, imm3, imm8: INTEGER;
410
 
411
BEGIN
412
    split16(imm12, imm4, imm1, imm3, imm8);
413
    Code(0F200H + LSL(imm1, 10) + r + 0A0H * ORD(sub));  (* addw/subw r, r, imm12 *)
414
    Code(LSL(imm3, 12) + LSL(r, 8) + imm8)
415
END AddSubImm12;
416
 
417
 
418
PROCEDURE MovImm8 (rd, imm8: INTEGER);
419
BEGIN
420
    gen3(0, rd, imm8)
421
END MovImm8;
422
 
423
 
424
PROCEDURE CmpImm8 (rd, imm8: INTEGER);
425
BEGIN
426
    gen3(1, rd, imm8)
427
END CmpImm8;
428
 
429
 
430
PROCEDURE Neg (r: INTEGER);
431
BEGIN
432
    gen4(9, r, r)
433
END Neg;
434
 
435
 
436
PROCEDURE Mul (rd, rs: INTEGER);
437
BEGIN
438
    gen4(13, rs, rd)
439
END Mul;
440
 
441
 
442
PROCEDURE Str32 (rs, rb: INTEGER);
443
BEGIN
444
    gen9(FALSE, FALSE, 0, rb, rs)
445
END Str32;
446
 
447
 
448
PROCEDURE Ldr32 (rd, rb: INTEGER);
449
BEGIN
450
    gen9(FALSE, TRUE, 0, rb, rd)
451
END Ldr32;
452
 
453
 
454
PROCEDURE Str16 (rs, rb: INTEGER);
455
BEGIN
456
    gen10(FALSE, 0, rb, rs)
457
END Str16;
458
 
459
 
460
PROCEDURE Ldr16 (rd, rb: INTEGER);
461
BEGIN
462
    gen10(TRUE, 0, rb, rd)
463
END Ldr16;
464
 
465
 
466
PROCEDURE Str8 (rs, rb: INTEGER);
467
BEGIN
468
    gen9(TRUE, FALSE, 0, rb, rs)
469
END Str8;
470
 
471
 
472
PROCEDURE Ldr8 (rd, rb: INTEGER);
473
BEGIN
474
    gen9(TRUE, TRUE, 0, rb, rd)
475
END Ldr8;
476
 
477
 
478
PROCEDURE Cmp (r1, r2: INTEGER);
479
BEGIN
480
    gen4(10, r2, r1)
481
END Cmp;
482
 
483
 
484
PROCEDURE Tst (r: INTEGER);
485
BEGIN
8859 leency 486
    gen3(1, r, 0) (* cmp r, 0 *)
7983 leency 487
END Tst;
488
 
489
 
490
PROCEDURE LdrSp (r, offset: INTEGER);
491
BEGIN
492
    gen11(TRUE, r, offset)
493
END LdrSp;
494
 
495
 
496
PROCEDURE MovImm32 (r, imm32: INTEGER);
497
BEGIN
498
    MovImm8(r, LSR(imm32, 24) MOD 256);
499
    LslImm(r, 8);
500
    AddImm8(r, LSR(imm32, 16) MOD 256);
501
    LslImm(r, 8);
502
    AddImm8(r, LSR(imm32, 8) MOD 256);
503
    LslImm(r, 8);
504
    AddImm8(r, imm32 MOD 256)
505
END MovImm32;
506
 
507
 
508
PROCEDURE low (x: INTEGER): INTEGER;
509
    RETURN x MOD 65536
510
END low;
511
 
512
 
513
PROCEDURE high (x: INTEGER): INTEGER;
514
    RETURN (x DIV 65536) MOD 65536
515
END high;
516
 
517
 
518
PROCEDURE movwt (r, imm16, t: INTEGER);
519
VAR
520
    imm1, imm3, imm4, imm8: INTEGER;
521
 
522
BEGIN
523
    ASSERT(range(r, 3));
524
    ASSERT(range(imm16, 16));
525
    ASSERT(range(t, 1));
526
    split16(imm16, imm4, imm1, imm3, imm8);
527
    Code(0F240H + imm1 * 1024 + t * 128 + imm4);
528
    Code(imm3 * 4096 + r * 256 + imm8);
529
END movwt;
530
 
531
 
532
PROCEDURE inv0 (cond: INTEGER): INTEGER;
533
    RETURN ORD(BITS(cond) / {0})
534
END inv0;
535
 
536
 
537
PROCEDURE fixup (CodeAdr, DataAdr, BssAdr: INTEGER);
538
VAR
539
    code:    ANYCODE;
540
    count:   INTEGER;
541
    shorted: BOOLEAN;
542
    jump:    JUMP;
543
 
544
    reloc, i, diff, len: INTEGER;
545
 
546
    RelocCode: RELOCCODE;
547
 
548
 
549
    PROCEDURE genjcc (cond, offset: INTEGER): INTEGER;
550
    BEGIN
551
        ASSERT(range(cond, 4));
552
        ASSERT(srange(offset, 8))
553
        RETURN 0D000H + cond * 256 + offset MOD 256
554
    END genjcc;
555
 
556
 
557
    PROCEDURE genjmp (offset: INTEGER): INTEGER;
558
    BEGIN
559
        ASSERT(srange(offset, 11))
560
        RETURN 0E000H + offset MOD 2048
561
    END genjmp;
562
 
563
 
564
    PROCEDURE movwt (r, imm16, t: INTEGER; VAR code: RELOCCODE);
565
    VAR
566
        imm1, imm3, imm4, imm8: INTEGER;
567
 
568
    BEGIN
569
        split16(imm16, imm4, imm1, imm3, imm8);
570
        code[t * 2]     := 0F240H + imm1 * 1024 + t * 128 + imm4;
571
        code[t * 2 + 1] := imm3 * 4096 + r * 256 + imm8
572
    END movwt;
573
 
574
 
575
    PROCEDURE genmovimm32 (r, value: INTEGER; VAR code: RELOCCODE);
576
    BEGIN
8859 leency 577
        IF _THUMB2 IN Target.InstrSet THEN
7983 leency 578
            movwt(r, low(value), 0, code);
579
            movwt(r, high(value), 1, code)
580
        ELSE
8859 leency 581
            code[0] := 2000H + r * 256 + UTILS.Byte(value, 3);  (* movs r, imm8 *)
582
            code[1] := 0200H + r * 9;                           (* lsls r, 8    *)
583
            code[2] := 3000H + r * 256 + UTILS.Byte(value, 2);  (* adds r, imm8 *)
584
            code[3] := code[1];                                 (* lsls r, 8    *)
585
            code[4] := 3000H + r * 256 + UTILS.Byte(value, 1);  (* adds r, imm8 *)
586
            code[5] := code[1];                                 (* lsls r, 8    *)
587
            code[6] := 3000H + r * 256 + UTILS.Byte(value, 0)   (* adds r, imm8 *)
7983 leency 588
        END
589
    END genmovimm32;
590
 
591
 
592
    PROCEDURE PutCode (code: INTEGER);
593
    BEGIN
594
        BIN.PutCode16LE(program, code)
595
    END PutCode;
596
 
597
 
8859 leency 598
    PROCEDURE genlongjmp (offset: INTEGER);
599
    BEGIN
600
        ASSERT(srange(offset, 22));
601
        PutCode(0F000H + ASR(offset, 11) MOD 2048);
602
        PutCode(0F800H + offset MOD 2048)
603
    END genlongjmp;
604
 
605
 
7983 leency 606
    PROCEDURE genbc (code: JUMP);
607
    BEGIN
608
        CASE code.len OF
609
        |1: PutCode(genjcc(code.cond, code.diff))
610
        |2: PutCode(genjcc(inv0(code.cond), 0));
611
            PutCode(genjmp(code.diff))
612
        |3: PutCode(genjcc(inv0(code.cond), 1));
8859 leency 613
            genlongjmp(code.diff)
7983 leency 614
        END
615
    END genbc;
616
 
617
 
618
    PROCEDURE SetIV (idx, label, CodeAdr: INTEGER);
619
    VAR
8097 maxcodehac 620
        l, h: LISTS.ITEM;
7983 leency 621
 
622
    BEGIN
8097 maxcodehac 623
        l := CodeList.first;
624
        h := l.next;
7983 leency 625
        WHILE idx > 0 DO
8097 maxcodehac 626
            l := h.next;
627
            h := l.next;
7983 leency 628
            DEC(idx)
629
        END;
630
        label := BIN.GetLabel(program, label) * 2 + CodeAdr + 1;
631
        l(CODE).code := low(label);
632
        h(CODE).code := high(label)
633
    END SetIV;
634
 
635
 
636
BEGIN
637
 
638
    REPEAT
639
 
640
        shorted := FALSE;
641
        count := 0;
642
 
643
        code := CodeList.first(ANYCODE);
644
        WHILE code # NIL DO
645
            code.offset := count;
646
 
647
            CASE code OF
648
            |CODE:  INC(count)
649
            |LABEL: BIN.SetLabel(program, code.label, count)
650
            |JUMP:  INC(count, code.len); code.offset := count + ORD(code.short)
8859 leency 651
            |RELOC: INC(count, 7 - ORD(_THUMB2 IN Target.InstrSet) * 3 + code.rel MOD 2)
7983 leency 652
            END;
653
 
654
            code := code.next(ANYCODE)
655
        END;
656
 
657
        code := CodeList.first(ANYCODE);
658
        WHILE code # NIL DO
659
 
660
            IF code IS JUMP THEN
661
                jump := code(JUMP);
662
                jump.diff := BIN.GetLabel(program, jump.label) - jump.offset;
663
                len := jump.len;
664
                diff := jump.diff;
665
                CASE jump OF
666
                |JMP:
667
                    IF (len = 2) & srange(diff, 11) THEN
668
                        len := 1
669
                    END
670
 
671
                |JCC:
672
                    CASE len OF
673
                    |1:
674
                    |2: IF srange(diff, 8) THEN DEC(len) END
675
                    |3: IF srange(diff, 11) THEN DEC(len) END
676
                    END
677
 
678
                |CBXZ:
679
                    CASE len OF
680
                    |1:
681
                    |2: IF range(diff, 6) THEN DEC(len) END
682
                    |3: IF srange(diff, 8) THEN DEC(len) END
683
                    |4: IF srange(diff, 11) THEN DEC(len) END
684
                    END
685
 
686
                |CALL:
687
 
688
                END;
689
                IF len # jump.len THEN
690
                    jump.len := len;
691
                    jump.short := TRUE;
692
                    shorted := TRUE
693
                END
694
            END;
695
 
696
            code := code.next(ANYCODE)
697
        END
698
 
699
    UNTIL ~shorted;
700
 
701
    FOR i := 1 TO Target.IVTLen - 1 DO
702
        SetIV(i, IVT[i], CodeAdr)
703
    END;
704
 
705
    code := CodeList.first(ANYCODE);
706
    WHILE code # NIL DO
707
 
708
        CASE code OF
709
 
710
        |CODE:  BIN.PutCode16LE(program, code.code)
711
 
712
        |LABEL:
713
 
714
        |JMP:
715
                IF code.len = 1 THEN
716
                    PutCode(genjmp(code.diff))
717
                ELSE
8859 leency 718
                    genlongjmp(code.diff)
7983 leency 719
                END
720
 
8097 maxcodehac 721
        |JCC:   genbc(code)
7983 leency 722
 
723
        |CBXZ:
724
                IF code.len > 1 THEN
8859 leency 725
                    PutCode(2800H + code.reg * 256); (* cmp code.reg, 0 *)
7983 leency 726
                    DEC(code.len);
727
                    genbc(code)
728
                ELSE
729
                    (* cb(n)z code.reg, L *)
8859 leency 730
                    PutCode(0B100H + 800H * ORD(code.cond = jne) + 200H * (code.diff DIV 32) + (code.diff MOD 32) * 8 + code.reg)
7983 leency 731
                END
732
 
8859 leency 733
        |CALL:  genlongjmp(code.diff)
7983 leency 734
 
735
        |RELOC:
736
                CASE code.rel OF
737
                |BIN.RCODE, BIN.PICCODE: reloc := BIN.GetLabel(program, code.value) * 2 + CodeAdr
738
                |BIN.RDATA, BIN.PICDATA: reloc := code.value + DataAdr
739
                |BIN.RBSS,  BIN.PICBSS:  reloc := code.value + BssAdr
740
                END;
741
                IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN
8859 leency 742
                    DEC(reloc, CodeAdr + 2 * (code.offset - 3 * ORD(_THUMB2 IN Target.InstrSet) + 9))
7983 leency 743
                END;
744
                genmovimm32(code.reg, reloc, RelocCode);
8859 leency 745
                FOR i := 0 TO 6 - 3 * ORD(_THUMB2 IN Target.InstrSet) DO
7983 leency 746
                    PutCode(RelocCode[i])
747
                END;
748
                IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN
8859 leency 749
                    PutCode(4478H + code.reg) (* add code.reg, pc *)
7983 leency 750
                END
751
        END;
752
 
753
        code := code.next(ANYCODE)
754
    END
755
 
756
END fixup;
757
 
758
 
759
PROCEDURE push (r: INTEGER);
760
BEGIN
761
    gen14(FALSE, FALSE, {r})
762
END push;
763
 
764
 
765
PROCEDURE pop (r: INTEGER);
766
BEGIN
767
    gen14(TRUE, FALSE, {r})
768
END pop;
769
 
770
 
771
PROCEDURE mov (r1, r2: INTEGER);
772
BEGIN
773
    IF (r1 < 8) & (r2 < 8) THEN
774
        gen1(0, 0, r2, r1)
775
    ELSE
776
        gen5(2, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8)
777
    END
778
END mov;
779
 
780
 
781
PROCEDURE xchg (r1, r2: INTEGER);
782
BEGIN
8097 maxcodehac 783
    push(r1);
784
    mov(r1, r2);
785
    pop(r2)
7983 leency 786
END xchg;
787
 
788
 
789
PROCEDURE drop;
790
BEGIN
791
    REG.Drop(R)
792
END drop;
793
 
794
 
795
PROCEDURE GetAnyReg (): INTEGER;
796
    RETURN REG.GetAnyReg(R)
797
END GetAnyReg;
798
 
799
 
800
PROCEDURE UnOp (VAR r: INTEGER);
801
BEGIN
802
    REG.UnOp(R, r)
803
END UnOp;
804
 
805
 
806
PROCEDURE BinOp (VAR r1, r2: INTEGER);
807
BEGIN
808
    REG.BinOp(R, r1, r2)
809
END BinOp;
810
 
811
 
812
PROCEDURE PushAll (NumberOfParameters: INTEGER);
813
BEGIN
814
    REG.PushAll(R);
815
    DEC(R.pushed, NumberOfParameters)
816
END PushAll;
817
 
818
 
819
PROCEDURE cond (op: INTEGER): INTEGER;
820
VAR
821
    res: INTEGER;
822
 
823
BEGIN
824
    CASE op OF
825
    |IL.opGT, IL.opGTC: res := jg
826
    |IL.opGE, IL.opGEC: res := jge
827
    |IL.opLT, IL.opLTC: res := jl
828
    |IL.opLE, IL.opLEC: res := jle
829
    |IL.opEQ, IL.opEQC: res := je
830
    |IL.opNE, IL.opNEC: res := jne
831
    END
832
 
833
    RETURN res
834
END cond;
835
 
836
 
837
PROCEDURE GetRegA;
838
BEGIN
839
    ASSERT(REG.GetReg(R, ACC))
840
END GetRegA;
841
 
842
 
843
PROCEDURE MovConst (r, c: INTEGER);
844
BEGIN
845
    IF (0 <= c) & (c <= 255) THEN
846
        MovImm8(r, c)
847
    ELSIF (-255 <= c) & (c < 0) THEN
848
        MovImm8(r, -c);
849
        Neg(r)
850
    ELSIF UTILS.Log2(c) >= 0 THEN
851
        MovImm8(r, 1);
852
        LslImm(r, UTILS.Log2(c))
853
    ELSIF c = UTILS.min32 THEN
854
        MovImm8(r, 1);
855
        LslImm(r, 31)
856
    ELSE
8859 leency 857
        IF _THUMB2 IN Target.InstrSet THEN
7983 leency 858
            movwt(r, low(c), 0);
859
            IF (c < 0) OR (c > 65535) THEN
860
                movwt(r, high(c), 1)
861
            END
862
        ELSE
863
            MovImm32(r, c)
864
        END
865
    END
866
END MovConst;
867
 
868
 
869
PROCEDURE CmpConst (r, c: INTEGER);
870
VAR
871
    r2: INTEGER;
872
 
873
BEGIN
874
    IF (0 <= c) & (c <= 255) THEN
875
        CmpImm8(r, c)
876
    ELSE
877
        r2 := GetAnyReg();
878
        ASSERT(r2 # r);
879
        MovConst(r2, c);
880
        Cmp(r, r2);
881
        drop
882
    END
883
END CmpConst;
884
 
885
 
886
PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
887
    RETURN offset + StkCount - ORD(offset > 0)
888
END LocalOffset;
889
 
890
 
891
PROCEDURE SetCC (cc, r: INTEGER);
892
VAR
893
    L1, L2: INTEGER;
894
 
895
BEGIN
8859 leency 896
    IF _IT IN Target.InstrSet THEN
7983 leency 897
        Code(0BF00H + cc * 16 + ((cc + 1) MOD 2) * 8 + 4); (* ite cc *)
898
        MovConst(r, 1);
899
        MovConst(r, 0)
900
    ELSE
901
        L1 := NewLabel();
902
        L2 := NewLabel();
903
        jcc(cc, L1);
904
        MovConst(r, 0);
905
        jmp(L2);
906
        Label(L1);
907
        MovConst(r, 1);
908
        Label(L2)
909
    END
910
END SetCC;
911
 
912
 
913
PROCEDURE PushConst (n: INTEGER);
914
VAR
915
    r: INTEGER;
916
 
917
BEGIN
918
    r := GetAnyReg();
919
    MovConst(r, n);
920
    push(r);
921
    drop
922
END PushConst;
923
 
924
 
925
PROCEDURE AddConst (r, n: INTEGER);
926
VAR
927
    r2: INTEGER;
928
 
929
BEGIN
930
    IF n # 0 THEN
931
        IF (-255 <= n) & (n <= 255) THEN
932
            IF n > 0 THEN
933
                AddImm8(r, n)
934
            ELSE
935
                SubImm8(r, -n)
936
            END
8859 leency 937
        ELSIF (_THUMB2 IN Target.InstrSet) & (-4095 <= n) & (n <= 4095) THEN
938
            AddSubImm12(r, ABS(n), n < 0)
7983 leency 939
        ELSE
940
            r2 := GetAnyReg();
941
            ASSERT(r2 # r);
942
            IF n > 0 THEN
943
                MovConst(r2, n);
944
                AddReg(r, r, r2)
945
            ELSE
946
                MovConst(r2, -n);
947
                SubReg(r, r, r2)
948
            END;
949
            drop
950
        END
951
    END
952
END AddConst;
953
 
954
 
955
PROCEDURE AddHH (r1, r2: INTEGER);
956
BEGIN
957
    ASSERT((r1 >= 8) OR (r2 >= 8));
958
    gen5(0, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8)
959
END AddHH;
960
 
961
 
962
PROCEDURE AddSP (n: INTEGER);
963
BEGIN
964
    IF n > 0 THEN
965
        IF n < 127 THEN
8859 leency 966
            Code(0B000H + n) (* add sp, n*4 *)
7983 leency 967
        ELSE
968
            ASSERT(R2 IN R.regs);
969
            MovConst(R2, n * 4);
970
            AddHH(SP, R2)
971
        END;
972
        DEC(StkCount, n)
973
    END
974
END AddSP;
975
 
976
 
8859 leency 977
PROCEDURE cbxz2 (c, r, label: INTEGER);
7983 leency 978
BEGIN
8859 leency 979
    IF _CBXZ IN Target.InstrSet THEN
980
        cbxz(c, r, label)
7983 leency 981
    ELSE
982
        Tst(r);
8859 leency 983
        jcc(c, label)
7983 leency 984
    END
8859 leency 985
END cbxz2;
986
 
987
 
988
PROCEDURE cbz (r, label: INTEGER);
989
BEGIN
990
    cbxz2(je, r, label)
7983 leency 991
END cbz;
992
 
993
 
994
PROCEDURE cbnz (r, label: INTEGER);
995
BEGIN
8859 leency 996
    cbxz2(jne, r, label)
7983 leency 997
END cbnz;
998
 
999
 
1000
PROCEDURE Shift (op, r1, r2: INTEGER);
1001
VAR
1002
    L: INTEGER;
1003
 
1004
BEGIN
1005
    LslImm(r2, 27);
1006
    LsrImm(r2, 27);
1007
    L := NewLabel();
1008
    cbz(r2, L);
1009
    CASE op OF
1010
    |IL.opLSL, IL.opLSL1: gen4(2, r2, r1)
1011
    |IL.opLSR, IL.opLSR1: gen4(3, r2, r1)
1012
    |IL.opASR, IL.opASR1: gen4(4, r2, r1)
1013
    |IL.opROR, IL.opROR1: gen4(7, r2, r1)
1014
    END;
1015
    Label(L)
1016
END Shift;
1017
 
1018
 
1019
PROCEDURE LocAdr (offs: INTEGER);
1020
VAR
1021
    r1, n: INTEGER;
1022
 
1023
BEGIN
1024
    r1 := GetAnyReg();
1025
    n := LocalOffset(offs);
1026
    IF n <= 255 THEN
1027
        gen12(TRUE, r1, n)
1028
    ELSE
1029
        MovConst(r1, n * 4);
1030
        AddHH(r1, SP)
1031
    END
1032
END LocAdr;
1033
 
1034
 
1035
PROCEDURE CallRTL (proc, par: INTEGER);
1036
BEGIN
1037
    call(IL.codes.rtl[proc]);
1038
    AddSP(par)
1039
END CallRTL;
1040
 
1041
 
1042
PROCEDURE divmod;
1043
BEGIN
1044
    call(sdivProc);
1045
    AddSP(2)
1046
END divmod;
1047
 
1048
 
8859 leency 1049
PROCEDURE cpsid_i;
1050
BEGIN
1051
    Code(0B672H)  (*  cpsid i  *)
1052
END cpsid_i;
1053
 
1054
 
1055
PROCEDURE cpsie_i;
1056
BEGIN
1057
    Code(0B662H)  (*  cpsie i  *)
1058
END cpsie_i;
1059
 
1060
 
7983 leency 1061
PROCEDURE translate (pic, stroffs: INTEGER);
1062
VAR
1063
    cmd, next: COMMAND;
1064
    opcode, param1, param2: INTEGER;
1065
 
1066
    r1, r2, r3: INTEGER;
1067
 
1068
    a, n, cc, L, L2: INTEGER;
1069
 
1070
BEGIN
1071
    cmd := IL.codes.commands.first(COMMAND);
1072
 
1073
    WHILE cmd # NIL DO
1074
 
1075
        param1 := cmd.param1;
1076
        param2 := cmd.param2;
1077
        opcode := cmd.opcode;
1078
 
1079
        CASE opcode OF
1080
 
1081
        |IL.opJMP:
1082
            jmp(param1)
1083
 
1084
        |IL.opLABEL:
1085
            Label(param1)
1086
 
1087
        |IL.opHANDLER:
1088
            IF param2 = 0 THEN
1089
                int0 := param1
1090
            ELSIF param2 = 1 THEN
1091
                trap := param1
1092
            ELSE
1093
                IVT[param2] := param1
1094
            END
1095
 
1096
        |IL.opCALL:
1097
            call(param1)
1098
 
1099
        |IL.opCALLP:
1100
            UnOp(r1);
8097 maxcodehac 1101
            AddImm8(r1, 1); (* Thumb mode *)
7983 leency 1102
            gen5(3, TRUE, FALSE, r1, 0); (* blx r1 *)
1103
            drop;
1104
            ASSERT(R.top = -1)
1105
 
1106
        |IL.opENTER:
1107
            ASSERT(R.top = -1);
1108
 
1109
            Label(param1);
1110
 
8859 leency 1111
            gen14(FALSE, TRUE, {}); (* push {lr} *)
7983 leency 1112
 
1113
            n := param2;
1114
            IF n >= 5 THEN
1115
                MovConst(ACC, 0);
1116
                MovConst(R2, n);
1117
                L := NewLabel();
1118
                Label(L);
1119
                push(ACC);
1120
                SubImm8(R2, 1);
1121
                Tst(R2);
1122
                jcc(jne, L)
1123
            ELSIF n > 0 THEN
1124
                MovConst(ACC, 0);
1125
                WHILE n > 0 DO
1126
                    push(ACC);
1127
                    DEC(n)
1128
                END
1129
            END;
1130
            StkCount := param2
1131
 
1132
        |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
1133
            IF opcode # IL.opLEAVE THEN
1134
                UnOp(r1);
1135
                IF r1 # ACC THEN
8859 leency 1136
                    mov(ACC, r1)
7983 leency 1137
                END;
1138
                drop
1139
            END;
1140
 
1141
            ASSERT(R.top = -1);
1142
            ASSERT(StkCount = param1);
1143
 
1144
            AddSP(param1);
8859 leency 1145
            gen14(TRUE, TRUE, {}) (* pop {pc} *)
7983 leency 1146
 
1147
        |IL.opLEAVEC:
8859 leency 1148
            gen5(3, FALSE, TRUE, 6, 0) (* bx lr *)
7983 leency 1149
 
1150
        |IL.opPRECALL:
1151
            PushAll(0)
1152
 
1153
        |IL.opPARAM:
1154
            n := param2;
1155
            IF n = 1 THEN
1156
                UnOp(r1);
1157
                push(r1);
1158
                drop
1159
            ELSE
1160
                ASSERT(R.top + 1 <= n);
1161
                PushAll(n)
1162
            END
1163
 
1164
        |IL.opCLEANUP:
1165
            AddSP(param2)
1166
 
1167
        |IL.opRES, IL.opRESF:
1168
            ASSERT(R.top = -1);
1169
            GetRegA
1170
 
1171
        |IL.opPUSHC:
1172
            PushConst(param2)
1173
 
1174
        |IL.opONERR:
8859 leency 1175
            cpsid_i;
7983 leency 1176
            MovConst(R0, param2);
1177
            push(R0);
1178
            DEC(StkCount);
1179
            jmp(param1)
1180
 
1181
        |IL.opERR:
1182
            call(genTrap)
1183
 
8097 maxcodehac 1184
        |IL.opNOP, IL.opAND, IL.opOR:
7983 leency 1185
 
1186
        |IL.opSADR:
1187
            reloc(GetAnyReg(), BIN.RDATA + pic, stroffs + param2)
1188
 
1189
        |IL.opGADR:
1190
            reloc(GetAnyReg(), BIN.RBSS + pic, param2)
1191
 
1192
        |IL.opLADR:
1193
            LocAdr(param2)
1194
 
1195
        |IL.opGLOAD32:
1196
            r1 := GetAnyReg();
1197
            reloc(r1, BIN.RBSS + pic, param2);
1198
            Ldr32(r1, r1)
1199
 
1200
        |IL.opGLOAD16:
1201
            r1 := GetAnyReg();
1202
            reloc(r1, BIN.RBSS + pic, param2);
1203
            Ldr16(r1, r1)
1204
 
1205
        |IL.opGLOAD8:
1206
            r1 := GetAnyReg();
1207
            reloc(r1, BIN.RBSS + pic, param2);
1208
            Ldr8(r1, r1)
1209
 
8859 leency 1210
        |IL.opLADR_SAVE:
1211
            UnOp(r1);
1212
            n := LocalOffset(param2);
1213
            IF n <= 255 THEN
1214
                gen11(FALSE, r1, n)  (* str r1, [sp, n*4] *)
1215
            ELSE
1216
                LocAdr(param2);
1217
                BinOp(r1, r2);
1218
                Str32(r1, r2);
1219
                drop
1220
            END;
1221
            drop
1222
 
1223
        |IL.opLADR_INCC:
1224
            n := LocalOffset(param1);
1225
            IF n <= 255 THEN
1226
                r1 := GetAnyReg();
1227
                LdrSp(r1, n);
1228
                AddConst(r1, param2);
1229
                gen11(FALSE, r1, n)  (* str r1, [sp, n*4] *)
1230
            ELSE
1231
                LocAdr(param1);
1232
                r1 := GetAnyReg();
1233
                BinOp(r2, r1);
1234
                Ldr32(r1, r2);
1235
                AddConst(r1, param2);
1236
                BinOp(r2, r1);
1237
                Str32(r1, r2);
1238
                drop
1239
            END;
1240
            drop
1241
 
7983 leency 1242
        |IL.opLLOAD32, IL.opVADR, IL.opVLOAD32:
1243
            r1 := GetAnyReg();
1244
            n := LocalOffset(param2);
1245
            IF n <= 255 THEN
1246
                LdrSp(r1, n)
1247
            ELSE
1248
                drop;
1249
                LocAdr(param2);
1250
                UnOp(r1);
1251
                Ldr32(r1, r1)
1252
            END;
1253
            IF opcode = IL.opVLOAD32 THEN
1254
                Ldr32(r1, r1)
1255
            END
1256
 
1257
        |IL.opLLOAD16:
1258
            LocAdr(param2);
1259
            UnOp(r1);
1260
            Ldr16(r1, r1)
1261
 
1262
        |IL.opLLOAD8:
1263
            LocAdr(param2);
1264
            UnOp(r1);
1265
            Ldr8(r1, r1)
1266
 
1267
        |IL.opLOAD32, IL.opLOADF:
1268
            UnOp(r1);
1269
            Ldr32(r1, r1)
1270
 
1271
        |IL.opLOAD16:
1272
            UnOp(r1);
1273
            Ldr16(r1, r1)
1274
 
1275
        |IL.opLOAD8:
1276
            UnOp(r1);
1277
            Ldr8(r1, r1)
1278
 
1279
        |IL.opVLOAD16:
1280
            LocAdr(param2);
1281
            UnOp(r1);
1282
            Ldr32(r1, r1);
1283
            Ldr16(r1, r1)
1284
 
1285
        |IL.opVLOAD8:
1286
            LocAdr(param2);
1287
            UnOp(r1);
1288
            Ldr32(r1, r1);
1289
            Ldr8(r1, r1)
1290
 
1291
        |IL.opSBOOL:
1292
            BinOp(r2, r1);
1293
            Tst(r2);
1294
            SetCC(jne, r2);
1295
            Str8(r2, r1);
1296
            drop;
1297
            drop
1298
 
1299
        |IL.opSBOOLC:
1300
            UnOp(r1);
1301
            r2 := GetAnyReg();
1302
            MovConst(r2, ORD(param2 # 0));
1303
            Str8(r2, r1);
1304
            drop;
1305
            drop
1306
 
1307
        |IL.opSAVEC:
1308
            UnOp(r1);
1309
            r2 := GetAnyReg();
1310
            MovConst(r2, param2);
1311
            Str32(r2, r1);
1312
            drop;
1313
            drop
1314
 
1315
        |IL.opSAVE16C:
1316
            UnOp(r1);
1317
            r2 := GetAnyReg();
1318
            MovConst(r2, low(param2));
1319
            Str16(r2, r1);
1320
            drop;
1321
            drop
1322
 
1323
        |IL.opSAVE8C:
1324
            UnOp(r1);
1325
            r2 := GetAnyReg();
1326
            MovConst(r2, param2 MOD 256);
1327
            Str8(r2, r1);
1328
            drop;
1329
            drop
1330
 
1331
        |IL.opSAVE, IL.opSAVE32, IL.opSAVEF:
1332
            BinOp(r2, r1);
1333
            Str32(r2, r1);
1334
            drop;
1335
            drop
1336
 
1337
        |IL.opSAVEFI:
1338
            BinOp(r2, r1);
1339
            Str32(r1, r2);
1340
            drop;
1341
            drop
1342
 
1343
        |IL.opSAVE16:
1344
            BinOp(r2, r1);
1345
            Str16(r2, r1);
1346
            drop;
1347
            drop
1348
 
1349
        |IL.opSAVE8:
1350
            BinOp(r2, r1);
1351
            Str8(r2, r1);
1352
            drop;
1353
            drop
1354
 
1355
        |IL.opSAVEP:
1356
            UnOp(r1);
1357
            r2 := GetAnyReg();
1358
            reloc(r2, BIN.RCODE + pic, param2);
1359
            Str32(r2, r1);
1360
            drop;
1361
            drop
1362
 
1363
        |IL.opPUSHP:
1364
            reloc(GetAnyReg(), BIN.RCODE + pic, param2)
1365
 
1366
        |IL.opEQB, IL.opNEB:
1367
            BinOp(r1, r2);
1368
            drop;
1369
 
1370
            L := NewLabel();
1371
            cbz(r1, L);
1372
            MovConst(r1, 1);
1373
            Label(L);
1374
 
1375
            L := NewLabel();
1376
            cbz(r2, L);
1377
            MovConst(r2, 1);
1378
            Label(L);
1379
 
1380
            Cmp(r1, r2);
1381
            IF opcode = IL.opEQB THEN
1382
                SetCC(je, r1)
1383
            ELSE
1384
                SetCC(jne, r1)
1385
            END
1386
 
1387
        |IL.opDROP:
1388
            UnOp(r1);
1389
            drop
1390
 
8097 maxcodehac 1391
        |IL.opJNZ1:
7983 leency 1392
            UnOp(r1);
1393
            cbnz(r1, param1)
1394
 
1395
        |IL.opJG:
1396
            UnOp(r1);
1397
            Tst(r1);
1398
            jcc(jg, param1)
1399
 
8097 maxcodehac 1400
        |IL.opJNZ:
7983 leency 1401
            UnOp(r1);
1402
            cbnz(r1, param1);
1403
            drop
1404
 
8097 maxcodehac 1405
        |IL.opJZ:
7983 leency 1406
            UnOp(r1);
1407
            cbz(r1, param1);
1408
            drop
1409
 
1410
        |IL.opSWITCH:
1411
            UnOp(r1);
1412
            IF param2 = 0 THEN
1413
                r2 := ACC
1414
            ELSE
1415
                r2 := R2
1416
            END;
1417
            IF r1 # r2 THEN
1418
                ASSERT(REG.GetReg(R, r2));
1419
                ASSERT(REG.Exchange(R, r1, r2));
1420
                drop
1421
            END;
1422
            drop
1423
 
1424
        |IL.opENDSW:
1425
 
1426
        |IL.opCASEL:
1427
            GetRegA;
1428
            CmpConst(ACC, param1);
1429
            jcc(jl, param2);
1430
            drop
1431
 
1432
        |IL.opCASER:
1433
            GetRegA;
1434
            CmpConst(ACC, param1);
1435
            jcc(jg, param2);
1436
            drop
1437
 
1438
        |IL.opCASELR:
1439
            GetRegA;
1440
            CmpConst(ACC, param1);
8859 leency 1441
            IF param2 = cmd.param3 THEN
1442
                jcc(jne, param2)
1443
            ELSE
1444
                jcc(jl, param2);
1445
                jcc(jg, cmd.param3)
1446
            END;
7983 leency 1447
            drop
1448
 
1449
        |IL.opCODE:
1450
            Code(param2)
1451
 
1452
        |IL.opEQ..IL.opGE,
1453
         IL.opEQC..IL.opGEC:
1454
            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
1455
                BinOp(r1, r2);
1456
                Cmp(r1, r2);
1457
                drop
1458
            ELSE
1459
                UnOp(r1);
1460
                CmpConst(r1, param2)
1461
            END;
1462
 
1463
            drop;
1464
            cc := cond(opcode);
1465
            next := cmd.next(COMMAND);
1466
 
8097 maxcodehac 1467
            IF next.opcode = IL.opJNZ THEN
7983 leency 1468
                jcc(cc, next.param1);
1469
                cmd := next
8097 maxcodehac 1470
            ELSIF next.opcode = IL.opJZ THEN
7983 leency 1471
                jcc(inv0(cc), next.param1);
1472
                cmd := next
1473
            ELSE
1474
                SetCC(cc, GetAnyReg())
1475
            END
1476
 
1477
        |IL.opINCC:
1478
            UnOp(r1);
1479
            r2 := GetAnyReg();
1480
            Ldr32(r2, r1);
1481
            AddConst(r2, param2);
1482
            Str32(r2, r1);
1483
            drop;
1484
            drop
1485
 
1486
        |IL.opINCCB, IL.opDECCB:
1487
            IF opcode = IL.opDECCB THEN
1488
                param2 := -param2
1489
            END;
1490
            UnOp(r1);
1491
            r2 := GetAnyReg();
1492
            Ldr8(r2, r1);
1493
            AddConst(r2, param2);
1494
            Str8(r2, r1);
1495
            drop;
1496
            drop
1497
 
1498
        |IL.opUMINUS:
1499
            UnOp(r1);
1500
            Neg(r1)
1501
 
1502
        |IL.opADD:
1503
            BinOp(r1, r2);
1504
            CASE cmd.next(COMMAND).opcode OF
1505
            |IL.opLOAD32, IL.opLOADF:
1506
                gen7(TRUE, FALSE, r2, r1, r1); (* ldr r1, [r1, r2] *)
1507
                cmd := cmd.next(COMMAND)
1508
            |IL.opLOAD8:
1509
                gen7(TRUE, TRUE, r2, r1, r1);  (* ldrb r1, [r1, r2] *)
1510
                cmd := cmd.next(COMMAND)
1511
            |IL.opLOAD16:
1512
                gen8(TRUE, FALSE, r2, r1, r1); (* ldrh r1, [r1, r2] *)
1513
                cmd := cmd.next(COMMAND)
1514
            ELSE
1515
                AddReg(r1, r1, r2)
1516
            END;
1517
            drop
1518
 
8097 maxcodehac 1519
        |IL.opADDC:
7983 leency 1520
            UnOp(r1);
1521
            AddConst(r1, param2)
1522
 
1523
        |IL.opSUB:
1524
            BinOp(r1, r2);
1525
            SubReg(r1, r1, r2);
1526
            drop
1527
 
1528
        |IL.opSUBL, IL.opSUBR:
1529
            UnOp(r1);
1530
            AddConst(r1, -param2);
1531
            IF opcode = IL.opSUBL THEN
1532
                Neg(r1)
1533
            END
1534
 
1535
        |IL.opMUL:
1536
            BinOp(r1, r2);
1537
            Mul(r1, r2);
1538
            drop
1539
 
1540
        |IL.opMULC:
1541
            UnOp(r1);
1542
 
1543
            a := param2;
1544
            IF a > 1 THEN
1545
                n := UTILS.Log2(a)
1546
            ELSIF a < -1 THEN
1547
                n := UTILS.Log2(-a)
1548
            ELSE
1549
                n := -1
1550
            END;
1551
 
1552
            IF a = 1 THEN
1553
 
1554
            ELSIF a = -1 THEN
1555
                Neg(r1)
1556
            ELSIF a = 0 THEN
1557
                MovConst(r1, 0)
1558
            ELSE
1559
                IF n > 0 THEN
1560
                    IF a < 0 THEN
1561
                        Neg(r1)
1562
                    END;
1563
                    LslImm(r1, n)
1564
                ELSE
1565
                    r2 := GetAnyReg();
1566
                    MovConst(r2, a);
1567
                    Mul(r1, r2);
1568
                    drop
1569
                END
1570
            END
1571
 
1572
        |IL.opABS:
1573
            UnOp(r1);
1574
            Tst(r1);
1575
            L := NewLabel();
1576
            jcc(jge, L);
1577
            Neg(r1);
1578
            Label(L)
1579
 
1580
        |IL.opNOT:
1581
            UnOp(r1);
1582
            Tst(r1);
1583
            SetCC(je, r1)
1584
 
1585
        |IL.opORD:
1586
            UnOp(r1);
1587
            Tst(r1);
1588
            SetCC(jne, r1)
1589
 
1590
        |IL.opCHR:
1591
            UnOp(r1);
8859 leency 1592
            Code(0B2C0H + r1 * 9) (* uxtb r1, r1 *)
7983 leency 1593
 
1594
        |IL.opWCHR:
1595
            UnOp(r1);
8859 leency 1596
            Code(0B280H + r1 * 9) (* uxth r1, r1 *)
7983 leency 1597
 
1598
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
1599
            BinOp(r1, r2);
1600
            Shift(opcode, r1, r2);
1601
            drop
1602
 
1603
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
1604
            MovConst(GetAnyReg(), param2);
1605
            BinOp(r2, r1);
1606
            Shift(opcode, r1, r2);
1607
            INCL(R.regs, r2);
1608
            DEC(R.top);
1609
            R.stk[R.top] := r1
1610
 
1611
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
1612
            n := param2 MOD 32;
1613
            IF n # 0 THEN
1614
                UnOp(r1);
1615
                CASE opcode OF
1616
                |IL.opASR2: AsrImm(r1, n)
1617
                |IL.opROR2: r2 := GetAnyReg(); MovConst(r2, n); Shift(IL.opROR, r1, r2); drop
1618
                |IL.opLSL2: LslImm(r1, n)
1619
                |IL.opLSR2: LsrImm(r1, n)
1620
                END
1621
            END
1622
 
1623
        |IL.opCHKBYTE:
1624
            BinOp(r1, r2);
1625
            CmpConst(r1, 256);
1626
            jcc(jb, param1)
1627
 
1628
        |IL.opCHKIDX:
1629
            UnOp(r1);
1630
            CmpConst(r1, param2);
1631
            jcc(jb, param1)
1632
 
1633
        |IL.opCHKIDX2:
1634
            BinOp(r1, r2);
1635
            IF param2 # -1 THEN
1636
                Cmp(r2, r1);
1637
                jcc(jb, param1)
1638
            END;
1639
            INCL(R.regs, r1);
1640
            DEC(R.top);
1641
            R.stk[R.top] := r2
1642
 
1643
        |IL.opLEN:
1644
            n := param2;
1645
            UnOp(r1);
1646
            drop;
1647
            EXCL(R.regs, r1);
1648
 
1649
            WHILE n > 0 DO
1650
                UnOp(r2);
1651
                drop;
1652
                DEC(n)
1653
            END;
1654
 
1655
            INCL(R.regs, r1);
1656
            ASSERT(REG.GetReg(R, r1))
1657
 
1658
        |IL.opINF:
1659
            MovConst(GetAnyReg(), inf)
1660
 
1661
        |IL.opPUSHF:
1662
            UnOp(r1);
1663
            push(r1);
1664
            drop
1665
 
1666
        |IL.opCONST:
1667
            MovConst(GetAnyReg(), param2)
1668
 
1669
        |IL.opEQP, IL.opNEP:
1670
            reloc(GetAnyReg(), BIN.RCODE + pic, param1);
1671
            BinOp(r1, r2);
1672
            Cmp(r1, r2);
1673
            drop;
1674
            IF opcode = IL.opEQP THEN
1675
                SetCC(je, r1)
1676
            ELSE
1677
                SetCC(jne, r1)
1678
            END
1679
 
1680
        |IL.opPUSHT:
1681
            UnOp(r1);
1682
            r2 := GetAnyReg();
1683
            mov(r2, r1);
1684
            SubImm8(r2, 4);
1685
            Ldr32(r2, r2)
1686
 
1687
        |IL.opGET, IL.opGETC:
1688
            IF opcode = IL.opGET THEN
1689
                BinOp(r1, r2)
1690
            ELSIF opcode = IL.opGETC THEN
1691
                UnOp(r2);
1692
                r1 := GetAnyReg();
1693
                MovConst(r1, param1)
1694
            END;
1695
            drop;
1696
            drop;
1697
 
1698
            CASE param2 OF
1699
            |1: Ldr8(r1, r1); Str8(r1, r2)
1700
            |2: Ldr16(r1, r1); Str16(r1, r2)
1701
            |4: Ldr32(r1, r1); Str32(r1, r2)
1702
            END
1703
 
1704
        |IL.opINC, IL.opDEC:
1705
            BinOp(r2, r1);
1706
            r3 := GetAnyReg();
1707
            Ldr32(r3, r1);
1708
            IF opcode = IL.opINC THEN
1709
                AddReg(r3, r3, r2)
1710
            ELSE
1711
                SubReg(r3, r3, r2)
1712
            END;
1713
            Str32(r3, r1);
1714
            drop;
1715
            drop;
1716
            drop
1717
 
1718
        |IL.opINCB, IL.opDECB:
1719
            BinOp(r2, r1);
1720
            r3 := GetAnyReg();
1721
            Ldr8(r3, r1);
1722
            IF opcode = IL.opINCB THEN
1723
                AddReg(r3, r3, r2)
1724
            ELSE
1725
                SubReg(r3, r3, r2)
1726
            END;
1727
            Str8(r3, r1);
1728
            drop;
1729
            drop;
1730
            drop
1731
 
1732
        |IL.opMIN, IL.opMAX:
1733
            BinOp(r1, r2);
1734
            Cmp(r1, r2);
1735
            L := NewLabel();
1736
            IF opcode = IL.opMIN THEN
1737
                cc := jle
1738
            ELSE
1739
                cc := jge
1740
            END;
1741
            jcc(cc, L);
1742
            mov(r1, r2);
1743
            Label(L);
1744
            drop
1745
 
1746
        |IL.opMINC, IL.opMAXC:
1747
            UnOp(r1);
1748
            CmpConst(r1, param2);
1749
            L := NewLabel();
1750
            IF opcode = IL.opMINC THEN
1751
                cc := jle
1752
            ELSE
1753
                cc := jge
1754
            END;
1755
            jcc(cc, L);
1756
            MovConst(r1, param2);
1757
            Label(L)
1758
 
1759
        |IL.opMULS:
1760
            BinOp(r1, r2);
8859 leency 1761
            gen4(0, r2, r1); (* ands r1, r2 *)
7983 leency 1762
            drop
1763
 
1764
        |IL.opMULSC:
1765
            MovConst(GetAnyReg(), param2);
1766
            BinOp(r1, r2);
8859 leency 1767
            gen4(0, r2, r1); (* ands r1, r2 *)
7983 leency 1768
            drop
1769
 
1770
        |IL.opDIVS:
1771
            BinOp(r1, r2);
8859 leency 1772
            gen4(1, r2, r1); (* eors r1, r2 *)
7983 leency 1773
            drop
1774
 
1775
        |IL.opDIVSC:
1776
            MovConst(GetAnyReg(), param2);
1777
            BinOp(r1, r2);
8859 leency 1778
            gen4(1, r2, r1); (* eors r1, r2 *)
7983 leency 1779
            drop
1780
 
1781
        |IL.opADDS:
1782
            BinOp(r1, r2);
8859 leency 1783
            gen4(12, r2, r1); (* orrs r1, r2 *)
7983 leency 1784
            drop
1785
 
1786
        |IL.opSUBS:
1787
            BinOp(r1, r2);
8859 leency 1788
            gen4(14, r2, r1); (* bics r1, r2 *)
7983 leency 1789
            drop
1790
 
8097 maxcodehac 1791
        |IL.opADDSC:
7983 leency 1792
            MovConst(GetAnyReg(), param2);
1793
            BinOp(r1, r2);
8859 leency 1794
            gen4(12, r2, r1); (* orrs r1, r2 *)
7983 leency 1795
            drop
1796
 
1797
        |IL.opSUBSL:
1798
            MovConst(GetAnyReg(), param2);
1799
            BinOp(r1, r2);
8859 leency 1800
            gen4(14, r1, r2); (* bics r2, r1 *)
7983 leency 1801
            INCL(R.regs, r1);
1802
            DEC(R.top);
1803
            R.stk[R.top] := r2
1804
 
1805
        |IL.opSUBSR:
1806
            MovConst(GetAnyReg(), param2);
1807
            BinOp(r1, r2);
8859 leency 1808
            gen4(14, r2, r1); (* bics r1, r2 *)
7983 leency 1809
            drop
1810
 
1811
        |IL.opUMINS:
1812
            UnOp(r1);
8859 leency 1813
            gen4(15, r1, r1) (* mvns r1, r1 *)
7983 leency 1814
 
1815
        |IL.opINCL, IL.opEXCL:
1816
            BinOp(r1, r2);
1817
            r3 := GetAnyReg();
1818
            MovConst(r3, 1);
1819
            CmpConst(r1, 32);
1820
            L := NewLabel();
1821
            jcc(jnb, L);
8859 leency 1822
            gen4(2, r1, r3); (* lsls r3, r1 *)
7983 leency 1823
            Ldr32(r1, r2);
1824
            IF opcode = IL.opINCL THEN
8859 leency 1825
                gen4(12, r3, r1) (* orrs r1, r3 *)
7983 leency 1826
            ELSE
8859 leency 1827
                gen4(14, r3, r1) (* bics r1, r3 *)
7983 leency 1828
            END;
1829
            Str32(r1, r2);
1830
            Label(L);
1831
            drop;
1832
            drop;
1833
            drop
1834
 
1835
        |IL.opINCLC, IL.opEXCLC:
1836
            UnOp(r2);
1837
            r1 := GetAnyReg();
1838
            r3 := GetAnyReg();
1839
            MovConst(r3, 1);
1840
            LslImm(r3, param2);
1841
            Ldr32(r1, r2);
1842
            IF opcode = IL.opINCLC THEN
8859 leency 1843
                gen4(12, r3, r1) (* orrs r1, r3 *)
7983 leency 1844
            ELSE
8859 leency 1845
                gen4(14, r3, r1) (* bics r1, r3 *)
7983 leency 1846
            END;
1847
            Str32(r1, r2);
1848
            drop;
1849
            drop;
1850
            drop
1851
 
1852
        |IL.opLENGTH:
1853
            PushAll(2);
1854
            CallRTL(IL._length, 2);
1855
            GetRegA
1856
 
1857
        |IL.opLENGTHW:
1858
            PushAll(2);
1859
            CallRTL(IL._lengthw, 2);
1860
            GetRegA
1861
 
1862
        |IL.opSAVES:
1863
            UnOp(r2);
1864
            REG.PushAll_1(R);
1865
            r1 := GetAnyReg();
1866
            reloc(r1, BIN.RDATA + pic, stroffs + param2);
1867
            push(r1);
1868
            drop;
1869
            push(r2);
1870
            drop;
1871
            PushConst(param1);
1872
            CallRTL(IL._move, 3)
1873
 
1874
        |IL.opEQS .. IL.opGES:
1875
            PushAll(4);
1876
            PushConst(opcode - IL.opEQS);
1877
            CallRTL(IL._strcmp, 5);
1878
            GetRegA
1879
 
1880
        |IL.opEQSW .. IL.opGESW:
1881
            PushAll(4);
1882
            PushConst(opcode - IL.opEQSW);
1883
            CallRTL(IL._strcmpw, 5);
1884
            GetRegA
1885
 
1886
        |IL.opCOPY:
1887
            PushAll(2);
1888
            PushConst(param2);
1889
            CallRTL(IL._move, 3)
1890
 
1891
        |IL.opMOVE:
1892
            PushAll(3);
1893
            CallRTL(IL._move, 3)
1894
 
1895
        |IL.opCOPYA:
1896
            PushAll(4);
1897
            PushConst(param2);
1898
            CallRTL(IL._arrcpy, 5);
1899
            GetRegA
1900
 
1901
        |IL.opCOPYS:
1902
            PushAll(4);
1903
            PushConst(param2);
1904
            CallRTL(IL._strcpy, 5)
1905
 
1906
        |IL.opDIV:
1907
            PushAll(2);
1908
            divmod;
1909
            GetRegA
1910
 
1911
        |IL.opDIVL:
1912
            UnOp(r1);
1913
            REG.PushAll_1(R);
1914
            PushConst(param2);
1915
            push(r1);
1916
            drop;
1917
            divmod;
1918
            GetRegA
1919
 
1920
        |IL.opDIVR:
1921
            n := UTILS.Log2(param2);
1922
            IF n > 0 THEN
1923
                UnOp(r1);
1924
                AsrImm(r1, n)
1925
            ELSIF n < 0 THEN
1926
                PushAll(1);
1927
                PushConst(param2);
1928
                divmod;
1929
                GetRegA
1930
            END
1931
 
1932
        |IL.opMOD:
1933
            PushAll(2);
1934
            divmod;
1935
            mov(R0, R1);
1936
            GetRegA
1937
 
1938
        |IL.opMODR:
1939
            n := UTILS.Log2(param2);
1940
            IF n > 0 THEN
1941
                UnOp(r1);
1942
                IF n = 8 THEN
8859 leency 1943
                    Code(0B2C0H + r1 * 9) (* uxtb r1, r1 *)
7983 leency 1944
                ELSIF n = 16 THEN
8859 leency 1945
                    Code(0B280H + r1 * 9) (* uxth r1, r1 *)
7983 leency 1946
                ELSE
1947
                    LslImm(r1, 32 - n);
1948
                    LsrImm(r1, 32 - n)
1949
                END
1950
            ELSIF n < 0 THEN
1951
                PushAll(1);
1952
                PushConst(param2);
1953
                divmod;
1954
                mov(R0, R1);
1955
                GetRegA
1956
            ELSE
1957
                UnOp(r1);
1958
                MovConst(r1, 0)
1959
            END
1960
 
1961
        |IL.opMODL:
1962
            UnOp(r1);
1963
            REG.PushAll_1(R);
1964
            PushConst(param2);
1965
            push(r1);
1966
            drop;
1967
            divmod;
1968
            mov(R0, R1);
1969
            GetRegA
1970
 
1971
        |IL.opIN, IL.opINR:
1972
            IF opcode = IL.opINR THEN
1973
                r2 := GetAnyReg();
1974
                MovConst(r2, param2)
1975
            END;
1976
            L := NewLabel();
1977
            L2 := NewLabel();
1978
            BinOp(r1, r2);
1979
            r3 := GetAnyReg();
1980
            CmpConst(r1, 32);
1981
            jcc(jb, L);
1982
            MovConst(r1, 0);
1983
            jmp(L2);
1984
            Label(L);
1985
            MovConst(r3, 1);
1986
            Shift(IL.opLSL, r3, r1);
8859 leency 1987
            gen4(0, r3, r2); (* ands r2, r3 *)
7983 leency 1988
            SetCC(jne, r1);
1989
            Label(L2);
1990
            drop;
1991
            drop
1992
 
1993
        |IL.opINL:
1994
            UnOp(r1);
1995
            r2 := GetAnyReg();
1996
            MovConst(r2, LSL(1, param2));
8859 leency 1997
            gen4(0, r2, r1); (* ands r1, r2 *)
7983 leency 1998
            SetCC(jne, r1);
1999
            drop
2000
 
2001
        |IL.opRSET:
2002
            PushAll(2);
2003
            CallRTL(IL._set, 2);
2004
            GetRegA
2005
 
2006
        |IL.opRSETR:
2007
            PushAll(1);
2008
            PushConst(param2);
2009
            CallRTL(IL._set, 2);
2010
            GetRegA
2011
 
2012
        |IL.opRSETL:
2013
            UnOp(r1);
2014
            REG.PushAll_1(R);
2015
            PushConst(param2);
2016
            push(r1);
2017
            drop;
2018
            CallRTL(IL._set, 2);
2019
            GetRegA
2020
 
2021
        |IL.opRSET1:
2022
            PushAll(1);
2023
            CallRTL(IL._set1, 1);
2024
            GetRegA
2025
 
2026
        |IL.opCONSTF:
2027
            MovConst(GetAnyReg(), UTILS.d2s(cmd.float))
2028
 
2029
        |IL.opMULF:
2030
            PushAll(2);
2031
            CallRTL(IL._fmul, 2);
2032
            GetRegA
2033
 
2034
        |IL.opDIVF:
2035
            PushAll(2);
2036
            CallRTL(IL._fdiv, 2);
2037
            GetRegA
2038
 
2039
        |IL.opDIVFI:
2040
            PushAll(2);
2041
            CallRTL(IL._fdivi, 2);
2042
            GetRegA
2043
 
8097 maxcodehac 2044
        |IL.opADDF:
7983 leency 2045
            PushAll(2);
2046
            CallRTL(IL._fadd, 2);
2047
            GetRegA
2048
 
2049
        |IL.opSUBFI:
2050
            PushAll(2);
2051
            CallRTL(IL._fsubi, 2);
2052
            GetRegA
2053
 
2054
        |IL.opSUBF:
2055
            PushAll(2);
2056
            CallRTL(IL._fsub, 2);
2057
            GetRegA
2058
 
2059
        |IL.opEQF..IL.opGEF:
2060
            PushAll(2);
2061
            PushConst(opcode - IL.opEQF);
2062
            CallRTL(IL._fcmp, 3);
2063
            GetRegA
2064
 
2065
        |IL.opFLOOR:
2066
            PushAll(1);
2067
            CallRTL(IL._floor, 1);
2068
            GetRegA
2069
 
2070
        |IL.opFLT:
2071
            PushAll(1);
2072
            CallRTL(IL._flt, 1);
2073
            GetRegA
2074
 
2075
        |IL.opUMINF:
2076
            UnOp(r1);
2077
            r2 := GetAnyReg();
2078
            MovConst(r2, 1);
2079
            LslImm(r2, 31);
8859 leency 2080
            gen4(1, r2, r1); (* eors r1, r2 *)
7983 leency 2081
            drop
2082
 
2083
        |IL.opFABS:
2084
            UnOp(r1);
2085
            r2 := GetAnyReg();
2086
            MovConst(r2, 1);
2087
            LslImm(r2, 31);
8859 leency 2088
            gen4(14, r2, r1); (* bics r1, r2 *)
7983 leency 2089
            drop
2090
 
2091
        |IL.opNEW:
8859 leency 2092
            cpsid_i;
7983 leency 2093
            PushAll(1);
8859 leency 2094
            n := param2 + 4;
2095
            ASSERT(UTILS.Align(n, 4));
7983 leency 2096
            PushConst(n);
2097
            PushConst(param1);
8859 leency 2098
            CallRTL(IL._new, 3);
2099
            cpsie_i
7983 leency 2100
 
2101
        |IL.opTYPEGP:
2102
            UnOp(r1);
2103
            PushAll(0);
2104
            push(r1);
2105
            PushConst(param2);
2106
            CallRTL(IL._guard, 2);
2107
            GetRegA
2108
 
2109
        |IL.opIS:
2110
            PushAll(1);
2111
            PushConst(param2);
2112
            CallRTL(IL._is, 2);
2113
            GetRegA
2114
 
2115
        |IL.opISREC:
2116
            PushAll(2);
2117
            PushConst(param2);
2118
            CallRTL(IL._guardrec, 3);
2119
            GetRegA
2120
 
2121
        |IL.opTYPEGR:
2122
            PushAll(1);
2123
            PushConst(param2);
2124
            CallRTL(IL._guardrec, 2);
2125
            GetRegA
2126
 
2127
        |IL.opTYPEGD:
2128
            UnOp(r1);
2129
            PushAll(0);
2130
            SubImm8(r1, 4);
2131
            Ldr32(r1, r1);
2132
            push(r1);
2133
            PushConst(param2);
2134
            CallRTL(IL._guardrec, 2);
2135
            GetRegA
2136
 
2137
        |IL.opCASET:
2138
            push(R2);
2139
            push(R2);
2140
            PushConst(param2);
2141
            CallRTL(IL._guardrec, 2);
2142
            pop(R2);
2143
            cbnz(ACC, param1)
2144
 
2145
        |IL.opROT:
2146
            PushAll(0);
2147
            mov(R2, SP);
2148
            push(R2);
2149
            PushConst(param2);
2150
            CallRTL(IL._rot, 2)
2151
 
2152
        |IL.opPACK:
2153
            PushAll(2);
2154
            CallRTL(IL._pack, 2)
2155
 
2156
        |IL.opPACKC:
2157
            PushAll(1);
2158
            PushConst(param2);
2159
            CallRTL(IL._pack, 2)
2160
 
2161
        |IL.opUNPK:
2162
            PushAll(2);
2163
            CallRTL(IL._unpk, 2)
2164
 
2165
        END;
2166
 
2167
        cmd := cmd.next(COMMAND)
2168
    END;
2169
 
2170
    ASSERT(R.pushed = 0);
2171
    ASSERT(R.top = -1)
2172
END translate;
2173
 
2174
 
8859 leency 2175
PROCEDURE prolog (GlobSize, tcount, pic, sp, ivt_len: INTEGER);
7983 leency 2176
VAR
2177
    r1, r2, i, dcount: INTEGER;
2178
 
2179
BEGIN
2180
    entry := NewLabel();
2181
    emptyProc := NewLabel();
2182
    genInt := NewLabel();
2183
    genTrap := NewLabel();
2184
    sdivProc := NewLabel();
2185
 
2186
    trap := emptyProc;
2187
    int0 := emptyProc;
2188
 
2189
    IVT[0] := sp;
2190
    IVT[1] := entry;
2191
    FOR i := 2 TO ivt_len - 1 DO
2192
        IVT[i] := genInt
2193
    END;
2194
 
2195
    FOR i := 0 TO ivt_len - 1 DO
2196
        Code(low(IVT[i]));
2197
        Code(high(IVT[i]))
2198
    END;
2199
 
2200
    Label(entry);
8859 leency 2201
    cpsie_i;
7983 leency 2202
 
2203
    r1 := GetAnyReg();
2204
    r2 := GetAnyReg();
2205
    reloc(r1, BIN.RDATA + pic, 0);
2206
 
2207
    FOR i := 0 TO tcount - 1 DO
2208
        MovConst(r2, CHL.GetInt(IL.codes.types, i));
2209
        Str32(r2, r1);
2210
        AddImm8(r1, 4)
2211
    END;
2212
 
2213
    dcount := CHL.Length(IL.codes.data);
2214
    FOR i := 0 TO dcount - 1 BY 4 DO
2215
        MovConst(r2, BIN.get32le(IL.codes.data, i));
2216
        Str32(r2, r1);
2217
        AddImm8(r1, 4)
2218
    END;
2219
 
2220
    drop;
2221
    drop;
2222
 
2223
    r1 := GetAnyReg();
2224
    MovConst(r1, sp);
2225
    mov(SP, r1);
2226
    reloc(r1, BIN.RDATA + pic, 0);
2227
    push(r1);
2228
    reloc(r1, BIN.RBSS + pic, 0);
2229
    r2 := GetAnyReg();
2230
    MovConst(r2, GlobSize);
2231
    AddReg(r1, r1, r2);
2232
    drop;
2233
    push(r1);
2234
    drop;
2235
    PushConst(tcount);
2236
    CallRTL(IL._init, 3)
2237
END prolog;
2238
 
2239
 
2240
PROCEDURE epilog;
2241
VAR
2242
    L1, L2, L3, L4: INTEGER;
2243
 
2244
BEGIN
8859 leency 2245
                   (* L2:  *)
2246
    Code(0E7FEH);  (* b L2 *)
7983 leency 2247
 
2248
    Label(genInt);
8859 leency 2249
    Code(0F3EFH); Code(08005H);  (* mrs r0, ipsr  *)
2250
    gen14(FALSE, TRUE, {R0});    (* push {lr, r0} *)
7983 leency 2251
    call(int0);
8859 leency 2252
    gen14(TRUE, TRUE, {R0});     (* pop {pc, r0}  *)
7983 leency 2253
 
2254
    Label(emptyProc);
2255
    Code(04770H);  (* bx lr *)
2256
 
2257
    Label(genTrap);
2258
    call(trap);
2259
    call(entry);
2260
 
2261
    Label(sdivProc);
8859 leency 2262
    IF _SDIV IN Target.InstrSet THEN
2263
        Code(09800H);  (* ldr  r0, [sp]    *)
2264
        Code(09901H);  (* ldr  r1, [sp, 4] *)
2265
        Code(0FB91H);  (* sdiv r2, r1, r0  *)
7983 leency 2266
        Code(0F2F0H);
8859 leency 2267
        Code(00013H);  (* movs r3, r2      *)
2268
        Code(04343H);  (* muls r3, r0, r3  *)
2269
        Code(01AC9H);  (* subs r1, r1, r3  *)
2270
        Code(0DA01H);  (* bge  L           *)
2271
        Code(01809H);  (* adds r1, r1, r0  *)
2272
        Code(03A01H);  (* subs r2, 1       *)
2273
                       (* L:               *)
2274
        Code(00010H);  (* movs r0, r2      *)
2275
        Code(04770H);  (* bx   lr          *)
7983 leency 2276
    ELSE
2277
        (* a / b; a >= 0 *)
2278
        L1 := NewLabel();
2279
        L2 := NewLabel();
2280
        L3 := NewLabel();
2281
        L4 := NewLabel();
2282
 
2283
        LdrSp(R1, 1);
2284
        LdrSp(R2, 0);
2285
        MovConst(R0, 0);
2286
        push(R4);
2287
 
2288
        Label(L4);
2289
        Cmp(R1, R2);
2290
        jcc(jl, L1);
2291
        MovConst(R3, 2);
2292
        mov(R4, R2);
2293
        LslImm(R4, 1);
2294
        Label(L3);
2295
        Cmp(R1, R4);
2296
        jcc(jl, L2);
2297
        CmpConst(R4, 0);
2298
        jcc(jle, L2);
2299
        LslImm(R4, 1);
2300
        LslImm(R3, 1);
2301
        jmp(L3);
2302
        Label(L2);
2303
        LsrImm(R4, 1);
2304
        LsrImm(R3, 1);
2305
        SubReg(R1, R1, R4);
2306
        AddReg(R0, R0, R3);
2307
        jmp(L4);
2308
        Label(L1);
2309
 
2310
        (* a / b; a < 0 *)
2311
        L1 := NewLabel();
2312
        L2 := NewLabel();
2313
        L3 := NewLabel();
2314
        L4 := NewLabel();
2315
 
2316
        Label(L4);
2317
        CmpConst(R1, 0);
2318
        jcc(jge, L1);
2319
        MovConst(R3, 2);
2320
        mov(R4, R2);
2321
        LslImm(R4, 1);
2322
        Neg(R1);
2323
        Label(L3);
2324
        Cmp(R1, R4);
2325
        jcc(jl, L2);
2326
        CmpConst(R4, 0);
2327
        jcc(jle, L2);
2328
        LslImm(R4, 1);
2329
        LslImm(R3, 1);
2330
        jmp(L3);
2331
        Label(L2);
2332
        Neg(R1);
2333
        LsrImm(R4, 1);
2334
        LsrImm(R3, 1);
2335
        AddReg(R1, R1, R4);
2336
        SubReg(R0, R0, R3);
2337
        jmp(L4);
2338
        Label(L1);
2339
 
2340
        pop(R4);
2341
        Code(04770H);  (* bx lr *)
2342
    END
2343
 
2344
END epilog;
2345
 
2346
 
8859 leency 2347
PROCEDURE SetTarget (FlashStart, SRAMStart: INTEGER; InstrSet: SET; isNXP: BOOLEAN);
7983 leency 2348
BEGIN
8859 leency 2349
    Target.FlashAdr := FlashStart;
2350
    Target.SRAMAdr  := SRAMStart;
2351
    Target.InstrSet := InstrSet;
2352
    Target.isNXP    := isNXP;
2353
 
2354
    Target.IVTLen   := 256; (* >= 192 *)
7983 leency 2355
    Target.Reserved := 0;
2356
    Target.MinStack := 512;
8859 leency 2357
END SetTarget;
7983 leency 2358
 
2359
 
2360
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
2361
VAR
2362
    opt: PROG.OPTIONS;
2363
 
8859 leency 2364
    ram, rom, i, j: INTEGER;
7983 leency 2365
 
2366
    DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER;
2367
 
2368
BEGIN
8859 leency 2369
    ram := MIN(MAX(options.ram, minRAM), maxRAM) * 1024;
2370
    rom := MIN(MAX(options.rom, minROM), maxROM) * 1024;
2371
 
7983 leency 2372
    IF target = TARGETS.STM32CM3 THEN
8859 leency 2373
        SetTarget(08000000H, 20000000H, CortexM3, FALSE)
7983 leency 2374
    END;
2375
 
2376
    tcount := CHL.Length(IL.codes.types);
2377
 
2378
    opt := options;
2379
    CodeList := LISTS.create(NIL);
2380
 
2381
    program := BIN.create(IL.codes.lcount);
2382
 
8859 leency 2383
    REG.Init(R, push, pop, mov, xchg, {R0, R1, R2, R3});
7983 leency 2384
 
2385
    StkCount := 0;
2386
 
2387
    DataAdr := Target.SRAMAdr + Target.Reserved;
2388
    DataSize := CHL.Length(IL.codes.data) + tcount * 4 + Target.Reserved;
2389
    WHILE DataSize MOD 4 # 0 DO
2390
        CHL.PushByte(IL.codes.data, 0);
2391
        INC(DataSize)
2392
    END;
2393
    BssAdr := DataAdr + DataSize - Target.Reserved;
2394
 
2395
    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4)));
2396
 
2397
    BssSize := IL.codes.bss;
2398
    ASSERT(UTILS.Align(BssSize, 4));
2399
 
8859 leency 2400
    prolog(BssSize, tcount, ORD(opt.pic), Target.SRAMAdr + ram, Target.IVTLen);
7983 leency 2401
    translate(ORD(opt.pic), tcount * 4);
2402
    epilog;
2403
 
2404
    fixup(Target.FlashAdr, DataAdr, BssAdr);
2405
 
2406
    INC(DataSize, BssSize);
2407
    CodeSize := CHL.Length(program.code);
2408
 
2409
    IF CodeSize > rom THEN
2410
        ERRORS.Error(203)
2411
    END;
2412
 
2413
    IF DataSize > ram - Target.MinStack THEN
2414
        ERRORS.Error(204)
2415
    END;
2416
 
8859 leency 2417
    IF Target.isNXP THEN
2418
        BIN.put32le(program.code, 2FCH, 0H); (* code read protection (CRP) *)
2419
        (* NXP checksum *)
2420
        j := 0;
2421
        FOR i := 0 TO 6 DO
2422
            INC(j, BIN.get32le(program.code, i * 4))
2423
        END;
2424
        BIN.put32le(program.code, 1CH, -j)
2425
    END;
2426
 
8097 maxcodehac 2427
    WR.Create(outname);
7983 leency 2428
 
8097 maxcodehac 2429
    HEX.Data2(program.code, 0, CodeSize, high(Target.FlashAdr));
2430
    HEX.End;
7983 leency 2431
 
8097 maxcodehac 2432
    WR.Close;
7983 leency 2433
 
8859 leency 2434
    C.Dashes;
7983 leency 2435
    C.String(  "  rom:  "); C.Int(CodeSize); C.String(" of "); C.Int(rom); C.String("  ("); C.Int(CodeSize * 100 DIV rom); C.StringLn("%)");
2436
    C.Ln;
8859 leency 2437
    C.String(  "  ram:  "); C.Int(DataSize); C.String(" of "); C.Int(ram); C.String("  ("); C.Int(DataSize * 100 DIV ram); C.StringLn("%)")
7983 leency 2438
END CodeGen;
2439
 
2440
 
2441
PROCEDURE SetIV* (idx: INTEGER): BOOLEAN;
2442
VAR
2443
    res: BOOLEAN;
2444
 
2445
BEGIN
2446
    res := IVT[idx] = 0;
2447
    IVT[idx] := 1
2448
 
2449
    RETURN res
2450
END SetIV;
2451
 
2452
 
2453
PROCEDURE init;
2454
VAR
2455
    i: INTEGER;
2456
 
2457
BEGIN
2458
    FOR i := 0 TO LEN(IVT) - 1 DO
2459
        IVT[i] := 0
2460
    END
2461
END init;
2462
 
2463
 
2464
BEGIN
2465
    init
2466
END THUMB.