Tfe

Ongi etorri tfe-ren webgunera...

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