Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
7983 leency 1
(*
2
    BSD 2-Clause License
3
 
4
    Copyright (c) 2019-2020, Anton Krotov
5
    All rights reserved.
6
*)
7
 
8
MODULE 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
8097 maxcodehac 619
        l, h: LISTS.ITEM;
7983 leency 620
 
621
    BEGIN
8097 maxcodehac 622
        l := CodeList.first;
623
        h := l.next;
7983 leency 624
        WHILE idx > 0 DO
8097 maxcodehac 625
            l := h.next;
626
            h := l.next;
7983 leency 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
 
8097 maxcodehac 722
        |JCC:   genbc(code)
7983 leency 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
8097 maxcodehac 787
    push(r1);
788
    mov(r1, r2);
789
    pop(r2)
7983 leency 790
END xchg;
791
 
792
 
793
PROCEDURE drop;
794
BEGIN
795
    REG.Drop(R)
796
END drop;
797
 
798
 
799
PROCEDURE GetAnyReg (): INTEGER;
800
    RETURN REG.GetAnyReg(R)
801
END GetAnyReg;
802
 
803
 
804
PROCEDURE UnOp (VAR r: INTEGER);
805
BEGIN
806
    REG.UnOp(R, r)
807
END UnOp;
808
 
809
 
810
PROCEDURE BinOp (VAR r1, r2: INTEGER);
811
BEGIN
812
    REG.BinOp(R, r1, r2)
813
END BinOp;
814
 
815
 
816
PROCEDURE PushAll (NumberOfParameters: INTEGER);
817
BEGIN
818
    REG.PushAll(R);
819
    DEC(R.pushed, NumberOfParameters)
820
END PushAll;
821
 
822
 
823
PROCEDURE cond (op: INTEGER): INTEGER;
824
VAR
825
    res: INTEGER;
826
 
827
BEGIN
828
    CASE op OF
829
    |IL.opGT, IL.opGTC: res := jg
830
    |IL.opGE, IL.opGEC: res := jge
831
    |IL.opLT, IL.opLTC: res := jl
832
    |IL.opLE, IL.opLEC: res := jle
833
    |IL.opEQ, IL.opEQC: res := je
834
    |IL.opNE, IL.opNEC: res := jne
835
    END
836
 
837
    RETURN res
838
END cond;
839
 
840
 
841
PROCEDURE GetRegA;
842
BEGIN
843
    ASSERT(REG.GetReg(R, ACC))
844
END GetRegA;
845
 
846
 
847
PROCEDURE MovConst (r, c: INTEGER);
848
BEGIN
849
    IF (0 <= c) & (c <= 255) THEN
850
        MovImm8(r, c)
851
    ELSIF (-255 <= c) & (c < 0) THEN
852
        MovImm8(r, -c);
853
        Neg(r)
854
    ELSIF UTILS.Log2(c) >= 0 THEN
855
        MovImm8(r, 1);
856
        LslImm(r, UTILS.Log2(c))
857
    ELSIF c = UTILS.min32 THEN
858
        MovImm8(r, 1);
859
        LslImm(r, 31)
860
    ELSE
861
        IF Target.InstrSet.thumb2 THEN
862
            movwt(r, low(c), 0);
863
            IF (c < 0) OR (c > 65535) THEN
864
                movwt(r, high(c), 1)
865
            END
866
        ELSE
867
            MovImm32(r, c)
868
        END
869
    END
870
END MovConst;
871
 
872
 
873
PROCEDURE CmpConst (r, c: INTEGER);
874
VAR
875
    r2: INTEGER;
876
 
877
BEGIN
878
    IF (0 <= c) & (c <= 255) THEN
879
        CmpImm8(r, c)
880
    ELSE
881
        r2 := GetAnyReg();
882
        ASSERT(r2 # r);
883
        MovConst(r2, c);
884
        Cmp(r, r2);
885
        drop
886
    END
887
END CmpConst;
888
 
889
 
890
PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
891
    RETURN offset + StkCount - ORD(offset > 0)
892
END LocalOffset;
893
 
894
 
895
PROCEDURE SetCC (cc, r: INTEGER);
896
VAR
897
    L1, L2: INTEGER;
898
 
899
BEGIN
900
    IF Target.InstrSet.it THEN
901
        Code(0BF00H + cc * 16 + ((cc + 1) MOD 2) * 8 + 4); (* ite cc *)
902
        MovConst(r, 1);
903
        MovConst(r, 0)
904
    ELSE
905
        L1 := NewLabel();
906
        L2 := NewLabel();
907
        jcc(cc, L1);
908
        MovConst(r, 0);
909
        jmp(L2);
910
        Label(L1);
911
        MovConst(r, 1);
912
        Label(L2)
913
    END
914
END SetCC;
915
 
916
 
917
PROCEDURE PushConst (n: INTEGER);
918
VAR
919
    r: INTEGER;
920
 
921
BEGIN
922
    r := GetAnyReg();
923
    MovConst(r, n);
924
    push(r);
925
    drop
926
END PushConst;
927
 
928
 
929
PROCEDURE AddConst (r, n: INTEGER);
930
VAR
931
    r2: INTEGER;
932
 
933
BEGIN
934
    IF n # 0 THEN
935
        IF (-255 <= n) & (n <= 255) THEN
936
            IF n > 0 THEN
937
                AddImm8(r, n)
938
            ELSE
939
                SubImm8(r, -n)
940
            END
941
        ELSIF Target.InstrSet.thumb2 & (-4095 <= n) & (n <= 4095) THEN
942
            IF n > 0 THEN
943
                AddSubImm12(r, n, FALSE)
944
            ELSE
945
                AddSubImm12(r, -n, TRUE)
946
            END
947
        ELSE
948
            r2 := GetAnyReg();
949
            ASSERT(r2 # r);
950
            IF n > 0 THEN
951
                MovConst(r2, n);
952
                AddReg(r, r, r2)
953
            ELSE
954
                MovConst(r2, -n);
955
                SubReg(r, r, r2)
956
            END;
957
            drop
958
        END
959
    END
960
END AddConst;
961
 
962
 
963
PROCEDURE AddHH (r1, r2: INTEGER);
964
BEGIN
965
    ASSERT((r1 >= 8) OR (r2 >= 8));
966
    gen5(0, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8)
967
END AddHH;
968
 
969
 
970
PROCEDURE AddSP (n: INTEGER);
971
BEGIN
972
    IF n > 0 THEN
973
        IF n < 127 THEN
974
            Code(0B000H + n) (*  add sp, n*4  *)
975
        ELSE
976
            ASSERT(R2 IN R.regs);
977
            MovConst(R2, n * 4);
978
            AddHH(SP, R2)
979
        END;
980
        DEC(StkCount, n)
981
    END
982
END AddSP;
983
 
984
 
985
PROCEDURE cbz (r, label: INTEGER);
986
BEGIN
987
    IF Target.InstrSet.cbxz THEN
988
        cbxz(je, r, label)
989
    ELSE
990
        Tst(r);
991
        jcc(je, label)
992
    END
993
END cbz;
994
 
995
 
996
PROCEDURE cbnz (r, label: INTEGER);
997
BEGIN
998
    IF Target.InstrSet.cbxz THEN
999
        cbxz(jne, r, label)
1000
    ELSE
1001
        Tst(r);
1002
        jcc(jne, label)
1003
    END
1004
END cbnz;
1005
 
1006
 
1007
PROCEDURE Shift (op, r1, r2: INTEGER);
1008
VAR
1009
    L: INTEGER;
1010
 
1011
BEGIN
1012
    LslImm(r2, 27);
1013
    LsrImm(r2, 27);
1014
    L := NewLabel();
1015
    cbz(r2, L);
1016
    CASE op OF
1017
    |IL.opLSL, IL.opLSL1: gen4(2, r2, r1)
1018
    |IL.opLSR, IL.opLSR1: gen4(3, r2, r1)
1019
    |IL.opASR, IL.opASR1: gen4(4, r2, r1)
1020
    |IL.opROR, IL.opROR1: gen4(7, r2, r1)
1021
    END;
1022
    Label(L)
1023
END Shift;
1024
 
1025
 
1026
PROCEDURE LocAdr (offs: INTEGER);
1027
VAR
1028
    r1, n: INTEGER;
1029
 
1030
BEGIN
1031
    r1 := GetAnyReg();
1032
    n := LocalOffset(offs);
1033
    IF n <= 255 THEN
1034
        gen12(TRUE, r1, n)
1035
    ELSE
1036
        MovConst(r1, n * 4);
1037
        AddHH(r1, SP)
1038
    END
1039
END LocAdr;
1040
 
1041
 
1042
PROCEDURE CallRTL (proc, par: INTEGER);
1043
BEGIN
1044
    call(IL.codes.rtl[proc]);
1045
    AddSP(par)
1046
END CallRTL;
1047
 
1048
 
1049
PROCEDURE divmod;
1050
BEGIN
1051
    call(sdivProc);
1052
    AddSP(2)
1053
END divmod;
1054
 
1055
 
1056
PROCEDURE translate (pic, stroffs: INTEGER);
1057
VAR
1058
    cmd, next: COMMAND;
1059
    opcode, param1, param2: INTEGER;
1060
 
1061
    r1, r2, r3: INTEGER;
1062
 
1063
    a, n, cc, L, L2: INTEGER;
1064
 
1065
BEGIN
1066
    cmd := IL.codes.commands.first(COMMAND);
1067
 
1068
    WHILE cmd # NIL DO
1069
 
1070
        param1 := cmd.param1;
1071
        param2 := cmd.param2;
1072
        opcode := cmd.opcode;
1073
 
1074
        CASE opcode OF
1075
 
1076
        |IL.opJMP:
1077
            jmp(param1)
1078
 
1079
        |IL.opLABEL:
1080
            Label(param1)
1081
 
1082
        |IL.opHANDLER:
1083
            IF param2 = 0 THEN
1084
                int0 := param1
1085
            ELSIF param2 = 1 THEN
1086
                trap := param1
1087
            ELSE
1088
                IVT[param2] := param1
1089
            END
1090
 
1091
        |IL.opCALL:
1092
            call(param1)
1093
 
1094
        |IL.opCALLP:
1095
            UnOp(r1);
8097 maxcodehac 1096
            AddImm8(r1, 1); (* Thumb mode *)
7983 leency 1097
            gen5(3, TRUE, FALSE, r1, 0); (* blx r1 *)
1098
            drop;
1099
            ASSERT(R.top = -1)
1100
 
1101
        |IL.opENTER:
1102
            ASSERT(R.top = -1);
1103
 
1104
            Label(param1);
1105
 
1106
            gen14(FALSE, TRUE, {}); (* push LR *)
1107
 
1108
            n := param2;
1109
            IF n >= 5 THEN
1110
                MovConst(ACC, 0);
1111
                MovConst(R2, n);
1112
                L := NewLabel();
1113
                Label(L);
1114
                push(ACC);
1115
                SubImm8(R2, 1);
1116
                Tst(R2);
1117
                jcc(jne, L)
1118
            ELSIF n > 0 THEN
1119
                MovConst(ACC, 0);
1120
                WHILE n > 0 DO
1121
                    push(ACC);
1122
                    DEC(n)
1123
                END
1124
            END;
1125
            StkCount := param2
1126
 
1127
        |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
1128
            IF opcode # IL.opLEAVE THEN
1129
                UnOp(r1);
1130
                IF r1 # ACC THEN
1131
                    GetRegA;
1132
                    ASSERT(REG.Exchange(R, r1, ACC));
1133
                    drop
1134
                END;
1135
                drop
1136
            END;
1137
 
1138
            ASSERT(R.top = -1);
1139
            ASSERT(StkCount = param1);
1140
 
1141
            AddSP(param1);
1142
            gen14(TRUE, TRUE, {}) (* pop PC *)
1143
 
1144
        |IL.opLEAVEC:
1145
            gen5(3, FALSE, TRUE, 6, 0) (* bx LR *)
1146
 
1147
        |IL.opPRECALL:
1148
            PushAll(0)
1149
 
1150
        |IL.opPARAM:
1151
            n := param2;
1152
            IF n = 1 THEN
1153
                UnOp(r1);
1154
                push(r1);
1155
                drop
1156
            ELSE
1157
                ASSERT(R.top + 1 <= n);
1158
                PushAll(n)
1159
            END
1160
 
1161
        |IL.opCLEANUP:
1162
            AddSP(param2)
1163
 
1164
        |IL.opRES, IL.opRESF:
1165
            ASSERT(R.top = -1);
1166
            GetRegA
1167
 
1168
        |IL.opPUSHC:
1169
            PushConst(param2)
1170
 
1171
        |IL.opONERR:
1172
            MovConst(R0, param2);
1173
            push(R0);
1174
            DEC(StkCount);
1175
            jmp(param1)
1176
 
1177
        |IL.opERR:
1178
            call(genTrap)
1179
 
8097 maxcodehac 1180
        |IL.opNOP, IL.opAND, IL.opOR:
7983 leency 1181
 
1182
        |IL.opSADR:
1183
            reloc(GetAnyReg(), BIN.RDATA + pic, stroffs + param2)
1184
 
1185
        |IL.opGADR:
1186
            reloc(GetAnyReg(), BIN.RBSS + pic, param2)
1187
 
1188
        |IL.opLADR:
1189
            LocAdr(param2)
1190
 
1191
        |IL.opGLOAD32:
1192
            r1 := GetAnyReg();
1193
            reloc(r1, BIN.RBSS + pic, param2);
1194
            Ldr32(r1, r1)
1195
 
1196
        |IL.opGLOAD16:
1197
            r1 := GetAnyReg();
1198
            reloc(r1, BIN.RBSS + pic, param2);
1199
            Ldr16(r1, r1)
1200
 
1201
        |IL.opGLOAD8:
1202
            r1 := GetAnyReg();
1203
            reloc(r1, BIN.RBSS + pic, param2);
1204
            Ldr8(r1, r1)
1205
 
1206
        |IL.opLLOAD32, IL.opVADR, IL.opVLOAD32:
1207
            r1 := GetAnyReg();
1208
            n := LocalOffset(param2);
1209
            IF n <= 255 THEN
1210
                LdrSp(r1, n)
1211
            ELSE
1212
                drop;
1213
                LocAdr(param2);
1214
                UnOp(r1);
1215
                Ldr32(r1, r1)
1216
            END;
1217
            IF opcode = IL.opVLOAD32 THEN
1218
                Ldr32(r1, r1)
1219
            END
1220
 
1221
        |IL.opLLOAD16:
1222
            LocAdr(param2);
1223
            UnOp(r1);
1224
            Ldr16(r1, r1)
1225
 
1226
        |IL.opLLOAD8:
1227
            LocAdr(param2);
1228
            UnOp(r1);
1229
            Ldr8(r1, r1)
1230
 
1231
        |IL.opLOAD32, IL.opLOADF:
1232
            UnOp(r1);
1233
            Ldr32(r1, r1)
1234
 
1235
        |IL.opLOAD16:
1236
            UnOp(r1);
1237
            Ldr16(r1, r1)
1238
 
1239
        |IL.opLOAD8:
1240
            UnOp(r1);
1241
            Ldr8(r1, r1)
1242
 
1243
        |IL.opVLOAD16:
1244
            LocAdr(param2);
1245
            UnOp(r1);
1246
            Ldr32(r1, r1);
1247
            Ldr16(r1, r1)
1248
 
1249
        |IL.opVLOAD8:
1250
            LocAdr(param2);
1251
            UnOp(r1);
1252
            Ldr32(r1, r1);
1253
            Ldr8(r1, r1)
1254
 
1255
        |IL.opSBOOL:
1256
            BinOp(r2, r1);
1257
            Tst(r2);
1258
            SetCC(jne, r2);
1259
            Str8(r2, r1);
1260
            drop;
1261
            drop
1262
 
1263
        |IL.opSBOOLC:
1264
            UnOp(r1);
1265
            r2 := GetAnyReg();
1266
            MovConst(r2, ORD(param2 # 0));
1267
            Str8(r2, r1);
1268
            drop;
1269
            drop
1270
 
1271
        |IL.opSAVEC:
1272
            UnOp(r1);
1273
            r2 := GetAnyReg();
1274
            MovConst(r2, param2);
1275
            Str32(r2, r1);
1276
            drop;
1277
            drop
1278
 
1279
        |IL.opSAVE16C:
1280
            UnOp(r1);
1281
            r2 := GetAnyReg();
1282
            MovConst(r2, low(param2));
1283
            Str16(r2, r1);
1284
            drop;
1285
            drop
1286
 
1287
        |IL.opSAVE8C:
1288
            UnOp(r1);
1289
            r2 := GetAnyReg();
1290
            MovConst(r2, param2 MOD 256);
1291
            Str8(r2, r1);
1292
            drop;
1293
            drop
1294
 
1295
        |IL.opSAVE, IL.opSAVE32, IL.opSAVEF:
1296
            BinOp(r2, r1);
1297
            Str32(r2, r1);
1298
            drop;
1299
            drop
1300
 
1301
        |IL.opSAVEFI:
1302
            BinOp(r2, r1);
1303
            Str32(r1, r2);
1304
            drop;
1305
            drop
1306
 
1307
        |IL.opSAVE16:
1308
            BinOp(r2, r1);
1309
            Str16(r2, r1);
1310
            drop;
1311
            drop
1312
 
1313
        |IL.opSAVE8:
1314
            BinOp(r2, r1);
1315
            Str8(r2, r1);
1316
            drop;
1317
            drop
1318
 
1319
        |IL.opSAVEP:
1320
            UnOp(r1);
1321
            r2 := GetAnyReg();
1322
            reloc(r2, BIN.RCODE + pic, param2);
1323
            Str32(r2, r1);
1324
            drop;
1325
            drop
1326
 
1327
        |IL.opPUSHP:
1328
            reloc(GetAnyReg(), BIN.RCODE + pic, param2)
1329
 
1330
        |IL.opEQB, IL.opNEB:
1331
            BinOp(r1, r2);
1332
            drop;
1333
 
1334
            L := NewLabel();
1335
            cbz(r1, L);
1336
            MovConst(r1, 1);
1337
            Label(L);
1338
 
1339
            L := NewLabel();
1340
            cbz(r2, L);
1341
            MovConst(r2, 1);
1342
            Label(L);
1343
 
1344
            Cmp(r1, r2);
1345
            IF opcode = IL.opEQB THEN
1346
                SetCC(je, r1)
1347
            ELSE
1348
                SetCC(jne, r1)
1349
            END
1350
 
1351
        |IL.opDROP:
1352
            UnOp(r1);
1353
            drop
1354
 
8097 maxcodehac 1355
        |IL.opJNZ1:
7983 leency 1356
            UnOp(r1);
1357
            cbnz(r1, param1)
1358
 
1359
        |IL.opJG:
1360
            UnOp(r1);
1361
            Tst(r1);
1362
            jcc(jg, param1)
1363
 
8097 maxcodehac 1364
        |IL.opJNZ:
7983 leency 1365
            UnOp(r1);
1366
            cbnz(r1, param1);
1367
            drop
1368
 
8097 maxcodehac 1369
        |IL.opJZ:
7983 leency 1370
            UnOp(r1);
1371
            cbz(r1, param1);
1372
            drop
1373
 
1374
        |IL.opSWITCH:
1375
            UnOp(r1);
1376
            IF param2 = 0 THEN
1377
                r2 := ACC
1378
            ELSE
1379
                r2 := R2
1380
            END;
1381
            IF r1 # r2 THEN
1382
                ASSERT(REG.GetReg(R, r2));
1383
                ASSERT(REG.Exchange(R, r1, r2));
1384
                drop
1385
            END;
1386
            drop
1387
 
1388
        |IL.opENDSW:
1389
 
1390
        |IL.opCASEL:
1391
            GetRegA;
1392
            CmpConst(ACC, param1);
1393
            jcc(jl, param2);
1394
            drop
1395
 
1396
        |IL.opCASER:
1397
            GetRegA;
1398
            CmpConst(ACC, param1);
1399
            jcc(jg, param2);
1400
            drop
1401
 
1402
        |IL.opCASELR:
1403
            GetRegA;
1404
            CmpConst(ACC, param1);
1405
            jcc(jl, param2);
1406
            jcc(jg, cmd.param3);
1407
            drop
1408
 
1409
        |IL.opCODE:
1410
            Code(param2)
1411
 
1412
        |IL.opEQ..IL.opGE,
1413
         IL.opEQC..IL.opGEC:
1414
            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
1415
                BinOp(r1, r2);
1416
                Cmp(r1, r2);
1417
                drop
1418
            ELSE
1419
                UnOp(r1);
1420
                CmpConst(r1, param2)
1421
            END;
1422
 
1423
            drop;
1424
            cc := cond(opcode);
1425
            next := cmd.next(COMMAND);
1426
 
8097 maxcodehac 1427
            IF next.opcode = IL.opJNZ THEN
7983 leency 1428
                jcc(cc, next.param1);
1429
                cmd := next
8097 maxcodehac 1430
            ELSIF next.opcode = IL.opJZ THEN
7983 leency 1431
                jcc(inv0(cc), next.param1);
1432
                cmd := next
1433
            ELSE
1434
                SetCC(cc, GetAnyReg())
1435
            END
1436
 
1437
        |IL.opINCC:
1438
            UnOp(r1);
1439
            r2 := GetAnyReg();
1440
            Ldr32(r2, r1);
1441
            AddConst(r2, param2);
1442
            Str32(r2, r1);
1443
            drop;
1444
            drop
1445
 
1446
        |IL.opINCCB, IL.opDECCB:
1447
            IF opcode = IL.opDECCB THEN
1448
                param2 := -param2
1449
            END;
1450
            UnOp(r1);
1451
            r2 := GetAnyReg();
1452
            Ldr8(r2, r1);
1453
            AddConst(r2, param2);
1454
            Str8(r2, r1);
1455
            drop;
1456
            drop
1457
 
1458
        |IL.opUMINUS:
1459
            UnOp(r1);
1460
            Neg(r1)
1461
 
1462
        |IL.opADD:
1463
            BinOp(r1, r2);
1464
            CASE cmd.next(COMMAND).opcode OF
1465
            |IL.opLOAD32, IL.opLOADF:
1466
                gen7(TRUE, FALSE, r2, r1, r1); (* ldr r1, [r1, r2] *)
1467
                cmd := cmd.next(COMMAND)
1468
            |IL.opLOAD8:
1469
                gen7(TRUE, TRUE, r2, r1, r1);  (* ldrb r1, [r1, r2] *)
1470
                cmd := cmd.next(COMMAND)
1471
            |IL.opLOAD16:
1472
                gen8(TRUE, FALSE, r2, r1, r1); (* ldrh r1, [r1, r2] *)
1473
                cmd := cmd.next(COMMAND)
1474
            ELSE
1475
                AddReg(r1, r1, r2)
1476
            END;
1477
            drop
1478
 
8097 maxcodehac 1479
        |IL.opADDC:
7983 leency 1480
            UnOp(r1);
1481
            AddConst(r1, param2)
1482
 
1483
        |IL.opSUB:
1484
            BinOp(r1, r2);
1485
            SubReg(r1, r1, r2);
1486
            drop
1487
 
1488
        |IL.opSUBL, IL.opSUBR:
1489
            UnOp(r1);
1490
            AddConst(r1, -param2);
1491
            IF opcode = IL.opSUBL THEN
1492
                Neg(r1)
1493
            END
1494
 
1495
        |IL.opMUL:
1496
            BinOp(r1, r2);
1497
            Mul(r1, r2);
1498
            drop
1499
 
1500
        |IL.opMULC:
1501
            UnOp(r1);
1502
 
1503
            a := param2;
1504
            IF a > 1 THEN
1505
                n := UTILS.Log2(a)
1506
            ELSIF a < -1 THEN
1507
                n := UTILS.Log2(-a)
1508
            ELSE
1509
                n := -1
1510
            END;
1511
 
1512
            IF a = 1 THEN
1513
 
1514
            ELSIF a = -1 THEN
1515
                Neg(r1)
1516
            ELSIF a = 0 THEN
1517
                MovConst(r1, 0)
1518
            ELSE
1519
                IF n > 0 THEN
1520
                    IF a < 0 THEN
1521
                        Neg(r1)
1522
                    END;
1523
                    LslImm(r1, n)
1524
                ELSE
1525
                    r2 := GetAnyReg();
1526
                    MovConst(r2, a);
1527
                    Mul(r1, r2);
1528
                    drop
1529
                END
1530
            END
1531
 
1532
        |IL.opABS:
1533
            UnOp(r1);
1534
            Tst(r1);
1535
            L := NewLabel();
1536
            jcc(jge, L);
1537
            Neg(r1);
1538
            Label(L)
1539
 
1540
        |IL.opNOT:
1541
            UnOp(r1);
1542
            Tst(r1);
1543
            SetCC(je, r1)
1544
 
1545
        |IL.opORD:
1546
            UnOp(r1);
1547
            Tst(r1);
1548
            SetCC(jne, r1)
1549
 
1550
        |IL.opCHR:
1551
            UnOp(r1);
1552
            Code(0B2C0H + r1 * 9) (* uxtb r1 *)
1553
 
1554
        |IL.opWCHR:
1555
            UnOp(r1);
1556
            Code(0B280H + r1 * 9) (* uxth r1 *)
1557
 
1558
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
1559
            BinOp(r1, r2);
1560
            Shift(opcode, r1, r2);
1561
            drop
1562
 
1563
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
1564
            MovConst(GetAnyReg(), param2);
1565
            BinOp(r2, r1);
1566
            Shift(opcode, r1, r2);
1567
            INCL(R.regs, r2);
1568
            DEC(R.top);
1569
            R.stk[R.top] := r1
1570
 
1571
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
1572
            n := param2 MOD 32;
1573
            IF n # 0 THEN
1574
                UnOp(r1);
1575
                CASE opcode OF
1576
                |IL.opASR2: AsrImm(r1, n)
1577
                |IL.opROR2: r2 := GetAnyReg(); MovConst(r2, n); Shift(IL.opROR, r1, r2); drop
1578
                |IL.opLSL2: LslImm(r1, n)
1579
                |IL.opLSR2: LsrImm(r1, n)
1580
                END
1581
            END
1582
 
1583
        |IL.opCHKBYTE:
1584
            BinOp(r1, r2);
1585
            CmpConst(r1, 256);
1586
            jcc(jb, param1)
1587
 
1588
        |IL.opCHKIDX:
1589
            UnOp(r1);
1590
            CmpConst(r1, param2);
1591
            jcc(jb, param1)
1592
 
1593
        |IL.opCHKIDX2:
1594
            BinOp(r1, r2);
1595
            IF param2 # -1 THEN
1596
                Cmp(r2, r1);
1597
                jcc(jb, param1)
1598
            END;
1599
            INCL(R.regs, r1);
1600
            DEC(R.top);
1601
            R.stk[R.top] := r2
1602
 
1603
        |IL.opLEN:
1604
            n := param2;
1605
            UnOp(r1);
1606
            drop;
1607
            EXCL(R.regs, r1);
1608
 
1609
            WHILE n > 0 DO
1610
                UnOp(r2);
1611
                drop;
1612
                DEC(n)
1613
            END;
1614
 
1615
            INCL(R.regs, r1);
1616
            ASSERT(REG.GetReg(R, r1))
1617
 
1618
        |IL.opLOOP, IL.opENDLOOP:
1619
 
1620
        |IL.opINF:
1621
            MovConst(GetAnyReg(), inf)
1622
 
1623
        |IL.opPUSHF:
1624
            UnOp(r1);
1625
            push(r1);
1626
            drop
1627
 
1628
        |IL.opCONST:
1629
            MovConst(GetAnyReg(), param2)
1630
 
1631
        |IL.opEQP, IL.opNEP:
1632
            reloc(GetAnyReg(), BIN.RCODE + pic, param1);
1633
            BinOp(r1, r2);
1634
            Cmp(r1, r2);
1635
            drop;
1636
            IF opcode = IL.opEQP THEN
1637
                SetCC(je, r1)
1638
            ELSE
1639
                SetCC(jne, r1)
1640
            END
1641
 
1642
        |IL.opPUSHT:
1643
            UnOp(r1);
1644
            r2 := GetAnyReg();
1645
            mov(r2, r1);
1646
            SubImm8(r2, 4);
1647
            Ldr32(r2, r2)
1648
 
1649
        |IL.opGET, IL.opGETC:
1650
            IF opcode = IL.opGET THEN
1651
                BinOp(r1, r2)
1652
            ELSIF opcode = IL.opGETC THEN
1653
                UnOp(r2);
1654
                r1 := GetAnyReg();
1655
                MovConst(r1, param1)
1656
            END;
1657
            drop;
1658
            drop;
1659
 
1660
            CASE param2 OF
1661
            |1: Ldr8(r1, r1); Str8(r1, r2)
1662
            |2: Ldr16(r1, r1); Str16(r1, r2)
1663
            |4: Ldr32(r1, r1); Str32(r1, r2)
1664
            END
1665
 
1666
        |IL.opINC, IL.opDEC:
1667
            BinOp(r2, r1);
1668
            r3 := GetAnyReg();
1669
            Ldr32(r3, r1);
1670
            IF opcode = IL.opINC THEN
1671
                AddReg(r3, r3, r2)
1672
            ELSE
1673
                SubReg(r3, r3, r2)
1674
            END;
1675
            Str32(r3, r1);
1676
            drop;
1677
            drop;
1678
            drop
1679
 
1680
        |IL.opINCB, IL.opDECB:
1681
            BinOp(r2, r1);
1682
            r3 := GetAnyReg();
1683
            Ldr8(r3, r1);
1684
            IF opcode = IL.opINCB THEN
1685
                AddReg(r3, r3, r2)
1686
            ELSE
1687
                SubReg(r3, r3, r2)
1688
            END;
1689
            Str8(r3, r1);
1690
            drop;
1691
            drop;
1692
            drop
1693
 
1694
        |IL.opMIN, IL.opMAX:
1695
            BinOp(r1, r2);
1696
            Cmp(r1, r2);
1697
            L := NewLabel();
1698
            IF opcode = IL.opMIN THEN
1699
                cc := jle
1700
            ELSE
1701
                cc := jge
1702
            END;
1703
            jcc(cc, L);
1704
            mov(r1, r2);
1705
            Label(L);
1706
            drop
1707
 
1708
        |IL.opMINC, IL.opMAXC:
1709
            UnOp(r1);
1710
            CmpConst(r1, param2);
1711
            L := NewLabel();
1712
            IF opcode = IL.opMINC THEN
1713
                cc := jle
1714
            ELSE
1715
                cc := jge
1716
            END;
1717
            jcc(cc, L);
1718
            MovConst(r1, param2);
1719
            Label(L)
1720
 
1721
        |IL.opMULS:
1722
            BinOp(r1, r2);
1723
            gen4(0, r2, r1); (* and r1, r2 *)
1724
            drop
1725
 
1726
        |IL.opMULSC:
1727
            MovConst(GetAnyReg(), param2);
1728
            BinOp(r1, r2);
1729
            gen4(0, r2, r1); (* and r1, r2 *)
1730
            drop
1731
 
1732
        |IL.opDIVS:
1733
            BinOp(r1, r2);
1734
            gen4(1, r2, r1); (* eor r1, r2 *)
1735
            drop
1736
 
1737
        |IL.opDIVSC:
1738
            MovConst(GetAnyReg(), param2);
1739
            BinOp(r1, r2);
1740
            gen4(1, r2, r1); (* eor r1, r2 *)
1741
            drop
1742
 
1743
        |IL.opADDS:
1744
            BinOp(r1, r2);
1745
            gen4(12, r2, r1); (* orr r1, r2 *)
1746
            drop
1747
 
1748
        |IL.opSUBS:
1749
            BinOp(r1, r2);
1750
            gen4(14, r2, r1); (* bic r1, r2 *)
1751
            drop
1752
 
8097 maxcodehac 1753
        |IL.opADDSC:
7983 leency 1754
            MovConst(GetAnyReg(), param2);
1755
            BinOp(r1, r2);
1756
            gen4(12, r2, r1); (* orr r1, r2 *)
1757
            drop
1758
 
1759
        |IL.opSUBSL:
1760
            MovConst(GetAnyReg(), param2);
1761
            BinOp(r1, r2);
1762
            gen4(14, r1, r2); (* bic r2, r1 *)
1763
            INCL(R.regs, r1);
1764
            DEC(R.top);
1765
            R.stk[R.top] := r2
1766
 
1767
        |IL.opSUBSR:
1768
            MovConst(GetAnyReg(), param2);
1769
            BinOp(r1, r2);
1770
            gen4(14, r2, r1); (* bic r1, r2 *)
1771
            drop
1772
 
1773
        |IL.opUMINS:
1774
            UnOp(r1);
1775
            gen4(15, r1, r1) (* mvn r1, r1 *)
1776
 
1777
        |IL.opINCL, IL.opEXCL:
1778
            BinOp(r1, r2);
1779
            r3 := GetAnyReg();
1780
            MovConst(r3, 1);
1781
            CmpConst(r1, 32);
1782
            L := NewLabel();
1783
            jcc(jnb, L);
1784
            gen4(2, r1, r3); (* lsl r3, r1 *)
1785
            Ldr32(r1, r2);
1786
            IF opcode = IL.opINCL THEN
1787
                gen4(12, r3, r1) (* orr r1, r3 *)
1788
            ELSE
1789
                gen4(14, r3, r1) (* bic r1, r3 *)
1790
            END;
1791
            Str32(r1, r2);
1792
            Label(L);
1793
            drop;
1794
            drop;
1795
            drop
1796
 
1797
        |IL.opINCLC, IL.opEXCLC:
1798
            UnOp(r2);
1799
            r1 := GetAnyReg();
1800
            r3 := GetAnyReg();
1801
            MovConst(r3, 1);
1802
            LslImm(r3, param2);
1803
            Ldr32(r1, r2);
1804
            IF opcode = IL.opINCLC THEN
1805
                gen4(12, r3, r1) (* orr r1, r3 *)
1806
            ELSE
1807
                gen4(14, r3, r1) (* bic r1, r3 *)
1808
            END;
1809
            Str32(r1, r2);
1810
            drop;
1811
            drop;
1812
            drop
1813
 
1814
        |IL.opLENGTH:
1815
            PushAll(2);
1816
            CallRTL(IL._length, 2);
1817
            GetRegA
1818
 
1819
        |IL.opLENGTHW:
1820
            PushAll(2);
1821
            CallRTL(IL._lengthw, 2);
1822
            GetRegA
1823
 
1824
        |IL.opSAVES:
1825
            UnOp(r2);
1826
            REG.PushAll_1(R);
1827
            r1 := GetAnyReg();
1828
            reloc(r1, BIN.RDATA + pic, stroffs + param2);
1829
            push(r1);
1830
            drop;
1831
            push(r2);
1832
            drop;
1833
            PushConst(param1);
1834
            CallRTL(IL._move, 3)
1835
 
1836
        |IL.opEQS .. IL.opGES:
1837
            PushAll(4);
1838
            PushConst(opcode - IL.opEQS);
1839
            CallRTL(IL._strcmp, 5);
1840
            GetRegA
1841
 
1842
        |IL.opEQSW .. IL.opGESW:
1843
            PushAll(4);
1844
            PushConst(opcode - IL.opEQSW);
1845
            CallRTL(IL._strcmpw, 5);
1846
            GetRegA
1847
 
1848
        |IL.opCOPY:
1849
            PushAll(2);
1850
            PushConst(param2);
1851
            CallRTL(IL._move, 3)
1852
 
1853
        |IL.opMOVE:
1854
            PushAll(3);
1855
            CallRTL(IL._move, 3)
1856
 
1857
        |IL.opCOPYA:
1858
            PushAll(4);
1859
            PushConst(param2);
1860
            CallRTL(IL._arrcpy, 5);
1861
            GetRegA
1862
 
1863
        |IL.opCOPYS:
1864
            PushAll(4);
1865
            PushConst(param2);
1866
            CallRTL(IL._strcpy, 5)
1867
 
1868
        |IL.opDIV:
1869
            PushAll(2);
1870
            divmod;
1871
            GetRegA
1872
 
1873
        |IL.opDIVL:
1874
            UnOp(r1);
1875
            REG.PushAll_1(R);
1876
            PushConst(param2);
1877
            push(r1);
1878
            drop;
1879
            divmod;
1880
            GetRegA
1881
 
1882
        |IL.opDIVR:
1883
            n := UTILS.Log2(param2);
1884
            IF n > 0 THEN
1885
                UnOp(r1);
1886
                AsrImm(r1, n)
1887
            ELSIF n < 0 THEN
1888
                PushAll(1);
1889
                PushConst(param2);
1890
                divmod;
1891
                GetRegA
1892
            END
1893
 
1894
        |IL.opMOD:
1895
            PushAll(2);
1896
            divmod;
1897
            mov(R0, R1);
1898
            GetRegA
1899
 
1900
        |IL.opMODR:
1901
            n := UTILS.Log2(param2);
1902
            IF n > 0 THEN
1903
                UnOp(r1);
1904
                IF n = 8 THEN
1905
                    Code(0B2C0H + r1 * 9) (* uxtb r1 *)
1906
                ELSIF n = 16 THEN
1907
                    Code(0B280H + r1 * 9) (* uxth r1 *)
1908
                ELSE
1909
                    LslImm(r1, 32 - n);
1910
                    LsrImm(r1, 32 - n)
1911
                END
1912
            ELSIF n < 0 THEN
1913
                PushAll(1);
1914
                PushConst(param2);
1915
                divmod;
1916
                mov(R0, R1);
1917
                GetRegA
1918
            ELSE
1919
                UnOp(r1);
1920
                MovConst(r1, 0)
1921
            END
1922
 
1923
        |IL.opMODL:
1924
            UnOp(r1);
1925
            REG.PushAll_1(R);
1926
            PushConst(param2);
1927
            push(r1);
1928
            drop;
1929
            divmod;
1930
            mov(R0, R1);
1931
            GetRegA
1932
 
1933
        |IL.opIN, IL.opINR:
1934
            IF opcode = IL.opINR THEN
1935
                r2 := GetAnyReg();
1936
                MovConst(r2, param2)
1937
            END;
1938
            L := NewLabel();
1939
            L2 := NewLabel();
1940
            BinOp(r1, r2);
1941
            r3 := GetAnyReg();
1942
            CmpConst(r1, 32);
1943
            jcc(jb, L);
1944
            MovConst(r1, 0);
1945
            jmp(L2);
1946
            Label(L);
1947
            MovConst(r3, 1);
1948
            Shift(IL.opLSL, r3, r1);
1949
            gen4(0, r3, r2); (* and r2, r3 *)
1950
            SetCC(jne, r1);
1951
            Label(L2);
1952
            drop;
1953
            drop
1954
 
1955
        |IL.opINL:
1956
            UnOp(r1);
1957
            r2 := GetAnyReg();
1958
            MovConst(r2, LSL(1, param2));
1959
            gen4(0, r2, r1); (* and r1, r2 *)
1960
            SetCC(jne, r1);
1961
            drop
1962
 
1963
        |IL.opRSET:
1964
            PushAll(2);
1965
            CallRTL(IL._set, 2);
1966
            GetRegA
1967
 
1968
        |IL.opRSETR:
1969
            PushAll(1);
1970
            PushConst(param2);
1971
            CallRTL(IL._set, 2);
1972
            GetRegA
1973
 
1974
        |IL.opRSETL:
1975
            UnOp(r1);
1976
            REG.PushAll_1(R);
1977
            PushConst(param2);
1978
            push(r1);
1979
            drop;
1980
            CallRTL(IL._set, 2);
1981
            GetRegA
1982
 
1983
        |IL.opRSET1:
1984
            PushAll(1);
1985
            CallRTL(IL._set1, 1);
1986
            GetRegA
1987
 
1988
        |IL.opCONSTF:
1989
            MovConst(GetAnyReg(), UTILS.d2s(cmd.float))
1990
 
1991
        |IL.opMULF:
1992
            PushAll(2);
1993
            CallRTL(IL._fmul, 2);
1994
            GetRegA
1995
 
1996
        |IL.opDIVF:
1997
            PushAll(2);
1998
            CallRTL(IL._fdiv, 2);
1999
            GetRegA
2000
 
2001
        |IL.opDIVFI:
2002
            PushAll(2);
2003
            CallRTL(IL._fdivi, 2);
2004
            GetRegA
2005
 
8097 maxcodehac 2006
        |IL.opADDF:
7983 leency 2007
            PushAll(2);
2008
            CallRTL(IL._fadd, 2);
2009
            GetRegA
2010
 
2011
        |IL.opSUBFI:
2012
            PushAll(2);
2013
            CallRTL(IL._fsubi, 2);
2014
            GetRegA
2015
 
2016
        |IL.opSUBF:
2017
            PushAll(2);
2018
            CallRTL(IL._fsub, 2);
2019
            GetRegA
2020
 
2021
        |IL.opEQF..IL.opGEF:
2022
            PushAll(2);
2023
            PushConst(opcode - IL.opEQF);
2024
            CallRTL(IL._fcmp, 3);
2025
            GetRegA
2026
 
2027
        |IL.opFLOOR:
2028
            PushAll(1);
2029
            CallRTL(IL._floor, 1);
2030
            GetRegA
2031
 
2032
        |IL.opFLT:
2033
            PushAll(1);
2034
            CallRTL(IL._flt, 1);
2035
            GetRegA
2036
 
2037
        |IL.opUMINF:
2038
            UnOp(r1);
2039
            r2 := GetAnyReg();
2040
            MovConst(r2, 1);
2041
            LslImm(r2, 31);
2042
            gen4(1, r2, r1); (* eor r1, r2 *)
2043
            drop
2044
 
2045
        |IL.opFABS:
2046
            UnOp(r1);
2047
            r2 := GetAnyReg();
2048
            MovConst(r2, 1);
2049
            LslImm(r2, 31);
2050
            gen4(14, r2, r1); (* bic r1, r2 *)
2051
            drop
2052
 
2053
        |IL.opNEW:
2054
            PushAll(1);
2055
            n := param2 + 8;
2056
            ASSERT(UTILS.Align(n, 32));
2057
            PushConst(n);
2058
            PushConst(param1);
2059
            CallRTL(IL._new, 3)
2060
 
2061
        |IL.opTYPEGP:
2062
            UnOp(r1);
2063
            PushAll(0);
2064
            push(r1);
2065
            PushConst(param2);
2066
            CallRTL(IL._guard, 2);
2067
            GetRegA
2068
 
2069
        |IL.opIS:
2070
            PushAll(1);
2071
            PushConst(param2);
2072
            CallRTL(IL._is, 2);
2073
            GetRegA
2074
 
2075
        |IL.opISREC:
2076
            PushAll(2);
2077
            PushConst(param2);
2078
            CallRTL(IL._guardrec, 3);
2079
            GetRegA
2080
 
2081
        |IL.opTYPEGR:
2082
            PushAll(1);
2083
            PushConst(param2);
2084
            CallRTL(IL._guardrec, 2);
2085
            GetRegA
2086
 
2087
        |IL.opTYPEGD:
2088
            UnOp(r1);
2089
            PushAll(0);
2090
            SubImm8(r1, 4);
2091
            Ldr32(r1, r1);
2092
            push(r1);
2093
            PushConst(param2);
2094
            CallRTL(IL._guardrec, 2);
2095
            GetRegA
2096
 
2097
        |IL.opCASET:
2098
            push(R2);
2099
            push(R2);
2100
            PushConst(param2);
2101
            CallRTL(IL._guardrec, 2);
2102
            pop(R2);
2103
            cbnz(ACC, param1)
2104
 
2105
        |IL.opROT:
2106
            PushAll(0);
2107
            mov(R2, SP);
2108
            push(R2);
2109
            PushConst(param2);
2110
            CallRTL(IL._rot, 2)
2111
 
2112
        |IL.opPACK:
2113
            PushAll(2);
2114
            CallRTL(IL._pack, 2)
2115
 
2116
        |IL.opPACKC:
2117
            PushAll(1);
2118
            PushConst(param2);
2119
            CallRTL(IL._pack, 2)
2120
 
2121
        |IL.opUNPK:
2122
            PushAll(2);
2123
            CallRTL(IL._unpk, 2)
2124
 
2125
        END;
2126
 
2127
        cmd := cmd.next(COMMAND)
2128
    END;
2129
 
2130
    ASSERT(R.pushed = 0);
2131
    ASSERT(R.top = -1)
2132
END translate;
2133
 
2134
 
2135
PROCEDURE prolog (GlobSize, tcount, pic, FlashAdr, sp, ivt_len: INTEGER);
2136
VAR
2137
    r1, r2, i, dcount: INTEGER;
2138
 
2139
BEGIN
2140
    entry := NewLabel();
2141
    emptyProc := NewLabel();
2142
    genInt := NewLabel();
2143
    genTrap := NewLabel();
2144
    sdivProc := NewLabel();
2145
 
2146
    trap := emptyProc;
2147
    int0 := emptyProc;
2148
 
2149
    IVT[0] := sp;
2150
    IVT[1] := entry;
2151
    FOR i := 2 TO ivt_len - 1 DO
2152
        IVT[i] := genInt
2153
    END;
2154
 
2155
    FOR i := 0 TO ivt_len - 1 DO
2156
        Code(low(IVT[i]));
2157
        Code(high(IVT[i]))
2158
    END;
2159
 
2160
    Label(entry);
2161
 
2162
    r1 := GetAnyReg();
2163
    r2 := GetAnyReg();
2164
    reloc(r1, BIN.RDATA + pic, 0);
2165
 
2166
    FOR i := 0 TO tcount - 1 DO
2167
        MovConst(r2, CHL.GetInt(IL.codes.types, i));
2168
        Str32(r2, r1);
2169
        AddImm8(r1, 4)
2170
    END;
2171
 
2172
    dcount := CHL.Length(IL.codes.data);
2173
    FOR i := 0 TO dcount - 1 BY 4 DO
2174
        MovConst(r2, BIN.get32le(IL.codes.data, i));
2175
        Str32(r2, r1);
2176
        AddImm8(r1, 4)
2177
    END;
2178
 
2179
    drop;
2180
    drop;
2181
 
2182
    r1 := GetAnyReg();
2183
    MovConst(r1, sp);
2184
    mov(SP, r1);
2185
    reloc(r1, BIN.RDATA + pic, 0);
2186
    push(r1);
2187
    reloc(r1, BIN.RBSS + pic, 0);
2188
    r2 := GetAnyReg();
2189
    MovConst(r2, GlobSize);
2190
    AddReg(r1, r1, r2);
2191
    drop;
2192
    push(r1);
2193
    drop;
2194
    PushConst(tcount);
2195
    CallRTL(IL._init, 3)
2196
END prolog;
2197
 
2198
 
2199
PROCEDURE epilog;
2200
VAR
2201
    L1, L2, L3, L4: INTEGER;
2202
 
2203
BEGIN
2204
    Code(0BF30H);  (* L2: wfi *)
2205
    Code(0E7FDH);  (* b L2    *)
2206
 
2207
    Label(genInt);
2208
    Code(0F3EFH); Code(08105H);  (* mrs r1, ipsr  *)
2209
    gen14(FALSE, TRUE, {R1});    (* push {LR, R1} *)
2210
    call(int0);
2211
    gen14(TRUE, TRUE, {R1});     (* pop {PC, R1}  *)
2212
 
2213
    Label(emptyProc);
2214
    Code(04770H);  (* bx lr *)
2215
 
2216
    Label(genTrap);
2217
    call(trap);
2218
    call(entry);
2219
 
2220
    Label(sdivProc);
2221
    IF Target.InstrSet.sdiv THEN
2222
        Code(09800H);  (* ldr  r0, [sp + #0] *)
2223
        Code(09901H);  (* ldr  r1, [sp + #4] *)
2224
        Code(0FB91H);  (* sdiv r2, r1, r0    *)
2225
        Code(0F2F0H);
2226
        Code(00013H);  (* mov  r3, r2        *)
2227
        Code(04343H);  (* mul  r3, r0        *)
2228
        Code(01AC9H);  (* sub  r1, r3        *)
2229
        Code(0DA01H);  (* bge  L             *)
2230
        Code(04401H);  (* add  r1, r0        *)
2231
        Code(03A01H);  (* sub  r2, #1        *)
2232
                       (* L:                 *)
2233
        Code(00010H);  (* mov  r0, r2        *)
2234
        Code(04770H);  (* bx   lr            *)
2235
    ELSE
2236
        (* a / b; a >= 0 *)
2237
        L1 := NewLabel();
2238
        L2 := NewLabel();
2239
        L3 := NewLabel();
2240
        L4 := NewLabel();
2241
 
2242
        LdrSp(R1, 1);
2243
        LdrSp(R2, 0);
2244
        MovConst(R0, 0);
2245
        push(R4);
2246
 
2247
        Label(L4);
2248
        Cmp(R1, R2);
2249
        jcc(jl, L1);
2250
        MovConst(R3, 2);
2251
        mov(R4, R2);
2252
        LslImm(R4, 1);
2253
        Label(L3);
2254
        Cmp(R1, R4);
2255
        jcc(jl, L2);
2256
        CmpConst(R4, 0);
2257
        jcc(jle, L2);
2258
        LslImm(R4, 1);
2259
        LslImm(R3, 1);
2260
        jmp(L3);
2261
        Label(L2);
2262
        LsrImm(R4, 1);
2263
        LsrImm(R3, 1);
2264
        SubReg(R1, R1, R4);
2265
        AddReg(R0, R0, R3);
2266
        jmp(L4);
2267
        Label(L1);
2268
 
2269
        (* a / b; a < 0 *)
2270
        L1 := NewLabel();
2271
        L2 := NewLabel();
2272
        L3 := NewLabel();
2273
        L4 := NewLabel();
2274
 
2275
        Label(L4);
2276
        CmpConst(R1, 0);
2277
        jcc(jge, L1);
2278
        MovConst(R3, 2);
2279
        mov(R4, R2);
2280
        LslImm(R4, 1);
2281
        Neg(R1);
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
        Neg(R1);
2292
        LsrImm(R4, 1);
2293
        LsrImm(R3, 1);
2294
        AddReg(R1, R1, R4);
2295
        SubReg(R0, R0, R3);
2296
        jmp(L4);
2297
        Label(L1);
2298
 
2299
        pop(R4);
2300
        Code(04770H);  (* bx lr *)
2301
    END
2302
 
2303
END epilog;
2304
 
2305
 
2306
PROCEDURE CortexM3;
2307
BEGIN
2308
    Target.FlashAdr := 08000000H;
2309
    Target.SRAMAdr  := 20000000H;
2310
    Target.IVTLen   := 256;
2311
    Target.Reserved := 0;
2312
    Target.MinStack := 512;
2313
    Target.InstrSet.thumb2 := TRUE;
2314
    Target.InstrSet.it     := TRUE;
2315
    Target.InstrSet.sdiv   := TRUE;
2316
    Target.InstrSet.cbxz   := TRUE
2317
END CortexM3;
2318
 
2319
 
2320
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
2321
VAR
2322
    opt: PROG.OPTIONS;
2323
 
2324
    ram, rom: INTEGER;
2325
 
2326
    DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER;
2327
 
2328
BEGIN
2329
    IF target = TARGETS.STM32CM3 THEN
2330
        CortexM3
2331
    END;
2332
 
2333
    ram := MIN(MAX(options.ram, STM32_minRAM), STM32_maxRAM) * 1024;
2334
    rom := MIN(MAX(options.rom, STM32_minROM), STM32_maxROM) * 1024;
2335
 
2336
    tcount := CHL.Length(IL.codes.types);
2337
 
2338
    opt := options;
2339
    CodeList := LISTS.create(NIL);
2340
 
2341
    program := BIN.create(IL.codes.lcount);
2342
 
2343
    REG.Init(R, push, pop, mov, xchg, NIL, NIL, {R0, R1, R2, R3}, {});
2344
 
2345
    StkCount := 0;
2346
 
2347
    DataAdr := Target.SRAMAdr + Target.Reserved;
2348
    DataSize := CHL.Length(IL.codes.data) + tcount * 4 + Target.Reserved;
2349
    WHILE DataSize MOD 4 # 0 DO
2350
        CHL.PushByte(IL.codes.data, 0);
2351
        INC(DataSize)
2352
    END;
2353
    BssAdr := DataAdr + DataSize - Target.Reserved;
2354
 
2355
    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4)));
2356
 
2357
    BssSize := IL.codes.bss;
2358
    ASSERT(UTILS.Align(BssSize, 4));
2359
 
2360
    prolog(BssSize, tcount, ORD(opt.pic), Target.FlashAdr, Target.SRAMAdr + ram, Target.IVTLen);
2361
    translate(ORD(opt.pic), tcount * 4);
2362
    epilog;
2363
 
2364
    fixup(Target.FlashAdr, DataAdr, BssAdr);
2365
 
2366
    INC(DataSize, BssSize);
2367
    CodeSize := CHL.Length(program.code);
2368
 
2369
    IF CodeSize > rom THEN
2370
        ERRORS.Error(203)
2371
    END;
2372
 
2373
    IF DataSize > ram - Target.MinStack THEN
2374
        ERRORS.Error(204)
2375
    END;
2376
 
8097 maxcodehac 2377
    WR.Create(outname);
7983 leency 2378
 
8097 maxcodehac 2379
    HEX.Data2(program.code, 0, CodeSize, high(Target.FlashAdr));
2380
    HEX.End;
7983 leency 2381
 
8097 maxcodehac 2382
    WR.Close;
7983 leency 2383
 
2384
    C.StringLn("--------------------------------------------");
2385
    C.String(  "  rom:  "); C.Int(CodeSize); C.String(" of "); C.Int(rom); C.String("  ("); C.Int(CodeSize * 100 DIV rom); C.StringLn("%)");
2386
    C.Ln;
2387
    C.String(  "  ram:  "); C.Int(DataSize); C.String(" of "); C.Int(ram);  C.String("  ("); C.Int(DataSize * 100 DIV ram);  C.StringLn("%)")
2388
 
2389
END CodeGen;
2390
 
2391
 
2392
PROCEDURE SetIV* (idx: INTEGER): BOOLEAN;
2393
VAR
2394
    res: BOOLEAN;
2395
 
2396
BEGIN
2397
    res := IVT[idx] = 0;
2398
    IVT[idx] := 1
2399
 
2400
    RETURN res
2401
END SetIV;
2402
 
2403
 
2404
PROCEDURE init;
2405
VAR
2406
    i: INTEGER;
2407
 
2408
BEGIN
2409
    FOR i := 0 TO LEN(IVT) - 1 DO
2410
        IVT[i] := 0
2411
    END
2412
END init;
2413
 
2414
 
2415
BEGIN
2416
    init
2417
END THUMB.