annotate applications/ide/compiler/assembler.py @ 39:600f48b74799

Move ide
author windel
date Fri, 03 Feb 2012 18:40:43 +0100
parents ide/compiler/assembler.py@92df07bc2081
children
rev   line source
1
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
1 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
2 Assembler code generation functions
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
3 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
5 from .errors import Error
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
6
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
7 modrm = {'rax': 0, 'rbx': 1}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
9 # Table 3.1 of the intel manual:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
10 # use REX.W on the table below:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
11 regs64 = {'rax': 0,'rcx':1,'rdx':2,'rbx':3,'rsp':4,'rbp':5,'rsi':6,'rdi':7,'r8':0,'r9':1,'r10':2,'r11':3,'r12':4,'r13':5,'r14':6,'r15':7}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
12 regs32 = {'eax': 0, 'ecx':1, 'edx':2, 'ebx': 3, 'esp': 4, 'ebp': 5, 'esi':6, 'edi':7}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
13 regs8 = {'al':0,'cl':1,'dl':2,'bl':3,'ah':4,'ch':5,'dh':6,'bh':7}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
14
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
15 # Calculation of the rexb bit:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
16 rexbit = {'rax': 0, 'rcx':0, 'rdx':0, 'rbx': 0, 'rsp': 0, 'rbp': 0, 'rsi':0, 'rdi':0,'r8':1,'r9':1,'r10':1,'r11':1,'r12':1,'r13':1,'r14':1,'r15':1}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
17
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
18 # Helper functions:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
19 def imm64(x):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
20 """ represent 64 bits integer in little endian 8 bytes"""
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
21 if x < 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
22 x = x + (1 << 64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
23 x = x & 0xFFFFFFFFFFFFFFFF
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
24 return [ (x >> (p*8)) & 0xFF for p in range(8) ]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
25
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
26 def imm32(x):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
27 """ represent 32 bits integer in little endian 4 bytes"""
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
28 if x < 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
29 x = x + (1 << 32)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
30 x = x & 0xFFFFFFFF
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
31 return [ (x >> (p*8)) & 0xFF for p in range(4) ]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
32
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
33 def imm8(x):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
34 if x < 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
35 x = x + (1 << 8)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
36 x = x & 0xFF
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
37 return [ x ]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
38
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
39 def modrm(mod=0, rm=0, reg=0):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
40 """ Construct the modrm byte from its components """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
41 assert(mod <= 3)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
42 assert(rm <= 7)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
43 assert(reg <= 7)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
44 return (mod << 6) | (reg << 3) | rm
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
45
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
46 def rex(w=0, r=0, x=0, b=0):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
47 """ Create a REX prefix byte """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
48 assert(w <= 1)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
49 assert(r <= 1)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
50 assert(x <= 1)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
51 assert(b <= 1)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
52 return 0x40 | (w<<3) | (r<<2) | (x<<1) | b
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
53
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
54 def sib(ss=0, index=0, base=0):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
55 assert(ss <= 3)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
56 assert(index <= 7)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
57 assert(base <= 7)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
58 return (ss << 6) | (index << 3) | base
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
59
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
60 tttn = {'L':0xc,'G':0xf,'NE':0x5,'GE':0xd,'LE':0xe, 'E':0x4}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
61
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
62 # Actual instructions:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
63 def nearjump(distance, condition=None):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
64 """ jmp imm32 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
65 lim = (1<<30)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
66 if abs(distance) > lim:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
67 Error('near jump cannot jump over more than {0} bytes'.format(lim))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
68 if condition:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
69 if distance < 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
70 distance -= 6 # Skip own instruction
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
71 opcode = 0x80 | tttn[condition] # Jcc imm32
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
72 return [0x0F, opcode] + imm32(distance)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
73 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
74 if distance < 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
75 distance -= 5 # Skip own instruction
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
76 return [ 0xE9 ] + imm32(distance)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
77
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
78 def shortjump(distance, condition=None):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
79 """ jmp imm8 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
80 lim = 118
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
81 if abs(distance) > lim:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
82 Error('short jump cannot jump over more than {0} bytes'.format(lim))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
83 if distance < 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
84 distance -= 2 # Skip own instruction
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
85 if condition:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
86 opcode = 0x70 | tttn[condition] # Jcc rel8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
87 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
88 opcode = 0xeb # jmp rel8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
89 return [opcode] + imm8(distance)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
90
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
91 # Helper that determines jump type:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
92 def reljump(distance):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
93 if abs(distance) < 110:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
94 return shortjump(distance)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
95 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
96 return nearjump(distance)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
97
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
98 def push(reg):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
99 if reg in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
100 if rexbit[reg] == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
101 return [0x41, 0x50 + regs64[reg]]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
102 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
103 return [0x50 + regs64[reg]]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
104 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
105 Error('push for {0} not implemented'.format(reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
106
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
107 def pop(reg):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
108 if reg in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
109 if rexbit[reg] == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
110 rexprefix = rex(b=1)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
111 opcode = 0x58 + regs64[reg]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
112 return [rexprefix, opcode]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
113 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
114 opcode = 0x58 + regs64[reg]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
115 return [ opcode ]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
116 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
117 Error('pop for {0} not implemented'.format(reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
118
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
119 def INT(number):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
120 opcode = 0xcd
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
121 return [opcode] + imm8(number)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
122
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
123 def syscall():
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
124 return [0x0F, 0x05]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
125
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
126 def call(distance):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
127 if type(distance) is int:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
128 return [0xe8]+imm32(distance)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
129 elif type(distance) is str and distance in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
130 reg = distance
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
131 opcode = 0xFF # 0xFF /2 == call r/m64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
132 mod_rm = modrm(mod=3, reg=2, rm=regs64[reg])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
133 if rexbit[reg] == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
134 rexprefix = rex(b=rexbit[reg])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
135 return [rexprefix, opcode, mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
136 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
137 return [opcode, mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
138 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
139 Error('Cannot call to {0}'.format(distance))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
140
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
141 def ret():
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
142 return [ 0xc3 ]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
143
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
144 def increg64(reg):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
145 assert(reg in regs64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
146 rexprefix = rex(w=1, b=rexbit[reg])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
147 opcode = 0xff
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
148 mod_rm = modrm(mod=3, rm=regs64[reg])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
149 return [rexprefix, opcode, mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
150
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
151 def prepost8(r8, rm8):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
152 assert(r8 in regs8)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
153 pre = []
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
154 if type(rm8) is list:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
155 # TODO: merge mem access with prepost for 64 bits
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
156 if len(rm8) == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
157 base, = rm8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
158 if type(base) is str and base in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
159 assert(not base in ['rbp', 'rsp', 'r12', 'r13'])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
160 mod_rm = modrm(mod=0, rm=regs64[base], reg=regs8[r8])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
161 if rexbit[base] == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
162 pre.append(rex(b=1))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
163 post = [mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
164 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
165 Error('One arg of type {0} not implemented'.format(base))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
166 elif len(rm8) == 2:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
167 base, offset = rm8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
168 assert(type(offset) is int)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
169 assert(base in regs64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
170
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
171 if base == 'rsp' or base == 'r12':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
172 Error('Cannot use rsp or r12 as base yet')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
173 if rexbit[base] == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
174 pre.append( rex(b=1) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
175 mod_rm = modrm(mod=1, rm=regs64[base], reg=regs8[r8])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
176 post = [mod_rm] + imm8(offset)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
177 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
178 Error('not supporting prepost8 with list len {0}'.format(len(rm8)))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
179 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
180 Error('Not supporting move with reg8 {0}'.format(r8))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
181 return pre, post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
182
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
183 def prepost(r64, rm64):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
184 assert(r64 in regs64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
185 if type(rm64) is list:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
186 if len(rm64) == 3:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
187 base, index, disp = rm64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
188 assert(base in regs64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
189 assert(index in regs64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
190 assert(type(disp) is int)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
191 # Assert that no special cases are used:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
192 # TODO: swap base and index to avoid special cases
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
193 # TODO: exploit special cases and make better code
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
194 assert(index != 'rsp')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
195
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
196 rexprefix = rex(w=1, r=rexbit[r64], x=rexbit[index], b=rexbit[base])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
197 # mod=1 and rm=4 indicates a SIB byte: [--][--]+imm8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
198 mod_rm = modrm(mod=1, rm=4, reg=regs64[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
199 si_b = sib(ss=0, index=regs64[index], base=regs64[base])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
200 return [rexprefix], [mod_rm, si_b] + imm8(disp)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
201 elif len(rm64) == 2:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
202 base, offset = rm64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
203 assert(type(offset) is int)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
204 if base == 'RIP':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
205 # RIP pointer relative addressing mode!
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
206 rexprefix = rex(w=1, r=rexbit[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
207 mod_rm = modrm(mod=0, rm=5, reg=regs64[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
208 return [rexprefix], [mod_rm] + imm32(offset)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
209 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
210 assert(base in regs64)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
211
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
212 if base == 'rsp' or base == 'r12':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
213 # extended function that uses SIB byte
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
214 rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[base])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
215 # rm=4 indicates a SIB byte follows
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
216 mod_rm = modrm(mod=1, rm=4, reg=regs64[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
217 # index=4 indicates that index is not used
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
218 si_b = sib(ss=0, index=4, base=regs64[base])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
219 return [rexprefix], [mod_rm, si_b] + imm8(offset)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
220 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
221 rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[base])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
222 mod_rm = modrm(mod=1, rm=regs64[base], reg=regs64[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
223 return [rexprefix], [mod_rm] + imm8(offset)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
224 elif len(rm64) == 1:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
225 offset = rm64[0]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
226 if type(offset) is int:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
227 rexprefix = rex(w=1, r=rexbit[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
228 mod_rm = modrm(mod=0, rm=4,reg=regs64[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
229 si_b = sib(ss=0, index=4,base=5) # 0x25
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
230 return [rexprefix], [mod_rm, si_b] + imm32(offset)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
231 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
232 Error('Memory reference of type {0} not implemented'.format(offset))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
233 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
234 Error('Memory reference not implemented')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
235 elif rm64 in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
236 rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[rm64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
237 mod_rm = modrm(3, rm=regs64[rm64], reg=regs64[r64])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
238 return [rexprefix], [mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
239
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
240 def leareg64(rega, m):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
241 opcode = 0x8d # lea r64, m
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
242 pre, post = prepost(rega, m)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
243 return pre + [opcode] + post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
244
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
245 def mov(rega, regb):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
246 if type(regb) is int:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
247 pre = [rex(w=1, b=rexbit[rega])]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
248 opcode = 0xb8 + regs64[rega]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
249 post = imm64(regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
250 elif type(regb) is str:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
251 if regb in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
252 opcode = 0x89 # mov r/m64, r64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
253 pre, post = prepost(regb, rega)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
254 elif regb in regs8:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
255 opcode = 0x88 # mov r/m8, r8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
256 pre, post = prepost8(regb, rega)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
257 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
258 Error('Unknown register {0}'.format(regb))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
259 elif type(rega) is str:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
260 if rega in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
261 opcode = 0x8b # mov r64, r/m64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
262 pre, post = prepost(rega, regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
263 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
264 Error('Unknown register {0}'.format(rega))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
265 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
266 Error('Move of this kind {0}, {1} not implemented'.format(rega, regb))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
267 return pre + [opcode] + post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
268
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
269 def xorreg64(rega, regb):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
270 rexprefix = rex(w=1, r=rexbit[regb], b=rexbit[rega])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
271 opcode = 0x31 # XOR r/m64, r64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
272 # Alternative is 0x33 XOR r64, r/m64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
273 mod_rm = modrm(3, rm=regs64[rega], reg=regs64[regb])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
274 return [rexprefix, opcode, mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
275
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
276 # integer arithmatic:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
277 def addreg64(rega, regb):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
278 if regb in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
279 pre, post = prepost(regb, rega)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
280 opcode = 0x01 # ADD r/m64, r64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
281 return pre + [opcode] + post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
282 elif type(regb) is int:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
283 if regb < 100:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
284 rexprefix = rex(w=1, b=rexbit[rega])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
285 opcode = 0x83 # add r/m, imm8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
286 mod_rm = modrm(3, rm=regs64[rega], reg=0)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
287 return [rexprefix, opcode, mod_rm]+imm8(regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
288 elif regb < (1<<31):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
289 rexprefix = rex(w=1, b=rexbit[rega])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
290 opcode = 0x81 # add r/m64, imm32
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
291 mod_rm = modrm(3, rm=regs64[rega], reg=0)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
292 return [rexprefix, opcode, mod_rm]+imm32(regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
293 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
294 Error('Constant value too large!')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
295 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
296 Error('unknown second operand!'.format(regb))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
297
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
298 def subreg64(rega, regb):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
299 if regb in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
300 pre, post = prepost(regb, rega)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
301 opcode = 0x29 # SUB r/m64, r64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
302 return pre + [opcode] + post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
303 elif type(regb) is int:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
304 if regb < 100:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
305 rexprefix = rex(w=1, b=rexbit[rega])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
306 opcode = 0x83 # sub r/m, imm8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
307 mod_rm = modrm(3, rm=regs64[rega], reg=5)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
308 return [rexprefix, opcode, mod_rm]+imm8(regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
309 elif regb < (1<<31):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
310 rexprefix = rex(w=1, b=rexbit[rega])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
311 opcode = 0x81 # sub r/m64, imm32
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
312 mod_rm = modrm(3, rm=regs64[rega], reg=5)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
313 return [rexprefix, opcode, mod_rm]+imm32(regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
314 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
315 Error('Constant value too large!')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
316
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
317 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
318 Error('unknown second operand!'.format(regb))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
319
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
320 def idivreg64(reg):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
321 rexprefix = rex(w=1, b=rexbit[reg])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
322 opcode = 0xf7 # IDIV r/m64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
323 mod_rm = modrm(3, rm=regs64[reg], reg=7)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
324 return [rexprefix, opcode, mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
325
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
326 def imulreg64_rax(reg):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
327 rexprefix = rex(w=1, b=rexbit[reg])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
328 opcode = 0xf7 # IMUL r/m64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
329 mod_rm = modrm(3, rm=regs64[reg], reg=5)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
330 return [rexprefix, opcode, mod_rm]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
331
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
332 def imulreg64(rega, regb):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
333 pre, post = prepost(rega, regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
334 opcode = 0x0f # IMUL r64, r/m64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
335 opcode2 = 0xaf
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
336 return pre + [opcode, opcode2] + post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
337
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
338 def cmpreg64(rega, regb):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
339 if regb in regs64:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
340 pre, post = prepost(regb, rega)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
341 opcode = 0x39 # CMP r/m64, r64
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
342 return pre + [opcode] + post
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
343 elif type(regb) is int:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
344 rexprefix = rex(w=1, b=rexbit[rega])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
345 opcode = 0x83 # CMP r/m64, imm8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
346 mod_rm = modrm(3, rm=regs64[rega], reg=7)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
347 return [rexprefix, opcode, mod_rm] + imm8(regb)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
348
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
349 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
350 Error('not implemented cmp64')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
351
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
352 # Mapping that maps string names to the right functions:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
353 opcodes = {'mov':(mov,2), 'lea':(leareg64,2), 'int':(INT,1), 'syscall':(syscall,0)}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
354