25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_sh_instr.c,v 1.56 2007/04/19 15:49:39 debug Exp $ |
* $Id: cpu_sh_instr.c,v 1.61 2007/06/04 06:32:25 debug Exp $ |
29 |
* |
* |
30 |
* SH instructions. |
* SH instructions. |
31 |
* |
* |
173 |
X(extu_b_rm_rn) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[0]); } |
X(extu_b_rm_rn) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[0]); } |
174 |
X(exts_w_rm_rn) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); } |
X(exts_w_rm_rn) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); } |
175 |
X(extu_w_rm_rn) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[0]); } |
X(extu_w_rm_rn) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[0]); } |
176 |
|
/* Note: rm and rn are the same on these: */ |
177 |
|
X(extu_b_rm) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[1]); } |
178 |
|
X(extu_w_rm) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[1]); } |
179 |
|
|
180 |
|
|
181 |
/* |
/* |
283 |
* arg[0] = int8_t imm, extended to at least int32_t |
* arg[0] = int8_t imm, extended to at least int32_t |
284 |
* arg[1] = ptr to rn |
* arg[1] = ptr to rn |
285 |
*/ |
*/ |
286 |
X(mov_imm_rn) { reg(ic->arg[1]) = (int32_t)ic->arg[0]; } |
X(mov_imm_rn) { reg(ic->arg[1]) = ic->arg[0]; } |
287 |
X(add_imm_rn) { reg(ic->arg[1]) += (int32_t)ic->arg[0]; } |
X(mov_0_rn) { reg(ic->arg[1]) = 0; } |
288 |
|
X(add_imm_rn) { reg(ic->arg[1]) += ic->arg[0]; } |
289 |
|
X(inc_rn) { reg(ic->arg[1]) ++; } |
290 |
|
X(add_4_rn) { reg(ic->arg[1]) += 4; } |
291 |
|
X(sub_4_rn) { reg(ic->arg[1]) -= 4; } |
292 |
|
X(dec_rn) { reg(ic->arg[1]) --; } |
293 |
|
|
294 |
|
|
295 |
/* |
/* |
1379 |
* sub_rm_rn: rn = rn - rm |
* sub_rm_rn: rn = rn - rm |
1380 |
* subc_rm_rn: rn = rn - rm - t; t = borrow |
* subc_rm_rn: rn = rn - rm - t; t = borrow |
1381 |
* tst_rm_rn: t = ((rm & rn) == 0) |
* tst_rm_rn: t = ((rm & rn) == 0) |
1382 |
|
* tst_rm: t = (rm == 0) |
1383 |
* xtrct_rm_rn: rn = (rn >> 16) | (rm << 16) |
* xtrct_rm_rn: rn = (rn >> 16) | (rm << 16) |
1384 |
* |
* |
1385 |
* arg[0] = ptr to rm |
* arg[0] = ptr to rm |
1421 |
else |
else |
1422 |
cpu->cd.sh.sr |= SH_SR_T; |
cpu->cd.sh.sr |= SH_SR_T; |
1423 |
} |
} |
1424 |
|
X(tst_rm) |
1425 |
|
{ |
1426 |
|
if (reg(ic->arg[0])) |
1427 |
|
cpu->cd.sh.sr &= ~SH_SR_T; |
1428 |
|
else |
1429 |
|
cpu->cd.sh.sr |= SH_SR_T; |
1430 |
|
} |
1431 |
X(xtrct_rm_rn) |
X(xtrct_rm_rn) |
1432 |
{ |
{ |
1433 |
uint32_t rn = reg(ic->arg[1]), rm = reg(ic->arg[0]); |
uint32_t rn = reg(ic->arg[1]), rm = reg(ic->arg[0]); |
1449 |
} |
} |
1450 |
X(div0s_rm_rn) |
X(div0s_rm_rn) |
1451 |
{ |
{ |
1452 |
int q = reg(ic->arg[1]) >> 31, m = reg(ic->arg[0]) >> 31; |
int q = reg(ic->arg[1]) & 0x80000000; |
1453 |
cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_M | SH_SR_T); |
int m = reg(ic->arg[0]) & 0x80000000; |
1454 |
|
uint32_t new_sr = cpu->cd.sh.sr & ~(SH_SR_Q | SH_SR_M | SH_SR_T); |
1455 |
if (q) |
if (q) |
1456 |
cpu->cd.sh.sr |= SH_SR_Q; |
new_sr |= SH_SR_Q; |
1457 |
if (m) |
if (m) |
1458 |
cpu->cd.sh.sr |= SH_SR_M; |
new_sr |= SH_SR_M; |
1459 |
if (m ^ q) |
if (m ^ q) |
1460 |
cpu->cd.sh.sr |= SH_SR_T; |
new_sr |= SH_SR_T; |
1461 |
|
cpu->cd.sh.sr = new_sr; |
1462 |
} |
} |
1463 |
X(div1_rm_rn) |
X(div1_rm_rn) |
1464 |
{ |
{ |
1631 |
X(shll_rn) |
X(shll_rn) |
1632 |
{ |
{ |
1633 |
uint32_t rn = reg(ic->arg[1]); |
uint32_t rn = reg(ic->arg[1]); |
1634 |
if (rn >> 31) |
if (rn & 0x80000000) |
1635 |
cpu->cd.sh.sr |= SH_SR_T; |
cpu->cd.sh.sr |= SH_SR_T; |
1636 |
else |
else |
1637 |
cpu->cd.sh.sr &= ~SH_SR_T; |
cpu->cd.sh.sr &= ~SH_SR_T; |
1648 |
} |
} |
1649 |
X(rotl_rn) |
X(rotl_rn) |
1650 |
{ |
{ |
1651 |
uint32_t rn = reg(ic->arg[1]); |
uint32_t rn = reg(ic->arg[1]), x; |
1652 |
if (rn >> 31) |
if (rn & 0x80000000) { |
1653 |
|
x = 1; |
1654 |
cpu->cd.sh.sr |= SH_SR_T; |
cpu->cd.sh.sr |= SH_SR_T; |
1655 |
else |
} else { |
1656 |
|
x = 0; |
1657 |
cpu->cd.sh.sr &= ~SH_SR_T; |
cpu->cd.sh.sr &= ~SH_SR_T; |
1658 |
reg(ic->arg[1]) = (rn << 1) | (rn >> 31); |
} |
1659 |
|
reg(ic->arg[1]) = (rn << 1) | x; |
1660 |
} |
} |
1661 |
X(rotr_rn) |
X(rotr_rn) |
1662 |
{ |
{ |
1766 |
* braf: Like bra, but using a register instead of an immediate |
* braf: Like bra, but using a register instead of an immediate |
1767 |
* bsrf: Like braf, but also sets PR to the return address |
* bsrf: Like braf, but also sets PR to the return address |
1768 |
* |
* |
1769 |
* arg[0] = immediate offset relative to start of page |
* arg[0] = immediate offset relative to start of page, |
1770 |
|
* or ptr to target instruction, for samepage branches |
1771 |
* arg[1] = ptr to Rn (for braf/bsrf) |
* arg[1] = ptr to Rn (for braf/bsrf) |
1772 |
*/ |
*/ |
1773 |
X(bra) |
X(bra) |
1785 |
} else |
} else |
1786 |
cpu->delay_slot = NOT_DELAYED; |
cpu->delay_slot = NOT_DELAYED; |
1787 |
} |
} |
1788 |
|
X(bra_samepage) |
1789 |
|
{ |
1790 |
|
cpu->delay_slot = TO_BE_DELAYED; |
1791 |
|
ic[1].f(cpu, ic+1); |
1792 |
|
cpu->n_translated_instrs ++; |
1793 |
|
if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) |
1794 |
|
cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[0]; |
1795 |
|
cpu->delay_slot = NOT_DELAYED; |
1796 |
|
} |
1797 |
X(bsr) |
X(bsr) |
1798 |
{ |
{ |
1799 |
MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) << |
MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) << |
1813 |
} else |
} else |
1814 |
cpu->delay_slot = NOT_DELAYED; |
cpu->delay_slot = NOT_DELAYED; |
1815 |
} |
} |
1816 |
|
X(bsr_samepage) |
1817 |
|
{ |
1818 |
|
uint32_t old_pc; |
1819 |
|
SYNCH_PC; |
1820 |
|
old_pc = cpu->pc; |
1821 |
|
cpu->delay_slot = TO_BE_DELAYED; |
1822 |
|
ic[1].f(cpu, ic+1); |
1823 |
|
cpu->n_translated_instrs ++; |
1824 |
|
if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) { |
1825 |
|
cpu->cd.sh.pr = old_pc + 4; |
1826 |
|
cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[0]; |
1827 |
|
} |
1828 |
|
cpu->delay_slot = NOT_DELAYED; |
1829 |
|
} |
1830 |
X(braf_rn) |
X(braf_rn) |
1831 |
{ |
{ |
1832 |
MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) << |
MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) << |
1870 |
* bf/s: Branch if false (with delay-slot) |
* bf/s: Branch if false (with delay-slot) |
1871 |
* |
* |
1872 |
* arg[0] = immediate offset relative to start of page |
* arg[0] = immediate offset relative to start of page |
1873 |
|
* arg[1] = for samepage functions, the new instruction pointer |
1874 |
*/ |
*/ |
1875 |
X(bt) |
X(bt) |
1876 |
{ |
{ |
1890 |
quick_pc_to_pointers(cpu); |
quick_pc_to_pointers(cpu); |
1891 |
} |
} |
1892 |
} |
} |
1893 |
|
X(bt_samepage) |
1894 |
|
{ |
1895 |
|
if (cpu->cd.sh.sr & SH_SR_T) |
1896 |
|
cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[1]; |
1897 |
|
} |
1898 |
|
X(bf_samepage) |
1899 |
|
{ |
1900 |
|
if (!(cpu->cd.sh.sr & SH_SR_T)) |
1901 |
|
cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[1]; |
1902 |
|
} |
1903 |
X(bt_s) |
X(bt_s) |
1904 |
{ |
{ |
1905 |
MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) << |
MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) << |
1938 |
} else |
} else |
1939 |
cpu->delay_slot = NOT_DELAYED; |
cpu->delay_slot = NOT_DELAYED; |
1940 |
} |
} |
1941 |
|
X(bt_s_samepage) |
1942 |
|
{ |
1943 |
|
int cond = cpu->cd.sh.sr & SH_SR_T; |
1944 |
|
cpu->delay_slot = TO_BE_DELAYED; |
1945 |
|
ic[1].f(cpu, ic+1); |
1946 |
|
cpu->n_translated_instrs ++; |
1947 |
|
if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) { |
1948 |
|
cpu->delay_slot = NOT_DELAYED; |
1949 |
|
if (cond) |
1950 |
|
cpu->cd.sh.next_ic = |
1951 |
|
(struct sh_instr_call *) ic->arg[1]; |
1952 |
|
else |
1953 |
|
cpu->cd.sh.next_ic ++; |
1954 |
|
} else |
1955 |
|
cpu->delay_slot = NOT_DELAYED; |
1956 |
|
} |
1957 |
|
X(bf_s_samepage) |
1958 |
|
{ |
1959 |
|
int cond = !(cpu->cd.sh.sr & SH_SR_T); |
1960 |
|
cpu->delay_slot = TO_BE_DELAYED; |
1961 |
|
ic[1].f(cpu, ic+1); |
1962 |
|
cpu->n_translated_instrs ++; |
1963 |
|
if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) { |
1964 |
|
cpu->delay_slot = NOT_DELAYED; |
1965 |
|
if (cond) |
1966 |
|
cpu->cd.sh.next_ic = |
1967 |
|
(struct sh_instr_call *) ic->arg[1]; |
1968 |
|
else |
1969 |
|
cpu->cd.sh.next_ic ++; |
1970 |
|
} else |
1971 |
|
cpu->delay_slot = NOT_DELAYED; |
1972 |
|
} |
1973 |
|
|
1974 |
|
|
1975 |
/* |
/* |
2883 |
uint64_t addr, low_pc; |
uint64_t addr, low_pc; |
2884 |
uint32_t iword; |
uint32_t iword; |
2885 |
unsigned char *page; |
unsigned char *page; |
2886 |
unsigned char ib[4]; |
unsigned char ib[2]; |
2887 |
int main_opcode, isize = cpu->cd.sh.compact? 2 : sizeof(ib); |
int main_opcode, isize = sizeof(ib); |
2888 |
int in_crosspage_delayslot = 0, r8, r4, lo4, lo8; |
int in_crosspage_delayslot = 0, r8, r4, lo4, lo8; |
2889 |
/* void (*samepage_function)(struct cpu *, struct sh_instr_call *); */ |
void (*samepage_function)(struct cpu *, struct sh_instr_call *); |
2890 |
|
|
2891 |
/* Figure out the (virtual) address of the instruction: */ |
/* Figure out the (virtual) address of the instruction: */ |
2892 |
low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page) |
low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page) |
2935 |
} |
} |
2936 |
} |
} |
2937 |
|
|
2938 |
if (cpu->cd.sh.compact) { |
iword = *((uint16_t *)&ib[0]); |
2939 |
iword = *((uint16_t *)&ib[0]); |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
2940 |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
iword = LE16_TO_HOST(iword); |
2941 |
iword = LE16_TO_HOST(iword); |
else |
2942 |
else |
iword = BE16_TO_HOST(iword); |
2943 |
iword = BE16_TO_HOST(iword); |
main_opcode = iword >> 12; |
2944 |
main_opcode = iword >> 12; |
r8 = (iword >> 8) & 0xf; |
2945 |
r8 = (iword >> 8) & 0xf; |
r4 = (iword >> 4) & 0xf; |
2946 |
r4 = (iword >> 4) & 0xf; |
lo8 = iword & 0xff; |
2947 |
lo8 = iword & 0xff; |
lo4 = iword & 0xf; |
|
lo4 = iword & 0xf; |
|
|
} else { |
|
|
iword = *((uint32_t *)&ib[0]); |
|
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
|
|
iword = LE32_TO_HOST(iword); |
|
|
else |
|
|
iword = BE32_TO_HOST(iword); |
|
|
main_opcode = -1; /* TODO */ |
|
|
fatal("SH5/SH64 isn't implemented yet. Sorry.\n"); |
|
|
goto bad; |
|
|
} |
|
2948 |
|
|
2949 |
|
|
2950 |
#define DYNTRANS_TO_BE_TRANSLATED_HEAD |
#define DYNTRANS_TO_BE_TRANSLATED_HEAD |
3039 |
case 0x09: /* NOP */ |
case 0x09: /* NOP */ |
3040 |
ic->f = instr(nop); |
ic->f = instr(nop); |
3041 |
if (iword & 0x0f00) { |
if (iword & 0x0f00) { |
3042 |
fatal("Unimplemented NOP variant?\n"); |
if (!cpu->translation_readahead) |
3043 |
|
fatal("Unimplemented NOP" |
3044 |
|
" variant?\n"); |
3045 |
goto bad; |
goto bad; |
3046 |
} |
} |
3047 |
break; |
break; |
3121 |
ic->arg[0] = (size_t)&cpu->cd.sh.dbr; |
ic->arg[0] = (size_t)&cpu->cd.sh.dbr; |
3122 |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; |
3123 |
break; |
break; |
3124 |
default:fatal("Unimplemented opcode 0x%x,0x%03x\n", |
default:if (!cpu->translation_readahead) |
3125 |
main_opcode, iword & 0xfff); |
fatal("Unimplemented opcode 0x%x," |
3126 |
|
"0x%03x\n", main_opcode, |
3127 |
|
iword & 0xfff); |
3128 |
goto bad; |
goto bad; |
3129 |
} |
} |
3130 |
} |
} |
3160 |
break; |
break; |
3161 |
case 0x8: /* TST Rm,Rn */ |
case 0x8: /* TST Rm,Rn */ |
3162 |
ic->f = instr(tst_rm_rn); |
ic->f = instr(tst_rm_rn); |
3163 |
|
if (r8 == r4) |
3164 |
|
ic->f = instr(tst_rm); |
3165 |
break; |
break; |
3166 |
case 0x9: /* AND Rm,Rn */ |
case 0x9: /* AND Rm,Rn */ |
3167 |
ic->f = instr(and_rm_rn); |
ic->f = instr(and_rm_rn); |
3184 |
case 0xf: /* MULS.W Rm,Rn */ |
case 0xf: /* MULS.W Rm,Rn */ |
3185 |
ic->f = instr(muls_w_rm_rn); |
ic->f = instr(muls_w_rm_rn); |
3186 |
break; |
break; |
3187 |
default:fatal("Unimplemented opcode 0x%x,0x%x\n", |
default:if (!cpu->translation_readahead) |
3188 |
main_opcode, lo4); |
fatal("Unimplemented opcode 0x%x,0x%x\n", |
3189 |
|
main_opcode, lo4); |
3190 |
goto bad; |
goto bad; |
3191 |
} |
} |
3192 |
break; |
break; |
3229 |
case 0xe: /* ADDC Rm,Rn */ |
case 0xe: /* ADDC Rm,Rn */ |
3230 |
ic->f = instr(addc_rm_rn); |
ic->f = instr(addc_rm_rn); |
3231 |
break; |
break; |
3232 |
default:fatal("Unimplemented opcode 0x%x,0x%x\n", |
default:if (!cpu->translation_readahead) |
3233 |
main_opcode, lo4); |
fatal("Unimplemented opcode 0x%x,0x%x\n", |
3234 |
|
main_opcode, lo4); |
3235 |
goto bad; |
goto bad; |
3236 |
} |
} |
3237 |
break; |
break; |
3454 |
ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; |
ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; |
3455 |
ic->arg[1] = (size_t)&cpu->cd.sh.dbr; |
ic->arg[1] = (size_t)&cpu->cd.sh.dbr; |
3456 |
break; |
break; |
3457 |
default:fatal("Unimplemented opcode 0x%x,0x%02x\n", |
default:if (!cpu->translation_readahead) |
3458 |
main_opcode, lo8); |
fatal("Unimplemented opcode 0x%x," |
3459 |
|
"0x%02x\n", main_opcode, lo8); |
3460 |
goto bad; |
goto bad; |
3461 |
} |
} |
3462 |
} |
} |
3516 |
break; |
break; |
3517 |
case 0xc: /* EXTU.B Rm,Rn */ |
case 0xc: /* EXTU.B Rm,Rn */ |
3518 |
ic->f = instr(extu_b_rm_rn); |
ic->f = instr(extu_b_rm_rn); |
3519 |
|
if (r8 == r4) |
3520 |
|
ic->f = instr(extu_b_rm); |
3521 |
break; |
break; |
3522 |
case 0xd: /* EXTU.W Rm,Rn */ |
case 0xd: /* EXTU.W Rm,Rn */ |
3523 |
ic->f = instr(extu_w_rm_rn); |
ic->f = instr(extu_w_rm_rn); |
3524 |
|
if (r8 == r4) |
3525 |
|
ic->f = instr(extu_w_rm); |
3526 |
break; |
break; |
3527 |
case 0xe: /* EXTS.B Rm,Rn */ |
case 0xe: /* EXTS.B Rm,Rn */ |
3528 |
ic->f = instr(exts_b_rm_rn); |
ic->f = instr(exts_b_rm_rn); |
3530 |
case 0xf: /* EXTS.W Rm,Rn */ |
case 0xf: /* EXTS.W Rm,Rn */ |
3531 |
ic->f = instr(exts_w_rm_rn); |
ic->f = instr(exts_w_rm_rn); |
3532 |
break; |
break; |
3533 |
default:fatal("Unimplemented opcode 0x%x,0x%x\n", |
default:if (!cpu->translation_readahead) |
3534 |
main_opcode, lo4); |
fatal("Unimplemented opcode 0x%x,0x%x\n", |
3535 |
|
main_opcode, lo4); |
3536 |
goto bad; |
goto bad; |
3537 |
} |
} |
3538 |
break; |
break; |
3540 |
case 0x7: /* ADD #imm,Rn */ |
case 0x7: /* ADD #imm,Rn */ |
3541 |
ic->f = instr(add_imm_rn); |
ic->f = instr(add_imm_rn); |
3542 |
ic->arg[0] = (int8_t)lo8; |
ic->arg[0] = (int8_t)lo8; |
3543 |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
3544 |
|
if (lo8 == 1) |
3545 |
|
ic->f = instr(inc_rn); |
3546 |
|
if (lo8 == 4) |
3547 |
|
ic->f = instr(add_4_rn); |
3548 |
|
if (lo8 == 0xfc) |
3549 |
|
ic->f = instr(sub_4_rn); |
3550 |
|
if (lo8 == 0xff) |
3551 |
|
ic->f = instr(dec_rn); |
3552 |
break; |
break; |
3553 |
|
|
3554 |
case 0x8: |
case 0x8: |
3556 |
ic->arg[0] = (int8_t)lo8 * 2 + |
ic->arg[0] = (int8_t)lo8 * 2 + |
3557 |
(addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
(addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
3558 |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4; |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4; |
3559 |
|
samepage_function = NULL; |
3560 |
|
|
3561 |
switch (r8) { |
switch (r8) { |
3562 |
case 0x0: /* MOV.B R0,@(disp,Rn) */ |
case 0x0: /* MOV.B R0,@(disp,Rn) */ |
3563 |
ic->f = instr(mov_b_r0_disp_rn); |
ic->f = instr(mov_b_r0_disp_rn); |
3585 |
break; |
break; |
3586 |
case 0x9: /* BT (disp,PC) */ |
case 0x9: /* BT (disp,PC) */ |
3587 |
ic->f = instr(bt); |
ic->f = instr(bt); |
3588 |
|
samepage_function = instr(bt_samepage); |
3589 |
break; |
break; |
3590 |
case 0xb: /* BF (disp,PC) */ |
case 0xb: /* BF (disp,PC) */ |
3591 |
ic->f = instr(bf); |
ic->f = instr(bf); |
3592 |
|
samepage_function = instr(bf_samepage); |
3593 |
break; |
break; |
3594 |
case 0xd: /* BT/S (disp,PC) */ |
case 0xd: /* BT/S (disp,PC) */ |
3595 |
ic->f = instr(bt_s); |
ic->f = instr(bt_s); |
3596 |
|
samepage_function = instr(bt_s_samepage); |
3597 |
break; |
break; |
3598 |
case 0xf: /* BF/S (disp,PC) */ |
case 0xf: /* BF/S (disp,PC) */ |
3599 |
ic->f = instr(bf_s); |
ic->f = instr(bf_s); |
3600 |
|
samepage_function = instr(bf_s_samepage); |
3601 |
break; |
break; |
3602 |
default:fatal("Unimplemented opcode 0x%x,0x%x\n", |
default:if (!cpu->translation_readahead) |
3603 |
main_opcode, r8); |
fatal("Unimplemented opcode 0x%x,0x%x\n", |
3604 |
|
main_opcode, r8); |
3605 |
goto bad; |
goto bad; |
3606 |
} |
} |
3607 |
|
|
3608 |
|
/* samepage branches: */ |
3609 |
|
if (samepage_function != NULL && ic->arg[0] < 0x1000 && |
3610 |
|
(addr & 0xfff) < 0xffe) { |
3611 |
|
ic->arg[1] = (size_t) (cpu->cd.sh.cur_ic_page + |
3612 |
|
(ic->arg[0] >> SH_INSTR_ALIGNMENT_SHIFT)); |
3613 |
|
ic->f = samepage_function; |
3614 |
|
} |
3615 |
|
|
3616 |
break; |
break; |
3617 |
|
|
3618 |
case 0x9: /* MOV.W @(disp,PC),Rn */ |
case 0x9: /* MOV.W @(disp,PC),Rn */ |
3619 |
ic->f = instr(mov_w_disp_pc_rn); |
ic->f = instr(mov_w_disp_pc_rn); |
3620 |
ic->arg[0] = lo8 * 2 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
ic->arg[0] = lo8 * 2 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
3621 |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4; |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4; |
3622 |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
|
3623 |
|
/* If the word is reachable from the same page as the |
3624 |
|
current address, then optimize it as a mov_imm_rn: */ |
3625 |
|
if (ic->arg[0] < 0x1000 && page != NULL) { |
3626 |
|
uint16_t *p = (uint16_t *) page; |
3627 |
|
uint16_t data = p[ic->arg[0] >> 1]; |
3628 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3629 |
|
data = LE16_TO_HOST(data); |
3630 |
|
else |
3631 |
|
data = BE16_TO_HOST(data); |
3632 |
|
ic->f = instr(mov_imm_rn); |
3633 |
|
ic->arg[0] = (int16_t) data; |
3634 |
|
} |
3635 |
break; |
break; |
3636 |
|
|
3637 |
case 0xa: /* BRA disp */ |
case 0xa: /* BRA disp */ |
3638 |
case 0xb: /* BSR disp */ |
case 0xb: /* BSR disp */ |
3639 |
ic->f = main_opcode == 0xa? instr(bra) : instr(bsr); |
samepage_function = NULL; |
3640 |
|
|
3641 |
|
switch (main_opcode) { |
3642 |
|
case 0xa: |
3643 |
|
ic->f = instr(bra); |
3644 |
|
samepage_function = instr(bra_samepage); |
3645 |
|
break; |
3646 |
|
case 0xb: |
3647 |
|
ic->f = instr(bsr); |
3648 |
|
samepage_function = instr(bsr_samepage); |
3649 |
|
break; |
3650 |
|
} |
3651 |
|
|
3652 |
ic->arg[0] = (int32_t) ( (addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
ic->arg[0] = (int32_t) ( (addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
3653 |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4 + |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4 + |
3654 |
(((int32_t)(int16_t)((iword & 0xfff) << 4)) >> 3) ); |
(((int32_t)(int16_t)((iword & 0xfff) << 4)) >> 3) ); |
3655 |
|
|
3656 |
|
/* samepage branches: */ |
3657 |
|
if (samepage_function != NULL && ic->arg[0] < 0x1000 && |
3658 |
|
(addr & 0xfff) < 0xffe) { |
3659 |
|
ic->arg[0] = (size_t) (cpu->cd.sh.cur_ic_page + |
3660 |
|
(ic->arg[0] >> SH_INSTR_ALIGNMENT_SHIFT)); |
3661 |
|
ic->f = samepage_function; |
3662 |
|
} |
3663 |
break; |
break; |
3664 |
|
|
3665 |
case 0xc: |
case 0xc: |
3726 |
ic->f = instr(or_b_imm_r0_gbr); |
ic->f = instr(or_b_imm_r0_gbr); |
3727 |
ic->arg[0] = lo8; |
ic->arg[0] = lo8; |
3728 |
break; |
break; |
3729 |
default:fatal("Unimplemented opcode 0x%x,0x%x\n", |
default:if (!cpu->translation_readahead) |
3730 |
main_opcode, r8); |
fatal("Unimplemented opcode 0x%x,0x%x\n", |
3731 |
|
main_opcode, r8); |
3732 |
goto bad; |
goto bad; |
3733 |
} |
} |
3734 |
break; |
break; |
3737 |
ic->f = instr(mov_l_disp_pc_rn); |
ic->f = instr(mov_l_disp_pc_rn); |
3738 |
ic->arg[0] = lo8 * 4 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
ic->arg[0] = lo8 * 4 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1) |
3739 |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4; |
<< SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4; |
3740 |
|
|
3741 |
|
/* If the word is reachable from the same page as the |
3742 |
|
current address, then optimize it as a mov_imm_rn: */ |
3743 |
|
if (ic->arg[0] < 0x1000 && page != NULL) { |
3744 |
|
uint32_t *p = (uint32_t *) page; |
3745 |
|
uint32_t data = p[ic->arg[0] >> 2]; |
3746 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3747 |
|
data = LE32_TO_HOST(data); |
3748 |
|
else |
3749 |
|
data = BE32_TO_HOST(data); |
3750 |
|
ic->f = instr(mov_imm_rn); |
3751 |
|
ic->arg[0] = data; |
3752 |
|
} |
3753 |
break; |
break; |
3754 |
|
|
3755 |
case 0xe: /* MOV #imm,Rn */ |
case 0xe: /* MOV #imm,Rn */ |
3756 |
ic->f = instr(mov_imm_rn); |
ic->f = instr(mov_imm_rn); |
3757 |
ic->arg[0] = (int8_t)lo8; |
ic->arg[0] = (int8_t)lo8; |
3758 |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
3759 |
|
if (lo8 == 0) |
3760 |
|
ic->f = instr(mov_0_rn); |
3761 |
break; |
break; |
3762 |
|
|
3763 |
case 0xf: |
case 0xf: |
3894 |
ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; |
ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; |
3895 |
ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8]; |
ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8]; |
3896 |
} else { |
} else { |
3897 |
fatal("Unimplemented opcode 0x%x,0x%02x\n", |
if (!cpu->translation_readahead) |
3898 |
main_opcode, lo8); |
fatal("Unimplemented opcode 0x%x,0x%02x\n", |
3899 |
|
main_opcode, lo8); |
3900 |
goto bad; |
goto bad; |
3901 |
} |
} |
3902 |
break; |
break; |
3903 |
|
|
3904 |
default:fatal("Unimplemented main opcode 0x%x\n", main_opcode); |
default:if (!cpu->translation_readahead) |
3905 |
|
fatal("Unimplemented main opcode 0x%x\n", main_opcode); |
3906 |
goto bad; |
goto bad; |
3907 |
} |
} |
3908 |
|
|