All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs
@ 2019-01-31 21:08 Richard Henderson
  2019-01-31 21:08 ` [Qemu-devel] [PATCH 1/2] decodetree: Initial support " Richard Henderson
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Richard Henderson @ 2019-01-31 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: ysato

I'm not sure how much simplication could be had for "simple"
variable-length ISAs like ARM thumb2 or RISC-V.

But the recently posted RX port is more complicated than those.
For me, what makes RX more difficult is that there is no easy
test of the first N bits to determine the length of the insn.

I put together a starting point for the RX decode.  I'm sure
there are a few mistakes, but it's close enough to see how the
decoding might work.

I have chosen to have this RX decoder only consider the "base"
instruction, without the "extra" bits like the immediate associated
with the LI field, or the memory displacement associated with
the LD field.

The new decode_load function reads the bytes of the insn with
minimal decoding and no further validation of invalid insns;
that is left for the main decode function.

This is expecting a helper function that assembles the bytes.
While I say I rule out Thumb2+RISC-V above, they are not implausible
examples.  These have uint16_t granularity, and I didn't want to
assume the endianness of the granules.

But for RX, with byte granularity,

uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
                           int i, int n)
{
    while (++i <= n) {
        uint8_t b = cpu_ldub_code(ctx->env, ctx->base.pc_next++);
        insn |= b << (32 - i * 8);
    }
    return insn;
}

For the actual port submission, I would break up the translation
into small bits.  Just a few lines into the decode file and the
associated functions within translate.c.


r~


Richard Henderson (2):
  decodetree: Initial support for variable-length ISAs
  decodetree: Expand a decode_load function

 scripts/decodetree.py | 213 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 200 insertions(+), 13 deletions(-)

---

&bcnd		cd dsp
&jdsp		dsp
&jreg		rs
&rr		rd rs
&ri		rd imm
&rrr		rd rs rs2
&rri		rd imm rs2
&rm		rd rs ld mi
&mi		rs ld mi imm
&mr		rs ld mi rs2

########

%b2_r_0		16:4
%b2_li_2	18:2 !function=li
%b2_li_8	24:2 !function=li
%b2_dsp5_3	23:4 19:1

@b2_rds		.... .... .... rd:4		&rr rs=%b2_r_0
@b2_rds_li	.... .... .... rd:4		&rri rs2=%b2_r_0 imm=%b2_li_8
@b2_rds_uimm4	.... .... imm:4 rd:4		&rri rs2=%b2_r_0
@b2_rds_imm5	.... ... imm:5 rd:4		&rri rs2=%b2_r_0
@b2_rd_rs_li	.... .... rs2:4 rd:4		&rri imm=%b2_li_8
@b2_rd_ld_ub	.... .. ld:2 rs:4 rd:4		&rm mi=4
@b2_ld_imm3	.... .. ld:2 rs:4 . imm:3	&mi mi=4

########

%b3_r_0		8:4
%b3_li_10	18:2 !function=li
%b3_dsp5_8	23:1 16:4

@b3_rd_rs	.... .... .... .... rs:4 rd:4		&rr
@b3_rd_li	.... .... .... .... .... rd:4 \
		&rri rs2=%b3_r_0 imm=%b3_li_10
@b3_rd_ld	.... .... mi:2 .... ld:2 rs:4 rd:4	&rm
@b3_rd_ld_ub	.... .... .... .. ld:2 rs:4 rd:4	&rm mi=4
@b3_rd_ld_ul	.... .... .... .. ld:2 rs:4 rd:4	&rm mi=2
@b3_rd_rs_rs2	.... .... .... rd:4 rs:4 rs2:4		&rrr
@b3_ld_rs2	.... .... .... .. ld:2 rs:4 rs2:4	&mr
@b3_rds_imm5	.... .... ....... imm:5 rd:4		&rri rs2=%b3_r_0
@b3_rd_rs_imm5	.... .... ... imm:5 rs2:4 rd:4		&rri

########

%b4_li_18	18:2 !function=li

@b4_rd_ldmi	.... .... mi:2 .... ld:2 .... .... rs:4 rd:4	&rm

########

ABS_rr		0111 1110 0010 ....			@b2_rds
ABS_rr		1111 1100 0000 1111 .... ....		@b3_rd_rs

ADC_ri		1111 1101 0111 ..00 0000 ....		@b3_rd_li
ADC_rr		1111 1100 0000 1011 .... ....		@b3_rd_rs
# Note only mi==2 allowed.
ADC_rl		0000 0110 ..10 00.. 0000 0010 .... ....	@b4_rd_ldmi

ADD_rri		0110 0010 .... ....			@b2_rds_uimm4
ADD_rri		0111 00.. .... ....			@b2_rd_rs_li
ADD_rl		0100 10.. .... ....			@b2_rd_ld_ub
ADD_rl		0000 0110 ..00 10.. .... ....		@b3_rd_ld
ADD_rrr		1111 1111 0010 .... .... ....		@b3_rd_rs_rs2

AND_rri		0110 0100 .... ....			@b2_rds_uimm4
AND_rri		0111 01.. 0010 ....			@b2_rds_li
AND_rl		0101 00.. .... ....			@b2_rd_ld_ub
AND_rl		0000 0110 ..01 00.. .... ....		@b3_rd_ld
AND_rrr		1111 1111 0100 .... .... ....		@b3_rd_rs_rs2

BCLR_li		1111 00.. .... 1...			@b2_ld_imm3
BCLR_ri		0111 101. .... ....			@b2_rds_imm5
BCLR_lr		1111 1100 0110 01.. .... ....		@b3_ld_rs2 mi=4

BCnd_s		0001 cd:1 dsp:3				&bcnd
BCnd_b		0010 cd:4 dsp:8				&bcnd
BCnd_w		0011 101 cd:1 dsp:16			&bcnd

# Note that BNOT has cd = 15
BMCnd_BNOT_mi	1111 1100 111 imm:3 ld:2 rd:4 cd:4
BMCnd_BNOT_ri	1111 1101 111 imm:5 cd:4 rd:4

BNOT_lr		1111 1100 0110 11.. .... ....		@b3_ld_rs2 mi=2

BRA_s		0000 1 dsp:3				&jdsp
#BRA_b		0010 1110 dsp:8		# overlaps BCnd_b
BRA_w		0011 1000 dsp:16			&jdsp
BRA_a		0000 0100 dsp:24			&jdsp

BRK		0000 0000

BSET_li		1111 00.. .... 0...			@b2_ld_imm3
BSET_ri		0111 100. .... ....			@b2_rds_imm5
BSET_lr		1111 1100 0110 00.. .... ....		@b3_ld_rs2 mi=4

BSR_w		0011 1001 dsp:16			&jdsp
BSR_a		0000 0101 dsp:24			&jdsp

BTST_li		1111 01.. .... 0...			@b2_ld_imm3
BTST_ri		0111 110. .... ....			@b2_rds_imm5
BTST_lr		1111 1100 0110 10.. .... ....		@b3_ld_rs2 mi=4

CLRPSW		0111 1111 1011 cb:4

CMP_ri		0110 0001 .... ....			@b2_rds_uimm4
CMP_ri		0111 0101 0101 rs2:4 imm:8		&rri rd=0
CMP_ri		0111 01.. 0000 rs2:4			&rri imm=%b2_li_8 rd=0
CMP_rl		0100 01.. .... ....			@b2_rd_ld_ub
CMP_rl		0000 0110 ..00 01.. .... ....		@b3_rd_ld

DIV_rri		1111 1101 0111 ..00 1000 ....		@b3_rd_li
DIV_rl		1111 1100 0010 00.. .... ....		@b3_rd_ld_ub
DIV_rl		0000 0110 ..10 00.. 0000 1000 .... ....	@b4_rd_ldmi

DIVU_rri	1111 1101 0111 ..00 1001 ....		@b3_rd_li
DIVU_rl		1111 1100 0010 01.. .... ....		@b3_rd_ld_ub
DIVU_rl		0000 0110 ..10 00.. 0000 1001 .... ....	@b4_rd_ldmi

EMUL_rri	1111 1101 0111 ..00 0110 ....		@b3_rd_li
EMUL_rl		1111 1100 0001 10.. .... ....		@b3_rd_ld_ub
EMUL_rl		0000 0110 ..10 00.. 0000 0110 .... ....	@b4_rd_ldmi

EMULU_rri	1111 1101 0111 ..00 0111 ....		@b3_rd_li
EMULU_rl	1111 1100 0001 11.. .... ....		@b3_rd_ld_ub
EMULU_rl	0000 0110 ..10 00.. 0000 0111 .... ....	@b4_rd_ldmi

FADD_ri		1111 1101 0111 0010 0010 rd:4
FADD_rl		1111 1100 1000 10.. .... ....		@b3_rd_ld_ul

FCMP_ri		1111 1101 0111 0010 0001 rd:4
FCMP_rl		1111 1100 1000 01.. .... ....		@b3_rd_ld_ul

FDIV_ri		1111 1101 0111 0010 0100 rd:4
FDIV_rl		1111 1100 1001 00.. .... ....		@b3_rd_ld_ul

FMUL_ri		1111 1101 0111 0010 0011 rd:4
FMUL_rl		1111 1100 1000 11.. .... ....		@b3_rd_ld_ul

FSUB_ri		1111 1101 0111 0010 0000 rd:4
FSUB_rl		1111 1100 1000 00.. .... ....		@b3_rd_ld_ul

FTOI		1111 1100 1001 01.. .... ....		@b3_rd_ld_ul

INT		0111 0101 0110 0000 imm:8

ITOF		1111 1100 0100 01.. .... ....		@b3_rd_ld_ub
ITOF		0000 0110 ..10 00.. 0001 0001 .... ....	@b4_rd_ldmi

JMP		0111 1111 0000 rs:4			&jreg
JSR		0111 1111 0001 rs:4			&jreg

MACHI		1111 1101 0000 0100 rs:4 rs2:4
MACLO		1111 1101 0000 0101 rs:4 rs2:4

MAX_ri		1111 1101 0111 ..00 0100 ....		@b3_rd_li
MAX_rl		1111 1100 0001 00.. .... ....		@b3_rd_ld_ub
MAX_rl		0000 0110 ..10 00.. 0000 0100 .... ....	@b4_rd_ldmi

MIN_ri		1111 1101 0111 ..00 0101 ....		@b3_rd_li
MIN_rl		1111 1100 0001 01.. .... ....		@b3_rd_ld_ub
MIN_rl		0000 0110 ..10 00.. 0000 0101 .... ....	@b4_rd_ldmi

MOV_mr		1000 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 mi=4
MOV_mr		1001 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 mi=3
MOV_mr		1010 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 mi=2
MOV_rm		1000 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 mi=0
MOV_rm		1001 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 mi=1
MOV_rm		1010 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 mi=2
MOV_ri		0110 0110 imm:4 rd:4
MOV_mi		0011 1100 . rd:3 .... imm:8		sz=0 dsp=%b3_dsp5_8
MOV_mi		0011 1101 . rd:3 .... imm:s8		sz=1 dsp=%b3_dsp5_8
MOV_mi		0011 1110 . rd:3 .... imm:s8		sz=2 dsp=%b3_dsp5_8
MOV_ri		0111 0101 0100 rd:4 imm:8
MOV_ri		1111 1011 rd:4 .. 10			imm=%b2_li_2
MOV_mi		1111 1000 rd:4 .. sz:2			dsp=0 imm=%b2_li_2
MOV_mi		1111 1001 rd:4 .. sz:2 dsp:8		imm=%b3_li_10
MOV_mi		1111 1010 rd:4 .. sz:2 dsp:16		imm=%b4_li_18
MOV_ar		1111 1110 01 sz:2 ri:4 rb:4 rd:4
MOV_ra		1111 1110 00 sz:2 ri:4 rb:4 rs:4
# Note ldd=3 and lds=3 indicate register src or dst
MOV_ll		1100 ldd:2 lds:2 rs:4 rd:4		sz=0
MOV_ll		1101 ldd:2 lds:2 rs:4 rd:4		sz=1
MOV_ll		1110 ldd:2 lds:2 rs:4 rd:4		sz=2
MOV_pr		1111 1101 0010 0 ad:1 sz:2 rd:4 rs:4
MOV_rp		1111 1101 0010 1 ad:1 sz:2 rs:4 rd:4

MOVU_rm		1011 sz:1 ... . rs:3 . rd:3		dsp=%b2_dsp5_3
MOVU_rl		0101 1 sz:1 ld:2 rs:4 rd:4
MOVU_ra		1111 1110 110 sz:1 ri:4 rb:4 rd:4
MOVU_rp		1111 1101 0011 1 ad:1 0 sz:1 rs:4 rd:4

MUL_ri		0110 0011 .... ....			@b2_rds_uimm4
MUL_ri		0111 01.. 0001 ....			@b2_rds_li
MUL_rl		0100 11.. .... ....			@b2_rd_ld_ub
MUL_rl		0000 0110 ..00 11.. .... ....		@b3_rd_ld
MUL_rrr		1111 1111 0011 .... .... ....		@b3_rd_rs_rs2

MULHI		1111 1101 0000 0000 rs:4 rs2:4
MULLO		1111 1101 0000 0001 rs:4 rs2:4

MVFACHI		1111 1101 0001 1111 0000 rd:4
MVFACMI		1111 1101 0001 1111 0010 rd:4

MVFC		1111 1101 0110 1010 cr:4 rd:4

MVTACHI		1111 1101 0001 0111 0000 rs:4
MVTACLO		1111 1101 0001 0111 0001 rs:4

MVTC_i		1111 1101 0111 ..11 0000 cr:4		imm=%b3_li_10
MVTC_r		1111 1101 0110 1000 rs:4 cr:4

NEG_rr		0111 1110 0001 ....			@b2_rds
NEG_rr		1111 1100 0000 0111 .... ....		@b3_rd_rs

NOP		0000 0011

NOT_rr		0111 1110 0000 ....			@b2_rds
NOT_rr		1111 1100 0011 1011 .... ....		@b3_rd_rs

OR_rri		0110 0101 .... ....			@b2_rds_uimm4
OR_rri		0111 01.. 0011 ....			@b2_rds_li
OR_rl		0101 01.. .... ....			@b2_rd_ld_ub
OR_rl		0000 0110 .. 0101 .. .... ....		@b3_rd_ld
OR_rrr		1111 1111 0101 .... .... ....		@b3_rd_rs_rs2

POP		0111 1110 1011 rd:4
POPC		0111 1110 1110 cr:4
POPM		0110 1111 rd:4 rd2:4

PUSH_r		0111 1110 1000 rs:4			sz=0
PUSH_r		0111 1110 1001 rs:4			sz=1
PUSH_r		0111 1110 1010 rs:4			sz=2
PUSH_m		1111 01 ld:2 rs:4 10 sz:2
PUSHC		0111 1110 1100 cr:4
PUSHM		0110 1110 rs:4 rs2:4

RACW		1111 1101 0001 1000 000 imm:1 0000

REVL		1111 1101 0110 0111 rs:4 rd:4
REVW		1111 1101 0110 0101 rs:4 rd:4

# Note that sz=3 overlaps SMOVF
RMPA		0111 1111 1000 1100			sz=0
RMPA		0111 1111 1000 1101			sz=1
RMPA		0111 1111 1000 1110			sz=2

ROLC		0111 1110 0101 ....			@b2_rds
RORC		0111 1110 0100 ....			@b2_rds

ROTL_ri		1111 1101 0110 111. .... ....		@b3_rds_imm5
ROTL_rr		1111 1101 0110 0110 .... ....		@b3_rd_rs

ROTR_ri		1111 1101 0110 110. .... ....		@b3_rds_imm5
ROTR_rr		1111 1101 0110 0100 .... ....		@b3_rd_rs

ROUND		1111 1100 1001 10 ld:2 rs:4 rd:4

RTE		0111 1111 1001 0101

RTFI		0111 1111 1001 0100

RTS		0000 0010

RTSD_i		0110 0111 imm:8
RTSD_irr	0011 1111 rd:4 rd2:4 imm:8

SAT		0111 1110 0011 ....			@b2_rds
SATR		0111 1111 1001 0011

SBB_rr		1111 1100 0000 0011 .... ....		@b3_rd_rs
# Note only mi==2 allowed.
SBB_rl		0000 0110 ..10 00.. 0000 0000 .... ....	@b4_rd_ldmi

SCCnd		1111 1100 1101 sz:2 ld:2 rd:4 cd:4

SCMPU		0111 1111 1000 0011

SETPSW		0111 1111 1010 cb:4

SHAR_rri	0110 101. .... ....			@b2_rds_imm5
SHAR_rri	1111 1101 101. .... .... ....		@b3_rd_rs_imm5
SHAR_rr		1111 1101 0110 0001 .... ....		@b3_rd_rs

SHLL_rri	0110 110. .... ....			@b2_rds_imm5
SHLL_rri	1111 1101 110. .... .... ....		@b3_rd_rs_imm5
SHLL_rr		1111 1101 0110 0010 .... ....		@b3_rd_rs

SHLR_rri	0110 100. .... ....			@b2_rds_imm5
SHLR_rri	1111 1101 100. .... .... ....		@b3_rd_rs_imm5
SHLR_rr		1111 1101 0110 0000 .... ....		@b3_rd_rs

SMOVB		0111 1111 1000 1011
SMOVF		0111 1111 1000 1111
SMOVU		0111 1111 1000 0111

# Note that sz=3 overlaps SMOVB
SSTR		0111 1111 1000 1000			sz=0
SSTR		0111 1111 1000 1001			sz=1
SSTR		0111 1111 1000 1010			sz=2

STNZ		1111 1101 0111 ..00 1111 ....		@b3_rd_li
STZ		1111 1101 0111 ..00 1110 ....		@b3_rd_li

SUB_rri		0110 0000 .... ....			@b2_rds_uimm4
SUB_rl		0100 00.. .... ....			@b2_rd_ld_ub
SUB_rl		0000 0110 ..00 00.. .... ....		@b3_rd_ld
SUB_rrr		1111 1111 0000 .... .... ....		@b3_rd_rs_rs2

# Note that sz=3 overlaps SCMPU
SUNTIL		0111 1111 1000 0000			sz=0
SUNTIL		0111 1111 1000 0001			sz=1
SUNTIL		0111 1111 1000 0010			sz=2

# Note that sz=3 overlaps SMOVU
SWHILE		0111 1111 1000 0100			sz=0
SWHILE		0111 1111 1000 0101			sz=1
SWHILE		0111 1111 1000 0110			sz=2

TST_ri		1111 1101 0111 ..00 1100 ....		@b3_rd_li

WAIT		0111 1111 1001 0110

XCHG_rl		1111 1100 0100 00.. .... ....		@b3_rd_ld_ub
XCHG_rl		0000 0110 ..10 00.. 0001 0000 .... ....	@b4_rd_ldmi

XOR_rri		1111 1101 0111 ..00 1101 ....		@b3_rd_li
XOR_rl		1111 1100 0011 01.. .... ....		@b3_rd_ld_ub
XOR_rl		0000 0110 ..10 00.. 0000 1101 .... ....	@b4_rd_ldmi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/2] decodetree: Initial support for variable-length ISAs
  2019-01-31 21:08 [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Richard Henderson
@ 2019-01-31 21:08 ` Richard Henderson
  2022-06-29 13:07   ` Peter Maydell
  2019-01-31 21:08 ` [Qemu-devel] [PATCH 2/2] decodetree: Expand a decode_load function Richard Henderson
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2019-01-31 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: ysato

Assuming that the ISA clearly describes how to determine
the length of the instruction, and the ISA has a reasonable
maximum instruction length, the input to the decoder can be
right-justified in an appropriate insn word.

This is not 100% convenient, as out-of-line %fields are
numbered relative to the maximum instruction length, but
this appears to still be usable.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 scripts/decodetree.py | 38 ++++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 2f8b5a1c92..5fb0acaa15 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -159,6 +159,7 @@ import getopt
 
 insnwidth = 32
 insnmask = 0xffffffff
+variablewidth = False
 fields = {}
 arguments = {}
 formats = {}
@@ -420,7 +421,7 @@ class Arguments:
 
 class General:
     """Common code between instruction formats and instruction patterns"""
-    def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds):
+    def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds, w):
         self.name = name
         self.file = input_file
         self.lineno = lineno
@@ -430,6 +431,7 @@ class General:
         self.undefmask = udfm
         self.fieldmask = fldm
         self.fields = flds
+        self.width = w
 
     def __str__(self):
         r = self.name
@@ -597,7 +599,7 @@ def infer_argument_set(flds):
     return arg
 
 
-def infer_format(arg, fieldmask, flds):
+def infer_format(arg, fieldmask, flds, width):
     global arguments
     global formats
     global decode_function
@@ -616,6 +618,8 @@ def infer_format(arg, fieldmask, flds):
             continue
         if fieldmask != fmt.fieldmask:
             continue
+        if width != fmt.width:
+            continue
         if not eq_fields_for_fmts(flds, fmt.fields):
             continue
         return (fmt, const_flds)
@@ -624,7 +628,7 @@ def infer_format(arg, fieldmask, flds):
     if not arg:
         arg = infer_argument_set(flds)
 
-    fmt = Format(name, 0, arg, 0, 0, 0, fieldmask, var_flds)
+    fmt = Format(name, 0, arg, 0, 0, 0, fieldmask, var_flds, width)
     formats[name] = fmt
 
     return (fmt, const_flds)
@@ -640,6 +644,7 @@ def parse_generic(lineno, is_format, name, toks):
     global re_ident
     global insnwidth
     global insnmask
+    global variablewidth
 
     fixedmask = 0
     fixedbits = 0
@@ -725,8 +730,15 @@ def parse_generic(lineno, is_format, name, toks):
             error(lineno, 'invalid token "{0}"'.format(t))
         width += shift
 
+    if variablewidth and width < insnwidth and width % 8 == 0:
+        shift = insnwidth - width
+        fixedbits <<= shift
+        fixedmask <<= shift
+        undefmask <<= shift
+        undefmask |= (1 << shift) - 1
+
     # We should have filled in all of the bits of the instruction.
-    if not (is_format and width == 0) and width != insnwidth:
+    elif not (is_format and width == 0) and width != insnwidth:
         error(lineno, 'definition has {0} bits'.format(width))
 
     # Do not check for fields overlaping fields; one valid usage
@@ -752,7 +764,7 @@ def parse_generic(lineno, is_format, name, toks):
         if name in formats:
             error(lineno, 'duplicate format name', name)
         fmt = Format(name, lineno, arg, fixedbits, fixedmask,
-                     undefmask, fieldmask, flds)
+                     undefmask, fieldmask, flds, width)
         formats[name] = fmt
     else:
         # Patterns can reference a format ...
@@ -762,12 +774,14 @@ def parse_generic(lineno, is_format, name, toks):
                 error(lineno, 'pattern specifies both format and argument set')
             if fixedmask & fmt.fixedmask:
                 error(lineno, 'pattern fixed bits overlap format fixed bits')
+            if width != fmt.width:
+                error(lineno, 'pattern uses format of different width')
             fieldmask |= fmt.fieldmask
             fixedbits |= fmt.fixedbits
             fixedmask |= fmt.fixedmask
             undefmask |= fmt.undefmask
         else:
-            (fmt, flds) = infer_format(arg, fieldmask, flds)
+            (fmt, flds) = infer_format(arg, fieldmask, flds, width)
         arg = fmt.base
         for f in flds.keys():
             if f not in arg.fields:
@@ -779,7 +793,7 @@ def parse_generic(lineno, is_format, name, toks):
             if f not in flds.keys() and f not in fmt.fields.keys():
                 error(lineno, 'field {0} not initialized'.format(f))
         pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
-                      undefmask, fieldmask, flds)
+                      undefmask, fieldmask, flds, width)
         patterns.append(pat)
 
     # Validate the masks that we have assembled.
@@ -987,12 +1001,14 @@ def main():
     global insntype
     global insnmask
     global decode_function
+    global variablewidth
 
     decode_scope = 'static '
 
-    long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=']
+    long_opts = ['decode=', 'translate=',
+                 'output=', 'insnwidth=', 'varinsnwidth=']
     try:
-        (opts, args) = getopt.getopt(sys.argv[1:], 'o:w:', long_opts)
+        (opts, args) = getopt.getopt(sys.argv[1:], 'o:vw:', long_opts)
     except getopt.GetoptError as err:
         error(0, err)
     for o, a in opts:
@@ -1004,7 +1020,9 @@ def main():
         elif o == '--translate':
             translate_prefix = a
             translate_scope = ''
-        elif o in ('-w', '--insnwidth'):
+        elif o in ('-w', '--insnwidth', '--varinsnwidth'):
+            if o == '--varinsnwidth':
+                variablewidth = True
             insnwidth = int(a)
             if insnwidth == 16:
                 insntype = 'uint16_t'
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/2] decodetree: Expand a decode_load function
  2019-01-31 21:08 [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Richard Henderson
  2019-01-31 21:08 ` [Qemu-devel] [PATCH 1/2] decodetree: Initial support " Richard Henderson
@ 2019-01-31 21:08 ` Richard Henderson
  2019-02-02  8:16 ` [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Yoshinori Sato
  2019-03-02  6:39 ` [Qemu-devel] [PATCH] decodetree: Add DisasContext to function part Yoshinori Sato
  3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2019-01-31 21:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: ysato

Read the instruction, loading no more bytes than necessary.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 scripts/decodetree.py | 175 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 172 insertions(+), 3 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 5fb0acaa15..05b6b3d18b 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -966,6 +966,147 @@ def build_tree(pats, outerbits, outermask):
 # end build_tree
 
 
+class SizeTree:
+    """Class representing a node in a size decode tree"""
+
+    def __init__(self, m, w):
+        self.mask = m
+        self.subs = []
+        self.base = None
+        self.width = w
+
+    def str1(self, i):
+        ind = str_indent(i)
+        r = '{0}{1:08x}'.format(ind, self.mask)
+        r += ' [\n'
+        for (b, s) in self.subs:
+            r += '{0}  {1:08x}:\n'.format(ind, b)
+            r += s.str1(i + 4) + '\n'
+        r += ind + ']'
+        return r
+
+    def __str__(self):
+        return self.str1(0)
+
+    def output_code(self, i, extracted, outerbits, outermask):
+        ind = str_indent(i)
+
+        # If we need to load more bytes to test, do so now.
+        if extracted < self.width:
+            output(ind, 'insn = ', decode_function,
+                   '_load_bytes(s, insn, {0}, {1});\n'
+                   .format(extracted / 8, self.width / 8));
+            extracted = self.width
+
+        # Attempt to aid the compiler in producing compact switch statements.
+        # If the bits in the mask are contiguous, extract them.
+        sh = is_contiguous(self.mask)
+        if sh > 0:
+            # Propagate SH down into the local functions.
+            def str_switch(b, sh=sh):
+                return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh)
+
+            def str_case(b, sh=sh):
+                return '0x{0:x}'.format(b >> sh)
+        else:
+            def str_switch(b):
+                return 'insn & 0x{0:08x}'.format(b)
+
+            def str_case(b):
+                return '0x{0:08x}'.format(b)
+
+        output(ind, 'switch (', str_switch(self.mask), ') {\n')
+        for b, s in sorted(self.subs):
+            innermask = outermask | self.mask
+            innerbits = outerbits | b
+            output(ind, 'case ', str_case(b), ':\n')
+            output(ind, '    /* ',
+                   str_match_bits(innerbits, innermask), ' */\n')
+            s.output_code(i + 4, extracted, innerbits, innermask)
+        output(ind, '}\n')
+        output(ind, 'return insn;\n')
+# end SizeTree
+
+class SizeLeaf:
+    """Class representing a leaf node in a size decode tree"""
+
+    def __init__(self, m, w):
+        self.mask = m
+        self.width = w
+
+    def str1(self, i):
+        ind = str_indent(i)
+        return '{0}{1:08x}'.format(ind, self.mask)
+
+    def __str__(self):
+        return self.str1(0)
+
+    def output_code(self, i, extracted, outerbits, outermask):
+        global decode_function
+        ind = str_indent(i)
+
+        # If we need to load more bytes, do so now.
+        if extracted < self.width:
+            output(ind, 'insn = ', decode_function,
+                   '_load_bytes(s, insn, {0}, {1});\n'
+                   .format(extracted / 8, self.width / 8));
+            extracted = self.width
+        output(ind, 'return insn;\n')
+# end SizeLeaf
+
+
+def build_size_tree(pats, width, outerbits, outermask):
+    global insnwidth
+
+    # Collect the mask of bits that are fixed in this width
+    innermask = 0xff << (insnwidth - width)
+    innermask &= ~outermask
+    minwidth = None
+    onewidth = True
+    for i in pats:
+        innermask &= i.fixedmask
+        if minwidth is None:
+            minwidth = i.width
+        elif minwidth != i.width:
+            onewidth = False;
+            if minwidth < i.width:
+                minwidth = i.width
+
+    if onewidth:
+        return SizeLeaf(innermask, minwidth)
+
+    if innermask == 0:
+        if width < minwidth:
+            return build_size_tree(pats, width + 8, outerbits, outermask)
+
+        pnames = []
+        for p in pats:
+            pnames.append(p.name + ':' + p.file + ':' + str(p.lineno))
+        error_with_file(pats[0].file, pats[0].lineno,
+                        'overlapping patterns size {0}:'.format(width), pnames)
+
+    bins = {}
+    for i in pats:
+        fb = i.fixedbits & innermask
+        if fb in bins:
+            bins[fb].append(i)
+        else:
+            bins[fb] = [i]
+
+    fullmask = outermask | innermask
+    lens = sorted(bins.keys())
+    if len(lens) == 1:
+        b = lens[0]
+        return build_size_tree(bins[b], width + 8, b | outerbits, fullmask)
+
+    r = SizeTree(innermask, width)
+    for b, l in bins.items():
+        s = build_size_tree(l, width, b | outerbits, fullmask)
+        r.subs.append((b, s))
+    return r
+# end build_size_tree
+
+
 def prop_format(tree):
     """Propagate Format objects into the decode tree"""
 
@@ -988,6 +1129,23 @@ def prop_format(tree):
 # end prop_format
 
 
+def prop_size(tree):
+    """Propagate minimum widths up the decode size tree"""
+
+    if isinstance(tree, SizeTree):
+        min = None
+        for (b, s) in tree.subs:
+            width = prop_size(s)
+            if min is None or min > width:
+                min = width
+        assert min >= tree.width
+        tree.width = min
+    else:
+        min = tree.width
+    return min
+# end prop_size
+
+
 def main():
     global arguments
     global formats
@@ -1040,8 +1198,12 @@ def main():
         parse_file(f)
         f.close()
 
-    t = build_tree(patterns, 0, 0)
-    prop_format(t)
+    if variablewidth:
+        stree = build_size_tree(patterns, 8, 0, 0)
+        prop_size(stree)
+
+    dtree = build_tree(patterns, 0, 0)
+    prop_format(dtree)
 
     if output_file:
         output_fd = open(output_file, 'w')
@@ -1081,10 +1243,17 @@ def main():
         output(i4, i4, f.struct_name(), ' f_', f.name, ';\n')
     output(i4, '} u;\n\n')
 
-    t.output_code(4, False, 0, 0)
+    dtree.output_code(4, False, 0, 0)
 
     output('}\n')
 
+    if variablewidth:
+        output('\n', decode_scope, insntype, ' ', decode_function,
+               '_load(DisasContext *ctx)\n{\n',
+               '    ', insntype, ' insn = 0;\n\n')
+        stree.output_code(4, 0, 0, 0)
+        output('}\n')
+
     if output_file:
         output_fd.close()
 # end main
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs
  2019-01-31 21:08 [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Richard Henderson
  2019-01-31 21:08 ` [Qemu-devel] [PATCH 1/2] decodetree: Initial support " Richard Henderson
  2019-01-31 21:08 ` [Qemu-devel] [PATCH 2/2] decodetree: Expand a decode_load function Richard Henderson
@ 2019-02-02  8:16 ` Yoshinori Sato
  2019-03-02  6:39 ` [Qemu-devel] [PATCH] decodetree: Add DisasContext to function part Yoshinori Sato
  3 siblings, 0 replies; 6+ messages in thread
From: Yoshinori Sato @ 2019-02-02  8:16 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

On Fri, 01 Feb 2019 06:08:49 +0900,
Richard Henderson wrote:
> 
> I'm not sure how much simplication could be had for "simple"
> variable-length ISAs like ARM thumb2 or RISC-V.
> 
> But the recently posted RX port is more complicated than those.
> For me, what makes RX more difficult is that there is no easy
> test of the first N bits to determine the length of the insn.
> 
> I put together a starting point for the RX decode.  I'm sure
> there are a few mistakes, but it's close enough to see how the
> decoding might work.
> 
> I have chosen to have this RX decoder only consider the "base"
> instruction, without the "extra" bits like the immediate associated
> with the LI field, or the memory displacement associated with
> the LD field.
> 
> The new decode_load function reads the bytes of the insn with
> minimal decoding and no further validation of invalid insns;
> that is left for the main decode function.

I tried that several MOV instructions can be decoded correctly.
I will confirm the rest of the instructions from now,
but I think that there is no problem because it is not as
complicated as MOV.

> This is expecting a helper function that assembles the bytes.
> While I say I rule out Thumb2+RISC-V above, they are not implausible
> examples.  These have uint16_t granularity, and I didn't want to
> assume the endianness of the granules.
> 
> But for RX, with byte granularity,
> 
> uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
>                            int i, int n)
> {
>     while (++i <= n) {
>         uint8_t b = cpu_ldub_code(ctx->env, ctx->base.pc_next++);
>         insn |= b << (32 - i * 8);
>     }
>     return insn;
> }
> 
> For the actual port submission, I would break up the translation
> into small bits.  Just a few lines into the decode file and the
> associated functions within translate.c.
>

OK.
Too many thanks.

> 
> r~
> 
> 
> Richard Henderson (2):
>   decodetree: Initial support for variable-length ISAs
>   decodetree: Expand a decode_load function
> 
>  scripts/decodetree.py | 213 +++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 200 insertions(+), 13 deletions(-)
> 
> ---
> 
> &bcnd		cd dsp
> &jdsp		dsp
> &jreg		rs
> &rr		rd rs
> &ri		rd imm
> &rrr		rd rs rs2
> &rri		rd imm rs2
> &rm		rd rs ld mi
> &mi		rs ld mi imm
> &mr		rs ld mi rs2
> 
> ########
> 
> %b2_r_0		16:4
> %b2_li_2	18:2 !function=li
> %b2_li_8	24:2 !function=li
> %b2_dsp5_3	23:4 19:1
> 
> @b2_rds		.... .... .... rd:4		&rr rs=%b2_r_0
> @b2_rds_li	.... .... .... rd:4		&rri rs2=%b2_r_0 imm=%b2_li_8
> @b2_rds_uimm4	.... .... imm:4 rd:4		&rri rs2=%b2_r_0
> @b2_rds_imm5	.... ... imm:5 rd:4		&rri rs2=%b2_r_0
> @b2_rd_rs_li	.... .... rs2:4 rd:4		&rri imm=%b2_li_8
> @b2_rd_ld_ub	.... .. ld:2 rs:4 rd:4		&rm mi=4
> @b2_ld_imm3	.... .. ld:2 rs:4 . imm:3	&mi mi=4
> 
> ########
> 
> %b3_r_0		8:4
> %b3_li_10	18:2 !function=li
> %b3_dsp5_8	23:1 16:4
> 
> @b3_rd_rs	.... .... .... .... rs:4 rd:4		&rr
> @b3_rd_li	.... .... .... .... .... rd:4 \
> 		&rri rs2=%b3_r_0 imm=%b3_li_10
> @b3_rd_ld	.... .... mi:2 .... ld:2 rs:4 rd:4	&rm
> @b3_rd_ld_ub	.... .... .... .. ld:2 rs:4 rd:4	&rm mi=4
> @b3_rd_ld_ul	.... .... .... .. ld:2 rs:4 rd:4	&rm mi=2
> @b3_rd_rs_rs2	.... .... .... rd:4 rs:4 rs2:4		&rrr
> @b3_ld_rs2	.... .... .... .. ld:2 rs:4 rs2:4	&mr
> @b3_rds_imm5	.... .... ....... imm:5 rd:4		&rri rs2=%b3_r_0
> @b3_rd_rs_imm5	.... .... ... imm:5 rs2:4 rd:4		&rri
> 
> ########
> 
> %b4_li_18	18:2 !function=li
> 
> @b4_rd_ldmi	.... .... mi:2 .... ld:2 .... .... rs:4 rd:4	&rm
> 
> ########
> 
> ABS_rr		0111 1110 0010 ....			@b2_rds
> ABS_rr		1111 1100 0000 1111 .... ....		@b3_rd_rs
> 
> ADC_ri		1111 1101 0111 ..00 0000 ....		@b3_rd_li
> ADC_rr		1111 1100 0000 1011 .... ....		@b3_rd_rs
> # Note only mi==2 allowed.
> ADC_rl		0000 0110 ..10 00.. 0000 0010 .... ....	@b4_rd_ldmi
> 
> ADD_rri		0110 0010 .... ....			@b2_rds_uimm4
> ADD_rri		0111 00.. .... ....			@b2_rd_rs_li
> ADD_rl		0100 10.. .... ....			@b2_rd_ld_ub
> ADD_rl		0000 0110 ..00 10.. .... ....		@b3_rd_ld
> ADD_rrr		1111 1111 0010 .... .... ....		@b3_rd_rs_rs2
> 
> AND_rri		0110 0100 .... ....			@b2_rds_uimm4
> AND_rri		0111 01.. 0010 ....			@b2_rds_li
> AND_rl		0101 00.. .... ....			@b2_rd_ld_ub
> AND_rl		0000 0110 ..01 00.. .... ....		@b3_rd_ld
> AND_rrr		1111 1111 0100 .... .... ....		@b3_rd_rs_rs2
> 
> BCLR_li		1111 00.. .... 1...			@b2_ld_imm3
> BCLR_ri		0111 101. .... ....			@b2_rds_imm5
> BCLR_lr		1111 1100 0110 01.. .... ....		@b3_ld_rs2 mi=4
> 
> BCnd_s		0001 cd:1 dsp:3				&bcnd
> BCnd_b		0010 cd:4 dsp:8				&bcnd
> BCnd_w		0011 101 cd:1 dsp:16			&bcnd
> 
> # Note that BNOT has cd = 15
> BMCnd_BNOT_mi	1111 1100 111 imm:3 ld:2 rd:4 cd:4
> BMCnd_BNOT_ri	1111 1101 111 imm:5 cd:4 rd:4
> 
> BNOT_lr		1111 1100 0110 11.. .... ....		@b3_ld_rs2 mi=2
> 
> BRA_s		0000 1 dsp:3				&jdsp
> #BRA_b		0010 1110 dsp:8		# overlaps BCnd_b
> BRA_w		0011 1000 dsp:16			&jdsp
> BRA_a		0000 0100 dsp:24			&jdsp
> 
> BRK		0000 0000
> 
> BSET_li		1111 00.. .... 0...			@b2_ld_imm3
> BSET_ri		0111 100. .... ....			@b2_rds_imm5
> BSET_lr		1111 1100 0110 00.. .... ....		@b3_ld_rs2 mi=4
> 
> BSR_w		0011 1001 dsp:16			&jdsp
> BSR_a		0000 0101 dsp:24			&jdsp
> 
> BTST_li		1111 01.. .... 0...			@b2_ld_imm3
> BTST_ri		0111 110. .... ....			@b2_rds_imm5
> BTST_lr		1111 1100 0110 10.. .... ....		@b3_ld_rs2 mi=4
> 
> CLRPSW		0111 1111 1011 cb:4
> 
> CMP_ri		0110 0001 .... ....			@b2_rds_uimm4
> CMP_ri		0111 0101 0101 rs2:4 imm:8		&rri rd=0
> CMP_ri		0111 01.. 0000 rs2:4			&rri imm=%b2_li_8 rd=0
> CMP_rl		0100 01.. .... ....			@b2_rd_ld_ub
> CMP_rl		0000 0110 ..00 01.. .... ....		@b3_rd_ld
> 
> DIV_rri		1111 1101 0111 ..00 1000 ....		@b3_rd_li
> DIV_rl		1111 1100 0010 00.. .... ....		@b3_rd_ld_ub
> DIV_rl		0000 0110 ..10 00.. 0000 1000 .... ....	@b4_rd_ldmi
> 
> DIVU_rri	1111 1101 0111 ..00 1001 ....		@b3_rd_li
> DIVU_rl		1111 1100 0010 01.. .... ....		@b3_rd_ld_ub
> DIVU_rl		0000 0110 ..10 00.. 0000 1001 .... ....	@b4_rd_ldmi
> 
> EMUL_rri	1111 1101 0111 ..00 0110 ....		@b3_rd_li
> EMUL_rl		1111 1100 0001 10.. .... ....		@b3_rd_ld_ub
> EMUL_rl		0000 0110 ..10 00.. 0000 0110 .... ....	@b4_rd_ldmi
> 
> EMULU_rri	1111 1101 0111 ..00 0111 ....		@b3_rd_li
> EMULU_rl	1111 1100 0001 11.. .... ....		@b3_rd_ld_ub
> EMULU_rl	0000 0110 ..10 00.. 0000 0111 .... ....	@b4_rd_ldmi
> 
> FADD_ri		1111 1101 0111 0010 0010 rd:4
> FADD_rl		1111 1100 1000 10.. .... ....		@b3_rd_ld_ul
> 
> FCMP_ri		1111 1101 0111 0010 0001 rd:4
> FCMP_rl		1111 1100 1000 01.. .... ....		@b3_rd_ld_ul
> 
> FDIV_ri		1111 1101 0111 0010 0100 rd:4
> FDIV_rl		1111 1100 1001 00.. .... ....		@b3_rd_ld_ul
> 
> FMUL_ri		1111 1101 0111 0010 0011 rd:4
> FMUL_rl		1111 1100 1000 11.. .... ....		@b3_rd_ld_ul
> 
> FSUB_ri		1111 1101 0111 0010 0000 rd:4
> FSUB_rl		1111 1100 1000 00.. .... ....		@b3_rd_ld_ul
> 
> FTOI		1111 1100 1001 01.. .... ....		@b3_rd_ld_ul
> 
> INT		0111 0101 0110 0000 imm:8
> 
> ITOF		1111 1100 0100 01.. .... ....		@b3_rd_ld_ub
> ITOF		0000 0110 ..10 00.. 0001 0001 .... ....	@b4_rd_ldmi
> 
> JMP		0111 1111 0000 rs:4			&jreg
> JSR		0111 1111 0001 rs:4			&jreg
> 
> MACHI		1111 1101 0000 0100 rs:4 rs2:4
> MACLO		1111 1101 0000 0101 rs:4 rs2:4
> 
> MAX_ri		1111 1101 0111 ..00 0100 ....		@b3_rd_li
> MAX_rl		1111 1100 0001 00.. .... ....		@b3_rd_ld_ub
> MAX_rl		0000 0110 ..10 00.. 0000 0100 .... ....	@b4_rd_ldmi
> 
> MIN_ri		1111 1101 0111 ..00 0101 ....		@b3_rd_li
> MIN_rl		1111 1100 0001 01.. .... ....		@b3_rd_ld_ub
> MIN_rl		0000 0110 ..10 00.. 0000 0101 .... ....	@b4_rd_ldmi
> 
> MOV_mr		1000 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 mi=4
> MOV_mr		1001 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 mi=3
> MOV_mr		1010 0 .... rd:3 . rs:3			dsp=%b2_dsp5_3 mi=2
> MOV_rm		1000 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 mi=0
> MOV_rm		1001 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 mi=1
> MOV_rm		1010 1 .... rs:3 . rd:3			dsp=%b2_dsp5_3 mi=2
> MOV_ri		0110 0110 imm:4 rd:4
> MOV_mi		0011 1100 . rd:3 .... imm:8		sz=0 dsp=%b3_dsp5_8
> MOV_mi		0011 1101 . rd:3 .... imm:s8		sz=1 dsp=%b3_dsp5_8
> MOV_mi		0011 1110 . rd:3 .... imm:s8		sz=2 dsp=%b3_dsp5_8
> MOV_ri		0111 0101 0100 rd:4 imm:8
> MOV_ri		1111 1011 rd:4 .. 10			imm=%b2_li_2
> MOV_mi		1111 1000 rd:4 .. sz:2			dsp=0 imm=%b2_li_2
> MOV_mi		1111 1001 rd:4 .. sz:2 dsp:8		imm=%b3_li_10
> MOV_mi		1111 1010 rd:4 .. sz:2 dsp:16		imm=%b4_li_18
> MOV_ar		1111 1110 01 sz:2 ri:4 rb:4 rd:4
> MOV_ra		1111 1110 00 sz:2 ri:4 rb:4 rs:4
> # Note ldd=3 and lds=3 indicate register src or dst
> MOV_ll		1100 ldd:2 lds:2 rs:4 rd:4		sz=0
> MOV_ll		1101 ldd:2 lds:2 rs:4 rd:4		sz=1
> MOV_ll		1110 ldd:2 lds:2 rs:4 rd:4		sz=2
> MOV_pr		1111 1101 0010 0 ad:1 sz:2 rd:4 rs:4
> MOV_rp		1111 1101 0010 1 ad:1 sz:2 rs:4 rd:4
> 
> MOVU_rm		1011 sz:1 ... . rs:3 . rd:3		dsp=%b2_dsp5_3
> MOVU_rl		0101 1 sz:1 ld:2 rs:4 rd:4
> MOVU_ra		1111 1110 110 sz:1 ri:4 rb:4 rd:4
> MOVU_rp		1111 1101 0011 1 ad:1 0 sz:1 rs:4 rd:4
> 
> MUL_ri		0110 0011 .... ....			@b2_rds_uimm4
> MUL_ri		0111 01.. 0001 ....			@b2_rds_li
> MUL_rl		0100 11.. .... ....			@b2_rd_ld_ub
> MUL_rl		0000 0110 ..00 11.. .... ....		@b3_rd_ld
> MUL_rrr		1111 1111 0011 .... .... ....		@b3_rd_rs_rs2
> 
> MULHI		1111 1101 0000 0000 rs:4 rs2:4
> MULLO		1111 1101 0000 0001 rs:4 rs2:4
> 
> MVFACHI		1111 1101 0001 1111 0000 rd:4
> MVFACMI		1111 1101 0001 1111 0010 rd:4
> 
> MVFC		1111 1101 0110 1010 cr:4 rd:4
> 
> MVTACHI		1111 1101 0001 0111 0000 rs:4
> MVTACLO		1111 1101 0001 0111 0001 rs:4
> 
> MVTC_i		1111 1101 0111 ..11 0000 cr:4		imm=%b3_li_10
> MVTC_r		1111 1101 0110 1000 rs:4 cr:4
> 
> NEG_rr		0111 1110 0001 ....			@b2_rds
> NEG_rr		1111 1100 0000 0111 .... ....		@b3_rd_rs
> 
> NOP		0000 0011
> 
> NOT_rr		0111 1110 0000 ....			@b2_rds
> NOT_rr		1111 1100 0011 1011 .... ....		@b3_rd_rs
> 
> OR_rri		0110 0101 .... ....			@b2_rds_uimm4
> OR_rri		0111 01.. 0011 ....			@b2_rds_li
> OR_rl		0101 01.. .... ....			@b2_rd_ld_ub
> OR_rl		0000 0110 .. 0101 .. .... ....		@b3_rd_ld
> OR_rrr		1111 1111 0101 .... .... ....		@b3_rd_rs_rs2
> 
> POP		0111 1110 1011 rd:4
> POPC		0111 1110 1110 cr:4
> POPM		0110 1111 rd:4 rd2:4
> 
> PUSH_r		0111 1110 1000 rs:4			sz=0
> PUSH_r		0111 1110 1001 rs:4			sz=1
> PUSH_r		0111 1110 1010 rs:4			sz=2
> PUSH_m		1111 01 ld:2 rs:4 10 sz:2
> PUSHC		0111 1110 1100 cr:4
> PUSHM		0110 1110 rs:4 rs2:4
> 
> RACW		1111 1101 0001 1000 000 imm:1 0000
> 
> REVL		1111 1101 0110 0111 rs:4 rd:4
> REVW		1111 1101 0110 0101 rs:4 rd:4
> 
> # Note that sz=3 overlaps SMOVF
> RMPA		0111 1111 1000 1100			sz=0
> RMPA		0111 1111 1000 1101			sz=1
> RMPA		0111 1111 1000 1110			sz=2
> 
> ROLC		0111 1110 0101 ....			@b2_rds
> RORC		0111 1110 0100 ....			@b2_rds
> 
> ROTL_ri		1111 1101 0110 111. .... ....		@b3_rds_imm5
> ROTL_rr		1111 1101 0110 0110 .... ....		@b3_rd_rs
> 
> ROTR_ri		1111 1101 0110 110. .... ....		@b3_rds_imm5
> ROTR_rr		1111 1101 0110 0100 .... ....		@b3_rd_rs
> 
> ROUND		1111 1100 1001 10 ld:2 rs:4 rd:4
> 
> RTE		0111 1111 1001 0101
> 
> RTFI		0111 1111 1001 0100
> 
> RTS		0000 0010
> 
> RTSD_i		0110 0111 imm:8
> RTSD_irr	0011 1111 rd:4 rd2:4 imm:8
> 
> SAT		0111 1110 0011 ....			@b2_rds
> SATR		0111 1111 1001 0011
> 
> SBB_rr		1111 1100 0000 0011 .... ....		@b3_rd_rs
> # Note only mi==2 allowed.
> SBB_rl		0000 0110 ..10 00.. 0000 0000 .... ....	@b4_rd_ldmi
> 
> SCCnd		1111 1100 1101 sz:2 ld:2 rd:4 cd:4
> 
> SCMPU		0111 1111 1000 0011
> 
> SETPSW		0111 1111 1010 cb:4
> 
> SHAR_rri	0110 101. .... ....			@b2_rds_imm5
> SHAR_rri	1111 1101 101. .... .... ....		@b3_rd_rs_imm5
> SHAR_rr		1111 1101 0110 0001 .... ....		@b3_rd_rs
> 
> SHLL_rri	0110 110. .... ....			@b2_rds_imm5
> SHLL_rri	1111 1101 110. .... .... ....		@b3_rd_rs_imm5
> SHLL_rr		1111 1101 0110 0010 .... ....		@b3_rd_rs
> 
> SHLR_rri	0110 100. .... ....			@b2_rds_imm5
> SHLR_rri	1111 1101 100. .... .... ....		@b3_rd_rs_imm5
> SHLR_rr		1111 1101 0110 0000 .... ....		@b3_rd_rs
> 
> SMOVB		0111 1111 1000 1011
> SMOVF		0111 1111 1000 1111
> SMOVU		0111 1111 1000 0111
> 
> # Note that sz=3 overlaps SMOVB
> SSTR		0111 1111 1000 1000			sz=0
> SSTR		0111 1111 1000 1001			sz=1
> SSTR		0111 1111 1000 1010			sz=2
> 
> STNZ		1111 1101 0111 ..00 1111 ....		@b3_rd_li
> STZ		1111 1101 0111 ..00 1110 ....		@b3_rd_li
> 
> SUB_rri		0110 0000 .... ....			@b2_rds_uimm4
> SUB_rl		0100 00.. .... ....			@b2_rd_ld_ub
> SUB_rl		0000 0110 ..00 00.. .... ....		@b3_rd_ld
> SUB_rrr		1111 1111 0000 .... .... ....		@b3_rd_rs_rs2
> 
> # Note that sz=3 overlaps SCMPU
> SUNTIL		0111 1111 1000 0000			sz=0
> SUNTIL		0111 1111 1000 0001			sz=1
> SUNTIL		0111 1111 1000 0010			sz=2
> 
> # Note that sz=3 overlaps SMOVU
> SWHILE		0111 1111 1000 0100			sz=0
> SWHILE		0111 1111 1000 0101			sz=1
> SWHILE		0111 1111 1000 0110			sz=2
> 
> TST_ri		1111 1101 0111 ..00 1100 ....		@b3_rd_li
> 
> WAIT		0111 1111 1001 0110
> 
> XCHG_rl		1111 1100 0100 00.. .... ....		@b3_rd_ld_ub
> XCHG_rl		0000 0110 ..10 00.. 0001 0000 .... ....	@b4_rd_ldmi
> 
> XOR_rri		1111 1101 0111 ..00 1101 ....		@b3_rd_li
> XOR_rl		1111 1100 0011 01.. .... ....		@b3_rd_ld_ub
> XOR_rl		0000 0110 ..10 00.. 0000 1101 .... ....	@b4_rd_ldmi
> 

-- 
Yosinori Sato

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH] decodetree: Add DisasContext to function part
  2019-01-31 21:08 [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Richard Henderson
                   ` (2 preceding siblings ...)
  2019-02-02  8:16 ` [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Yoshinori Sato
@ 2019-03-02  6:39 ` Yoshinori Sato
  3 siblings, 0 replies; 6+ messages in thread
From: Yoshinori Sato @ 2019-03-02  6:39 UTC (permalink / raw)
  To: qemu-devel, Richard Henderson; +Cc: Yoshinori Sato

OK. RX decoder works fine.

Since it is necessary to read additional bytes in the function
of the operand, we need to have DisasContext passed as an argument.

> %b2_li_2	18:2 !function=li
"li" read more extra byte. It use cpu_env in DisasContext.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 scripts/decodetree.py | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index e23d43e354..fa9a75ccad 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -387,7 +387,11 @@ class FunctionField:
         return self.func + '(' + str(self.base) + ')'
 
     def str_extract(self):
-        return self.func + '(' + self.base.str_extract() + ')'
+        if variablewidth:
+            ctx = 'ctx, '
+        else:
+            ctx = ''
+        return self.func + '(' + ctx + self.base.str_extract() + ')'
 
     def __eq__(self, other):
         return self.func == other.func and self.base == other.base
@@ -454,7 +458,11 @@ class Format(General):
         return 'extract_' + self.name
 
     def output_extract(self):
-        output('static void ', self.extract_name(), '(',
+        if variablewidth:
+            ctx_p = 'DisasContext *ctx, '
+        else:
+            ctx_p = ''
+        output('static void ', self.extract_name(), '(' + ctx_p,
                self.base.struct_name(), ' *a, ', insntype, ' insn)\n{\n')
         for n, f in self.fields.items():
             output('    a->', n, ' = ', f.str_extract(), ';\n')
@@ -468,10 +476,14 @@ class Pattern(General):
     def output_decl(self):
         global translate_scope
         global translate_prefix
+        if variablewidth:
+            ctx_p = 'DisasContext *ctx, '
+        else:
+            ctx_p = ''
         output('typedef ', self.base.base.struct_name(),
                ' arg_', self.name, ';\n')
         output(translate_scope, 'bool ', translate_prefix, '_', self.name,
-               '(DisasContext *ctx, arg_', self.name, ' *a);\n')
+               '(', ctx_p, 'arg_', self.name, ' *a);\n')
 
     def output_code(self, i, extracted, outerbits, outermask):
         global translate_prefix
@@ -479,7 +491,8 @@ class Pattern(General):
         arg = self.base.base.name
         output(ind, '/* ', self.file, ':', str(self.lineno), ' */\n')
         if not extracted:
-            output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
+            output(ind, self.base.extract_name(),
+                   '(ctx, &u.f_', arg, ', insn);\n')
         for n, f in self.fields.items():
             output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
         output(ind, 'return ', translate_prefix, '_', self.name,
@@ -890,11 +903,16 @@ class Tree:
     def output_code(self, i, extracted, outerbits, outermask):
         ind = str_indent(i)
 
+        if variablewidth:
+            ctx = 'ctx, '
+        else:
+            ctx = ''
         # If we identified all nodes below have the same format,
         # extract the fields now.
         if not extracted and self.base:
             output(ind, self.base.extract_name(),
-                   '(&u.f_', self.base.base.name, ', insn);\n')
+                   '(', ctx, '&u.f_', self.base.base.name,
+                   ', insn);\n')
             extracted = True
 
         # Attempt to aid the compiler in producing compact switch statements.
@@ -994,7 +1012,7 @@ class SizeTree:
         # If we need to load more bytes to test, do so now.
         if extracted < self.width:
             output(ind, 'insn = ', decode_function,
-                   '_load_bytes(s, insn, {0}, {1});\n'
+                   '_load_bytes(ctx, insn, {0}, {1});\n'
                    .format(extracted / 8, self.width / 8));
             extracted = self.width
 
@@ -1048,7 +1066,7 @@ class SizeLeaf:
         # If we need to load more bytes, do so now.
         if extracted < self.width:
             output(ind, 'insn = ', decode_function,
-                   '_load_bytes(s, insn, {0}, {1});\n'
+                   '_load_bytes(ctx, insn, {0}, {1});\n'
                    .format(extracted / 8, self.width / 8));
             extracted = self.width
         output(ind, 'return insn;\n')
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] decodetree: Initial support for variable-length ISAs
  2019-01-31 21:08 ` [Qemu-devel] [PATCH 1/2] decodetree: Initial support " Richard Henderson
@ 2022-06-29 13:07   ` Peter Maydell
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2022-06-29 13:07 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, ysato

On Thu, 31 Jan 2019 at 21:10, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Assuming that the ISA clearly describes how to determine
> the length of the instruction, and the ISA has a reasonable
> maximum instruction length, the input to the decoder can be
> right-justified in an appropriate insn word.
>
> This is not 100% convenient, as out-of-line %fields are
> numbered relative to the maximum instruction length, but
> this appears to still be usable.

Prompted by a query on IRC I noticed that this patch from a few
years back added variable-insn-width support to decodetree,
including a new commandline argument --varinsnwidth, but
we don't document how to use it in docs/devel/decodetree.rst.
In fact decodetree.rst doesn't document decodetree.py's
commandline options at all. Could you maybe write up a
docs patch to describe them?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-06-29 13:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-31 21:08 [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Richard Henderson
2019-01-31 21:08 ` [Qemu-devel] [PATCH 1/2] decodetree: Initial support " Richard Henderson
2022-06-29 13:07   ` Peter Maydell
2019-01-31 21:08 ` [Qemu-devel] [PATCH 2/2] decodetree: Expand a decode_load function Richard Henderson
2019-02-02  8:16 ` [Qemu-devel] [PATCH 0/2] decodetree: Support for variable-length ISAs Yoshinori Sato
2019-03-02  6:39 ` [Qemu-devel] [PATCH] decodetree: Add DisasContext to function part Yoshinori Sato

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.