OffsetSet instrSuccOffsets(PC opc, const Unit* unit) { OffsetSet succBcOffs; auto const bcStart = unit->entry(); auto const op = peek_op(opc); if (!instrIsControlFlow(op)) { Offset succOff = opc + instrLen(opc) - bcStart; succBcOffs.insert(succOff); return succBcOffs; } if (instrAllowsFallThru(op)) { Offset succOff = opc + instrLen(opc) - bcStart; succBcOffs.insert(succOff); } if (isSwitch(op)) { foreachSwitchTarget(opc, [&](Offset offset) { succBcOffs.insert(offset + opc - bcStart); }); } else { Offset target = instrJumpTarget(bcStart, opc - bcStart); if (target != InvalidAbsoluteOffset) { succBcOffs.insert(target); } } return succBcOffs; }
/** * Create blocks for each entry point as well as ordinary control * flow boundaries. Calls are not treated as basic-block ends. */ void GraphBuilder::createBlocks() { PC bc = m_unit->entry(); m_graph->param_count = m_func->params().size(); m_graph->first_linear = createBlock(m_func->base()); // DV entry points m_graph->entries = new (m_arena) Block*[m_graph->param_count + 1]; int dv_index = 0; for (auto& param : m_func->params()) { m_graph->entries[dv_index++] = !param.hasDefaultValue() ? 0 : createBlock(param.funcletOff); } // main entry point assert(dv_index == m_graph->param_count); m_graph->entries[dv_index] = createBlock(m_func->base()); // ordinary basic block boundaries for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); if ((isCF(pc) || isTF(pc)) && !i.empty()) createBlock(i.front()); if (isSwitch(peek_op(pc))) { foreachSwitchTarget(pc, [&](Offset o) { createBlock(pc + o); }); } else { Offset target = instrJumpTarget(bc, pc - bc); if (target != InvalidAbsoluteOffset) createBlock(target); } } }
/** * Returns the set of bytecode offsets for the instructions that may * be executed immediately after opc. */ static OffsetSet findSuccOffsets(Op* opc, const Unit* unit) { OffsetSet succBcOffs; Op* bcStart = (Op*)(unit->entry()); if (!instrIsControlFlow(*opc)) { Offset succOff = opc + instrLen(opc) - bcStart; succBcOffs.insert(succOff); return succBcOffs; } if (instrAllowsFallThru(*opc)) { Offset succOff = opc + instrLen(opc) - bcStart; succBcOffs.insert(succOff); } if (isSwitch(*opc)) { foreachSwitchTarget(opc, [&](Offset& offset) { succBcOffs.insert(offset); }); } else { Offset target = instrJumpTarget(bcStart, opc - bcStart); if (target != InvalidAbsoluteOffset) { succBcOffs.insert(target); } } return succBcOffs; }
void Controller::sendSettings(){ #ifdef SUPPORT_MQTT if ( isSwitch() ){ MQTT::publishSwitch( getName(), false ); } else { MQTT::publishTempSetup( getName(), getTargetT(), getMinimumLevel(), getProfileID() ); } #endif }
bool InputManager::handleEvent(QEvent* event) { if (event->type() != QEvent::KeyPress && event->type() != QEvent::KeyRelease) return false; QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); Qt::Key key = static_cast<Qt::Key>(keyEvent->key()); const char* keyCategory = NULL; // NOTE: We can potentially get key presses on the device before // com.palm.keys comes up, and these won't be broadcast to subscribers // However, we assume that we wouldn't want them to receive a collection // of queued up key presses // Each subset of keys must not overlap in the current handling if (isAudioKey(key)) { keyCategory = CATEGORY_AUDIO; } else if (isMediaKey(key)) { keyCategory = CATEGORY_MEDIA; } else if (isSwitch(key)) { keyCategory = CATEGORY_SWITCHES; } else if (isHeadsetKey(key)) { if (!(key == KEYS::Key_Headset || key == KEYS::Key_HeadsetMic)) { // state machine time -- headset button headsetStateMachine(keyEvent); } keyCategory = CATEGORY_HEADSET; } else if (isBluetoothKey(key)) { handleBluetoothKey(keyEvent); return true; } else { // Not a key that we care about, so we indicate we didn't handle it return false; } // first event that comes in sets the sticky state, no matter // whether it is a real action that a user did or a generated // "InitialState" static int switchInitCount = 0; if (setKeyState(key, event->type())) { if (NULL == m_publicService && (++switchInitCount == HostBase::instance()->getNumberOfSwitches() )) { startService(); } } // We don't post the "InitialState" key because it is internally // generated in order to get initial state of a key if (!(keyEvent->nativeModifiers() & SysMgrNativeKeyboardModifier_InitialState)) { const char* keyString = NULL; keyToString(key, &keyString); (void)postKeyToSubscribers(keyEvent, keyCategory, keyString, NULL); } return true; }
/****************************************************************************** * mv_eth_tool_get_settings * Description: * ethtool get standard port settings * INPUT: * netdev Network device structure pointer * OUTPUT * cmd command (settings) * RETURN: * 0 for success * *******************************************************************************/ int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { struct eth_port *priv = MV_ETH_PRIV(netdev); MV_U32 mv_phy_addr; MV_ETH_PORT_SPEED speed; MV_ETH_PORT_DUPLEX duplex; MV_ETH_PORT_STATUS status; if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) { printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name); return -EOPNOTSUPP; } cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_1000baseT_Full); mv_phy_addr = mvBoardPhyAddrGet(priv->port); mvNetaLinkStatus(priv->port, &status); switch (status.speed) { case MV_ETH_SPEED_1000: cmd->speed = SPEED_1000; break; case MV_ETH_SPEED_100: cmd->speed = SPEED_100; break; case MV_ETH_SPEED_10: cmd->speed = SPEED_10; break; default: return -EINVAL; } if (status.duplex == MV_ETH_DUPLEX_FULL) cmd->duplex = 1; else cmd->duplex = 0; cmd->port = PORT_MII; cmd->phy_address = mv_phy_addr; cmd->transceiver = XCVR_INTERNAL; /* check if speed and duplex are AN */ mvNetaSpeedDuplexGet(priv->port, &speed, &duplex); if (speed == MV_ETH_SPEED_AN && duplex == MV_ETH_DUPLEX_AN) { /* Note: lp_advertising not available in this kernel */ cmd->advertising = 0; cmd->autoneg = AUTONEG_ENABLE; mvEthPhyAdvertiseGet(mv_phy_addr, (MV_U16 *)&(cmd->advertising)); } else cmd->autoneg = AUTONEG_DISABLE; return 0; }
// Place internal breakpoints to get out of the current function. This may place // multiple internal breakpoints, and it may place them more than one frame up. // Some instructions can cause PHP to be invoked without an explicit call. A set // which causes a destructor to run, a iteration init which causes an object's // next() method to run, a RetC which causes destructors to run, etc. This // recgonizes such cases and ensures we have internal breakpoints to cover the // destination(s) of such instructions. void CmdFlowControl::setupStepOuts() { // Existing step outs should be cleaned up before making new ones. assert(!hasStepOuts()); auto fp = g_context->getFP(); if (!fp) return; // No place to step out to! Offset returnOffset; bool fromVMEntry; while (!hasStepOuts()) { fp = g_context->getPrevVMState(fp, &returnOffset, nullptr, &fromVMEntry); // If we've run off the top of the stack, just return having setup no // step outs. This will cause cmds like Next and Out to just let the program // run, which is appropriate. if (!fp) break; Unit* returnUnit = fp->m_func->unit(); PC returnPC = returnUnit->at(returnOffset); TRACE(2, "CmdFlowControl::setupStepOuts: at '%s' offset %d opcode %s\n", fp->m_func->fullName()->data(), returnOffset, opcodeToName(*reinterpret_cast<const Op*>(returnPC))); // Don't step out to generated functions, keep looking. if (fp->m_func->line1() == 0) continue; if (fromVMEntry) { TRACE(2, "CmdFlowControl::setupStepOuts: VM entry\n"); // We only execute this for opcodes which invoke more PHP, and that does // not include switches. Thus, we'll have at most two destinations. assert(!isSwitch(*reinterpret_cast<const Op*>(returnPC)) && (numSuccs(reinterpret_cast<const Op*>(returnPC)) <= 2)); // Set an internal breakpoint after the instruction if it can fall thru. if (instrAllowsFallThru(*reinterpret_cast<const Op*>(returnPC))) { Offset nextOffset = returnOffset + instrLen((Op*)returnPC); TRACE(2, "CmdFlowControl: step out to '%s' offset %d (fall-thru)\n", fp->m_func->fullName()->data(), nextOffset); m_stepOut1 = StepDestination(returnUnit, nextOffset); } // Set an internal breakpoint at the target of a control flow instruction. // A good example of a control flow op that invokes PHP is IterNext. if (instrIsControlFlow(*reinterpret_cast<const Op*>(returnPC))) { Offset target = instrJumpTarget(reinterpret_cast<const Op*>(returnPC), 0); if (target != InvalidAbsoluteOffset) { Offset targetOffset = returnOffset + target; TRACE(2, "CmdFlowControl: step out to '%s' offset %d (jump target)\n", fp->m_func->fullName()->data(), targetOffset); m_stepOut2 = StepDestination(returnUnit, targetOffset); } } // If we have no place to step out to, then unwind another frame and try // again. The most common case that leads here is Ret*, which does not // fall-thru and has no encoded target. } else { TRACE(2, "CmdFlowControl: step out to '%s' offset %d\n", fp->m_func->fullName()->data(), returnOffset); m_stepOut1 = StepDestination(returnUnit, returnOffset); } } }
Offset* instrJumpOffset(Opcode* instr) { static const int8_t jumpMask[] = { #define NA 0 #define MA 0 #define IVA 0 #define I64A 0 #define DA 0 #define SA 0 #define AA 0 #define BA 1 #define HA 0 #define IA 0 #define OA 0 #define ONE(a) a #define TWO(a, b) (a + 2 * b) #define THREE(a, b, c) (a + 2 * b + 4 * c) #define FOUR(a, b, c, d) (a + 2 * b + 4 * c + 8 * d) #define O(name, imm, pop, push, flags) imm, OPCODES #undef NA #undef MA #undef IVA #undef I64A #undef DA #undef SA #undef AA #undef HA #undef IA #undef BA #undef OA #undef ONE #undef TWO #undef THREE #undef FOUR #undef O }; assert(!isSwitch(*instr)); int mask = jumpMask[*instr]; if (mask == 0) { return nullptr; } int immNum; switch (mask) { case 0: return nullptr; case 1: immNum = 0; break; case 2: immNum = 1; break; case 4: immNum = 2; break; case 8: immNum = 3; break; default: assert(false); return nullptr; } return &getImmPtr(instr, immNum)->u_BA; }
/** * Return the number of successor-edges including fall-through paths but not * implicit exception paths. */ int numSuccs(const Op* instr) { if ((instrFlags(*instr) & TF) != 0) { if (isSwitch(*instr)) { return *(int*)(instr + 1); } if (isUnconditionalJmp(*instr) || *instr == OpIterBreak) return 1; return 0; } if (!instrIsControlFlow(*instr)) return 1; if (instrJumpOffset(const_cast<Op*>(instr))) return 2; return 1; }
/** * Return the number of successor-edges including fall-through paths but not * implicit exception paths. */ int numSuccs(const Opcode* instr) { if (!instrIsControlFlow(*instr)) return 1; if ((instrFlags(*instr) & TF) != 0) { if (isSwitch(*instr)) { return *(int*)(instr + 1); } if (Op(*instr) == OpJmp) return 1; return 0; } if (instrJumpOffset(const_cast<Opcode*>(instr))) return 2; return 1; }
/** * Return the number of successor-edges including fall-through paths but not * implicit exception paths. */ int numSuccs(PC const origPC) { auto pc = origPC; auto const op = decode_op(pc); if ((instrFlags(op) & TF) != 0) { if (isSwitch(op)) { return decode_raw<int32_t>(pc); } if (isUnconditionalJmp(op) || op == OpIterBreak) return 1; return 0; } if (!instrIsControlFlow(op)) return 1; if (instrJumpOffset(origPC)) return 2; return 1; }
/****************************************************************************** * mv_eth_tool_nway_reset * Description: * ethtool restart auto negotiation * INPUT: * netdev Network device structure pointer * OUTPUT * None * RETURN: * 0 on success * *******************************************************************************/ int mv_eth_tool_nway_reset(struct net_device *netdev) { struct eth_port *priv = MV_ETH_PRIV(netdev); MV_U32 mv_phy_addr = mvBoardPhyAddrGet(priv->port); #ifdef CONFIG_MV_ETH_SWITCH if (isSwitch(priv)) return -EPERM; #endif /* CONFIG_MV_ETH_SWITCH */ if (mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK) return -EINVAL; return 0; }
/****************************************************************************** * mv_eth_tool_get_link * Description: * ethtool get link status * INPUT: * netdev Network device structure pointer * OUTPUT * None * RETURN: * 0 if link is down, 1 if link is up * *******************************************************************************/ u32 mv_eth_tool_get_link(struct net_device *netdev) { struct eth_port *pp = MV_ETH_PRIV(netdev); #ifdef CONFIG_MV_ETH_SWITCH if (isSwitch(pp)) return -EPERM; #endif /* CONFIG_MV_ETH_SWITCH */ if (pp) { if (mvNetaLinkIsUp(pp->port)) return 1; } return 0; }
/****************************************************************************** * mv_eth_tool_nway_reset * Description: * ethtool restart auto negotiation * INPUT: * netdev Network device structure pointer * OUTPUT * None * RETURN: * 0 on success * *******************************************************************************/ int mv_eth_tool_nway_reset(struct net_device *netdev) { struct eth_port *priv = MV_ETH_PRIV(netdev); MV_U32 phy_addr; if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) { printk(KERN_ERR "interface %s is not supported\n", netdev->name); return -EOPNOTSUPP; } phy_addr = mvBoardPhyAddrGet(priv->port); if (mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK) return -EINVAL; return 0; }
/****************************************************************************** * mv_eth_tool_get_settings * Description: * ethtool get standard port settings * INPUT: * netdev Network device structure pointer * OUTPUT * cmd command (settings) * RETURN: * 0 for success * *******************************************************************************/ int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { struct eth_port *priv = MV_ETH_PRIV(netdev); int retval; #ifdef CONFIG_MV_ETH_SWITCH if (isSwitch(priv)) return -EPERM; #endif /* CONFIG_MV_ETH_SWITCH */ #ifdef CONFIG_MII retval = mii_ethtool_gset(&priv->mii, cmd); if (retval) return retval; #endif /* CONFIG_MII */ if (priv) { MV_ETH_PORT_STATUS status; mvNetaLinkStatus(priv->port, &status); switch (status.speed) { case MV_ETH_SPEED_1000: cmd->speed = SPEED_1000; break; case MV_ETH_SPEED_100: cmd->speed = SPEED_100; break; case MV_ETH_SPEED_10: cmd->speed = SPEED_10; break; default: return -EINVAL; } if (status.duplex == MV_ETH_DUPLEX_FULL) cmd->duplex = 1; else cmd->duplex = 0; cmd->port = PORT_MII; cmd->phy_address = mvBoardPhyAddrGet(priv->port); } return 0; }
/** * Return the number of successor-edges including fall-through paths but not * implicit exception paths. */ int numSuccs(PC const origPC) { auto pc = origPC; auto const op = decode_op(pc); if ((instrFlags(op) & TF) != 0) { if (isSwitch(op)) { if (op == Op::Switch) { decode_raw<SwitchKind>(pc); // skip bounded flag decode_raw<int64_t>(pc); // skip base } return decode_raw<int32_t>(pc); // vector length } if (isUnconditionalJmp(op) || op == OpIterBreak) return 1; return 0; } if (!instrIsControlFlow(op)) return 1; if (instrJumpOffset(origPC)) return 2; return 1; }
/****************************************************************************** * mv_eth_tool_get_link * Description: * ethtool get link status * INPUT: * netdev Network device structure pointer * OUTPUT * None * RETURN: * 0 if link is down, 1 if link is up * *******************************************************************************/ u32 mv_eth_tool_get_link(struct net_device *netdev) { struct eth_port *pp = MV_ETH_PRIV(netdev); struct eth_netdev *dev_priv = MV_DEV_PRIV(netdev); if (pp == NULL) { printk(KERN_ERR "interface %s is not supported\n", netdev->name); return -EOPNOTSUPP; } if (isSwitch(pp)) { if (dev_priv == NULL) return -EOPNOTSUPP; return (dev_priv->link_map != 0); } #ifdef CONFIG_MV_PON if (MV_PON_PORT(pp->port)) return mv_pon_link_status(); #endif /* CONFIG_MV_PON */ return mvNetaLinkIsUp(pp->port); }
/****************************************************************************** * mv_eth_tool_set_tso * Description: * ethtool enable/disable TCP segmentation offloading * INPUT: * netdev Network device structure pointer * data Command data * OUTPUT * None * RETURN: * 0 on success * *******************************************************************************/ int mv_eth_tool_set_tso(struct net_device *netdev, uint32_t data) { #ifdef CONFIG_MV_ETH_SWITCH struct eth_port *priv = MV_ETH_PRIV(netdev); if (isSwitch(priv)) { printk("mv_eth_tool_set_tso() is not supported on a switch port\n"); return -EOPNOTSUPP; } #endif /* CONFIG_MV_ETH_SWITCH */ #if defined(CONFIG_MV_ETH_TSO) if (data) netdev->features |= NETIF_F_TSO; else netdev->features &= ~NETIF_F_TSO; return 0; #else return -EOPNOTSUPP; #endif }
/****************************************************************************** * mv_eth_tool_set_pauseparam * Description: * ethtool configure pause parameters * INPUT: * netdev Network device structure pointer * pause Pause paranmeters * OUTPUT * None * RETURN: * 0 on success * *******************************************************************************/ int mv_eth_tool_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct eth_port *priv = MV_ETH_PRIV(netdev); int port = priv->port; MV_U32 phy_addr; MV_STATUS status = MV_FAIL; #ifdef CONFIG_MV_ETH_SWITCH if (isSwitch(priv)) return -EPERM; #endif /* CONFIG_MV_ETH_SWITCH */ if (pause->rx_pause && pause->tx_pause) { /* Enable FC */ if (pause->autoneg) { /* autoneg enable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_SYM); } else { /* autoneg disable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_ENABLE); } } else if (!pause->rx_pause && !pause->tx_pause) { /* Disable FC */ if (pause->autoneg) { /* autoneg enable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_NO); } else { /* autoneg disable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_DISABLE); } } /* Only symmetric change for RX and TX flow control is allowed */ if (status == MV_OK) { phy_addr = mvBoardPhyAddrGet(priv->port); status = mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT); } if (status != MV_OK) return -EINVAL; return 0; }
/** * Link ordinary blocks with ordinary edges and set their last instruction * and end offsets */ void GraphBuilder::linkBlocks() { PC bc = m_unit->entry(); Block* block = m_graph->first_linear; block->id = m_graph->block_count++; for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); block->last = pc; if (isCF(pc)) { if (isSwitch(*reinterpret_cast<const Op*>(pc))) { int i = 0; foreachSwitchTarget((Op*)pc, [&](Offset& o) { succs(block)[i++] = at(pc + o); }); } else { Offset target = instrJumpTarget((Op*)bc, pc - bc); if (target != InvalidAbsoluteOffset) { assert(numSuccBlocks(block) > 0); succs(block)[numSuccBlocks(block) - 1] = at(target); } } } PC next_pc = !i.empty() ? i.front() : m_unit->at(m_func->past()); Block* next = at(next_pc); if (next) { block->next_linear = next; block->end = next_pc; if (!isTF(pc)) { assert(numSuccBlocks(block) > 0); succs(block)[0] = next; } block = next; block->id = m_graph->block_count++; } } block->end = m_unit->at(m_func->past()); }
/****************************************************************************** * mv_eth_tool_set_pauseparam * Description: * ethtool configure pause parameters * INPUT: * netdev Network device structure pointer * pause Pause paranmeters * OUTPUT * None * RETURN: * 0 on success * *******************************************************************************/ int mv_eth_tool_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct eth_port *priv = MV_ETH_PRIV(netdev); int port = priv->port; MV_U32 phy_addr; MV_STATUS status = MV_FAIL; if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) { printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name); return -EOPNOTSUPP; } if (pause->rx_pause && pause->tx_pause) { /* Enable FC */ if (pause->autoneg) { /* autoneg enable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_SYM); } else { /* autoneg disable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_ENABLE); } } else if (!pause->rx_pause && !pause->tx_pause) { /* Disable FC */ if (pause->autoneg) { /* autoneg enable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_NO); } else { /* autoneg disable */ status = mvNetaFlowCtrlSet(port, MV_ETH_FC_DISABLE); } } /* Only symmetric change for RX and TX flow control is allowed */ if (status == MV_OK) { phy_addr = mvBoardPhyAddrGet(priv->port); status = mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT); } if (status != MV_OK) return -EINVAL; return 0; }
Offset* instrJumpOffset(Op* instr) { static const int8_t jumpMask[] = { #define NA 0 #define MA 0 #define IVA 0 #define I64A 0 #define DA 0 #define SA 0 #define AA 0 #define BA 1 #define LA 0 #define IA 0 #define OA 0 #define ONE(a) a #define TWO(a, b) (a + 2 * b) #define THREE(a, b, c) (a + 2 * b + 4 * c) #define FOUR(a, b, c, d) (a + 2 * b + 4 * c + 8 * d) #define O(name, imm, pop, push, flags) imm, OPCODES #undef NA #undef MA #undef IVA #undef I64A #undef DA #undef SA #undef AA #undef LA #undef IA #undef BA #undef OA #undef ONE #undef TWO #undef THREE #undef FOUR #undef O }; assert(!isSwitch(*instr)); if (Op(*instr) == OpIterBreak) { uint32_t veclen = *(uint32_t *)(instr + 1); assert(veclen > 0); Offset* target = (Offset *)((uint32_t *)(instr + 1) + 2 * veclen + 1); return target; } int mask = jumpMask[uint8_t(*instr)]; if (mask == 0) { return nullptr; } int immNum; switch (mask) { case 0: return nullptr; case 1: immNum = 0; break; case 2: immNum = 1; break; case 4: immNum = 2; break; case 8: immNum = 3; break; default: assert(false); return nullptr; } return &getImmPtr(instr, immNum)->u_BA; }
/** * Iterate the game board and markup for found combinations **/ bool findMatches() { // One look for explosions bool matchesFound = false; // Double or singe black? Must be a switch if (s_switch.first.x != -1) { if (s_pieces[XYp(s_switch.first)].colour == kBlack && s_pieces[XYp(s_switch.second)].colour == kBlack) { // double black explode(kBOOM, s_switch.second.x, s_switch.second.y, 0); matchesFound = true; } else if (s_pieces[XYp(s_switch.first)].colour == kWhite && s_pieces[XYp(s_switch.second)].colour == kBlack) { //White black explode(kCross, s_switch.second.x, s_switch.second.y, 0); matchesFound = true; } else if (s_pieces[XYp(s_switch.first)].colour == kBlack && s_pieces[XYp(s_switch.second)].colour == kWhite) { //Black white explode(kCross, s_switch.second.x, s_switch.second.y, 0); matchesFound = true; } else if (s_pieces[XYp(s_switch.first)].colour == kBlack) { // Single black A explode(kMiniBoom, s_switch.second.x, s_switch.second.y, s_pieces[XYp(s_switch.second)].colour); s_pieces[XYp(s_switch.first)].exploded = true; matchesFound = true; } else if (s_pieces[XYp(s_switch.second)].colour == kBlack) { // Single black B explode(kMiniBoom, s_switch.first.x, s_switch.first.y, s_pieces[XYp(s_switch.first)].colour); s_pieces[XYp(s_switch.second)].exploded = true; matchesFound = true; } } // Markup the board for (int dir = 0; dir < 2; ++dir) { // x or y int xStop = 0, yStop = 0, max = 0; if (dir == 0) { // go along x, look in y yStop = 2; max = BOARD_PIECES_Y; } else { // go along y, look in x xStop = 2; max = BOARD_PIECES_X; } for (int x=0; x < BOARD_PIECES_X - xStop; ++x) { for (int y=0; y < BOARD_PIECES_Y - yStop; ++y) { // Find a run int runSize = 1, nextX, nextY; if (dir == 0) { nextX = x; nextY = y+1; } else { nextX = x+1; nextY = y; } Colour_t runColour = s_pieces[XY(x,y)].colour; while (1) { if (runColour == kWhite) runColour = s_pieces[XY(nextX,nextY)].colour; // If first colour(s) were white - need to update to know colour of run if ( s_pieces[XY(nextX,nextY)].colour == runColour) {} // Progress - Same colour else if ( s_pieces[XY(nextX,nextY)].colour == kWhite ) {} // Progress - Wildcard, white always matches else break; // Square is different colour - stop here ++runSize; // Square accepted if (dir == 0) { if (++nextY == max) break; // This is where the asymmetric grid bug was hiding before, only compare one } else { if (++nextX == max) break; } } if (runSize > 4) { explode(kColourBoom, 0, 0, runColour); // do colour BOOM matchesFound = true; } else if (runSize > 2) { if (runColour == kBlack) { // Special - three blacks? Very rare, but deserves a big explosion! Like an extended black-black match //APP_LOG(APP_LOG_LEVEL_DEBUG,"MATCH-3-or-4-BLACK!!!!"); if (dir == 0) for (int P=y; P < nextY; ++P) explode(kBOOM, x, P, 0); else for (int P=x; P < nextX; ++P) explode(kBOOM, P, y, 0); matchesFound = true; } else { //APP_LOG(APP_LOG_LEVEL_DEBUG,"MATCH-3-or-4"); runSize == 3 ? score(kMatch3, 0) : score(kMatch4, 0); if (dir == 0) for (int P=y; P < nextY; ++P) s_pieces[XY(x,P)].match++; // A piece can be matched up to twice else for (int P=x; P < nextX; ++P) s_pieces[XY(P,y)].match++; matchesFound = true; } } //Promote white if (runSize == 4) { // We promote the switched piece if user instagated, or the final piece if part of a cascade //APP_LOG(APP_LOG_LEVEL_DEBUG,"PROMOTE WHITE"); if (dir == 0) { for (int P=y; P < nextY; ++P) { if (isSwitch(x,P) || P == nextY-1) { s_pieces[XY(x,P)].promoteFlag = kWhite; break; } } } else { for (int P=x; P < nextX; ++P) { if (isSwitch(P,y) || P == nextX-1) { s_pieces[XY(P,y)].promoteFlag = kWhite; break; } } } } // Skip over the cells we've just dealed with (remember we're at the end of the loop so going to get a +1 anyway) if (dir == 0 && runSize > 2) y += (runSize-1); else if (dir == 1 && runSize > 2) x += (runSize-1); } } } // Promote black for (int x=0; x < BOARD_PIECES_X; ++x) { for (int y=0; y < BOARD_PIECES_Y; ++y) { if (s_pieces[XY(x,y)].match == kMatchedTwice) { score(kMatchT, 0); // This is a bonus on top of the 2x match-3 / match-4s s_pieces[XY(x,y)].promoteFlag = kBlack; // This can in theory overwrite a promote white command //APP_LOG(APP_LOG_LEVEL_DEBUG,"PROMOTE BLACK"); } } } //remember to unset switches so they don't trigger on iterations of this phase s_switch.first = GPoint(-1,-1); s_switch.second = GPoint(-1,-1); if (matchesFound == true) { // Remove and repeat, continue to cascade until no runs remain s_gameState = kFlashRemoved; if (s_currentRun < ANIM_FPS/3) ++s_currentRun; // This makes things faster if more matches are found } else { // No more runs s_gameState = kFindNextMove; // Let the comp try and find a valid move, if any } return false; // don't redraw, nothing graphical }
/*============================================================================== * FUNCTION: processProc * OVERVIEW: Process a procedure, given a native (source machine) address. * PARAMETERS: address - the address at which the procedure starts * delta - the offset of the above address from the logical * address at which the procedure starts (i.e. the one * given by dis) * uUpper - the highest address of the text segment * pProc - the procedure object * decoder - NJMCDecoder object * RETURNS: <nothing> *============================================================================*/ void processProc(ADDRESS uAddr, ptrdiff_t delta, ADDRESS uUpper, UserProc* pProc, NJMCDecoder& decoder) { PBB pBB; // Pointer to the current basic block INSTTYPE type; // Cfg type of instruction (e.g. IRET) // Declare a queue of targets not yet processed yet. This has to be // individual to the procedure! TARGETS targets; // Indicates whether or not the next instruction to be decoded is the // lexical successor of the current one. Will be true for all NCTs and for // CTIs with a fall through branch. bool sequentialDecode = true; Cfg* pCfg = pProc->getCFG(); // Initialise the queue of control flow targets that have yet to be decoded. targets.push(uAddr); // Clear the pointer used by the caller prologue code to access the last // call rtl of this procedure //decoder.resetLastCall(); while ((uAddr = nextAddress(targets, pCfg)) != 0) { // The list of RTLs for the current basic block list<HRTL*>* BB_rtls = new list<HRTL*>(); // Keep decoding sequentially until a CTI without a fall through branch // is decoded ADDRESS start = uAddr; DecodeResult inst; while (sequentialDecode) { // Decode and classify the current instruction if (progOptions.trace) cout << "*" << hex << uAddr << "\t" << flush; // Decode the inst at uAddr. inst = decoder.decodeInstruction(uAddr, delta, pProc); // Need to construct a new list of RTLs if a basic block has just // been finished but decoding is continuing from its lexical // successor if (BB_rtls == NULL) BB_rtls = new list<HRTL*>(); HRTL* pRtl = inst.rtl; if (inst.numBytes == 0) { // An invalid instruction. Most likely because a call did // not return (e.g. call _exit()), etc. Best thing is to // emit a INVALID BB, and continue with valid instructions ostrstream ost; ost << "invalid instruction at " << hex << uAddr; warning(str(ost)); // Emit the RTL anyway, so we have the address and maybe // some other clues BB_rtls->push_back(new RTL(uAddr)); pBB = pCfg->newBB(BB_rtls, INVALID, 0); sequentialDecode = false; BB_rtls = NULL; continue; } HLJump* rtl_jump = static_cast<HLJump*>(pRtl); // Display RTL representation if asked if (progOptions.rtl) pRtl->print(); ADDRESS uDest; switch (pRtl->getKind()) { case JUMP_HRTL: { uDest = rtl_jump->getFixedDest(); // Handle one way jumps and computed jumps separately if (uDest != NO_ADDRESS) { BB_rtls->push_back(pRtl); sequentialDecode = false; pBB = pCfg->newBB(BB_rtls,ONEWAY,1); // Exit the switch now and stop decoding sequentially if the // basic block already existed if (pBB == 0) { sequentialDecode = false; BB_rtls = NULL; break; } // Add the out edge if it is to a destination within the // procedure if (uDest < uUpper) { visit(pCfg, uDest, targets, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { ostrstream ost; ost << "Error: Instruction at " << hex << uAddr; ost << " branches beyond end of section, to "; ost << uDest; error(str(ost)); } } break; } case NWAYJUMP_HRTL: { BB_rtls->push_back(pRtl); // We create the BB as a COMPJUMP type, then change // to an NWAY if it turns out to be a switch stmt pBB = pCfg->newBB(BB_rtls, COMPJUMP, 0); if (isSwitch(pBB, rtl_jump->getDest(), pProc, pBF)) { processSwitch(pBB, delta, pCfg, targets, pBF); } else // Computed jump { // Not a switch statement ostrstream ost; string sKind("JUMP"); if (type == I_COMPCALL) sKind = "CALL"; ost << "COMPUTED " << sKind << " at " << hex << uAddr << endl; warning(str(ost)); BB_rtls = NULL; // New HRTLList for next BB } sequentialDecode = false; break; } case JCOND_HRTL: { uDest = rtl_jump->getFixedDest(); BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, TWOWAY, 2); // Stop decoding sequentially if the basic block already existed // otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else { // Add the out edge if it is to a destination within the // procedure if (uDest < uUpper) { visit(pCfg, uDest, targets, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { ostrstream ost; ost << "Error: Instruction at " << hex << uAddr; ost << " branches beyond end of section, to "; ost << uDest; error(str(ost)); } // Add the fall-through outedge pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; break; } case CALL_HRTL: { HLCall* call = static_cast<HLCall*>(pRtl); // Treat computed and static calls seperately if (call->isComputed()) { BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, COMPCALL, 1); // Stop decoding sequentially if the basic block already // existed otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } else // Static call { BB_rtls->push_back(pRtl); // Find the address of the callee. ADDRESS uNewAddr = call->getFixedDest(); // Add this non computed call site to the set of call // sites which need to be analysed later. pCfg->addCall(call); // Record the called address as the start of a new // procedure if it didn't already exist. if ((uNewAddr != NO_ADDRESS) && prog.findProc(uNewAddr) == NULL) { prog.visitProc(uNewAddr); if (progOptions.trace) cout << "p" << hex << uNewAddr << "\t" << flush; } // Check if this is the _exit function. May prevent us from // attempting to decode invalid instructions. char* name = prog.pBF->SymbolByAddress(uNewAddr); if (name && strcmp(name, "_exit") == 0) { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 0); // Stop decoding sequentially sequentialDecode = false; } else { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 1); if (call->isReturnAfterCall()) { // Constuct the RTLs for the new basic block list<HRTL*>* rtls = new list<HRTL*>(); // The only RTL in the basic block is a high level // return that doesn't have any RTs. rtls->push_back(new HLReturn(0, NULL)); BasicBlock* returnBB = pCfg->newBB(rtls, RET, 0); // Add out edge from call to return pCfg->addOutEdge(pBB, returnBB); // Put a label on the return BB (since it's an // orphan); a jump will be reqd pCfg->setLabel(returnBB); pBB->setJumpReqd(); // Give the enclosing proc a dummy callee epilogue pProc->setEpilogue(new CalleeEpilogue("__dummy", list<string>())); // Mike: do we need to set return locations? // This ends the function sequentialDecode = false; } else { // Add the fall through edge if the block didn't // already exist if (pBB != NULL) pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } } } // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; break; } case RET_HRTL: // Stop decoding sequentially sequentialDecode = false; // Add the RTL to the list BB_rtls->push_back(pRtl); // Create the basic block pBB = pCfg->newBB(BB_rtls, RET, 0); // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; // New HRTLList for next BB break; case SCOND_HRTL: // This is just an ordinary instruction; no control transfer // Fall through case LOW_LEVEL_HRTL: // We must emit empty RTLs for NOPs, because they could be the // destinations of jumps (and splitBB won't work) // Just emit the current instr to the current BB BB_rtls->push_back(pRtl); break; } // switch (pRtl->getKind()) uAddr += inst.numBytes; // Update the RTL's number of bytes for coverage analysis (only) inst.rtl->updateNumBytes(inst.numBytes); // If sequentially decoding, check if the next address happens to // be the start of an existing BB. If so, finish off the current BB // (if any RTLs) as a fallthrough, and no need to decode again // (unless it's an incomplete BB, then we do decode it). // In fact, mustn't decode twice, because it will muck up the // coverage, but also will cause subtle problems like add a call // to the list of calls to be processed, then delete the call RTL // (e.g. Pentium 134.perl benchmark) if (sequentialDecode && pCfg->existsBB(uAddr)) { // Create the fallthrough BB, if there are any RTLs at all if (BB_rtls) { PBB pBB = pCfg->newBB(BB_rtls, FALL, 1); // Add an out edge to this address if (pBB) { pCfg->addOutEdge(pBB, uAddr); BB_rtls = NULL; // Need new list of RTLs } } // Pick a new address to decode from, if the BB is complete if (!pCfg->isIncomplete(uAddr)) sequentialDecode = false; } } // while sequentialDecode // Add this range to the coverage pProc->addRange(start, uAddr); // Must set sequentialDecode back to true sequentialDecode = true; } // while nextAddress() // This pass is to remove up to 3 nops between ranges. // These will be assumed to be padding for alignments of BBs // Possibly removes a lot of ranges that could otherwise be combined ADDRESS a1, a2; COV_CIT ii; Coverage temp; if (pProc->getFirstGap(a1, a2, ii)) { do { int gap = a2 - a1; if (gap < 8) { bool allNops = true; for (int i=0; i < gap; i+= 2) { // Beware endianness! getWord will work properly if (getWord(a1+i+delta) != 0x4e71) { allNops = false; break; } } if (allNops) // Remove this gap, by adding a range equal to the gap // Note: it's not safe to add the range now, so we put // the range into a temp Coverage object to be added later temp.addRange(a1, a2); } } while (pProc->getNextGap(a1, a2, ii)); } // Now add the ranges in temp pProc->addRanges(temp); }
void draw(cursorType* cur, playField* pf, SDL_Surface* screen) { int x,y; listItem* t; //general purpose, reusable psysSet_t ps; SDL_BlitSurface(graphics.boardImg , NULL, screen, &(setting()->bgPos) ); for(x=0;x<NUMTILES;x++) { playAni(graphics.tileAni[x]); } //Draw static bricks for(y=0; y < FIELDSIZE; y++) { for(x=0; x < FIELDSIZE; x++) { //Bricks-Walls if(pf->board[x][y] && pf->board[x][y]->type != RESERVED) { //We treat walls/glue/oneways/switches/evilbricks/copybricks and rembricks as walls (they will have the walltile defined) if( isWall(pf, x, y) ) { drawSprite(screen, graphics.walls[pf->board[x][y]->wall], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } if( pf->board[x][y]->type != STDWALL && graphics.tiles[pf->board[x][y]->type-1]) { //We draw the animated extra-tiles if they exist. if(graphics.tileAni[pf->board[x][y]->type-1]) { if( !isSwitch( pf->board[x][y] ) ) { drawAni(screen, graphics.tileAni[pf->board[x][y]->type-1], pf->board[x][y]->pxx-5, pf->board[x][y]->pxy-5); } else { //We only end here when it's a switch if( (pf->board[x][y]->type==SWON)?pf->board[x][y]->isActive:!pf->board[x][y]->isActive) { drawAni(screen, graphics.tileAni[SWON-1], pf->board[x][y]->pxx-5, pf->board[x][y]->pxy-5); } else { drawAni(screen, graphics.tileAni[SWOFF-1], pf->board[x][y]->pxx-5, pf->board[x][y]->pxy-5); } } //Fall back to the static non-moving tiles if no animation is found. } else { if( !isSwitch( pf->board[x][y] ) ) { drawSprite(screen, graphics.tiles[pf->board[x][y]->type-1], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } else { if( (pf->board[x][y]->type==SWON)?pf->board[x][y]->isActive:!pf->board[x][y]->isActive) { drawSprite(screen, graphics.tiles[SWON-1], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } else { drawSprite(screen, graphics.tiles[SWOFF-1], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } } } } // not a wall. } //Not a reserved brick. /*else if( pf->board[x][y] && pf->board[x][y]->type == RESERVED ) { drawSprite(screen, graphics.tiles[RESERVED-1], x*brickSize+boardOffsetX, y*brickSize+boardOffsetY); }*/ } } //xy loop //Draw moving bricks t=pf->movingList; brickType* b; while( (t = t->next) ) { b=(brickType*)t->data; if(graphics.tileAni[b->type-1]) { drawAni(screen, graphics.tileAni[b->type-1], b->pxx-5, b->pxy-5); } else { drawSprite(screen, graphics.tiles[b->type-1], b->pxx, b->pxy); } } //Particle systems that are between bricks and die animantion runParticlesLayer(screen, PSYS_LAYER_UNDERDEATHANIM); //Draw dying bricks, animation? t=pf->removeList; while( (t = t->next) ) { b=(brickType*)t->data; //Draw base brick if time enough left if(b->tl > (pf->levelInfo->brick_die_ticks/2)) { if(graphics.tileAni[b->type-1]) { drawAni(screen, graphics.tileAni[b->type-1], b->pxx-5, b->pxy-5); } else { drawSprite(screen, graphics.tiles[b->type-1], b->pxx, b->pxy); } } int explFrame = 16*(pf->levelInfo->brick_die_ticks-b->tl)/pf->levelInfo->brick_die_ticks; drawAniFrame(screen, graphics.brickExpl[b->type-1], b->pxx-5, b->pxy-5,explFrame); //Spawn particles for brick death if(explFrame==8 && pf->levelInfo->brickDieParticles) { ps.layer=pf->levelInfo->brickDieParticles; ps.x=b->pxx; ps.y=b->pxy; ps.vel=50; ps.life=750; ps.lifeVar=1000; ps.gravity=0; ps.bounce=0; ps.srcImg=graphics.tiles[b->type-1]->img; ps.srcRect=graphics.tiles[b->type-1]->clip; spawnParticleSystem(&ps); } } //Teleport overlay t = pf->levelInfo->teleList; telePort_t* tp; while( (t=t->next) ) { tp = (telePort_t*)t->data; if(graphics.tileAni[TELESRC-1]) { drawAni(screen, graphics.tileAni[TELESRC-1], boardOffsetX+20*tp->sx-5, boardOffsetY+20*tp->sy-5); } else { drawSprite(screen, graphics.tiles[TELESRC-1], boardOffsetX+20*tp->sx, boardOffsetY+20*tp->sy); } //if cursor is on it, draw the path too if(cur->x == tp->sx && cur->y == tp->sy) { drawTelePath( screen, tp, 1 ); } } //Particles runParticles(screen); //Cursor updateCursor(cur); if(!cur->lock) drawSprite(screen, graphics.curSpr[0], cur->px, cur->py); else drawSprite(screen, graphics.curSpr[1], cur->px, cur->py); if(graphics.curSpr[0] && cur->moving ) { ps.layer=PSYS_LAYER_TOP; ps.x=cur->px; ps.y=cur->py; ps.vel=50; ps.life=100; ps.lifeVar=100; ps.gravity=0; ps.srcImg=graphics.curSpr[0]->img; ps.srcRect=graphics.curSpr[0]->clip; spawnParticleSystem(&ps); } }
Offset* instrJumpOffset(const Op* instr) { static const int8_t jumpMask[] = { #define IMM_NA 0 #define IMM_MA 0 #define IMM_IVA 0 #define IMM_I64A 0 #define IMM_DA 0 #define IMM_SA 0 #define IMM_AA 0 #define IMM_RATA 0 #define IMM_BA 1 #define IMM_BLA 0 // these are jump offsets, but must be handled specially #define IMM_ILA 0 #define IMM_SLA 0 #define IMM_LA 0 #define IMM_IA 0 #define IMM_OA(x) 0 #define IMM_VSA 0 #define ONE(a) IMM_##a #define TWO(a, b) (IMM_##a + 2 * IMM_##b) #define THREE(a, b, c) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c) #define FOUR(a, b, c, d) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c + 8 * IMM_##d) #define O(name, imm, pop, push, flags) imm, OPCODES #undef IMM_NA #undef IMM_MA #undef IMM_IVA #undef IMM_I64A #undef IMM_DA #undef IMM_SA #undef IMM_AA #undef IMM_RATA #undef IMM_LA #undef IMM_IA #undef IMM_BA #undef IMM_BLA #undef IMM_ILA #undef IMM_SLA #undef IMM_OA #undef IMM_VSA #undef ONE #undef TWO #undef THREE #undef FOUR #undef O }; assert(!isSwitch(*instr)); // BLA doesn't work here if (Op(*instr) == OpIterBreak) { uint32_t veclen; std::memcpy(&veclen, instr + 1, sizeof veclen); assert(veclen > 0); auto const target = const_cast<Offset*>( reinterpret_cast<const Offset*>( reinterpret_cast<const uint32_t*>(instr + 1) + 2 * veclen + 1 ) ); return target; } int mask = jumpMask[uint8_t(*instr)]; if (mask == 0) { return nullptr; } int immNum; switch (mask) { case 0: return nullptr; case 1: immNum = 0; break; case 2: immNum = 1; break; case 4: immNum = 2; break; case 8: immNum = 3; break; default: assert(false); return nullptr; } return &getImmPtr(instr, immNum)->u_BA; }
/****************************************************************************** * mv_eth_tool_restore_settings * Description: * restore saved speed/dublex/an settings * INPUT: * netdev Network device structure pointer * OUTPUT * None * RETURN: * 0 for success * *******************************************************************************/ int mv_eth_tool_restore_settings(struct net_device *netdev) { struct eth_port *priv = MV_ETH_PRIV(netdev); int mv_phy_speed, mv_phy_duplex; MV_U32 mv_phy_addr = mvBoardPhyAddrGet(priv->port); MV_ETH_PORT_SPEED mv_mac_speed; MV_ETH_PORT_DUPLEX mv_mac_duplex; int err = -EINVAL; if ((priv == NULL) || (isSwitch(priv))) return -EOPNOTSUPP; switch (priv->speed_cfg) { case SPEED_10: mv_phy_speed = 0; mv_mac_speed = MV_ETH_SPEED_10; break; case SPEED_100: mv_phy_speed = 1; mv_mac_speed = MV_ETH_SPEED_100; break; case SPEED_1000: mv_phy_speed = 2; mv_mac_speed = MV_ETH_SPEED_1000; break; default: return -EINVAL; } switch (priv->duplex_cfg) { case DUPLEX_HALF: mv_phy_duplex = 0; mv_mac_duplex = MV_ETH_DUPLEX_HALF; break; case DUPLEX_FULL: mv_phy_duplex = 1; mv_mac_duplex = MV_ETH_DUPLEX_FULL; break; default: return -EINVAL; } if (priv->autoneg_cfg == AUTONEG_ENABLE) { err = mvNetaSpeedDuplexSet(priv->port, MV_ETH_SPEED_AN, MV_ETH_DUPLEX_AN); if (!err) err = mvEthPhyAdvertiseSet(mv_phy_addr, priv->advertise_cfg); /* Restart AN on PHY enables it */ if (!err) { err = mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT); if (err == MV_TIMEOUT) { MV_ETH_PORT_STATUS ps; mvNetaLinkStatus(priv->port, &ps); if (!ps.linkup) err = 0; } } } else if (priv->autoneg_cfg == AUTONEG_DISABLE) { err = mvEthPhyDisableAN(mv_phy_addr, mv_phy_speed, mv_phy_duplex); if (!err) err = mvNetaSpeedDuplexSet(priv->port, mv_mac_speed, mv_mac_duplex); } else { err = -EINVAL; } return err; }
FuncInfo find_func_info(const Func* func) { auto finfo = FuncInfo(func->unit(), func); auto label_num = uint32_t{0}; auto gen_label = [&] (const char* kind) { return folly::format("{}{}", kind, label_num++).str(); }; auto add_target = [&] (const char* kind, Offset off) -> std::string { auto it = finfo.labels.find(off); if (it != end(finfo.labels)) return it->second; auto const label = gen_label(kind); finfo.labels[off] = label; return label; }; auto find_jump_targets = [&] { auto it = func->unit()->at(func->base()); auto const stop = func->unit()->at(func->past()); auto const bcBase = reinterpret_cast<const Op*>(func->unit()->at(0)); for (; it != stop; it += instrLen(reinterpret_cast<const Op*>(it))) { auto const pop = reinterpret_cast<const Op*>(it); auto const off = func->unit()->offsetOf(pop); if (isSwitch(*pop)) { foreachSwitchTarget(pop, [&] (Offset off) { add_target("L", pop - bcBase + off); }); continue; } auto const target = instrJumpTarget(bcBase, off); if (target != InvalidAbsoluteOffset) { add_target("L", target); continue; } } }; auto find_eh_entries = [&] { for (auto& eh : func->ehtab()) { finfo.ehInfo[&eh] = [&]() -> EHInfo { switch (eh.m_type) { case EHEnt::Type::Catch: { auto catches = EHCatch {}; for (auto& kv : eh.m_catches) { auto const clsName = func->unit()->lookupLitstrId(kv.first); catches.blocks[clsName->data()] = add_target("C", kv.second); } return catches; } case EHEnt::Type::Fault: return EHFault { add_target("F", eh.m_fault) }; } not_reached(); }(); finfo.ehStarts.emplace_back(eh.m_base, &eh); } }; auto find_dv_entries = [&] { for (auto i = uint32_t{0}; i < func->numParams(); ++i) { auto& param = func->params()[i]; if (param.hasDefaultValue()) { add_target("DV", func->params()[i].funcletOff()); } } }; find_jump_targets(); find_eh_entries(); find_dv_entries(); return finfo; }
Offset* instrJumpOffset(PC const origPC) { static const int8_t jumpMask[] = { #define IMM_NA 0 #define IMM_IVA 0 #define IMM_I64A 0 #define IMM_DA 0 #define IMM_SA 0 #define IMM_AA 0 #define IMM_RATA 0 #define IMM_BA 1 #define IMM_BLA 0 // these are jump offsets, but must be handled specially #define IMM_ILA 0 #define IMM_SLA 0 #define IMM_LA 0 #define IMM_IA 0 #define IMM_OA(x) 0 #define IMM_VSA 0 #define IMM_KA 0 #define ONE(a) IMM_##a #define TWO(a, b) (IMM_##a + 2 * IMM_##b) #define THREE(a, b, c) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c) #define FOUR(a, b, c, d) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c + 8 * IMM_##d) #define O(name, imm, pop, push, flags) imm, OPCODES #undef IMM_NA #undef IMM_IVA #undef IMM_I64A #undef IMM_DA #undef IMM_SA #undef IMM_AA #undef IMM_RATA #undef IMM_LA #undef IMM_IA #undef IMM_BA #undef IMM_BLA #undef IMM_ILA #undef IMM_SLA #undef IMM_OA #undef IMM_VSA #undef IMM_KA #undef ONE #undef TWO #undef THREE #undef FOUR #undef O }; auto pc = origPC; auto const op = decode_op(pc); assert(!isSwitch(op)); // BLA doesn't work here if (op == OpIterBreak) { auto const veclen = decode_raw<uint32_t>(pc); assert(veclen > 0); auto const target = const_cast<Offset*>( reinterpret_cast<const Offset*>( reinterpret_cast<const uint32_t*>(pc) + 2 * veclen ) ); return target; } int mask = jumpMask[size_t(op)]; if (mask == 0) { return nullptr; } int immNum; switch (mask) { case 0: return nullptr; case 1: immNum = 0; break; case 2: immNum = 1; break; case 4: immNum = 2; break; case 8: immNum = 3; break; default: assert(false); return nullptr; } return &getImmPtr(origPC, immNum)->u_BA; }
Offset* instrJumpOffset(const PC origPC) { static const int8_t jumpMask[] = { #define IMM_NA 0 #define IMM_IVA 0 #define IMM_I64A 0 #define IMM_DA 0 #define IMM_SA 0 #define IMM_AA 0 #define IMM_RATA 0 #define IMM_BA 1 #define IMM_BLA 0 // these are jump offsets, but must be handled specially #define IMM_ILA 0 #define IMM_I32LA 0 #define IMM_BLLA 0 #define IMM_SLA 0 #define IMM_LA 0 #define IMM_IA 0 #define IMM_CAR 0 #define IMM_CAW 0 #define IMM_OA(x) 0 #define IMM_VSA 0 #define IMM_KA 0 #define IMM_LAR 0 #define IMM_FCA 0 #define ONE(a) IMM_##a #define TWO(a, b) (IMM_##a + 2 * IMM_##b) #define THREE(a, b, c) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c) #define FOUR(a, b, c, d) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c + 8 * IMM_##d) #define FIVE(a, b, c, d, e) (IMM_##a + 2 * IMM_##b + 4 * IMM_##c + 8 * IMM_##d + 16 * IMM_##e) #define O(name, imm, pop, push, flags) imm, OPCODES #undef IMM_NA #undef IMM_IVA #undef IMM_I64A #undef IMM_DA #undef IMM_SA #undef IMM_AA #undef IMM_RATA #undef IMM_LA #undef IMM_IA #undef IMM_CAR #undef IMM_CAW #undef IMM_BA #undef IMM_BLA #undef IMM_ILA #undef IMM_I32LA #undef IMM_BLLA #undef IMM_SLA #undef IMM_OA #undef IMM_VSA #undef IMM_KA #undef IMM_LAR #undef IMM_FCA #undef ONE #undef TWO #undef THREE #undef FOUR #undef FIVE #undef O }; auto pc = origPC; auto const op = decode_op(pc); assertx(!isSwitch(op)); // BLA doesn't work here if (op == OpIterBreak) { // offset is imm number 0 return const_cast<Offset*>(reinterpret_cast<const Offset*>(pc)); } int mask = jumpMask[size_t(op)]; if (mask == 0) { return nullptr; } int immNum; switch (mask) { case 0: return nullptr; case 1: immNum = 0; break; case 2: immNum = 1; break; case 4: immNum = 2; break; case 8: immNum = 3; break; case 16: immNum = 4; break; default: assertx(false); return nullptr; } return &getImmPtr(origPC, immNum)->u_BA; }