smt_astt smt_convt::overflow_arith(const expr2tc &expr) { // If in integer mode, this is completely pointless. Return false. if (int_encoding) return mk_smt_bool(false); const overflow2t &overflow = to_overflow2t(expr); const arith_2ops &opers = static_cast<const arith_2ops &>(*overflow.operand); assert(opers.side_1->type == opers.side_2->type); constant_int2tc zero(opers.side_1->type, BigInt(0)); lessthan2tc op1neg(opers.side_1, zero); lessthan2tc op2neg(opers.side_2, zero); equality2tc op1iszero(opers.side_1, zero); equality2tc op2iszero(opers.side_2, zero); or2tc containszero(op1iszero, op2iszero); // Guess whether we're performing a signed or unsigned comparison. bool is_signed = (is_signedbv_type(opers.side_1) || is_signedbv_type(opers.side_2)); if (is_add2t(overflow.operand)) { if (is_signed) { // Two cases: pos/pos, and neg/neg, which can over and underflow resp. // In pos/neg cases, no overflow or underflow is possible, for any value. constant_int2tc zero(opers.side_1->type, BigInt(0)); lessthan2tc op1pos(zero, opers.side_1); lessthan2tc op2pos(zero, opers.side_2); and2tc both_pos(op1pos, op2pos); not2tc negop1(op1pos); not2tc negop2(op2pos); and2tc both_neg(negop1, negop2); implies2tc nooverflow(both_pos, greaterthanequal2tc(overflow.operand, zero)); implies2tc nounderflow(both_neg, lessthanequal2tc(overflow.operand, zero)); return convert_ast(not2tc(and2tc(nooverflow, nounderflow))); } else { // Just ensure the result is >= both operands. greaterthanequal2tc ge1(overflow.operand, opers.side_1); greaterthanequal2tc ge2(overflow.operand, opers.side_2); and2tc res(ge1, ge2); not2tc inv(res); return convert_ast(inv); } } else if (is_sub2t(overflow.operand)) { if (is_signed) { // Convert to be an addition neg2tc negop2(opers.side_2->type, opers.side_2); add2tc anadd(opers.side_1->type, opers.side_1, negop2); expr2tc add_overflows(new overflow2t(anadd)); // Corner case: subtracting MIN_INT from many things overflows. The result // should always be positive. constant_int2tc zero(opers.side_1->type, BigInt(0)); uint64_t topbit = 1ULL << (opers.side_1->type->get_width() - 1); constant_int2tc min_int(opers.side_1->type, BigInt(topbit)); equality2tc is_min_int(min_int, opers.side_2); implies2tc imp(is_min_int, greaterthan2tc(overflow.operand, zero)); return convert_ast(or2tc(add_overflows, is_min_int)); } else { // Just ensure the result is >= the operands. lessthanequal2tc le1(overflow.operand, opers.side_1); lessthanequal2tc le2(overflow.operand, opers.side_2); and2tc res(le1, le2); not2tc inv(res); return convert_ast(inv); } } else { assert(is_mul2t(overflow.operand) && "unexpected overflow_arith operand"); // Zero extend; multiply; Make a decision based on the top half. unsigned int sz = zero->type->get_width(); smt_sortt boolsort = boolean_sort; smt_sortt normalsort = mk_sort(SMT_SORT_BV, sz, false); smt_sortt bigsort = mk_sort(SMT_SORT_BV, sz * 2, false); // All one bit vector is tricky, might be 64 bits wide for all we know. constant_int2tc allonesexpr(zero->type, BigInt((sz == 64) ? 0xFFFFFFFFFFFFFFFFULL : ((1ULL << sz) - 1))); smt_astt allonesvector = convert_ast(allonesexpr); smt_astt arg1_ext, arg2_ext; if (is_signed) { // sign extend top bits. arg1_ext = convert_ast(opers.side_1); arg1_ext = convert_sign_ext(arg1_ext, bigsort, sz - 1, sz); arg2_ext = convert_ast(opers.side_2); arg2_ext = convert_sign_ext(arg2_ext, bigsort, sz - 1, sz); } else { // Zero extend the top parts arg1_ext = convert_ast(opers.side_1); arg1_ext = convert_zero_ext(arg1_ext, bigsort, sz); arg2_ext = convert_ast(opers.side_2); arg2_ext = convert_zero_ext(arg2_ext, bigsort, sz); } smt_astt result = mk_func_app(bigsort, SMT_FUNC_BVMUL, arg1_ext, arg2_ext); // Extract top half. smt_astt toppart = mk_extract(result, (sz * 2) - 1, sz, normalsort); if (is_signed) { // It should either be zero or all one's; which depends on what // configuration of signs it had. If both pos / both neg, then the top // should all be zeros, otherwise all ones. Implement with xor. smt_astt op1neg_ast = convert_ast(op1neg); smt_astt op2neg_ast = convert_ast(op2neg); smt_astt allonescond = mk_func_app(boolsort, SMT_FUNC_XOR, op1neg_ast, op2neg_ast); smt_astt zerovector = convert_ast(zero); smt_astt initial_switch = mk_func_app(normalsort, SMT_FUNC_ITE, allonescond, allonesvector, zerovector); // either value being zero means the top must be zero. smt_astt contains_zero_ast = convert_ast(containszero); smt_astt second_switch = mk_func_app(normalsort, SMT_FUNC_ITE, contains_zero_ast, zerovector, initial_switch); smt_astt is_eq = mk_func_app(boolsort, SMT_FUNC_EQ, second_switch, toppart); return mk_func_app(boolsort, SMT_FUNC_NOT, &is_eq, 1); } else { // It should be zero; if not, overflow smt_astt iseq = mk_func_app(boolsort, SMT_FUNC_EQ, toppart, convert_ast(zero)); return mk_func_app(boolsort, SMT_FUNC_NOT, &iseq, 1); } } return NULL; }
static dma_addr_t i915_stolen_to_dma(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = dev_priv->drm.pdev; struct i915_ggtt *ggtt = &dev_priv->ggtt; struct resource *r; dma_addr_t base; /* Almost universally we can find the Graphics Base of Stolen Memory * at register BSM (0x5c) in the igfx configuration space. On a few * (desktop) machines this is also mirrored in the bridge device at * different locations, or in the MCHBAR. * * On 865 we just check the TOUD register. * * On 830/845/85x the stolen memory base isn't available in any * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. * */ base = 0; if (INTEL_GEN(dev_priv) >= 3) { u32 bsm; pci_read_config_dword(pdev, INTEL_BSM, &bsm); base = bsm & INTEL_BSM_MASK; } else if (IS_I865G(dev_priv)) { u32 tseg_size = 0; u16 toud = 0; u8 tmp; pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I845_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) { switch (tmp & I845_TSEG_SIZE_MASK) { case I845_TSEG_SIZE_512K: tseg_size = KB(512); break; case I845_TSEG_SIZE_1M: tseg_size = MB(1); break; } } pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), I865_TOUD, &toud); base = (toud << 16) + tseg_size; } else if (IS_I85X(dev_priv)) { u32 tseg_size = 0; u32 tom; u8 tmp; pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I85X_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) tseg_size = MB(1); pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 1), I85X_DRB3, &tmp); tom = tmp * MB(32); base = tom - tseg_size - ggtt->stolen_size; } else if (IS_I845G(dev_priv)) { u32 tseg_size = 0; u32 tom; u8 tmp; pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I845_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) { switch (tmp & I845_TSEG_SIZE_MASK) { case I845_TSEG_SIZE_512K: tseg_size = KB(512); break; case I845_TSEG_SIZE_1M: tseg_size = MB(1); break; } } pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I830_DRB3, &tmp); tom = tmp * MB(32); base = tom - tseg_size - ggtt->stolen_size; } else if (IS_I830(dev_priv)) { u32 tseg_size = 0; u32 tom; u8 tmp; pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I830_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) { if (tmp & I830_TSEG_SIZE_1M) tseg_size = MB(1); else tseg_size = KB(512); } pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I830_DRB3, &tmp); tom = tmp * MB(32); base = tom - tseg_size - ggtt->stolen_size; } if (base == 0 || add_overflows(base, ggtt->stolen_size)) return 0; /* make sure we don't clobber the GTT if it's within stolen memory */ if (INTEL_GEN(dev_priv) <= 4 && !IS_G33(dev_priv) && !IS_PINEVIEW(dev_priv) && !IS_G4X(dev_priv)) { struct { dma_addr_t start, end; } stolen[2] = { { .start = base, .end = base + ggtt->stolen_size, }, { .start = base, .end = base + ggtt->stolen_size, }, };