summaryrefslogtreecommitdiff
path: root/rtl/core/decode
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rtl/core/decode/decode.sv99
-rw-r--r--rtl/core/decode/ldst/misc.sv28
-rw-r--r--rtl/core/decode/ldst/multiple.sv32
-rw-r--r--rtl/core/decode/ldst/single.sv30
-rw-r--r--rtl/core/decode/snd.sv9
5 files changed, 180 insertions, 18 deletions
diff --git a/rtl/core/decode/decode.sv b/rtl/core/decode/decode.sv
index f4de2d0..d14841b 100644
--- a/rtl/core/decode/decode.sv
+++ b/rtl/core/decode/decode.sv
@@ -3,8 +3,8 @@
module core_decode
(
- input word insn,
- input psr_flags flags,
+ input word insn,
+ input psr_flags flags,
output logic execute,
undefined,
@@ -16,6 +16,10 @@ module core_decode
output data_decode data_ctrl
);
+ //TODO
+ logic restore_spsr;
+ ldst_decode ldst_ctrl;
+
logic cond_undefined;
core_decode_conds conds
@@ -25,13 +29,14 @@ module core_decode
.*
);
- logic snd_is_imm, snd_shift_by_reg_if_reg, snd_undefined;
+ logic snd_is_imm, snd_ror_if_imm, snd_shift_by_reg_if_reg, snd_undefined;
snd_decode snd;
core_decode_snd snd_operand
(
.decode(snd),
.is_imm(snd_is_imm),
+ .ror_if_imm(snd_ror_if_imm),
.shift_by_reg_if_reg(snd_shift_by_reg_if_reg),
.undefined(snd_undefined),
.*
@@ -46,22 +51,49 @@ module core_decode
.*
);
- //TODO
- logic restore_spsr;
-
- logic data_writeback, data_update_flags, data_is_imm, data_shift_by_reg_if_reg;
data_decode data;
+ logic data_writeback, data_update_flags, data_restore_spsr,
+ data_is_imm, data_shift_by_reg_if_reg;
core_decode_data group_data
(
.decode(data),
.writeback(data_writeback),
.update_flags(data_update_flags),
+ .restore_spsr(data_restore_spsr),
.snd_is_imm(data_is_imm),
.snd_shift_by_reg_if_reg(data_shift_by_reg_if_reg),
.*
);
+ logic ldst_single_is_imm;
+ ldst_decode ldst_single;
+
+ core_decode_ldst_single group_ldst_single
+ (
+ .snd_is_imm(ldst_single_is_imm),
+ .decode(ldst_single),
+ .*
+ );
+
+ ldst_decode ldst_misc;
+
+ core_decode_ldst_misc group_ldst_misc
+ (
+ .decode(ldst_misc),
+ .*
+ );
+
+ logic ldst_mult_restore_spsr;
+ ldst_decode ldst_multiple;
+
+ core_decode_ldst_multiple group_ldst_multiple
+ (
+ .decode(ldst_multiple),
+ .restore_spsr(ldst_mult_restore_spsr),
+ .*
+ );
+
always_comb begin
undefined = cond_undefined;
@@ -75,8 +107,13 @@ module core_decode
snd_ctrl.shr = 0;
snd_ctrl.ror = 0;
snd_is_imm = 1'bx;
+ snd_ror_if_imm = 1'bx;
snd_shift_by_reg_if_reg = 1'bx;
+ ldst_ctrl = {($bits(ldst_ctrl)){1'bx}};
+ ldst_ctrl.enable = 0;
+
+ // El orden de los casos es importante, NO CAMBIAR
priority casez(insn `FIELD_OP)
`GROUP_B: begin
branch = 1;
@@ -89,6 +126,7 @@ module core_decode
`GROUP_ALU: begin
snd_is_imm = data_is_imm;
+ snd_ror_if_imm = 1;
snd_shift_by_reg_if_reg = data_shift_by_reg_if_reg;
snd_ctrl = snd;
@@ -96,26 +134,57 @@ module core_decode
writeback = data_writeback;
update_flags = data_update_flags;
+ restore_spsr = data_restore_spsr;
undefined = undefined | snd_undefined;
end
`INSN_MUL: ;
`GROUP_BIGMUL: ;
- `GROUP_LDST_MISC: ;
- `GROUP_LDST_MULT: ;
+
+ `GROUP_LDST_SINGLE_IMM, `GROUP_LDST_SINGLE_REG: begin
+ snd_is_imm = ldst_single_is_imm;
+ snd_ror_if_imm = 0;
+ snd_shift_by_reg_if_reg = 0;
+
+ snd_ctrl = snd;
+ ldst_ctrl = ldst_single;
+ ldst_ctrl.enable = 1;
+
+ undefined = undefined | snd_undefined;
+ end
+
+ `GROUP_LDST_MISC_IMM, `GROUP_LDST_MISC_REG:
+ priority casez(insn `FIELD_OP)
+ `INSN_LDRB, `INSN_LDRSB, `INSN_LDRSH, `INSN_STRH: begin
+ ldst_ctrl = ldst_misc;
+ ldst_ctrl.enable = 1;
+ end
+
+ default: undefined = 1;
+ endcase
+
+ `GROUP_LDST_MULT: begin
+ ldst_ctrl = ldst_multiple;
+ ldst_ctrl.enable = 1;
+ restore_spsr = ldst_mult_restore_spsr;
+ end
+
`GROUP_SWP: ;
`GROUP_CP: ;
`INSN_MRS: ;
`GROUP_MSR: ;
`INSN_SWI: ;
- default: begin
- undefined = 1;
- branch = 1'bx;
- writeback = 1'bx;
- snd_ctrl = {($bits(snd_ctrl)){1'bx}};
- end
+ default: undefined = 1;
endcase
+
+ if(undefined) begin
+ branch = 1'bx;
+ writeback = 1'bx;
+ snd_ctrl = {($bits(snd_ctrl)){1'bx}};
+ data_ctrl = {($bits(data_ctrl)){1'bx}};
+ ldst_ctrl = {($bits(ldst_ctrl)){1'bx}};
+ end
end
endmodule
diff --git a/rtl/core/decode/ldst/misc.sv b/rtl/core/decode/ldst/misc.sv
new file mode 100644
index 0000000..de2428f
--- /dev/null
+++ b/rtl/core/decode/ldst/misc.sv
@@ -0,0 +1,28 @@
+`include "core/isa.sv"
+`include "core/uarch.sv"
+
+module core_decode_ldst_misc
+(
+ input word insn,
+
+ output ldst_decode decode
+);
+
+ logic p, w;
+
+ assign decode.rn = insn `FIELD_LDST_MISC_RN;
+ assign decode.rd = insn `FIELD_LDST_MISC_RD;
+ assign decode.size = insn `FIELD_LDST_MISC_H ? LDST_HALF : LDST_BYTE;
+ assign decode.load = insn `FIELD_LDST_LD;
+ assign decode.increment = insn `FIELD_LDST_MISC_U;
+ assign decode.writeback = !p || w;
+ assign decode.sign_extend = insn `FIELD_LDST_MISC_S;
+ assign decode.pre_indexed = p && w;
+ assign decode.unprivileged = 0;
+ assign decode.user_regs = 0;
+ assign decode.reg_list = 16'b0;
+
+ assign p = insn `FIELD_LDST_MISC_P;
+ assign w = insn `FIELD_LDST_MISC_W;
+
+endmodule
diff --git a/rtl/core/decode/ldst/multiple.sv b/rtl/core/decode/ldst/multiple.sv
new file mode 100644
index 0000000..24e8e5b
--- /dev/null
+++ b/rtl/core/decode/ldst/multiple.sv
@@ -0,0 +1,32 @@
+`include "core/isa.sv"
+`include "core/uarch.sv"
+
+module core_decode_ldst_multiple
+(
+ input word insn,
+
+ output ldst_decode decode,
+ output logic restore_spsr
+);
+
+ logic s, l;
+ logic[15:0] reg_list;
+
+ assign decode.rn = insn `FIELD_LDST_MULT_RN;
+ assign decode.size = LDST_WORD;
+ assign decode.load = l;
+ assign decode.increment = insn `FIELD_LDST_MULT_U;
+ assign decode.writeback = insn `FIELD_LDST_MULT_W;
+ assign decode.sign_extend = 0;
+ assign decode.pre_indexed = insn `FIELD_LDST_MULT_P;
+ assign decode.unprivileged = 0;
+ assign decode.user_regs = s && (!l || !reg_list[`R15]);
+ assign decode.reg_list = reg_list;
+
+ assign s = insn `FIELD_LDST_MULT_S;
+ assign l = insn `FIELD_LDST_LD;
+
+ assign reg_list = insn `FIELD_LDST_MULT_LIST;
+ assign restore_spsr = s && l && reg_list[`R15];
+
+endmodule
diff --git a/rtl/core/decode/ldst/single.sv b/rtl/core/decode/ldst/single.sv
new file mode 100644
index 0000000..5bcb638
--- /dev/null
+++ b/rtl/core/decode/ldst/single.sv
@@ -0,0 +1,30 @@
+`include "core/isa.sv"
+`include "core/uarch.sv"
+
+module core_decode_ldst_single
+(
+ input word insn,
+
+ output ldst_decode decode,
+ output logic snd_is_imm
+);
+
+ logic p, w;
+
+ assign decode.rn = insn `FIELD_LDST_SINGLE_RN;
+ assign decode.rd = insn `FIELD_LDST_SINGLE_RD;
+ assign decode.size = insn `FIELD_LDST_SINGLE_B ? LDST_BYTE : LDST_WORD;
+ assign decode.load = insn `FIELD_LDST_LD;
+ assign decode.increment = insn `FIELD_LDST_SINGLE_U;
+ assign decode.writeback = !p || w;
+ assign decode.sign_extend = 0;
+ assign decode.pre_indexed = p && w;
+ assign decode.unprivileged = !p && w;
+ assign decode.user_regs = 0;
+ assign decode.reg_list = 16'b0;
+
+ assign p = insn `FIELD_LDST_SINGLE_P;
+ assign w = insn `FIELD_LDST_SINGLE_W;
+ assign snd_is_imm = !insn `FIELD_LDST_SINGLE_REG;
+
+endmodule
diff --git a/rtl/core/decode/snd.sv b/rtl/core/decode/snd.sv
index 5110d57..4dbb028 100644
--- a/rtl/core/decode/snd.sv
+++ b/rtl/core/decode/snd.sv
@@ -5,6 +5,7 @@ module core_decode_snd
(
input word insn,
input logic is_imm,
+ ror_if_imm,
shift_by_reg_if_reg,
output snd_decode decode,
@@ -13,7 +14,7 @@ module core_decode_snd
reg_num r, r_shift;
logic shift_by_reg, shl, shr, ror, put_carry, sign_extend;
- logic[7:0] imm;
+ logic[11:0] imm;
logic[5:0] shift_imm;
assign decode.r = r;
@@ -30,7 +31,7 @@ module core_decode_snd
assign r = insn `FIELD_SND_RM;
assign r_shift = insn `FIELD_SND_RS;
- assign imm = insn `FIELD_SND_IMM8;
+ assign imm = ror_if_imm ? {4'b0, insn `FIELD_SND_IMM8} : insn `FIELD_SND_IMM12;
assign shift_by_reg = ~is_imm & shift_by_reg_if_reg;
assign undefined = shift_by_reg & insn `FIELD_SND_ZEROIFREG;
@@ -43,7 +44,9 @@ module core_decode_snd
put_carry = 0;
sign_extend = 1'bx;
- if(is_imm)
+ if(is_imm && !ror_if_imm)
+ shift_imm = 6'b0;
+ else if(is_imm && !ror_if_imm)
shift_imm = {1'b0, insn `FIELD_SND_ROR8, 1'b0};
else begin
shift_imm = {1'b0, insn `FIELD_SND_SHIFTIMM};