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: Russ Cox <rsc@golang.org>
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);
}
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);
}
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)
}
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)
}
{"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)"},
p.get(',')
}
}
- a.Type = obj.TYPE_CONST
+ a.Type = obj.TYPE_REGLIST
a.Offset = int64(bits)
}
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
C_REG
C_REGREG
C_REGREG2
+ C_REGLIST
C_SHIFT
C_FREG
C_PSR
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},
case obj.TYPE_REGREG2:
return C_REGREG2
+ case obj.TYPE_REGLIST:
+ return C_REGLIST
+
case obj.TYPE_SHIFT:
return C_SHIFT
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 {
// 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.
//
TYPE_REGREG
TYPE_REGREG2
TYPE_INDIR
+ TYPE_REGLIST
)
// TODO(rsc): Describe prog.
}
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 {
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 {
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
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
}
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
+}