comparison 68kinst.c @ 13:168b1a873895

Improve disassembly. FIx some decoding bugs.
author Mike Pavone <pavone@retrodev.com>
date Thu, 15 Nov 2012 22:15:43 -0800
parents db60ed283d8d
children c0f339564819
comparison
equal deleted inserted replaced
12:db60ed283d8d 13:168b1a873895
401 } 401 }
402 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 402 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
403 decoded->dst.addr_mode = MODE_REG; 403 decoded->dst.addr_mode = MODE_REG;
404 decoded->dst.addr_mode = m68K_reg_quick_field(*istream); 404 decoded->dst.addr_mode = m68K_reg_quick_field(*istream);
405 } else { 405 } else {
406 if ((*istream & 0xB80) == 0x880) { 406 opmode = (*istream >> 3) & 0x7;
407 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG && opmode != MODE_AREG_POSTINC) {
407 decoded->op = M68K_MOVEM; 408 decoded->op = M68K_MOVEM;
408 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; 409 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
410 reg = *istream & 0x7;
409 immed = *(++istream); 411 immed = *(++istream);
410 opmode = (*istream >> 3) & 0x7;
411 reg = *istream & 0x7;
412 if(*istream & 0x400) { 412 if(*istream & 0x400) {
413 decoded->dst.addr_mode = MODE_REG; 413 decoded->dst.addr_mode = MODE_REG;
414 decoded->dst.params.u16 = immed; 414 decoded->dst.params.u16 = immed;
415 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src)); 415 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src));
416 } else { 416 } else {
519 default: 519 default:
520 if (!(*istream & 0x1C0)) { 520 if (!(*istream & 0x1C0)) {
521 decoded->op = M68K_NBCD; 521 decoded->op = M68K_NBCD;
522 decoded->extra.size = OPSIZE_BYTE; 522 decoded->extra.size = OPSIZE_BYTE;
523 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); 523 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
524 } else if(*istream & 0x1C0 == 0x40) { 524 } else if((*istream & 0x1C0) == 0x40) {
525 decoded->op = M68K_PEA; 525 decoded->op = M68K_PEA;
526 decoded->extra.size = OPSIZE_LONG; 526 decoded->extra.size = OPSIZE_LONG;
527 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->dst)); 527 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->dst));
528 } 528 }
529 } 529 }
580 decoded->op = M68K_LINK; 580 decoded->op = M68K_LINK;
581 decoded->extra.size = OPSIZE_WORD; 581 decoded->extra.size = OPSIZE_WORD;
582 decoded->src.addr_mode = MODE_AREG; 582 decoded->src.addr_mode = MODE_AREG;
583 decoded->src.params.regs.pri = *istream & 0x7; 583 decoded->src.params.regs.pri = *istream & 0x7;
584 decoded->dst.addr_mode = MODE_IMMEDIATE; 584 decoded->dst.addr_mode = MODE_IMMEDIATE;
585 decoded->dst.params.u16 = immed; 585 decoded->dst.params.u16 = *(++istream);
586 break; 586 break;
587 case 3: 587 case 3:
588 //UNLK 588 //UNLK
589 decoded->op = M68K_UNLK; 589 decoded->op = M68K_UNLK;
590 decoded->extra.size = OPSIZE_UNSIZED; 590 decoded->extra.size = OPSIZE_UNSIZED;
1047 char * mnemonics[] = { 1047 char * mnemonics[] = {
1048 "abcd", 1048 "abcd",
1049 "add", 1049 "add",
1050 "addx", 1050 "addx",
1051 "and", 1051 "and",
1052 "andi_ccr", 1052 "andi",//ccr
1053 "andi_sr", 1053 "andi",//sr
1054 "asl", 1054 "asl",
1055 "asr", 1055 "asr",
1056 "bcc", 1056 "bcc",
1057 "bchg", 1057 "bchg",
1058 "bclr", 1058 "bclr",
1064 "cmp", 1064 "cmp",
1065 "dbcc", 1065 "dbcc",
1066 "divs", 1066 "divs",
1067 "divu", 1067 "divu",
1068 "eor", 1068 "eor",
1069 "eori_ccr", 1069 "eori",//ccr
1070 "eori_sr", 1070 "eori",//sr
1071 "exg", 1071 "exg",
1072 "ext", 1072 "ext",
1073 "illegal", 1073 "illegal",
1074 "jmp", 1074 "jmp",
1075 "jsr", 1075 "jsr",
1076 "lea", 1076 "lea",
1077 "link", 1077 "link",
1078 "lsl", 1078 "lsl",
1079 "lsr", 1079 "lsr",
1080 "move", 1080 "move",
1081 "move_ccr", 1081 "move",//ccr
1082 "move_from_sr", 1082 "move",//from_sr
1083 "move_sr", 1083 "move",//sr
1084 "move_usp", 1084 "move_usp",
1085 "movem", 1085 "movem",
1086 "movep", 1086 "movep",
1087 "muls", 1087 "muls",
1088 "mulu", 1088 "mulu",
1090 "neg", 1090 "neg",
1091 "negx", 1091 "negx",
1092 "nop", 1092 "nop",
1093 "not", 1093 "not",
1094 "or", 1094 "or",
1095 "ori_ccr", 1095 "ori",//ccr
1096 "ori_sr", 1096 "ori",//sr
1097 "pea", 1097 "pea",
1098 "reset", 1098 "reset",
1099 "rol", 1099 "rol",
1100 "ror", 1100 "ror",
1101 "roxl", 1101 "roxl",
1134 "lt", 1134 "lt",
1135 "gt", 1135 "gt",
1136 "le" 1136 "le"
1137 }; 1137 };
1138 1138
1139 int m68K_disasm_op(m68k_op_info *decoded, uint8_t size, char *dst, int need_comma) 1139 int m68k_disasm_op(m68k_op_info *decoded, uint8_t size, char *dst, int need_comma)
1140 { 1140 {
1141 char * c = need_comma ? "," : ""; 1141 char * c = need_comma ? "," : "";
1142 switch(decoded->addr_mode) 1142 switch(decoded->addr_mode)
1143 { 1143 {
1144 case MODE_REG: 1144 case MODE_REG:
1149 return sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri); 1149 return sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
1150 case MODE_AREG_POSTINC: 1150 case MODE_AREG_POSTINC:
1151 return sprintf(dst, "%s (a%d)+", c, decoded->params.regs.pri); 1151 return sprintf(dst, "%s (a%d)+", c, decoded->params.regs.pri);
1152 case MODE_AREG_PREDEC: 1152 case MODE_AREG_PREDEC:
1153 return sprintf(dst, "%s -(a%d)", c, decoded->params.regs.pri); 1153 return sprintf(dst, "%s -(a%d)", c, decoded->params.regs.pri);
1154 case MODE_AREG_DISPLACE:
1155 return sprintf(dst, "%s (a%d, %d)", c, decoded->params.regs.pri, decoded->params.regs.displacement);
1154 case MODE_IMMEDIATE: 1156 case MODE_IMMEDIATE:
1155 return sprintf(dst, "%s #%d", c, (size == OPSIZE_LONG || size == OPSIZE_UNSIZED) ? decoded->params.u32 : (size == OPSIZE_WORD ? decoded->params.u16 : decoded->params.u8)); 1157 return sprintf(dst, "%s #%d", c, (size == OPSIZE_LONG || size == OPSIZE_UNSIZED) ? decoded->params.u32 : (size == OPSIZE_WORD ? decoded->params.u16 : decoded->params.u8));
1158 case MODE_ABSOLUTE_SHORT:
1159 return sprintf(dst, "%s $%X.w", c, decoded->params.u32);
1160 case MODE_ABSOLUTE:
1161 return sprintf(dst, "%s $%X", c, decoded->params.u32);
1162 case MODE_PC_DISPLACE:
1163 return sprintf(dst, "%s (pc, %d)", c, decoded->params.regs.displacement);
1156 default: 1164 default:
1157 return 0; 1165 return 0;
1166 }
1167 }
1168
1169 int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, uint8_t size, char *dst, int need_comma)
1170 {
1171 int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1;
1172 char *rtype, *last_rtype;
1173 int oplen;
1174 if (decoded->addr_mode == MODE_REG) {
1175 if (other->addr_mode == MODE_AREG_PREDEC) {
1176 bit = 15;
1177 dir = -1;
1178 } else {
1179 reg = 0;
1180 bit = 1;
1181 }
1182 strcat(dst, " ");
1183 for (oplen = 1, reg=0; bit < 16 && bit > -1; bit += dir, reg++) {
1184 if (decoded->params.u16 & (1 << bit)) {
1185 if (reg > 7) {
1186 rtype = "a";
1187 regnum = reg - 8;
1188 } else {
1189 rtype = "d";
1190 regnum = reg;
1191 }
1192 if (last >= 0 && last == regnum - 1 && lastreg == reg - 1) {
1193 last = regnum;
1194 lastreg = reg;
1195 } else if(last >= 0) {
1196 if (first != last) {
1197 oplen += sprintf(dst + oplen, "-%s%d/%s%d",last_rtype, last, rtype, regnum);
1198 } else {
1199 oplen += sprintf(dst + oplen, "/%s%d", rtype, regnum);
1200 }
1201 first = last = regnum;
1202 last_rtype = rtype;
1203 lastreg = reg;
1204 } else {
1205 oplen += sprintf(dst + oplen, "%s%d", rtype, regnum);
1206 first = last = regnum;
1207 last_rtype = rtype;
1208 lastreg = reg;
1209 }
1210 }
1211 }
1212 if (last >= 0 && last != first) {
1213 oplen += sprintf(dst + oplen, "-%s%d", last_rtype, last);
1214 }
1215 return oplen;
1216 } else {
1217 return m68k_disasm_op(decoded, size, dst, need_comma);
1158 } 1218 }
1159 } 1219 }
1160 1220
1161 int m68k_disasm(m68kinst * decoded, char * dst) 1221 int m68k_disasm(m68kinst * decoded, char * dst)
1162 { 1222 {
1163 int ret,op1len; 1223 int ret,op1len;
1164 uint8_t size; 1224 uint8_t size;
1165 if (decoded->op == M68K_BCC || decoded->op == M68K_DBCC || decoded->op == M68K_SCC) { 1225 char * special_op = "CCR";
1226 switch (decoded->op)
1227 {
1228 case M68K_BCC:
1229 case M68K_DBCC:
1230 case M68K_SCC:
1166 ret = strlen(mnemonics[decoded->op]) - 2; 1231 ret = strlen(mnemonics[decoded->op]) - 2;
1167 memcpy(dst, mnemonics[decoded->op], ret); 1232 memcpy(dst, mnemonics[decoded->op], ret);
1168 dst[ret] = 0; 1233 dst[ret] = 0;
1169 strcat(dst, cond_mnem[decoded->extra.cond]); 1234 strcat(dst, cond_mnem[decoded->extra.cond]);
1170 ret = strlen(dst); 1235 ret = strlen(dst);
1171 size = decoded->op = M68K_BCC ? OPSIZE_LONG : OPSIZE_WORD; 1236 size = decoded->op = M68K_BCC ? OPSIZE_LONG : OPSIZE_WORD;
1172 } else if (decoded->op == M68K_BSR) { 1237 break;
1238 case M68K_BSR:
1173 size = OPSIZE_LONG; 1239 size = OPSIZE_LONG;
1174 ret = sprintf(dst, "bsr%s", decoded->variant == VAR_BYTE ? ".s" : ""); 1240 ret = sprintf(dst, "bsr%s", decoded->variant == VAR_BYTE ? ".s" : "");
1175 } else { 1241 break;
1242 case M68K_MOVE_FROM_SR:
1243 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
1244 ret += sprintf(dst + ret, " SR");
1245 ret += m68k_disasm_op(&(decoded->dst), decoded->extra.size, dst + ret, 1);
1246 return ret;
1247 case M68K_ANDI_SR:
1248 case M68K_EORI_SR:
1249 case M68K_MOVE_SR:
1250 case M68K_ORI_SR:
1251 special_op = "SR";
1252 case M68K_ANDI_CCR:
1253 case M68K_EORI_CCR:
1254 case M68K_MOVE_CCR:
1255 case M68K_ORI_CCR:
1256 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
1257 ret += m68k_disasm_op(&(decoded->src), decoded->extra.size, dst + ret, 0);
1258 ret += sprintf(dst + ret, ", %s", special_op);
1259 return ret;
1260 default:
1176 size = decoded->extra.size; 1261 size = decoded->extra.size;
1177 ret = sprintf(dst, "%s%s.%s", 1262 ret = sprintf(dst, "%s%s%s",
1178 mnemonics[decoded->op], 1263 mnemonics[decoded->op],
1179 decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""), 1264 decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
1180 size == OPSIZE_BYTE ? "b" : (size == OPSIZE_WORD ? "w" : (size == OPSIZE_LONG ? "l" : ""))); 1265 size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
1181 } 1266 }
1182 op1len = m68K_disasm_op(&(decoded->src), size, dst + ret, 0); 1267 if (decoded->op == M68K_MOVEM) {
1183 ret += op1len; 1268 op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), size, dst + ret, 0);
1184 ret += m68K_disasm_op(&(decoded->dst), size, dst + ret, op1len); 1269 ret += op1len;
1270 ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), size, dst + ret, op1len);
1271 } else {
1272 op1len = m68k_disasm_op(&(decoded->src), size, dst + ret, 0);
1273 ret += op1len;
1274 ret += m68k_disasm_op(&(decoded->dst), size, dst + ret, op1len);
1275 }
1185 return ret; 1276 return ret;
1186 } 1277 }
1187 1278