249 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| branch(brtyp, link, val)
 | |
| word_t brtyp;
 | |
| word_t link;
 | |
| valu_t val;
 | |
| {
 | |
| 	valu_t offset;
 | |
| 
 | |
| 	offset = val - DOTVAL - 8;
 | |
| 	if ((offset & 0xFC000000) != 0 && (offset & 0xFC000000) != 0xFC000000){
 | |
| 		serror("offset out of range");
 | |
| 	}
 | |
| 	offset = offset>>2 & 0xFFFFFF; 
 | |
| 	emit4(brtyp|link|offset);
 | |
| 	return;
 | |
| }
 | |
| 
 | |
| data(opc, ins, val, typ)
 | |
| word_t opc, ins;
 | |
| valu_t val;
 | |
| short typ;
 | |
| {
 | |
| 	valu_t tmpval;
 | |
| 
 | |
| 	if (typ == S_REG){
 | |
| 		emit4(opc|ins|val);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	ins |= 0x02000000;
 | |
| 
 | |
| 	tmpval = val;
 | |
| 	if (typ == S_ABS){
 | |
| 		if (calcimm(&opc, &tmpval, typ)){
 | |
| 			emit4(opc|ins|tmpval);
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	tmpval = val;
 | |
| 	if (small(calcimm(&opc, &tmpval, typ),12)){
 | |
| 		emit4(opc|ins|tmpval);
 | |
| 		return;
 | |
| 	}	
 | |
| 
 | |
| 	switch (opc){
 | |
| 	case MOV:
 | |
| 		if (small((val & 0xF0000000) == 0xF0000000, 8)){
 | |
| 			emit4(0xE51F0004 | (ins & 0xF000));
 | |
| 			emit4(val);
 | |
| 			return;
 | |
| 		}
 | |
| 		if (small(1,4)){
 | |
| 			emit4(0xE51F0000 | (ins & 0xF000));
 | |
| 			emit4(0xEA000000);
 | |
| 			emit4(val);
 | |
| 			return;
 | |
| 		}
 | |
| 		DOTVAL += 16;
 | |
| 		return;
 | |
| 	case ADD:
 | |
| 		if (small((val & 0xF0000000) == 0xF0000000, 4)){
 | |
| 			emit4(0xE51F0004 | (ins & 0xF000));
 | |
| 			emit4(val);
 | |
| 			emit4(0xE2800000 | (ins&0xFF000) | (ins&0xF000)>>12);
 | |
| 			return;
 | |
| 		}
 | |
| 		emit4(0xE51F0000 | (ins & 0xF000));
 | |
| 		emit4(0xEA000000);
 | |
| 		emit4(val);
 | |
| 		emit4(0xE2800000 | (ins&0xFF000) | (ins&0xF000)>>12);
 | |
| 		return;
 | |
| 	default:
 | |
| 		if (pass == PASS_1)
 | |
| 			DOTVAL += 16;
 | |
| 		else
 | |
| 			serror("immediate value out of range");
 | |
| 		return;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| calcimm(opc,val,typ)
 | |
| word_t *opc;
 | |
| valu_t *val;
 | |
| short typ;
 | |
| {
 | |
| 	int i = 0;
 | |
| 
 | |
| 	if (typ == S_UND) return 0;
 | |
| 
 | |
| 	if ((*val & ~0xFF) == 0) return 1;
 | |
| 
 | |
| 	if ((~*val & ~0xFF) == 0){
 | |
| 		switch (*opc){
 | |
| 		case AND:
 | |
| 			*val = ~*val;
 | |
| 			*opc = BIC;
 | |
| 			return 1;
 | |
| 		case MOV:
 | |
| 			*val = ~*val;
 | |
| 			*opc = MVN;
 | |
| 			return 1;
 | |
| 		case ADC:
 | |
| 			*val = ~*val;
 | |
| 			*opc = SBC;
 | |
| 			return 1;
 | |
| 		default : 
 | |
| 			break;
 | |
| 		}
 | |
| 	}	
 | |
| 	if ((-1**val & ~0xFF) == 0 ){
 | |
| 		switch (*opc){
 | |
| 		case ADD:
 | |
| 			*val *= -1;
 | |
| 			*opc = SUB;
 | |
| 			return 1;
 | |
| 		case CMP:
 | |
| 			*val *= -1;
 | |
| 			*opc = CMN;
 | |
| 			return 1;
 | |
| 		default:
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	do{
 | |
| 		rotateleft2(&*val);
 | |
| 		i++;
 | |
| 		if((*val & ~0xFF) == 0){
 | |
| 			*val = *val|i<<8;
 | |
| 			return 1;
 | |
| 		}
 | |
| 		if ((~*val & ~0xFF) == 0){
 | |
| 			switch (*opc){
 | |
| 			case AND:
 | |
| 				*val = ~*val|i<<8;
 | |
| 				*opc = BIC;
 | |
| 				return 1;
 | |
| 			case MOV:
 | |
| 				*val = ~*val|i<<8;
 | |
| 				*opc = MVN;
 | |
| 				return 1;
 | |
| 			case ADC:
 | |
| 				*val = ~*val|i<<8;
 | |
| 				*opc = SBC;
 | |
| 				return 1;
 | |
| 			default : 
 | |
| 				break;
 | |
| 			}
 | |
| 		}	
 | |
| 	}while(i<15);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| word_t
 | |
| calcoffset(val)
 | |
| valu_t val;
 | |
| {
 | |
| 	if((val & ~0xFFF) == 0)
 | |
| 		return(val|0x00800000);
 | |
| 	val *= -1;
 | |
| 	if((val & ~0xFFF) == 0)
 | |
| 		return(val);
 | |
| 	serror("offset out of range");
 | |
| 	return(0);
 | |
| }
 | |
| 
 | |
| word_t
 | |
| calcaddress(val,typ,reg)
 | |
| valu_t val;
 | |
| short typ;
 | |
| word_t reg;
 | |
| {
 | |
| 	int tmpval;
 | |
| 
 | |
| 	if (typ == S_UND){
 | |
| 		DOTVAL += 8;
 | |
| 		return 0;
 | |
| 	}
 | |
| 	tmpval = val - DOTVAL - 8;
 | |
| 	if(small((tmpval & ~0xFFF) == 0, 8))
 | |
| 		return(val|0x008F0000);
 | |
| 	tmpval *= -1;
 | |
| 	if(small((tmpval & ~0xFFF) == 0, 8))
 | |
| 		return(val|0x000F0000);
 | |
| 	emit4(0xE51F0004 | reg << 12);
 | |
| 	emit4(val | 0xF0000000);
 | |
| 	return(reg << 16);
 | |
| }
 | |
| 
 | |
| word_t
 | |
| calcadr(reg, val, typ)
 | |
| word_t reg;
 | |
| valu_t val;
 | |
| short typ;
 | |
| {
 | |
| 	valu_t tmpval = val;
 | |
| 	int i = 0;
 | |
| 
 | |
| 	if ((val & 0xFC000000) && (typ != S_UND)){
 | |
| 		serror("address out of range");
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	if (typ != S_ABS){
 | |
| 		tmpval = val-DOTVAL-8;
 | |
| 		if (small((tmpval & ~0xFF) == 0),12){
 | |
| 			emit4(0xE2000000|ADD|0xF<<16|reg<<12|tmpval);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	
 | |
| 		tmpval *= -1;
 | |
| 		if (small((tmpval & ~0xFF) == 0), 12){
 | |
| 			emit4(0xE2000000|SUB|0xF<<16|reg<<12|tmpval);
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	data(MOV, 0xE2000000||reg<<12, val, typ);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| word_t
 | |
| calcshft(val, typ, styp)
 | |
| valu_t val;
 | |
| short typ;
 | |
| word_t styp;
 | |
| {
 | |
| 	if (typ=S_UND) return 0;
 | |
| 	if (val & ~0x1F) serror("shiftcount out of range");
 | |
| 	if (styp && !val) warning("shiftcount 0");
 | |
| 	return((val & 0x1F)<<7);
 | |
| }
 | |
| 
 | |
| rotateleft2(x)
 | |
| long *x;
 | |
| {
 | |
| 	unsigned long bits;
 | |
| 
 | |
| 	bits = *x & 0xC0000000;
 | |
| 	*x <<= 2 ;
 | |
| 	if (bits){
 | |
| 		bits >>= 30;
 | |
| 		*x |= bits;
 | |
| 	}
 | |
| 	return;
 | |
| }
 |