📄 gglassembler.cpp
字号:
} if (mask & Z_WRITE) { if (mask == Z_WRITE) { // only z-write asked, cc is meaningless ic = AL; } MOV(AL, 0, depth, reg_imm(z, LSR, 16)); STRH(ic, depth, zbase); } }}void GGLAssembler::build_iterate_z(const fragment_parts_t& parts){ const needs_t& needs = mBuilderContext.needs; if ((mDepthTest != GGL_ALWAYS) || GGL_READ_NEEDS(P_MASK_Z, needs.p)) { Scratch scratches(registerFile()); int dzdx = scratches.obtain(); CONTEXT_LOAD(dzdx, generated_vars.dzdx); // stall ADD(AL, 0, parts.z.reg, parts.z.reg, dzdx); }}void GGLAssembler::build_iterate_f(const fragment_parts_t& parts){ const needs_t& needs = mBuilderContext.needs; if (GGL_READ_NEEDS(P_FOG, needs.p)) { Scratch scratches(registerFile()); int dfdx = scratches.obtain(); int f = scratches.obtain(); CONTEXT_LOAD(f, generated_vars.f); CONTEXT_LOAD(dfdx, generated_vars.dfdx); // stall ADD(AL, 0, f, f, dfdx); CONTEXT_STORE(f, generated_vars.f); }}// ---------------------------------------------------------------------------void GGLAssembler::build_logic_op(pixel_t& pixel, Scratch& regs){ const needs_t& needs = mBuilderContext.needs; const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR; if (opcode == GGL_COPY) return; comment("logic operation"); pixel_t s(pixel); if (!(pixel.flags & CORRUPTIBLE)) { pixel.reg = regs.obtain(); pixel.flags |= CORRUPTIBLE; } pixel_t d(mDstPixel); switch(opcode) { case GGL_CLEAR: MOV(AL, 0, pixel.reg, imm(0)); break; case GGL_AND: AND(AL, 0, pixel.reg, s.reg, d.reg); break; case GGL_AND_REVERSE: BIC(AL, 0, pixel.reg, s.reg, d.reg); break; case GGL_COPY: break; case GGL_AND_INVERTED: BIC(AL, 0, pixel.reg, d.reg, s.reg); break; case GGL_NOOP: MOV(AL, 0, pixel.reg, d.reg); break; case GGL_XOR: EOR(AL, 0, pixel.reg, s.reg, d.reg); break; case GGL_OR: ORR(AL, 0, pixel.reg, s.reg, d.reg); break; case GGL_NOR: ORR(AL, 0, pixel.reg, s.reg, d.reg); MVN(AL, 0, pixel.reg, pixel.reg); break; case GGL_EQUIV: EOR(AL, 0, pixel.reg, s.reg, d.reg); MVN(AL, 0, pixel.reg, pixel.reg); break; case GGL_INVERT: MVN(AL, 0, pixel.reg, d.reg); break; case GGL_OR_REVERSE: // s | ~d == ~(~s & d) BIC(AL, 0, pixel.reg, d.reg, s.reg); MVN(AL, 0, pixel.reg, pixel.reg); break; case GGL_COPY_INVERTED: MVN(AL, 0, pixel.reg, s.reg); break; case GGL_OR_INVERTED: // ~s | d == ~(s & ~d) BIC(AL, 0, pixel.reg, s.reg, d.reg); MVN(AL, 0, pixel.reg, pixel.reg); break; case GGL_NAND: AND(AL, 0, pixel.reg, s.reg, d.reg); MVN(AL, 0, pixel.reg, pixel.reg); break; case GGL_SET: MVN(AL, 0, pixel.reg, imm(0)); break; }; }// ---------------------------------------------------------------------------static uint32_t find_bottom(uint32_t val){ uint32_t i = 0; while (!(val & (3<<i))) i+= 2; return i;}static void normalize(uint32_t& val, uint32_t& rot){ rot = 0; while (!(val&3) || (val & 0xFC000000)) { uint32_t newval; newval = val >> 2; newval |= (val&3) << 30; val = newval; rot += 2; if (rot == 32) { rot = 0; break; } }}void GGLAssembler::build_and_immediate(int d, int s, uint32_t mask, int bits){ uint32_t rot; uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1; mask &= size; if (mask == size) { if (d != s) MOV( AL, 0, d, s); return; } int negative_logic = !isValidImmediate(mask); if (negative_logic) { mask = ~mask & size; } normalize(mask, rot); if (mask) { while (mask) { uint32_t bitpos = find_bottom(mask); int shift = rot + bitpos; uint32_t m = mask & (0xff << bitpos); mask &= ~m; m >>= bitpos; int32_t newMask = (m<<shift) | (m>>(32-shift)); if (!negative_logic) { AND( AL, 0, d, s, imm(newMask) ); } else { BIC( AL, 0, d, s, imm(newMask) ); } s = d; } } else { MOV( AL, 0, d, imm(0)); }} void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs){ if (!mMasking) return; comment("color mask"); pixel_t fb(mDstPixel); pixel_t s(pixel); if (!(pixel.flags & CORRUPTIBLE)) { pixel.reg = regs.obtain(); pixel.flags |= CORRUPTIBLE; } int mask = 0; for (int i=0 ; i<4 ; i++) { const int component_mask = 1<<i; const int h = fb.format.c[i].h; const int l = fb.format.c[i].l; if (h && (!(mMasking & component_mask))) { mask |= ((1<<(h-l))-1) << l; } } // There is no need to clear the masked components of the source // (unless we applied a logic op), because they're already zeroed // by contruction (masked components are not computed) if (mLogicOp) { const needs_t& needs = mBuilderContext.needs; const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR; if (opcode != GGL_CLEAR) { // clear masked component of source build_and_immediate(pixel.reg, s.reg, mask, fb.size()); s = pixel; } } // clear non masked components of destination build_and_immediate(fb.reg, fb.reg, ~mask, fb.size()); // or back the channels that were masked if (s.reg == fb.reg) { // this is in fact a MOV if (s.reg == pixel.reg) { // ugh. this in in fact a nop } else { MOV(AL, 0, pixel.reg, fb.reg); } } else { ORR(AL, 0, pixel.reg, s.reg, fb.reg); }}// ---------------------------------------------------------------------------void GGLAssembler::base_offset( const pointer_t& d, const pointer_t& b, const reg_t& o){ switch (b.size) { case 32: ADD(AL, 0, d.reg, b.reg, reg_imm(o.reg, LSL, 2)); break; case 24: if (d.reg == b.reg) { ADD(AL, 0, d.reg, b.reg, reg_imm(o.reg, LSL, 1)); ADD(AL, 0, d.reg, d.reg, o.reg); } else { ADD(AL, 0, d.reg, o.reg, reg_imm(o.reg, LSL, 1)); ADD(AL, 0, d.reg, d.reg, b.reg); } break; case 16: ADD(AL, 0, d.reg, b.reg, reg_imm(o.reg, LSL, 1)); break; case 8: ADD(AL, 0, d.reg, b.reg, o.reg); break; }}// ----------------------------------------------------------------------------// cheezy register allocator...// ----------------------------------------------------------------------------void RegisterAllocator::reset(){ mRegs.reset();}int RegisterAllocator::reserveReg(int reg){ return mRegs.reserve(reg);}int RegisterAllocator::obtainReg(){ return mRegs.obtain();}void RegisterAllocator::recycleReg(int reg){ mRegs.recycle(reg);}RegisterAllocator::RegisterFile& RegisterAllocator::registerFile(){ return mRegs;}// ----------------------------------------------------------------------------RegisterAllocator::RegisterFile::RegisterFile() : mRegs(0), mTouched(0), mStatus(0){ reserve(ARMAssemblerInterface::SP); reserve(ARMAssemblerInterface::PC);}RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs) : mRegs(rhs.mRegs), mTouched(rhs.mTouched){}RegisterAllocator::RegisterFile::~RegisterFile(){}bool RegisterAllocator::RegisterFile::operator == (const RegisterFile& rhs) const{ return (mRegs == rhs.mRegs);}void RegisterAllocator::RegisterFile::reset(){ mRegs = mTouched = mStatus = 0; reserve(ARMAssemblerInterface::SP); reserve(ARMAssemblerInterface::PC);}int RegisterAllocator::RegisterFile::reserve(int reg){ LOG_ALWAYS_FATAL_IF(isUsed(reg), "reserving register %d, but already in use", reg); mRegs |= (1<<reg); mTouched |= mRegs; return reg;}void RegisterAllocator::RegisterFile::reserveSeveral(uint32_t regMask){ mRegs |= regMask; mTouched |= regMask;}int RegisterAllocator::RegisterFile::isUsed(int reg) const{ LOG_ALWAYS_FATAL_IF(reg>=16, "invalid register %d", reg); return mRegs & (1<<reg);}int RegisterAllocator::RegisterFile::obtain(){ const char priorityList[14] = { 0, 1, 2, 3, 12, 14, 4, 5, 6, 7, 8, 9, 10, 11 }; const int nbreg = sizeof(priorityList); int i, r; for (i=0 ; i<nbreg ; i++) { r = priorityList[i]; if (!isUsed(r)) { break; } } // this is not an error anymore because, we'll try again with // a lower optimization level. //LOGE_IF(i >= nbreg, "pixelflinger ran out of registers\n"); if (i >= nbreg) { mStatus |= OUT_OF_REGISTERS; // we return SP so we can more easily debug things // the code will never be run anyway. return ARMAssemblerInterface::SP; } reserve(r); return r;}bool RegisterAllocator::RegisterFile::hasFreeRegs() const{ return ((mRegs & 0xFFFF) == 0xFFFF) ? false : true;}int RegisterAllocator::RegisterFile::countFreeRegs() const{ int f = ~mRegs & 0xFFFF; // now count number of 1 f = (f & 0x5555) + ((f>>1) & 0x5555); f = (f & 0x3333) + ((f>>2) & 0x3333); f = (f & 0x0F0F) + ((f>>4) & 0x0F0F); f = (f & 0x00FF) + ((f>>8) & 0x00FF); return f;}void RegisterAllocator::RegisterFile::recycle(int reg){ LOG_FATAL_IF(!isUsed(reg), "recycling unallocated register %d", reg); mRegs &= ~(1<<reg);}void RegisterAllocator::RegisterFile::recycleSeveral(uint32_t regMask){ LOG_FATAL_IF((mRegs & regMask)!=regMask, "recycling unallocated registers " "(recycle=%08x, allocated=%08x, unallocated=%08x)", regMask, mRegs, mRegs®Mask); mRegs &= ~regMask;}uint32_t RegisterAllocator::RegisterFile::touched() const{ return mTouched;}// ----------------------------------------------------------------------------}; // namespace android
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -