Commit 10ea6519 authored by Russ Cox's avatar Russ Cox

build: make int 64 bits on amd64

The assembly offsets were converted mechanically using
code.google.com/p/rsc/cmd/asmlint. The instruction
changes were done by hand.

Fixes #2188.

R=iant, r, bradfitz, remyoudompheng
CC=golang-dev
https://golang.org/cl/6550058
parent f8c58373
<!--{
"Title": "Go 1.1 Release Notes",
"Path": "/doc/go1.1"
"Template": true
}-->
<h2 id="introduction">Introduction to Go 1.1</h2>
TODO
- overview
- link back to Go 1 and also Go 1 Compatibility docs.
<h2 id="language">Changes to the language</h2>
TODO
<h2 id="impl">Changes to the implementations and tools</h2>
TODO: more
<h3 id="int">Size of int on 64-bit platforms</h3>
<p>
The language allows the implementation to choose whether the <code>int</code> type and <code>uint</code> types are 32 or 64 bits. Previous Go implementations made <code>int</code> and <code>uint</code> 32 bits on all systems. Both the gc and gccgo implementations (TODO: check that gccgo does) <a href="http://golang.org/issue/2188">now make <code>int</code> and <code>uint</code> 64 bits on 64-bit platforms such as AMD64/x86-64</a>.
Among other things, this enables the allocation of slices with
more than 2 billion elements on 64-bit platforms.
</p>
<p>
<em>Updating</em>:
Most programs will be unaffected by this change.
Because Go does not allow implicit conversions between distinct
<a href="/ref/spec#Numeric_types">numeric types</a>,
no programs will stop compiling due to this change.
However, programs that contain implicit assumptions
that <code>int</code> is only 32 bits may change behavior.
For example, this code prints a positive number on 64-bit systems and
a negative one on 32-bit systems:
<pre>
x := ^uint32(0) // x is 0xffffffff
i := int(x) // i is -1 on 32-bit systems, 0xffffffff on 64-bit
fmt.Println(i)
</pre>
<p>Portable code intending 32-bit sign extension (yielding -1 on all systems)
would instead say:
</p>
<pre>
i := int(int32(x))
</pre>
<h3 id="asm">Assembler</h3>
<p>
Due to the <a href="#int">int</a> and TODO: OTHER changes,
the placement of function arguments on the stack has changed.
Functions written in assembly will need to be revised at least
to adjust frame pointer offsets.
</p>
<h2 id="library">Changes to the standard library</h2>
TODO
<!--{
"Title": "FAQ"
"Title": "FAQ",
"Path": "/doc/faq"
}-->
<h2 id="Origins">Origins</h2>
......@@ -1052,9 +1053,11 @@ Why is <code>int</code> 32 bits on 64 bit machines?</h3>
<p>
The sizes of <code>int</code> and <code>uint</code> are implementation-specific
but the same as each other on a given platform.
The 64 bit Go compilers (both gc and gccgo) use a 32 bit representation for
<code>int</code>. Code that relies on a particular
For portability, code that relies on a particular
size of value should use an explicitly sized type, like <code>int64</code>.
Prior to Go 1.1, the 64-bit Go compilers (both gc and gccgo) used
a 32-bit representation for <code>int</code>. As of Go 1.1 they use
a 64-bit representation.
On the other hand, floating-point scalars and complex
numbers are always sized: <code>float32</code>, <code>complex64</code>,
etc., because programmers should be aware of precision when using
......
......@@ -17,8 +17,8 @@ vlong MAXWIDTH = 1LL<<50;
*/
Typedef typedefs[] =
{
"int", TINT, TINT32,
"uint", TUINT, TUINT32,
"int", TINT, TINT64,
"uint", TUINT, TUINT64,
"uintptr", TUINTPTR, TUINT64,
0
};
......@@ -27,7 +27,7 @@ void
betypeinit(void)
{
widthptr = 8;
widthint = 4;
widthint = 8;
zprog.link = P;
zprog.as = AGOK;
......
......@@ -41,7 +41,7 @@ enum
{
thechar = '6',
PtrSize = 8,
IntSize = 4,
IntSize = 8,
// Loop alignment constants:
// want to align loop entry to LoopAlign-byte boundary,
......
......@@ -132,7 +132,7 @@ var ptrSizeMap = map[string]int64{
var intSizeMap = map[string]int64{
"386": 4,
"amd64": 4,
"amd64": 8,
"arm": 4,
}
......
......@@ -28,7 +28,7 @@ static Buf *output;
enum
{
use64bitint = 0,
use64bitint = 1,
};
static int
......
......@@ -4,11 +4,11 @@
TEXT ·IndexByte(SB),7,$0
MOVQ s+0(FP), SI
MOVL s+8(FP), BX
MOVB c+16(FP), AL
MOVQ s+8(FP), BX
MOVB c+24(FP), AL
MOVQ SI, DI
CMPL BX, $16
CMPQ BX, $16
JLT small
// round up to first 16-byte boundary
......@@ -63,15 +63,15 @@ condition:
JZ success
failure:
MOVL $-1, r+24(FP)
MOVQ $-1, r+32(FP)
RET
// handle for lengths < 16
small:
MOVL BX, CX
MOVQ BX, CX
REPN; SCASB
JZ success
MOVL $-1, r+24(FP)
MOVQ $-1, r+32(FP)
RET
// we've found the chunk containing the byte
......@@ -81,28 +81,28 @@ ssesuccess:
BSFW DX, DX
SUBQ SI, DI
ADDQ DI, DX
MOVL DX, r+24(FP)
MOVQ DX, r+32(FP)
RET
success:
SUBQ SI, DI
SUBL $1, DI
MOVL DI, r+24(FP)
MOVQ DI, r+32(FP)
RET
TEXT ·Equal(SB),7,$0
MOVL a+8(FP), BX
MOVL b+24(FP), CX
MOVQ a+8(FP), BX
MOVQ b+32(FP), CX
MOVL $0, AX
CMPL BX, CX
CMPQ BX, CX
JNE eqret
MOVQ a+0(FP), SI
MOVQ b+16(FP), DI
MOVQ b+24(FP), DI
CLD
REP; CMPSB
MOVL $1, DX
CMOVLEQ DX, AX
eqret:
MOVB AX, r+32(FP)
MOVB AX, r+48(FP)
RET
......@@ -6,12 +6,12 @@
TEXT ·castagnoliSSE42(SB),7,$0
MOVL crc+0(FP), AX // CRC value
MOVQ p+8(FP), SI // data pointer
MOVL p+16(FP), CX // len(p)
MOVQ p+16(FP), CX // len(p)
NOTL AX
/* If there's less than 8 bytes to process, we do it byte-by-byte. */
CMPL CX, $8
CMPQ CX, $8
JL cleanup
/* Process individual bytes until the input is 8-byte aligned. */
......@@ -21,13 +21,13 @@ startup:
JZ aligned
CRC32B (SI), AX
DECL CX
DECQ CX
INCQ SI
JMP startup
aligned:
/* The input is now 8-byte aligned and we can process 8-byte chunks. */
CMPL CX, $8
CMPQ CX, $8
JL cleanup
CRC32Q (SI), AX
......@@ -37,7 +37,7 @@ aligned:
cleanup:
/* We may have some bytes left over that we process one at a time. */
CMPL CX, $0
CMPQ CX, $0
JE done
CRC32B (SI), AX
......@@ -47,7 +47,7 @@ cleanup:
done:
NOTL AX
MOVL AX, r+24(FP)
MOVL AX, r+32(FP)
RET
// func haveSSE42() bool
......
......@@ -36,9 +36,9 @@ TEXT ·divWW(SB),7,$0
// func addVV(z, x, y []Word) (c Word)
TEXT ·addVV(SB),7,$0
MOVL z+8(FP), DI
MOVQ x+16(FP), R8
MOVQ y+32(FP), R9
MOVQ z+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ z+0(FP), R10
MOVQ $0, CX // c = 0
......@@ -83,16 +83,16 @@ L1: // n > 0
SUBQ $1, DI // n--
JG L1 // if n > 0 goto L1
E1: MOVQ CX, c+48(FP) // return c
E1: MOVQ CX, c+72(FP) // return c
RET
// func subVV(z, x, y []Word) (c Word)
// (same as addVV except for SBBQ instead of ADCQ and label names)
TEXT ·subVV(SB),7,$0
MOVL z+8(FP), DI
MOVQ x+16(FP), R8
MOVQ y+32(FP), R9
MOVQ z+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ z+0(FP), R10
MOVQ $0, CX // c = 0
......@@ -137,15 +137,15 @@ L2: // n > 0
SUBQ $1, DI // n--
JG L2 // if n > 0 goto L2
E2: MOVQ CX, c+48(FP) // return c
E2: MOVQ CX, c+72(FP) // return c
RET
// func addVW(z, x []Word, y Word) (c Word)
TEXT ·addVW(SB),7,$0
MOVL z+8(FP), DI
MOVQ x+16(FP), R8
MOVQ y+32(FP), CX // c = y
MOVQ z+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), CX // c = y
MOVQ z+0(FP), R10
MOVQ $0, SI // i = 0
......@@ -188,16 +188,16 @@ L3: // n > 0
SUBQ $1, DI // n--
JG L3 // if n > 0 goto L3
E3: MOVQ CX, c+40(FP) // return c
E3: MOVQ CX, c+56(FP) // return c
RET
// func subVW(z, x []Word, y Word) (c Word)
// (same as addVW except for SUBQ/SBBQ instead of ADDQ/ADCQ and label names)
TEXT ·subVW(SB),7,$0
MOVL z+8(FP), DI
MOVQ x+16(FP), R8
MOVQ y+32(FP), CX // c = y
MOVQ z+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), CX // c = y
MOVQ z+0(FP), R10
MOVQ $0, SI // i = 0
......@@ -241,26 +241,26 @@ L4: // n > 0
SUBQ $1, DI // n--
JG L4 // if n > 0 goto L4
E4: MOVQ CX, c+40(FP) // return c
E4: MOVQ CX, c+56(FP) // return c
RET
// func shlVU(z, x []Word, s uint) (c Word)
TEXT ·shlVU(SB),7,$0
MOVL z+8(FP), BX // i = z
SUBL $1, BX // i--
MOVQ z+8(FP), BX // i = z
SUBQ $1, BX // i--
JL X8b // i < 0 (n <= 0)
// n > 0
MOVQ z+0(FP), R10
MOVQ x+16(FP), R8
MOVL s+32(FP), CX
MOVQ x+24(FP), R8
MOVQ s+48(FP), CX
MOVQ (R8)(BX*8), AX // w1 = x[n-1]
MOVQ $0, DX
SHLQ CX, DX:AX // w1>>ŝ
MOVQ DX, c+40(FP)
MOVQ DX, c+56(FP)
CMPL BX, $0
CMPQ BX, $0
JLE X8a // i <= 0
// i > 0
......@@ -268,7 +268,7 @@ L8: MOVQ AX, DX // w = w1
MOVQ -8(R8)(BX*8), AX // w1 = x[i-1]
SHLQ CX, DX:AX // w<<s | w1>>ŝ
MOVQ DX, (R10)(BX*8) // z[i] = w<<s | w1>>ŝ
SUBL $1, BX // i--
SUBQ $1, BX // i--
JG L8 // i > 0
// i <= 0
......@@ -276,24 +276,24 @@ X8a: SHLQ CX, AX // w1<<s
MOVQ AX, (R10) // z[0] = w1<<s
RET
X8b: MOVQ $0, c+40(FP)
X8b: MOVQ $0, c+56(FP)
RET
// func shrVU(z, x []Word, s uint) (c Word)
TEXT ·shrVU(SB),7,$0
MOVL z+8(FP), R11
SUBL $1, R11 // n--
MOVQ z+8(FP), R11
SUBQ $1, R11 // n--
JL X9b // n < 0 (n <= 0)
// n > 0
MOVQ z+0(FP), R10
MOVQ x+16(FP), R8
MOVL s+32(FP), CX
MOVQ x+24(FP), R8
MOVQ s+48(FP), CX
MOVQ (R8), AX // w1 = x[0]
MOVQ $0, DX
SHRQ CX, DX:AX // w1<<ŝ
MOVQ DX, c+40(FP)
MOVQ DX, c+56(FP)
MOVQ $0, BX // i = 0
JMP E9
......@@ -303,7 +303,7 @@ L9: MOVQ AX, DX // w = w1
MOVQ 8(R8)(BX*8), AX // w1 = x[i+1]
SHRQ CX, DX:AX // w>>s | w1<<ŝ
MOVQ DX, (R10)(BX*8) // z[i] = w>>s | w1<<ŝ
ADDL $1, BX // i++
ADDQ $1, BX // i++
E9: CMPQ BX, R11
JL L9 // i < n-1
......@@ -313,17 +313,17 @@ X9a: SHRQ CX, AX // w1>>s
MOVQ AX, (R10)(R11*8) // z[n-1] = w1>>s
RET
X9b: MOVQ $0, c+40(FP)
X9b: MOVQ $0, c+56(FP)
RET
// func mulAddVWW(z, x []Word, y, r Word) (c Word)
TEXT ·mulAddVWW(SB),7,$0
MOVQ z+0(FP), R10
MOVQ x+16(FP), R8
MOVQ y+32(FP), R9
MOVQ r+40(FP), CX // c = r
MOVL z+8(FP), R11
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ r+56(FP), CX // c = r
MOVQ z+8(FP), R11
MOVQ $0, BX // i = 0
JMP E5
......@@ -333,21 +333,21 @@ L5: MOVQ (R8)(BX*8), AX
ADCQ $0, DX
MOVQ AX, (R10)(BX*8)
MOVQ DX, CX
ADDL $1, BX // i++
ADDQ $1, BX // i++
E5: CMPQ BX, R11 // i < n
JL L5
MOVQ CX, c+48(FP)
MOVQ CX, c+64(FP)
RET
// func addMulVVW(z, x []Word, y Word) (c Word)
TEXT ·addMulVVW(SB),7,$0
MOVQ z+0(FP), R10
MOVQ x+16(FP), R8
MOVQ y+32(FP), R9
MOVL z+8(FP), R11
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ z+8(FP), R11
MOVQ $0, BX // i = 0
MOVQ $0, CX // c = 0
JMP E6
......@@ -359,41 +359,41 @@ L6: MOVQ (R8)(BX*8), AX
ADDQ AX, (R10)(BX*8)
ADCQ $0, DX
MOVQ DX, CX
ADDL $1, BX // i++
ADDQ $1, BX // i++
E6: CMPQ BX, R11 // i < n
JL L6
MOVQ CX, c+40(FP)
MOVQ CX, c+56(FP)
RET
// func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
TEXT ·divWVW(SB),7,$0
MOVQ z+0(FP), R10
MOVQ xn+16(FP), DX // r = xn
MOVQ x+24(FP), R8
MOVQ y+40(FP), R9
MOVL z+8(FP), BX // i = z
MOVQ xn+24(FP), DX // r = xn
MOVQ x+32(FP), R8
MOVQ y+56(FP), R9
MOVQ z+8(FP), BX // i = z
JMP E7
L7: MOVQ (R8)(BX*8), AX
DIVQ R9
MOVQ AX, (R10)(BX*8)
E7: SUBL $1, BX // i--
E7: SUBQ $1, BX // i--
JGE L7 // i >= 0
MOVQ DX, r+48(FP)
MOVQ DX, r+64(FP)
RET
// func bitLen(x Word) (n int)
TEXT ·bitLen(SB),7,$0
BSRQ x+0(FP), AX
JZ Z1
ADDL $1, AX
MOVL AX, n+8(FP)
ADDQ $1, AX
MOVQ AX, n+8(FP)
RET
Z1: MOVL $0, n+8(FP)
Z1: MOVQ $0, n+8(FP)
RET
......@@ -19,8 +19,8 @@ typedef double float64;
#ifdef _64BIT
typedef uint64 uintptr;
typedef int64 intptr;
typedef int32 intgo; // Go's int
typedef uint32 uintgo; // Go's uint
typedef int64 intgo; // Go's int
typedef uint64 uintgo; // Go's uint
#else
typedef uint32 uintptr;
typedef int32 intptr;
......
......@@ -21,6 +21,7 @@ import (
"flag"
"fmt"
"os"
"runtime"
)
const prolog = `
......@@ -224,6 +225,10 @@ func main() {
// the next pass from running.
// So run it as a separate check.
thisPass = 1
} else if i == "i64big" || i == "i64bigger" && runtime.GOARCH == "amd64" {
// On amd64, these huge numbers do fit in an int, so they are not
// rejected at compile time.
thisPass = 0
} else {
thisPass = 2
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment