Mercurial > repos > tabletprog
comparison modules/x86.tp @ 180:270d31c6c4cd
Add support for jmps and labels in x86 module
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 24 Aug 2013 15:08:00 -0700 |
parents | 75aca5f87969 |
children | f188723c15b4 |
comparison
equal
deleted
inserted
replaced
179:75aca5f87969 | 180:270d31c6c4cd |
---|---|
8 string <- { regnames get: regnum } | 8 string <- { regnames get: regnum } |
9 rm <- :tail { reg or 0xC0u8 | tail } | 9 rm <- :tail { reg or 0xC0u8 | tail } |
10 validforSize? <- :size { true } | 10 validforSize? <- :size { true } |
11 isInteger? <- { false } | 11 isInteger? <- { false } |
12 register? <- { true } | 12 register? <- { true } |
13 localLabel? <- { false } | |
13 upper? <- { true } | 14 upper? <- { true } |
14 needsRex? <- { regnum >= 8u8 } | 15 needsRex? <- { regnum >= 8u8 } |
15 rexBitReg <- { | 16 rexBitReg <- { |
16 if: needsRex? { | 17 if: needsRex? { |
17 4u8 | 18 4u8 |
41 validforSize? <- :size { | 42 validforSize? <- :size { |
42 size = byte | 43 size = byte |
43 } | 44 } |
44 isInteger? <- { false } | 45 isInteger? <- { false } |
45 register? <- { true } | 46 register? <- { true } |
47 localLabel? <- { false } | |
46 upper? <- { true } | 48 upper? <- { true } |
47 needsRex? <- { false } | 49 needsRex? <- { false } |
48 = <- :other { | 50 = <- :other { |
49 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num) | 51 (not: (other isInteger?)) && (other register?) && (other upper?) && regnum = (other num) |
50 } | 52 } |
162 _ah <- upper: 4u8 | 164 _ah <- upper: 4u8 |
163 _ch <- upper: 5u8 | 165 _ch <- upper: 5u8 |
164 _dh <- upper: 6u8 | 166 _dh <- upper: 6u8 |
165 _bh <- upper: 7u8 | 167 _bh <- upper: 7u8 |
166 | 168 |
169 inst <- :ilist { | |
170 #{ | |
171 length <- { ilist length } | |
172 flattenTo:at <- :dest :idx { | |
173 ilist fold: idx with: :idx byte { | |
174 dest set: idx byte | |
175 idx + 1 | |
176 } | |
177 } | |
178 } | |
179 } | |
180 | |
167 op:withCode:withImmed:withOpEx <- :src dst size :normal :immed :myopex { | 181 op:withCode:withImmed:withOpEx <- :src dst size :normal :immed :myopex { |
168 reg <- src | 182 reg <- src |
169 rm <- dst | 183 rm <- dst |
170 base <- if: (src isInteger?) { | 184 base <- if: (src isInteger?) { |
171 reg <- fakesrc | 185 reg <- fakesrc |
177 reg <- dst | 191 reg <- dst |
178 rm <- src | 192 rm <- src |
179 (size_bit: normal or 0x02u8 size) | (mod_rm: dst src) | 193 (size_bit: normal or 0x02u8 size) | (mod_rm: dst src) |
180 } | 194 } |
181 } | 195 } |
182 prefix: reg rm size withInstruction: base | 196 inst: (prefix: reg rm size withInstruction: base) |
183 } | 197 } |
184 | 198 |
185 op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt { | 199 op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt { |
186 reg <- src | 200 reg <- src |
187 rm <- dst | 201 rm <- dst |
194 (size_bit: immedRax size) | (int_op: src size) | 208 (size_bit: immedRax size) | (int_op: src size) |
195 } else: { | 209 } else: { |
196 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size)) | 210 (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size)) |
197 } | 211 } |
198 } | 212 } |
199 prefix: reg rm size withInstruction: base | 213 inst: (prefix: reg rm size withInstruction: base) |
200 } else: { | 214 } else: { |
201 op: src dst size withCode: normal withImmed: immed withOpEx: myopex | 215 op: src dst size withCode: normal withImmed: immed withOpEx: myopex |
202 } | 216 } |
203 | |
204 } | 217 } |
205 | 218 |
206 #{ | 219 #{ |
207 rax <- { _rax } | 220 rax <- { _rax } |
208 rcx <- { _rcx } | 221 rcx <- { _rcx } |
242 reg <- src | 255 reg <- src |
243 rm <- dst | 256 rm <- dst |
244 if: (src isInteger?) && (dst register?) { | 257 if: (src isInteger?) && (dst register?) { |
245 opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } | 258 opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } |
246 base <- opval | (int_op64: src size) | 259 base <- opval | (int_op64: src size) |
247 prefix: fakesrc rm size withInstruction: base | 260 inst: (prefix: fakesrc rm size withInstruction: base) |
248 } else: { | 261 } else: { |
249 op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 | 262 op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 |
250 } | 263 } |
251 } | 264 } |
252 | 265 |
253 ret <- { [ 0xC3u8 ] } | 266 ret <- { inst: [ 0xC3u8 ] } |
267 | |
268 label <- { | |
269 _offset <- -1 | |
270 _forwardRefs <- #[] | |
271 #{ | |
272 length <- { 0 } | |
273 hasOffset? <- { _offset >= 0 } | |
274 offset <- { _offset } | |
275 register? <- { false } | |
276 localLabel? <- { true } | |
277 flattenTo:at <- :dest :idx { | |
278 if: (not: hasOffset?) { | |
279 _offset <- idx | |
280 foreach: _forwardRefs :idx fun { | |
281 fun: _offset | |
282 } | |
283 _forwardRefs <- #[] | |
284 } | |
285 idx | |
286 } | |
287 withOffset:else <- :fun :elsefun { | |
288 if: hasOffset? { | |
289 fun: _offset | |
290 } else: { | |
291 _forwardRefs append: fun | |
292 elsefun: | |
293 } | |
294 } | |
295 } | |
296 } | |
297 | |
298 jmp <- :jmpDest { | |
299 if: (jmpDest localLabel?) { | |
300 _size <- -1 | |
301 #{ | |
302 length <- { if: _size < 0 { 5 } else: { _size } } | |
303 flattenTo:at <- :dest :idx { | |
304 jmpDest withOffset: :off { | |
305 if: _size < 0 { | |
306 rel <- off - (idx + 2) | |
307 if: rel < 128 && rel >= -128 { | |
308 _size <- 2 | |
309 } else: { | |
310 rel <- rel - 2 | |
311 if: rel < 32768 && rel >= -32768 { | |
312 _size <- 4 | |
313 } else: { | |
314 _size <- 5 | |
315 } | |
316 } | |
317 } | |
318 rel <- off - (idx + _size) | |
319 if: _size = 2 { | |
320 dest set: idx 0xEBu8 | |
321 dest set: (idx + 1) (uint8: rel) | |
322 } else: { | |
323 if: _size = 4 { | |
324 dest set: idx 0x66u8 | |
325 dest set: (idx + 1) 0xE9u8 | |
326 dest set: (idx + 2) (uint8: rel) | |
327 dest set: (idx + 3) (uint8: (rshift: rel by: 8)) | |
328 } else: { | |
329 dest set: idx 0xE9u8 | |
330 dest set: (idx + 1) (uint8: rel) | |
331 dest set: (idx + 2) (uint8: (rshift: rel by: 8)) | |
332 dest set: (idx + 3) (uint8: (rshift: rel by: 16)) | |
333 dest set: (idx + 4) (uint8: (rshift: rel by: 24)) | |
334 } | |
335 } | |
336 } else: { | |
337 _size <- 5 | |
338 } | |
339 idx + _size | |
340 } | |
341 } | |
342 } else: { | |
343 inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest) | |
344 } | |
345 } | |
254 | 346 |
255 | 347 |
256 main <- { | 348 main <- { |
257 print: ((add: rax r8 b) map: :el { hex: el }) | 349 foo <- label: |
258 print: "\n" | 350 bar <- label: |
259 print: ((add: r9 rdx w) map: :el { hex: el }) | |
260 print: "\n" | |
261 print: ((add: rax rbx q) map: :el { hex: el }) | |
262 print: "\n" | |
263 print: ((add: 25 rax q) map: :el { hex: el }) | |
264 print: "\n" | |
265 print: ((add: rcx rdx d) map: :el { hex: el }) | |
266 print: "\n" | |
267 prog <- #[ | 351 prog <- #[ |
268 mov: rdi rax q | 352 mov: rdi rax q |
269 sub: 1 rdi q | 353 sub: 1 rdi q |
270 add: rdi rax q | 354 add: rdi rax q |
355 jmp: bar | |
356 foo | |
271 ret: | 357 ret: |
358 bar | |
359 sub: 13 rax q | |
360 jmp: foo | |
272 ] | 361 ] |
362 | |
273 ba <- bytearray executableFromBytes: prog | 363 ba <- bytearray executableFromBytes: prog |
274 res <- ba runWithArg: 24u64 | 364 res <- ba runWithArg: 24u64 |
275 print: (string: res) . "\n" | 365 print: (string: res) . "\n" |
276 0 | 366 0 |
277 } | 367 } |