1/* 2 * Loongson SIMD optimized h264chroma 3 * 4 * Copyright (c) 2018 Loongson Technology Corporation Limited 5 * Contributed by Shiyou Yin <yinshiyou-hf@loongson.cn> 6 * Gu Xiwei(guxiwei-hf@loongson.cn) 7 * 8 * This file is part of FFmpeg. 9 * 10 * FFmpeg is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * FFmpeg is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with FFmpeg; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25#ifndef AVCODEC_MIPS_CABAC_H 26#define AVCODEC_MIPS_CABAC_H 27 28#include "libavutil/attributes.h" 29#include "libavcodec/cabac.h" 30#include "libavutil/mips/mmiutils.h" 31#include "config.h" 32 33#define get_cabac_inline get_cabac_inline_mips 34static av_always_inline int get_cabac_inline_mips(CABACContext *c, 35 uint8_t * const state){ 36 mips_reg tmp0, tmp1, tmp2, bit; 37 38 __asm__ volatile ( 39 "lbu %[bit], 0(%[state]) \n\t" 40 "and %[tmp0], %[c_range], 0xC0 \n\t" 41 PTR_SLL "%[tmp0], %[tmp0], 0x01 \n\t" 42 PTR_ADDU "%[tmp0], %[tmp0], %[tables] \n\t" 43 PTR_ADDU "%[tmp0], %[tmp0], %[bit] \n\t" 44 /* tmp1: RangeLPS */ 45 "lbu %[tmp1], %[lps_off](%[tmp0]) \n\t" 46 47 PTR_SUBU "%[c_range], %[c_range], %[tmp1] \n\t" 48 PTR_SLL "%[tmp0], %[c_range], 0x11 \n\t" 49 "slt %[tmp2], %[tmp0], %[c_low] \n\t" 50 "beqz %[tmp2], 1f \n\t" 51 "move %[c_range], %[tmp1] \n\t" 52 "not %[bit], %[bit] \n\t" 53 PTR_SUBU "%[c_low], %[c_low], %[tmp0] \n\t" 54 55 "1: \n\t" 56 /* tmp1: *state */ 57 PTR_ADDU "%[tmp0], %[tables], %[bit] \n\t" 58 "lbu %[tmp1], %[mlps_off](%[tmp0]) \n\t" 59 /* tmp2: lps_mask */ 60 PTR_ADDU "%[tmp0], %[tables], %[c_range] \n\t" 61 "lbu %[tmp2], %[norm_off](%[tmp0]) \n\t" 62 63 "sb %[tmp1], 0(%[state]) \n\t" 64 "and %[bit], %[bit], 0x01 \n\t" 65 PTR_SLL "%[c_range], %[c_range], %[tmp2] \n\t" 66 PTR_SLL "%[c_low], %[c_low], %[tmp2] \n\t" 67 68 "and %[tmp1], %[c_low], %[cabac_mask] \n\t" 69 "bnez %[tmp1], 1f \n\t" 70 PTR_ADDIU "%[tmp0], %[c_low], -0X01 \n\t" 71 "xor %[tmp0], %[c_low], %[tmp0] \n\t" 72 PTR_SRA "%[tmp0], %[tmp0], 0x0f \n\t" 73 PTR_ADDU "%[tmp0], %[tmp0], %[tables] \n\t" 74 /* tmp2: ff_h264_norm_shift[x >> (CABAC_BITS - 1)] */ 75 "lbu %[tmp2], %[norm_off](%[tmp0]) \n\t" 76#if HAVE_BIGENDIAN 77 "lhu %[tmp0], 0(%[c_bytestream]) \n\t" 78#else 79 "lhu %[tmp0], 0(%[c_bytestream]) \n\t" 80#if HAVE_MIPS32R2 || HAVE_MIPS64R2 81 "wsbh %[tmp0], %[tmp0] \n\t" 82#else 83 "and %[tmp1], %[tmp0], 0xff00ff00 \n\t" 84 "srl %[tmp1], %[tmp1], 8 \n\t" 85 "and %[tmp0], %[tmp0], 0x00ff00ff \n\t" 86 "sll %[tmp0], %[tmp0], 8 \n\t" 87 "or %[tmp0], %[tmp0], %[tmp1] \n\t" 88#endif 89#endif 90 PTR_SLL "%[tmp0], %[tmp0], 0x01 \n\t" 91 PTR_SUBU "%[tmp0], %[tmp0], %[cabac_mask] \n\t" 92 93 "li %[tmp1], 0x07 \n\t" 94 PTR_SUBU "%[tmp1], %[tmp1], %[tmp2] \n\t" 95 PTR_SLL "%[tmp0], %[tmp0], %[tmp1] \n\t" 96 PTR_ADDU "%[c_low], %[c_low], %[tmp0] \n\t" 97 98#if UNCHECKED_BITSTREAM_READER 99 PTR_ADDIU "%[c_bytestream], %[c_bytestream], 0x02 \n\t" 100#else 101 "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" 102 PTR_ADDIU "%[tmp2], %[c_bytestream], 0x02 \n\t" 103 "movn %[c_bytestream], %[tmp2], %[tmp0] \n\t" 104#endif 105 "1: \n\t" 106 : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), 107 [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), 108 [c_bytestream]"+&r"(c->bytestream) 109 : [state]"r"(state), [tables]"r"(ff_h264_cabac_tables), 110#if !UNCHECKED_BITSTREAM_READER 111 [c_bytestream_end]"r"(c->bytestream_end), 112#endif 113 [lps_off]"i"(H264_LPS_RANGE_OFFSET), 114 [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), 115 [norm_off]"i"(H264_NORM_SHIFT_OFFSET), 116 [cabac_mask]"r"(CABAC_MASK) 117 : "memory" 118 ); 119 120 return bit; 121} 122 123#define get_cabac_bypass get_cabac_bypass_mips 124static av_always_inline int get_cabac_bypass_mips(CABACContext *c) 125{ 126 mips_reg tmp0, tmp1; 127 int res = 0; 128 __asm__ volatile( 129 PTR_SLL "%[c_low], %[c_low], 0x01 \n\t" 130 "and %[tmp0], %[c_low], %[cabac_mask] \n\t" 131 "bnez %[tmp0], 1f \n\t" 132#if HAVE_BIGENDIAN 133 "lhu %[tmp1], 0(%[c_bytestream]) \n\t" 134#else 135 "lhu %[tmp1], 0(%[c_bytestream]) \n\t" 136#if HAVE_MIPS32R2 || HAVE_MIPS64R2 137 "wsbh %[tmp1], %[tmp1] \n\t" 138#else 139 "and %[tmp0], %[tmp1], 0xff00ff00 \n\t" 140 "srl %[tmp0], %[tmp0], 8 \n\t" 141 "and %[tmp1], %[tmp1], 0x00ff00ff \n\t" 142 "sll %[tmp1], %[tmp1], 8 \n\t" 143 "or %[tmp1], %[tmp1], %[tmp0] \n\t" 144#endif 145#endif 146 PTR_SLL "%[tmp1], %[tmp1], 0x01 \n\t" 147 PTR_SUBU "%[tmp1], %[tmp1], %[cabac_mask] \n\t" 148 PTR_ADDU "%[c_low], %[c_low], %[tmp1] \n\t" 149#if UNCHECKED_BITSTREAM_READER 150 PTR_ADDIU "%[c_bytestream], %[c_bytestream], 0x02 \n\t" 151#else 152 "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" 153 PTR_ADDIU "%[tmp1], %[c_bytestream], 0x02 \n\t" 154 "movn %[c_bytestream], %[tmp1], %[tmp0] \n\t" 155#endif 156 "1: \n\t" 157 PTR_SLL "%[tmp1], %[c_range], 0x11 \n\t" 158 "slt %[tmp0], %[c_low], %[tmp1] \n\t" 159 PTR_SUBU "%[tmp1], %[c_low], %[tmp1] \n\t" 160 "movz %[res], %[one], %[tmp0] \n\t" 161 "movz %[c_low], %[tmp1], %[tmp0] \n\t" 162 : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [res]"+&r"(res), 163 [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), 164 [c_bytestream]"+&r"(c->bytestream) 165 : [cabac_mask]"r"(CABAC_MASK), 166#if !UNCHECKED_BITSTREAM_READER 167 [c_bytestream_end]"r"(c->bytestream_end), 168#endif 169 [one]"r"(0x01) 170 : "memory" 171 ); 172 return res; 173} 174 175#define get_cabac_bypass_sign get_cabac_bypass_sign_mips 176static av_always_inline int get_cabac_bypass_sign_mips(CABACContext *c, int val) 177{ 178 mips_reg tmp0, tmp1; 179 int res = val; 180 __asm__ volatile( 181 PTR_SLL "%[c_low], %[c_low], 0x01 \n\t" 182 "and %[tmp0], %[c_low], %[cabac_mask] \n\t" 183 "bnez %[tmp0], 1f \n\t" 184#if HAVE_BIGENDIAN 185 "lhu %[tmp1], 0(%[c_bytestream]) \n\t" 186#else 187 "lhu %[tmp1], 0(%[c_bytestream]) \n\t" 188#if HAVE_MIPS32R2 || HAVE_MIPS64R2 189 "wsbh %[tmp1], %[tmp1] \n\t" 190#else 191 "and %[tmp0], %[tmp1], 0xff00ff00 \n\t" 192 "srl %[tmp0], %[tmp0], 8 \n\t" 193 "and %[tmp1], %[tmp1], 0x00ff00ff \n\t" 194 "sll %[tmp1], %[tmp1], 8 \n\t" 195 "or %[tmp1], %[tmp1], %[tmp0] \n\t" 196#endif 197#endif 198 PTR_SLL "%[tmp1], %[tmp1], 0x01 \n\t" 199 PTR_SUBU "%[tmp1], %[tmp1], %[cabac_mask] \n\t" 200 PTR_ADDU "%[c_low], %[c_low], %[tmp1] \n\t" 201#if UNCHECKED_BITSTREAM_READER 202 PTR_ADDIU "%[c_bytestream], %[c_bytestream], 0x02 \n\t" 203#else 204 "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" 205 PTR_ADDIU "%[tmp1], %[c_bytestream], 0x02 \n\t" 206 "movn %[c_bytestream], %[tmp1], %[tmp0] \n\t" 207#endif 208 "1: \n\t" 209 PTR_SLL "%[tmp1], %[c_range], 0x11 \n\t" 210 "slt %[tmp0], %[c_low], %[tmp1] \n\t" 211 PTR_SUBU "%[tmp1], %[c_low], %[tmp1] \n\t" 212 "movz %[c_low], %[tmp1], %[tmp0] \n\t" 213 PTR_SUBU "%[tmp1], %[zero], %[res] \n\t" 214 "movn %[res], %[tmp1], %[tmp0] \n\t" 215 : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [res]"+&r"(res), 216 [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), 217 [c_bytestream]"+&r"(c->bytestream) 218 : [cabac_mask]"r"(CABAC_MASK), 219#if !UNCHECKED_BITSTREAM_READER 220 [c_bytestream_end]"r"(c->bytestream_end), 221#endif 222 [zero]"r"(0x0) 223 : "memory" 224 ); 225 226 return res; 227} 228#endif /* AVCODEC_MIPS_CABAC_H */ 229