]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj: clean up handling of register list operand on ARM
authorRob Pike <r@golang.org>
Fri, 27 Feb 2015 21:50:26 +0000 (13:50 -0800)
committerRob Pike <r@golang.org>
Sat, 28 Feb 2015 20:10:59 +0000 (20:10 +0000)
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>
src/cmd/5a/a.y
src/cmd/5a/y.go
src/cmd/asm/internal/asm/operand_test.go
src/cmd/asm/internal/asm/parse.go
src/cmd/asm/internal/asm/testdata/arm.out
src/cmd/internal/obj/arm/5.out.go
src/cmd/internal/obj/arm/asm5.go
src/cmd/internal/obj/arm/list5.go
src/cmd/internal/obj/link.go
src/cmd/internal/obj/pass.go
src/cmd/internal/obj/util.go

index 39fab8fa26e7e2938c068b7fdd66f79ffe46f515..c1ca3beaa8b6975412ef4b1d702081b69ac50708 100644 (file)
@@ -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);
        }
index 7c7de64b15df73bcb379ab64ad5eab0fad84fdfd..a79f61d3162e60de78320d467a4cca0405083278 100644 (file)
@@ -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)
                }
index e8d3cda48956e151cc17afbe542d13ff6a2d29fb..fd0331eb2cbbaded4e34d4b3eaa4f2ec62723c1d 100644 (file)
@@ -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)"},
index 9048cca9849c37beda726d601ae5bbb9e6d8c92d..27d311293f543bb750cd94681cde17e4a05f1252 100644 (file)
@@ -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)
 }
 
index 1c4c7e79f6c548e3c4051b1834f55b8bb095ccf7..9e6f080069124d506e80071fb01a55f201f18b5a 100644 (file)
 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
index bebc091a88e9a359de22030076b635f968ece273..d4b0170e583e823bf8145bc171234551be55660e 100644 (file)
@@ -106,6 +106,7 @@ const (
        C_REG
        C_REGREG
        C_REGREG2
+       C_REGLIST
        C_SHIFT
        C_FREG
        C_PSR
index 236b2418ce7bdbf1d94c957b9e87838595bff935..f82b737b5afa28fbd8a0308b0199f11333b6f5c8 100644 (file)
@@ -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
 
index 1570948575c150ec1fd99810baf76d6d56b6f34d..70280f3876ce2da2bdfcd8dde6169d6bcaec15fd 100644 (file)
@@ -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 {
index a2baec4021cd9c2eca5b10d265b7f3d9a3826fc7..990072937f1a51b542af55a97a119189a0ab2401 100644 (file)
@@ -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.
index b03cd431a98587b448f4de9a3731f40271f025b4..50d21e9e008e44a6dff89357a0e5548d2685d698 100644 (file)
@@ -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 {
index 4a7578b2573f76e42973f081de725c422e09941e..1fda2c32a679658ab64dcacc631090c9715e8ce1 100644 (file)
@@ -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
+}