162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_M68K_SETUP_H 362306a36Sopenharmony_ci#define _ASM_M68K_SETUP_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <asm/setup.h> 662306a36Sopenharmony_ci#include <linux/linkage.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* Status Register bits */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* accrued exception bits */ 1162306a36Sopenharmony_ci#define FPSR_AEXC_INEX 3 1262306a36Sopenharmony_ci#define FPSR_AEXC_DZ 4 1362306a36Sopenharmony_ci#define FPSR_AEXC_UNFL 5 1462306a36Sopenharmony_ci#define FPSR_AEXC_OVFL 6 1562306a36Sopenharmony_ci#define FPSR_AEXC_IOP 7 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* exception status bits */ 1862306a36Sopenharmony_ci#define FPSR_EXC_INEX1 8 1962306a36Sopenharmony_ci#define FPSR_EXC_INEX2 9 2062306a36Sopenharmony_ci#define FPSR_EXC_DZ 10 2162306a36Sopenharmony_ci#define FPSR_EXC_UNFL 11 2262306a36Sopenharmony_ci#define FPSR_EXC_OVFL 12 2362306a36Sopenharmony_ci#define FPSR_EXC_OPERR 13 2462306a36Sopenharmony_ci#define FPSR_EXC_SNAN 14 2562306a36Sopenharmony_ci#define FPSR_EXC_BSUN 15 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* quotient byte, assumes big-endian, of course */ 2862306a36Sopenharmony_ci#define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1)) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* condition code bits */ 3162306a36Sopenharmony_ci#define FPSR_CC_NAN 24 3262306a36Sopenharmony_ci#define FPSR_CC_INF 25 3362306a36Sopenharmony_ci#define FPSR_CC_Z 26 3462306a36Sopenharmony_ci#define FPSR_CC_NEG 27 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* Control register bits */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* rounding mode */ 4062306a36Sopenharmony_ci#define FPCR_ROUND_RN 0 /* round to nearest/even */ 4162306a36Sopenharmony_ci#define FPCR_ROUND_RZ 1 /* round to zero */ 4262306a36Sopenharmony_ci#define FPCR_ROUND_RM 2 /* minus infinity */ 4362306a36Sopenharmony_ci#define FPCR_ROUND_RP 3 /* plus infinity */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* rounding precision */ 4662306a36Sopenharmony_ci#define FPCR_PRECISION_X 0 /* long double */ 4762306a36Sopenharmony_ci#define FPCR_PRECISION_S 1 /* double */ 4862306a36Sopenharmony_ci#define FPCR_PRECISION_D 2 /* float */ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Flags to select the debugging output */ 5262306a36Sopenharmony_ci#define PDECODE 0 5362306a36Sopenharmony_ci#define PEXECUTE 1 5462306a36Sopenharmony_ci#define PCONV 2 5562306a36Sopenharmony_ci#define PNORM 3 5662306a36Sopenharmony_ci#define PREGISTER 4 5762306a36Sopenharmony_ci#define PINSTR 5 5862306a36Sopenharmony_ci#define PUNIMPL 6 5962306a36Sopenharmony_ci#define PMOVEM 7 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define PMDECODE (1<<PDECODE) 6262306a36Sopenharmony_ci#define PMEXECUTE (1<<PEXECUTE) 6362306a36Sopenharmony_ci#define PMCONV (1<<PCONV) 6462306a36Sopenharmony_ci#define PMNORM (1<<PNORM) 6562306a36Sopenharmony_ci#define PMREGISTER (1<<PREGISTER) 6662306a36Sopenharmony_ci#define PMINSTR (1<<PINSTR) 6762306a36Sopenharmony_ci#define PMUNIMPL (1<<PUNIMPL) 6862306a36Sopenharmony_ci#define PMMOVEM (1<<PMOVEM) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#include <linux/kernel.h> 7362306a36Sopenharmony_ci#include <linux/sched.h> 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciunion fp_mant64 { 7662306a36Sopenharmony_ci unsigned long long m64; 7762306a36Sopenharmony_ci unsigned long m32[2]; 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciunion fp_mant128 { 8162306a36Sopenharmony_ci unsigned long long m64[2]; 8262306a36Sopenharmony_ci unsigned long m32[4]; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* internal representation of extended fp numbers */ 8662306a36Sopenharmony_cistruct fp_ext { 8762306a36Sopenharmony_ci unsigned char lowmant; 8862306a36Sopenharmony_ci unsigned char sign; 8962306a36Sopenharmony_ci unsigned short exp; 9062306a36Sopenharmony_ci union fp_mant64 mant; 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* C representation of FPU registers */ 9462306a36Sopenharmony_ci/* NOTE: if you change this, you have to change the assembler offsets 9562306a36Sopenharmony_ci below and the size in <asm/fpu.h>, too */ 9662306a36Sopenharmony_cistruct fp_data { 9762306a36Sopenharmony_ci struct fp_ext fpreg[8]; 9862306a36Sopenharmony_ci unsigned int fpcr; 9962306a36Sopenharmony_ci unsigned int fpsr; 10062306a36Sopenharmony_ci unsigned int fpiar; 10162306a36Sopenharmony_ci unsigned short prec; 10262306a36Sopenharmony_ci unsigned short rnd; 10362306a36Sopenharmony_ci struct fp_ext temp[2]; 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#ifdef FPU_EMU_DEBUG 10762306a36Sopenharmony_ciextern unsigned int fp_debugprint; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define dprint(bit, fmt, ...) ({ \ 11062306a36Sopenharmony_ci if (fp_debugprint & (1 << (bit))) \ 11162306a36Sopenharmony_ci pr_info(fmt, ##__VA_ARGS__); \ 11262306a36Sopenharmony_ci}) 11362306a36Sopenharmony_ci#else 11462306a36Sopenharmony_ci#define dprint(bit, fmt, ...) no_printk(fmt, ##__VA_ARGS__) 11562306a36Sopenharmony_ci#endif 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define uprint(str) ({ \ 11862306a36Sopenharmony_ci static int __count = 3; \ 11962306a36Sopenharmony_ci \ 12062306a36Sopenharmony_ci if (__count > 0) { \ 12162306a36Sopenharmony_ci pr_err("You just hit an unimplemented " \ 12262306a36Sopenharmony_ci "fpu instruction (%s)\n", str); \ 12362306a36Sopenharmony_ci pr_err("Please report this to ....\n"); \ 12462306a36Sopenharmony_ci __count--; \ 12562306a36Sopenharmony_ci } \ 12662306a36Sopenharmony_ci}) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define FPDATA ((struct fp_data *)current->thread.fp) 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#else /* __ASSEMBLY__ */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#define FPDATA %a2 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* offsets from the base register to the floating point data in the task struct */ 13562306a36Sopenharmony_ci#define FPD_FPREG (TASK_THREAD+THREAD_FPREG+0) 13662306a36Sopenharmony_ci#define FPD_FPCR (TASK_THREAD+THREAD_FPREG+96) 13762306a36Sopenharmony_ci#define FPD_FPSR (TASK_THREAD+THREAD_FPREG+100) 13862306a36Sopenharmony_ci#define FPD_FPIAR (TASK_THREAD+THREAD_FPREG+104) 13962306a36Sopenharmony_ci#define FPD_PREC (TASK_THREAD+THREAD_FPREG+108) 14062306a36Sopenharmony_ci#define FPD_RND (TASK_THREAD+THREAD_FPREG+110) 14162306a36Sopenharmony_ci#define FPD_TEMPFP1 (TASK_THREAD+THREAD_FPREG+112) 14262306a36Sopenharmony_ci#define FPD_TEMPFP2 (TASK_THREAD+THREAD_FPREG+124) 14362306a36Sopenharmony_ci#define FPD_SIZEOF (TASK_THREAD+THREAD_FPREG+136) 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* offsets on the stack to access saved registers, 14662306a36Sopenharmony_ci * these are only used during instruction decoding 14762306a36Sopenharmony_ci * where we always know how deep we're on the stack. 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_ci#define FPS_DO (PT_OFF_D0) 15062306a36Sopenharmony_ci#define FPS_D1 (PT_OFF_D1) 15162306a36Sopenharmony_ci#define FPS_D2 (PT_OFF_D2) 15262306a36Sopenharmony_ci#define FPS_A0 (PT_OFF_A0) 15362306a36Sopenharmony_ci#define FPS_A1 (PT_OFF_A1) 15462306a36Sopenharmony_ci#define FPS_A2 (PT_OFF_A2) 15562306a36Sopenharmony_ci#define FPS_SR (PT_OFF_SR) 15662306a36Sopenharmony_ci#define FPS_PC (PT_OFF_PC) 15762306a36Sopenharmony_ci#define FPS_EA (PT_OFF_PC+6) 15862306a36Sopenharmony_ci#define FPS_PC2 (PT_OFF_PC+10) 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci.macro fp_get_fp_reg 16162306a36Sopenharmony_ci lea (FPD_FPREG,FPDATA,%d0.w*4),%a0 16262306a36Sopenharmony_ci lea (%a0,%d0.w*8),%a0 16362306a36Sopenharmony_ci.endm 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* Macros used to get/put the current program counter. 16662306a36Sopenharmony_ci * 020/030 use a different stack frame then 040/060, for the 16762306a36Sopenharmony_ci * 040/060 the return pc points already to the next location, 16862306a36Sopenharmony_ci * so this only needs to be modified for jump instructions. 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci.macro fp_get_pc dest 17162306a36Sopenharmony_ci move.l (FPS_PC+4,%sp),\dest 17262306a36Sopenharmony_ci.endm 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci.macro fp_put_pc src,jump=0 17562306a36Sopenharmony_ci move.l \src,(FPS_PC+4,%sp) 17662306a36Sopenharmony_ci.endm 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci.macro fp_get_instr_data f,s,dest,label 17962306a36Sopenharmony_ci getuser \f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4) 18062306a36Sopenharmony_ci addq.l #\s,%sp@(FPS_PC+4) 18162306a36Sopenharmony_ci.endm 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci.macro fp_get_instr_word dest,label,addr 18462306a36Sopenharmony_ci fp_get_instr_data w,2,\dest,\label,\addr 18562306a36Sopenharmony_ci.endm 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci.macro fp_get_instr_long dest,label,addr 18862306a36Sopenharmony_ci fp_get_instr_data l,4,\dest,\label,\addr 18962306a36Sopenharmony_ci.endm 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci/* These macros are used to read from/write to user space 19262306a36Sopenharmony_ci * on error we jump to the fixup section, load the fault 19362306a36Sopenharmony_ci * address into %a0 and jump to the exit. 19462306a36Sopenharmony_ci * (derived from <asm/uaccess.h>) 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci.macro getuser size,src,dest,label,addr 19762306a36Sopenharmony_ci| printf ,"[\size<%08x]",1,\addr 19862306a36Sopenharmony_ci.Lu1\@: moves\size \src,\dest 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci .section .fixup,"ax" 20162306a36Sopenharmony_ci .even 20262306a36Sopenharmony_ci.Lu2\@: move.l \addr,%a0 20362306a36Sopenharmony_ci jra \label 20462306a36Sopenharmony_ci .previous 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci .section __ex_table,"a" 20762306a36Sopenharmony_ci .align 4 20862306a36Sopenharmony_ci .long .Lu1\@,.Lu2\@ 20962306a36Sopenharmony_ci .previous 21062306a36Sopenharmony_ci.endm 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci.macro putuser size,src,dest,label,addr 21362306a36Sopenharmony_ci| printf ,"[\size>%08x]",1,\addr 21462306a36Sopenharmony_ci.Lu1\@: moves\size \src,\dest 21562306a36Sopenharmony_ci.Lu2\@: 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci .section .fixup,"ax" 21862306a36Sopenharmony_ci .even 21962306a36Sopenharmony_ci.Lu3\@: move.l \addr,%a0 22062306a36Sopenharmony_ci jra \label 22162306a36Sopenharmony_ci .previous 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci .section __ex_table,"a" 22462306a36Sopenharmony_ci .align 4 22562306a36Sopenharmony_ci .long .Lu1\@,.Lu3\@ 22662306a36Sopenharmony_ci .long .Lu2\@,.Lu3\@ 22762306a36Sopenharmony_ci .previous 22862306a36Sopenharmony_ci.endm 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* work around binutils idiocy */ 23162306a36Sopenharmony_ciold_gas=-1 23262306a36Sopenharmony_ci.irp gas_ident.x .x 23362306a36Sopenharmony_ciold_gas=old_gas+1 23462306a36Sopenharmony_ci.endr 23562306a36Sopenharmony_ci.if !old_gas 23662306a36Sopenharmony_ci.irp m b,w,l 23762306a36Sopenharmony_ci.macro getuser.\m src,dest,label,addr 23862306a36Sopenharmony_ci getuser .\m,\src,\dest,\label,\addr 23962306a36Sopenharmony_ci.endm 24062306a36Sopenharmony_ci.macro putuser.\m src,dest,label,addr 24162306a36Sopenharmony_ci putuser .\m,\src,\dest,\label,\addr 24262306a36Sopenharmony_ci.endm 24362306a36Sopenharmony_ci.endr 24462306a36Sopenharmony_ci.endif 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci.macro movestack nr,arg1,arg2,arg3,arg4,arg5 24762306a36Sopenharmony_ci .if \nr 24862306a36Sopenharmony_ci movestack (\nr-1),\arg2,\arg3,\arg4,\arg5 24962306a36Sopenharmony_ci move.l \arg1,-(%sp) 25062306a36Sopenharmony_ci .endif 25162306a36Sopenharmony_ci.endm 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci.macro printf bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5 25462306a36Sopenharmony_ci#ifdef FPU_EMU_DEBUG 25562306a36Sopenharmony_ci .data 25662306a36Sopenharmony_ci.Lpdata\@: 25762306a36Sopenharmony_ci .string "\string" 25862306a36Sopenharmony_ci .previous 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci movem.l %d0/%d1/%a0/%a1,-(%sp) 26162306a36Sopenharmony_ci .if \bit+1 26262306a36Sopenharmony_ci#if 0 26362306a36Sopenharmony_ci moveq #\bit,%d0 26462306a36Sopenharmony_ci andw #7,%d0 26562306a36Sopenharmony_ci btst %d0,fp_debugprint+((31-\bit)/8) 26662306a36Sopenharmony_ci#else 26762306a36Sopenharmony_ci btst #\bit,fp_debugprint+((31-\bit)/8) 26862306a36Sopenharmony_ci#endif 26962306a36Sopenharmony_ci jeq .Lpskip\@ 27062306a36Sopenharmony_ci .endif 27162306a36Sopenharmony_ci movestack \nr,\arg1,\arg2,\arg3,\arg4,\arg5 27262306a36Sopenharmony_ci pea .Lpdata\@ 27362306a36Sopenharmony_ci jsr printk 27462306a36Sopenharmony_ci lea ((\nr+1)*4,%sp),%sp 27562306a36Sopenharmony_ci.Lpskip\@: 27662306a36Sopenharmony_ci movem.l (%sp)+,%d0/%d1/%a0/%a1 27762306a36Sopenharmony_ci#endif 27862306a36Sopenharmony_ci.endm 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci.macro printx bit,fp 28162306a36Sopenharmony_ci#ifdef FPU_EMU_DEBUG 28262306a36Sopenharmony_ci movem.l %d0/%a0,-(%sp) 28362306a36Sopenharmony_ci lea \fp,%a0 28462306a36Sopenharmony_ci#if 0 28562306a36Sopenharmony_ci moveq #'+',%d0 28662306a36Sopenharmony_ci tst.w (%a0) 28762306a36Sopenharmony_ci jeq .Lx1\@ 28862306a36Sopenharmony_ci moveq #'-',%d0 28962306a36Sopenharmony_ci.Lx1\@: printf \bit," %c",1,%d0 29062306a36Sopenharmony_ci move.l (4,%a0),%d0 29162306a36Sopenharmony_ci bclr #31,%d0 29262306a36Sopenharmony_ci jne .Lx2\@ 29362306a36Sopenharmony_ci printf \bit,"0." 29462306a36Sopenharmony_ci jra .Lx3\@ 29562306a36Sopenharmony_ci.Lx2\@: printf \bit,"1." 29662306a36Sopenharmony_ci.Lx3\@: printf \bit,"%08x%08x",2,%d0,%a0@(8) 29762306a36Sopenharmony_ci move.w (2,%a0),%d0 29862306a36Sopenharmony_ci ext.l %d0 29962306a36Sopenharmony_ci printf \bit,"E%04x",1,%d0 30062306a36Sopenharmony_ci#else 30162306a36Sopenharmony_ci printf \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8) 30262306a36Sopenharmony_ci#endif 30362306a36Sopenharmony_ci movem.l (%sp)+,%d0/%a0 30462306a36Sopenharmony_ci#endif 30562306a36Sopenharmony_ci.endm 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci.macro debug instr,args 30862306a36Sopenharmony_ci#ifdef FPU_EMU_DEBUG 30962306a36Sopenharmony_ci \instr \args 31062306a36Sopenharmony_ci#endif 31162306a36Sopenharmony_ci.endm 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci#endif /* _ASM_M68K_SETUP_H */ 317