comparison modules/x86.tp @ 180:270d31c6c4cd

Add support for jmps and labels in x86 module
author Mike Pavone <pavone@retrodev.com>
date Sat, 24 Aug 2013 15:08:00 -0700
parents 75aca5f87969
children f188723c15b4
comparison
equal deleted inserted replaced
179:75aca5f87969 180:270d31c6c4cd
8 string <- { regnames get: regnum } 8 string <- { regnames get: regnum }
9 rm <- :tail { reg or 0xC0u8 | tail } 9 rm <- :tail { reg or 0xC0u8 | tail }
10 validforSize? <- :size { true } 10 validforSize? <- :size { true }
11 isInteger? <- { false } 11 isInteger? <- { false }
12 register? <- { true } 12 register? <- { true }
13 localLabel? <- { false }
13 upper? <- { true } 14 upper? <- { true }
14 needsRex? <- { regnum >= 8u8 } 15 needsRex? <- { regnum >= 8u8 }
15 rexBitReg <- { 16 rexBitReg <- {
16 if: needsRex? { 17 if: needsRex? {
17 4u8 18 4u8
41 validforSize? <- :size { 42 validforSize? <- :size {
42 size = byte 43 size = byte
43 } 44 }
44 isInteger? <- { false } 45 isInteger? <- { false }
45 register? <- { true } 46 register? <- { true }
47 localLabel? <- { false }
46 upper? <- { true } 48 upper? <- { true }
47 needsRex? <- { false } 49 needsRex? <- { false }
48 = <- :other { 50 = <- :other {
49 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num) 51 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num)
50 } 52 }
162 _ah <- upper: 4u8 164 _ah <- upper: 4u8
163 _ch <- upper: 5u8 165 _ch <- upper: 5u8
164 _dh <- upper: 6u8 166 _dh <- upper: 6u8
165 _bh <- upper: 7u8 167 _bh <- upper: 7u8
166 168
169 inst <- :ilist {
170 #{
171 length <- { ilist length }
172 flattenTo:at <- :dest :idx {
173 ilist fold: idx with: :idx byte {
174 dest set: idx byte
175 idx + 1
176 }
177 }
178 }
179 }
180
167 op:withCode:withImmed:withOpEx <- :src dst size :normal :immed :myopex { 181 op:withCode:withImmed:withOpEx <- :src dst size :normal :immed :myopex {
168 reg <- src 182 reg <- src
169 rm <- dst 183 rm <- dst
170 base <- if: (src isInteger?) { 184 base <- if: (src isInteger?) {
171 reg <- fakesrc 185 reg <- fakesrc
177 reg <- dst 191 reg <- dst
178 rm <- src 192 rm <- src
179 (size_bit: normal or 0x02u8 size) | (mod_rm: dst src) 193 (size_bit: normal or 0x02u8 size) | (mod_rm: dst src)
180 } 194 }
181 } 195 }
182 prefix: reg rm size withInstruction: base 196 inst: (prefix: reg rm size withInstruction: base)
183 } 197 }
184 198
185 op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt { 199 op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt {
186 reg <- src 200 reg <- src
187 rm <- dst 201 rm <- dst
194 (size_bit: immedRax size) | (int_op: src size) 208 (size_bit: immedRax size) | (int_op: src size)
195 } else: { 209 } else: {
196 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size)) 210 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size))
197 } 211 }
198 } 212 }
199 prefix: reg rm size withInstruction: base 213 inst: (prefix: reg rm size withInstruction: base)
200 } else: { 214 } else: {
201 op: src dst size withCode: normal withImmed: immed withOpEx: myopex 215 op: src dst size withCode: normal withImmed: immed withOpEx: myopex
202 } 216 }
203
204 } 217 }
205 218
206 #{ 219 #{
207 rax <- { _rax } 220 rax <- { _rax }
208 rcx <- { _rcx } 221 rcx <- { _rcx }
242 reg <- src 255 reg <- src
243 rm <- dst 256 rm <- dst
244 if: (src isInteger?) && (dst register?) { 257 if: (src isInteger?) && (dst register?) {
245 opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } 258 opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 }
246 base <- opval | (int_op64: src size) 259 base <- opval | (int_op64: src size)
247 prefix: fakesrc rm size withInstruction: base 260 inst: (prefix: fakesrc rm size withInstruction: base)
248 } else: { 261 } else: {
249 op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 262 op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8
250 } 263 }
251 } 264 }
252 265
253 ret <- { [ 0xC3u8 ] } 266 ret <- { inst: [ 0xC3u8 ] }
267
268 label <- {
269 _offset <- -1
270 _forwardRefs <- #[]
271 #{
272 length <- { 0 }
273 hasOffset? <- { _offset >= 0 }
274 offset <- { _offset }
275 register? <- { false }
276 localLabel? <- { true }
277 flattenTo:at <- :dest :idx {
278 if: (not: hasOffset?) {
279 _offset <- idx
280 foreach: _forwardRefs :idx fun {
281 fun: _offset
282 }
283 _forwardRefs <- #[]
284 }
285 idx
286 }
287 withOffset:else <- :fun :elsefun {
288 if: hasOffset? {
289 fun: _offset
290 } else: {
291 _forwardRefs append: fun
292 elsefun:
293 }
294 }
295 }
296 }
297
298 jmp <- :jmpDest {
299 if: (jmpDest localLabel?) {
300 _size <- -1
301 #{
302 length <- { if: _size < 0 { 5 } else: { _size } }
303 flattenTo:at <- :dest :idx {
304 jmpDest withOffset: :off {
305 if: _size < 0 {
306 rel <- off - (idx + 2)
307 if: rel < 128 && rel >= -128 {
308 _size <- 2
309 } else: {
310 rel <- rel - 2
311 if: rel < 32768 && rel >= -32768 {
312 _size <- 4
313 } else: {
314 _size <- 5
315 }
316 }
317 }
318 rel <- off - (idx + _size)
319 if: _size = 2 {
320 dest set: idx 0xEBu8
321 dest set: (idx + 1) (uint8: rel)
322 } else: {
323 if: _size = 4 {
324 dest set: idx 0x66u8
325 dest set: (idx + 1) 0xE9u8
326 dest set: (idx + 2) (uint8: rel)
327 dest set: (idx + 3) (uint8: (rshift: rel by: 8))
328 } else: {
329 dest set: idx 0xE9u8
330 dest set: (idx + 1) (uint8: rel)
331 dest set: (idx + 2) (uint8: (rshift: rel by: 8))
332 dest set: (idx + 3) (uint8: (rshift: rel by: 16))
333 dest set: (idx + 4) (uint8: (rshift: rel by: 24))
334 }
335 }
336 } else: {
337 _size <- 5
338 }
339 idx + _size
340 }
341 }
342 } else: {
343 inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest)
344 }
345 }
254 346
255 347
256 main <- { 348 main <- {
257 print: ((add: rax r8 b) map: :el { hex: el }) 349 foo <- label:
258 print: "\n" 350 bar <- label:
259 print: ((add: r9 rdx w) map: :el { hex: el })
260 print: "\n"
261 print: ((add: rax rbx q) map: :el { hex: el })
262 print: "\n"
263 print: ((add: 25 rax q) map: :el { hex: el })
264 print: "\n"
265 print: ((add: rcx rdx d) map: :el { hex: el })
266 print: "\n"
267 prog <- #[ 351 prog <- #[
268 mov: rdi rax q 352 mov: rdi rax q
269 sub: 1 rdi q 353 sub: 1 rdi q
270 add: rdi rax q 354 add: rdi rax q
355 jmp: bar
356 foo
271 ret: 357 ret:
358 bar
359 sub: 13 rax q
360 jmp: foo
272 ] 361 ]
362
273 ba <- bytearray executableFromBytes: prog 363 ba <- bytearray executableFromBytes: prog
274 res <- ba runWithArg: 24u64 364 res <- ba runWithArg: 24u64
275 print: (string: res) . "\n" 365 print: (string: res) . "\n"
276 0 366 0
277 } 367 }