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

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