diff options
-rw-r--r-- | src/cmd/5g/cgen64.c | 106 | ||||
-rw-r--r-- | src/pkg/os/dir_linux_arm.go | 81 | ||||
-rw-r--r-- | src/pkg/os/stat_linux_arm.go | 44 | ||||
-rw-r--r-- | src/pkg/syscall/asm_linux_arm.s | 4 | ||||
-rw-r--r-- | src/pkg/syscall/ztypes_linux_arm.go | 28 |
5 files changed, 203 insertions, 60 deletions
diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c index 9c42a4958..05e49fa73 100644 --- a/src/cmd/5g/cgen64.c +++ b/src/cmd/5g/cgen64.c @@ -98,13 +98,13 @@ cgen64(Node *n, Node *res) regfree(&bh); break; -// case OSUB: -// // TODO: Constants. -// gins(AMOVL, &lo1, &ax); -// gins(AMOVL, &hi1, &dx); -// gins(ASUBL, &lo2, &ax); -// gins(ASBBL, &hi2, &dx); -// break; + case OSUB: + // TODO: Constants. + gins(AMOVW, &lo1, &al); + gins(AMOVW, &hi1, &ah); + gins(ASUB, &lo2, &al); + gins(ASBC, &hi2, &ah); + break; case OMUL: // TODO(kaib): this can be done with 4 regs and does not need 6 @@ -156,40 +156,53 @@ cgen64(Node *n, Node *res) break; -// case OLSH: - // TODO(kaib): optimize for OLITERAL -// regalloc(&s1, types[TPTR32], N); -// regalloc(&s2, types[TPTR32], N); + case OLSH: + if(r->op == OLITERAL) { + v = mpgetfix(r->val.u.xval); + if(v >= 64) { + // TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al) + // here and below (verify it optimizes to EOR) + gins(AEOR, &al, &al); + gins(AEOR, &ah, &ah); + break; + } + if(v >= 32) { + gins(AEOR, &al, &al); + // MOVW lo1<<(v-32), ah + p1 = gins(AMOVW, &lo1, &ah); + p1->from.type = D_SHIFT; + p1->from.offset = SHIFT_LL | (v-32)<<7 | lo1.val.u.reg; + p1->from.reg = NREG; + break; + } -// gins(AMOVW, &lo1, &al); -// gins(AMOVW, &hi1, &ah); -// if(is64(r->type)) { -// gins(AMOVW, &lo2, &s1); -// gins(AMOVW, &hi2, &s2); -// p1 = gins(AOR, &s2, &s1); -// p1->from.type = D_SHIFT; -// p1->from.offset = 5 << 7 | s2.val.u.reg; // s2<<7 -// p1->from.reg = NREG; -// } else -// gins(AMOVW, r, &s1 -// p1 = gins(AMOVW, &s1, &s2); -// p1->from.offset = -32; + // general literal left shift -// // MOVW ah<<s1, ah -// p1 = gins(AMOVW, &ah, &ah); -// p1->from.offset = ah.val.u.reg | 1<<4 | s1.val.u.reg <<8; + // MOVW lo1<<v, al + p1 = gins(AMOVW, &lo1, &al); + p1->from.type = D_SHIFT; + p1->from.offset = SHIFT_LL | v<<7 | lo1.val.u.reg; + p1->from.reg = NREG; + break; - // OR al<<s2, ah -// p1 = gins(AOR, &al, &ah); -// p1->from.offset = al.val.u.reg | 1<<4 | s2.val.u.reg << 8; + // MOVW hi1<<v, ah + p1 = gins(AMOVW, &hi1, &ah); + p1->from.type = D_SHIFT; + p1->from.offset = SHIFT_LL | v<<7 | hi1.val.u.reg; + p1->from.reg = NREG; + break; - // MOVW al<<s1, al -// p1 = gins(AMOVW, &al, &al); -// p1->from.offset = al.val.u.reg | 1<<4 | s1.val.u.reg <<8; + // OR lo1>>(32-v), ah + p1 = gins(AORR, &lo1, &ah); + p1->from.type = D_SHIFT; + p1->from.offset = SHIFT_LR | (32-v)<<7 | lo1.val.u.reg; + p1->from.reg = NREG; + break; + } + + fatal("cgen64 OLSH, !OLITERAL not implemented"); + break; -// regfree(&s1); -// regfree(&s2); -// break; case ORSH: if(r->op == OLITERAL) { @@ -237,7 +250,7 @@ cgen64(Node *n, Node *res) break; } - // general shift + // general literal right shift // MOVW lo1>>v, al p1 = gins(AMOVW, &lo1, &al); @@ -319,10 +332,11 @@ cgen64(Node *n, Node *res) // patch(p2, pc); // break; -// case OXOR: -// case OAND: -// case OOR: -// // make constant the right side (it usually is anyway). + case OXOR: + case OAND: + case OOR: + // TODO(kaib): literal optimizations + // make constant the right side (it usually is anyway). // if(lo1.op == OLITERAL) { // nswap(&lo1, &lo2); // nswap(&hi1, &hi2); @@ -413,11 +427,11 @@ cgen64(Node *n, Node *res) // splitclean(); // goto out; // } -// gins(AMOVL, &lo1, &ax); -// gins(AMOVL, &hi1, &dx); -// gins(optoas(n->op, lo1.type), &lo2, &ax); -// gins(optoas(n->op, lo1.type), &hi2, &dx); -// break; + gins(AMOVW, &lo1, &al); + gins(AMOVW, &hi1, &ah); + gins(optoas(n->op, lo1.type), &lo2, &al); + gins(optoas(n->op, lo1.type), &hi2, &ah); + break; } if(is64(r->type)) splitclean(); diff --git a/src/pkg/os/dir_linux_arm.go b/src/pkg/os/dir_linux_arm.go new file mode 100644 index 000000000..0e70f0ba0 --- /dev/null +++ b/src/pkg/os/dir_linux_arm.go @@ -0,0 +1,81 @@ +// Copyright 2009 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. + +// TODO(rsc): Once the porting dust settles, consider +// whether this file should be dir_linux.go (and similarly +// dir_darwin.go) instead of having one copy per architecture. + +package os + +import ( + "syscall"; + "unsafe"; +) + +const ( + blockSize = 4096 // TODO(r): use statfs +) + +func clen(n []byte) int { + for i := 0; i < len(n); i++ { + if n[i] == 0 { + return i + } + } + return len(n) +} + +func (file *File) Readdirnames(count int) (names []string, err Error) { + // If this file has no dirinfo, create one. + if file.dirinfo == nil { + file.dirinfo = new(dirInfo); + // The buffer must be at least a block long. + // TODO(r): use fstatfs to find fs block size. + file.dirinfo.buf = make([]byte, blockSize); + } + d := file.dirinfo; + size := count; + if size < 0 { + size = 100 + } + names = make([]string, 0, size); // Empty with room to grow. + for count != 0 { + // Refill the buffer if necessary + if d.bufp >= d.nbuf { + var errno int; + d.nbuf, errno = syscall.Getdents(file.fd, d.buf); + if errno != 0 { + return names, NewSyscallError("getdents", errno) + } + if d.nbuf <= 0 { + break // EOF + } + d.bufp = 0; + } + // Drain the buffer + for count != 0 && d.bufp < d.nbuf { + dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); + d.bufp += int(dirent.Reclen); + if dirent.Ino == 0 { // File absent in directory. + continue + } + bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); + var name = string(bytes[0:clen(bytes)]); + if name == "." || name == ".." { // Useless names + continue + } + count--; + if len(names) == cap(names) { + nnames := make([]string, len(names), 2*len(names)); + for i := 0; i < len(names); i++ { + nnames[i] = names[i] + } + names = nnames; + } + names = names[0:len(names)+1]; + names[len(names)-1] = name; + } + } + return names, nil; +} diff --git a/src/pkg/os/stat_linux_arm.go b/src/pkg/os/stat_linux_arm.go new file mode 100644 index 000000000..d08fabcc6 --- /dev/null +++ b/src/pkg/os/stat_linux_arm.go @@ -0,0 +1,44 @@ +// Copyright 2009 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. + +// TODO(rsc): Once the porting dust settles, consider +// whether this file should be stat_linux.go (and similarly +// stat_darwin.go) instead of having one copy per architecture. + +// 386, Linux + +package os + +import "syscall" + +func isSymlink(stat *syscall.Stat_t) bool { + return stat.Mode & syscall.S_IFMT == syscall.S_IFLNK +} + +func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { + dir.Dev = stat.Dev; + dir.Ino = uint64(stat.Ino); + dir.Nlink = uint64(stat.Nlink); + dir.Mode = stat.Mode; + dir.Uid = stat.Uid; + dir.Gid = stat.Gid; + dir.Rdev = stat.Rdev; + dir.Size = uint64(stat.Size); + dir.Blksize = uint64(stat.Blksize); + dir.Blocks = uint64(stat.Blocks); + dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim)); + dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim)); + dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim)); + for i := len(name) - 1; i >= 0; i-- { + if name[i] == '/' { + name = name[i+1:len(name)]; + break; + } + } + dir.Name = name; + if isSymlink(lstat) && !isSymlink(stat) { + dir.FollowedSymlink = true; + } + return dir; +} diff --git a/src/pkg/syscall/asm_linux_arm.s b/src/pkg/syscall/asm_linux_arm.s new file mode 100644 index 000000000..024018d5a --- /dev/null +++ b/src/pkg/syscall/asm_linux_arm.s @@ -0,0 +1,4 @@ +// Copyright 2009 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. + diff --git a/src/pkg/syscall/ztypes_linux_arm.go b/src/pkg/syscall/ztypes_linux_arm.go index a3b1e6b79..c038e0243 100644 --- a/src/pkg/syscall/ztypes_linux_arm.go +++ b/src/pkg/syscall/ztypes_linux_arm.go @@ -1,4 +1,4 @@ -// godefs -gsyscall -f-m32 types_linux.c types_linux_386.c +// godefs -gsyscall -f-m32 types_linux.c // MACHINE GENERATED - DO NOT EDIT. @@ -163,18 +163,18 @@ type Timex struct { Calcnt int32; Errcnt int32; Stbcnt int32; - int32; - int32; - int32; - int32; - int32; - int32; - int32; - int32; - int32; - int32; - int32; - int32; + Pad0 int32; + Pad1 int32; + Pad2 int32; + Pad3 int32; + Pad4 int32; + Pad5 int32; + Pad6 int32; + Pad7 int32; + Pad8 int32; + Pad9 int32; + Pad10 int32; + Pad11 int32; } type Time_t int32 @@ -314,7 +314,7 @@ type PtraceRegs struct { __fs uint16; Gs uint16; __gs uint16; - Eax int32; + Orig_eax int32; Eip int32; Cs uint16; __cs uint16; |