view python/ppci/target/thumb/armtarget.py @ 367:577ed7fb3fe4

Try to make thumb work again
author Windel Bouwman
date Fri, 21 Mar 2014 10:27:57 +0100
parents 3bb7dcfe5529
children 6df89163e114
line wrap: on
line source

import struct
from ..basetarget import Register, Instruction, Target, Label, Alignment
from .instructions import Add2, Sub, Sub3, Add3, Cmp, Lsl, Orr, Add, Cmp2, Sub2, Add2, Mul, And
from .instructions import Dcd, Pop, Push, Yield, Mov2, Mov3
from .instructions import B, Bl, Bne, Beq, Blt, Bgt
from .instructions import Ldr, Str2, Ldr2, Str1, Ldr1, Ldr3

from .frame import ArmFrame
from .arminstructionselector import ArmInstructionSelector
from ..arm.registers import R0, R1, R2, R3, R4, R5, R6, R7, SP, LR, PC
from ..arm.registers import register_range


""" ARM target description. """

# TODO: encode this in DSL (domain specific language)
# TBD: is this required?
# TODO: make a difference between armv7 and armv5?

thumb_assembly_rules = []
def add_rule(rhs, f):
    thumb_assembly_rules.append(('instruction', rhs, f))


class ThumbTarget(Target):
    def __init__(self):
        super().__init__('thumb')
        self.ins_sel = ArmInstructionSelector()
        self.FrameClass = ArmFrame
        self.add_rules()

        # Add lowering options:
        self.add_lowering(Str2, lambda im: Str2(im.src[1], im.src[0], im.others[0]))
        self.add_lowering(Ldr2, lambda im: Ldr2(im.dst[0], im.src[0], im.others[0]))
        self.add_lowering(Ldr3, lambda im: Ldr3(im.dst[0],  im.others[0]))
        self.add_lowering(Mov3, lambda im: Mov3(im.dst[0],  im.others[0]))
        self.add_lowering(Add2, lambda im: Add2(im.dst[0], im.src[0], im.others[0]))
        self.add_lowering(Sub2, lambda im: Sub2(im.dst[0], im.src[0], im.others[0]))
        self.add_lowering(Mov2, lambda im: Mov2(im.dst[0], im.src[0]))
        self.add_lowering(Add3, lambda im: Add3(im.dst[0], im.src[0], im.src[1]))
        self.add_lowering(Sub3, lambda im: Sub3(im.dst[0], im.src[0], im.src[1]))
        self.add_lowering(Mul, lambda im: Mul(im.src[0], im.dst[0]))
        self.add_lowering(And, lambda im: And(im.src[0], im.src[1]))
        self.add_lowering(Orr, lambda im: Orr(im.src[0], im.src[1]))
        self.add_lowering(Lsl, lambda im: Lsl(im.src[0], im.src[1]))
        self.add_lowering(Cmp, lambda im: Cmp(im.src[0], im.src[1]))

    def add_rules(self):

        # Add instructions:
        self.add_keyword('dcd')
        self.add_instruction(['dcd', 'imm32'], lambda rhs: Dcd(rhs[1]))

        self.add_keyword('mov')
        self.add_instruction(['mov', 'reg8', ',', 'reg8'],
                lambda rhs: Mov2(rhs[1], rhs[3]))

        self.add_instruction(['mov', 'reg8', ',', 'imm8'],
                lambda rhs: Mov3(rhs[1], rhs[3]))

        self.add_keyword('add')
        self.add_instruction(['add', 'reg8', ',', 'reg8', ',', 'imm3'],
                lambda rhs: Add2(rhs[1], rhs[3], rhs[5]))

        self.add_instruction(['add', 'reg8', ',', 'reg8', ',', 'reg8'],
                lambda rhs: Add3(rhs[1], rhs[3], rhs[5]))

        self.add_keyword('sub')
        self.add_instruction(['sub', 'reg8', ',', 'reg8', ',', 'imm3'],
                lambda rhs: Sub(rhs[1], rhs[3], rhs[5]))

        self.add_instruction(['sub', 'sp', ',', 'sp', ',', 'imm8'],
                lambda rhs: Sub(SP, SP, rhs[5]))

        self.add_instruction(['add', 'sp', ',', 'sp', ',', 'imm8'],
                lambda rhs: Add(SP, SP, rhs[5]))

        self.add_keyword('cmp')
        self.add_instruction(['cmp', 'reg8', ',', 'reg8'],
                lambda rhs: Cmp(rhs[1], rhs[3]))
        self.add_instruction(['cmp', 'reg8', ',', 'imm8'],
                lambda rhs: Cmp2(rhs[1], rhs[3]))

        self.add_keyword('lsl')
        self.add_instruction(['lsl', 'reg8', ',', 'reg8'],
                lambda rhs: Lsl(rhs[1], rhs[3]))

        self.add_keyword('str')
        self.add_instruction(['str', 'reg8', ',', '[', 'reg8', '+', 'imm5', ']'],
                lambda rhs: Str2(rhs[1], rhs[4], rhs[6]))

        self.add_keyword('ldr')
        self.add_instruction(['ldr', 'reg8', ',', '[', 'reg8', '+', 'imm5', ']'],
                lambda rhs: Ldr2(rhs[1], rhs[4], rhs[6]))

        self.add_instruction(['str', 'reg8', ',', '[', 'sp', '+', 'imm8', ']'],
                lambda rhs: Str1(rhs[1], rhs[6]))

        self.add_instruction(['ldr', 'reg8', ',', '[', 'sp', '+', 'imm8', ']'],
                lambda rhs: Ldr1(rhs[1], rhs[6]))

        self.add_keyword('pop')
        self.add_instruction(['pop', 'reg_list'], lambda rhs: Pop(rhs[1]))
        self.add_keyword('push')
        self.add_instruction(['push', 'reg_list'], lambda rhs: Push(rhs[1]))

        self.add_keyword('yield')
        self.add_instruction(['yield'], lambda rhs: Yield())

        self.add_keyword('b')
        self.add_keyword('bl')
        self.add_instruction(['b', 'ID'], lambda rhs: B(rhs[1].val))
        self.add_instruction(['bl', 'ID'], lambda rhs: Bl(rhs[1].val))
        self.add_keyword('beq')
        self.add_keyword('bne')
        self.add_keyword('blt')
        self.add_keyword('bgt')
        self.add_instruction(['beq', 'ID'], lambda rhs: Beq(rhs[1].val))
        self.add_instruction(['bne', 'ID'], lambda rhs: Bne(rhs[1].val))
        self.add_instruction(['blt', 'ID'], lambda rhs: Blt(rhs[1].val))
        self.add_instruction(['bgt', 'ID'], lambda rhs: Bgt(rhs[1].val))

        self.add_keyword('align')
        self.add_instruction(['align', 'imm8'], lambda rhs: Alignment(rhs[1]))

        self.add_instruction(['ldr', 'reg8', ',', 'ID'],
                lambda rhs: Ldr(rhs[1], rhs[3].val))

        # Additional rules:

        # Register list grammar:
        self.add_rule('reg_list', ['{', 'reg_list_inner', '}'],
            lambda rhs: rhs[1])
        self.add_rule('reg_list_inner', ['reg_or_range'],
            lambda rhs: rhs[0])
        self.add_rule('reg_list_inner', ['reg_or_range', ',', 'reg_list_inner'],
            lambda rhs: rhs[0] | rhs[2])
        self.add_rule('reg_or_range', ['reg8'], lambda rhs: {rhs[0]})
        self.add_rule('reg_or_range', ['lr'], lambda rhs: {LR})
        self.add_rule('reg_or_range', ['pc'], lambda rhs: {PC})

        self.add_rule('reg_or_range', ['reg8', '-', 'reg8'],
            lambda rhs: register_range(rhs[0], rhs[2]))

        self.add_keyword('r0')
        self.add_keyword('r1')
        self.add_keyword('r2')
        self.add_keyword('r3')
        self.add_keyword('r4')
        self.add_keyword('r5')
        self.add_keyword('r6')
        self.add_keyword('r7')
        self.add_keyword('sp')
        self.add_keyword('lr')
        self.add_keyword('pc')
        self.add_rule('reg8', ['r0'], lambda rhs: R0)
        self.add_rule('reg8', ['r1'], lambda rhs: R1)
        self.add_rule('reg8', ['r2'], lambda rhs: R2)
        self.add_rule('reg8', ['r3'], lambda rhs: R3)
        self.add_rule('reg8', ['r4'], lambda rhs: R4)
        self.add_rule('reg8', ['r5'], lambda rhs: R5)
        self.add_rule('reg8', ['r6'], lambda rhs: R6)
        self.add_rule('reg8', ['r7'], lambda rhs: R7)