URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libcpu/] [i386/] [cpuModel.S] - Rev 502
Go to most recent revision | Compare with Previous | Blame | View Log
/* cpuModel.S** This file contains all assembly code for the Intel Cpu identification.* It is based on linux cpu detection code.** Intel also provides public similar code in the book* called :** Pentium Processor Family* Developer Family* Volume 3 : Architecture and Programming Manual** At the following place :** Chapter 5 : Feature determination* Chapter 25: CPUID instruction** COPYRIGHT (c) 1998 valette@crf.canon.fr** The license and distribution terms for this file may be* found in the file LICENSE in this distribution or at* http://www.OARcorp.com/rtems/license.html.** $Id: cpuModel.S,v 1.2 2001-09-27 12:01:22 chris Exp $*/#include <asm.h>#include <libcpu/registers.h>BEGIN_CODEPUBLIC(checkCPUtypeSetCr0);/** check Processor type: 386, 486, 6x86(L) or CPUID capable processor*/SYM (checkCPUtypeSetCr0):/** Assume 386 for now*/movl $3, SYM (x86)/** Start using the EFLAGS AC bit determination method described in* the book mentioned above page 5.1. If this bit can be set we* have a 486 or above.*/pushfl /* save EFLAGS */pushfl /* Get EFLAGS in EAX */popl eaxmovl eax,ecx /* save original EFLAGS in ECX */xorl $EFLAGS_ALIGN_CHECK,eax /* flip AC bit in EAX */pushl eax /* set EAX as EFLAGS */popflpushfl /* Get new EFLAGS in EAX */popl eaxxorl ecx,eax /* check if AC bit changed */andl $EFLAGS_ALIGN_CHECK,eaxje is386 /* If not : we have a 386 *//** Assume 486 for now*/movl $4,SYM (x86)movl ecx,eax /* Restore orig EFLAGS in EAX */xorl $EFLAGS_ID,eax /* flip ID flag */pushl eax /* set EAX as EFLAGS */popflpushfl /* Get new EFLAGS in EAX */popl eaxxorl ecx,eax /* check if ID bit changed */andl $EFLAGS_ID,eax/** if we are on a straight 486DX,* SX, or 487SX we can't change it* OTOH 6x86MXs and MIIs check OK* Also if we are on a Cyrix 6x86(L)*/je is486xisnew:/** restore original EFLAGS*/popflincl SYM(have_cpuid) /* we have CPUID instruction *//* use it to get :* processor type,* processor model,* processor mask,* by using it with EAX = 1*/movl $1, eaxcpuidmovb al, cl /* save reg for future use */andb $0x0f,ah /* mask processor family */movb ah,SYM (x86) /* put result in x86 var */andb $0xf0, al /* get model */shrb $4, almovb al,SYM (x86_model) /* store it in x86_model */andb $0x0f, cl /* get mask revision */movb cl,SYM (x86_mask) /* store it in x86_mask */movl edx,SYM(x86_capability) /* store feature flags in x86_capability *//* get vendor info by using CPUID with EXA = 0 */xorl eax, eaxcpuid/** store results contained in ebx, edx, ecx in* x86_vendor_id variable.*/movl ebx,SYM(x86_vendor_id)movl edx,SYM(x86_vendor_id)+4movl ecx,SYM(x86_vendor_id)+8movl cr0,eax /* 486+ */andl $(CR0_PAGING | CR0_PROTECTION_ENABLE | CR0_EXTENSION_TYPE), eaxorl $(CR0_ALIGMENT_MASK | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR | CR0_MONITOR_COPROC),eaxjmp 2f/* Now we test if we have a Cyrix 6x86(L). We didn't test before to avoid* clobbering the new BX chipset used with the Pentium II, which has a register* at the same addresses as those used to access the Cyrix special configuration* registers (CCRs).*//** A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2* (and it _must_ be 5 divided by 2) while other CPUs change* them in undefined ways. We need to know this since we may* need to enable the CPUID instruction at least.* We couldn't use this test before since the PPro and PII behave* like Cyrix chips in this respect.*/is486x: xor ax,axsahfmovb $5,almovb $2,bldiv bllahfcmpb $2,ahjne ncyrix/** N.B. The pattern of accesses to 0x22 and 0x23 is *essential** so do not try to "optimize" it! For the same reason we* do all this with interrupts off.*/#define setCx86(reg, val) \movb reg,al; \outb al,$0x22; \movb val,al; \outb al,$0x23#define getCx86(reg) \movb reg,al; \outb al,$0x22; \inb $0x23,alcligetCx86($0xc3) /* get CCR3 */movb al,cl /* Save old value */movb al,blandb $0x0f,bl /* Enable access to all config registers */orb $0x10,bl /* by setting bit 4 */setCx86($0xc3,bl)getCx86($0xe8) /* now we can get CCR4 */orb $0x80,al /* and set bit 7 (CPUIDEN) */movb al,bl /* to enable CPUID execution */setCx86($0xe8,bl)getCx86($0xfe) /* DIR0 : let's check this is a 6x86(L) */andb $0xf0,al /* should be 3xh */cmpb $0x30,aljne n6x86getCx86($0xe9) /* CCR5 : we reset the SLOP bit */andb $0xfd,al /* so that udelay calculation */movb al,bl /* is correct on 6x86(L) CPUs */setCx86($0xe9,bl)setCx86($0xc3,cl) /* Restore old CCR3 */stijmp isnew /* We enabled CPUID now */n6x86: setCx86($0xc3,cl) /* Restore old CCR3 */stincyrix: /* restore original EFLAGS */popflmovl cr0,eax /* 486 */andl $(CR0_PAGING | CR0_EXTENSION_TYPE | CR0_PROTECTION_ENABLE),eax /* Save PG,PE,ET */orl $(CR0_ALIGMENT_MASK | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR | CR0_MONITOR_COPROC),eax /* set AM, WP, NE and MP */jmp 2fis386: /* restore original EFLAGS */popflmovl cr0,eax /* 386 */andl $(CR0_PAGING | CR0_EXTENSION_TYPE | CR0_PROTECTION_ENABLE),eax /* Save PG,PE,ET */orl $CR0_MONITOR_COPROC,eax /* set MP */2: movl eax,cr0call check_x87ret/** We depend on ET to be correct. This checks for 287/387.*/check_x87:movb $0,SYM(hard_math)cltsfninitfstsw axcmpb $0,alje 1fmovl cr0,eax /* no coprocessor: have to set bits */xorl $4,eax /* set EM */movl eax,cr0ret.align 161: movb $1,SYM(hard_math).byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */retEND_CODEBEGIN_DATAPUBLIC(x86)PUBLIC(have_cpuid)PUBLIC(x86_model)PUBLIC(x86_mask)PUBLIC(x86_capability)PUBLIC(x86_vendor_id)PUBLIC(hard_math)SYM(x86):.byte 0SYM(have_cpuid):.long 0SYM(x86_model):.byte 0SYM(x86_mask):.byte 0SYM(x86_capability):.long 0SYM(x86_vendor_id):.zero 13SYM(hard_math):.byte 0END_DATA
Go to most recent revision | Compare with Previous | Blame | View Log
