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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [FT64.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"
 
extern TYP              stdfunc;
 
extern void DumpCSETable();
extern void scan(Statement *);
extern void GenerateComment(char *);
int TempFPInvalidate();
int TempInvalidate();
void TempRevalidate(int,int);
void TempFPRevalidate(int);
void ReleaseTempRegister(Operand *ap);
Operand *GetTempRegister();
extern void GenLoad(Operand *ap1, Operand *ap3, int ssize, int size);
 
Operand *GenExpr(ENODE *node)
{
	Operand *ap1,*ap2,*ap3,*ap4;
	int lab0, lab1;
	int size;
	int op;
 
    lab0 = nextlabel++;
    lab1 = nextlabel++;
 
	switch(node->nodetype) {
	case en_eq:		op = op_seq;	break;
	case en_ne:		op = op_sne;	break;
	case en_lt:		op = op_slt;	break;
	case en_ult:	op = op_sltu;	break;
	case en_le:		op = op_sle;	break;
	case en_ule:	op = op_sleu;	break;
	case en_gt:		op = op_sgt;	break;
	case en_ugt:	op = op_sgtu;	break;
	case en_ge:		op = op_sge;	break;
	case en_uge:	op = op_sgeu;	break;
	case en_flt:	op = op_fslt;	break;
	case en_fle:	op = op_fsle;	break;
	case en_fgt:	op = op_fsgt;	break;
	case en_fge:	op = op_fsge;	break;
	case en_feq:	op = op_fseq;	break;
	case en_fne:	op = op_fsne;	break;
	case en_veq:
		size = GetNaturalSize(node);
		ap3 = GetTempVectorRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateTriadic(op_vseq,0,ap3,ap1,ap2);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		return (ap3);
	case en_vne:
		size = GetNaturalSize(node);
		ap3 = GetTempVectorRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateTriadic(op_vsne,0,ap3,ap1,ap2);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		return (ap3);
	case en_vlt:
		size = GetNaturalSize(node);
		ap3 = GetTempVectorRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateTriadic(op_vslt,0,ap3,ap1,ap2);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		return (ap3);
	case en_vle:
		size = GetNaturalSize(node);
		ap3 = GetTempVectorRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateTriadic(op_vsle,0,ap3,ap1,ap2);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		return (ap3);
	case en_vgt:
		size = GetNaturalSize(node);
		ap3 = GetTempVectorRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateTriadic(op_vsgt,0,ap3,ap1,ap2);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		return (ap3);
	case en_vge:
		size = GetNaturalSize(node);
		ap3 = GetTempVectorRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		GenerateTriadic(op_vsge,0,ap3,ap1,ap2);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		return (ap3);
	default:	// en_land, en_lor
		//ap1 = GetTempRegister();
		//ap2 = GenerateExpression(node,F_REG,8);
		//GenerateDiadic(op_redor,0,ap1,ap2);
		//ReleaseTempReg(ap2);
		GenerateFalseJump(node,lab0,0);
		ap1 = GetTempRegister();
		GenerateDiadic(op_ldi,0,ap1,make_immed(1));
		GenerateMonadic(op_bra,0,make_label(lab1));
		GenerateLabel(lab0);
		GenerateDiadic(op_ldi,0,ap1,make_immed(0));
		GenerateLabel(lab1);
		return ap1;
	}
 
	switch (node->nodetype) {
	case en_eq:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op_xnor, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		GenerateDiadic(op_redor, 0, ap3, ap3);
		return (ap3);
	case en_ne:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op_xor, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		GenerateDiadic(op_redor, 0, ap3, ap3);
		return (ap3);
	case en_lt:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op_slt, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_slt,0,ap3,ap3);
		return (ap3);
	case en_le:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op_sle, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_sle,0,ap3,ap3);
		return (ap3);
	case en_gt:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		if (ap2->mode == am_reg)
			GenerateTriadic(op_slt, 0, ap3, ap2, ap1);
		else
			GenerateTriadic(op_sgt, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_sgt,0,ap3,ap3);
		return (ap3);
	case en_ge:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op_slt, 0, ap3, ap1, ap2);
		GenerateDiadic(op_not, 0, ap3, ap3);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_sge,0,ap3,ap3);
		return (ap3);
	case en_ult:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		GenerateTriadic(op_sltu, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_slt,0,ap3,ap3);
		return (ap3);
	case en_ule:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		if (ap2->mode == am_imm) {
			GenerateTriadic(op_sgt, 0, ap3, ap1, ap2);
			GenerateDiadic(op_not, 0, ap3, ap3);
		}
		else
			GenerateTriadic(op_sleu, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_sle,0,ap3,ap3);
		return (ap3);
	case en_ugt:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		if (ap2->mode == am_reg)
			GenerateTriadic(op_sleu, 0, ap3, ap2, ap1);
		else
			GenerateTriadic(op_sgtu, 0, ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		//		GenerateDiadic(op_sgt,0,ap3,ap3);
		return (ap3);
	case en_uge:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_REG, size);
		ap2 = GenerateExpression(node->p[1], F_REG | F_IMMED, size);
		if (ap2->mode == am_reg)
			GenerateTriadic(op_sleu, 0, ap3, ap2, ap1);
		else {
			GenerateTriadic(op_sltu, 0, ap3, ap1, ap2);
			GenerateDiadic(op_not, 0, ap3, ap3);
		}
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
//		GenerateDiadic(op_sge,0,ap3,ap3);
		return (ap3);
	case en_flt:
	case en_fle:
	case en_fgt:
	case en_fge:
	case en_feq:
	case en_fne:
		size = GetNaturalSize(node);
		ap3 = GetTempRegister();
		ap1 = GenerateExpression(node->p[0], F_FPREG, size);
		ap2 = GenerateExpression(node->p[1], F_FPREG, size);
		GenerateTriadic(op, ap1->fpsize(), ap3, ap1, ap2);
		ReleaseTempRegister(ap2);
		ReleaseTempRegister(ap1);
		return (ap3);
		/*
	case en_ne:
	case en_lt:
	case en_ult:
	case en_gt:
	case en_ugt:
	case en_le:
	case en_ule:
	case en_ge:
	case en_uge:
		size = GetNaturalSize(node);
		ap1 = GenerateExpression(node->p[0],F_REG, size);
		ap2 = GenerateExpression(node->p[1],F_REG|F_IMMED,size);
		GenerateTriadic(op,0,ap1,ap1,ap2);
		ReleaseTempRegister(ap2);
		return ap1;
*/
	case en_chk:
		size = GetNaturalSize(node);
        ap4 = GetTempRegister();         
		ap1 = GenerateExpression(node->p[0],F_REG,size);
		ap2 = GenerateExpression(node->p[1],F_REG,size);
		ap3 = GenerateExpression(node->p[2],F_REG|F_IMM0,size);
		if (ap3->mode == am_imm) {  // must be a zero
		   ap3->mode = am_reg;
		   ap3->preg = 0;
        }
   		Generate4adic(op_chk,0,ap4,ap1,ap2,ap3);
        ReleaseTempRegister(ap3);
        ReleaseTempRegister(ap2);
        ReleaseTempRegister(ap1);
        return ap4;
	}
	size = GetNaturalSize(node);
    ap3 = GetTempRegister();         
	ap1 = GenerateExpression(node->p[0],F_REG,size);
	ap2 = GenerateExpression(node->p[1],F_REG|F_IMMED,size);
	GenerateTriadic(op,0,ap3,ap1,ap2);
    ReleaseTempRegister(ap2);
    ReleaseTempRegister(ap1);
    return ap3;
	/*
    GenerateFalseJump(node,lab0,0);
    ap1 = GetTempRegister();
    GenerateDiadic(op_ld,0,ap1,make_immed(1));
    GenerateMonadic(op_bra,0,make_label(lab1));
    GenerateLabel(lab0);
    GenerateDiadic(op_ld,0,ap1,make_immed(0));
    GenerateLabel(lab1);
    return ap1;
	*/
}
 
void GenerateCmp(ENODE *node, int op, int label, int predreg, unsigned int prediction)
{
	int size, sz;
	Operand *ap1, *ap2, *ap3;
 
	size = GetNaturalSize(node);
    if (op==op_flt || op==op_fle || op==op_fgt || op==op_fge || op==op_feq || op==op_fne) {
    	ap1 = GenerateExpression(node->p[0],F_FPREG,size);
	    ap2 = GenerateExpression(node->p[1],F_FPREG,size);
    }
    else {
    	ap1 = GenerateExpression(node->p[0],F_REG, size);
	    ap2 = GenerateExpression(node->p[1],F_REG|F_IMMED,size);
    }
	/*
	// Optimize CMP to zero and branch into plain branch, this works only for
	// signed relational compares.
	if (ap2->mode == am_imm && ap2->offset->i==0 && (op==op_eq || op==op_ne || op==op_lt || op==op_le || op==op_gt || op==op_ge)) {
    	switch(op)
    	{
    	case op_eq:	op = op_beq; break;
    	case op_ne:	op = op_bne; break;
    	case op_lt: op = op_blt; break;
    	case op_le: op = op_ble; break;
    	case op_gt: op = op_bgt; break;
    	case op_ge: op = op_bge; break;
    	}
    	ReleaseTempReg(ap3);
		ReleaseTempReg(ap2);
		ReleaseTempReg(ap1);
		GenerateDiadic(op,0,ap1,make_clabel(label));
		return;
	}
	*/
	/*
	if (op==op_ltu || op==op_leu || op==op_gtu || op==op_geu)
 	    GenerateTriadic(op_cmpu,0,ap3,ap1,ap2);
    else if (op==op_flt || op==op_fle || op==op_fgt || op==op_fge || op==op_feq || op==op_fne)
        GenerateTriadic(op_fdcmp,0,ap3,ap1,ap2);
	else 
 	    GenerateTriadic(op_cmp,0,ap3,ap1,ap2);
	*/
	sz = 0;
	switch(op)
	{
	case op_bchk:	break;
	case op_eq:	op = op_beq; break;
	case op_ne:	op = op_bne; break;
	case op_lt: op = op_blt; break;
	case op_le: op = op_ble; break;
	case op_gt: op = op_bgt; break;
	case op_ge: op = op_bge; break;
	case op_ltu: op = op_bltu; break;
	case op_leu: op = op_bleu; break;
	case op_gtu: op = op_bgtu; break;
	case op_geu: op = op_bgeu; break;
	case op_feq:	op = op_fbeq; sz = 'd'; break;
	case op_fne:	op = op_fbne; sz = 'd'; break;
	case op_flt:	op = op_fblt; sz = 'd'; break;
	case op_fle:	op = op_fble; sz = 'd'; break;
	case op_fgt:	op = op_fbgt; sz = 'd'; break;
	case op_fge:	op = op_fbge; sz = 'd'; break;
	/*
		GenerateTriadic(op_fcmp,'q',ap3,ap1,ap2);
		GenerateTriadic(op_bbs,0,ap3,make_immed(0),make_clabel(label));
		goto xit;
	case op_fne:
		GenerateTriadic(op_fcmp,'q',ap3,ap1,ap2);
		GenerateTriadic(op_bbc,0,ap3,make_immed(0),make_clabel(label));
		goto xit;
	case op_flt:
		GenerateTriadic(op_fcmp,'q',ap3,ap1,ap2);
		GenerateTriadic(op_bbs,0,ap3,make_immed(1),make_clabel(label));
		goto xit;
	case op_fle:
		GenerateTriadic(op_fcmp,'q',ap3,ap1,ap2);
		GenerateTriadic(op_bbs,0,ap3,make_immed(2),make_clabel(label));
		goto xit;
	case op_fgt:
		GenerateTriadic(op_fcmp,'q',ap3,ap1,ap2);
		GenerateTriadic(op_bbc,0,ap3,make_immed(2),make_clabel(label));
		goto xit;
	case op_fge:
		GenerateTriadic(op_fcmp,'q',ap3,ap1,ap2);
		GenerateTriadic(op_bbc,0,ap3,make_immed(1),make_clabel(label));
		goto xit;
	*/
	}
	if (op==op_fbne || op==op_fbeq || op==op_fblt || op==op_fble || op==op_fbgt || op==op_fbge) {
		switch(op) {
		case op_fbne:
			if (ap2->mode==am_imm) {
				ap3 = GetTempFPRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_fbne,sz,ap1,ap3,make_clabel(label));
			}
			else
				GenerateTriadic(op_fbne,sz,ap1,ap2,make_clabel(label));
			break;
		case op_fbeq:
			if (ap2->mode==am_imm) {
				ap3 = GetTempRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_fbeq,sz,ap1,ap3,make_clabel(label));
			}
			else
				GenerateTriadic(op_fbeq,sz,ap1,ap2,make_clabel(label));
			break;
		case op_fblt:
			if (ap2->mode==am_imm) {
				ap3 = GetTempRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_fblt,sz,ap1,ap3,make_clabel(label));
			}
			else
				GenerateTriadic(op_fblt,sz,ap1,ap2,make_clabel(label));
			break;
		case op_fble:
			if (ap2->mode==am_imm) {
				ap3 = GetTempRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_fbge,sz,ap3,ap1,make_clabel(label));
			}
			else
				GenerateTriadic(op_fbge,sz,ap2,ap1,make_clabel(label));
			break;
		case op_fbgt:
			if (ap2->mode==am_imm) {
				ap3 = GetTempRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_fblt,sz,ap3,ap1,make_clabel(label));
			}
			else
				GenerateTriadic(op_fblt,sz,ap2,ap1,make_clabel(label));
			break;
		case op_fbge:
			if (ap2->mode==am_imm) {
				ap3 = GetTempRegister();
				GenerateDiadic(op_ldi,0,ap3,ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_fbge,sz,ap1,ap3,make_clabel(label));
			}
			else
				GenerateTriadic(op_fbge,sz,ap1,ap2,make_clabel(label));
			break;
		}
	}
	else {
		switch(op) {
		case op_beq:
			if (ap2->mode==am_imm && ap2->offset->nodetype==en_icon && ap2->offset->i >= -128 && ap2->offset->i <=128) {
				GenerateTriadic(op_beqi,0,ap1,ap2,make_clabel(label));
			}
			else if (ap2->mode==am_imm) {
				ap3 = GetTempRegister();
				GenerateTriadic(op_xor, 0, ap3, ap1, ap2);
				ReleaseTempRegister(ap3);
				GenerateTriadic(op_beq,0,ap3,makereg(0),make_clabel(label));
			}
			else {
				ReleaseTempReg(ap2);
				ReleaseTempReg(ap1);
				GenerateTriadic(op_beq, 0, ap1, ap2, make_clabel(label));
				return;
			}
			break;
		case op_bne:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0)
					GenerateTriadic(op_bne,0,ap1,makereg(0),make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_xor, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_bne,0,ap3,makereg(0),make_clabel(label));
				}
			}
			else {
				GenerateTriadic(op_bne,0,ap1,ap2,make_clabel(label));
			}
			break;
		case op_blt:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0)
					GenerateTriadic(op_blt,0,ap1,makereg(0),make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_slt, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_bne,0,ap3,makereg(0),make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_blt,0,ap1,ap2,make_clabel(label));
			break;
		case op_ble:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0)
					GenerateTriadic(op_bge,0,makereg(0),ap1,make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_sle , 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_bne,0,makereg(0),ap3,make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_bge,0,ap2,ap1,make_clabel(label));
			break;
		case op_bgt:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0)
					GenerateTriadic(op_blt,0,makereg(0),ap1,make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_sle, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_beq,0,makereg(0),ap3,make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_blt,0,ap2,ap1,make_clabel(label));
			break;
		case op_bge:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i==0) {
					GenerateTriadic(op_bge,0,ap1,makereg(0),make_clabel(label));
				}
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_slt, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_beq,0,ap3,makereg(0),make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_bge,0,ap1,ap2,make_clabel(label));
			break;
		case op_bltu:
			if (ap2->mode==am_imm) {
				// Don't generate any code if testing against unsigned zero.
				// An unsigned number can't be less than zero so the branch will
				// always be false. Spit out a warning, its probably coded wrong.
				if (ap2->offset->i == 0)
					error(ERR_UBLTZ);	//GenerateTriadic(op_bltu,0,ap1,makereg(0),make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_sltu, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_bne,0,ap3,makereg(0),make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_bltu,0,ap1,ap2,make_clabel(label));
			break;
		case op_bleu:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0)
					GenerateTriadic(op_bgeu,0,makereg(0),ap1,make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_sleu, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_bne,0,makereg(0),ap3,make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_bgeu,0,ap2,ap1,make_clabel(label));
			break;
		case op_bgtu:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0)
					GenerateTriadic(op_bltu,0,makereg(0),ap1,make_clabel(label));
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_sleu, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_beq,0,makereg(0),ap3,make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_bltu,0,ap2,ap1,make_clabel(label));
			break;
		case op_bgeu:
			if (ap2->mode==am_imm) {
				if (ap2->offset->i == 0) {
					// This branch is always true
					error(ERR_UBGEQ);
					GenerateTriadic(op_bgeu,0,ap1,makereg(0),make_clabel(label));
				}
				else {
					ap3 = GetTempRegister();
					GenerateTriadic(op_sltu, 0, ap3, ap1, ap2);
					ReleaseTempRegister(ap3);
					GenerateTriadic(op_beq,0,ap3,makereg(0),make_clabel(label));
				}
			}
			else
				GenerateTriadic(op_bgeu,0,ap1,ap2,make_clabel(label));
			break;
		}
		//GenerateTriadic(op,sz,ap1,ap2,make_clabel(label));
	}
   	ReleaseTempReg(ap2);
   	ReleaseTempReg(ap1);
}
 
 
static void SaveRegisterSet(SYM *sym)
{
	int nn, mm;
 
	if (!cpu.SupportsPush) {
		mm = sym->tp->GetBtp()->type!=bt_void ? 29 : 30;
		GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(mm*sizeOfWord));
		mm = 0;
		for (nn = 1 + (sym->tp->GetBtp()->type!=bt_void ? 1 : 0); nn < 31; nn++) {
			GenerateDiadic(op_sw,0,makereg(nn),make_indexed(mm,regSP));
			mm += sizeOfWord;
		}
	}
	else
		for (nn = 1 + (sym->tp->GetBtp()->type!=bt_void ? 1 : 0); nn < 31; nn++)
			GenerateMonadic(op_push,0,makereg(nn));
}
 
static void RestoreRegisterSet(SYM * sym)
{
	int nn, mm;
 
	if (!cpu.SupportsPop) {
		mm = 0;
		for (nn = 1 + (sym->tp->GetBtp()->type!=bt_void ? 1 : 0); nn < 31; nn++) {
			GenerateDiadic(op_lw,0,makereg(nn),make_indexed(mm,regSP));
			mm += sizeOfWord;
		}
		mm = sym->tp->GetBtp()->type!=bt_void ? 29 : 30;
		GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(mm*sizeOfWord));
	}
	else
		for (nn = 1 + (sym->tp->GetBtp()->type!=bt_void ? 1 : 0); nn < 31; nn++)
			GenerateMonadic(op_pop,0,makereg(nn));
}
 
 
// Push temporaries on the stack.
 
void SaveRegisterVars(int64_t mask, int64_t rmask)
{
	int cnt;
	int nn;
 
	if( mask != 0 ) {
		cnt = 0;
		GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(popcnt(mask)*8));
		for (nn = 0; nn < 64; nn++) {
			if (rmask & (0x8000000000000000ULL >> nn)) {
				GenerateDiadic(op_sw,0,makereg(nn),make_indexed(cnt,regSP));
				cnt+=sizeOfWord;
			}
		}
	}
}
 
void SaveFPRegisterVars(int64_t mask, int64_t rmask)
{
	int cnt;
	int nn;
 
	if( mask != 0 ) {
		cnt = 0;
		GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(popcnt(mask)*8));
		for (nn = 0; nn < 64; nn++) {
			if (rmask & (0x8000000000000000ULL >> nn)) {
				GenerateDiadic(op_sf,'d',makefpreg(nn),make_indexed(cnt,regSP));
				cnt+=sizeOfWord;
			}
		}
	}
}
 
// Restore registers used as register variables.
 
static void RestoreRegisterVars()
{
	int cnt2, cnt;
	int nn;
 
	if( save_mask != 0 ) {
		cnt2 = cnt = popcnt(save_mask)*sizeOfWord;
		cnt = 0;
		for (nn = 0; nn < 64; nn++) {
			if (save_mask & (1LL << nn)) {
				GenerateDiadic(op_lw,0,makereg(nn),make_indexed(cnt,regSP));
				cnt += sizeOfWord;
			}
		}
		GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(cnt2));
	}
}
 
static void RestoreFPRegisterVars()
{
	int cnt2, cnt;
	int nn;
 
	if( fpsave_mask != 0 ) {
		cnt2 = cnt = popcnt(fpsave_mask)*sizeOfWord;
		cnt = 0;
		for (nn = 0; nn < 64; nn++) {
			if (fpsave_mask & (1LL << nn)) {
				GenerateDiadic(op_lf,'d',makefpreg(nn),make_indexed(cnt,regSP));
				cnt += sizeOfWord;
			}
		}
		GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(cnt2));
	}
}
 
static int round4(int n)
{
    while(n & 3) n++;
    return (n);
};
 
static void SaveTemporaries(Function *sym, int *sp, int *fsp)
{
	if (sym) {
		if (sym->UsesTemps) {
			*sp = TempInvalidate(fsp);
			//*fsp = TempFPInvalidate();
		}
	}
	else {
		*sp = TempInvalidate(fsp);
		//*fsp = TempFPInvalidate();
	}
}
 
static void RestoreTemporaries(Function *sym, int sp, int fsp)
{
	if (sym) {
		if (sym->UsesTemps) {
			//TempFPRevalidate(fsp);
			TempRevalidate(sp,fsp);
		}
	}
	else {
		//TempFPRevalidate(fsp);
		TempRevalidate(sp,fsp);
	}
}
 
// push the operand expression onto the stack.
// Structure variables are represented as an address in a register and arrive
// here as autocon nodes if on the stack. If the variable size is greater than
// 8 we assume a structure variable and we assume we have the address in a reg.
// Returns: number of stack words pushed.
//
static int GeneratePushParameter(ENODE *ep, int regno, int stkoffs)
{    
	Operand *ap, *ap3;
	int nn = 0;
	int sz;
 
	switch(ep->etype) {
	case bt_quad:	sz = sizeOfFPD; break;
	case bt_triple:	sz = sizeOfFPT; break;
	case bt_double:	sz = sizeOfFPD; break;
	case bt_float:	sz = sizeOfFPD; break;
	default:	sz = sizeOfWord; break;
	}
	if (ep->tp) {
		if (ep->tp->IsFloatType())
			ap = GenerateExpression(ep,F_REG,sizeOfFP);
		else
			ap = GenerateExpression(ep,F_REG|F_IMMED,sizeOfWord);
	}
	else if (ep->etype==bt_quad)
		ap = GenerateExpression(ep,F_REG,sz);
	else if (ep->etype==bt_double)
		ap = GenerateExpression(ep,F_REG,sz);
	else if (ep->etype==bt_triple)
		ap = GenerateExpression(ep,F_REG,sz);
	else if (ep->etype==bt_float)
		ap = GenerateExpression(ep,F_REG,sz);
	else
		ap = GenerateExpression(ep,F_REG|F_IMMED,sz);
	switch(ap->mode) {
    case am_reg:
    case am_fpreg:
    case am_imm:
/*
        nn = round8(ep->esize); 
        if (nn > 8) {// && (ep->tp->type==bt_struct || ep->tp->type==bt_union)) {           // structure or array ?
            ap2 = GetTempRegister();
            GenerateTriadic(op_subui,0,makereg(regSP),makereg(regSP),make_immed(nn));
            GenerateDiadic(op_mov, 0, ap2, makereg(regSP));
            GenerateMonadic(op_push,0,make_immed(ep->esize));
            GenerateMonadic(op_push,0,ap);
            GenerateMonadic(op_push,0,ap2);
            GenerateMonadic(op_bsr,0,make_string("memcpy_"));
            GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(24));
          	GenerateMonadic(op_push,0,ap2);
            ReleaseTempReg(ap2);
            nn = nn >> 3;
        }
        else {
*/
			if (regno) {
				GenerateMonadic(op_hint,0,make_immed(1));
				if (ap->mode==am_imm) {
					GenerateDiadic(op_ldi,0,makereg(regno & 0x7fff), ap);
					if (regno & 0x8000) {
						GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(sizeOfWord));
						nn = 1;
					}
				}
				else if (ap->mode==am_fpreg) {
					GenerateDiadic(op_mov,0,makefpreg(regno & 0x7fff), ap);
					if (regno & 0x8000) {
						GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(sz));
						nn = sz/sizeOfWord;
					}
				}
				else {
					//ap->preg = regno & 0x7fff;
					GenerateDiadic(op_mov,0,makereg(regno & 0x7fff), ap);
					if (regno & 0x8000) {
						GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(sizeOfWord));
						nn = 1;
					}
				}
			}
			else {
				if (cpu.SupportsPush) {
					if (ap->mode==am_imm) {	// must have been a zero
						if (ap->offset->i==0)
         					GenerateMonadic(op_push,0,makereg(0));
						else {
							ap3 = GetTempRegister();
							GenerateDiadic(op_ldi,0,ap3,ap);
							GenerateMonadic(op_push,0,ap3);
							ReleaseTempReg(ap3);
						}
						nn = 1;
					}
					else {
						if (ap->type=stddouble.GetIndex()) {
							GenerateMonadic(op_push,ap->FloatSize,ap);
							nn = sz/sizeOfWord;
						}
						else {
          					GenerateMonadic(op_push,0,ap);
							nn = 1;
						}
					}
				}
				else {
					if (ap->mode==am_imm) {	// must have been a zero
						ap3 = nullptr;
						if (ap->offset->i!=0) {
							ap3 = GetTempRegister();
							GenerateDiadic(op_ldi,0,ap3,ap);
	         				GenerateDiadic(op_sw,0,ap3,make_indexed(stkoffs,regSP));
							ReleaseTempReg(ap3);
						}
						else
         					GenerateDiadic(op_sw,0,makereg(0),make_indexed(stkoffs,regSP));
						nn = 1;
					}
					else {
						if (ap->type==stddouble.GetIndex() || ap->mode==am_fpreg) {
							GenerateDiadic(op_sf,'d',ap,make_indexed(stkoffs,regSP));
							nn = sz/sizeOfWord;
						}
						else {
          					GenerateDiadic(op_sw,0,ap,make_indexed(stkoffs,regSP));
							nn = 1;
						}
					}
				}
			}
//        }
    	break;
    }
//	ReleaseTempReg(ap);
	return nn;
}
 
// Store entire argument list onto stack
//
static int GenerateStoreArgumentList(Function *sym, ENODE *plist)
{
	TypeArray *ta = nullptr;
	int i,sum;
	OCODE *ip;
	ENODE *p;
	ENODE *pl[100];
	int nn;
 
	sum = 0;
	if (sym)
		ta = sym->GetProtoTypes();
 
	ip = peep_tail;
	GenerateTriadic(op_sub,0,makereg(regSP),makereg(regSP),make_immed(0));
	// Capture the parameter list. It is needed in the reverse order.
	for (nn = 0, p = plist; p != NULL; p = p->p[1], nn++) {
		pl[nn] = p->p[0];
	}
	for(--nn, i = 0; nn >= 0; --nn,i++ )
    {
//		sum += GeneratePushParameter(pl[nn],ta ? ta->preg[ta->length - i - 1] : 0,sum*8);
		sum += GeneratePushParameter(pl[nn],ta ? ta->preg[i] : 0,sum*8);
//		plist = plist->p[1];
    }
	if (sum==0)
		MarkRemove(ip->fwd);
	else
		ip->fwd->oper3 = make_immed(sum*sizeOfWord);
	if (ta)
		delete ta;
    return sum;
}
 
Operand *GenerateFunctionCall(ENODE *node, int flags)
{ 
	Operand *ap;
	Function *sym;
	Function *o_fn;
	SYM *s;
    int i;
	int sp = 0;
	int fsp = 0;
	int ps;
	TypeArray *ta = nullptr;
	int64_t mask,fmask;
	CSETable *csetbl;
 
	sym = nullptr;
 
	// Call the function
	if( node->p[0]->nodetype == en_nacon || node->p[0]->nodetype == en_cnacon ) {
		s = gsearch(*node->p[0]->sp);
 		sym = s->fi;
        i = 0;
		sym->SaveTemporaries(&sp, &fsp);
  /*
    	if ((sym->tp->GetBtp()->type==bt_struct || sym->tp->GetBtp()->type==bt_union) && sym->tp->GetBtp()->size > 8) {
            nn = tmpAlloc(sym->tp->GetBtp()->size) + lc_auto + round8(sym->tp->GetBtp()->size);
            GenerateMonadic(op_pea,0,make_indexed(-nn,regFP));
            i = 1;
        }
*/
		if (currentFn->HasRegisterParameters())
			sym->SaveRegisterArguments();
        i = i + GenerateStoreArgumentList(sym,node->p[1]);
//		ReleaseTempRegister(ap);
		if (sym && sym->IsInline) {
			o_fn = currentFn;
			mask = save_mask;
			fmask = fpsave_mask;
			currentFn = sym;
			ps = pass;
			sym->Gen();
			pass = ps;
			currentFn = o_fn;
			fpsave_mask = fmask;
			save_mask = mask;
		}
		else {
			GenerateMonadic(op_call,0,make_offset(node->p[0]));
			GenerateMonadic(op_bex,0,make_label(throwlab));
		}
	}
    else
    {
        i = 0;
    /*
    	if ((node->p[0]->tp->GetBtp()->type==bt_struct || node->p[0]->tp->GetBtp()->type==bt_union) && node->p[0]->tp->GetBtp()->size > 8) {
            nn = tmpAlloc(node->p[0]->tp->GetBtp()->size) + lc_auto + round8(node->p[0]->tp->GetBtp()->size);
            GenerateMonadic(op_pea,0,make_indexed(-nn,regFP));
            i = 1;
        }
     */
		ap = GenerateExpression(node->p[0],F_REG,sizeOfWord);
		if (ap->offset)
			sym = ap->offset->sym->fi;
		sym->SaveTemporaries(&sp, &fsp);
		if (currentFn->HasRegisterParameters())
			sym->SaveRegisterArguments();
        i = i + GenerateStoreArgumentList(sym,node->p[1]);
		ap->mode = am_ind;
		ap->offset = 0;
		if (sym && sym->IsInline) {
			o_fn = currentFn;
			mask = save_mask;
			fmask = fpsave_mask;
			currentFn = sym;
			ps = pass;
			sym->Gen();
			pass = ps;
			currentFn = o_fn;
			fpsave_mask = fmask;
			save_mask = mask;
		}
		else {
			GenerateMonadic(op_call,0,ap);
			GenerateMonadic(op_bex,0,make_label(throwlab));
		}
		ReleaseTempRegister(ap);
    }
	// Pop parameters off the stack
	if (i!=0) {
		if (sym) {
			if (!sym->IsPascal)
				GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(i * sizeOfWord));
		}
		else
			GenerateTriadic(op_add,0,makereg(regSP),makereg(regSP),make_immed(i * sizeOfWord));
	}
	if (currentFn->HasRegisterParameters())
		sym->RestoreRegisterArguments();
	sym->RestoreTemporaries(sp, fsp);
	/*
	if (sym) {
	   if (sym->tp->type==bt_double)
           result = GetTempFPRegister();
	   else
           result = GetTempRegister();
    }
    else {
        if (node->etype==bt_double)
            result = GetTempFPRegister();
        else
            result = GetTempRegister();
    }
	*/
	if (sym
		&& sym->sym
		&& sym->sym->tp 
		&& sym->sym->tp->GetBtp()
		&& sym->sym->tp->GetBtp()->IsFloatType()) {
		return (makefpreg(1));
	}
	if (sym 
		&& sym->sym
		&& sym->sym->tp
		&& sym->sym->tp->GetBtp()
		&& sym->sym->tp->GetBtp()->IsVectorType())
		return (makevreg(1));
	ap = makereg(1);
	if (sym 
		&& sym->sym
		&& sym->sym->tp
		&& sym->sym->tp->GetBtp()
		)
		ap->isPtr = sym->sym->tp->GetBtp()->type == bt_pointer;
	return (ap);
	/*
	else {
		if( result->preg != 1 || (flags & F_REG) == 0 ) {
			if (sym) {
				if (sym->tp->GetBtp()->type==bt_void)
					;
				else {
                    if (sym->tp->type==bt_double)
					    GenerateDiadic(op_fdmov,0,result,makefpreg(1));
                    else
					    GenerateDiadic(op_mov,0,result,makereg(1));
                }
			}
			else {
                if (node->etype==bt_double)
      				GenerateDiadic(op_fdmov,0,result,makereg(1));
                else
		     		GenerateDiadic(op_mov,0,result,makereg(1));
            }
		}
	}
    return result;
	*/
}
 
void GenLdi(Operand *ap1, Operand *ap2)
{
	GenerateDiadic(op_ldi,0,ap1,ap2);
  return;
}
 
 

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.