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);
 | |
| }
 |