I've been trying off and on for a couple of days to create a machine
description that handles the following target and produces the output I
am hoping for.
The CPU has a 16 bit word size - and only has word size registers. As a
consequence it sign or zero extends when loading byte operands -
depending on the instruction used.
In addition this is a two address machine so binary operators have the form
Rn op= operand
e.g.
add r0,r1
add r0,[memory]
or when referencing Signed Byte (bs) operands in memory
addBS r0,[byte value address]
compiling
signed char ch1, ch2;
void f( void )
{
ch1 += ch;
}
gives an assembly output of
(1)
movbs r1,[_ch1]
movbs r2,[_ch2]
add r1,r2
stb r1,[ch1
Based on this error message ...
(insn 9 8 10 3 (set (reg:QI 19 [ ch1.4 ]) <-- non_strict_
(pre-reload/regalloc) ? -> reg:QI plus:HI HI HI
(plus:HI (reg:HI 21)
(sign_extend:HI (reg:QI 22)))) t.c:6 -1
when using this pattern ...
(define_insn "addqi3i"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (match_operand:HI 1 "register_operand" "%0")
(sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))]
I altered the pattern to...
(define_insn "addqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(truncate:QI
(plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
(sign_extend:HI (match_operand:QI 2 "memory_operand" "m")))))]
""
"addbs %0,[%2]"
[(set_attr "length" "2")]
)
I then get an assembly output of ...
(2)
movbs r1,[_ch1] ;# 5 *movqi_insn/3 [length = 2]
addbs r1,[_ch2] ;# 6 addqi3 [length = 2]
stb r1,[_ch1] ;# 7 *movqi_insn/4 [length = 2]
which is exactly what I was after. The problem comes when compiling an
expression matching a mix of int and char operands - the above addqi3
pattern causes
t.c: In function âfâ:
t.c:14:1: error: unrecognisable insn:
(insn 8 7 9 3 (set (reg:QI 26)
(truncate:QI (plus:HI (sign_extend:HI (reg:QI 24))
(sign_extend:HI (reg:QI 25))))) t.c:6 -1
(nil))
t.c:14:1: internal compiler error: in extract_insn, at recog.c:2109
changing the addqi3 pattern to
(define_insn "addqi3i"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (match_operand:HI 1 "register_operand" "%0")
(sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))]
Fixes this, however when adding two bytes together I now get the
suboptimal output shown in (1) above.
I've tried using a define_expand for addqi3 and then including both the
addqi3 patterns above (with custom names) as specialisations - however
at least one of the specialisations isn't used when I do this.
Can anyone give me an idea what patterns I should be using to address
this problem ? I've tried looking at the combine dump to see what gcc is
expecting but that hasn't been of much help.
The word width instructions work perfectly so I assumed that the
sign/zero extension was the problem. I have trawled the gcc internals
docs to see if there is a way to tell gcc that the target doesn't have
registers narrower than a word - in the hope that I could prevent gcc
from requiring the reg:QI 19 in ...
(insn 9 8 10 3 (set (reg:QI 19 [ ch1.4 ]) <-- non_strict_
(pre-reload/regalloc) ? -> reg:QI plus:HI HI HI
(plus:HI (reg:HI 21)
(sign_extend:HI (reg:QI 22)))) t.c:6 -1
and haven't found anything to help ?
Any advice would be greatly appreciated.
Cheers, Paul.