annotate python/target/x86_2.py @ 305:0615b5308710

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