Mercurial > repos > tabletprog
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 } |