bool op_or(t_vm *vm, t_process *process, uint32_t const *args, uint8_t args_types) { uint32_t val; val = GET_VALUE(vm, process, args, args_types, 0) | GET_VALUE(vm, process, args, args_types, 1); SET_CARRY(process, val); if (args[2] >= 1 && args[2] <= REG_NUMBER) process->reg[args[2] - 1] = val; return (true); }
void MicroBlazeIss::step(void) { bool branch = 0xdeadbeef; int next_pc = 0xdeadbeef; /*\ * Local variable used to build the value send on the * interconnect. * It looks like endianness and byte enable are misteriously * interpreted, so each byte or half world is replicated to * avoid headaches \*/ uint32_t data; uint32_t addr; char ins_opcode; int ins_rd; int ins_ra; int ins_rb = 0xdeadbeef; int ins_imm = 0xdeadbeef; bool exception = false; /*\ * Setting exceptions in the correct priority order * Assumption: the value in the r_imm register is lost in case of * exception, even though this is not specified in the Xilinx doc. \*/ if (m_ibe) { r_esr = INSTRUCTION_BUS_ERROR_EXCEPTION; exception = true; } if (m_dbe) { r_esr = DATA_BUS_ERROR_EXCEPTION; r_ear = r_mem_addr; exception = true; } if (r_dbe) { r_esr = DATA_BUS_ERROR_EXCEPTION; r_ear = r_mem_addr; r_dbe = false; exception = true; } if (exception) { HANDLE_EXCEPTION; } /*\ * Cancel the instruction in the delay slot if any, * regardless of interruptions \*/ if (m_cancel) { m_cancel = false; m_delay = false; r_pc = r_npc; r_npc = r_pc + 4; return; } /*\ * Reset flags before executing a new instruction \*/ m_cancel = false; m_delay = false; /* Decode the current instruction */ IDecode(m_ir, &ins_opcode, &ins_rd, &ins_ra, &ins_rb, &ins_imm); #if MBDEBUG printf("%8s 0x%08x : \n", name().c_str(), r_pc); #endif switch (ins_opcode) { case OP_ADD: #if MBDEBUG printf("add r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + r_gpr[ins_rb]; SET_CARRY(r_gpr[ins_rd] < r_gpr[ins_ra]); next_pc = r_npc + 4; break; case OP_ADDC: #if MBDEBUG printf("addc r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + r_gpr[ins_rb] + GET_CARRY; SET_CARRY(r_gpr[ins_rd] < r_gpr[ins_ra]); next_pc = r_npc + 4; break; case OP_ADDK: #if MBDEBUG printf("addk r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + r_gpr[ins_rb]; next_pc = r_npc + 4; break; case OP_ADDKC: #if MBDEBUG printf("addkc r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + r_gpr[ins_rb] + GET_CARRY; next_pc = r_npc + 4; break; case OP_ADDI: #if MBDEBUG printf("addi r%d, r%d, 0x%x\n", ins_rd, ins_ra, ins_imm); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + IMM_OP; SET_CARRY(r_gpr[ins_rd] < r_gpr[ins_ra]); next_pc = r_npc + 4; break; case OP_ADDIC: #if MBDEBUG printf("addic r%d, r%d, 0x%x\n", ins_rd, ins_ra, ins_imm); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + IMM_OP + GET_CARRY; SET_CARRY(r_gpr[ins_rd] < r_gpr[ins_ra]); next_pc = r_npc + 4; break; case OP_ADDIK: #if MBDEBUG printf("addik r%d, r%d, 0x%x\n", ins_rd, ins_ra, ins_imm); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + IMM_OP; next_pc = r_npc + 4; break; case OP_ADDIKC: #if MBDEBUG printf("addikc r%d, r%d, 0x%x\n", ins_rd, ins_ra, ins_imm); #endif r_gpr[ins_rd] = r_gpr[ins_ra] + IMM_OP + GET_CARRY; next_pc = r_npc + 4; break; case OP_AND: #if MBDEBUG printf("and r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif r_gpr[ins_rd] = r_gpr[ins_ra] & r_gpr[ins_rb]; next_pc = r_npc + 4; break; case OP_ANDI: #if MBDEBUG printf("andi r%d, r%d, 0x%x\n", ins_rd, ins_ra, ins_imm); #endif r_gpr[ins_rd] = r_gpr[ins_ra] & IMM_OP; next_pc = r_npc + 4; break; case OP_ANDN: #if MBDEBUG printf("andn r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif r_gpr[ins_rd] = r_gpr[ins_ra] & ~r_gpr[ins_rb]; next_pc = r_npc + 4; break; case OP_ANDNI: #if MBDEBUG printf("andni r%d, r%d, 0x%x\n", ins_rd, ins_ra, ins_imm); #endif r_gpr[ins_rd] = r_gpr[ins_ra] & ~IMM_OP; next_pc = r_npc + 4; break; case OP_BRNC: switch (ins_rd & 0xf) { case 0x0:// for beq #if MBDEBUG printf("beq%s r%d, r%d\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_rb); #endif branch = r_gpr[ins_ra] == 0; break; case 0x1:// for bne #if MBDEBUG printf("bne%s r%d, r%d\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_rb); #endif branch = r_gpr[ins_ra] != 0; break; case 0x2:// for blt #if MBDEBUG printf("blt%s r%d, r%d\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_rb); #endif branch = (int32_t)r_gpr[ins_ra] < 0; break; case 0x3:// for ble #if MBDEBUG printf("ble%s r%d, r%d\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_rb); #endif branch = (int32_t)r_gpr[ins_ra] <= 0; break; case 0x4:// for bgt #if MBDEBUG printf("bgt%s r%d, r%d\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_rb); #endif branch = (int32_t)r_gpr[ins_ra] > 0; break; case 0x5:// for bge #if MBDEBUG printf("bge%s r%d, r%d\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_rb); #endif branch = (int32_t)r_gpr[ins_ra] >= 0; break; default: printf("brnc has some errors, please check\n"); break; } next_pc = r_pc + (!branch ? 8 : r_gpr[ins_rb]); if (!(ins_rd & 0x10) && branch) m_cancel = true; break; case OP_BRNI: switch (ins_rd & 0xf) { case 0x0:// for beqi #if MBDEBUG printf("beqi%s r%d, 0x%x\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_imm); #endif branch = r_gpr[ins_ra] == 0; break; case 0x1:// for bnei #if MBDEBUG printf("bnei%s r%d, 0x%x\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_imm); #endif branch = r_gpr[ins_ra] != 0; break; case 0x2:// for blti #if MBDEBUG printf("blti%s r%d, 0x%x\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_imm); #endif branch = (int32_t)r_gpr[ins_ra] < 0; break; case 0x3:// for blei #if MBDEBUG printf("blei%s r%d, 0x%x\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_imm); #endif branch = (int32_t)r_gpr[ins_ra] <= 0; break; case 0x4:// for bgti #if MBDEBUG printf("bgti%s r%d, 0x%x\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_imm); #endif branch = (int32_t)r_gpr[ins_ra] > 0; break; case 0x5:// for bgei #if MBDEBUG printf("bgei%s r%d, 0x%x\n", ins_rd & 0x10 ? "d" : "", ins_ra, ins_imm); #endif branch = (int32_t)r_gpr[ins_ra] >= 0; break; default: printf("brni has some errors, please check\n"); break; } // + seems to have precedence over ?: finally :) next_pc = r_pc + (!branch ? 8 : IMM_OP); if (!(ins_rd & 0x10) && branch) m_cancel = true; break; case OP_BR://br bra brd brad brld brald if (ins_ra & 0x04) r_gpr[ins_rd] = r_pc; if (ins_ra & 0x08) next_pc = r_gpr[ins_rb]; else next_pc = r_pc + r_gpr[ins_rb]; if (!(ins_ra & 0x10)) { // Delay slot m_cancel = true; if ((ins_ra & 0x1F) == 0x0C) // it is a brk r_msr |= MSR_BIP; } #if MBDEBUG { char a, l, d, b; l = ins_ra & 0x04; a = ins_ra & 0x08; d = ins_ra & 0x10; b = (ins_ra & 0x1F) == 0x0C; if (b) printf("brk r%d, r%d\n", ins_rd, ins_rb); else if (!l) printf("br%s%s r%d\n", a ? "a" : "", d ? "d" : "", ins_rb); else printf("br%sl%s r%d, r%d\n", a ? "a" : "", d ? "d" : "", ins_rd, ins_rb); } #endif break; case OP_BRI://bri brai brid braid brlid bralid if (ins_ra & 0x04) r_gpr[ins_rd] = r_pc; if (ins_ra & 0x08) // for BRA next_pc = IMM_OP; else next_pc = r_pc + IMM_OP; if (!(ins_ra & 0x10)) { // Delay slot m_cancel = true; if ((ins_ra & 0x1F) == 0x0C) // it is a brki r_msr |= MSR_BIP; } #if MBDEBUG { char a, l, d, b; l = ins_ra & 0x04; a = ins_ra & 0x08; d = ins_ra & 0x10; b = (ins_ra & 0x1F) == 0x0C; if (b) printf("brki r%d, 0x%x\n", ins_rd, ins_imm); else if (!l) printf("br%si%s 0x%x\n", a ? "a" : "", d ? "d" : "", ins_imm); else printf("br%sli%s r%d, 0x%x\n", a ? "a" : "", d ? "d" : "", ins_rd, ins_imm); } #endif break; case OP_BS: if (ins_imm & 0x400) { // S == 1, left shift r_gpr[ins_rd] = r_gpr[ins_ra] << (r_gpr[ins_rb] & 0x1F); #if MBDEBUG printf("bsll r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif } else { // S = 0, right shift if (ins_imm & 0x200) { // T == 1, arithmetic shift #if MBDEBUG printf("bsra r%d, r%d, r%d\n", ins_rd, ins_ra, ins_rb); #endif if (r_gpr[ins_rb] & 0x1F) { // operand not null r_gpr[ins_rd] = ((int32_t)r_gpr[ins_ra]) >> (r_gpr[ins_rb] & 0x1F); } else { r_gpr[ins_rd] = r_gpr[ins_ra]; } } else {