/* Copyright 2009-2024 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)