具有共享构建问题的power8汇编代码,具有TOC的保存和恢复功能

时间:2017-01-03 21:59:38

标签: powerpc

我有以下汇编代码

from PyQt5.QtWidgets import QGraphicsItem, QMenu
from PyQt5.QtGui import QTransform, QPen, QPainter, QColor, QBrush
from PyQt5.QtCore import Qt, QPointF, QRectF, QEvent
from math import sqrt


def scaleRect(rect, scale_x, scale_y):
    T = QTransform.fromScale(scale_x, scale_y)
    return T.mapRect(rect)

def debugPrintTransformMatrix(T):
    print(str(T.m11()) + '  ' + str(T.m12()) + '  ' + str(T.m13()))
    print(str(T.m21()) + '  ' + str(T.m22()) + '  ' + str(T.m23()))
    print(str(T.m31()) + '  ' + str(T.m32()) + '  ' + str(T.m33()))

# Assumes no shearing or stretching.   
# Only Rotation, Translation, and Scaling. 
def extractTransformScale(T):
    # This is math matrix notation transposed (debug print self.sceneTransform() to see)
    Sx = sqrt(T.m11()**2 + T.m12()**2)      
    Sy = sqrt(T.m21()**2 + T.m22()**2)
    return Sx, Sy    

def extractTransformTranslate(T):
    return T.m31(), T.m32()


class Object(QGraphicsItem):
    def sceneEvent(self, event):
        if event.type() == QEvent.GraphicsSceneMouseMove: 
            # move, scale, or rotate
            if self._mode in ['scale', 'rotate']:
                mouse_pos = event.scenePos()
                last_pos = event.lastScenePos()
                if self._mode == 'scale':
                    s = self.mouseScalingFactors(mouse_pos, last_pos)
                    self.setTransform(self.transform().scale(*s))
                if self._mode == 'rotate':
                    r = self.mouseRotationAngle(mouse_pos, last_pos)
                    self.setRotation(self.rotation() + r)
                return True

        return super().sceneEvent(event)

    def __init__(self):
        super().__init__()
        self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsSelectable)
        self._selectionPen = QPen(Qt.black, 1.0, style=Qt.DotLine, cap=Qt.FlatCap)
        self._lastPos = QPointF(0, 0)
        self.setPos(self._lastPos)
        self._mode = 'neutral'

    def setRenderHints(self, painter):
        painter.setRenderHints(QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing | QPainter.TextAntialiasing)

    def boundingRectExtraScale(self):
        return (1.2 , 1.2) 

    def mouseScalingFactors(self, pos, last_pos):
        delta = pos - last_pos
        return (1.01 ** delta.x(), 1.01 ** delta.y())

    def mouseRotationAngle(self, pos, last_pos):
        return 1   #TODO

    def createDefaultContextMenu(self):
        menu = QMenu()
        if self._mode == 'neutral':
            menu.addAction('Scale').triggered.connect(lambda: self.setMode('scale'))
            menu.addAction('Rotate').triggered.connect(lambda: self.setMode('rotate'))
        else:
            menu.addAction('Done Editing').triggered.connect(lambda: self.setMode('neutral'))
        return menu

    def contextMenuEvent(self, event):
            menu = self.createDefaultContextMenu()
            menu.exec(event.screenPos())

    def setMode(self, mode):
        self._mode = mode

    def setSelected(self, selected):
        super().setSelected(selected)
        self.update()


class ShapedObject(Object):
    def __init__(self):
        super().__init__()
        self._shape = {
            'name' : 'ellipse',
            'radius': 35
        }
        self._brush = QBrush(Qt.darkGreen)
        self._pen = QPen(Qt.yellow, 3)        

    def shapeDef(self):
        return self._shape

    def boundingRect(self):
        rect = self.shapeRect()
        s = self.boundingRectExtraScale()
        return scaleRect(rect, *s)

    def shape(self):      #TODO QPainterPath shape for collision detection
        # Should call self.boundingRectExtraScale()
        return super().shape()

    def paint(self, painter, option, widget):
        self.setRenderHints(painter)
        #super().paint(painter, option, widget)

        shape = self.shapeDef()
        name = shape['name']

        painter.setBrush(self._brush)
        painter.setPen(self._pen)

        painter.save()

        # ********** HERE IS THE PROBLEM ************* 

        debugPrintTransformMatrix(painter.transform())
        painter.rotate(5)
        debugPrintTransformMatrix(painter.transform())

        rect = self.shapeRect()
        if name == 'ellipse':
            painter.drawEllipse(rect)


        painter.restore()  


    def shapeRect(self):
        shape = self.shapeDef()
        name = shape['name']
        if name == 'ellipse':
            r = shape['radius']
            rect = QRectF(-r,  -r, 2*r, 2*r)
        return rect


####

import sys
from PyQt5.QtWidgets import QMainWindow, QGraphicsScene, QGraphicsView, QApplication

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QMainWindow()
    view = QGraphicsView()
    scene = QGraphicsScene()
    view.setScene(scene)
    window.setCentralWidget(view)

    ellipse = ShapedObject()
    scene.addItem(ellipse)

    window.show()

    sys.exit(app.exec_())

这适用于静态构建,但共享构建会导致分段错误   .machine power8 .abiversion 2 .section ".toc","aw" .section .text GLOBAL(myfunc) myfunc: stdu 1,-240(1) mflr 0 std 0, 0*8(1) mfcr 8 std 8, 1*8(1) std 2, 2*8(1) # Save all non-volatile registers R14-R31 std 14, 4*8(1) ... # Save all the non-volatile FPRs ... stwu 1, -48(1) bl function_call nop addi 1, 1, 48 ld 0, 0*8(1) mtlr 0 ld 8, 1*8(1) ld 2, 2*8(1) ... # epilogue, restore stack frame ,是否应该在power8 w.r.t TOC中以不同方式处理共享版本?

1 个答案:

答案 0 :(得分:1)

POWER 8和以前的处理器之间的调用约定是相同的。但是,对于ABIv1和ABIv2之间的TOC指针(r2)处理有一些变化。

在ABIv2中,调用者未在r2中建立TOC指针;被调用的函数应该对全局入口点执行此操作(即,TOC指针可能与被调用者中使用的指针不同)。为此,ABIv2函数将有一个设置r2

的序言
0000000000000000 <foo>:
   0:   00 00 4c 3c     addis   r2,r12,0
   4:   00 00 42 38     addi    r2,r2,0

- 这取决于r12包含函数全局入口点的地址(这些0值将在最终链接时替换为实际偏移量。)

我在示例中没有看到任何适当的代码设置r12。你确定你在那里遵守v2 ABI吗?

ABIv2规范可在此处获取:https://members.openpowerfoundation.org/document/dl/576第2.3.2节与此问题最相关。