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