binutils-esp32ulp icon indicating copy to clipboard operation
binutils-esp32ulp copied to clipboard

Incorrect relative address error

Open Mucka opened this issue 7 years ago • 2 comments

Apperance of an error: coprocessor.ulp.pS:276: Error: rel too far BFD_JUMPR_STEP do not depend on relative position of instructions but for some reason on absolute position of instruction. Above error appears in my code:

jumpr quit, 256, ge
halt
quit: wake

when those lines are very far away e.g.

 276 ???? 00010182 	    jumpr quit, 256, ge
 277 ???? 000000B0 	    halt
 278              	quit:
 279 ???? 01000090 	    wake

but won't appear if those lines are at the beginning of code. The problem also affects jumps instruction.

EDIT: I have found that if label which i selected to jump into is going to be over 0x0200 address in resultant code, such error appears, so I can generate code:

 186 01f8 00000040 	    nop
 187              	test1:
 188 01fc 00010182 	    jumpr test1, 256, ge
 189              	test2:
 190 0200 00000040 	    nop

when i try to jump to test1, but only when I try to jump into test2 I get:

coprocessor.ulp.pS: Assembler messages:
coprocessor.ulp.pS:188: Error: rel too far BFD_JUMPR_STEP
 186 ???? 00000040 	    nop
 187              	test1:
 188 ???? 00010182 	    jumpr test2, 256, ge
 189              	test2:
 190 ???? 00000040 	    nop

the error is thrown by function md_apply_fix in file gas/config/tc-esp32ulp.c, but the condition checked there seems legit:

	case BFD_RELOC_ESP32ULP_JUMPR_STEP:
		if ((value > 0x1FF) || (value < -0x1ff))
			as_bad_where(fixP->fx_file, fixP->fx_line, _("rel too far BFD_JUMPR_STEP"));

because it assume (i hope) that value is relative offset of jump, but for some reason in this case it is not, and it happened to be absolute offset of jump, I am not sure from where this function is called, because I am not so familiar with binutils source code.

Mucka avatar Aug 30 '17 17:08 Mucka

Hi Mucka!

To solve the problem you have two ways:

  1. You can just define the jump label as a global label, like:
    .global quit
    jumpr quit, 256, ge
    halt
    quit: wake

  1. You can just remove the lines that check the value. The relative shift will be calculated in next functions, and here are useless. The value here is an absolute address of the label, if the label is local. Just remove the lines that you have found.
if ((value > 0x1FF) || (value < -0x1ff))
			as_bad_where(fixP->fx_file, fixP->fx_line, _("rel too far BFD_JUMPR_STEP"));

Thank you very much!

Dmitry

dmitry1945 avatar Oct 10 '17 08:10 dmitry1945

I suspect this is a related presentation of the same bug. Trying to compile assembler for the ULP a small jumps results in a error that the relative jump is too far. Here is a code snippet:

	.global measurea
measurea:
	/* measure and add value to accumulator */
	adc r1, 0, adc_channel_a + 1
	add r0, r0, r1
	/* increment loop counter and check exit condition */
	stage_inc 1 
	jumps measurea, adc_oversampling_factor, lt // Apparently a jump too far?!

It is very nearly a direct copy from one of the ulp-adc examples, but I haven't done any assembler since Z80A days so maybe I'm missing something obvious! I made measurea global in the hope it would help, it didn't.

adc.ulp.S:25: Error: rel too far BFD_JUMPS_THRESH

(BTW the "line numbers" the compiler reports are very difficult to track back to lines in the source- is there any trick to help with this?, thanks!)

ed-french avatar May 11 '20 21:05 ed-french