|
|
1.1.1.3 ! root 1: /* $Id: m68k-insns.c,v 1.14 2005/03/23 11:53: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.3 ! root 39: _TME_RCSID("$Id: m68k-insns.c,v 1.14 2005/03/23 11:53: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.3 ! root 189: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc + 2 + disp); 1.1 root 190: TME_M68K_INSN_OK; 191: } 1.1.1.3 ! root 192: TME_M68K_INSN(tme_m68k_bsr) ! 193: { ! 194: _tme_m68k_bsr(ic, TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OPCODE)); ! 195: } ! 196: TME_M68K_INSN(tme_m68k_bsrl) ! 197: { ! 198: _tme_m68k_bsr(ic, TME_M68K_INSN_OP0(tme_int32_t)); ! 199: } 1.1 root 200: 201: /* this can fault: */ 202: TME_M68K_INSN(tme_m68k_pea) 203: { 204: TME_M68K_INSN_CANFAULT; 205: tme_m68k_push32(ic, TME_M68K_INSN_OP1(tme_uint32_t)); 206: /* while the above push can fault, we don't have to worry about 207: restarting here, because after this point, nothing can fault for 208: the remainder of this instruction (the executor makes no stores 209: on behalf of a pea): */ 210: TME_M68K_INSN_OK; 211: } 212: 213: /* this cannot fault: */ 214: TME_M68K_INSN(tme_m68k_bkpt) 215: { 1.1.1.3 ! root 216: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL); 1.1 root 217: } 218: 219: /* this cannot fault: */ 220: TME_M68K_INSN(tme_m68k_illegal) 221: { 1.1.1.3 ! root 222: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL); 1.1 root 223: } 224: 225: /* this can fault: */ 226: TME_M68K_INSN(tme_m68k_tas) 227: { 228: struct tme_m68k_tlb *tlb; 229: tme_uint8_t flags; 230: tme_int8_t value; 231: 232: TME_M68K_INSN_CANFAULT; 233: 234: /* start the read/modify/write cycle: */ 235: tlb = tme_m68k_rmw_start(ic); 236: if (tlb == NULL) 237: TME_M68K_INSN_OK; 238: 239: /* the read part of the read/modify/write cycle: */ 240: tme_m68k_read8(ic, tlb, 241: &ic->_tme_m68k_ea_function_code, 242: &ic->_tme_m68k_ea_address, 243: &ic->tme_m68k_ireg_memx8, 244: TME_M68K_BUS_CYCLE_RMW); 245: 246: /* the modify part of the read/modify/write cycle: */ 247: value = ic->tme_m68k_ireg_memx8; 248: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 249: if (value < 0) flags |= TME_M68K_FLAG_N; 250: if (value == 0) flags |= TME_M68K_FLAG_Z; 251: ic->tme_m68k_ireg_ccr = flags; 252: ic->tme_m68k_ireg_memx8 |= 0x80; 253: 254: /* the write part of the read/modify/write cycle: */ 255: tme_m68k_write8(ic, tlb, 256: &ic->_tme_m68k_ea_function_code, 257: &ic->_tme_m68k_ea_address, 258: &ic->tme_m68k_ireg_memx8, 259: TME_M68K_BUS_CYCLE_RMW); 260: 261: /* finish the read/modify/write cycle: */ 262: tme_m68k_rmw_finish(ic, tlb); 263: 264: TME_M68K_INSN_OK; 265: } 266: 267: /* this cannot fault: */ 268: TME_M68K_INSN(tme_m68k_tas_r) 269: { 270: tme_uint8_t flags; 271: tme_int8_t value; 272: value = TME_M68K_INSN_OP1(tme_int8_t); 273: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 274: if (value < 0) flags |= TME_M68K_FLAG_N; 275: if (value == 0) flags |= TME_M68K_FLAG_Z; 276: ic->tme_m68k_ireg_ccr = flags; 277: TME_M68K_INSN_OP1(tme_int8_t) = value | 0x80; 278: TME_M68K_INSN_OK; 279: } 280: 281: /* this cannot fault: */ 282: TME_M68K_INSN(tme_m68k_move_usp) 283: { 284: TME_M68K_INSN_PRIV; 285: if (TME_M68K_INSN_OPCODE & TME_BIT(3)) { 286: TME_M68K_INSN_OP1(tme_uint32_t) = ic->tme_m68k_ireg_usp; 287: } 288: else { 289: ic->tme_m68k_ireg_usp = TME_M68K_INSN_OP1(tme_uint32_t); 290: } 291: TME_M68K_INSN_OK; 292: } 293: 294: /* this cannot fault: */ 295: TME_M68K_INSN(tme_m68k_trap) 296: { 297: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 ! root 298: 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 299: } 300: 301: /* this cannot fault: */ 302: TME_M68K_INSN(tme_m68k_trapv) 303: { 304: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_V) { 1.1.1.3 ! root 305: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 306: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 ! root 307: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP)); 1.1 root 308: } 309: TME_M68K_INSN_OK; 310: } 311: 312: /* this can fault: */ 313: TME_M68K_INSN(tme_m68k_link) 314: { 315: TME_M68K_INSN_CANFAULT; 316: tme_m68k_push32(ic, TME_M68K_INSN_OP1(tme_uint32_t)); 317: TME_M68K_INSN_OP1(tme_uint32_t) = ic->tme_m68k_ireg_a7; 318: ic->tme_m68k_ireg_a7 += TME_M68K_INSN_OP0(tme_uint32_t); 319: TME_M68K_INSN_OK; 320: } 321: 322: /* this can fault: */ 323: TME_M68K_INSN(tme_m68k_unlk) 324: { 325: TME_M68K_INSN_CANFAULT; 326: ic->tme_m68k_ireg_a7 = TME_M68K_INSN_OP0(tme_uint32_t); 327: tme_m68k_pop32(ic, &TME_M68K_INSN_OP0(tme_uint32_t)); 328: TME_M68K_INSN_OK; 329: } 330: 331: /* this cannot fault: */ 332: TME_M68K_INSN(tme_m68k_movec) 333: { 334: int ireg; 335: tme_uint32_t *creg; 1.1.1.2 root 336: tme_uint32_t mask; 1.1.1.3 ! root 337: int illegal; 1.1 root 338: TME_M68K_INSN_PRIV; 339: /* in case we're reading the msp or isp and we're on that stack, 340: this flushes %a7 to that register: */ 341: tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr); 342: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 1.1.1.2 root 343: mask = 0xffffffff; 1.1.1.3 ! root 344: illegal = FALSE; 1.1 root 345: switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 12)) { 1.1.1.2 root 346: case 0x000: creg = &ic->tme_m68k_ireg_sfc; mask = TME_M68K_FC_7; break; 347: case 0x001: creg = &ic->tme_m68k_ireg_dfc; mask = TME_M68K_FC_7; break; 1.1.1.3 ! root 348: case 0x002: creg = &ic->tme_m68k_ireg_cacr; mask = 0x3; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break; 1.1 root 349: case 0x800: creg = &ic->tme_m68k_ireg_usp; break; 350: case 0x801: creg = &ic->tme_m68k_ireg_vbr; break; 1.1.1.3 ! root 351: case 0x802: creg = &ic->tme_m68k_ireg_caar; illegal = (ic->tme_m68k_type != TME_M68K_M68020); break; ! 352: case 0x803: creg = &ic->tme_m68k_ireg_msp; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break; ! 353: case 0x804: creg = &ic->tme_m68k_ireg_isp; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break; ! 354: default: illegal = TRUE; creg = NULL; ! 355: } ! 356: if (illegal) { ! 357: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL); 1.1 root 358: } 359: if (TME_M68K_INSN_OPCODE & TME_BIT(0)) { 1.1.1.2 root 360: *creg = ic->tme_m68k_ireg_uint32(ireg) & mask; 1.1 root 361: } 362: else { 363: ic->tme_m68k_ireg_uint32(ireg) = *creg; 364: } 365: /* in case we're writing the msp or isp and we're on that stack, 366: this flushes that register to %a7: */ 367: tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr); 368: TME_M68K_INSN_OK; 369: } 370: 371: /* this cannot fault: */ 372: TME_M68K_INSN(tme_m68k_reset) 373: { 1.1.1.2 root 374: struct tme_bus_connection *conn_bus; 375: int rc; 376: 1.1 root 377: TME_M68K_INSN_PRIV; 1.1.1.2 root 378: 379: /* get the bus connection: */ 380: conn_bus = &ic->_tme_m68k_bus_connection->tme_m68k_bus_connection; 381: 382: /* assert the RESET line: */ 383: rc = (*conn_bus->tme_bus_signal) 384: (conn_bus, 385: (TME_BUS_SIGNAL_RESET 1.1.1.3 ! root 386: | TME_BUS_SIGNAL_LEVEL_ASSERTED)); 1.1.1.2 root 387: assert (rc == TME_OK); 388: 389: /* XXX RESET is supposed to be asserted for 512 clocks, 390: so a sleep is needed here: */ 391: 392: /* negate the RESET line: */ 393: rc = (*conn_bus->tme_bus_signal) 394: (conn_bus, 395: (TME_BUS_SIGNAL_RESET 1.1.1.3 ! root 396: | TME_BUS_SIGNAL_LEVEL_NEGATED)); 1.1.1.2 root 397: assert (rc == TME_OK); 398: 399: TME_M68K_INSN_OK; 1.1 root 400: } 401: 402: /* this can fault: */ 403: TME_M68K_INSN(tme_m68k_rtd) 404: { 405: TME_M68K_INSN_CANFAULT; 406: tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32); 407: /* while the above pop can fault, we don't have to worry about 408: restarting here, because after this point, nothing can fault for 409: the remainder of this instruction (the executor makes no stores 410: on behalf of an rtd): */ 411: ic->tme_m68k_ireg_a7 += TME_M68K_INSN_OP0(tme_uint32_t); 412: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32); 413: TME_M68K_INSN_OK; 414: } 415: 416: /* this can fault: */ 417: TME_M68K_INSN(tme_m68k_rtr) 418: { 419: TME_M68K_INSN_CANFAULT; 420: tme_m68k_pop16(ic, &ic->tme_m68k_ireg_memx16); 421: if (!TME_M68K_SEQUENCE_RESTARTING) { 422: ic->tme_m68k_ireg_ccr = ic->tme_m68k_ireg_memx8 & TME_M68K_FLAG_CCR; 423: } 424: tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32); 425: /* while the above pop can fault, we don't have to worry about 426: restarting here, because after this point, nothing can fault for 427: the remainder of this instruction (the executor makes no stores 428: on behalf of an rtr): */ 429: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32); 430: TME_M68K_INSN_OK; 431: } 432: 433: /* this can fault: */ 434: TME_M68K_INSN(tme_m68k_rts) 435: { 436: TME_M68K_INSN_CANFAULT; 437: tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32); 438: TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32); 439: TME_M68K_INSN_OK; 440: } 441: 442: /* this can fault: */ 443: TME_M68K_INSN(tme_m68k_jsr) 444: { 445: TME_M68K_INSN_CANFAULT; 446: tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_next); 447: TME_M68K_INSN_BRANCH(ic->_tme_m68k_ea_address); 448: TME_M68K_INSN_OK; 449: } 450: 451: /* this cannot fault: */ 452: TME_M68K_INSN(tme_m68k_jmp) 453: { 454: TME_M68K_INSN_BRANCH(ic->_tme_m68k_ea_address); 455: TME_M68K_INSN_OK; 456: } 457: 458: /* this cannot fault: */ 459: TME_M68K_INSN(tme_m68k_rte) 460: { 461: TME_M68K_INSN_PRIV; 462: ic->_tme_m68k_mode = TME_M68K_MODE_RTE; 463: TME_M68K_SEQUENCE_START; 464: tme_m68k_redispatch(ic); 465: } 466: 467: /* this cannot fault: */ 468: TME_M68K_INSN(tme_m68k_stop) 469: { 470: TME_M68K_INSN_PRIV; 471: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 472: ic->tme_m68k_ireg_sr = TME_M68K_INSN_SPECOP; 473: ic->_tme_m68k_mode = TME_M68K_MODE_STOP; 474: TME_M68K_SEQUENCE_START; 475: tme_m68k_redispatch(ic); 476: } 477: 478: /* this cannot fault: */ 479: TME_M68K_INSN(tme_m68k_priv) 480: { 1.1.1.3 ! root 481: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_PRIV); 1.1 root 482: } 483: 484: /* this can fault: */ 485: TME_M68K_INSN(tme_m68k_cmp2_chk2) 486: { 487: tme_uint32_t ireg; 488: unsigned int size_bytes, size_name, size_ireg; 489: tme_uint32_t uvalue, ulower, uupper; 490: tme_int32_t value, lower, upper; 491: 492: TME_M68K_INSN_CANFAULT; 493: 494: /* get the register to check and the operand size: */ 495: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 496: size_bytes = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 2); 497: size_ireg = 2 - size_bytes; 498: size_name = TME_M68K_SIZE_8 + size_bytes; 499: size_bytes = 1 << size_bytes; 500: 501: /* read in the two bounds: */ 502: (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMX32 << size_ireg); 503: if (!TME_M68K_SEQUENCE_RESTARTING) { 504: ic->_tme_m68k_ea_address += size_bytes; 505: } 506: (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMY32 << size_ireg); 507: 508: /* if we have an address register, sign-extend the bounds to 32 509: bits: */ 510: if (ireg >= TME_M68K_IREG_A0) { 511: if (size_name == TME_M68K_SIZE_8) { 512: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMX8)); 513: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMY8)); 514: } 515: else if (size_name == TME_M68K_SIZE_16) { 516: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMX16)); 517: ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMY16)); 518: } 519: size_bytes = sizeof(tme_uint32_t); 520: size_name = TME_M68K_SIZE_32; 521: } 522: 523: /* get the values to check: */ 524: switch (size_name) { 525: case TME_M68K_SIZE_8: 526: uvalue = ic->tme_m68k_ireg_uint8(ireg); 527: ulower = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMX8); 528: uupper = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMY8); 529: value = ic->tme_m68k_ireg_int8(ireg); 530: lower = ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMX8); 531: upper = ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMY8); 532: break; 533: case TME_M68K_SIZE_16: 534: uvalue = ic->tme_m68k_ireg_uint16(ireg); 535: ulower = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMX16); 536: uupper = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMY16); 537: value = ic->tme_m68k_ireg_int16(ireg); 538: lower = ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMX16); 539: upper = ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMY16); 540: break; 541: case TME_M68K_SIZE_32: 542: uvalue = ic->tme_m68k_ireg_uint32(ireg); 543: ulower = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMX32); 544: uupper = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMY32); 545: value = ic->tme_m68k_ireg_int32(ireg); 546: lower = ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32); 547: upper = ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32); 548: break; 549: default: abort(); 550: } 551: 552: /* do the comparison. if the value is out-of-bounds and this is 553: a chk2 instruction, trap: */ 554: ic->tme_m68k_ireg_ccr = (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 555: if (uvalue == ulower 556: || uvalue == uupper) { 557: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 558: } 559: else if ((ulower > uupper) 560: /* signed comparison: */ 561: ? (value < lower || value > upper) 562: /* unsigned comparison: */ 563: : (uvalue < ulower || uvalue > uupper)) { 564: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_C; 565: if (TME_M68K_INSN_OPCODE & TME_BIT(11)) { 1.1.1.3 ! root 566: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 567: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 ! root 568: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); 1.1 root 569: } 570: } 571: 572: TME_M68K_INSN_OK; 573: } 574: 575: TME_M68K_INSN(tme_m68k_callm) 576: { 577: /* TBD */ 578: abort(); 579: } 580: 581: TME_M68K_INSN(tme_m68k_rtm) 582: { 583: /* TBD */ 584: abort(); 585: } 586: 587: /* this cannot fault: */ 588: TME_M68K_INSN(tme_m68k_trapcc) 589: { 590: if (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) { 1.1.1.3 ! root 591: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 592: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 ! root 593: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP)); 1.1 root 594: } 595: TME_M68K_INSN_OK; 596: } 597: 598: /* the bitfield helper functions handle faults: */ 599: TME_M68K_INSN(tme_m68k_bfchg) 600: { 601: tme_uint32_t bf_value; 602: bf_value = tme_m68k_bitfield_read_unsigned(ic); 603: tme_m68k_bitfield_write_unsigned(ic, ~bf_value, FALSE); 604: TME_M68K_INSN_OK; 605: } 606: 607: /* the bitfield helper functions handle faults: */ 608: TME_M68K_INSN(tme_m68k_bfclr) 609: { 610: (void) tme_m68k_bitfield_read_unsigned(ic); 611: tme_m68k_bitfield_write_unsigned(ic, 0, FALSE); 612: TME_M68K_INSN_OK; 613: } 614: 615: /* the bitfield helper functions handle faults: */ 616: TME_M68K_INSN(tme_m68k_bfexts) 617: { 618: tme_int32_t bf_value; 619: bf_value = tme_m68k_bitfield_read_signed(ic); 620: ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)) 621: = bf_value; 622: TME_M68K_INSN_OK; 623: } 624: 625: /* the bitfield helper functions handle faults: */ 626: TME_M68K_INSN(tme_m68k_bfextu) 627: { 628: tme_uint32_t bf_value; 629: bf_value = tme_m68k_bitfield_read_unsigned(ic); 630: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)) 631: = bf_value; 632: TME_M68K_INSN_OK; 633: } 634: 635: /* the bitfield helper functions handle faults: */ 636: TME_M68K_INSN(tme_m68k_bfffo) 637: { 638: tme_int16_t specop; 639: tme_int32_t bf_offset; 640: unsigned int bf_width; 641: tme_uint32_t bf_value; 1.1.1.3 ! root 642: unsigned int bf_pos; 1.1 root 643: 644: /* get the bitfield offset from a data register or as an immediate: */ 645: specop = TME_M68K_INSN_SPECOP; 646: bf_offset = ((specop & TME_BIT(11)) 647: ? ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 6, 3)) 648: : (tme_int32_t) TME_FIELD_EXTRACTU(specop, 6, 5)); 649: 650: /* get the bitfield width: */ 651: bf_width = tme_m68k_bitfield_width(ic); 652: 653: /* get the bitfield value: */ 654: bf_value = tme_m68k_bitfield_read_unsigned(ic); 655: 1.1.1.3 ! root 656: /* find the first set bit: */ ! 657: for (bf_pos = 0, bf_value <<= (32 - bf_width); ! 658: bf_pos < bf_width && !(bf_value & 0x80000000); ! 659: bf_pos++, bf_value <<= 1); ! 660: 1.1 root 661: /* set the result: */ 662: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 12, 3)) 1.1.1.3 ! root 663: = bf_offset + bf_pos; 1.1 root 664: 665: TME_M68K_INSN_OK; 666: } 667: 668: /* the bitfield helper functions handle faults: */ 669: TME_M68K_INSN(tme_m68k_bfins) 670: { 671: tme_m68k_bitfield_write_unsigned(ic, 672: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 673: + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)), 674: TRUE); 675: TME_M68K_INSN_OK; 676: } 677: 678: /* the bitfield helper functions handle faults: */ 679: TME_M68K_INSN(tme_m68k_bfset) 680: { 681: (void) tme_m68k_bitfield_read_unsigned(ic); 682: tme_m68k_bitfield_write_unsigned(ic, 0xffffffff, FALSE); 683: TME_M68K_INSN_OK; 684: } 685: 686: /* the bitfield helper functions handle faults: */ 687: TME_M68K_INSN(tme_m68k_bftst) 688: { 689: (void) tme_m68k_bitfield_read_unsigned(ic); 690: TME_M68K_INSN_OK; 691: } 692: 693: /* this can fault: */ 694: TME_M68K_INSN(tme_m68k_pack) 695: { 696: int ireg_x, ireg_y; 697: tme_uint16_t value; 698: 699: TME_M68K_INSN_CANFAULT; 700: 701: /* get the two registers: */ 702: ireg_x = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 703: ireg_y = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 704: 705: /* if this is a memory pack: */ 706: if (TME_M68K_INSN_OPCODE & TME_BIT(3)) { 707: ireg_x += TME_M68K_IREG_A0; 708: ireg_y += TME_M68K_IREG_A0; 709: 710: /* do the predecrement read of two bytes: */ 711: if (!TME_M68K_SEQUENCE_RESTARTING) { 712: ic->tme_m68k_ireg_uint32(ireg_x) -= sizeof(tme_uint16_t); 713: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 714: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_x); 715: } 716: tme_m68k_read_memx16(ic); 717: 718: /* get the two bytes and add the extension: */ 719: value = ic->tme_m68k_ireg_memx16 + TME_M68K_INSN_SPECOP; 720: 721: /* do the predecrement write of one byte: */ 722: if (!TME_M68K_SEQUENCE_RESTARTING) { 723: ic->tme_m68k_ireg_uint32(ireg_y) -= sizeof(tme_uint8_t); 724: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 725: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_y); 726: ic->tme_m68k_ireg_memx8 = (tme_uint8_t) ((value & 0x0f) | (value >> 4)); 727: } 728: tme_m68k_write_memx8(ic); 729: } 730: 731: /* if this is a register pack: */ 732: else { 733: ireg_x += TME_M68K_IREG_D0; 734: ireg_y += TME_M68K_IREG_D0; 735: value = ic->tme_m68k_ireg_uint16(ireg_x << 1) + TME_M68K_INSN_SPECOP; 736: ic->tme_m68k_ireg_uint8(ireg_y << 2) = (tme_uint8_t) ((value & 0x0f) | (value >> 4)); 737: } 738: 739: TME_M68K_INSN_OK; 740: } 741: 742: /* this can fault: */ 743: TME_M68K_INSN(tme_m68k_unpk) 744: { 745: int ireg_x, ireg_y; 746: tme_uint16_t value; 747: 748: TME_M68K_INSN_CANFAULT; 749: 750: /* get the two registers: */ 751: ireg_x = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 752: ireg_y = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 753: 754: /* if this is a memory pack: */ 755: if (TME_M68K_INSN_OPCODE & TME_BIT(3)) { 756: ireg_x += TME_M68K_IREG_A0; 757: ireg_y += TME_M68K_IREG_A0; 758: 759: /* do the predecrement read of one byte: */ 760: if (!TME_M68K_SEQUENCE_RESTARTING) { 761: ic->tme_m68k_ireg_uint32(ireg_x) -= sizeof(tme_uint8_t); 762: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 763: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_x); 764: } 765: tme_m68k_read_memx8(ic); 766: 767: /* unpack the byte and add the extension: */ 768: value = ic->tme_m68k_ireg_memx8; 769: value = ((value & 0x0f) | ((value & 0xf0) << 4)) + TME_M68K_INSN_SPECOP; 770: 771: /* do the predecrement write of two bytes: */ 772: if (!TME_M68K_SEQUENCE_RESTARTING) { 773: ic->tme_m68k_ireg_uint32(ireg_y) -= sizeof(tme_uint16_t); 774: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 775: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_y); 776: ic->tme_m68k_ireg_memx16 = value; 777: } 778: tme_m68k_write_memx16(ic); 779: } 780: 781: /* if this is a register pack: */ 782: else { 783: ireg_x += TME_M68K_IREG_D0; 784: ireg_y += TME_M68K_IREG_D0; 785: value = ic->tme_m68k_ireg_uint8(ireg_x << 2); 786: value = ((value & 0x0f) | ((value & 0xf0) << 4)) + TME_M68K_INSN_SPECOP; 787: ic->tme_m68k_ireg_uint16(ireg_y << 1) = value; 788: } 789: 790: TME_M68K_INSN_OK; 791: } 792: 1.1.1.3 ! root 793: /* these just redispatch into one of the multiply or divide insns: */ ! 794: TME_M68K_INSN(tme_m68k_mull) ! 795: { ! 796: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { ! 797: tme_m68k_mulsl(ic, _op0, _op1); ! 798: } ! 799: else { ! 800: tme_m68k_mulul(ic, _op0, _op1); ! 801: } ! 802: } ! 803: TME_M68K_INSN(tme_m68k_divl) ! 804: { ! 805: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { ! 806: tme_m68k_divsl(ic, _op0, _op1); ! 807: } ! 808: else { ! 809: tme_m68k_divul(ic, _op0, _op1); ! 810: } ! 811: } ! 812: 1.1 root 813: #include "m68k-bus-auto.c" 814: 815: #include "m68k-insns-auto.c"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.