////////////////// // 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