<commit_before>// Copyright 2018 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 arm64 implements an ARM64 assembler. Go assembly syntax is different from GNU ARM64
syntax, but we can still follow the general rules to map between them.

Instructions mnemonics mapping rules

1. Most instructions use width suffixes of instruction names to indicate operand width rather than
using different register names.

  Examples:
    ADC R24, R14, R12          <=>     adc x12, x24
    ADDW R26->24, R21, R15     <=>     add w15, w21, w26, asr #24
    FCMPS F2, F3               <=>     fcmp s3, s2
    FCMPD F2, F3               <=>     fcmp d3, d2
    FCVTDH F2, F3              <=>     fcvt h3, d2

2. Go uses .P and .W suffixes to indicate post-increment and pre-increment.

  Examples:
    MOVD.P -8(R10), R8         <=>      ldr x8, [x10],#-8
    MOVB.W 16(R16), R10        <=>      ldrsb x10, [x16,#16]!
    MOVBU.W 16(R16), R10       <=>      ldrb x10, [x16,#16]!

3. Go uses a series of MOV instructions as load and store.

64-bit variant ldr, str, stur => MOVD;
32-bit variant str, stur, ldrsw => MOVW;
32-bit variant ldr => MOVWU;
ldrb => MOVBU; ldrh => MOVHU;
ldrsb, sturb, strb => MOVB;
ldrsh, sturh, strh =>  MOVH.

4. Go moves conditions into opcode suffix, like BLT.

5. Go adds a V prefix for most floating-point and SIMD instructions, except cryptographic extension
instructions and floating-point(scalar) instructions.

  Examples:
    VADD V5.H8, V18.H8, V9.H8         <=>      add v9.8h, v18.8h, v5.8h
    VLD1.P (R6)(R11), [V31.D1]        <=>      ld1 {v31.1d}, [x6], x11
    VFMLA V29.S2, V20.S2, V14.S2      <=>      fmla v14.2s, v20.2s, v29.2s
    AESD V22.B16, V19.B16             <=>      aesd v19.16b, v22.16b
    SCVTFWS R3, F16                   <=>      scvtf s17, w6

6. Align directive

Go asm supports the PCALIGN directive, which indicates that the next instruction should be aligned
to a specified boundary by padding with NOOP instruction. The alignment value supported on arm64
must be a power of 2 and in the range of [8, 2048].

  Examples:
    PCALIGN $16
    MOVD $2, R0          // This instruction is aligned with 16 bytes.
    PCALIGN $1024
    MOVD $3, R1          // This instruction is aligned with 1024 bytes.

PCALIGN also changes the function alignment. If a function has one or more PCALIGN directives,
its address will be aligned to the same or coarser boundary, which is the maximum of all the
alignment values.

In the following example, the function Add is aligned with 128 bytes.
  Examples:
    TEXT ·Add(SB),$40-16
    MOVD $2, R0
    PCALIGN $32
    MOVD $4, R1
    PCALIGN $128
    MOVD $8, R2
    RET

On arm64, functions in Go are aligned to 16 bytes by default, we can also use PCALGIN to set the
function alignment. The functions that need to be aligned are preferably using NOFRAME and NOSPLIT
to avoid the impact of the prologues inserted by the assembler, so that the function address will
have the same alignment as the first hand-written instruction.

In the following example, PCALIGN at the entry of the function Add will align its address to 2048 bytes.

  Examples:
    TEXT ·Add(SB),NOSPLIT|NOFRAME,$0
      PCALIGN $2048
      MOVD $1, R0
      MOVD $1, R1
      RET

7. Move large constants to vector registers.

Go asm uses VMOVQ/VMOVD/VMOVS to move 128-bit, 64-bit and 32-bit constants into vector registers, respectively.
And for a 128-bit interger, it take two 64-bit operands, for the high and low parts separately.

  Examples:
    VMOVS $0x11223344, V0
    VMOVD $0x1122334455667788, V1
    VMOVQ $0x1122334455667788, $8877665544332211, V2   // V2=0x11223344556677888877665544332211

Special Cases.

(1) umov is written as VMOV.

(2) br is renamed JMP, blr is renamed CALL.

(3) No need to add "W" suffix: LDARB, LDARH, LDAXRB, LDAXRH, LDTRH, LDXRB, LDXRH.
<commit_msg>cmd/internal/obj/arm64: add a restriction on move constant instructions<commit_after>// Copyright 2018 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 arm64 implements an ARM64 assembler. Go assembly syntax is different from GNU ARM64
syntax, but we can still follow the general rules to map between them.

Instructions mnemonics mapping rules

1. Most instructions use width suffixes of instruction names to indicate operand width rather than
using different register names.

  Examples:
    ADC R24, R14, R12          <=>     adc x12, x24
    ADDW R26->24, R21, R15     <=>     add w15, w21, w26, asr #24
    FCMPS F2, F3               <=>     fcmp s3, s2
    FCMPD F2, F3               <=>     fcmp d3, d2
    FCVTDH F2, F3              <=>     fcvt h3, d2

2. Go uses .P and .W suffixes to indicate post-increment and pre-increment.

  Examples:
    MOVD.P -8(R10), R8         <=>      ldr x8, [x10],#-8
    MOVB.W 16(R16), R10        <=>      ldrsb x10, [x16,#16]!
    MOVBU.W 16(R16), R10       <=>      ldrb x10, [x16,#16]!

3. Go uses a series of MOV instructions as load and store.

64-bit variant ldr, str, stur => MOVD;
32-bit variant str, stur, ldrsw => MOVW;
32-bit variant ldr => MOVWU;
ldrb => MOVBU; ldrh => MOVHU;
ldrsb, sturb, strb => MOVB;
ldrsh, sturh, strh =>  MOVH.

4. Go moves conditions into opcode suffix, like BLT.

5. Go adds a V prefix for most floating-point and SIMD instructions, except cryptographic extension
instructions and floating-point(scalar) instructions.

  Examples:
    VADD V5.H8, V18.H8, V9.H8         <=>      add v9.8h, v18.8h, v5.8h
    VLD1.P (R6)(R11), [V31.D1]        <=>      ld1 {v31.1d}, [x6], x11
    VFMLA V29.S2, V20.S2, V14.S2      <=>      fmla v14.2s, v20.2s, v29.2s
    AESD V22.B16, V19.B16             <=>      aesd v19.16b, v22.16b
    SCVTFWS R3, F16                   <=>      scvtf s17, w6

6. Align directive

Go asm supports the PCALIGN directive, which indicates that the next instruction should be aligned
to a specified boundary by padding with NOOP instruction. The alignment value supported on arm64
must be a power of 2 and in the range of [8, 2048].

  Examples:
    PCALIGN $16
    MOVD $2, R0          // This instruction is aligned with 16 bytes.
    PCALIGN $1024
    MOVD $3, R1          // This instruction is aligned with 1024 bytes.

PCALIGN also changes the function alignment. If a function has one or more PCALIGN directives,
its address will be aligned to the same or coarser boundary, which is the maximum of all the
alignment values.

In the following example, the function Add is aligned with 128 bytes.
  Examples:
    TEXT ·Add(SB),$40-16
    MOVD $2, R0
    PCALIGN $32
    MOVD $4, R1
    PCALIGN $128
    MOVD $8, R2
    RET

On arm64, functions in Go are aligned to 16 bytes by default, we can also use PCALGIN to set the
function alignment. The functions that need to be aligned are preferably using NOFRAME and NOSPLIT
to avoid the impact of the prologues inserted by the assembler, so that the function address will
have the same alignment as the first hand-written instruction.

In the following example, PCALIGN at the entry of the function Add will align its address to 2048 bytes.

  Examples:
    TEXT ·Add(SB),NOSPLIT|NOFRAME,$0
      PCALIGN $2048
      MOVD $1, R0
      MOVD $1, R1
      RET

7. Move large constants to vector registers.

Go asm uses VMOVQ/VMOVD/VMOVS to move 128-bit, 64-bit and 32-bit constants into vector registers, respectively.
And for a 128-bit interger, it take two 64-bit operands, for the high and low parts separately.

  Examples:
    VMOVS $0x11223344, V0
    VMOVD $0x1122334455667788, V1
    VMOVQ $0x1122334455667788, $8877665544332211, V2   // V2=0x11223344556677888877665544332211

8. Move an optionally-shifted 16-bit immediate value to a register.

The instructions are MOVK(W), MOVZ(W) and MOVN(W), the assembly syntax is "op $(uimm16<<shift), <Rd>". The <uimm16>
is the 16-bit unsigned immediate, in the range 0 to 65535; For the 32-bit variant, the <shift> is 0 or 16, for the
64-bit variant, the <shift> is 0, 16, 32 or 48.

The current Go assembler does not accept zero shifts, such as "op $0, Rd" and "op $(0<<(16|32|48)), Rd" instructions.

  Examples:
    MOVK $(10<<32), R20     <=>      movk x20, #10, lsl #32
    MOVZW $(20<<16), R8     <=>      movz w8, #20, lsl #16
    MOVK $(0<<16), R10 will be reported as an error by the assembler.

Special Cases.

(1) umov is written as VMOV.

(2) br is renamed JMP, blr is renamed CALL.

(3) No need to add "W" suffix: LDARB, LDARH, LDAXRB, LDAXRH, LDTRH, LDXRB, LDXRH.

{'fraction_non_alphanumeric': 0.08373927163071213, 'fraction_numerical': 0.08443516585479008, 'mean_word_length': 2.777047744196233, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5540937', 'n_tokens_mistral': 3375, 'n_tokens_neox': 2958, 'n_words': 1230}