コード例 #1
0
ファイル: thread.py プロジェクト: sophiawisdom/cricket-py3
 def __init__(self, ROM, align=4, skipInitialization=False):
     if not skipInitialization:
         self.r = _RegisterList()
         self.s = [0] * 32
         self.d = [0] * 32
         self.q = [0] * 16
         self.cpsr = Status(16)
         self.spsr = Status(16)
         self.fcpsr = FloatingPointStatus()
         self.memory = Memory(ROM, align)
         self.r[13] = StackPointer(0)
         self.r[14] = Return
         self.onBranch = lambda p, i, t: None
コード例 #2
0
ファイル: thread.py プロジェクト: Maroc-OS/EcaFretni
 def __init__(self, ROM, align=4, skipInitialization=False):
     if not skipInitialization:
         self.r = _RegisterList()
         self.s = [0] * 32
         self.d = [0] * 32
         self.q = [0] * 16
         self.cpsr = Status(16)
         self.spsr = Status(16)
         self.fcpsr = FloatingPointStatus()
         self.memory = Memory(ROM, align)
         self.r[13] = StackPointer(0)
         self.r[14] = Return
         self.onBranch = lambda p, i, t: None
コード例 #3
0
ファイル: thread.py プロジェクト: Maroc-OS/EcaFretni
class Thread(object):
    '''
    This class represents a thread of execution on ARM. A thread consists of
    registers and a :class:`~cpu.Memory`.

    .. attribute:: r

        The general registers r0 to r15 as a list.

    .. attribute:: cpsr

        The Current Program Status Register.

    .. attribute:: spsr

        The Saved Program Status Register.

    .. attribute:: fpscr

        The Floating-point Status and Control Register.


    .. attribute:: s

        The VFP registers s0 to s31 as an array. These registers hold 32-bit
        integers or IEEE single-precision (binary32) numbers.

    .. attribute:: d

        The VFP/NEON registers d0 to d31 as an array. These registers hold
        64-bit integers or IEEE double-precision (binary64) numbers.


    .. attribute:: q

        The NEON regiters q0 to q15 as an array. These registers hold 128-bit
        integers.

        .. note::

            In the actual ARM chip, the :attr:`s`, :attr:`d` and :attr:`q`
            registers share the same memory location. To simplify the
            implementation, this feature will not be replicated.

    .. attribute:: memory

        The :class:`~cpu.memory.Memory` associated to this thread.

    .. attribute:: onBranch

        This is a user-defined callback callable. This callable is called when
        the :meth:`~cpu.arm.instruction.Instruction.execute` method caused
        :attr:`pc` to depart from its normal flow. The callable's signature must
        be of the form::

            def onBranch(previousLocation, instruction, thread):
                ...

    '''

    def __init__(self, ROM, align=4, skipInitialization=False):
        if not skipInitialization:
            self.r = _RegisterList()
            self.s = [0] * 32
            self.d = [0] * 32
            self.q = [0] * 16
            self.cpsr = Status(16)
            self.spsr = Status(16)
            self.fcpsr = FloatingPointStatus()
            self.memory = Memory(ROM, align)
            self.r[13] = StackPointer(0)
            self.r[14] = Return
            self.onBranch = lambda p, i, t: None

    def __copy__(self):
        'Create a completely isolated copy (fork) of the current thread.'
        retval = type(self)(None, skipInitialization=True)
        retval.r = deepcopy(self.r)
        retval.s = deepcopy(self.s)
        retval.d = deepcopy(self.d)
        retval.q = deepcopy(self.q)
        retval.cpsr = copy(self.cpsr)
        retval.spsr = copy(self.spsr)
        retval.fcpsr = copy(self.fcpsr)
        retval.memory = self.memory.__copy__()
        retval.onBranch = self.onBranch
        return retval

    @property
    def sl(self):
        'This is an alias to ``r[10]``. The acronym means "stack limit".'
        return self.r[10]
    @sl.setter
    def sl(self, value):
        self.r[10] = value

    @property
    def fp(self):
        'This is an alias to ``r[11]``. The acronym means "frame pointer".'
        return self.r[11]
    @fp.setter
    def fp(self, value):
        self.r[11] = value

    @property
    def ip(self):
        'This is an alias to ``r[12]``. The acronym means "instruction pointer".'
        return self.r[12]
    @ip.setter
    def ip(self, value):
        self.r[12] = value

    @property
    def sp(self):
        '''This is an alias to ``r[13]``. The acronym means "stack pointer". The
        value should be a :class:`~cpu.pointers.StackPointer` pointing to the
        top of the stack.'''
        return self.r[REG_SP]
    @sp.setter
    def sp(self, value):
        self.r[REG_SP] = value

    @property
    def lr(self):
        '''This is an alias to ``r[14]``. The acronym means "link register".
        This register often holds the address to the caller, although sometimes
        it is also used as a general-purpose register.'''
        return self.r[REG_LR]
    @lr.setter
    def lr(self, value):
        self.r[REG_LR] = value

    @property
    def pc(self):
        '''This is an alias to ``r[15]``. The acronym means "program counter".
        This is a special register which always points to 4 or 8 bytes after the
        current instruction on read. Modifying this value will cause the program
        jump to another position.'''
        return self.r[REG_PC]
    @pc.setter
    def pc(self, value):
        self.r[REG_PC] = value

    @property
    def pcRaw(self):
        '''The raw pc register without the 4 or 8 byte offset.'''
        return self.r.pcRaw

    @property
    def instructionSet(self):
        '''Get/set the processor's current instruction set.

        +-------+-----------------+
        | Value | Instruction set |
        +=======+=================+
        | 0     | ARM             |
        +-------+-----------------+
        | 1     | Thumb           |
        +-------+-----------------+
        | 2     | Jazelle         |
        +-------+-----------------+
        | 3     | ThumbEE         |
        +-------+-----------------+

        .. note::

            Always use this property to change the instruction set instead of
            ``thread.cpsr.instructionSet``. This allows the pc offset to be
            updated correctly.
        '''
        return self.cpsr.instructionSet
    @instructionSet.setter
    def instructionSet(self, newIS):
        self.cpsr.instructionSet = newIS
        self.adjustPcOffset()

    def adjustPcOffset(self):
        'Adjust the read offset for :attr:`pc` to match the current instruction set.'
        self.r.pcOffset = 4 if self.cpsr.T else 8

    def fetch(self):
        '''Fetch an instruction at the current position. Returns a little-endian
        encoded integer that contains the full instruction, and the length of
        the instruction. You need to call :meth:`advance` manually to move the
        program counter.'''
        cpsr = self.cpsr
        instrSet = cpsr.instructionSet
        itstate = cpsr.IT
        thumbMode = instrSet & 1
        loc = self.r.pcRaw
        try:
            instr = self.memory.get(loc, length=4)
        except struct.error:
            # not enough instruction left to get. try length 2 in thumb mode.
            if thumbMode:
                instr = self.memory.get(loc, length=2)
                if instr >= 0b11101 << 11:
                    raise
            else:
                raise
        instrLen = 4
        if thumbMode:
            # Thumb instructions can be 2-byte long.
            instr = (instr & 0xffff) << 16 | instr >> 16
            if instr < (0b11101 << 27):
                instr >>= 16
                instrLen = 2
        cond = COND_NONE
        if itstate:
            cond = itstate >> 4
            cpsr.IT = ITAdvance(itstate)

        return InstructionDecoder.create(instr, instrLen, instrSet, cond)

    def execute(self):
        'Run 1 instruction and return that instruction.'
        instr = self.fetch()
        instr.execute(self)
        return instr

    def run(self, address=None):
        '''Run many instructions until hitting *address* (if provided) or
        ``Return``, whichever comes first.'''
        while self.pcRaw != Return or address is not None and self.pcRaw != address:
            self.execute()

    def forceReturn(self):
        'Force early return from a function by performing ``bx lr``.'
        (self.pc, self.cpsr.T) = fixPCAddrBX(self.lr)
        self.adjustPcOffset()
コード例 #4
0
ファイル: thread.py プロジェクト: sophiawisdom/cricket-py3
class Thread(object):
    '''
    This class represents a thread of execution on ARM. A thread consists of
    registers and a :class:`~cpu.Memory`.

    .. attribute:: r

        The general registers r0 to r15 as a list.

    .. attribute:: cpsr

        The Current Program Status Register.

    .. attribute:: spsr

        The Saved Program Status Register.

    .. attribute:: fpscr

        The Floating-point Status and Control Register.


    .. attribute:: s

        The VFP registers s0 to s31 as an array. These registers hold 32-bit
        integers or IEEE single-precision (binary32) numbers.

    .. attribute:: d

        The VFP/NEON registers d0 to d31 as an array. These registers hold
        64-bit integers or IEEE double-precision (binary64) numbers.


    .. attribute:: q

        The NEON regiters q0 to q15 as an array. These registers hold 128-bit
        integers.

        .. note::

            In the actual ARM chip, the :attr:`s`, :attr:`d` and :attr:`q`
            registers share the same memory location. To simplify the
            implementation, this feature will not be replicated.

    .. attribute:: memory

        The :class:`~cpu.memory.Memory` associated to this thread.

    .. attribute:: onBranch

        This is a user-defined callback callable. This callable is called when
        the :meth:`~cpu.arm.instruction.Instruction.execute` method caused
        :attr:`pc` to depart from its normal flow. The callable's signature must
        be of the form::

            def onBranch(previousLocation, instruction, thread):
                ...

    '''
    def __init__(self, ROM, align=4, skipInitialization=False):
        if not skipInitialization:
            self.r = _RegisterList()
            self.s = [0] * 32
            self.d = [0] * 32
            self.q = [0] * 16
            self.cpsr = Status(16)
            self.spsr = Status(16)
            self.fcpsr = FloatingPointStatus()
            self.memory = Memory(ROM, align)
            self.r[13] = StackPointer(0)
            self.r[14] = Return
            self.onBranch = lambda p, i, t: None

    def __copy__(self):
        'Create a completely isolated copy (fork) of the current thread.'
        retval = type(self)(None, skipInitialization=True)
        retval.r = deepcopy(self.r)
        retval.s = deepcopy(self.s)
        retval.d = deepcopy(self.d)
        retval.q = deepcopy(self.q)
        retval.cpsr = copy(self.cpsr)
        retval.spsr = copy(self.spsr)
        retval.fcpsr = copy(self.fcpsr)
        retval.memory = self.memory.__copy__()
        retval.onBranch = self.onBranch
        return retval

    @property
    def sl(self):
        'This is an alias to ``r[10]``. The acronym means "stack limit".'
        return self.r[10]

    @sl.setter
    def sl(self, value):
        self.r[10] = value

    @property
    def fp(self):
        'This is an alias to ``r[11]``. The acronym means "frame pointer".'
        return self.r[11]

    @fp.setter
    def fp(self, value):
        self.r[11] = value

    @property
    def ip(self):
        'This is an alias to ``r[12]``. The acronym means "instruction pointer".'
        return self.r[12]

    @ip.setter
    def ip(self, value):
        self.r[12] = value

    @property
    def sp(self):
        '''This is an alias to ``r[13]``. The acronym means "stack pointer". The
        value should be a :class:`~cpu.pointers.StackPointer` pointing to the
        top of the stack.'''
        return self.r[REG_SP]

    @sp.setter
    def sp(self, value):
        self.r[REG_SP] = value

    @property
    def lr(self):
        '''This is an alias to ``r[14]``. The acronym means "link register".
        This register often holds the address to the caller, although sometimes
        it is also used as a general-purpose register.'''
        return self.r[REG_LR]

    @lr.setter
    def lr(self, value):
        self.r[REG_LR] = value

    @property
    def pc(self):
        '''This is an alias to ``r[15]``. The acronym means "program counter".
        This is a special register which always points to 4 or 8 bytes after the
        current instruction on read. Modifying this value will cause the program
        jump to another position.'''
        return self.r[REG_PC]

    @pc.setter
    def pc(self, value):
        self.r[REG_PC] = value

    @property
    def pcRaw(self):
        '''The raw pc register without the 4 or 8 byte offset.'''
        return self.r.pcRaw

    @property
    def instructionSet(self):
        '''Get/set the processor's current instruction set.

        +-------+-----------------+
        | Value | Instruction set |
        +=======+=================+
        | 0     | ARM             |
        +-------+-----------------+
        | 1     | Thumb           |
        +-------+-----------------+
        | 2     | Jazelle         |
        +-------+-----------------+
        | 3     | ThumbEE         |
        +-------+-----------------+

        .. note::

            Always use this property to change the instruction set instead of
            ``thread.cpsr.instructionSet``. This allows the pc offset to be
            updated correctly.
        '''
        return self.cpsr.instructionSet

    @instructionSet.setter
    def instructionSet(self, newIS):
        self.cpsr.instructionSet = newIS
        self.adjustPcOffset()

    def adjustPcOffset(self):
        'Adjust the read offset for :attr:`pc` to match the current instruction set.'
        self.r.pcOffset = 4 if self.cpsr.T else 8

    def fetch(self):
        '''Fetch an instruction at the current position. Returns a little-endian
        encoded integer that contains the full instruction, and the length of
        the instruction. You need to call :meth:`advance` manually to move the
        program counter.'''
        cpsr = self.cpsr
        instrSet = cpsr.instructionSet
        itstate = cpsr.IT
        thumbMode = instrSet & 1
        loc = self.r.pcRaw
        try:
            instr = self.memory.get(loc, length=4)
        except struct.error:
            # not enough instruction left to get. try length 2 in thumb mode.
            if thumbMode:
                instr = self.memory.get(loc, length=2)
                if instr >= 0b11101 << 11:
                    raise
            else:
                raise
        instrLen = 4
        if thumbMode:
            # Thumb instructions can be 2-byte long.
            instr = (instr & 0xffff) << 16 | instr >> 16
            if instr < (0b11101 << 27):
                instr >>= 16
                instrLen = 2
        cond = COND_NONE
        if itstate:
            cond = itstate >> 4
            cpsr.IT = ITAdvance(itstate)

        return InstructionDecoder.create(instr, instrLen, instrSet, cond)

    def execute(self):
        'Run 1 instruction and return that instruction.'
        instr = self.fetch()
        instr.execute(self)
        return instr

    def run(self, address=None):
        '''Run many instructions until hitting *address* (if provided) or
        ``Return``, whichever comes first.'''
        while self.pcRaw != Return or address is not None and self.pcRaw != address:
            self.execute()

    def forceReturn(self):
        'Force early return from a function by performing ``bx lr``.'
        (self.pc, self.cpsr.T) = fixPCAddrBX(self.lr)
        self.adjustPcOffset()