comparison modules/x86.tp @ 179:75aca5f87969

A bunch of fixes in x86 instruction encoding
author Mike Pavone <pavone@retrodev.com>
date Sat, 24 Aug 2013 09:56:29 -0700
parents 20b6041a8b23
children 270d31c6c4cd
comparison
equal deleted inserted replaced
178:e823e104b845 179:75aca5f87969
1 { 1 {
2 regnames <- #["rax" "rcx" "rdx" "rbx" "rsp" "rbp" "rsi" "rdi" "r8" "r9" "r10" "r11" "r12" "r13" "r14" "r15"]
3 uppernames <- #["ah" "ch" "dh" "bh"]
2 ireg <- :regnum { 4 ireg <- :regnum {
3 #{ 5 #{
4 num <- { regnum } 6 num <- { regnum }
5 reg <- { regnum and 7u8} 7 reg <- { regnum and 7u8}
8 string <- { regnames get: regnum }
6 rm <- :tail { reg or 0xC0u8 | tail } 9 rm <- :tail { reg or 0xC0u8 | tail }
7 validforSize? <- :size { true } 10 validforSize? <- :size { true }
8 isInteger? <- { false } 11 isInteger? <- { false }
9 register? <- { true } 12 register? <- { true }
10 upper? <- { true } 13 upper? <- { true }
31 34
32 upper <- :regnum { 35 upper <- :regnum {
33 #{ 36 #{
34 num <- { regnum } 37 num <- { regnum }
35 reg <- { regnum } 38 reg <- { regnum }
39 string <- { uppernames get: regnum - 4 }
36 rm <- :tail { regnum or 0xC0u8 | tail } 40 rm <- :tail { regnum or 0xC0u8 | tail }
37 validforSize? <- :size { 41 validforSize? <- :size {
38 size = byte 42 size = byte
39 } 43 }
40 isInteger? <- { false } 44 isInteger? <- { false }
86 90
87 size_bit <- :opcode size { 91 size_bit <- :opcode size {
88 if: size = byte { 92 if: size = byte {
89 opcode 93 opcode
90 } else: { 94 } else: {
91 opcode or 2u8 95 opcode or 1u8
92 } 96 }
93 } 97 }
94 opex <- :val { 98 opex <- :val {
95 #{ 99 #{
96 reg <- { val } 100 reg <- { val }
101 string <- { "opex " . val}
97 } 102 }
98 } 103 }
99 104
100 mod_rm:withTail <- :register regmem :end { 105 mod_rm:withTail <- :register regmem :end {
101 l <- regmem rm: end 106 l <- regmem rm: end
102 (l value) or (register reg) | (l tail) 107 (l value) or ( lshift: (register reg) by: 3u8) | (l tail)
103 } 108 }
104 109
105 mod_rm <- :reg rm { 110 mod_rm <- :reg rm {
106 mod_rm: reg rm withTail: [] 111 mod_rm: reg rm withTail: []
107 } 112 }
108 113
109 int_op:withTail <- :value size :tail { 114 int_op:withTail <- :value size :tail {
110 if: size >= dword { 115 if: size >= dword {
111 tail <- (uint8: (value rshift: 16)) | (uint8: (value rshift: 24)) | tail 116 tail <- (uint8: (rshift: value by: 16u64)) | (uint8: (rshift: value by: 24u64)) | tail
112 } 117 }
113 if: size >= word { 118 if: size >= word {
114 tail <- (uint8: (value rshift: 8)) | tail 119 tail <- (uint8: (rshift: value by: 8u64)) | tail
115 } 120 }
116 (uint8: value) | tail 121 (uint8: value) | tail
117 } 122 }
118 int_op <- :value size { 123 int_op <- :value size {
119 int_op: value size withTail: [] 124 int_op: value size withTail: []
120 } 125 }
121 //used for mov instructions that support 64-bit immediate operands/offsets 126 //used for mov instructions that support 64-bit immediate operands/offsets
122 int_op64 <- :value size { 127 int_op64 <- :value size {
123 tail <- [] 128 tail <- []
124 if: size = qword { 129 if: size = qword {
125 tail <- (uint8: (value rshift: 32)) | (uint8: (value rshift: 40)) | (uint8: (value rshift: 48)) | (uint8: (value rshift: 56)) | tail 130 tail <- (uint8: (rshift: value by: 32u64)) | (uint8: (rshift: value by: 40u64)) | (uint8: (rshift: value by: 48u64)) | (uint8: (rshift: value by: 56u64)) | tail
126 } 131 }
127 int_op: value size withTail: tail 132 int_op: value size withTail: tail
128 } 133 }
129 134
130 prefix:withInstruction <- :reg rm size :inst { 135 prefix:withInstruction <- :reg rm size :inst {
181 reg <- src 186 reg <- src
182 rm <- dst 187 rm <- dst
183 if: (src isInteger?) { 188 if: (src isInteger?) {
184 reg <- fakesrc 189 reg <- fakesrc
185 base <- if: size > byte && (((src signed?) && src < 128 && src >= -128) || ((not: (src signed?)) && src < 256)) { 190 base <- if: size > byte && (((src signed?) && src < 128 && src >= -128) || ((not: (src signed?)) && src < 256)) {
186 0x83u8 | (mod_rm: (opex: myopex) dst withTail: [(uint8: src)]) 191 byteExt | (mod_rm: (opex: myopex) dst withTail: [(uint8: src)])
187 } else: { 192 } else: {
188 if: dst = _rax { 193 if: dst = _rax {
189 (size_bit: immedRax size) | (int_op: src size) 194 (size_bit: immedRax size) | (int_op: src size)
190 } else: { 195 } else: {
191 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size)) 196 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size))
257 print: "\n" 262 print: "\n"
258 print: ((add: 25 rax q) map: :el { hex: el }) 263 print: ((add: 25 rax q) map: :el { hex: el })
259 print: "\n" 264 print: "\n"
260 print: ((add: rcx rdx d) map: :el { hex: el }) 265 print: ((add: rcx rdx d) map: :el { hex: el })
261 print: "\n" 266 print: "\n"
267 prog <- #[
268 mov: rdi rax q
269 sub: 1 rdi q
270 add: rdi rax q
271 ret:
272 ]
273 ba <- bytearray executableFromBytes: prog
274 res <- ba runWithArg: 24u64
275 print: (string: res) . "\n"
262 0 276 0
263 } 277 }
264 } 278 }
265 } 279 }