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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [CodeGenerator.cpp] - Rev 48

Compare with Previous | Blame | View Log

// ============================================================================
//        __
//   \\__/ o\    (C) 2012-2018  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
// CC64 - 'C' derived language compiler
//  - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
//                                                                          
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//                                                                          
// ============================================================================
//
#include "stdafx.h"
 
/*
 *      this module contains all of the code generation routines
 *      for evaluating expressions and conditions.
 */
 
int hook_predreg=15;
 
Operand *GenerateExpression();            /* forward ParseSpecifieraration */
 
extern Operand *copy_addr(Operand *);
extern Operand *GenExpr(ENODE *node);
extern Operand *GenerateFunctionCall(ENODE *node, int flags);
extern void GenLdi(Operand*,Operand *);
extern void GenerateCmp(ENODE *node, int op, int label, int predreg, unsigned int prediction);
 
void GenerateRaptor64Cmp(ENODE *node, int op, int label, int predreg);
void GenerateTable888Cmp(ENODE *node, int op, int label, int predreg);
void GenerateThorCmp(ENODE *node, int op, int label, int predreg);
void GenLoad(Operand *ap3, Operand *ap1, int ssize, int size);
void GenerateZeroExtend(Operand *ap, int isize, int osize);
void GenerateSignExtend(Operand *ap, int isize, int osize, int flags);
 
extern int throwlab;
static int nest_level = 0;
 
static void Enter(char *p)
{
/*
     int nn;
 
     for (nn = 0; nn < nest_level; nn++)
         printf(" ");
     printf("%s: %d ", p, lineno);
     nest_level++;
*/
}
static void Leave(char *p, int n)
{
/*
     int nn;
 
     nest_level--;
     for (nn = 0; nn < nest_level; nn++)
         printf(" ");
     printf("%s (%d) ", p, n);
*/
}
 
 
/*
 *      construct a reference node for an internal label number.
 */
Operand *make_label(int lab)
{
	ENODE *lnode;
	Operand *ap;
 
	lnode = allocEnode();
	lnode->nodetype = en_labcon;
	lnode->i = lab;
	ap = allocOperand();
	ap->mode = am_direct;
	ap->offset = lnode;
	ap->isUnsigned = TRUE;
	return ap;
}
 
Operand *make_clabel(int lab)
{
	ENODE *lnode;
    Operand *ap;
 
    lnode = allocEnode();
    lnode->nodetype = en_clabcon;
    lnode->i = lab;
	if (lab==-1)
		printf("-1\r\n");
    ap = allocOperand();
    ap->mode = am_direct;
    ap->offset = lnode;
	ap->isUnsigned = TRUE;
    return ap;
}
 
Operand *make_string(char *s)
{
	ENODE *lnode;
	Operand *ap;
 
	lnode = allocEnode();
	lnode->nodetype = en_nacon;
	lnode->sp = new std::string(s);
	ap = allocOperand();
	ap->mode = am_direct;
	ap->offset = lnode;
	return ap;
}
 
/*
 *      make a node to reference an immediate value i.
 */
Operand *make_immed(int64_t i)
{
	Operand *ap;
    ENODE *ep;
    ep = allocEnode();
    ep->nodetype = en_icon;
    ep->i = i;
    ap = allocOperand();
    ap->mode = am_imm;
    ap->offset = ep;
    return ap;
}
 
Operand *make_indirect(int i)
{
	Operand *ap;
    ENODE *ep;
    ep = allocEnode();
    ep->nodetype = en_uw_ref;
    ep->i = 0;
    ap = allocOperand();
	ap->mode = am_ind;
	ap->preg = i;
    ap->offset = 0;//ep;	//=0;
    return ap;
}
 
Operand *make_indexed(int64_t o, int i)
{
	Operand *ap;
    ENODE *ep;
    ep = allocEnode();
    ep->nodetype = en_icon;
    ep->i = o;
    ap = allocOperand();
	ap->mode = am_indx;
	ap->preg = i;
    ap->offset = ep;
    return ap;
}
 
/*
 *      make a direct reference to a node.
 */
Operand *make_offset(ENODE *node)
{
	Operand *ap;
	ap = allocOperand();
	ap->mode = am_direct;
	ap->offset = node;
	return ap;
}
 
Operand *make_indx(ENODE *node, int rg)
{
	Operand *ap;
    ap = allocOperand();
    ap->mode = am_indx;
    ap->offset = node;
    ap->preg = rg;
    return ap;
}
 
void GenerateHint(int num)
{
	GenerateMonadic(op_hint,0,make_immed(num));
}
 
void GenerateComment(char *cm)
{
	GenerateMonadic(op_rem2,0,make_string(cm));
}
 
 
void GenLoad(Operand *ap3, Operand *ap1, int ssize, int size)
{
	if (ap3->type==stdvector.GetIndex()) {
        GenerateDiadic(op_lv,0,ap3,ap1);
	}
	else if (ap3->type == stdflt.GetIndex()) {
		GenerateDiadic(op_lf, 'd', ap3, ap1);
	}
	else if (ap3->type==stddouble.GetIndex()) {
		GenerateDiadic(op_lf,'d',ap3,ap1);
	}
	else if (ap3->type == stdquad.GetIndex()) {
		GenerateDiadic(op_lf, 'q', ap3, ap1);
	}
	else if (ap3->type == stdtriple.GetIndex()) {
		GenerateDiadic(op_lf, 't', ap3, ap1);
	}
	else if (ap3->isUnsigned) {
		if (ap3->isVolatile) {
			switch (size) {
			case 1:	GenerateDiadic(op_lvbu, 0, ap3, ap1); break;
			case 2:	GenerateDiadic(op_lvcu, 0, ap3, ap1); break;
			case 4:	GenerateDiadic(op_lvhu, 0, ap3, ap1); break;
			case 8: GenerateDiadic(op_lvw, 0, ap3, ap1); break;
			}
		}
		else {
			switch (size) {
			case 1:	GenerateDiadic(op_lbu, 0, ap3, ap1); break;
			case 2:	GenerateDiadic(op_lcu, 0, ap3, ap1); break;
			case 4:	GenerateDiadic(op_lhu, 0, ap3, ap1); break;
			case 8: GenerateDiadic(op_lw, 0, ap3, ap1); break;
			}
		}
    }
    else {
		if (ap3->isVolatile) {
			switch (size) {
			case 1:	GenerateDiadic(op_lvb, 0, ap3, ap1); break;
			case 2:	GenerateDiadic(op_lvc, 0, ap3, ap1); break;
			case 4:	GenerateDiadic(op_lvh, 0, ap3, ap1); break;
			case 8:	GenerateDiadic(op_lvw, 0, ap3, ap1); break;
			}
		}
		else {
			switch (size) {
			case 1:	GenerateDiadic(op_lb, 0, ap3, ap1); break;
			case 2:	GenerateDiadic(op_lc, 0, ap3, ap1); break;
			case 4:	GenerateDiadic(op_lh, 0, ap3, ap1); break;
			case 8:	GenerateDiadic(op_lw, 0, ap3, ap1); break;
			}
		}
    }
}
 
void GenStore(Operand *ap1, Operand *ap3, int size)
{
	if (ap1->isPtr) {
		GenerateDiadic(op_sw, 0, ap1, ap3);
	}
	else if (ap1->type==stdvector.GetIndex())
	    GenerateDiadic(op_sv,0,ap1,ap3);
	else if (ap1->type == stdflt.GetIndex()) {
		GenerateDiadic(op_sf, 'd', ap1, ap3);
	}
	else if (ap1->type == stddouble.GetIndex()) {
		GenerateDiadic(op_sf, 'd', ap1, ap3);
	}
	else if (ap1->type == stdquad.GetIndex()) {
		GenerateDiadic(op_sf, 'q', ap1, ap3);
	}
	else if (ap1->type == stdtriple.GetIndex()) {
		GenerateDiadic(op_sf, 't', ap1, ap3);
	}
	else if (ap1->mode==am_fpreg)
		GenerateDiadic(op_sf,'d',ap1,ap3);
	else {
		switch (size) {
		case 1: GenerateDiadic(op_sb, 0, ap1, ap3); break;
		case 2: GenerateDiadic(op_sc, 0, ap1, ap3); break;
		case 4: GenerateDiadic(op_sh, 0, ap1, ap3); break;
		case 8: GenerateDiadic(op_sw, 0, ap1, ap3); break;
		default:;
		}
	}
}
 
//
//  Return the addressing mode of a dereferenced node.
//
Operand *GenerateDereference(ENODE *node,int flags,int size, int su)
{    
	Operand *ap1;
    int siz1;
 
    Enter("Genderef");
	siz1 = node->GetReferenceSize();
	// When dereferencing a struct or union return a pointer to the struct or
	// union.
//	if (node->tp->type==bt_struct || node->tp->type==bt_union) {
//        return GenerateExpression(node,F_REG|F_MEM,size);
//    }
    if( node->p[0]->nodetype == en_add )
    {
//        ap2 = GetTempRegister();
        ap1 = node->p[0]->GenIndex();
//        GenerateTriadic(op_add,0,ap2,makereg(ap1->preg),makereg(regGP));
		ap1->isUnsigned = !su;//node->isUnsigned;
		// *** may have to fix for stackseg
		ap1->segment = dataseg;
//		ap2->mode = ap1->mode;
//		ap2->segment = dataseg;
//		ap2->offset = ap1->offset;
//		ReleaseTempRegister(ap1);
		if (!node->isUnsigned)
			ap1->GenSignExtend(siz1,size,flags);
		else
		    ap1->MakeLegal(flags,siz1);
        ap1->MakeLegal(flags,size);
		goto xit;
    }
    else if( node->p[0]->nodetype == en_autocon )
    {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
        ap1->preg = regFP;
		ap1->segment = stackseg;
        ap1->offset = makeinode(en_icon,node->p[0]->i);
		ap1->offset->sym = node->p[0]->sym;
		ap1->isUnsigned = !su;
		if (!node->isUnsigned)
	        ap1->GenSignExtend(siz1,size,flags);
		else
		    ap1->MakeLegal(flags,siz1);
        ap1->MakeLegal(flags,size);
		goto xit;
    }
    else if( node->p[0]->nodetype == en_classcon )
    {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
        ap1->preg = regCLP;
		ap1->segment = dataseg;
        ap1->offset = makeinode(en_icon,node->p[0]->i);
		ap1->offset->sym = node->p[0]->sym;
		ap1->isUnsigned = !su;
		if (!node->isUnsigned)
	        ap1->GenSignExtend(siz1,size,flags);
		else
		    ap1->MakeLegal(flags,siz1);
        ap1->MakeLegal(flags,size);
		goto xit;
    }
    else if( node->p[0]->nodetype == en_autofcon )
    {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
        ap1->preg = regFP;
        ap1->offset = makeinode(en_icon,node->p[0]->i);
		ap1->offset->sym = node->p[0]->sym;
		if (node->p[0]->tp)
			switch(node->p[0]->tp->precision) {
			case 32: ap1->FloatSize = 's'; break;
			case 64: ap1->FloatSize = 'd'; break;
			default: ap1->FloatSize = 'd'; break;
			}
		else
			ap1->FloatSize = 'd';
		ap1->segment = stackseg;
		switch (node->p[0]->tp->type) {
		case bt_float:	ap1->type = stdflt.GetIndex(); break;
		case bt_double:	ap1->type = stddouble.GetIndex(); break;
		case bt_triple:	ap1->type = stdtriple.GetIndex(); break;
		case bt_quad:	ap1->type = stdquad.GetIndex(); break;
		}
//	    ap1->MakeLegal(flags,siz1);
        ap1->MakeLegal(flags,size);
		goto xit;
    }
    else if( node->p[0]->nodetype == en_autovcon )
    {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
        ap1->preg = regFP;
        ap1->offset = makeinode(en_icon,node->p[0]->i);
		ap1->offset->sym = node->p[0]->sym;
		if (node->p[0]->tp)
			switch(node->p[0]->tp->precision) {
			case 32: ap1->FloatSize = 's'; break;
			case 64: ap1->FloatSize = 'd'; break;
			default: ap1->FloatSize = 'd'; break;
			}
		else
			ap1->FloatSize = 'd';
		ap1->segment = stackseg;
		ap1->type = stdvector.GetIndex();
		//	    ap1->MakeLegal(flags,siz1);
        ap1->MakeLegal(flags,size);
		goto xit;
    }
    else if( node->p[0]->nodetype == en_autovmcon )
    {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
        ap1->preg = regFP;
        ap1->offset = makeinode(en_icon,node->p[0]->i);
		ap1->offset->sym = node->p[0]->sym;
		if (node->p[0]->tp)
			switch(node->p[0]->tp->precision) {
			case 32: ap1->FloatSize = 's'; break;
			case 64: ap1->FloatSize = 'd'; break;
			default: ap1->FloatSize = 'd'; break;
			}
		else
			ap1->FloatSize = 'd';
		ap1->segment = stackseg;
		ap1->type = stdvectormask->GetIndex();
		//	    ap1->MakeLegal(flags,siz1);
        ap1->MakeLegal(flags,size);
		goto xit;
    }
	else if ((node->p[0]->nodetype == en_labcon) && use_gp)
	{
		ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
		switch (node->p[0]->segment) {
		case dataseg:	ap1->preg = regGP; break;
		case tlsseg:	ap1->preg = regTP; break;
		default:	ap1->preg = regPP; break;
		}
		ap1->segment = node->p[0]->segment;
		ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
		ap1->isUnsigned = !su;
		if (!node->isUnsigned)
			ap1->GenSignExtend(siz1, size, flags);
		else
			ap1->MakeLegal( flags, siz1);
		ap1->isVolatile = node->isVolatile;
		ap1->MakeLegal( flags, size);
		goto xit;
	}
	else if(( node->p[0]->nodetype==en_nacon ) && use_gp)
    {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_indx;
        ap1->preg = regGP;
		ap1->segment = dataseg;
        ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
		ap1->isUnsigned = !su;
		if (!node->isUnsigned)
	        ap1->GenSignExtend(siz1,size,flags);
		else
		    ap1->MakeLegal(flags,siz1);
        ap1->isVolatile = node->isVolatile;
		switch (node->p[0]->tp->type) {
		case bt_float:	ap1->type = stdflt.GetIndex(); break;
		case bt_double:	ap1->type = stddouble.GetIndex(); break;
		case bt_triple:	ap1->type = stdtriple.GetIndex(); break;
		case bt_quad:	ap1->type = stdquad.GetIndex(); break;
		}
		ap1->MakeLegal(flags,size);
		goto xit;
    }
	else if ((node->p[0]->nodetype == en_labcon) && !use_gp)
	{
		ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_direct;
		ap1->preg = 0;
		ap1->segment = node->p[0]->segment;
		ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
		ap1->isUnsigned = !su;
		if (!node->isUnsigned)
			ap1->GenSignExtend(siz1, size, flags);
		else
			ap1->MakeLegal( flags, siz1);
		ap1->isVolatile = node->isVolatile;
		ap1->MakeLegal( flags, size);
		goto xit;
	}
	else if ((node->p[0]->nodetype == en_nacon) && !use_gp)
	{
		ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = am_direct;
		ap1->preg = 0;
		ap1->segment = dataseg;
		ap1->offset = node->p[0];//makeinode(en_icon,node->p[0]->i);
		ap1->isUnsigned = !su;
		if (!node->isUnsigned)
			ap1->GenSignExtend(siz1, size, flags);
		else
			ap1->MakeLegal( flags, siz1);
		ap1->isVolatile = node->isVolatile;
		switch (node->p[0]->tp->type) {
		case bt_float:	ap1->type = stdflt.GetIndex(); break;
		case bt_double:	ap1->type = stddouble.GetIndex(); break;
		case bt_triple:	ap1->type = stdtriple.GetIndex(); break;
		case bt_quad:	ap1->type = stdquad.GetIndex(); break;
		}
		ap1->MakeLegal( flags, size);
		goto xit;
	}
	else if (node->p[0]->nodetype == en_regvar) {
        ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		// For parameters we want Rn, for others [Rn]
		// This seems like an error earlier in the compiler
		// See setting val_flag in ParseExpressions
		ap1->mode = node->p[0]->i < 18 ? am_ind : am_reg;
//		ap1->mode = node->p[0]->tp->val_flag ? am_reg : am_ind;
		ap1->preg = node->p[0]->i;
		ap1->MakeLegal(flags,size);
	    Leave("Genderef",3);
        return ap1;
	}
	else if (node->p[0]->nodetype == en_fpregvar) {
		/*error(ERR_DEREF)*/;
		ap1 = allocOperand();
		ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
		ap1->mode = node->p[0]->i < 18 ? am_ind : am_fpreg;
		ap1->preg = node->p[0]->i;
		switch (node->p[0]->tp->type) {
		case bt_float:	ap1->type = stdflt.GetIndex(); break;
		case bt_double:	ap1->type = stddouble.GetIndex(); break;
		case bt_triple:	ap1->type = stdtriple.GetIndex(); break;
		case bt_quad:	ap1->type = stdquad.GetIndex(); break;
		}
        ap1->MakeLegal(flags,size);
	    Leave("Genderef",3);
        return (ap1);
	}
	else if (node->p[0]->nodetype == en_vex) {
		Operand *ap2;
		if (node->p[0]->p[0]->nodetype==en_vector_ref) {
			ap1 = GenerateDereference(node->p[0]->p[0],F_REG,8,0);
			ap2 = GenerateExpression(node->p[0]->p[1],F_REG,8);
			if (ap1->offset && ap2->offset) {
				GenerateTriadic(op_add,0,ap1,makereg(0),make_immed(ap2->offset->i));
			}
			ReleaseTempReg(ap2);
			//ap1->mode = node->p[0]->i < 18 ? am_ind : am_reg;
			//ap1->preg = node->p[0]->i;
			ap1->type = stdvector.GetIndex();
			ap1->MakeLegal(flags,size);
			return (ap1);
		}
	}
    ap1 = GenerateExpression(node->p[0],F_REG | F_IMMED,8); /* generate address */
	ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
	if( ap1->mode == am_reg)
    {
//        ap1->mode = am_ind;
          if (use_gp) {
              ap1->mode = am_indx;
              ap1->sreg = regGP;
          }
          else
             ap1->mode = am_ind;
		  if (node->p[0]->constflag==TRUE)
			  ap1->offset = node->p[0];
		  else
			ap1->offset = nullptr;	// ****
		  ap1->isUnsigned = !su | ap1->isPtr;
		if (!node->isUnsigned)
	        ap1->GenSignExtend(siz1,size,flags);
		else
		    ap1->MakeLegal(flags,siz1);
        ap1->isVolatile = node->isVolatile;
        ap1->MakeLegal(flags,size);
		goto xit;
    }
	// Note sure about this, but immediate were being incorrectly
	// dereferenced as direct addresses because it would fall through
	// to the following dead code.
 
	if (ap1->mode == am_imm) {
		ap1->MakeLegal( flags, size);
		goto xit;
	}
 
	// *********************************************************************
	// I think what follows is dead code.
	// am_reg and am_imm the only codes that should be generated are
	// checked for above.
	// *********************************************************************
 
	// See segments notes
	//if (node->p[0]->nodetype == en_labcon &&
	//	node->p[0]->etype == bt_pointer && node->p[0]->constflag)
	//	ap1->segment = codeseg;
	//else
	//	ap1->segment = dataseg;
	ap1->isPtr = node->nodetype == en_wp_ref || node->nodetype == en_hp_ref;
	if (use_gp) {
        ap1->mode = am_indx;
        ap1->preg = regGP;
    	ap1->segment = dataseg;
    }
    else {
        ap1->mode = am_direct;
	    ap1->isUnsigned = !su | ap1->isPtr;
    }
//    ap1->offset = makeinode(en_icon,node->p[0]->i);
    ap1->isUnsigned = !su | ap1->isPtr;
	if (!node->isUnsigned)
	    ap1->GenSignExtend(siz1,size,flags);
	else
		ap1->MakeLegal(flags,siz1);
    ap1->isVolatile = node->isVolatile;
    ap1->MakeLegal(flags,size);
xit:
    Leave("Genderef",0);
    return (ap1);
}
 
/*
 *      generate code to evaluate a multiply node. 
 */
Operand *GenerateMultiply(ENODE *node, int flags, int size, int op)
{       
	Operand *ap1, *ap2, *ap3;
  Enter("Genmul");
    if( node->p[0]->nodetype == en_icon )
        swap_nodes(node);
    if (op==op_fmul) {
        ap3 = GetTempFPRegister();
        ap1 = GenerateExpression(node->p[0],F_FPREG,size);
        ap2 = GenerateExpression(node->p[1],F_FPREG,size);
    }
    else {
        ap3 = GetTempRegister();
        ap1 = GenerateExpression(node->p[0],F_REG,8);
        ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8);
    }
	if (op==op_fmul) {
		// Generate a convert operation ?
		if (ap1->fpsize() != ap2->fpsize()) {
			if (ap2->fpsize()=='s')
				GenerateDiadic(op_fcvtsq, 0, ap2, ap2);
		}
	    GenerateTriadic(op,ap1->fpsize(),ap3,ap1,ap2);
	}
	else
		GenerateTriadic(op,0,ap3,ap1,ap2);
	ReleaseTempReg(ap2);
	ReleaseTempReg(ap1);
	ap3->MakeLegal(flags,2);
	Leave("Genmul",0);
	return ap3;
}
 
void GenMemop(int op, Operand *ap1, Operand *ap2, int ssize)
{
	Operand *ap3;
 
	if (ap1->type==stddouble.GetIndex()) {
     	ap3 = GetTempFPRegister();
		GenLoad(ap3,ap1,ssize,ssize);
		GenerateTriadic(op,ap1->FloatSize,ap3,ap3,ap2);
		GenStore(ap3,ap1,ssize);
		ReleaseTempReg(ap3);
		return;
	}
	else if (ap1->type==stdvector.GetIndex()) {
   		ap3 = GetTempVectorRegister();
		GenLoad(ap3,ap1,ssize,ssize);
		GenerateTriadic(op,0,ap3,ap3,ap2);
		GenStore(ap3,ap1,ssize);
		ReleaseTempReg(ap3);
		return;
	}
	//if (ap1->mode != am_indx2)
	{
		if (op==op_add && ap2->mode==am_imm && ap2->offset->i >= -16 && ap2->offset->i < 16 && ssize==8) {
			GenerateDiadic(op_inc,0,ap1,ap2);
			return;
		}
		if (op==op_sub && ap2->mode==am_imm && ap2->offset->i >= -15 && ap2->offset->i < 15 && ssize==8) {
			GenerateDiadic(op_dec,0,ap1,ap2);
			return;
		}
	}
   	ap3 = GetTempRegister();
	ap3->isPtr = ap1->isPtr;
    GenLoad(ap3,ap1,ssize,ssize);
	GenerateTriadic(op,0,ap3,ap3,ap2);
	GenStore(ap3,ap1,ssize);
	ReleaseTempReg(ap3);
}
 
//
//      generate a *= node.
//
Operand *GenerateAssignMultiply(ENODE *node,int flags, int size, int op)
{
	Operand *ap1, *ap2, *ap3;
    int             ssize;
    ssize = GetNaturalSize(node->p[0]);
    if( ssize > size )
            size = ssize;
	if (node->p[0]->IsBitfield()) {
		ap3 = GetTempRegister();
		ap1 = GenerateBitfieldDereference(node->p[0], F_REG | F_MEM, size);
		GenerateDiadic(op_mov, 0, ap3, ap1);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op, 0, ap1, ap1, ap2);
		GenerateBitfieldInsert(ap3, ap1, ap1->offset->bit_offset, ap1->offset->bit_width);
		GenStore(ap3, ap1->next, ssize);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1->next);
		ReleaseTempReg(ap1);
		ap3->MakeLegal( flags, size);
		return (ap3);
	}
	if (node->etype==bt_double || node->etype==bt_quad || node->etype==bt_float || node->etype==bt_triple) {
        ap1 = GenerateExpression(node->p[0],F_FPREG | F_MEM,ssize);
        ap2 = GenerateExpression(node->p[1],F_FPREG,size);
        op = op_fmul;
    }
    else if (node->etype==bt_vector) {
        ap1 = GenerateExpression(node->p[0],F_REG | F_MEM,ssize);
        ap2 = GenerateExpression(node->p[1],F_REG,size);
		op = ap2->type==stdvector.GetIndex() ? op_vmul : op_vmuls;
    }
    else {
        ap1 = GenerateExpression(node->p[0],F_ALL & ~F_IMMED,ssize);
        ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
    }
	if (ap1->mode==am_reg) {
	    GenerateTriadic(op,0,ap1,ap1,ap2);
	}
	else if (ap1->mode==am_fpreg) {
	    GenerateTriadic(op,ssize==4?'s':ssize==8?'d':ssize==12?'t':ssize==16 ? 'q' : 'd',ap1,ap1,ap2);
	    ReleaseTempReg(ap2);
	    ap1->MakeLegal(flags,size);
		return (ap1);
	}
	else {
		GenMemop(op, ap1, ap2, ssize);
	}
    ReleaseTempReg(ap2);
    ap1->GenSignExtend(ssize,size,flags);
    ap1->MakeLegal(flags,size);
    return (ap1);
}
 
/*
 *      generate /= and %= nodes.
 */
Operand *GenerateAssignModiv(ENODE *node,int flags,int size,int op)
{
	Operand *ap1, *ap2, *ap3;
    int             siz1;
    int isFP;
 
    siz1 = GetNaturalSize(node->p[0]);
	if (node->p[0]->IsBitfield()) {
		ap3 = GetTempRegister();
		ap1 = GenerateBitfieldDereference(node->p[0], F_REG | F_MEM, size);
		GenerateDiadic(op_mov, 0, ap3, ap1);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op, 0, ap1, ap1, ap2);
		GenerateBitfieldInsert(ap3, ap1, ap1->offset->bit_offset, ap1->offset->bit_width);
		GenStore(ap3, ap1->next, siz1);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1->next);
		ReleaseTempReg(ap1);
		ap3->MakeLegal( flags, size);
		return (ap3);
	}
	isFP = node->etype==bt_double || node->etype==bt_float || node->etype==bt_triple || node->etype==bt_quad;
    if (isFP) {
        if (op==op_div || op==op_divu)
           op = op_fdiv;
        ap1 = GenerateExpression(node->p[0],F_FPREG,siz1);
        ap2 = GenerateExpression(node->p[1],F_FPREG,size);
		GenerateTriadic(op,siz1==4?'s':siz1==8?'d':siz1==12?'t':siz1==16?'q':'d',ap1,ap1,ap2);
	    ReleaseTempReg(ap2);
		ap1->MakeLegal(flags,size);
	    return (ap1);
//        else if (op==op_mod || op==op_modu)
//           op = op_fdmod;
    }
    else {
        ap1 = GetTempRegister();
        ap2 = GenerateExpression(node->p[0],F_ALL & ~F_IMMED,siz1);
    }
	if (ap2->mode==am_reg && ap2->preg != ap1->preg)
		GenerateDiadic(op_mov,0,ap1,ap2);
	else if (ap2->mode==am_fpreg && ap2->preg != ap1->preg)
		GenerateDiadic(op_mov,0,ap1,ap2);
	else
        GenLoad(ap1,ap2,siz1,siz1);
    //GenerateSignExtend(ap1,siz1,2,flags);
    if (isFP)
        ap3 = GenerateExpression(node->p[1],F_FPREG,8);
    else
        ap3 = GenerateExpression(node->p[1],F_REG|F_IMMED,8);
	if (op==op_fdiv) {
		GenerateTriadic(op,siz1==4?'s':siz1==8?'d':siz1==12?'t':siz1==16?'q':'d',ap1,ap1,ap3);
	}
	else
		GenerateTriadic(op,0,ap1,ap1,ap3);
    ReleaseTempReg(ap3);
    //GenerateDiadic(op_ext,0,ap1,0);
	if (ap2->mode==am_reg)
		GenerateDiadic(op_mov,0,ap2,ap1);
	else if (ap2->mode==am_fpreg)
		GenerateDiadic(op_mov,0,ap2,ap1);
	else
	    GenStore(ap1,ap2,siz1);
    ReleaseTempReg(ap2);
	if (!isFP)
		ap1->MakeLegal(flags,size);
    return (ap1);
}
 
// This little bit of code a debugging aid.
// Dumps the expression nodes associated with an aggregate assignment.
 
void DumpStructEnodes(ENODE *node)
{
	ENODE *head;
	TYP *tp;
 
	lfs.printf("{");
	head = node;
	while (head) {
		tp = head->tp;
		if (tp)
			tp->put_ty();
		if (head->nodetype==en_aggregate) {
			DumpStructEnodes(head->p[0]);
		}
		if (head->nodetype==en_icon)
			lfs.printf("%d", head->i);
		head = head->p[2];
	}
	lfs.printf("}");
}
 
Operand *GenerateAssign(ENODE *node, int flags, int size);
 
// Generate an assignment to a structure type. The type passed must be a
// structure type.
 
void GenerateStructAssign(TYP *tp, int64_t offset, ENODE *ep, Operand *base)
{
	SYM *thead, *first;
	Operand *ap1, *ap2;
	int64_t offset2;
 
	first = thead = SYM::GetPtr(tp->lst.GetHead());
	ep = ep->p[0];
	while (thead) {
		if (ep == nullptr)
			break;
		if (thead->tp->IsAggregateType()) {
			if (ep->p[2])
				GenerateStructAssign(thead->tp, offset, ep->p[2], base);
		}
		else {
			ap2 = nullptr;
			if (ep->p[2]==nullptr)
				break;
			ap1 = GenerateExpression(ep->p[2],F_REG,thead->tp->size);
			if (ap1->mode==am_imm) {
				ap2 = GetTempRegister();
				GenLdi(ap2,ap1);
			}
			else {
				ap2 = ap1;
				ap1 = nullptr;
			}
			if (base->offset)
				offset2 = base->offset->i + offset;
			else
				offset2 = offset;
			switch(thead->tp->size)
			{
			case 1:	GenerateDiadic(op_sb,0,ap2,make_indexed(offset,base->preg)); break;
			case 2:	GenerateDiadic(op_sc,0,ap2,make_indexed(offset,base->preg)); break;
			case 4:	GenerateDiadic(op_sh,0,ap2,make_indexed(offset,base->preg)); break;
			case 512:	GenerateDiadic(op_sv,0,ap2,make_indexed(offset,base->preg)); break;
			default:	GenerateDiadic(op_sw,0,ap2,make_indexed(offset,base->preg)); break;
			}
			if (ap2)
				ReleaseTempReg(ap2);
			if (ap1)
				ReleaseTempReg(ap1);
		}
		if (!thead->tp->IsUnion())
			offset += thead->tp->size;
		thead = SYM::GetPtr(thead->next);
		ep = ep->p[2];
	}
	if (!thead && ep)
		error(ERR_TOOMANYELEMENTS);
}
 
 
Operand *GenerateAggregateAssign(ENODE *node1, ENODE *node2);
 
// Generate an assignment to an array.
 
void GenerateArrayAssign(TYP *tp, ENODE *node1, ENODE *node2, Operand *base)
{
	ENODE *ep1;
	Operand *ap1, *ap2;
	int size = tp->size;
	int64_t offset, offset2;
 
	offset = 0;
	if (node1->tp)
		tp = node1->tp->GetBtp();
	else
		tp = nullptr;
	if (tp==nullptr)
		tp = &stdlong;
	if (tp->IsStructType()) {
		ep1 = nullptr;
		ep1 = node2->p[0];
		while (ep1 && offset < size) {
			GenerateStructAssign(tp, offset, ep1->p[2], base);
			if (!tp->IsUnion())
				offset += tp->size;
			ep1 = ep1->p[2];
		}
	}
	else if (tp->IsAggregateType()){
		GenerateAggregateAssign(node1->p[0],node2->p[0]);
	}
	else {
		ep1 = node2->p[0];
		offset = 0;
		if (base->offset)
			offset = base->offset->i;
		ep1 = ep1->p[2];
		while (ep1) {
			ap1 = GenerateExpression(ep1,F_REG|F_IMMED,sizeOfWord);
			ap2 = GetTempRegister();
			if (ap1->mode==am_imm)
				GenLdi(ap2,ap1);
			else {
				if (ap1->offset)
					offset2 = ap1->offset->i;
				else
					offset2 = 0;
				GenerateDiadic(op_mov,0,ap2,ap1);
			}
			switch(tp->GetElementSize())
			{
			case 1:	GenerateDiadic(op_sb,0,ap2,make_indexed(offset,base->preg)); break;
			case 2:	GenerateDiadic(op_sc,0,ap2,make_indexed(offset,base->preg)); break;
			case 4:	GenerateDiadic(op_sh,0,ap2,make_indexed(offset,base->preg)); break;
			case 512:	GenerateDiadic(op_sv,0,ap2,make_indexed(offset,base->preg)); break;
			default:	GenerateDiadic(op_sw,0,ap2,make_indexed(offset,base->preg)); break;
			}
			offset += tp->GetElementSize();
			ReleaseTempReg(ap2);
			ReleaseTempReg(ap1);
			ep1 = ep1->p[2];
		}
	}
}
 
Operand *GenerateAggregateAssign(ENODE *node1, ENODE *node2)
{
	Operand *base;
	TYP *tp;
	int64_t offset = 0;
 
	if (node1==nullptr || node2==nullptr)
		return nullptr;
	//DumpStructEnodes(node2);
	base = GenerateExpression(node1,F_MEM,sizeOfWord);
	//base = GenerateDereference(node1,F_MEM,sizeOfWord,0);
	tp = node1->tp;
	if (tp==nullptr)
		tp = &stdlong;
	if (tp->IsStructType()) {
		if (base->offset)
			offset = base->offset->i;
		else
			offset = 0;
		GenerateStructAssign(tp,offset,node2->p[0],base);
		//GenerateStructAssign(tp,offset2,node2->p[0]->p[0],base);
	}
	// Process Array
	else {
		GenerateArrayAssign(tp, node1, node2, base);
	}
	return base;
}
 
 
// ----------------------------------------------------------------------------
// Generate code for an assignment node. If the size of the assignment
// destination is larger than the size passed then everything below this node
// will be evaluated with the assignment size.
// ----------------------------------------------------------------------------
Operand *GenerateAssign(ENODE *node, int flags, int size)
{
	Operand *ap1, *ap2 ,*ap3;
	TYP *tp;
    int ssize;
 
    Enter("GenAssign");
 
    if (node->p[0]->IsBitfield()) {
      Leave("GenAssign",0);
		return GenerateBitfieldAssign(node, flags, size);
    }
 
	ssize = node->p[0]->GetReferenceSize();
//	if( ssize > size )
//			size = ssize;
/*
    if (node->tp->type==bt_struct || node->tp->type==bt_union) {
		ap1 = GenerateExpression(node->p[0],F_REG,ssize);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateMonadic(op_push,0,make_immed(node->tp->size));
		GenerateMonadic(op_push,0,ap2);
		GenerateMonadic(op_push,0,ap1);
		GenerateMonadic(op_bsr,0,make_string("memcpy_"));
		GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(24));
		ReleaseTempReg(ap2);
		return ap1;
    }
*/
	tp = node->p[0]->tp;
	if (tp) {
		if (node->p[0]->tp->IsAggregateType() || node->p[1]->nodetype==en_list || node->p[1]->nodetype==en_aggregate)
			return GenerateAggregateAssign(node->p[0],node->p[1]);
	}
	//if (size > 8) {
	//	ap1 = GenerateExpression(node->p[0],F_MEM,ssize);
	//	ap2 = GenerateExpression(node->p[1],F_MEM,size);
	//}
	//else {
		ap1 = GenerateExpression(node->p[0], F_REG | F_FPREG | F_MEM | F_VREG | F_VMREG, ssize);
		ap2 = GenerateExpression(node->p[1],F_ALL,size);
		if (node->p[0]->isUnsigned && !node->p[1]->isUnsigned)
		    ap2->GenZeroExtend(size,ssize);
//	}
	if (ap1->mode == am_reg || ap1->mode==am_fpreg) {
		switch(ap2->mode) {
		case am_reg:
			GenerateHint(2);
			if (ap2->isPtr) {
				GenerateZeradic(op_setwb);
				ap1->isPtr = TRUE;
			}
			GenerateDiadic(op_mov, 0, ap1, ap2);
			break;
		case am_fpreg:
			GenerateHint(2);
			if (ap1->mode==am_fpreg)
				GenerateDiadic(op_mov,0,ap1,ap2);
			else
				GenerateDiadic(op_mov,0,ap1,ap2);
			break;
		case am_imm:
			if (ap2->isPtr)
				GenerateZeradic(op_setwb);
			GenerateDiadic(op_ldi,0,ap1,ap2);
			ap1->isPtr = ap2->isPtr;
			break;
		default:
			GenLoad(ap1,ap2,ssize,size);
			ap1->isPtr = ap2->isPtr;
			break;
		}
	}
	else if (ap1->mode == am_vreg) {
		if (ap2->mode==am_vreg) {
			GenerateDiadic(op_mov,0,ap1,ap2);
		}
		else
			GenLoad(ap1,ap2,ssize,size);
	}
	// ap1 is memory
	else {
		if (ap2->mode == am_reg || ap2->mode == am_fpreg) {
		    GenStore(ap2,ap1,ssize);
        }
		else if (ap2->mode == am_imm) {
            if (ap2->offset->i == 0 && ap2->offset->nodetype != en_labcon) {
                GenStore(makereg(0),ap1,ssize);
            }
            else {
    			ap3 = GetTempRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				GenStore(ap3,ap1,ssize);
		    	ReleaseTempReg(ap3);
          }
		}
		else {
			if (ap1->type==stddouble.GetIndex() || ap1->type==stdflt.GetIndex()
				|| ap1->type==stdtriple.GetIndex() || ap1->type==stdquad.GetIndex())
				ap3 = GetTempFPRegister();
			else
				ap3 = GetTempRegister();
			// Generate a memory to memory move (struct assignments)
			if (ssize > 8) {
				if (ap1->type==stdvector.GetIndex() && ap2->type==stdvector.GetIndex()) {
					if (ap2->mode==am_reg)
						GenStore(ap2,ap1,ssize);
					else {
						ap3 = GetTempVectorRegister();
						GenLoad(ap3,ap2,ssize,ssize);
						GenStore(ap3,ap1,ssize);
						ReleaseTempRegister(ap3);
					}
				}
				else {
					if (!cpu.SupportsPush) {
						GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(3 * sizeOfWord));
						ap3 = GetTempRegister();
						GenerateDiadic(op_ldi,0,ap3,make_immed(size));
						GenerateDiadic(op_sw,0,ap3,make_indexed(2 * sizeOfWord,regSP));
						GenerateDiadic(op_mov,0,ap3,ap2);
						GenerateDiadic(op_sw,0,ap3,make_indexed(1 * sizeOfWord,regSP));
						GenerateDiadic(op_mov,0,ap3,ap1);
						GenerateDiadic(op_sw,0,ap3,make_indirect(regSP));
					}
					else {
						GenerateMonadic(op_push,0,make_immed(size));
						GenerateMonadic(op_push,0,ap2);
						GenerateMonadic(op_push,0,ap1);
					}
					GenerateDiadic(op_jal,0,makereg(regLR),make_string("memcpy_"));
					GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(3*sizeOfWord));
				}
			}
			else {
				ap3->isPtr = ap2->isPtr;
                GenLoad(ap3,ap2,ssize,size);
/*                
				if (ap1->isUnsigned) {
					switch(size) {
					case 1:	GenerateDiadic(op_lbu,0,ap3,ap2); break;
					case 2:	GenerateDiadic(op_lcu,0,ap3,ap2); break;
					case 4: GenerateDiadic(op_lhu,0,ap3,ap2); break;
					case 8:	GenerateDiadic(op_lw,0,ap3,ap2); break;
					}
				}
				else {
					switch(size) {
					case 1:	GenerateDiadic(op_lb,0,ap3,ap2); break;
					case 2:	GenerateDiadic(op_lc,0,ap3,ap2); break;
					case 4: GenerateDiadic(op_lh,0,ap3,ap2); break;
					case 8:	GenerateDiadic(op_lw,0,ap3,ap2); break;
					}
					if (ssize > size) {
						switch(size) {
						case 1:	GenerateDiadic(op_sxb,0,ap3,ap3); break;
						case 2:	GenerateDiadic(op_sxc,0,ap3,ap3); break;
						case 4: GenerateDiadic(op_sxh,0,ap3,ap3); break;
						}
					}
				}
*/
				GenStore(ap3,ap1,ssize);
				ReleaseTempRegister(ap3);
			}
		}
	}
/*
	if (ap1->mode == am_reg) {
		if (ap2->mode==am_imm)	// must be zero
			GenerateDiadic(op_mov,0,ap1,makereg(0));
		else
			GenerateDiadic(op_mov,0,ap1,ap2);
	}
	else {
		if (ap2->mode==am_imm)
		switch(size) {
		case 1:	GenerateDiadic(op_sb,0,makereg(0),ap1); break;
		case 2:	GenerateDiadic(op_sc,0,makereg(0),ap1); break;
		case 4: GenerateDiadic(op_sh,0,makereg(0),ap1); break;
		case 8:	GenerateDiadic(op_sw,0,makereg(0),ap1); break;
		}
		else
		switch(size) {
		case 1:	GenerateDiadic(op_sb,0,ap2,ap1); break;
		case 2:	GenerateDiadic(op_sc,0,ap2,ap1); break;
		case 4: GenerateDiadic(op_sh,0,ap2,ap1); break;
		case 8:	GenerateDiadic(op_sw,0,ap2,ap1); break;
		// Do structure assignment
		default: {
			ap3 = GetTempRegister();
			GenerateDiadic(op_ldi,0,ap3,make_immed(size));
			GenerateTriadic(op_push,0,ap3,ap2,ap1);
			GenerateDiadic(op_jal,0,makereg(LR),make_string("memcpy"));
			GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(24));
			ReleaseTempRegister(ap3);
		}
		}
	}
*/
	ReleaseTempReg(ap2);
    ap1->MakeLegal(flags,size);
    Leave("GenAssign",1);
	return ap1;
}
 
// autocon and autofcon nodes
 
Operand *GenAutocon(ENODE *node, int flags, int size, int type)
{
	Operand *ap1, *ap2;
 
	if (type==stddouble.GetIndex() || type==stdflt.GetIndex() || type==stdtriple.GetIndex() || type==stdquad.GetIndex())
		ap1 = GetTempFPRegister();
	else
		ap1 = GetTempRegister();
	ap2 = allocOperand();
	ap2->isPtr = node->etype == bt_pointer;
	ap2->mode = am_indx;
	ap2->preg = regFP;          /* frame pointer */
	ap2->offset = node;     /* use as constant node */
	ap2->type = type;
	ap1->type = type;
	GenerateDiadic(op_lea,0,ap1,ap2);
	ap1->MakeLegal(flags,size);
	return (ap1);             /* return reg */
}
 
//
// General expression evaluation. returns the addressing mode
// of the result.
//
Operand *GenerateExpression(ENODE *node, int flags, int size)
{   
	Operand *ap1, *ap2;
    int natsize;
	static char buf[4][20];
	static int ndx;
	static int numDiags = 0;
 
    Enter("<GenerateExpression>"); 
    if( node == (ENODE *)NULL )
    {
		throw new C64PException(ERR_NULLPOINTER, 'G');
		numDiags++;
        printf("DIAG - null node in GenerateExpression.\n");
		if (numDiags > 100)
			exit(0);
        Leave("</GenerateExpression>",2); 
        return (Operand *)NULL;
    }
	//size = node->esize;
    switch( node->nodetype )
    {
	case en_fcon:
        ap1 = allocOperand();
		ap1->isPtr = node->IsPtr();
		ap1->mode = am_direct;
        ap1->offset = node;
		ap1->type = stddouble.GetIndex();
        ap1->MakeLegal(flags,size);
        Leave("</GenerateExpression>",2); 
        return (ap1);
		/*
            ap1 = allocOperand();
            ap1->mode = am_imm;
            ap1->offset = node;
			ap1->isFloat = TRUE;
            ap1->MakeLegal(flags,size);
         Leave("GenExperssion",2); 
            return ap1;
		*/
    case en_icon:
        ap1 = allocOperand();
        ap1->mode = am_imm;
        ap1->offset = node;
        ap1->MakeLegal(flags,size);
        Leave("GenExpression",3); 
        return (ap1);
 
	case en_labcon:
            if (use_gp) {
                ap1 = GetTempRegister();
                ap2 = allocOperand();
                ap2->mode = am_indx;
				switch (node->segment) {
				case tlsseg:	ap2->preg = regTP; break;
				case dataseg:	ap2->preg = regGP; break;
				default:	ap2->preg = regPP;
				}
                ap2->offset = node;     // use as constant node
                GenerateDiadic(op_lea,0,ap1,ap2);
				ap1->MakeLegal(flags,size);
         Leave("GenExperssion",4); 
                return ap1;             // return reg
            }
            ap1 = allocOperand();
			ap1->isPtr = node->IsPtr();
			/* this code not really necessary, see segments notes
			if (node->etype==bt_pointer && node->constflag) {
				ap1->segment = codeseg;
			}
			else {
				ap1->segment = dataseg;
			}
			*/
            ap1->mode = am_imm;
            ap1->offset = node;
			ap1->isUnsigned = node->isUnsigned;
            ap1->MakeLegal(flags,size);
         Leave("GenExperssion",5); 
            return ap1;
 
    case en_nacon:
            if (use_gp) {
                ap1 = GetTempRegister();
                ap2 = allocOperand();
                ap2->mode = am_indx;
                ap2->preg = regGP;      // global pointer
                ap2->offset = node;     // use as constant node
                GenerateDiadic(op_lea,0,ap1,ap2);
				ap1->MakeLegal(flags,size);
				Leave("GenExpression",6); 
                return ap1;             // return reg
            }
            // fallthru
	case en_cnacon:
            ap1 = allocOperand();
			ap1->isPtr = node->IsPtr();
			ap1->mode = am_imm;
            ap1->offset = node;
			if (node->i==0)
				node->i = -1;
			ap1->isUnsigned = node->isUnsigned;
            ap1->MakeLegal(flags,size);
			Leave("GenExpression",7); 
            return ap1;
	case en_clabcon:
            ap1 = allocOperand();
            ap1->mode = am_imm;
            ap1->offset = node;
			ap1->isUnsigned = node->isUnsigned;
            ap1->MakeLegal(flags,size);
			Leave("GenExpression",7); 
            return ap1;
    case en_autocon:	return GenAutocon(node, flags, size, stdint.GetIndex());
    case en_autofcon:	
		switch (node->tp->type)
		{
		case bt_float:	return GenAutocon(node, flags, size, stdflt.GetIndex());
		case bt_double:	return GenAutocon(node, flags, size, stddouble.GetIndex());
		case bt_triple:	return GenAutocon(node, flags, size, stdtriple.GetIndex());
		case bt_quad:	return GenAutocon(node, flags, size, stdquad.GetIndex());
		}
		break;
    case en_autovcon:	return GenAutocon(node, flags, size, stdvector.GetIndex());
    case en_autovmcon:	return GenAutocon(node, flags, size, stdvectormask->GetIndex());
    case en_classcon:
            ap1 = GetTempRegister();
            ap2 = allocOperand();
            ap2->mode = am_indx;
            ap2->preg = regCLP;     /* frame pointer */
            ap2->offset = node;     /* use as constant node */
            GenerateDiadic(op_lea,0,ap1,ap2);
			ap1->MakeLegal(flags,size);
            return ap1;             /* return reg */
    case en_ub_ref:
	case en_uc_ref:
	case en_uh_ref:
	case en_uw_ref:
		ap1 = GenerateDereference(node, flags, size, 0);
		ap1->isUnsigned = TRUE;
		return ap1;
	case en_hp_ref:
	case en_wp_ref:
			ap1 = GenerateDereference(node,flags,size,0);
			ap1->isPtr = TRUE;
			ap1->isUnsigned = TRUE;
            return ap1;
	case en_vector_ref:	return GenerateDereference(node,flags,512,0);
	case en_ref32:	return GenerateDereference(node,flags,4,1);
	case en_ref32u:	return GenerateDereference(node,flags,4,0);
    case en_b_ref:	return GenerateDereference(node,flags,1,1);
	case en_c_ref:	return GenerateDereference(node,flags,2,1);
	case en_h_ref:	return GenerateDereference(node,flags,4,1);
    case en_w_ref:	return GenerateDereference(node,flags,8,1);
	case en_flt_ref:
		ap1 = GenerateDereference(node, flags, size, 1);
		ap1->type = stdflt.GetIndex();
		return (ap1);
	case en_dbl_ref:
		ap1 = GenerateDereference(node, flags, size, 1);
		ap1->type = stddouble.GetIndex();
		return (ap1);
	case en_triple_ref:
		ap1 = GenerateDereference(node, flags, size, 1);
		ap1->type = stdtriple.GetIndex();
		return (ap1);
	case en_quad_ref:
			ap1 = GenerateDereference(node,flags,size,1);
			ap1->type = stdquad.GetIndex();
            return (ap1);
	case en_ubfieldref:
	case en_ucfieldref:
	case en_uhfieldref:
	case en_uwfieldref:
			ap1 = (flags & BF_ASSIGN) ? GenerateDereference(node,flags & ~BF_ASSIGN,size,0) : GenerateBitfieldDereference(node,flags,size);
			ap1->isUnsigned = TRUE;
			return ap1;
	case en_wfieldref:
	case en_bfieldref:
	case en_cfieldref:
	case en_hfieldref:
			ap1 = (flags & BF_ASSIGN) ? GenerateDereference(node,flags & ~BF_ASSIGN,size,1) : GenerateBitfieldDereference(node,flags,size);
			return ap1;
	case en_regvar:
    case en_tempref:
            ap1 = allocOperand();
			ap1->isPtr = node->IsPtr();
            ap1->mode = am_reg;
            ap1->preg = node->i;
            ap1->tempflag = 0;      /* not a temporary */
            ap1->MakeLegal(flags,size);
            return (ap1);
    case en_tempfpref:
            ap1 = allocOperand();
            ap1->mode = am_fpreg;
            ap1->preg = node->i;
            ap1->tempflag = 0;      /* not a temporary */
			if (node->tp)
				switch (node->tp->type) {
				case bt_float:	ap1->type = stdflt.GetIndex(); break;
				case bt_double:	ap1->type = stddouble.GetIndex(); break;
				case bt_triple:	ap1->type = stdtriple.GetIndex(); break;
				case bt_quad:	ap1->type = stdquad.GetIndex(); break;
				}
			else
				ap1->type = stddouble.GetIndex();
			ap1->MakeLegal(flags,size);
            return ap1;
	case en_fpregvar:
//    case en_fptempref:
            ap1 = allocOperand();
            ap1->mode = am_fpreg;
            ap1->preg = node->i;
            ap1->tempflag = 0;      /* not a temporary */
			if (node->tp)
				switch (node->tp->type) {
				case bt_float:	ap1->type = stdflt.GetIndex(); break;
				case bt_double:	ap1->type = stddouble.GetIndex(); break;
				case bt_triple:	ap1->type = stdtriple.GetIndex(); break;
				case bt_quad:	ap1->type = stdquad.GetIndex(); break;
				}
			else
				ap1->type = stddouble.GetIndex();
			ap1->MakeLegal(flags,size);
            return ap1;
	case en_abs:	return node->GenUnary(flags,size,op_abs);
    case en_uminus: return node->GenUnary(flags,size,op_neg);
    case en_compl:  return node->GenUnary(flags,size,op_com);
	case en_not:	return (node->GenUnary(flags, 8, op_not));
    case en_add:    return node->GenBinary(flags,size,op_add);
    case en_sub:    return node->GenBinary(flags,size,op_sub);
    case en_i2d:
         ap1 = GetTempFPRegister();	
         ap2=GenerateExpression(node->p[0],F_REG,8);
         GenerateDiadic(op_itof,'d',ap1,ap2);
         ReleaseTempReg(ap2);
         return (ap1);
    case en_i2q:
         ap1 = GetTempFPRegister();	
         ap2 = GenerateExpression(node->p[0],F_REG,8);
		 GenerateTriadic(op_csrrw,0,makereg(0),make_immed(0x18),ap2);
		 GenerateZeradic(op_nop);
		 GenerateZeradic(op_nop);
         GenerateDiadic(op_itof,'q',ap1,makereg(63));
         ReleaseTempReg(ap2);
         return (ap1);
    case en_i2t:
         ap1 = GetTempFPRegister();	
         ap2 = GenerateExpression(node->p[0],F_REG,8);
		 GenerateTriadic(op_csrrw,0,makereg(0),make_immed(0x18),ap2);
		 GenerateZeradic(op_nop);
		 GenerateZeradic(op_nop);
         GenerateDiadic(op_itof,'t',ap1,makereg(63));
         ReleaseTempReg(ap2);
         return (ap1);
    case en_d2i:
         ap1 = GetTempRegister();	
         ap2 = GenerateExpression(node->p[0],F_FPREG,8);
         GenerateDiadic(op_ftoi,'d',ap1,ap2);
         ReleaseTempReg(ap2);
         return (ap1);
    case en_q2i:
         ap1 = GetTempRegister();
         ap2 = GenerateExpression(node->p[0],F_FPREG,8);
         GenerateDiadic(op_ftoi,'q',makereg(63),ap2);
		 GenerateZeradic(op_nop);
		 GenerateZeradic(op_nop);
		 GenerateTriadic(op_csrrw,0,ap1,make_immed(0x18),makereg(0));
         ReleaseTempReg(ap2);
         return (ap1);
    case en_t2i:
         ap1 = GetTempRegister();
         ap2 = GenerateExpression(node->p[0],F_FPREG,8);
         GenerateDiadic(op_ftoi,'t',makereg(63),ap2);
		 GenerateZeradic(op_nop);
		 GenerateZeradic(op_nop);
		 GenerateTriadic(op_csrrw,0,ap1,make_immed(0x18),makereg(0));
         ReleaseTempReg(ap2);
         return (ap1);
	case en_s2q:
		ap1 = GetTempFPRegister();
        ap2 = GenerateExpression(node->p[0],F_FPREG,8);
        GenerateDiadic(op_fcvtsq,0,ap1,ap2);
		ap1->type = stdquad.GetIndex();
		ReleaseTempReg(ap2);
		return ap1;
	case en_d2q:
		ap1 = GetTempFPRegister();
		ap2 = GenerateExpression(node->p[0], F_FPREG, 8);
		GenerateDiadic(op_fcvtdq, 0, ap1, ap2);
		ap1->type = stdquad.GetIndex();
		ReleaseTempReg(ap2);
		return ap1;
	case en_t2q:
		ap1 = GetTempFPRegister();
		ap2 = GenerateExpression(node->p[0], F_FPREG, 8);
		GenerateDiadic(op_fcvttq, 0, ap1, ap2);
		ap1->type = stdquad.GetIndex();
		ReleaseTempReg(ap2);
		return ap1;
 
	case en_vadd:	  return node->GenBinary(flags,size,op_vadd);
	case en_vsub:	  return node->GenBinary(flags,size,op_vsub);
	case en_vmul:	  return node->GenBinary(flags,size,op_vmul);
	case en_vadds:	  return node->GenBinary(flags,size,op_vadds);
	case en_vsubs:	  return node->GenBinary(flags,size,op_vsubs);
	case en_vmuls:	  return node->GenBinary(flags,size,op_vmuls);
	case en_vex:      return node->GenBinary(flags,size,op_vex);
	case en_veins:    return node->GenBinary(flags,size,op_veins);
 
	case en_fadd:	  return node->GenBinary(flags,size,op_fadd);
	case en_fsub:	  return node->GenBinary(flags,size,op_fsub);
	case en_fmul:	  return node->GenBinary(flags,size,op_fmul);
	case en_fdiv:	  return node->GenBinary(flags,size,op_fdiv);
 
	case en_fdadd:    return node->GenBinary(flags,size,op_fdadd);
    case en_fdsub:    return node->GenBinary(flags,size,op_fdsub);
    case en_fsadd:    return node->GenBinary(flags,size,op_fsadd);
    case en_fssub:    return node->GenBinary(flags,size,op_fssub);
    case en_fdmul:    return GenerateMultiply(node,flags,size,op_fmul);
    case en_fsmul:    return GenerateMultiply(node,flags,size,op_fmul);
    case en_fddiv:    return GenerateMultiply(node,flags,size,op_fddiv);
    case en_fsdiv:    return GenerateMultiply(node,flags,size,op_fsdiv);
	case en_ftadd:    return node->GenBinary(flags,size,op_ftadd);
    case en_ftsub:    return node->GenBinary(flags,size,op_ftsub);
    case en_ftmul:    return GenerateMultiply(node,flags,size,op_ftmul);
    case en_ftdiv:    return GenerateMultiply(node,flags,size,op_ftdiv);
 
	case en_land:	return (node->GenLand(flags,op_and));
	case en_lor:	return (node->GenLand(flags, op_or));
	case en_and:    return node->GenBinary(flags,size,op_and);
    case en_or:     return node->GenBinary(flags,size,op_or);
	case en_xor:	return node->GenBinary(flags,size,op_xor);
    case en_mul:    return GenerateMultiply(node,flags,size,op_mul);
    case en_mulu:   return GenerateMultiply(node,flags,size,op_mulu);
    case en_div:    return node->GenDivMod(flags,size,op_div);
    case en_udiv:   return node->GenDivMod(flags,size,op_divu);
    case en_mod:    return node->GenDivMod(flags,size,op_mod);
    case en_umod:   return node->GenDivMod(flags,size,op_modu);
    case en_asl:    return node->GenShift(flags,size,op_asl);
    case en_shl:    return node->GenShift(flags,size,op_shl);
    case en_shlu:   return node->GenShift(flags,size,op_shl);
    case en_asr:	return node->GenShift(flags,size,op_asr);
    case en_shr:	return node->GenShift(flags,size,op_asr);
    case en_shru:   return node->GenShift(flags,size,op_shru);
	case en_rol:   return node->GenShift(flags,size,op_rol);
	case en_ror:   return node->GenShift(flags,size,op_ror);
	/*	
	case en_asfadd: return GenerateAssignAdd(node,flags,size,op_fadd);
	case en_asfsub: return GenerateAssignAdd(node,flags,size,op_fsub);
	case en_asfmul: return GenerateAssignAdd(node,flags,size,op_fmul);
	case en_asfdiv: return GenerateAssignAdd(node,flags,size,op_fdiv);
	*/
    case en_asadd:  return node->GenAssignAdd(flags,size,op_add);
    case en_assub:  return node->GenAssignAdd(flags,size,op_sub);
    case en_asand:  return node->GenAssignLogic(flags,size,op_and);
    case en_asor:   return node->GenAssignLogic(flags,size,op_or);
	case en_asxor:  return node->GenAssignLogic(flags,size,op_xor);
    case en_aslsh:  return (node->GenAssignShift(flags,size,op_shl));
    case en_asrsh:  return (node->GenAssignShift(flags,size,op_asr));
	case en_asrshu: return (node->GenAssignShift(flags,size,op_shru));
    case en_asmul: return GenerateAssignMultiply(node,flags,size,op_mul);
    case en_asmulu: return GenerateAssignMultiply(node,flags,size,op_mulu);
    case en_asdiv: return GenerateAssignModiv(node,flags,size,op_div);
    case en_asdivu: return GenerateAssignModiv(node,flags,size,op_divu);
    case en_asmod: return GenerateAssignModiv(node,flags,size,op_mod);
    case en_asmodu: return GenerateAssignModiv(node,flags,size,op_modu);
    case en_assign:
            return (GenerateAssign(node,flags,size));
 
	case en_chk:
        return (GenExpr(node));
 
    case en_eq:     case en_ne:
    case en_lt:     case en_le:
    case en_gt:     case en_ge:
    case en_ult:    case en_ule:
    case en_ugt:    case en_uge:
    case en_feq:    case en_fne:
    case en_flt:    case en_fle:
    case en_fgt:    case en_fge:
    case en_veq:    case en_vne:
    case en_vlt:    case en_vle:
    case en_vgt:    case en_vge:
      return GenExpr(node);
 
	case en_cond:
            return node->GenHook(flags,size);
    case en_void:
            natsize = GetNaturalSize(node->p[0]);
            ReleaseTempRegister(GenerateExpression(node->p[0],F_ALL | F_NOVALUE,natsize));
			ap1 = GenerateExpression(node->p[1], flags, size);
			ap1->isPtr = node->IsPtr();
            return (ap1);
 
    case en_fcall:
		return (GenerateFunctionCall(node,flags));
 
	case en_sxb:
		ap2 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, 8);
		GenerateDiadic(op_sxb, 0, ap2, ap1);
		ReleaseTempReg(ap1);
		ap2->MakeLegal( flags, 8);
		return (ap2);
	case en_sxc:
		ap2 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, 8);
		GenerateDiadic(op_sxc, 0, ap2, ap1);
		ReleaseTempReg(ap1);
		ap2->MakeLegal( flags, 8);
		return (ap2);
	case en_sxh:
		ap2 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, 8);
		GenerateDiadic(op_sxh, 0, ap2, ap1);
		ReleaseTempReg(ap1);
		ap2->MakeLegal( flags, 8);
		return (ap2);
	case en_cubw:
	case en_cubu:
	case en_cbu:
			ap1 = GenerateExpression(node->p[0],F_REG,size);
			GenerateTriadic(op_and,0,ap1,ap1,make_immed(0xff));
			return (ap1);
	case en_cucw:
	case en_cucu:
	case en_ccu:
			ap1 = GenerateExpression(node->p[0],F_REG,size);
			GenerateDiadic(op_zxc,0,ap1,ap1);
			return ap1;
	case en_ccwp:
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap1->isPtr = TRUE;
		GenerateDiadic(op_sxc, 0, ap1, ap1);
		return ap1;
	case en_cucwp:
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap1->isPtr = TRUE;
		GenerateDiadic(op_zxc, 0, ap1, ap1);
		return ap1;
	case en_cuhw:
	case en_cuhu:
	case en_chu:
			ap1 = GenerateExpression(node->p[0],F_REG,size);
			GenerateDiadic(op_zxh,0,ap1,ap1);
			return ap1;
	case en_cbw:
			ap1 = GenerateExpression(node->p[0],F_REG,size);
			//GenerateDiadic(op_sxb,0,ap1,ap1);
			GenerateDiadic(op_sxb,0,ap1,ap1);
			return ap1;
	case en_ccw:
			ap1 = GenerateExpression(node->p[0],F_REG,size);
			GenerateDiadic(op_sxc,0,ap1,ap1);
			return ap1;
	case en_chw:
			ap1 = GenerateExpression(node->p[0],F_REG,size);
			GenerateDiadic(op_sxh,0,ap1,ap1);
			return ap1;
	case en_object_list:
			ap1 = GetTempRegister();
			GenerateDiadic(op_lea,0,ap1,make_indexed(-8,regFP));
			ap1->MakeLegal(flags,sizeOfWord);
			return (ap1);
    default:
            printf("DIAG - uncoded node (%d) in GenerateExpression.\n", node->nodetype);
            return 0;
    }
	return(0);
}
 
// return the natural evaluation size of a node.
 
int GetNaturalSize(ENODE *node)
{ 
	int siz0, siz1;
	if( node == NULL )
		return 0;
	switch( node->nodetype )
	{
	case en_uwfieldref:
	case en_wfieldref:
		return sizeOfWord;
	case en_bfieldref:
	case en_ubfieldref:
		return 1;
	case en_cfieldref:
	case en_ucfieldref:
		return 2;
	case en_hfieldref:
	case en_uhfieldref:
		return 4;
	case en_icon:
		if (node->i >= -128 && node->i < 128)
			return (1);
		if( -32768 <= node->i && node->i <= 32767 )
			return (2);
		if (-2147483648LL <= node->i && node->i <= 2147483647LL)
			return (4);
		return (8);
	case en_fcon:
		return node->tp->precision / 16;
	case en_tcon: return 6;
	case en_fcall:  case en_labcon: case en_clabcon:
	case en_cnacon: case en_nacon:  case en_autocon: case en_classcon:
	case en_tempref:
	case en_cbw: case en_cubw:
	case en_ccw: case en_cucw:
	case en_chw: case en_cuhw:
	case en_cbu: case en_ccu: case en_chu:
	case en_cubu: case en_cucu: case en_cuhu:
	case en_ccwp: case en_cucwp:
	case en_sxb:	case en_sxc:	case en_sxh:
		return 8;
	case en_regvar:
	case en_fpregvar:
		if (node->tp)
			return (node->tp->size);
		else
			return (8);
	case en_autofcon:
		return 8;
	case en_ref32: case en_ref32u:
		return 4;
	case en_b_ref:
	case en_ub_ref:
		return 1;
	case en_cbc:
	case en_c_ref:	return 2;
	case en_uc_ref:	return 2;
	case en_cbh:	return 2;
	case en_cch:	return 2;
	case en_h_ref:	return 4;
	case en_uh_ref:	return 4;
	case en_flt_ref: return sizeOfFPS;
	case en_w_ref:  case en_uw_ref:
		return 8;
	case en_hp_ref:
		return 4;
	case en_wp_ref:
		return 8;
	case en_autovcon:
	case en_vector_ref:
		return 512;
	case en_dbl_ref:
		return sizeOfFPD;
	case en_quad_ref:
		return sizeOfFPQ;
	case en_triple_ref:
		return sizeOfFPT;
	case en_tempfpref:
	if (node->tp)
		return node->tp->precision/16;
	else
		return 8;
	case en_not:    case en_compl:
	case en_uminus: case en_assign:
		return GetNaturalSize(node->p[0]);
	case en_fadd:	case en_fsub:
	case en_fmul:	case en_fdiv:
	case en_fsadd:	case en_fssub:
	case en_fsmul:	case en_fsdiv:
	case en_vadd:	case en_vsub:
	case en_vmul:	case en_vdiv:
	case en_vadds:	case en_vsubs:
	case en_vmuls:	case en_vdivs:
	case en_add:    case en_sub:
	case en_mul:    case en_mulu:
	case en_div:	case en_udiv:
	case en_mod:    case en_umod:
	case en_and:    case en_or:     case en_xor:
	case en_asl:
	case en_shl:    case en_shlu:
	case en_shr:	case en_shru:
	case en_asr:	case en_asrshu:
	case en_feq:    case en_fne:
	case en_flt:    case en_fle:
	case en_fgt:    case en_fge:
	case en_eq:     case en_ne:
	case en_lt:     case en_le:
	case en_gt:     case en_ge:
	case en_ult:	case en_ule:
	case en_ugt:	case en_uge:
	case en_land:   case en_lor:
	case en_asadd:  case en_assub:
	case en_asmul:  case en_asmulu:
	case en_asdiv:	case en_asdivu:
	case en_asmod:  case en_asand:
	case en_asor:   case en_asxor:	case en_aslsh:
	case en_asrsh:
		siz0 = GetNaturalSize(node->p[0]);
		siz1 = GetNaturalSize(node->p[1]);
		if( siz1 > siz0 )
			return siz1;
		else
			return siz0;
	case en_void:   case en_cond:
		return GetNaturalSize(node->p[1]);
	case en_bchk:
		return (GetNaturalSize(node->p[0]));
	case en_chk:
		return 8;
	case en_q2i:
	case en_t2i:
		return (sizeOfWord);
	case en_i2d:
		return (sizeOfWord);
	case en_i2t:
	case en_d2t:
		return (sizeOfFPT);
	case en_i2q:
	case en_d2q:
	case en_t2q:
		return (sizeOfFPQ);
	default:
		printf("DIAG - natural size error %d.\n", node->nodetype);
		break;
	}
	return 0;
}
 
 
static void GenerateCmp(ENODE *node, int op, int label, unsigned int prediction)
{
	Enter("GenCmp");
	GenerateCmp(node, op, label, 0, prediction);
	Leave("GenCmp",0);
}
 
//
// Generate a jump to label if the node passed evaluates to
// a true condition.
//
void GenerateTrueJump(ENODE *node, int label, unsigned int prediction)
{ 
	Operand  *ap1;
	int    siz1;
 
	if( node == 0 )
		return;
	switch( node->nodetype )
	{
	case en_bchk:	break;
	case en_eq:	GenerateCmp(node, op_eq, label, prediction); break;
	case en_ne: GenerateCmp(node, op_ne, label, prediction); break;
	case en_lt: GenerateCmp(node, op_lt, label, prediction); break;
	case en_le:	GenerateCmp(node, op_le, label, prediction); break;
	case en_gt: GenerateCmp(node, op_gt, label, prediction); break;
	case en_ge: GenerateCmp(node, op_ge, label, prediction); break;
	case en_ult: GenerateCmp(node, op_ltu, label, prediction); break;
	case en_ule: GenerateCmp(node, op_leu, label, prediction); break;
	case en_ugt: GenerateCmp(node, op_gtu, label, prediction); break;
	case en_uge: GenerateCmp(node, op_geu, label, prediction); break;
	case en_feq: GenerateCmp(node, op_feq, label, prediction); break;
	case en_fne: GenerateCmp(node, op_fne, label, prediction); break;
	case en_flt: GenerateCmp(node, op_flt, label, prediction); break;
	case en_fle: GenerateCmp(node, op_fle, label, prediction); break;
	case en_fgt: GenerateCmp(node, op_fgt, label, prediction); break;
	case en_fge: GenerateCmp(node, op_fge, label, prediction); break;
	case en_veq: GenerateCmp(node, op_vseq, label, prediction); break;
	case en_vne: GenerateCmp(node, op_vsne, label, prediction); break;
	case en_vlt: GenerateCmp(node, op_vslt, label, prediction); break;
	case en_vle: GenerateCmp(node, op_vsle, label, prediction); break;
	case en_vgt: GenerateCmp(node, op_vsgt, label, prediction); break;
	case en_vge: GenerateCmp(node, op_vsge, label, prediction); break;
	case en_lor:
		GenerateTrueJump(node->p[0],label,prediction);
		GenerateTrueJump(node->p[1],label,prediction);
		break;
	default:
		siz1 = GetNaturalSize(node);
		ap1 = GenerateExpression(node,F_REG,siz1);
		//                        GenerateDiadic(op_tst,siz1,ap1,0);
		ReleaseTempRegister(ap1);
		GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(label));
		break;
	}
}
 
//
// Generate code to execute a jump to label if the expression
// passed is false.
//
void GenerateFalseJump(ENODE *node,int label, unsigned int prediction)
{
	Operand *ap;
	int siz1;
	int lab0;
 
	if( node == (ENODE *)NULL )
		return;
	switch( node->nodetype )
	{
	case en_bchk:	break;
	case en_eq:	GenerateCmp(node, op_ne, label, prediction); break;
	case en_ne: GenerateCmp(node, op_eq, label, prediction); break;
	case en_lt: GenerateCmp(node, op_ge, label, prediction); break;
	case en_le: GenerateCmp(node, op_gt, label, prediction); break;
	case en_gt: GenerateCmp(node, op_le, label, prediction); break;
	case en_ge: GenerateCmp(node, op_lt, label, prediction); break;
	case en_ult: GenerateCmp(node, op_geu, label, prediction); break;
	case en_ule: GenerateCmp(node, op_gtu, label, prediction); break;
	case en_ugt: GenerateCmp(node, op_leu, label, prediction); break;
	case en_uge: GenerateCmp(node, op_ltu, label, prediction); break;
	case en_feq: GenerateCmp(node, op_fne, label, prediction); break;
	case en_fne: GenerateCmp(node, op_feq, label, prediction); break;
	case en_flt: GenerateCmp(node, op_fge, label, prediction); break;
	case en_fle: GenerateCmp(node, op_fgt, label, prediction); break;
	case en_fgt: GenerateCmp(node, op_fle, label, prediction); break;
	case en_fge: GenerateCmp(node, op_flt, label, prediction); break;
	case en_veq: GenerateCmp(node, op_vsne, label, prediction); break;
	case en_vne: GenerateCmp(node, op_vseq, label, prediction); break;
	case en_vlt: GenerateCmp(node, op_vsge, label, prediction); break;
	case en_vle: GenerateCmp(node, op_vsgt, label, prediction); break;
	case en_vgt: GenerateCmp(node, op_vsle, label, prediction); break;
	case en_vge: GenerateCmp(node, op_vslt, label, prediction); break;
	case en_land:
		GenerateFalseJump(node->p[0],label,prediction^1);
		GenerateFalseJump(node->p[1],label,prediction^1);
		break;
	case en_lor:
		lab0 = nextlabel++;
		GenerateTrueJump(node->p[0],lab0,prediction);
		GenerateFalseJump(node->p[1],label,prediction^1);
		GenerateLabel(lab0);
		break;
	case en_not:
		GenerateTrueJump(node->p[0],label,prediction);
		break;
	default:
		siz1 = GetNaturalSize(node);
		ap = GenerateExpression(node,F_REG,siz1);
		//                        GenerateDiadic(op_tst,siz1,ap,0);
		ReleaseTempRegister(ap);
		GenerateTriadic(op_beq,0,ap,makereg(0),make_label(label));
		break;
	}
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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