blob: 4f2b5b5797592a1b4721c8a11db2e9f621d75e8c [file] [log] [blame]
/*
* Startup glue code for parisc firmware
*
* (C) 2017-2024 Helge Deller <deller@gmx.de>
*/
#include "parisc/hppa.h"
#include "parisc/hppa_hardware.h"
#include "parisc/pdc.h"
#include "autoconf.h"
#include "autoversion.h"
/* load 32-bit 'value' into 'reg' with
sign-extension when running in wide mode. */
.macro load32_sign_extend value, reg
ldil L%\value, \reg
ldo R%\value(\reg), \reg
.endm
/* load 32-bit 'value' into 'reg' compensating for the ldil
* sign-extension when running in wide mode. */
.macro load32 value, reg
ldil L%\value, \reg
ldo R%\value(\reg), \reg
#ifdef CONFIG_64BIT
depdi 0, 31, 32, \reg
#endif
.endm
/* set upper 32-bits of firmware address */
.macro load_fw_upper32 reg
#ifdef CONFIG_64BIT
depdi FIRMWARE_HIGH, 31, 32, \reg
#endif
.endm
.macro load32_firmware value, reg
ldil L%\value, \reg
ldo R%\value(\reg), \reg
#ifdef CONFIG_64BIT
depdi FIRMWARE_HIGH, 31, 32, \reg
#endif
.endm
;! set the W bit
#define set_PSW_W .level 2.0 ! ssm PSW_W_SM, %r0 ! .level LEVEL
;! nuke the W bit
#define clear_PSW_W .level 2.0 ! rsm PSW_W_SM, %r0 ! .level LEVEL
#define ENTRY(name) \
.export name !\
.align 4 !\
name:
#define END(name) \
.size name, .-name
#define ENDPROC(name) \
.type name, @function !\
END(name)
#define BOOTADDR(x) (x)
.macro loadgp
#ifdef CONFIG_64BIT
ldil L%__gp, %r27
ldo R%__gp(%r27), %r27
load_fw_upper32 %r27
#else
ldil L%$global$, %r27
ldo R%$global$(%r27), %r27
#endif
.endm
#ifdef CONFIG_64BIT
#define LEVEL 2.0w
#define LDREG ldd
#define STREG std
#define LDREGX ldd,s
#define LDREGM ldd,mb
#define STREGM std,ma
#define SHRREG shrd
#define SHLREG shld
#define ANDCM andcm,*
#define COND(x) * ## x
#define FRAME_SIZE 128
#define FRAME_SIZE32 64
#define CALLEE_REG_FRAME_SIZE 144
#define ASM_ULONG_INSN .dword
#define WORD_LEN 8
#define INT_LEN 4
#else /* CONFIG_64BIT */
#define LEVEL 1.1
#define LDREG ldw
#define STREG stw
#define LDREGX ldwx,s
#define LDREGM ldwm
#define STREGM stwm
#define SHRREG shr
#define SHLREG shlw
#define ANDCM andcm
#define COND(x) x
#define FRAME_SIZE 64
#define CALLEE_REG_FRAME_SIZE 128
#define ASM_ULONG_INSN .word
#define WORD_LEN 4
#define INT_LEN 4
#endif
/* various control register and irq bits */
#define PSW_I 1
#define PSW_Q 8
#define CR_EIRR 23
#define CR_IVA 14
#define CR_EIEM 15
#define PSW_W_SM 0x200
#define PSW_W_BIT 36
.import $global$
.section ".head.text","ax"
.level LEVEL
/* On HPMC, the CPUs will start here at 0xf0000000 */
hpmc_entry:
b,n toc_asm_entry /* TOC and HPMC */
reset_entry:
/* at reset, the CPU begins fetching instructions from address 0xf0000004. */
b,n startup
marker:
/* file identification, useful for strings command on binary file to see version. */
.stringz "PA-RISC/HPPA PDC Firmware " SEABIOS_HPPA_VERSION_STR " (SeaBIOS fork)"
.stringz "https://github.com/hdeller/seabios-hppa"
.stringz BUILD_VERSION
/*******************************************************
Firmware startup code
*******************************************************/
.align 0x80
ENTRY(startup)
rsm PSW_I, %r0 /* disable local irqs */
ssm PSW_Q, %r0 /* enable PSW_Q flag */
#ifdef CONFIG_64BIT
/* check if we really run on 64-bit CPU */
ldo -1(%r0), %r1
mtctl %r1,%cr11
mfctl,w %cr11, %r1
ldo -31(%r1),%r1
cmpib,<>,n 0,%r1,1f
.word 0xfffdead0 /* immediately halt the emulator */
1:
/* we now know we run on a 64-bit CPU. */
/* next step: turn on the PSW.W flag (enable 64-bit mode) */
load32 2f,%r11
load_fw_upper32 %r11
mtctl %r0,%cr17 /* Clear IIASQ tail */
mtctl %r0,%cr17 /* Clear IIASQ head */
/* Load RFI target into PC queue */
mtctl %r11,%cr18 /* IIAOQ head */
ldo 4(%r11),%r11
mtctl %r11,%cr18 /* IIAOQ tail */
load32 (0x08000000 | PSW_Q),%r10 /* PSW.W=1 */
mtctl %r10,%ipsw
/* Jump through hyperspace to enable PSW.W */
rfi
nop
2:
#else
/* clear any PSW.W on 32-bit firmware */
clear_PSW_W
#endif
/* Make sure space registers are set to zero */
mtsp %r0,%sr0
mtsp %r0,%sr1
mtsp %r0,%sr2
mtsp %r0,%sr3
mtsp %r0,%sr4
mtsp %r0,%sr5
mtsp %r0,%sr6
mtsp %r0,%sr7
/* If CPU HPA is already set in CPU_HPA_CR_REG then the
* CPU is already initialized and the machine was only reset */
mfctl CPU_HPA_CR_REG, %r1
comib,= 0,%r1,$startup_fresh_booted
nop
$startup_just_rebooted:
/* Get current CPU HPA. It was stored there at initial bootup. */
mfctl CPU_HPA_CR_REG, %r5
/* branch if this is the monarch cpu */
load32_sign_extend CPU_HPA, %r1
comb,=,n %r5,%r1,$is_monarch_cpu_reboot
b,n enter_smp_idle_loop
$startup_fresh_booted:
/* Here the machine was booted from scratch: */
/* Save CPU HPA in cr7, hopefully HP-UX will not use that register. */
#ifdef CONFIG_64BIT
extrw,s,>= %r5,31,32,%r5 /* sign extend CPU HPA */
#endif
mtctl %r5, CPU_HPA_CR_REG /* store CPU HPA */
/* branch if this is the monarch cpu */
load32_sign_extend CPU_HPA,%r1
comb,= %r5,%r1,$is_monarch_cpu
nop
ENTRY(enter_smp_idle_loop)
/* IDLE LOOP for SMP CPUs - wait for rendenzvous. */
mfctl CPU_HPA_CR_REG, %r25 /* get CPU HPA from cr7 */
rsm PSW_I, %r0 /* disable local irqs */
mtctl %r0, CR_EIEM /* disable all external irqs */
/* EIRR : clear all pending external intr */
load32 -1,%r1
mtctl %r1, CR_EIRR
mfctl CR_EIRR, %r0
mtctl %r0, CR_EIRR
/* Load IVT for SMT tiny loop exit */
load32_firmware BOOTADDR(smp_ivt),%r1
mtctl %r1, CR_IVA
/* enable CPU local interrupts */
load32 1<<31, %r1 /* allow IRQ0 (Timer) */
mtctl %r1, CR_EIEM
ssm PSW_I, %r0 /* enable local irqs */
/* endless idle loop for secondary CPUs. Exits to $smp_exit_loop by IRQ only */
$smp_idle_loop:
b $smp_idle_loop
or %r10,%r10,%r10 /* qemu sleep instruction */
$smp_exit_loop:
rsm PSW_I, %r0 /* disable local irqs */
mtctl %r0, CR_EIEM
/* Load IVT to detect and report crashes */
load32_firmware BOOTADDR(firmware_default_ivt),%r1
mtctl %r1, CR_IVA
/* provide PDCE_PROC entry in arg0 (required on 64-bit) */
load32 MEM_PDC_ENTRY, %arg0
/* jump to rendevouz */
ldw 0x10(%r0),%r3 /* MEM_RENDEZ */
#ifdef CONFIG_64BIT
addb,*>,n %r0,%r0,1f /* branch if narrow addressing */
ldw 0x28(%r0),%r1 /* MEM_RENDEZ_HI */
depd %r1, 31, 32, %r3
1:
#endif
cmpb,=,n %r0,%r3,enter_smp_idle_loop
nop /* failed backward branch is nullified */
load32_firmware startup, %rp
bv,n 0(%r3)
$is_monarch_cpu:
/* Save boot_args in PAGE0->pad608[]. Only monarch CPU does this once. */
load32 BOOTADDR(0x608),%r1
STREGM %r26,WORD_LEN(%r1)
STREGM %r25,WORD_LEN(%r1)
STREGM %r24,WORD_LEN(%r1)
STREGM %r23,WORD_LEN(%r1)
STREGM %r22,WORD_LEN(%r1)
STREGM %r21,WORD_LEN(%r1)
STREGM %r20,WORD_LEN(%r1)
STREGM %r19,WORD_LEN(%r1)
$is_monarch_cpu_reboot:
/* Initialize stack pointer */
load32_firmware BOOTADDR(parisc_stack),%r1
ldo FRAME_SIZE(%r1),%sp
/* Initialize the global data pointer */
loadgp
/* Clear BSS on monarch CPU */
.import _bss,data
.import _ebss,data
load32_firmware BOOTADDR(_bss),%r3
load32_firmware BOOTADDR(_ebss),%r4
$bss_loop:
cmpb,<<,n %r3,%r4,$bss_loop
STREGM %r0,WORD_LEN(%r3)
/* Load IVT to detect and report crashes */
load32_firmware BOOTADDR(firmware_default_ivt),%r1
mtctl %r1, CR_IVA
load32_firmware BOOTADDR(start_parisc_firmware),%r3
bv 0(%r3)
copy %r0,%r2
END(startup)
/*******************************************************/
ENTRY(start_kernel)
#ifdef CONFIG_64BIT
bv 0(%r22)
clear_PSW_W /* clear PSW before we start the kernel! */
#else
ldw -0x34(%sp),%r1
bv,n 0(%r1)
#endif
END(start_kernel)
/*******************************************************
TOC handler
Write all GRs, CRs, SRs and the iaoq_back and iasq_back registers (in
r24/r25) into PIM area (when it's not filled yet). This is done by trashing the
shadow registers.
In a second step call the arificial getshadowregs asm instruction to restore
the shadow registers to their real values and store them in PIM as well. Then
call the C-code.
*******************************************************/
/* uses the shadow registers: 1,8,9,16,17,24,25 */
#define PIM_PTR %r1
#define TEMP %r8
#define TEMP2 %r9
#define PIM_SAVE %r16
#define IASQ_BACK %r24 /* provided by qemu */
#define IAOQ_BACK %r25 /* provided by qemu */
.import pim_toc_data, data
ENTRY(toc_asm_entry)
/* serialize CPUs on entry */
load32_firmware BOOTADDR(toc_lock),TEMP
0: ldcw,co 0(TEMP),TEMP2
cmpib,= 0,TEMP2,0b
nop
mfctl CPU_HPA_CR_REG, TEMP2 /* get CPU HPA from cr7 */
extru TEMP2,31-12,4, TEMP /* extract cpu id */
load32_firmware BOOTADDR(pim_toc_data), PIM_PTR
1: comib,= 0,TEMP,2f
ldo -1(TEMP),TEMP
ldo (PIM_STORAGE_SIZE)(PIM_PTR), PIM_PTR /* find PIM entry */
b 1b
2: copy PIM_PTR, PIM_SAVE
mtsp %r0,%sr0
/* save registers into PIM only if cpu_state field is empty */
ldw ((32+32+8+2)*WORD_LEN + 1*INT_LEN)(PIM_SAVE), TEMP
comib,<>,n 0, TEMP, 5f
/* save all general registers */
.set loop,0
.rept 32
copy loop,TEMP
STREGM TEMP, WORD_LEN(PIM_PTR)
.set loop,loop+1
.endr
/* save all control registers */
.set loop,0
.rept 32
mfctl loop,TEMP
STREGM TEMP, WORD_LEN(PIM_PTR)
.set loop,loop+1
.endr
/* save all space registers */
.set loop,0
.rept 8
mfsp loop,TEMP
STREGM TEMP, WORD_LEN(PIM_PTR)
.set loop,loop+1
.endr
/* save IASQ_back and IAOQ_back as provided by qemu */
STREG IASQ_BACK, ((32+32+8+0)*WORD_LEN)(PIM_SAVE)
STREG IAOQ_BACK, ((32+32+8+1)*WORD_LEN)(PIM_SAVE)
/* restore shadow registers, can not use PIM_SAVE reg for this */
copy PIM_SAVE, %r26
.word 0xfffdead2 /* qemu artificial getshadowregs asm instruction */
STREG %r1, (1*WORD_LEN)(%r26)
STREG %r8, (8*WORD_LEN)(%r26)
STREG %r9, (9*WORD_LEN)(%r26)
STREG %r16, (16*WORD_LEN)(%r26)
STREG %r17, (17*WORD_LEN)(%r26)
STREG %r24, (24*WORD_LEN)(%r26)
STREG %r25, (25*WORD_LEN)(%r26)
#ifdef CONFIG_64BIT
/* cr11 (sar) is a funny one. 5 bits on PA1.1 and 6 bit on PA2.0
* For PA2.0 mtsar or mtctl always write 6 bits, but mfctl only
* reads 5 bits. Use mfctl,w to read all six bits. Otherwise
* we lose the 6th bit on a save/restore. */
mfctl,w %cr11, TEMP
STREG TEMP, ((32+11)*WORD_LEN)(%r26)
#endif
5: /* call the "C" toc_handler in SeaBIOS */
loadgp
load32_firmware BOOTADDR(parisc_stack), %sp
b,l toc_handler, %r2
ldo FRAME_SIZE(%sp),%sp
/* call OS handler, in case it returns reset the system */
load32_firmware BOOTADDR(reset), %rp
bv,n 0(%ret0)
END(toc_asm_entry)
/*******************************************************
SMP Interrupt vector table (IVT)
*******************************************************/
.macro DEF_IVA_ENTRY
.align 32
load32_firmware BOOTADDR($smp_exit_loop),%r1
bv 0(%r1)
nop
.endm
.align 32 /* should be 4k aligned but qemu does not check */
ENTRY(smp_ivt)
.rept 32
DEF_IVA_ENTRY
.endr
END(smp_ivt)
/*******************************************************
Fault detection & reporting Interrupt vector table (IVT)
*******************************************************/
/* fault happened at bootup. Return to instruction after fault. */
ENTRY(fault_return_to_caller)
mfctl %cr18,TEMP
ldo 4(TEMP),TEMP
mtctl TEMP,%cr18 /* IIAOQ head */
ldo 4(TEMP),TEMP
mtctl TEMP,%cr18 /* IIAOQ tail */
rfi
nop
END(fault_return_to_caller)
/* call firmware_fault_handler in parisc.c and halt. */
ENTRY(fault_call_firmware)
load32_firmware firmware_fault_handler,TEMP
loadgp
bv,n 0(TEMP)
END(fault_call_firmware)
.align 32
ENTRY(firmware_default_ivt) /* to detect crashes */
.set loop,0
.import firmware_fault_handler,code
.rept 32
/* Make sure to use shadow registers only! */
/* While booting up we check if various devices are available.
Allow such checks and do not raise an HPMC. */
ldi loop,TEMP /* trap# into TEMP */
cmpib,= 1,TEMP,fault_return_to_caller
nop
b fault_call_firmware
ldi loop,%arg0 /* trap# into arg0 */
.set loop,loop+1
.align 32
.endr
END(smp_ivt)
/*******************************************************
PDC and IODC entry
*******************************************************/
/* pdc_entry_table will be copied into low memory. */
ENTRY(pdc_entry_table)
#ifdef CONFIG_64BIT
/* see section "Testing the Current State of the PSW W-Bit",
page I-2 in parisc2 spec */
addb,*>,n %r0,%r0,pdc_called_narrow /* branch if narrow addressing */
pdc_called_wide:
#if 0 /* automatically set wide-bit */
.import psw_defaults, data
load32_firmware psw_defaults,%r1 /* set PDC_PSW_ENDIAN_BIT in psw_defaults */
ldi PDC_PSW_ENDIAN_BIT,%r31
stw %r31,0(%r1)
#endif
/* we know that PDC was called with PSW.W=1 */
load32_firmware pdc_entry_64_64,%r1
bv,n %r0(%r1)
pdc_called_narrow:
/* we know that PDC was called with PSW.W=0 */
load32 MEM_PDC_ENTRY + pdc_entry_64_32 - pdc_entry_table,%r1
bv 0(%r1)
set_PSW_W /* enable PSW.W */
#else
ENTRY(pdc_entry_32) /* 32-bit PDC */
stw %rp,-20(%sp)
stw %dp,-32(%sp)
stw %arg0,-36(%sp)
stw %arg1,-40(%sp)
stw %arg2,-44(%sp)
stw %arg3,-48(%sp)
ldo -FRAME_SIZE(%sp),%arg0
loadgp
load32 MEM_PDC_ENTRY + 1f - pdc_entry_table,%rp
load32 parisc_pdc_entry, %r1
clear_PSW_W
bv 0(%r1)
ldo FRAME_SIZE(%sp),%sp
1:
ldo -FRAME_SIZE(%sp),%sp
ldw -20(%sp),%rp
ldw -32(%sp),%dp
bv,n %r0(%rp)
END(pdc_entry_32)
#endif
END(pdc_entry_table)
#ifdef CONFIG_64BIT
ENTRY(pdc_entry_64_32) /* 32-bit call on 64-bit PDC */
/* clear upper bits */
depdi 0, 31, 32, %sp
depdi 0, 31, 32, %rp
depdi 0, 31, 32, %dp
depdi 0, 31, 32, %arg0
depdi 0, 31, 32, %arg1
depdi 0, 31, 32, %arg2
depdi 0, 31, 32, %arg3
copy %sp,%r1 /* copy original stack pointer */
ldo 2*FRAME_SIZE(%sp),%sp /* build new 64-bit stack */
std %rp,-0x10(%sp)
std %dp,-0x18(%sp)
std %arg0,-0x20(%sp)
std %arg1,-0x28(%sp)
std %arg2,-0x30(%sp)
std %arg3,-0x38(%sp)
ldw -FRAME_SIZE32 + 12(%r1),%arg0 /* ARG4 */
depdi 0, 31, 32, %arg0
std %arg0, -0x40(%sp)
ldw -FRAME_SIZE32 + 8(%r1),%arg0 /* ARG5 */
depdi 0, 31, 32, %arg0
std %arg0, -0x48(%sp)
ldw -FRAME_SIZE32 + 4(%r1),%arg0 /* ARG6 */
depdi 0, 31, 32, %arg0
std %arg0, -0x50(%sp)
ldw -FRAME_SIZE32 + 0(%r1),%arg0 /* ARG7 */
depdi 0, 31, 32, %arg0
std %arg0, -0x58(%sp)
ldo -0x58(%sp),%arg0 /* points to arg7 */
loadgp
load32_firmware parisc_pdc_entry,%r1
load32 MEM_PDC_ENTRY + c64_32_return - pdc_entry_table,%rp
bv 0(%r1)
ldo FRAME_SIZE(%sp),%sp
c64_32_return:
/* return from PDC call */
ldo -FRAME_SIZE(%sp),%sp
ldd -0x10(%sp),%rp
ldd -0x18(%sp),%dp
ldd -0x30(%sp),%arg2 /* addr of result buffer */
ldo -2*FRAME_SIZE(%sp),%sp /* restore original 32-bit stack */
#if 0
.import psw_defaults, data
load32_firmware psw_defaults,%r1 /* test PDC_PSW_ENDIAN_BIT in psw_defaults */
ldw 0(%r1),%r1
ldi PDC_PSW_ENDIAN_BIT,%arg3
and %r1,%arg3,%r1
cmpb,<>,n %r1,%r0,5f /* skip copy results */
#elif 0
.import firmware_width_locked, data
load32_firmware firmware_width_locked,%r1
ldw 0(%r1),%r1
cmpb,=,n %r1,%r0,5f /* skip copy results */
#endif
cmpb,=,n %r0,%arg2,5f /* skip copy results if target buffer is NULL */
cmpb,< %ret0,%r0,5f /* skip copy results if return value was negative (=error) */
ldi MEM_PDC_ENTRY,%r1
cmpb,>=,n %arg2,%r1,convert_ret64_buffer /* copy results if target buffer >= MEM_PDC_ENTRY */
b,n .
.word 0xfffdead0 /* immediately halt the emulator */
convert_ret64_buffer:
/* copy 64-bit-wide PDC result to 32-bit wide results */
ldi 32,%r1
copy %arg2,%arg3
.L1: ldd,ma 8(%arg2),%arg1
stwm %arg1, 4(%arg3)
ldo -1(%r1),%r1
cmpb,>>,n %r1,%r0,.L1
5: /* return to caller */
clear_PSW_W
bv,n %r0(%rp)
ENTRY(pdc_entry_64_64) /* 64-bit call on 64-bit PDC */
std %rp,-0x10(%sp)
stw %dp,-0x18(%sp)
std %arg0,-0x20(%sp)
std %arg1,-0x28(%sp)
std %arg2,-0x30(%sp)
std %arg3,-0x38(%sp)
std %r22, -0x40(%sp)
std %r21, -0x48(%sp)
std %r20, -0x50(%sp)
std %r19, -0x58(%sp)
ldo -0x58(%sp),%arg0 /* points to arg7 */
loadgp
b,l parisc_pdc_entry, %rp
ldo FRAME_SIZE(%sp),%sp
ldo -FRAME_SIZE(%sp),%sp
ldd -0x10(%sp),%rp
ldd -0x18(%sp),%dp
bv,n %r0(%rp)
END(pdc_entry_64_32)
#endif
ENTRY(iodc_entry_table)
load32 parisc_iodc_ENTRY_INIT, %r1
iodc_entry_table_one_entry:
.export iodc_entry_table_one_entry
load32 parisc_iodc_ENTRY_IO, %r1
load32 parisc_iodc_ENTRY_SPA, %r1
load32 parisc_iodc_ENTRY_CONFIG, %r1
load32 hlt, %r1 /* obsolete */
load32 parisc_iodc_ENTRY_TEST, %r1
load32 parisc_iodc_ENTRY_TLB, %r1
END(iodc_entry_table)
/* the code for iodc_entry[] will be copied to user.
the first load32* wil be replaced by an entry from
the iodc_entry_table[] table above. */
ENTRY(iodc_entry)
/* this first call we be replaced at runtime: */
load32 parisc_iodc_ENTRY_IO, %r1
#ifdef CONFIG_64BIT
addb,*>,n %r0,%r0,iodc_narrow /* branch if narrow addressing */
nop
#if 1
// HALT
load32_firmware hlt,%r1
bv,n %r0(%r1)
#endif
b,n iodc_wide
iodc_narrow:
/* we run narrow, but want wide! Jump to firmware to set PSW.W=1 */
stw %r1,-20(%sp) /* temporarily store r1 */
/* Switch to wide mode. */
#if 0
1: mfia %r1
ldo 2f-1b(%r1),%r1
depdi 0,31,32,%r1
#else
load32 MEM_PDC_ENTRY + 2f - pdc_entry_table,%r1
#endif
bv 0(%r1)
set_PSW_W
2: /* now in wide mode, running in low memory */
depdi 0, 31, 32, %sp
ldw -20(%sp),%r1 /* restore r1 */
load_fw_upper32 %r1
stw %rp,-20(%sp)
stw %dp,-32(%sp)
stw %arg0,-36(%sp)
stw %arg1,-40(%sp)
stw %arg2,-44(%sp)
stw %arg3,-48(%sp)
ldo -FRAME_SIZE32(%sp),%arg0
loadgp
load32 MEM_PDC_ENTRY + .iodc_ret32 - pdc_entry_table,%rp
bv %r0(%r1)
ldo 2*FRAME_SIZE(%sp),%sp
.iodc_ret32:
ldo -2*FRAME_SIZE(%sp),%sp
ldw -20(%sp),%rp
ldw -32(%sp),%dp
bv %r0(%rp)
clear_PSW_W
/* END for 32-bit IODC call */
iodc_narrow_jump_to_firmware:
/* clear upper bits */
depdi 0, 31, 32, %rp
depdi 0, 31, 32, %dp
depdi 0, 31, 32, %arg0
depdi 0, 31, 32, %arg1
depdi 0, 31, 32, %arg2
depdi 0, 31, 32, %arg3
depdi 0, 31, 32, %r22
depdi 0, 31, 32, %r21
depdi 0, 31, 32, %r20
depdi 0, 31, 32, %r19
iodc_wide:
std %rp,-0x10(%sp)
std %dp,-0x18(%sp)
std %arg0,-0x20(%sp)
std %arg1,-0x28(%sp)
std %arg2,-0x30(%sp)
std %arg3,-0x38(%sp)
std %r22, -0x40(%sp)
std %r21, -0x48(%sp)
std %r20, -0x50(%sp)
std %r19, -0x58(%sp)
ldo -0x58(%sp),%arg0 /* points to arg7 */
#else
stw %rp,-20(%sp)
stw %dp,-32(%sp)
stw %arg0,-36(%sp)
stw %arg1,-40(%sp)
stw %arg2,-44(%sp)
stw %arg3,-48(%sp)
ldo -FRAME_SIZE(%sp),%arg0
#endif
loadgp
load32 .iodc_ret, %rp
bv %r0(%r1)
ldo FRAME_SIZE(%sp),%sp
.iodc_ret:
ldo -FRAME_SIZE(%sp),%sp
#ifdef CONFIG_64BIT
ldd -0x10(%sp),%rp
ldd -0x18(%sp),%dp
#else
ldw -20(%sp),%rp
ldw -32(%sp),%dp
#endif
bv %r0(%rp)
clear_PSW_W
END(iodc_entry)
/* PDC is copied up until here: */
pdc_entry_table_end:
.export pdc_entry_table_end
/****************************************************************
* Rom Header for VGA / STI
****************************************************************/
#if 0 // def CONFIG_BUILD_VGABIOS
.section .rom.header
.global _rom_header, _rom_header_size, _rom_header_checksum
_rom_header:
.word 0xaa55
_rom_header_size:
.byte 0
_rom_header_entry:
.word _optionrom_entry // b,n ?
_rom_header_checksum:
.byte 0
_rom_header_other:
.space 17
_rom_header_pcidata:
#if CONFIG_VGA_PCI == 1
.word rom_pci_data
#else
.word 0
#endif
_rom_header_pnpdata:
.word 0
_rom_header_other2:
.word 0
_rom_header_signature:
.asciz "IBM"
ENTRY(_optionrom_entry)
.import vga_post
load32 BOOTADDR(vga_post), %r1
bv,n %r0(%r1)
END(_optionrom_entry)
#endif /* CONFIG_BUILD_VGABIOS */