2015-01-19 14:34:58 -05:00
|
|
|
// Copyright 2015 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package obj
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
2015-02-13 14:40:36 -05:00
|
|
|
"log"
|
2015-01-19 14:34:58 -05:00
|
|
|
"os"
|
|
|
|
|
"strconv"
|
2015-02-25 09:07:02 -08:00
|
|
|
"strings"
|
2015-01-19 14:34:58 -05:00
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
2015-02-25 09:07:02 -08:00
|
|
|
const REG_NONE = 0
|
|
|
|
|
|
2015-01-19 14:34:58 -05:00
|
|
|
var start time.Time
|
|
|
|
|
|
|
|
|
|
func Cputime() float64 {
|
|
|
|
|
if start.IsZero() {
|
|
|
|
|
start = time.Now()
|
|
|
|
|
}
|
|
|
|
|
return time.Since(start).Seconds()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Biobuf struct {
|
2015-02-13 14:40:36 -05:00
|
|
|
unget [2]int
|
|
|
|
|
numUnget int
|
|
|
|
|
f *os.File
|
|
|
|
|
r *bufio.Reader
|
|
|
|
|
w *bufio.Writer
|
|
|
|
|
linelen int
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
func Bopenw(name string) (*Biobuf, error) {
|
2015-02-13 14:40:36 -05:00
|
|
|
f, err := os.Create(name)
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &Biobuf{f: f, w: bufio.NewWriter(f)}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func Bopenr(name string) (*Biobuf, error) {
|
|
|
|
|
f, err := os.Open(name)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &Biobuf{f: f, r: bufio.NewReader(f)}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 14:34:58 -05:00
|
|
|
func Binitw(w io.Writer) *Biobuf {
|
|
|
|
|
return &Biobuf{w: bufio.NewWriter(w)}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Biobuf) Write(p []byte) (int, error) {
|
|
|
|
|
return b.w.Write(p)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func Bwritestring(b *Biobuf, p string) (int, error) {
|
|
|
|
|
return b.w.WriteString(p)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Bseek(b *Biobuf, offset int64, whence int) int64 {
|
|
|
|
|
if b.w != nil {
|
|
|
|
|
if err := b.w.Flush(); err != nil {
|
2015-02-25 09:07:02 -08:00
|
|
|
log.Fatalf("writing output: %v", err)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
} else if b.r != nil {
|
|
|
|
|
if whence == 1 {
|
|
|
|
|
offset -= int64(b.r.Buffered())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
off, err := b.f.Seek(offset, whence)
|
|
|
|
|
if err != nil {
|
2015-02-25 09:07:02 -08:00
|
|
|
log.Fatalf("seeking in output: %v", err)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if b.r != nil {
|
|
|
|
|
b.r.Reset(b.f)
|
|
|
|
|
}
|
|
|
|
|
return off
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Boffset(b *Biobuf) int64 {
|
|
|
|
|
if err := b.w.Flush(); err != nil {
|
2015-02-25 09:07:02 -08:00
|
|
|
log.Fatalf("writing output: %v", err)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
off, err := b.f.Seek(0, 1)
|
|
|
|
|
if err != nil {
|
2015-02-25 09:07:02 -08:00
|
|
|
log.Fatalf("seeking in output: %v", err)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return off
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 14:34:58 -05:00
|
|
|
func (b *Biobuf) Flush() error {
|
|
|
|
|
return b.w.Flush()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Bwrite(b *Biobuf, p []byte) (int, error) {
|
|
|
|
|
return b.w.Write(p)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Bputc(b *Biobuf, c byte) {
|
|
|
|
|
b.w.WriteByte(c)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
const Beof = -1
|
|
|
|
|
|
|
|
|
|
func Bread(b *Biobuf, p []byte) int {
|
|
|
|
|
n, err := io.ReadFull(b.r, p)
|
|
|
|
|
if n == 0 {
|
|
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
|
n = -1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 14:34:58 -05:00
|
|
|
func Bgetc(b *Biobuf) int {
|
2015-02-13 14:40:36 -05:00
|
|
|
if b.numUnget > 0 {
|
|
|
|
|
b.numUnget--
|
|
|
|
|
return int(b.unget[b.numUnget])
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
c, err := b.r.ReadByte()
|
2015-02-13 14:40:36 -05:00
|
|
|
r := int(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
r = -1
|
|
|
|
|
}
|
|
|
|
|
b.unget[1] = b.unget[0]
|
|
|
|
|
b.unget[0] = r
|
|
|
|
|
return r
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Bgetrune(b *Biobuf) int {
|
|
|
|
|
r, _, err := b.r.ReadRune()
|
2015-01-19 14:34:58 -05:00
|
|
|
if err != nil {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
return int(r)
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func Bungetrune(b *Biobuf) {
|
|
|
|
|
b.r.UnreadRune()
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func (b *Biobuf) Read(p []byte) (int, error) {
|
|
|
|
|
return b.r.Read(p)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Brdline(b *Biobuf, delim int) string {
|
|
|
|
|
s, err := b.r.ReadBytes(byte(delim))
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("reading input: %v", err)
|
|
|
|
|
}
|
|
|
|
|
b.linelen = len(s)
|
|
|
|
|
return string(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Brdstr(b *Biobuf, delim int, cut int) string {
|
|
|
|
|
s, err := b.r.ReadString(byte(delim))
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("reading input: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if len(s) > 0 && cut > 0 {
|
|
|
|
|
s = s[:len(s)-1]
|
|
|
|
|
}
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Access(name string, mode int) int {
|
|
|
|
|
if mode != 0 {
|
|
|
|
|
panic("bad access")
|
|
|
|
|
}
|
|
|
|
|
_, err := os.Stat(name)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Blinelen(b *Biobuf) int {
|
|
|
|
|
return b.linelen
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Bungetc(b *Biobuf) {
|
|
|
|
|
b.numUnget++
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Bflush(b *Biobuf) error {
|
|
|
|
|
return b.w.Flush()
|
|
|
|
|
}
|
|
|
|
|
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
func Bterm(b *Biobuf) error {
|
2015-02-13 14:40:36 -05:00
|
|
|
var err error
|
|
|
|
|
if b.w != nil {
|
|
|
|
|
err = b.w.Flush()
|
|
|
|
|
}
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
err1 := b.f.Close()
|
|
|
|
|
if err == nil {
|
|
|
|
|
err = err1
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 12:27:36 -05:00
|
|
|
func envOr(key, value string) string {
|
|
|
|
|
if x := os.Getenv(key); x != "" {
|
|
|
|
|
return x
|
|
|
|
|
}
|
|
|
|
|
return value
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 14:34:58 -05:00
|
|
|
func Getgoroot() string {
|
2015-01-21 12:27:36 -05:00
|
|
|
return envOr("GOROOT", defaultGOROOT)
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getgoarch() string {
|
2015-01-21 12:27:36 -05:00
|
|
|
return envOr("GOARCH", defaultGOARCH)
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getgoos() string {
|
2015-01-21 12:27:36 -05:00
|
|
|
return envOr("GOOS", defaultGOOS)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getgoarm() string {
|
|
|
|
|
return envOr("GOARM", defaultGOARM)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func Getgo386() string {
|
|
|
|
|
return envOr("GO386", defaultGO386)
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 12:27:36 -05:00
|
|
|
func Getgoversion() string {
|
|
|
|
|
return version
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Atoi(s string) int {
|
|
|
|
|
i, _ := strconv.Atoi(s)
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Prog) Line() string {
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
return Linklinefmt(p.Ctxt, int(p.Lineno), false, false)
|
2015-01-19 14:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Prog) String() string {
|
|
|
|
|
if p.Ctxt == nil {
|
|
|
|
|
return fmt.Sprintf("<Prog without ctxt>")
|
|
|
|
|
}
|
|
|
|
|
return p.Ctxt.Arch.Pconv(p)
|
|
|
|
|
}
|
2015-01-21 21:45:29 -05:00
|
|
|
|
|
|
|
|
func (ctxt *Link) NewProg() *Prog {
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
p := new(Prog) // should be the only call to this; all others should use ctxt.NewProg
|
2015-01-21 21:45:29 -05:00
|
|
|
p.Ctxt = ctxt
|
|
|
|
|
return p
|
|
|
|
|
}
|
[dev.cc] cmd/internal/obj: reconvert from liblink
cmd/internal/obj reconverted using rsc.io/c2go rev 2a95256.
- Brings in new, more regular Prog, Addr definitions
- Add Prog* argument to oclass in liblink/asm[68].c, for c2go conversion.
- Update objwriter for change in TEXT size encoding.
- Merge 5a, 6a, 8a, 9a changes into new5a, new6a, new8a, new9a (by hand).
- Add +build ignore to cmd/asm/internal/{addr,arch,asm}, cmd/asm.
They need to be updated for the changes.
- Reenable verifyAsm in cmd/go.
- Reenable GOOBJ=2 mode by default in liblink.
All architectures build successfully again.
Change-Id: I2c845c5d365aa484b570476898171bee657b626d
Reviewed-on: https://go-review.googlesource.com/3963
Reviewed-by: Rob Pike <r@golang.org>
2015-02-05 03:57:44 -05:00
|
|
|
|
|
|
|
|
func (ctxt *Link) Line(n int) string {
|
|
|
|
|
return Linklinefmt(ctxt, n, false, false)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
func (ctxt *Link) Rconv(reg int) string {
|
|
|
|
|
return ctxt.Arch.Rconv(reg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getcallerpc(interface{}) uintptr {
|
|
|
|
|
return 1
|
|
|
|
|
}
|
2015-02-25 09:07:02 -08:00
|
|
|
|
|
|
|
|
func (ctxt *Link) Dconv(a *Addr) string {
|
|
|
|
|
return Dconv(nil, ctxt.Rconv, a)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Dconv(p *Prog, Rconv func(int) string, a *Addr) string {
|
|
|
|
|
var str string
|
|
|
|
|
|
|
|
|
|
switch a.Type {
|
|
|
|
|
default:
|
|
|
|
|
str = fmt.Sprintf("type=%d", a.Type)
|
|
|
|
|
|
|
|
|
|
case TYPE_NONE:
|
|
|
|
|
str = ""
|
|
|
|
|
if a.Name != NAME_NONE || a.Reg != 0 || a.Sym != nil {
|
|
|
|
|
str = fmt.Sprintf("%v(%v)(NONE)", Mconv(Rconv, a), Rconv(int(a.Reg)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_REG:
|
|
|
|
|
// TODO(rsc): This special case is for x86 instructions like
|
|
|
|
|
// PINSRQ CX,$1,X6
|
|
|
|
|
// where the $1 is included in the p->to Addr.
|
|
|
|
|
// Move into a new field.
|
|
|
|
|
if a.Offset != 0 {
|
|
|
|
|
str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(int(a.Reg)))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str = fmt.Sprintf("%v", Rconv(int(a.Reg)))
|
|
|
|
|
if a.Name != TYPE_NONE || a.Sym != nil {
|
|
|
|
|
str = fmt.Sprintf("%v(%v)(REG)", Mconv(Rconv, a), Rconv(int(a.Reg)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_BRANCH:
|
|
|
|
|
if a.Sym != nil {
|
|
|
|
|
str = fmt.Sprintf("%s(SB)", a.Sym.Name)
|
|
|
|
|
} else if p != nil && p.Pcond != nil {
|
|
|
|
|
str = fmt.Sprintf("%d", p.Pcond.Pc)
|
|
|
|
|
} else if a.U.Branch != nil {
|
|
|
|
|
str = fmt.Sprintf("%d", a.U.Branch.Pc)
|
|
|
|
|
} else {
|
|
|
|
|
str = fmt.Sprintf("%d(PC)", a.Offset)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_MEM:
|
|
|
|
|
str = Mconv(Rconv, a)
|
|
|
|
|
if a.Index != REG_NONE {
|
|
|
|
|
str += fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_CONST:
|
|
|
|
|
if a.Reg != 0 {
|
|
|
|
|
str = fmt.Sprintf("$%v(%v)", Mconv(Rconv, a), Rconv(int(a.Reg)))
|
|
|
|
|
} else {
|
|
|
|
|
str = fmt.Sprintf("$%v", Mconv(Rconv, a))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_TEXTSIZE:
|
|
|
|
|
if a.U.Argsize == ArgsSizeUnknown {
|
|
|
|
|
str = fmt.Sprintf("$%d", a.Offset)
|
|
|
|
|
} else {
|
|
|
|
|
str = fmt.Sprintf("$%d-%d", a.Offset, a.U.Argsize)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_FCONST:
|
|
|
|
|
str = fmt.Sprintf("%.17g", a.U.Dval)
|
|
|
|
|
// Make sure 1 prints as 1.0
|
|
|
|
|
if !strings.ContainsAny(str, ".e") {
|
|
|
|
|
str += ".0"
|
|
|
|
|
}
|
|
|
|
|
str = fmt.Sprintf("$(%s)", str)
|
|
|
|
|
|
|
|
|
|
case TYPE_SCONST:
|
|
|
|
|
str = fmt.Sprintf("$%q", a.U.Sval)
|
|
|
|
|
|
|
|
|
|
case TYPE_ADDR:
|
|
|
|
|
str = fmt.Sprintf("$%s", Mconv(Rconv, a))
|
|
|
|
|
|
|
|
|
|
case TYPE_SHIFT:
|
|
|
|
|
v := int(a.Offset)
|
|
|
|
|
op := string("<<>>->@>"[((v>>5)&3)<<1:])
|
|
|
|
|
if v&(1<<4) != 0 {
|
|
|
|
|
str = fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
|
|
|
|
|
} else {
|
|
|
|
|
str = fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
|
|
|
|
|
}
|
|
|
|
|
if a.Reg != 0 {
|
|
|
|
|
str += fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TYPE_REGREG:
|
|
|
|
|
str = fmt.Sprintf("(%v, %v)", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
|
|
|
|
|
|
|
|
|
|
case TYPE_REGREG2:
|
|
|
|
|
str = fmt.Sprintf("%v, %v", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Mconv(Rconv func(int) string, a *Addr) string {
|
|
|
|
|
var str string
|
|
|
|
|
|
|
|
|
|
switch a.Name {
|
|
|
|
|
default:
|
|
|
|
|
str = fmt.Sprintf("name=%d", a.Name)
|
|
|
|
|
|
|
|
|
|
case NAME_NONE:
|
|
|
|
|
switch {
|
|
|
|
|
case a.Reg == REG_NONE:
|
|
|
|
|
str = fmt.Sprintf("%d", a.Offset)
|
|
|
|
|
case a.Offset == 0:
|
|
|
|
|
str = fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
|
|
|
|
|
case a.Offset != 0:
|
|
|
|
|
str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(int(a.Reg)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case NAME_EXTERN:
|
|
|
|
|
str = fmt.Sprintf("%s%s(SB)", a.Sym.Name, offConv(a.Offset))
|
|
|
|
|
|
|
|
|
|
case NAME_STATIC:
|
|
|
|
|
str = fmt.Sprintf("%s<>%s(SB)", a.Sym.Name, offConv(a.Offset))
|
|
|
|
|
|
|
|
|
|
case NAME_AUTO:
|
|
|
|
|
if a.Sym != nil {
|
|
|
|
|
str = fmt.Sprintf("%s%s(SP)", a.Sym.Name, offConv(a.Offset))
|
|
|
|
|
} else {
|
|
|
|
|
str = fmt.Sprintf("%s(SP)", offConv(a.Offset))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case NAME_PARAM:
|
|
|
|
|
if a.Sym != nil {
|
|
|
|
|
str = fmt.Sprintf("%s%s(FP)", a.Sym.Name, offConv(a.Offset))
|
|
|
|
|
} else {
|
|
|
|
|
str = fmt.Sprintf("%s(FP)", offConv(a.Offset))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func offConv(off int64) string {
|
|
|
|
|
if off == 0 {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%+d", off)
|
|
|
|
|
}
|