Skip to content

Commit

Permalink
support for MSP430 and PIC18 microcontrollers
Browse files Browse the repository at this point in the history
  • Loading branch information
bdcht committed Aug 28, 2014
1 parent 0d34eed commit f478894
Show file tree
Hide file tree
Showing 22 changed files with 2,150 additions and 11 deletions.
2 changes: 1 addition & 1 deletion amoco/arch/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def buildspec(self):
go = +1
chklen = True
if direction=='<': # format goes from high bits to low bits
fmt = reversed(fmt)
fmt = list(reversed(fmt))
go = -1
if size == '*':
self.size = 0
Expand Down
Empty file added amoco/arch/msp430/__init__.py
Empty file.
189 changes: 189 additions & 0 deletions amoco/arch/msp430/asm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/env python

# This code is part of Amoco
# Copyright (C) 2013 Axel Tillequin ([email protected])
# published under GPLv2 license

from .env import *

from amoco.cas.utils import *

def autoinc(i,fmap):
rr = i.misc['autoinc']
sz = 2 if i.BW else 1
if rr is not None: fmap[rr] = fmap(rr+sz)

# Ref: MSP430x1xx Family Users's Guide (Rev. F)
#------------------------------------------------------------------------------

def i_MOV(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
fmap[dst] = fmap(src)
autoinc(i,fmap)

def i_ADD(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst))
fmap[dst] = result
fmap[cf] = carry
fmap[zf] = (result==0)
fmap[nf] = result[dst.size-1:dst.size]
fmap[vf] = overflow
autoinc(i,fmap)

def i_ADDC(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst),fmap(cf))
fmap[dst] = result
fmap[cf] = carry
fmap[zf] = (result==0)
fmap[nf] = result[dst.size-1:dst.size]
fmap[vf] = overflow
autoinc(i,fmap)

def i_SUB(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst))
fmap[dst] = result
fmap[cf] = carry
fmap[zf] = (result==0)
fmap[nf] = result[dst.size-1:dst.size]
fmap[vf] = overflow
autoinc(i,fmap)

def i_CMP(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst))
fmap[cf] = carry
fmap[zf] = (result==0)
fmap[nf] = result[dst.size-1:dst.size]
fmap[vf] = overflow
autoinc(i,fmap)

def i_SUBC(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst),fmap(cf))
fmap[dst] = result
fmap[cf] = carry
fmap[zf] = (result==0)
fmap[nf] = result[dst.size-1:dst.size]
fmap[vf] = overflow
autoinc(i,fmap)

def i_AND(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result = fmap(src&dst)
fmap[dst] = result
fmap[nf] = result[dst.size-1:dst.size]
fmap[zf] = (result==0)
fmap[cf] = ~fmap(zf)
fmap[vf] = bit0
autoinc(i,fmap)

def i_XOR(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
fmap[dst] = fmap(src^dst)
fmap[nf] = result[dst.size-1:dst.size]
fmap[zf] = (result==0)
fmap[cf] = ~fmap(zf)
fmap[vf] = bit0
autoinc(i,fmap)

def i_BIC(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
fmap[dst] = fmap((~src)&dst)
autoinc(i,fmap)

def i_BIS(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
fmap[dst] = fmap(src|dst)
autoinc(i,fmap)

def i_BIT(i,fmap):
fmap[pc] = fmap[pc]+i.length
src,dst = i.operands
result = fmap(src|dst)
fmap[nf] = result[dst.size-1:dst.size]
fmap[zf] = (result==0)
fmap[cf] = ~fmap(zf)
fmap[vf] = bit0
autoinc(i,fmap)

def i_CALL(i,fmap):
fmap[pc] = fmap[pc]+i.length
dst = i.operands[0]
tmp = fmap(dst)
fmap[sp] = fmap(sp-2)
fmap[mem(sp,pc.size)] = fmap(pc)
fmap[pc] = tmp
autoinc(i,fmap)

#def i_RETI(i,fmap):
# dst = i.operands[0]

#def i_DADD(i,fmap):
# NotImplemented

def i_RRC(i,fmap):
fmap[pc] = fmap[pc]+i.length
dst = i.operands[0]
res,carry = RORWithCarry(fmap(dst),1,fmap(cf))
fmap[dst] = res
fmap[cf] = carry
fmap[nf] = res[dst.size-1:dst.size]
fmap[zf] = (res==0)
fmap[vf] = bit0

def i_SWPB(i,fmap):
fmap[pc] = fmap[pc]+i.length
dst = i.operands[0]
res = composer([fmap(dst[8:16]),fmap(dst[0:8])])
fmap[dst] = res

def i_RRA(i,fmap):
fmap[pc] = fmap[pc]+i.length
dst = i.operands[0]
res,carry = RORWithCarry(fmap(dst),1,fmap(dst[dst.size-1:dst.size]))
fmap[dst] = res
fmap[cf] = carry
fmap[nf] = res[dst.size-1:dst.size]
fmap[zf] = (res==0)
fmap[vf] = bit0

def i_SXT(i,fmap):
fmap[pc] = fmap[pc]+i.length
dst = i.operands[0]
res = fmap(dst[0:8]).signextend(16)
fmap[dst] = res
fmap[nf] = res[dst.size-1:dst.size]
fmap[zf] = (res==0)
fmap[cf] = ~fmap(zf)
fmap[vf] = bit0

def i_PUSH(i,fmap):
src = i.operands[0]
fmap[sp] = fmap(sp-src.size)
fmap[mem(sp,src.size)] = fmap(src)
autoinc(i,fmap)

def i_JMP(i,fmap):
offset = i.operands[0]*2
fmap[pc] = fmap(pc+i.length+offset)
autoinc(i,fmap)

def i_Jcc(i,fmap):
fmap[pc] = fmap[pc]+i.length
offset = i.operands[0]*2
cond = fmap(COND[i.cond][1])
fmap[pc] = tst(cond,fmap(pc+offset),fmap(pc))
autoinc(i,fmap)
17 changes: 17 additions & 0 deletions amoco/arch/msp430/cpu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from amoco.arch.msp430.asm import *
# expose "microarchitecture" (instructions semantics)
uarch = dict(filter(lambda kv:kv[0].startswith('i_'),locals().iteritems()))

#import specifications:
from amoco.arch.core import instruction, disassembler

instruction.set_uarch(uarch)

from amoco.arch.msp430.formats import MSP430_synthetic
instruction.set_formatter(MSP430_synthetic)

#define disassembler:
from amoco.arch.msp430 import spec_msp430

disassemble = disassembler([spec_msp430])
disassemble.maxlen = 6
44 changes: 44 additions & 0 deletions amoco/arch/msp430/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python

# This code is part of Amoco
# Copyright (C) 2014 Axel Tillequin ([email protected])
# published under GPLv2 license

# import expressions:
from amoco.cas.expressions import *

#reference documentation:
# MSP430x1xx User's Guide, Texas Instruments, 2006.

#registers :
#-----------

# general registers:
R = [reg('r%d'%x,16) for x in range(16)]

pc = R[0]
sp = R[1]
sr = R[2]
cg1 = sr
cg2 = R[3]

pc.ref = 'pc'
sp.ref = 'sp'
sr.ref = 'sr'

cf = slc(sr,0,1,ref='cf')
zf = slc(sr,1,1,ref='zf')
nf = slc(sr,2,1,ref='nf')
vf = slc(sr,8,1,ref='vf')

COND = {
0b000: ('NE/NZ',zf==bit0),
0b001: ('EQ/Z',zf==bit1),
0b010: ('NC/LO',cf==bit0),
0b011: ('C/HS',cf==bit1),
0b100: ('N',nf==bit1),
0b101: ('GE',vf==nf),
0b110: ('L',vf!=nf),
0b111: ('',bit1),
}

89 changes: 89 additions & 0 deletions amoco/arch/msp430/formats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from .env import *
from amoco.arch.core import Formatter

def mnemo(i,pad=8):
m = i.mnemonic
if i.BW: m+='.B'
return m.lower().ljust(pad)

def mnemo_cond(i):
m = mnemo(i,pad=0).replace('jcc','j')
s = COND[i.cond][0].split('/')[0]
return (m+s).lower().ljust(8)

def ops(i):
s = []
for o in i.operands:
if o._is_slc:
assert i.BW
o = o.x
if o._is_reg:
s.append(str(o))
elif o._is_cst:
s.append('#%s'%o)
else:
assert o._is_mem
a = o.a.base
if a._is_reg:
if i.misc['autoinc'] is a:
s.append('@%s+'%a)
else:
s.append('@%s'%a)
elif a._is_cst:
s.append('&%s'%a)
else:
assert a._is_eqn
l,r = a.l,a.r
if l==pc and i.address:
s.append('*%s'%(i.address+r))
else:
s.append('%s(%s)'%(r,l))
return ', '.join(s)

MSP430_full_formats = {
'msp430_doubleop' : [mnemo, ops],
'msp430_singleop' : [mnemo, ops],
'msp430_jumps' : [mnemo_cond, ops],
}

MSP430_full = Formatter(MSP430_full_formats)

def MSP430_synthetic(null,i):
s = MSP430_full(i)
if i.mnemonic == 'ADDC' and i.operands[0]==0:
return s.replace('addc','adc').replace('#0x0,','')
if i.mnemonic == 'DADD' and i.operands[0]==0:
return s.replace('dadd','dadc').replace('#0x0,','')
if i.mnemonic == 'CMP' and i.operands[0]==0:
return s.replace('cmp','tst').replace('#0x0,','')
if i.mnemonic == 'MOV':
if i.operands[1] is pc:
return s.replace('mov','br').replace(',pc','')
elif i.operands[0]==0:
return s.replace('mov','clr').replace('#0x0,','')
elif i.misc['autoinc'] is sp:
if i.operands[1] is pc: return 'ret'
return s.replace('mov','pop').replace('@sp+,','')
if i.mnemonic == 'BIC':
if i.operands[1] is sr:
if i.operands[0]==1: return 'clrc'
if i.operands[0]==4: return 'clrn'
if i.operands[0]==2: return 'clrz'
if i.operands[0]==8: return 'dint'
if i.mnemonic == 'BIS':
if i.operands[1] is sr:
if i.operands[0]==1: return 'setc'
if i.operands[0]==4: return 'setn'
if i.operands[0]==2: return 'setz'
if i.operands[0]==8: return 'eint'
if i.mnemonic == 'SUB' and i.operands[0]==1:
return s.replace('sub','dec').replace('#0x1,','')
if i.mnemonic == 'SUB' and i.operands[0]==2:
return s.replace('sub','decd').replace('#0x2,','')
if i.mnemonic == 'ADD' and i.operands[0]==1:
return s.replace('add','inc').replace('#0x1,','')
if i.mnemonic == 'ADD' and i.operands[0]==2:
return s.replace('add','incd').replace('#0x2,','')
if i.mnemonic == 'XOR' and i.operands[0].signextend(16).value==-1:
return 'inv '+ops(i).split(',')[-1].strip()
return s
Loading

0 comments on commit f478894

Please sign in to comment.