This relocation is specific to PowerPC. @davidgiven suggested the name RELOPPC_LIS in https://github.com/davidgiven/ack/pull/52#issuecomment-279856501 Reindent the list in h/out.h and util/led/ack.out.5 because RELOLIS_PPC is a long name. I use spaces and no tabs because the tabs looked bad in the manual page.
		
			
				
	
	
		
			75 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			75 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
static int hl_token;
 | 
						|
static expr_t hl_expr;
 | 
						|
 | 
						|
void no_hl(void) {
 | 
						|
	hl_token = 0;
 | 
						|
}
 | 
						|
 | 
						|
word_t eval_hl(expr_t* expr, int token)
 | 
						|
{
 | 
						|
	word_t val = expr->val;
 | 
						|
	uint16_t hi = val >> 16;
 | 
						|
	uint16_t lo = val & 0xffff;
 | 
						|
 | 
						|
	hl_token = token;
 | 
						|
	hl_expr = *expr;
 | 
						|
 | 
						|
	switch (token) {
 | 
						|
	case OP_HI:  /* hi16[expr] */
 | 
						|
		return hi;
 | 
						|
	case OP_HA:  /* ha16[expr]*/
 | 
						|
		/*
 | 
						|
		 * If the low half will be treated as a signed value,
 | 
						|
		 * then values greater than 0x7fff will cause the high
 | 
						|
		 * half to have 1 subtracted from it; so we apply an
 | 
						|
		 * adjustment here.
 | 
						|
		 */
 | 
						|
		if (lo > 0x7fff)
 | 
						|
			hi++;
 | 
						|
		return hi;
 | 
						|
	case OP_LO:  /* lo16[expr] */
 | 
						|
		return lo;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void emit_hl(word_t in)
 | 
						|
{
 | 
						|
	word_t reg;
 | 
						|
	int type;
 | 
						|
 | 
						|
	switch (hl_token) {
 | 
						|
	case OP_HI:  /* hi16[expr] */
 | 
						|
	case OP_HA:  /* ha16[expr] */
 | 
						|
		if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) {
 | 
						|
			/*
 | 
						|
			 * RELOPPC_LIS only works with lis _, _ (same
 | 
						|
			 * as addis _, r0, _).  Check if instruction
 | 
						|
			 * isn't addis or register RA isn't r0.
 | 
						|
			 */
 | 
						|
			if ((in & 0xfc1f0000) != (0x3c000000))
 | 
						|
				serror("relocation only works with lis");
 | 
						|
 | 
						|
			/*
 | 
						|
			 * High bit: ha16 flag
 | 
						|
			 * Next 5 bits: register RT
 | 
						|
			 * Low 26 bits: signed offset
 | 
						|
			 */
 | 
						|
			fit(fitx(hl_expr.val, 26));
 | 
						|
			newrelo(hl_expr.typ, RELOPPC_LIS | FIXUPFLAGS);
 | 
						|
			reg = (in >> 21) & 0x1f;
 | 
						|
			in = (hl_token == OP_HA) << 31;
 | 
						|
			in |= reg << 26;
 | 
						|
			in |= hl_expr.val & 0x03ffffff;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case OP_LO:  /* lo16[expr] */
 | 
						|
		if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) {
 | 
						|
			DOTVAL += 2;
 | 
						|
			newrelo(hl_expr.typ, RELO2 | FIXUPFLAGS);
 | 
						|
			DOTVAL -= 2;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	emit4(in);
 | 
						|
}
 |