# HG changeset patch # User Mike Pavone # Date 1377097257 25200 # Node ID 8b5829372ad1d971b3dbaed202890efbfa605037 # Parent 158444b77c092b9ffdb83a2ba687f7089fbd989d Initial work on x86 instruction encoding module diff -r 158444b77c09 -r 8b5829372ad1 modules/x86.tp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/x86.tp Wed Aug 21 08:00:57 2013 -0700 @@ -0,0 +1,224 @@ +{ + ireg <- :regnum { + #{ + num <- { regnum } + reg <- { regnum and 7u8} + rm <- :tail { reg or 0xC0u8 | tail } + validforSize? <- :size { true } + isInteger? <- { false } + register? <- { true } + upper? <- { true } + needsRex? <- { regnum >= 8u8 } + rexBitReg <- { + if: needsRex? { + 4u8 + } else: { + 0u8 + } + } + rexBitRM <- { + if: needsRex? { + 1u8 + } else: { + 0u8 + } + } + = <- :other { + (not: (other isInteger?)) && (other register?) && (not: (other upper?)) && regnum = (other num) + } + } + } + + upper <- :regnum { + #{ + num <- { regnum } + reg <- { regnum } + rm <- :tail { regnum or 0xC0u8 | tail } + validforSize? <- :size { + size = byte + } + isInteger? <- { false } + register? <- { true } + upper? <- { true } + needsRex? <- { false } + = <- :other { + (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num) + } + } + } + fakesrc <- #{ + needsRex? <- { false } + rexBitReg <- { 0u8 } + rexBitRM <- { 0u8 } + } + size <- :s { + #{ + num <- { s } + = <- :other { + s = (other num) + } + > <- :other { + s > (other num) + } + >= <- :other { + s >= (other num) + } + < <- :other { + s < (other num) + } + <= <- :other { + s <= (other num) + } + needsRex? <- { s = 3 } + rexBit <- { + if: needsRex? { + 0x08u8 + } else: { + 0u8 + } + } + } + } + byte <- size: 0 + word <- size: 1 + dword <- size: 2 + qword <- size: 3 + + size_bit <- :opcode size { + if: size = byte { + opcode + } else: { + opcode or 2u8 + } + } + opex <- :val { + #{ + reg <- { val } + } + } + + mod_rm:withTail <- :register regmem :end { + l <- regmem rm: end + (l value) or (register reg) | (l tail) + } + + mod_rm <- :reg rm { + mod_rm: reg rm withTail: [] + } + + int_op <- :value size { + tail <- [] + if: size >= dword { + tail <- (uint8: (value rshift: 16)) | (uint8: (value rshift: 24)) | tail + } + if: size >= word { + tail <- (uint8: (value rshift: 8)) | tail + } + (uint8: value) | tail + } + + prefix:withInstruction <- :reg rm size :inst { + if: size = word { + inst <- 0x66u8 | inst + } + if: (size needsRex?) || (reg needsRex?) || (rm needsRex?) { + rex <- 0x40u8 or (size rexBit) or (reg rexBitReg) or (rm rexBitRM) + inst <- rex | inst + } + inst + } + + _rax <- ireg: 0u8 + _rcx <- ireg: 1u8 + _rdx <- ireg: 2u8 + _rbx <- ireg: 3u8 + _rsp <- ireg: 4u8 + _rbp <- ireg: 5u8 + _rsi <- ireg: 6u8 + _rdi <- ireg: 7u8 + _r8 <- ireg: 8u8 + _r9 <- ireg: 9u8 + _r10 <- ireg: 10u8 + _r11 <- ireg: 11u8 + _r12 <- ireg: 12u8 + _r13 <- ireg: 13u8 + _r14 <- ireg: 14u8 + _r15 <- ireg: 15u8 + _ah <- upper: 4u8 + _ch <- upper: 5u8 + _dh <- upper: 6u8 + _bh <- upper: 7u8 + + op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt { + reg <- src + rm <- dst + base <- if: (src isInteger?) { + reg <- fakesrc + if: size > byte && (((src signed?) && src < 128 && src >= -128) || ((not: (src signed?)) && src < 256)) { + 0x83u8 | (mod_rm: (opex: myopex) dst withTail: [(uint8: src)]) + } else: { + if: dst = _rax { + (size_bit: immedRax size) | (int_op: src size) + } else: { + (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size)) + } + } + } else: { + if: (src register?) { + (size_bit: normal size) | (mod_rm: src dst) + } else: { + reg <- dst + rm <- src + (size_bit: normal or 0x02u8 size) | (mod_rm: dst src) + } + } + prefix: reg rm size withInstruction: base + } + + #{ + rax <- { _rax } + rcx <- { _rcx } + rdx <- { _rdx } + rbx <- { _rbx } + rsp <- { _rsp } + rbp <- { _rbp } + rsi <- { _rsi } + rdi <- { _rdi } + r8 <- { _r8 } + r9 <- { _r9 } + r10 <- { _r10 } + r11 <- { _r11 } + r12 <- { _r12 } + r13 <- { _r13 } + r14 <- { _r14 } + r15 <- { _r15 } + ah <- { _ah } + ch <- { _ch } + dh <- { _dh } + bh <- { _bh } + + b <- { byte } + w <- { word } + d <- { dword } + q <- { qword } + + add <- :src dst size { + op: src dst size withCode: 0u8 withImmed: 0x80u8 withImmedRax: 0x04u8 withOpEx: 0u8 withByteExtend: 0x83u8 + } + + + main <- { + print: ((add: rax r8 b) map: :el { hex: el }) + print: "\n" + print: ((add: r9 rdx w) map: :el { hex: el }) + print: "\n" + print: ((add: rax rbx q) map: :el { hex: el }) + print: "\n" + print: ((add: 25 rax q) map: :el { hex: el }) + print: "\n" + print: ((add: rcx rdx d) map: :el { hex: el }) + print: "\n" + 0 + } + } +}