void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) { int flags; uint32_t src; uint32_t dest; uint32_t tmp; #define HIGHBIT 0x80000000u #define SET_NZ(x) do { \ if ((x) == 0) \ flags |= CCF_Z; \ else if ((int32_t)(x) < 0) \ flags |= CCF_N; \ } while (0) #define SET_FLAGS_SUB(type, utype) do { \ SET_NZ((type)dest); \ tmp = dest + src; \ if ((utype) tmp < (utype) src) \ flags |= CCF_C; \ if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \ flags |= CCF_V; \ } while (0) flags = 0; src = env->cc_src; dest = env->cc_dest; switch (cc_op) { case CC_OP_FLAGS: flags = dest; break; case CC_OP_LOGIC: SET_NZ(dest); break; case CC_OP_ADD: SET_NZ(dest); if (dest < src) flags |= CCF_C; tmp = dest - src; if (HIGHBIT & (src ^ dest) & ~(tmp ^ src)) flags |= CCF_V; break; case CC_OP_SUB: SET_FLAGS_SUB(int32_t, uint32_t); break; case CC_OP_CMPB: SET_FLAGS_SUB(int8_t, uint8_t); break; case CC_OP_CMPW: SET_FLAGS_SUB(int16_t, uint16_t); break; case CC_OP_ADDX: SET_NZ(dest); if (dest <= src) flags |= CCF_C; tmp = dest - src - 1; if (HIGHBIT & (src ^ dest) & ~(tmp ^ src)) flags |= CCF_V; break; case CC_OP_SUBX: SET_NZ(dest); tmp = dest + src + 1; if (tmp <= src) flags |= CCF_C; if (HIGHBIT & (tmp ^ dest) & (tmp ^ src)) flags |= CCF_V; break; case CC_OP_SHIFT: SET_NZ(dest); if (src) flags |= CCF_C; break; default: cpu_abort(env, "Bad CC_OP %d", cc_op); } env->cc_op = CC_OP_FLAGS; env->cc_dest = flags; }
int arch_pdp11_translate_instr(cpu_t *cpu, addr_t pc, BasicBlock *bb) { uint16_t opcode = cpu->RAM[pc]; //LOG("%s:%d PC=$%04X\n", __func__, __LINE__, pc); switch (get_instr(opcode)) { /* flags */ case INSTR_CLC: LET1(cpu->ptr_C, FALSE); break; case INSTR_CLD: LET1(ptr_D, FALSE); break; case INSTR_CLI: LET1(ptr_I, FALSE); break; case INSTR_CLV: LET1(cpu->ptr_V, FALSE); break; case INSTR_SEC: LET1(cpu->ptr_C, TRUE); break; case INSTR_SED: LET1(ptr_D, TRUE); break; case INSTR_SEI: LET1(ptr_I, TRUE); break; /* register transfer */ case INSTR_TAX: SET_NZ(LET(X,R(A))); break; case INSTR_TAY: SET_NZ(LET(Y,R(A))); break; case INSTR_TXA: SET_NZ(LET(A,R(X))); break; case INSTR_TYA: SET_NZ(LET(A,R(Y))); break; case INSTR_TSX: SET_NZ(LET(X,R(S))); break; case INSTR_TXS: SET_NZ(LET(S,R(X))); break; /* load */ case INSTR_LDA: SET_NZ(LET(A,OPERAND)); break; case INSTR_LDX: SET_NZ(LET(X,OPERAND)); break; case INSTR_LDY: SET_NZ(LET(Y,OPERAND)); break; /* store */ case INSTR_STA: STORE(R(A),LOPERAND); break; case INSTR_STX: STORE(R(X),LOPERAND); break; case INSTR_STY: STORE(R(Y),LOPERAND); break; /* stack */ case INSTR_PHA: PUSH(R(A)); break; case INSTR_PHP: PUSH(arch_flags_encode(cpu, bb)); break; case INSTR_PLA: SET_NZ(LET(A,PULL)); break; case INSTR_PLP: arch_flags_decode(cpu, PULL, bb); break; /* shift */ case INSTR_ASL: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, false)); break; case INSTR_LSR: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, false)); break; case INSTR_ROL: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, true)); break; case INSTR_ROR: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, true)); break; /* bit logic */ case INSTR_AND: SET_NZ(LET(A,AND(R(A),OPERAND))); break; case INSTR_ORA: SET_NZ(LET(A,OR(R(A),OPERAND))); break; case INSTR_EOR: SET_NZ(LET(A,XOR(R(A),OPERAND))); break; case INSTR_BIT: SET_NZ(OPERAND); break; /* arithmetic */ case INSTR_ADC: SET_NZ(ADC(ptr_A, ptr_A, OPERAND, true, false)); break; case INSTR_SBC: SET_NZ(ADC(ptr_A, ptr_A, COM(OPERAND), true, false)); break; case INSTR_CMP: SET_NZ(ADC(NULL, ptr_A, COM(OPERAND), false, true)); break; case INSTR_CPX: SET_NZ(ADC(NULL, ptr_X, COM(OPERAND), false, true)); break; case INSTR_CPY: SET_NZ(ADC(NULL, ptr_Y, COM(OPERAND), false, true)); break; /* increment/decrement */ case INSTR_INX: SET_NZ(LET(X,INC(R(X)))); break; case INSTR_INY: SET_NZ(LET(Y,INC(R(Y)))); break; case INSTR_DEX: SET_NZ(LET(X,DEC(R(X)))); break; case INSTR_DEY: SET_NZ(LET(Y,DEC(R(Y)))); break; case INSTR_INC: SET_NZ(STORE(INC(OPERAND),LOPERAND)); break; case INSTR_DEC: SET_NZ(STORE(DEC(OPERAND),LOPERAND)); break; /* control flow */ case INSTR_JMP: if (get_addmode(opcode) == ADDMODE_IND) { Value *v = LOAD_RAM16(CONST32(OPERAND_16)); new StoreInst(v, cpu->ptr_PC, bb); } break; case INSTR_JSR: PUSH16(pc+2); break; case INSTR_RTS: STORE(ADD(PULL16, CONST16(1)), cpu->ptr_PC); break; /* branch */ case INSTR_BEQ: case INSTR_BNE: case INSTR_BCS: case INSTR_BCC: case INSTR_BMI: case INSTR_BPL: case INSTR_BVS: case INSTR_BVC: break; /* other */ case INSTR_NOP: break; case INSTR_BRK: arch_6502_trap(cpu, pc, bb); break; case INSTR_RTI: arch_6502_trap(cpu, pc, bb); break; case INSTR_XXX: arch_6502_trap(cpu, pc, bb); break; } return get_length(get_addmode(opcode)); }