[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[MiNT] [PATCH] FreeMiNT on native ColdFire



Hello.

Here is the long awaited patch for FreeMiNT on native ColdFire.

Basically, it allows running mintv4e.prg over EmuTOS for ColdFire.
In that case, everything is 100% ColdFire. Nothing is emulated, it is as fast as possible.

The big advantage is that in that native mode, there is no cheat, the whole ColdFire features are available from supervisor mode and kernel modules. New kernel modules could be written right now for the FireBee specific hardware.

The drawback is that native ColdFire mode allows only to run 100% ColdFire MiNT programs. Any classic 680x0 binary will die with an Illegal Instruction exception.

Of course, mintv4e.prg is still compatible with FireTOS. If 680x0 emulation is detected, it is used for specific supervisor instructions (exception stack frame format, rte, cache management...). Only supervisor instructions are emulated, so there is almost no performance loss.

Best of all, all that emulation mess is hidden in the kernel itself. ColdFire kernel modules and user programs can run equally well on FireTOS or EmuTOS :-) Currently, the FireBee FEC (ethernet) driver cleanly fails to load on EmuTOS because it uses FireTOS specific features (the DMA API). But we will find a solution for that.

native_coldfire.patch
Added support for native ColdFire. Contributed by Vincent Riviere.

Alan or Helmut, please commit!

--
Vincent Rivière
diff -aurN -x CVS freemint.orig/sys/arch/check_exc.c freemint/sys/arch/check_exc.c
--- freemint.orig/sys/arch/check_exc.c	2011-07-30 21:20:59.000000000 +0200
+++ freemint/sys/arch/check_exc.c	2012-09-21 22:15:56.218750000 +0200
@@ -536,16 +536,28 @@
 long _cdecl
 check_priv(struct privilege_violation_stackframe *frame)
 {
+	bool emulate_obsolete_instructions = true;
 	ushort opcode;
 	opcode = *frame->pc;
 	UNUSED(opcode);
+
+#ifdef __mcoldfire__
+	if (!coldfire_68k_emulation)
+	{
+		/* Fortunately, pure ColdFire programs are brand new
+		 * and does not contain any obsolete instruction.
+		 */
+		emulate_obsolete_instructions = false;
+	}
+#endif
+
 # ifndef M68000
 	/* Emulate the "move from sr" instruction,
 	 * which is not privileged on 68000, and privileged later.
 	 * Thus many programs (even Thing Desktop) execute it in
 	 * user mode, if they need an access to the condition codes.
 	 */
-	if ((opcode & MODE_REG_MASK) == MOVE_FROM_SR)
+	if (emulate_obsolete_instructions && (opcode & MODE_REG_MASK) == MOVE_FROM_SR)
 	{
 		ushort mode, reg;
 
diff -aurN -x CVS freemint.orig/sys/arch/check_exc.h freemint/sys/arch/check_exc.h
--- freemint.orig/sys/arch/check_exc.h	2007-07-13 23:32:49.000000000 +0200
+++ freemint/sys/arch/check_exc.h	2012-09-18 19:48:40.875000000 +0200
@@ -289,6 +289,16 @@
 	} bottom;
 };
 
+/* ColdFire exception stack frame */
+struct coldfire_frame
+{
+	ulong data_reg[8];
+	ulong addr_reg[7];
+	ushort format_word;
+	ushort sr;
+	ushort *pc;
+};
+
 struct m68k_stack_frames
 {
 	union {
@@ -300,6 +310,7 @@
 		struct mc68030_bus_frame_long		m68030_lbus;
 		struct mc68040_bus_frame		m68040_bus;
 		struct mc68060_bus_frame		m68060_bus;
+		struct coldfire_frame			coldfire;
 	} type;
 };
 
diff -aurN -x CVS freemint.orig/sys/arch/context.S freemint/sys/arch/context.S
--- freemint.orig/sys/arch/context.S	2011-06-16 11:25:06.000000000 +0200
+++ freemint/sys/arch/context.S	2012-09-21 22:19:23.953125000 +0200
@@ -93,6 +93,26 @@
 	lea	12(sp),a1		// start of the interesting stack area
 	move.w	(a1)+,d0		// 68000 fake frame format
 
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	build_68k
+
+	move.w	(a1)+,C_SFMT(a0)	// save format/vector word of context
+	move.w	(a1)+,d0		// get SR of context
+	move.w	d0,C_SR(a0)		// save it
+	move.l	(a1)+,C_PC(a0)		// save PC of context
+
+	move.w	C_SFMT(a0),d1
+	andi.l	#0x3000,d1		// keep the filler size bits
+	beq.s	build_stack_fixed
+	addq.l	#2,a1			// assume 2-byte filler after the exception frame
+build_stack_fixed:
+
+	// TODO FPU
+
+	bra.s	short1
+build_68k:
+#endif
 #ifdef M68000
 	move.w	(0x59e).w,d1		// get process frame flag
 	bne.s	nojunk			// we have some junk on the stack
@@ -253,7 +273,17 @@
 // valid assumption, in which case the above FPU code is redundant, the
 // next line is not however!
 
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	save_68k
+
+	move.w	#0x4000,C_SFMT(a0)	// standard frame/vector word
+
+	bra.s	save_ptrace
+save_68k:
+#endif
 	clr.w	C_SFMT(a0)		// mark as a 4 word stack frame
+save_ptrace:
 	clr.b	C_PTRACE(a0)		// no pending traces, thanks!
 
 	lea	8(sp),a1
@@ -310,6 +340,22 @@
 //	pmove	C_TC(a0),tc		// restore MMU control register
 //noprot3:
 
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	restore_68k
+
+	// TODO FPU
+
+	move.l	C_PC(a0),-(sp)		// push the PC
+	move.w	C_SR(a0),-(sp)		// push the status register
+	move.w	#0x4000,-(sp)		// push the frame/vector word
+	// Since we are just going to return using rte very soon,
+	// we can push a standard frame/vector word instead of C_SFMT(a0),
+	// so we don't have to add any extra filler byte.
+
+	bra.s	restore_check_trace
+restore_68k:
+#endif
 #ifdef M68000
 	tst.w	(0x59e).w		// test longframe (AKP)
 	beq.s	short3
@@ -391,6 +437,7 @@
 short3:
 	move.l	C_PC(a0),-(sp)		// push the PC
 	move.w	C_SR(a0),-(sp)		// push the status register
+restore_check_trace:
 	tst.b	C_PTRACE(a0)		// check for a pending trace
 	movem.l	(a0),d0-d7/a0-a6	// restore registers d0-d7/a0-a6
 	beq.s	notrace
@@ -445,6 +492,22 @@
 noprot4:
 #endif
 
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	change_68k
+
+	// TODO FPU
+
+	move.l	C_PC(a0),-(sp)		// push the PC
+	move.w	C_SR(a0),-(sp)		// push the status register
+	move.w	#0x4000,-(sp)		// push the frame/vector word
+	// Since we are just going to return using rte very soon,
+	// we can push a standard frame/vector word instead of C_SFMT(a0),
+	// so we don't have to add any extra filler byte.
+
+	bra.s	change_check_trace
+change_68k:
+#endif
 #ifdef M68000
 	tst.w	(0x59e).w		// test longframe (AKP)
 	beq.s	short6
@@ -528,6 +591,7 @@
 short6:
 	move.l	C_PC(a0),-(sp)		// push the PC
 	move.w	C_SR(a0),-(sp)		// push status register
+change_check_trace:
 	tst.b	C_PTRACE(a0)		// check for a pending trace
 	movem.l	(a0),d0-d7/a0-a6	// restore registers d0-d7/a0-a6
 	beq.s	notrace2
diff -aurN -x CVS freemint.orig/sys/arch/cpu.S freemint/sys/arch/cpu.S
--- freemint.orig/sys/arch/cpu.S	2011-09-18 23:23:34.091726500 +0200
+++ freemint/sys/arch/cpu.S	2012-09-21 22:51:59.125000000 +0200
@@ -22,9 +22,15 @@
 
 _get_superscalar:
 #ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	get_superscalar_68k
+	rts				// nothing to do
+get_superscalar_68k:
+#endif
+#ifdef __mcoldfire__
 	moveq	#60,d1
 	cmp.w	_mcpu+2,d1
-	bpl.s	ssret
+	bhi.s	ssret
 #else
 	cmp.w	#60,_mcpu+2
 	bmi.s	ssret
@@ -43,6 +49,10 @@
 _is_superscalar:
 	clr.w	d0
 #ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	beq.s	ssret			// not superscalar
+#endif
+#ifdef __mcoldfire__
 	moveq	#60,d1
 	cmp.w	_mcpu+2,d1
 	bpl.s	ssret
@@ -94,6 +104,18 @@
 #else
 	movem.l	d0-d1/a0-a3,-(sp)
 #endif
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	init_cache_68k
+
+	lea	_cache_coldfire,a0
+	movea.l	a0,a3
+	lea	clq,a1
+	movea.l	a1,a2
+
+	bra.s	icset
+init_cache_68k:
+#endif
 	move.l	_mcpu,d0
 	beq	icquit
 	cmp.w	#10,d0
@@ -195,6 +217,10 @@
 // Set the CACR according to the Cache Control Word and Mask
 
 _ccw_set:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	beq	clq			// currently unsupported
+#endif
 	tst.w	hascaches
 #ifdef __mcoldfire__
 	beq	clq
@@ -266,6 +292,13 @@
 // Extract Cache Control Word from the CACR
 
 _ccw_get:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	ccw_get_68k
+	moveq	#0x0007,d0		// rough approximation
+	rts
+ccw_get_68k:
+#endif
 	tst.w	hascaches
 	beq.s	clq
 #ifdef __mcoldfire__
@@ -296,6 +329,13 @@
 // get default Cache Control Mask for currently used CPU
 
 _ccw_getdmask:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	ccw_getdmask_68k
+	moveq	#0x0007,d0		// rough approximation
+	rts
+ccw_getdmask_68k:
+#endif
 	move.l	_mcpu,d0		// high word assumed 0
 	divu.w	#5,d0
 	and.l	#0x0000ffff,d0		// better to be safe...
@@ -749,6 +789,46 @@
 	dc.w	0xF478			// this is "cpusha dc"
 	dc.w	0xF498			// this is "cinva ic"
 	rts
+
+#ifdef __mcoldfire__
+_cache_coldfire:			// ColdFire cache
+        // This code comes from the MCF547x Reference Manual
+        // Section 7.11 Cache Management
+        //
+        // The ColdFire has no cinva instruction.
+        // Instead, cpushl writes the modified cache data to the RAM
+        // then invalidates the caches (data + instruction) except if
+        // the bits DDPI and IDPI have been set in the CACR.
+        //
+        // The ColdFire V4e core has a 32 kB instruction cache
+        // and a 32 kB data cache. Both caches have the same structure.
+        // The data is stored in "Line" elements of 16 bytes.
+        // The Lines are stored in a 2D array of 4 Ways * 512 Sets.
+        //
+        // The following changes have been made to the original code:
+        // - flush both caches with "cpushl bc" instead of "cpushl dc"
+        // - flush the 512 Sets (original code forgot the last one)
+        
+	nop			// synchronize/flush store buffer
+	moveq.l #0,d0		// initialize way counter
+	moveq.l #0,d1		// initialize set counter
+	move.l  d0,a0		// initialize cpushl pointer
+
+setloop:
+	cpushl	bc,(a0) 	// push cache line a0 (both caches)
+	add.l	#0x0010,a0	// increment set index by 1
+	addq.l	#1,d1		// increment set counter
+	cmpi.l	#512,d1 	// are sets for this way done?
+	bne.s	setloop
+
+	moveq.l #0,d1		// set counter to zero again
+	addq.l	#1,d0		// increment to next way
+	move.l	d0,a0		// set = 0, way = d0
+	cmpi.l	#4,d0		// flushed all the ways?
+	bne.s	setloop
+	rts
+#endif /* COLDFIRE */
+
 // ---------------------------------------------------
 
 // log2phys
diff -aurN -x CVS freemint.orig/sys/arch/detect.S freemint/sys/arch/detect.S
--- freemint.orig/sys/arch/detect.S	2011-06-03 10:56:48.000000000 +0200
+++ freemint/sys/arch/detect.S	2012-09-21 22:56:04.187500000 +0200
@@ -261,8 +261,8 @@
 //
 
 _detect_cpu:
-#ifdef COLDFIRE
-	moveq	#60,d0
+#ifdef __mcoldfire__
+	moveq	#60,d0		// only true when coldfire_68k_emulation = true
 #else
 	movem.l	a0-a2/d1-d2,-(sp)
 
@@ -384,8 +384,8 @@
 	.globl	_mcpu
 
 _detect_fpu:
-#ifdef COLDFIRE
-	moveq	#0,d0
+#ifdef __mcoldfire__
+	moveq	#0,d0		// TODO ColdFire FPU
 #else
 	movem.l	a0-a2/d1,-(sp)
 	move.l	sp,a0		// save the ssp
diff -aurN -x CVS freemint.orig/sys/arch/init_mach.c freemint/sys/arch/init_mach.c
--- freemint.orig/sys/arch/init_mach.c	2011-06-16 11:25:06.000000000 +0200
+++ freemint/sys/arch/init_mach.c	2012-09-26 19:57:33.531250000 +0200
@@ -174,6 +174,14 @@
 					break;
 				}
 # endif
+
+#ifdef __mcoldfire__
+				case COOKIE__CPU:
+				{
+					coldfire_68k_emulation = true;
+					break;
+				}
+#endif
 			}
 			
 			jar++;
@@ -303,7 +311,11 @@
 					machine = "Atari TT";
 					break;
 				case FALCON:
+#ifdef __mcoldfire__
+					machine = "FireBee";
+#else
 					machine = "Atari Falcon";
+#endif
 					break;
 				case MILAN_C:
 					machine = "Milan";
@@ -333,6 +345,14 @@
 	
 	_fpu = " no ";
 	
+#ifdef __mcoldfire__
+	if (!coldfire_68k_emulation)
+	{
+		fpu_type = "ColdFire V4e";
+		_fpu = "/";
+	}
+	else
+#endif
 	if (fpu)
 	{
 		switch (fputype >> 16)
@@ -360,57 +380,70 @@
 		}
 	}
 	
-	_cpu = "m68k";
-	_mmu = "";
-	
-	switch (mcpu)
+#ifdef __mcoldfire__
+	UNUSED(buf);
+
+	if (!coldfire_68k_emulation)
 	{
-		case 0:
-			cpu_type = "68000";
-			_cpu = cpu_type;
-			_mmu = "";
-			break;
-		case 10:
-			cpu_type = "68010";
-			_cpu = cpu_type;
-			_mmu = "";
-			break;
-		case 20:
-			cpu_type = "68020";
-			_cpu = cpu_type;
-			_mmu = "";
-			break;
-		case 30:
-			cpu_type = mmu_type = "68030";
-			_cpu = cpu_type;
-			_mmu = "/MMU";
-			break;
-		case 40:
-			cpu_type = mmu_type = "68040";
-			_cpu = cpu_type;
-			_mmu = "/MMU";
-			break;
-		case 60:
+		cpu_type = mmu_type = "ColdFire V4e";
+		_cpu = cpu_type;
+		_mmu = "/MMU";
+	}
+	else
+#endif
+	{
+		_cpu = "m68k";
+		_mmu = "";
+		
+		switch (mcpu)
 		{
-			ulong pcr;
-			
-			__asm__
-			(
-				".word 0x4e7a,0x0808;"
-				"movl %%d0,%0"
-				: "=d"(pcr)
-				:
-				: "d0"
-			);
-			
-			ksprintf (buf, sizeof (buf), "68%s060 rev.%ld",
-					pcr & 0x10000 ? "LC/EC" : "",
-					(pcr >> 8) & 0xff);
-			
-			cpu_type = mmu_type = "68060";
-			_cpu = buf;
-			_mmu = "/MMU";
-			break;
+			case 0:
+				cpu_type = "68000";
+				_cpu = cpu_type;
+				_mmu = "";
+				break;
+			case 10:
+				cpu_type = "68010";
+				_cpu = cpu_type;
+				_mmu = "";
+				break;
+			case 20:
+				cpu_type = "68020";
+				_cpu = cpu_type;
+				_mmu = "";
+				break;
+			case 30:
+				cpu_type = mmu_type = "68030";
+				_cpu = cpu_type;
+				_mmu = "/MMU";
+				break;
+			case 40:
+				cpu_type = mmu_type = "68040";
+				_cpu = cpu_type;
+				_mmu = "/MMU";
+				break;
+			case 60:
+			{
+				ulong pcr;
+				
+				__asm__
+				(
+					".word 0x4e7a,0x0808;"
+					"movl %%d0,%0"
+					: "=d"(pcr)
+					:
+					: "d0"
+				);
+				
+				ksprintf (buf, sizeof (buf), "68%s060 rev.%ld",
+						pcr & 0x10000 ? "LC/EC" : "",
+						(pcr >> 8) & 0xff);
+				
+				cpu_type = mmu_type = "68060";
+				_cpu = buf;
+				_mmu = "/MMU";
+				break;
+			}
 		}
 	}
 	
diff -aurN -x CVS freemint.orig/sys/arch/intr.S freemint/sys/arch/intr.S
--- freemint.orig/sys/arch/intr.S	2011-06-13 09:52:06.000000000 +0200
+++ freemint/sys/arch/intr.S	2012-09-26 21:16:36.765625000 +0200
@@ -82,13 +82,30 @@
 	move.w	d0,vblcnt
 	bra.s	L_novbl
 L_vbl:
+	// set up an exception stack frame for VBL emulation
+	tst.w	_coldfire_68k_emulation
+	bne.s	L_frame060
+
+	// set up a ColdFire stack frame
 	subq.l	#8,sp
 	move.l	8(sp),(sp)	// move the d0 backup on the top of the stack
-	clr.w	10(sp)		// set up a jump to VBL emulation
+	move.w	#0x4000,4(sp)	// format/vector word
+	move.w	sr,d0
+	move.w	d0,6(sp)	// return sr
 	move.l	#_mint_vbl,d0
-	move.l	d0,6(sp)
+	move.l	d0,8(sp)	// return pc
+	bra.s	L_novbl
+
+L_frame060:
+	// set up a 68060 stack frame
+	subq.l	#8,sp
+	move.l	8(sp),(sp)	// move the d0 backup on the top of the stack
 	move.w	sr,d0
-	move.w	d0,4(sp)
+	move.w	d0,4(sp)	// return sr
+	move.l	#_mint_vbl,d0
+	move.l	d0,6(sp)	// return pc
+	clr.w	10(sp)		// format/vector word
+
 L_novbl:
 	move.l	(sp)+,d0		// restore register
 	move.l	_old_5ms.w(pc),-(sp)	// push old vector & save a bit of memory
@@ -276,8 +293,21 @@
 
 // "VBL" things go here (50 times per second at IPL 3)
 
-txit:	btst	#2,24(sp)		// don't perform if saved IPL is higher than 3 (bit 2 set)
+txit:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	txit_68k
+
+	btst	#2,26(sp)		// don't perform if saved IPL is higher than 3 (bit 2 set)
 	bne.s	L_popnout
+
+	bra.s	L_vbl_emu
+txit_68k:
+#endif
+	btst	#2,24(sp)		// don't perform if saved IPL is higher than 3 (bit 2 set)
+	bne.s	L_popnout
+
+L_vbl_emu:
 	move.w	#0x2400,sr		// lower the current IPL
 
 // floppy stuff
@@ -354,8 +384,19 @@
 // Process' time has expired, check if we can preempt
 
 L_expired:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	L_expired_68k
+
+	btst	#5,2(sp) 		// user mode?
+	bne.s	L_out			// no -- switching is not possible
+
+	bra.s	L_expired2
+L_expired_68k:
+#endif
 	btst	#5,(sp) 		// user mode?
 	bne.s	L_out			// no -- switching is not possible
+L_expired2:
 	tst.w	(0x043e).w		// test floppy disk lock variable
 	bne.s	L_out			// if locked, can't switch
 #ifdef __mcoldfire__
@@ -717,7 +758,17 @@
 	move.l	_curproc,a0
 	move.l	sp,P_EXCSSP(a0)
 	addq.l	#4,P_EXCSSP(a0)
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	do_sig_68k
+
+	move.l	8(sp),P_EXCPC(a0)
+	bra.s	do_sig_restore
+
+do_sig_68k:
+#endif
 	move.l	6(sp),P_EXCPC(a0)
+do_sig_restore:
 	move.l	(sp)+,a0
 
 	tst.w	_in_kernel		// are we already in the kernel?
@@ -780,6 +831,15 @@
 	move.l	a2,-(sp)
 	move.l	_curproc,a0
 	move.l	P_EXCSSP(a0),a1 	// a1 is now exception_ssp
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	mmu_sigbus_68k
+
+	// TODO ColdFire MMU
+
+	bra.s	ms_goon
+mmu_sigbus_68k:
+#endif
 #if !defined(M68040) && !defined(M68060)
 	move.w	0xA(a1),d0		// d0 is SSW
 	btst	#6,d0			// read or write?
@@ -1204,26 +1264,33 @@
 	dc.l	0
 _new_trace:
 #ifdef __mcoldfire__
+	move.l	a0,-(sp)
 	move.l	d0,-(sp)
-	btst	#5,4(sp) 		// only check when called from supervisor mode
+
+	tst.w	_coldfire_68k_emulation
+	bne.s	cf_68k_trace
+
+	lea	10(sp),a0		// native coldfire: sr, pc
+	bra.s	cf_trace
+
+cf_68k_trace:
+	lea	8(sp),a0		// 68K emulation: sr, pc
+
+cf_trace:
+	btst	#5,(a0) 		// only check when called from supervisor mode
 	beq.s	S_1
-	move.l	#_mint_dos,d0
-	cmp.l	6(sp),d0		// lets not trace the kernel !
+	move.l	2(a0),d0		// pc
+	cmp.l	#_mint_dos,d0		// lets not trace the kernel !
 	beq.s	S_2
-	move.l	#_mint_xbios,d0
-	cmp.l	6(sp),d0
+	cmp.l	#_mint_xbios,d0
 	beq.s	S_2
-	move.l	#_mint_bios,d0
-	cmp.l	6(sp),d0
+	cmp.l	#_mint_bios,d0
 	beq.s	S_2
-	move.l	#_new_divzero,d0
-	cmp.l	6(sp),d0
+	cmp.l	#_new_divzero,d0
 	beq.s	S_2
-	move.l	#_new_trapv,d0
-	cmp.l	6(sp),d0
+	cmp.l	#_new_trapv,d0
 	beq.s	S_2
-	move.l	#_new_chk,d0
-	cmp.l	6(sp),d0
+	cmp.l	#_new_chk,d0
 	beq.s	S_2
 
 // add any other non-traceable entities here...
@@ -1233,12 +1300,14 @@
 	move.l	#_sigtrap,d0
 	move.l	d0,_sig_routine
 	move.l	(sp)+,d0
+	move.l	(sp)+,a0
 	bra	Do_sig
 
-S_2:	move.w	4(sp),d0
+S_2:	move.w	(a0),d0
 	and.l	#0x3fff,d0		// clear both trace bits
-	move.w	d0,4(sp)
+	move.w	d0,(a0)
 	move.l	(sp)+,d0
+	move.l	(sp)+,a0
 #else
 	btst	#5,(sp) 		// only check when called from supervisor mode
 	beq.s	S_1
diff -aurN -x CVS freemint.orig/sys/arch/kernfs_mach.c freemint/sys/arch/kernfs_mach.c
--- freemint.orig/sys/arch/kernfs_mach.c	2001-06-13 22:21:36.000000000 +0200
+++ freemint/sys/arch/kernfs_mach.c	2012-09-19 01:13:53.890625000 +0200
@@ -59,6 +59,13 @@
 
 	clockfactor = 0;
 
+#ifdef __mcoldfire__
+	if (!coldfire_68k_emulation)
+	{
+		clockfactor = 2; // Experimentally almost accurate
+	}
+	else
+#endif	
 	switch (mcpu)
 	{
 		case 20:
diff -aurN -x CVS freemint.orig/sys/arch/sig_mach.c freemint/sys/arch/sig_mach.c
--- freemint.orig/sys/arch/sig_mach.c	2011-06-16 11:25:06.000000000 +0200
+++ freemint/sys/arch/sig_mach.c	2012-09-21 23:11:30.218750000 +0200
@@ -134,11 +134,7 @@
 	
 	/* set a new system stack, with a bit of buffer space */
 	oldstack = curproc->sysstack;
-# ifdef COLDFIRE
 	newstack = ((unsigned long) &newcurrent) - 0x40UL - 12UL - 0x100UL;
-# else
-	newstack = ((unsigned long) &newcurrent) - 0x40UL - 12UL - 0x100UL;
-# endif	
 	if (newstack < (unsigned long) curproc->stack + ISTKSIZE + 256)
 	{
 		ALERT("stack overflow");
@@ -307,11 +303,7 @@
 	else
 	{
 		unwound_stack = 0;
-# ifdef COLDFIRE	
-		oldctxt = (CONTEXT *) (((long) &frame[2]) + 0x40 + 0x100);
-# else
 		oldctxt = (CONTEXT *) (((long) &frame[2]) + 0x40 + 0x100);
-# endif
 		if (oldctxt->regs[0] != CTXT_MAGIC)
 		{
 			FATAL ("p_sigreturn: corrupted context");
diff -aurN -x CVS freemint.orig/sys/arch/syscall.S freemint/sys/arch/syscall.S
--- freemint.orig/sys/arch/syscall.S	2011-06-13 09:52:06.000000000 +0200
+++ freemint/sys/arch/syscall.S	2012-09-21 23:17:38.234375000 +0200
@@ -224,6 +224,22 @@
 	bra	reentrant_trap
 
 norm_xbios:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	LX_68k
+
+	btst	#5,2(sp) 		// test for user/super mode
+	beq.s	LX_usr
+
+	move.w	(sp),d1			// format/vector word
+	andi.l	#0x3000,d1		// keep the filler size bits
+	beq.s	LX_stack_fixed
+	moveq	#2,d1			// assume 2-byte filler after the exception frame
+LX_stack_fixed:
+	lea	8(sp,d1.l),a1
+	bra.s	LX_check
+LX_68k:
+#endif
 	btst	#5,(sp) 		// test for user/super mode
 	beq.s	LX_usr
 #ifndef M68000
@@ -376,8 +392,19 @@
 	tst.w	_bconbdev		// is BIOS buffering on?
 	bmi	L_bios			// no, skip all this
 
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	L_68k
+
+	btst	#5,2(sp) 		// test for user/super mode
+	bne	L_bios			// if super, goto L_bios
+
+	bra.s	L_user
+L_68k:
+#endif
 	btst	#5,(sp) 		// test for user/super mode
 	bne.s	L_bios			// if super, goto L_bios
+L_user:
 	tst.w	_proc_clock		// are we about to be preempted?
 	beq.s	L_bios
 
@@ -684,8 +711,10 @@
 
 norm_trap2:
 #ifdef __mcoldfire__
+	move.l	a0,-(sp)		// backup a0
 	lea	_in_kernel,a0
 	bset	#0x07,(a0)
+	move.l	(sp)+,a0		// restore a0
 #else
 	bset	#0x07,_in_kernel
 #endif
@@ -785,6 +814,17 @@
 	.text
 
 _trap_1_emu:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	TE_D_68K
+
+	move.w	sr,d0
+	move.w	d0,-(sp)	// return sr
+	move.w	#0x4000,-(sp)	// format/vector word
+
+	bra.s	TE_D_JMP_OLD
+TE_D_68K:
+#endif
 #ifdef M68000
 	tst.w	(0x059e).w		// test longframe
 	beq.s	TE_D
@@ -799,6 +839,7 @@
 #else
 	move.w	sr,-(sp)
 #endif
+TE_D_JMP_OLD:
 #if !(defined(M68000) || defined(__mcoldfire__))
 	jmp	([_old_dos])
 #else
@@ -809,6 +850,20 @@
 	// Ozk: we cannot use D0/D1 becaues the ugly VDI and AES
 	// passes paremters in these registers.
 _trap_2_emu:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	TE_AV_68K
+
+	subq.l	#6,sp
+	move.w	d0,(sp)		// backup d0
+	move.w	#0x4000,2(sp)	// format/vector word
+	move.w	sr,d0
+	move.w	d0,4(sp)	// return sr
+	move.w	(sp)+,d0	// restore d0
+
+	bra.s	TE_AV_JMP_OLD
+TE_AV_68K:
+#endif
 #ifdef	M68000
 	tst.w	(0x059e).w
 	beq.s	TE_AV
@@ -826,6 +881,7 @@
 #else
 	move.w	sr,-(sp)
 #endif
+TE_AV_JMP_OLD:
 #if !(defined(M68000) || defined(__mcoldfire__))
 	jmp	([_old_trap2])
 #else
@@ -834,6 +890,17 @@
 #endif
 	
 _trap_13_emu:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	TE_B_68K
+
+	move.w	sr,d0
+	move.w	d0,-(sp)	// return sr
+	move.w	#0x4000,-(sp)	// format/vector word
+
+	bra.s	TE_B_JMP_OLD
+TE_B_68K:
+#endif
 #ifdef M68000
 	tst.w	(0x059e).w		// test longframe
 	beq.s	TE_B
@@ -848,6 +915,7 @@
 #else
 	move.w	sr,-(sp)
 #endif
+TE_B_JMP_OLD:
 #if !(defined(M68000) || defined(__mcoldfire__))
 	jmp	([_old_bios])
 #else
@@ -856,6 +924,17 @@
 #endif
 
 _trap_14_emu:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	TE_X_68K
+
+	move.w	sr,d0
+	move.w	d0,-(sp)	// return sr
+	move.w	#0x4000,-(sp)	// format/vector word
+
+	bra.s	TE_X_JMP_OLD
+TE_X_68K:
+#endif
 #ifdef M68000
 	tst.w	(0x059e).w		// test longframe
 	beq.s	TE_X
@@ -870,6 +949,7 @@
 #else
 	move.w	sr,-(sp)
 #endif
+TE_X_JMP_OLD:
 #if !(defined(M68000) || defined(__mcoldfire__))
 	jmp	([_old_xbios])
 #else
@@ -1138,6 +1218,18 @@
 // 68000 not tested (with M68000)
 //
 reentrant_trap:
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	reent_68k
+
+	move.w	(a0),d1			// format/vector word
+	addq.l	#2+2+4,a0		// skip format/vector word, sr and pc
+	andi.l	#0x3000,d1		// keep the filler size bits
+	beq.s	reent_fpu
+	addq.l	#2,a0			// assume 2-byte filler after the exception frame
+	bra.s	reent_fpu
+reent_68k:
+#endif
 #ifdef M68000
 	addq.l	#2+4,a0
 	tst.w	(0x59e).w
@@ -1147,6 +1239,7 @@
 #else
 	addq.l	#2+4+2,a0
 #endif
+reent_fpu:
 	// Save hardware registers (CPU/FPU)
 	tst.w	_fpu
 	beq.s	reent_fpu_saved
@@ -1357,6 +1450,18 @@
 	// Since we're not interested in the stack now,
 	// we wont bother with it. VDI/AES passes args in D0/D1.
 #ifdef	TRAP2_STACK_PARAMS
+#ifdef __mcoldfire__
+	tst.w	_coldfire_68k_emulation
+	bne.s	reent2_68k
+
+	move.w	(a0),d1			// format/vector word
+	addq.l	#2+2+4,a0		// skip format/vector word, sr and pc
+	andi.l	#0x3000,d1		// keep the filler size bits
+	beq.s	reent2_fpu
+	addq.l	#2,a0			// assume 2-byte filler after the exception frame
+	bra.s	reent2_fpu
+reent2_68k:
+#endif
 #ifdef M68000
 	addq.l	#2+4,a0
 	tst.w	(0x59e).w
@@ -1367,6 +1472,7 @@
 	addq.l	#2+4+2,a0
 #endif
 #endif
+reent2_fpu:
 	// Save hardware registers (CPU/FPU)
 	tst.w	_fpu
 	beq.s	reent2_fpu_saved
diff -aurN -x CVS freemint.orig/sys/arch/v4epatch.S freemint/sys/arch/v4epatch.S
--- freemint.orig/sys/arch/v4epatch.S	2007-03-19 22:05:48.000000000 +0100
+++ freemint/sys/arch/v4epatch.S	2012-09-18 23:30:42.937500000 +0200
@@ -1,4 +1,4 @@
-#ifdef COLDFIRE
+#ifdef __mcoldfire__
 
 	.data
 
diff -aurN -x CVS freemint.orig/sys/cookie.c freemint/sys/cookie.c
--- freemint.orig/sys/cookie.c	2012-02-25 09:53:45.218750000 +0100
+++ freemint/sys/cookie.c	2012-09-26 19:45:00.125000000 +0200
@@ -185,20 +185,26 @@
 	newcookie = (struct cookie *) attach_region (rootproc, newjar_region);
 # endif
 
-	/* set the hardware detected CPU and FPU rather
-	 * than trust the TOS
-	 */
-	TRACE(("_CPU cookie = %08lx", mcpu));
+#ifdef __mcoldfire__
+	/* do not set _CPU and _FPU on native ColdFire */
+	if (coldfire_68k_emulation)
+#endif
+	{
+		/* set the hardware detected CPU and FPU rather
+		 * than trust the TOS
+		 */
+		TRACE(("_CPU cookie = %08lx", mcpu));
 
-	newcookie[i].tag = COOKIE__CPU;
-	newcookie[i].value = mcpu;
-	i++;
+		newcookie[i].tag = COOKIE__CPU;
+		newcookie[i].value = mcpu;
+		i++;
 
-	TRACE(("_FPU cookie = %08lx", fputype));
+		TRACE(("_FPU cookie = %08lx", fputype));
 
-	newcookie[i].tag = COOKIE__FPU;
-	newcookie[i].value = fputype;
-	i++;
+		newcookie[i].tag = COOKIE__FPU;
+		newcookie[i].value = fputype;
+		i++;
+	}
 
 	/* We install basic Atari cookies, if these ain't
 	 * there, assuming we're on an old ST.
diff -aurN -x CVS freemint.orig/sys/global.c freemint/sys/global.c
--- freemint.orig/sys/global.c	2012-02-25 09:53:45.234375000 +0100
+++ freemint/sys/global.c	2012-09-16 22:49:20.341298000 +0200
@@ -42,6 +42,9 @@
 long mcpu = 0;
 long pmmu = 0;
 short fpu = 0;
+#ifdef __mcoldfire__
+bool coldfire_68k_emulation = false;
+#endif
 short secure_mode = 0;
 unsigned long c20ms = 0;
 
diff -aurN -x CVS freemint.orig/sys/global.h freemint/sys/global.h
--- freemint.orig/sys/global.h	2012-02-25 09:53:45.234375000 +0100
+++ freemint/sys/global.h	2012-09-16 22:53:12.091298000 +0200
@@ -63,6 +63,14 @@
  */
 extern short fpu; /* flag if fpu is present */
 
+#ifdef __mcoldfire__
+/* When true, we have a ColdFire CPU running a 68K emulation layer.
+ * So ColdFire supervisor instructions are not available.
+ * We also have 68K exception stack frames, not native ColdFire ones.
+ */
+extern bool coldfire_68k_emulation;
+#endif
+
 /* if this variable is set, then we have "secure mode" enabled; that
  * means only the superuser may access some functions those may be
  * critical for system security.
diff -aurN -x CVS freemint.orig/sys/memory.c freemint/sys/memory.c
--- freemint.orig/sys/memory.c	2012-03-22 19:56:56.515625000 +0100
+++ freemint/sys/memory.c	2012-09-26 19:49:52.187500000 +0200
@@ -37,8 +37,8 @@
 
 # include "proc.h"
 
-# ifdef COLDFIRE
-extern void   patch_memset_purec(BASEPAGE *b);
+# ifdef __mcoldfire__
+extern void patch_memset_purec(BASEPAGE *b);
 # endif
 
 struct screen
@@ -1614,9 +1614,18 @@
 	DEBUG (("load_region: return region = %lx", reg));
 
 	SANITY_CHECK_MAPS ();
-#ifdef COLDFIRE
-   patch_memset_purec(b);
+
+#ifdef __mcoldfire__
+	if (coldfire_68k_emulation)
+	{
+		/* Unfortunately, a few 680x0 user instructions can't be
+		 * emulated via illegal instruction handler on ColdFire,
+		 * so they require to be dynamically patched.
+		 */
+		patch_memset_purec(b);
+	}
 #endif
+
 	return reg;
 }
 
diff -aurN -x CVS freemint.orig/sys/xbios.c freemint/sys/xbios.c
--- freemint.orig/sys/xbios.c	2011-06-16 11:25:05.000000000 +0200
+++ freemint/sys/xbios.c	2012-09-18 23:41:19.218750000 +0200
@@ -116,9 +116,6 @@
 	usrarg3 = arg3;
 	usrarg4 = arg4;
 	usrarg5 = arg5;
-#ifdef COLDFIRE
-/*	return (*usrcall)((long) usrcall, usrarg1, usrarg2, usrarg3, usrarg4, usrarg5); */
-#endif
 	SIGACTION(get_curproc(), 0).sa_handler = (long) do_usrcall;
 	savesr = syscall->sr;	/* save old super/user mode flag */
 	syscall->sr |= 0x2000;	/* set supervisor mode */