25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_m88k_instr.c,v 1.33 2007/06/05 06:41:30 debug Exp $ |
* $Id: cpu_m88k_instr.c,v 1.42 2007/06/28 13:36:46 debug Exp $ |
29 |
* |
* |
30 |
* M88K instructions. |
* M88K instructions. |
31 |
* |
* |
58 |
* bsr_samepage: Branch to subroutine (to within the same translated page) |
* bsr_samepage: Branch to subroutine (to within the same translated page) |
59 |
* |
* |
60 |
* arg[0] = pointer to new instr_call |
* arg[0] = pointer to new instr_call |
61 |
|
* arg[2] = offset to return address, from start of page |
62 |
*/ |
*/ |
63 |
X(br_samepage) |
X(br_samepage) |
64 |
{ |
{ |
66 |
} |
} |
67 |
X(bsr_samepage) |
X(bsr_samepage) |
68 |
{ |
{ |
69 |
SYNCH_PC; |
cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & |
70 |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + sizeof(uint32_t); |
~((M88K_IC_ENTRIES_PER_PAGE-1) << M88K_INSTR_ALIGNMENT_SHIFT)) |
71 |
|
+ ic->arg[2]; |
72 |
cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[0]; |
cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[0]; |
73 |
} |
} |
74 |
|
|
80 |
* bsr.n: Branch to subroutine (to a different page) with delay slot |
* bsr.n: Branch to subroutine (to a different page) with delay slot |
81 |
* |
* |
82 |
* arg[1] = relative offset from start of page |
* arg[1] = relative offset from start of page |
83 |
|
* arg[2] = offset to return address, from start of page |
84 |
*/ |
*/ |
85 |
X(br) |
X(br) |
86 |
{ |
{ |
104 |
} |
} |
105 |
X(bsr) |
X(bsr) |
106 |
{ |
{ |
107 |
SYNCH_PC; |
cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
108 |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + sizeof(uint32_t); |
M88K_INSTR_ALIGNMENT_SHIFT); |
109 |
cpu->pc = (uint32_t)((cpu->pc & 0xfffff000) + (int32_t)ic->arg[1]); |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2]; |
110 |
|
cpu->pc = (uint32_t) (cpu->pc + ic->arg[1]); |
111 |
quick_pc_to_pointers(cpu); |
quick_pc_to_pointers(cpu); |
112 |
} |
} |
113 |
X(bsr_n) |
X(bsr_n) |
114 |
{ |
{ |
115 |
cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
116 |
M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[1]; |
M88K_INSTR_ALIGNMENT_SHIFT); |
117 |
SYNCH_PC; |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2] + 4; |
118 |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + sizeof(uint32_t) * 2; |
cpu->cd.m88k.delay_target = cpu->pc + ic->arg[1]; |
119 |
cpu->delay_slot = TO_BE_DELAYED; |
cpu->delay_slot = TO_BE_DELAYED; |
120 |
ic[1].f(cpu, ic+1); |
ic[1].f(cpu, ic+1); |
121 |
cpu->n_translated_instrs ++; |
cpu->n_translated_instrs ++; |
129 |
} |
} |
130 |
X(bsr_trace) |
X(bsr_trace) |
131 |
{ |
{ |
132 |
SYNCH_PC; |
cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
133 |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + sizeof(uint32_t); |
M88K_INSTR_ALIGNMENT_SHIFT); |
134 |
cpu->pc = (uint32_t)((cpu->pc & 0xfffff000) + (int32_t)ic->arg[1]); |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2]; |
135 |
|
cpu->pc = (uint32_t) (cpu->pc + ic->arg[1]); |
136 |
cpu_functioncall_trace(cpu, cpu->pc); |
cpu_functioncall_trace(cpu, cpu->pc); |
137 |
quick_pc_to_pointers(cpu); |
quick_pc_to_pointers(cpu); |
138 |
} |
} |
139 |
X(bsr_n_trace) |
X(bsr_n_trace) |
140 |
{ |
{ |
141 |
cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
142 |
M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[1]; |
M88K_INSTR_ALIGNMENT_SHIFT); |
143 |
SYNCH_PC; |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2] + 4; |
144 |
cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + sizeof(uint32_t) * 2; |
cpu->cd.m88k.delay_target = cpu->pc + ic->arg[1]; |
145 |
cpu->delay_slot = TO_BE_DELAYED; |
cpu->delay_slot = TO_BE_DELAYED; |
146 |
ic[1].f(cpu, ic+1); |
ic[1].f(cpu, ic+1); |
147 |
cpu->n_translated_instrs ++; |
cpu->n_translated_instrs ++; |
179 |
} |
} |
180 |
X(bb0_n) |
X(bb0_n) |
181 |
{ |
{ |
182 |
int cond = !(reg(ic->arg[0]) & ic->arg[1]); |
int cond = !(reg(ic->arg[0]) & (uint32_t)ic->arg[1]); |
183 |
cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) << |
184 |
M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[2]; |
M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[2]; |
185 |
cpu->delay_slot = TO_BE_DELAYED; |
cpu->delay_slot = TO_BE_DELAYED; |
484 |
X(clr) |
X(clr) |
485 |
{ |
{ |
486 |
int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f; |
int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f; |
487 |
uint32_t x = w == 0? 0xffffffff : (1 << w) - 1; |
uint32_t x = w == 0? 0xffffffff : ((uint32_t)1 << w) - 1; |
488 |
x <<= o; |
x <<= o; |
489 |
reg(ic->arg[0]) = reg(ic->arg[1]) & ~x; |
reg(ic->arg[0]) = reg(ic->arg[1]) & ~x; |
490 |
} |
} |
491 |
X(set) |
X(set) |
492 |
{ |
{ |
493 |
int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f; |
int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f; |
494 |
uint32_t x = w == 0? 0xffffffff : (1 << w) - 1; |
uint32_t x = w == 0? 0xffffffff : ((uint32_t)1 << w) - 1; |
495 |
x <<= o; |
x <<= o; |
496 |
reg(ic->arg[0]) = reg(ic->arg[1]) | x; |
reg(ic->arg[0]) = reg(ic->arg[1]) | x; |
497 |
} |
} |
774 |
m88k_stcr(cpu, cpu->cd.m88k.cr[M88K_CR_EPSR], M88K_CR_PSR, 1); |
m88k_stcr(cpu, cpu->cd.m88k.cr[M88K_CR_EPSR], M88K_CR_PSR, 1); |
775 |
|
|
776 |
/* First try the NIP, if it is Valid: */ |
/* First try the NIP, if it is Valid: */ |
777 |
if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_V) { |
cpu->pc = cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR; |
778 |
cpu->pc = cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR; |
if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_E) { |
779 |
if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_E) { |
fatal("rte: NIP: TODO: single-step support\n"); |
780 |
fatal("rte: NIP: TODO: single-step support\n"); |
goto abort_dump; |
|
goto abort_dump; |
|
|
} |
|
|
} else { |
|
|
/* The FIP must be valid... */ |
|
|
if (!(cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_NIP_V)) { |
|
|
fatal("rte: neither FIP nor NIP valid? TODO\n"); |
|
|
goto abort_dump; |
|
|
} |
|
|
cpu->pc = cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR; |
|
781 |
} |
} |
782 |
|
|
783 |
if (cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_E) { |
if (cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_E) { |
785 |
goto abort_dump; |
goto abort_dump; |
786 |
} |
} |
787 |
|
|
788 |
if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_FIP_V && |
if ((cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR) |
789 |
cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_V && |
== (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR)) { |
790 |
(cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR) |
cpu->cd.m88k.cr[M88K_CR_SFIP] = cpu->pc + 4; |
791 |
|
} |
792 |
|
|
793 |
|
if ((cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR) |
794 |
!= (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR) + 4) { |
!= (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR) + 4) { |
795 |
/* |
/* |
796 |
* The NIP instruction should first be executed (this |
* The NIP instruction should first be executed (this |
1024 |
<< M88K_INSTR_ALIGNMENT_SHIFT); |
<< M88K_INSTR_ALIGNMENT_SHIFT); |
1025 |
cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT); |
cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT); |
1026 |
|
|
1027 |
|
if (low_pc < 0 || low_pc > ((M88K_IC_ENTRIES_PER_PAGE+1) |
1028 |
|
<< M88K_INSTR_ALIGNMENT_SHIFT)) { |
1029 |
|
printf("[ end_of_page2: HUH? low_pc=%i, cpu->pc = %08" |
1030 |
|
PRIx32" ]\n", low_pc, (uint32_t) cpu->pc); |
1031 |
|
} |
1032 |
|
|
1033 |
/* This doesn't count as an executed instruction. */ |
/* This doesn't count as an executed instruction. */ |
1034 |
cpu->n_translated_instrs --; |
cpu->n_translated_instrs --; |
1035 |
|
|
1318 |
ic->arg[0] = (size_t) ( cpu->cd.m88k.cur_ic_page + |
ic->arg[0] = (size_t) ( cpu->cd.m88k.cur_ic_page + |
1319 |
(offset >> M88K_INSTR_ALIGNMENT_SHIFT) ); |
(offset >> M88K_INSTR_ALIGNMENT_SHIFT) ); |
1320 |
ic->arg[1] = offset; |
ic->arg[1] = offset; |
1321 |
|
ic->arg[2] = (addr & 0xffc) + 4; /* Return offset |
1322 |
|
for bsr_samepage */ |
1323 |
|
|
1324 |
if (offset >= 0 && offset <= 0xffc && |
if (offset >= 0 && offset <= 0xffc && |
1325 |
samepage_function != NULL) |
samepage_function != NULL) |
1408 |
int w = ic->arg[2] >> 5; |
int w = ic->arg[2] >> 5; |
1409 |
int o = ic->arg[2] & 0x1f; |
int o = ic->arg[2] & 0x1f; |
1410 |
uint32_t x = w == 0? 0xffffffff |
uint32_t x = w == 0? 0xffffffff |
1411 |
: (1 << w) - 1; |
: ((uint32_t)1 << w) - 1; |
1412 |
x <<= o; |
x <<= o; |
1413 |
ic->arg[2] = ~x; |
ic->arg[2] = ~x; |
1414 |
} |
} |
1418 |
int w = ic->arg[2] >> 5; |
int w = ic->arg[2] >> 5; |
1419 |
int o = ic->arg[2] & 0x1f; |
int o = ic->arg[2] & 0x1f; |
1420 |
uint32_t x = w == 0? 0xffffffff |
uint32_t x = w == 0? 0xffffffff |
1421 |
: (1 << w) - 1; |
: ((uint32_t)1 << w) - 1; |
1422 |
x <<= o; |
x <<= o; |
1423 |
ic->arg[2] = x; |
ic->arg[2] = x; |
1424 |
} |
} |