changeset 174:8b5829372ad1

Initial work on x86 instruction encoding module
author Mike Pavone <pavone@retrodev.com>
date Wed, 21 Aug 2013 08:00:57 -0700
parents 158444b77c09
children 20b6041a8b23
files modules/x86.tp
diffstat 1 files changed, 224 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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
+		}
+	}
+}