Subversion Repositories Kolibri OS

Rev

Rev 9177 | Details | Compare with Previous | Last modification | View Log | RSS feed

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