Annotation of tme/ic/m68k/m68k-insns.c, revision 1.1.1.4

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"

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.