Mercurial > repos > blastem
comparison gen_x86.c @ 151:6b593ea0ed90
Implement MULU/MULS and DIVU/DIVS
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 03 Jan 2013 22:07:40 -0800 |
parents | 5416a5c4628e |
children | 811163790e6c |
comparison
equal
deleted
inserted
replaced
150:3e68e517cc01 | 151:6b593ea0ed90 |
---|---|
23 #define OP_MOVSXD 0x63 | 23 #define OP_MOVSXD 0x63 |
24 #define PRE_SIZE 0x66 | 24 #define PRE_SIZE 0x66 |
25 #define OP_JCC 0x70 | 25 #define OP_JCC 0x70 |
26 #define OP_IMMED_ARITH 0x80 | 26 #define OP_IMMED_ARITH 0x80 |
27 #define OP_MOV 0x88 | 27 #define OP_MOV 0x88 |
28 #define OP_CDQ 0x99 | |
28 #define OP_PUSHF 0x9C | 29 #define OP_PUSHF 0x9C |
29 #define OP_POPF 0x9D | 30 #define OP_POPF 0x9D |
30 #define OP_MOV_I8R 0xB0 | 31 #define OP_MOV_I8R 0xB0 |
31 #define OP_MOV_IR 0xB8 | 32 #define OP_MOV_IR 0xB8 |
32 #define OP_SHIFTROT_IR 0xC0 | 33 #define OP_SHIFTROT_IR 0xC0 |
42 | 43 |
43 #define OP2_JCC 0x80 | 44 #define OP2_JCC 0x80 |
44 #define OP2_SETCC 0x90 | 45 #define OP2_SETCC 0x90 |
45 #define OP2_BT 0xA3 | 46 #define OP2_BT 0xA3 |
46 #define OP2_BTS 0xAB | 47 #define OP2_BTS 0xAB |
48 #define OP2_IMUL 0xAF | |
47 #define OP2_BTR 0xB3 | 49 #define OP2_BTR 0xB3 |
48 #define OP2_BTX_I 0xBA | 50 #define OP2_BTX_I 0xBA |
49 #define OP2_BTC 0xBB | 51 #define OP2_BTC 0xBB |
50 #define OP2_MOVSX 0xBE | 52 #define OP2_MOVSX 0xBE |
53 #define OP2_MOVZX 0xB6 | |
51 | 54 |
52 #define OP_EX_ADDI 0x0 | 55 #define OP_EX_ADDI 0x0 |
53 #define OP_EX_ORI 0x1 | 56 #define OP_EX_ORI 0x1 |
54 #define OP_EX_ADCI 0x2 | 57 #define OP_EX_ADCI 0x2 |
55 #define OP_EX_SBBI 0x3 | 58 #define OP_EX_SBBI 0x3 |
73 #define OP_EX_BTC 0x7 | 76 #define OP_EX_BTC 0x7 |
74 | 77 |
75 #define OP_EX_TEST_I 0x0 | 78 #define OP_EX_TEST_I 0x0 |
76 #define OP_EX_NOT 0x2 | 79 #define OP_EX_NOT 0x2 |
77 #define OP_EX_NEG 0x3 | 80 #define OP_EX_NEG 0x3 |
81 #define OP_EX_MUL 0x4 | |
82 #define OP_EX_IMUL 0x5 | |
83 #define OP_EX_DIV 0x6 | |
84 #define OP_EX_IDIV 0x7 | |
78 | 85 |
79 #define OP_EX_INC 0x0 | 86 #define OP_EX_INC 0x0 |
80 #define OP_EX_DEC 0x1 | 87 #define OP_EX_DEC 0x1 |
81 #define OP_EX_CALL_EA 0x2 | 88 #define OP_EX_CALL_EA 0x2 |
82 #define OP_EX_JMP_EA 0x4 | 89 #define OP_EX_JMP_EA 0x4 |
108 X86_R13, | 115 X86_R13, |
109 X86_R14, | 116 X86_R14, |
110 X86_R15 | 117 X86_R15 |
111 } x86_regs_enc; | 118 } x86_regs_enc; |
112 | 119 |
113 uint8_t * x86_rr_sizedir(uint8_t * out, uint8_t opcode, uint8_t src, uint8_t dst, uint8_t size) | 120 uint8_t * x86_rr_sizedir(uint8_t * out, uint16_t opcode, uint8_t src, uint8_t dst, uint8_t size) |
114 { | 121 { |
115 //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix | 122 //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix |
116 uint8_t tmp; | 123 uint8_t tmp; |
117 if (size == SZ_W) { | 124 if (size == SZ_W) { |
118 *(out++) = PRE_SIZE; | 125 *(out++) = PRE_SIZE; |
146 dst -= (AH-X86_AH); | 153 dst -= (AH-X86_AH); |
147 } | 154 } |
148 } else { | 155 } else { |
149 opcode |= BIT_SIZE; | 156 opcode |= BIT_SIZE; |
150 } | 157 } |
151 *(out++) = opcode; | 158 if (opcode >= 0x100) { |
159 *(out++) = opcode >> 8; | |
160 *(out++) = opcode; | |
161 } else { | |
162 *(out++) = opcode; | |
163 } | |
152 *(out++) = MODE_REG_DIRECT | dst | (src << 3); | 164 *(out++) = MODE_REG_DIRECT | dst | (src << 3); |
153 return out; | 165 return out; |
154 } | 166 } |
155 | 167 |
156 uint8_t * x86_rrdisp8_sizedir(uint8_t * out, uint8_t opcode, uint8_t reg, uint8_t base, int8_t disp, uint8_t size, uint8_t dir) | 168 uint8_t * x86_rrdisp8_sizedir(uint8_t * out, uint16_t opcode, uint8_t reg, uint8_t base, int8_t disp, uint8_t size, uint8_t dir) |
157 { | 169 { |
158 //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix | 170 //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix |
159 uint8_t tmp; | 171 uint8_t tmp; |
160 if (size == SZ_W) { | 172 if (size == SZ_W) { |
161 *(out++) = PRE_SIZE; | 173 *(out++) = PRE_SIZE; |
180 reg -= (AH-X86_AH); | 192 reg -= (AH-X86_AH); |
181 } | 193 } |
182 } else { | 194 } else { |
183 opcode |= BIT_SIZE; | 195 opcode |= BIT_SIZE; |
184 } | 196 } |
185 *(out++) = opcode | dir; | 197 opcode |= dir; |
198 if (opcode >= 0x100) { | |
199 *(out++) = opcode >> 8; | |
200 *(out++) = opcode; | |
201 } else { | |
202 *(out++) = opcode; | |
203 } | |
186 *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3); | 204 *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3); |
187 if (base == RSP) { | 205 if (base == RSP) { |
188 //add SIB byte, with no index and RSP as base | 206 //add SIB byte, with no index and RSP as base |
189 *(out++) = (RSP << 3) | RSP; | 207 *(out++) = (RSP << 3) | RSP; |
190 } | 208 } |
826 uint8_t * cmp_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size) | 844 uint8_t * cmp_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size) |
827 { | 845 { |
828 return x86_rrdisp8_sizedir(out, OP_CMP, dst, src_base, disp, size, BIT_DIR); | 846 return x86_rrdisp8_sizedir(out, OP_CMP, dst, src_base, disp, size, BIT_DIR); |
829 } | 847 } |
830 | 848 |
849 uint8_t * imul_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) | |
850 { | |
851 return x86_rr_sizedir(out, OP2_IMUL | (PRE_2BYTE << 8), dst, src, size); | |
852 } | |
853 | |
854 uint8_t * imul_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size) | |
855 { | |
856 return x86_rrdisp8_sizedir(out, OP2_IMUL | (PRE_2BYTE << 8), dst, src_base, disp, size, 0); | |
857 } | |
858 | |
831 uint8_t * not_r(uint8_t * out, uint8_t dst, uint8_t size) | 859 uint8_t * not_r(uint8_t * out, uint8_t dst, uint8_t size) |
832 { | 860 { |
833 return x86_r_size(out, OP_NOT_NEG, OP_EX_NOT, dst, size); | 861 return x86_r_size(out, OP_NOT_NEG, OP_EX_NOT, dst, size); |
834 } | 862 } |
835 | 863 |
844 } | 872 } |
845 | 873 |
846 uint8_t * neg_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size) | 874 uint8_t * neg_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size) |
847 { | 875 { |
848 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_NEG, dst_base, disp, size); | 876 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_NEG, dst_base, disp, size); |
877 } | |
878 | |
879 uint8_t * mul_r(uint8_t * out, uint8_t dst, uint8_t size) | |
880 { | |
881 return x86_r_size(out, OP_NOT_NEG, OP_EX_MUL, dst, size); | |
882 } | |
883 | |
884 uint8_t * imul_r(uint8_t * out, uint8_t dst, uint8_t size) | |
885 { | |
886 return x86_r_size(out, OP_NOT_NEG, OP_EX_IMUL, dst, size); | |
887 } | |
888 | |
889 uint8_t * div_r(uint8_t * out, uint8_t dst, uint8_t size) | |
890 { | |
891 return x86_r_size(out, OP_NOT_NEG, OP_EX_DIV, dst, size); | |
892 } | |
893 | |
894 uint8_t * idiv_r(uint8_t * out, uint8_t dst, uint8_t size) | |
895 { | |
896 return x86_r_size(out, OP_NOT_NEG, OP_EX_IDIV, dst, size); | |
897 } | |
898 | |
899 uint8_t * mul_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size) | |
900 { | |
901 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_MUL, dst_base, disp, size); | |
902 } | |
903 | |
904 uint8_t * imul_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size) | |
905 { | |
906 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_IMUL, dst_base, disp, size); | |
907 } | |
908 | |
909 uint8_t * div_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size) | |
910 { | |
911 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_DIV, dst_base, disp, size); | |
912 } | |
913 | |
914 uint8_t * idiv_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size) | |
915 { | |
916 return x86_rdisp8_size(out, OP_NOT_NEG, OP_EX_IDIV, dst_base, disp, size); | |
849 } | 917 } |
850 | 918 |
851 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) | 919 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) |
852 { | 920 { |
853 return x86_rr_sizedir(out, OP_MOV, src, dst, size); | 921 return x86_rr_sizedir(out, OP_MOV, src, dst, size); |
1060 *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3); | 1128 *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3); |
1061 *(out++) = disp; | 1129 *(out++) = disp; |
1062 return out; | 1130 return out; |
1063 } | 1131 } |
1064 | 1132 |
1133 uint8_t * movzx_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size) | |
1134 { | |
1135 if (size == SZ_W) { | |
1136 *(out++) = PRE_SIZE; | |
1137 } | |
1138 if (size == SZ_Q || dst >= R8 || src >= R8) { | |
1139 *out = PRE_REX; | |
1140 if (size == SZ_Q) { | |
1141 *out |= REX_QUAD; | |
1142 } | |
1143 if (src >= R8) { | |
1144 *out |= REX_RM_FIELD; | |
1145 src -= (R8 - X86_R8); | |
1146 } | |
1147 if (dst >= R8) { | |
1148 *out |= REX_REG_FIELD; | |
1149 dst -= (R8 - X86_R8); | |
1150 } | |
1151 out++; | |
1152 } | |
1153 *(out++) = PRE_2BYTE; | |
1154 *(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE); | |
1155 *(out++) = MODE_REG_DIRECT | src | (dst << 3); | |
1156 return out; | |
1157 } | |
1158 | |
1159 uint8_t * movzx_rdisp8r(uint8_t * out, uint8_t src, int8_t disp, uint8_t dst, uint8_t src_size, uint8_t size) | |
1160 { | |
1161 if (size == SZ_W) { | |
1162 *(out++) = PRE_SIZE; | |
1163 } | |
1164 if (size == SZ_Q || dst >= R8 || src >= R8) { | |
1165 *out = PRE_REX; | |
1166 if (size == SZ_Q) { | |
1167 *out |= REX_QUAD; | |
1168 } | |
1169 if (src >= R8) { | |
1170 *out |= REX_RM_FIELD; | |
1171 src -= (R8 - X86_R8); | |
1172 } | |
1173 if (dst >= R8) { | |
1174 *out |= REX_REG_FIELD; | |
1175 dst -= (R8 - X86_R8); | |
1176 } | |
1177 out++; | |
1178 } | |
1179 *(out++) = PRE_2BYTE; | |
1180 *(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE); | |
1181 *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3); | |
1182 *(out++) = disp; | |
1183 return out; | |
1184 } | |
1185 | |
1065 uint8_t * pushf(uint8_t * out) | 1186 uint8_t * pushf(uint8_t * out) |
1066 { | 1187 { |
1067 *(out++) = OP_PUSHF; | 1188 *(out++) = OP_PUSHF; |
1068 return out; | 1189 return out; |
1069 } | 1190 } |
1404 { | 1525 { |
1405 *(out++) = OP_RETN; | 1526 *(out++) = OP_RETN; |
1406 return out; | 1527 return out; |
1407 } | 1528 } |
1408 | 1529 |
1409 | 1530 uint8_t * cdq(uint8_t * out) |
1531 { | |
1532 *(out++) = OP_CDQ; | |
1533 return out; | |
1534 } | |
1535 | |
1536 |