comparison modules/x86.tp @ 181:f188723c15b4

Add call instruction to x86 module
author Mike Pavone <pavone@retrodev.com>
date Sat, 24 Aug 2013 16:21:42 -0700
parents 270d31c6c4cd
children 97f107b9e8d3
comparison
equal deleted inserted replaced
180:270d31c6c4cd 181:f188723c15b4
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 label? <- { false }
14 upper? <- { true } 14 upper? <- { true }
15 needsRex? <- { regnum >= 8u8 } 15 needsRex? <- { regnum >= 8u8 }
16 rexBitReg <- { 16 rexBitReg <- {
17 if: needsRex? { 17 if: needsRex? {
18 4u8 18 4u8
42 validforSize? <- :size { 42 validforSize? <- :size {
43 size = byte 43 size = byte
44 } 44 }
45 isInteger? <- { false } 45 isInteger? <- { false }
46 register? <- { true } 46 register? <- { true }
47 localLabel? <- { false } 47 label? <- { false }
48 upper? <- { true } 48 upper? <- { true }
49 needsRex? <- { false } 49 needsRex? <- { false }
50 = <- :other { 50 = <- :other {
51 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num) 51 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num)
52 } 52 }
265 265
266 ret <- { inst: [ 0xC3u8 ] } 266 ret <- { inst: [ 0xC3u8 ] }
267 267
268 label <- { 268 label <- {
269 _offset <- -1 269 _offset <- -1
270 _address <- 0u64
270 _forwardRefs <- #[] 271 _forwardRefs <- #[]
271 #{ 272 #{
272 length <- { 0 } 273 length <- { 0 }
273 hasOffset? <- { _offset >= 0 } 274 hasOffset? <- { _offset >= 0 }
274 offset <- { _offset } 275 offset <- { _offset }
275 register? <- { false } 276 register? <- { false }
276 localLabel? <- { true } 277 label? <- { true }
277 flattenTo:at <- :dest :idx { 278 flattenTo:at <- :dest :idx {
278 if: (not: hasOffset?) { 279 if: (not: hasOffset?) {
279 _offset <- idx 280 _offset <- idx
281 _address <- dest addressAt: idx
280 foreach: _forwardRefs :idx fun { 282 foreach: _forwardRefs :idx fun {
281 fun: _offset 283 fun: _offset
282 } 284 }
283 _forwardRefs <- #[] 285 _forwardRefs <- #[]
284 } 286 }
294 } 296 }
295 } 297 }
296 } 298 }
297 299
298 jmp <- :jmpDest { 300 jmp <- :jmpDest {
299 if: (jmpDest localLabel?) { 301 if: (jmpDest label?) {
300 _size <- -1 302 _size <- -1
301 #{ 303 #{
302 length <- { if: _size < 0 { 5 } else: { _size } } 304 length <- { if: _size < 0 { 5 } else: { _size } }
303 flattenTo:at <- :dest :idx { 305 flattenTo:at <- :dest :idx {
304 jmpDest withOffset: :off { 306 jmpDest withOffset: :off {
342 } else: { 344 } else: {
343 inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest) 345 inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest)
344 } 346 }
345 } 347 }
346 348
349 call <- :callDest {
350 if: (callDest label?) {
351 #{
352 length <- { 5 }
353 flattenTo:at <- :dest :idx {
354 dest set: idx 0xE8u8
355 callDest withOffset: :off {
356 rel <- off - (idx + 5)
357 dest set: (idx + 1) (uint8: rel)
358 dest set: (idx + 2) (uint8: (rshift: rel by: 8))
359 dest set: (idx + 3) (uint8: (rshift: rel by: 16))
360 dest set: (idx + 4) (uint8: (rshift: rel by: 24))
361 } else: {
362 }
363 idx + 5
364 }
365 }
366 } else: {
367 inst: 0xFFu8 | (mod_rm: (opex: 2u8) callDest)
368 }
369 }
347 370
348 main <- { 371 main <- {
349 foo <- label: 372 foo <- label:
350 bar <- label: 373 bar <- label:
374 baz <- label:
351 prog <- #[ 375 prog <- #[
352 mov: rdi rax q 376 mov: rdi rax q
353 sub: 1 rdi q 377 sub: 1 rdi q
354 add: rdi rax q 378 add: rdi rax q
355 jmp: bar 379 jmp: bar
356 foo 380 foo
357 ret: 381 ret:
358 bar 382 bar
359 sub: 13 rax q 383 sub: 13 rax q
384 call: baz
360 jmp: foo 385 jmp: foo
386 baz
387 add: 1 rax q
388 ret:
361 ] 389 ]
362 390
363 ba <- bytearray executableFromBytes: prog 391 ba <- bytearray executableFromBytes: prog
364 res <- ba runWithArg: 24u64 392 res <- ba runWithArg: 24u64
365 print: (string: res) . "\n" 393 print: (string: res) . "\n"