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

Subversion Repositories raptor64

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 37 robfinch
// ============================================================================
2
// (C) 2012 Robert Finch
3
// All Rights Reserved.
4
// robfinch<remove>@opencores.org
5
//
6
// C64 - Raptor64 'C' derived language compiler
7
//  - 64 bit CPU
8
//
9
// This source file is free software: you can redistribute it and/or modify 
10
// it under the terms of the GNU Lesser General Public License as published 
11
// by the Free Software Foundation, either version 3 of the License, or     
12
// (at your option) any later version.                                      
13
//                                                                          
14
// This source file is distributed in the hope that it will be useful,      
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
17
// GNU General Public License for more details.                             
18
//                                                                          
19
// You should have received a copy of the GNU General Public License        
20
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
21
//                                                                          
22
// ============================================================================
23
//
24
#include <stdio.h>
25
#include <string.h>
26
#include "c.h"
27
#include "expr.h"
28
#include "Statement.h"
29
#include "gen.h"
30
#include "cglbdec.h"
31
 
32
extern int     breaklab;
33
extern int     contlab;
34
extern int     retlab;
35
extern int              throwlab;
36
 
37
extern int lastsph;
38
extern char *semaphores[20];
39
 
40
extern TYP              stdfunc;
41
 
42
void GenerateReturn(SYM *sym, Statement *stmt);
43
 
44
 
45
// Generate a function body.
46
//
47
void GenerateFunction(SYM *sym, Statement *stmt)
48
{
49
        char buf[20];
50
        char *bl;
51
 
52
        throwlab = retlab = contlab = breaklab = -1;
53
        lastsph = 0;
54
        memset(semaphores,0,sizeof(semaphores));
55
        throwlab = nextlabel++;
56
        while( lc_auto & 7 )    /* round frame size to word */
57
                ++lc_auto;
58
        if (sym->IsInterrupt) {
59 51 robfinch
                //GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8));
60
                //GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE));
61 37 robfinch
        }
62
        if (!sym->IsNocall) {
63
                GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(24));
64
                // For a leaf routine don't bother to store the link register or exception link register.
65
                if (sym->IsLeaf)
66
                        GenerateDiadic(op_sw,0,makereg(27),make_indirect(30));
67
                else {
68 51 robfinch
                        GenerateDiadic(op_sw, 0, makereg(27), make_indexed(0,30));
69
                        GenerateDiadic(op_sw, 0, makereg(28), make_indexed(8,30));
70
                        GenerateDiadic(op_sw, 0, makereg(31), make_indexed(16,30));
71 37 robfinch
                        GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab));
72
                }
73
                GenerateDiadic(op_mov,0,makereg(27),makereg(30));
74
                if (lc_auto)
75
                        GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(lc_auto));
76
        }
77
        if (optimize)
78
                opt1(stmt);
79
    GenerateStatement(stmt);
80
    GenerateReturn(sym,0);
81
        // Generate code for the hidden default catch
82
        GenerateLabel(throwlab);
83
        if (sym->IsLeaf){
84
                if (sym->DoesThrow) {
85
                        GenerateDiadic(op_mov,0,makereg(31),makereg(28));
86
                        GenerateDiadic(op_bra,0,make_label(retlab),NULL);                                // goto regular return cleanup code
87
                }
88
        }
89
        else {
90 51 robfinch
                GenerateDiadic(op_lw,0,makereg(31),make_indexed(8,27));          // load throw return address from stack into LR
91
                GenerateDiadic(op_sw,0,makereg(31),make_indexed(16,27));         // and store it back (so it can be loaded with the lm)
92 37 robfinch
                GenerateDiadic(op_bra,0,make_label(retlab),NULL);                                // goto regular return cleanup code
93
        }
94
}
95
 
96
 
97
// Generate a return statement.
98
//
99
void GenerateReturn(SYM *sym, Statement *stmt)
100
{
101
        AMODE *ap;
102
        int nn;
103
        int lab1;
104 51 robfinch
        int cnt;
105 37 robfinch
 
106
    if( stmt != NULL && stmt->exp != NULL )
107
        {
108
                initstack();
109
                ap = GenerateExpression(stmt->exp,F_REG|F_IMMED,8);
110
                // Force return value into register 1
111
                if( ap->preg != 1 ) {
112
                        if (ap->mode == am_immed)
113
                                GenerateTriadic(op_ori, 0, makereg(1),makereg(0),ap);
114
                        else
115
                                GenerateDiadic(op_mov, 0, makereg(1),ap);
116
                }
117
        }
118
        // Generate the return code only once. Branch to the return code for all returns.
119
        if( retlab == -1 )
120
    {
121
                retlab = nextlabel++;
122
                GenerateLabel(retlab);
123
                // Unlock any semaphores that may have been set
124
                for (nn = lastsph - 1; nn >= 0; nn--)
125
                        GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn]));
126
                if (sym->IsNocall)      // nothing to do for nocall convention
127
                        return;
128
                // Restore registers used as register variables.
129
                if( save_mask != 0 ) {
130 51 robfinch
                        cnt = (bitsset(save_mask)-1)*8;
131
                        for (nn = 31; nn >=1 ; nn--) {
132
                                if (save_mask & (1 << nn)) {
133
                                        GenerateTriadic(op_lw,0,makereg(nn),make_indexed(cnt,30),NULL);
134
                                        cnt -= 8;
135
                                }
136 37 robfinch
                        }
137 51 robfinch
                        GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(save_mask)*8));
138 37 robfinch
                }
139
                // Unlink the stack
140
                // For a leaf routine the link register and exception link register doesn't need to be saved/restored.
141
                GenerateDiadic(op_mov,0,makereg(30),makereg(27));
142
                if (sym->IsLeaf)
143
                        GenerateDiadic(op_lw,0,makereg(27),make_indirect(30));
144 51 robfinch
                else {
145
                        GenerateDiadic(op_lw,0,makereg(27),make_indirect(30));
146
                        GenerateDiadic(op_lw,0,makereg(28),make_indexed(8,30));
147
                        GenerateDiadic(op_lw,0,makereg(31),make_indexed(16,30));
148
                }
149 37 robfinch
                //if (isOscall) {
150
                //      GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave"));
151
                //      gen_regrestore();
152
                //}
153
                // Generate the return instruction. For the Pascal calling convention pop the parameters
154
                // from the stack.
155
                if (sym->IsInterrupt) {
156 51 robfinch
                        //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24));
157
                        //GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE));
158
                        //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8));
159
                        GenerateMonadic(op_iret,0,NULL);
160 37 robfinch
                        return;
161
                }
162
                if (sym->IsPascal)
163
                        GenerateDiadic(op_ret,0,make_immed(24+sym->NumParms * 8),NULL);
164
                else
165
                        GenerateDiadic(op_ret,0,make_immed(24),NULL);
166
    }
167
        // Just branch to the already generated stack cleanup code.
168
        else {
169
                GenerateDiadic(op_bra,0,make_label(retlab),0);
170
        }
171
}
172
 
173
// push the operand expression onto the stack.
174
//
175
static void GeneratePushParameter(ENODE *ep, int i, int n)
176
{
177
        AMODE *ap;
178
        ap = GenerateExpression(ep,F_REG,8);
179
        GenerateDiadic(op_sw,0,ap,make_indexed((n-i)*8-8,30));
180
        ReleaseTempRegister(ap);
181
}
182
 
183
// push entire parameter list onto stack
184
//
185
static int GeneratePushParameterList(ENODE *plist)
186
{
187
        ENODE *st = plist;
188
        int i,n;
189
        // count the number of parameters
190
        for(n = 0; plist != NULL; n++ )
191
                plist = plist->p[1];
192
        // move stack pointer down by number of parameters
193
        if (st)
194
                GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(n*8));
195
        plist = st;
196
    for(i = 0; plist != NULL; i++ )
197
    {
198
                GeneratePushParameter(plist->p[0],i,n);
199
                plist = plist->p[1];
200
    }
201
    return i;
202
}
203
 
204
AMODE *GenerateFunctionCall(ENODE *node, int flags)
205
{
206
        AMODE *ap, *result;
207
        SYM *sym;
208
    int             i;
209
        int msk;
210
 
211
        msk = SaveTempRegs();
212
        sym = NULL;
213
    i = GeneratePushParameterList(node->p[1]);
214
        // Call the function
215
        if( node->p[0]->nodetype == en_nacon ) {
216
        GenerateDiadic(op_call,0,make_offset(node->p[0]),NULL);
217
                sym = gsearch(node->p[0]->sp);
218
        }
219
    else
220
    {
221
                ap = GenerateExpression(node->p[0],F_REG,8);
222
                ap->mode = am_ind;
223
                GenerateDiadic(op_jal,0,makereg(31),ap);
224
                ReleaseTempRegister(ap);
225
    }
226
        // Pop parameters off the stack
227
        if (i!=0) {
228
                if (sym) {
229
                        if (!sym->IsPascal)
230
                                GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
231
                }
232
                else
233
                        GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
234
        }
235
        RestoreTempRegs(msk);
236
    result = GetTempRegister();
237
    if( result->preg != 1 || (flags & F_REG) == 0 )
238
                if (sym) {
239
                        if (sym->tp->btp->type==bt_void)
240
                                ;
241
                        else
242 51 robfinch
                                GenerateDiadic(op_mov,0,result,makereg(1));
243 37 robfinch
                }
244
                else
245 51 robfinch
                        GenerateDiadic(op_mov,0,result,makereg(1));
246 37 robfinch
    return result;
247
}
248
 

powered by: WebSVN 2.1.0

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