summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--68kinst.c95
-rw-r--r--68kinst.h6
-rw-r--r--blastem.c71
3 files changed, 96 insertions, 76 deletions
diff --git a/68kinst.c b/68kinst.c
index e72b66b..b9e25aa 100644
--- a/68kinst.c
+++ b/68kinst.c
@@ -1,6 +1,6 @@
/*
Copyright 2013 Michael Pavone
- This file is part of BlastEm.
+ This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include "68kinst.h"
@@ -434,8 +434,8 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
break;
case 7:
-
-
+
+
break;
}
}
@@ -459,7 +459,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
break;
case MISC:
-
+
if ((*istream & 0x1C0) == 0x1C0) {
decoded->op = M68K_LEA;
decoded->extra.size = OPSIZE_LONG;
@@ -682,7 +682,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
}
}
- break;
+ break;
case 6:
//MULU, MULS, DIVU, DIVUL, DIVS, DIVSL
#ifdef M68020
@@ -918,7 +918,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
decoded->op = M68K_INVALID;
return start+1;
}
- break;
+ break;
}
} else {
decoded->op = M68K_OR;
@@ -1259,7 +1259,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
decoded->dst.addr_mode = MODE_REG;
decoded->dst.params.regs.pri = *istream & 0x7;
-
+
} else {
#ifdef M68020
//TODO: Implement bitfield instructions for M68020+ support
@@ -1273,6 +1273,79 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
return istream+1;
}
+uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs)
+{
+ if(inst->op == M68K_BCC || inst->op == M68K_BSR || inst->op == M68K_DBCC) {
+ return inst->address + 2 + inst->src.params.immed;
+ } else if(inst->op == M68K_JMP || inst->op == M68K_JSR) {
+ uint32_t ret = 0;
+ switch(inst->src.addr_mode)
+ {
+ case MODE_AREG_INDIRECT:
+ ret = aregs[inst->src.params.regs.pri];
+ break;
+ case MODE_AREG_INDEX_DISP8: {
+ uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
+ ret = aregs[inst->src.params.regs.pri];
+ uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
+ if (inst->src.params.regs.sec & 1) {
+ //32-bit index register
+ ret += regfile[sec_reg];
+ } else {
+ //16-bit index register
+ if (regfile[sec_reg] & 0x8000) {
+ ret += (0xFFFF0000 | regfile[sec_reg]);
+ } else {
+ ret += regfile[sec_reg];
+ }
+ }
+ ret += inst->src.params.regs.displacement;
+ break;
+ }
+ case MODE_PC_DISPLACE:
+ ret = inst->src.params.regs.displacement + inst->address + 2;
+ break;
+ case MODE_PC_INDEX_DISP8: {
+ uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
+ ret = inst->address + 2;
+ uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
+ if (inst->src.params.regs.sec & 1) {
+ //32-bit index register
+ ret += regfile[sec_reg];
+ } else {
+ //16-bit index register
+ if (regfile[sec_reg] & 0x8000) {
+ ret += (0xFFFF0000 | regfile[sec_reg]);
+ } else {
+ ret += regfile[sec_reg];
+ }
+ }
+ ret += inst->src.params.regs.displacement;
+ break;
+ }
+ case MODE_ABSOLUTE:
+ case MODE_ABSOLUTE_SHORT:
+ ret = inst->src.params.immed;
+ break;
+ }
+ return ret;
+ }
+ return 0;
+}
+
+uint8_t m68k_is_branch(m68kinst * inst)
+{
+ return (inst->op == M68K_BCC && inst->extra.cond != COND_FALSE)
+ || (inst->op == M68K_DBCC && inst->extra.cond != COND_TRUE)
+ || inst->op == M68K_BSR || inst->op == M68K_JMP || inst->op == M68K_JSR;
+}
+
+uint8_t m68k_is_noncall_branch(m68kinst * inst)
+{
+ return m68k_is_branch(inst) && inst->op != M68K_BSR && inst->op != M68K_JSR;
+}
+
+
char * mnemonics[] = {
"abcd",
"add",
@@ -1504,7 +1577,7 @@ int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels)
break;
case M68K_BSR:
if (labels) {
- ret = sprintf(dst, "bsr%s ADR_%X", decoded->variant == VAR_BYTE ? ".s" : "",
+ ret = sprintf(dst, "bsr%s ADR_%X", decoded->variant == VAR_BYTE ? ".s" : "",
decoded->address + 2 + decoded->src.params.immed);
} else {
ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
@@ -1540,9 +1613,9 @@ int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels)
return ret;
default:
size = decoded->extra.size;
- ret = sprintf(dst, "%s%s%s",
- mnemonics[decoded->op],
- decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
+ ret = sprintf(dst, "%s%s%s",
+ mnemonics[decoded->op],
+ decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
}
if (decoded->op == M68K_MOVEM) {
diff --git a/68kinst.h b/68kinst.h
index 0dc5a3f..768793f 100644
--- a/68kinst.h
+++ b/68kinst.h
@@ -1,6 +1,6 @@
/*
Copyright 2013 Michael Pavone
- This file is part of BlastEm.
+ This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#ifndef M68KINST_H_
@@ -230,7 +230,9 @@ typedef enum {
} m68k_vector;
uint16_t * m68k_decode(uint16_t * istream, m68kinst * dst, uint32_t address);
-uint32_t m68k_cycles(m68kinst * inst);
+uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs);
+uint8_t m68k_is_branch(m68kinst * inst);
+uint8_t m68k_is_noncall_branch(m68kinst * inst);
int m68k_disasm(m68kinst * decoded, char * dst);
int m68k_disasm_labels(m68kinst * decoded, char * dst);
diff --git a/blastem.c b/blastem.c
index d7cf953..6b13ed5 100644
--- a/blastem.c
+++ b/blastem.c
@@ -1469,72 +1469,17 @@ m68k_context * debugger(m68k_context * context, uint32_t address)
after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
} else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
- } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) {
- if (inst.extra.cond == COND_TRUE) {
- after = inst.address + 2 + inst.src.params.immed;
- } else {
+ } else if(m68k_is_noncall_branch(&inst)) {
+ if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
branch_f = after;
- branch_t = inst.address + 2 + inst.src.params.immed;
+ branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
insert_breakpoint(context, branch_t, (uint8_t *)debugger);
- }
- } else if(inst.op == M68K_DBCC) {
- if (inst.extra.cond == COND_FALSE) {
- if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
- after = inst.address + 2 + inst.src.params.immed;
- }
- } else if (inst.extra.cond != COND_TRUE) {
+ } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) {
branch_t = after;
- branch_f = inst.address + 2 + inst.src.params.immed;
- }
- } else if(inst.op == M68K_JMP) {
- switch(inst.src.addr_mode)
- {
- case MODE_AREG_INDIRECT:
- after = context->aregs[inst.src.params.regs.pri];
- break;
- case MODE_AREG_INDEX_DISP8: {
- uint8_t sec_reg = inst.src.params.regs.sec >> 1 & 0x7;
- after = context->aregs[inst.src.params.regs.pri];
- uint32_t * regfile = inst.src.params.regs.sec & 0x10 ? context->aregs : context->dregs;
- if (inst.src.params.regs.sec & 1) {
- //32-bit index register
- after += regfile[sec_reg];
- } else {
- //16-bit index register
- if (regfile[sec_reg] & 0x8000) {
- after += (0xFFFF0000 | regfile[sec_reg]);
- } else {
- after += regfile[sec_reg];
- }
- }
- after += inst.src.params.regs.displacement;
- break;
- }
- case MODE_PC_DISPLACE:
- after = inst.src.params.regs.displacement + address + 2;
- break;
- case MODE_PC_INDEX_DISP8: {
- uint8_t sec_reg = inst.src.params.regs.sec >> 1 & 0x7;
- after = address + 2;
- uint32_t * regfile = inst.src.params.regs.sec & 0x10 ? context->aregs : context->dregs;
- if (inst.src.params.regs.sec & 1) {
- //32-bit index register
- after += regfile[sec_reg];
- } else {
- //16-bit index register
- if (regfile[sec_reg] & 0x8000) {
- after += (0xFFFF0000 | regfile[sec_reg]);
- } else {
- after += regfile[sec_reg];
- }
- }
- after += inst.src.params.regs.displacement;
- break;
- }
- case MODE_ABSOLUTE:
- case MODE_ABSOLUTE_SHORT:
- after = inst.src.params.immed;
- break;
+ branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
+ insert_breakpoint(context, branch_f, (uint8_t *)debugger);
+ } else {
+ after = m68k_branch_target(&inst, context->dregs, context->aregs);
}
}
insert_breakpoint(context, after, (uint8_t *)debugger);