comparison modules/x86.tp @ 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
children 20b6041a8b23
comparison
equal deleted inserted replaced
173:158444b77c09 174:8b5829372ad1
1 {
2 ireg <- :regnum {
3 #{
4 num <- { regnum }
5 reg <- { regnum and 7u8}
6 rm <- :tail { reg or 0xC0u8 | tail }
7 validforSize? <- :size { true }
8 isInteger? <- { false }
9 register? <- { true }
10 upper? <- { true }
11 needsRex? <- { regnum >= 8u8 }
12 rexBitReg <- {
13 if: needsRex? {
14 4u8
15 } else: {
16 0u8
17 }
18 }
19 rexBitRM <- {
20 if: needsRex? {
21 1u8
22 } else: {
23 0u8
24 }
25 }
26 = <- :other {
27 (not: (other isInteger?)) && (other register?) && (not: (other upper?)) && regnum = (other num)
28 }
29 }
30 }
31
32 upper <- :regnum {
33 #{
34 num <- { regnum }
35 reg <- { regnum }
36 rm <- :tail { regnum or 0xC0u8 | tail }
37 validforSize? <- :size {
38 size = byte
39 }
40 isInteger? <- { false }
41 register? <- { true }
42 upper? <- { true }
43 needsRex? <- { false }
44 = <- :other {
45 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num)
46 }
47 }
48 }
49 fakesrc <- #{
50 needsRex? <- { false }
51 rexBitReg <- { 0u8 }
52 rexBitRM <- { 0u8 }
53 }
54 size <- :s {
55 #{
56 num <- { s }
57 = <- :other {
58 s = (other num)
59 }
60 > <- :other {
61 s > (other num)
62 }
63 >= <- :other {
64 s >= (other num)
65 }
66 < <- :other {
67 s < (other num)
68 }
69 <= <- :other {
70 s <= (other num)
71 }
72 needsRex? <- { s = 3 }
73 rexBit <- {
74 if: needsRex? {
75 0x08u8
76 } else: {
77 0u8
78 }
79 }
80 }
81 }
82 byte <- size: 0
83 word <- size: 1
84 dword <- size: 2
85 qword <- size: 3
86
87 size_bit <- :opcode size {
88 if: size = byte {
89 opcode
90 } else: {
91 opcode or 2u8
92 }
93 }
94 opex <- :val {
95 #{
96 reg <- { val }
97 }
98 }
99
100 mod_rm:withTail <- :register regmem :end {
101 l <- regmem rm: end
102 (l value) or (register reg) | (l tail)
103 }
104
105 mod_rm <- :reg rm {
106 mod_rm: reg rm withTail: []
107 }
108
109 int_op <- :value size {
110 tail <- []
111 if: size >= dword {
112 tail <- (uint8: (value rshift: 16)) | (uint8: (value rshift: 24)) | tail
113 }
114 if: size >= word {
115 tail <- (uint8: (value rshift: 8)) | tail
116 }
117 (uint8: value) | tail
118 }
119
120 prefix:withInstruction <- :reg rm size :inst {
121 if: size = word {
122 inst <- 0x66u8 | inst
123 }
124 if: (size needsRex?) || (reg needsRex?) || (rm needsRex?) {
125 rex <- 0x40u8 or (size rexBit) or (reg rexBitReg) or (rm rexBitRM)
126 inst <- rex | inst
127 }
128 inst
129 }
130
131 _rax <- ireg: 0u8
132 _rcx <- ireg: 1u8
133 _rdx <- ireg: 2u8
134 _rbx <- ireg: 3u8
135 _rsp <- ireg: 4u8
136 _rbp <- ireg: 5u8
137 _rsi <- ireg: 6u8
138 _rdi <- ireg: 7u8
139 _r8 <- ireg: 8u8
140 _r9 <- ireg: 9u8
141 _r10 <- ireg: 10u8
142 _r11 <- ireg: 11u8
143 _r12 <- ireg: 12u8
144 _r13 <- ireg: 13u8
145 _r14 <- ireg: 14u8
146 _r15 <- ireg: 15u8
147 _ah <- upper: 4u8
148 _ch <- upper: 5u8
149 _dh <- upper: 6u8
150 _bh <- upper: 7u8
151
152 op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt {
153 reg <- src
154 rm <- dst
155 base <- if: (src isInteger?) {
156 reg <- fakesrc
157 if: size > byte && (((src signed?) && src < 128 && src >= -128) || ((not: (src signed?)) && src < 256)) {
158 0x83u8 | (mod_rm: (opex: myopex) dst withTail: [(uint8: src)])
159 } else: {
160 if: dst = _rax {
161 (size_bit: immedRax size) | (int_op: src size)
162 } else: {
163 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size))
164 }
165 }
166 } else: {
167 if: (src register?) {
168 (size_bit: normal size) | (mod_rm: src dst)
169 } else: {
170 reg <- dst
171 rm <- src
172 (size_bit: normal or 0x02u8 size) | (mod_rm: dst src)
173 }
174 }
175 prefix: reg rm size withInstruction: base
176 }
177
178 #{
179 rax <- { _rax }
180 rcx <- { _rcx }
181 rdx <- { _rdx }
182 rbx <- { _rbx }
183 rsp <- { _rsp }
184 rbp <- { _rbp }
185 rsi <- { _rsi }
186 rdi <- { _rdi }
187 r8 <- { _r8 }
188 r9 <- { _r9 }
189 r10 <- { _r10 }
190 r11 <- { _r11 }
191 r12 <- { _r12 }
192 r13 <- { _r13 }
193 r14 <- { _r14 }
194 r15 <- { _r15 }
195 ah <- { _ah }
196 ch <- { _ch }
197 dh <- { _dh }
198 bh <- { _bh }
199
200 b <- { byte }
201 w <- { word }
202 d <- { dword }
203 q <- { qword }
204
205 add <- :src dst size {
206 op: src dst size withCode: 0u8 withImmed: 0x80u8 withImmedRax: 0x04u8 withOpEx: 0u8 withByteExtend: 0x83u8
207 }
208
209
210 main <- {
211 print: ((add: rax r8 b) map: :el { hex: el })
212 print: "\n"
213 print: ((add: r9 rdx w) map: :el { hex: el })
214 print: "\n"
215 print: ((add: rax rbx q) map: :el { hex: el })
216 print: "\n"
217 print: ((add: 25 rax q) map: :el { hex: el })
218 print: "\n"
219 print: ((add: rcx rdx d) map: :el { hex: el })
220 print: "\n"
221 0
222 }
223 }
224 }