02774 always @(posedge clock or negedge reset_n) begin
02775 if(reset_n == 1'b0) begin
02776 sr <= { 1'b0, 1'b0, 1'b1, 2'b0, 3'b111, 8'b0 };
02777 result <= 32'd0;
02778 alu_signal <= 1'b0;
02779 interrupt_mask_copy <= 3'b0;
02780 was_interrupt <= 1'b0;
02781 end
02782 else begin
02783 case(alu_control)
02784 `ALU_SR_SET_INTERRUPT: begin
02785 interrupt_mask_copy <= interrupt_mask[2:0];
02786 was_interrupt <= 1'b1;
02787 end
02788
02789 `ALU_SR_SET_TRAP: begin
02790 if(was_interrupt == 1'b1) begin
02791 sr <= { 1'b0, sr[14], 1'b1, sr[12:11], interrupt_mask_copy[2:0], sr[7:0] };
02792 end
02793 else begin
02794 sr <= { 1'b0, sr[14], 1'b1, sr[12:0] };
02795 end
02796 was_interrupt <= 1'b0;
02797 end
02798
02799 `ALU_MOVEP_M2R_1: begin
02800 if(ir[6] == 1'b1) result[31:24] <= operand1[7:0];
02801 else result[15:8] <= operand1[7:0];
02802 //CCR: no change
02803 end
02804 `ALU_MOVEP_M2R_2: begin
02805 if(ir[6] == 1'b1) result[23:16] <= operand1[7:0];
02806 else result[7:0] <= operand1[7:0];
02807 //CCR: no change
02808 end
02809 `ALU_MOVEP_M2R_3: begin
02810 if(ir[6] == 1'b1) result[15:8] <= operand1[7:0];
02811 //CCR: no change
02812 end
02813 `ALU_MOVEP_M2R_4: begin
02814 if(ir[6] == 1'b1) result[7:0] <= operand1[7:0];
02815 //CCR: no change
02816 end
02817
02818
02819 `ALU_MOVEP_R2M_1: begin
02820 if(ir[6] == 1'b1) result[7:0] <= operand1[31:24];
02821 else result[7:0] <= operand1[15:8];
02822 // CCR: no change
02823 end
02824 `ALU_MOVEP_R2M_2: begin
02825 if(ir[6] == 1'b1) result[7:0] <= operand1[23:16];
02826 else result[7:0] <= operand1[7:0];
02827 // CCR: no change
02828 end
02829 `ALU_MOVEP_R2M_3: begin
02830 result[7:0] <= operand1[15:8];
02831 // CCR: no change
02832 end
02833 `ALU_MOVEP_R2M_4: begin
02834 result[7:0] <= operand1[7:0];
02835 // CCR: no change
02836 end
02837
02838 `ALU_SIGN_EXTEND: begin
02839 // move operand1 with sign-extension to result
02840 if(size[1] == 1'b1) begin
02841 result <= { {16{operand1[15]}}, operand1[15:0] };
02842 end
02843 else begin
02844 result <= operand1;
02845 end
02846 // CCR: no change
02847 end
02848
02849 `ALU_ARITHMETIC_LOGIC: begin
02850
02851 // OR,OR to mem,OR to Dn
02852 if(decoder_alu_reg[0]) result[31:0] = operand1[31:0] | operand2[31:0];
02853 // AND,AND to mem,AND to Dn
02854 else if(decoder_alu_reg[1]) result[31:0] = operand1[31:0] & operand2[31:0];
02855 // EORI,EOR
02856 else if(decoder_alu_reg[2]) result[31:0] = operand1[31:0] ^ operand2[31:0];
02857 // ADD,ADD to mem,ADD to Dn,ADDQ
02858 else if(decoder_alu_reg[3]) result[31:0] = operand1[31:0] + operand2[31:0];
02859 // SUBI,CMPI,CMPM,SUB to mem,SUB to Dn,CMP,SUBQ
02860 else if(decoder_alu_reg[4] | decoder_alu_reg[5]) result[31:0] = operand1[31:0] - operand2[31:0];
02861
02862 // Z
02863 sr[2] <= `Z;
02864 // N
02865 sr[3] <= `Rm;
02866
02867 // CMPI,CMPM,CMP
02868 if(decoder_alu_reg[5]) begin
02869 // C,V
02870 sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
02871 sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
02872 // X not affected
02873 end
02874 // ADDI,ADD to mem,ADD to Dn,ADDQ
02875 else if(decoder_alu_reg[3]) begin
02876 // C,X,V
02877 sr[0] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm);
02878 sr[4] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm); //=ccr[0];
02879 sr[1] <= (`Sm & `Dm & ~`Rm) | (~`Sm & ~`Dm & `Rm);
02880 end
02881 // SUBI,SUB to mem,SUB to Dn,SUBQ
02882 else if(decoder_alu_reg[4]) begin
02883 // C,X,V
02884 sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
02885 sr[4] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm); //=ccr[0];
02886 sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
02887 end
02888 // ANDI,EORI,ORI,EOR,OR to mem,AND to mem,OR to Dn,AND to Dn
02889 else begin
02890 // C,V
02891 sr[0] <= 1'b0;
02892 sr[1] <= 1'b0;
02893 // X not affected
02894 end
02895 end
02896
02897 `ALU_ABCD_SBCD_ADDX_SUBX_prepare: begin
02898 // ABCD
02899 if( ir[14:12] == 3'b100) begin
02900 result[13:8] = {1'b0, operand1[3:0]} + {1'b0, operand2[3:0]} + {4'b0, sr[4]};
02901 result[19:14] = {1'b0, operand1[7:4]} + {1'b0, operand2[7:4]};
02902
02903 result[31:23] = operand1[7:0] + operand2[7:0] + {7'b0, sr[4]};
02904
02905 result[13:8] = (result[13:8] > 6'd9) ? (result[13:8] + 6'd6) : result[13:8];
02906 end
02907 // SBCD
02908 else if( ir[14:12] == 3'b000 ) begin
02909 result[13:8] = 6'd32 + {2'b0, operand1[3:0]} - {2'b0, operand2[3:0]} - {5'b0, sr[4]};
02910 result[19:14] = 6'd32 + {2'b0, operand1[7:4]} - {2'b0, operand2[7:4]};
02911
02912 result[31:23] = operand1[7:0] - operand2[7:0] - {7'b0, sr[4]};
02913
02914 result[13:8] = (result[13:8] < 6'd32) ? (result[13:8] - 6'd6) : result[13:8];
02915 end
02916 end
02917
02918 `ALU_ABCD_SBCD_ADDX_SUBX: begin
02919 // ABCD
02920 if( ir[14:12] == 3'b100) begin
02921 result[19:14] = (result[13:8] > 6'h1F) ? (result[19:14] + 6'd2) :
02922 (result[13:8] > 6'h0F) ? (result[19:14] + 6'd1) :
02923 result[19:14];
02924 result[19:14] = (result[19:14] > 6'd9) ? (result[19:14] + 6'd6) : result[19:14];
02925
02926 result[7:4] = result[17:14];
02927 result[3:0] = result[11:8];
02928
02929 // C
02930 sr[0] <= (result[19:14] > 6'd9) ? 1'b1 : 1'b0;
02931 // X = C
02932 sr[4] <= (result[19:14] > 6'd9) ? 1'b1 : 1'b0;
02933
02934 // V
02935 sr[1] <= (result[30] == 1'b0 && result[7] == 1'b1) ? 1'b1 : 1'b0;
02936 end
02937 // SBCD
02938 else if( ir[14:12] == 3'b000 ) begin
02939 result[19:14] = (result[13:8] < 6'd16) ? (result[19:14] - 6'd2) :
02940 (result[13:8] < 6'd32) ? (result[19:14] - 6'd1) :
02941 result[19:14];
02942 result[19:14] = (result[19:14] < 6'd32 && result[31] == 1'b1) ? (result[19:14] - 6'd6) : result[19:14];
02943
02944 result[7:4] = result[17:14];
02945 result[3:0] = result[11:8];
02946
02947 // C
02948 sr[0] <= (result[19:14] < 6'd32) ? 1'b1 : 1'b0;
02949 // X = C
02950 sr[4] <= (result[19:14] < 6'd32) ? 1'b1 : 1'b0;
02951
02952 // V
02953 sr[1] <= (result[30] == 1'b1 && result[7] == 1'b0) ? 1'b1 : 1'b0;
02954 end
02955 // ADDX
02956 else if( ir[14:12] == 3'b101 ) begin
02957 result[31:0] = operand1[31:0] + operand2[31:0] + sr[4];
02958
02959 // C,X,V
02960 sr[0] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm);
02961 sr[4] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm); //=ccr[0];
02962 sr[1] <= (`Sm & `Dm & ~`Rm) | (~`Sm & ~`Dm & `Rm);
02963 end
02964 // SUBX
02965 else if( ir[14:12] == 3'b001 ) begin
02966 result[31:0] = operand1[31:0] - operand2[31:0] - sr[4];
02967
02968 // C,X,V
02969 sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
02970 sr[4] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm); //=ccr[0];
02971 sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
02972 end
02973
02974 // Z
02975 sr[2] <= sr[2] & `Z;
02976 // N
02977 sr[3] <= `Rm;
02978 end
02979
02980 `ALU_ASL_LSL_ROL_ROXL_ASR_LSR_ROR_ROXR_prepare: begin
02981 // 32-bit load even for 8-bit and 16-bit operations
02982 // The extra bits will be anyway discarded during register / memory write
02983 result[31:0] = operand1[31:0];
02984
02985 // V cleared
02986 sr[1] <= 1'b0;
02987 // C for ROXL,ROXR: set to X
02988 if(decoder_alu_reg[11] | decoder_alu_reg[15]) begin
02989 sr[0] <= sr[4];
02990 end
02991 else begin
02992 // C cleared
02993 sr[0] <= 1'b0;
02994 end
02995
02996 // N set
02997 sr[3] <= `Rm;
02998 // Z set
02999 sr[2] <= `Z;
03000 end
03001
03002 `ALU_ASL_LSL_ROL_ROXL_ASR_LSR_ROR_ROXR: begin
03003 // ASL / LSL / ROL / ROXL
03004 if (decoder_alu_reg[8] | decoder_alu_reg[9] | decoder_alu_reg[10] | decoder_alu_reg[11]) begin
03005 result[31:0] = {operand1[30:0], lbit};
03006
03007 sr[0] <= `Dm; // C for ASL / LSL / ROL / ROXL
03008 if (decoder_alu_reg[8])
03009 sr[1] <= (sr[1] == 1'b0)? (`Rm != `Dm) : 1'b1; // V for ASL
03010 else
03011 sr[1] <= 1'b0; // V for LSL / ROL / ROXL
03012
03013 if (!decoder_alu_reg[10]) sr[4] <= `Dm; // X for ASL / LSL / ROXL
03014 end
03015 // ASR / LSR / ROR / ROXR
03016 else begin
03017 result[6:0] = operand1[7:1];
03018 result[7] = (size[0]) ? rbit : operand1[8];
03019 result[14:8] = operand1[15:9];
03020 result[15] = (size[1]) ? rbit : operand1[16];
03021 result[30:16] = operand1[31:17];
03022 result[31] = rbit;
03023 sr[0] <= operand1[0]; // C for ASR / LSR / ROR / ROXR
03024 sr[1] <= 1'b0; // V for ASR / LSR / ROR / ROXR
03025 if (!decoder_alu_reg[14]) sr[4] <= operand1[0]; // X for ASR / LSR / ROXR
03026 end
03027
03028 // N set
03029 sr[3] <= `Rm;
03030 // Z set
03031 sr[2] <= `Z;
03032 end
03033
03034 `ALU_MOVE: begin
03035 result = operand1;
03036
03037 // X not affected
03038 // C cleared
03039 sr[0] <= 1'b0;
03040 // V cleared
03041 sr[1] <= 1'b0;
03042
03043 // N set
03044 sr[3] <= `Rm;
03045 // Z set
03046 sr[2] <= `Z;
03047 end
03048
03049 `ALU_ADDA_SUBA_CMPA_ADDQ_SUBQ: begin
03050 // ADDA: 1101
03051 // CMPA: 1011
03052 // SUBA: 1001
03053 // ADDQ,SUBQ: 0101 xxx0,1
03054 // operation requires that operand2 was sign extended
03055
03056 // ADDA,ADDQ
03057 if(decoder_alu_reg[6]) result[31:0] = operand1[31:0] + operand2[31:0];
03058 // SUBA,CMPA,SUBQ
03059 else result[31:0] = operand1[31:0] - operand2[31:0];
03060
03061 // for CMPA
03062 if( ir[15:12] == 4'b1011 ) begin
03063 // Z
03064 sr[2] <= `Z;
03065 // N
03066 sr[3] <= `Rm;
03067
03068 // C,V
03069 sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
03070 sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
03071 // X not affected
03072 end
03073 // for ADDA,SUBA,ADDQ,SUBQ: ccr not affected
03074 end
03075
03076 `ALU_CHK: begin
03077 result[15:0] = operand1[15:0] - operand2[15:0];
03078
03079 // undocumented behavior: Z flag, see 68knotes.txt
03080 //sr[2] <= (operand1[15:0] == 16'b0) ? 1'b1 : 1'b0;
03081 // undocumented behavior: C,V flags, see 68knotes.txt
03082 //sr[0] <= 1'b0;
03083 //sr[1] <= 1'b0;
03084
03085 // C,X,V
03086 // sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
03087 // sr[4] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm); //=ccr[0];
03088 // sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
03089 // +: 0-1, 0-0=0, 1-1=0
03090 // -: 0-0=1, 1-0, 1-1=1
03091 // operand1 - operand2 > 0
03092 if( operand1[15:0] != operand2[15:0] && ((~`Dm & `Sm) | (~`Dm & ~`Sm & ~`Rm) | (`Dm & `Sm & ~`Rm)) == 1'b1 ) begin
03093 // clear N
03094 sr[3] <= 1'b0;
03095 alu_signal <= 1'b1;
03096 end
03097 // operand1 < 0
03098 else if( operand1[15] == 1'b1 ) begin
03099 // set N
03100 sr[3] <= 1'b1;
03101 alu_signal <= 1'b1;
03102 end
03103 // no trap
03104 else begin
03105 // N undefined: not affected
03106 alu_signal <= 1'b0;
03107 end
03108
03109 // X not affected
03110 end
03111
03112 `ALU_MULS_MULU_DIVS_DIVU: begin
03113
03114 // division by 0
03115 if(ir[15:12] == 4'b1000 && operand2[15:0] == 16'b0) begin
03116 // X not affected
03117 // C cleared
03118 sr[0] <= 1'b0;
03119 // V,Z,N undefined: cleared
03120 sr[1] <= 1'b0;
03121 sr[2] <= 1'b0;
03122 sr[3] <= 1'b0;
03123
03124 // set trap
03125 alu_signal <= 1'b1;
03126 end
03127 // division in idle state
03128 else if(ir[15:12] == 4'b1000 && div_count == 5'd0) begin
03129 alu_signal <= 1'b0;
03130 end
03131 // division overflow: divu, divs
03132 else if(ir[15:12] == 4'b1000 && div_overflow == 1'b1) begin
03133 // X not affected
03134 // C cleared
03135 sr[0] <= 1'b0;
03136 // V set
03137 sr[1] <= 1'b1;
03138 // Z,N undefined: cleared and set
03139 sr[2] <= 1'b0;
03140 sr[3] <= 1'b1;
03141
03142 // set trap
03143 alu_signal <= 1'b1;
03144 end
03145 // division
03146 else if( ir[15:12] == 4'b1000 ) begin
03147 result[31:0] <= {div_remainder, div_quotient};
03148
03149 // X not affected
03150 // C cleared
03151 sr[0] <= 1'b0;
03152 // V cleared
03153 sr[1] <= 1'b0;
03154 // Z
03155 sr[2] <= (div_quotient == 16'b0);
03156 // N
03157 sr[3] <= (div_quotient[15] == 1'b1);
03158
03159 // set trap
03160 alu_signal <= 1'b0;
03161 end
03162 // multiplication
03163 else if( ir[15:12] == 4'b1100 ) begin
03164 result[31:0] <= mult_result[31:0];
03165
03166 // X not affected
03167 // C cleared
03168 sr[0] <= 1'b0;
03169 // V cleared
03170 sr[1] <= 1'b0;
03171 // Z
03172 sr[2] <= (mult_result[31:0] == 32'b0);
03173 // N
03174 sr[3] <= (mult_result[31] == 1'b1);
03175
03176 // set trap
03177 alu_signal <= 1'b0;
03178 end
03179 end
03180
03181
03182 `ALU_BCHG_BCLR_BSET_BTST: begin // 97 LE
03183 // byte
03184 if( ir[5:3] != 3'b000 ) begin
03185 sr[2] <= ~(operand1[ operand2[2:0] ]);
03186 result = operand1;
03187 result[ operand2[2:0] ] = (ir[7:6] == 2'b01) ? ~(operand1[ operand2[2:0] ]) : (ir[7:6] == 2'b10) ? 1'b0 : 1'b1;
03188 end
03189 // long
03190 else if( ir[5:3] == 3'b000 ) begin
03191 sr[2] <= ~(operand1[ operand2[4:0] ]);
03192 result = operand1;
03193 result[ operand2[4:0] ] = (ir[7:6] == 2'b01) ? ~(operand1[ operand2[4:0] ]) : (ir[7:6] == 2'b10) ? 1'b0 : 1'b1;
03194 end
03195
03196 // C,V,N,X not affected
03197 end
03198
03199 `ALU_TAS: begin
03200 result[7:0] <= { 1'b1, operand1[6:0] };
03201
03202 // X not affected
03203 // C cleared
03204 sr[0] <= 1'b0;
03205 // V cleared
03206 sr[1] <= 1'b0;
03207
03208 // N set
03209 sr[3] <= (operand1[7] == 1'b1);
03210 // Z set
03211 sr[2] <= (operand1[7:0] == 8'b0);
03212 end
03213
03214
03215 `ALU_NEGX_CLR_NEG_NOT_NBCD_SWAP_EXT: begin
03216 // NEGX / CLR / NEG / NOT
03217 // Optimization thanks to Frederic Requin
03218 if ((ir[11:8] == 4'b0000) || (ir[11:8] == 4'b0010) || (ir[11:8] == 4'b0100) || (ir[11:8] == 4'b0110))
03219 result = 32'b0 - (operand1[31:0] & {32{ir[10] | ~ir[9]}}) - ((sr[4] & ~ir[10] & ~ir[9]) | (ir[10] & ir[9]));
03220 // NBCD
03221 else if( ir[11:6] == 6'b1000_00 ) begin
03222 result[3:0] = 5'd25 - operand1[3:0];
03223 result[7:4] = (operand1[3:0] > 4'd9) ? (5'd24 - operand1[7:4]) : (5'd25 - operand1[7:4]);
03224
03225 if(sr[4] == 1'b0 && result[3:0] == 4'd9 && result[7:4] == 4'd9) begin
03226 result[3:0] = 4'd0;
03227 result[7:4] = 4'd0;
03228 end
03229 else if(sr[4] == 1'b0 && (result[3:0] == 4'd9 || result[3:0] == 4'd15)) begin
03230 result[3:0] = 4'd0;
03231 result[7:4] = result[7:4] + 4'd1;
03232 end
03233 else if(sr[4] == 1'b0) begin
03234 result[3:0] = result[3:0] + 4'd1;
03235 end
03236
03237 //V undefined: unchanged
03238 //Z
03239 sr[2] <= sr[2] & `Z;
03240 //C,X
03241 sr[0] <= (operand1[7:0] == 8'd0 && sr[4] == 1'b0) ? 1'b0 : 1'b1;
03242 sr[4] <= (operand1[7:0] == 8'd0 && sr[4] == 1'b0) ? 1'b0 : 1'b1; //=C
03243 end
03244 // SWAP
03245 else if( ir[11:6] == 6'b1000_01 ) result = { operand1[15:0], operand1[31:16] };
03246 // EXT byte to word
03247 else if( ir[11:6] == 6'b1000_10 ) result = { result[31:16], {8{operand1[7]}}, operand1[7:0] };
03248 // EXT word to long
03249 else if( ir[11:6] == 6'b1000_11 ) result = { {16{operand1[15]}}, operand1[15:0] };
03250
03251 // N set if negative else clear
03252 sr[3] <= `Rm;
03253
03254 // CLR,NOT,SWAP,EXT
03255 if( ir[11:8] == 4'b0010 || ir[11:8] == 4'b0110 || ir[11:6] == 6'b1000_01 || ir[11:7] == 5'b1000_1 ) begin
03256 // X not affected
03257 // C,V cleared
03258 sr[0] <= 1'b0;
03259 sr[1] <= 1'b0;
03260 // Z set
03261 sr[2] <= `Z;
03262 end
03263 // NEGX
03264 else if( ir[11:8] == 4'b0000 ) begin
03265 // C set if borrow
03266 sr[0] <= `Dm | `Rm;
03267 // X=C
03268 sr[4] <= `Dm | `Rm;
03269 // V set if overflow
03270 sr[1] <= `Dm & `Rm;
03271 // Z cleared if nonzero else unchanged
03272 sr[2] <= sr[2] & `Z;
03273 end
03274 // NEG
03275 else if( ir[11:8] == 4'b0100 ) begin
03276 // C clear if zero else set
03277 sr[0] <= `Dm | `Rm;
03278 // X=C
03279 sr[4] <= `Dm | `Rm;
03280 // V set if overflow
03281 sr[1] <= `Dm & `Rm;
03282 // Z set if zero else clear
03283 sr[2] <= `Z;
03284 end
03285 end
03286
03287
03288 `ALU_SIMPLE_LONG_ADD: begin
03289 result <= operand1[31:0] + operand2[31:0];
03290
03291 // CCR not affected
03292 end
03293
03294 `ALU_SIMPLE_LONG_SUB: begin
03295 result <= operand1[31:0] - operand2[31:0];
03296
03297 // CCR not affected
03298 end
03299
03300 `ALU_MOVE_TO_CCR_SR_RTE_RTR_STOP_LOGIC_TO_CCR_SR: begin
03301
03302 // MOVE TO SR,RTE,STOP,ORI to SR,ANDI to SR,EORI to SR
03303 if(decoder_alu_reg[16]) sr <= { operand1[15], 1'b0, operand1[13], 2'b0, operand1[10:8], 3'b0, operand1[4:0] };
03304 // MOVE TO CCR,RTR,ORI to CCR,ANDI to CCR,EORI to CCR
03305 else sr <= { sr[15:8], 3'b0, operand1[4:0] };
03306 end
03307
03308 `ALU_SIMPLE_MOVE: begin
03309 result <= operand1;
03310
03311 // CCR not affected
03312 end
03313
03314 `ALU_LINK_MOVE: begin
03315 if(ir[3:0] == 3'b111) begin
03316 result <= operand1 - 32'd4;
03317 end
03318 else begin
03319 result <= operand1;
03320 end
03321
03322 // CCR not affected
03323 end
03324
03325 endcase
03326 end
03327 end