relax and .lss files

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess I may be the last one to have spotted this but is everyone else aware that when you use -Wl,-relax the .lss file can no longer be used. I was looking at the intermediate .s files and the .loc directives inserted to support the debugging; for any particular block the line numbers there agreed with the line numbers of the relevant source lines but the actual source annotation produced with avr-objdump -S leads to wrong source lines being shown. Switching off -relax fixes this. I guess that the .loc's are used at the stage that CALLs are produced with the assumption they will create 4 bytes of output and then the relaxation happens and reduces 4 bytes to 2 so the actual offsets into the disassembly change but nothing has corrected the symbolic debug info to account for this. The affect is cumulative so source line annotation gets further and further away from the relevant opcodes the further into the file you get.

It's just a little irritating when a bootloader builds to 2020 bytes with relax but about 2200 without and the bootloader section is 2048 bytes! I guess I just have to live with the consequences.

Relax, don't do it, when you want to go to it!

EDIT: how embarrassing, so I AM the last person to spot this - I even read this thread: https://www.avrfreaks.net/index.p...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't even need to go and submit a bug report:

http://sourceware.org/bugzilla/s...

But, honestly, who cares? The amateur switches off -relax, the pro needs no stinkin' intermingled source... :-)

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff,

could you please post a simple example to reproduce the problem?

Thanks,

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well I guess the source of this shows it:

http://spaces.atmel.com/gf/proje...

as it's exactly that I'm trying to debug (after fleshing out the FAT16 support to also do FAT32) but I'll try to isolate things to something a little simpler. The key thing is to have plenty of CALLs so my nested UART debug routines were what really showed it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This has been fixed in binutils trunk back in July. The next release of binutils (2.23) should work ok, I guess, unless the AVR target specific code doesn't set the right flags for the fix to take effect. See http://sourceware-org.1504.n7.nabble.com/Commit-Patch-GAS-Fix-DWARF-line-number-generation-for-target-that-use-linker-relaxation-td149558.html

Regards

Senthil

 

blog | website

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

This has been fixed in binutils trunk back in July.

Oh good news. Just need to wait for a packaged build that picks it up then. Wonder when Atmel plans the next release of "toolchain"?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

This has been fixed in binutils trunk back in July.

Oh good news. Just need to wait for a packaged build that picks it up then. Wonder when Atmel plans the next release of "toolchain"?

Ah, forget about Atmel.
You are brave enough to go for the real stuff! :-)

http://sourceforge.net/projects/...

c:\tmp\>avr-ld --version
GNU ld (GNU Binutils) 2.23.51.20120813

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jan,

In SVN I added the files necessary to build at the command line which, because of the AS6 heritage, is in the .\Debug\ subdirectory. If you "make all" there you will get a pfboot.lss. That one works. If you now edit the Makefile and add -Wl,-relax to the line that does the link and rebuild you see the error.

To show that I've done both and attach two .lss files. The one with "r" in the name is the relaxed one. Note how line 196 in the working listing has this:

		// ready to read the root directory sector
		disk_read(RootDir);
    38da:	c7 01       	movw	r24, r14
    38dc:	b6 01       	movw	r22, r12
    38de:	0e 94 8a 1d 	call	0x3b14	; 0x3b14 

That annotation has occurred right above the call that it's describing. Now look at the relaxed one around line 195 and you find:

    38cc:	c7 01       	movw	r24, r14
    38ce:	b6 01       	movw	r22, r12
    38d0:	12 d1       	rcall	.+548    	; 0x3af6 
    38d2:	80 e6       	ldi	r24, 0x60	; 96
    38d4:	90 e0       	ldi	r25, 0x00	; 0
		SecPerClus = Buff[BPB_SecPerClus];
    38d6:	9b 83       	std	Y+3, r25	; 0x03
    38d8:	8a 83       	std	Y+2, r24	; 0x02
		// ready to read the root directory sector
		disk_read(RootDir);
    38da:	8c 01       	movw	r16, r24

So the two MOVW's and the RCALL are there. It's just the line that's supposed to annotate this doesn't actually appear until about 8 lines later.

Clearly the annotation information says "show this at 38da" whether the code it's related to is at that address or not.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OMG, who wrote that makefile generator crap? It's horrible.

Whoever was that, he should be told that the "all" target is customarily put as the first, for a good reason. And that there are customary variables such as CC, again for good reason. And that "cmd.exe" is not a shell.

Not to mention the hardcoded directories (folders for him) and file names.

Phoey.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff,

can't you simply use -mshort-calls to get the rcall/rjmp right from the beginning?

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

can't you simply use -mshort-calls

As that's the first I've heard of it only time will tell ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-mshort-calls is deprecated and removed from the sources. See the release notes.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh that was a short lived hope then :-(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hrm, that could explain why debugging is a bit of a crap-shoot some times in Atmel Studio and the old AVR Studio, linker relaxations are enabled in the project templates by default.

I'll notify the Toolchain team about this to try to make sure they upgrade binutils as soon as possible to fix it.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'll notify the Toolchain team about this to try to make sure they upgrade binutils as soon as possible to fix it.

Woo hoo.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is this purely limited to the listing files, or does it impact the debug data encoded in the ELF file too?

As for toolchain and AS6 issues, I encourage you to report all problems and enhancements in the tracker; the tools team read them and at the very least put them into our internal tracker, even if they aren't prioritized to be fixed immediately.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:
Is this purely limited to the listing files, or does it impact the debug data encoded in the ELF file too?
.lss file is generated from .elf

abcminiuser wrote:
As for toolchain and AS6 issues, I encourage you to report all problems and enhancements in the tracker; the tools team read them and at the very least put them into our internal tracker, even if they aren't prioritized to be fixed immediately.

- Dean :twisted:

As for binutils issues, they should be reported to the binutils tracker, which is doubtlessly followed by the Atmel team regularly.

Open source is about contibuting back, and Atmel is no exemption.

Please feel free to forward my comments above about the generated makefile, verbatim, to whom it may concern.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:
Hrm, that could explain why debugging is a bit of a crap-shoot some times in Atmel Studio and the old AVR Studio,
Reportedly, the new toolchain's debug information can shred the debugger, i.e. it crashes without -gstrict-dwarf or with -gdwarf-4.

avr-gcc 4.7 and newer use a new prologue layout so that any debugger that scans instruction sequences in order to detect prologue instead of using debug information is likely to produce unexpected results.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

saaadhu wrote:
This has been fixed in binutils trunk back in July. The next release of binutils (2.23) should work ok, I guess, unless the AVR target specific code doesn't set the right flags for the fix to take effect. See http://sourceware-org.1504.n7.nabble.com/Commit-Patch-GAS-Fix-DWARF-line-number-generation-for-target-that-use-linker-relaxation-td149558.html
I'd say, it's the "unless" case. I tried Johann's 4.7.2 build which as I posted above uses a 2.23 ld/as of August, but the problem persists.

Johann, could you comment on this, please?

Jan

PS. Attached my take on the makefile. I am not proud of it; it would make more sense to start off mfile's template than trying to salvage what AS6 spit out.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so enough is enough. I got seriously cheesed trying to debug -relax code with source annotation that did not match so I remembered the point I made above and that is that the .s file does have the right .loc values in it. So I've written a little utility that will take a .s sequence such as (fairly illegible):

.L21:
	.loc 1 243 0
	ldd r30,Y+1	 ; , %sfp
	sub r24,r30	 ;  lba,
	sbc r25,__zero_reg__	 ;  lba
	sbc r26,__zero_reg__	 ;  lba
	sbc r27,__zero_reg__	 ;  lba
.LVL56:
	.loc 1 244 0
	mov r18,r5	 ;  SecPerClus, SecPerClus
	ldi r19,lo8(0)	 ;  SecPerClus,
	ldi r20,lo8(0)	 ;  SecPerClus,
	ldi r21,hi8(0)	 ;  SecPerClus,
	movw r22,r24	 ; , lba
	movw r24,r26	 ; , lba
	call __mulsi3
	movw r8,r22	 ;  lba,
	movw r10,r24	 ;  lba,
.LVL57:
	.loc 1 245 0
	add r8,r12	 ;  lba, RootDir
	adc r9,r13	 ;  lba, RootDir
	adc r10,r14	 ;  lba, RootDir
	adc r11,r15	 ;  lba, RootDir

and turn it into:

.L21:
//==> 					lba = firstclust - fat_offset;
	ldd r30,Y+1	 ; , %sfp
	sub r24,r30	 ;  lba,
	sbc r25,__zero_reg__	 ;  lba
	sbc r26,__zero_reg__	 ;  lba
	sbc r27,__zero_reg__	 ;  lba
.LVL56:
//==> 					lba *= SecPerClus;
	mov r18,r5	 ;  SecPerClus, SecPerClus
	ldi r19,lo8(0)	 ;  SecPerClus,
	ldi r20,lo8(0)	 ;  SecPerClus,
	ldi r21,hi8(0)	 ;  SecPerClus,
	movw r22,r24	 ; , lba
	movw r24,r26	 ; , lba
	call __mulsi3
	movw r8,r22	 ;  lba,
	movw r10,r24	 ;  lba,
.LVL57:
//==> 					lba += RootDir;
	add r8,r12	 ;  lba, RootDir
	adc r9,r13	 ;  lba, RootDir
	adc r10,r14	 ;  lba, RootDir
	adc r11,r15	 ;  lba, RootDir

This might be useful for anyone who studies .s files. However I'm afraid it's real "sledgehammer to crack a nut" stuff:

#include 
#include 
#include 

FILE * fin;
FILE * fout;
FILE *fsrc;

char fname[256];
char buff[1024];
char files[100][100];

int main(int argc, char *argv[])
{
	char * p;
	int fnum, lnum;
	if (argc != 2) {
		printf("usage: avr-source filename.s\n");
		return 1;
	}
	fin = fopen(argv[1], "rt");
	strcpy(fname, argv[1]);
	strcat(fname, ".source");
	fout = fopen(fname, "wt");
	do {
		fgets(buff, 1024, fin);
		if (p=strstr(buff, ".file ")) {
			int i;
			p += strlen(".file ");
			fnum = atoi(p);
			p=strchr(p, '"');
			p++;
			i = 0;
			while(*p != '"') {
				files[fnum][i++] = *p++;
			}
			printf("file %u = %s\n", fnum, files[fnum]);
		}
	}while (!feof(fin));
	rewind(fin);
	do {
		fgets(buff, 1024, fin);
		if (strstr(buff, ".file ")) {
			continue; // no point putting the .file's we've used in output
		}
		if (p=strstr(buff, ".loc")) {
			p += strlen(".loc ");
			fnum = atoi(p);
			while(*p != ' ') p++;
			p++;
			lnum = atoi(p);
			//sprintf(buff, "replace with file %s, line %u\n", files[fnum], lnum);
			fsrc = fopen(files[fnum], "rt");
			if (!fsrc) {
				sprintf(buff, "!!SOURCE FILE MISSING!!: %s line %u\n", files[fnum], lnum);
			}
			else {
				// waste the lines to get to the right place
				while (lnum) {
					fgets(buff, 1024, fsrc);
					lnum--;
				}
				fclose(fsrc);
				fprintf(fout, "//==> ");
			}
			fputs(buff, fout);
		}
		else {
			fputs(buff, fout);
		}
	}while (!feof(fin));

	fclose(fin);
	fclose(fout);
	return 0;
}

You use "avr-source main.s" and it produces main.s.source.

Al I do is open the file and first read through for any line with ".file N pathname" and store this to the Nth entry of a filename array (I allow for 100 files with 100 characters per path - completely arbitrary). I then rewind() the input file and this time scan through it again mostly just doing an fgets() from the input and a straight fputs() to the output. When I hit ".file N" lines I ignore them as there's no point them being in the output any more and when I find ".loc N M" lines I open file N (stored in the array) then read M lines (the "sledgehammer!") to get to the right place and output that line to the output file instead of the previous .loc. Oh and I prepend "\\==> " to try and signify it is C source annotation.

And that's it really. When debugging -relax code I think I'll just turn -g off all together and then match the AS6 disassembler to the .s.source file.

Source (almost as in this post) and .exe (built with Pelles in Windows) attached in .zip.

BTW if you move the .s from the place where it was built then any relative paths in .loc won't work so run this in place. Otherwise you'll see a lot of "!!SOURCE FILE MISSING!!:" lines!

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK things move fast in this game. I have improved it (attached) and think it works best with -g2 in AS6. A source file looks like this:

#include "uart.h"

void UART_init(void) {
	UCSRB = (1 << TXEN);
	UBRRL = 5; // 38400 @ 3.6864MHz
}

void UART_put(uint8_t c) {
	while (!(UCSRA & (1 << UDRE)));
	UDR = c;
}

void UART_puts(const char * str) {
	while (*str) {
		UART_put(*str++);
	}
}

void UART_newline(void){
	UART_put('\r');
	UART_put('\n');
}

void UART_putnibble(uint8_t c) {
	if (c < 10) {
		UART_put('0' + c);
	}
	else {
		UART_put('A' + c - 10);
	}
}

void UART_puthex(uint8_t c) {
	UART_putnibble(c >> 4);
	UART_putnibble(c & 0x0F);
}

void UART_puthex16(uint16_t n) {
	UART_puthex(n >> 8);
	UART_puthex(n & 0xFF);
}

void UART_putsP(const char * str, uint16_t n) {
	while (pgm_read_byte(str) != 0) {
		UART_put(pgm_read_byte(str++));
	}
	UART_puthex16(n);
	UART_newline();
}

void UART_dumpsector(uint8_t * Buff) {
	for (uint16_t i=0; i<512; i++) {
		if ((i % 16) == 0) {
			UART_put(' ');
			for(uint16_t j=(i -16); j<=i; j++) {
				UART_put(((Buff[j]>=(uint8_t)32) && (Buff[j]<(uint8_t)127)) ? Buff[j] : '.');
			}
			UART_newline();
		}
		UART_puthex(Buff[i]);
		UART_put(' ');
	}
	UART_newline();
}

The "normal" .s looks like this:

	.file	"uart.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__CCP__ = 0x34
__tmp_reg__ = 0
__zero_reg__ = 1
	.global __do_copy_data
	.global __do_clear_bss
	.text
.Ltext0:
	.cfi_sections	.debug_frame
	.section	.text.UART_init,"ax",@progbits
.global	UART_init
	.type	UART_init, @function
UART_init:
.LFB1:
	.file 1 "../uart/uart.c"
	.loc 1 3 0
	.cfi_startproc
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	.loc 1 4 0
	ldi r24,lo8(8)
	out 42-32,r24
	.loc 1 5 0
	ldi r24,lo8(5)
	out 41-32,r24
/* epilogue start */
	.loc 1 6 0
	ret
	.cfi_endproc
.LFE1:
	.size	UART_init, .-UART_init
	.section	.text.UART_put,"ax",@progbits
.global	UART_put
	.type	UART_put, @function
UART_put:
.LFB2:
	.loc 1 8 0
	.cfi_startproc
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
.LVL0:
.L3:
	.loc 1 9 0 discriminator 1
	sbis 43-32,5
	rjmp .L3
	.loc 1 10 0
	out 44-32,r24
/* epilogue start */
	.loc 1 11 0
	ret
	.cfi_endproc
.LFE2:
	.size	UART_put, .-UART_put
	.section	.text.UART_puts,"ax",@progbits
.global	UART_puts
	.type	UART_puts, @function
UART_puts:
.LFB3:
	.loc 1 13 0
	.cfi_startproc
.LVL1:
	push r28
.LCFI0:
	.cfi_def_cfa_offset 3
	.cfi_offset 28, -2
	push r29
.LCFI1:
	.cfi_def_cfa_offset 4
	.cfi_offset 29, -3
/* prologue: function */
/* frame size = 0 */
/* stack size = 2 */
.L__stack_usage = 2
	movw r28,r24
	.loc 1 14 0
	ld r24,Y
.LVL2:
	tst r24
	breq .L5
	.loc 1 13 0
	adiw r28,1
.LVL3:
.L7:
	.loc 1 15 0
	call UART_put
	.loc 1 14 0
	ld r24,Y+
	tst r24
	brne .L7
.L5:
/* epilogue start */
	.loc 1 17 0
	pop r29
	pop r28
	ret
	.cfi_endproc
.LFE3:
	.size	UART_puts, .-UART_puts
	.section	.text.UART_newline,"ax",@progbits
.global	UART_newline
	.type	UART_newline, @function
UART_newline:
.LFB4:
	.loc 1 19 0
	.cfi_startproc
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	.loc 1 20 0
	ldi r24,lo8(13)
	call UART_put
	.loc 1 21 0
	ldi r24,lo8(10)
	call UART_put
/* epilogue start */
	.loc 1 22 0
	ret
	.cfi_endproc
.LFE4:
	.size	UART_newline, .-UART_newline
	.section	.text.UART_putnibble,"ax",@progbits
.global	UART_putnibble
	.type	UART_putnibble, @function
UART_putnibble:
.LFB5:
	.loc 1 24 0
	.cfi_startproc
.LVL4:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	.loc 1 25 0
	cpi r24,lo8(10)
	brsh .L11
	.loc 1 26 0
	subi r24,lo8(-(48))
.LVL5:
	call UART_put
.LVL6:
	ret
.LVL7:
.L11:
	.loc 1 29 0
	subi r24,lo8(-(55))
.LVL8:
	call UART_put
.LVL9:
	ret
	.cfi_endproc
.LFE5:
	.size	UART_putnibble, .-UART_putnibble
	.section	.text.UART_puthex,"ax",@progbits
.global	UART_puthex
	.type	UART_puthex, @function
UART_puthex:
.LFB6:
	.loc 1 33 0
	.cfi_startproc
.LVL10:
	push r28
.LCFI2:
	.cfi_def_cfa_offset 3
	.cfi_offset 28, -2
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
	mov r28,r24
	.loc 1 34 0
	swap r24
.LVL11:
	andi r24,lo8(15)
	call UART_putnibble
	.loc 1 35 0
	mov r24,r28
	andi r24,lo8(15)
	call UART_putnibble
/* epilogue start */
	.loc 1 36 0
	pop r28
.LVL12:
	ret
	.cfi_endproc
.LFE6:
	.size	UART_puthex, .-UART_puthex
	.section	.text.UART_puthex16,"ax",@progbits
.global	UART_puthex16
	.type	UART_puthex16, @function
UART_puthex16:
.LFB7:
	.loc 1 38 0
	.cfi_startproc
.LVL13:
	push r28
.LCFI3:
	.cfi_def_cfa_offset 3
	.cfi_offset 28, -2
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
	mov r28,r24
	.loc 1 39 0
	mov r24,r25
.LVL14:
	call UART_puthex
	.loc 1 40 0
	mov r24,r28
	call UART_puthex
/* epilogue start */
	.loc 1 41 0
	pop r28
	ret
	.cfi_endproc
.LFE7:
	.size	UART_puthex16, .-UART_puthex16
	.section	.text.UART_putsP,"ax",@progbits
.global	UART_putsP
	.type	UART_putsP, @function
UART_putsP:
.LFB8:
	.loc 1 43 0
	.cfi_startproc
.LVL15:
	push r16
.LCFI4:
	.cfi_def_cfa_offset 3
	.cfi_offset 16, -2
	push r17
.LCFI5:
	.cfi_def_cfa_offset 4
	.cfi_offset 17, -3
	push r28
.LCFI6:
	.cfi_def_cfa_offset 5
	.cfi_offset 28, -4
	push r29
.LCFI7:
	.cfi_def_cfa_offset 6
	.cfi_offset 29, -5
/* prologue: function */
/* frame size = 0 */
/* stack size = 4 */
.L__stack_usage = 4
	movw r28,r24
	movw r16,r22
.LVL16:
.LBB2:
	.loc 1 44 0
	movw r30,r28
/* #APP */
 ;  44 "../uart/uart.c" 1
	lpm r18, Z
	
 ;  0 "" 2
.LVL17:
/* #NOAPP */
.LBE2:
	tst r18
	breq .L16
.LVL18:
.L18:
.LBB3:
	.loc 1 45 0
	adiw r28,1
.LVL19:
	movw r30,r24
/* #APP */
 ;  45 "../uart/uart.c" 1
	lpm r24, Z
	
 ;  0 "" 2
.LVL20:
/* #NOAPP */
.LBE3:
	call UART_put
.LVL21:
.LBB4:
	.loc 1 44 0
	movw r24,r28
.LVL22:
	movw r30,r28
/* #APP */
 ;  44 "../uart/uart.c" 1
	lpm r18, Z
	
 ;  0 "" 2
.LVL23:
/* #NOAPP */
.LBE4:
	tst r18
	brne .L18
.LVL24:
.L16:
	.loc 1 47 0
	movw r24,r16
.LVL25:
	call UART_puthex16
.LVL26:
	.loc 1 48 0
	call UART_newline
/* epilogue start */
	.loc 1 49 0
	pop r29
	pop r28
.LVL27:
	pop r17
	pop r16
.LVL28:
	ret
	.cfi_endproc
.LFE8:
	.size	UART_putsP, .-UART_putsP
	.section	.text.UART_dumpsector,"ax",@progbits
.global	UART_dumpsector
	.type	UART_dumpsector, @function
UART_dumpsector:
.LFB9:
	.loc 1 51 0
	.cfi_startproc
.LVL29:
	push r10
.LCFI8:
	.cfi_def_cfa_offset 3
	.cfi_offset 10, -2
	push r11
.LCFI9:
	.cfi_def_cfa_offset 4
	.cfi_offset 11, -3
	push r12
.LCFI10:
	.cfi_def_cfa_offset 5
	.cfi_offset 12, -4
	push r13
.LCFI11:
	.cfi_def_cfa_offset 6
	.cfi_offset 13, -5
	push r14
.LCFI12:
	.cfi_def_cfa_offset 7
	.cfi_offset 14, -6
	push r15
.LCFI13:
	.cfi_def_cfa_offset 8
	.cfi_offset 15, -7
	push r16
.LCFI14:
	.cfi_def_cfa_offset 9
	.cfi_offset 16, -8
	push r17
.LCFI15:
	.cfi_def_cfa_offset 10
	.cfi_offset 17, -9
	push r28
.LCFI16:
	.cfi_def_cfa_offset 11
	.cfi_offset 28, -10
	push r29
.LCFI17:
	.cfi_def_cfa_offset 12
	.cfi_offset 29, -11
/* prologue: function */
/* frame size = 0 */
/* stack size = 10 */
.L__stack_usage = 10
.LVL30:
.LBB5:
.LBB6:
	.loc 1 56 0
	mov r18,r24
	mov r19,r25
.LBE6:
.LBE5:
	.loc 1 51 0
	movw r12,r18
	.loc 1 52 0
	clr r14
	clr r15
.LBB9:
.LBB7:
	.loc 1 51 0
	mov __tmp_reg__,r31
	ldi r31,lo8(-16)
	mov r10,r31
	ldi r31,hi8(-16)
	mov r11,r31
	mov r31,__tmp_reg__
	add r10,r18
	adc r11,r19
.LVL31:
.L25:
.LBE7:
	.loc 1 53 0
	movw r24,r14
	andi r24,lo8(15)
	andi r25,hi8(15)
	sbiw r24,0
	brne .L21
	.loc 1 54 0
	ldi r24,lo8(32)
	call UART_put
.LBB8:
	.loc 1 55 0
	movw r28,r14
	sbiw r28,16
.LVL32:
	cp r14,r28
	cpc r15,r29
	brlo .L22
	.loc 1 51 0
	movw r16,r10
	add r16,r14
	adc r17,r15
.L24:
	.loc 1 56 0
	movw r30,r16
	ld r24,Z+
	movw r16,r30
	mov r25,r24
	subi r25,lo8(-(-32))
	cpi r25,lo8(95)
	brlo .L23
	ldi r24,lo8(46)
.L23:
	.loc 1 56 0 is_stmt 0 discriminator 3
	call UART_put
	.loc 1 55 0 is_stmt 1 discriminator 3
	adiw r28,1
.LVL33:
	cp r14,r28
	cpc r15,r29
	brsh .L24
.L22:
.LBE8:
	.loc 1 58 0
	call UART_newline
.LVL34:
.L21:
	.loc 1 60 0
	movw r30,r12
	ld r24,Z+
	movw r12,r30
	call UART_puthex
	.loc 1 61 0
	ldi r24,lo8(32)
	call UART_put
	.loc 1 52 0
	sec
	adc r14,__zero_reg__
	adc r15,__zero_reg__
.LVL35:
	ldi r31,lo8(512)
	cp r14,r31
	ldi r31,hi8(512)
	cpc r15,r31
	brne .L25
.LBE9:
	.loc 1 63 0
	call UART_newline
/* epilogue start */
	.loc 1 64 0
	pop r29
	pop r28
	pop r17
	pop r16
	pop r15
	pop r14
.LVL36:
	pop r13
	pop r12
	pop r11
	pop r10
	ret
	.cfi_endproc
.LFE9:
	.size	UART_dumpsector, .-UART_dumpsector
	.text
.Letext0:
	.file 2 "c:\\program files\\atmel\\atmel studio 6.0\\extensions\\atmel\\avrgcc\\3.4.0.65\\avrtoolchain\\bin\\../lib/gcc/avr/4.6.2/../../../../avr/include/stdint.h"
	.section	.debug_info,"",@progbits

and processed it looks like:

	.file	"uart.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__CCP__ = 0x34
__tmp_reg__ = 0
__zero_reg__ = 1
	.global __do_copy_data
	.global __do_clear_bss
	.text
.Ltext0:

	.section	.text.UART_init,"ax",@progbits
.global	UART_init
	.type	UART_init, @function
UART_init:
//==> void UART_init(void) {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==> 	UCSRB = (1 << TXEN);
	ldi r24,lo8(8)
	out 42-32,r24
//==> 	UBRRL = 5; // 38400 @ 3.6864MHz
	ldi r24,lo8(5)
	out 41-32,r24
/* epilogue start */
//==> }
	ret
	.size	UART_init, .-UART_init

	.section	.text.UART_put,"ax",@progbits
.global	UART_put
	.type	UART_put, @function
UART_put:
//==> void UART_put(uint8_t c) {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
.L3:
//==> 	while (!(UCSRA & (1 << UDRE)));
	sbis 43-32,5
	rjmp .L3
//==> 	UDR = c;
	out 44-32,r24
/* epilogue start */
//==> }
	ret
	.size	UART_put, .-UART_put

	.section	.text.UART_puts,"ax",@progbits
.global	UART_puts
	.type	UART_puts, @function
UART_puts:
//==> void UART_puts(const char * str) {
	push r28
	push r29
/* prologue: function */
/* frame size = 0 */
/* stack size = 2 */
.L__stack_usage = 2
	movw r28,r24
//==> 	while (*str) {
	ld r24,Y
	tst r24
	breq .L5
//==> void UART_puts(const char * str) {
	adiw r28,1
.L7:
//==> 		UART_put(*str++);
	call UART_put
//==> 	while (*str) {
	ld r24,Y+
	tst r24
	brne .L7
.L5:
/* epilogue start */
//==> }
	pop r29
	pop r28
	ret
	.size	UART_puts, .-UART_puts

	.section	.text.UART_newline,"ax",@progbits
.global	UART_newline
	.type	UART_newline, @function
UART_newline:
//==> void UART_newline(void){
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==> 	UART_put('\r');
	ldi r24,lo8(13)
	call UART_put
//==> 	UART_put('\n');
	ldi r24,lo8(10)
	call UART_put
/* epilogue start */
//==> }
	ret
	.size	UART_newline, .-UART_newline

	.section	.text.UART_putnibble,"ax",@progbits
.global	UART_putnibble
	.type	UART_putnibble, @function
UART_putnibble:
//==> void UART_putnibble(uint8_t c) {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==> 	if (c < 10) {
	cpi r24,lo8(10)
	brsh .L11
//==> 		UART_put('0' + c);
	subi r24,lo8(-(48))
	call UART_put
	ret
.L11:
//==> 		UART_put('A' + c - 10);
	subi r24,lo8(-(55))
	call UART_put
	ret
	.size	UART_putnibble, .-UART_putnibble

	.section	.text.UART_puthex,"ax",@progbits
.global	UART_puthex
	.type	UART_puthex, @function
UART_puthex:
//==> void UART_puthex(uint8_t c) {
	push r28
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
	mov r28,r24
//==> 	UART_putnibble(c >> 4);
	swap r24
	andi r24,lo8(15)
	call UART_putnibble
//==> 	UART_putnibble(c & 0x0F);
	mov r24,r28
	andi r24,lo8(15)
	call UART_putnibble
/* epilogue start */
//==> }
	pop r28
	ret
	.size	UART_puthex, .-UART_puthex

	.section	.text.UART_puthex16,"ax",@progbits
.global	UART_puthex16
	.type	UART_puthex16, @function
UART_puthex16:
//==> void UART_puthex16(uint16_t n) {
	push r28
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
	mov r28,r24
//==> 	UART_puthex(n >> 8);
	mov r24,r25
	call UART_puthex
//==> 	UART_puthex(n & 0xFF);
	mov r24,r28
	call UART_puthex
/* epilogue start */
//==> }
	pop r28
	ret
	.size	UART_puthex16, .-UART_puthex16

	.section	.text.UART_putsP,"ax",@progbits
.global	UART_putsP
	.type	UART_putsP, @function
UART_putsP:
//==> void UART_putsP(const char * str, uint16_t n) {
	push r16
	push r17
	push r28
	push r29
/* prologue: function */
/* frame size = 0 */
/* stack size = 4 */
.L__stack_usage = 4
	movw r28,r24
	movw r16,r22
//==> 	while (pgm_read_byte(str) != 0) {
	movw r30,r28
/* #APP */
 ;  44 "../uart/uart.c" 1
	lpm r18, Z
	
 ;  0 "" 2
/* #NOAPP */
	tst r18
	breq .L16
.L18:
//==> 		UART_put(pgm_read_byte(str++));
	adiw r28,1
	movw r30,r24
/* #APP */
 ;  45 "../uart/uart.c" 1
	lpm r24, Z
	
 ;  0 "" 2
/* #NOAPP */
	call UART_put
//==> 	while (pgm_read_byte(str) != 0) {
	movw r24,r28
	movw r30,r28
/* #APP */
 ;  44 "../uart/uart.c" 1
	lpm r18, Z
	
 ;  0 "" 2
/* #NOAPP */
	tst r18
	brne .L18
.L16:
//==> 	UART_puthex16(n);
	movw r24,r16
	call UART_puthex16
//==> 	UART_newline();
	call UART_newline
/* epilogue start */
//==> }
	pop r29
	pop r28
	pop r17
	pop r16
	ret
	.size	UART_putsP, .-UART_putsP

	.section	.text.UART_dumpsector,"ax",@progbits
.global	UART_dumpsector
	.type	UART_dumpsector, @function
UART_dumpsector:
//==> void UART_dumpsector(uint8_t * Buff) {
	push r10
	push r11
	push r12
	push r13
	push r14
	push r15
	push r16
	push r17
	push r28
	push r29
/* prologue: function */
/* frame size = 0 */
/* stack size = 10 */
.L__stack_usage = 10
//==> 				UART_put(((Buff[j]>=(uint8_t)32) && (Buff[j]<(uint8_t)127)) ? Buff[j] : '.');
	mov r18,r24
	mov r19,r25
//==> void UART_dumpsector(uint8_t * Buff) {
	movw r12,r18
//==> 	for (uint16_t i=0; i<512; i++) {
	clr r14
	clr r15
//==> void UART_dumpsector(uint8_t * Buff) {
	mov __tmp_reg__,r31
	ldi r31,lo8(-16)
	mov r10,r31
	ldi r31,hi8(-16)
	mov r11,r31
	mov r31,__tmp_reg__
	add r10,r18
	adc r11,r19
.L25:
//==> 		if ((i % 16) == 0) {
	movw r24,r14
	andi r24,lo8(15)
	andi r25,hi8(15)
	sbiw r24,0
	brne .L21
//==> 			UART_put(' ');
	ldi r24,lo8(32)
	call UART_put
//==> 			for(uint16_t j=(i -16); j<=i; j++) {
	movw r28,r14
	sbiw r28,16
	cp r14,r28
	cpc r15,r29
	brlo .L22
//==> void UART_dumpsector(uint8_t * Buff) {
	movw r16,r10
	add r16,r14
	adc r17,r15
.L24:
//==> 				UART_put(((Buff[j]>=(uint8_t)32) && (Buff[j]<(uint8_t)127)) ? Buff[j] : '.');
	movw r30,r16
	ld r24,Z+
	movw r16,r30
	mov r25,r24
	subi r25,lo8(-(-32))
	cpi r25,lo8(95)
	brlo .L23
	ldi r24,lo8(46)
.L23:
//==> 				UART_put(((Buff[j]>=(uint8_t)32) && (Buff[j]<(uint8_t)127)) ? Buff[j] : '.');
	call UART_put
//==> 			for(uint16_t j=(i -16); j<=i; j++) {
	adiw r28,1
	cp r14,r28
	cpc r15,r29
	brsh .L24
.L22:
//==> 			UART_newline();
	call UART_newline
.L21:
//==> 		UART_puthex(Buff[i]);
	movw r30,r12
	ld r24,Z+
	movw r12,r30
	call UART_puthex
//==> 		UART_put(' ');
	ldi r24,lo8(32)
	call UART_put
//==> 	for (uint16_t i=0; i<512; i++) {
	sec
	adc r14,__zero_reg__
	adc r15,__zero_reg__
	ldi r31,lo8(512)
	cp r14,r31
	ldi r31,hi8(512)
	cpc r15,r31
	brne .L25
//==> 	UART_newline();
	call UART_newline
/* epilogue start */
//==> }	pop r29
	pop r28
	pop r17
	pop r16
	pop r15
	pop r14
	pop r13
	pop r12
	pop r11
	pop r10
	ret
	.size	UART_dumpsector, .-UART_dumpsector
	.text
.Letext0:

Wish I'd done this a long time ago.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh and I finally found and fixed the bug I'd been hunting as a result of this. It all came down to my ill-advised use of "naked" on main(). I just liberally added stack frame variables and everything appeared to work but this was only because the use of all the variables was all so localised they were cached into registers EXCEPT for one flag (FAT16/FAT32) I added more recently which I set near the very top of the program but did not use until very near the end. So much happened in between that the code couldn't hold it in a register but put it on the stack frame at Y+1. That is the the stack frame I'd told it not to create - doh! :oops:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not use OS_main then?

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I spoke too soon. While the fix in trunk does the right thing by generating relocations (thus postponing the PC offset until link time), the AVR target specific code undoes all that work and writes the PC offset as known at assembly time into the object file.

I'm working on a patch that fixes the target specific code. I'll post it here once I'm done.

Regards

Senthil

 

blog | website