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