MIPS: MIPS32r1: Added optimization for Disto4x4 (TTransform)
Change-Id: Ieb20c5c52b964247cfe46f45f9a7415725bf7c02
This commit is contained in:
parent
2298d5f301
commit
7dad095bb4
@ -245,6 +245,166 @@ static int QuantizeBlockMIPS32(int16_t in[16], int16_t out[16],
|
||||
|
||||
#undef QUANTIZE_ONE
|
||||
|
||||
// macro for one horizontal pass in Disto4x4 (TTransform)
|
||||
// two calls of function TTransform are merged into single one
|
||||
// A..D - offsets in bytes to load from a and b buffers
|
||||
// E..H - offsets in bytes to store first results to tmp buffer
|
||||
// E1..H1 - offsets in bytes to store second results to tmp buffer
|
||||
#define HORIZONTAL_PASS(A, B, C, D, E, F, G, H, E1, F1, G1, H1) \
|
||||
"lbu %[temp0], "#A"(%[a]) \n\t" \
|
||||
"lbu %[temp1], "#B"(%[a]) \n\t" \
|
||||
"lbu %[temp2], "#C"(%[a]) \n\t" \
|
||||
"lbu %[temp3], "#D"(%[a]) \n\t" \
|
||||
"lbu %[temp4], "#A"(%[b]) \n\t" \
|
||||
"lbu %[temp5], "#B"(%[b]) \n\t" \
|
||||
"lbu %[temp6], "#C"(%[b]) \n\t" \
|
||||
"lbu %[temp7], "#D"(%[b]) \n\t" \
|
||||
"addu %[temp8], %[temp0], %[temp2] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp2] \n\t" \
|
||||
"addu %[temp2], %[temp1], %[temp3] \n\t" \
|
||||
"subu %[temp1], %[temp1], %[temp3] \n\t" \
|
||||
"addu %[temp3], %[temp4], %[temp6] \n\t" \
|
||||
"subu %[temp4], %[temp4], %[temp6] \n\t" \
|
||||
"addu %[temp6], %[temp5], %[temp7] \n\t" \
|
||||
"subu %[temp5], %[temp5], %[temp7] \n\t" \
|
||||
"addu %[temp7], %[temp8], %[temp2] \n\t" \
|
||||
"subu %[temp2], %[temp8], %[temp2] \n\t" \
|
||||
"addu %[temp8], %[temp0], %[temp1] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp1] \n\t" \
|
||||
"addu %[temp1], %[temp3], %[temp6] \n\t" \
|
||||
"subu %[temp3], %[temp3], %[temp6] \n\t" \
|
||||
"addu %[temp6], %[temp4], %[temp5] \n\t" \
|
||||
"subu %[temp4], %[temp4], %[temp5] \n\t" \
|
||||
"sw %[temp7], "#E"(%[tmp]) \n\t" \
|
||||
"sw %[temp2], "#H"(%[tmp]) \n\t" \
|
||||
"sw %[temp8], "#F"(%[tmp]) \n\t" \
|
||||
"sw %[temp0], "#G"(%[tmp]) \n\t" \
|
||||
"sw %[temp1], "#E1"(%[tmp]) \n\t" \
|
||||
"sw %[temp3], "#H1"(%[tmp]) \n\t" \
|
||||
"sw %[temp6], "#F1"(%[tmp]) \n\t" \
|
||||
"sw %[temp4], "#G1"(%[tmp]) \n\t"
|
||||
|
||||
// macro for one vertical pass in Disto4x4 (TTransform)
|
||||
// two calls of function TTransform are merged into single one
|
||||
// since only one accu is available in mips32r1 instruction set
|
||||
// first is done second call of function TTransform and after
|
||||
// that first one.
|
||||
// const int sum1 = TTransform(a, w);
|
||||
// const int sum2 = TTransform(b, w);
|
||||
// return abs(sum2 - sum1) >> 5;
|
||||
// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1)
|
||||
// A..D - offsets in bytes to load first results from tmp buffer
|
||||
// A1..D1 - offsets in bytes to load second results from tmp buffer
|
||||
// E..H - offsets in bytes to load from w buffer
|
||||
#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \
|
||||
"lw %[temp0], "#A1"(%[tmp]) \n\t" \
|
||||
"lw %[temp1], "#C1"(%[tmp]) \n\t" \
|
||||
"lw %[temp2], "#B1"(%[tmp]) \n\t" \
|
||||
"lw %[temp3], "#D1"(%[tmp]) \n\t" \
|
||||
"addu %[temp8], %[temp0], %[temp1] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp1] \n\t" \
|
||||
"addu %[temp1], %[temp2], %[temp3] \n\t" \
|
||||
"subu %[temp2], %[temp2], %[temp3] \n\t" \
|
||||
"addu %[temp3], %[temp8], %[temp1] \n\t" \
|
||||
"subu %[temp8], %[temp8], %[temp1] \n\t" \
|
||||
"addu %[temp1], %[temp0], %[temp2] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp2] \n\t" \
|
||||
"sra %[temp4], %[temp3], 31 \n\t" \
|
||||
"sra %[temp5], %[temp1], 31 \n\t" \
|
||||
"sra %[temp6], %[temp0], 31 \n\t" \
|
||||
"sra %[temp7], %[temp8], 31 \n\t" \
|
||||
"xor %[temp3], %[temp3], %[temp4] \n\t" \
|
||||
"xor %[temp1], %[temp1], %[temp5] \n\t" \
|
||||
"xor %[temp0], %[temp0], %[temp6] \n\t" \
|
||||
"xor %[temp8], %[temp8], %[temp7] \n\t" \
|
||||
"subu %[temp3], %[temp3], %[temp4] \n\t" \
|
||||
"subu %[temp1], %[temp1], %[temp5] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp6] \n\t" \
|
||||
"subu %[temp8], %[temp8], %[temp7] \n\t" \
|
||||
"lhu %[temp4], "#E"(%[w]) \n\t" \
|
||||
"lhu %[temp5], "#F"(%[w]) \n\t" \
|
||||
"lhu %[temp6], "#G"(%[w]) \n\t" \
|
||||
"lhu %[temp7], "#H"(%[w]) \n\t" \
|
||||
"madd %[temp4], %[temp3] \n\t" \
|
||||
"madd %[temp5], %[temp1] \n\t" \
|
||||
"madd %[temp6], %[temp0] \n\t" \
|
||||
"madd %[temp7], %[temp8] \n\t" \
|
||||
"lw %[temp0], "#A"(%[tmp]) \n\t" \
|
||||
"lw %[temp1], "#C"(%[tmp]) \n\t" \
|
||||
"lw %[temp2], "#B"(%[tmp]) \n\t" \
|
||||
"lw %[temp3], "#D"(%[tmp]) \n\t" \
|
||||
"addu %[temp8], %[temp0], %[temp1] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp1] \n\t" \
|
||||
"addu %[temp1], %[temp2], %[temp3] \n\t" \
|
||||
"subu %[temp2], %[temp2], %[temp3] \n\t" \
|
||||
"addu %[temp3], %[temp8], %[temp1] \n\t" \
|
||||
"subu %[temp1], %[temp8], %[temp1] \n\t" \
|
||||
"addu %[temp8], %[temp0], %[temp2] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp2] \n\t" \
|
||||
"sra %[temp2], %[temp3], 31 \n\t" \
|
||||
"xor %[temp3], %[temp3], %[temp2] \n\t" \
|
||||
"subu %[temp3], %[temp3], %[temp2] \n\t" \
|
||||
"msub %[temp4], %[temp3] \n\t" \
|
||||
"sra %[temp2], %[temp8], 31 \n\t" \
|
||||
"sra %[temp3], %[temp0], 31 \n\t" \
|
||||
"sra %[temp4], %[temp1], 31 \n\t" \
|
||||
"xor %[temp8], %[temp8], %[temp2] \n\t" \
|
||||
"xor %[temp0], %[temp0], %[temp3] \n\t" \
|
||||
"xor %[temp1], %[temp1], %[temp4] \n\t" \
|
||||
"subu %[temp8], %[temp8], %[temp2] \n\t" \
|
||||
"subu %[temp0], %[temp0], %[temp3] \n\t" \
|
||||
"subu %[temp1], %[temp1], %[temp4] \n\t" \
|
||||
"msub %[temp5], %[temp8] \n\t" \
|
||||
"msub %[temp6], %[temp0] \n\t" \
|
||||
"msub %[temp7], %[temp1] \n\t"
|
||||
|
||||
static int Disto4x4MIPS32(const uint8_t* const a, const uint8_t* const b,
|
||||
const uint16_t* const w) {
|
||||
int tmp[32];
|
||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
|
||||
|
||||
__asm__ volatile(
|
||||
HORIZONTAL_PASS( 0, 1, 2, 3, 0, 4, 8, 12, 64, 68, 72, 76)
|
||||
HORIZONTAL_PASS(16, 17, 18, 19, 16, 20, 24, 28, 80, 84, 88, 92)
|
||||
HORIZONTAL_PASS(32, 33, 34, 35, 32, 36, 40, 44, 96, 100, 104, 108)
|
||||
HORIZONTAL_PASS(48, 49, 50, 51, 48, 52, 56, 60, 112, 116, 120, 124)
|
||||
"mthi $zero \n\t"
|
||||
"mtlo $zero \n\t"
|
||||
VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24)
|
||||
VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26)
|
||||
VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28)
|
||||
VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30)
|
||||
"mflo %[temp0] \n\t"
|
||||
"sra %[temp1], %[temp0], 31 \n\t"
|
||||
"xor %[temp0], %[temp0], %[temp1] \n\t"
|
||||
"subu %[temp0], %[temp0], %[temp1] \n\t"
|
||||
"sra %[temp0], %[temp0], 5 \n\t"
|
||||
|
||||
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
|
||||
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
|
||||
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
|
||||
: [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp)
|
||||
: "memory", "hi", "lo"
|
||||
);
|
||||
|
||||
return temp0;
|
||||
}
|
||||
|
||||
#undef VERTICAL_PASS
|
||||
#undef HORIZONTAL_PASS
|
||||
|
||||
static int Disto16x16MIPS32(const uint8_t* const a, const uint8_t* const b,
|
||||
const uint16_t* const w) {
|
||||
int D = 0;
|
||||
int x, y;
|
||||
for (y = 0; y < 16 * BPS; y += 4 * BPS) {
|
||||
for (x = 0; x < 16; x += 4) {
|
||||
D += Disto4x4MIPS32(a + x + y, b + x + y, w);
|
||||
}
|
||||
}
|
||||
return D;
|
||||
}
|
||||
|
||||
#endif // WEBP_USE_MIPS32
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -256,5 +416,7 @@ void VP8EncDspInitMIPS32(void) {
|
||||
#if defined(WEBP_USE_MIPS32)
|
||||
VP8ITransform = ITransformMIPS32;
|
||||
VP8EncQuantizeBlock = QuantizeBlockMIPS32;
|
||||
VP8TDisto4x4 = Disto4x4MIPS32;
|
||||
VP8TDisto16x16 = Disto16x16MIPS32;
|
||||
#endif // WEBP_USE_MIPS32
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user