Skip to content

Commit f478894

Browse files
committed
support for MSP430 and PIC18 microcontrollers
1 parent 0d34eed commit f478894

22 files changed

+2150
-11
lines changed

amoco/arch/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ def buildspec(self):
286286
go = +1
287287
chklen = True
288288
if direction=='<': # format goes from high bits to low bits
289-
fmt = reversed(fmt)
289+
fmt = list(reversed(fmt))
290290
go = -1
291291
if size == '*':
292292
self.size = 0

amoco/arch/msp430/__init__.py

Whitespace-only changes.

amoco/arch/msp430/asm.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/env python
2+
3+
# This code is part of Amoco
4+
# Copyright (C) 2013 Axel Tillequin (bdcht3@gmail.com)
5+
# published under GPLv2 license
6+
7+
from .env import *
8+
9+
from amoco.cas.utils import *
10+
11+
def autoinc(i,fmap):
12+
rr = i.misc['autoinc']
13+
sz = 2 if i.BW else 1
14+
if rr is not None: fmap[rr] = fmap(rr+sz)
15+
16+
# Ref: MSP430x1xx Family Users's Guide (Rev. F)
17+
#------------------------------------------------------------------------------
18+
19+
def i_MOV(i,fmap):
20+
fmap[pc] = fmap[pc]+i.length
21+
src,dst = i.operands
22+
fmap[dst] = fmap(src)
23+
autoinc(i,fmap)
24+
25+
def i_ADD(i,fmap):
26+
fmap[pc] = fmap[pc]+i.length
27+
src,dst = i.operands
28+
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst))
29+
fmap[dst] = result
30+
fmap[cf] = carry
31+
fmap[zf] = (result==0)
32+
fmap[nf] = result[dst.size-1:dst.size]
33+
fmap[vf] = overflow
34+
autoinc(i,fmap)
35+
36+
def i_ADDC(i,fmap):
37+
fmap[pc] = fmap[pc]+i.length
38+
src,dst = i.operands
39+
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst),fmap(cf))
40+
fmap[dst] = result
41+
fmap[cf] = carry
42+
fmap[zf] = (result==0)
43+
fmap[nf] = result[dst.size-1:dst.size]
44+
fmap[vf] = overflow
45+
autoinc(i,fmap)
46+
47+
def i_SUB(i,fmap):
48+
fmap[pc] = fmap[pc]+i.length
49+
src,dst = i.operands
50+
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst))
51+
fmap[dst] = result
52+
fmap[cf] = carry
53+
fmap[zf] = (result==0)
54+
fmap[nf] = result[dst.size-1:dst.size]
55+
fmap[vf] = overflow
56+
autoinc(i,fmap)
57+
58+
def i_CMP(i,fmap):
59+
fmap[pc] = fmap[pc]+i.length
60+
src,dst = i.operands
61+
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst))
62+
fmap[cf] = carry
63+
fmap[zf] = (result==0)
64+
fmap[nf] = result[dst.size-1:dst.size]
65+
fmap[vf] = overflow
66+
autoinc(i,fmap)
67+
68+
def i_SUBC(i,fmap):
69+
fmap[pc] = fmap[pc]+i.length
70+
src,dst = i.operands
71+
result,carry,overflow = AddWithCarry(fmap(src),fmap(dst),fmap(cf))
72+
fmap[dst] = result
73+
fmap[cf] = carry
74+
fmap[zf] = (result==0)
75+
fmap[nf] = result[dst.size-1:dst.size]
76+
fmap[vf] = overflow
77+
autoinc(i,fmap)
78+
79+
def i_AND(i,fmap):
80+
fmap[pc] = fmap[pc]+i.length
81+
src,dst = i.operands
82+
result = fmap(src&dst)
83+
fmap[dst] = result
84+
fmap[nf] = result[dst.size-1:dst.size]
85+
fmap[zf] = (result==0)
86+
fmap[cf] = ~fmap(zf)
87+
fmap[vf] = bit0
88+
autoinc(i,fmap)
89+
90+
def i_XOR(i,fmap):
91+
fmap[pc] = fmap[pc]+i.length
92+
src,dst = i.operands
93+
fmap[dst] = fmap(src^dst)
94+
fmap[nf] = result[dst.size-1:dst.size]
95+
fmap[zf] = (result==0)
96+
fmap[cf] = ~fmap(zf)
97+
fmap[vf] = bit0
98+
autoinc(i,fmap)
99+
100+
def i_BIC(i,fmap):
101+
fmap[pc] = fmap[pc]+i.length
102+
src,dst = i.operands
103+
fmap[dst] = fmap((~src)&dst)
104+
autoinc(i,fmap)
105+
106+
def i_BIS(i,fmap):
107+
fmap[pc] = fmap[pc]+i.length
108+
src,dst = i.operands
109+
fmap[dst] = fmap(src|dst)
110+
autoinc(i,fmap)
111+
112+
def i_BIT(i,fmap):
113+
fmap[pc] = fmap[pc]+i.length
114+
src,dst = i.operands
115+
result = fmap(src|dst)
116+
fmap[nf] = result[dst.size-1:dst.size]
117+
fmap[zf] = (result==0)
118+
fmap[cf] = ~fmap(zf)
119+
fmap[vf] = bit0
120+
autoinc(i,fmap)
121+
122+
def i_CALL(i,fmap):
123+
fmap[pc] = fmap[pc]+i.length
124+
dst = i.operands[0]
125+
tmp = fmap(dst)
126+
fmap[sp] = fmap(sp-2)
127+
fmap[mem(sp,pc.size)] = fmap(pc)
128+
fmap[pc] = tmp
129+
autoinc(i,fmap)
130+
131+
#def i_RETI(i,fmap):
132+
# dst = i.operands[0]
133+
134+
#def i_DADD(i,fmap):
135+
# NotImplemented
136+
137+
def i_RRC(i,fmap):
138+
fmap[pc] = fmap[pc]+i.length
139+
dst = i.operands[0]
140+
res,carry = RORWithCarry(fmap(dst),1,fmap(cf))
141+
fmap[dst] = res
142+
fmap[cf] = carry
143+
fmap[nf] = res[dst.size-1:dst.size]
144+
fmap[zf] = (res==0)
145+
fmap[vf] = bit0
146+
147+
def i_SWPB(i,fmap):
148+
fmap[pc] = fmap[pc]+i.length
149+
dst = i.operands[0]
150+
res = composer([fmap(dst[8:16]),fmap(dst[0:8])])
151+
fmap[dst] = res
152+
153+
def i_RRA(i,fmap):
154+
fmap[pc] = fmap[pc]+i.length
155+
dst = i.operands[0]
156+
res,carry = RORWithCarry(fmap(dst),1,fmap(dst[dst.size-1:dst.size]))
157+
fmap[dst] = res
158+
fmap[cf] = carry
159+
fmap[nf] = res[dst.size-1:dst.size]
160+
fmap[zf] = (res==0)
161+
fmap[vf] = bit0
162+
163+
def i_SXT(i,fmap):
164+
fmap[pc] = fmap[pc]+i.length
165+
dst = i.operands[0]
166+
res = fmap(dst[0:8]).signextend(16)
167+
fmap[dst] = res
168+
fmap[nf] = res[dst.size-1:dst.size]
169+
fmap[zf] = (res==0)
170+
fmap[cf] = ~fmap(zf)
171+
fmap[vf] = bit0
172+
173+
def i_PUSH(i,fmap):
174+
src = i.operands[0]
175+
fmap[sp] = fmap(sp-src.size)
176+
fmap[mem(sp,src.size)] = fmap(src)
177+
autoinc(i,fmap)
178+
179+
def i_JMP(i,fmap):
180+
offset = i.operands[0]*2
181+
fmap[pc] = fmap(pc+i.length+offset)
182+
autoinc(i,fmap)
183+
184+
def i_Jcc(i,fmap):
185+
fmap[pc] = fmap[pc]+i.length
186+
offset = i.operands[0]*2
187+
cond = fmap(COND[i.cond][1])
188+
fmap[pc] = tst(cond,fmap(pc+offset),fmap(pc))
189+
autoinc(i,fmap)

amoco/arch/msp430/cpu.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from amoco.arch.msp430.asm import *
2+
# expose "microarchitecture" (instructions semantics)
3+
uarch = dict(filter(lambda kv:kv[0].startswith('i_'),locals().iteritems()))
4+
5+
#import specifications:
6+
from amoco.arch.core import instruction, disassembler
7+
8+
instruction.set_uarch(uarch)
9+
10+
from amoco.arch.msp430.formats import MSP430_synthetic
11+
instruction.set_formatter(MSP430_synthetic)
12+
13+
#define disassembler:
14+
from amoco.arch.msp430 import spec_msp430
15+
16+
disassemble = disassembler([spec_msp430])
17+
disassemble.maxlen = 6

amoco/arch/msp430/env.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env python
2+
3+
# This code is part of Amoco
4+
# Copyright (C) 2014 Axel Tillequin (bdcht3@gmail.com)
5+
# published under GPLv2 license
6+
7+
# import expressions:
8+
from amoco.cas.expressions import *
9+
10+
#reference documentation:
11+
# MSP430x1xx User's Guide, Texas Instruments, 2006.
12+
13+
#registers :
14+
#-----------
15+
16+
# general registers:
17+
R = [reg('r%d'%x,16) for x in range(16)]
18+
19+
pc = R[0]
20+
sp = R[1]
21+
sr = R[2]
22+
cg1 = sr
23+
cg2 = R[3]
24+
25+
pc.ref = 'pc'
26+
sp.ref = 'sp'
27+
sr.ref = 'sr'
28+
29+
cf = slc(sr,0,1,ref='cf')
30+
zf = slc(sr,1,1,ref='zf')
31+
nf = slc(sr,2,1,ref='nf')
32+
vf = slc(sr,8,1,ref='vf')
33+
34+
COND = {
35+
0b000: ('NE/NZ',zf==bit0),
36+
0b001: ('EQ/Z',zf==bit1),
37+
0b010: ('NC/LO',cf==bit0),
38+
0b011: ('C/HS',cf==bit1),
39+
0b100: ('N',nf==bit1),
40+
0b101: ('GE',vf==nf),
41+
0b110: ('L',vf!=nf),
42+
0b111: ('',bit1),
43+
}
44+

amoco/arch/msp430/formats.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from .env import *
2+
from amoco.arch.core import Formatter
3+
4+
def mnemo(i,pad=8):
5+
m = i.mnemonic
6+
if i.BW: m+='.B'
7+
return m.lower().ljust(pad)
8+
9+
def mnemo_cond(i):
10+
m = mnemo(i,pad=0).replace('jcc','j')
11+
s = COND[i.cond][0].split('/')[0]
12+
return (m+s).lower().ljust(8)
13+
14+
def ops(i):
15+
s = []
16+
for o in i.operands:
17+
if o._is_slc:
18+
assert i.BW
19+
o = o.x
20+
if o._is_reg:
21+
s.append(str(o))
22+
elif o._is_cst:
23+
s.append('#%s'%o)
24+
else:
25+
assert o._is_mem
26+
a = o.a.base
27+
if a._is_reg:
28+
if i.misc['autoinc'] is a:
29+
s.append('@%s+'%a)
30+
else:
31+
s.append('@%s'%a)
32+
elif a._is_cst:
33+
s.append('&%s'%a)
34+
else:
35+
assert a._is_eqn
36+
l,r = a.l,a.r
37+
if l==pc and i.address:
38+
s.append('*%s'%(i.address+r))
39+
else:
40+
s.append('%s(%s)'%(r,l))
41+
return ', '.join(s)
42+
43+
MSP430_full_formats = {
44+
'msp430_doubleop' : [mnemo, ops],
45+
'msp430_singleop' : [mnemo, ops],
46+
'msp430_jumps' : [mnemo_cond, ops],
47+
}
48+
49+
MSP430_full = Formatter(MSP430_full_formats)
50+
51+
def MSP430_synthetic(null,i):
52+
s = MSP430_full(i)
53+
if i.mnemonic == 'ADDC' and i.operands[0]==0:
54+
return s.replace('addc','adc').replace('#0x0,','')
55+
if i.mnemonic == 'DADD' and i.operands[0]==0:
56+
return s.replace('dadd','dadc').replace('#0x0,','')
57+
if i.mnemonic == 'CMP' and i.operands[0]==0:
58+
return s.replace('cmp','tst').replace('#0x0,','')
59+
if i.mnemonic == 'MOV':
60+
if i.operands[1] is pc:
61+
return s.replace('mov','br').replace(',pc','')
62+
elif i.operands[0]==0:
63+
return s.replace('mov','clr').replace('#0x0,','')
64+
elif i.misc['autoinc'] is sp:
65+
if i.operands[1] is pc: return 'ret'
66+
return s.replace('mov','pop').replace('@sp+,','')
67+
if i.mnemonic == 'BIC':
68+
if i.operands[1] is sr:
69+
if i.operands[0]==1: return 'clrc'
70+
if i.operands[0]==4: return 'clrn'
71+
if i.operands[0]==2: return 'clrz'
72+
if i.operands[0]==8: return 'dint'
73+
if i.mnemonic == 'BIS':
74+
if i.operands[1] is sr:
75+
if i.operands[0]==1: return 'setc'
76+
if i.operands[0]==4: return 'setn'
77+
if i.operands[0]==2: return 'setz'
78+
if i.operands[0]==8: return 'eint'
79+
if i.mnemonic == 'SUB' and i.operands[0]==1:
80+
return s.replace('sub','dec').replace('#0x1,','')
81+
if i.mnemonic == 'SUB' and i.operands[0]==2:
82+
return s.replace('sub','decd').replace('#0x2,','')
83+
if i.mnemonic == 'ADD' and i.operands[0]==1:
84+
return s.replace('add','inc').replace('#0x1,','')
85+
if i.mnemonic == 'ADD' and i.operands[0]==2:
86+
return s.replace('add','incd').replace('#0x2,','')
87+
if i.mnemonic == 'XOR' and i.operands[0].signextend(16).value==-1:
88+
return 'inv '+ops(i).split(',')[-1].strip()
89+
return s

0 commit comments

Comments
 (0)