Old stuff/ecole_etude_fac_de_pau/licence_3/archi/mips/dlx.gm
(Deskargatu)
//////////////////
// memory banks //
//////////////////
microcode bank[31:0] control.mcode;
macrocode bank[31:0] memory.m1;
map bank[6:0] control.map;
//////////////////////
// microcode fields //
//////////////////////
////////////////
// microprogram
field next[31:30]={
inc=0,
fetch=1,
jmap=2,
jaddr=3
};
field addr[8:1];
field TrapOver[29]; // enable branching to trap instead of fetch on overflow
///////
// ALU
field ALUOp[28:25]={
func=0,
test=5,
add=8,
sub=10
};
field ALUSrcA[24]={
PC=0,
DA=1
};
field ALUSrcB[23:22]={
DB=0,
num4=1,
immed=2,
branch=3
};
//////
// PC
field PCWrite[21:20]={
no=0,
always=1,
eqz=2,
nez=3
};
field PCSource[19:18]={
ALURes=0, // ALU output
ALUOut=1, // ALUOut register
jump=2, // jump target
DA=3 // register A
};
//////////
// memory
field MemAddr[17]={
PC=0,
ALU=1
};
field MemWrite[16];
/////////////
// registers
field RegWA[15:14]={
I=0, // i-format instruction, WA = IR[16:20]
R=1, // r-format instruction, WA = IR[11:15]
link=2 // WA=31, 0x1f (link register)
};
field RegWD[13:12]={
Mem=0,
ALU=1,
cond=2, // WD = 0^31 ## Cond (used for set-on-compare instructions)
PC=3
};
field RegWrite[11];
//////
// IR
field IRWrite[10];
/////////////////////
// condition testing
field CondSign[9]={
S=0, // use signed numbers when testing condition
U=1 // use unsigned numbers when testing condition
};
// one bit unused
field unused[0];
///////////////
// registers //
///////////////
registers $r0=0, $at=1, $v0=2, $v1=3, $a0=4, $a1=5, $a2=6, $a3=7, $t0=8, $t1=9, $t2=10, $t3=11, $t4=12, $t5=13, $t6=14, $t7=15, $s0=16, $s1=17, $s2=18, $s3=19, $s4=20, $s5=21, $s6=22, $s7=23, $t8=24, $t9=25, $k0=26, $k1=27, $gp=28, $sp=29, $s8=30, $ra=31;
/////////////////////
// operand formats //
/////////////////////
// r-format
// Op rsA rsB rd zero funct
// xxxxxxAA AAABBBBB DDDDD000 00ffffff
// 31 25 20 15 10 5
operands rform {
%1,%2,%3 = { +0[25:21]=%2; +0[20:16]=%3; +0[15:11]=%1; };
%1, %2 = { +0[25:21]=%1; +0[20:16]=%2; +0[15:11]=%1; };
};
// i-format
// Op rsA rd Immed
// xxxxxxAA AAADDDDD IIIIIIII IIIIIIII
// 31 25 20 15
operands iform {
%1,%2,#3 = { +0[25:21]=%2; +0[20:16]=%1; +0[15:0]=#3; };
%1, #2 = { +0[25:21]=%1; +0[20:16]=%1; +0[15:0]=#2; };
};
// i-format -- only two operands (lhi)
// Op rd zero Immed
// xxxxxxDD DDD00000 IIIIIIII IIIIIIII
// 31 25 20 15
operands iform2 {
%1,#2 = { +0[25:21]=%1; +0[20:16]=0; +0[15:0]=#2; };
};
// i-format -- only one operand (jr, jalr)
// Op rd zero zero
// xxxxxxDD DDD00000 00000000 00000000
// 31 25 20 15
operands iform1 {
%1 = { +0[25:21]=%1; +0[20:16]=0; +0[15:0]=0; };
};
// j-format -- absolute addressing
// Op jump address
// xxxxxxJJ JJJJJJJJ JJJJJJJJ JJJJJJJJ
// 25
operands jform {
#1 = { +0[25:0]=#1; };
};
// memory (lw, sw)
// Op base reg offset
// xxxxxxBB BBBRRRRR OOOOOOOO OOOOOOOO
// 31 25 20 15
operands mem {
%1,#2(%3) = { +0[25:21]=%3; +0[20:16]=%1; +0[15:0]=#2; };
%1,#2 = { +0[25:21]=0; +0[20:16]=%1; +0[15:0]=#2; };
%1,%2 = { +0[25:21]=%2; +0[20:16]=%1; +0[15:0]=0; };
};
// branch -- PC-relative addressing
// Op rsA zero Immed
// xxxxxxAA AAA00000 IIIIIIII IIIIIIII
// 31 25 20 15
operands branch {
%1,#2 = { +0[25:21]=%1; +0[20:16]=0; +0[15:0]=#2; };
};
/////////////
// opcodes //
/////////////
// map index is (r-format?) ## opcode, seven bits
// or opcode + 0x40 for r-format instructions
// r-format first (funct field)
op nop {
map alu : 0x40;
map trap : 0x7f; // no sensical place to put it
+0[31:26] = 0x00;
+0[5:0] = 0x00;
operands {
- = { +0[25:6]=0; };
};
};
////////
// shift
op sll {
map alu : 0x44;
+0[31:26] = 0x00;
+0[5:0] = 0x04;
operands rform;
};
op srl {
map alu : 0x46;
+0[31:26] = 0x00;
+0[5:0] = 0x06;
operands rform;
};
op sra {
map alu : 0x47;
+0[31:26] = 0x00;
+0[5:0] = 0x07;
operands rform;
};
///////////////////
// set-on-condition (unsigned)
op sequ {
map set_u : 0x50;
+0[31:26] = 0x00;
+0[5:0] = 0x10;
operands rform;
};
op sneu {
map set_u : 0x51;
+0[31:26] = 0x00;
+0[5:0] = 0x11;
operands rform;
};
op sltu {
map set_u : 0x52;
+0[31:26] = 0x00;
+0[5:0] = 0x12;
operands rform;
};
op sgtu {
map set_u : 0x53;
+0[31:26] = 0x00;
+0[5:0] = 0x13;
operands rform;
};
op sleu {
map set_u : 0x54;
+0[31:26] = 0x00;
+0[5:0] = 0x14;
operands rform;
};
op sgeu {
map set_u : 0x55;
+0[31:26] = 0x00;
+0[5:0] = 0x15;
operands rform;
};
///////////////////
// arithmetic/logic
op add {
map alu : 0x60;
+0[31:26] = 0x00;
+0[5:0] = 0x20;
operands rform;
};
op addu {
map alu_u : 0x61;
+0[31:26] = 0x00;
+0[5:0] = 0x21;
operands rform;
};
op sub {
map alu : 0x62;
+0[31:26] = 0x00;
+0[5:0] = 0x22;
operands rform;
};
op subu {
map alu_u : 0x63;
+0[31:26] = 0x00;
+0[5:0] = 0x23;
operands rform;
};
op and {
map alu : 0x64;
+0[31:26] = 0x00;
+0[5:0] = 0x24;
operands rform;
};
op or {
map alu : 0x65;
+0[31:26] = 0x00;
+0[5:0] = 0x25;
operands rform;
};
op xor {
map alu : 0x66;
+0[31:26] = 0x00;
+0[5:0] = 0x26;
operands rform;
};
////////////////////
// set-on-condition
op seq {
map set : 0x68;
+0[31:26] = 0x00;
+0[5:0] = 0x28;
operands rform;
};
op sne {
map set : 0x69;
+0[31:26] = 0x00;
+0[5:0] = 0x29;
operands rform;
};
op slt {
map set : 0x6a;
+0[31:26] = 0x00;
+0[5:0] = 0x2a;
operands rform;
};
op sgt {
map set : 0x6b;
+0[31:26] = 0x00;
+0[5:0] = 0x2b;
operands rform;
};
op sle {
map set : 0x6c;
+0[31:26] = 0x00;
+0[5:0] = 0x2c;
operands rform;
};
op sge {
map set : 0x6d;
+0[31:26] = 0x00;
+0[5:0] = 0x2d;
operands rform;
};
////////////////////////////////////////
// move instructions not yet implemented
// 0x30-0x35
/////////////////////////////////
// now for i-form instructions...
op j {
map j : 0x02;
+0[31:26] = 0x02;
operands jform;
};
op jal {
map jal : 0x03;
+0[31:26] = 0x03;
operands jform;
};
op beqz {
map beqz : 0x04;
+0[31:26] = 0x04;
operands branch;
};
op bnez {
map bnez : 0x05;
+0[31:26] = 0x05;
operands branch;
};
// floating-point branches unsupported: bfpt, bfpf
///////////////////
// arithmetic/logic
op addi {
map alu_i : 0x08;
+0[31:26] = 0x08;
operands iform;
};
op addui {
map alu_ui : 0x09;
+0[31:26] = 0x09;
operands iform;
};
op subi {
map alu_i : 0x0a;
+0[31:26] = 0x0a;
operands iform;
};
op subui {
map alu_ui : 0x0b;
+0[31:26] = 0x0b;
operands iform;
};
op andi {
map alu_i : 0x0c;
+0[31:26] = 0x0c;
operands iform;
};
op ori {
map alu_i : 0x0d;
+0[31:26] = 0x0d;
operands iform;
};
op xori {
map alu_i : 0x0e;
+0[31:26] = 0x0e;
operands iform;
};
op lhi {
map alu_i : 0x0f;
+0[31:26] = 0x0f;
operands iform2;
};
// exceptions unsupported: rfe, trap
op jr {
map jr : 0x12;
+0[31:26] = 0x12;
operands iform1;
};
op jalr {
map jalr : 0x13;
+0[31:26] = 0x13;
operands iform1;
};
////////
// shift
op slli {
map alu_i : 0x14;
+0[31:26] = 0x14;
operands iform;
};
op srli {
map alu_i : 0x16;
+0[31:26] = 0x16;
operands iform;
};
op srai {
map alu_i : 0x17;
+0[31:26] = 0x17;
operands iform;
};
///////////////////
// set-on-condition
// Op[2:0] gives condition code
op seqi {
map set_i : 0x18;
+0[31:26] = 0x18;
operands iform;
};
op snei {
map set_i : 0x19;
+0[31:26] = 0x19;
operands iform;
};
op slti {
map set_i : 0x1a;
+0[31:26] = 0x1a;
operands iform;
};
op sgti {
map set_i : 0x1b;
+0[31:26] = 0x1b;
operands iform;
};
op slei {
map set_i : 0x1c;
+0[31:26] = 0x1c;
operands iform;
};
op sgei {
map set_i : 0x1d;
+0[31:26] = 0x1d;
operands iform;
};
/////////////////////////////////
// load/store memory instructions
// aligned-only for now, no FP
op lw {
map lw : 0x23;
+0[31:26] = 0x23;
operands mem;
};
op sw {
map sw : 0x2b;
+0[31:26] = 0x2b;
operands mem;
};
//////////////////////////////
// set-on-condition (unsigned)
// Op[2:0] gives condition code
op sequi {
map set_ui : 0x30;
+0[31:26] = 0x30;
operands iform;
};
op sneui {
map set_ui : 0x31;
+0[31:26] = 0x31;
operands iform;
};
op sltui {
map set_ui : 0x32;
+0[31:26] = 0x32;
operands iform;
};
op sgtui {
map set_ui : 0x33;
+0[31:26] = 0x33;
operands iform;
};
op sleui {
map set_ui : 0x34;
+0[31:26] = 0x34;
operands iform;
};
op sgeui {
map set_ui : 0x35;
+0[31:26] = 0x35;
operands iform;
};
// and that's that, except for floating-point ops
// fake opcode, translates to add with $r0
op move {
+0[31:26] = 0x00;
+0[5:0] = 0x20;
operands {
%1, %2 = { +0[25:21]=%2; +0[20:16]=0; +0[15:11]=%1; };
};
};
// translates to addi with $r0
op li {
+0[31:26] = 0x08;
operands {
%1,#2 = { +0[25:21]=0; +0[20:16]=%1; +0[15:0]=#2; };
};
};
// aliases for branch instructions
// true/false (for use after a set-on-compare instruction)
op bf {
map beqz : 0x04;
+0[31:26] = 0x04;
operands branch;
};
op bt {
map bnez : 0x05;
+0[31:26] = 0x05;
operands branch;
};
///////////////
// microcode //
///////////////
begin microcode @ 0
fetch: MemAddr=PC IRWrite
ALUOp=add ALUSrcA=PC ALUSrcB=num4
PCSource=ALURes PCWrite=always
next=inc;
decode: ALUSrcA=PC ALUSrcB=branch ALUOp=add
// also waiting for register fetch
next=jmap; // jump to opcode
// load word
lw: ALUSrcA=DA ALUSrcB=immed ALUOp=add // memory addr
next=inc;
lw2: ALUSrcA=DA ALUSrcB=immed ALUOp=add // maintain
MemAddr=ALU
next=inc;
lw3: MemAddr=ALU
RegWA=I RegWD=Mem RegWrite
next=fetch;
// store word
sw: ALUSrcA=DA ALUSrcB=immed ALUOp=add // memory addr
MemAddr=ALU
next=inc;
sw2: ALUSrcA=DA ALUSrcB=immed ALUOp=add // maintain
MemAddr=ALU MemWrite
next=fetch;
// ALU ops
alu: ALUOp=func ALUSrcA=DA ALUSrcB=DB
TrapOver
next=jaddr addr=alu_2;
alu_u: ALUOp=func ALUSrcA=DA ALUSrcB=DB
next=jaddr addr=alu_2;
alu_i: ALUOp=func ALUSrcA=DA ALUSrcB=immed
TrapOver
next=jaddr addr=alu_i2;
alu_ui: ALUOp=func ALUSrcA=DA ALUSrcB=immed
next=jaddr addr=alu_i2;
alu_2: RegWA=R RegWD=ALU RegWrite
next=fetch;
alu_i2: RegWA=I RegWD=ALU RegWrite
next=fetch;
// set-on-compare
set: ALUOp=sub ALUSrcA=DA ALUSrcB=DB CondSign=S
RegWD=cond
next=inc;
set2: ALUOp=sub ALUSrcA=DA ALUSrcB=DB CondSign=S
RegWA=R RegWD=cond RegWrite
next=fetch;
set_u: ALUOp=sub ALUSrcA=DA ALUSrcB=DB CondSign=U
next=inc;
set_u2: CondSign=U
RegWA=R RegWD=cond RegWrite
next=fetch;
set_i: ALUOp=sub ALUSrcA=DA ALUSrcB=immed CondSign=S
next=inc;
set_i2: CondSign=S
RegWA=I RegWD=cond RegWrite
next=fetch;
set_ui: ALUOp=sub ALUSrcA=DA ALUSrcB=immed CondSign=U
next=inc;
set_ui2:CondSign=U
RegWA=I RegWD=cond RegWrite
next=fetch;
// jump
j: PCWrite=always PCSource=jump
next=fetch;
jal: PCWrite=always PCSource=jump
RegWA=link RegWD=PC RegWrite
next=fetch;
jr: PCWrite=always PCSource=DA
next=fetch;
jalr: PCWrite=always PCSource=DA
RegWA=link RegWD=PC RegWrite
next=fetch;
// branch
beqz: PCWrite=eqz PCSource=ALUOut
ALUOp=test ALUSrcA=DA // 'test' just copies, but zero flag gets set
next=fetch;
bnez: PCWrite=nez PCSource=ALUOut
ALUOp=test ALUSrcA=DA
next=fetch;
// voodoo
undef: PCWrite=always PCSource=trap // cause?
next=fetch;
over: PCWrite=always PCSource=trap // cause?
next=fetch;
trap: PCWrite=always PCSource=trap // cause?
next=fetch;
end
///////////////
// macrocode //
///////////////
begin macrocode @ 0
first: .symbol 0x100
num: .symbol 0x104
data_top: .symbol 0x108
start:
lw $a0, first //00 0 start number
lw $s0, num //04 1 count
li $s2, data_top //08 2 first place to write out
loop: beqz $s0, 6 //0c 3 count==0 -> done
subi $s0, 1 //10 4 count--
jal prime //14 5 $v0 = prime($a0)
sw $v0, $s2 //18 6 store to $s2
addi $s2, 4 //1c 7 $s2+=4 (one word)
move $a0, $v0 //20 8 $a0=$v0
j loop //24 9 loop
done: j done //28 a done, loop forever
prime: move $v0, $a0 //2c b $v0=$a0
newnum: addi $v0, 1 //30 c $v0++
li $t0, 2 //34 d $t0 is current factor, start at 2
srli $t1, $v0, 1 //38 e $t1 is last factor, = $v0/2
loop1: move $t2, $v0 //3c f $t2=$v0
loop2: slt $t3, $t2, $t0 //40 10 $t2<$t0?
bt $t3, 2 //44 11 -> done1 - done with division
sub $t2, $t0 //48 12 $t2 -= $t0
j loop2 //4c 13 loop
done1: beqz $t2, -9 //50 14 remainder zero? -> newnum
addi $t0, 1 //54 15 otherwise, try next factor
sgt $t3, $t0, $t1 //58 16 tried all factors?
bf $t3, -9 //5c 17 no -> loop1, divide again
jr $ra //60 18 yes -> done, num is in $v0
// data
end