| /* Copyright 2009-2021 Free Software Foundation, Inc. |
| |
| This file is part of the Xilinx MicroBlaze simulator. |
| |
| This library is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, see <http://www.gnu.org/licenses/>. */ |
| |
| /* |
| * MICROBLAZE Instruction Set Architecture |
| * |
| * INSTRUCTION(NAME, |
| * OPCODE, |
| * TYPE, |
| * SEMANTICS) |
| * |
| */ |
| |
| INSTRUCTION(add, |
| 0x00, |
| INST_TYPE_RD_RA_RB, |
| CARRY = C_calc(RA, RB, 0); |
| RD = RA + RB; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsub, |
| 0x01, |
| INST_TYPE_RD_RA_RB, |
| CARRY = C_calc(RB, ~RA, 1); |
| RD = RB + ~RA + 1; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(addc, |
| 0x02, |
| INST_TYPE_RD_RA_RB, |
| CARRY = C_calc(RA, RB, C_rd); |
| RD = RA + RB + C_rd; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubc, |
| 0x03, |
| INST_TYPE_RD_RA_RB, |
| CARRY = C_calc(RB, ~RA, C_rd); |
| RD = RB + ~RA + C_rd; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(addk, |
| 0x04, |
| INST_TYPE_RD_RA_RB, |
| RD = RA + RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubk, |
| 0x05, |
| INST_TYPE_RD_RA_RB, |
| RD = RB + ~RA + 1; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(cmp, |
| 0x05, |
| INST_TYPE_RD_RA_RB, |
| { |
| int tmp_reg = RB + ~RA + 1; |
| if ((RB & 0x80000000) ^ (RA & 0x80000000)) { |
| tmp_reg = ((tmp_reg & 0x7fffffff) | (RB & 0x80000000)); |
| } |
| RD = tmp_reg; |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(cmpu, |
| 0x05, |
| INST_TYPE_RD_RA_RB, |
| { |
| int tmp_reg = RB + ~RA + 1; |
| if ((RB & 0x80000000) ^ (RA & 0x80000000)) { |
| tmp_reg = ((tmp_reg & 0x7fffffff) | (RA & 0x80000000)); |
| } |
| RD = tmp_reg; |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(addkc, |
| 0x06, |
| INST_TYPE_RD_RA_RB, |
| RD = RA + RB + C_rd; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubkc, |
| 0x07, |
| INST_TYPE_RD_RA_RB, |
| RD = RB + ~RA + C_rd; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(addi, |
| 0x08, |
| INST_TYPE_RD_RA_IMM, |
| CARRY = C_calc(RA, IMM, 0); |
| RD = RA + IMM; |
| TRACE_REGISTER (cpu, "r%i = r%i + %i", rd, ra, IMM); |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubi, |
| 0x09, |
| INST_TYPE_RD_RA_IMM, |
| CARRY = C_calc(IMM, ~RA, 1); |
| RD = IMM + ~RA + 1; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(addic, |
| 0x0A, |
| INST_TYPE_RD_RA_IMM, |
| CARRY = C_calc(RA, IMM, C_rd); |
| RD = RA + IMM + C_rd; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubic, |
| 0x0B, |
| INST_TYPE_RD_RA_IMM, |
| CARRY = C_calc(IMM, ~RA, C_rd); |
| RD = IMM + ~RA + C_rd; |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(addik, |
| 0x0C, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA + IMM; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubik, |
| 0x0D, |
| INST_TYPE_RD_RA_IMM, |
| RD = IMM + ~RA + 1; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(addikc, |
| 0x0E, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA + IMM + C_rd; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rsubikc, |
| 0x0F, |
| INST_TYPE_RD_RA_IMM, |
| RD = IMM + ~RA + C_rd; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(mul, |
| 0x10, |
| INST_TYPE_RD_RA_RB, |
| RD = RA * RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(bsrl, |
| 0x11, |
| INST_TYPE_RD_RA_RB, |
| RD = (unsigned_4)RA >> RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(bsra, |
| 0x11, |
| INST_TYPE_RD_RA_RB, |
| RD = (signed_4)RA >> RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(bsll, |
| 0x11, |
| INST_TYPE_RD_RA_RB, |
| RD = (unsigned_4)RA << RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(idiv, |
| 0x12, |
| INST_TYPE_RD_RA_RB, |
| RD = (signed_4) RB / (signed_4) RA; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(idivu, |
| 0x12, |
| INST_TYPE_RD_RA_RB, |
| RD = (unsigned_4) RB / (unsigned_4) RA; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(muli, |
| 0x18, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA * IMM; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(bsrli, |
| 0x19, |
| INST_TYPE_RD_RA_IMM5, |
| RD = (unsigned_4)RA >> (IMM & 0x1F); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(bsrai, |
| 0x19, |
| INST_TYPE_RD_RA_IMM5, |
| RD = (signed_4)RA >> (IMM & 0x1F); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(bslli, |
| 0x19, |
| INST_TYPE_RD_RA_IMM5, |
| RD = (unsigned_4)RA << (IMM & 0x1F); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(get, |
| 0x1b, |
| INST_TYPE_RD_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(put, |
| 0x1b, |
| INST_TYPE_R1_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(nget, |
| 0x1b, |
| INST_TYPE_RD_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(nput, |
| 0x1b, |
| INST_TYPE_R1_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(cget, |
| 0x1b, |
| INST_TYPE_RD_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(cput, |
| 0x1b, |
| INST_TYPE_R1_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(ncget, |
| 0x1b, |
| INST_TYPE_RD_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(ncput, |
| 0x1b, |
| INST_TYPE_R1_IMM12, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(microblaze_or, |
| 0x20, |
| INST_TYPE_RD_RA_RB, |
| RD = RA | RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(microblaze_and, |
| 0x21, |
| INST_TYPE_RD_RA_RB, |
| RD = RA & RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(microblaze_xor, |
| 0x22, |
| INST_TYPE_RD_RA_RB, |
| RD = RA ^ RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(andn, |
| 0x23, |
| INST_TYPE_RD_RA_RB, |
| RD = RA & ~RB; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sra, |
| 0x24, |
| INST_TYPE_RD_RA, |
| CARRY = (RA & 0x1); |
| RD = (int) (RA >> 1); |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(src, |
| 0x24, |
| INST_TYPE_RD_RA, |
| CARRY = (RA & 0x1); |
| RD = ((((int) (RA >> 1)) & 0x7FFFFFFF) | (unsigned_4)(C_rd << 31)); |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(srl, |
| 0x24, |
| INST_TYPE_RD_RA, |
| CARRY = (RA & 0x1); |
| RD = (unsigned_4) ((RA >> 1) & 0x7FFFFFFF); |
| C_wr(CARRY); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sext8, |
| 0x24, |
| INST_TYPE_RD_RA, |
| RD = MICROBLAZE_SEXT8(RA); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sext16, |
| 0x24, |
| INST_TYPE_RD_RA, |
| RD = MICROBLAZE_SEXT16(RA); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(wdc, |
| 0x24, |
| INST_TYPE_RA_RB, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(wic, |
| 0x24, |
| INST_TYPE_RA_RB, |
| PC += INST_SIZE) |
| |
| INSTRUCTION(mts, |
| 0x25, |
| INST_TYPE_SA_RA, |
| SA = RA; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(mfs, |
| 0x25, |
| INST_TYPE_RD_SA, |
| RD = SA; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(br, |
| 0x26, |
| INST_TYPE_RB, |
| PC += RB; |
| BRANCH) |
| |
| INSTRUCTION(brd, |
| 0x26, |
| INST_TYPE_RB, |
| PC += RB; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(brld, |
| 0x26, |
| INST_TYPE_RD_RB, |
| RD = PC; |
| PC += RB; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(bra, |
| 0x26, |
| INST_TYPE_RB, |
| PC = RB; |
| BRANCH) |
| |
| INSTRUCTION(brad, |
| 0x26, |
| INST_TYPE_RB, |
| PC = RB; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(brald, |
| 0x26, |
| INST_TYPE_RD_RB, |
| RD = PC; |
| PC = RB; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(microblaze_brk, |
| 0x26, |
| INST_TYPE_RD_RB, |
| RD = PC; |
| PC = RB; |
| MSR = MSR | BIP_MASK; |
| BRANCH) |
| |
| INSTRUCTION(beq, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA == 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(beqd, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA == 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(bne, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA != 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bned, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA != 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(blt, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA < 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bltd, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA < 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(ble, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA <= 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bled, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA <= 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(bgt, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA > 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bgtd, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA > 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(bge, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA >= 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bged, |
| 0x27, |
| INST_TYPE_RA_RB, |
| if (RA >= 0) { |
| PC += RB; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(ori, |
| 0x28, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA | IMM; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(andi, |
| 0x29, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA & IMM; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(xori, |
| 0x2A, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA ^ IMM; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(andni, |
| 0x2B, |
| INST_TYPE_RD_RA_IMM, |
| RD = RA & ~IMM; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(imm, |
| 0x2C, |
| INST_TYPE_IMM, |
| IMM_H = IMM_L; |
| PC += INST_SIZE) |
| |
| INSTRUCTION(rtsd, |
| 0x2D, |
| INST_TYPE_RA_IMM, |
| PC = RA + IMM; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(rtid, |
| 0x2D, |
| INST_TYPE_RA_IMM, |
| PC = RA + IMM; |
| MSR = MSR | INTR_EN_MASK; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(rtbd, |
| 0x2D, |
| INST_TYPE_RA_IMM, |
| PC = RA + IMM; |
| MSR = MSR & ~BIP_MASK; |
| BRANCH; |
| DELAY_SLOT;) |
| |
| INSTRUCTION(bri, |
| 0x2E, |
| INST_TYPE_IMM, |
| PC += IMM; |
| BRANCH) |
| |
| INSTRUCTION(brid, |
| 0x2E, |
| INST_TYPE_IMM, |
| PC += IMM; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(brlid, |
| 0x2E, |
| INST_TYPE_RD_IMM, |
| RD = PC; |
| PC += IMM; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(brai, |
| 0x2E, |
| INST_TYPE_IMM, |
| PC = IMM; |
| BRANCH) |
| |
| INSTRUCTION(braid, |
| 0x2E, |
| INST_TYPE_IMM, |
| PC = IMM; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(bralid, |
| 0x2E, |
| INST_TYPE_RD_IMM, |
| RD = PC; |
| PC = IMM; |
| BRANCH; |
| DELAY_SLOT) |
| |
| INSTRUCTION(brki, |
| 0x2E, |
| INST_TYPE_RD_IMM, |
| RD = PC; |
| PC = IMM; |
| MSR = MSR | BIP_MASK; |
| BRANCH) |
| |
| INSTRUCTION(beqi, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA == 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(beqid, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA == 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(bnei, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA != 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bneid, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA != 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(blti, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA < 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bltid, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA < 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(blei, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA <= 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bleid, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA <= 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(bgti, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA > 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bgtid, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA > 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(bgei, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA >= 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| }) |
| |
| INSTRUCTION(bgeid, |
| 0x2F, |
| INST_TYPE_RA_IMM, |
| if (RA >= 0) { |
| PC += IMM; |
| BRANCH; |
| } else { |
| PC += INST_SIZE; |
| } |
| DELAY_SLOT) |
| |
| INSTRUCTION(lbu, |
| 0x30, |
| INST_TYPE_RD_RA_RB, |
| RD = (MEM_RD_UBYTE(RA + RB)); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(lhu, |
| 0x31, |
| INST_TYPE_RD_RA_RB, |
| RD = (MEM_RD_UHALF((RA + RB) & ~0x1)); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(lw, |
| 0x32, |
| INST_TYPE_RD_RA_RB, |
| RD = (MEM_RD_WORD((RA + RB) & ~0x3)); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sb, |
| 0x34, |
| INST_TYPE_RD_RA_RB, |
| MEM_WR_BYTE(RA + RB, RD); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sh, |
| 0x35, |
| INST_TYPE_RD_RA_RB, |
| MEM_WR_HALF((RA + RB) & ~0x1, RD); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sw, |
| 0x36, |
| INST_TYPE_RD_RA_RB, |
| MEM_WR_WORD((RA + RB) & ~0x3, RD); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(lbui, |
| 0x38, |
| INST_TYPE_RD_RA_IMM, |
| RD = (MEM_RD_UBYTE(RA + IMM)); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(lhui, |
| 0x39, |
| INST_TYPE_RD_RA_IMM, |
| RD = (MEM_RD_UHALF((RA+IMM) & ~0x1)); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(lwi, |
| 0x3A, |
| INST_TYPE_RD_RA_IMM, |
| RD = (MEM_RD_WORD((RA+IMM) & ~0x3)); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(sbi, |
| 0x3C, |
| INST_TYPE_RD_RA_IMM, |
| MEM_WR_BYTE(RA + IMM, RD); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(shi, |
| 0x3D, |
| INST_TYPE_RD_RA_IMM, |
| MEM_WR_HALF((RA + IMM) & ~0x1, RD); |
| PC += INST_SIZE) |
| |
| INSTRUCTION(swi, |
| 0x3E, |
| INST_TYPE_RD_RA_IMM, |
| MEM_WR_WORD((RA + IMM) & ~0x3, RD); |
| PC += INST_SIZE) |