| 4098 | |
| 4099 | #define SMC_MAXHITS 8 |
| 4100 | static void smc_detector(uaecptr addr, int rwi, int size, uae_u32 *valp) |
| 4101 | { |
| 4102 | int hitcnt; |
| 4103 | uaecptr hitaddr, hitpc; |
| 4104 | |
| 4105 | if (!smc_table) |
| 4106 | return; |
| 4107 | if (addr + size > smc_size) |
| 4108 | return; |
| 4109 | |
| 4110 | if (rwi == 2) { |
| 4111 | for (int i = 0; i < size; i++) { |
| 4112 | struct smc_item *si = &smc_table[addr + i]; |
| 4113 | if (si->version != smc_version) { |
| 4114 | si->version = smc_version; |
| 4115 | si->addr = 0xffffffff; |
| 4116 | si->cnt = 0; |
| 4117 | } |
| 4118 | if (si->cnt < SMC_MAXHITS) { |
| 4119 | si->addr = m68k_getpc(); |
| 4120 | } |
| 4121 | } |
| 4122 | return; |
| 4123 | } |
| 4124 | hitpc = 0xffffffff; |
| 4125 | for (int i = 0; i < size && hitpc == 0xffffffff && addr + i < smc_size; i += 2) { |
| 4126 | struct smc_item *si = &smc_table[addr + i]; |
| 4127 | if (si->version == smc_version) { |
| 4128 | hitpc = si->addr; |
| 4129 | } |
| 4130 | } |
| 4131 | if (hitpc == 0xffffffff) { |
| 4132 | return; |
| 4133 | } |
| 4134 | if ((hitpc & 0xFFF80000) == 0xF80000) { |
| 4135 | return; |
| 4136 | } |
| 4137 | hitaddr = addr; |
| 4138 | hitcnt = 0; |
| 4139 | while (addr < smc_size) { |
| 4140 | struct smc_item *si = &smc_table[addr]; |
| 4141 | if (si->addr == 0xffffffff || si->version != smc_version) { |
| 4142 | break; |
| 4143 | } |
| 4144 | si->addr = 0xffffffff; |
| 4145 | hitcnt++; |
| 4146 | addr++; |
| 4147 | } |
| 4148 | if (currprefs.cpu_model <= 68010 && currprefs.cpu_compatible) { |
| 4149 | /* ignore single-word unconditional jump instructions |
| 4150 | * (instruction prefetch from PC+2 can cause false positives) */ |
| 4151 | if (regs.irc == 0x4e75 || regs.irc == 0x4e74 || regs.irc == 0x4e73 || regs.irc == 0x4e77) |
| 4152 | return; /* RTS, RTD, RTE, RTR */ |
| 4153 | if ((regs.irc & 0xff00) == 0x6000 && (regs.irc & 0x00ff) != 0 && (regs.irc & 0x00ff) != 0xff) |
| 4154 | return; /* BRA.B */ |
| 4155 | } |
| 4156 | if (hitcnt < 100) { |
| 4157 | struct smc_item *si = &smc_table[hitaddr]; |
no test coverage detected