From 644ab15610472198047f17a00e0fde56ae759e3a Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 11 Jan 2009 15:13:00 +0100 Subject: [PATCH] Update of bit operations primitives in cpu_def.h for h8300-elf-gcc (GCC) 4.3.2. This version provides more functionality, full array support for char, short, int, long in clear_bit() and set_bit() functions and the constrains used for bset and bclr instructions allows compilation with newer GCC versions. The fallback "o" case is not fully correct because it allows register with displacement address but dummy "r" constrains argument forces to prepare address in register anyway and should eliminate problematic case. If internal GCC optimization is corrected "o" case should be removed. Signed-off-by: Pavel Pisa --- arch/h8300/generic/defines/cpu_def.h | 157 +++++++++++---------------- 1 file changed, 63 insertions(+), 94 deletions(-) diff --git a/arch/h8300/generic/defines/cpu_def.h b/arch/h8300/generic/defines/cpu_def.h index 68516b7..eea5555 100644 --- a/arch/h8300/generic/defines/cpu_def.h +++ b/arch/h8300/generic/defines/cpu_def.h @@ -5,8 +5,8 @@ cpu_def.h - low level CPU support for C programs atomic bit operations, interrupts and exceptions - Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz - (C) 2002 by PiKRON Ltd. http://www.pikron.com + Copyright (C) 2001-2008 by Pavel Pisa pisa@cmp.felk.cvut.cz + (C) 2002-2008 by PiKRON Ltd. http://www.pikron.com Functions names and concept inspired by Linux kernel @@ -20,122 +20,91 @@ /* atomic access routines */ /* There should be possible to generate more optimized code - if %0 changed to %U0 and "r" to "rn", but GCC nor assembler - wants to switch to aa:8 or aaaa:16 instruction version */ + if %0 changed to %R0 and "r" to "rn", but GCC nor assembler + wants to switch to aa:8 or aaaa:16 instruction version + but different versions of GCC expose different problems. + Simple "U" constrains leads to infinite loops in compiler + optimization code, constrains "o" is almost safe, it requires + offsetable address, which is register, absolute address + or register plus displacement in H8S case, the last one is + eliminated by requirement of simple register address storage + in dummy argument with "r" constrain for "o" case */ + +#define __byte_xop_bit(nr,v,__aop) \ + ({ volatile char *__pb_1 =(char*)(v); \ + unsigned short __nr_1=(nr); \ + __asm__ __volatile__ ( __aop " %w1,%R0 /*mybit*/\n" : \ + "=U,o" (*__pb_1) : "rn,rn" (__nr_1), "U,o" (*__pb_1), "rnio,r" (__pb_1)); \ + }) -#define __CONST_DATA_XOP_BIT(__nr,__pb,__aln) \ - case __nr: \ - __asm__ __volatile__ ( __aln " %1,%0 /*mybit 1*/\n" : \ - "+m" (*__pb) : "i" (__nr), "r" (__pb)); \ - break; +void __xop_bit_unsuported_pointer_type_size(void); -#define __xop_bit(nr,v,__aln) \ - ({ volatile __typeof(*v) *__pv =(__typeof(*v) *)(v); \ +#define __xop_bit(nr,v,__aop) \ + ({ __typeof(*(v)) *__pv =(v); \ unsigned short __nr=(nr); \ volatile char *__pb=(char*)__pv; \ - __pb+=sizeof(*__pv)-1-(__nr)/8; \ + unsigned short __nr_byte=__nr/8; \ + switch(sizeof(*__pv)) { \ + case 1: __pb+=__nr_byte; break; \ + case 2: __pb+=(__nr_byte^1); break; \ + case 4: __pb+=(__nr_byte^3); break; \ + case 8: __pb+=(__nr_byte^7); break; \ + default: __xop_bit_unsuported_pointer_type_size(); \ + } \ + /* __pb+=sizeof(*__pv)-1-(__nr)/8; */ \ __nr&=7; \ - if(__builtin_constant_p(__nr)) \ - switch(__nr){ \ - __CONST_DATA_XOP_BIT(0,__pb,__aln); \ - __CONST_DATA_XOP_BIT(1,__pb,__aln); \ - __CONST_DATA_XOP_BIT(2,__pb,__aln); \ - __CONST_DATA_XOP_BIT(3,__pb,__aln); \ - __CONST_DATA_XOP_BIT(4,__pb,__aln); \ - __CONST_DATA_XOP_BIT(5,__pb,__aln); \ - __CONST_DATA_XOP_BIT(6,__pb,__aln); \ - __CONST_DATA_XOP_BIT(7,__pb,__aln); \ - } \ - else \ - __asm__ __volatile__ ( __aln " %w1,%0 /*mybit 2*/\n" : \ - "+m" (*__pb) : "r" (__nr), "r" (__pb)); \ - }) + __byte_xop_bit(__nr,__pb,__aop); \ + }) #define set_bit(nr,v) (__xop_bit((nr),(v),"bset")) #define clear_bit(nr,v) (__xop_bit((nr),(v),"bclr")) -#define __xcase_xop_mask_b1(mask,v,__aln,__aconaddr,__acondata) \ +#define __xcase_xop_mask_b1(mask,v,__aop) \ ({ volatile char *__pv=(char*)(v); \ unsigned __mask=(mask); \ - if(__mask&0x0001) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (0), "0" (*__pv)); \ - if(__mask&0x0002) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (1), "0" (*__pv)); \ - if(__mask&0x0004) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (2), "0" (*__pv)); \ - if(__mask&0x0008) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (3), "0" (*__pv)); \ - if(__mask&0x0010) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (4), "0" (*__pv)); \ - if(__mask&0x0020) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (5), "0" (*__pv)); \ - if(__mask&0x0040) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (6), "0" (*__pv)); \ - if(__mask&0x0080) __asm__ __volatile__(__aln " /*mymask b1*/\n": "=U" (*__pv) : __acondata (7), "0" (*__pv)); \ + if(__mask&0x0001) __byte_xop_bit(0,__pv,__aop); \ + if(__mask&0x0002) __byte_xop_bit(1,__pv,__aop); \ + if(__mask&0x0004) __byte_xop_bit(2,__pv,__aop); \ + if(__mask&0x0008) __byte_xop_bit(3,__pv,__aop); \ + if(__mask&0x0010) __byte_xop_bit(4,__pv,__aop); \ + if(__mask&0x0020) __byte_xop_bit(5,__pv,__aop); \ + if(__mask&0x0040) __byte_xop_bit(6,__pv,__aop); \ + if(__mask&0x0080) __byte_xop_bit(7,__pv,__aop); \ }) - -#define __constant_atomic_clear_mask_b1(mask, v) \ - __xcase_xop_mask_b1(mask,v,"bclr %1,%0\n","i","n") - -#define __generic_atomic_clear_mask_b1(mask, v) \ - __xcase_xop_mask_b1(mask,v,"bclr %1,%0\n","r","n") - - #define atomic_clear_mask_b1(mask, v) \ - ( __builtin_constant_p(v) ? \ - __constant_atomic_clear_mask_b1(mask, v) : \ - __generic_atomic_clear_mask_b1(mask, v)) - -#define __constant_atomic_set_mask_b1(mask, v) \ - __xcase_xop_mask_b1(mask,v,"bset %1,%0\n","i","n") - -#define __generic_atomic_set_mask_b1(mask, v) \ - __xcase_xop_mask_b1(mask,v,"bset %1,%0\n","r","n") + __xcase_xop_mask_b1(mask,v,"bclr") #define atomic_set_mask_b1(mask, v) \ - ( __builtin_constant_p(v) ?\ - __constant_atomic_set_mask_b1(mask, v) : \ - __generic_atomic_set_mask_b1(mask, v)) - + __xcase_xop_mask_b1(mask,v,"bset") -#define __xcase_xop_mask_w1(mask,v,__aln,__aconaddr,__acondata) \ - ({ volatile char *__pv; \ +#define __xcase_xop_mask_w1(mask,v,__aop) \ + ({ volatile char *__pv = (char*)v; \ unsigned __mask=(mask); \ - if(__mask&0x0001) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (0), "0" (*__pv)); } \ - if(__mask&0x0002) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (1), "0" (*__pv)); } \ - if(__mask&0x0004) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (2), "0" (*__pv)); } \ - if(__mask&0x0008) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (3), "0" (*__pv)); } \ - if(__mask&0x0010) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (4), "0" (*__pv)); } \ - if(__mask&0x0020) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (5), "0" (*__pv)); } \ - if(__mask&0x0040) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (6), "0" (*__pv)); } \ - if(__mask&0x0080) { __pv=(char*)(v)+1; __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (7), "0" (*__pv)); } \ - if(__mask&0x0100) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (0), "0" (*__pv)); } \ - if(__mask&0x0200) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (1), "0" (*__pv)); } \ - if(__mask&0x0400) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (2), "0" (*__pv)); } \ - if(__mask&0x0800) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (3), "0" (*__pv)); } \ - if(__mask&0x1000) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (4), "0" (*__pv)); } \ - if(__mask&0x2000) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (5), "0" (*__pv)); } \ - if(__mask&0x4000) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (6), "0" (*__pv)); } \ - if(__mask&0x8000) { __pv=(char*)(v); __asm__ __volatile__(__aln " /*mymask w1*/\n": "=U" (*__pv) : __acondata (7), "0" (*__pv)); } \ + if(__mask&0x0001) __byte_xop_bit(0,__pv+1,__aop); \ + if(__mask&0x0002) __byte_xop_bit(1,__pv+1,__aop); \ + if(__mask&0x0004) __byte_xop_bit(2,__pv+1,__aop); \ + if(__mask&0x0008) __byte_xop_bit(3,__pv+1,__aop); \ + if(__mask&0x0010) __byte_xop_bit(4,__pv+1,__aop); \ + if(__mask&0x0020) __byte_xop_bit(5,__pv+1,__aop); \ + if(__mask&0x0040) __byte_xop_bit(6,__pv+1,__aop); \ + if(__mask&0x0080) __byte_xop_bit(7,__pv+1,__aop); \ + if(__mask&0x0100) __byte_xop_bit(0,__pv+0,__aop); \ + if(__mask&0x0200) __byte_xop_bit(1,__pv+0,__aop); \ + if(__mask&0x0400) __byte_xop_bit(2,__pv+0,__aop); \ + if(__mask&0x0800) __byte_xop_bit(3,__pv+0,__aop); \ + if(__mask&0x1000) __byte_xop_bit(4,__pv+0,__aop); \ + if(__mask&0x2000) __byte_xop_bit(5,__pv+0,__aop); \ + if(__mask&0x4000) __byte_xop_bit(6,__pv+0,__aop); \ + if(__mask&0x8000) __byte_xop_bit(7,__pv+0,__aop); \ }) -#define __constant_atomic_clear_mask_w1(mask, v) \ - __xcase_xop_mask_w1(mask,v,"bclr %1,%0\n","i","n") - -#define __generic_atomic_clear_mask_w1(mask, v) \ - __xcase_xop_mask_w1(mask,v,"bclr %1,%0\n","r","n") - - #define atomic_clear_mask_w1(mask, v) \ - ( __builtin_constant_p(v) ? \ - __constant_atomic_clear_mask_w1(mask, v) : \ - __generic_atomic_clear_mask_w1(mask, v)) - -#define __constant_atomic_set_mask_w1(mask, v) \ - __xcase_xop_mask_w1(mask,v,"bset %1,%0\n","i","n") - -#define __generic_atomic_set_mask_w1(mask, v) \ - __xcase_xop_mask_w1(mask,v,"bset %1,%0\n","r","nP") + __xcase_xop_mask_w1(mask,v,"bclr") #define atomic_set_mask_w1(mask, v) \ - ( __builtin_constant_p(v) ?\ - __constant_atomic_set_mask_w1(mask, v) : \ - __generic_atomic_set_mask_w1(mask, v)) + __xcase_xop_mask_w1(mask,v,"bset") /* -- 2.39.2