[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] PATCH: fix ctype linker errors
From: |
Stefano Fedrigo |
Subject: |
Re: [avr-libc-dev] PATCH: fix ctype linker errors |
Date: |
Mon, 04 Apr 2005 18:42:26 +0200 |
User-agent: |
Mozilla Thunderbird 1.0.2 (X11/20050324) |
Dmitry K. wrote:
>>ctype.S contains several functions that end up in different sections.
>>All them branch to __cty_isfalse and __cty_istrue, which resides in yet
>>another section. Thus there is no guarantee that all sections are
>>allocated next to each other within the limit of relative branch
>>instructions.
>
> ...
>
>>The best fix I could come up with consists in copying the
>>three-instruction sequence into each section. Is there a better solution?
>
> There is, for example:
>
> TEXT_SEG(ctype, isdigit)
> FUNCTION(isdigit)
> GLOBAL(isdigit)
> TST rHigh
> BRNE __ctype_isfalse
> CPI rLow,'0'
> BRLT __ctype_isfalse
> CPI rLow,'9'+1
> BRGE __ctype_isfalse
> RET ; '0' <= rLow <= '9' (!= 0!!)
> in to:
> ...
> cpse rHigh, r1
> 1: rjmp __ctype_isfalse
> CPI rLow,'0'
> BRLT 1b
> CPI rLow,'9'+1
> BRGE 1b
> RET ; '0' <= rLow <= '9' (!= 0!!)
I didn't see that all the code in the file resides in the same section
(.progmem.ctype). However the range of branch instructions is only 128
words. I improved my patch keeping the __ctype_is_false section and
using RJMP to jump to it (4 Kwords range), without duplication of the
__ctype_is_false code in each function.
I tested the new code with an atmega128. The patch is attached.
Which value should the function iscntrl() return for input between 128
and 255? Currently returns true: is this correct?
GLOBAL(iscntrl)
TST rHigh
BRNE __ctype_isfalse
CPI rLow,0x7F
BREQ __ctype_istrue
CPI rLow,0x1F+1
BRGE __ctype_isfalse
SER rLow ; 0 is cntrl, too! -> return true
RET
If not, the last BRGE should be a BRSH.
Can I submit this patch on Savannah?
--
// Stefano Fedrigo - Develer S.r.l., R&D dept.
\X/ http://www.develer.com
diff -Nru avr-libc-1.2.2.orig/libc/stdlib/ctype.S
avr-libc-1.2.2/libc/stdlib/ctype.S
--- avr-libc-1.2.2.orig/libc/stdlib/ctype.S 2005-03-24 22:25:38.000000000
+0100
+++ avr-libc-1.2.2/libc/stdlib/ctype.S 2005-03-29 19:48:37.000000000 +0200
@@ -75,8 +75,8 @@
FUNCTION(isascii)
GLOBAL(isascii)
- TST rHigh
- BRNE __ctype_isfalse
+ CPSE rHigh,__zero_reg__
+ RJMP _U(__ctype_isfalse)
COM rLow
ANDI rLow, 0x80
RET
@@ -101,13 +101,15 @@
FUNCTION(isalnum)
GLOBAL(isalnum)
- TST rHigh
- BRNE __ctype_isfalse
+ CPSE rHigh,__zero_reg__
+ RJMP _U(__ctype_isfalse)
PUSH rLow ; save, destroyed by isdigit returning 0
RCALL _U(isdigit)
TST rLow
POP rLow
- BRNE __ctype_istrue
+ BREQ 1f
+ RET ; true
+1:
RJMP _U(isalpha)
ENDFUNC
@@ -133,19 +135,20 @@
FUNCTION(isupper)
GLOBAL(isupper)
- ;TST rHigh
- ;BRNE __ctype_isfalse ; checked by _islower later on
+ ;CPSE rHigh,__zero_reg__
+ ;RJMP _U(__ctype_isfalse) ; checked by _islower later on
SBRC rLow,5 ; if bit 5 is set it is no upper
- RJMP __ctype_isfalse ; bit 5 is clear, so if isalpha is true it
is an upper
+ RJMP _U(__ctype_isfalse) ; bit 5 is clear, so if isalpha is
true it is an upper
GLOBAL(isalpha)
ORI rLow,0x20 ; make a lower out of an upper (all others
are changed but do not get alpha)
GLOBAL(islower)
- TST rHigh
- BRNE __ctype_isfalse
+ CPSE rHigh,__zero_reg__
+1:
+ RJMP _U(__ctype_isfalse)
CPI rLow,'a'
- BRLT __ctype_isfalse
+ BRLT 1b
CPI rLow,'z'+1
- BRGE __ctype_isfalse
+ BRGE 1b
RET ; 'a' <= rLow <= 'z' (!= 0!!, Z=0)
ENDFUNC
@@ -158,13 +161,13 @@
FUNCTION(isdigit)
GLOBAL(isdigit)
- TST rHigh
- BRNE __ctype_isfalse
- CPI rLow,'0'
- BRLT __ctype_isfalse
- CPI rLow,'9'+1
- BRGE __ctype_isfalse
- RET ; '0' <= rLow <= '9' (!= 0!!)
+ CPSE rHigh,__zero_reg__
+1:
+ RJMP _U(__ctype_isfalse)
+ SUBI rLow,'0'
+ SUBI rLow,10
+ BRSH 1b
+ RET ; rLow: -10..-1
ENDFUNC
#endif
@@ -181,8 +184,10 @@
CPI rLow,'a'
BRLT _isxdigit00
CPI rLow,'f'+1
- BRGE __ctype_isfalse
+ BRGE 1f
RET ; 'a' <= rLow <= 'f' (!= 0!!)
+1:
+ RJMP _U(__ctype_isfalse)
_isxdigit00:
MOV rLow,__tmp_reg__
RJMP _U(isdigit)
@@ -197,13 +202,15 @@
FUNCTION(iscntrl)
GLOBAL(iscntrl)
- TST rHigh
- BRNE __ctype_isfalse
+ CPSE rHigh,__zero_reg__
+1:
+ RJMP _U(__ctype_isfalse)
CPI rLow,0x7F
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x1F+1
- BRGE __ctype_isfalse
+ BRGE 1b
SER rLow ; 0 is cntrl, too! -> return true
+2:
RET
ENDFUNC
@@ -217,15 +224,17 @@
GLOBAL(isgraph)
CPI rLow,' '
- BREQ __ctype_isfalse
+ BREQ 1f
GLOBAL(isprint)
TST rHigh
- BRNE __ctype_isfalse
+ BRNE 1f
CPI rLow,' '
- BRLT __ctype_isfalse
+ BRLT 1f
CPI rLow,0x7E+1
- BRGE __ctype_isfalse ; ' ' <= rLow <= 0x7E (!= 0!!)
+ BRGE 1f ; ' ' <= rLow <= 0x7E (!= 0!!)
RET
+1:
+ RJMP _U(__ctype_isfalse)
ENDFUNC
#endif
@@ -237,20 +246,22 @@
FUNCTION(isspace)
GLOBAL(isspace)
- TST rHigh
- BRNE __ctype_isfalse
+ CPSE rHigh,__zero_reg__
+1:
+ RJMP _U(__ctype_isfalse)
CPI rLow,' ' ; blank
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x0A ;'\n' ; line feed
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x0C ;'\f' ; form feed
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x0D ;'\r' ; carriage return
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x09 ;'\t' ; tab
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x0B ;'\v' ; vertical tab
- BRNE __ctype_isfalse
+ BRNE 1b
+2:
RET
ENDFUNC
@@ -268,12 +279,13 @@
BREQ _ispunct00 ; true : CPI rLow,0x7E+1 -> NE, rLow
unchanged
RCALL _U(isspace)
- TST rLow
- BRNE __ctype_isfalse
+ CPSE rLow,__zero_reg__
+1:
+ RJMP _U(__ctype_isfalse)
mov rLow, __tmp_reg__ ; **changed**
RCALL _U(isalnum)
TST rLow
- BRNE __ctype_isfalse
+ BRNE 1b
SER rLow
_ispunct00:
RET
@@ -288,14 +300,16 @@
FUNCTION(isblank)
GLOBAL(isblank)
- TST rHigh
- BRNE __ctype_isfalse
+ CPSE rHigh,__zero_reg__
+1:
+ RJMP _U(__ctype_isfalse)
CPI rLow,' ' ; blank
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x09 ;'\t' ; tab
- BREQ __ctype_istrue
+ BREQ 2f
CPI rLow,0x0B ;'\v' ; vertical tab
- BRNE __ctype_isfalse
+ BRNE 1b
+2:
RET
ENDFUNC
- Re: [avr-libc-dev] PATCH: fix ctype linker errors,
Stefano Fedrigo <=