|
|
1.1.1.4 ! root 1: /* $Id: m68k-insns.c,v 1.16 2007/08/25 22:05:02 fredette Exp $ */ 1.1 root 2: 1.1.1.2 root 3: /* ic/m68k/m68k-insns.c - m68k instruction functions: */ 4: 5: /* 6: * Copyright (c) 2002, 2003 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 1.1 root 35: 36: /* includes: */ 37: #include "m68k-impl.h" 38: 1.1.1.4 ! root 39: _TME_RCSID("$Id: m68k-insns.c,v 1.16 2007/08/25 22:05:02 fredette Exp $"); 1.1 root 40: 41: #define TME_M68K_STD_FLAGS \ 42: do { \ 43: ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr \ 44: & TME_M68K_FLAG_X) \ 45: | (res < 0 ? TME_M68K_FLAG_N : 0) \ 46: | (res == 0 ? TME_M68K_FLAG_Z : 0)); \ 47: } while (/* CONSTCOND */ 0) 48: 49: /* this cannot fault: */ 50: TME_M68K_INSN(tme_m68k_exg) 51: { 52: tme_uint32_t tmp; 53: tmp = TME_M68K_INSN_OP0(tme_uint32_t); 54: TME_M68K_INSN_OP0(tme_uint32_t) = TME_M68K_INSN_OP1(tme_uint32_t); 55: TME_M68K_INSN_OP1(tme_uint32_t) = tmp; 56: TME_M68K_INSN_OK; 57: } 58: 59: /* this cannot fault: */ 60: TME_M68K_INSN(tme_m68k_extw) 61: { 62: tme_int16_t res; 63: res = TME_EXT_S8_S16((tme_int8_t) TME_M68K_INSN_OP1(tme_int16_t)); 64: TME_M68K_INSN_OP1(tme_int16_t) = res; 65: TME_M68K_STD_FLAGS; 66: TME_M68K_INSN_OK; 67: } 68: 69: /* this cannot fault: */ 70: TME_M68K_INSN(tme_m68k_extl) 71: { 72: tme_int32_t res; 73: res = TME_EXT_S16_S32((tme_int16_t) TME_M68K_INSN_OP1(tme_int32_t)); 74: TME_M68K_INSN_OP1(tme_int32_t) = res; 75: TME_M68K_STD_FLAGS; 76: TME_M68K_INSN_OK; 77: } 78: 79: /* this cannot fault: */ 80: TME_M68K_INSN(tme_m68k_extbl) 81: { 82: tme_int32_t res; 83: res = TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OP1(tme_int32_t)); 84: TME_M68K_INSN_OP1(tme_int32_t) = res; 85: TME_M68K_STD_FLAGS; 86: TME_M68K_INSN_OK; 87: } 88: 89: /* this cannot fault: */ 90: TME_M68K_INSN(tme_m68k_lea) 91: { 92: TME_M68K_INSN_OP0(tme_uint32_t) = TME_M68K_INSN_OP1(tme_uint32_t); 93: TME_M68K_INSN_OK; 94: } 95: 96: /* this cannot fault: */ 97: TME_M68K_INSN(tme_m68k_move_from_ccr) 98: { 99: TME_M68K_INSN_OP1(tme_uint16_t) = ic->tme_m68k_ireg_ccr; 100: TME_M68K_INSN_OK; 101: } 102: 103: /* this cannot fault: */ 104: TME_M68K_INSN(tme_m68k_move_from_sr) 105: { 106: TME_M68K_INSN_PRIV; 107: TME_M68K_INSN_OP1(tme_uint16_t) = ic->tme_m68k_ireg_sr; 108: TME_M68K_INSN_OK; 109: } 110: 111: /* this cannot fault: */ 112: /* this is the 68000 version, which isn't privileged: */ 113: TME_M68K_INSN(tme_m68k_move_from_sr0) 114: { 115: TME_M68K_INSN_OP1(tme_uint16_t) = ic->tme_m68k_ireg_sr; 116: TME_M68K_INSN_OK; 117: } 118: 119: /* this cannot fault: */ 120: TME_M68K_INSN(tme_m68k_swap) 121: { 122: tme_uint32_t tmp; 123: tme_int32_t res; 124: tmp = TME_M68K_INSN_OP1(tme_uint32_t); 125: tmp = (TME_FIELD_EXTRACTU(tmp, 0, 16) << 16) | TME_FIELD_EXTRACTU(tmp, 16, 16); 126: TME_M68K_INSN_OP1(tme_uint32_t) = tmp; 127: res = (tme_int32_t) tmp; 128: TME_M68K_STD_FLAGS; 129: TME_M68K_INSN_OK; 130: } 131: 132: /* this cannot fault: */ 133: TME_M68K_INSN(tme_m68k_nop) 134: { 135: TME_M68K_INSN_OK; 136: } 137: 138: /* this cannot fault: */ 139: TME_M68K_INSN(tme_m68k_scc) 140: { 141: TME_M68K_INSN_OP1(tme_uint8_t) = 142: (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4)) 143: ? 0xff 144: : 0x00); 145: TME_M68K_INSN_OK; 146: } 147: 148: /* this cannot fault: */ 149: TME_M68K_INSN(tme_m68k_dbcc) 150: { 151: if (!TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) { 152: if (--TME_M68K_INSN_OP0(tme_int16_t) != -1) { 153: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc 154: + 2 155: + TME_EXT_S16_U32(TME_M68K_INSN_OP1(tme_int16_t))); 156: } 157: } 158: TME_M68K_INSN_OK; 159: } 160: 161: /* this cannot fault: */ 1.1.1.3 root 162: static void 163: _tme_m68k_bcc(struct tme_m68k *ic, tme_int32_t disp) 1.1 root 164: { 165: if (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) { 1.1.1.3 root 166: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc + 2 + disp); 1.1 root 167: } 168: TME_M68K_INSN_OK; 169: } 1.1.1.3 root 170: TME_M68K_INSN(tme_m68k_bcc) 171: { 172: _tme_m68k_bcc(ic, TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OPCODE)); 173: } 174: TME_M68K_INSN(tme_m68k_bccl) 175: { 176: _tme_m68k_bcc(ic, TME_M68K_INSN_OP0(tme_int32_t)); 177: } 1.1 root 178: 179: /* this can fault: */ 1.1.1.3 root 180: static void 181: _tme_m68k_bsr(struct tme_m68k *ic, tme_int32_t disp) 1.1 root 182: { 183: TME_M68K_INSN_CANFAULT; 184: tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_next); 185: /* while the above push can fault, we don't have to worry about 186: restarting here, because after this point, nothing can fault for 187: the remainder of this instruction (the executor makes no stores 188: on behalf of a bsr): */ 1.1.1.4 ! root 189: tme_m68k_log(ic, 250, TME_OK, ! 190: (TME_M68K_LOG_HANDLE(ic), ! 191: _("bsr 0x%08x"), ! 192: (ic->tme_m68k_ireg_pc + 2 + disp))); 1.1.1.3 root 193: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc + 2 + disp); 1.1 root 194: TME_M68K_INSN_OK; 195: } 1.1.1.3 root 196: TME_M68K_INSN(tme_m68k_bsr) 197: { 198: _tme_m68k_bsr(ic, TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OPCODE)); 199: } 200: TME_M68K_INSN(tme_m68k_bsrl) 201: { 202: _tme_m68k_bsr(ic, TME_M68K_INSN_OP0(tme_int32_t)); 203: } 1.1 root 204: 205: /* this can fault: */ 206: TME_M68K_INSN(tme_m68k_pea) 207: { 208: TME_M68K_INSN_CANFAULT; 209: tme_m68k_push32(ic, TME_M68K_INSN_OP1(tme_uint32_t)); 210: /* while the above push can fault, we don't have to worry about 211: restarting here, because after this point, nothing can fault for 212: the remainder of this instruction (the executor makes no stores 213: on behalf of a pea): */ 214: TME_M68K_INSN_OK; 215: } 216: 217: /* this cannot fault: */ 218: TME_M68K_INSN(tme_m68k_bkpt) 219: { 1.1.1.3 root 220: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL); 1.1 root 221: } 222: 223: /* this cannot fault: */ 224: TME_M68K_INSN(tme_m68k_illegal) 225: { 1.1.1.3 root 226: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL); 1.1 root 227: } 228: 229: /* this can fault: */ 230: TME_M68K_INSN(tme_m68k_tas) 231: { 1.1.1.4 ! root 232: struct tme_m68k_rmw rmw; 1.1 root 233: struct tme_m68k_tlb *tlb; 1.1.1.4 ! root 234: tme_shared tme_int8_t *mem; 1.1 root 235: tme_uint8_t flags; 236: tme_int8_t value; 1.1.1.4 ! root 237: tme_int8_t value_written; ! 238: tme_int8_t value_verify; 1.1 root 239: 240: /* start the read/modify/write cycle: */ 1.1.1.4 ! root 241: rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address; ! 242: rmw.tme_m68k_rmw_address_count = 1; ! 243: rmw.tme_m68k_rmw_size = sizeof(tme_uint8_t); ! 244: if (tme_m68k_rmw_start(ic, ! 245: &rmw)) 1.1 root 246: TME_M68K_INSN_OK; 247: 1.1.1.4 ! root 248: /* if this TLB entry allows fast reading: */ ! 249: if (!rmw.tme_m68k_rmw_slow_reads[0]) { ! 250: ! 251: /* get this TLB entry: */ ! 252: tlb = rmw.tme_m68k_rmw_tlbs[0]; 1.1 root 253: 1.1.1.4 ! root 254: /* make the emulator memory pointer: */ ! 255: mem = (tme_shared tme_int8_t *) (tlb->tme_m68k_tlb_emulator_off_read + ic->_tme_m68k_ea_address); ! 256: ! 257: /* read memory: */ ! 258: value ! 259: = tme_memory_atomic_read8((tme_shared tme_uint8_t *) mem, ! 260: tlb->tme_m68k_tlb_bus_rwlock, ! 261: sizeof(tme_uint8_t)); ! 262: ! 263: /* spin the tas in a compare-and-exchange loop: */ ! 264: for (;;) { ! 265: ! 266: /* make the value to write: */ ! 267: value_written = value | 0x80; ! 268: ! 269: /* try the compare-and-exchange: */ ! 270: value_verify ! 271: = tme_memory_atomic_cx8((tme_shared tme_uint8_t *) mem, ! 272: value, ! 273: value_written, ! 274: tlb->tme_m68k_tlb_bus_rwlock, ! 275: sizeof(tme_uint8_t)); ! 276: ! 277: /* if the compare-and-exchange failed: */ ! 278: if (__tme_predict_false(value_verify != value)) { ! 279: ! 280: /* loop with the new value read from the memory: */ ! 281: value = value_verify; ! 282: continue; ! 283: } ! 284: ! 285: /* stop now: */ ! 286: break; ! 287: } ! 288: ! 289: /* store the value read: */ ! 290: ic->tme_m68k_ireg_memx8 = value; ! 291: } ! 292: 1.1 root 293: /* the modify part of the read/modify/write cycle: */ 294: value = ic->tme_m68k_ireg_memx8; 295: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 296: if (value < 0) flags |= TME_M68K_FLAG_N; 297: if (value == 0) flags |= TME_M68K_FLAG_Z; 298: ic->tme_m68k_ireg_ccr = flags; 299: ic->tme_m68k_ireg_memx8 |= 0x80; 300: 301: /* finish the read/modify/write cycle: */ 1.1.1.4 ! root 302: tme_m68k_rmw_finish(ic, ! 303: &rmw, ! 304: TRUE); 1.1 root 305: 306: TME_M68K_INSN_OK; 307: } 308: 309: /* this cannot fault: */ 310: TME_M68K_INSN(tme_m68k_tas_r) 311: { 312: tme_uint8_t flags; 313: tme_int8_t value; 314: value = TME_M68K_INSN_OP1(tme_int8_t); 315: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 316: if (value < 0) flags |= TME_M68K_FLAG_N; 317: if (value == 0) flags |= TME_M68K_FLAG_Z; 318: ic->tme_m68k_ireg_ccr = flags; 319: TME_M68K_INSN_OP1(tme_int8_t) = value | 0x80; 320: TME_M68K_INSN_OK; 321: } 322: 323: /* this cannot fault: */ 324: TME_M68K_INSN(tme_m68k_move_usp) 325: { 326: TME_M68K_INSN_PRIV; 327: if (TME_M68K_INSN_OPCODE & TME_BIT(3)) { 328: TME_M68K_INSN_OP1(tme_uint32_t) = ic->tme_m68k_ireg_usp; 329: } 330: else { 331: ic->tme_m68k_ireg_usp = TME_M68K_INSN_OP1(tme_uint32_t); 332: } 333: TME_M68K_INSN_OK; 334: } 335: 336: /* this cannot fault: */ 337: TME_M68K_INSN(tme_m68k_trap) 338: { 339: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 340: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP_0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 4))); 1.1 root 341: } 342: 343: /* this cannot fault: */ 344: TME_M68K_INSN(tme_m68k_trapv) 345: { 346: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_V) { 1.1.1.3 root 347: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 348: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 349: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP)); 1.1 root 350: } 351: TME_M68K_INSN_OK; 352: } 353: 354: /* this can fault: */ 355: TME_M68K_INSN(tme_m68k_link) 356: { 357: TME_M68K_INSN_CANFAULT; 358: tme_m68k_push32(ic, TME_M68K_INSN_OP1(tme_uint32_t)); 359: TME_M68K_INSN_OP1(tme_uint32_t) = ic->tme_m68k_ireg_a7; 360: ic->tme_m68k_ireg_a7 += TME_M68K_INSN_OP0(tme_uint32_t); 361: TME_M68K_INSN_OK; 362: } 363: 364: /* this can fault: */ 365: TME_M68K_INSN(tme_m68k_unlk) 366: { 367: TME_M68K_INSN_CANFAULT; 368: ic->tme_m68k_ireg_a7 = TME_M68K_INSN_OP0(tme_uint32_t); 369: tme_m68k_pop32(ic, &TME_M68K_INSN_OP0(tme_uint32_t)); 370: TME_M68K_INSN_OK; 371: } 372: 373: /* this cannot fault: */ 374: TME_M68K_INSN(tme_m68k_movec) 375: { 376: int ireg; 377: tme_uint32_t *creg; 1.1.1.2 root 378: tme_uint32_t mask; 1.1.1.3 root 379: int illegal; 1.1 root 380: TME_M68K_INSN_PRIV; 381: /* in case we're reading the msp or isp and we're on that stack, 382: this flushes %a7 to that register: */ 383: tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr); 384: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 1.1.1.2 root 385: mask = 0xffffffff; 1.1.1.3 root 386: illegal = FALSE; 1.1 root 387: switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 12)) { 1.1.1.2 root 388: case 0x000: creg = &ic->tme_m68k_ireg_sfc; mask = TME_M68K_FC_7; break; 389: case 0x001: creg = &ic->tme_m68k_ireg_dfc; mask = TME_M68K_FC_7; break; 1.1.1.3 root 390: case 0x002: creg = &ic->tme_m68k_ireg_cacr; mask = 0x3; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break; 1.1 root 391: case 0x800: creg = &ic->tme_m68k_ireg_usp; break; 392: case 0x801: creg = &ic->tme_m68k_ireg_vbr; break; 1.1.1.3 root 393: case 0x802: creg = &ic->tme_m68k_ireg_caar; illegal = (ic->tme_m68k_type != TME_M68K_M68020); break; 394: case 0x803: creg = &ic->tme_m68k_ireg_msp; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break; 395: case 0x804: creg = &ic->tme_m68k_ireg_isp; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break; 396: default: illegal = TRUE; creg = NULL; 397: } 398: if (illegal) { 399: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL); 1.1 root 400: } 401: if (TME_M68K_INSN_OPCODE & TME_BIT(0)) { 1.1.1.2 root 402: *creg = ic->tme_m68k_ireg_uint32(ireg) & mask; 1.1 root 403: } 404: else { 405: ic->tme_m68k_ireg_uint32(ireg) = *creg; 406: } 407: /* in case we're writing the msp or isp and we're on that stack, 408: this flushes that register to %a7: */ 409: tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr); 410: TME_M68K_INSN_OK; 411: } 412: 413: /* this cannot fault: */ 414: TME_M68K_INSN(tme_m68k_reset) 415: { 1.1.1.2 root 416: struct tme_bus_connection *conn_bus; 417: int rc; 418: 1.1 root 419: TME_M68K_INSN_PRIV; 1.1.1.2 root 420: 421: /* get the bus connection: */ 422: conn_bus = &ic->_tme_m68k_bus_connection->tme_m68k_bus_connection; 423: 1.1.1.4 ! root 424: /* unlock for the callout: */ ! 425: tme_m68k_callout_unlock(ic); ! 426: 1.1.1.2 root 427: /* assert the RESET line: */ 428: rc = (*conn_bus->tme_bus_signal) 429: (conn_bus, 430: (TME_BUS_SIGNAL_RESET 1.1.1.3 root 431: | TME_BUS_SIGNAL_LEVEL_ASSERTED)); 1.1.1.2 root 432: assert (rc == TME_OK); 433: 434: /* XXX RESET is supposed to be asserted for 512 clocks, 435: so a sleep is needed here: */ 436: 437: /* negate the RESET line: */ 438: rc = (*conn_bus->tme_bus_signal) 439: (conn_bus, 440: (TME_BUS_SIGNAL_RESET 1.1.1.3 root 441: | TME_BUS_SIGNAL_LEVEL_NEGATED)); 1.1.1.2 root 442: assert (rc == TME_OK); 1.1.1.4 ! root 443: ! 444: /* relock after the callout: */ ! 445: tme_m68k_callout_relock(ic); 1.1.1.2 root 446: 447: TME_M68K_INSN_OK; 1.1 root 448: } 449: 450: /* this can fault: */ 451: TME_M68K_INSN(tme_m68k_rtd) 452: { 453: TME_M68K_INSN_CANFAULT; 454: tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32); 455: /* while the above pop can fault, we don't have to worry about 456: restarting here, because after this point, nothing can fault for 457: the remainder of this instruction (the executor makes no stores 458: on behalf of an rtd): */ 459: ic->tme_m68k_ireg_a7 += TME_M68K_INSN_OP0(tme_uint32_t); 460: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32); 461: TME_M68K_INSN_OK; 462: } 463: 464: /* this can fault: */ 465: TME_M68K_INSN(tme_m68k_rtr) 466: { 467: TME_M68K_INSN_CANFAULT; 468: tme_m68k_pop16(ic, &ic->tme_m68k_ireg_memx16); 469: if (!TME_M68K_SEQUENCE_RESTARTING) { 470: ic->tme_m68k_ireg_ccr = ic->tme_m68k_ireg_memx8 & TME_M68K_FLAG_CCR; 471: } 472: tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32); 473: /* while the above pop can fault, we don't have to worry about 474: restarting here, because after this point, nothing can fault for 475: the remainder of this instruction (the executor makes no stores 476: on behalf of an rtr): */ 477: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32); 478: TME_M68K_INSN_OK; 479: } 480: 481: /* this can fault: */ 482: TME_M68K_INSN(tme_m68k_rts) 483: { 484: TME_M68K_INSN_CANFAULT; 485: tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32); 1.1.1.4 ! root 486: tme_m68k_log(ic, 250, TME_OK, ! 487: (TME_M68K_LOG_HANDLE(ic), ! 488: _("rts 0x%08x"), ! 489: ic->tme_m68k_ireg_memx32)); 1.1 root 490: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32); 491: TME_M68K_INSN_OK; 492: } 493: 494: /* this can fault: */ 495: TME_M68K_INSN(tme_m68k_jsr) 496: { 497: TME_M68K_INSN_CANFAULT; 498: tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_next); 1.1.1.4 ! root 499: tme_m68k_log(ic, 250, TME_OK, ! 500: (TME_M68K_LOG_HANDLE(ic), ! 501: _("jsr 0x%08x"), ! 502: ic->_tme_m68k_ea_address)); 1.1 root 503: TME_M68K_INSN_BRANCH(ic->_tme_m68k_ea_address); 504: TME_M68K_INSN_OK; 505: } 506: 507: /* this cannot fault: */ 508: TME_M68K_INSN(tme_m68k_jmp) 509: { 510: TME_M68K_INSN_BRANCH(ic->_tme_m68k_ea_address); 511: TME_M68K_INSN_OK; 512: } 513: 514: /* this cannot fault: */ 515: TME_M68K_INSN(tme_m68k_rte) 516: { 517: TME_M68K_INSN_PRIV; 518: ic->_tme_m68k_mode = TME_M68K_MODE_RTE; 519: TME_M68K_SEQUENCE_START; 520: tme_m68k_redispatch(ic); 521: } 522: 523: /* this cannot fault: */ 524: TME_M68K_INSN(tme_m68k_stop) 525: { 526: TME_M68K_INSN_PRIV; 527: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 528: ic->tme_m68k_ireg_sr = TME_M68K_INSN_SPECOP; 529: ic->_tme_m68k_mode = TME_M68K_MODE_STOP; 530: TME_M68K_SEQUENCE_START; 531: tme_m68k_redispatch(ic); 532: } 533: 534: /* this cannot fault: */ 535: TME_M68K_INSN(tme_m68k_priv) 536: { 1.1.1.3 root 537: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_PRIV); 1.1 root 538: } 539: 540: /* this can fault: */ 541: TME_M68K_INSN(tme_m68k_cmp2_chk2) 542: { 543: tme_uint32_t ireg; 544: unsigned int size_bytes, size_name, size_ireg; 545: tme_uint32_t uvalue, ulower, uupper; 546: 547: TME_M68K_INSN_CANFAULT; 548: 549: /* get the register to check and the operand size: */ 550: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 551: size_bytes = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 2); 552: size_ireg = 2 - size_bytes; 553: size_bytes = 1 << size_bytes; 1.1.1.4 ! root 554: #if TME_M68K_SIZE_8 != 1 ! 555: #error "TME_M68K_SIZE_8 must be 1" ! 556: #endif ! 557: #if TME_M68K_SIZE_16 != 2 ! 558: #error "TME_M68K_SIZE_16 must be 2" ! 559: #endif ! 560: #if TME_M68K_SIZE_32 != 4 ! 561: #error "TME_M68K_SIZE_32 must be 4" ! 562: #endif ! 563: size_name = size_bytes; 1.1 root 564: 565: /* read in the two bounds: */ 566: (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMX32 << size_ireg); 567: if (!TME_M68K_SEQUENCE_RESTARTING) { 568: ic->_tme_m68k_ea_address += size_bytes; 569: } 570: (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMY32 << size_ireg); 571: 572: /* if we have an address register, sign-extend the bounds to 32 573: bits: */ 574: if (ireg >= TME_M68K_IREG_A0) { 575: if (size_name == TME_M68K_SIZE_8) { 576: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMX8)); 577: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMY8)); 578: } 579: else if (size_name == TME_M68K_SIZE_16) { 580: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMX16)); 581: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMY16)); 582: } 583: size_bytes = sizeof(tme_uint32_t); 584: size_name = TME_M68K_SIZE_32; 585: } 586: 587: /* get the values to check: */ 588: switch (size_name) { 589: case TME_M68K_SIZE_8: 1.1.1.4 ! root 590: uvalue = ic->tme_m68k_ireg_uint8(ireg << 2); 1.1 root 591: ulower = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMX8); 592: uupper = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMY8); 593: break; 594: case TME_M68K_SIZE_16: 1.1.1.4 ! root 595: uvalue = ic->tme_m68k_ireg_uint16(ireg << 1); 1.1 root 596: ulower = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMX16); 597: uupper = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMY16); 598: break; 599: case TME_M68K_SIZE_32: 600: uvalue = ic->tme_m68k_ireg_uint32(ireg); 601: ulower = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMX32); 602: uupper = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMY32); 603: break; 604: default: abort(); 605: } 606: 607: /* do the comparison. if the value is out-of-bounds and this is 608: a chk2 instruction, trap: */ 609: ic->tme_m68k_ireg_ccr = (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 610: if (uvalue == ulower 611: || uvalue == uupper) { 612: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 613: } 614: else if ((ulower > uupper) 1.1.1.4 ! root 615: ? (uvalue < ulower && uvalue > uupper) 1.1 root 616: : (uvalue < ulower || uvalue > uupper)) { 617: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_C; 1.1.1.4 ! root 618: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { 1.1.1.3 root 619: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 620: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 621: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); 1.1 root 622: } 623: } 624: 625: TME_M68K_INSN_OK; 626: } 627: 628: TME_M68K_INSN(tme_m68k_callm) 629: { 630: /* TBD */ 631: abort(); 632: } 633: 634: TME_M68K_INSN(tme_m68k_rtm) 635: { 636: /* TBD */ 637: abort(); 638: } 639: 640: /* this cannot fault: */ 641: TME_M68K_INSN(tme_m68k_trapcc) 642: { 643: if (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) { 1.1.1.3 root 644: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 645: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 646: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP)); 1.1 root 647: } 648: TME_M68K_INSN_OK; 649: } 650: 651: /* the bitfield helper functions handle faults: */ 652: TME_M68K_INSN(tme_m68k_bfchg) 653: { 654: tme_uint32_t bf_value; 655: bf_value = tme_m68k_bitfield_read_unsigned(ic); 656: tme_m68k_bitfield_write_unsigned(ic, ~bf_value, FALSE); 657: TME_M68K_INSN_OK; 658: } 659: 660: /* the bitfield helper functions handle faults: */ 661: TME_M68K_INSN(tme_m68k_bfclr) 662: { 663: (void) tme_m68k_bitfield_read_unsigned(ic); 664: tme_m68k_bitfield_write_unsigned(ic, 0, FALSE); 665: TME_M68K_INSN_OK; 666: } 667: 668: /* the bitfield helper functions handle faults: */ 669: TME_M68K_INSN(tme_m68k_bfexts) 670: { 671: tme_int32_t bf_value; 672: bf_value = tme_m68k_bitfield_read_signed(ic); 673: ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)) 674: = bf_value; 675: TME_M68K_INSN_OK; 676: } 677: 678: /* the bitfield helper functions handle faults: */ 679: TME_M68K_INSN(tme_m68k_bfextu) 680: { 681: tme_uint32_t bf_value; 682: bf_value = tme_m68k_bitfield_read_unsigned(ic); 683: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)) 684: = bf_value; 685: TME_M68K_INSN_OK; 686: } 687: 688: /* the bitfield helper functions handle faults: */ 689: TME_M68K_INSN(tme_m68k_bfffo) 690: { 691: tme_int16_t specop; 692: tme_int32_t bf_offset; 693: unsigned int bf_width; 694: tme_uint32_t bf_value; 1.1.1.3 root 695: unsigned int bf_pos; 1.1 root 696: 697: /* get the bitfield offset from a data register or as an immediate: */ 698: specop = TME_M68K_INSN_SPECOP; 699: bf_offset = ((specop & TME_BIT(11)) 700: ? ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 6, 3)) 701: : (tme_int32_t) TME_FIELD_EXTRACTU(specop, 6, 5)); 702: 703: /* get the bitfield width: */ 704: bf_width = tme_m68k_bitfield_width(ic); 705: 706: /* get the bitfield value: */ 707: bf_value = tme_m68k_bitfield_read_unsigned(ic); 708: 1.1.1.3 root 709: /* find the first set bit: */ 710: for (bf_pos = 0, bf_value <<= (32 - bf_width); 711: bf_pos < bf_width && !(bf_value & 0x80000000); 712: bf_pos++, bf_value <<= 1); 713: 1.1 root 714: /* set the result: */ 715: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 12, 3)) 1.1.1.3 root 716: = bf_offset + bf_pos; 1.1 root 717: 718: TME_M68K_INSN_OK; 719: } 720: 721: /* the bitfield helper functions handle faults: */ 722: TME_M68K_INSN(tme_m68k_bfins) 723: { 724: tme_m68k_bitfield_write_unsigned(ic, 725: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 726: + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)), 727: TRUE); 728: TME_M68K_INSN_OK; 729: } 730: 731: /* the bitfield helper functions handle faults: */ 732: TME_M68K_INSN(tme_m68k_bfset) 733: { 734: (void) tme_m68k_bitfield_read_unsigned(ic); 735: tme_m68k_bitfield_write_unsigned(ic, 0xffffffff, FALSE); 736: TME_M68K_INSN_OK; 737: } 738: 739: /* the bitfield helper functions handle faults: */ 740: TME_M68K_INSN(tme_m68k_bftst) 741: { 742: (void) tme_m68k_bitfield_read_unsigned(ic); 743: TME_M68K_INSN_OK; 744: } 745: 746: /* this can fault: */ 747: TME_M68K_INSN(tme_m68k_pack) 748: { 749: int ireg_x, ireg_y; 750: tme_uint16_t value; 751: 752: TME_M68K_INSN_CANFAULT; 753: 754: /* get the two registers: */ 755: ireg_x = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 756: ireg_y = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 757: 758: /* if this is a memory pack: */ 759: if (TME_M68K_INSN_OPCODE & TME_BIT(3)) { 760: ireg_x += TME_M68K_IREG_A0; 761: ireg_y += TME_M68K_IREG_A0; 762: 763: /* do the predecrement read of two bytes: */ 764: if (!TME_M68K_SEQUENCE_RESTARTING) { 765: ic->tme_m68k_ireg_uint32(ireg_x) -= sizeof(tme_uint16_t); 766: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 767: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_x); 768: } 769: tme_m68k_read_memx16(ic); 770: 771: /* get the two bytes and add the extension: */ 772: value = ic->tme_m68k_ireg_memx16 + TME_M68K_INSN_SPECOP; 773: 774: /* do the predecrement write of one byte: */ 775: if (!TME_M68K_SEQUENCE_RESTARTING) { 776: ic->tme_m68k_ireg_uint32(ireg_y) -= sizeof(tme_uint8_t); 777: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 778: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_y); 779: ic->tme_m68k_ireg_memx8 = (tme_uint8_t) ((value & 0x0f) | (value >> 4)); 780: } 781: tme_m68k_write_memx8(ic); 782: } 783: 784: /* if this is a register pack: */ 785: else { 786: ireg_x += TME_M68K_IREG_D0; 787: ireg_y += TME_M68K_IREG_D0; 788: value = ic->tme_m68k_ireg_uint16(ireg_x << 1) + TME_M68K_INSN_SPECOP; 789: ic->tme_m68k_ireg_uint8(ireg_y << 2) = (tme_uint8_t) ((value & 0x0f) | (value >> 4)); 790: } 791: 792: TME_M68K_INSN_OK; 793: } 794: 795: /* this can fault: */ 796: TME_M68K_INSN(tme_m68k_unpk) 797: { 798: int ireg_x, ireg_y; 799: tme_uint16_t value; 800: 801: TME_M68K_INSN_CANFAULT; 802: 803: /* get the two registers: */ 804: ireg_x = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 805: ireg_y = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 806: 807: /* if this is a memory pack: */ 808: if (TME_M68K_INSN_OPCODE & TME_BIT(3)) { 809: ireg_x += TME_M68K_IREG_A0; 810: ireg_y += TME_M68K_IREG_A0; 811: 812: /* do the predecrement read of one byte: */ 813: if (!TME_M68K_SEQUENCE_RESTARTING) { 814: ic->tme_m68k_ireg_uint32(ireg_x) -= sizeof(tme_uint8_t); 815: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 816: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_x); 817: } 818: tme_m68k_read_memx8(ic); 819: 820: /* unpack the byte and add the extension: */ 821: value = ic->tme_m68k_ireg_memx8; 822: value = ((value & 0x0f) | ((value & 0xf0) << 4)) + TME_M68K_INSN_SPECOP; 823: 824: /* do the predecrement write of two bytes: */ 825: if (!TME_M68K_SEQUENCE_RESTARTING) { 826: ic->tme_m68k_ireg_uint32(ireg_y) -= sizeof(tme_uint16_t); 827: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 828: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_y); 829: ic->tme_m68k_ireg_memx16 = value; 830: } 831: tme_m68k_write_memx16(ic); 832: } 833: 834: /* if this is a register pack: */ 835: else { 836: ireg_x += TME_M68K_IREG_D0; 837: ireg_y += TME_M68K_IREG_D0; 838: value = ic->tme_m68k_ireg_uint8(ireg_x << 2); 839: value = ((value & 0x0f) | ((value & 0xf0) << 4)) + TME_M68K_INSN_SPECOP; 840: ic->tme_m68k_ireg_uint16(ireg_y << 1) = value; 841: } 842: 843: TME_M68K_INSN_OK; 844: } 845: 1.1.1.3 root 846: /* these just redispatch into one of the multiply or divide insns: */ 847: TME_M68K_INSN(tme_m68k_mull) 848: { 849: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { 850: tme_m68k_mulsl(ic, _op0, _op1); 851: } 852: else { 853: tme_m68k_mulul(ic, _op0, _op1); 854: } 855: } 856: TME_M68K_INSN(tme_m68k_divl) 857: { 858: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { 859: tme_m68k_divsl(ic, _op0, _op1); 860: } 861: else { 862: tme_m68k_divul(ic, _op0, _op1); 863: } 864: } 865: 1.1 root 866: #include "m68k-bus-auto.c" 867: 868: #include "m68k-insns-auto.c"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.