root/sys/i386/include/asmacros.h
/* -*- mode: asm -*- */
/*-
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _MACHINE_ASMACROS_H_
#define _MACHINE_ASMACROS_H_

#include <sys/cdefs.h>

/* XXX too much duplication in various asm*.h's. */

/*
 * CNAME is used to manage the relationship between symbol names in C
 * and the equivalent assembly language names.  CNAME is given a name as
 * it would be used in a C program.  It expands to the equivalent assembly
 * language name.
 */
#define CNAME(csym)             csym

#define ALIGN_DATA      .p2align 2      /* 4 byte alignment, zero filled */
#define ALIGN_TEXT      .p2align 2,0x90 /* 4-byte alignment, nop filled */
#define SUPERALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */

#define GEN_ENTRY(name)         ALIGN_TEXT; .globl CNAME(name); \
                                .type CNAME(name),@function; CNAME(name):
#define ENTRY(name)             GEN_ENTRY(name)
#define ALTENTRY(name)          GEN_ENTRY(name)
#define END(name)               .size name, . - name

#ifdef LOCORE

#define GSEL_KPL        0x0020  /* GSEL(GCODE_SEL, SEL_KPL) */
#define SEL_RPL_MASK    0x0003

/*
 * Convenience macro for declaring interrupt entry points.
 */
#define IDTVEC(name)    ALIGN_TEXT; .globl __CONCAT(X,name); \
                        .type __CONCAT(X,name),@function; __CONCAT(X,name):

/*
 * Macros to create and destroy a trap frame.
 */
        .macro  PUSH_FRAME2
        pushal
        pushl   $0
        movw    %ds,(%esp)
        pushl   $0
        movw    %es,(%esp)
        pushl   $0
        movw    %fs,(%esp)
        movl    %esp,%ebp
        .endm

        .macro  PUSH_FRAME
        pushl   $0              /* dummy error code */
        pushl   $0              /* dummy trap type */
        PUSH_FRAME2
        .endm

/*
 * Access per-CPU data.
 */
#define PCPU(member)    %fs:PC_ ## member

#define PCPU_ADDR(member, reg)                                          \
        movl %fs:PC_PRVSPACE, reg ;                                     \
        addl $PC_ ## member, reg

/*
 * Setup the kernel segment registers.
 */
        .macro  SET_KERNEL_SREGS
        movl    $KDSEL, %eax    /* reload with kernel's data segment */
        movl    %eax, %ds
        movl    %eax, %es
        movl    $KPSEL, %eax    /* reload with per-CPU data segment */
        movl    %eax, %fs
        .endm

        .macro  NMOVE_STACKS
        movl    PCPU(KESP0), %edx
        movl    $TF_SZ, %ecx
        testl   $PSL_VM, TF_EFLAGS(%esp)
        jz      .L\@.1
        addl    $VM86_STACK_SPACE, %ecx
.L\@.1: subl    %ecx, %edx
        movl    %edx, %edi
        movl    %esp, %esi
        rep; movsb
        movl    %edx, %esp
        .endm

        .macro  LOAD_KCR3
        call    .L\@.1
.L\@.1: popl    %eax
        movl    (tramp_idleptd - .L\@.1)(%eax), %eax
        movl    %eax, %cr3
        .endm

        .macro  MOVE_STACKS
        LOAD_KCR3
        NMOVE_STACKS
        .endm

        .macro  KENTER
        testl   $PSL_VM, TF_EFLAGS(%esp)
        jz      .L\@.1
        LOAD_KCR3
        movl    PCPU(CURPCB), %eax
        testl   $PCB_VM86CALL, PCB_FLAGS(%eax)
        jnz     .L\@.3
        NMOVE_STACKS
        movl    $handle_ibrs_entry,%edx
        call    *%edx
        jmp     .L\@.3
.L\@.1: testb   $SEL_RPL_MASK, TF_CS(%esp)
        jz      .L\@.3
.L\@.2: MOVE_STACKS
        movl    $handle_ibrs_entry,%edx
        call    *%edx
.L\@.3:
        .endm

#endif /* LOCORE */

#ifdef __STDC__
#define ELFNOTE(name, type, desctype, descdata...) \
.pushsection .note.name, "a", @note     ;       \
  .align 4                              ;       \
  .long 2f - 1f         /* namesz */    ;       \
  .long 4f - 3f         /* descsz */    ;       \
  .long type                            ;       \
1:.asciz #name                          ;       \
2:.align 4                              ;       \
3:desctype descdata                     ;       \
4:.align 4                              ;       \
.popsection
#else /* !__STDC__, i.e. -traditional */
#define ELFNOTE(name, type, desctype, descdata) \
.pushsection .note.name, "a", @note     ;       \
  .align 4                              ;       \
  .long 2f - 1f         /* namesz */    ;       \
  .long 4f - 3f         /* descsz */    ;       \
  .long type                            ;       \
1:.asciz "name"                         ;       \
2:.align 4                              ;       \
3:desctype descdata                     ;       \
4:.align 4                              ;       \
.popsection
#endif /* __STDC__ */

#endif /* !_MACHINE_ASMACROS_H_ */