public inbox for cgen@sourceware.org
 help / color / mirror / Atom feed
* How does CGEN decide what ifields to use for CGEN_IVALUE?
@ 2009-01-14 17:09 John Stubley
  2009-01-14 18:49 ` Dave Brolley
  0 siblings, 1 reply; 5+ messages in thread
From: John Stubley @ 2009-01-14 17:09 UTC (permalink / raw)
  To: cgen

Hi,

I am writing a binutils port for our own internal proprietary CPU using
CGEN.  I am using binutils v2.19 stable and cgen monthly snapshot
20081101.

I am seeing some odd behaviour in the disassembly shown by objdump when
it is analysing the opcodes I am generating using GAS.  In some cases,
if I change the value of an operand I can cause the disassembler to fail
to recognise the opcode.

Our instruction packing is quite tight and so some of the operand fields
overlap with some of the opcode mnemonic fields.  I have tried to define
the instruction families so that they don't overlap, but I can't quite
do it.  Ideally, I would like to teach CGEN a simple hierarchy of
mnemonics so that it can order the opcode table correctly.  However, it
appears at first instance that there is no way to write the .cpu file to
give CGEN enough hints.  I assume it has something to do with the
CGEN_OPCODE_* macros for CGEN_IVALUE in cgen.h.  I have tried setting
the decode-assist in the define-isa, but this appears to have no effect.

I would appreciate any pointers that you could give me, particularly if
there is an existing CPU that attempts something similar.

With thanks,

John Stubley
Development Engineer
DisplayLink (UK) Limited

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

* Re: How does CGEN decide what ifields to use for CGEN_IVALUE?
  2009-01-14 17:09 How does CGEN decide what ifields to use for CGEN_IVALUE? John Stubley
@ 2009-01-14 18:49 ` Dave Brolley
  2009-01-16  8:36   ` John Stubley
  0 siblings, 1 reply; 5+ messages in thread
From: Dave Brolley @ 2009-01-14 18:49 UTC (permalink / raw)
  To: John Stubley; +Cc: cgen

Can you give an example of a set of insns with this problem? I's hard to 
help without seeing the specifics. In general, I've found that 
disassembly problems are usuallu due to incompletely specified insns, 
i.e. not all bits are completely specified in the .cpu file.

Dave

John Stubley wrote:
> Hi,
>
> I am writing a binutils port for our own internal proprietary CPU using
> CGEN.  I am using binutils v2.19 stable and cgen monthly snapshot
> 20081101.
>
> I am seeing some odd behaviour in the disassembly shown by objdump when
> it is analysing the opcodes I am generating using GAS.  In some cases,
> if I change the value of an operand I can cause the disassembler to fail
> to recognise the opcode.
>
> Our instruction packing is quite tight and so some of the operand fields
> overlap with some of the opcode mnemonic fields.  I have tried to define
> the instruction families so that they don't overlap, but I can't quite
> do it.  Ideally, I would like to teach CGEN a simple hierarchy of
> mnemonics so that it can order the opcode table correctly.  However, it
> appears at first instance that there is no way to write the .cpu file to
> give CGEN enough hints.  I assume it has something to do with the
> CGEN_OPCODE_* macros for CGEN_IVALUE in cgen.h.  I have tried setting
> the decode-assist in the define-isa, but this appears to have no effect.
>
> I would appreciate any pointers that you could give me, particularly if
> there is an existing CPU that attempts something similar.
>
> With thanks,
>
> John Stubley
> Development Engineer
> DisplayLink (UK) Limited
>
>   

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

* RE: How does CGEN decide what ifields to use for CGEN_IVALUE?
  2009-01-14 18:49 ` Dave Brolley
@ 2009-01-16  8:36   ` John Stubley
  2009-01-22 17:33     ` Dave Brolley
  0 siblings, 1 reply; 5+ messages in thread
From: John Stubley @ 2009-01-16  8:36 UTC (permalink / raw)
  To: Dave Brolley; +Cc: cgen

Hi Dave,

Thank you for your reply.  You asked for a few more details, so here
goes:

The CPU has 16-bit word and 32-bit instruction lengths.  The
instructions are mostly packed into bits 3-0 and 31-18, where lsb-0 is
true.  The significant bitfields are as follows:

Opcode family: 4-3
Opcode (for most instructions): 2-0
Subopcodes are opcode dependent.

The problem is that some instructions load immediate data in bits
2-0,31-18 and thus do not have an opcode field - only an opcode family.
I think what happens is that the immediate data is being used as a hash
in the CGEN_IVALUE part of the table, and so is dependent on the actual
data field. Thus sometimes the disassembler cannot identify the
instruction.

Below are some extracts from the CPU file (some of the comments need
updating, though).  The last instruction shown is the one that will
disassemble oddly:
-----------------------------8<-----------------------------------------
----
(define-arch
  (name proc16)
  (comment "Proc16")
  (insn-lsb0? #t)
  (machs proc16)
  (isas proc16)
)
 
(define-isa
  ; Name of the ISA.
  (name proc16)

  ; Words size is 16 bits.
  (default-insn-word-bitsize 16)

  ; Default instrction length.  The insns are always 18 bits wide.
  (default-insn-bitsize 32)

  ; Base instruction length.  The insns are always 18 bits wide.
  (base-insn-bitsize 32)

  ; This may not be needed...
  (decode-assist (4 3 2 1 0))

  ; Fetches 1 insn at a time.
  (liw-insns 1)
  (parallel-insns 1)
)

; CPU family definitions.
  
(define-cpu
  ; CPU names must be distinct from the architecture name and machine
names.
  ; The "b" suffix stands for "base" and is the convention.
  ; The "f" suffix stands for "family" and is the convention.
  (name proc16bf)
  (comment "Proc16 base family")
  (endian little)
  (insn-chunk-bitsize 32)
  (word-bitsize 16)
)

-----------------------------8<-----------------------------------------
----; Instruction classes.
(dnf f-padhead    "unused header"      (RESERVED)            15  11)
(dnf f-opfamily   "opcode family"      ()                    4   2)
(dnf f-padfoot    "unused footer"      (RESERVED)            17  2)
(dnf f-opcode     "opcode"             ()                    2   3)
(dnf f-padbit     "unused bit"         (RESERVED)            31  1)

; Immediates.
(dnf f-n4        "address offset (4)"  ()                    29  4)
(dnf f-a8        "address (8)"         (ABS-ADDR)            29  8)
(dnf f-k7        "imm data (7)"        ()                    28  7)

(dnf f-a16hi     "abs address (16) [15]"   ()                0   1)
(dnf f-a16lo     "abs address (16) [14:0]" ()                30  15)
(dnf f-k8hi      "imm data (8) [7]"        ()                30  1)
(dnf f-k8lo      "imm data (8) [0-6]"      ()                28  7)
(dnf f-k16hi     "imm data (16) [15:13]"   ()                2   3)
(dnf f-k16lo     "imm data (16) [12:0]"    ()                30  13)

(df f-a14        "rel address (14)"    (PCREL-ADDR)          29  14
                 INT
                 ((value pc) (sub WI value pc))
                 ((value pc) (add WI value pc))
)
(dnmf f-a16      "abs address (16)"    (ABS-ADDR)
      UINT
      (f-a16hi f-a16lo)
      ; insert
      (sequence ()
		   (set (ifield f-a16hi)  (srl (ifield f-a16) (const
15)))
		   (set (ifield f-a16lo)  (and (ifield f-a16) (const
#x7fff)))
		  )
      ; extract
      (sequence ()
		   (set (ifield f-a16)  (or (sll (ifield f-a16hi) (const
15))
                                     (ifield f-a16lo)))
		  )
)


(dnmf f-k8       "imm data (8)"        ()
      UINT
      (f-k8hi f-k8lo)
      ; insert
      (sequence ()
		   (set (ifield f-k8hi)  (srl (ifield f-k8) (const 7)))
		   (set (ifield f-k8lo)  (and (ifield f-k8) (const
#x7f)))
		  )
      ; extract
      (sequence ()
		   (set (ifield f-k8)  (or (sll (ifield f-k8hi) (const
7))
                                    (ifield f-k8lo)))
		  )
)

(dnmf f-k16       "imm data (16)"        ()
      UINT
      (f-k16hi f-k16lo)
      ; insert
      (sequence ()
		   (set (ifield f-k16hi)  (srl (ifield f-k16) (const
13)))
		   (set (ifield f-k16lo)  (and (ifield f-k16) (const
#x1fff)))
		  )
      ; extract
      (sequence ()
		   (set (ifield f-k16)  (or (sll (ifield f-k16hi) (const
13))
                                     (ifield f-k16lo)))
		  )
)
-----------------------------8<-----------------------------------------
----; insn-opfamily: bits 2-3
(define-normal-insn-enum insn-opfamily "insn family enums" () OPF_
f-opfamily
 (("LOADSTORE" 0)
  ("ARITH" 1)
  ("BRANCH" 2)
  ("SPECIAL" 3))
)

; insn-opcode-loadstore: bits 31,0-1, Load/Store family
(define-normal-insn-enum insn-opcode-loadstore "l/s insn code enums" ()
OPL_ f-opcode
 (("LOAD" 0)
  ("Reserved1" 1)
  ("FETCH" 2)
  ("INPUT" 3)
  ("STORE" 4)
  ("OUTPUT" 5)
  ("LOADPC" 6)
  ("RET" 7))
)

; insn-opcode-arithmetic: bits 31,0-1, Arithmetic family
(define-normal-insn-enum insn-opcode-arithmetic "arith insn code enums"
() OPA_ f-opcode
 (("ADD" 0)
  ("ADC" 1)
  ("SUB" 2)
  ("SBC" 3)
  ("AND" 4)
  ("OR" 5)
  ("XOR" 6)
  ("BIT" 7))
)

-----------------------------8<-----------------------------------------
----
; Instruction operands.

(dnop k16     "16 bit unsigned immediate"  ()          h-uint  f-k16)
(dnop k8      "8 bit unsigned immediate"   ()          h-uint  f-k8)
(dnop k7      "7 bit unsigned immediate"   ()          h-uint  f-k7)
(dnop a16     "16 bit absolute address"    ()          h-iaddr f-a16)
(dnop a14     "14 bit relative address"    ()          h-iaddr f-a14)
(dnop a8      "8 bit absolute address"     ()          h-addr  f-a8)
(dnop n4      "4 bit address offset"       ()          h-addr  f-n4)

(dnop rX      "destination register"       ()          h-gr    f-rx)
(dnop rY      "source register"            ()          h-gr    f-ry)

-----------------------------8<-----------------------------------------
----; Load / Store instructions

(dni loadreg "load registers"
     ()
     "load $rX,$rY"
     (+ OPF_LOADSTORE OPL_LOAD (f-padhead 0) (f-padbit 0) (f-padfoot 0)
(f-pad5 0) rY rX)
     (set rX rY)
     ()
)

(dni loadimm "load immediate"
     ()
     "load $rX,$k8"
     (+ OPF_LOADSTORE OPL_LOAD OPAI_IMM (f-padhead 0) (f-padbit 0)
(f-padfoot 0) k8 rX)
     (set rX k8)
     ()
)

-----------------------------8<-----------------------------------------
----; Special instructions
(dni loadword "load word immediate"
     ()
     "load r0,$k16"
     (+ OPF_SPECIAL (f-padhead 0) (f-padbit 0) (f-padfoot 0) k16)
     (set (reg WI r0) k16)
     ()
)

-----------------------------8<-----------------------------------------
----

John

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

* Re: How does CGEN decide what ifields to use for CGEN_IVALUE?
  2009-01-16  8:36   ` John Stubley
@ 2009-01-22 17:33     ` Dave Brolley
  2009-01-23  9:20       ` John Stubley
  0 siblings, 1 reply; 5+ messages in thread
From: Dave Brolley @ 2009-01-22 17:33 UTC (permalink / raw)
  To: John Stubley; +Cc: cgen

HI John,

Sorry to take so long to look at this....

The first potential problem I see is in the use of decode-assist. The 
bits specified here must be opcode bits for *every* insn. By using 
decide-assist, this is what you are telling the decoder and it will 
believe you.  According to you, bits 2-0 are not always opcode bits. 
decode-assist is simply an optimization and I would recommend not using 
it at all unless the default generated decoder ends up being 
particularly inefficient.

I didn't see any glaring problems otherwise.

I hope this helps,
Dave

John Stubley wrote:
> Hi Dave,
>
> Thank you for your reply.  You asked for a few more details, so here
> goes:
>
> The CPU has 16-bit word and 32-bit instruction lengths.  The
> instructions are mostly packed into bits 3-0 and 31-18, where lsb-0 is
> true.  The significant bitfields are as follows:
>
> Opcode family: 4-3
> Opcode (for most instructions): 2-0
> Subopcodes are opcode dependent.
>
> The problem is that some instructions load immediate data in bits
> 2-0,31-18 and thus do not have an opcode field - only an opcode family.
> I think what happens is that the immediate data is being used as a hash
> in the CGEN_IVALUE part of the table, and so is dependent on the actual
> data field. Thus sometimes the disassembler cannot identify the
> instruction.
>
> Below are some extracts from the CPU file (some of the comments need
> updating, though).  The last instruction shown is the one that will
> disassemble oddly:
> -----------------------------8<-----------------------------------------
> ----
> (define-arch
>   (name proc16)
>   (comment "Proc16")
>   (insn-lsb0? #t)
>   (machs proc16)
>   (isas proc16)
> )
>  
> (define-isa
>   ; Name of the ISA.
>   (name proc16)
>
>   ; Words size is 16 bits.
>   (default-insn-word-bitsize 16)
>
>   ; Default instrction length.  The insns are always 18 bits wide.
>   (default-insn-bitsize 32)
>
>   ; Base instruction length.  The insns are always 18 bits wide.
>   (base-insn-bitsize 32)
>
>   ; This may not be needed...
>   (decode-assist (4 3 2 1 0))
>
>   ; Fetches 1 insn at a time.
>   (liw-insns 1)
>   (parallel-insns 1)
> )
>
> ; CPU family definitions.
>   
> (define-cpu
>   ; CPU names must be distinct from the architecture name and machine
> names.
>   ; The "b" suffix stands for "base" and is the convention.
>   ; The "f" suffix stands for "family" and is the convention.
>   (name proc16bf)
>   (comment "Proc16 base family")
>   (endian little)
>   (insn-chunk-bitsize 32)
>   (word-bitsize 16)
> )
>
> -----------------------------8<-----------------------------------------
> ----; Instruction classes.
> (dnf f-padhead    "unused header"      (RESERVED)            15  11)
> (dnf f-opfamily   "opcode family"      ()                    4   2)
> (dnf f-padfoot    "unused footer"      (RESERVED)            17  2)
> (dnf f-opcode     "opcode"             ()                    2   3)
> (dnf f-padbit     "unused bit"         (RESERVED)            31  1)
>
> ; Immediates.
> (dnf f-n4        "address offset (4)"  ()                    29  4)
> (dnf f-a8        "address (8)"         (ABS-ADDR)            29  8)
> (dnf f-k7        "imm data (7)"        ()                    28  7)
>
> (dnf f-a16hi     "abs address (16) [15]"   ()                0   1)
> (dnf f-a16lo     "abs address (16) [14:0]" ()                30  15)
> (dnf f-k8hi      "imm data (8) [7]"        ()                30  1)
> (dnf f-k8lo      "imm data (8) [0-6]"      ()                28  7)
> (dnf f-k16hi     "imm data (16) [15:13]"   ()                2   3)
> (dnf f-k16lo     "imm data (16) [12:0]"    ()                30  13)
>
> (df f-a14        "rel address (14)"    (PCREL-ADDR)          29  14
>                  INT
>                  ((value pc) (sub WI value pc))
>                  ((value pc) (add WI value pc))
> )
> (dnmf f-a16      "abs address (16)"    (ABS-ADDR)
>       UINT
>       (f-a16hi f-a16lo)
>       ; insert
>       (sequence ()
> 		   (set (ifield f-a16hi)  (srl (ifield f-a16) (const
> 15)))
> 		   (set (ifield f-a16lo)  (and (ifield f-a16) (const
> #x7fff)))
> 		  )
>       ; extract
>       (sequence ()
> 		   (set (ifield f-a16)  (or (sll (ifield f-a16hi) (const
> 15))
>                                      (ifield f-a16lo)))
> 		  )
> )
>
>
> (dnmf f-k8       "imm data (8)"        ()
>       UINT
>       (f-k8hi f-k8lo)
>       ; insert
>       (sequence ()
> 		   (set (ifield f-k8hi)  (srl (ifield f-k8) (const 7)))
> 		   (set (ifield f-k8lo)  (and (ifield f-k8) (const
> #x7f)))
> 		  )
>       ; extract
>       (sequence ()
> 		   (set (ifield f-k8)  (or (sll (ifield f-k8hi) (const
> 7))
>                                     (ifield f-k8lo)))
> 		  )
> )
>
> (dnmf f-k16       "imm data (16)"        ()
>       UINT
>       (f-k16hi f-k16lo)
>       ; insert
>       (sequence ()
> 		   (set (ifield f-k16hi)  (srl (ifield f-k16) (const
> 13)))
> 		   (set (ifield f-k16lo)  (and (ifield f-k16) (const
> #x1fff)))
> 		  )
>       ; extract
>       (sequence ()
> 		   (set (ifield f-k16)  (or (sll (ifield f-k16hi) (const
> 13))
>                                      (ifield f-k16lo)))
> 		  )
> )
> -----------------------------8<-----------------------------------------
> ----; insn-opfamily: bits 2-3
> (define-normal-insn-enum insn-opfamily "insn family enums" () OPF_
> f-opfamily
>  (("LOADSTORE" 0)
>   ("ARITH" 1)
>   ("BRANCH" 2)
>   ("SPECIAL" 3))
> )
>
> ; insn-opcode-loadstore: bits 31,0-1, Load/Store family
> (define-normal-insn-enum insn-opcode-loadstore "l/s insn code enums" ()
> OPL_ f-opcode
>  (("LOAD" 0)
>   ("Reserved1" 1)
>   ("FETCH" 2)
>   ("INPUT" 3)
>   ("STORE" 4)
>   ("OUTPUT" 5)
>   ("LOADPC" 6)
>   ("RET" 7))
> )
>
> ; insn-opcode-arithmetic: bits 31,0-1, Arithmetic family
> (define-normal-insn-enum insn-opcode-arithmetic "arith insn code enums"
> () OPA_ f-opcode
>  (("ADD" 0)
>   ("ADC" 1)
>   ("SUB" 2)
>   ("SBC" 3)
>   ("AND" 4)
>   ("OR" 5)
>   ("XOR" 6)
>   ("BIT" 7))
> )
>
> -----------------------------8<-----------------------------------------
> ----
> ; Instruction operands.
>
> (dnop k16     "16 bit unsigned immediate"  ()          h-uint  f-k16)
> (dnop k8      "8 bit unsigned immediate"   ()          h-uint  f-k8)
> (dnop k7      "7 bit unsigned immediate"   ()          h-uint  f-k7)
> (dnop a16     "16 bit absolute address"    ()          h-iaddr f-a16)
> (dnop a14     "14 bit relative address"    ()          h-iaddr f-a14)
> (dnop a8      "8 bit absolute address"     ()          h-addr  f-a8)
> (dnop n4      "4 bit address offset"       ()          h-addr  f-n4)
>
> (dnop rX      "destination register"       ()          h-gr    f-rx)
> (dnop rY      "source register"            ()          h-gr    f-ry)
>
> -----------------------------8<-----------------------------------------
> ----; Load / Store instructions
>
> (dni loadreg "load registers"
>      ()
>      "load $rX,$rY"
>      (+ OPF_LOADSTORE OPL_LOAD (f-padhead 0) (f-padbit 0) (f-padfoot 0)
> (f-pad5 0) rY rX)
>      (set rX rY)
>      ()
> )
>
> (dni loadimm "load immediate"
>      ()
>      "load $rX,$k8"
>      (+ OPF_LOADSTORE OPL_LOAD OPAI_IMM (f-padhead 0) (f-padbit 0)
> (f-padfoot 0) k8 rX)
>      (set rX k8)
>      ()
> )
>
> -----------------------------8<-----------------------------------------
> ----; Special instructions
> (dni loadword "load word immediate"
>      ()
>      "load r0,$k16"
>      (+ OPF_SPECIAL (f-padhead 0) (f-padbit 0) (f-padfoot 0) k16)
>      (set (reg WI r0) k16)
>      ()
> )
>
> -----------------------------8<-----------------------------------------
> ----
>
> John
>   

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

* RE: How does CGEN decide what ifields to use for CGEN_IVALUE?
  2009-01-22 17:33     ` Dave Brolley
@ 2009-01-23  9:20       ` John Stubley
  0 siblings, 0 replies; 5+ messages in thread
From: John Stubley @ 2009-01-23  9:20 UTC (permalink / raw)
  To: Dave Brolley; +Cc: cgen

Hi Dave,

Thanks for looking into this for me.

I tried removing the decode-assist, but it actually makes no difference,
so the default decoder is choosing the same bits anyway.  I suppose
there's not much I can do to force it to decode in two stages without
significant surgery.

I appreciate your help,

John
   

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

end of thread, other threads:[~2009-01-23  9:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-14 17:09 How does CGEN decide what ifields to use for CGEN_IVALUE? John Stubley
2009-01-14 18:49 ` Dave Brolley
2009-01-16  8:36   ` John Stubley
2009-01-22 17:33     ` Dave Brolley
2009-01-23  9:20       ` John Stubley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).