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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [ocode.cpp] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// CC64 - 'C' derived language compiler
9
//  - 64 bit CPU
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
// ============================================================================
25
//
26
#include "stdafx.h"
27
 
28
// Return true if the instruction has a target register.
29
 
30
bool OCODE::HasTargetReg() const
31
{
32
        if (insn)
33
                return (insn->HasTarget());
34
        else
35
                return (false);
36
}
37
 
38
bool OCODE::HasSourceReg(int regno) const
39
{
40
        if (oper1 && !insn->HasTarget()) {
41
                if (oper1->preg==regno)
42
                        return (true);
43
                if (oper1->sreg==regno)
44
                        return (true);
45
        }
46
        if (oper2 && oper2->preg==regno)
47
                return (true);
48
        if (oper2 && oper2->sreg==regno)
49
                return (true);
50
        if (oper3 && oper3->preg==regno)
51
                return (true);
52
        if (oper3 && oper3->sreg==regno)
53
                return (true);
54
        if (oper4 && oper4->preg==regno)
55
                return (true);
56
        if (oper4 && oper4->sreg==regno)
57
                return (true);
58
        // The call instruction implicitly has register arguments as source registers.
59
        if (opcode==op_call) {
60
                if (IsArgumentReg(regno))
61
                        return(true);
62
        }
63
        return (false);
64
}
65
 
66
// Get target reg needs to distinguish floating-point registers from regular
67
// general purpose registers. It returns a one for floating-point registers or
68
// a zero for general-purpose registers.
69
 
70
int OCODE::GetTargetReg(int *rg1, int *rg2) const
71
{
72
        if (insn==nullptr)
73
                return(0);
74
        if (insn->HasTarget()) {
75
                // Handle implicit targets
76
                switch(insn->opcode) {
77
                case op_pop:
78
                case op_unlk:
79
                case op_link:
80
                        *rg1 = regSP;
81
                        *rg2 = oper1->preg;
82
                        return(0);
83
                case op_divmod:
84
                case op_mul:
85
                case op_mulu:
86
                case op_sort:
87
                case op_demux:
88
                case op_mov2:
89
                        *rg1 = oper1->preg;
90
                        *rg2 = oper1->sreg;
91
                        return (0);
92
                case op_pea:
93
                case op_push:
94
                case op_ret:
95
                case op_call:
96
                        *rg1 = regSP;
97
                        *rg2 = 0;
98
                        return (0);
99
                default:
100
                        if (oper1->mode == am_fpreg) {
101
                                *rg1 = oper1->preg;
102
                                *rg2 = 0;
103
                                return (1);
104
                        }
105
                        else {
106
                                *rg1 = oper1->preg;
107
                                *rg2 = 0;
108
                                return (0);
109
                        }
110
                }
111
        }
112
        else {
113
                *rg1 = 0;
114
                *rg2 = 0;
115
                return (0);
116
        }
117
}
118
 
119
OCODE *OCODE::Clone(OCODE *c)
120
{
121
        OCODE *cd;
122
        cd = (OCODE *)xalloc(sizeof(OCODE));
123
        memcpy(cd, c, sizeof(OCODE));
124
        return (cd);
125
}
126
 
127
//
128
//      mov r3,r3 removed
129
//
130
// Code Like:
131
//              add             r3,r2,#10
132
//              mov             r3,r5
133
// Changed to:
134
//              mov             r3,r5
135
 
136
void OCODE::OptMove()
137
{
138
        if (OCODE::IsEqualOperand(oper1, oper2)) {
139
                MarkRemove();
140
                optimized++;
141
                return;
142
        }
143
}
144
 
145
//         sge          $v1,$r12,$v2
146
//     redor    $v2,$v1
147
// Translates to:
148
//         sge          $v1,$r12,$v2
149
//     mov              $v2,$v1
150
// Because redundant moves will be eliminated by further compiler
151
// optimizations.
152
 
153
void OCODE::OptRedor()
154
{
155
        if (back == nullptr)
156
                return;
157
        if (back->insn->IsSetInsn()) {
158
                if (back->oper1->preg == oper2->preg) {
159
                        opcode = op_mov;
160
                        insn = GetInsn(op_mov);
161
                        optimized++;
162
                }
163
        }
164
}
165
 
166
void OCODE::storeHex(txtoStream& ofs)
167
{
168
        ENODE *ep;
169
 
170
        switch (opcode) {
171
        case op_label:
172
                ofs.printf("L");
173
                ofs.printf("%05X", (int)oper1);
174
                ofs.printf(GetNamespace());
175
                ofs.printf("\n");
176
                break;
177
        case op_fnname:
178
                ep = (ENODE *)oper1->offset;
179
                ofs.printf("F%s:\n", (char *)ep->sp->c_str());
180
                break;
181
        default:
182
                ofs.printf("C");
183
                insn->storeHex(ofs);
184
                ofs.printf("L%01d", length);
185
                if (oper1) oper1->storeHex(ofs);
186
                if (oper2) oper2->storeHex(ofs);
187
                if (oper3) oper3->storeHex(ofs);
188
                if (oper4) oper4->storeHex(ofs);
189
                ofs.printf("\n");
190
        }
191
}
192
 
193
OCODE *OCODE::loadHex(std::ifstream& ifs)
194
{
195
        OCODE *cd;
196
        char buf[20];
197
        int op;
198
 
199
        cd = (OCODE *)allocx(sizeof(OCODE));
200
        ifs.read(buf, 1);
201
        if (buf[0] != 'I') {
202
                while (!ifs.eof() && buf[0] != '\n')
203
                        ifs.read(buf, 1);
204
                return (nullptr);
205
        }
206
        cd->insn = Instruction::loadHex(ifs);
207
        cd->opcode = cd->insn->opcode;
208
        ifs.read(buf, 1);
209
        if (buf[0] == 'L') {
210
                ifs.read(buf, 1);
211
                buf[1] = '\0';
212
                cd->length = atoi(buf);
213
                ifs.read(buf, 1);
214
        }
215
        cd->oper1 = nullptr;
216
        cd->oper2 = nullptr;
217
        cd->oper3 = nullptr;
218
        cd->oper4 = nullptr;
219
        switch (buf[0]) {
220
        case '1': cd->oper1 = Operand::loadHex(ifs); break;
221
        case '2': cd->oper2 = Operand::loadHex(ifs); break;
222
        case '3': cd->oper3 = Operand::loadHex(ifs); break;
223
        case '4': cd->oper4 = Operand::loadHex(ifs); break;
224
        default:
225
                while (!ifs.eof() && buf[0] != '\n')
226
                        ifs.read(buf, 1);
227
        }
228
        return (cd);
229
}
230
 
231
//
232
// Output a generic instruction.
233
//
234
void OCODE::store(txtoStream& ofs)
235
{
236
        static BasicBlock *b = nullptr;
237
        int op = opcode;
238
        Operand *ap1, *ap2, *ap3, *ap4;
239
        ENODE *ep;
240
        int predreg = pregreg;
241
        char buf[8];
242
        int nn;
243
 
244
        ap1 = oper1;
245
        ap2 = oper2;
246
        ap3 = oper3;
247
        ap4 = oper4;
248
 
249
        if (bb != b) {
250
                ofs.printf(";====================================================\n");
251
                ofs.printf("; Basic Block %d\n", bb->num);
252
                ofs.printf(";====================================================\n");
253
                b = bb;
254
        }
255
        if (comment) {
256
                ofs.printf("; %s\n", (char *)comment->oper1->offset->sp->c_str());
257
        }
258
        if (remove)
259
                ofs.printf(";-1");
260
        if (remove2)
261
                ofs.printf(";-2");
262
        if (op != op_fnname)
263
        {
264
                if (op == op_rem2) {
265
                        ofs.printf(";\t");
266
                        ofs.printf("%6.6s\t", "");
267
                        ofs.printf(ap1->offset->sp->c_str());
268
                        ofs.printf("\n");
269
                        return;
270
                }
271
                else {
272
                        ofs.printf("\t");
273
                        ofs.printf("%6.6s\t", "");
274
                        nn = insn->store(ofs);
275
                        buf[0] = '\0';
276
                        if (length) {
277
                                if (length <= 16) {
278
                                        switch (length) {
279
                                        case 1: sprintf_s(buf, sizeof(buf), ".b"); nn += 2; break;
280
                                        case 2: sprintf_s(buf, sizeof(buf), ".c"); nn += 2; break;
281
                                        case 4: sprintf_s(buf, sizeof(buf), ".h"); nn += 2; break;
282
                                        }
283
                                }
284
                                else {
285
                                        if (length != 'w' && length != 'W') {
286
                                                sprintf_s(buf, sizeof(buf), ".%c", length);
287
                                                nn += 2;
288
                                        }
289
                                }
290
                        }
291
                        ofs.write(buf);
292
                        // The longest mnemonic is 7 chars
293
                        while (nn < 9) {
294
                                ofs.write(" ");
295
                                nn++;
296
                        }
297
                }
298
        }
299
        if (op == op_fnname) {
300
                ep = (ENODE *)oper1->offset;
301
                ofs.printf("%s:", (char *)ep->sp->c_str());
302
        }
303
        else if (ap1 != 0)
304
        {
305
                ofs.printf("\t");
306
                ap1->store(ofs);
307
                if (ap2 != 0)
308
                {
309
                        if (op == op_push || op == op_pop)
310
                                ofs.printf("/");
311
                        else
312
                                ofs.printf(",");
313
                        if (op == op_cmp && ap2->mode != am_reg)
314
                                printf("aha\r\n");
315
                        ap2->store(ofs);
316
                        if (ap3 != NULL) {
317
                                if (op == op_push || op == op_pop)
318
                                        ofs.printf("/");
319
                                else
320
                                        ofs.printf(",");
321
                                ap3->store(ofs);
322
                                if (ap4 != NULL) {
323
                                        if (op == op_push || op == op_pop)
324
                                                ofs.printf("/");
325
                                        else
326
                                                ofs.printf(",");
327
                                        ap4->store(ofs);
328
                                }
329
                        }
330
                }
331
        }
332
        ofs.printf("\n");
333
}
334
 
335
 
336
 

powered by: WebSVN 2.1.0

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