OpenCores
URL https://opencores.org/ocsvn/raptor64/raptor64/trunk

Subversion Repositories raptor64

[/] [raptor64/] [trunk/] [software/] [c64/] [source/] [Analyze.c] - Blame information for rev 37

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 37 robfinch
#include        <stdio.h>
2
#include        "c.h"
3
#include        "expr.h"
4
#include "Statement.h"
5
#include        "gen.h"
6
#include        "cglbdec.h"
7
 
8
/*
9
 *      68000 C compiler
10
 *
11
 *      Copyright 1984, 1985, 1986 Matthew Brandt.
12
 *  all commercial rights reserved.
13
 *
14
 *      This compiler is intended as an instructive tool for personal use. Any
15
 *      use for profit without the written consent of the author is prohibited.
16
 *
17
 *      This compiler may be distributed freely for non-commercial use as long
18
 *      as this notice stays intact. Please forward any enhancements or questions
19
 *      to:
20
 *
21
 *              Matthew Brandt
22
 *              Box 920337
23
 *              Norcross, Ga 30092
24
 */
25
 
26
/*******************************************************
27
        Modified to support Raptor64 'C64' language
28
        by Robert Finch
29
        robfinch@opencores.org
30
*******************************************************/
31
 
32
extern int popcnt(int m);
33
 
34
/*
35
 *      this module will step through the parse tree and find all
36
 *      optimizable expressions. at present these expressions are
37
 *      limited to expressions that are valid throughout the scope
38
 *      of the function. the list of optimizable expressions is:
39
 *
40
 *              constants
41
 *              global and static addresses
42
 *              auto addresses
43
 *              contents of auto addresses.
44
 *
45
 *      contents of auto addresses are valid only if the address is
46
 *      never referred to without dereferencing.
47
 *
48
 *      scan will build a list of optimizable expressions which
49
 *      opt1 will replace during the second optimization pass.
50
 */
51
 
52
static CSE *olist;         /* list of optimizable expressions */
53
 
54
/*
55
 *      equalnode will return 1 if the expressions pointed to by
56
 *      node1 and node2 are equivalent.
57
 */
58
static int equalnode(ENODE *node1, ENODE *node2)
59
{
60
//      if( node1 == 0 || node2 == 0 )
61
//                return 0;
62
//        if( node1->nodetype != node2->nodetype )
63
//                return 0;
64
//        if( (node1->nodetype == en_icon || node1->nodetype == en_labcon ||
65
//            node1->nodetype == en_nacon || node1->nodetype == en_autocon) &&
66
//            node1->v.i == node2->v.i )
67
//                return 1;
68
//        if( IsLValue(node1) && equalnode(node1->v.p[0], node2->v.p[0]) )
69
//                return 1;
70
//        return 0;
71
//}
72
    if (node1 == NULL || node2 == NULL)
73
                return FALSE;
74
    if (node1->nodetype != node2->nodetype)
75
                return FALSE;
76
    switch (node1->nodetype) {
77
      case en_icon:
78
      case en_labcon:
79
      case en_autocon:
80
                        return (node1->i == node2->i);
81
      case en_nacon:
82
                        return (!strcmp(node1->sp, node2->sp));
83
      default:
84
                if( IsLValue(node1) && equalnode(node1->p[0], node2->p[0])  )
85
                        return TRUE;
86
                return FALSE;
87
    }
88
}
89
 
90
/*
91
 *      SearchCSEList will search the common expression table for an entry
92
 *      that matches the node passed and return a pointer to it.
93
 */
94
static CSE *SearchCSEList(ENODE *node)
95
{
96
        CSE *csp;
97
 
98
    csp = olist;
99
    while( csp != NULL ) {
100
        if( equalnode(node,csp->exp) )
101
            return csp;
102
        csp = csp->next;
103
    }
104
    return NULL;
105
}
106
 
107
/*
108
 *      copy the node passed into a new enode so it wont get
109
 *      corrupted during substitution.
110
 */
111
static ENODE *DuplicateEnode(ENODE *node)
112
{
113
        ENODE *temp;
114
 
115
    if( node == NULL )
116
        return NULL;
117
    temp = allocEnode();
118
        memcpy(temp,node,sizeof(ENODE));        // copy all the fields
119
    return temp;
120
}
121
 
122
/*
123
 *      InsertNodeIntoCSEList will enter a reference to an expression node into the
124
 *      common expression table. duse is a flag indicating whether or not
125
 *      this reference will be dereferenced.
126
 */
127
CSE *InsertNodeIntoCSEList(ENODE *node, int duse)
128
{
129
        CSE *csp;
130
 
131
    if( (csp = SearchCSEList(node)) == NULL ) {   /* add to tree */
132
        csp = allocCSE();
133
        csp->next = olist;
134
        csp->uses = 1;
135
        csp->duses = (duse != 0);
136
        csp->exp = DuplicateEnode(node);
137
        csp->voidf = 0;
138
                csp->reg = 0;
139
        olist = csp;
140
        return csp;
141
    }
142
    ++(csp->uses);
143
    if( duse )
144
            ++(csp->duses);
145
    return csp;
146
}
147
 
148
/*
149
 *      voidauto will void an auto dereference node which points to
150
 *      the same auto constant as node.
151
 */
152
CSE *voidauto(ENODE *node)
153
{
154
        CSE *csp;
155
 
156
        csp = olist;
157
    while( csp != NULL ) {
158
        if( IsLValue(csp->exp) && equalnode(node,csp->exp->p[0]) ) {
159
            if( csp->voidf )
160
                 return NULL;
161
            csp->voidf = 1;
162
            return csp;
163
        }
164
        csp = csp->next;
165
    }
166
    return NULL;
167
}
168
 
169
/*
170
 *      scanexpr will scan the expression pointed to by node for optimizable
171
 *      subexpressions. when an optimizable expression is found it is entered
172
 *      into the tree. if a reference to an autocon node is scanned the
173
 *      corresponding auto dereferenced node will be voided. duse should be
174
 *      set if the expression will be dereferenced.
175
 */
176
static void scanexpr(ENODE *node, int duse)
177
{
178
        CSE *csp, *csp1;
179
 
180
    if( node == NULL )
181
        return;
182
 
183
        switch( node->nodetype ) {
184
        case en_icon:
185
        case en_labcon:
186
        case en_nacon:
187
                InsertNodeIntoCSEList(node,duse);
188
                break;
189
        case en_autocon:
190
                if( (csp = voidauto(node)) != NULL ) {
191
                    csp1 = InsertNodeIntoCSEList(node,duse);
192
                    csp1->uses = (csp1->duses += csp->uses);
193
                    }
194
                else
195
                    InsertNodeIntoCSEList(node,duse);
196
                break;
197
        case en_b_ref:
198
                case en_c_ref:
199
                case en_h_ref:
200
        case en_w_ref:
201
        case en_ub_ref:
202
                case en_uc_ref:
203
                case en_uh_ref:
204
        case en_uw_ref:
205
                case en_bfieldref:
206
                case en_ubfieldref:
207
                case en_cfieldref:
208
                case en_ucfieldref:
209
                case en_hfieldref:
210
                case en_uhfieldref:
211
                case en_wfieldref:
212
                case en_uwfieldref:
213
                if( node->p[0]->nodetype == en_autocon ) {
214
                        csp = InsertNodeIntoCSEList(node,duse);
215
                        if( csp->voidf )
216
                                scanexpr(node->p[0],1);
217
                        }
218
                else
219
                        scanexpr(node->p[0],1);
220
                break;
221
        case en_cbc:
222
                case en_cbh:
223
                case en_cbw:
224
                case en_cch:
225
                case en_ccw:
226
                case en_chw:
227
        case en_uminus:
228
        case en_compl:  case en_ainc:
229
        case en_adec:   case en_not:
230
                scanexpr(node->p[0],duse);
231
                break;
232
        case en_asadd:  case en_assub:
233
        case en_add:    case en_sub:
234
                scanexpr(node->p[0],duse);
235
                scanexpr(node->p[1],duse);
236
                break;
237
                case en_mul:    case en_mulu:   case en_div:    case en_udiv:
238
                case en_shl:    case en_shr:    case en_shru:
239
        case en_mod:    case en_and:
240
        case en_or:     case en_xor:
241
        case en_lor:    case en_land:
242
        case en_eq:     case en_ne:
243
        case en_gt:     case en_ge:
244
        case en_lt:     case en_le:
245
        case en_asmul:  case en_asdiv:
246
        case en_asmod:  case en_aslsh:
247
                case en_asrsh:
248
                case en_asand:  case en_asxor: case en_asor:
249
                case en_cond:
250
        case en_void:   case en_assign:
251
                scanexpr(node->p[0],0);
252
                scanexpr(node->p[1],0);
253
                break;
254
        case en_fcall:
255
                scanexpr(node->p[0],1);
256
                scanexpr(node->p[1],0);
257
                break;
258
        }
259
}
260
 
261
/*
262
 *      scan will gather all optimizable expressions into the expression
263
 *      list for a block of statements.
264
 */
265
static void scan(Statement *block)
266
{
267
        while( block != NULL ) {
268
        switch( block->stype ) {
269
            case st_return:
270
                        case st_throw:
271
            case st_expr:
272
                    opt4(&block->exp);
273
                    scanexpr(block->exp,0);
274
                    break;
275
            case st_while:
276
                        case st_until:
277
            case st_do:
278
                        case st_dountil:
279
                    opt4(&block->exp);
280
                    scanexpr(block->exp,0);
281
                        case st_doloop:
282
                        case st_forever:
283
                    scan(block->s1);
284
                    break;
285
            case st_for:
286
                    opt4(&block->initExpr);
287
                    scanexpr(block->initExpr,0);
288
                    opt4(&block->exp);
289
                    scanexpr(block->exp,0);
290
                    scan(block->s1);
291
                    opt4(&block->incrExpr);
292
                    scanexpr(block->incrExpr,0);
293
                    break;
294
            case st_if:
295
                    opt4(&block->exp);
296
                    scanexpr(block->exp,0);
297
                    scan(block->s1);
298
                    scan(block->s2);
299
                    break;
300
            case st_switch:
301
                    opt4(&block->exp);
302
                    scanexpr(block->exp,0);
303
                    scan(block->s1);
304
                    break;
305
            case st_case:
306
                    scan(block->s1);
307
                    break;
308
            case st_spinlock:
309
                    scan(block->s1);
310
                    break;
311
        }
312
        block = block->next;
313
    }
314
}
315
 
316
/*
317
 *      exchange will exchange the order of two expression entries
318
 *      following c1 in the linked list.
319
 */
320
static void exchange(CSE **c1)
321
{
322
        CSE *csp1, *csp2;
323
 
324
    csp1 = *c1;
325
    csp2 = csp1->next;
326
    csp1->next = csp2->next;
327
    csp2->next = csp1;
328
    *c1 = csp2;
329
}
330
 
331
/*
332
 *      returns the desirability of optimization for a subexpression.
333
 */
334
int OptimizationDesireability(CSE *csp)
335
{
336
        if( csp->voidf || (csp->exp->nodetype == en_icon &&
337
                       csp->exp->i < 256 && csp->exp->i >= 0))
338
        return 0;
339
    if( IsLValue(csp->exp) )
340
            return 2 * csp->uses;
341
    return csp->uses;
342
}
343
 
344
/*
345
 *      bsort implements a bubble sort on the expression list.
346
 */
347
int bsort(CSE **list)
348
{
349
        CSE *csp1, *csp2;
350
    int i;
351
 
352
    csp1 = *list;
353
    if( csp1 == NULL || csp1->next == NULL )
354
        return FALSE;
355
    i = bsort( &(csp1->next));
356
    csp2 = csp1->next;
357
    if( OptimizationDesireability(csp1) < OptimizationDesireability(csp2) ) {
358
        exchange(list);
359
        return TRUE;
360
    }
361
    return FALSE;
362
}
363
 
364
/*
365
 *      AllocateRegisterVars will allocate registers for the expressions that have
366
 *      a high enough desirability.
367
 */
368
void AllocateRegisterVars()
369
{
370
        CSE *csp;
371
    ENODE *exptr;
372
    int reg, mask, rmask;
373
    AMODE *ap, *ap2;
374
        int nn;
375
 
376
        reg = 11;
377
    mask = 0;
378
        rmask = 0;
379
    while( bsort(&olist) );         /* sort the expression list */
380
    csp = olist;
381
    while( csp != NULL ) {
382
        if( OptimizationDesireability(csp) < 3 )        // was < 3
383
            csp->reg = -1;
384
//        else if( csp->duses > csp->uses / 8 && reg < 18 )     // was / 4
385
        else if( reg < 18 )     // was / 4
386
            csp->reg = reg++;
387
        else
388
            csp->reg = -1;
389
        if( csp->reg != -1 )
390
                {
391
                        rmask = rmask | (1 << (31 - csp->reg));
392
            mask = mask | (1 << csp->reg);
393
                }
394
        csp = csp->next;
395
    }
396
        if( mask != 0 ) {
397
                if (bitsset(rmask) < 2) {
398
                        for (nn = 0; nn < 32; nn++)
399
                                if (rmask & (0x80000000 >> nn)) {
400
                                        GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(8));
401
                                        GenerateTriadic(op_sw,0,makereg(nn&31),make_indirect(30),NULL);
402
                                }
403
                }
404
                else {
405
                        GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(popcnt(mask)*8));
406
            GenerateDiadic(op_sm,0,make_indirect(30),make_mask(mask),NULL);
407
                }
408
        }
409
    save_mask = mask;
410
    csp = olist;
411
    while( csp != NULL ) {
412
            if( csp->reg != -1 )
413
                    {               /* see if preload needed */
414
                    exptr = csp->exp;
415
                    if( !IsLValue(exptr) || (exptr->p[0]->i > 0) )
416
                            {
417
                            initstack();
418
                            ap = GenerateExpression(exptr,F_REG|F_IMMED,8);
419
                            ap2 = makereg(csp->reg);
420
                                                        if (ap->mode==am_immed)
421
                                                                GenerateTriadic(op_ori,0,ap2,makereg(0),ap);
422
                                                        else
423
                                                                GenerateDiadic(op_mov,0,ap2,ap);
424
                            ReleaseTempRegister(ap);
425
                            }
426
                    }
427
            csp = csp->next;
428
            }
429
}
430
 
431
/*
432
 *      repexpr will replace all allocated references within an expression
433
 *      with tempref nodes.
434
 */
435
void repexpr(ENODE *node)
436
{
437
        struct cse      *csp;
438
        if( node == NULL )
439
                return;
440
        switch( node->nodetype ) {
441
                case en_icon:
442
                case en_nacon:
443
                case en_labcon:
444
                case en_autocon:
445
                        if( (csp = SearchCSEList(node)) != NULL )
446
                                if( csp->reg > 0 ) {
447
                                        node->nodetype = en_regvar;
448
                                        node->i = csp->reg;
449
                                        }
450
                        break;
451
                case en_b_ref:
452
                                case en_c_ref:
453
                                case en_h_ref:
454
                case en_w_ref:
455
                case en_ub_ref:
456
                                case en_uc_ref:
457
                                case en_uh_ref:
458
                case en_uw_ref:
459
                                case en_bfieldref:
460
                                case en_ubfieldref:
461
                                case en_cfieldref:
462
                                case en_ucfieldref:
463
                                case en_hfieldref:
464
                                case en_uhfieldref:
465
                                case en_wfieldref:
466
                                case en_uwfieldref:
467
                        if( (csp = SearchCSEList(node)) != NULL ) {
468
                                if( csp->reg > 0 ) {
469
                                        node->nodetype = en_regvar;
470
                                        node->i = csp->reg;
471
                                        }
472
                                else
473
                                        repexpr(node->p[0]);
474
                                }
475
                        else
476
                                repexpr(node->p[0]);
477
                        break;
478
                                case en_cbc:
479
                                case en_cbh:
480
                case en_cbw:
481
                                case en_cch:
482
                                case en_ccw:
483
                                case en_chw:
484
                case en_uminus:
485
                case en_not:    case en_compl:
486
                case en_ainc:   case en_adec:
487
                        repexpr(node->p[0]);
488
                        break;
489
                case en_add:    case en_sub:
490
                                case en_mul:    case en_mulu:   case en_div:    case en_udiv:
491
                                case en_mod:    case en_shl:    case en_shru:
492
                case en_shr:    case en_and:
493
                case en_or:     case en_xor:
494
                case en_land:   case en_lor:
495
                case en_eq:     case en_ne:
496
                case en_lt:     case en_le:
497
                case en_gt:     case en_ge:
498
                case en_cond:   case en_void:
499
                case en_asadd:  case en_assub:
500
                case en_asmul:  case en_asdiv:
501
                case en_asor:   case en_asand:
502
                case en_asmod:  case en_aslsh:
503
                case en_asrsh:  case en_fcall:
504
                case en_assign:
505
                        repexpr(node->p[0]);
506
                        repexpr(node->p[1]);
507
                        break;
508
                }
509
}
510
 
511
/*
512
 *      repcse will scan through a block of statements replacing the
513
 *      optimized expressions with their temporary references.
514
 */
515
void repcse(Statement *block)
516
{
517
        while( block != NULL ) {
518
        switch( block->stype ) {
519
                        case st_return:
520
                        case st_throw:
521
                                        repexpr(block->exp);
522
                                        break;
523
                        case st_expr:
524
                                        repexpr(block->exp);
525
                                        break;
526
                        case st_while:
527
                        case st_until:
528
                        case st_do:
529
                        case st_dountil:
530
                                        repexpr(block->exp);
531
                        case st_doloop:
532
                        case st_forever:
533
                                        repcse(block->s1);
534
                                        repcse(block->s2);
535
                                        break;
536
                        case st_for:
537
                                        repexpr(block->initExpr);
538
                                        repexpr(block->exp);
539
                                        repcse(block->s1);
540
                                        repexpr(block->incrExpr);
541
                                        break;
542
                        case st_if:
543
                                        repexpr(block->exp);
544
                                        repcse(block->s1);
545
                                        repcse(block->s2);
546
                                        break;
547
                        case st_switch:
548
                                        repexpr(block->exp);
549
                                        repcse(block->s1);
550
                                        break;
551
                        case st_try:
552
                        case st_catch:
553
                        case st_case:
554
                                        repcse(block->s1);
555
                                        break;
556
                        case st_spinlock:
557
                                        repcse(block->s1);
558
                                        repcse(block->s2);      // lockfail statement
559
                                        break;
560
        }
561
        block = block->next;
562
    }
563
}
564
 
565
/*
566
 *      opt1 is the externally callable optimization routine. it will
567
 *      collect and allocate common subexpressions and substitute the
568
 *      tempref for all occurrances of the expression within the block.
569
 *
570
 *              optimizer is currently turned off...
571
 */
572
void opt1(Statement *block)
573
{
574
        olist = NULL;
575
    scan(block);            /* collect expressions */
576
    AllocateRegisterVars();             /* allocate registers */
577
    repcse(block);          /* replace allocated expressions */
578
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.