Mercurial > repos > blastem
comparison z80inst.c @ 205:19b323614309
Add support for IX bit instructions to decoder
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 23 Jan 2013 21:50:54 -0800 |
parents | 02dfa5962522 |
children | 807ca611b561 |
comparison
equal
deleted
inserted
replaced
204:02dfa5962522 | 205:19b323614309 |
---|---|
763 NOP2, | 763 NOP2, |
764 NOP2, | 764 NOP2, |
765 NOP2 | 765 NOP2 |
766 }; | 766 }; |
767 | 767 |
768 #define SHIFT_BLOCK_IX(op) \ | |
769 {op, Z80_B, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
770 {op, Z80_C, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
771 {op, Z80_D, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
772 {op, Z80_E, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
773 {op, Z80_H, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
774 {op, Z80_L, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
775 {op, Z80_UNUSED, Z80_IX_DISPLACE | Z80_DIR, 0, 0},\ | |
776 {op, Z80_A, Z80_IX_DISPLACE | Z80_DIR, 0, 0} | |
777 | |
778 #define BIT_BLOCK_IX(bit) \ | |
779 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
780 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
781 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
782 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
783 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
784 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
785 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
786 {Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit} | |
787 | |
788 #define BIT_BLOCK_IX_REG(op, bit) \ | |
789 {op, Z80_B, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\ | |
790 {op, Z80_C, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\ | |
791 {op, Z80_D, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\ | |
792 {op, Z80_E, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\ | |
793 {op, Z80_H, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\ | |
794 {op, Z80_L, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\ | |
795 {op, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\ | |
796 {op, Z80_A, Z80_IX_DISPLACE | Z80_DIR, 0, bit} | |
797 | |
798 z80inst z80_tbl_ix_bit[256] = { | |
799 //0 | |
800 SHIFT_BLOCK_IX(Z80_RLC), | |
801 SHIFT_BLOCK_IX(Z80_RRC), | |
802 //1 | |
803 SHIFT_BLOCK_IX(Z80_RL), | |
804 SHIFT_BLOCK_IX(Z80_RR), | |
805 //2 | |
806 SHIFT_BLOCK_IX(Z80_SLA), | |
807 SHIFT_BLOCK_IX(Z80_SRA), | |
808 //3 | |
809 SHIFT_BLOCK_IX(Z80_SLL), | |
810 SHIFT_BLOCK_IX(Z80_SRL), | |
811 //4 | |
812 BIT_BLOCK_IX(0), | |
813 BIT_BLOCK_IX(1), | |
814 //5 | |
815 BIT_BLOCK_IX(2), | |
816 BIT_BLOCK_IX(3), | |
817 //6 | |
818 BIT_BLOCK_IX(4), | |
819 BIT_BLOCK_IX(5), | |
820 //7 | |
821 BIT_BLOCK_IX(6), | |
822 BIT_BLOCK_IX(7), | |
823 //8 | |
824 BIT_BLOCK_IX_REG(Z80_RES, 0), | |
825 BIT_BLOCK_IX_REG(Z80_RES, 1), | |
826 //9 | |
827 BIT_BLOCK_IX_REG(Z80_RES, 2), | |
828 BIT_BLOCK_IX_REG(Z80_RES, 3), | |
829 //A | |
830 BIT_BLOCK_IX_REG(Z80_RES, 4), | |
831 BIT_BLOCK_IX_REG(Z80_RES, 5), | |
832 //B | |
833 BIT_BLOCK_IX_REG(Z80_RES, 6), | |
834 BIT_BLOCK_IX_REG(Z80_RES, 7), | |
835 //C | |
836 BIT_BLOCK_IX_REG(Z80_SET, 0), | |
837 BIT_BLOCK_IX_REG(Z80_SET, 1), | |
838 //D | |
839 BIT_BLOCK_IX_REG(Z80_SET, 2), | |
840 BIT_BLOCK_IX_REG(Z80_SET, 3), | |
841 //E | |
842 BIT_BLOCK_IX_REG(Z80_SET, 4), | |
843 BIT_BLOCK_IX_REG(Z80_SET, 5), | |
844 //F | |
845 BIT_BLOCK_IX_REG(Z80_SET, 6), | |
846 BIT_BLOCK_IX_REG(Z80_SET, 7), | |
847 }; | |
768 | 848 |
769 z80inst z80_tbl_iy[256] = { | 849 z80inst z80_tbl_iy[256] = { |
770 //0 | 850 //0 |
771 NOP2, | 851 NOP2, |
772 NOP2, | 852 NOP2, |
1041 NOP2 | 1121 NOP2 |
1042 }; | 1122 }; |
1043 | 1123 |
1044 uint8_t * z80_decode(uint8_t * istream, z80inst * decoded) | 1124 uint8_t * z80_decode(uint8_t * istream, z80inst * decoded) |
1045 { | 1125 { |
1126 uint8_t tmp; | |
1046 if (*istream == 0xCB) { | 1127 if (*istream == 0xCB) { |
1047 istream++; | 1128 istream++; |
1048 memcpy(decoded, z80_tbl_bit + *istream, sizeof(z80inst)); | 1129 memcpy(decoded, z80_tbl_bit + *istream, sizeof(z80inst)); |
1049 } else if (*istream == 0xDD) { | 1130 } else if (*istream == 0xDD) { |
1050 istream++; | 1131 istream++; |
1051 if (*istream == 0xCB) { | 1132 if (*istream == 0xCB) { |
1133 tmp = *(++istream); | |
1134 istream++; | |
1135 memcpy(decoded, z80_tbl_ix_bit + *istream, sizeof(z80inst)); | |
1136 decoded->ea_reg = tmp; | |
1052 } else { | 1137 } else { |
1053 memcpy(decoded, z80_tbl_ix + *istream, sizeof(z80inst)); | 1138 memcpy(decoded, z80_tbl_ix + *istream, sizeof(z80inst)); |
1139 if ((decoded->addr_mode & 0x1F) == Z80_IX_DISPLACE) { | |
1140 decoded->ea_reg = *(++istream); | |
1141 } | |
1054 } | 1142 } |
1055 } else if (*istream == 0xED) { | 1143 } else if (*istream == 0xED) { |
1056 istream++; | 1144 istream++; |
1057 if (*istream < 0x40 || *istream >= 0xC0) { | 1145 if (*istream < 0x40 || *istream >= 0xC0) { |
1058 memcpy(decoded, z80_tbl_extd + 0xBF, sizeof(z80inst)); | 1146 memcpy(decoded, z80_tbl_extd + 0xBF, sizeof(z80inst)); |
1062 } else if (*istream == 0xFD) { | 1150 } else if (*istream == 0xFD) { |
1063 istream++; | 1151 istream++; |
1064 if (*istream == 0xCB) { | 1152 if (*istream == 0xCB) { |
1065 } else { | 1153 } else { |
1066 memcpy(decoded, z80_tbl_iy + *istream, sizeof(z80inst)); | 1154 memcpy(decoded, z80_tbl_iy + *istream, sizeof(z80inst)); |
1155 if ((decoded->addr_mode & 0x1F) == Z80_IY_DISPLACE) { | |
1156 decoded->ea_reg = *(++istream); | |
1157 } | |
1067 } | 1158 } |
1068 } else { | 1159 } else { |
1069 memcpy(decoded, z80_tbl_a + *istream, sizeof(z80inst)); | 1160 memcpy(decoded, z80_tbl_a + *istream, sizeof(z80inst)); |
1070 | 1161 |
1071 } | 1162 } |
1072 if ((decoded->addr_mode & 0x1F) == Z80_IX_DISPLACE || (decoded->addr_mode & 0x1F) == Z80_IY_DISPLACE) { | 1163 if ((decoded->addr_mode & 0x1F) == Z80_IMMED && decoded->op != Z80_RST && decoded->op != Z80_IM) { |
1073 decoded->ea_reg = *(++istream); | |
1074 } else if ((decoded->addr_mode & 0x1F) == Z80_IMMED && decoded->op != Z80_RST && decoded->op != Z80_IM) { | |
1075 decoded->immed = *(++istream); | 1164 decoded->immed = *(++istream); |
1076 if (decoded->reg >= Z80_BC && decoded->reg < Z80_USE_IMMED) { | 1165 if (decoded->reg >= Z80_BC && decoded->reg < Z80_UNUSED) { |
1077 decoded->immed |= *(++istream) << 8; | 1166 decoded->immed |= *(++istream) << 8; |
1078 } else if (decoded->immed & 0x80) { | 1167 } else if (decoded->immed & 0x80) { |
1079 decoded->immed |= 0xFF00; | 1168 decoded->immed |= 0xFF00; |
1080 } | 1169 } |
1081 } else if ((decoded->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { | 1170 } else if ((decoded->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { |
1197 }; | 1286 }; |
1198 | 1287 |
1199 int z80_disasm(z80inst * decoded, char * dst) | 1288 int z80_disasm(z80inst * decoded, char * dst) |
1200 { | 1289 { |
1201 int len = sprintf(dst, "%s", z80_mnemonics[decoded->op]); | 1290 int len = sprintf(dst, "%s", z80_mnemonics[decoded->op]); |
1291 uint8_t needcomma; | |
1202 if (decoded->addr_mode & Z80_DIR) { | 1292 if (decoded->addr_mode & Z80_DIR) { |
1293 needcomma = 1; | |
1203 switch (decoded->addr_mode & 0x1F) | 1294 switch (decoded->addr_mode & 0x1F) |
1204 { | 1295 { |
1205 case Z80_REG: | 1296 case Z80_REG: |
1206 len += sprintf(dst+len, " %s", z80_regs[decoded->ea_reg]); | 1297 len += sprintf(dst+len, " %s", z80_regs[decoded->ea_reg]); |
1207 break; | 1298 break; |
1218 len += sprintf(dst+len, " (ix+%d)", decoded->ea_reg); | 1309 len += sprintf(dst+len, " (ix+%d)", decoded->ea_reg); |
1219 break; | 1310 break; |
1220 case Z80_IY_DISPLACE: | 1311 case Z80_IY_DISPLACE: |
1221 len += sprintf(dst+len, " (iy+%d)", decoded->ea_reg); | 1312 len += sprintf(dst+len, " (iy+%d)", decoded->ea_reg); |
1222 break; | 1313 break; |
1314 default: | |
1315 needcomma = 0; | |
1223 } | 1316 } |
1224 if (decoded->reg == Z80_USE_IMMED) { | 1317 if (decoded->reg & Z80_IMMED_FLAG) { |
1225 len += sprintf(dst+len, " %d", decoded->immed); | 1318 len += sprintf(dst+len, "%s %d", needcomma ? "," : "", decoded->immed); |
1226 } else if (decoded->reg != Z80_UNUSED) { | 1319 } |
1320 if ((decoded->reg & 0x1F) != Z80_UNUSED) { | |
1227 if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) { | 1321 if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) { |
1228 len += sprintf(dst+len, "%s %s", decoded->reg == Z80_UNUSED ? "" : "," , z80_conditions[decoded->reg]); | 1322 len += sprintf(dst+len, "%s %s", needcomma ? "," : "", z80_conditions[decoded->reg & 0x1F]); |
1229 } else { | 1323 } else { |
1230 len += sprintf(dst+len, "%s %s", decoded->reg == Z80_UNUSED ? "" : "," , z80_regs[decoded->reg]); | 1324 len += sprintf(dst+len, "%s %s", needcomma ? "," : "", z80_regs[decoded->reg & 0x1F]); |
1231 } | 1325 } |
1232 } | 1326 } |
1233 } else { | 1327 } else { |
1234 if (decoded->reg == Z80_USE_IMMED) { | 1328 needcomma = 0; |
1329 if (decoded->reg & Z80_IMMED_FLAG) { | |
1235 len += sprintf(dst+len, " %d", decoded->immed); | 1330 len += sprintf(dst+len, " %d", decoded->immed); |
1236 } else if (decoded->reg != Z80_UNUSED) { | 1331 needcomma = 1; |
1332 } | |
1333 if ((decoded->reg & 0x1F) != Z80_UNUSED) { | |
1237 if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) { | 1334 if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) { |
1238 len += sprintf(dst+len, " %s", z80_conditions[decoded->reg]); | 1335 len += sprintf(dst+len, " %s", z80_conditions[decoded->reg & 0x1F]); |
1239 } else { | 1336 } else { |
1240 len += sprintf(dst+len, " %s", z80_regs[decoded->reg]); | 1337 len += sprintf(dst+len, " %s", z80_regs[decoded->reg & 0x1F]); |
1241 } | 1338 } |
1339 needcomma = 1; | |
1242 } | 1340 } |
1243 switch (decoded->addr_mode) | 1341 switch (decoded->addr_mode) |
1244 { | 1342 { |
1245 case Z80_REG: | 1343 case Z80_REG: |
1246 len += sprintf(dst+len, "%s %s", decoded->reg == Z80_UNUSED ? "" : "," , z80_regs[decoded->ea_reg]); | 1344 len += sprintf(dst+len, "%s %s", needcomma ? "," : "" , z80_regs[decoded->ea_reg]); |
1247 break; | 1345 break; |
1248 case Z80_REG_INDIRECT: | 1346 case Z80_REG_INDIRECT: |
1249 len += sprintf(dst+len, "%s (%s)", decoded->reg == Z80_UNUSED ? "" : "," , z80_regs[decoded->ea_reg]); | 1347 len += sprintf(dst+len, "%s (%s)", needcomma ? "," : "" , z80_regs[decoded->ea_reg]); |
1250 break; | 1348 break; |
1251 case Z80_IMMED: | 1349 case Z80_IMMED: |
1252 len += sprintf(dst+len, "%s %d", decoded->reg == Z80_UNUSED ? "" : "," , decoded->immed); | 1350 len += sprintf(dst+len, "%s %d", needcomma ? "," : "" , decoded->immed); |
1253 break; | 1351 break; |
1254 case Z80_IMMED_INDIRECT: | 1352 case Z80_IMMED_INDIRECT: |
1255 len += sprintf(dst+len, "%s (%d)", decoded->reg == Z80_UNUSED ? "" : "," , decoded->immed); | 1353 len += sprintf(dst+len, "%s (%d)", needcomma ? "," : "" , decoded->immed); |
1256 break; | 1354 break; |
1257 case Z80_IX_DISPLACE: | 1355 case Z80_IX_DISPLACE: |
1258 len += sprintf(dst+len, "%s (ix+%d)", decoded->reg == Z80_UNUSED ? "" : "," , decoded->ea_reg); | 1356 len += sprintf(dst+len, "%s (ix+%d)", needcomma ? "," : "" , decoded->ea_reg); |
1259 break; | 1357 break; |
1260 case Z80_IY_DISPLACE: | 1358 case Z80_IY_DISPLACE: |
1261 len += sprintf(dst+len, "%s (iy+%d)", decoded->reg == Z80_UNUSED ? "" : "," , decoded->ea_reg); | 1359 len += sprintf(dst+len, "%s (iy+%d)", needcomma ? "," : "" , decoded->ea_reg); |
1262 break; | 1360 break; |
1263 } | 1361 } |
1264 } | 1362 } |
1265 return len; | 1363 return len; |
1266 } | 1364 } |