comparison gen_x86.c @ 82:6331ddec228f

Initial stab at interrupt support. Make native code offsets bigger so I don't have to worry about overflowing the offset. Implement neg and not (untested).
author Mike Pavone <pavone@retrodev.com>
date Wed, 26 Dec 2012 11:09:04 -0800
parents 6d231dbe75ab
children e3594572fb98
comparison
equal deleted inserted replaced
81:6d231dbe75ab 82:6331ddec228f
35 #define OP_SHIFTROT_1 0xD0 35 #define OP_SHIFTROT_1 0xD0
36 #define OP_SHIFTROT_CL 0xD2 36 #define OP_SHIFTROT_CL 0xD2
37 #define OP_CALL 0xE8 37 #define OP_CALL 0xE8
38 #define OP_JMP 0xE9 38 #define OP_JMP 0xE9
39 #define OP_JMP_BYTE 0xEB 39 #define OP_JMP_BYTE 0xEB
40 #define OP_NOT_NEG 0xF6
40 #define OP_SINGLE_EA 0xFF 41 #define OP_SINGLE_EA 0xFF
41 42
42 #define OP2_JCC 0x80 43 #define OP2_JCC 0x80
43 #define OP2_SETCC 0x90 44 #define OP2_SETCC 0x90
44 #define OP2_BT 0xA3 45 #define OP2_BT 0xA3
65 66
66 #define OP_EX_BT 0x4 67 #define OP_EX_BT 0x4
67 #define OP_EX_BTS 0x5 68 #define OP_EX_BTS 0x5
68 #define OP_EX_BTR 0x6 69 #define OP_EX_BTR 0x6
69 #define OP_EX_BTC 0x7 70 #define OP_EX_BTC 0x7
71
72 #define OP_EX_TEST_I 0x0
73 #define OP_EX_NOT 0x2
74 #define OP_EX_NEG 0x3
70 75
71 #define OP_EX_INC 0x0 76 #define OP_EX_INC 0x0
72 #define OP_EX_DEC 0x1 77 #define OP_EX_DEC 0x1
73 #define OP_EX_CALL_EA 0x2 78 #define OP_EX_CALL_EA 0x2
74 #define OP_EX_JMP_EA 0x4 79 #define OP_EX_JMP_EA 0x4
220 *(out++) = (RSP << 3) | RSP; 225 *(out++) = (RSP << 3) | RSP;
221 } 226 }
222 return out; 227 return out;
223 } 228 }
224 229
230 uint8_t * x86_r_size(uint8_t * out, uint8_t opcode, uint8_t opex, uint8_t dst, uint8_t size)
231 {
232 uint8_t tmp;
233 if (size == SZ_W) {
234 *(out++) = PRE_SIZE;
235 }
236 if (size == SZ_Q || dst >= R8) {
237 *out = PRE_REX;
238 if (size == SZ_Q) {
239 *out |= REX_QUAD;
240 }
241 if (dst >= R8) {
242 *out |= REX_RM_FIELD;
243 dst -= (R8 - X86_R8);
244 }
245 out++;
246 }
247 if (size == SZ_B) {
248 if (dst >= AH && dst <= BH) {
249 dst -= (AH-X86_AH);
250 }
251 } else {
252 opcode |= BIT_SIZE;
253 }
254 *(out++) = opcode;
255 *(out++) = MODE_REG_DIRECT | dst | (opex << 3);
256 return out;
257 }
258
259 uint8_t * x86_rdisp8_size(uint8_t * out, uint8_t opcode, uint8_t opex, uint8_t dst, int8_t disp, uint8_t size)
260 {
261 uint8_t tmp;
262 if (size == SZ_W) {
263 *(out++) = PRE_SIZE;
264 }
265 if (size == SZ_Q || dst >= R8) {
266 *out = PRE_REX;
267 if (size == SZ_Q) {
268 *out |= REX_QUAD;
269 }
270 if (dst >= R8) {
271 *out |= REX_RM_FIELD;
272 dst -= (R8 - X86_R8);
273 }
274 out++;
275 }
276 if (size != SZ_B) {
277 opcode |= BIT_SIZE;
278 }
279 *(out++) = opcode;
280 *(out++) = MODE_REG_DISPLACE8 | dst | (opex << 3);
281 *(out++) = disp;
282 return out;
283 }
284
225 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) 285 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)
226 { 286 {
227 uint8_t sign_extend = 0; 287 uint8_t sign_extend = 0;
228 if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) { 288 if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
229 sign_extend = 1; 289 sign_extend = 1;
295 *out |= REX_RM_FIELD; 355 *out |= REX_RM_FIELD;
296 dst -= (R8 - X86_R8); 356 dst -= (R8 - X86_R8);
297 } 357 }
298 out++; 358 out++;
299 } 359 }
300 if (dst >= AH && dst <= BH) {
301 dst -= (AH-X86_AH);
302 }
303 if (size != SZ_B) { 360 if (size != SZ_B) {
304 opcode |= BIT_SIZE; 361 opcode |= BIT_SIZE;
305 } 362 }
306 *(out++) = opcode; 363 *(out++) = opcode;
307 *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3); 364 *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
714 } 771 }
715 772
716 uint8_t * cmp_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size) 773 uint8_t * cmp_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size)
717 { 774 {
718 return x86_rrdisp8_sizedir(out, OP_CMP, dst, src_base, disp, size, BIT_DIR); 775 return x86_rrdisp8_sizedir(out, OP_CMP, dst, src_base, disp, size, BIT_DIR);
776 }
777
778 uint8_t * not_r(uint8_t * out, uint8_t dst, uint8_t size)
779 {
780 return x86_r_size(out, OP_NOT_NEG, OP_EX_NOT, dst, size);
781 }
782
783 uint8_t * neg_r(uint8_t * out, uint8_t dst, uint8_t size)
784 {
785 return x86_r_size(out, OP_NOT_NEG, OP_EX_NEG, dst, size);
786 }
787
788 uint8_t * not_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size)
789 {
790 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_NOT, dst_base, disp, size);
791 }
792
793 uint8_t * neg_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size)
794 {
795 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_NEG, dst_base, disp, size);
719 } 796 }
720 797
721 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) 798 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
722 { 799 {
723 return x86_rr_sizedir(out, OP_MOV, src, dst, size); 800 return x86_rr_sizedir(out, OP_MOV, src, dst, size);
1145 1222
1146 uint8_t * jmp_r(uint8_t * out, uint8_t dst) 1223 uint8_t * jmp_r(uint8_t * out, uint8_t dst)
1147 { 1224 {
1148 *(out++) = OP_SINGLE_EA; 1225 *(out++) = OP_SINGLE_EA;
1149 *(out++) = MODE_REG_DIRECT | dst | (OP_EX_JMP_EA << 3); 1226 *(out++) = MODE_REG_DIRECT | dst | (OP_EX_JMP_EA << 3);
1227 return out;
1150 } 1228 }
1151 1229
1152 uint8_t * call(uint8_t * out, uint8_t * fun) 1230 uint8_t * call(uint8_t * out, uint8_t * fun)
1153 { 1231 {
1154 ptrdiff_t disp = fun-(out+5); 1232 ptrdiff_t disp = fun-(out+5);