Sida 1 av 1

avr-gcc - bit-operation tar 3 instruktioner

Postat: 29 oktober 2008, 20:17:59
av bearing
Märkte när jag lade till följande kod att binärfilen blev 10(!) bytes större. Detta borde väl ta endast en instruktion?

Kod: Markera allt

UCSR0B |= (1<<TXEN0);
lst-filen visar följande:

Kod: Markera allt

    UCSR0B |= (1<<TXEN0);
    1ada:	80 91 c1 00 	lds	r24, 0x00C1
    1ade:	88 60       	ori	r24, 0x08	; 8
    1ae0:	80 93 c1 00 	sts	0x00C1, r24
Finns det något annat sätta att skriva C-koden på så att avr-gcc förstår att den endast ska använda instruktionen som sätter en enskild bit?

Postat: 29 oktober 2008, 21:04:00
av bearing
Hmm, det verkar som att det här registret är placerat på olika ställen i olika AVR-er.

Jag använder ATMega88:

Kod: Markera allt

iomx8.h:591:	#define UCSR0B  _SFR_MEM8 (0xC1)
I en annan AVR:

Kod: Markera allt

ATMega8. iom8.h:74:	#define UCSRB	_SFR_IO8(0x0A)
Jag är inte så insatt i instruktionsuppsättningen, men jag antar att detta betyder att bit-operationen inte går att utföra mot "MEM8"-register, fast mot "IO8"-register.

Postat: 30 oktober 2008, 01:31:19
av sodjan
Om du tittar på bit-instruktionerna så ser du att adressen i själva
instruktionen (som pekar mot aktuellt register) har en begränsad
adressarea. Det gör att bit-instruktioner (t.ex, det finns även andra)
inte fungerar mot alla register, vilka vet man bara om man kollar
upp respektive registers adress. Atmel har exempel (i assembler)
där man använder macron som väljer olika instruktioner beroende på
registrets adress.

Om det är så att vissa register är flyttade mellan olika modeller så
att de hamnar på den ena sidan om gränsen eller den andra, så
behövs dessa macron för att göra koden flyttbar mellan dom.

Om detta har med MEM8/IO8 att göra (eller vad det är) vet jag dock inte...

Postat: 30 oktober 2008, 05:51:40
av bearing
Aha, då förstår jag. Ja, det är klart att de inte har möjlighet att lägga så stora adresser där om det ska vara möjligt att skapa många instruktioner.

Hittade en kommentar om det här i databladet, samt avr-lib definitionen av makrona.

Kod: Markera allt

2. I/O Registers within the address range 0x00 - 0x1F are directly bit-accessible using the SBI and CBI instructions. In these
registers, the value of single bits can be checked by using the SBIS and SBIC instructions.
...
4. When using the I/O specific commands IN and OUT, the I/O addresses 0x00 - 0x3F must be used. When addressing I/O
Registers as data space using LD and ST instructions, 0x20 must be added to these addresses. The ATmega48/88/168 is a complex
microcontroller with more peripheral units than can be supported within the 64 location reserved in Opcode for the IN
and OUT instructions. For the Extended I/O space from 0x60 - 0xFF in SRAM, only the ST/STS/STD and LD/LDS/LDD
instructions can be used.

Kod: Markera allt

#ifndef __SFR_OFFSET
/* Define as 0 before including this file for compatibility with old asm
   sources that don't subtract __SFR_OFFSET from symbolic I/O addresses.  */
#define __SFR_OFFSET 0x20
#endif

#if (__SFR_OFFSET != 0) && (__SFR_OFFSET != 0x20)
#error "__SFR_OFFSET must be 0 or 0x20"
#endif

#define _SFR_MEM8(mem_addr) (mem_addr)
#define _SFR_MEM16(mem_addr) (mem_addr)
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
#define _SFR_IO16(io_addr) ((io_addr) + __SFR_OFFSET)

Postat: 30 oktober 2008, 12:42:19
av sodjan
Växtvärk, kan man väl säga.
Antagligen hade den ursprungliga AVR arkitekturen inte mer
än 64 I/O registers så då var det inget problem...