Annotation of nono/util/runx/m680x0.cpp, revision 1.1.1.1

1.1       root        1: // vi:set ts=4:
                      2: 
                      3: //
                      4: // nono
                      5: // Copyright (C) 2024 nono project
                      6: // Licensed under nono-license.txt
                      7: //
                      8: 
                      9: #include "runx.h"
                     10: 
                     11: #define CCR_X  (0x0010)
                     12: #define CCR_N  (0x0008)
                     13: #define CCR_Z  (0x0004)
                     14: #define CCR_V  (0x0002)
                     15: #define CCR_C  (0x0001)
                     16: 
                     17: #define SUPERVISOR_OP()    do {    \
                     18:    if ((emul.sr & 0x2000) == 0) \
                     19:        goto unpriv;    \
                     20: } while (0)
                     21: 
                     22: #define push2(data)    do {    \
                     23:    RegA(7) -= 2;   \
                     24:    writemem2(RegA(7), (data)); \
                     25: } while (0)
                     26: 
                     27: #define push4(data)    do {    \
                     28:    RegA(7) -= 4;   \
                     29:    writemem4(RegA(7), (data)); \
                     30: } while (0)
                     31: 
                     32: static uint32 exception_common(struct reg *, uint32, uint32, uint32);
                     33: 
                     34: #define pop2() ({  \
                     35:    uint32 data_ = readmem2(RegA(7));   \
                     36:    RegA(7) += 2;   \
                     37:    data_;  \
                     38: })
                     39: #define pop4() ({  \
                     40:    uint32 data_ = readmem4(RegA(7));   \
                     41:    RegA(7) += 4;   \
                     42:    data_;  \
                     43: })
                     44: 
                     45: // MOVE.* 系の CCR をセットする共通部分。
                     46: static void
                     47: acc_move(struct reg *reg, bool z, bool n)
                     48: {
                     49:    RegCCR &= ~(CCR_N | CCR_Z | CCR_V | CCR_C);
                     50:    if (z)
                     51:        RegCCR |= CCR_Z;
                     52:    if (n)
                     53:        RegCCR |= CCR_N;
                     54: }
                     55: 
                     56: // MOVE.B 系の CCR をセットする。
                     57: static void
                     58: acc_move_1(struct reg *reg, uint32 data)
                     59: {
                     60:    bool z = ((data & 0xff) == 0);
                     61:    bool n = (data & 0x80);
                     62:    acc_move(reg, z, n);
                     63: }
                     64: 
                     65: // MOVE.L 系の CCR をセットする。
                     66: static void
                     67: acc_move_4(struct reg *reg, uint32 data)
                     68: {
                     69:    bool z = (data == 0);
                     70:    bool n = (data & 0x8000'0000);
                     71:    acc_move(reg, z, n);
                     72: }
                     73: 
                     74: // スタックフレームフォーマット0 の例外を起こす。
                     75: // pc はスタックに積む PC (例外ごとにこの命令か次の命令かが違う)。
                     76: uint32
                     77: exception_format0(struct reg *reg, uint32 vector, uint32 pc)
                     78: {
                     79:    return exception_common(reg, 0, vector, pc);
                     80: }
                     81: 
                     82: // スタックフレームフォーマット2 の例外を起こす。
                     83: uint32
                     84: exception_format2(struct reg *reg, uint32 vector)
                     85: {
                     86:    // XXX ここに積む INSTRUCTION ADDRESS は今の所取り出す方法がない。
                     87:    // たぶん見てないのでへーきへーき。
                     88:    push4(RegPC - 2);
                     89:    return exception_common(reg, 2, vector, RegPC);
                     90: }
                     91: 
                     92: static uint32
                     93: exception_common(struct reg *reg, uint32 frame, uint32 vector, uint32 pc)
                     94: {
                     95:    // 本当はスタックに積む前だが、ここでは影響ない。
                     96:    SetSR(GetSR | 0x2000);
                     97: 
                     98:    push2((frame << 12) | (vector << 2));
                     99:    push4(pc);
                    100:    push2(GetSR);
                    101: 
                    102:    uint32 addr = readmem4(emul.vbr + (vector << 2));
                    103:    return addr;
                    104: }
                    105: 
                    106: // inst は命令の1ワード目 (16bit 下詰め)。
                    107: // 戻り値は更新した nextpc。
                    108: uint32
                    109: exec_op(pid_t pid, struct reg *reg, int signo, uint32 inst)
                    110: {
                    111:    uint32 inst2;
                    112:    uint32 addr;
                    113:    uint32 data;
                    114:    uint n;
                    115:    uint m;
                    116:    uint oplen;
                    117: 
                    118:    oplen = 2;
                    119:    switch (inst) {
                    120:     case 0x007c:   // ori.w #imm,sr
                    121:        SUPERVISOR_OP();
                    122: 
                    123:        data = readmem2(RegPC + 2);
                    124:        TRACE(RegPC, "ori.w #$%04x,sr", data);
                    125:        data |= GetSR;
                    126:        SetSR(data);
                    127:        oplen = 4;
                    128:        break;
                    129: 
                    130:     case 0x06fa:   // callm
                    131:        TRACE(RegPC, "callm");
                    132:        return exception_format0(reg, 4, RegPC);
                    133: 
                    134:     case 0x21c9:   // move.l an,abs.w
                    135:        n = inst & 7;
                    136:        addr = (int32)(int16)readmem2(RegPC + 2);
                    137:        TRACE(RegPC, "move.l a%u,$%04x.w", n, addr);
                    138:        data = RegA(n);
                    139:        acc_move_4(reg, data);
                    140:        writemem4(addr, data);
                    141:        oplen = 4;
                    142:        break;
                    143: 
                    144:     case 0x21df:   // move.l (an)+,abs.w
                    145:        n = inst & 7;
                    146:        addr = (int32)(int16)readmem2(RegPC + 2);
                    147:        TRACE(RegPC, "move.l (a%u)+,$%04x.w", n, addr);
                    148:        data = readmem4(RegA(n));
                    149:        acc_move_4(reg, data);
                    150:        writemem4(addr, data);
                    151:        RegA(n) += 4;
                    152:        oplen = 4;
                    153:        break;
                    154: 
                    155:     case 0x2855:   // movea.l (an),am
                    156:        n = inst & 7;
                    157:        m = (inst >> 9) & 7;
                    158:        TRACE(RegPC, "move.l (a%u),a%u", n, m);
                    159:        data = readmem4(RegA(n));
                    160:        RegA(m) = data;
                    161:        break;
                    162: 
                    163:     case 0x2a88:   // move.l an,(am)
                    164:     case 0x2a89:
                    165:     case 0x2a8a:
                    166:     case 0x2a8b:
                    167:     case 0x2a8c:
                    168:     case 0x2a8d:
                    169:     case 0x2a8e:
                    170:     case 0x2a8f:
                    171:        n = inst & 7;
                    172:        m = (inst >> 9) & 7;
                    173:        TRACE(RegPC, "move.l a%u,(a%u)", n, m);
                    174:        data = RegA(n);
                    175:        acc_move_4(reg, data);
                    176:        writemem4(RegA(m), data);
                    177:        break;
                    178: 
                    179:     case 0x2f38:   // move.l abs.w,-(an)
                    180:        n = (inst >> 9) & 7;
                    181:        addr = (int32)(int16)readmem2(RegPC + 2);
                    182:        TRACE(RegPC, "move.l $%04x.w,-(a%u)", addr, n);
                    183:        data = readmem4(addr);
                    184:        acc_move_4(reg, data);
                    185:        RegA(n) -= 4;
                    186:        writemem4(RegA(n), data);
                    187:        oplen = 4;
                    188:        break;
                    189: 
                    190:     case 0x40c0:   // move.w sr,dn
                    191:        n = inst & 7;
                    192:        if ((GetSR & 0x2000)) {
                    193:            TRACE(RegPC, "move.w sr,d%u", n);
                    194:            data = GetSR;
                    195:            RegD(n) = (RegD(n) & 0xffff0000) | data;
                    196:        } else {
                    197:            // Human68k が move from sr を move from ccr に書き換えて
                    198:            // この命令から再実行。
                    199:            TRACE(RegPC, "Patch move.w sr,d%u -> move.w ccr,d%u", n, n);
                    200:            writemem2(RegPC, inst | 0x0200);
                    201:            oplen = 0;
                    202:        }
                    203:        break;
                    204: 
                    205:     case 0x40e0:
                    206:     case 0x40e1:
                    207:     case 0x40e2:
                    208:     case 0x40e3:
                    209:     case 0x40e4:
                    210:     case 0x40e5:
                    211:     case 0x40e6:
                    212:     case 0x40e7:   // move.w sr,(a7)
                    213:        SUPERVISOR_OP();
                    214: 
                    215:        n = inst & 7;
                    216:        TRACE(RegPC, "move.w sr,(a%u)", n);
                    217:        addr = RegA(n);
                    218:        data = GetSR;
                    219:        writemem2(addr, data);
                    220:        break;
                    221: 
                    222:     case 0x46df:   // move.w (a7)+,sr
                    223:        SUPERVISOR_OP();
                    224: 
                    225:        n = inst & 7;
                    226:        TRACE(RegPC, "move.w (a%u)+,sr", n);
                    227:        addr = RegA(n);
                    228:        RegA(n) += 2;
                    229:        data = readmem2(addr);
                    230:        SetSR(data);
                    231:        break;
                    232: 
                    233:     case 0x4e73:   // rte
                    234:     {
                    235:        uint32 sr = pop2();
                    236:        uint32 pc = pop4();
                    237:        uint32 frame = pop2();
                    238:        TRACE(RegPC, "rte (frame=$%x, retpc=$%06x)", frame, pc);
                    239:        switch (frame >> 12) {
                    240:         case 0:
                    241:            SetSR(sr);
                    242:            return pc;
                    243: 
                    244:         case 2:
                    245:            // +08.L INSTRUCTION ADDRESS を読み捨てる
                    246:            RegA(7) += 4;
                    247:            SetSR(sr);
                    248:            return pc;
                    249: 
                    250:         default:
                    251:            errx(1, "%06x: rte: Unimplemented format $%x", RegPC, frame);
                    252:            break;
                    253:        }
                    254:        break;
                    255:     }
                    256: 
                    257:     case 0x4e7a:
                    258:        inst2 = readmem2(RegPC + 2);
                    259:        n = inst2 >> 12;
                    260:        switch (inst2 & 0xfff) {
                    261:         case 0x0801:
                    262:            // movec.l vbr,d0
                    263:            TRACE(RegPC, "movec.l vbr,%c%u", (n < 8) ? 'd' : 'a', n & 7);
                    264:            RegR(n) = emul.vbr;
                    265:            break;
                    266: 
                    267:         case 0x0802:
                    268:            // movec.l caar,d0
                    269:            TRACE(RegPC, "movec.l caar,%c%u", (n < 8) ? 'd' : 'a', n & 7);
                    270:            RegR(n) = emul.caar;
                    271:            break;
                    272: 
                    273:         default:
                    274:            warnx("%06x: Illegal instruction %04x %04x", RegPC, inst, inst2);
                    275:            return -1;
                    276:        }
                    277:        oplen = 4;
                    278:        break;
                    279: 
                    280:     case 0xf200 ... 0xf23f:    // FPU
                    281:        if (signo == SIGILL) {
                    282:            inst2 = readmem2(RegPC + 2);
                    283:            TRACE(RegPC, "Illegal FP instruction %04x %04x", inst, inst2);
                    284:            return exception_format0(reg, 11, RegPC);
                    285:        } else {
                    286:            // default へ
                    287:        }
                    288:        // FALLTHROUGH
                    289: 
                    290:     default:
                    291:        if (signo == SIGILL) {
                    292:            warnx("%06x: Illegal instruction %04x", RegPC, inst);
                    293:        } else {
                    294:            // SIGSEGV なら fault address を取り出して表示。
                    295:            struct ptrace_siginfo psi;
                    296:            if (ptrace(PT_GET_SIGINFO, pid, &psi, sizeof(psi)) < 0) {
                    297:                warn("ptrace(PT_GET_SIGINFO)");
                    298:            }
                    299:            warnx("%06x: SIGSEGV caught (instruction %04x, address $%06x)",
                    300:                RegPC, inst, (uint)(uintptr_t)psi.psi_siginfo.si_addr);
                    301:        }
                    302:        return -1;
                    303:    }
                    304: 
                    305:    return RegPC + oplen;
                    306: 
                    307:  unpriv:
                    308:    warnx("%06x: Unprivledged instruction %04x", RegPC, inst);
                    309:    return -1;
                    310: }

unix.superglobalmegacorp.com

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