blob: c811dce01194b12649ae43d8193d06425fa964bd [file] [log] [blame]
/* 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)