Annotation of nono/util/runx/m680x0.cpp, revision 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.