Commit 0eeb5cf0 authored by Rob Pike's avatar Rob Pike

cmd/internal/obj: clean up handling of register list operand on ARM

ARM operands for MOVM have lists of registers: [R1,R2,R5-R8].
Handle them cleanly.

It was TYPE_CONST with special handling, which meant operand printing
didn't work right and the special handling was ugly. Add a new TYPE_REGLIST
for this case and it all gets cleaner.

Change-Id: I4a64f70fb9765e63cb636619a7a8553611bfe970
Reviewed-on: https://go-review.googlesource.com/6300
Run-TryBot: Rob Pike <r@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent bc9748ee
......@@ -179,7 +179,7 @@ inst:
var g obj.Addr
g = nullgen;
g.Type = obj.TYPE_CONST;
g.Type = obj.TYPE_REGLIST;
g.Offset = int64($6);
outcode($1, $2, &$3, 0, &g);
}
......@@ -188,7 +188,7 @@ inst:
var g obj.Addr
g = nullgen;
g.Type = obj.TYPE_CONST;
g.Type = obj.TYPE_REGLIST;
g.Offset = int64($4);
outcode($1, $2, &g, 0, &$7);
}
......
......@@ -785,7 +785,7 @@ yydefault:
var g obj.Addr
g = nullgen
g.Type = obj.TYPE_CONST
g.Type = obj.TYPE_REGLIST
g.Offset = int64(yyDollar[6].lval)
outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &g)
}
......@@ -796,7 +796,7 @@ yydefault:
var g obj.Addr
g = nullgen
g.Type = obj.TYPE_CONST
g.Type = obj.TYPE_REGLIST
g.Offset = int64(yyDollar[4].lval)
outcode(yyDollar[1].lval, yyDollar[2].lval, &g, 0, &yyDollar[7].addr)
}
......
......@@ -316,12 +316,11 @@ var armOperandTests = []operandTest{
{"R6", "R6"},
{"R7", "R7"},
{"R8", "R8"},
// TODO: Fix Dconv to handle these. MOVM print shows the registers.
{"[R0,R1,g,R15]", "$33795"},
{"[R0-R7]", "$255"},
{"[R(0)-R(7)]", "$255"},
{"[R0]", "$1"},
{"[R1-R12]", "$8190"},
{"[R0,R1,g,R15]", "[R0,R1,g,R15]"},
{"[R0-R7]", "[R0,R1,R2,R3,R4,R5,R6,R7]"},
{"[R(0)-R(7)]", "[R0,R1,R2,R3,R4,R5,R6,R7]"},
{"[R0]", "[R0]"},
{"[R1-R12]", "[R1,R2,R3,R4,R5,R6,R7,R8,R9,g,R11,R12]"},
{"armCAS64(SB)", "armCAS64(SB)"},
{"asmcgocall<>(SB)", "asmcgocall<>(SB)"},
{"c+28(FP)", "c+28(FP)"},
......
......@@ -714,7 +714,7 @@ func (p *Parser) registerList(a *obj.Addr) {
p.get(',')
}
}
a.Type = obj.TYPE_CONST
a.Type = obj.TYPE_REGLIST
a.Offset = int64(bits)
}
......
......@@ -28,10 +28,10 @@
110 00028 (testdata/arm.s:110) CMP.S $1,R2,
111 00029 (testdata/arm.s:111) CMP.S R1<<R2,R3,
112 00030 (testdata/arm.s:112) CMP.S R1,R2,
126 00031 (testdata/arm.s:126) MOVM (R1),[R2,R5,R8,R10]
126 00031 (testdata/arm.s:126) MOVM (R1),[R2,R5,R8,g]
127 00032 (testdata/arm.s:127) MOVM (R1),[R2,R3,R4,R5]
128 00033 (testdata/arm.s:128) MOVM.S (R1),[R2]
139 00034 (testdata/arm.s:139) MOVM [R2,R5,R8,R10],(R1)
139 00034 (testdata/arm.s:139) MOVM [R2,R5,R8,g],(R1)
140 00035 (testdata/arm.s:140) MOVM [R2,R3,R4,R5],(R1)
141 00036 (testdata/arm.s:141) MOVM.S [R2],(R1)
150 00037 (testdata/arm.s:150) STREX.S (R2),R1,R3
......
......@@ -106,6 +106,7 @@ const (
C_REG
C_REGREG
C_REGREG2
C_REGLIST
C_SHIFT
C_FREG
C_PSR
......
......@@ -161,8 +161,8 @@ var optab = []Optab{
Optab{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
Optab{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
Optab{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
Optab{AMOVM, C_LCON, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
Optab{AMOVM, C_SOREG, C_NONE, C_LCON, 39, 4, 0, 0, 0},
Optab{AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
Optab{AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0},
Optab{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
Optab{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
Optab{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
......@@ -1040,6 +1040,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
case obj.TYPE_REGREG2:
return C_REGREG2
case obj.TYPE_REGLIST:
return C_REGLIST
case obj.TYPE_SHIFT:
return C_SHIFT
......
......@@ -83,18 +83,7 @@ func Pconv(p *obj.Prog) string {
if s&C_UBIT != 0 { /* ambiguous with FBIT */
sc += ".U"
}
if a == AMOVM {
if p.From.Type == obj.TYPE_CONST {
str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v",
p.Pc, p.Line(), Aconv(a), sc, RAconv(&p.From), obj.Dconv(p, &p.To))
} else if p.To.Type == obj.TYPE_CONST {
str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v",
p.Pc, p.Line(), Aconv(a), sc, obj.Dconv(p, &p.From), RAconv(&p.To))
} else {
str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v",
p.Pc, p.Line(), Aconv(a), sc, obj.Dconv(p, &p.From), obj.Dconv(p, &p.To))
}
} else if a == obj.ADATA {
if a == obj.ADATA {
str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v",
p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To))
} else if p.As == obj.ATEXT {
......
......@@ -383,6 +383,12 @@ type Pciter struct {
// reg = first register
// offset = second register
//
// [reg, reg, reg-reg]
// Register list for ARM.
// Encoding:
// type = TYPE_REGLIST
// offset = bit mask of registers in list; R0 is low bit.
//
// reg, reg
// TYPE_REGREG2, to be removed.
//
......@@ -409,6 +415,7 @@ const (
TYPE_REGREG
TYPE_REGREG2
TYPE_INDIR
TYPE_REGLIST
)
// TODO(rsc): Describe prog.
......
......@@ -102,7 +102,7 @@ func checkaddr(ctxt *Link, p *Prog, a *Addr) {
}
return
// TODO(rsc): After fixing PINSRQ, check a->offset != 0 too.
// TODO(rsc): After fixing PINSRQ, check a->offset != 0 too.
// TODO(rsc): After fixing SHRQ, check a->index != 0 too.
case TYPE_REG:
if a.Scale != 0 || a.Name != 0 || a.Sym != nil {
......@@ -134,7 +134,10 @@ func checkaddr(ctxt *Link, p *Prog, a *Addr) {
case TYPE_REGREG2:
return
// Expect sym and name to be set, nothing else.
case TYPE_REGLIST:
return
// Expect sym and name to be set, nothing else.
// Technically more is allowed, but this is only used for *name(SB).
case TYPE_INDIR:
if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name == 0 || a.Offset != 0 || a.Sym == nil || a.U.Bits != 0 {
......
......@@ -362,6 +362,9 @@ func Dconv(p *Prog, a *Addr) string {
case TYPE_REGREG2:
str = fmt.Sprintf("%v, %v", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
case TYPE_REGLIST:
str = regListConv(int(a.Offset))
}
return str
......@@ -438,6 +441,8 @@ const (
RBaseARM = 3 * 1024
RBasePPC64 = 4 * 1024
// The next free base is 8*1024 (PPC64 has many registers).
// Alternatively, the next architecture, with an ordinary
// number of registers, could go under PPC64.
)
// RegisterRegister binds a pretty-printer (Rconv) for register
......@@ -459,3 +464,26 @@ func Rconv(reg int) string {
}
return fmt.Sprintf("R???%d", reg)
}
func regListConv(list int) string {
str := ""
for i := 0; i < 16; i++ { // TODO: 16 is ARM-specific.
if list&(1<<uint(i)) != 0 {
if str == "" {
str += "["
} else {
str += ","
}
// This is ARM-specific; R10 is g.
if i == 10 {
str += "g"
} else {
str += fmt.Sprintf("R%d", i)
}
}
}
str += "]"
return str
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment