comparison gen_x86.c @ 15:c0f339564819

Make x86 generator generic with respect to operand size for immediate parameters.
author Mike Pavone <pavone@retrodev.com>
date Tue, 27 Nov 2012 22:43:32 -0800
parents 2bdad0f52f42
children 3e7bfde7606e
comparison
equal deleted inserted replaced
14:2bdad0f52f42 15:c0f339564819
27 #define OP_PUSHF 0x9C 27 #define OP_PUSHF 0x9C
28 #define OP_POPF 0x9D 28 #define OP_POPF 0x9D
29 #define OP_MOV_I8R 0xB0 29 #define OP_MOV_I8R 0xB0
30 #define OP_MOV_IR 0xB8 30 #define OP_MOV_IR 0xB8
31 #define OP_RETN 0xC3 31 #define OP_RETN 0xC3
32 #define OP_MOV_IEA 0xC6
32 #define OP_CALL 0xE8 33 #define OP_CALL 0xE8
33 #define OP_CALL_EA 0xFF 34 #define OP_CALL_EA 0xFF
34 35
35 #define OP2_JCC 0x80 36 #define OP2_JCC 0x80
36 #define OP2_SETCC 0x90 37 #define OP2_SETCC 0x90
195 *(out++) = opcode | dir; 196 *(out++) = opcode | dir;
196 *(out++) = MODE_REG_INDIRECT | base | (reg << 3); 197 *(out++) = MODE_REG_INDIRECT | base | (reg << 3);
197 return out; 198 return out;
198 } 199 }
199 200
200 uint8_t * x86_i8r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, uint8_t val, uint8_t dst) 201 uint8_t * x86_ir(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst, uint8_t size)
201 { 202 {
202 if (dst == RAX) { 203 uint8_t sign_extend = 0;
204 if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
205 sign_extend = 1;
206 opcode |= BIT_DIR;
207 }
208 if (size == SZ_W) {
209 *(out++) = PRE_SIZE;
210 }
211 if (dst == RAX && !sign_extend) {
212 if (size != SZ_B) {
213 al_opcode |= BIT_SIZE;
214 if (size == SZ_Q) {
215 *out = PRE_REX | REX_QUAD;
216 }
217 }
203 *(out++) = al_opcode | BIT_IMMED_RAX; 218 *(out++) = al_opcode | BIT_IMMED_RAX;
204 } else { 219 } else {
220 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
221 *out = PRE_REX;
222 if (size == SZ_Q) {
223 *out |= REX_QUAD;
224 }
225 if (dst >= R8) {
226 *out |= REX_RM_FIELD;
227 dst -= (R8 - X86_R8);
228 }
229 out++;
230 }
205 if (dst >= AH && dst <= BH) { 231 if (dst >= AH && dst <= BH) {
206 dst -= (AH-X86_AH); 232 dst -= (AH-X86_AH);
207 } else if(dst >= R8) { 233 }
208 *(out++) = PRE_REX | REX_RM_FIELD; 234 if (size != SZ_B) {
235 opcode |= BIT_SIZE;
209 } 236 }
210 *(out++) = opcode; 237 *(out++) = opcode;
211 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); 238 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
212 } 239 }
213 *(out++) = val; 240 *(out++) = val;
214 return out; 241 if (size != SZ_B && !sign_extend) {
215 }
216
217 uint8_t * x86_i32r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst)
218 {
219 uint8_t sign_extend = 0;
220 if (val <= 0x7F && val >= -0x80) {
221 sign_extend = 1;
222 opcode |= BIT_DIR;
223 }
224 if (dst == RAX && !sign_extend) {
225 *(out++) = al_opcode | BIT_IMMED_RAX | BIT_SIZE;
226 } else {
227 if(dst >= R8) {
228 *(out++) = PRE_REX | REX_RM_FIELD;
229 }
230 *(out++) = opcode | BIT_SIZE;
231 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
232 }
233 *(out++) = val;
234 if (!sign_extend) {
235 val >>= 8; 242 val >>= 8;
236 *(out++) = val; 243 *(out++) = val;
244 if (size != SZ_W) {
245 val >>= 8;
246 *(out++) = val;
247 val >>= 8;
248 *(out++) = val;
249 }
250 }
251 return out;
252 }
253
254
255 uint8_t * add_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
256 {
257 return x86_rr_sizedir(out, OP_ADD, src, dst, size);
258 }
259
260 uint8_t * add_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
261 {
262 return x86_ir(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst, size);
263 }
264
265 uint8_t * or_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
266 {
267 return x86_rr_sizedir(out, OP_OR, src, dst, size);
268 }
269 uint8_t * or_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
270 {
271 return x86_ir(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst, size);
272 }
273
274 uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
275 {
276 return x86_rr_sizedir(out, OP_AND, src, dst, size);
277 }
278
279 uint8_t * and_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
280 {
281 return x86_ir(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst, size);
282 }
283
284 uint8_t * xor_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
285 {
286 return x86_rr_sizedir(out, OP_XOR, src, dst, size);
287 }
288
289 uint8_t * xor_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
290 {
291 return x86_ir(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst, size);
292 }
293
294 uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
295 {
296 return x86_rr_sizedir(out, OP_SUB, src, dst, size);
297 }
298
299 uint8_t * sub_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
300 {
301 return x86_ir(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst, size);
302 }
303
304 uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
305 {
306 return x86_rr_sizedir(out, OP_CMP, src, dst, size);
307 }
308
309 uint8_t * cmp_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
310 {
311 return x86_ir(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst, size);
312 }
313
314 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
315 {
316 return x86_rr_sizedir(out, OP_MOV, src, dst, size);
317 }
318
319 uint8_t * mov_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size)
320 {
321 return x86_rrdisp8_sizedir(out, OP_MOV, src, dst_base, disp, size, 0);
322 }
323
324 uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size)
325 {
326 return x86_rrdisp8_sizedir(out, OP_MOV, dst, src_base, disp, size, BIT_DIR);
327 }
328
329 uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
330 {
331 return x86_rrind_sizedir(out, OP_MOV, src, dst, size, 0);
332 }
333
334 uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
335 {
336 return x86_rrind_sizedir(out, OP_MOV, dst, src, size, BIT_DIR);
337 }
338
339 uint8_t * mov_ir(uint8_t * out, int64_t val, uint8_t dst, uint8_t size)
340 {
341 uint8_t sign_extend = 0;
342 if (size == SZ_Q && val <= 0x7FFFFFFF && val >= -2147483648) {
343 sign_extend = 1;
344 }
345 if (size == SZ_W) {
346 *(out++) = PRE_SIZE;
347 }
348 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
349 *out = PRE_REX;
350 if (size == SZ_Q) {
351 *out |= REX_QUAD;
352 }
353 if (dst >= R8) {
354 *out |= REX_RM_FIELD;
355 dst -= (R8 - X86_R8);
356 }
357 out++;
358 }
359 if (dst >= AH && dst <= BH) {
360 dst -= (AH-X86_AH);
361 }
362 if (size == SZ_B) {
363 *(out++) = OP_MOV_I8R;
364 } else if (size == SZ_Q && sign_extend) {
365 *(out++) = OP_MOV_IEA | BIT_SIZE;
366 *(out++) = MODE_REG_DIRECT | dst;
367 } else {
368 *(out++) = OP_MOV_IR;
369 }
370 *(out++) = val;
371 if (size != SZ_B) {
237 val >>= 8; 372 val >>= 8;
238 *(out++) = val; 373 *(out++) = val;
239 val >>= 8; 374 if (size != SZ_W) {
240 *(out++) = val; 375 val >>= 8;
241 } 376 *(out++) = val;
242 return out; 377 val >>= 8;
243 } 378 *(out++) = val;
244 379 if (size == SZ_Q && !sign_extend) {
245 uint8_t * add_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) 380 val >>= 8;
246 { 381 *(out++) = val;
247 return x86_rr_sizedir(out, OP_ADD, src, dst, size); 382 val >>= 8;
248 } 383 *(out++) = val;
249 384 val >>= 8;
250 uint8_t * add_i8r(uint8_t * out, uint8_t val, uint8_t dst) 385 *(out++) = val;
251 { 386 val >>= 8;
252 return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst); 387 *(out++) = val;
253 } 388 }
254 389 }
255 uint8_t * add_i32r(uint8_t * out, int32_t val, uint8_t dst) 390 }
256 {
257 return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst);
258 }
259
260 uint8_t * or_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
261 {
262 return x86_rr_sizedir(out, OP_OR, src, dst, size);
263 }
264
265 uint8_t * or_i8r(uint8_t * out, uint8_t val, uint8_t dst)
266 {
267 return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst);
268 }
269
270 uint8_t * or_i32r(uint8_t * out, int32_t val, uint8_t dst)
271 {
272 return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst);
273 }
274
275 uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
276 {
277 return x86_rr_sizedir(out, OP_AND, src, dst, size);
278 }
279
280 uint8_t * and_i8r(uint8_t * out, uint8_t val, uint8_t dst)
281 {
282 return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst);
283 }
284
285 uint8_t * and_i32r(uint8_t * out, int32_t val, uint8_t dst)
286 {
287 return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst);
288 }
289
290 uint8_t * xor_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
291 {
292 return x86_rr_sizedir(out, OP_XOR, src, dst, size);
293 }
294
295 uint8_t * xor_i8r(uint8_t * out, uint8_t val, uint8_t dst)
296 {
297 return x86_i8r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst);
298 }
299
300 uint8_t * xor_i32r(uint8_t * out, int32_t val, uint8_t dst)
301 {
302 return x86_i32r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst);
303 }
304
305 uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
306 {
307 return x86_rr_sizedir(out, OP_SUB, src, dst, size);
308 }
309
310 uint8_t * sub_i8r(uint8_t * out, uint8_t val, uint8_t dst)
311 {
312 return x86_i8r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst);
313 }
314
315 uint8_t * sub_i32r(uint8_t * out, int32_t val, uint8_t dst)
316 {
317 return x86_i32r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst);
318 }
319
320
321 uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
322 {
323 return x86_rr_sizedir(out, OP_CMP, src, dst, size);
324 }
325
326 uint8_t * cmp_i8r(uint8_t * out, uint8_t val, uint8_t dst)
327 {
328 return x86_i8r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst);
329 }
330
331 uint8_t * cmp_i32r(uint8_t * out, int32_t val, uint8_t dst)
332 {
333 return x86_i32r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst);
334 }
335
336 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
337 {
338 return x86_rr_sizedir(out, OP_MOV, src, dst, size);
339 }
340
341 uint8_t * mov_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size)
342 {
343 return x86_rrdisp8_sizedir(out, OP_MOV, src, dst_base, disp, size, 0);
344 }
345
346 uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size)
347 {
348 return x86_rrdisp8_sizedir(out, OP_MOV, dst, src_base, disp, size, BIT_DIR);
349 }
350
351 uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
352 {
353 return x86_rrind_sizedir(out, OP_MOV, src, dst, size, 0);
354 }
355
356 uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
357 {
358 return x86_rrind_sizedir(out, OP_MOV, dst, src, size, BIT_DIR);
359 }
360
361 uint8_t * mov_i8r(uint8_t * out, uint8_t val, uint8_t dst)
362 {
363 if (dst >= AH && dst <= BH) {
364 dst -= AH - X86_AH;
365 } else if (dst >= RSP && dst <= RDI) {
366 *(out++) = PRE_REX;
367 } else if (dst >= R8) {
368 *(out++) = PRE_REX | REX_RM_FIELD;
369 dst -= R8 - X86_R8;
370 }
371 *(out++) = OP_MOV_I8R | dst;
372 *(out++) = val;
373 return out;
374 }
375
376 uint8_t * mov_i16r(uint8_t * out, uint16_t val, uint8_t dst)
377 {
378 *(out++) = PRE_SIZE;
379 if (dst >= R8) {
380 *(out++) = PRE_REX | REX_RM_FIELD;
381 dst -= R8 - X86_R8;
382 }
383 *(out++) = OP_MOV_IR | dst;
384 *(out++) = val;
385 val >>= 8;
386 *(out++) = val;
387 return out;
388 }
389
390 uint8_t * mov_i32r(uint8_t * out, uint32_t val, uint8_t dst)
391 {
392 if (dst >= R8) {
393 *(out++) = PRE_REX | REX_RM_FIELD;
394 dst -= R8 - X86_R8;
395 }
396 *(out++) = OP_MOV_IR | dst;
397 *(out++) = val;
398 val >>= 8;
399 *(out++) = val;
400 val >>= 8;
401 *(out++) = val;
402 val >>= 8;
403 *(out++) = val;
404 return out; 391 return out;
405 } 392 }
406 393
407 uint8_t * pushf(uint8_t * out) 394 uint8_t * pushf(uint8_t * out)
408 { 395 {