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

Subversion Repositories raptor64

[/] [raptor64/] [trunk/] [software/] [c64/] [source/] [Peepgen.c] - Blame information for rev 53

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
static void AddToPeepList(struct ocode *newc);
9
void peep_add(struct ocode *ip);
10
static void PeepoptSub(struct ocode *ip);
11
void peep_move(struct ocode     *ip);
12
void peep_cmp(struct ocode *ip);
13
void opt3();
14
void put_ocode(struct ocode *p);
15
 
16
/*
17
 *      68000 C compiler
18
 *
19
 *      Copyright 1984, 1985, 1986 Matthew Brandt.
20
 *  all commercial rights reserved.
21
 *
22
 *      This compiler is intended as an instructive tool for personal use. Any
23
 *      use for profit without the written consent of the author is prohibited.
24
 *
25
 *      This compiler may be distributed freely for non-commercial use as long
26
 *      as this notice stays intact. Please forward any enhancements or questions
27
 *      to:
28
 *
29
 *              Matthew Brandt
30
 *              Box 920337
31
 *              Norcross, Ga 30092
32
 */
33
/*******************************************************
34
        Copyright 2012  Robert Finch
35
        Modified to support Raptor64 'C64' language
36
        by Robert Finch
37
        robfinch@opencores.org
38
*******************************************************/
39
 
40
struct ocode    *peep_head = NULL,
41
                *peep_tail = NULL;
42
 
43
AMODE *copy_addr(AMODE *ap)
44
{
45
        AMODE *newap;
46
    if( ap == NULL )
47
        return NULL;
48
    newap = allocAmode();
49
        memcpy(newap,ap,sizeof(AMODE));
50
    return newap;
51
}
52
 
53
void GenerateMonadic(int op, int len, AMODE *ap1)
54
{
55
        struct ocode *cd;
56
    cd = (struct ocode *)xalloc(sizeof(struct ocode));
57
    cd->opcode = op;
58
    cd->length = len;
59
    cd->oper1 = copy_addr(ap1);
60
    cd->oper2 = NULL;
61
        cd->oper3 = NULL;
62
    AddToPeepList(cd);
63
}
64
 
65
void GenerateDiadic(int op, int len, AMODE *ap1, AMODE *ap2)
66
{
67
        struct ocode *cd;
68
    cd = (struct ocode *)xalloc(sizeof(struct ocode));
69
    cd->opcode = op;
70
    cd->length = len;
71
    cd->oper1 = copy_addr(ap1);
72
    cd->oper2 = copy_addr(ap2);
73
        cd->oper3 = NULL;
74
    AddToPeepList(cd);
75
}
76
 
77
void GenerateTriadic(int op, int len, AMODE *ap1, AMODE *ap2, AMODE *ap3)
78
{
79
        struct ocode    *cd;
80
    cd = (struct ocode *)xalloc(sizeof(struct ocode));
81
    cd->opcode = op;
82
    cd->length = len;
83
    cd->oper1 = copy_addr(ap1);
84
    cd->oper2 = copy_addr(ap2);
85
        cd->oper3 = copy_addr(ap3);
86
    AddToPeepList(cd);
87
}
88
 
89
static void AddToPeepList(struct ocode *cd)
90
{
91
        if( peep_head == NULL )
92
    {
93
                peep_head = peep_tail = cd;
94
                cd->fwd = NULL;
95
                cd->back = NULL;
96
    }
97
    else
98
    {
99
                cd->fwd = NULL;
100
                cd->back = peep_tail;
101
                peep_tail->fwd = cd;
102
                peep_tail = cd;
103
    }
104
}
105
 
106
/*
107
 *      add a compiler generated label to the peep list.
108
 */
109
void GenerateLabel(int labno)
110
{
111
        struct ocode *newl;
112
    newl = (struct ocode *)xalloc(sizeof(struct ocode));
113
    newl->opcode = op_label;
114
    newl->oper1 = (struct amode *)labno;
115
    AddToPeepList(newl);
116
}
117
 
118
//void gen_ilabel(char *name)
119
//{      
120
//      struct ocode    *new;
121
//    new = (struct ocode *)xalloc(sizeof(struct ocode));
122
//    new->opcode = op_ilabel;
123
//    new->oper1 = (struct amode *)name;
124
//    add_peep(new);
125
//}
126
 
127
/*
128
 *      output all code and labels in the peep list.
129
 */
130
void flush_peep()
131
{
132
        if (optimize)
133
                opt3();         /* do the peephole optimizations */
134
    while( peep_head != NULL )
135
    {
136
                if( peep_head->opcode == op_label )
137
                        put_label(peep_head->oper1);
138
                else
139
                        put_ocode(peep_head);
140
                peep_head = peep_head->fwd;
141
    }
142
}
143
 
144
/*
145
 *      output the instruction passed.
146
 */
147
void put_ocode(struct ocode *p)
148
{
149
        put_code(p->opcode,p->length,p->oper1,p->oper2,p->oper3);
150
}
151
 
152
/*
153
 *      peephole optimization for move instructions.
154
 *      makes quick immediates when possible.
155
 *      changes move #0,d to clr d.
156
 *      changes long moves to address registers to short when
157
 *              possible.
158
 *      changes move immediate to stack to pea.
159
 */
160
void peep_move(struct ocode     *ip)
161
{
162
        return;
163
}
164
 
165
/*
166
 *      compare two address nodes and return true if they are
167
 *      equivalent.
168
 */
169
int equal_address(AMODE *ap1, AMODE *ap2)
170
{
171
        if( ap1 == NULL || ap2 == NULL )
172
                return FALSE;
173
    if( ap1->mode != ap2->mode )
174
        return FALSE;
175
    switch( ap1->mode )
176
    {
177
        case am_reg:
178
            return ap1->preg == ap2->preg;
179
    }
180
    return FALSE;
181
}
182
 
183
/*
184
 *      peephole optimization for add instructions.
185
 *      makes quick immediates out of small constants.
186
 */
187
void peep_add(struct ocode    *ip)
188
{
189
        return;
190
}
191
 
192
// 'subui' followed by a 'bne' gets turned into 'loop'
193
//
194
static void PeepoptSub(struct ocode *ip)
195
{
196
        if (ip->opcode==op_subui) {
197
                if (ip->oper3) {
198
                        if (ip->oper3->mode==am_immed) {
199
                                if (ip->oper3->offset->nodetype==en_icon && ip->oper3->offset->i==1) {
200
                                        if (ip->fwd) {
201
                                                if (ip->fwd->opcode==op_bne && ip->fwd->oper2->mode==am_reg && ip->fwd->oper2->preg==0) {
202
                                                        if (ip->fwd->oper1->preg==ip->oper1->preg) {
203
                                                                ip->opcode = op_loop;
204
                                                                ip->oper2 = ip->fwd->oper3;
205
                                                                ip->oper3 = NULL;
206
                                                                if (ip->fwd->back) ip->fwd->back = ip;
207
                                                                ip->fwd = ip->fwd->fwd;
208
                                                                return;
209
                                                        }
210
                                                }
211
                                        }
212
                                }
213
                        }
214
                }
215
        }
216
        return;
217
}
218
 
219
/*
220
 *      peephole optimization for compare instructions.
221
 */
222
void peep_cmp(struct ocode *ip)
223
{
224
        return;
225
}
226
 
227
/*
228
 *      changes multiplies and divides by convienient values
229
 *      to shift operations. op should be either op_asl or
230
 *      op_asr (for divide).
231
 */
232
void PeepoptMuldiv(struct ocode *ip, int op)
233
{
234
        int     shcnt;
235
 
236
    if( ip->oper1->mode != am_immed )
237
         return;
238
    if( ip->oper1->offset->nodetype != en_icon )
239
         return;
240
 
241
        shcnt = ip->oper1->offset->i;
242
                // remove multiply / divide by 1
243
                // This shouldn't get through Optimize, but does sometimes.
244
                if (shcnt==1) {
245
                        if (ip->back)
246
                                ip->back->fwd = ip->fwd;
247
                        if (ip->fwd)
248
                                ip->fwd->back = ip->back;
249
                        return;
250
                }
251
/*      vax c doesn't do this type of switch well       */
252
        if( shcnt == 2) shcnt = 1;
253
        else if( shcnt == 4) shcnt = 2;
254
        else if( shcnt == 8) shcnt = 3;
255
        else if( shcnt == 16) shcnt = 4;
256
        else if( shcnt == 32) shcnt = 5;
257
        else if( shcnt == 64) shcnt = 6;
258
        else if( shcnt == 128) shcnt = 7;
259
        else if( shcnt == 256) shcnt = 8;
260
        else if( shcnt == 512) shcnt = 9;
261
        else if( shcnt == 1024) shcnt = 10;
262
        else if( shcnt == 2048) shcnt = 11;
263
        else if( shcnt == 4096) shcnt = 12;
264
        else if( shcnt == 8192) shcnt = 13;
265
        else if( shcnt == 16384) shcnt = 14;
266
                else if( shcnt == 32768) shcnt = 15;
267
        else return;
268
        ip->oper1->offset->i = shcnt;
269
        ip->opcode = op;
270
        ip->length = 4;
271
}
272
 
273
// Optimize unconditional control flow transfers
274
// Instructions that follow an unconditional transfer won't be executed
275
// unless there is a label to branch to them.
276
//
277
void PeepoptUctran(struct ocode    *ip)
278
{
279
        if (uctran_off) return;
280
        while( ip->fwd != NULL && ip->fwd->opcode != op_label)
281
    {
282
                ip->fwd = ip->fwd->fwd;
283
                if( ip->fwd != NULL )
284
                        ip->fwd->back = ip;
285
    }
286
}
287
 
288
/*
289
 *      peephole optimizer. This routine calls the instruction
290
 *      specific optimization routines above for each instruction
291
 *      in the peep list.
292
 */
293
void opt3()
294
{
295
        struct ocode    *ip;
296
    ip = peep_head;
297
    while( ip != NULL )
298
    {
299
        switch( ip->opcode )
300
        {
301
            case op_move:
302
                    peep_move(ip);
303
                    break;
304
            case op_add:
305
                    peep_add(ip);
306
                    break;
307
            case op_sub:
308
                    PeepoptSub(ip);
309
                    break;
310
            case op_cmp:
311
                    peep_cmp(ip);
312
                    break;
313
            case op_muls:
314
                    PeepoptMuldiv(ip,op_shl);
315
                    break;
316
            case op_bra:
317
            case op_jmp:
318
            case op_ret:
319
                        case op_iret:
320
                    PeepoptUctran(ip);
321
            }
322
               ip = ip->fwd;
323
        }
324
}

powered by: WebSVN 2.1.0

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