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

Subversion Repositories raptor64

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

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 51 robfinch
        case en_ugt:    case en_uge:
246
        case en_ult:    case en_ule:
247 37 robfinch
        case en_asmul:  case en_asdiv:
248
        case en_asmod:  case en_aslsh:
249
                case en_asrsh:
250
                case en_asand:  case en_asxor: case en_asor:
251
                case en_cond:
252
        case en_void:   case en_assign:
253
                scanexpr(node->p[0],0);
254
                scanexpr(node->p[1],0);
255
                break;
256
        case en_fcall:
257
                scanexpr(node->p[0],1);
258
                scanexpr(node->p[1],0);
259
                break;
260
        }
261
}
262
 
263
/*
264
 *      scan will gather all optimizable expressions into the expression
265
 *      list for a block of statements.
266
 */
267
static void scan(Statement *block)
268
{
269
        while( block != NULL ) {
270
        switch( block->stype ) {
271
            case st_return:
272
                        case st_throw:
273
            case st_expr:
274
                    opt4(&block->exp);
275
                    scanexpr(block->exp,0);
276
                    break;
277
            case st_while:
278
                        case st_until:
279
            case st_do:
280
                        case st_dountil:
281
                    opt4(&block->exp);
282
                    scanexpr(block->exp,0);
283
                        case st_doloop:
284
                        case st_forever:
285
                    scan(block->s1);
286
                    break;
287
            case st_for:
288
                    opt4(&block->initExpr);
289
                    scanexpr(block->initExpr,0);
290
                    opt4(&block->exp);
291
                    scanexpr(block->exp,0);
292
                    scan(block->s1);
293
                    opt4(&block->incrExpr);
294
                    scanexpr(block->incrExpr,0);
295
                    break;
296
            case st_if:
297
                    opt4(&block->exp);
298
                    scanexpr(block->exp,0);
299
                    scan(block->s1);
300
                    scan(block->s2);
301
                    break;
302
            case st_switch:
303
                    opt4(&block->exp);
304
                    scanexpr(block->exp,0);
305
                    scan(block->s1);
306
                    break;
307
            case st_case:
308
                    scan(block->s1);
309
                    break;
310
            case st_spinlock:
311
                    scan(block->s1);
312 51 robfinch
                    scan(block->s2);
313 37 robfinch
                    break;
314
        }
315
        block = block->next;
316
    }
317
}
318
 
319
/*
320
 *      exchange will exchange the order of two expression entries
321
 *      following c1 in the linked list.
322
 */
323
static void exchange(CSE **c1)
324
{
325
        CSE *csp1, *csp2;
326
 
327
    csp1 = *c1;
328
    csp2 = csp1->next;
329
    csp1->next = csp2->next;
330
    csp2->next = csp1;
331
    *c1 = csp2;
332
}
333
 
334
/*
335
 *      returns the desirability of optimization for a subexpression.
336
 */
337
int OptimizationDesireability(CSE *csp)
338
{
339
        if( csp->voidf || (csp->exp->nodetype == en_icon &&
340
                       csp->exp->i < 256 && csp->exp->i >= 0))
341
        return 0;
342
    if( IsLValue(csp->exp) )
343
            return 2 * csp->uses;
344
    return csp->uses;
345
}
346
 
347
/*
348
 *      bsort implements a bubble sort on the expression list.
349
 */
350
int bsort(CSE **list)
351
{
352
        CSE *csp1, *csp2;
353
    int i;
354
 
355
    csp1 = *list;
356
    if( csp1 == NULL || csp1->next == NULL )
357
        return FALSE;
358
    i = bsort( &(csp1->next));
359
    csp2 = csp1->next;
360
    if( OptimizationDesireability(csp1) < OptimizationDesireability(csp2) ) {
361
        exchange(list);
362
        return TRUE;
363
    }
364
    return FALSE;
365
}
366
 
367
/*
368
 *      AllocateRegisterVars will allocate registers for the expressions that have
369
 *      a high enough desirability.
370
 */
371
void AllocateRegisterVars()
372
{
373
        CSE *csp;
374
    ENODE *exptr;
375
    int reg, mask, rmask;
376
    AMODE *ap, *ap2;
377
        int nn;
378 51 robfinch
        int cnt;
379 37 robfinch
 
380
        reg = 11;
381
    mask = 0;
382
        rmask = 0;
383
    while( bsort(&olist) );         /* sort the expression list */
384
    csp = olist;
385
    while( csp != NULL ) {
386
        if( OptimizationDesireability(csp) < 3 )        // was < 3
387
            csp->reg = -1;
388 51 robfinch
//        else if( csp->duses > csp->uses / 4 && reg < 18 )
389 37 robfinch
        else if( reg < 18 )     // was / 4
390
            csp->reg = reg++;
391
        else
392
            csp->reg = -1;
393
        if( csp->reg != -1 )
394
                {
395
                        rmask = rmask | (1 << (31 - csp->reg));
396
            mask = mask | (1 << csp->reg);
397
                }
398
        csp = csp->next;
399
    }
400
        if( mask != 0 ) {
401 51 robfinch
                cnt = 0;
402
                GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(bitsset(rmask)*8));
403
                for (nn = 0; nn < 32; nn++) {
404
                        if (rmask & (0x80000000 >> nn)) {
405
                                GenerateTriadic(op_sw,0,makereg(nn&31),make_indexed(cnt,30),NULL);
406
                                cnt+=8;
407
                        }
408 37 robfinch
                }
409 51 robfinch
                //else {
410
                //      GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(popcnt(mask)*8));
411
  //          GenerateDiadic(op_sm,0,make_indirect(30),make_mask(mask),NULL);
412
                //}
413 37 robfinch
        }
414
    save_mask = mask;
415
    csp = olist;
416
    while( csp != NULL ) {
417
            if( csp->reg != -1 )
418
                    {               /* see if preload needed */
419
                    exptr = csp->exp;
420
                    if( !IsLValue(exptr) || (exptr->p[0]->i > 0) )
421
                            {
422
                            initstack();
423
                            ap = GenerateExpression(exptr,F_REG|F_IMMED,8);
424
                            ap2 = makereg(csp->reg);
425
                                                        if (ap->mode==am_immed)
426
                                                                GenerateTriadic(op_ori,0,ap2,makereg(0),ap);
427
                                                        else
428
                                                                GenerateDiadic(op_mov,0,ap2,ap);
429
                            ReleaseTempRegister(ap);
430
                            }
431
                    }
432
            csp = csp->next;
433
            }
434
}
435
 
436
/*
437
 *      repexpr will replace all allocated references within an expression
438
 *      with tempref nodes.
439
 */
440
void repexpr(ENODE *node)
441
{
442
        struct cse      *csp;
443
        if( node == NULL )
444
                return;
445
        switch( node->nodetype ) {
446
                case en_icon:
447
                case en_nacon:
448
                case en_labcon:
449
                case en_autocon:
450
                        if( (csp = SearchCSEList(node)) != NULL )
451
                                if( csp->reg > 0 ) {
452
                                        node->nodetype = en_regvar;
453
                                        node->i = csp->reg;
454
                                        }
455
                        break;
456
                case en_b_ref:
457
                                case en_c_ref:
458
                                case en_h_ref:
459
                case en_w_ref:
460
                case en_ub_ref:
461
                                case en_uc_ref:
462
                                case en_uh_ref:
463
                case en_uw_ref:
464
                                case en_bfieldref:
465
                                case en_ubfieldref:
466
                                case en_cfieldref:
467
                                case en_ucfieldref:
468
                                case en_hfieldref:
469
                                case en_uhfieldref:
470
                                case en_wfieldref:
471
                                case en_uwfieldref:
472
                        if( (csp = SearchCSEList(node)) != NULL ) {
473
                                if( csp->reg > 0 ) {
474
                                        node->nodetype = en_regvar;
475
                                        node->i = csp->reg;
476
                                        }
477
                                else
478
                                        repexpr(node->p[0]);
479
                                }
480
                        else
481
                                repexpr(node->p[0]);
482
                        break;
483
                                case en_cbc:
484
                                case en_cbh:
485
                case en_cbw:
486
                                case en_cch:
487
                                case en_ccw:
488
                                case en_chw:
489
                case en_uminus:
490
                case en_not:    case en_compl:
491
                case en_ainc:   case en_adec:
492
                        repexpr(node->p[0]);
493
                        break;
494
                case en_add:    case en_sub:
495
                                case en_mul:    case en_mulu:   case en_div:    case en_udiv:
496
                                case en_mod:    case en_shl:    case en_shru:
497
                case en_shr:    case en_and:
498
                case en_or:     case en_xor:
499
                case en_land:   case en_lor:
500
                case en_eq:     case en_ne:
501
                case en_lt:     case en_le:
502
                case en_gt:     case en_ge:
503 51 robfinch
                                case en_ult:    case en_ule:
504
                                case en_ugt:    case en_uge:
505 37 robfinch
                case en_cond:   case en_void:
506
                case en_asadd:  case en_assub:
507
                case en_asmul:  case en_asdiv:
508
                case en_asor:   case en_asand:
509
                case en_asmod:  case en_aslsh:
510
                case en_asrsh:  case en_fcall:
511
                case en_assign:
512
                        repexpr(node->p[0]);
513
                        repexpr(node->p[1]);
514
                        break;
515
                }
516
}
517
 
518
/*
519
 *      repcse will scan through a block of statements replacing the
520
 *      optimized expressions with their temporary references.
521
 */
522
void repcse(Statement *block)
523
{
524
        while( block != NULL ) {
525
        switch( block->stype ) {
526
                        case st_return:
527
                        case st_throw:
528
                                        repexpr(block->exp);
529
                                        break;
530
                        case st_expr:
531
                                        repexpr(block->exp);
532
                                        break;
533
                        case st_while:
534
                        case st_until:
535
                        case st_do:
536
                        case st_dountil:
537
                                        repexpr(block->exp);
538
                        case st_doloop:
539
                        case st_forever:
540
                                        repcse(block->s1);
541
                                        repcse(block->s2);
542
                                        break;
543
                        case st_for:
544
                                        repexpr(block->initExpr);
545
                                        repexpr(block->exp);
546
                                        repcse(block->s1);
547
                                        repexpr(block->incrExpr);
548
                                        break;
549
                        case st_if:
550
                                        repexpr(block->exp);
551
                                        repcse(block->s1);
552
                                        repcse(block->s2);
553
                                        break;
554
                        case st_switch:
555
                                        repexpr(block->exp);
556
                                        repcse(block->s1);
557
                                        break;
558
                        case st_try:
559
                        case st_catch:
560
                        case st_case:
561
                                        repcse(block->s1);
562
                                        break;
563
                        case st_spinlock:
564
                                        repcse(block->s1);
565
                                        repcse(block->s2);      // lockfail statement
566
                                        break;
567
        }
568
        block = block->next;
569
    }
570
}
571
 
572
/*
573
 *      opt1 is the externally callable optimization routine. it will
574
 *      collect and allocate common subexpressions and substitute the
575
 *      tempref for all occurrances of the expression within the block.
576
 *
577
 *              optimizer is currently turned off...
578
 */
579
void opt1(Statement *block)
580
{
581
        olist = NULL;
582
    scan(block);            /* collect expressions */
583
    AllocateRegisterVars();             /* allocate registers */
584
    repcse(block);          /* replace allocated expressions */
585
}

powered by: WebSVN 2.1.0

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