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

Subversion Repositories thor

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2012-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
/*
29
 *      this module contains all of the code generation routines
30
 *      for evaluating expressions and conditions.
31
 */
32
 
33
int hook_predreg=15;
34
 
35
Operand *GenerateExpression();            /* forward ParseSpecifieraration */
36
 
37
extern Operand *copy_addr(Operand *);
38
extern Operand *GenExpr(ENODE *node);
39
extern Operand *GenerateFunctionCall(ENODE *node, int flags);
40
extern void GenLdi(Operand*,Operand *);
41
extern void GenerateCmp(ENODE *node, int op, int label, int predreg, unsigned int prediction);
42
 
43
void GenerateRaptor64Cmp(ENODE *node, int op, int label, int predreg);
44
void GenerateTable888Cmp(ENODE *node, int op, int label, int predreg);
45
void GenerateThorCmp(ENODE *node, int op, int label, int predreg);
46
void GenLoad(Operand *ap3, Operand *ap1, int ssize, int size);
47
void GenerateZeroExtend(Operand *ap, int isize, int osize);
48
void GenerateSignExtend(Operand *ap, int isize, int osize, int flags);
49
 
50
extern int throwlab;
51
static int nest_level = 0;
52
 
53
static void Enter(char *p)
54
{
55
/*
56
     int nn;
57
 
58
     for (nn = 0; nn < nest_level; nn++)
59
         printf(" ");
60
     printf("%s: %d ", p, lineno);
61
     nest_level++;
62
*/
63
}
64
static void Leave(char *p, int n)
65
{
66
/*
67
     int nn;
68
 
69
     nest_level--;
70
     for (nn = 0; nn < nest_level; nn++)
71
         printf(" ");
72
     printf("%s (%d) ", p, n);
73
*/
74
}
75
 
76
 
77
/*
78
 *      construct a reference node for an internal label number.
79
 */
80
Operand *make_label(int lab)
81
{
82
        ENODE *lnode;
83
        Operand *ap;
84
 
85
        lnode = allocEnode();
86
        lnode->nodetype = en_labcon;
87
        lnode->i = lab;
88
        ap = allocOperand();
89
        ap->mode = am_direct;
90
        ap->offset = lnode;
91
        ap->isUnsigned = TRUE;
92
        return ap;
93
}
94
 
95
Operand *make_clabel(int lab)
96
{
97
        ENODE *lnode;
98
    Operand *ap;
99
 
100
    lnode = allocEnode();
101
    lnode->nodetype = en_clabcon;
102
    lnode->i = lab;
103
        if (lab==-1)
104
                printf("-1\r\n");
105
    ap = allocOperand();
106
    ap->mode = am_direct;
107
    ap->offset = lnode;
108
        ap->isUnsigned = TRUE;
109
    return ap;
110
}
111
 
112
Operand *make_string(char *s)
113
{
114
        ENODE *lnode;
115
        Operand *ap;
116
 
117
        lnode = allocEnode();
118
        lnode->nodetype = en_nacon;
119
        lnode->sp = new std::string(s);
120
        ap = allocOperand();
121
        ap->mode = am_direct;
122
        ap->offset = lnode;
123
        return ap;
124
}
125
 
126
/*
127
 *      make a node to reference an immediate value i.
128
 */
129
Operand *make_immed(int64_t i)
130
{
131
        Operand *ap;
132
    ENODE *ep;
133
    ep = allocEnode();
134
    ep->nodetype = en_icon;
135
    ep->i = i;
136
    ap = allocOperand();
137
    ap->mode = am_imm;
138
    ap->offset = ep;
139
    return ap;
140
}
141
 
142
Operand *make_indirect(int i)
143
{
144
        Operand *ap;
145
    ENODE *ep;
146
    ep = allocEnode();
147
    ep->nodetype = en_uw_ref;
148
    ep->i = 0;
149
    ap = allocOperand();
150
        ap->mode = am_ind;
151
        ap->preg = i;
152
    ap->offset = 0;//ep; //=0;
153
    return ap;
154
}
155
 
156
Operand *make_indexed(int64_t o, int i)
157
{
158
        Operand *ap;
159
    ENODE *ep;
160
    ep = allocEnode();
161
    ep->nodetype = en_icon;
162
    ep->i = o;
163
    ap = allocOperand();
164
        ap->mode = am_indx;
165
        ap->preg = i;
166
    ap->offset = ep;
167
    return ap;
168
}
169
 
170
/*
171
 *      make a direct reference to a node.
172
 */
173
Operand *make_offset(ENODE *node)
174
{
175
        Operand *ap;
176
        ap = allocOperand();
177
        ap->mode = am_direct;
178
        ap->offset = node;
179
        return ap;
180
}
181
 
182
Operand *make_indx(ENODE *node, int rg)
183
{
184
        Operand *ap;
185
    ap = allocOperand();
186
    ap->mode = am_indx;
187
    ap->offset = node;
188
    ap->preg = rg;
189
    return ap;
190
}
191
 
192
void GenerateHint(int num)
193
{
194
        GenerateMonadic(op_hint,0,make_immed(num));
195
}
196
 
197
void GenerateComment(char *cm)
198
{
199
        GenerateMonadic(op_rem2,0,make_string(cm));
200
}
201
 
202
 
203
void GenLoad(Operand *ap3, Operand *ap1, int ssize, int size)
204
{
205
        if (ap3->type==stdvector.GetIndex()) {
206
        GenerateDiadic(op_lv,0,ap3,ap1);
207
        }
208
        else if (ap3->type == stdflt.GetIndex()) {
209
                GenerateDiadic(op_lf, 'd', ap3, ap1);
210
        }
211
        else if (ap3->type==stddouble.GetIndex()) {
212
                GenerateDiadic(op_lf,'d',ap3,ap1);
213
        }
214
        else if (ap3->type == stdquad.GetIndex()) {
215
                GenerateDiadic(op_lf, 'q', ap3, ap1);
216
        }
217
        else if (ap3->type == stdtriple.GetIndex()) {
218
                GenerateDiadic(op_lf, 't', ap3, ap1);
219
        }
220
        else if (ap3->isUnsigned) {
221
                if (ap3->isVolatile) {
222
                        switch (size) {
223
                        case 1: GenerateDiadic(op_lvbu, 0, ap3, ap1); break;
224
                        case 2: GenerateDiadic(op_lvcu, 0, ap3, ap1); break;
225
                        case 4: GenerateDiadic(op_lvhu, 0, ap3, ap1); break;
226
                        case 8: GenerateDiadic(op_lvw, 0, ap3, ap1); break;
227
                        }
228
                }
229
                else {
230
                        switch (size) {
231
                        case 1: GenerateDiadic(op_lbu, 0, ap3, ap1); break;
232
                        case 2: GenerateDiadic(op_lcu, 0, ap3, ap1); break;
233
                        case 4: GenerateDiadic(op_lhu, 0, ap3, ap1); break;
234
                        case 8: GenerateDiadic(op_lw, 0, ap3, ap1); break;
235
                        }
236
                }
237
    }
238
    else {
239
                if (ap3->isVolatile) {
240
                        switch (size) {
241
                        case 1: GenerateDiadic(op_lvb, 0, ap3, ap1); break;
242
                        case 2: GenerateDiadic(op_lvc, 0, ap3, ap1); break;
243
                        case 4: GenerateDiadic(op_lvh, 0, ap3, ap1); break;
244
                        case 8: GenerateDiadic(op_lvw, 0, ap3, ap1); break;
245
                        }
246
                }
247
                else {
248
                        switch (size) {
249
                        case 1: GenerateDiadic(op_lb, 0, ap3, ap1); break;
250
                        case 2: GenerateDiadic(op_lc, 0, ap3, ap1); break;
251
                        case 4: GenerateDiadic(op_lh, 0, ap3, ap1); break;
252
                        case 8: GenerateDiadic(op_lw, 0, ap3, ap1); break;
253
                        }
254
                }
255
    }
256
}
257
 
258
void GenStore(Operand *ap1, Operand *ap3, int size)
259
{
260
        if (ap1->isPtr) {
261
                GenerateDiadic(op_sw, 0, ap1, ap3);
262
        }
263
        else if (ap1->type==stdvector.GetIndex())
264
            GenerateDiadic(op_sv,0,ap1,ap3);
265
        else if (ap1->type == stdflt.GetIndex()) {
266
                GenerateDiadic(op_sf, 'd', ap1, ap3);
267
        }
268
        else if (ap1->type == stddouble.GetIndex()) {
269
                GenerateDiadic(op_sf, 'd', ap1, ap3);
270
        }
271
        else if (ap1->type == stdquad.GetIndex()) {
272
                GenerateDiadic(op_sf, 'q', ap1, ap3);
273
        }
274
        else if (ap1->type == stdtriple.GetIndex()) {
275
                GenerateDiadic(op_sf, 't', ap1, ap3);
276
        }
277
        else if (ap1->mode==am_fpreg)
278
                GenerateDiadic(op_sf,'d',ap1,ap3);
279
        else {
280
                switch (size) {
281
                case 1: GenerateDiadic(op_sb, 0, ap1, ap3); break;
282
                case 2: GenerateDiadic(op_sc, 0, ap1, ap3); break;
283
                case 4: GenerateDiadic(op_sh, 0, ap1, ap3); break;
284
                case 8: GenerateDiadic(op_sw, 0, ap1, ap3); break;
285
                default:;
286
                }
287
        }
288
}
289
 
290
//
291
//  Return the addressing mode of a dereferenced node.
292
//
293
Operand *GenerateDereference(ENODE *node,int flags,int size, int su)
294
{
295
        Operand *ap1;
296
    int siz1;
297
 
298
    Enter("Genderef");
299
        siz1 = node->GetReferenceSize();
300
        // When dereferencing a struct or union return a pointer to the struct or
301
        // union.
302
//      if (node->tp->type==bt_struct || node->tp->type==bt_union) {
303
//        return GenerateExpression(node,F_REG|F_MEM,size);
304
//    }
305
    if( node->p[0]->nodetype == en_add )
306
    {
307
//        ap2 = GetTempRegister();
308
        ap1 = node->p[0]->GenIndex();
309
//        GenerateTriadic(op_add,0,ap2,makereg(ap1->preg),makereg(regGP));
310
                ap1->isUnsigned = !su;//node->isUnsigned;
311
                // *** may have to fix for stackseg
312
                ap1->segment = dataseg;
313
//              ap2->mode = ap1->mode;
314
//              ap2->segment = dataseg;
315
//              ap2->offset = ap1->offset;
316
//              ReleaseTempRegister(ap1);
317
                if (!node->isUnsigned)
318
                        ap1->GenSignExtend(siz1,size,flags);
319
                else
320
                    ap1->MakeLegal(flags,siz1);
321
        ap1->MakeLegal(flags,size);
322
                goto xit;
323
    }
324
    else if( node->p[0]->nodetype == en_autocon )
325
    {
326
        ap1 = allocOperand();
327
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
328
                ap1->mode = am_indx;
329
        ap1->preg = regFP;
330
                ap1->segment = stackseg;
331
        ap1->offset = makeinode(en_icon,node->p[0]->i);
332
                ap1->offset->sym = node->p[0]->sym;
333
                ap1->isUnsigned = !su;
334
                if (!node->isUnsigned)
335
                ap1->GenSignExtend(siz1,size,flags);
336
                else
337
                    ap1->MakeLegal(flags,siz1);
338
        ap1->MakeLegal(flags,size);
339
                goto xit;
340
    }
341
    else if( node->p[0]->nodetype == en_classcon )
342
    {
343
        ap1 = allocOperand();
344
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
345
                ap1->mode = am_indx;
346
        ap1->preg = regCLP;
347
                ap1->segment = dataseg;
348
        ap1->offset = makeinode(en_icon,node->p[0]->i);
349
                ap1->offset->sym = node->p[0]->sym;
350
                ap1->isUnsigned = !su;
351
                if (!node->isUnsigned)
352
                ap1->GenSignExtend(siz1,size,flags);
353
                else
354
                    ap1->MakeLegal(flags,siz1);
355
        ap1->MakeLegal(flags,size);
356
                goto xit;
357
    }
358
    else if( node->p[0]->nodetype == en_autofcon )
359
    {
360
        ap1 = allocOperand();
361
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
362
                ap1->mode = am_indx;
363
        ap1->preg = regFP;
364
        ap1->offset = makeinode(en_icon,node->p[0]->i);
365
                ap1->offset->sym = node->p[0]->sym;
366
                if (node->p[0]->tp)
367
                        switch(node->p[0]->tp->precision) {
368
                        case 32: ap1->FloatSize = 's'; break;
369
                        case 64: ap1->FloatSize = 'd'; break;
370
                        default: ap1->FloatSize = 'd'; break;
371
                        }
372
                else
373
                        ap1->FloatSize = 'd';
374
                ap1->segment = stackseg;
375
                switch (node->p[0]->tp->type) {
376
                case bt_float:  ap1->type = stdflt.GetIndex(); break;
377
                case bt_double: ap1->type = stddouble.GetIndex(); break;
378
                case bt_triple: ap1->type = stdtriple.GetIndex(); break;
379
                case bt_quad:   ap1->type = stdquad.GetIndex(); break;
380
                }
381
//          ap1->MakeLegal(flags,siz1);
382
        ap1->MakeLegal(flags,size);
383
                goto xit;
384
    }
385
    else if( node->p[0]->nodetype == en_autovcon )
386
    {
387
        ap1 = allocOperand();
388
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
389
                ap1->mode = am_indx;
390
        ap1->preg = regFP;
391
        ap1->offset = makeinode(en_icon,node->p[0]->i);
392
                ap1->offset->sym = node->p[0]->sym;
393
                if (node->p[0]->tp)
394
                        switch(node->p[0]->tp->precision) {
395
                        case 32: ap1->FloatSize = 's'; break;
396
                        case 64: ap1->FloatSize = 'd'; break;
397
                        default: ap1->FloatSize = 'd'; break;
398
                        }
399
                else
400
                        ap1->FloatSize = 'd';
401
                ap1->segment = stackseg;
402
                ap1->type = stdvector.GetIndex();
403
                //          ap1->MakeLegal(flags,siz1);
404
        ap1->MakeLegal(flags,size);
405
                goto xit;
406
    }
407
    else if( node->p[0]->nodetype == en_autovmcon )
408
    {
409
        ap1 = allocOperand();
410
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
411
                ap1->mode = am_indx;
412
        ap1->preg = regFP;
413
        ap1->offset = makeinode(en_icon,node->p[0]->i);
414
                ap1->offset->sym = node->p[0]->sym;
415
                if (node->p[0]->tp)
416
                        switch(node->p[0]->tp->precision) {
417
                        case 32: ap1->FloatSize = 's'; break;
418
                        case 64: ap1->FloatSize = 'd'; break;
419
                        default: ap1->FloatSize = 'd'; break;
420
                        }
421
                else
422
                        ap1->FloatSize = 'd';
423
                ap1->segment = stackseg;
424
                ap1->type = stdvectormask->GetIndex();
425
                //          ap1->MakeLegal(flags,siz1);
426
        ap1->MakeLegal(flags,size);
427
                goto xit;
428
    }
429
        else if ((node->p[0]->nodetype == en_labcon) && use_gp)
430
        {
431
                ap1 = allocOperand();
432
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
433
                ap1->mode = am_indx;
434
                switch (node->p[0]->segment) {
435
                case dataseg:   ap1->preg = regGP; break;
436
                case tlsseg:    ap1->preg = regTP; break;
437
                default:        ap1->preg = regPP; break;
438
                }
439
                ap1->segment = node->p[0]->segment;
440
                ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
441
                ap1->isUnsigned = !su;
442
                if (!node->isUnsigned)
443
                        ap1->GenSignExtend(siz1, size, flags);
444
                else
445
                        ap1->MakeLegal( flags, siz1);
446
                ap1->isVolatile = node->isVolatile;
447
                ap1->MakeLegal( flags, size);
448
                goto xit;
449
        }
450
        else if(( node->p[0]->nodetype==en_nacon ) && use_gp)
451
    {
452
        ap1 = allocOperand();
453
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
454
                ap1->mode = am_indx;
455
        ap1->preg = regGP;
456
                ap1->segment = dataseg;
457
        ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
458
                ap1->isUnsigned = !su;
459
                if (!node->isUnsigned)
460
                ap1->GenSignExtend(siz1,size,flags);
461
                else
462
                    ap1->MakeLegal(flags,siz1);
463
        ap1->isVolatile = node->isVolatile;
464
                switch (node->p[0]->tp->type) {
465
                case bt_float:  ap1->type = stdflt.GetIndex(); break;
466
                case bt_double: ap1->type = stddouble.GetIndex(); break;
467
                case bt_triple: ap1->type = stdtriple.GetIndex(); break;
468
                case bt_quad:   ap1->type = stdquad.GetIndex(); break;
469
                }
470
                ap1->MakeLegal(flags,size);
471
                goto xit;
472
    }
473
        else if ((node->p[0]->nodetype == en_labcon) && !use_gp)
474
        {
475
                ap1 = allocOperand();
476
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
477
                ap1->mode = am_direct;
478
                ap1->preg = 0;
479
                ap1->segment = node->p[0]->segment;
480
                ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
481
                ap1->isUnsigned = !su;
482
                if (!node->isUnsigned)
483
                        ap1->GenSignExtend(siz1, size, flags);
484
                else
485
                        ap1->MakeLegal( flags, siz1);
486
                ap1->isVolatile = node->isVolatile;
487
                ap1->MakeLegal( flags, size);
488
                goto xit;
489
        }
490
        else if ((node->p[0]->nodetype == en_nacon) && !use_gp)
491
        {
492
                ap1 = allocOperand();
493
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
494
                ap1->mode = am_direct;
495
                ap1->preg = 0;
496
                ap1->segment = dataseg;
497
                ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
498
                ap1->isUnsigned = !su;
499
                if (!node->isUnsigned)
500
                        ap1->GenSignExtend(siz1, size, flags);
501
                else
502
                        ap1->MakeLegal( flags, siz1);
503
                ap1->isVolatile = node->isVolatile;
504
                switch (node->p[0]->tp->type) {
505
                case bt_float:  ap1->type = stdflt.GetIndex(); break;
506
                case bt_double: ap1->type = stddouble.GetIndex(); break;
507
                case bt_triple: ap1->type = stdtriple.GetIndex(); break;
508
                case bt_quad:   ap1->type = stdquad.GetIndex(); break;
509
                }
510
                ap1->MakeLegal( flags, size);
511
                goto xit;
512
        }
513
        else if (node->p[0]->nodetype == en_regvar) {
514
        ap1 = allocOperand();
515
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
516
                // For parameters we want Rn, for others [Rn]
517
                // This seems like an error earlier in the compiler
518
                // See setting val_flag in ParseExpressions
519
                ap1->mode = node->p[0]->i < 18 ? am_ind : am_reg;
520
//              ap1->mode = node->p[0]->tp->val_flag ? am_reg : am_ind;
521
                ap1->preg = node->p[0]->i;
522
                ap1->MakeLegal(flags,size);
523
            Leave("Genderef",3);
524
        return ap1;
525
        }
526
        else if (node->p[0]->nodetype == en_fpregvar) {
527
                /*error(ERR_DEREF)*/;
528
                ap1 = allocOperand();
529
                ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
530
                ap1->mode = node->p[0]->i < 18 ? am_ind : am_fpreg;
531
                ap1->preg = node->p[0]->i;
532
                switch (node->p[0]->tp->type) {
533
                case bt_float:  ap1->type = stdflt.GetIndex(); break;
534
                case bt_double: ap1->type = stddouble.GetIndex(); break;
535
                case bt_triple: ap1->type = stdtriple.GetIndex(); break;
536
                case bt_quad:   ap1->type = stdquad.GetIndex(); break;
537
                }
538
        ap1->MakeLegal(flags,size);
539
            Leave("Genderef",3);
540
        return (ap1);
541
        }
542
        else if (node->p[0]->nodetype == en_vex) {
543
                Operand *ap2;
544
                if (node->p[0]->p[0]->nodetype==en_vector_ref) {
545
                        ap1 = GenerateDereference(node->p[0]->p[0],F_REG,8,0);
546
                        ap2 = GenerateExpression(node->p[0]->p[1],F_REG,8);
547
                        if (ap1->offset && ap2->offset) {
548
                                GenerateTriadic(op_add,0,ap1,makereg(0),make_immed(ap2->offset->i));
549
                        }
550
                        ReleaseTempReg(ap2);
551
                        //ap1->mode = node->p[0]->i < 18 ? am_ind : am_reg;
552
                        //ap1->preg = node->p[0]->i;
553
                        ap1->type = stdvector.GetIndex();
554
                        ap1->MakeLegal(flags,size);
555
                        return (ap1);
556
                }
557
        }
558
    ap1 = GenerateExpression(node->p[0],F_REG | F_IMMED,8); /* generate address */
559
        ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
560
        if( ap1->mode == am_reg)
561
    {
562
//        ap1->mode = am_ind;
563
          if (use_gp) {
564
              ap1->mode = am_indx;
565
              ap1->sreg = regGP;
566
          }
567
          else
568
             ap1->mode = am_ind;
569
                  if (node->p[0]->constflag==TRUE)
570
                          ap1->offset = node->p[0];
571
                  else
572
                        ap1->offset = nullptr;  // ****
573
                  ap1->isUnsigned = !su | ap1->isPtr;
574
                if (!node->isUnsigned)
575
                ap1->GenSignExtend(siz1,size,flags);
576
                else
577
                    ap1->MakeLegal(flags,siz1);
578
        ap1->isVolatile = node->isVolatile;
579
        ap1->MakeLegal(flags,size);
580
                goto xit;
581
    }
582
        // Note sure about this, but immediate were being incorrectly
583
        // dereferenced as direct addresses because it would fall through
584
        // to the following dead code.
585
 
586
        if (ap1->mode == am_imm) {
587
                ap1->MakeLegal( flags, size);
588
                goto xit;
589
        }
590
 
591
        // *********************************************************************
592
        // I think what follows is dead code.
593
        // am_reg and am_imm the only codes that should be generated are
594
        // checked for above.
595
        // *********************************************************************
596
 
597
        // See segments notes
598
        //if (node->p[0]->nodetype == en_labcon &&
599
        //      node->p[0]->etype == bt_pointer && node->p[0]->constflag)
600
        //      ap1->segment = codeseg;
601
        //else
602
        //      ap1->segment = dataseg;
603
        ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
604
        if (use_gp) {
605
        ap1->mode = am_indx;
606
        ap1->preg = regGP;
607
        ap1->segment = dataseg;
608
    }
609
    else {
610
        ap1->mode = am_direct;
611
            ap1->isUnsigned = !su | ap1->isPtr;
612
    }
613
//    ap1->offset = makeinode(en_icon,node->p[0]->i);
614
    ap1->isUnsigned = !su | ap1->isPtr;
615
        if (!node->isUnsigned)
616
            ap1->GenSignExtend(siz1,size,flags);
617
        else
618
                ap1->MakeLegal(flags,siz1);
619
    ap1->isVolatile = node->isVolatile;
620
    ap1->MakeLegal(flags,size);
621
xit:
622
    Leave("Genderef",0);
623
    return (ap1);
624
}
625
 
626
/*
627
 *      generate code to evaluate a multiply node.
628
 */
629
Operand *GenerateMultiply(ENODE *node, int flags, int size, int op)
630
{
631
        Operand *ap1, *ap2, *ap3;
632
  Enter("Genmul");
633
    if( node->p[0]->nodetype == en_icon )
634
        swap_nodes(node);
635
    if (op==op_fmul) {
636
        ap3 = GetTempFPRegister();
637
        ap1 = GenerateExpression(node->p[0],F_FPREG,size);
638
        ap2 = GenerateExpression(node->p[1],F_FPREG,size);
639
    }
640
    else {
641
        ap3 = GetTempRegister();
642
        ap1 = GenerateExpression(node->p[0],F_REG,8);
643
        ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8);
644
    }
645
        if (op==op_fmul) {
646
                // Generate a convert operation ?
647
                if (ap1->fpsize() != ap2->fpsize()) {
648
                        if (ap2->fpsize()=='s')
649
                                GenerateDiadic(op_fcvtsq, 0, ap2, ap2);
650
                }
651
            GenerateTriadic(op,ap1->fpsize(),ap3,ap1,ap2);
652
        }
653
        else
654
                GenerateTriadic(op,0,ap3,ap1,ap2);
655
        ReleaseTempReg(ap2);
656
        ReleaseTempReg(ap1);
657
        ap3->MakeLegal(flags,2);
658
        Leave("Genmul",0);
659
        return ap3;
660
}
661
 
662
void GenMemop(int op, Operand *ap1, Operand *ap2, int ssize)
663
{
664
        Operand *ap3;
665
 
666
        if (ap1->type==stddouble.GetIndex()) {
667
        ap3 = GetTempFPRegister();
668
                GenLoad(ap3,ap1,ssize,ssize);
669
                GenerateTriadic(op,ap1->FloatSize,ap3,ap3,ap2);
670
                GenStore(ap3,ap1,ssize);
671
                ReleaseTempReg(ap3);
672
                return;
673
        }
674
        else if (ap1->type==stdvector.GetIndex()) {
675
                ap3 = GetTempVectorRegister();
676
                GenLoad(ap3,ap1,ssize,ssize);
677
                GenerateTriadic(op,0,ap3,ap3,ap2);
678
                GenStore(ap3,ap1,ssize);
679
                ReleaseTempReg(ap3);
680
                return;
681
        }
682
        //if (ap1->mode != am_indx2)
683
        {
684
                if (op==op_add && ap2->mode==am_imm && ap2->offset->i >= -16 && ap2->offset->i < 16 && ssize==8) {
685
                        GenerateDiadic(op_inc,0,ap1,ap2);
686
                        return;
687
                }
688
                if (op==op_sub && ap2->mode==am_imm && ap2->offset->i >= -15 && ap2->offset->i < 15 && ssize==8) {
689
                        GenerateDiadic(op_dec,0,ap1,ap2);
690
                        return;
691
                }
692
        }
693
        ap3 = GetTempRegister();
694
        ap3->isPtr = ap1->isPtr;
695
    GenLoad(ap3,ap1,ssize,ssize);
696
        GenerateTriadic(op,0,ap3,ap3,ap2);
697
        GenStore(ap3,ap1,ssize);
698
        ReleaseTempReg(ap3);
699
}
700
 
701
//
702
//      generate a *= node.
703
//
704
Operand *GenerateAssignMultiply(ENODE *node,int flags, int size, int op)
705
{
706
        Operand *ap1, *ap2, *ap3;
707
    int             ssize;
708
    ssize = GetNaturalSize(node->p[0]);
709
    if( ssize > size )
710
            size = ssize;
711
        if (node->p[0]->IsBitfield()) {
712
                ap3 = GetTempRegister();
713
                ap1 = GenerateBitfieldDereference(node->p[0], F_REG | F_MEM, size);
714
                GenerateDiadic(op_mov, 0, ap3, ap1);
715
                ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
716
                GenerateTriadic(op, 0, ap1, ap1, ap2);
717
                GenerateBitfieldInsert(ap3, ap1, ap1->offset->bit_offset, ap1->offset->bit_width);
718
                GenStore(ap3, ap1->next, ssize);
719
                ReleaseTempReg(ap2);
720
                ReleaseTempReg(ap1->next);
721
                ReleaseTempReg(ap1);
722
                ap3->MakeLegal( flags, size);
723
                return (ap3);
724
        }
725
        if (node->etype==bt_double || node->etype==bt_quad || node->etype==bt_float || node->etype==bt_triple) {
726
        ap1 = GenerateExpression(node->p[0],F_FPREG | F_MEM,ssize);
727
        ap2 = GenerateExpression(node->p[1],F_FPREG,size);
728
        op = op_fmul;
729
    }
730
    else if (node->etype==bt_vector) {
731
        ap1 = GenerateExpression(node->p[0],F_REG | F_MEM,ssize);
732
        ap2 = GenerateExpression(node->p[1],F_REG,size);
733
                op = ap2->type==stdvector.GetIndex() ? op_vmul : op_vmuls;
734
    }
735
    else {
736
        ap1 = GenerateExpression(node->p[0],F_ALL & ~F_IMMED,ssize);
737
        ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
738
    }
739
        if (ap1->mode==am_reg) {
740
            GenerateTriadic(op,0,ap1,ap1,ap2);
741
        }
742
        else if (ap1->mode==am_fpreg) {
743
            GenerateTriadic(op,ssize==4?'s':ssize==8?'d':ssize==12?'t':ssize==16 ? 'q' : 'd',ap1,ap1,ap2);
744
            ReleaseTempReg(ap2);
745
            ap1->MakeLegal(flags,size);
746
                return (ap1);
747
        }
748
        else {
749
                GenMemop(op, ap1, ap2, ssize);
750
        }
751
    ReleaseTempReg(ap2);
752
    ap1->GenSignExtend(ssize,size,flags);
753
    ap1->MakeLegal(flags,size);
754
    return (ap1);
755
}
756
 
757
/*
758
 *      generate /= and %= nodes.
759
 */
760
Operand *GenerateAssignModiv(ENODE *node,int flags,int size,int op)
761
{
762
        Operand *ap1, *ap2, *ap3;
763
    int             siz1;
764
    int isFP;
765
 
766
    siz1 = GetNaturalSize(node->p[0]);
767
        if (node->p[0]->IsBitfield()) {
768
                ap3 = GetTempRegister();
769
                ap1 = GenerateBitfieldDereference(node->p[0], F_REG | F_MEM, size);
770
                GenerateDiadic(op_mov, 0, ap3, ap1);
771
                ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
772
                GenerateTriadic(op, 0, ap1, ap1, ap2);
773
                GenerateBitfieldInsert(ap3, ap1, ap1->offset->bit_offset, ap1->offset->bit_width);
774
                GenStore(ap3, ap1->next, siz1);
775
                ReleaseTempReg(ap2);
776
                ReleaseTempReg(ap1->next);
777
                ReleaseTempReg(ap1);
778
                ap3->MakeLegal( flags, size);
779
                return (ap3);
780
        }
781
        isFP = node->etype==bt_double || node->etype==bt_float || node->etype==bt_triple || node->etype==bt_quad;
782
    if (isFP) {
783
        if (op==op_div || op==op_divu)
784
           op = op_fdiv;
785
        ap1 = GenerateExpression(node->p[0],F_FPREG,siz1);
786
        ap2 = GenerateExpression(node->p[1],F_FPREG,size);
787
                GenerateTriadic(op,siz1==4?'s':siz1==8?'d':siz1==12?'t':siz1==16?'q':'d',ap1,ap1,ap2);
788
            ReleaseTempReg(ap2);
789
                ap1->MakeLegal(flags,size);
790
            return (ap1);
791
//        else if (op==op_mod || op==op_modu)
792
//           op = op_fdmod;
793
    }
794
    else {
795
        ap1 = GetTempRegister();
796
        ap2 = GenerateExpression(node->p[0],F_ALL & ~F_IMMED,siz1);
797
    }
798
        if (ap2->mode==am_reg && ap2->preg != ap1->preg)
799
                GenerateDiadic(op_mov,0,ap1,ap2);
800
        else if (ap2->mode==am_fpreg && ap2->preg != ap1->preg)
801
                GenerateDiadic(op_mov,0,ap1,ap2);
802
        else
803
        GenLoad(ap1,ap2,siz1,siz1);
804
    //GenerateSignExtend(ap1,siz1,2,flags);
805
    if (isFP)
806
        ap3 = GenerateExpression(node->p[1],F_FPREG,8);
807
    else
808
        ap3 = GenerateExpression(node->p[1],F_REG|F_IMMED,8);
809
        if (op==op_fdiv) {
810
                GenerateTriadic(op,siz1==4?'s':siz1==8?'d':siz1==12?'t':siz1==16?'q':'d',ap1,ap1,ap3);
811
        }
812
        else
813
                GenerateTriadic(op,0,ap1,ap1,ap3);
814
    ReleaseTempReg(ap3);
815
    //GenerateDiadic(op_ext,0,ap1,0);
816
        if (ap2->mode==am_reg)
817
                GenerateDiadic(op_mov,0,ap2,ap1);
818
        else if (ap2->mode==am_fpreg)
819
                GenerateDiadic(op_mov,0,ap2,ap1);
820
        else
821
            GenStore(ap1,ap2,siz1);
822
    ReleaseTempReg(ap2);
823
        if (!isFP)
824
                ap1->MakeLegal(flags,size);
825
    return (ap1);
826
}
827
 
828
// This little bit of code a debugging aid.
829
// Dumps the expression nodes associated with an aggregate assignment.
830
 
831
void DumpStructEnodes(ENODE *node)
832
{
833
        ENODE *head;
834
        TYP *tp;
835
 
836
        lfs.printf("{");
837
        head = node;
838
        while (head) {
839
                tp = head->tp;
840
                if (tp)
841
                        tp->put_ty();
842
                if (head->nodetype==en_aggregate) {
843
                        DumpStructEnodes(head->p[0]);
844
                }
845
                if (head->nodetype==en_icon)
846
                        lfs.printf("%d", head->i);
847
                head = head->p[2];
848
        }
849
        lfs.printf("}");
850
}
851
 
852
Operand *GenerateAssign(ENODE *node, int flags, int size);
853
 
854
// Generate an assignment to a structure type. The type passed must be a
855
// structure type.
856
 
857
void GenerateStructAssign(TYP *tp, int64_t offset, ENODE *ep, Operand *base)
858
{
859
        SYM *thead, *first;
860
        Operand *ap1, *ap2;
861
        int64_t offset2;
862
 
863
        first = thead = SYM::GetPtr(tp->lst.GetHead());
864
        ep = ep->p[0];
865
        while (thead) {
866
                if (ep == nullptr)
867
                        break;
868
                if (thead->tp->IsAggregateType()) {
869
                        if (ep->p[2])
870
                                GenerateStructAssign(thead->tp, offset, ep->p[2], base);
871
                }
872
                else {
873
                        ap2 = nullptr;
874
                        if (ep->p[2]==nullptr)
875
                                break;
876
                        ap1 = GenerateExpression(ep->p[2],F_REG,thead->tp->size);
877
                        if (ap1->mode==am_imm) {
878
                                ap2 = GetTempRegister();
879
                                GenLdi(ap2,ap1);
880
                        }
881
                        else {
882
                                ap2 = ap1;
883
                                ap1 = nullptr;
884
                        }
885
                        if (base->offset)
886
                                offset2 = base->offset->i + offset;
887
                        else
888
                                offset2 = offset;
889
                        switch(thead->tp->size)
890
                        {
891
                        case 1: GenerateDiadic(op_sb,0,ap2,make_indexed(offset,base->preg)); break;
892
                        case 2: GenerateDiadic(op_sc,0,ap2,make_indexed(offset,base->preg)); break;
893
                        case 4: GenerateDiadic(op_sh,0,ap2,make_indexed(offset,base->preg)); break;
894
                        case 512:       GenerateDiadic(op_sv,0,ap2,make_indexed(offset,base->preg)); break;
895
                        default:        GenerateDiadic(op_sw,0,ap2,make_indexed(offset,base->preg)); break;
896
                        }
897
                        if (ap2)
898
                                ReleaseTempReg(ap2);
899
                        if (ap1)
900
                                ReleaseTempReg(ap1);
901
                }
902
                if (!thead->tp->IsUnion())
903
                        offset += thead->tp->size;
904
                thead = SYM::GetPtr(thead->next);
905
                ep = ep->p[2];
906
        }
907
        if (!thead && ep)
908
                error(ERR_TOOMANYELEMENTS);
909
}
910
 
911
 
912
Operand *GenerateAggregateAssign(ENODE *node1, ENODE *node2);
913
 
914
// Generate an assignment to an array.
915
 
916
void GenerateArrayAssign(TYP *tp, ENODE *node1, ENODE *node2, Operand *base)
917
{
918
        ENODE *ep1;
919
        Operand *ap1, *ap2;
920
        int size = tp->size;
921
        int64_t offset, offset2;
922
 
923
        offset = 0;
924
        if (node1->tp)
925
                tp = node1->tp->GetBtp();
926
        else
927
                tp = nullptr;
928
        if (tp==nullptr)
929
                tp = &stdlong;
930
        if (tp->IsStructType()) {
931
                ep1 = nullptr;
932
                ep1 = node2->p[0];
933
                while (ep1 && offset < size) {
934
                        GenerateStructAssign(tp, offset, ep1->p[2], base);
935
                        if (!tp->IsUnion())
936
                                offset += tp->size;
937
                        ep1 = ep1->p[2];
938
                }
939
        }
940
        else if (tp->IsAggregateType()){
941
                GenerateAggregateAssign(node1->p[0],node2->p[0]);
942
        }
943
        else {
944
                ep1 = node2->p[0];
945
                offset = 0;
946
                if (base->offset)
947
                        offset = base->offset->i;
948
                ep1 = ep1->p[2];
949
                while (ep1) {
950
                        ap1 = GenerateExpression(ep1,F_REG|F_IMMED,sizeOfWord);
951
                        ap2 = GetTempRegister();
952
                        if (ap1->mode==am_imm)
953
                                GenLdi(ap2,ap1);
954
                        else {
955
                                if (ap1->offset)
956
                                        offset2 = ap1->offset->i;
957
                                else
958
                                        offset2 = 0;
959
                                GenerateDiadic(op_mov,0,ap2,ap1);
960
                        }
961
                        switch(tp->GetElementSize())
962
                        {
963
                        case 1: GenerateDiadic(op_sb,0,ap2,make_indexed(offset,base->preg)); break;
964
                        case 2: GenerateDiadic(op_sc,0,ap2,make_indexed(offset,base->preg)); break;
965
                        case 4: GenerateDiadic(op_sh,0,ap2,make_indexed(offset,base->preg)); break;
966
                        case 512:       GenerateDiadic(op_sv,0,ap2,make_indexed(offset,base->preg)); break;
967
                        default:        GenerateDiadic(op_sw,0,ap2,make_indexed(offset,base->preg)); break;
968
                        }
969
                        offset += tp->GetElementSize();
970
                        ReleaseTempReg(ap2);
971
                        ReleaseTempReg(ap1);
972
                        ep1 = ep1->p[2];
973
                }
974
        }
975
}
976
 
977
Operand *GenerateAggregateAssign(ENODE *node1, ENODE *node2)
978
{
979
        Operand *base;
980
        TYP *tp;
981
        int64_t offset = 0;
982
 
983
        if (node1==nullptr || node2==nullptr)
984
                return nullptr;
985
        //DumpStructEnodes(node2);
986
        base = GenerateExpression(node1,F_MEM,sizeOfWord);
987
        //base = GenerateDereference(node1,F_MEM,sizeOfWord,0);
988
        tp = node1->tp;
989
        if (tp==nullptr)
990
                tp = &stdlong;
991
        if (tp->IsStructType()) {
992
                if (base->offset)
993
                        offset = base->offset->i;
994
                else
995
                        offset = 0;
996
                GenerateStructAssign(tp,offset,node2->p[0],base);
997
                //GenerateStructAssign(tp,offset2,node2->p[0]->p[0],base);
998
        }
999
        // Process Array
1000
        else {
1001
                GenerateArrayAssign(tp, node1, node2, base);
1002
        }
1003
        return base;
1004
}
1005
 
1006
 
1007
// ----------------------------------------------------------------------------
1008
// Generate code for an assignment node. If the size of the assignment
1009
// destination is larger than the size passed then everything below this node
1010
// will be evaluated with the assignment size.
1011
// ----------------------------------------------------------------------------
1012
Operand *GenerateAssign(ENODE *node, int flags, int size)
1013
{
1014
        Operand *ap1, *ap2 ,*ap3;
1015
        TYP *tp;
1016
    int ssize;
1017
 
1018
    Enter("GenAssign");
1019
 
1020
    if (node->p[0]->IsBitfield()) {
1021
      Leave("GenAssign",0);
1022
                return GenerateBitfieldAssign(node, flags, size);
1023
    }
1024
 
1025
        ssize = node->p[0]->GetReferenceSize();
1026
//      if( ssize > size )
1027
//                      size = ssize;
1028
/*
1029
    if (node->tp->type==bt_struct || node->tp->type==bt_union) {
1030
                ap1 = GenerateExpression(node->p[0],F_REG,ssize);
1031
                ap2 = GenerateExpression(node->p[1],F_REG,size);
1032
                GenerateMonadic(op_push,0,make_immed(node->tp->size));
1033
                GenerateMonadic(op_push,0,ap2);
1034
                GenerateMonadic(op_push,0,ap1);
1035
                GenerateMonadic(op_bsr,0,make_string("memcpy_"));
1036
                GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(24));
1037
                ReleaseTempReg(ap2);
1038
                return ap1;
1039
    }
1040
*/
1041
        tp = node->p[0]->tp;
1042
        if (tp) {
1043
                if (node->p[0]->tp->IsAggregateType() || node->p[1]->nodetype==en_list || node->p[1]->nodetype==en_aggregate)
1044
                        return GenerateAggregateAssign(node->p[0],node->p[1]);
1045
        }
1046
        //if (size > 8) {
1047
        //      ap1 = GenerateExpression(node->p[0],F_MEM,ssize);
1048
        //      ap2 = GenerateExpression(node->p[1],F_MEM,size);
1049
        //}
1050
        //else {
1051
                ap1 = GenerateExpression(node->p[0], F_REG | F_FPREG | F_MEM | F_VREG | F_VMREG, ssize);
1052
                ap2 = GenerateExpression(node->p[1],F_ALL,size);
1053
                if (node->p[0]->isUnsigned && !node->p[1]->isUnsigned)
1054
                    ap2->GenZeroExtend(size,ssize);
1055
//      }
1056
        if (ap1->mode == am_reg || ap1->mode==am_fpreg) {
1057
                switch(ap2->mode) {
1058
                case am_reg:
1059
                        GenerateHint(2);
1060
                        if (ap2->isPtr) {
1061
                                GenerateZeradic(op_setwb);
1062
                                ap1->isPtr = TRUE;
1063
                        }
1064
                        GenerateDiadic(op_mov, 0, ap1, ap2);
1065
                        break;
1066
                case am_fpreg:
1067
                        GenerateHint(2);
1068
                        if (ap1->mode==am_fpreg)
1069
                                GenerateDiadic(op_mov,0,ap1,ap2);
1070
                        else
1071
                                GenerateDiadic(op_mov,0,ap1,ap2);
1072
                        break;
1073
                case am_imm:
1074
                        if (ap2->isPtr)
1075
                                GenerateZeradic(op_setwb);
1076
                        GenerateDiadic(op_ldi,0,ap1,ap2);
1077
                        ap1->isPtr = ap2->isPtr;
1078
                        break;
1079
                default:
1080
                        GenLoad(ap1,ap2,ssize,size);
1081
                        ap1->isPtr = ap2->isPtr;
1082
                        break;
1083
                }
1084
        }
1085
        else if (ap1->mode == am_vreg) {
1086
                if (ap2->mode==am_vreg) {
1087
                        GenerateDiadic(op_mov,0,ap1,ap2);
1088
                }
1089
                else
1090
                        GenLoad(ap1,ap2,ssize,size);
1091
        }
1092
        // ap1 is memory
1093
        else {
1094
                if (ap2->mode == am_reg || ap2->mode == am_fpreg) {
1095
                    GenStore(ap2,ap1,ssize);
1096
        }
1097
                else if (ap2->mode == am_imm) {
1098
            if (ap2->offset->i == 0 && ap2->offset->nodetype != en_labcon) {
1099
                GenStore(makereg(0),ap1,ssize);
1100
            }
1101
            else {
1102
                        ap3 = GetTempRegister();
1103
                                GenerateDiadic(op_ldi,0,ap3,ap2);
1104
                                GenStore(ap3,ap1,ssize);
1105
                        ReleaseTempReg(ap3);
1106
          }
1107
                }
1108
                else {
1109
                        if (ap1->type==stddouble.GetIndex() || ap1->type==stdflt.GetIndex()
1110
                                || ap1->type==stdtriple.GetIndex() || ap1->type==stdquad.GetIndex())
1111
                                ap3 = GetTempFPRegister();
1112
                        else
1113
                                ap3 = GetTempRegister();
1114
                        // Generate a memory to memory move (struct assignments)
1115
                        if (ssize > 8) {
1116
                                if (ap1->type==stdvector.GetIndex() && ap2->type==stdvector.GetIndex()) {
1117
                                        if (ap2->mode==am_reg)
1118
                                                GenStore(ap2,ap1,ssize);
1119
                                        else {
1120
                                                ap3 = GetTempVectorRegister();
1121
                                                GenLoad(ap3,ap2,ssize,ssize);
1122
                                                GenStore(ap3,ap1,ssize);
1123
                                                ReleaseTempRegister(ap3);
1124
                                        }
1125
                                }
1126
                                else {
1127
                                        if (!cpu.SupportsPush) {
1128
                                                GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(3 * sizeOfWord));
1129
                                                ap3 = GetTempRegister();
1130
                                                GenerateDiadic(op_ldi,0,ap3,make_immed(size));
1131
                                                GenerateDiadic(op_sw,0,ap3,make_indexed(2 * sizeOfWord,regSP));
1132
                                                GenerateDiadic(op_mov,0,ap3,ap2);
1133
                                                GenerateDiadic(op_sw,0,ap3,make_indexed(1 * sizeOfWord,regSP));
1134
                                                GenerateDiadic(op_mov,0,ap3,ap1);
1135
                                                GenerateDiadic(op_sw,0,ap3,make_indirect(regSP));
1136
                                        }
1137
                                        else {
1138
                                                GenerateMonadic(op_push,0,make_immed(size));
1139
                                                GenerateMonadic(op_push,0,ap2);
1140
                                                GenerateMonadic(op_push,0,ap1);
1141
                                        }
1142
                                        GenerateDiadic(op_jal,0,makereg(regLR),make_string("memcpy_"));
1143
                                        GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(3*sizeOfWord));
1144
                                }
1145
                        }
1146
                        else {
1147
                                ap3->isPtr = ap2->isPtr;
1148
                GenLoad(ap3,ap2,ssize,size);
1149
/*
1150
                                if (ap1->isUnsigned) {
1151
                                        switch(size) {
1152
                                        case 1: GenerateDiadic(op_lbu,0,ap3,ap2); break;
1153
                                        case 2: GenerateDiadic(op_lcu,0,ap3,ap2); break;
1154
                                        case 4: GenerateDiadic(op_lhu,0,ap3,ap2); break;
1155
                                        case 8: GenerateDiadic(op_lw,0,ap3,ap2); break;
1156
                                        }
1157
                                }
1158
                                else {
1159
                                        switch(size) {
1160
                                        case 1: GenerateDiadic(op_lb,0,ap3,ap2); break;
1161
                                        case 2: GenerateDiadic(op_lc,0,ap3,ap2); break;
1162
                                        case 4: GenerateDiadic(op_lh,0,ap3,ap2); break;
1163
                                        case 8: GenerateDiadic(op_lw,0,ap3,ap2); break;
1164
                                        }
1165
                                        if (ssize > size) {
1166
                                                switch(size) {
1167
                                                case 1: GenerateDiadic(op_sxb,0,ap3,ap3); break;
1168
                                                case 2: GenerateDiadic(op_sxc,0,ap3,ap3); break;
1169
                                                case 4: GenerateDiadic(op_sxh,0,ap3,ap3); break;
1170
                                                }
1171
                                        }
1172
                                }
1173
*/
1174
                                GenStore(ap3,ap1,ssize);
1175
                                ReleaseTempRegister(ap3);
1176
                        }
1177
                }
1178
        }
1179
/*
1180
        if (ap1->mode == am_reg) {
1181
                if (ap2->mode==am_imm)  // must be zero
1182
                        GenerateDiadic(op_mov,0,ap1,makereg(0));
1183
                else
1184
                        GenerateDiadic(op_mov,0,ap1,ap2);
1185
        }
1186
        else {
1187
                if (ap2->mode==am_imm)
1188
                switch(size) {
1189
                case 1: GenerateDiadic(op_sb,0,makereg(0),ap1); break;
1190
                case 2: GenerateDiadic(op_sc,0,makereg(0),ap1); break;
1191
                case 4: GenerateDiadic(op_sh,0,makereg(0),ap1); break;
1192
                case 8: GenerateDiadic(op_sw,0,makereg(0),ap1); break;
1193
                }
1194
                else
1195
                switch(size) {
1196
                case 1: GenerateDiadic(op_sb,0,ap2,ap1); break;
1197
                case 2: GenerateDiadic(op_sc,0,ap2,ap1); break;
1198
                case 4: GenerateDiadic(op_sh,0,ap2,ap1); break;
1199
                case 8: GenerateDiadic(op_sw,0,ap2,ap1); break;
1200
                // Do structure assignment
1201
                default: {
1202
                        ap3 = GetTempRegister();
1203
                        GenerateDiadic(op_ldi,0,ap3,make_immed(size));
1204
                        GenerateTriadic(op_push,0,ap3,ap2,ap1);
1205
                        GenerateDiadic(op_jal,0,makereg(LR),make_string("memcpy"));
1206
                        GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(24));
1207
                        ReleaseTempRegister(ap3);
1208
                }
1209
                }
1210
        }
1211
*/
1212
        ReleaseTempReg(ap2);
1213
    ap1->MakeLegal(flags,size);
1214
    Leave("GenAssign",1);
1215
        return ap1;
1216
}
1217
 
1218
// autocon and autofcon nodes
1219
 
1220
Operand *GenAutocon(ENODE *node, int flags, int size, int type)
1221
{
1222
        Operand *ap1, *ap2;
1223
 
1224
        if (type==stddouble.GetIndex() || type==stdflt.GetIndex() || type==stdtriple.GetIndex() || type==stdquad.GetIndex())
1225
                ap1 = GetTempFPRegister();
1226
        else
1227
                ap1 = GetTempRegister();
1228
        ap2 = allocOperand();
1229
        ap2->isPtr = node->etype == bt_pointer;
1230
        ap2->mode = am_indx;
1231
        ap2->preg = regFP;          /* frame pointer */
1232
        ap2->offset = node;     /* use as constant node */
1233
        ap2->type = type;
1234
        ap1->type = type;
1235
        GenerateDiadic(op_lea,0,ap1,ap2);
1236
        ap1->MakeLegal(flags,size);
1237
        return (ap1);             /* return reg */
1238
}
1239
 
1240
//
1241
// General expression evaluation. returns the addressing mode
1242
// of the result.
1243
//
1244
Operand *GenerateExpression(ENODE *node, int flags, int size)
1245
{
1246
        Operand *ap1, *ap2;
1247
    int natsize;
1248
        static char buf[4][20];
1249
        static int ndx;
1250
        static int numDiags = 0;
1251
 
1252
    Enter("<GenerateExpression>");
1253
    if( node == (ENODE *)NULL )
1254
    {
1255
                throw new C64PException(ERR_NULLPOINTER, 'G');
1256
                numDiags++;
1257
        printf("DIAG - null node in GenerateExpression.\n");
1258
                if (numDiags > 100)
1259
                        exit(0);
1260
        Leave("</GenerateExpression>",2);
1261
        return (Operand *)NULL;
1262
    }
1263
        //size = node->esize;
1264
    switch( node->nodetype )
1265
    {
1266
        case en_fcon:
1267
        ap1 = allocOperand();
1268
                ap1->isPtr = node->IsPtr();
1269
                ap1->mode = am_direct;
1270
        ap1->offset = node;
1271
                ap1->type = stddouble.GetIndex();
1272
        ap1->MakeLegal(flags,size);
1273
        Leave("</GenerateExpression>",2);
1274
        return (ap1);
1275
                /*
1276
            ap1 = allocOperand();
1277
            ap1->mode = am_imm;
1278
            ap1->offset = node;
1279
                        ap1->isFloat = TRUE;
1280
            ap1->MakeLegal(flags,size);
1281
         Leave("GenExperssion",2);
1282
            return ap1;
1283
                */
1284
    case en_icon:
1285
        ap1 = allocOperand();
1286
        ap1->mode = am_imm;
1287
        ap1->offset = node;
1288
        ap1->MakeLegal(flags,size);
1289
        Leave("GenExpression",3);
1290
        return (ap1);
1291
 
1292
        case en_labcon:
1293
            if (use_gp) {
1294
                ap1 = GetTempRegister();
1295
                ap2 = allocOperand();
1296
                ap2->mode = am_indx;
1297
                                switch (node->segment) {
1298
                                case tlsseg:    ap2->preg = regTP; break;
1299
                                case dataseg:   ap2->preg = regGP; break;
1300
                                default:        ap2->preg = regPP;
1301
                                }
1302
                ap2->offset = node;     // use as constant node
1303
                GenerateDiadic(op_lea,0,ap1,ap2);
1304
                                ap1->MakeLegal(flags,size);
1305
         Leave("GenExperssion",4);
1306
                return ap1;             // return reg
1307
            }
1308
            ap1 = allocOperand();
1309
                        ap1->isPtr = node->IsPtr();
1310
                        /* this code not really necessary, see segments notes
1311
                        if (node->etype==bt_pointer && node->constflag) {
1312
                                ap1->segment = codeseg;
1313
                        }
1314
                        else {
1315
                                ap1->segment = dataseg;
1316
                        }
1317
                        */
1318
            ap1->mode = am_imm;
1319
            ap1->offset = node;
1320
                        ap1->isUnsigned = node->isUnsigned;
1321
            ap1->MakeLegal(flags,size);
1322
         Leave("GenExperssion",5);
1323
            return ap1;
1324
 
1325
    case en_nacon:
1326
            if (use_gp) {
1327
                ap1 = GetTempRegister();
1328
                ap2 = allocOperand();
1329
                ap2->mode = am_indx;
1330
                ap2->preg = regGP;      // global pointer
1331
                ap2->offset = node;     // use as constant node
1332
                GenerateDiadic(op_lea,0,ap1,ap2);
1333
                                ap1->MakeLegal(flags,size);
1334
                                Leave("GenExpression",6);
1335
                return ap1;             // return reg
1336
            }
1337
            // fallthru
1338
        case en_cnacon:
1339
            ap1 = allocOperand();
1340
                        ap1->isPtr = node->IsPtr();
1341
                        ap1->mode = am_imm;
1342
            ap1->offset = node;
1343
                        if (node->i==0)
1344
                                node->i = -1;
1345
                        ap1->isUnsigned = node->isUnsigned;
1346
            ap1->MakeLegal(flags,size);
1347
                        Leave("GenExpression",7);
1348
            return ap1;
1349
        case en_clabcon:
1350
            ap1 = allocOperand();
1351
            ap1->mode = am_imm;
1352
            ap1->offset = node;
1353
                        ap1->isUnsigned = node->isUnsigned;
1354
            ap1->MakeLegal(flags,size);
1355
                        Leave("GenExpression",7);
1356
            return ap1;
1357
    case en_autocon:    return GenAutocon(node, flags, size, stdint.GetIndex());
1358
    case en_autofcon:
1359
                switch (node->tp->type)
1360
                {
1361
                case bt_float:  return GenAutocon(node, flags, size, stdflt.GetIndex());
1362
                case bt_double: return GenAutocon(node, flags, size, stddouble.GetIndex());
1363
                case bt_triple: return GenAutocon(node, flags, size, stdtriple.GetIndex());
1364
                case bt_quad:   return GenAutocon(node, flags, size, stdquad.GetIndex());
1365
                }
1366
                break;
1367
    case en_autovcon:   return GenAutocon(node, flags, size, stdvector.GetIndex());
1368
    case en_autovmcon:  return GenAutocon(node, flags, size, stdvectormask->GetIndex());
1369
    case en_classcon:
1370
            ap1 = GetTempRegister();
1371
            ap2 = allocOperand();
1372
            ap2->mode = am_indx;
1373
            ap2->preg = regCLP;     /* frame pointer */
1374
            ap2->offset = node;     /* use as constant node */
1375
            GenerateDiadic(op_lea,0,ap1,ap2);
1376
                        ap1->MakeLegal(flags,size);
1377
            return ap1;             /* return reg */
1378
    case en_ub_ref:
1379
        case en_uc_ref:
1380
        case en_uh_ref:
1381
        case en_uw_ref:
1382
                ap1 = GenerateDereference(node, flags, size, 0);
1383
                ap1->isUnsigned = TRUE;
1384
                return ap1;
1385
        case en_hp_ref:
1386
        case en_wp_ref:
1387
                        ap1 = GenerateDereference(node,flags,size,0);
1388
                        ap1->isPtr = TRUE;
1389
                        ap1->isUnsigned = TRUE;
1390
            return ap1;
1391
        case en_vector_ref:     return GenerateDereference(node,flags,512,0);
1392
        case en_ref32:  return GenerateDereference(node,flags,4,1);
1393
        case en_ref32u: return GenerateDereference(node,flags,4,0);
1394
    case en_b_ref:      return GenerateDereference(node,flags,1,1);
1395
        case en_c_ref:  return GenerateDereference(node,flags,2,1);
1396
        case en_h_ref:  return GenerateDereference(node,flags,4,1);
1397
    case en_w_ref:      return GenerateDereference(node,flags,8,1);
1398
        case en_flt_ref:
1399
                ap1 = GenerateDereference(node, flags, size, 1);
1400
                ap1->type = stdflt.GetIndex();
1401
                return (ap1);
1402
        case en_dbl_ref:
1403
                ap1 = GenerateDereference(node, flags, size, 1);
1404
                ap1->type = stddouble.GetIndex();
1405
                return (ap1);
1406
        case en_triple_ref:
1407
                ap1 = GenerateDereference(node, flags, size, 1);
1408
                ap1->type = stdtriple.GetIndex();
1409
                return (ap1);
1410
        case en_quad_ref:
1411
                        ap1 = GenerateDereference(node,flags,size,1);
1412
                        ap1->type = stdquad.GetIndex();
1413
            return (ap1);
1414
        case en_ubfieldref:
1415
        case en_ucfieldref:
1416
        case en_uhfieldref:
1417
        case en_uwfieldref:
1418
                        ap1 = (flags & BF_ASSIGN) ? GenerateDereference(node,flags & ~BF_ASSIGN,size,0) : GenerateBitfieldDereference(node,flags,size);
1419
                        ap1->isUnsigned = TRUE;
1420
                        return ap1;
1421
        case en_wfieldref:
1422
        case en_bfieldref:
1423
        case en_cfieldref:
1424
        case en_hfieldref:
1425
                        ap1 = (flags & BF_ASSIGN) ? GenerateDereference(node,flags & ~BF_ASSIGN,size,1) : GenerateBitfieldDereference(node,flags,size);
1426
                        return ap1;
1427
        case en_regvar:
1428
    case en_tempref:
1429
            ap1 = allocOperand();
1430
                        ap1->isPtr = node->IsPtr();
1431
            ap1->mode = am_reg;
1432
            ap1->preg = node->i;
1433
            ap1->tempflag = 0;      /* not a temporary */
1434
            ap1->MakeLegal(flags,size);
1435
            return (ap1);
1436
    case en_tempfpref:
1437
            ap1 = allocOperand();
1438
            ap1->mode = am_fpreg;
1439
            ap1->preg = node->i;
1440
            ap1->tempflag = 0;      /* not a temporary */
1441
                        if (node->tp)
1442
                                switch (node->tp->type) {
1443
                                case bt_float:  ap1->type = stdflt.GetIndex(); break;
1444
                                case bt_double: ap1->type = stddouble.GetIndex(); break;
1445
                                case bt_triple: ap1->type = stdtriple.GetIndex(); break;
1446
                                case bt_quad:   ap1->type = stdquad.GetIndex(); break;
1447
                                }
1448
                        else
1449
                                ap1->type = stddouble.GetIndex();
1450
                        ap1->MakeLegal(flags,size);
1451
            return ap1;
1452
        case en_fpregvar:
1453
//    case en_fptempref:
1454
            ap1 = allocOperand();
1455
            ap1->mode = am_fpreg;
1456
            ap1->preg = node->i;
1457
            ap1->tempflag = 0;      /* not a temporary */
1458
                        if (node->tp)
1459
                                switch (node->tp->type) {
1460
                                case bt_float:  ap1->type = stdflt.GetIndex(); break;
1461
                                case bt_double: ap1->type = stddouble.GetIndex(); break;
1462
                                case bt_triple: ap1->type = stdtriple.GetIndex(); break;
1463
                                case bt_quad:   ap1->type = stdquad.GetIndex(); break;
1464
                                }
1465
                        else
1466
                                ap1->type = stddouble.GetIndex();
1467
                        ap1->MakeLegal(flags,size);
1468
            return ap1;
1469
        case en_abs:    return node->GenUnary(flags,size,op_abs);
1470
    case en_uminus: return node->GenUnary(flags,size,op_neg);
1471
    case en_compl:  return node->GenUnary(flags,size,op_com);
1472
        case en_not:    return (node->GenUnary(flags, 8, op_not));
1473
    case en_add:    return node->GenBinary(flags,size,op_add);
1474
    case en_sub:    return node->GenBinary(flags,size,op_sub);
1475
    case en_i2d:
1476
         ap1 = GetTempFPRegister();
1477
         ap2=GenerateExpression(node->p[0],F_REG,8);
1478
         GenerateDiadic(op_itof,'d',ap1,ap2);
1479
         ReleaseTempReg(ap2);
1480
         return (ap1);
1481
    case en_i2q:
1482
         ap1 = GetTempFPRegister();
1483
         ap2 = GenerateExpression(node->p[0],F_REG,8);
1484
                 GenerateTriadic(op_csrrw,0,makereg(0),make_immed(0x18),ap2);
1485
                 GenerateZeradic(op_nop);
1486
                 GenerateZeradic(op_nop);
1487
         GenerateDiadic(op_itof,'q',ap1,makereg(63));
1488
         ReleaseTempReg(ap2);
1489
         return (ap1);
1490
    case en_i2t:
1491
         ap1 = GetTempFPRegister();
1492
         ap2 = GenerateExpression(node->p[0],F_REG,8);
1493
                 GenerateTriadic(op_csrrw,0,makereg(0),make_immed(0x18),ap2);
1494
                 GenerateZeradic(op_nop);
1495
                 GenerateZeradic(op_nop);
1496
         GenerateDiadic(op_itof,'t',ap1,makereg(63));
1497
         ReleaseTempReg(ap2);
1498
         return (ap1);
1499
    case en_d2i:
1500
         ap1 = GetTempRegister();
1501
         ap2 = GenerateExpression(node->p[0],F_FPREG,8);
1502
         GenerateDiadic(op_ftoi,'d',ap1,ap2);
1503
         ReleaseTempReg(ap2);
1504
         return (ap1);
1505
    case en_q2i:
1506
         ap1 = GetTempRegister();
1507
         ap2 = GenerateExpression(node->p[0],F_FPREG,8);
1508
         GenerateDiadic(op_ftoi,'q',makereg(63),ap2);
1509
                 GenerateZeradic(op_nop);
1510
                 GenerateZeradic(op_nop);
1511
                 GenerateTriadic(op_csrrw,0,ap1,make_immed(0x18),makereg(0));
1512
         ReleaseTempReg(ap2);
1513
         return (ap1);
1514
    case en_t2i:
1515
         ap1 = GetTempRegister();
1516
         ap2 = GenerateExpression(node->p[0],F_FPREG,8);
1517
         GenerateDiadic(op_ftoi,'t',makereg(63),ap2);
1518
                 GenerateZeradic(op_nop);
1519
                 GenerateZeradic(op_nop);
1520
                 GenerateTriadic(op_csrrw,0,ap1,make_immed(0x18),makereg(0));
1521
         ReleaseTempReg(ap2);
1522
         return (ap1);
1523
        case en_s2q:
1524
                ap1 = GetTempFPRegister();
1525
        ap2 = GenerateExpression(node->p[0],F_FPREG,8);
1526
        GenerateDiadic(op_fcvtsq,0,ap1,ap2);
1527
                ap1->type = stdquad.GetIndex();
1528
                ReleaseTempReg(ap2);
1529
                return ap1;
1530
        case en_d2q:
1531
                ap1 = GetTempFPRegister();
1532
                ap2 = GenerateExpression(node->p[0], F_FPREG, 8);
1533
                GenerateDiadic(op_fcvtdq, 0, ap1, ap2);
1534
                ap1->type = stdquad.GetIndex();
1535
                ReleaseTempReg(ap2);
1536
                return ap1;
1537
        case en_t2q:
1538
                ap1 = GetTempFPRegister();
1539
                ap2 = GenerateExpression(node->p[0], F_FPREG, 8);
1540
                GenerateDiadic(op_fcvttq, 0, ap1, ap2);
1541
                ap1->type = stdquad.GetIndex();
1542
                ReleaseTempReg(ap2);
1543
                return ap1;
1544
 
1545
        case en_vadd:     return node->GenBinary(flags,size,op_vadd);
1546
        case en_vsub:     return node->GenBinary(flags,size,op_vsub);
1547
        case en_vmul:     return node->GenBinary(flags,size,op_vmul);
1548
        case en_vadds:    return node->GenBinary(flags,size,op_vadds);
1549
        case en_vsubs:    return node->GenBinary(flags,size,op_vsubs);
1550
        case en_vmuls:    return node->GenBinary(flags,size,op_vmuls);
1551
        case en_vex:      return node->GenBinary(flags,size,op_vex);
1552
        case en_veins:    return node->GenBinary(flags,size,op_veins);
1553
 
1554
        case en_fadd:     return node->GenBinary(flags,size,op_fadd);
1555
        case en_fsub:     return node->GenBinary(flags,size,op_fsub);
1556
        case en_fmul:     return node->GenBinary(flags,size,op_fmul);
1557
        case en_fdiv:     return node->GenBinary(flags,size,op_fdiv);
1558
 
1559
        case en_fdadd:    return node->GenBinary(flags,size,op_fdadd);
1560
    case en_fdsub:    return node->GenBinary(flags,size,op_fdsub);
1561
    case en_fsadd:    return node->GenBinary(flags,size,op_fsadd);
1562
    case en_fssub:    return node->GenBinary(flags,size,op_fssub);
1563
    case en_fdmul:    return GenerateMultiply(node,flags,size,op_fmul);
1564
    case en_fsmul:    return GenerateMultiply(node,flags,size,op_fmul);
1565
    case en_fddiv:    return GenerateMultiply(node,flags,size,op_fddiv);
1566
    case en_fsdiv:    return GenerateMultiply(node,flags,size,op_fsdiv);
1567
        case en_ftadd:    return node->GenBinary(flags,size,op_ftadd);
1568
    case en_ftsub:    return node->GenBinary(flags,size,op_ftsub);
1569
    case en_ftmul:    return GenerateMultiply(node,flags,size,op_ftmul);
1570
    case en_ftdiv:    return GenerateMultiply(node,flags,size,op_ftdiv);
1571
 
1572
        case en_land:   return (node->GenLand(flags,op_and));
1573
        case en_lor:    return (node->GenLand(flags, op_or));
1574
        case en_and:    return node->GenBinary(flags,size,op_and);
1575
    case en_or:     return node->GenBinary(flags,size,op_or);
1576
        case en_xor:    return node->GenBinary(flags,size,op_xor);
1577
    case en_mul:    return GenerateMultiply(node,flags,size,op_mul);
1578
    case en_mulu:   return GenerateMultiply(node,flags,size,op_mulu);
1579
    case en_div:    return node->GenDivMod(flags,size,op_div);
1580
    case en_udiv:   return node->GenDivMod(flags,size,op_divu);
1581
    case en_mod:    return node->GenDivMod(flags,size,op_mod);
1582
    case en_umod:   return node->GenDivMod(flags,size,op_modu);
1583
    case en_asl:    return node->GenShift(flags,size,op_asl);
1584
    case en_shl:    return node->GenShift(flags,size,op_shl);
1585
    case en_shlu:   return node->GenShift(flags,size,op_shl);
1586
    case en_asr:        return node->GenShift(flags,size,op_asr);
1587
    case en_shr:        return node->GenShift(flags,size,op_asr);
1588
    case en_shru:   return node->GenShift(flags,size,op_shru);
1589
        case en_rol:   return node->GenShift(flags,size,op_rol);
1590
        case en_ror:   return node->GenShift(flags,size,op_ror);
1591
        /*
1592
        case en_asfadd: return GenerateAssignAdd(node,flags,size,op_fadd);
1593
        case en_asfsub: return GenerateAssignAdd(node,flags,size,op_fsub);
1594
        case en_asfmul: return GenerateAssignAdd(node,flags,size,op_fmul);
1595
        case en_asfdiv: return GenerateAssignAdd(node,flags,size,op_fdiv);
1596
        */
1597
    case en_asadd:  return node->GenAssignAdd(flags,size,op_add);
1598
    case en_assub:  return node->GenAssignAdd(flags,size,op_sub);
1599
    case en_asand:  return node->GenAssignLogic(flags,size,op_and);
1600
    case en_asor:   return node->GenAssignLogic(flags,size,op_or);
1601
        case en_asxor:  return node->GenAssignLogic(flags,size,op_xor);
1602
    case en_aslsh:  return (node->GenAssignShift(flags,size,op_shl));
1603
    case en_asrsh:  return (node->GenAssignShift(flags,size,op_asr));
1604
        case en_asrshu: return (node->GenAssignShift(flags,size,op_shru));
1605
    case en_asmul: return GenerateAssignMultiply(node,flags,size,op_mul);
1606
    case en_asmulu: return GenerateAssignMultiply(node,flags,size,op_mulu);
1607
    case en_asdiv: return GenerateAssignModiv(node,flags,size,op_div);
1608
    case en_asdivu: return GenerateAssignModiv(node,flags,size,op_divu);
1609
    case en_asmod: return GenerateAssignModiv(node,flags,size,op_mod);
1610
    case en_asmodu: return GenerateAssignModiv(node,flags,size,op_modu);
1611
    case en_assign:
1612
            return (GenerateAssign(node,flags,size));
1613
 
1614
        case en_chk:
1615
        return (GenExpr(node));
1616
 
1617
    case en_eq:     case en_ne:
1618
    case en_lt:     case en_le:
1619
    case en_gt:     case en_ge:
1620
    case en_ult:    case en_ule:
1621
    case en_ugt:    case en_uge:
1622
    case en_feq:    case en_fne:
1623
    case en_flt:    case en_fle:
1624
    case en_fgt:    case en_fge:
1625
    case en_veq:    case en_vne:
1626
    case en_vlt:    case en_vle:
1627
    case en_vgt:    case en_vge:
1628
      return GenExpr(node);
1629
 
1630
        case en_cond:
1631
            return node->GenHook(flags,size);
1632
    case en_void:
1633
            natsize = GetNaturalSize(node->p[0]);
1634
            ReleaseTempRegister(GenerateExpression(node->p[0],F_ALL | F_NOVALUE,natsize));
1635
                        ap1 = GenerateExpression(node->p[1], flags, size);
1636
                        ap1->isPtr = node->IsPtr();
1637
            return (ap1);
1638
 
1639
    case en_fcall:
1640
                return (GenerateFunctionCall(node,flags));
1641
 
1642
        case en_sxb:
1643
                ap2 = GetTempRegister();
1644
                ap1 = GenerateExpression(node->p[0], F_REG, 8);
1645
                GenerateDiadic(op_sxb, 0, ap2, ap1);
1646
                ReleaseTempReg(ap1);
1647
                ap2->MakeLegal( flags, 8);
1648
                return (ap2);
1649
        case en_sxc:
1650
                ap2 = GetTempRegister();
1651
                ap1 = GenerateExpression(node->p[0], F_REG, 8);
1652
                GenerateDiadic(op_sxc, 0, ap2, ap1);
1653
                ReleaseTempReg(ap1);
1654
                ap2->MakeLegal( flags, 8);
1655
                return (ap2);
1656
        case en_sxh:
1657
                ap2 = GetTempRegister();
1658
                ap1 = GenerateExpression(node->p[0], F_REG, 8);
1659
                GenerateDiadic(op_sxh, 0, ap2, ap1);
1660
                ReleaseTempReg(ap1);
1661
                ap2->MakeLegal( flags, 8);
1662
                return (ap2);
1663
        case en_cubw:
1664
        case en_cubu:
1665
        case en_cbu:
1666
                        ap1 = GenerateExpression(node->p[0],F_REG,size);
1667
                        GenerateTriadic(op_and,0,ap1,ap1,make_immed(0xff));
1668
                        return (ap1);
1669
        case en_cucw:
1670
        case en_cucu:
1671
        case en_ccu:
1672
                        ap1 = GenerateExpression(node->p[0],F_REG,size);
1673
                        GenerateDiadic(op_zxc,0,ap1,ap1);
1674
                        return ap1;
1675
        case en_ccwp:
1676
                ap1 = GenerateExpression(node->p[0], F_REG, size);
1677
                ap1->isPtr = TRUE;
1678
                GenerateDiadic(op_sxc, 0, ap1, ap1);
1679
                return ap1;
1680
        case en_cucwp:
1681
                ap1 = GenerateExpression(node->p[0], F_REG, size);
1682
                ap1->isPtr = TRUE;
1683
                GenerateDiadic(op_zxc, 0, ap1, ap1);
1684
                return ap1;
1685
        case en_cuhw:
1686
        case en_cuhu:
1687
        case en_chu:
1688
                        ap1 = GenerateExpression(node->p[0],F_REG,size);
1689
                        GenerateDiadic(op_zxh,0,ap1,ap1);
1690
                        return ap1;
1691
        case en_cbw:
1692
                        ap1 = GenerateExpression(node->p[0],F_REG,size);
1693
                        //GenerateDiadic(op_sxb,0,ap1,ap1);
1694
                        GenerateDiadic(op_sxb,0,ap1,ap1);
1695
                        return ap1;
1696
        case en_ccw:
1697
                        ap1 = GenerateExpression(node->p[0],F_REG,size);
1698
                        GenerateDiadic(op_sxc,0,ap1,ap1);
1699
                        return ap1;
1700
        case en_chw:
1701
                        ap1 = GenerateExpression(node->p[0],F_REG,size);
1702
                        GenerateDiadic(op_sxh,0,ap1,ap1);
1703
                        return ap1;
1704
        case en_object_list:
1705
                        ap1 = GetTempRegister();
1706
                        GenerateDiadic(op_lea,0,ap1,make_indexed(-8,regFP));
1707
                        ap1->MakeLegal(flags,sizeOfWord);
1708
                        return (ap1);
1709
    default:
1710
            printf("DIAG - uncoded node (%d) in GenerateExpression.\n", node->nodetype);
1711
            return 0;
1712
    }
1713
        return(0);
1714
}
1715
 
1716
// return the natural evaluation size of a node.
1717
 
1718
int GetNaturalSize(ENODE *node)
1719
{
1720
        int siz0, siz1;
1721
        if( node == NULL )
1722
                return 0;
1723
        switch( node->nodetype )
1724
        {
1725
        case en_uwfieldref:
1726
        case en_wfieldref:
1727
                return sizeOfWord;
1728
        case en_bfieldref:
1729
        case en_ubfieldref:
1730
                return 1;
1731
        case en_cfieldref:
1732
        case en_ucfieldref:
1733
                return 2;
1734
        case en_hfieldref:
1735
        case en_uhfieldref:
1736
                return 4;
1737
        case en_icon:
1738
                if (node->i >= -128 && node->i < 128)
1739
                        return (1);
1740
                if( -32768 <= node->i && node->i <= 32767 )
1741
                        return (2);
1742
                if (-2147483648LL <= node->i && node->i <= 2147483647LL)
1743
                        return (4);
1744
                return (8);
1745
        case en_fcon:
1746
                return node->tp->precision / 16;
1747
        case en_tcon: return 6;
1748
        case en_fcall:  case en_labcon: case en_clabcon:
1749
        case en_cnacon: case en_nacon:  case en_autocon: case en_classcon:
1750
        case en_tempref:
1751
        case en_cbw: case en_cubw:
1752
        case en_ccw: case en_cucw:
1753
        case en_chw: case en_cuhw:
1754
        case en_cbu: case en_ccu: case en_chu:
1755
        case en_cubu: case en_cucu: case en_cuhu:
1756
        case en_ccwp: case en_cucwp:
1757
        case en_sxb:    case en_sxc:    case en_sxh:
1758
                return 8;
1759
        case en_regvar:
1760
        case en_fpregvar:
1761
                if (node->tp)
1762
                        return (node->tp->size);
1763
                else
1764
                        return (8);
1765
        case en_autofcon:
1766
                return 8;
1767
        case en_ref32: case en_ref32u:
1768
                return 4;
1769
        case en_b_ref:
1770
        case en_ub_ref:
1771
                return 1;
1772
        case en_cbc:
1773
        case en_c_ref:  return 2;
1774
        case en_uc_ref: return 2;
1775
        case en_cbh:    return 2;
1776
        case en_cch:    return 2;
1777
        case en_h_ref:  return 4;
1778
        case en_uh_ref: return 4;
1779
        case en_flt_ref: return sizeOfFPS;
1780
        case en_w_ref:  case en_uw_ref:
1781
                return 8;
1782
        case en_hp_ref:
1783
                return 4;
1784
        case en_wp_ref:
1785
                return 8;
1786
        case en_autovcon:
1787
        case en_vector_ref:
1788
                return 512;
1789
        case en_dbl_ref:
1790
                return sizeOfFPD;
1791
        case en_quad_ref:
1792
                return sizeOfFPQ;
1793
        case en_triple_ref:
1794
                return sizeOfFPT;
1795
        case en_tempfpref:
1796
        if (node->tp)
1797
                return node->tp->precision/16;
1798
        else
1799
                return 8;
1800
        case en_not:    case en_compl:
1801
        case en_uminus: case en_assign:
1802
                return GetNaturalSize(node->p[0]);
1803
        case en_fadd:   case en_fsub:
1804
        case en_fmul:   case en_fdiv:
1805
        case en_fsadd:  case en_fssub:
1806
        case en_fsmul:  case en_fsdiv:
1807
        case en_vadd:   case en_vsub:
1808
        case en_vmul:   case en_vdiv:
1809
        case en_vadds:  case en_vsubs:
1810
        case en_vmuls:  case en_vdivs:
1811
        case en_add:    case en_sub:
1812
        case en_mul:    case en_mulu:
1813
        case en_div:    case en_udiv:
1814
        case en_mod:    case en_umod:
1815
        case en_and:    case en_or:     case en_xor:
1816
        case en_asl:
1817
        case en_shl:    case en_shlu:
1818
        case en_shr:    case en_shru:
1819
        case en_asr:    case en_asrshu:
1820
        case en_feq:    case en_fne:
1821
        case en_flt:    case en_fle:
1822
        case en_fgt:    case en_fge:
1823
        case en_eq:     case en_ne:
1824
        case en_lt:     case en_le:
1825
        case en_gt:     case en_ge:
1826
        case en_ult:    case en_ule:
1827
        case en_ugt:    case en_uge:
1828
        case en_land:   case en_lor:
1829
        case en_asadd:  case en_assub:
1830
        case en_asmul:  case en_asmulu:
1831
        case en_asdiv:  case en_asdivu:
1832
        case en_asmod:  case en_asand:
1833
        case en_asor:   case en_asxor:  case en_aslsh:
1834
        case en_asrsh:
1835
                siz0 = GetNaturalSize(node->p[0]);
1836
                siz1 = GetNaturalSize(node->p[1]);
1837
                if( siz1 > siz0 )
1838
                        return siz1;
1839
                else
1840
                        return siz0;
1841
        case en_void:   case en_cond:
1842
                return GetNaturalSize(node->p[1]);
1843
        case en_bchk:
1844
                return (GetNaturalSize(node->p[0]));
1845
        case en_chk:
1846
                return 8;
1847
        case en_q2i:
1848
        case en_t2i:
1849
                return (sizeOfWord);
1850
        case en_i2d:
1851
                return (sizeOfWord);
1852
        case en_i2t:
1853
        case en_d2t:
1854
                return (sizeOfFPT);
1855
        case en_i2q:
1856
        case en_d2q:
1857
        case en_t2q:
1858
                return (sizeOfFPQ);
1859
        default:
1860
                printf("DIAG - natural size error %d.\n", node->nodetype);
1861
                break;
1862
        }
1863
        return 0;
1864
}
1865
 
1866
 
1867
static void GenerateCmp(ENODE *node, int op, int label, unsigned int prediction)
1868
{
1869
        Enter("GenCmp");
1870
        GenerateCmp(node, op, label, 0, prediction);
1871
        Leave("GenCmp",0);
1872
}
1873
 
1874
//
1875
// Generate a jump to label if the node passed evaluates to
1876
// a true condition.
1877
//
1878
void GenerateTrueJump(ENODE *node, int label, unsigned int prediction)
1879
{
1880
        Operand  *ap1;
1881
        int    siz1;
1882
 
1883
        if( node == 0 )
1884
                return;
1885
        switch( node->nodetype )
1886
        {
1887
        case en_bchk:   break;
1888
        case en_eq:     GenerateCmp(node, op_eq, label, prediction); break;
1889
        case en_ne: GenerateCmp(node, op_ne, label, prediction); break;
1890
        case en_lt: GenerateCmp(node, op_lt, label, prediction); break;
1891
        case en_le:     GenerateCmp(node, op_le, label, prediction); break;
1892
        case en_gt: GenerateCmp(node, op_gt, label, prediction); break;
1893
        case en_ge: GenerateCmp(node, op_ge, label, prediction); break;
1894
        case en_ult: GenerateCmp(node, op_ltu, label, prediction); break;
1895
        case en_ule: GenerateCmp(node, op_leu, label, prediction); break;
1896
        case en_ugt: GenerateCmp(node, op_gtu, label, prediction); break;
1897
        case en_uge: GenerateCmp(node, op_geu, label, prediction); break;
1898
        case en_feq: GenerateCmp(node, op_feq, label, prediction); break;
1899
        case en_fne: GenerateCmp(node, op_fne, label, prediction); break;
1900
        case en_flt: GenerateCmp(node, op_flt, label, prediction); break;
1901
        case en_fle: GenerateCmp(node, op_fle, label, prediction); break;
1902
        case en_fgt: GenerateCmp(node, op_fgt, label, prediction); break;
1903
        case en_fge: GenerateCmp(node, op_fge, label, prediction); break;
1904
        case en_veq: GenerateCmp(node, op_vseq, label, prediction); break;
1905
        case en_vne: GenerateCmp(node, op_vsne, label, prediction); break;
1906
        case en_vlt: GenerateCmp(node, op_vslt, label, prediction); break;
1907
        case en_vle: GenerateCmp(node, op_vsle, label, prediction); break;
1908
        case en_vgt: GenerateCmp(node, op_vsgt, label, prediction); break;
1909
        case en_vge: GenerateCmp(node, op_vsge, label, prediction); break;
1910
        case en_lor:
1911
                GenerateTrueJump(node->p[0],label,prediction);
1912
                GenerateTrueJump(node->p[1],label,prediction);
1913
                break;
1914
        default:
1915
                siz1 = GetNaturalSize(node);
1916
                ap1 = GenerateExpression(node,F_REG,siz1);
1917
                //                        GenerateDiadic(op_tst,siz1,ap1,0);
1918
                ReleaseTempRegister(ap1);
1919
                GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(label));
1920
                break;
1921
        }
1922
}
1923
 
1924
//
1925
// Generate code to execute a jump to label if the expression
1926
// passed is false.
1927
//
1928
void GenerateFalseJump(ENODE *node,int label, unsigned int prediction)
1929
{
1930
        Operand *ap;
1931
        int siz1;
1932
        int lab0;
1933
 
1934
        if( node == (ENODE *)NULL )
1935
                return;
1936
        switch( node->nodetype )
1937
        {
1938
        case en_bchk:   break;
1939
        case en_eq:     GenerateCmp(node, op_ne, label, prediction); break;
1940
        case en_ne: GenerateCmp(node, op_eq, label, prediction); break;
1941
        case en_lt: GenerateCmp(node, op_ge, label, prediction); break;
1942
        case en_le: GenerateCmp(node, op_gt, label, prediction); break;
1943
        case en_gt: GenerateCmp(node, op_le, label, prediction); break;
1944
        case en_ge: GenerateCmp(node, op_lt, label, prediction); break;
1945
        case en_ult: GenerateCmp(node, op_geu, label, prediction); break;
1946
        case en_ule: GenerateCmp(node, op_gtu, label, prediction); break;
1947
        case en_ugt: GenerateCmp(node, op_leu, label, prediction); break;
1948
        case en_uge: GenerateCmp(node, op_ltu, label, prediction); break;
1949
        case en_feq: GenerateCmp(node, op_fne, label, prediction); break;
1950
        case en_fne: GenerateCmp(node, op_feq, label, prediction); break;
1951
        case en_flt: GenerateCmp(node, op_fge, label, prediction); break;
1952
        case en_fle: GenerateCmp(node, op_fgt, label, prediction); break;
1953
        case en_fgt: GenerateCmp(node, op_fle, label, prediction); break;
1954
        case en_fge: GenerateCmp(node, op_flt, label, prediction); break;
1955
        case en_veq: GenerateCmp(node, op_vsne, label, prediction); break;
1956
        case en_vne: GenerateCmp(node, op_vseq, label, prediction); break;
1957
        case en_vlt: GenerateCmp(node, op_vsge, label, prediction); break;
1958
        case en_vle: GenerateCmp(node, op_vsgt, label, prediction); break;
1959
        case en_vgt: GenerateCmp(node, op_vsle, label, prediction); break;
1960
        case en_vge: GenerateCmp(node, op_vslt, label, prediction); break;
1961
        case en_land:
1962
                GenerateFalseJump(node->p[0],label,prediction^1);
1963
                GenerateFalseJump(node->p[1],label,prediction^1);
1964
                break;
1965
        case en_lor:
1966
                lab0 = nextlabel++;
1967
                GenerateTrueJump(node->p[0],lab0,prediction);
1968
                GenerateFalseJump(node->p[1],label,prediction^1);
1969
                GenerateLabel(lab0);
1970
                break;
1971
        case en_not:
1972
                GenerateTrueJump(node->p[0],label,prediction);
1973
                break;
1974
        default:
1975
                siz1 = GetNaturalSize(node);
1976
                ap = GenerateExpression(node,F_REG,siz1);
1977
                //                        GenerateDiadic(op_tst,siz1,ap,0);
1978
                ReleaseTempRegister(ap);
1979
                GenerateTriadic(op_beq,0,ap,makereg(0),make_label(label));
1980
                break;
1981
        }
1982
}

powered by: WebSVN 2.1.0

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