Mercurial > repos > tabletprog
comparison modules/x86.tp @ 183:97f107b9e8d3
Fix a few bugs in the x86 module and add jcc, push and pop instructions
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 24 Aug 2013 19:03:18 -0700 |
parents | f188723c15b4 |
children | 4293c725394c |
comparison
equal
deleted
inserted
replaced
182:ab7c142090a0 | 183:97f107b9e8d3 |
---|---|
88 byte <- size: 0 | 88 byte <- size: 0 |
89 word <- size: 1 | 89 word <- size: 1 |
90 dword <- size: 2 | 90 dword <- size: 2 |
91 qword <- size: 3 | 91 qword <- size: 3 |
92 | 92 |
93 condition <- :num { | |
94 #{ | |
95 cc <- { num } | |
96 } | |
97 } | |
98 _o <- condition: 0u8 | |
99 _no <- condition: 1u8 | |
100 _c <- condition: 2u8 | |
101 _nc <- condition: 3u8 | |
102 _z <- condition: 4u8 | |
103 _nz <- condition: 5u8 | |
104 _be <- condition: 6u8 | |
105 _nbe <- condition: 7u8 | |
106 _s <- condition: 8u8 | |
107 _ns <- condition: 9u8 | |
108 _p <- condition: 10u8 | |
109 _np <- condition: 11u8 | |
110 _l <- condition: 12u8 | |
111 _nl <- condition: 13u8 | |
112 _le <- condition: 14u8 | |
113 _nle <- condition: 15u8 | |
114 | |
115 | |
93 size_bit <- :opcode size { | 116 size_bit <- :opcode size { |
94 if: size = byte { | 117 if: size = byte { |
95 opcode | 118 opcode |
96 } else: { | 119 } else: { |
97 opcode or 1u8 | 120 opcode or 1u8 |
126 int_op: value size withTail: [] | 149 int_op: value size withTail: [] |
127 } | 150 } |
128 //used for mov instructions that support 64-bit immediate operands/offsets | 151 //used for mov instructions that support 64-bit immediate operands/offsets |
129 int_op64 <- :value size { | 152 int_op64 <- :value size { |
130 tail <- [] | 153 tail <- [] |
154 value <- uint64: value | |
131 if: size = qword { | 155 if: size = qword { |
132 tail <- (uint8: (rshift: value by: 32u64)) | (uint8: (rshift: value by: 40u64)) | (uint8: (rshift: value by: 48u64)) | (uint8: (rshift: value by: 56u64)) | tail | 156 tail <- (uint8: (rshift: value by: 32u64)) | (uint8: (rshift: value by: 40u64)) | (uint8: (rshift: value by: 48u64)) | (uint8: (rshift: value by: 56u64)) | tail |
133 } | 157 } |
134 int_op: value size withTail: tail | 158 int_op: value size withTail: tail |
135 } | 159 } |
212 } | 236 } |
213 inst: (prefix: reg rm size withInstruction: base) | 237 inst: (prefix: reg rm size withInstruction: base) |
214 } else: { | 238 } else: { |
215 op: src dst size withCode: normal withImmed: immed withOpEx: myopex | 239 op: src dst size withCode: normal withImmed: immed withOpEx: myopex |
216 } | 240 } |
241 } | |
242 | |
243 _jmprel <- :op jmpDest { | |
217 } | 244 } |
218 | 245 |
219 #{ | 246 #{ |
220 rax <- { _rax } | 247 rax <- { _rax } |
221 rcx <- { _rcx } | 248 rcx <- { _rcx } |
241 b <- { byte } | 268 b <- { byte } |
242 w <- { word } | 269 w <- { word } |
243 d <- { dword } | 270 d <- { dword } |
244 q <- { qword } | 271 q <- { qword } |
245 | 272 |
273 o <- { _o } | |
274 no <- { _no } | |
275 c <- { _c } | |
276 nc <- { _nc } | |
277 ae <- { _nc } | |
278 z <- { _z } | |
279 e <- { _z } | |
280 nz <- { _nz } | |
281 ne <- { _nz } | |
282 be <- { _be } | |
283 nbe <- { _nbe } | |
284 a <- { _nbe } | |
285 s <- { _s } | |
286 ns <- { _ns } | |
287 p <- { _p } | |
288 pe <- { _p } | |
289 np <- { _np } | |
290 po <- { _np } | |
291 l <- { _l } | |
292 nl <- { _nl } | |
293 ge <- { _nl } | |
294 le <- { _le } | |
295 nle <- { _nle } | |
296 g <- { _nle } | |
297 | |
246 add <- :src dst size { | 298 add <- :src dst size { |
247 op: src dst size withCode: 0u8 withImmed: 0x80u8 withImmedRax: 0x04u8 withOpEx: 0u8 withByteExtend: 0x83u8 | 299 op: src dst size withCode: 0u8 withImmed: 0x80u8 withImmedRax: 0x04u8 withOpEx: 0u8 withByteExtend: 0x83u8 |
248 } | 300 } |
249 | 301 |
250 sub <- :src dst size { | 302 sub <- :src dst size { |
251 op: src dst size withCode: 0x28u8 withImmed: 0x80u8 withImmedRax: 0x2Cu8 withOpEx: 5u8 withByteExtend: 0x83u8 | 303 op: src dst size withCode: 0x28u8 withImmed: 0x80u8 withImmedRax: 0x2Cu8 withOpEx: 5u8 withByteExtend: 0x83u8 |
252 } | 304 } |
253 | 305 |
254 mov <- :src dst size { | 306 mov <- :src dst size { |
255 reg <- src | |
256 rm <- dst | 307 rm <- dst |
257 if: (src isInteger?) && (dst register?) { | 308 if: (src isInteger?) && (dst register?) { |
258 opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } | 309 opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } |
259 base <- opval | (int_op64: src size) | 310 base <- opval or (dst reg) | (int_op64: src size) |
260 inst: (prefix: fakesrc rm size withInstruction: base) | 311 inst: (prefix: fakesrc rm size withInstruction: base) |
261 } else: { | 312 } else: { |
262 op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 | 313 op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 |
263 } | 314 } |
264 } | 315 } |
265 | 316 |
266 ret <- { inst: [ 0xC3u8 ] } | 317 ret <- { inst: [ 0xC3u8 ] } |
267 | 318 |
268 label <- { | 319 label <- { |
269 _offset <- -1 | 320 _offset <- -1 |
270 _address <- 0u64 | |
271 _forwardRefs <- #[] | 321 _forwardRefs <- #[] |
272 #{ | 322 #{ |
273 length <- { 0 } | 323 length <- { 0 } |
274 hasOffset? <- { _offset >= 0 } | 324 hasOffset? <- { _offset >= 0 } |
275 offset <- { _offset } | 325 offset <- { _offset } |
276 register? <- { false } | 326 register? <- { false } |
277 label? <- { true } | 327 label? <- { true } |
278 flattenTo:at <- :dest :idx { | 328 flattenTo:at <- :dest :idx { |
279 if: (not: hasOffset?) { | 329 if: (not: hasOffset?) { |
280 _offset <- idx | 330 _offset <- idx |
281 _address <- dest addressAt: idx | |
282 foreach: _forwardRefs :idx fun { | 331 foreach: _forwardRefs :idx fun { |
283 fun: _offset | 332 fun: _offset |
284 } | 333 } |
285 _forwardRefs <- #[] | 334 _forwardRefs <- #[] |
286 } | 335 } |
344 } else: { | 393 } else: { |
345 inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest) | 394 inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest) |
346 } | 395 } |
347 } | 396 } |
348 | 397 |
398 jcc <- :cond jmpDest { | |
399 _size <- -1 | |
400 #{ | |
401 length <- { if: _size < 0 { 5 } else: { _size } } | |
402 flattenTo:at <- :dest :idx { | |
403 jmpDest withOffset: :off { | |
404 if: _size < 0 { | |
405 rel <- off - (idx + 2) | |
406 if: rel < 128 && rel >= -128 { | |
407 _size <- 2 | |
408 } else: { | |
409 _size <- 6 | |
410 } | |
411 } | |
412 rel <- off - (idx + _size) | |
413 if: _size = 2 { | |
414 dest set: idx 0x70u8 or (cond cc) | |
415 dest set: (idx + 1) (uint8: rel) | |
416 } else: { | |
417 dest set: idx 0x0Fu8 | |
418 dest set: (idx + 1) 0x80u8 or (cond cc) | |
419 dest set: (idx + 2) (uint8: rel) | |
420 dest set: (idx + 3) (uint8: (rshift: rel by: 8)) | |
421 dest set: (idx + 4) (uint8: (rshift: rel by: 16)) | |
422 dest set: (idx + 5) (uint8: (rshift: rel by: 24)) | |
423 } | |
424 } else: { | |
425 _size <- 6 | |
426 } | |
427 idx + _size | |
428 } | |
429 } | |
430 } | |
431 | |
349 call <- :callDest { | 432 call <- :callDest { |
350 if: (callDest label?) { | 433 if: (callDest label?) { |
351 #{ | 434 #{ |
352 length <- { 5 } | 435 length <- { 5 } |
353 flattenTo:at <- :dest :idx { | 436 flattenTo:at <- :dest :idx { |
366 } else: { | 449 } else: { |
367 inst: 0xFFu8 | (mod_rm: (opex: 2u8) callDest) | 450 inst: 0xFFu8 | (mod_rm: (opex: 2u8) callDest) |
368 } | 451 } |
369 } | 452 } |
370 | 453 |
454 push <- :src { | |
455 if: (src isInteger?) { | |
456 if: src < 128 && src > -128 { | |
457 inst: 0x6Au8 | (uint8: src) | |
458 } else: { | |
459 inst: 0x68u8 | (uint8: src) | (uint8: (rshift: src by: 8)) | (uint8: (rshift: src by: 16)) | (uint8: (rshift: src by: 24)) | |
460 } | |
461 } else: { | |
462 base <- if: (src register?) { | |
463 [0x50u8 or (src reg)] | |
464 } else: { | |
465 0xFFu8 | (mod_rm: (opex: 6u8) src) | |
466 } | |
467 inst: (prefix: fakesrc src d withInstruction: base) | |
468 } | |
469 } | |
470 | |
471 pop <- :dst { | |
472 base <- if: (dst register?) { | |
473 [0x58u8 or (dst reg)] | |
474 } else: { | |
475 0x8Fu8 | (mod_rm: (opex: 0u8) dst) | |
476 } | |
477 inst: (prefix: fakesrc dst d withInstruction: base) | |
478 } | |
479 | |
371 main <- { | 480 main <- { |
372 foo <- label: | 481 fib <- label: |
373 bar <- label: | 482 notbase <- label: |
374 baz <- label: | |
375 prog <- #[ | 483 prog <- #[ |
376 mov: rdi rax q | 484 fib |
377 sub: 1 rdi q | 485 sub: 2 rdi q |
486 jcc: ge notbase | |
487 mov: 1 rax q | |
488 ret: | |
489 | |
490 notbase | |
491 push: rdi | |
492 call: fib | |
493 pop: rdi | |
494 push: rax | |
495 add: 1 rdi q | |
496 call: fib | |
497 pop: rdi | |
378 add: rdi rax q | 498 add: rdi rax q |
379 jmp: bar | |
380 foo | |
381 ret: | |
382 bar | |
383 sub: 13 rax q | |
384 call: baz | |
385 jmp: foo | |
386 baz | |
387 add: 1 rax q | |
388 ret: | 499 ret: |
389 ] | 500 ] |
390 | 501 |
391 ba <- bytearray executableFromBytes: prog | 502 ba <- bytearray executableFromBytes: prog |
392 res <- ba runWithArg: 24u64 | 503 res <- ba runWithArg: 30u64 |
393 print: (string: res) . "\n" | 504 print: (string: res) . "\n" |
394 0 | 505 0 |
395 } | 506 } |
396 } | 507 } |
397 } | 508 } |