Libav
|
00001 /* 00002 * Copyright (c) 2009 Mans Rullgard <mans@mansr.com> 00003 * 00004 * This file is part of FFmpeg. 00005 * 00006 * FFmpeg is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * FFmpeg is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with FFmpeg; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #ifndef AVUTIL_AVR32_INTREADWRITE_H 00022 #define AVUTIL_AVR32_INTREADWRITE_H 00023 00024 #include <stdint.h> 00025 #include "config.h" 00026 #include "libavutil/bswap.h" 00027 00028 /* 00029 * AVR32 does not support unaligned memory accesses, except for the AP 00030 * series which suppports unaligned 32-bit loads and stores. 16-bit 00031 * and 64-bit accesses must be aligned to 16 and 32 bits, respectively. 00032 * This means we cannot use the byte-swapping load/store instructions 00033 * here. 00034 * 00035 * For 16-bit, 24-bit, and (on UC series) 32-bit loads, we instead use 00036 * the LDINS.B instruction, which gcc fails to utilise with the 00037 * generic code. GCC also fails to use plain LD.W and ST.W even for 00038 * AP processors, so we override the generic code. The 64-bit 00039 * versions are improved by using our optimised 32-bit functions. 00040 */ 00041 00042 #define AV_RL16 AV_RL16 00043 static av_always_inline uint16_t AV_RL16(const void *p) 00044 { 00045 uint16_t v; 00046 __asm__ ("ld.ub %0, %1 \n\t" 00047 "ldins.b %0:l, %2 \n\t" 00048 : "=&r"(v) 00049 : "m"(*(const uint8_t*)p), "RKs12"(*((const uint8_t*)p+1))); 00050 return v; 00051 } 00052 00053 #define AV_RB16 AV_RB16 00054 static av_always_inline uint16_t AV_RB16(const void *p) 00055 { 00056 uint16_t v; 00057 __asm__ ("ld.ub %0, %2 \n\t" 00058 "ldins.b %0:l, %1 \n\t" 00059 : "=&r"(v) 00060 : "RKs12"(*(const uint8_t*)p), "m"(*((const uint8_t*)p+1))); 00061 return v; 00062 } 00063 00064 #define AV_RB24 AV_RB24 00065 static av_always_inline uint32_t AV_RB24(const void *p) 00066 { 00067 uint32_t v; 00068 __asm__ ("ld.ub %0, %3 \n\t" 00069 "ldins.b %0:l, %2 \n\t" 00070 "ldins.b %0:u, %1 \n\t" 00071 : "=&r"(v) 00072 : "RKs12"(* (const uint8_t*)p), 00073 "RKs12"(*((const uint8_t*)p+1)), 00074 "m" (*((const uint8_t*)p+2))); 00075 return v; 00076 } 00077 00078 #define AV_RL24 AV_RL24 00079 static av_always_inline uint32_t AV_RL24(const void *p) 00080 { 00081 uint32_t v; 00082 __asm__ ("ld.ub %0, %1 \n\t" 00083 "ldins.b %0:l, %2 \n\t" 00084 "ldins.b %0:u, %3 \n\t" 00085 : "=&r"(v) 00086 : "m" (* (const uint8_t*)p), 00087 "RKs12"(*((const uint8_t*)p+1)), 00088 "RKs12"(*((const uint8_t*)p+2))); 00089 return v; 00090 } 00091 00092 #if ARCH_AVR32_AP 00093 00094 #define AV_RB32 AV_RB32 00095 static av_always_inline uint32_t AV_RB32(const void *p) 00096 { 00097 uint32_t v; 00098 __asm__ ("ld.w %0, %1" : "=r"(v) : "m"(*(const uint32_t*)p)); 00099 return v; 00100 } 00101 00102 #define AV_WB32 AV_WB32 00103 static av_always_inline void AV_WB32(void *p, uint32_t v) 00104 { 00105 __asm__ ("st.w %0, %1" : "=m"(*(uint32_t*)p) : "r"(v)); 00106 } 00107 00108 /* These two would be defined by generic code, but we need them sooner. */ 00109 #define AV_RL32(p) bswap_32(AV_RB32(p)) 00110 #define AV_WL32(p, v) AV_WB32(p, bswap_32(v)) 00111 00112 #define AV_WB64 AV_WB64 00113 static av_always_inline void AV_WB64(void *p, uint64_t v) 00114 { 00115 union { uint64_t v; uint32_t hl[2]; } vv = { v }; 00116 AV_WB32(p, vv.hl[0]); 00117 AV_WB32((uint32_t*)p+1, vv.hl[1]); 00118 } 00119 00120 #define AV_WL64 AV_WL64 00121 static av_always_inline void AV_WL64(void *p, uint64_t v) 00122 { 00123 union { uint64_t v; uint32_t hl[2]; } vv = { v }; 00124 AV_WL32(p, vv.hl[1]); 00125 AV_WL32((uint32_t*)p+1, vv.hl[0]); 00126 } 00127 00128 #else /* ARCH_AVR32_AP */ 00129 00130 #define AV_RB32 AV_RB32 00131 static av_always_inline uint32_t AV_RB32(const void *p) 00132 { 00133 uint32_t v; 00134 __asm__ ("ld.ub %0, %4 \n\t" 00135 "ldins.b %0:l, %3 \n\t" 00136 "ldins.b %0:u, %2 \n\t" 00137 "ldins.b %0:t, %1 \n\t" 00138 : "=&r"(v) 00139 : "RKs12"(* (const uint8_t*)p), 00140 "RKs12"(*((const uint8_t*)p+1)), 00141 "RKs12"(*((const uint8_t*)p+2)), 00142 "m" (*((const uint8_t*)p+3))); 00143 return v; 00144 } 00145 00146 #define AV_RL32 AV_RL32 00147 static av_always_inline uint32_t AV_RL32(const void *p) 00148 { 00149 uint32_t v; 00150 __asm__ ("ld.ub %0, %1 \n\t" 00151 "ldins.b %0:l, %2 \n\t" 00152 "ldins.b %0:u, %3 \n\t" 00153 "ldins.b %0:t, %4 \n\t" 00154 : "=&r"(v) 00155 : "m" (* (const uint8_t*)p), 00156 "RKs12"(*((const uint8_t*)p+1)), 00157 "RKs12"(*((const uint8_t*)p+2)), 00158 "RKs12"(*((const uint8_t*)p+3))); 00159 return v; 00160 } 00161 00162 #endif /* ARCH_AVR32_AP */ 00163 00164 #define AV_RB64 AV_RB64 00165 static av_always_inline uint64_t AV_RB64(const void *p) 00166 { 00167 union { uint64_t v; uint32_t hl[2]; } v; 00168 v.hl[0] = AV_RB32(p); 00169 v.hl[1] = AV_RB32((const uint32_t*)p+1); 00170 return v.v; 00171 } 00172 00173 #define AV_RL64 AV_RL64 00174 static av_always_inline uint64_t AV_RL64(const void *p) 00175 { 00176 union { uint64_t v; uint32_t hl[2]; } v; 00177 v.hl[1] = AV_RL32(p); 00178 v.hl[0] = AV_RL32((const uint32_t*)p+1); 00179 return v.v; 00180 } 00181 00182 #endif /* AVUTIL_AVR32_INTREADWRITE_H */