[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [MiNT] CPU detection broken
So here is my patch for the CPU detection.
Now the behaviour is correct for every CPU supported by the MiNTLib
(including ColdFire, I hope).
I had to rewrite Getcookie() and get_sysvar() in assembly language, because
they have to be compatible with every CPU. I know assembly language should
be avoided as much as possible because of portability issues, but in this
case there was no other solution. Fortunately, these assembly sources are
small and simple, it will be easy to modify them. However, these functions
are rarely modified.
I kept the "Backward compatibility kludge for MiNT 1.14.7", so if a cookie
has a value of -42, Getcookie() will return 0 instead :-(
I wrote that code carefully, and I tested it as much as possible, I didn't
found any problem. However, I cannot guarantee there is no hidden
regression, so be careful. Code reviews will be highly appreciated.
I didn't include a copyright notice in the new files, because I don't want
to own them. I didn't know what to put instead.
Please commit this patch with the following description:
----------------------------------------------------------------------
Fixed 68020+ detection.
Added ColdFire detection.
Rewritten getcookie.c in assembly language.
Split sysvar.c into getsysvar.S and setsysvar.c
Fixed MiNTLib Ident string for ColdFire.
Contributed by Vincent Riviere.
----------------------------------------------------------------------
--
Vincent Rivière
diff -aurN -x CVS mintlib.orig/mintlib/SRCFILES mintlib/mintlib/SRCFILES
--- mintlib.orig/mintlib/SRCFILES 2009-05-22 22:35:36.812500000 +0200
+++ mintlib/mintlib/SRCFILES 2009-05-31 23:20:46.317317500 +0200
@@ -17,6 +17,7 @@
assert.c \
buffindf.c \
calloc.c \
+ checkcpu.S \
console.c \
crtinit.c \
ctermid.c \
@@ -32,12 +33,13 @@
frexp.S \
ftime.c \
ftw.c \
- getcookie.c \
+ getcookie.S \
getcwd.c \
getenv.c \
getloadavg.c \
getlogin.c \
getopt_old.c \
+ getsysvar.S \
getumask.c \
getwd.c \
globals.c \
@@ -89,12 +91,12 @@
setjmp.S \
setlocale.c \
setstack.S \
+ setsysvar.c \
spawn.c \
spawnve.c \
spawnvp.c \
stksiz.c \
syscall.c \
- sysvar.c \
tell.c \
thread.c \
toxxx.c \
diff -aurN -x CVS mintlib.orig/mintlib/checkcpu.S mintlib/mintlib/checkcpu.S
--- mintlib.orig/mintlib/checkcpu.S 1970-01-01 01:00:00.000000000 +0100
+++ mintlib/mintlib/checkcpu.S 2009-06-01 17:10:49.515625000 +0200
@@ -0,0 +1,117 @@
+| checkcpu.S -- MiNTLib.
+|
+| This file is part of the MiNTLib project, and may only be used
+| modified and distributed under the terms of the MiNTLib project
+| license, COPYMINT. By continuing to use, modify, or distribute
+| this file you indicate that you have read the license and
+| understand and accept it fully.
+
+| void _checkcpu(void);
+|
+| Check if the actual CPU is compatible with this binary.
+| If it is compatible, the function returns silently.
+| If it is not compatible, it displays an error message then exits with the
+| error code -1. In that case, this function never returns.
+|
+| WARNING: This function is called from the startup code before knowing the
+| actual CPU type. So it must be compatible with any processor (including
+| 680x0 and ColdFire models). So it must be written carefully by using only
+| instructions common to all of the supported processors. Especially, gas
+| pseudo-jump instructions must be avoided (jbsr, jbra...), because they may
+| be translated to unsupported jump instructions.
+
+ .extern _Getcookie | int Getcookie(long cookie, long *val);
+
+ .globl __checkcpu
+__checkcpu:
+#ifdef __M68020__
+ subql #4,sp | Local variable for cookie value
+
+ pea sp@
+ movl #0x5f435055,sp@- | "_CPU"
+ jsr _Getcookie
+ addql #8,sp
+
+ movel sp@+,d1 | Cookie value
+
+ tstl d0
+ bnes .bad020 | _CPU cookie not found
+
+ cmpl #20,d1
+ bhss .ok020 | CPU >= 68020
+
+.bad020:
+ pea .err020 | Error message
+ bra .printexit
+
+.err020:
+ .ascii "This program requires a 68020 or higher\r\n", \
+ "processor and cannot be run on this\r\n", \
+ "machine.\r\n\0"
+ .even
+.ok020:
+#endif
+
+#ifdef __mcoldfire__
+ subql #4,sp | Local variable for cookie value
+
+ pea sp@
+ movl #0x5f43465f,sp@- | "_CF_"
+ jsr _Getcookie
+ addql #8,sp
+
+ movel sp@+,d1 | Cookie value
+
+ tstl d0
+ beqs .okv4e | _CF_ cookie found
+
+ pea .errv4e | Error message
+ bra .printexit
+
+.errv4e:
+ .ascii "This program requires a ColdFire V4e\r\n", \
+ "processor and cannot be run on this\r\n", \
+ "machine.\r\n\0"
+ .even
+.okv4e:
+#endif
+
+#ifdef __M68881__
+ subql #4,sp | Local variable for cookie value
+
+ pea sp@
+ movl #0x5f465055,sp@- | "_FPU"
+ jsr _Getcookie
+ addql #8,sp
+
+ movel sp@+,d1 | Cookie value
+
+ tstl d0
+ bnes .bad881 | _FPU cookie not found
+
+ tstl d1
+ bnes .ok881 | FPU present
+
+.bad881:
+ pea .err881 | Error message
+ bra .printexit
+
+.err881:
+ .ascii "This program requires a 68881 or higher\r\n", \
+ "arithmetic coprocessor and cannot be run\r\n", \
+ "on this machine.\r\n\0"
+ .even
+.ok881:
+#endif
+ rts | All requirements passed
+
+| Print a message then exit.
+| The message must have been pushed on the stack.
+.printexit:
+ movew #9,sp@- | Cconws()
+ trap #1
+ addql #6,sp
+
+ movew #-1,sp@- | Failure
+ movew #0x4c,sp@- | Pterm()
+ trap #1
diff -aurN -x CVS mintlib.orig/mintlib/getcookie.S mintlib/mintlib/getcookie.S
--- mintlib.orig/mintlib/getcookie.S 1970-01-01 01:00:00.000000000 +0100
+++ mintlib/mintlib/getcookie.S 2009-06-01 14:48:04.406250000 +0200
@@ -0,0 +1,94 @@
+| getcookie.S -- MiNTLib.
+|
+| This file is part of the MiNTLib project, and may only be used
+| modified and distributed under the terms of the MiNTLib project
+| license, COPYMINT. By continuing to use, modify, or distribute
+| this file you indicate that you have read the license and
+| understand and accept it fully.
+
+| int Getcookie(long cookie, long *p_value);
+|
+| Get the value of a system Cookie.
+|
+| WARNING: This function is called from the startup code before knowing the
+| actual CPU type. So it must be compatible with any processor (including
+| 680x0 and ColdFire models). So it must be written carefully by using only
+| instructions common to all of the supported processors. Especially, gas
+| pseudo-jump instructions must be avoided (jbsr, jbra...), because they may
+| be translated to unsupported jump instructions.
+
+ .extern ___has_no_ssystem | int __has_no_ssystem;
+ .extern _get_sysvar | long get_sysvar(void *var);
+
+ .globl _Getcookie
+_Getcookie:
+ lea sp@(-16),sp
+ movml d2/d3/a2/a3,sp@ | ColdFire compatibility
+
+ movel sp@(16+4),d3 | cookie
+ movel sp@(16+8),a3 | p_value
+
+ tstl ___has_no_ssystem
+ beqs .get_with_ssystem
+
+ pea 0x5a0 | _p_cookies
+ jsr _get_sysvar
+ addql #4,sp
+
+ tstl d0
+ beqs .error | No cookie jar
+
+ movl d0,a0
+
+.nextcookie:
+ tstl a0@
+ beqs .error | End of Cookie Jar
+
+ movel a0@+,d0 | Cookie name
+ movel a0@+,d1 | Cookie value
+
+ cmpl d3,d0 | Right cookie ?
+ bnes .nextcookie
+
+ moveq #0,d0 | E_OK
+
+.return:
+ cmpl #0,a3
+ beqs .restore | p_value == NULL
+
+ movl d1,a3@ | *p_value = value;
+
+.restore:
+ movml sp@,d2/d3/a2/a3 | ColdFire compatibility
+ lea sp@(16),sp
+ rts
+
+.error:
+ moveq #-1,d0 | EERROR
+ moveq #0,d1 | Cookie value
+
+ bras .return
+
+.get_with_ssystem:
+ pea -42 | Local variable for cookie value
+
+ pea sp@ | Pointer to the output variable
+ movl d3,sp@- | cookie
+ movew #8,sp@- | S_GETCOOKIE
+ movew #0x154,sp@- | Ssystem()
+ trap #1
+ lea sp@(12),sp
+
+ movel sp@+,d1 | Cookie value
+
+ cmpl #-1,d0
+ beqs .error | Fail
+
+ | Backward compatibility for MiNT 1.14.7:
+ | Ssystem() returns cookie value and ignores arg2!!
+ cmpl #-42,d1
+ bnes .return
+
+ movl d0,d1 | Get value from return value
+
+ bras .return
diff -aurN -x CVS mintlib.orig/mintlib/getcookie.c mintlib/mintlib/getcookie.c
--- mintlib.orig/mintlib/getcookie.c 2002-03-14 21:44:50.000000000 +0100
+++ mintlib/mintlib/getcookie.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,86 +0,0 @@
-/*
- * Getcookie for MiNTlib
- *
- * Author: jerry g geiger
- *
- * - Ssystem extension Draco
- * - corrected by Frank Naumann, 1998-09-09
- *
- * returns:
- *
- * - 0 if cookie was found
- * - EERROR if cookie is missing
- *
- * if p_value is set, cookie value is copied to *p_value
- *
- */
-
-#include <errno.h>
-#include <mint/mintbind.h>
-#include <mint/ssystem.h>
-#include <mint/sysvars.h>
-
-#include "lib.h"
-
-int
-Getcookie (long cookie, long *p_value)
-{
- if (__has_no_ssystem)
- {
- /* old method */
- long *cookieptr = (long*) get_sysvar(_p_cookies);
-
- if (cookieptr)
- {
- while (*cookieptr)
- {
- if (*cookieptr == cookie)
- {
- if (p_value)
- *p_value = cookieptr [1];
-
- return 0;
- }
-
- cookieptr += 2;
- }
- }
- if (p_value)
- *p_value = 0;
-
- return EERROR;
- }
- else
- {
- /* Ssystem supported, use it */
- int r;
- long v = -42;
-
- /* Make sure that P_VALUE is zeroed if the cookie can't
- be found. Reported by Tommy Andersen
- (tommya@post3.tele.dk). */
- if (p_value)
- *p_value = 0;
-
- r = Ssystem(S_GETCOOKIE, cookie, &v);
- /*
- * Backward compatibility for MiNT 1.14.7:
- * Ssystems() returns cookie value and ignores arg2!!
- */
- if (r != -1 && v == -42)
- v = r;
-
- if (r == -1) /* not found */
- {
- v = 0;
- r = EERROR;
- }
- else
- r = 0;
-
- if (p_value)
- *p_value = v;
-
- return r;
- }
-}
diff -aurN -x CVS mintlib.orig/mintlib/getsysvar.S mintlib/mintlib/getsysvar.S
--- mintlib.orig/mintlib/getsysvar.S 1970-01-01 01:00:00.000000000 +0100
+++ mintlib/mintlib/getsysvar.S 2009-06-01 17:41:03.625000000 +0200
@@ -0,0 +1,72 @@
+| getsysvar.S -- MiNTLib.
+|
+| This file is part of the MiNTLib project, and may only be used
+| modified and distributed under the terms of the MiNTLib project
+| license, COPYMINT. By continuing to use, modify, or distribute
+| this file you indicate that you have read the license and
+| understand and accept it fully.
+
+| long get_sysvar(void *var);
+|
+| Read an OS variable.
+|
+| WARNING: This function is called from the startup code before knowing the
+| actual CPU type. So it must be compatible with any processor (including
+| 680x0 and ColdFire models). So it must be written carefully by using only
+| instructions common to all of the supported processors. Especially, gas
+| pseudo-jump instructions must be avoided (jbsr, jbra...), because they may
+| be translated to unsupported jump instructions.
+
+ .extern ___has_no_ssystem | int __has_no_ssystem;
+
+ .globl _get_sysvar
+_get_sysvar:
+ lea sp@(-16),sp
+ movml d2/d3/a2/a3,sp@ | ColdFire compatibility
+
+ movel sp@(16+4),a3 | var
+
+ tstl ___has_no_ssystem
+ beqs .get_with_ssystem
+
+ movel #1,sp@- | SUP_INQUIRE
+ movew #0x20,sp@- | Super()
+ trap #1
+ addql #6,sp
+
+ tstl d0
+ beqs .get_usermode | We are in user mode
+
+ movel a3@,d0 | Read the variable directly
+
+.return:
+ movml sp@,d2/d3/a2/a3 | ColdFire compatibility
+ lea sp@(16),sp
+ rts
+
+.get_with_ssystem:
+ clrl sp@-
+ movl a3,sp@- | var
+ movew #10,sp@- | S_GETLVAL
+ movew #0x154,sp@- | Ssystem()
+ trap #1
+ lea sp@(12),sp
+
+ bras .return
+
+.get_usermode:
+ clrl sp@- | SUP_SET
+ movew #0x20,sp@- | Super()
+ trap #1 | Switch to supervisor mode
+ addql #6,sp
+
+ movel a3@,d3 | Get the variable value
+
+ movel d0,sp@- | Old SSP
+ movew #0x20,sp@- | Super()
+ trap #1 | Restore user mode
+ addql #6,sp
+
+ movel d3,d0
+
+ bras .return
diff -aurN -x CVS mintlib.orig/mintlib/ident.c mintlib/mintlib/ident.c
--- mintlib.orig/mintlib/ident.c 2001-09-27 18:31:39.000000000 +0200
+++ mintlib/mintlib/ident.c 2009-06-01 11:26:38.968750000 +0200
@@ -4,6 +4,9 @@
#ifdef __M68020__
"-m68020-60 "
#endif
+#ifdef __mcoldfire__
+"-mcpu=5475 "
+#endif
#ifdef __M68881__
"-m68881 "
#endif
diff -aurN -x CVS mintlib.orig/mintlib/setsysvar.c mintlib/mintlib/setsysvar.c
--- mintlib.orig/mintlib/setsysvar.c 1970-01-01 01:00:00.000000000 +0100
+++ mintlib/mintlib/setsysvar.c 2009-05-31 22:46:08.406250000 +0200
@@ -0,0 +1,20 @@
+
+#include <support.h>
+#include <mint/mintbind.h>
+#include <mint/ssystem.h>
+
+#include "lib.h"
+
+void
+set_sysvar_to_long (void *var, long val)
+{
+ if(__has_no_ssystem) {
+ long save_ssp;
+
+ save_ssp = (long) Super((void *) 0L);
+ *((volatile long *)var) = val;
+ (void)Super((void *) save_ssp);
+ }
+ else
+ (void) Ssystem (S_SETLVAL, var, val); /* note: root only! */
+}
diff -aurN -x CVS mintlib.orig/mintlib/sysvar.c mintlib/mintlib/sysvar.c
--- mintlib.orig/mintlib/sysvar.c 2008-09-29 17:35:27.000000000 +0200
+++ mintlib/mintlib/sysvar.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,45 +0,0 @@
-
-#include <support.h>
-#include <mint/mintbind.h>
-#include <mint/ssystem.h>
-
-#include "lib.h"
-
-
-long
-get_sysvar (void *var)
-{
- if(__has_no_ssystem) {
- long ret;
-
- if (Super(1L) == 0L) {
- long save_ssp = (long) Super((void *) 0L);
-
- /* note: dont remove volatile, otherwise gcc will reorder these
- * statements and we get bombs */
- ret = *((volatile long *)var);
-
- (void)Super((void *) save_ssp);
- } else {
- ret = *((volatile long *)var);
- }
-
- return ret;
- }
- else
- return Ssystem (S_GETLVAL, var, NULL);
-}
-
-void
-set_sysvar_to_long (void *var, long val)
-{
- if(__has_no_ssystem) {
- long save_ssp;
-
- save_ssp = (long) Super((void *) 0L);
- *((volatile long *)var) = val;
- (void)Super((void *) save_ssp);
- }
- else
- (void) Ssystem (S_SETLVAL, var, val); /* note: root only! */
-}
diff -aurN -x CVS mintlib.orig/startup/crt0.S mintlib/startup/crt0.S
--- mintlib.orig/startup/crt0.S 2009-05-30 00:31:46.187500000 +0200
+++ mintlib/startup/crt0.S 2009-06-01 14:52:42.171875000 +0200
@@ -6,11 +6,24 @@
| Initialization code; this is common to both 16 and 32 bit libraries,
| so be careful!
|
- .globl __app | short, declared in crtinit.c
- .globl __base | BASEPAGE *, declared in globals.c
+| WARNING: All the instructions before the call to _checkcpu() must be
+| compatible with any processor (including 680x0 and ColdFire models).
+| So it must be written carefully by using only instructions common to all
+| of the supported processors. Especially, gas pseudo-jump instructions must
+| be avoided (jbsr, jbra...), because they may be translated to unsupported
+| jump instructions.
+
+|
+| The following external symbols are declared with .globl rather than
+| .extern in order to ensure they will be linked into the executable
+| even if they are not used in this file.
+
+ .globl __app | short, defined in crtinit.c
+ .globl __base | BASEPAGE *, defined in globals.c
.globl __heapbase | void *
- .globl __stksize | long, declared by user or in stksiz.c
+ .globl __stksize | long, defined by user or in stksiz.c
.globl _main | for references
+ .globl ___has_no_ssystem | int, defined in globals.c
|
| externs to pull ident strings of all used libraries into the
@@ -22,6 +35,13 @@
.globl ___Ident_gem
|
+| Functions defined elsewhere.
+
+ .extern __checkcpu | void _checkcpu(void);
+ .extern __acc_main | void _acc_main(void);
+ .extern __crtinit | void _crtinit(void);
+
+|
| Assumption: basepage is passed in a0 for accessories; for programs
| a0 is always 0.
@@ -30,12 +50,14 @@
.globl __start
__start:
subl a6, a6 | clear a6 for debuggers
- cmpw #0, a0 | test if acc or program
- jeq __startprg | if a program, go elsewhere
+ cmpl #0, a0 | test if acc or program
+ beqs __startprg | if a program, go elsewhere
tstl a0@(36) | also test parent basepage pointer
- jne __startprg | for accs, it must be 0
+ bnes __startprg | for accs, it must be 0
movel a0, __base | acc basepage is in A0
lea a0@(252), sp | use the command line as a temporary stack
+ jsr .early_init | early initialization
+ jsr __checkcpu | check for correct CPU or exit
jmp __acc_main | function is in crtinit.c
|
| program startup code: doesn''t actually do much, other than push
@@ -47,9 +69,27 @@
movel a0@(4), d0 | get _base->p_hitpa
bclr #0, d0 | round off
movel d0, sp | set stack (temporarily)
+ jsr .early_init | early initialization
+ jsr __checkcpu | check for correct CPU or exit
jmp __crtinit | in crtinit.c
|
+| Initialize global variables required by early initialization code.
+| Warning: The registers are not preserved
+|
+.early_init:
+ clrl sp@-
+ clrl sp@-
+ movew #-1,sp@- | Check Ssystem() availability
+ movew #0x154,sp@- | Ssystem()
+ trap #1
+ lea sp@(12),sp
+
+ movel d0,___has_no_ssystem
+
+ rts
+
+|
| interfaces for gprof: for crt0.o, does nothing, but for gcrt0.o branches
| to the appropriate subroutines
|
@@ -58,9 +98,9 @@
.globl ___mcleanup
#ifdef GCRT0
- .globl _monstartup
- .globl _moncontrol
- .globl __mcleanup
+ .extern _monstartup
+ .extern _moncontrol
+ .extern __mcleanup
__monstartup:
jmp _monstartup