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

Subversion Repositories thor

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2017-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
Operand *Operand::Clone()
29
{
30
        Operand *newap;
31
 
32
        if (this == NULL)
33
                return NULL;
34
        newap = allocOperand();
35
        memcpy(newap, this, sizeof(Operand));
36
        return (newap);
37
}
38
 
39
 
40
//      compare two address nodes and return true if they are
41
//      equivalent.
42
 
43
bool Operand::IsEqual(Operand *ap1, Operand *ap2)
44
{
45
        if (ap1 == nullptr || ap2 == nullptr)
46
                return (false);
47
        if (ap1->mode != ap2->mode && !((ap1->mode == am_ind && ap2->mode == am_indx) || (ap1->mode == am_indx && ap2->mode == am_ind)))
48
                return (false);
49
        switch (ap1->mode)
50
        {
51
        case am_imm:
52
                return (ap1->offset->i == ap2->offset->i);
53
        case am_fpreg:
54
        case am_reg:
55
                return (ap1->preg == ap2->preg);
56
        case am_ind:
57
        case am_indx:
58
                if (ap1->preg != ap2->preg)
59
                        return (false);
60
                if (ap1->offset == ap2->offset)
61
                        return (true);
62
                if (ap1->offset == nullptr || ap2->offset == nullptr)
63
                        return (false);
64
                if (ap1->offset->i != ap2->offset->i)
65
                        return (false);
66
                return (true);
67
        }
68
        return (false);
69
}
70
 
71
char Operand::fpsize()
72
{
73
        if (type == stddouble.GetIndex())
74
                return 'd';
75
        if (type == stdquad.GetIndex())
76
                return 'q';
77
        if (type == stdflt.GetIndex())
78
                return 's';
79
        if (type == stdtriple.GetIndex())
80
                return 't';
81
 
82
        if (FloatSize)
83
                return (FloatSize);
84
        if (offset == nullptr)
85
                return ('d');
86
        if (offset->tp == nullptr)
87
                return ('d');
88
        switch (offset->tp->precision) {
89
        case 32:        return ('s');
90
        case 64:        return ('d');
91
        case 96:        return ('t');
92
        case 128:       return ('q');
93
        default:        return ('d');
94
        }
95
}
96
 
97
void Operand::GenZeroExtend(int isize, int osize)
98
{
99
        if (isize == osize)
100
                return;
101
        MakeLegal(F_REG, isize);
102
        switch (osize)
103
        {
104
        case 1: GenerateDiadic(op_zxb, 0, this, this); break;
105
        case 2: GenerateDiadic(op_zxc, 0, this, this); break;
106
        case 4: GenerateDiadic(op_zxh, 0, this, this); break;
107
        }
108
}
109
 
110
void Operand::GenSignExtend(int isize, int osize, int flags)
111
{
112
        Operand *ap1;
113
        Operand *ap = this;
114
 
115
        if (isize == osize)
116
                return;
117
        if (ap->isUnsigned)
118
                return;
119
        if (ap->mode != am_reg && ap->mode != am_fpreg) {
120
                ap1 = GetTempRegister();
121
                GenLoad(ap1, ap, isize, isize);
122
                switch (isize)
123
                {
124
                case 1: GenerateDiadic(op_sxb, 0, ap1, ap1); break;
125
                case 2: GenerateDiadic(op_sxc, 0, ap1, ap1); break;
126
                case 4: GenerateDiadic(op_sxh, 0, ap1, ap1); break;
127
                }
128
                GenStore(ap1, ap, osize);
129
                ReleaseTempRegister(ap1);
130
                return;
131
                //MakeLegalOperand(ap,flags & (F_REG|F_FPREG),isize);
132
        }
133
        if (ap->type == stddouble.GetIndex()) {
134
                switch (isize) {
135
                case 4: GenerateDiadic(op_fs2d, 0, ap, ap); break;
136
                }
137
        }
138
        else {
139
                switch (isize)
140
                {
141
                case 1: GenerateDiadic(op_sxb, 0, ap, ap); break;
142
                case 2: GenerateDiadic(op_sxc, 0, ap, ap); break;
143
                case 4: GenerateDiadic(op_sxh, 0, ap, ap); break;
144
                }
145
        }
146
}
147
 
148
// ----------------------------------------------------------------------------
149
// MakeLegal will coerce the addressing mode in ap1 into a mode that is
150
// satisfactory for the flag word.
151
// ----------------------------------------------------------------------------
152
void Operand::MakeLegal(int flags, int size)
153
{
154
        Operand *ap2, *ap1;
155
        int64_t i;
156
 
157
        if (this == nullptr)
158
                return;
159
 
160
        //      if (flags & F_NOVALUE) return;
161
        if (((flags & F_VOL) == 0) || tempflag)
162
        {
163
                switch (mode) {
164
                case am_imm:
165
                        i = ((ENODE *)(offset))->i;
166
                        if (flags & F_IMM8) {
167
                                if (i < 256 && i >= 0)
168
                                        return;
169
                        }
170
                        else if (flags & F_IMM6) {
171
                                if (i < 64 && i >= 0)
172
                                        return;
173
                        }
174
                        else if (flags & F_IMM0) {
175
                                if (i == 0)
176
                                        return;
177
                        }
178
                        else if (flags & F_IMMED)
179
                                return;         /* mode ok */
180
                        break;
181
                case am_reg:
182
                        if (flags & F_REG)
183
                                return;
184
                        break;
185
                case am_fpreg:
186
                        if (flags & F_FPREG)
187
                                return;
188
                        break;
189
                case am_ind:
190
                case am_indx:
191
                case am_indx2:
192
                case am_direct:
193
                        if (flags & F_MEM)
194
                                return;
195
                        break;
196
                }
197
        }
198
 
199
        if (flags & F_REG)
200
        {
201
                if (mode == am_reg)     // Might get this if F_VOL specified
202
                        return;
203
                ReleaseTempRegister(this);      // maybe we can use it...
204
                if (this)
205
                        ap2 = GetTempRegister();// GetTempReg(ap->type);
206
                else
207
                        ap2 = GetTempReg(stdint.GetIndex());
208
                if (mode == am_ind || mode == am_indx)
209
                        GenLoad(ap2, this, size, size);
210
                else if (mode == am_imm) {
211
                        GenerateDiadic(op_ldi, 0, ap2, this);
212
                }
213
                else {
214
                        if (mode == am_reg || mode == am_fpreg)
215
                                GenerateDiadic(op_mov, 0, ap2, this);
216
                        else
217
                                GenLoad(ap2, this, size, size);
218
                }
219
                mode = am_reg;
220
                preg = ap2->preg;
221
                deep = ap2->deep;
222
                pdeep = ap2->pdeep;
223
                tempflag = 1;
224
                return;
225
        }
226
        if (flags & F_FPREG)
227
        {
228
                ReleaseTempReg(this);      /* maybe we can use it... */
229
                ap2 = GetTempFPRegister();
230
                if (mode == am_ind || mode == am_indx)
231
                        GenLoad(ap2, this, size, size);
232
                else if (mode == am_imm) {
233
                        ap1 = GetTempRegister();
234
                        GenerateDiadic(op_ldi, 0, ap1, this);
235
                        GenerateDiadic(op_mov, 0, ap2, ap1);
236
                        ReleaseTempReg(ap1);
237
                }
238
                else {
239
                        if (mode == am_reg)
240
                                GenerateDiadic(op_mov, 0, ap2, this);
241
                        else
242
                                GenLoad(ap2, this, size, size);
243
                }
244
                mode = am_fpreg;
245
                preg = ap2->preg;
246
                deep = ap2->deep;
247
                pdeep = ap2->pdeep;
248
                tempflag = 1;
249
                return;
250
        }
251
        // Here we wanted the mode to be non-register (memory/immed)
252
        // Should fix the following to place the result in memory and
253
        // not a register.
254
        if (size == 1)
255
        {
256
                ReleaseTempRegister(this);
257
                ap2 = GetTempRegister();
258
                GenerateDiadic(op_mov, 0, ap2, this);
259
                if (isUnsigned)
260
                        GenerateTriadic(op_and, 0, ap2, ap2, make_immed(255));
261
                else {
262
                        GenerateDiadic(op_sext8, 0, ap2, ap2);
263
                }
264
                mode = ap2->mode;
265
                preg = ap2->preg;
266
                deep = ap2->deep;
267
                pdeep = ap2->pdeep;
268
                size = 2;
269
        }
270
        ap2 = GetTempRegister();
271
        switch (mode) {
272
        case am_ind:
273
        case am_indx:
274
                GenLoad(ap2, this, size, size);
275
                break;
276
        case am_imm:
277
                GenerateDiadic(op_ldi, 0, ap2, this);
278
                break;
279
        case am_reg:
280
                GenerateDiadic(op_mov, 0, ap2, this);
281
                break;
282
        default:
283
                GenLoad(ap2, this, size, size);
284
        }
285
        mode = am_reg;
286
        preg = ap2->preg;
287
        deep = ap2->deep;
288
        pdeep = ap2->pdeep;
289
        tempflag = 1;
290
        //     Leave("MkLegalOperand",0);
291
}
292
 
293
void Operand::storeHex(txtoStream& ofs)
294
{
295
        ofs.printf("O");
296
        switch (mode) {
297
        case am_imm:
298
                ofs.printf("#");
299
        }
300
}
301
 
302
Operand *Operand::loadHex(std::ifstream& ifs)
303
{
304
        Operand *oper;
305
 
306
        oper = allocOperand();
307
        return (oper);
308
}
309
 
310
 
311
void Operand::store(txtoStream& ofs)
312
{
313
        if (mode == 0)
314
                mode = am_reg;
315
        switch (mode)
316
        {
317
        case am_imm:
318
                ofs.write("#");
319
                // Fall through
320
        case am_direct:
321
                offset->PutConstant(ofs, lowhigh, rshift);
322
                break;
323
        case am_reg:
324
                if (type == stdvector.GetIndex())
325
                        ofs.printf("v%d", (int)preg);
326
                else if (type == stdvectormask->GetIndex())
327
                        ofs.printf("vm%d", (int)preg);
328
                else if (type == stddouble.GetIndex())
329
                        ofs.printf("$fp%d", (int)preg);
330
                else {
331
                        ofs.write(RegMoniker(preg));
332
                        //if (renamed)
333
                        //      ofs.printf(".%d", (int)pregs);
334
                }
335
                break;
336
        case am_vmreg:
337
                ofs.printf("vm%d", (int)preg);
338
                break;
339
        case am_fpreg:
340
                ofs.printf("$fp%d", (int)preg);
341
                break;
342
        case am_ind:
343
                ofs.printf("[%s]", RegMoniker(preg));
344
                break;
345
        case am_indx:
346
                // It's not known the function is a leaf routine until code
347
                // generation time. So the parameter offsets can't be determined
348
                // until code is being output. This bit of code first adds onto
349
                // parameter offset the size of the return block, then later
350
                // subtracts it off again.
351
                if (offset) {
352
                        if (preg == regFP) {
353
                                if (offset->sym) {
354
                                        if (offset->sym->IsParameter) { // must be an parameter
355
                                                offset->i += Compiler::GetReturnBlockSize();
356
                                        }
357
                                }
358
                        }
359
                        offset->PutConstant(ofs, 0, 0);
360
                        if (preg == regFP) {
361
                                if (offset->sym) {
362
                                        if (offset->sym->IsParameter) {
363
                                                offset->i -= Compiler::GetReturnBlockSize();
364
                                        }
365
                                }
366
                        }
367
                }
368
                ofs.printf("[%s]", RegMoniker(preg));
369
                break;
370
 
371
        case am_indx2:
372
                if (scale == 1 || scale == 0)
373
                        ofs.printf("[%s+%s]", RegMoniker(sreg), RegMoniker(preg));
374
                else
375
                        ofs.printf("[%s+%s*%d]", RegMoniker(sreg), RegMoniker(preg), scale);
376
                break;
377
 
378
//      case am_mask:
379
//              put_mask((int)offset);
380
//              break;
381
        default:
382
                printf("DIAG - illegal address mode.\n");
383
                break;
384
        }
385
}
386
 

powered by: WebSVN 2.1.0

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