view python/arm_cm3.py @ 205:d77cb5962cc5

Added some handcoded arm code generation
author Windel Bouwman
date Sun, 23 Jun 2013 18:23:18 +0200
parents ca1ea402f6a1
children 6c6bf8890d8a
line wrap: on
line source

import struct, types
from target import Register, Instruction, Target
from asmnodes import ASymbol, ANumber
from ppci import CompilerError
import ir

def u16(h):
    return struct.pack('<H', h)

def u32(x):
    return struct.pack('<I', x)

armtarget = Target('arm')

class ArmReg(Register):
    def __init__(self, num, name):
        super().__init__(name)
        self.num = num

class ArmImm:
    def __init__(self, i):
        self.i = i

class RegOp:
    def __init__(self, num):
        assert num < 8
        self.num = num

    @classmethod
    def Create(cls, vop):
        if type(vop) is ASymbol:
            name = vop.name
            regs = {}
            for r in armtarget.registers:
                regs[r.name] = r
            if name in regs:
                r = regs[name]
                return cls(r.num)

class Label:
    def __init__(self, name):
        self.name = name

    @classmethod
    def Create(cls, vop):
        if type(vop) is ASymbol:
            name = vop.name
            return cls(name)

class Imm8:
    def __init__(self, imm):
        assert imm < 256
        self.imm = imm

    @classmethod
    def Create(cls, vop):
        if type(vop) is ANumber and vop.number < 256:
            return cls(vop.number)
        
class Imm3:
    def __init__(self, imm):
        assert imm < 8
        assert type(imm) is int
        self.imm = imm

    @classmethod
    def Create(cls, vop):
        if type(vop) is ANumber and vop.number < 8:
            return cls(vop.number)

class RegisterSet:
    def __init__(self, regs):
        pass

# 8 bit registers:
r0 = ArmReg(0, 'r0')
armtarget.registers.append(r0)
r4 = ArmReg(4, 'r4')
armtarget.registers.append(r4)
r5 = ArmReg(5, 'r5')
armtarget.registers.append(r5)
r6 = ArmReg(6, 'r6')
armtarget.registers.append(r6)
r7 = ArmReg(7, 'r7')
armtarget.registers.append(r7)

class ArmInstruction(Instruction):
    pass

@armtarget.instruction
class ldr_ins(ArmInstruction):
    mnemonic = 'ldr'
    opcode = 1337
    irpattern = 'todo'

@armtarget.instruction
class dcd_ins(ArmInstruction):
    mnemonic = 'dcd'
    def __init__(self, expr):
        self.expr = expr
    def encode(self):
        return u32(self.expr)

class Operand2:
    def __init__(self, expr):
        if type(expr) is ANumber:
            pass
    pass

@armtarget.instruction
class mov_ins(ArmInstruction):
    """ mov Rd, imm8, move immediate value into register """
    mnemonic = 'mov'
    opcode = 4 # 00100 Rd(3) imm8
    operands = (RegOp, Imm8)
    irpattern = ir.ImmLoad
    def __init__(self, rd, imm):
        self.imm = imm.imm
        self.r = rd.num

    @classmethod
    def FromIr(cls, ir_ins):
        pass

    def encode(self):
        rd = self.r
        opcode = self.opcode
        imm8 = self.imm
        h = (opcode << 11) | (rd << 8) | imm8
        return u16(h)
        
@armtarget.instruction
class movregreg_ins(ArmInstruction):
    """ mov Rd, Rm """
    mnemonic = 'mov'
    opcode = 8 # 01000 Rd(3) imm8
    operands = (RegOp, RegOp)
    def __init__(self, rd, rm):
        self.rd = rd
        self.rm = rm
    def encode(self):
        rd = self.rd.num
        D = (rd & 0x8) >> 3
        assert D < 2
        rd = rd & 0x7
        rm = self.rm.num
        assert rm < 16
        opcode = self.opcode
        h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
        return u16(h)

@armtarget.instruction
class addregregimm3_ins(ArmInstruction):
    """ add Rd, Rn, imm3 """
    mnemonic = 'add'
    opcode = 3 # 00011
    operands = (RegOp, RegOp, Imm3)
    irpattern = 3
    def __init__(self, rd, rn, imm3):
        self.rd = rd
        self.rn = rn
        self.imm3 = imm3
    def encode(self):
        rd = self.rd.num
        rn = self.rn.num
        imm3 = self.imm3.imm
        opcode = self.opcode
        h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
        return u16(h)

@armtarget.instruction
class cmpregimm8_ins(ArmInstruction):
    """ cmp Rn, imm8 """
    mnemonic = 'cmp'
    opcode = 5 # 00101
    operands = (RegOp, Imm8)
    def __init__(self, rn, imm):
        self.rn = rn
        self.imm = imm
    def encode(self):
        rn = self.rn.num
        imm = self.imm.imm
        opcode = self.opcode
        h = (opcode << 11) | (rn << 8) | imm
        return u16(h)

@armtarget.instruction
class jmp_ins(ArmInstruction):
    operands = (Label)
    mnemonic = 'jmp'
    def __init__(self, target_label):
        self.target = target_label
    def fixUp(self):
        pass
    def encode(self):
        h = 1337 # TODO
        return u16(h)

@armtarget.instruction
class push_ins(ArmInstruction):
    operands = (RegisterSet)
    mnemonic = 'push'
    def __init__(self, regs):
        self.regs = regs
    def encode(self):
        return u16(0)

@armtarget.instruction
class pop_ins(ArmInstruction):
    operands = (RegisterSet)
    mnemonic = 'pop'
    def __init__(self, regs):
        self.regs = regs
    def encode(self):
        return u16(0)

@armtarget.instruction
class yield_ins(ArmInstruction):
    operands = ()
    mnemonic = 'yield'
    def encode(self):
        return u16(0xbf10)