Subversion Repositories Kolibri OS

Rev

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