Adding new assembly instructions

352 views
Skip to first unread message

quarnster

unread,
Jan 30, 2013, 3:11:36 PM1/30/13
to golan...@googlegroups.com
Hi,

The contributing guide explicitly states to discuss issues here before sending in a change list, so here I am :)

I'm toying around with 6a and SSE instructions and notice that some of the ones I'd like to try out aren't currently implemented. Adding a new instruction was trivial although the undocumented enums with more or less cryptic names do not help in giving me confidence that I've chosen the correct magic. Is there an explanation somewhere behind the naming or are the LTYPE*, Y*, Z* bits considered common knowledge and obvious to compiler people?

Is there anything I need to be careful with as to where I put the new instructions in the tables?
What would be a good test for making sure I've got the instructions right? I presume it involves objdump but I didn't see a test suite for the assemblers in the code base.

Anything else I need to be aware of?


I'm don't know exactly which opcodes I'll end up trying out, but right now I have DPPS seemingly working and want to look at one or more of the BLENDs from SSE4.1.


Any pointers would be appreciated.


Cheers,

/f


Diff for DPPS FOLLOWS

$ hg diff -w
diff -r 3a153f3d2680 src/cmd/6a/lex.c
--- a/src/cmd/6a/lex.c Fri Jan 25 23:07:21 2013 -0500
+++ b/src/cmd/6a/lex.c Wed Jan 30 20:32:16 2013 +0100
@@ -828,6 +828,7 @@
  "CVTPD2PL", LTYPE3, ACVTPD2PL,
  "CVTPD2PS", LTYPE3, ACVTPD2PS,
  "CVTPS2PL", LTYPE3, ACVTPS2PL,
+ "DPPS",  LTYPEX, ADPPS,
  "PF2IW", LTYPE3, APF2IW,
  "PF2IL", LTYPE3, APF2IL,
  "PF2ID", LTYPE3, APF2IL, /* syn */
diff -r 3a153f3d2680 src/cmd/6l/6.out.h
--- a/src/cmd/6l/6.out.h Fri Jan 25 23:07:21 2013 -0500
+++ b/src/cmd/6l/6.out.h Wed Jan 30 20:32:16 2013 +0100
@@ -564,6 +564,7 @@
  ADIVPS,
  ADIVSD,
  ADIVSS,
+ ADPPS,
  AEMMS,
  AFXRSTOR,
  AFXRSTOR64,
diff -r 3a153f3d2680 src/cmd/6l/optab.c
--- a/src/cmd/6l/optab.c Fri Jan 25 23:07:21 2013 -0500
+++ b/src/cmd/6l/optab.c Wed Jan 30 20:32:16 2013 +0100
@@ -526,6 +526,11 @@
  Yxm, Yxr, Zibm_r, 2,
  0
 };
+uchar yxdp[] =
+{
+ Yxm, Yxr, Zibm_r, 3,
+ 0
+};
 uchar yextrw[] =
 {
  Yxr, Yrl, Zibm_r, 2,
@@ -783,6 +788,7 @@
  { ADIVSD, yxm, Pf2, 0x5e },
  { ADIVSS, yxm, Pf3, 0x5e },
  { ADIVW, ydivl, Pe, 0xf7,(06) },
+ { ADPPS, yxdp, Pq, 0x3a, 0x40, (00)},
  { AEMMS, ynone, Pm, 0x77 },
  { AENTER }, /* botch */
  { AFXRSTOR, ysvrs, Pm, 0xae,(01),0xae,(01) },

quarnster

unread,
Jan 30, 2013, 3:28:06 PM1/30/13
to golan...@googlegroups.com
Also, on a somewhat related note, is it possible to define a receiver method in assembly code? The syntax that is spit out by "go build -gcflags -S" does not appear to work and I could only find non receiver methods in the assembly sources in the go code base.

/f

Nigel Tao

unread,
Jan 30, 2013, 6:45:38 PM1/30/13
to quarnster, golang-nuts
On Thu, Jan 31, 2013 at 7:28 AM, quarnster <quar...@gmail.com> wrote:
> Also, on a somewhat related note, is it possible to define a receiver method
> in assembly code? The syntax that is spit out by "go build -gcflags -S" does
> not appear to work

Can you give an example of what you are trying, and any errors you are getting?

quarnster

unread,
Jan 31, 2013, 2:51:45 AM1/31/13
to golan...@googlegroups.com, quarnster
 Short version

TEXT    (*Hello).WorldAsm+0(SB),$0-16
    ./hello.s:1 syntax error, last name: TEXT
TEXT    Hello.WorldAsm+0(SB),$0-16
    ./hello.s:1 syntax error, last name: .WorldAsm
TEXT    Hello·WorldAsm+0(SB),$0-16
    _/tmp/hello.TestWorld: undefined: _/tmp/hello.(*Hello).WorldAsm
TEXT    hello·Hello·WorldAsm+0(SB),$0-16
    _/tmp/hello.TestWorld: undefined: _/tmp/hello.(*Hello).WorldAsm
TEXT    hello·(*Hello)·WorldAsm+0(SB),$0-16
    ./hello.s:1 syntax error, last name: hello.
TEXT    hello·(Hello)·WorldAsm+0(SB),$0-16
    ./hello.s:1 syntax error, last name: Hello
TEXT    hello·*Hello·WorldAsm+0(SB),$0-16
    ./hello.s:1 syntax error, last name: hello.





Long version:


$ cat hello.go
package hello

type Hello struct {
    world int
}

func (h *Hello) World() int { return h.world }
$ go build -gcflags -S
# _/tmp/hello

--- prog list "(*Hello).World" ---
0000 (/tmp/hello/hello.go:7) TEXT    (*Hello).World+0(SB),$0-16
0001 (/tmp/hello/hello.go:7) MOVQ    h+0(FP),BX
0002 (/tmp/hello/hello.go:7) MOVQ    (BX),BP
0003 (/tmp/hello/hello.go:7) MOVQ    BP,.noname+8(FP)
0004 (/tmp/hello/hello.go:7) RET     ,
$ echo "func(h *Hello) WorldAsm() int" >> hello.go

... typity type ..

$ cat hello_test.go
package hello

import "testing"

func TestWorld(t *testing.T) {
    a := Hello{1337}
    t.Log(a.World())
    t.Log(a.WorldAsm())
}
$ cat hello.s
TEXT    (*Hello).WorldAsm+0(SB),$0-16
MOVQ    h+0(FP),BX
MOVQ    (BX),BP
MOVQ    BP,.noname+8(FP)
RET     ,
$ go test
# _/tmp/hello
./hello.s:1 syntax error, last name: TEXT
FAIL    _/tmp/hello [build failed]
$ sed s/\(\\*Hello\)/Hello/ hello.s > hello2.s && mv hello2.s hello.s && go test 
# _/tmp/hello
./hello.s:1 syntax error, last name: .WorldAsm
FAIL    _/tmp/hello [build failed]
$ sed s/.W/·W/ hello.s > hello2.s && mv hello2.s hello.s && go test
# testmain
_/tmp/hello.TestWorld: undefined: _/tmp/hello.(*Hello).WorldAsm
FAIL    _/tmp/hello [build failed]
$ sed s/Hello/hello·Hello/ hello.s > hello2.s && mv hello2.s hello.s && go test
# testmain
_/tmp/hello.TestWorld: undefined: _/tmp/hello.(*Hello).WorldAsm
FAIL    _/tmp/hello [build failed]
$ sed s/Hello/\(\\*Hello\)/ hello.s > hello2.s && mv hello2.s hello.s && go test
# _/tmp/hello
./hello.s:1 syntax error, last name: hello.
FAIL    _/tmp/hello [build failed]
$ sed s/\\*// hello.s > hello2.s && mv hello2.s hello.s && go test
# _/tmp/hello
./hello.s:1 syntax error, last name: Hello
FAIL    _/tmp/hello [build failed]
$ sed s/\(Hello\)/\\*Hello/ hello.s > hello2.s && mv hello2.s hello.s && go test
# _/tmp/hello
./hello.s:1 syntax error, last name: hello.
FAIL    _/tmp/hello [build failed]

Anthony Martin

unread,
Jan 31, 2013, 4:38:57 AM1/31/13
to quarnster, golan...@googlegroups.com
quarnster <quar...@gmail.com> once said:
> Also, on a somewhat related note, is it possible to define a receiver
> method in assembly code? The syntax that is spit out by "go build -gcflags
> -S" does not appear to work and I could only find non receiver methods in
> the assembly sources in the go code base.

The assmemblers use a very simple grammar.
The fancy names emitted by the Go compiler
won't work. What you have to do is write
methods in Go that simply proxy to the
assembly routines. Notice how the reciever
is the first parameter. This is exactly how
the compiler would generate it.

$ cat a.go
package main

type T int

func set(*T, int)
func get(*T) int

func (t *T) Set(i int) { set(t, i) }
func (t *T) Get() int { return get(t) }

func main() {
var t T

println(t.Get())
t.Set(42)
println(t.Get())
}

$ cat b.s
TEXT ·set(SB),7,$0
MOVQ t+0(FP), BX
MOVQ i+8(FP), BP
MOVQ BP, (BX)
RET

TEXT ·get(SB),7,$0
MOVQ t+0(FP), BX
MOVQ (BX), BP
MOVQ BP, ret+8(FP)
RET

$ go build -o a.out
$ ./a.out
0
42
$

Cheers,
Anthony

Nigel Tao

unread,
Jan 31, 2013, 6:45:04 PM1/31/13
to quarnster, golang-nuts
On Thu, Jan 31, 2013 at 7:11 AM, quarnster <quar...@gmail.com> wrote:
> Is there an explanation somewhere behind the naming or are
> the LTYPE*, Y*, Z* bits considered common knowledge and obvious to compiler
> people?

The naming is obvious to Ken Thompson, but is otherwise not as well
documented as it could be.

If you "hg log src/cmd/6l/optab.c" and look up some of those changes
(e.g. https://codereview.appspot.com/5970055/) you might get a sense
of what else is needed to add new assembly instructions.

Russ Cox

unread,
Feb 3, 2013, 12:40:52 PM2/3/13
to Nigel Tao, quarnster, golang-nuts
There's a comment in src/cmd/6l/optab.c "You are doasm..." that explains the basic structure of the tables.


Reply all
Reply to author
Forward
0 new messages