package elw.dp.mips;
public class Alu {
protected static Integer s32(long unsigned) {
return (int) unsigned;
}
/*
* switches from 32bit signed to 64bit signed holding same bit sequence
* treated as 32bit unsigned
*/
protected static long u32(final int signed) {
return (long) signed & 0xFFFFFFFFL;
}
/*
* switches from 32bit signed to 32bit signed holding value of 16
* least significant bits treated as unsigned
*/
protected static int u16(final int signed) {
return (int) signed & 0x0000FFFF;
}
@InstructionDesc(
syntax = "addu $d, $s, $t",
template = "000000ssssstttttddddd00000100001",
writeRegs = "$d",
unsigned = true
)
public void addu(final InstructionContext ctx) {
ctx.setD(s32(u32(ctx.getS()) + u32(ctx.getT())));
ctx.advPc();
}
@InstructionDesc(
syntax = "add $d, $s, $t",
template = "000000ssssstttttddddd00000100000",
writeRegs = "$d"
)
public void add(final InstructionContext ctx) {
ctx.setD(ctx.getS() + ctx.getT());
ctx.advPc();
}
@InstructionDesc(
syntax = "addi $t, $s, imm16",
template = "001000ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void addi(final InstructionContext ctx) {
ctx.setT(ctx.getS() + ctx.getI16());
ctx.advPc();
}
@InstructionDesc(
syntax = "addiu $t, $s, imm16",
template = "001001ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t",
unsigned = true
)
public void addiu(final InstructionContext ctx) {
ctx.setT(ctx.getS() + u16(ctx.getI16()));
ctx.advPc();
}
@InstructionDesc(
syntax = "and $d, $s, $t",
template = "000000ssssstttttddddd00000100100",
writeRegs = "$d"
)
public void and(final InstructionContext ctx) {
ctx.setD(ctx.getS() & ctx.getT());
ctx.advPc();
}
@InstructionDesc(
syntax = "andi $t, $s, imm16",
template = "001100ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void andi(final InstructionContext ctx) {
ctx.setT(ctx.getS() & ctx.getI16());
ctx.advPc();
}
@InstructionDesc(
syntax = "beq $s, $t, addr16",
template = "000100ssssstttttiiiiiiiiiiiiiiii",
writeRegs = ""
)
public void beq(final InstructionContext ctx) {
if (ctx.getS() == ctx.getT()) {
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "bgez $s, addr16",
template = "000001sssss00001iiiiiiiiiiiiiiii",
writeRegs = ""
)
public void bgez(final InstructionContext ctx) {
if (ctx.getS() >= 0) {
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "bgezal $s, addr16",
template = "000001sssss10001iiiiiiiiiiiiiiii",
writeRegs = ""
)
public void bgezal(final InstructionContext ctx) {
if (ctx.getS() >= 0) {
ctx.storeRa();
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "bgtz $s, addr16",
template = "000111sssss00000iiiiiiiiiiiiiiii",
writeRegs = ""
)
public void bgtz(final InstructionContext ctx) {
if (ctx.getS() > 0) {
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "blez $s, addr16",
template = "000110sssss00000iiiiiiiiiiiiiiii",
writeRegs = ""
)
public void blez(final InstructionContext ctx) {
if (ctx.getS() <= 0) {
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "bltz $s, addr16",
template = "000001sssss00000iiiiiiiiiiiiiiii",
writeRegs = ""
)
public void bltz(final InstructionContext ctx) {
if (ctx.getS() < 0) {
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "bltzal $s, addr16",
template = "000001sssss10000iiiiiiiiiiiiiiii",
writeRegs = ""
)
public void bltzal(final InstructionContext ctx) {
if (ctx.getS() < 0) {
ctx.storeRa();
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "bne $s, $t, addr16",
template = "000101ssssstttttiiiiiiiiiiiiiiii",
writeRegs = ""
)
public void bne(final InstructionContext ctx) {
if (ctx.getS() != ctx.getT()) {
ctx.advPc(ctx.getI16() << 2);
} else {
ctx.advPc();
}
}
@InstructionDesc(
syntax = "divu $s, $t",
template = "000000sssssttttt0000000000011011",
writeRegs = "",
unsigned = true
)
public void divu(final InstructionContext ctx) {
final long s = u32(ctx.getS());
final long t = u32(ctx.getT());
ctx.getRegisters().setReg(Reg.lo, s32(s / t));
ctx.getRegisters().setReg(Reg.hi, s32(s % t));
ctx.advPc();
}
@InstructionDesc(
syntax = "div $s, $t",
template = "000000sssssttttt0000000000011010",
writeRegs = ""
)
public void div(final InstructionContext ctx) {
final int s = ctx.getS();
final int t = ctx.getT();
ctx.getRegisters().setReg(Reg.lo, s / t);
ctx.getRegisters().setReg(Reg.hi, s % t);
ctx.advPc();
}
@InstructionDesc(
syntax = "j addr26",
template = "000010iiiiiiiiiiiiiiiiiiiiiiiiii",
writeRegs = ""
)
public void j(final InstructionContext ctx) {
final Registers regs = ctx.getRegisters();
regs.setReg(Reg.pc, regs.getReg(Reg.pc) & 0xF0000000 | ctx.getI26() << 2);
}
@InstructionDesc(
syntax = "jal addr26",
template = "000011iiiiiiiiiiiiiiiiiiiiiiiiii",
writeRegs = ""
)
public void jal(final InstructionContext ctx) {
final Registers regs = ctx.getRegisters();
ctx.storeRa();
regs.setReg(Reg.pc, regs.getReg(Reg.pc) & 0xF0000000 | ctx.getI26() << 2);
}
@InstructionDesc(
syntax = "jr $s",
template = "000000sssss000000000000000001000",
writeRegs = ""
)
public void jr(final InstructionContext ctx) {
final Registers regs = ctx.getRegisters();
regs.setReg(Reg.pc, ctx.getS());
}
@InstructionDesc(
syntax = "lb $t, imm16($s)",
template = "100000ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void lb(final InstructionContext ctx) {
ctx.setT(ctx.getMemory().getByte(ctx.getS() + ctx.getI16()));
ctx.advPc();
}
@InstructionDesc(
syntax = "lui $t, imm16",
template = "001111-----tttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void lui(final InstructionContext ctx) {
ctx.setT(ctx.getI16() << 16);
ctx.advPc();
}
@InstructionDesc(
syntax = "lw $t, imm16($s)",
template = "100011ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void lw(final InstructionContext ctx) {
ctx.setT(ctx.getMemory().getWord(ctx.getS() + ctx.getI16()));
ctx.advPc();
}
@InstructionDesc(
syntax = "mfhi $d",
template = "0000000000000000ddddd00000010000",
writeRegs = "$d"
)
public void mfhi(final InstructionContext ctx) {
ctx.setD(ctx.getRegisters().getReg(Reg.hi));
ctx.advPc();
}
@InstructionDesc(
syntax = "mflo $d",
template = "0000000000000000ddddd00000010010",
writeRegs = "$d"
)
public void mflo(final InstructionContext ctx) {
ctx.setD(ctx.getRegisters().getReg(Reg.lo));
ctx.advPc();
}
@InstructionDesc(
syntax = "multu $s, $t",
template = "000000sssssttttt0000000000011001",
writeRegs = "",
unsigned = true
)
public void multu(final InstructionContext ctx) {
final int s = ctx.getS();
final int t = ctx.getT();
final long value = u32(s) * u32(t);
ctx.getRegisters().setReg(Reg.lo, (int) value);
ctx.getRegisters().setReg(Reg.hi, (int) (value >> 32));
ctx.advPc();
}
@InstructionDesc(
syntax = "mult $s, $t",
template = "000000sssssttttt0000000000011000",
writeRegs = ""
)
public void mult(final InstructionContext ctx) {
final int s = ctx.getS();
final int t = ctx.getT();
final long value = (long) s * t;
ctx.getRegisters().setReg(Reg.lo, (int) value);
ctx.getRegisters().setReg(Reg.hi, (int) (value >> 32));
ctx.advPc();
}
@InstructionDesc(
syntax = "noop",
template = "00000000000000000000000000000000",
writeRegs = ""
)
public void noop(final InstructionContext ctx) {
ctx.advPc();
}
@InstructionDesc(
syntax = "nor $d, $s, $t",
template = "000000ssssstttttddddd00000100111",
writeRegs = "$d"
)
public void nor(final InstructionContext ctx) {
ctx.setD(~(ctx.getS() | ctx.getT()));
ctx.advPc();
}
@InstructionDesc(
syntax = "or $d, $s, $t",
template = "000000ssssstttttddddd00000100101",
writeRegs = "$d"
)
public void or(final InstructionContext ctx) {
ctx.setD(ctx.getS() | ctx.getT());
ctx.advPc();
}
@InstructionDesc(
syntax = "ori $t, $s, imm16",
template = "001101ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void ori(final InstructionContext ctx) {
ctx.setT(ctx.getS() | ctx.getI16());
ctx.advPc();
}
@InstructionDesc(
syntax = "sb $t, imm16($s)",
template = "101000ssssstttttiiiiiiiiiiiiiiii",
writeRegs = ""
)
public void sb(final InstructionContext ctx) {
ctx.getMemory().setByte(ctx.getS() + ctx.getI16(), (byte) (0xFF & ctx.getT()));
ctx.advPc();
}
@InstructionDesc(
syntax = "sll $d, $t, h5",
template = "000000-----tttttdddddhhhhh000000",
writeRegs = "$d"
)
public void sll(final InstructionContext ctx) {
ctx.setD(ctx.getT() << ctx.getInstruction().getBits(Instruction.T_H5));
ctx.advPc();
}
@InstructionDesc(
syntax = "sllv $d, $t, $s",
template = "000000ssssstttttddddd-----000100",
writeRegs = "$d"
)
public void sllv(final InstructionContext ctx) {
ctx.setD(ctx.getT() << ctx.getS());
ctx.advPc();
}
@InstructionDesc(
syntax = "sltu $d, $s, $t",
template = "000000ssssstttttddddd00000101011",
writeRegs = "$d",
unsigned = true
)
public void sltu(final InstructionContext ctx) {
if (u32(ctx.getS()) < u32(ctx.getT())) {
ctx.setD(1);
} else {
ctx.setD(0);
}
ctx.advPc();
}
@InstructionDesc(
syntax = "slt $d, $s, $t",
template = "000000ssssstttttddddd00000101010",
writeRegs = "$d"
)
public void slt(final InstructionContext ctx) {
if (ctx.getS() < ctx.getT()) {
ctx.setD(1);
} else {
ctx.setD(0);
}
ctx.advPc();
}
@InstructionDesc(
syntax = "sltiu $t, $s, imm16",
template = "001011ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t",
unsigned = true
)
public void sltiu(final InstructionContext ctx) {
if (ctx.getS() < u16(ctx.getI16())) {
ctx.setT(1);
} else {
ctx.setT(0);
}
ctx.advPc();
}
@InstructionDesc(
syntax = "slti $t, $s, imm16",
template = "001010ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void slti(final InstructionContext ctx) {
if (ctx.getS() < ctx.getI16()) {
ctx.setT(1);
} else {
ctx.setT(0);
}
ctx.advPc();
}
@InstructionDesc(
syntax = "sra $d, $t, h5",
template = "000000-----tttttdddddhhhhh000011",
writeRegs = "$d"
)
public void sra(final InstructionContext ctx) {
ctx.setD(ctx.getT() >> ctx.getInstruction().getBits(Instruction.T_H5));
ctx.advPc();
}
@InstructionDesc(
syntax = "srl $d, $t, h5",
template = "000000-----tttttdddddhhhhh000010",
writeRegs = "$d"
)
public void srl(final InstructionContext ctx) {
ctx.setD(ctx.getT() >>> ctx.getInstruction().getBits(Instruction.T_H5));
ctx.advPc();
}
@InstructionDesc(
syntax = "srlv $d, $t, $s",
template = "000000ssssstttttddddd00000000110",
writeRegs = "$d"
)
public void srlv(final InstructionContext ctx) {
ctx.setD(ctx.getT() >>> ctx.getS());
ctx.advPc();
}
@InstructionDesc(
syntax = "sub $d, $s, $t",
template = "000000ssssstttttddddd00000100010",
writeRegs = "$d"
)
public void sub(final InstructionContext ctx) {
ctx.setD(ctx.getS() - ctx.getT());
ctx.advPc();
}
@InstructionDesc(
syntax = "subu $d, $s, $t",
template = "000000ssssstttttddddd00000100011",
writeRegs = "$d",
unsigned = true
)
public void subu(final InstructionContext ctx) {
ctx.setD(s32(u32(ctx.getS()) - u32(ctx.getT())));
ctx.advPc();
}
@InstructionDesc(
syntax = "sw $t, imm16($s)",
template = "101011ssssstttttiiiiiiiiiiiiiiii",
writeRegs = ""
)
public void sw(final InstructionContext ctx) {
ctx.getMemory().setWord(ctx.getS() + ctx.getI16(), ctx.getT());
ctx.advPc();
}
@InstructionDesc(
syntax = "syscall",
template = "000000--------------------001100",
writeRegs = ""
)
public void syscall(final InstructionContext ctx) {
ctx.advPc();
}
@InstructionDesc(
syntax = "xor $d, $s, $t",
template = "000000ssssstttttddddd-----100110",
writeRegs = "$d"
)
public void xor(final InstructionContext ctx) {
ctx.setD(ctx.getS() ^ ctx.getT());
ctx.advPc();
}
@InstructionDesc(
syntax = "xori $t, $s, imm16",
template = "001110ssssstttttiiiiiiiiiiiiiiii",
writeRegs = "$t"
)
public void xori(final InstructionContext ctx) {
ctx.setT(ctx.getS() ^ ctx.getI16());
ctx.advPc();
}
}