changeset 364:e44f65abaf0e

Support labels in non-branch instructions. String literals now work and so does the llhello sample
author Michael Pavone <pavone@retrodev.com>
date Sun, 26 Apr 2015 11:16:14 -0700
parents d949fe826e04
children 3d36d69aab7f 6b5096b07dd5
files modules/x86.tp
diffstat 1 files changed, 43 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/modules/x86.tp	Sat Apr 25 20:56:02 2015 -0700
+++ b/modules/x86.tp	Sun Apr 26 11:16:14 2015 -0700
@@ -61,6 +61,7 @@
 	_size <- :s {
 		#{
 			num <- { s }
+			bytes <- { lshift: 1 by: s }
 			= <- :other {
 				s = (other num)
 			}
@@ -234,6 +235,25 @@
 			string <- { (ilist map: :el { hex: el}) join: " "}
 		}
 	}
+	
+	labelinst <- :prefix label size {
+		_length <- (prefix length) + (size bytes)
+		#{
+			length <- { _length }
+			flattenTo:at <- :dest :idx {
+				label withOffset: :off {
+					writeBytes <- :idx byte {
+						dest set: idx byte
+						idx + 1
+					}
+					idx <- prefix fold: idx with: writeBytes
+					(int_op64: ((dest _buf_ptr) address) + (off uint64) size) fold: idx with: writeBytes
+				} else: {
+					idx + _length
+				}
+			}
+		}
+	}
 	multiInst <- :instarr {
 		#{
 			length <- {
@@ -274,19 +294,27 @@
 	op:withCode:withImmed:withOpEx <- :src dst size :normal :immed :myopex {
 		reg <- src
 		rm <- dst
-		base <- if: (src isInteger?) || (src label?) {
-			reg <- fakesrc
-			(size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size))
+		if: (not: (src isInteger?)) && (src label?) {
+			//most instructions only support 32-bit immediates
+			if: size = qword {
+				size <- dword
+			}
+			labelinst: (prefix: reg rm size withInstruction: (size_bit: immed size) | (mod_rm: (opex: myopex) dst)) src size
 		} else: {
-			if: (src register?) {
-				(size_bit: normal size) | (mod_rm: src dst)
+			base <- if: (src isInteger?) {
+				reg <- fakesrc
+				(size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size))
 			} else: {
-				reg <- dst
-				rm <- src
-				(size_bit: normal or 0x02u8 size) | (mod_rm: dst src)
+				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)
+				}
 			}
+			inst: (prefix: reg rm size withInstruction: base)
 		}
-		inst: (prefix: reg rm size withInstruction: base)
 	}
 
 	op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt {
@@ -440,7 +468,12 @@
 				base <- opval or (dst reg) | (int_op64: src size)
 				inst: (prefix: fakesrc rm size withInstruction: base)
 			} else: {
-				op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8
+				if: (src label?) && (dst register?) {
+					opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 }
+					labelinst: (prefix: fakesrc rm size withInstruction: [opval or (dst reg)]) src size
+				} else: {
+					op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8
+				}
 			}
 		}