summaryrefslogtreecommitdiff
path: root/rtl/core/decode
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rtl/core/decode/data.sv90
1 files changed, 90 insertions, 0 deletions
diff --git a/rtl/core/decode/data.sv b/rtl/core/decode/data.sv
new file mode 100644
index 0000000..7958631
--- /dev/null
+++ b/rtl/core/decode/data.sv
@@ -0,0 +1,90 @@
+`include "core/isa.sv"
+`include "core/psr.sv"
+`include "core/uarch.sv"
+
+module core_decode_data
+(
+ input logic[31:0] insn,
+ input psr_flags flags,
+
+ output alu_op op,
+ output reg_num rn,
+ rd,
+ output logic writeback,
+ update_flags,
+ restore_spsr,
+ zero_fst,
+ negate_fst,
+ negate_snd,
+ carry_in
+);
+
+ assign rn = insn `FIELD_DATA_RN;
+ assign rd = insn `FIELD_DATA_RD;
+
+ always_comb begin
+ update_flags = insn `FIELD_DATA_S;
+ writeback = 1;
+
+ op = ALU_ADD;
+ zero_fst = 0;
+ negate_fst = 0;
+ negate_snd = 0;
+ carry_in = 0;
+
+ unique case(insn `FIELD_DATA_OPCODE)
+ `DATA_ADD: ;
+
+ `DATA_AND: op = ALU_AND;
+ `DATA_EOR: op = ALU_XOR;
+ `DATA_ORR: op = ALU_ORR;
+ `DATA_SUB: negate_snd = 1;
+ `DATA_RSB: negate_fst = 1;
+ `DATA_ADC: carry_in = flags.c;
+ `DATA_MOV: zero_fst = 1;
+ `DATA_CMN: writeback = 0;
+
+ `DATA_MVN: begin
+ zero_fst = 1;
+ negate_snd = 1;
+ end
+
+ `DATA_SBC: begin
+ negate_snd = 1;
+ carry_in = flags.c;
+ end
+
+ `DATA_RSC: begin
+ negate_fst = 1;
+ carry_in = flags.c;
+ end
+
+ `DATA_BIC: begin
+ op = ALU_AND;
+ negate_snd = 1;
+ carry_in = 1;
+ end
+
+ `DATA_TST: begin
+ op = ALU_AND;
+ writeback = 0;
+ end
+
+ `DATA_TEQ: begin
+ op = ALU_XOR;
+ writeback = 0;
+ end
+
+ `DATA_CMP: begin
+ writeback = 0;
+ negate_snd = 1;
+ end
+
+ endcase
+
+ restore_spsr = (rd == `R15) & update_flags;
+ if(restore_spsr)
+ update_flags = 0;
+ end
+
+endmodule