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

Subversion Repositories raptor64

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

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        "gen.h"
5
#include        "cglbdec.h"
6
 
7
/*
8
 *      68000 C compiler
9
 *
10
 *      Copyright 1984, 1985, 1986 Matthew Brandt.
11
 *  all commercial rights reserved.
12
 *
13
 *      This compiler is intended as an instructive tool for personal use. Any
14
 *      use for profit without the written consent of the author is prohibited.
15
 *
16
 *      This compiler may be distributed freely for non-commercial use as long
17
 *      as this notice stays intact. Please forward any enhancements or questions
18
 *      to:
19
 *
20
 *              Matthew Brandt
21
 *              Box 920337
22
 *              Norcross, Ga 30092
23
 */
24
 
25
/*      Modified to support 64 bit Raptor64 by
26
        Robert Finch    robfinch<remove>@opencores.org
27
*/
28
 
29
void fold_const(struct enode **node);
30
 
31
/*
32
 *      dooper will execute a constant operation in a node and
33
 *      modify the node to be the result of the operation.
34
 */
35
void dooper(ENODE **node)
36
{
37
        ENODE *ep;
38
 
39
        ep = *node;
40
        switch( ep->nodetype ) {
41
                case en_add:
42
                        ep->nodetype = en_icon;
43
                        ep->i = ep->p[0]->i + ep->p[1]->i;
44
                        break;
45
                case en_sub:
46
                        ep->nodetype = en_icon;
47
                        ep->i = ep->p[0]->i - ep->p[1]->i;
48
                        break;
49
                case en_mul:
50
                                case en_mulu:
51
                        ep->nodetype = en_icon;
52
                        ep->i = ep->p[0]->i * ep->p[1]->i;
53
                        break;
54
                case en_div:
55
                                case en_udiv:
56
                        ep->nodetype = en_icon;
57
                        ep->i = ep->p[0]->i / ep->p[1]->i;
58
                        break;
59
                case en_shl:
60
                        ep->nodetype = en_icon;
61
                        ep->i = ep->p[0]->i << ep->p[1]->i;
62
                        break;
63
                case en_shr:
64
                        ep->nodetype = en_icon;
65
                        ep->i = ep->p[0]->i >> ep->p[1]->i;
66
                        break;
67
                case en_shru:
68
                        ep->nodetype = en_icon;
69
                        ep->i = (unsigned)ep->p[0]->i >> ep->p[1]->i;
70
                        break;
71
                case en_and:
72
                        ep->nodetype = en_icon;
73
                        ep->i = ep->p[0]->i & ep->p[1]->i;
74
                        break;
75
                case en_or:
76
                        ep->nodetype = en_icon;
77
                        ep->i = ep->p[0]->i | ep->p[1]->i;
78
                        break;
79
                case en_xor:
80
                        ep->nodetype = en_icon;
81
                        ep->i = ep->p[0]->i ^ ep->p[1]->i;
82
                        break;
83
                }
84
}
85
 
86
/*
87
 *      return which power of two i is or -1.
88
 */
89
int pwrof2(__int64 i)
90
{
91
        int p;
92
        __int64 q;
93
 
94
    q = 2;
95
    p = 1;
96
    while( q > 0 )
97
    {
98
                if( q == i )
99
                        return p;
100
                q <<= 1;
101
                ++p;
102
    }
103
    return -1;
104
}
105
 
106
/*
107
 *      make a mod mask for a power of two.
108
 */
109
__int64 mod_mask(int i)
110
{
111
        __int64 m;
112
    m = 0;
113
    while( i-- )
114
        m = (m << 1) | 1;
115
    return m;
116
}
117
 
118
/*
119
 *      opt0 - delete useless expressions and combine constants.
120
 *
121
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
122
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
123
 *      by node and combine obvious constant operations. It cannot
124
 *      combine name and label constants but will combine icon type
125
 *      nodes.
126
 */
127
void opt0(ENODE **node)
128
{
129
        ENODE *ep;
130
    __int64 val, sc;
131
 
132
    ep = *node;
133
    if( ep == NULL )
134
        return;
135
    switch( (*node)->nodetype ) {
136
            case en_b_ref:
137
                        case en_c_ref:
138
                        case en_h_ref:
139
            case en_w_ref:          /* optimize unary node */
140
            case en_ub_ref:
141
                        case en_uc_ref:
142
                        case en_uh_ref:
143
            case en_uw_ref:          /* optimize unary node */
144
                        case en_cbc:
145
                        case en_cbh:
146
                        case en_cbw:
147
                        case en_cch:
148
                        case en_ccw:
149
                        case en_chw:
150
                        case en_ainc:
151
                        case en_adec:
152
                        case en_not:
153
                        case en_compl:
154
                    opt0( &((*node)->p[0]));
155
                    return;
156
            case en_uminus:
157
                    opt0( &(ep->p[0]));
158
                    if( ep->p[0]->nodetype == en_icon )
159
                    {
160
                        ep->nodetype = en_icon;
161
                        ep->i = -ep->p[0]->i;
162
                    }
163
                    return;
164
            case en_add:
165
            case en_sub:
166
                    opt0(&(ep->p[0]));
167
                    opt0(&(ep->p[1]));
168
                    if( ep->p[0]->nodetype == en_icon ) {
169
                        if( ep->p[1]->nodetype == en_icon ) {
170
                            dooper(node);
171
                            return;
172
                        }
173
                        if( ep->p[0]->i == 0 ) {
174
                                                        if( ep->nodetype == en_sub )
175
                                                        {
176
                                                                ep->p[0] = ep->p[1];
177
                                ep->nodetype = en_uminus;
178
                                                        }
179
                                                        else
180
                                                                *node = ep->p[1];
181
                                                                return;
182
                        }
183
                    }
184
                    else if( ep->p[1]->nodetype == en_icon ) {
185
                        if( ep->p[1]->i == 0 ) {
186
                            *node = ep->p[0];
187
                            return;
188
                        }
189
                    }
190
                    return;
191
            case en_mul:
192
                        case en_mulu:
193
                    opt0(&(ep->p[0]));
194
                    opt0(&(ep->p[1]));
195
                    if( ep->p[0]->nodetype == en_icon ) {
196
                        if( ep->p[1]->nodetype == en_icon ) {
197
                            dooper(node);
198
                            return;
199
                        }
200
                        val = ep->p[0]->i;
201
                        if( val == 0 ) {
202
                            *node = ep->p[0];
203
                            return;
204
                        }
205
                        if( val == 1 ) {
206
                            *node = ep->p[1];
207
                            return;
208
                        }
209
                        sc = pwrof2(val);
210
                        if( sc != -1 )
211
                        {
212
                            swap_nodes(ep);
213
                            ep->p[1]->i = sc;
214
                            ep->nodetype = en_shl;
215
                        }
216
                    }
217
                    else if( ep->p[1]->nodetype == en_icon ) {
218
                        val = ep->p[1]->i;
219
                        if( val == 0 ) {
220
                            *node = ep->p[1];
221
                            return;
222
                        }
223
                        if( val == 1 ) {
224
                            *node = ep->p[0];
225
                            return;
226
                        }
227
                        sc = pwrof2(val);
228
                        if( sc != -1 )
229
                        {
230
                                                        ep->p[1]->i = sc;
231
                                                        ep->nodetype = en_shl;
232
                        }
233
                    }
234
                    break;
235
            case en_div:
236
                        case en_udiv:
237
                    opt0(&(ep->p[0]));
238
                    opt0(&(ep->p[1]));
239
                    if( ep->p[0]->nodetype == en_icon ) {
240
                            if( ep->p[1]->nodetype == en_icon ) {
241
                                    dooper(node);
242
                                    return;
243
                                    }
244
                            if( ep->p[0]->i == 0 ) {    /* 0/x */
245
                                    *node = ep->p[0];
246
                                    return;
247
                                    }
248
                            }
249
                    else if( ep->p[1]->nodetype == en_icon ) {
250
                            val = ep->p[1]->i;
251
                            if( val == 1 ) {        /* x/1 */
252
                                    *node = ep->p[0];
253
                                    return;
254
                                    }
255
                            sc = pwrof2(val);
256
                            if( sc != -1 )
257
                                    {
258
                                    ep->p[1]->i = sc;
259
                                    ep->nodetype = en_shr;
260
                                    }
261
                            }
262
                    break;
263
            case en_mod:
264
                    opt0(&(ep->p[0]));
265
                    opt0(&(ep->p[1]));
266
                    if( ep->p[1]->nodetype == en_icon )
267
                            {
268
                            if( ep->p[0]->nodetype == en_icon )
269
                                    {
270
                                    dooper(node);
271
                                    return;
272
                                    }
273
                            sc = pwrof2(ep->p[1]->i);
274
                            if( sc != -1 )
275
                                    {
276
                                    ep->p[1]->i = mod_mask(sc);
277
                                    ep->nodetype = en_and;
278
                                    }
279
                            }
280
                    break;
281
            case en_and:    case en_or:
282
                        case en_xor:    case en_shr:    case en_shru:
283
            case en_shl:
284
                    opt0(&(ep->p[0]));
285
                    opt0(&(ep->p[1]));
286
                    if( ep->p[0]->nodetype == en_icon &&
287
                            ep->p[1]->nodetype == en_icon )
288
                            dooper(node);
289
                    break;
290
            case en_land:   case en_lor:
291
                        case en_ult:    case en_ule:
292
                        case en_ugt:    case en_uge:
293
                        case en_lt:             case en_le:
294
                        case en_gt:             case en_ge:
295
                        case en_eq:             case en_ne:
296
            case en_asand:  case en_asor:
297
            case en_asadd:  case en_assub:
298
            case en_asmul:  case en_asdiv:
299
            case en_asmod:  case en_asrsh:
300
            case en_aslsh:  case en_cond:
301
            case en_fcall:  case en_void:
302
            case en_assign:
303
                    opt0(&(ep->p[0]));
304
                    opt0(&(ep->p[1]));
305
                    break;
306
            }
307
}
308
 
309
/*
310
 *      xfold will remove constant nodes and return the values to
311
 *      the calling routines.
312
 */
313
__int64 xfold(ENODE *node)
314
{
315
        __int64 i;
316
 
317
        if( node == NULL )
318
                return 0;
319
        switch( node->nodetype )
320
                {
321
                case en_icon:
322
                        i = node->i;
323
                        node->i = 0;
324
                        return i;
325
                case en_add:
326
                        return xfold(node->p[0]) + xfold(node->p[1]);
327
                case en_sub:
328
                        return xfold(node->p[0]) - xfold(node->p[1]);
329
                case en_mul:
330
                                case en_mulu:
331
                        if( node->p[0]->nodetype == en_icon )
332
                                return xfold(node->p[1]) * node->p[0]->i;
333
                        else if( node->p[1]->nodetype == en_icon )
334
                                return xfold(node->p[0]) * node->p[1]->i;
335
                        else return 0;
336
                case en_shl:
337
                        if( node->p[0]->nodetype == en_icon )
338
                                return xfold(node->p[1]) << node->p[0]->i;
339
                        else if( node->p[1]->nodetype == en_icon )
340
                                return xfold(node->p[0]) << node->p[1]->i;
341
                        else return 0;
342
                case en_uminus:
343
                        return - xfold(node->p[0]);
344
                                case en_shr:    case en_div:    case en_udiv:   case en_shru:
345
                case en_mod:    case en_asadd:
346
                case en_assub:  case en_asmul:
347
                case en_asdiv:  case en_asmod:
348
                case en_and:    case en_land:
349
                case en_or:     case en_lor:
350
                case en_xor:    case en_asand:
351
                case en_asor:   case en_void:
352
                case en_fcall:  case en_assign:
353
                        fold_const(&node->p[0]);
354
                        fold_const(&node->p[1]);
355
                        return 0;
356
                                case en_ub_ref: case en_uw_ref:
357
                                case en_uc_ref: case en_uh_ref:
358
                case en_b_ref:  case en_w_ref:
359
                                case en_c_ref:  case en_h_ref:
360
                case en_compl:
361
                case en_not:
362
                        fold_const(&node->p[0]);
363
                        return 0;
364
                }
365
        return 0;
366
}
367
 
368
/*
369
 *      reorganize an expression for optimal constant grouping.
370
 */
371
void fold_const(ENODE **node)
372
{       ENODE *ep;
373
        __int64 i;
374
        ep = *node;
375
        if( ep == 0 )
376
                return;
377
        if( ep->nodetype == en_add )
378
                {
379
                if( ep->p[0]->nodetype == en_icon )
380
                        {
381
                        ep->p[0]->i += xfold(ep->p[1]);
382
                        return;
383
                        }
384
                else if( ep->p[1]->nodetype == en_icon )
385
                        {
386
                        ep->p[1]->i += xfold(ep->p[0]);
387
                        return;
388
                        }
389
                }
390
        else if( ep->nodetype == en_sub )
391
                {
392
                if( ep->p[0]->nodetype == en_icon )
393
                        {
394
                        ep->p[0]->i -= xfold(ep->p[1]);
395
                        return;
396
                        }
397
                else if( ep->p[1]->nodetype == en_icon )
398
                        {
399
                        ep->p[1]->i -= xfold(ep->p[0]);
400
                        return;
401
                        }
402
                }
403
        i = xfold(ep);
404
        if( i != 0 )
405
                {
406
                ep = makeinode(en_icon,i);
407
                ep = makenode(en_add,ep,*node);
408
                *node = ep;
409
                }
410
}
411
 
412
/*
413
 *      apply all constant optimizations.
414
 */
415
void opt4(struct enode **node)
416
{
417
        opt0(node);
418
        fold_const(node);
419
        opt0(node);
420
}

powered by: WebSVN 2.1.0

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