diff options
Diffstat (limited to 'src/pkg/runtime/amd64/closure.c')
-rw-r--r-- | src/pkg/runtime/amd64/closure.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/src/pkg/runtime/amd64/closure.c b/src/pkg/runtime/amd64/closure.c index 5717d3c5e..21ac7c383 100644 --- a/src/pkg/runtime/amd64/closure.c +++ b/src/pkg/runtime/amd64/closure.c @@ -43,47 +43,49 @@ sys·closure(int32 siz, byte *fn, byte *arg0) p = mal(n); *ret = p; q = p + n - siz; - mcpy(q, (byte*)&arg0, siz); - // SUBQ $siz, SP - *p++ = 0x48; - *p++ = 0x81; - *p++ = 0xec; - *(uint32*)p = siz; - p += 4; + if(siz > 0) { + mcpy(q, (byte*)&arg0, siz); - // MOVQ $q, SI - *p++ = 0x48; - *p++ = 0xbe; - *(byte**)p = q; - p += 8; + // SUBQ $siz, SP + *p++ = 0x48; + *p++ = 0x81; + *p++ = 0xec; + *(uint32*)p = siz; + p += 4; - // MOVQ SP, DI - *p++ = 0x48; - *p++ = 0x89; - *p++ = 0xe7; + // MOVQ $q, SI + *p++ = 0x48; + *p++ = 0xbe; + *(byte**)p = q; + p += 8; - if(siz <= 4*8) { - for(i=0; i<siz; i+=8) { - // MOVSQ + // MOVQ SP, DI + *p++ = 0x48; + *p++ = 0x89; + *p++ = 0xe7; + + if(siz <= 4*8) { + for(i=0; i<siz; i+=8) { + // MOVSQ + *p++ = 0x48; + *p++ = 0xa5; + } + } else { + // MOVQ $(siz/8), CX [32-bit immediate siz/8] + *p++ = 0x48; + *p++ = 0xc7; + *p++ = 0xc1; + *(uint32*)p = siz/8; + p += 4; + + // REP; MOVSQ + *p++ = 0xf3; *p++ = 0x48; *p++ = 0xa5; } - } else { - // MOVQ $(siz/8), CX [32-bit immediate siz/8] - *p++ = 0x48; - *p++ = 0xc7; - *p++ = 0xc1; - *(uint32*)p = siz/8; - p += 4; - - // REP; MOVSQ - *p++ = 0xf3; - *p++ = 0x48; - *p++ = 0xa5; } - // call fn pcrel = fn - (p+5); if((int32)pcrel == pcrel) { |