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

Subversion Repositories raptor64

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

Go to most recent revision | 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
                GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8));
60
                GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE));
61
        }
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
                        GenerateDiadic(op_sm, 0, make_indirect(30), make_mask(0x98000000));
69
                        GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab));
70
                }
71
                GenerateDiadic(op_mov,0,makereg(27),makereg(30));
72
                if (lc_auto)
73
                        GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(lc_auto));
74
        }
75
        if (optimize)
76
                opt1(stmt);
77
    GenerateStatement(stmt);
78
    GenerateReturn(sym,0);
79
        // Generate code for the hidden default catch
80
        GenerateLabel(throwlab);
81
        if (sym->IsLeaf){
82
                if (sym->DoesThrow) {
83
                        GenerateDiadic(op_mov,0,makereg(31),makereg(28));
84
                        GenerateDiadic(op_bra,0,make_label(retlab),NULL);                                // goto regular return cleanup code
85
                }
86
        }
87
        else {
88
                GenerateDiadic(op_lw,0,makereg(31),make_indexed(16,27));         // load throw return address from stack into LR
89
                GenerateDiadic(op_sw,0,makereg(31),make_indirect(27));           // and store it back (so it can be loaded with the lm)
90
                GenerateDiadic(op_bra,0,make_label(retlab),NULL);                                // goto regular return cleanup code
91
        }
92
}
93
 
94
 
95
// Generate a return statement.
96
//
97
void GenerateReturn(SYM *sym, Statement *stmt)
98
{
99
        AMODE *ap;
100
        int nn;
101
        int lab1;
102
 
103
    if( stmt != NULL && stmt->exp != NULL )
104
        {
105
                initstack();
106
                ap = GenerateExpression(stmt->exp,F_REG|F_IMMED,8);
107
                // Force return value into register 1
108
                if( ap->preg != 1 ) {
109
                        if (ap->mode == am_immed)
110
                                GenerateTriadic(op_ori, 0, makereg(1),makereg(0),ap);
111
                        else
112
                                GenerateDiadic(op_mov, 0, makereg(1),ap);
113
                }
114
        }
115
        // Generate the return code only once. Branch to the return code for all returns.
116
        if( retlab == -1 )
117
    {
118
                retlab = nextlabel++;
119
                GenerateLabel(retlab);
120
                // Unlock any semaphores that may have been set
121
                for (nn = lastsph - 1; nn >= 0; nn--)
122
                        GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn]));
123
                if (sym->IsNocall)      // nothing to do for nocall convention
124
                        return;
125
                // Restore registers used as register variables.
126
                if( save_mask != 0 ) {
127
                        if (bitsset(save_mask) < 2) {
128
                        for (nn = 31; nn >=1 ; nn--)
129
                                if (save_mask & (1 << nn))
130
                                        GenerateTriadic(op_lw,0,makereg(nn),make_indirect(30),NULL);
131
                        }
132
                        else
133
                                GenerateTriadic(op_lm,0,make_indirect(30),make_mask(save_mask),NULL);
134
                }
135
                // Unlink the stack
136
                // For a leaf routine the link register and exception link register doesn't need to be saved/restored.
137
                GenerateDiadic(op_mov,0,makereg(30),makereg(27));
138
                if (sym->IsLeaf)
139
                        GenerateDiadic(op_lw,0,makereg(27),make_indirect(30));
140
                else
141
                        GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x98000000));
142
                //if (isOscall) {
143
                //      GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave"));
144
                //      gen_regrestore();
145
                //}
146
                // Generate the return instruction. For the Pascal calling convention pop the parameters
147
                // from the stack.
148
                if (sym->IsInterrupt) {
149
                        GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24));
150
                        GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE));
151
                        GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8));
152
                        GenerateDiadic(op_iret,0,NULL,NULL);
153
                        return;
154
                }
155
                if (sym->IsPascal)
156
                        GenerateDiadic(op_ret,0,make_immed(24+sym->NumParms * 8),NULL);
157
                else
158
                        GenerateDiadic(op_ret,0,make_immed(24),NULL);
159
    }
160
        // Just branch to the already generated stack cleanup code.
161
        else {
162
                GenerateDiadic(op_bra,0,make_label(retlab),0);
163
        }
164
}
165
 
166
// push the operand expression onto the stack.
167
//
168
static void GeneratePushParameter(ENODE *ep, int i, int n)
169
{
170
        AMODE *ap;
171
        ap = GenerateExpression(ep,F_REG,8);
172
        GenerateDiadic(op_sw,0,ap,make_indexed((n-i)*8-8,30));
173
        ReleaseTempRegister(ap);
174
}
175
 
176
// push entire parameter list onto stack
177
//
178
static int GeneratePushParameterList(ENODE *plist)
179
{
180
        ENODE *st = plist;
181
        int i,n;
182
        // count the number of parameters
183
        for(n = 0; plist != NULL; n++ )
184
                plist = plist->p[1];
185
        // move stack pointer down by number of parameters
186
        if (st)
187
                GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(n*8));
188
        plist = st;
189
    for(i = 0; plist != NULL; i++ )
190
    {
191
                GeneratePushParameter(plist->p[0],i,n);
192
                plist = plist->p[1];
193
    }
194
    return i;
195
}
196
 
197
AMODE *GenerateFunctionCall(ENODE *node, int flags)
198
{
199
        AMODE *ap, *result;
200
        SYM *sym;
201
    int             i;
202
        int msk;
203
 
204
        msk = SaveTempRegs();
205
        sym = NULL;
206
    i = GeneratePushParameterList(node->p[1]);
207
        // Call the function
208
        if( node->p[0]->nodetype == en_nacon ) {
209
        GenerateDiadic(op_call,0,make_offset(node->p[0]),NULL);
210
                sym = gsearch(node->p[0]->sp);
211
        }
212
    else
213
    {
214
                ap = GenerateExpression(node->p[0],F_REG,8);
215
                ap->mode = am_ind;
216
                GenerateDiadic(op_jal,0,makereg(31),ap);
217
                ReleaseTempRegister(ap);
218
    }
219
        // Pop parameters off the stack
220
        if (i!=0) {
221
                if (sym) {
222
                        if (!sym->IsPascal)
223
                                GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
224
                }
225
                else
226
                        GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
227
        }
228
        RestoreTempRegs(msk);
229
    result = GetTempRegister();
230
    if( result->preg != 1 || (flags & F_REG) == 0 )
231
                if (sym) {
232
                        if (sym->tp->btp->type==bt_void)
233
                                ;
234
                        else
235
                                GenerateTriadic(op_or,0,result,makereg(1),makereg(0));
236
                }
237
                else
238
                        GenerateTriadic(op_or,0,result,makereg(1),makereg(0));
239
    return result;
240
}
241
 

powered by: WebSVN 2.1.0

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