Mercurial > ecos
changeset 2649:c8ac62402c90
Contribute eCosCentric's M68K architectural HAL, replacing the old
code.
line wrap: on
line diff
--- a/packages/hal/m68k/arch/current/ChangeLog +++ b/packages/hal/m68k/arch/current/ChangeLog @@ -1,13 +1,326 @@ -2004-04-22 Jani Monoses <jani@iv.ro> +2008-11-18 Bart Veer <bartv@ecoscentric.com> + + * whole package. Replace the original M68K port. + +2008-11-17 Bart Veer <bartv@ecoscentric.com> + + * doc/m68k.sgml, cdl/hal_m68k.cdl, include/arch.inc, + src/hal_arch.S, src/m68k.ld, src/m68k_stub.c: minor clean-ups. + +2008-09-11 Bart Veer <bartv@ecoscentric.com> + + * src/hal_arch.S: in the interrupt VSR only lock the scheduler in + kernel configurations. + + * include/hal_intr.h (hal_interrupt_handlers): add a define'd + alias for cyg_hal_interrupt_handlers, needed by objloader. + +2008-05-08 Bart Veer <bartv@ecoscentric.com> + + * include/hal_arch.h: add bset and bclr utility macros. + +2008-02-28 Bart Veer <bartv@ecoscentric.com> + + * src/hal_arch.S: call DSRs even in non-kernel configurations. + + * include/arch.inc: include some debug info in assembler functions + + * cdl/hal_m68k.cdl, tests/iram1.c: add test for on-chip memory and + the iram linker script section. + +2008-02-14 Bart Veer <bartv@ecoscentric.com> + + * include/hal_io.h: cope with being #include'd from inside a + linker script. + + * include/hal_intr.h: fix HAL_VSR_SET() macro for + autoincrement/decrement pointer argument. Fix HAL_DELAY_US() + support for cached vs. uncached execution. + +2007-02-04 Bart Veer <bartv@ecoscentric.com> + + * src/plf_stub.h (HAL_STUB_PLATFORM_INIT_SERIAL): do not both with + plf_comms_init() if the virtual vector init code has already taken + care of it. + +2006-12-21 Bart Veer <bartv@ecoscentric.com> + + * src/m68k.ld: ensure the ctors table is properly aligned. + +2006-12-13 Bart Veer <bartv@ecoscentric.com> + + * src/m68k.ld: default to placing _stext at the start of + .m68k_startup instead of .text, but allow platforms to override + this. + + * src/vectors.S: minor code size optimizations to the startup + code. + +2006-12-03 Bart Veer <bartv@ecoscentric.com> + + * src/vectors.S: allow platforms to suppress the exception vector + entries in .ram_vectors while preserving the virtual vectors and + any variant/processor/platform-specific data. + + * include/hal_cache.h: allow indirect inclusion from assembler + files. + +2006-10-12 Bart Veer <bartv@ecoscentric.com> + + * src/m68k.ld (SECTION_iram): fix alignment problems when the + on-chip code is not a multiple of 4 bytes + +2006-10-11 Nick Garnett <nickg@ecoscentric.com> + + * src/m68k.ld: Removed a stray '.' from _EH_FRAME1_. Added + _region_ argument to _EH_FRAME1_ and _GCC_EXCEPT_TABLE1_. + +2006-09-25 Bart Veer <bartv@ecoscentric.com> + + * doc/m68k.sgml: update to reflect recent changes in the M68K + HALs. + +2006-09-25 John Dallaway <jld@ecoscentric.com> + + * cdl/hal_m68k.cdl: Restore CYGBLD_LINKER_SCRIPT - required by the + eCos Configuration Tool. + +2006-09-13 Jonathan Larmour <jifl@eCosCentric.com> + + * src/vectors.S: Place hal_m68k_exception_reset in its own + section, to avoid its section being at 0x0 which confuses + GDB. + +2006-09-10 Bart Veer <bartv@ecoscentric.com> + + * cdl/hal_m68k.cdl: there is no need for the linker script to be + an option. + + * cdl/hal_m68k.cdl, src/plf_stub.h: allow the architectural HAL to + provide plf_stub.h at the platform HAL's request, to avoid lots of + duplication of the same header. + +2006-09-08 Bart Veer <bartv@ecoscentric.com> + + * src/m68k.ld: greatly simplify M68K linker script support. Add + support for on-chip RAM. + + * src/vectors.S: tidy up. Add support for on-chip RAM. + + * src/hal_m68k.c: move hal_if_init() up the hierarchy + + * include/hal_io.h: can now be safely #include'd by assembler + files. + + * include/hal_arch.h: change gdb stub target_register_t definition + to avoid compiler warning. + +2006-09-05 Bart Veer <bartv@ecoscentric.com> + + * src/vectors.S: fix fencepost bug in BSS initialization + + * src/m68k.ld: discard exception-related sections unless libstdcxx + is in the configuration. + + * src/hal_m68k.c: remove idle thread action function, now defaults + to just an empty macro. + + * src/hal_arch.S: tidy up comment. + + * include/hal_intr.h: HAL_VSR_SET() is now optional. + + * include/hal_cache.h: fix default cache definitions. + + * include/hal_arch.h: allow lower-level HAL to provide the LSBIT + and MSBIT macros. Do not initialize interrupts in a thread context + when building RedBoot, so loaded applications start with ints + disabled. + + * cdl/hal_m68k.cdl: fix custom build rules for proper dependency + handling. + + +2006-07-10 Bart Veer <bartv@ecoscentric.com> + + * src/m68k.ld, src/vectors.S: distinguish cleanly between the + exception vectors and the startup code. Add support for mcf52xx + cfm flash security settings. + + * src/hal_m68k.c: rationalize hal_arch_default_isr() & + hal_default_isr() functions + + * cdl/hal_m68k.cdl, src/hal_arch.S, include/arch.inc: default to + providing startup/interrupt stack in the architectural HAL + + * include/hal_intr.h: default to providing HAL_DELAY_US() in the + architectural HAL + +2006-06-26 Jonathan Larmour <jifl@ecoscentric.com> - * cdl/hal_m68k.cdl : - Invoke tail with stricter syntax that works in latest coreutils. + * cdl/hal_m68k.cdl: Use correct syntax for modern GNU tail. + +2006-03-10 John Dallaway <jld@ecoscentric.com> + + * cdl/hal_m68k.cdl: Add reference to M68k architecture documentation. + +2006-02-21 Bart Veer <bartv@ecoscentric.com> + + * include/hal_intr.h (HAL_ENABLE_INTERRUPTS): fix + DEFAULT_IPL_LEVEL usage. + +2005-06-10 Jonathan Larmour <jifl@eCosCentric.com> + + * src/m68k.ld: gcc_except_table subsections don't need to be + kept. + +2005-06-03 Jonathan Larmour <jifl@eCosCentric.com> + + * src/m68k.ld: gcc_except_table needs to be marked KEEP. + +2005-05-23 Jonathan Larmour <jifl@eCosCentric.com> +2005-05-23 Bart Veer <bartv@eCosCentric.com> + + * src/hal_arch.S (hal_m68k_exception_handler): Zero frame pointer + to improve GDB backtraces. + (hal_interrupt_stack_call_pending_DSRs): Ditto. + * src/vectors.S (hal_m68k_exception_reset): Use shorter suba.l + instruction to zero frame pointer. + +2005-02-17 Jonathan Larmour <jifl@eCosCentric.com> + + * src/m68k.ld: Use CYGBLD_HAL_LINKER_GROUPED_LIBS from the common HAL + for GROUP() list now. + +2004-10-22 Bart Veer <bartv@ecoscentric.com> + + * src/hal_m68k.c (hal_m68k_startup): add more init macros if the + platform needs them. + * doc/m68k.sgml: document the various init macros + +2004-09-22 John Dallaway <jld@ecoscentric.com> + + * src/m68k.ld: Add got, frame and RELOCS sections. Accommodate .bss* + +2004-06-24 Bart Veer <bartv@ecoscentric.com> + + * src/vectors.S: extend fixed_vectors with sections for the + variant, processor and platform HALs. This makes it easier to + share data between RedBoot and the application. + + * src/hal_m68k.c (hal_m68k_startup): support init routines + provided by the variant and processor HALs. + +2004-02-11 Bart Veer <bartv@ecoscentric.com> + + * src/vectors.S: give .fixed_vectors the right section attributes, + and fix comment. + + * src/hal_arch.S (hal_m68k_interrupt_vsr): use new macro + hal_context_extract_isr_vector_shl2, saving an instruction in the + main interrupt handling path. + + * doc/m68k.sgml: document new macro + hal_context_extract_isr_vector_shl2 + +2004-01-09 John Dallaway <jld@ecoscentric.com> + + * cdl/hal_m68k.cdl: + Correct capitalisation of "Variant details" string. + +2004-01-05 Bart Veer <bartv@ecoscentric.com> + + * src/hal_m68k.c (cyg_hal_invoke_constructors): + This function should not be static. In some configurations it may + get called from the libc startup code. + +2003-09-30 Bart Veer <bartv@ecoscentric.com> + + * src/hal_arch.S: __profile_mcount() was referenced even if the + profiling package was absent. This was only a problem when + building without linker garbage collection. + +2003-09-26 Bart Veer <bartv@ecoscentric.com> + + * cdl/hal_m68k.cdl, src/hal_arch.S, doc/m68k.sgml: + The architectural HAL now provides mcount profiling support. + +2003-08-01 Bart Veer <bartv@ecoscentric.com> + + * src/hal_arch.S: rework VSR and + hal_interrupt_stack_call_pending_DSRs so that interrupts are only + re-enabled while running the DSR, not elsewhere in the interrupt + handling code. Currently this is the only way to guarantee that + stack usage remains bounded. + + * src/hal_m68k.c: define new variable hal_m68k_dsr_ipl_level, + the IPL level that should be used when running DSRs. + + * include/hal_intr.h: HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() is + now defined even when not running with an interrupt stack, so that + DSRs still run with interrupts enabled. + + * doc/m68k.sgml: Minor updates following changes to the interrupt + handling. + + * include/hal_arch.h (HAL_THREAD_INIT_CONTEXT): A thread would be + initialized with the wrong status register value if the default + IPL level was not zero + +2003-07-22 Bart Veer <bartv@ecoscentric.com> + + * doc/m68k.sgml: Fix various typos etc. + +2003-07-17 Bart Veer <bartv@ecoscentric.com> + + * doc/m68k.sgml: update documentation. + +2003-07-06 Bart Veer <bartv@ecoscentric.com> + + * src/hal_arch.S: Add support for kernel interrupt + instrumentation. + +2003-07-04 Bart Veer <bartv@ecoscentric.com> + + * src/hal_arch.S: + Rework interrupt and exception VSR's to make the use of an + interrupt stack optional, and to allow interrupt nesting to be + disabled. + + * src/hal_m68k.c: + * src/vectors.S: + hal_m68k_interrupt_nesting count is no longer required. Instead + the stack pointer itself is compared with the interrupt stack base + and top when deciding whether or not to switch to the interrupt + stack. + + * include/hal_intr.h: + HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() is only provided if there + is an interrupt stack + + * include/hal_arch.h: + Adjust stack sizes for different interrupt-related configurations + + * cdl/hal_m68k.cdl: + Interrupt stacks and nesting are now optional as on other + architectures. + +2003-06-25 Bart Veer <bartv@ecoscentric.com> + + * include/hal_arch.h: + Eliminate a build warning. + + * include/hal_intr.h: + Provide default implementation of HAL_TRANSLATE_VECTOR() + +2003-06-04 Bart Veer <bartv@ecoscentric.com> + + * New version of the M68K support //=========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003, 2004, 2005, 2006 eCosCentric Limited // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -31,9 +344,6 @@ 2004-04-22 Jani Monoses <jani@iv.ro> // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //===========================================================================
--- a/packages/hal/m68k/arch/current/cdl/hal_m68k.cdl +++ b/packages/hal/m68k/arch/current/cdl/hal_m68k.cdl @@ -6,72 +6,255 @@ # # ==================================================================== #####ECOSGPLCOPYRIGHTBEGIN#### -## ------------------------------------------- -## This file is part of eCos, the Embedded Configurable Operating System. -## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -## -## eCos is free software; you can redistribute it and/or modify it under -## the terms of the GNU General Public License as published by the Free -## Software Foundation; either version 2 or (at your option) any later version. -## -## eCos is distributed in the hope that it will be useful, but WITHOUT ANY -## WARRANTY; without even the implied warranty of MERCHANTABILITY or -## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -## for more details. -## -## You should have received a copy of the GNU General Public License along -## with eCos; if not, write to the Free Software Foundation, Inc., -## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -## -## As a special exception, if other files instantiate templates or use macros -## or inline functions from this file, or you compile this file and link it -## with other works to produce a work based on this file, this file does not -## by itself cause the resulting work to be covered by the GNU General Public -## License. However the source code for this file must still be made available -## in accordance with section (3) of the GNU General Public License. -## -## This exception does not invalidate any other reasons why a work based on -## this file might be covered by the GNU General Public License. -## -## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -## at http://sources.redhat.com/ecos/ecos-license/ -## ------------------------------------------- +# ------------------------------------------- +# This file is part of eCos, the Embedded Configurable Operating System. +# Copyright (C) 2003,2004,2006,2008 Free Software Foundation, Inc. +# +# eCos is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 or (at your option) any later version. +# +# eCos is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with eCos; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# As a special exception, if other files instantiate templates or use macros +# or inline functions from this file, or you compile this file and link it +# with other works to produce a work based on this file, this file does not +# by itself cause the resulting work to be covered by the GNU General Public +# License. However the source code for this file must still be made available +# in accordance with section (3) of the GNU General Public License. +# +# This exception does not invalidate any other reasons why a work based on +# this file might be covered by the GNU General Public License. +# ------------------------------------------- #####ECOSGPLCOPYRIGHTEND#### # ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Date: 2003-06-04 +# +#####DESCRIPTIONEND#### +#======================================================================== cdl_package CYGPKG_HAL_M68K { display "m68k architecture" parent CYGPKG_HAL + doc ref/hal-m68k-arch.html hardware - include_dir cyg/hal - define_header hal_m68k.h description " - The m68k architecture HAL package provides generic - support for this processor architecture. It is also - necessary to select a specific target platform HAL - package." + The m68k architecture HAL package provides generic + support for 68000 and ColdFire processors." + + include_dir cyg/hal + compile hal_m68k.c hal_arch.S m68k_stub.c + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_m68k.h>" + } + make { + <PREFIX>/lib/vectors.o : <PACKAGE>/src/vectors.S + $(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(ACTUAL_CFLAGS) -c -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 vectors.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm vectors.tmp + } - cdl_interface CYGINT_HAL_M68K_VARIANT { - display "Number of variant implementations in this configuration" - requires 1 == CYGINT_HAL_M68K_VARIANT + # callgraph profiling, i.e. compiling with -pg, is supported. However + # -pg is incompatible with -fomit-frame-pointer + implements CYGINT_PROFILE_HAL_MCOUNT + requires { ! (is_substr(CYGBLD_GLOBAL_CFLAGS, " -pg") && is_substr(CYGBLD_GLOBAL_CFLAGS, "-fomit-frame-pointer")) } + + cdl_option CYGNUM_HAL_DEFAULT_INTERRUPT_STACK_SIZE { + display "Default size for the startup and interrupt stack" + description " + The M68K HAL uses a single stack for system startup and for handling + interrupts and exceptions. The size of this stack is configurable via + the common HAL's CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE option, but + this architectural HAL provides a default value." + flavor data + calculated { is_enabled(CYGNUM_HAL_M68K_PLATFORM_DEFAULT_INTERRUPT_STACK_SIZE) ? + CYGNUM_HAL_M68K_PLATFORM_DEFAULT_INTERRUPT_STACK_SIZE : + (CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING ? 4096 : 2048) } } - compile hal_startup.c hal_misc.c m68k_stub.c hal_arch.S + cdl_option CYGNUM_HAL_M68K_STARTUP_STACK_SIZE { + display "Stack size to use during startup" + active_if !CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + flavor data + default_value 2048 + description " + By default eCos runs with a separate interrupt stack, which also gets + used during system startup. This saves memory because it is not necessary + to allow for interrupt overheads on every thread stack, but adds a number + of instructions to the interrupt processing code. If the interrupt stack + is disabled then a separate startup stack is needed. That stack will be + used for running system initialization and for running some application + code including cyg_start() and C++ static constructions." + } + + cdl_component CYGPKG_HAL_M68K_VARIANT { + display "Variant details" + flavor none + description " + Various subsystems like the floating point and memory management + units are available on some but not all 68000 processors. Variant + HAL packages will list which of these subsystems are actually + present." + + cdl_interface CYGINT_HAL_M68K_VARIANT_TYPES { + display "Data types" + flavor bool + description " + This interface will be implemented if the specific processor + being used requires non-default data type definitions." + } + + cdl_interface CYGINT_HAL_M68K_VARIANT_FPU { + display "Floating point unit" + flavor bool + description " + This interface will be implemented if the specific processor + being used has floating point hardware." + } - make { - <PREFIX>/lib/target.ld: <PACKAGE>/src/m68k.ld - $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $< - @echo $@ ": \\" > $(notdir $@).deps - @tail -n +2 target.tmp >> $(notdir $@).deps - @echo >> $(notdir $@).deps - @rm target.tmp + if { 0 } { + # No MMU support available yet + cdl_interface CYGINT_HAL_M68K_VARIANT_MMU { + display "Floating point unit" + flavor bool + description " + This interface will be implemented if the specific processor + being used has a memory management unit." + } + } + + cdl_interface CYGINT_HAL_M68K_VARIANT_CACHE { + display "Cache" + flavor bool + description " + This interface will be implemented if the specific processor + being used has an instruction cache, a data cache, or both." + } + + cdl_interface CYGINT_HAL_M68K_VARIANT_IRAM { + display "On-chip RAM" + flavor bool + description " + This interface will be implemented if the specific processor + being used has on-chip RAM." + } + + cdl_interface CYGINT_HAL_M68K_USE_STANDARD_PLATFORM_STUB_SUPPORT { + display "Use standard platform gdb stub support" + flavor bool + make -priority 1 { + <PREFIX>/include/cyg/hal/plf_stub.h : <PACKAGE>/src/plf_stub.h + @cp $< $@ + } + description " + For platforms where target-side gdb stub support may be used the + platform HAL is expected to provide a header file <cyg/hal/plf_stub.h>. + In practice the same header file is applicable to nearly all platforms + so the M68K architectural HAL will provide this header when the platform + HAL requests this interface." + } } - cdl_option CYGBLD_LINKER_SCRIPT { - display "Linker script" - flavor data - no_define - calculated { "src/m68k.ld" } + cdl_component CYGPKG_HAL_M68K_FPU { + display "Support for the floating point unit" + active_if CYGINT_HAL_M68K_VARIANT_FPU + flavor none + description " + If the target processor has a hardware floating point unit then + this component defines additional configuration options related + to that unit." + + cdl_option CYGIMP_HAL_M68K_FPU_SAVE { + display "Save FPU state during context switch" + default_value 1 + description " + By default the floating point context gets saved during a + context switch. This can be suppressed if the application + does not actually perform any floating point arithmetic, or + if it only does so from one thread." + } + + cdl_option CYGNUM_HAL_M68K_FPU_CR_DEFAULT { + display "Default value for the FPU control register" + flavor data + default_value 0 + legal_values 0 to 0x0FFFF + description " + The FPU control register controls rounding modes, precision, + and exceptions. The default value of 0 gives IEE754 standard + behaviour. It is assumed that the control register's value is + not changed while the system is running, and hence does not + have to be saved or restored during a thread switch or when + an interrupt happens." + } } + cdl_component CYGPKG_HAL_M68K_OPTIONS { + display "Architectural HAL build options" + flavor none + description " + Package-specific build options including control over compiler + flags used only when building this package, and details of which + tests are built." + + cdl_option CYGPKG_HAL_M68K_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for building + the architectural HAL package. These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_HAL_M68K_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for building + the architectural HAL package. These flags are removed from + the set of global flags if present." + } + + cdl_option CYGPKG_HAL_M68K_TESTS { + display "Architectural HAL tests" + flavor data + no_define + calculated { (CYGINT_HAL_M68K_VARIANT_IRAM ? "tests/iram1" : "") . + "" + } + description " + This option specifies the set of tests for the M68K architectural HAL." + } + + cdl_option CYGBLD_LINKER_SCRIPT { + display "Linker script" + flavor data + no_define + calculated { "src/m68k.ld" } + make { + <PREFIX>/lib/target.ld: <PACKAGE>/src/m68k.ld + $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(ACTUAL_CFLAGS) -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 target.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm target.tmp + } + } + } }
new file mode 100644 --- /dev/null +++ b/packages/hal/m68k/arch/current/doc/m68k.sgml @@ -0,0 +1,878 @@ +<!-- DOCTYPE part PUBLIC "-//OASIS//DTD DocBook V3.1//EN" --> + +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- m68k.sgml --> +<!-- --> +<!-- m68k architectural documentation. --> +<!-- --> +<!-- =============================================================== --> +<!-- ####COPYRIGHTBEGIN#### --> +<!-- --> +<!-- Copyright (C) 2003,2004,2006,2008 --> +<!-- Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- --> +<!-- ####COPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- Author(s): bartv --> +<!-- Contact(s): bartv --> +<!-- Date: 2003/06/04 --> +<!-- Version: 0.01 --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<part id="hal-m68k-arch"><title>M68000 Architectural Support</title> + +<!-- {{{ Overview --> + +<refentry id="m68k"> + <refmeta> + <refentrytitle>Overview</refentrytitle> + </refmeta> + <refnamediv> + <refname>Overview</refname> + <refpurpose>eCos Support for the M68K Family of Processors</refpurpose> + </refnamediv> + + <refsect1 id="m68k-description"><title>Description</title> + <para> +The original Motorola 68000 processor was released in 1979, and +featured the following: + </para> + <itemizedlist> + <listitem><para> +Eight general purpose 32-bit data registers, %D0 to %D7. Seven 32-bit +address registers %A0 to %A6, with %A7 dedicated as the stack pointer. +A 16-bit status register. + </para></listitem> + <listitem><para> +A linear address space, limited to 24-bits because the chip package +only had 24 address pins. Hence the processor could address 16 +megabytes of memory. + </para></listitem> + <listitem><para> +No separate address space for I/O operations. Instead devices are +accessed just like memory via the main address and data buses. + </para></listitem> + <listitem><para> +16-bit external data bus, even though the data registers were 32 bits +wide. + </para></listitem> + <listitem><para> +A CISC variable-length instruction set with no less than 14 different +addressing modes (although of course the terms RISC and CISC were not +yet in common use). + </para></listitem> + <listitem><para> +Separate supervisor and user modes. The processor actually has two +distinct stack pointer registers %A7, and the mode determines which one +gets used. + </para></listitem> + <listitem><para> +An interrupt subsystem with support for vectored and prioritized +interrupts. + </para></listitem> + </itemizedlist> + <para> +The 68000 processor was used in several microcomputers of its time, +including the original Apple Macintosh, the Commodore Amiga, and the +Atari ST. Over the years numerous variants have been developed. The +core instruction set has remained essentially unchanged. Some of the +variants have additional instructions. The development of MMUs led to +changes in exception handling. In more recent variants, notably the +Freescale ColdFire family, some infrequently used instructions and +addressing modes have been removed. + </para> + <itemizedlist> + <listitem><para> +The 68008 reduced the widths of the external data and address buses to +8 bits and 20 bits respectively, giving the processor slow access to +only one megabyte. + </para></listitem> + <listitem><para> +The 68010 (1982) added virtual memory support. + </para></listitem> + <listitem><para> +In the 68020 (1984) both the address and data buses were made 32-bits wide. A +256-byte instruction cache was added, as were some new instructions +and addressing modes. + </para></listitem> + <listitem><para> +The 68030 (1987) included an on-chip mmu and a 256-byte data cache. + </para></listitem> + <listitem><para> +The 68040 (1991) added hardware floating point (previous processors relied on +an external coprocessor or on software emulation). It also had larger +caches and an improved mmu. + </para></listitem> + <listitem><para> +The 68060 (1994) involved an internally very different superscalar +implementation of the architecture, but few changes at the interface +level. It also contained support for power management. + </para></listitem> + <listitem><para> +There have been numerous 683xx variants for embedded use, with +on-chip peripherals like UARTs and timers. The cpu core of these +variants is also known as cpu32. + </para></listitem> + <listitem><para> +The MCFxxxx ColdFire series (1995) resembles a stripped-down 68060, +with some instructions and addressing modes removed to allow for a +much smaller and more efficient implementation. Various hardware units +such as the and FPU and MMU have become optional. + </para></listitem> + </itemizedlist> + + <para> +eCos only provides support for some of these variants, although it +should be possible to add support for additional variants with few or +no changes to the architectural HAL package. + </para> + <para> +The architectural HAL provides support for those features which are +common to all members of the 68000 and ColdFire families, and for +certain features which are present on some but not all members. A +typical eCos configuration will also contain: a variant HAL package +with support code for a family of processors, for example MCFxxxx; +possibly a processor HAL package with support for one specific +processor, for example the MCF5272; and a platform HAL +which contains the code needed for a specific hardware platform such +as the m5272c3. + </para> + </refsect1> +</refentry> + +<!-- }}} --> +<!-- {{{ Configuration --> + +<refentry id="m68k-configuration"> + <refmeta> + <refentrytitle>Configuration</refentrytitle> + </refmeta> + <refnamediv> + <refname>Options</refname> + <refpurpose>Configuring the M68K Architectural Package</refpurpose> + </refnamediv> + + <refsect1 id="m68k-config-load"><title>Loading and Unloading the Package</title> + <para> +The M68K architectural HAL package <varname>CYGPKG_HAL_M68K</varname> +should be loaded automatically when eCos is configured for M68K-based +target hardware. It should never be necessary to load this package +explicitly. Unloading the package should only happen as a side effect +of switching target hardware. <varname>CYGPKG_HAL_M68K</varname> +serves primarily as a container for lower-level HALs and has only a +small number of configuration options. + </para> + </refsect1> + + <refsect1 id="m68k-config-stacks"><title>Stacks</title> + <para> +By default the architectural HAL provides a single block of memory to +act as both the startup stack and the interrupt stack. The variant, +processor or platform HAL may override this. For example if there are +several banks of RAM with different performance characteristics it may +be desirable to place the interrupt stack in fast RAM rather than in +ordinary RAM. + </para> + <para> +The assembler startup code sets the stack pointer to the startup stack +before switching to C code. This stack used for all HAL +initialization, running any C++ static constructors defined either by +eCos or by the application, and the <function>cyg_start</function> +entry point. In configurations containing the eCos kernel +<function>cyg_start</function> will enable interrupts, activate the +scheduler and threads will then run on their own stacks. In non-kernel +single-threaded applications the whole system continues to run on the +startup stack. + </para> + <para> +When an interrupt occurs the default behaviour is to switch to a +separate interrupt stack. This behaviour is controlled by the common +HAL configuration option +<varname>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</varname>. +It reduces the stack requirements of all threads in the system, at the +cost of some extra instructions during interrupt handling. In kernel +configurations the startup stack is no longer used once the scheduler +starts running so its memory can be reused for the interrupt stack. To +handle the possibility of nested interrupts the interrupt handling +code will detect if it is already on the interrupt stack, so in +non-kernel configurations it is also safe to use the same area of +memory for both startup and interrupt stacks. This leads to the +following scenarios: + </para> + <orderedlist> + <listitem><para> +If interrupt stacks are enabled via +<varname>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</varname> +and the interrupt stack is not provided by the variant, processor or +platform HAL then a single block of memory will be used for both +startup and interrupt stacks. The size of this block is determined by +the common HAL configuration option +<varname>CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE</varname>, with a +default value +<varname>CYGNUM_HAL_DEFAULT_INTERRUPT_STACK_SIZE</varname> provided by +the M68K architectural HAL. + </para></listitem> + <listitem><para> +If the use of an interrupt stack is disabled then the M68K +architectural HAL will provide just the startup stack, unless this is +done by the variant, processor or platform HAL. The size of the +startup stack is controlled by +<varname>CYGNUM_HAL_M68K_STARTUP_STACK_SIZE</varname>. + </para></listitem> + <listitem><para> +Otherwise the interrupt and/or startup stacks are provided by other +packages and it is up to those packages to provide configuration +options for setting the sizes. + </para></listitem> + </orderedlist> + </refsect1> + + <refsect1 id="m68k-config-fpu"><title>Floating Point Support</title> + <para> +There are many variants of the basic M68K architecture. Some of these +have hardware floating point support. Originally this came in the form +of a separate 68881 coprocessor, but with modern variants it will be +part of the main processor chip. If the processor does not have +hardware floating point then software emulation will be used instead. + </para> + <para> +If the processor on the target hardware has a floating point unit then +the variant or processor HAL will implement the CDL interface +<varname>CYGINT_HAL_M68K_VARIANT_FPU</varname>. This allows the +architectural HAL and other packages to do the right thing on +different hardware. + </para> + <para> +Saving and restoring hardware floating point context increases +interrupt and dispatch latency, code size, and data size. If the +application does not actually use floating point then these overheads +are unnecessary, and can be suppressed by disabling the configuration +option <varname>CYGIMP_HAL_M68K_FPU_SAVE</varname>. Some applications +do use floating point but only in one thread. In that scenario it is +also unnecessary to save the floating point context during interrupts +and context switches, so the configuration option can be disabled. + </para> + <para> +The exact behaviour of the hardware floating point unit is determined +by the floating point control register <varname>%fpcr</varname>. By +default this is initialized to 0, giving IEE754 standard behaviour, +but another initial value can be specified using the configuration +option <varname>CYGNUM_HAL_M68K_FPU_CR_DEFAULT</varname>. For details +of the various bits in this control register see appropriate hardware +documentation. eCos assumes that the control register does not change +on a per-thread basis and hence the register is not saved or restored +during interrupt handling or a context switch. + </para> + <warning> + <para> +At the time of writing eCos has not run on an M68K processor with +hardware floating point so the support for this is untested. + </para> + </warning> + </refsect1> + + <refsect1 id="m68k-config-other"><title>Other Options</title> + <para> +There are configuration options to change the compiler flags used for +building this packages. +The M68K architectural HAL package does not define any other +configuration options that can be manipulated by the user. It does +define a number of interfaces such as +<varname>CYGINT_HAL_M68K_USE_STANDARD_PLATFORM_STUB_SUPPORT</varname> +which can be used by lower levels of the M68K HAL hierarchy to enable +certain functionality within the architectural package. Usually these +are of no interest to application developers. + </para> + </refsect1> +</refentry> + +<!-- }}} --> +<!-- {{{ HAL Porting Details --> + +<refentry id="m68k-port"> + <refmeta> + <refentrytitle>The HAL Port</refentrytitle> + </refmeta> + <refnamediv> + <refname>HAL Port</refname> + <refpurpose>Implementation Details</refpurpose> + </refnamediv> + + <refsect1 id="m68k-port-description"><title>Description</title> + <para> +This documentation explains how the eCos HAL specification has been +mapped onto M68K hardware, and should be read in conjunction with +that specification. It also describes how variant, processor and +platform HALs can modify the default behaviour. + </para> + <para> +eCos support for any given target will involve either three or four +HAL packages: the architectural HAL, the platform HAL, the variant +HAL, and optionally a processor HAL. This package, the architectural +HAL, provides code and definitions that are applicable to all M68K +processors. The platform HAL provides support for one specific +board, for example an M5272C3 evaluation board, or possibly for a +number of almost-identical boards. The processor HAL, if present, +serves mainly to provide details of on-chip peripherals including the +interrupt controller. The variant HAL provides functionality that is +common to a group of processors, for example all MCFxxxx processors +have very similar UARTs and hence can share HAL diagnostic code. +There is no fixed specification of what should go into the variant HAL +versus the processor HAL. For simplicity the description below only +refers to variant HALs, but the work may actually happen in a +processor HAL instead. + </para> + <para> +As a design goal lower-level HALs can always override functionality +that is normally provided higher up. For example the architectural HAL +will provide the required eCos <function>HAL_LSBIT_INDEX</function> +and <function>HAL_MSBIT_INDEX</function> macros, but these can be +provided lower down instead. Many but not all ColdFire processors have +the <literal>ff1</literal> and <literal>bitrev</literal> instructions +which allow for a more efficient implementation than the default +architectural ones. In some areas such as handling context switching +the architectural HAL will usually provide the basic functionality but +it may be extended by lower HALs, for example to add support for the +multiply-accumulate units present in certain ColdFire processors. + </para> + <para> +The architectural HAL provides header files <filename +class="headerfile">cyg/hal/hal_arch.h</filename>, <filename +class="headerfile">cyg/hal/hal_intr.h</filename>, <filename +class="headerfile">cyg/hal/hal_cache.h</filename>, <filename +class="headerfile">cyg/hal/hal_io.h</filename> and <filename +class="headerfile">cyg/hal/arch.inc</filename>. These automatically +include an equivalent header file from the variant HAL, for example +<filename class="headerfile">cyg/hal/var_arch.h</filename>. The +variant HAL header will in turn include processor and +platform-specific headers. This means that application developers and +other packages can simply include the architectural HAL headers +without needing to know about variants or platforms. It also allows +the variant and platform HALs to override architectural settings. + </para> + <para> +The port assumes that eCos and application code always runs in +supervisor mode, with full access to all hardware and special +registers. + </para> + + <refsect2 id="m68k-port-types"><title>Data Types</title> + <para> +For eCos purposes all M68K processors are big-endian and 32-bit, so +the default data types in <filename +class="headerfile">cyg/infra/cyg_type.h</filename> are used. Some +variants have external bus widths less than 32-bit, but this does not +affect the architectural HAL. + </para> + <para> +When porting to another variant it is possible to override some or all +of the type definitions. The variant HAL needs to implement the CDL +interface <varname>CYGINT_HAL_M68K_VARIANT_TYPES</varname> and provide +a header file <filename +class="headerfile">cyg/hal/var_basetype.h</filename>. + </para> + </refsect2> + + <refsect2 id="m68k-port-startup"><title>Startup and Exception Vectors</title> + <para> +The conventional bootstrap mechanism involves a table of exception +vectors at the base of memory. The first two words of this table give +the initial program counter and stack pointer. In a typical embedded +system the hardware is arranged such that non-volatile flash memory is +found at location 0x0 so it is the start of flash that contains the +exception vectors and the boot code. The table of exception vectors is +used subsequently for interrupt handling and for hardware exceptions +such as attempts to execute an illegal instruction. There are a number +of common scenarios: + </para> + <orderedlist> + <listitem><para> +On systems with very limited memory flash may remain mapped at +location 0 and the table of exception vectors remains mapped there as +well. The M68K architecture defines the table to have 256 entries and +hence it occupies 1K of memory, but in reality many of the entries are +unused so part of the table may get used for code instead. Since the +whole exception vector table is in read-only memory parts of the eCos +interrupt and exception handling mechanisms have to be statically +initialized and macros like <function>HAL_VSR_SET</function> are not +available. + </para></listitem> + <listitem><para> +As a minor variation of the previous case, flash remains at location 0 +but the table of exception vectors gets remapped elsewhere in the +address space, usually RAM. This allows +<function>HAL_VSR_SET</function> to operate normally but at the cost +of increased memory usage. The exception vector table in flash only +contains two entries, for the initial program counter and stack +pointer. The exception vector table in RAM typically gets initialized +at run-time. + </para></listitem> + <listitem><para> +On systems with more memory it is conventional to rearrange the +address map during bootstrap. The flash gets relocated, typically to +near the end of the address space, and RAM gets placed at location 0 +instead. The exception vector table stays at location 0 but is now in +RAM and gets initialized at run-time. The bootstrap exception vector +table in flash again only needs two entries. A variation places the +RAM elsewhere in the address space and moves the exception vector +table there, leaving location 0 unused. This provides some protection +against null pointer accesses in errant code. + </para> + <para> +As a further complication, larger systems typically support different +startup types. The application can be linked against a ROM startup +configuration and placed directly in flash, as before. Alternatively +there may be a ROM monitor such as RedBoot in the flash, taking care +of initial bootstrap. The user's application is linked against a RAM +startup configuration, loaded into RAM via the ROM monitor, and +debugged using functionality provided by the ROM monitor. Yet another +possibility involves a RAM startup application but it gets loaded and +run via a hardware debug technology such as BDM, and the ROM monitor +is either missing or not used. + </para></listitem> + </orderedlist> + <para> +The exact hardware details, the various startup types, the steps +needed for low-level hardware initialization, and so on are not known +to the architectural HAL. Hence although the architectural HAL does +provide the basic framework for startup, much of the work is done via +macros provided by lower-level HAL packages and those macros are +likely to depend on various configuration options. Rather than try to +enumerate all the various combinations here it is better to look at +the actual code in <filename>vectors.S</filename> and in appropriate +variant, processor or platform HALs. <filename>vectors.S</filename> is +responsible for any low-level initialization that needs to happen. +This includes setting up a standard C environment with the stack +pointer set to the startup stack in working RAM, making sure all +statically initialized global variables have the correct values, and +that all uninitialized global variables are zeroed. Once the C +environment has been set up the code jumps to +<function>hal_m68k_c_startup</function> in file +<filename>hal_m68k.c</filename> which completes the initialization and +jumps to the application entry point. + </para> + </refsect2> + + <refsect2 id="m68k-port-interrupts"><title>Interrupt Handling</title> + <para> +The M68K architecture reserves a 1K area of memory for 256 exception +vectors. These are used for internal and external interrupts, +exceptions, software traps, and special operations such as reset +handling. Some of the vectors have well-defined uses. However when it +comes to interrupt handling the details will depend on the processor +variant and on the platform, and the appropriate package documentation +should be consulted for full details. Most platforms will not use the +full set of 256 vectors, instead re-using some of this memory for +other purposes. + </para> + <para> +By default the exception vectors are located at location 0, but some +variants allow the vectors to be located elsewhere. This is managed by +an M68K-specific macro <varname>CYG_HAL_VSR_TABLE</varname>. The +default value is 0, but a variant HAL can provide an alternative value. + </para> + <para> +The standard eCos macros <function>HAL_VSR_GET</function> and +<function>HAL_VSR_SET</function> just manipulate one of the 256 +entries in the table of exception vectors. Hence it is usually +possible to replace the default handlers for exceptions and traps in +addition to interrupt handlers. +<filename class="headerfile">hal_intr.h</filename> +provides <literal>#define</literal>'s for the more common exception +vectors, and additional ones can be provided by the platform or +variant. It is the responsibility of the platform or variant HAL to +initialize the table, and to provide the +<function>HAL_VSR_SET_TO_ECOS_HANDLER</function> macro since that +requires knowledge of the default table entries. + </para> + <para> +It should be noted that in some configurations the table of exception +vectors may reside in read-only memory so entries cannot be changed. +If so then the <function>HAL_VSR_SET</function> and +<function>HAL_VSR_SET_TO_ECOS_HANDLER</function> macros will not be +defined. Portable code may need to consider this possibility and test +for the existence of these macros before using them. + </para> + <para> +The architectural HAL provides an entry point +<function>hal_m68k_interrupt_vsr</function> in the file +<filename>hal_arch.S</filename>. When an interrupt occurs the original +68000 pushed the program counter and the status register on to the +stack, and then called the VSR via the exception table. On newer +variants some additional information is pushed, including details of +the interrupt source. <function>hal_m68k_interrupt_vsr</function> +assumes the latter and can be used directly as the VSR on these newer +variants. On older variants a small trampoline is needed which pushes +the additional information and then jumps to the generic VSR. +Interpreting the additional information is handled via an assembler +macro <function>hal_context_extract_isr_vector_shl2</function> +which should be defined by the variant, matching the behaviour of the +hardware or the trampoline. + </para> + <para> +At the architecture level there is no fixed mapping between VSR and +ISR vectors. Instead that is left to the variant or platform HAL. The +architectural HAL does provide default implementations of +<function>HAL_INTERRUPT_ATTACH</function>, +<function>HAL_INTERRUPT_DETACH</function> and +<function>HAL_INTERRUPT_IN_USE</function> since these just involve +updating a static table. + </para> + <para> +By default the interrupt state control macros +<function>HAL_DISABLE_INTERRUPTS</function>, +<function>HAL_RESTORE_INTERRUPTS</function>, +<function>HAL_ENABLE_INTERRUPTS</function> and +<function>HAL_QUERY_INTERRUPTS</function> are implemented by the +architectural HAL, and simply involve updating the status register. +Disabling interrupts involves setting the three IPL bits to 0x07. +Enabling interrupts involves setting those bits to a smaller value, +<varname>CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL</varname>, which +defaults to 0. + </para> + <para> +<function>HAL_DISABLE_INTERRUPTS</function> has no effect on +non-maskable interrupts. This causes a problem because parts of the +system assume that all normal interrupt sources are affected by this +macro. If the target hardware can raise non-maskable interrupts then +it is the responsibility of application code to install a suitable VSR +and handle non-maskable interrupts entirely within the application, +bypassing the usual eCos ISR and DSR mechanisms. + </para> + <para> +The architectural HAL does not provide any support for the interrupt +controller management macros like +<function>HAL_INTERRUPT_MASK</function>. These can only be implemented +on a per-variant, per-processor or per-platform basis. + </para> + </refsect2> + + <refsect2 id="m68k-port-exceptions"><title>Exception Handling</title> + <para> +Synchronous exception handling is done in much the same way as +interrupt handling. The architectural HAL provides a generic entry +point <function>hal_m68k_exception_vsr</function>. On some variants +this can be used directly as the exception VSR, on others it will be +called via a small trampoline. + </para> + <para> +The details of exception handling vary widely from one variant to the +next. Some variants push a great deal of additional information on to +the stack for certain exceptions, but not all. The pushed program +counter may correspond to the specific instruction that caused the +exception, or the next instruction, or there may be only a loose +correlation because of buffered writes. The architectural HAL makes no +attempt to cope with all these differences, although some variants may +provide more advanced support. Otherwise if an exception needs to be +handled in a very specific way then it is up to the application to +install a suitable VSR and handle the exception directly. + </para> + </refsect2> + + <refsect2 id="m68k-port-stacks"><title>Stacks and Stack Sizes</title> + <para> +<filename class="headerfile">cyg/hal/hal_arch.h</filename> defines +values for minimal and recommended thread stack sizes, +<varname>CYGNUM_HAL_STACK_SIZE_MINIMUM</varname> and +<varname>CYGNUM_HAL_STACK_SIZE_TYPICAL</varname>. These values are +specific to the current configuration, and are affected mainly by +options related to interrupt handling. + </para> + <para> +By default eCos uses a separate interrupt stack, although this can be +disabled through the configuration option +<varname>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</varname>. +When an interrupt or exception occurs eCos will save the context on +the current stack and then switch to the interrupt stack before +calling the appropriate ISR interrupt handler. This means that thread +stacks can be significantly smaller because there is no need to worry +about interrupt handling overheads, just the thread context. However +switching the stack does require some extra work and hence increases +the interrupt latency. Disabling the interrupt stack removes this +processing overhead but requires larger stack sizes. It depends on +the application whether or not this is a sensible trade off. + </para> + <para> +By default eCos does not allow nested interrupts, but this can be +controlled via the configuration option +<varname>CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING</varname>. +Supporting nested interrupts requires larger thread stacks, especially +if the separate interrupt stack is also disabled. + </para> + <para> +Although the M68K has enough registers for typical operation, the +calling conventions are memory-oriented. In particular all arguments +are pushed on the stack rather than held in registers, and the return +address is also pushed rather than ending up in a link register. To +allow for this the recommended minimum stack sizes are a little bit +larger than for some other architectures. Variant HALs cannot directly +affect these stack sizes. However the sizes do depend in part on the +size of a thread context, so if for example the processor supports +hardware floating point and support for that is enabled then the stack +sizes will increase. + </para> + <para> +Usually the M68K architectural HAL will provide a single block of +memory which acts as both the startup and interrupt stack, and there +are <link linkend="m68k-config-stacks">configuration options</link> to +control the size of this block. Alternatively a variant, processor or +platform HAL may define either or both of +<varname>_HAL_M68K_STARTUP_STACK_</varname> and +<varname>_HAL_M68K_INTERRUPT_STACK_BASE_</varname> if for some reason +the stacks should not be placed in ordinary RAM. + </para> + </refsect2> + + <refsect2 id="m68k-port-context"><title>Thread Contexts and Setjmp/Longjmp</title> + <para> +A typical thread context consists of the following: + </para> + <orderedlist> + <listitem><para> +The integer context. This consists of the data registers +<varname>%d0</varname> to <varname>%d7</varname> and the address +registers <varname>%a0</varname> to <varname>%a6</varname>, The stack +pointer register <varname>%a7</varname> does not have to be saved +explicitly since it is implicit in the pointer to the saved context. + </para> + <para> +The caller-save registers are <varname>%d0</varname>, +<varname>%d1</varname>, <varname>%a0</varname>, +<varname>%a1</varname>, <varname>%a7</varname> and the status +register. The remaining registers are callee-save. Function arguments +are always passed on the stack. The result is held in +<varname>%d0</varname>. + </para></listitem> + <listitem><para> +Floating point context, consisting of eight 64-bit floating point +registers <varname>%fp0</varname> to <varname>%fp7</varname> and two +support registers <varname>%fpsr</varname> and +<varname>%fpiar</varname>. Support for this is only relevant if the +processor variant has a hardware floating point unit, and even then +saving floating point context is optional and can be disabled using a +configuration option <varname>CYGIMP_HAL_M68K_FPU_SAVE</varname>. The +control register <varname>%fpcr</varname> is not saved as part of the +context. It is assumed that a single <varname>%fpcr</varname> value, +usually <literal>0</literal>, will be used throughout the application. + </para> + <para> +The architectural HAL provides support for the hardware floating point +unit. The variant or processor HAL should implement the CDL interface +<varname>CYGINT_HAL_M68K_VARIANT_FPU</varname> if this hardware unit +is actually present. + </para></listitem> + <listitem><para> +Some M68K variants have additional hardware units, for example the +multiply-accumulate units in certain ColdFire processors. The +architectural HAL allows the context to be extended through various +macros such as <varname>HAL_CONTEXT_OTHER</varname>. + </para></listitem> + <listitem><para> +The status register <varname>%sr</varname> and the program counter. +These are special because when an interrupt occurs the hardware +automatically pushes these onto the stack, but exactly what gets +pushed depends on the variant. + </para></listitem> + </orderedlist> + <para> +<function>setjmp</function> and <function>longjmp</function> only deal +with the integer and fpu contexts. It is assumed that any special +hardware units will only be used by application code, not by the +compiler. Hence it is the responsibility of application code to +define and implement appropriate setjmp semantics for these units. +The variant HAL package can override the default implementations if +necessary. + </para> + <para> +When porting to a new M68K variant, if this has a hardware floating +point unit then the variant HAL should implement the CDL interface +<varname>CYGINT_HAL_M68K_VARIANT_FPU</varname>, thus enabling support +provided by the architectural HAL. If the variant has additional +hardware units involving state that should be preserved during a +context switch or when an interrupt occurs, the variant HAL should +define a number of macros. The header file <filename +class="headerfile">cyg/hal/var_arch.h</filename> should define +<varname>HAL_CONTEXT_OTHER</varname>, +<varname>HAL_CONTEXT_OTHER_SIZE</varname>, and +<varname>HAL_CONTEXT_OTHER_INIT</varname>, either directly or via +<filename class="headerfile">cyg/hal/proc_arch.h</filename>. The +assembler header file <filename +class="headerfile">cyg/hal/var.inc</filename> should define a number +of macros such as <function>hal_context_other_save_caller</function>. +For details of these macros see the architectural +<filename>hal_arch.S</filename> file. + </para> + <para> +Variants also need to define exactly how the status register and +program counter are saved onto the stack when an interrupt or +exception occurs. This is handled through C macros +<varname>HAL_CONTEXT_PCSR_SIZE</varname>, +<varname>HAL_CONTEXT_PCSR_RTE_ADJUST</varname>, and +<function>HAL_CONTEXT_PCSR_INIT</function>, and a number of assembler +macros such as <function>hal_context_pcsr_save_sr</function>. Again +the architectural files <filename +class="headerfile">cyg/hal/hal_arch.h</filename> and +<filename>hal_arch.S</filename> provide more details of these. + </para> + </refsect2> + + <refsect2 id="m68k-port-bitindex"><title>Bit Indexing</title> + <para> +For performance reasons the <function>HAL_LSBIT_INDEX</function> and +<function>HAL_MSBIT_INDEX</function> macros are implemented using +assembler functions. A variant HAL can override the default +definitions if, for example, the variant has special instructions to +perform these operations. + </para> + </refsect2> + + <refsect2 id="m68k-port-idle"><title>Idle Thread Processing</title> + <para> +The default <function>HAL_IDLE_THREAD_ACTION</function> implementation +is a no-op. A variant HAL may override this, for example to put the +processor into sleep mode. Alternative implementations should consider +exactly how this macro gets used in eCos kernel code. + </para> + </refsect2> + + <refsect2 id="m68k-port-clock"><title>Clock Support</title> + <para> +The architectural HAL cannot provide the required clock support +because it does not know what timer hardware may be available on the +target hardware. Instead this is left to either the variant or +platform HAL, depending on whether the processor has a suitable +on-chip timer or whether an off-chip timer has to be used. + </para> + </refsect2> + + <refsect2 id="m68k-port-io"><title>HAL I/O</title> + <para> +The M68K architecture does not have a separate I/O bus. Instead all +hardware is assumed to be memory-mapped. Further it is assumed that +all peripherals on the memory bus are wired appropriately for a +big-endian processor and that there is no need for any byte swapping. +Hence the various HAL macros for performing I/O simply involve +pointers to volatile memory. + </para> + <para> +The variant, processor and platform equivalents of the <filename +class="headerfile">cyg/hal/hal_io.h</filename> header will typically +also provide details of some or all of the peripherals, for example +register offsets and the meaning of various bits in those registers. + </para> + </refsect2> + + <refsect2 id="m68k-port-cache"><title>Cache Handling</title> + <para> +If the processor has a cache then the variant HAL should implement the +CDL interface <varname>CYGINT_HAL_M68K_VARIANT_CACHE</varname>. This +causes the architectural header <filename +class="headerfile">cyg/hal/hal_cache.h</filename> to pick up +appropriate definitions from <filename +class="headerfile">cyg/hal/var_cache.h</filename>. The architectural +header will provide null defaults for anything not defined by the +variant. + </para> + </refsect2> + + <refsect2 id="m68k-port-ldscript"><title>Linker Scripts</title> + <para> +The architectural HAL will generate the linker script for eCos +applications. This involves the architectural file +<filename>m68k.ld</filename> and a <filename>.ldi</filename> memory +layout file provided lower down, typically by the platform HAL. It is +the LDI file which specifies the types and amount of memory available +and which places code and data in appropriate places, but most of the +hard work is done via macros provided by the architectural +<filename>m68k.ld</filename> file. + </para> + </refsect2> + + <refsect2 id="m68k-port-diag"><title>Diagnostic Support</title> + <para> +The architectural HAL does not implement diagnostic support. Instead +this is left to the variant or platform HAL, depending on whether +suitable peripherals are available on-chip or off-chip. + </para> + </refsect2> + + <refsect2 id="m68k-port-smp"><title>SMP Support</title> + <para> +The M68K port does not have SMP support. + </para> + </refsect2> + + <refsect2 id="m68k-port-gdb"><title>Debug Support</title> + <para> +The M68K architectural HAL package provides basic support only for gdb +stubs. There is no support for more advanced debug features like +hardware watchpoints. + </para> + <para> +The generic gdb support in the common HAL requires a platform header +<filename class="headerfile"><cyg/hal/plf_stub.h</filename>. In +practice there is rarely any need for the contents of this file to +change between platforms so the architectural HAL can provide a +suitable default. It will do so if the CDL interface +<varname>CYGINT_HAL_M68K_USE_STANDARD_PLATFORM_STUB_SUPPORT</varname> +is implemented. + </para> + </refsect2> + + <refsect2 id="m68k-port-delay"><title>HAL_DELAY_US Macro</title> + <para> +The architectural HAL provides a default implementation of the +standard <function>HAL_DELAY_US</function> macro using a simply busy +loop. To use this support a lower-level HAL should define +<varname>_HAL_M68K_DELAY_US_LOOPS_</varname>, typically a small number +of about 20 but it will need to be calibrated during the porting +process. If the processor has a cache then the lower-level HAL may +also define <varname>_HAL_M68K_DELAY_US_LOOPS_UNCACHED_</varname> for +the case when a delay loop is triggered while the cache is disabled. + </para> + </refsect2> + + <refsect2 id="m68k-port-profiling"><title>Profiling Support</title> + <para> +The M68K architectural HAL implements the <function>mcount</function> +function, allowing profiling tools like +<application>gprof</application> to determine the application's call +graph. It does not implement the profiling timer. Instead that +functionality needs to be provided by the variant or platform HAL. +The implementation of <function>mcount</function> requires a dedicated +frame pointer register so code should be compiled without the +<option>-fomit-frame-pointer</option> flag. + </para> + </refsect2> + + <refsect2 id="m68k-port-other"><title>Other Functionality</title> + <para> +The M68K architectural HAL only implements the functionality provided +by the eCos HAL specification and does not export any extra +functionality. + </para> + </refsect2> + + </refsect1> + +</refentry> + +<!-- }}} --> + +</part>
new file mode 100644 --- /dev/null +++ b/packages/hal/m68k/arch/current/include/arch.inc @@ -0,0 +1,86 @@ +##============================================================================= +## +## arch.inc +## +## M68K architecture assembler header file +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2003,2006,2008 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +##============================================================================= +#######DESCRIPTIONBEGIN#### +## +## Author(s): bartv +## Date: 2003-06-04 +######DESCRIPTIONEND#### +##============================================================================= + +#include <pkgconf/hal.h> +#include <cyg/hal/var.inc> + +// ---------------------------------------------------------------------------- +// Utility macros for defining normal and weak functions. + +#define FUNC_START(name) \ + .section .text. ## name ; \ + .balign 4 ; \ + .globl name ; \ + .type name, @function ; \ +name: + +#define FUNC_START_WEAK(name) \ + .section .text._ ## name ; \ + .weak name ; \ + .set name, _ ## name ; \ + .balign 4 ; \ + .globl _ ## name ; \ + .type name, @function ; \ +_ ## name: + +// ---------------------------------------------------------------------------- +// Default system and interrupt stack. This is used only if the +// platform HAL has not already supplied suitable stacks. + +#ifndef _HAL_M68K_STARTUP_STACK_ + .extern _hal_m68k_startup_stack_base_ + .extern _hal_m68k_startup_stack_ +# define _HAL_M68K_STARTUP_STACK_ # _hal_m68k_startup_stack_ +# define _HAL_M68K_INSTANTIATE_STARTUP_STACK_ +#endif +#ifndef _HAL_M68K_INTERRUPT_STACK_BASE_ + .extern _hal_m68k_interrupt_stack_base_ + .extern _hal_m68k_interrupt_stack_ +# define _HAL_M68K_INTERRUPT_STACK_BASE_ # _hal_m68k_interrupt_stack_base_ +# define _HAL_M68K_INTERRUPT_STACK_ # _hal_m68k_interrupt_stack_ +# define _HAL_M68K_INSTANTIATE_INTERRUPT_STACK_ +#endif + +#------------------------------------------------------------------------------ +# end of arch.inc
--- a/packages/hal/m68k/arch/current/include/basetype.h +++ b/packages/hal/m68k/arch/current/include/basetype.h @@ -8,11 +8,10 @@ // Standard types for this architecture. // //============================================================================= -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -35,30 +34,32 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //============================================================================= +//####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +//####DESCRIPTIONEND#### +//============================================================================= -// Include variant specific types. -#include <cyg/hal/var_basetype.h> - -// Include the standard variable sizes. -#include <cyg/hal/gen_types.h> +#include <pkgconf/hal_m68k.h> +#ifdef CYGINT_HAL_M68K_VARIANT_TYPES +# include <cyg/hal/var_basetype.h> +#endif //----------------------------------------------------------------------------- -// Characterize the architecture - -#define CYG_BYTEORDER CYG_MSBFIRST // Big endian +// Characterize the architecture: big-endian +#ifndef CYG_BYTEORDER +# define CYG_BYTEORDER CYG_MSBFIRST +#endif //----------------------------------------------------------------------------- -// 68k does not usually use labels with underscores. Some labels generated -// by the linker do, so add an underscore where required. +// 68k does not usually use labels with underscores. +#define CYG_LABEL_NAME(_name_) _name_ -#define CYG_LABEL_NAME(_name_) _##_name_ - +// ---------------------------------------------------------------------------- // The 68k architecture uses the default definitions of the base types, // so we do not need to define any here. @@ -67,25 +68,12 @@ // Most 68k variants use a 4 byte alignment. // A few variants (68000) may override this setting to use a 2 byte alignment. #ifndef CYGARC_ALIGNMENT -#define CYGARC_ALIGNMENT 4 +# define CYGARC_ALIGNMENT 4 #endif // the corresponding power of two alignment #ifndef CYGARC_P2ALIGNMENT -#define CYGARC_P2ALIGNMENT 2 -#endif - - -//----------------------------------------------------------------------------- -// Define a compiler-specific rune for saying a function doesn't return - -// WARNING: There is a bug in some versions of gcc for the m68k that does -// not handle the noreturn attribute correctly. It is safe to just disable -// this attribute. - -#ifndef CYGBLD_ATTRIB_NORET -# define CYGBLD_ATTRIB_NORET +# define CYGARC_P2ALIGNMENT 2 #endif //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_BASETYPE_H -
deleted file mode 100644 --- a/packages/hal/m68k/arch/current/include/gen_types.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef _GEN_TYPES_H -#define _GEN_TYPES_H -//========================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with eCos; if not, write to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// As a special exception, if other files instantiate templates or use macros -// or inline functions from this file, or you compile this file and link it -// with other works to produce a work based on this file, this file does not -// by itself cause the resulting work to be covered by the GNU General Public -// License. However the source code for this file must still be made available -// in accordance with section (3) of the GNU General Public License. -// -// This exception does not invalidate any other reasons why a work based on -// this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ -// ------------------------------------------- -//####ECOSGPLCOPYRIGHTEND#### -//========================================================================== - -/***************************************************************************** - - ********************* - * * - * General Types * - * * - ********************* - - Define some simple variable sizes for this platform. - - Note that these types are useful for making user threads that are -not eCos-specific. - -*****************************************************************************/ - -// Include some architecture variant specific types. - -#include <cyg/hal/var_gen_types.h> - -// Define types to use for specific sized variables. Note that the above -// include file could have defined some of these types differently. If the -// type is already defined, always use the previous definition. - -#ifndef _GEN_TYPES_I8_T -#define _GEN_TYPES_I8_T char -#endif -#ifndef _GEN_TYPES_I16_T -#define _GEN_TYPES_I16_T short -#endif -#ifndef _GEN_TYPES_I32_T -#define _GEN_TYPES_I32_T int -#endif -#ifndef _GEN_TYPES_I64_T -#define _GEN_TYPES_I64_T long long -#endif -#ifndef _GEN_TYPES_S8_T -#define _GEN_TYPES_S8_T signed _GEN_TYPES_I8_T -#endif -#ifndef _GEN_TYPES_S16_T -#define _GEN_TYPES_S16_T signed _GEN_TYPES_I16_T -#endif -#ifndef _GEN_TYPES_S32_T -#define _GEN_TYPES_S32_T signed _GEN_TYPES_I32_T -#endif -#ifndef _GEN_TYPES_S64_T -#define _GEN_TYPES_S64_T signed _GEN_TYPES_I64_T -#endif -#ifndef _GEN_TYPES_U8_T -#define _GEN_TYPES_U8_T unsigned _GEN_TYPES_I8_T -#endif -#ifndef _GEN_TYPES_U16_T -#define _GEN_TYPES_U16_T unsigned _GEN_TYPES_I16_T -#endif -#ifndef _GEN_TYPES_U32_T -#define _GEN_TYPES_U32_T unsigned _GEN_TYPES_I32_T -#endif -#ifndef _GEN_TYPES_U64_T -#define _GEN_TYPES_U64_T unsigned _GEN_TYPES_I64_T -#endif -#ifndef _GEN_TYPES_ADDR_T -#define _GEN_TYPES_ADDR_T void * -#endif - -typedef _GEN_TYPES_I8_T i8_t; -typedef _GEN_TYPES_I16_T i16_t; -typedef _GEN_TYPES_I32_T i32_t; -typedef _GEN_TYPES_I64_T i64_t; -typedef _GEN_TYPES_S8_T s8_t; -typedef _GEN_TYPES_S16_T s16_t; -typedef _GEN_TYPES_S32_T s32_t; -typedef _GEN_TYPES_S64_T s64_t; -typedef _GEN_TYPES_U8_T u8_t; -typedef _GEN_TYPES_U16_T u16_t; -typedef _GEN_TYPES_U32_T u32_t; -typedef _GEN_TYPES_U64_T u64_t; -typedef _GEN_TYPES_ADDR_T addr_t; - -// Use int_t and uint_t for fast counter variables. The size of these -// types depends on the architecture but it will always be at least 16 bits. -// For example, 16-bit numbers are faster on the 68000 but 32-bit numbers are -// faster on the mcf5200. If you need to assume the size of the variable use -// u16_t or u32_t instead. - -#ifndef _GEN_TYPES_INT_T -#define _GEN_TYPES_INT_T i32_t -#endif -#ifndef _GEN_TYPES_SINT_T -#define _GEN_TYPES_SINT_T s32_t -#endif -#ifndef _GEN_TYPES_UINT_T -#define _GEN_TYPES_UINT_T u32_t -#endif - -typedef _GEN_TYPES_INT_T int_t; -typedef _GEN_TYPES_SINT_T sint_t; -typedef _GEN_TYPES_UINT_T uint_t; - -#endif // _GEN_TYPES_H -
--- a/packages/hal/m68k/arch/current/include/hal_arch.h +++ b/packages/hal/m68k/arch/current/include/hal_arch.h @@ -8,11 +8,10 @@ // Architecture specific abstractions // //============================================================================= -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2006,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -35,214 +34,327 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //============================================================================= +//####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +//####DESCRIPTIONEND#### +//============================================================================= +#include <pkgconf/system.h> #include <pkgconf/hal.h> +#include <pkgconf/hal_m68k.h> + #include <cyg/infra/cyg_type.h> - -// Include some variant specific architectural defines. #include <cyg/hal/var_arch.h> -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#include <cyg/hal/m68k_stub.h> -#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +// ---------------------------------------------------------------------------- +// The default IPL level for when interrupts are enabled. Usually this will +// be set to 0, but on some platforms it may be appropriate to run with +// a higher IPL level and effectively leave some interrupts disabled. -#ifndef HAL_NORMAL_SAVED_CONTEXT -/***************************************************************************** -HAL_NORMAL_SAVED_CONTEXT -- Saved by a normal context switch +#ifndef CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL +# define CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL 0 +#endif - Define a generic structure to save a thread context. Some -architecture variants will want to redefine this. +// ---------------------------------------------------------------------------- +// setjmp/longjmp support. These only deal with the integer and fpu units. +// If there are other hardware units then they are unlikely to be used +// directly by the compiler, only by application code. Hence it is +// application code that should decide whether or not each unit's state +// should be preserved across setjmp/longjmp boundaries. +// +// Floating point registers have to be saved/restored here even if they +// are not saved during a context switch, because we are concerned +// about state within a single thread. The control and status registers +// are saved as well, but fpiar can be ignored - setjmp() is not going +// to happen while handling a floating point exception. +// +// The default implementation is in assembler and uses weak aliases. That +// code has to be kept in step with this structure definition. -*****************************************************************************/ -typedef struct -{ - - // Data regs D0-D7 - - #define HAL_NORMAL_SAVED_NUM_D_REGS 8 - CYG_WORD32 d[HAL_NORMAL_SAVED_NUM_D_REGS]; +#ifndef HAL_SETJMP +#define HAL_SETJMP - // Address regs A0-A6 +typedef struct { + CYG_ADDRESS pc; + CYG_ADDRESS sp; + cyg_uint32 d[6]; // d2 to d7, d0 and d1 are caller-save + CYG_ADDRESS a[5]; // a2 to a6, a0 and a1 are caller-save, a7 (sp) is separate +#ifdef CYGINT_HAL_M68K_VARIANT_FPU + long double f[6]; // f2 to f7, f0 and f1 are caller-save +#endif +} hal_jmp_buf_t; - #define HAL_NORMAL_SAVED_NUM_A_REGS 7 - CYG_ADDRESS a[HAL_NORMAL_SAVED_NUM_A_REGS]; - - // Program Counter - - CYG_ADDRESS pc; +// This type is used by normal routines to pass the address of the +// structure into our routines without having to explicitly take the +// address of the structure. +typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)]; -} __attribute__ ((aligned, packed)) HAL_SavedRegisters_normal; -#endif // HAL_NORMAL_SAVED_CONTEXT +externC int hal_m68k_setjmp(hal_jmp_buf); +externC void hal_m68k_longjmp(hal_jmp_buf, int); +#define hal_setjmp(_env) hal_m68k_setjmp(_env) +#define hal_longjmp(_env, _val) hal_m68k_longjmp(_env, _val) + +#endif // HAL_SETJMP -#ifndef HAL_GENERIC_SAVED_CONTEXT -/***************************************************************************** -HAL_GENERIC_SAVED_CONTEXT -- Generic saved context structure - - This is a generic structure that should describe various saved -processor contexts on this platform. - - If the variant HAL does not define this, just define a saved register -structure with a normal context. +// ---------------------------------------------------------------------------- +// Thread context support. The implementation is in assembler functions +// rather than inline macros. That makes it easier to cope with +// hardware-specific units which have their own context. +// +// A thread context consists of an integer part, a floating point part +// (iff the hardware has a standard FPU and if the configuration makes +// FPU context part of the save state), and OTHER for extra hardware +// units. -*****************************************************************************/ -#define HAL_GENERIC_SAVED_CONTEXT \ -typedef union \ -{ \ - HAL_SavedRegisters_normal normal; \ -} __attribute__ ((aligned, packed)) HAL_SavedRegisters; -#endif // HAL_GENERIC_SAVED_CONTEXT -HAL_GENERIC_SAVED_CONTEXT; +#define HAL_M68K_SR_C (0x01 << 0) +#define HAL_M68K_SR_V (0x01 << 1) +#define HAL_M68K_SR_Z (0x01 << 2) +#define HAL_M68K_SR_N (0x01 << 3) +#define HAL_M68K_SR_X (0x01 << 4) +#define HAL_M68K_SR_S (0x01 << 13) +#define HAL_M68K_SR_T (0x01 << 15) +#define HAL_M68K_SR_IPL_MASK (0x07 << 8) +#define HAL_M68K_SR_IPL_SHIFT 8 -#ifndef HAL_THREAD_SWITCH_CONTEXT -/***************************************************************************** -HAL_THREAD_SWITCH_CONTEXT +typedef struct { + // The integer context, d0-d7,a0-a6 + cyg_uint32 da[15]; - This macro saves the state of the currently running thread and writes -its stack pointer to *(_fspptr_). - - It then switches to the thread context that *(_tspptr_) points to. + // FPU context. This is only relevant if the hardware has an FPU, + // and then only if the configuration makes the FPU context part + // of the save state. +#ifdef CYGIMP_HAL_M68K_FPU_SAVE + cyg_uint32 fpsr; + CYG_ADDRESS fpiar; + long double f[8]; +#endif -INPUT: - - _fspptr_: A pointer to the location to save the current thread's stack -pointer to. - - _tspptr_: A pointer to the location containing the stack pointer of -the thread context to switch to. + // Some m68k variants may have additional state that should be part + // of a thread context. +#ifdef HAL_CONTEXT_OTHER + HAL_CONTEXT_OTHER +#endif -OUTPUT: - - *(_fspptr_): Contains the stack pointer of the previous thread's -context. + // Program counter, status register, etc. The exact layout is + // determined by the variant. The intention is that the structure + // matches the state pushed onto the stack by the hardware when an + // interrupt occurs, so the context can overlap this part of the + // stack. That avoids having to copy the saved PC and SR registers + // from the stack into the context structure. The final step of + // a context switch is an rte instruction. + HAL_CONTEXT_PCSR + +} HAL_SavedRegisters; -*****************************************************************************/ -#define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \ -CYG_MACRO_START \ - asm volatile (" pea 1f(%%pc)\n" \ - " lea -(8+7)*4(%%sp),%%sp\n" \ - " movem.l %%d0-%%d7/%%a0-%%a6,(%%sp)\n" \ - " move.l %%sp,%0\n" \ - " move.l %1,%%sp\n" \ - " movem.l (%%sp),%%d0-%%d7/%%a0-%%a6\n" \ - " lea (8+7)*4(%%sp),%%sp\n" \ - " rts\n" \ - "1:\n" \ - : "=g" (*(_fspptr_)) \ - : "g" (*(_tspptr_)) \ - : "memory"); \ -CYG_MACRO_END -#if HAL_NORMAL_SAVED_NUM_D_REGS != 8 - #error +#define HAL_CONTEXT_INTEGER_SIZE (15 * 4) +#ifdef CYGIMP_HAL_M68K_FPU_SAVE +# define HAL_CONTEXT_FPU_SIZE ((2 * 4) + (8 * 12)) +#else +# define HAL_CONTEXT_FPU_SIZE 0 +#endif +#ifndef HAL_CONTEXT_OTHER_SIZE +# define HAL_CONTEXT_OTHER_SIZE 0 +#endif +#ifndef HAL_CONTEXT_PCSR_SIZE +# define HAL_CONTEXT_PCSR_SIZE 8 #endif -#if HAL_NORMAL_SAVED_NUM_A_REGS != 7 - #error -#endif -#endif // HAL_THREAD_SWITCH_CONTEXT + +#define HAL_CONTEXT_FULL_SIZE (HAL_CONTEXT_INTEGER_SIZE + HAL_CONTEXT_FPU_SIZE + HAL_CONTEXT_OTHER_SIZE + HAL_CONTEXT_PCSR_SIZE) + +// Load and switch are handled by functions in hal_arch.S. One level +// of indirection is removed here for the destination thread, so that +// the actual stack pointer gets passed to assembler. +externC void hal_thread_load_context(CYG_ADDRESS) CYGBLD_ATTRIB_NORET; +externC void hal_thread_switch_context(CYG_ADDRESS, CYG_ADDRESS); + +#define HAL_THREAD_LOAD_CONTEXT(_to_) \ + CYG_MACRO_START \ + hal_thread_load_context((CYG_ADDRESS) *(_to_)); \ + CYG_MACRO_END + +#define HAL_THREAD_SWITCH_CONTEXT(_from_, _to_) \ + CYG_MACRO_START \ + hal_thread_switch_context((CYG_ADDRESS)(_from_), (CYG_ADDRESS)*(_to_)); \ + CYG_MACRO_END -#ifndef HAL_THREAD_LOAD_CONTEXT -/***************************************************************************** -HAL_THREAD_LOAD_CONTEXT - - This macro loads the thread context that *(_tspptr_) points to. +// Init context can be done easily in C. +// +// LOAD_CONTEXT and SWITCH_CONTEXT will end up doing an rte, so at the top +// of the stack we want the SR, return PC, a dummy PC for the entry point's +// stack frame, and the argument to the function. +// +// +----------------+ +// | _thread_ arg | +// +----------------+ +// | return PC | +// +----------------+ +// | _entry_ PC | +// +- - - - - - - - + +// | SR | +// SP ----> +- - - - - - - - + +// | HAL | +// | SavedRegisters | +// | | +// +// FPU and OTHER contexts are handled by macros which may or may not expand. +// +// The PC/SR fields are handled by variant-specific code. - This macro does not return. - -INPUT: - - _tspptr_: A pointer to the location containing the stack pointer of -the thread context to switch to. +#ifdef CYGIMP_HAL_M68K_FPU_SAVE +# define HAL_CONTEXT_FPU_INIT(_regs_) \ + CYG_MACRO_START \ + int _j_; \ + (_regs_)->fpsr = 0; \ + (_regs_)->fpiar = 0; \ + for (_j_ = 0; _j_ < 8; _j_++) { \ + (_regs_)->f[_j_] = 0.0; \ + } \ + CYG_MACRO_END +#else +# define HAL_CONTEXT_FPU_INIT(_regs_) +#endif +#ifndef HAL_CONTEXT_OTHER_INIT +# define HAL_CONTEXT_OTHER_INIT(_regs_) +#endif -*****************************************************************************/ -#define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \ -CYG_MACRO_START \ - asm volatile (" move.l %0,%%sp\n" \ - " movem.l (%%sp),%%d0-%%d7/%%a0-%%a6\n" \ - " lea (8+7)*4(%%sp),%%sp\n" \ - " rts\n" \ - : \ - : "g" (*(_tspptr_)) \ - : "memory"); \ -CYG_MACRO_END -#if HAL_NORMAL_SAVED_NUM_D_REGS != 8 - #error -#endif -#if HAL_NORMAL_SAVED_NUM_A_REGS != 7 - #error +// Only initialize with ints enabled if CYGPKG_KERNEL. RedBoot does a +// LoadContext, causing interrupts to be enabled prematurely. +#ifdef CYGPKG_KERNEL +# define _HAL_M68K_INIT_CONTEXT_SR_ (0x2000 | (CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL<<8)) +#else +# define _HAL_M68K_INIT_CONTEXT_SR_ (0x2700) #endif -#endif // HAL_THREAD_LOAD_CONTEXT - -#ifndef HAL_THREAD_INIT_CONTEXT -/***************************************************************************** -HAL_THREAD_INIT_CONTEXT -- Context Initialization - - Initialize the context of a thread. -INPUT: - - _sparg_: The name of the variable containing the current sp. This -will be written with the new sp. +#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_) \ + CYG_MACRO_START \ + cyg_uint32* _sp_ = ((cyg_uint32*) ((cyg_uint32)(_sparg_) & ~(CYGARC_ALIGNMENT - 1))); \ + HAL_SavedRegisters* _regs_; \ + int _i_; \ + *(--_sp_) = (cyg_uint32)(_thread_); \ + *(--_sp_) = 0xDEADC0DE; \ + _regs_ = (HAL_SavedRegisters*) ((cyg_uint32)_sp_ - sizeof(HAL_SavedRegisters)); \ + for (_i_ = 0; _i_ < 14; _i_++) { \ + _regs_->da[_i_] = _id_; \ + } \ + _regs_->da[14] = 0; \ + HAL_CONTEXT_FPU_INIT(_regs_) \ + HAL_CONTEXT_OTHER_INIT(_regs_) \ + HAL_CONTEXT_PCSR_INIT(_regs_, _entry_, _HAL_M68K_INIT_CONTEXT_SR_); \ + (_sparg_) = (CYG_ADDRESS) (_regs_); \ + CYG_MACRO_END - _thread_: The thread object address, passed as argument to entry -point. +// ---------------------------------------------------------------------------- +// Minimal and sensible stack sizes: the intention is that applications +// will use these to provide a stack size in the first instance prior to +// proper analysis. Idle thread stack should be this big. +// +// THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. +// THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. +// YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! +// +// This is not a config option because it should not be adjusted except +// under "enough rope" sort of disclaimers. - _entry_: The thread's entry point address. +// Stack frame overhead per call. 6 data registers, 5 address +// registers, frame pointer, and return address. We can't guess the +// local variables so just assume that using all of the registers +// averages out. +# define CYGNUM_HAL_STACK_FRAME_SIZE ((6 + 5 + 1 + 1) * 4) - _id_: A bit pattern used in initializing registers, for debugging. +// Stack needed for a context switch. Allow for sr and vector as well. +#ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE +# define CYGNUM_HAL_STACK_CONTEXT_SIZE HAL_CONTEXT_FULL_SIZE +#endif + +// Interrupt handling. These need to allow for nesting and a +// separate interrupt stack. +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK +# ifndef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING + +// No interrupt stack, no nesting. Worst case: a saved context, a +// frame for the interrupt_end() call, six frames for DSR processing, +// another saved context for an interrupt during the DSRs, and +// six frames for the ISR. +# define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((2 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (13 * CYGNUM_HAL_STACK_FRAME_SIZE)) -OUTPUT: +# else +// No interrupt stack but nesting. Worst case: a saved context, +// a frame for interrupt_end(), six frames for DSR processing, then +// up to five higher priority interrupts each requiring a context +// and six frames. +# define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((6 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (37 * CYGNUM_HAL_STACK_FRAME_SIZE)) +# endif + +#else - _sparg_: Updated with the value of the new sp. +# ifndef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING +// An interrupt stack but no nesting. Worst case: a saved context, +// a frame for interrupt_end(), and another saved context. There +// is no need to worry about ISR or DSR frames since those will +// be on the interrupt stack. We also need to allow for nested +// interrupts before these are disabled, which will involve only +// 2 words rather than a full stack. +# define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((2 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (1 * CYGNUM_HAL_STACK_FRAME_SIZE) + (5 * 2 * 4)) + +# else +// An interrupt stack and nesting. We need to allow for another five +// nested contexts because nested interrupts may happen after pushing +// the current context but before switching to the interrupt stack. +# define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((7 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (1 * CYGNUM_HAL_STACK_FRAME_SIZE)) + +# endif +#endif -*****************************************************************************/ -#define HAL_THREAD_INIT_CONTEXT(_sparg_, _thread_, _entry_, _id_) \ - CYG_MACRO_START \ - CYG_WORD32 * _sp_ = ((CYG_WORD32*)((CYG_WORD32)(_sparg_) & ~15)); \ - HAL_SavedRegisters_normal * _regs_; \ - int _i_; \ - \ - *(--_sp_) = (CYG_WORD32)(_thread_); /* Thread's parameter. */ \ - *(--_sp_) = (CYG_WORD32)0xDEADC0DE; /* Thread's return addr. */ \ - \ - _regs_ = (HAL_SavedRegisters_normal*) \ - ((CYG_WORD32)_sp_ - sizeof(HAL_SavedRegisters_normal)); \ - \ - for (_i_=0; _i_ < HAL_NORMAL_SAVED_NUM_A_REGS; _i_++) \ - _regs_->a[_i_] = _regs_->d[_i_] = (_id_); \ - _regs_->d[_i_] = (_id_); /* D7 */ \ - /* A6, initial frame pointer should be null */ \ - _regs_->a[HAL_NORMAL_SAVED_NUM_A_REGS-1] = (CYG_ADDRESS)0; \ - /* Thread's starting PC */ \ - _regs_->pc = (CYG_ADDRESS)(_entry_); \ - \ - (_sparg_) = (CYG_ADDRESS)_regs_; \ +// We define a minimum stack size as the minimum any thread could ever +// legitimately get away with. We can throw asserts if users ask for +// less than this. This allows for a saved context for context switching +// plus eight stack frames for cals, in addition to the interrupt overhead. +#define CYGNUM_HAL_STACK_SIZE_MINIMUM (CYGNUM_HAL_STACK_INTERRUPT_SIZE + CYGNUM_HAL_STACK_CONTEXT_SIZE + (8 * CYGNUM_HAL_STACK_FRAME_SIZE)) + +// Now make a reasonable choice for a typical thread size. Allow for +// another 8 call frames and a K for on-stack buffers, printf(), +// and debugging overheads. +#define CYGNUM_HAL_STACK_SIZE_TYPICAL (CYGNUM_HAL_STACK_SIZE_MINIMUM + (8 * CYGNUM_HAL_STACK_FRAME_SIZE) + 1024) + +// ----------------------------------------------------------------------------- +// Bit manipulation routines. The vanilla 68000 has no special +// instructions for this so assembler implementations are used +// instead. Newer ColdFires do have suitable instructions so will +// define their own versions of these macro. + +#ifndef HAL_LSBIT_INDEX +externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask); +#define HAL_LSBIT_INDEX(index, mask) (index) = hal_lsbit_index(mask); +#endif +#ifndef HAL_MSBIT_INDEX +externC cyg_uint32 hal_msbit_index(cyg_uint32 mask); +#define HAL_MSBIT_INDEX(index, mask) (index) = hal_msbit_index(mask); +#endif + +// There are some useful bit-set and bit-clear instructions which allow +// for atomic updates of a single byte of memory. +#define HAL_M68K_BSET(_address_, _bit_) \ + CYG_MACRO_START \ + asm volatile("bset %0,(%1)\n" : : "i" (_bit_), "a" (_address_) : "cc", "memory"); \ CYG_MACRO_END -#endif // HAL_THREAD_INIT_CONTEXT - -//----------------------------------------------------------------------------- -// Bit manipulation routines - -externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask); -externC cyg_uint32 hal_msbit_index(cyg_uint32 mask); - -#define HAL_LSBIT_INDEX(index, mask) (index) = hal_lsbit_index(mask); -#define HAL_MSBIT_INDEX(index, mask) (index) = hal_msbit_index(mask); - +#define HAL_M68K_BCLR(_address_, _bit_) \ + CYG_MACRO_START \ + asm volatile("bclr %0,(%1)\n" : : "i" (_bit_), "a" (_address_) : "cc", "memory"); \ + CYG_MACRO_END + //----------------------------------------------------------------------------- -// Idle thread code. -// This macro is called in the idle thread loop, and gives the HAL the -// chance to insert code. Typical idle thread behaviour might be to halt the -// processor. +// Idle thread code. A plain 68000 has no special support, so a no-op +// function is used. Variants may use this to go into sleep mode. -externC void hal_idle_thread_action(cyg_uint32 loop_count); - -#define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_) +#ifndef HAL_IDLE_THREAD_ACTION +# define HAL_IDLE_THREAD_ACTION(_count_) CYG_EMPTY_STATEMENT +#endif //----------------------------------------------------------------------------- // Execution reorder barrier. @@ -250,27 +362,98 @@ externC void hal_idle_thread_action(cyg_ // where the order of actions is vital, this can sometimes cause problems. // This macro may be inserted into places where reordering should not happen. -#define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" ) +#define HAL_REORDER_BARRIER() __asm__ volatile ( "" : : : "memory" ) + +//-------------------------------------------------------------------------- +// Macros for switching context between two eCos instances (jump from +// code in ROM to code in RAM or vice versa). The 68000 does not have any +// relevant global state so these macros are no-ops. + +#define CYGARC_HAL_SAVE_GP() +#define CYGARC_HAL_RESTORE_GP() //----------------------------------------------------------------------------- -// Breakpoint support +// gdb support + +// Translate a stack pointer as saved by the thread context macros +// into a pointer to a HAL_SavedRegisters structure. On the 68K +// these are equivalent. +#define HAL_THREAD_GET_SAVED_REGISTERS(_stack_, _regs_) \ + CYG_MACRO_START \ + (_regs_) = (HAL_SavedRegisters*)(_stack_); \ + CYG_MACRO_END + +// Translate between an eCos context and a gdb register set. +externC void hal_get_gdb_registers(CYG_ADDRWORD*, HAL_SavedRegisters*); +externC void hal_set_gdb_registers(HAL_SavedRegisters*, CYG_ADDRWORD*); + +#define HAL_GET_GDB_REGISTERS(_regval_, _regs_) \ + CYG_MACRO_START \ + hal_get_gdb_registers((CYG_ADDRWORD*)(_regval_), (HAL_SavedRegisters*)(_regs_)); \ + CYG_MACRO_END + +#define HAL_SET_GDB_REGISTERS(_regs_,_regval_) \ + CYG_MACRO_START \ + hal_set_gdb_registers((HAL_SavedRegisters*)(_regs_), (CYG_ADDRWORD*)(_regval_)); \ + CYG_MACRO_END + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen // if executed. // HAL_BREAKINST is the value of the breakpoint instruction and // HAL_BREAKINST_SIZE is its size in bytes. -#define HAL_BREAKPOINT(_label_) \ -asm volatile (" .globl " #_label_ ";" \ - #_label_":" \ - " trap #1" \ +#define HAL_BREAKPOINT(_label_) \ +__asm__ volatile (" .globl " #_label_ ";" \ + #_label_":" \ + " trap #15" \ ); -#define HAL_BREAKINST 0x4E41 +#define HAL_BREAKINST 0x4E4F #define HAL_BREAKINST_SIZE 2 -#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ - defined(CYGPKG_HAL_EXCEPTIONS) +// The GDB register definitions. as per gdb/m68k-stub.c +// FIXME: more work is needed for floating point support. +enum regnames { + D0, D1, D2, D3, D4, D5, D6, D7, + A0, A1, A2, A3, A4, A5, FP, SP, + PS, PC, +#ifdef CYGINT_HAL_M68K_VARIANT_FPU + FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, + FPCONTROL, FPSTATUS, FPIADDR +#endif +}; + +#ifdef CYGINT_HAL_M68K_VARIANT_FPU +# define NUMREGS 29 +#else +# define NUMREGS 18 +#endif + +#define REGSIZE(_x_) (4) + +typedef enum regnames regnames_t; +typedef CYG_ADDRWORD target_register_t; + +externC int __computeSignal(unsigned int trap_number); +externC int __get_trap_number(void); +externC void __install_breakpoints(void); +externC void __clear_breakpoints(void); +externC void __single_step(void); +externC void __clear_single_step(void); +externC void __skipinst(void); +externC int __is_breakpoint_function(void); +externC void set_pc(target_register_t); + +#define HAL_STUB_PLATFORM_STUBS_FIXUP() \ + CYG_MACRO_START \ + if (CYGNUM_HAL_VECTOR_TRAP15 == __get_trap_number()) \ + put_register(PC, get_register(PC) - 2); \ + CYG_MACRO_END + +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS //----------------------------------------------------------------------------- // Exception handling function. @@ -278,111 +461,9 @@ asm volatile (" .globl " #_label_ ";" // invoked from the HAL to deal with any CPU exceptions that the HAL does // not want to deal with itself. It usually invokes the kernel's exception // delivery mechanism. - +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && defined(CYGPKG_HAL_EXCEPTIONS) externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); - -#endif /* defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) */ - -//----------------------------------------------------------------------------- -// Minimal and sensible stack sizes: the intention is that applications -// will use these to provide a stack size in the first instance prior to -// proper analysis. Idle thread stack should be this big. - -// THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. -// THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. -// YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! - -// This is not a config option because it should not be adjusted except -// under "enough rope" sort of disclaimers. - -// Stack frame overhead per call. 6 data registers, 5 address registers, -// frame pointer, and return address. We can't guess the local variables so -// just assume that using all of the registers averages out. - -#define CYGNUM_HAL_STACK_FRAME_SIZE ((6 + 5 + 1 + 1) * 4) - -// Stack needed for a context switch. -// All registers + pc + sr + vector - -#ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE -#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((8+8+1+1+1)*4) -#endif // CYGNUM_HAL_STACK_CONTEXT_SIZE - -// Interrupt + call to ISR, interrupt_end() and the DSR - -#define CYGNUM_HAL_STACK_INTERRUPT_SIZE \ - ((CYGNUM_HAL_STACK_CONTEXT_SIZE) + (8*CYGNUM_HAL_STACK_FRAME_SIZE)) - -// We define a minimum stack size as the minimum any thread could ever -// legitimately get away with. We can throw asserts if users ask for less -// than this. Allow enough for four interrupt sources - clock, serial, -// nic, and one other - -// No separate interrupt stack exists. Make sure all threads contain -// a stack sufficiently large - -#define CYGNUM_HAL_STACK_SIZE_MINIMUM \ - ((4*CYGNUM_HAL_STACK_INTERRUPT_SIZE) \ - + (16*CYGNUM_HAL_STACK_FRAME_SIZE)) - -// Now make a reasonable choice for a typical thread size. Pluck figures -// from thin air and say 30 call frames with an average of 16 words of -// automatic variables per call frame - -#define CYGNUM_HAL_STACK_SIZE_TYPICAL \ - (CYGNUM_HAL_STACK_SIZE_MINIMUM + \ - (30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4)))) - -//-------------------------------------------------------------------------- -// Macros for switching context between two eCos instances (jump from -// code in ROM to code in RAM or vice versa). -#define CYGARC_HAL_SAVE_GP() -#define CYGARC_HAL_RESTORE_GP() - -#ifndef HAL_SETJMP -#define HAL_SETJMP -/***************************************************************************** -hal_setjmp/hal_longjmp - - We do the best we can to define generic setjmp and longjmp routines -for the m68k architecture. Some architectures will need to override this. - -*****************************************************************************/ - -// We must save all of the registers that are preserved across routine -// calls. The assembly code assumes that this structure is defined in the -// following format. Any changes to this structure will result in changes to -// the assembly code!! - -typedef struct { - cyg_uint32 d2; - cyg_uint32 d3; - cyg_uint32 d4; - cyg_uint32 d5; - cyg_uint32 d6; - cyg_uint32 d7; - cyg_uint32 a2; - cyg_uint32 a3; - cyg_uint32 a4; - cyg_uint32 a5; - cyg_uint32 a6; - cyg_uint32 sp; - cyg_uint32 pc; -} hal_jmp_buf_t; - -// This type is used by normal routines to pass the address of the -// structure into our routines without having to explicitly take the address -// of the structure. - -typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)]; - -// Define the generic setjmp and longjmp routines. - -externC int hal_m68k_setjmp(hal_jmp_buf env); -externC void hal_m68k_longjmp(hal_jmp_buf env, int val); -#define hal_setjmp(_env) hal_m68k_setjmp(_env) -#define hal_longjmp(_env, _val) hal_m68k_longjmp(_env, _val) -#endif // HAL_SETJMP +#endif //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_ARCH_H
--- a/packages/hal/m68k/arch/current/include/hal_cache.h +++ b/packages/hal/m68k/arch/current/include/hal_cache.h @@ -8,11 +8,10 @@ // HAL cache control API // //============================================================================= -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2006,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -35,17 +34,66 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //============================================================================= +//####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +//####DESCRIPTIONEND#### +//============================================================================= #include <pkgconf/hal.h> +#include <pkgconf/hal_m68k.h> +#ifndef __ASSEMBLER__ #include <cyg/infra/cyg_type.h> +#endif + +#ifdef CYGINT_HAL_M68K_VARIANT_CACHE +# include <cyg/hal/var_cache.h> +#endif -#include <cyg/hal/var_cache.h> +// Default anything not defined by the variant HAL. Some of these +// macros get used unconditionally by other code so must be +// defined, to no-op. +#ifndef HAL_ICACHE_ENABLE +# define HAL_ICACHE_ENABLE() +#endif +#ifndef HAL_ICACHE_DISABLE +# define HAL_ICACHE_DISABLE() +#endif +#ifndef HAL_ICACHE_SYNC +# define HAL_ICACHE_SYNC() +#endif +#ifndef HAL_ICACHE_INVALIDATE_ALL +# define HAL_ICACHE_INVALIDATE_ALL() +#endif +#ifndef HAL_ICACHE_IS_ENABLED +# define HAL_ICACHE_IS_ENABLED(_state_) \ + CYG_MACRO_START \ + (_state_) = 0; \ + CYG_MACRO_END +#endif + +#ifndef HAL_DCACHE_ENABLE +# define HAL_DCACHE_ENABLE() +#endif +#ifndef HAL_DCACHE_DISABLE +# define HAL_DCACHE_DISABLE() +#endif +#ifndef HAL_DCACHE_SYNC +# define HAL_DCACHE_SYNC() +#endif +#ifndef HAL_DCACHE_INVALIDATE_ALL +# define HAL_DCACHE_INVALIDATE_ALL() +#endif +#ifndef HAL_DCACHE_IS_ENABLED +# define HAL_DCACHE_IS_ENABLED(_state_) \ + CYG_MACRO_START \ + (_state_) = 0; \ + CYG_MACRO_END +#endif //----------------------------------------------------------------------------- #endif // ifndef CYGONCE_HAL_CACHE_H
deleted file mode 100644 --- a/packages/hal/m68k/arch/current/include/hal_diag.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef CYGONCE_HAL_HAL_DIAG_H -#define CYGONCE_HAL_HAL_DIAG_H - -//============================================================================= -// -// hal_diag.h -// -// HAL Support for Kernel Diagnostic Routines -// -//============================================================================= -//####UNSUPPORTEDBEGIN#### -// -// ------------------------------------------- -// This source file has been contributed to eCos/Red Hat. It may have been -// changed slightly to provide an interface consistent with those of other -// files. -// -// The functionality and contents of this file is supplied "AS IS" -// without any form of support and will not necessarily be kept up -// to date by Red Hat. -// -// All inquiries about this file, or the functionality provided by it, -// should be directed to the 'ecos-discuss' mailing list (see -// http://ecos.sourceware.org/ecos/intouch.html for details). -// -// Maintained by: <Unmaintained> -// ------------------------------------------- -// -//####UNSUPPORTEDEND#### -//============================================================================= -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with eCos; if not, write to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// As a special exception, if other files instantiate templates or use macros -// or inline functions from this file, or you compile this file and link it -// with other works to produce a work based on this file, this file does not -// by itself cause the resulting work to be covered by the GNU General Public -// License. However the source code for this file must still be made available -// in accordance with section (3) of the GNU General Public License. -// -// This exception does not invalidate any other reasons why a work based on -// this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ -// ------------------------------------------- -//####ECOSGPLCOPYRIGHTEND#### -//============================================================================= - -#include <pkgconf/hal.h> - -#include <cyg/infra/cyg_type.h> - -//----------------------------------------------------------------------------- -// functions implemented in hal_diag.c - -externC void hal_diag_init(void); - -externC void hal_diag_write_char(cyg_int8 c); - -externC cyg_int8 hal_diag_read_char(void); - -//----------------------------------------------------------------------------- - -#define HAL_DIAG_INIT() hal_diag_init() - -#define HAL_DIAG_WRITE_CHAR(_c_) hal_diag_write_char(_c_) - -#define HAL_DIAG_READ_CHAR(_c_) ((_c_) = hal_diag_read_char()) - -//----------------------------------------------------------------------------- -// end of hal_diag.h -#endif // CYGONCE_HAL_HAL_DIAG_H -
--- a/packages/hal/m68k/arch/current/include/hal_intr.h +++ b/packages/hal/m68k/arch/current/include/hal_intr.h @@ -8,11 +8,10 @@ // m68k Interrupt and clock support // //========================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2006,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -35,22 +34,48 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== +//####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +//####DESCRIPTIONEND#### +//============================================================================= #include <pkgconf/hal.h> #include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> #include <cyg/hal/hal_arch.h> +// Allow variants to override some of these settings. #include <cyg/hal/var_intr.h> //-------------------------------------------------------------------------- // m68k exception vectors. These correspond to VSRs and are the values // to use for HAL_VSR_GET/SET + +extern CYG_ADDRESS hal_m68k_vsr_table[]; + +#ifndef HAL_VSR_GET +# define HAL_VSR_GET( _vector_, _pvsr_ ) \ + CYG_MACRO_START \ + *((CYG_ADDRESS *)(_pvsr_)) = hal_m68k_vsr_table[(_vector_)]; \ + CYG_MACRO_END +#endif + +#if !defined(HAL_VSR_SET) && !defined(_HAL_M68K_NO_VSR_SET_) +# define HAL_VSR_SET( _vector_arg_, _vsr_, _poldvsr_arg_ ) \ + CYG_MACRO_START \ + cyg_uint32 _vector_ = (cyg_uint32) (_vector_arg_); \ + CYG_ADDRESS* _poldvsr_ = (CYG_ADDRESS*)(_poldvsr_arg_); \ + if(_poldvsr_ != (CYG_ADDRESS*)0 ) \ + *_poldvsr_ = hal_m68k_vsr_table[(_vector_)]; \ + hal_m68k_vsr_table[(_vector_)] = (CYG_ADDRESS)(_vsr_); \ + CYG_MACRO_END +#endif + #define CYGNUM_HAL_VECTOR_SSP 0 #define CYGNUM_HAL_VECTOR_RESET 1 #define CYGNUM_HAL_VECTOR_BUSERR 2 @@ -62,8 +87,10 @@ #define CYGNUM_HAL_VECTOR_PRIVVIOLATION 8 #define CYGNUM_HAL_VECTOR_TRACE 9 #define CYGNUM_HAL_VECTOR_L1010 10 +// 12-14 are reserved #define CYGNUM_HAL_VECTOR_L1111 11 #define CYGNUM_HAL_VECTOR_UNINITINT 15 +// 16-23 are reserved #define CYGNUM_HAL_VECTOR_SPURINT 24 #define CYGNUM_HAL_VECTOR_AUTOVEC1 25 #define CYGNUM_HAL_VECTOR_AUTOVEC2 26 @@ -73,9 +100,27 @@ #define CYGNUM_HAL_VECTOR_AUTOVEC6 30 #define CYGNUM_HAL_VECTOR_AUTOVEC7 31 #define CYGNUM_HAL_VECTOR_NMI CYGNUM_HAL_VECTOR_AUTOVEC7 +#define CYGNUM_HAL_VECTOR_TRAP0 32 #define CYGNUM_HAL_VECTOR_TRAPFIRST 32 +#define CYGNUM_HAL_VECTOR_TRAP1 33 +#define CYGNUM_HAL_VECTOR_TRAP2 34 +#define CYGNUM_HAL_VECTOR_TRAP3 35 +#define CYGNUM_HAL_VECTOR_TRAP4 36 +#define CYGNUM_HAL_VECTOR_TRAP5 37 +#define CYGNUM_HAL_VECTOR_TRAP6 38 +#define CYGNUM_HAL_VECTOR_TRAP7 39 +#define CYGNUM_HAL_VECTOR_TRAP8 40 +#define CYGNUM_HAL_VECTOR_TRAP9 41 +#define CYGNUM_HAL_VECTOR_TRAP10 42 +#define CYGNUM_HAL_VECTOR_TRAP11 43 +#define CYGNUM_HAL_VECTOR_TRAP12 44 +#define CYGNUM_HAL_VECTOR_TRAP13 45 +#define CYGNUM_HAL_VECTOR_TRAP14 46 +/* TRAP15 is used by gdb stubs */ +#define CYGNUM_HAL_VECTOR_TRAP15 47 +#define CYGNUM_HAL_VECTOR_TRAPLAST CYGNUM_HAL_VECTOR_TRAP15 #define CYGNUM_HAL_VECTOR_NUMTRAPS 16 -#define CYGNUM_HAL_VECTOR_TRAPLAST (CYGNUM_HAL_VECTOR_TRAPFIRST+CYGNUM_HAL_VECTOR_NUMTRAPS-1) +// 48-63 are reserved #define CYGNUM_HAL_VECTOR_INTRFIRST 64 #define CYGNUM_HAL_VECTOR_NUMINTRS 192 #define CYGNUM_HAL_VECTOR_INTRLAST (CYGNUM_HAL_VECTOR_INTRFIRST+CYGNUM_HAL_VECTOR_NUMINTRS-1) @@ -84,176 +129,218 @@ #define CYGNUM_HAL_VSR_MAX CYGNUM_HAL_VECTOR_INTRLAST #define CYGNUM_HAL_VSR_COUNT (CYGNUM_HAL_VSR_MAX+1) -//-------------------------------------------------------------------------- -// Interrupt vectors. +// ---------------------------------------------------------------------------- +// Also give details of the defined exceptions. Only some of the exceptions +// are named explicitly here. +// NOTE: FPU exceptions should be added -#ifndef CYGNUM_HAL_ISR_MAX -#define CYGNUM_HAL_ISR_MIN 0 -#define CYGNUM_HAL_ISR_MAX 255 -#define CYGNUM_HAL_ISR_COUNT (7+CYGNUM_HAL_VECTOR_NUMINTRS) -#endif /* CYGNUM_HAL_ISR_MAX */ +#define CYGNUM_HAL_EXCEPTION_DATA_ACCESS CYGNUM_HAL_VECTOR_BUSERR +#define CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS CYGNUM_HAL_VECTOR_ADDERR +#define CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION CYGNUM_HAL_VECTOR_ILLINST +#define CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO CYGNUM_HAL_VECTOR_ZERODIV +#define CYGNUM_HAL_EXCEPTION_SYSTEM_ERROR CYGNUM_HAL_VECTOR_CHKINST +#define CYGNUM_HAL_EXCEPTION_TRACE CYGNUM_HAL_VECTOR_TRACE +#define CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP CYGNUM_HAL_VECTOR_TRAP15 #ifndef CYGNUM_HAL_EXCEPTION_COUNT -#define CYGNUM_HAL_EXCEPTION_MIN CYGNUM_HAL_VECTOR_BUSERR -#define CYGNUM_HAL_EXCEPTION_MAX CYGNUM_HAL_VECTOR_SPURINT -#define CYGNUM_HAL_EXCEPTION_COUNT ((CYGNUM_HAL_EXCEPTION_MAX-CYGNUM_HAL_EXCEPTION_MIN)+1) -#endif /* CYGNUM_HAL_EXCEPTION_COUNT */ +# define CYGNUM_HAL_EXCEPTION_MIN CYGNUM_HAL_VECTOR_BUSERR +# define CYGNUM_HAL_EXCEPTION_MAX CYGNUM_HAL_VECTOR_TRAPLAST +# define CYGNUM_HAL_EXCEPTION_COUNT ((CYGNUM_HAL_EXCEPTION_MAX-CYGNUM_HAL_EXCEPTION_MIN)+1) +#endif //-------------------------------------------------------------------------- -// Static data used by HAL +// ISR vectors. + +#ifndef CYGNUM_HAL_ISR_COUNT +# error The variant or platform HAL should provide details of ISR vectors. +#endif -// ISR tables -externC volatile CYG_ADDRESS cyg_hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; -externC volatile CYG_ADDRWORD cyg_hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; -externC volatile CYG_ADDRESS cyg_hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; +// Default definition of HAL_TRANSLATE_VECTOR() +#ifndef HAL_TRANSLATE_VECTOR +# define HAL_TRANSLATE_VECTOR(_vector_, _index_) \ + ((_index_) = ((_vector_) - CYGNUM_HAL_ISR_MIN)) +#endif -// VSR table -externC volatile CYG_ADDRESS cyg_hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; - -//--------------------------------------------------------------------------- -// Translate a vector number into an ISR table index. +externC volatile CYG_ADDRESS cyg_hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +externC volatile CYG_ADDRWORD cyg_hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; +externC volatile CYG_ADDRESS cyg_hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; +externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); +// For consistency with other architectures. +#define hal_interrupt_handlers cyg_hal_interrupt_handlers -#define HAL_TRANSLATE_VECTOR(_vector_,_index_) \ - CYG_MACRO_START \ - switch ((_vector_)) \ - { \ - case CYGNUM_HAL_VECTOR_AUTOVEC1 ... CYGNUM_HAL_VECTOR_AUTOVEC7: \ - (_index_) = ((_vector_) - CYGNUM_HAL_VECTOR_AUTOVEC1); \ - break; \ - case CYGNUM_HAL_VECTOR_INTRFIRST ... CYGNUM_HAL_VECTOR_INTRLAST: \ - (_index_) = ((_vector_) \ - - CYGNUM_HAL_VECTOR_INTRFIRST \ - + (CYGNUM_HAL_VECTOR_AUTOVEC7 \ - - CYGNUM_HAL_VECTOR_AUTOVEC1 \ - + 1)); \ - break; \ - default: \ - CYG_FAIL("Unknown Interrupt!!!"); \ - (_index_) = (typeof(_index_))-1; \ - } \ +#ifndef HAL_INTERRUPT_IN_USE +# define HAL_INTERRUPT_IN_USE( _vector_, _state_) \ + CYG_MACRO_START \ + if (cyg_hal_interrupt_handlers[(_vector_)] ==(CYG_ADDRESS)&hal_default_isr) \ + (_state_) = 0; \ + else \ + (_state_) = 1; \ CYG_MACRO_END +#endif + +#ifndef HAL_INTERRUPT_ATTACH +# define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_, _object_ ) \ + CYG_MACRO_START \ + cyg_hal_interrupt_handlers[(_vector_)] = (CYG_ADDRESS)(_isr_); \ + cyg_hal_interrupt_data[(_vector_)] = (CYG_ADDRWORD)(_data_); \ + cyg_hal_interrupt_objects[(_vector_)] = (CYG_ADDRESS)(_object_); \ + CYG_MACRO_END +#endif + +#ifndef HAL_INTERRUPT_DETACH +# define HAL_INTERRUPT_DETACH( _vector_, _isr_ ) \ + CYG_MACRO_START \ + if (cyg_hal_interrupt_handlers[(_vector_)] == (CYG_ADDRESS)(_isr_)) { \ + cyg_hal_interrupt_handlers[(_vector_)] = (CYG_ADDRESS)&hal_default_isr; \ + cyg_hal_interrupt_data[(_vector_)] = 0; \ + cyg_hal_interrupt_objects[(_vector_)] = 0; \ + } \ + CYG_MACRO_END +#endif //-------------------------------------------------------------------------- -// Interrupt state storage +// Interrupt control macros. These just operate on the entire status +// register. typedef cyg_uint16 CYG_INTERRUPT_STATE; -//--------------------------------------------------------------------------- -// Interrupt and VSR attachment macros - -externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); -externC void hal_default_exception_handler(CYG_WORD vector, - HAL_SavedRegisters *regs); - -#define HAL_INTERRUPT_IN_USE( _vector_, _state_) \ - CYG_MACRO_START \ - cyg_uint32 _index_; \ - HAL_TRANSLATE_VECTOR ((_vector_), _index_); \ - \ - if (cyg_hal_interrupt_handlers[_index_] \ - ==(CYG_ADDRESS)&hal_default_isr) \ - (_state_) = 0; \ - else \ - (_state_) = 1; \ - CYG_MACRO_END - -#define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_, _object_ ) \ - CYG_MACRO_START \ - cyg_uint32 _index_; \ - HAL_TRANSLATE_VECTOR((_vector_), _index_); \ - \ - if (cyg_hal_interrupt_handlers[_index_] \ - ==(CYG_ADDRESS)&hal_default_isr) \ - { \ - cyg_hal_interrupt_handlers[_index_] = (CYG_ADDRESS)(_isr_); \ - cyg_hal_interrupt_data[_index_] = (CYG_ADDRWORD)(_data_); \ - cyg_hal_interrupt_objects[_index_] = (CYG_ADDRESS)(_object_); \ - } \ - CYG_MACRO_END - -#define HAL_INTERRUPT_DETACH( _vector_, _isr_ ) \ -CYG_MACRO_START \ - cyg_uint32 _index_; \ - HAL_INTERRUPT_MASK(_vector_); \ - HAL_TRANSLATE_VECTOR((_vector_), _index_); \ - if (cyg_hal_interrupt_handlers[_index_] \ - == (CYG_ADDRESS)(_isr_)) \ - { \ - cyg_hal_interrupt_handlers[_index_] = \ - (CYG_ADDRESS)&hal_default_isr; \ - cyg_hal_interrupt_data[_index_] = 0; \ - cyg_hal_interrupt_objects[_index_] = 0; \ - } \ -CYG_MACRO_END - -#define HAL_VSR_GET( _vector_, _pvsr_ ) \ - *((CYG_ADDRESS *)(_pvsr_)) = cyg_hal_vsr_table[(_vector_)]; - - -#define HAL_VSR_SET( _vector_, _vsr_, _poldvsr_ ) \ - CYG_MACRO_START \ - if( (_poldvsr_) != NULL ) \ - *(CYG_ADDRESS *)(_poldvsr_) = cyg_hal_vsr_table[(_vector_)]; \ - cyg_hal_vsr_table[(_vector_)] = (CYG_ADDRESS)(_vsr_); \ - CYG_MACRO_END - -//-------------------------------------------------------------------------- -// Interrupt control macros - -// The following interrupt control macros are the default for the 68k -// architecture. Some architectures will override these definitions by -// defining them in their var_intr.h file. Some architectures support -// instructions like andi.w #xxxx,%sr but others (Coldfire) do not. -// Architectures that support these other instructions will want to define -// their own macros. - -#define HAL_M68K_SET_SR(__newsr__) \ - CYG_MACRO_START \ - asm volatile ("move.w %0,%%sr\n" \ - : \ - : "g" ((CYG_INTERRUPT_STATE)(__newsr__))); \ - CYG_MACRO_END - #ifndef HAL_ENABLE_INTERRUPTS -#define HAL_ENABLE_INTERRUPTS() \ - CYG_MACRO_START \ - CYG_INTERRUPT_STATE _msk_; \ - HAL_QUERY_INTERRUPTS(_msk_); \ - HAL_M68K_SET_SR((_msk_ & (CYG_INTERRUPT_STATE)0xf8ff)); \ +# define HAL_ENABLE_INTERRUPTS() \ + CYG_MACRO_START \ + asm volatile ("move.w %0,%%sr\n" \ + : \ + : "J" (0x2000 | (CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL << 8)) \ + : "cc"); \ CYG_MACRO_END #endif // HAL_ENABLE_INTERRUPTS #ifndef HAL_DISABLE_INTERRUPTS -#define HAL_DISABLE_INTERRUPTS(_old_) \ +# define HAL_DISABLE_INTERRUPTS(_old_) \ CYG_MACRO_START \ - HAL_QUERY_INTERRUPTS(_old_); \ - HAL_M68K_SET_SR((_old_ | (CYG_INTERRUPT_STATE)0x0700)); \ + asm volatile ("move.w %%sr,%0\n" \ + "move.w #0x2700,%%sr\n" : "=d" (_old_) : : "cc"); \ + CYG_MACRO_END +#endif // HAL_DISABLE_INTERRUPTS + +#ifndef HAL_RESTORE_INTERRUPTS +# define HAL_RESTORE_INTERRUPTS(_prev_) \ + CYG_MACRO_START \ + asm volatile ("move.w %0,%%sr\n" : : "d" (_prev_) : "cc"); \ CYG_MACRO_END -#endif //HAL_DISABLE_INTERRUPTS +#endif -#define HAL_RESTORE_INTERRUPTS(_prev_) \ +#ifndef HAL_QUERY_INTERRUPTS +# define HAL_QUERY_INTERRUPTS(_old_) \ CYG_MACRO_START \ - CYG_INTERRUPT_STATE _msk_; \ - HAL_QUERY_INTERRUPTS(_msk_); \ - _msk_ &= (CYG_INTERRUPT_STATE)0xf8ff; \ - _msk_ |= (((CYG_INTERRUPT_STATE)(_prev_)) \ - & (CYG_INTERRUPT_STATE)0x0700); \ - asm volatile ("move.w %0,%%sr\n" \ - : \ - : "g" (_msk_)); \ + asm volatile ("move.w %%sr,%0\n" : "=d" (_old_) : ); \ CYG_MACRO_END +#endif + +// ---------------------------------------------------------------------------- +// DSR's should always run on the interrupt stack if available. +// Even if no interrupt stack is in use we still want to go +// via call_pending_DSRs() so that it can manipulate the IPL +// level. +externC void hal_interrupt_stack_call_pending_DSRs(void); +# define HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() hal_interrupt_stack_call_pending_DSRs() -// Use the extra assignment to avoid warnings. -// The compiler should optimize it out. -#define HAL_QUERY_INTERRUPTS(__oldmask__) \ +// ---------------------------------------------------------------------------- +// HAL_DELAY_US(). This implementation should work fine on all M68K +// processors. The variant/processor/platform HAL may already have +// supplied an implementation if for some reason this version is +// inappropriate. +// +// Lower-level HALs should define a count _HAL_M68K_DELAY_US_LOOPS_, +// and optionally _HAL_M68K_DELAY_US_LOOPS_UNCACHED_. These give the +// number of iterations needed for a single microsecond delay. In +// theory it can be worked out from the cpu and board specs, but in +// practice it is easier to do a bit of experimenting and fine-tune +// the numbers. Good initial values are 20 and 1 respectively. Note +// that the symbols need not be compile-time constants if e.g. the +// processor frequency may change at run-time for power management, +// but it is assumed that the values will not change as a side +// effect of interrupts or anything like that. +// +// An inline assembler version is used for two reasons. First it +// prevents the compiler from optimizing the code. Second it avoids +// problems when different versions of the compiler generate slightly +// better or worse code. +#ifndef HAL_DELAY_US +# ifndef _HAL_M68K_DELAY_US_LOOPS_ +# error Variant, processor or platform HAL should supply loop count parameters +# else +# ifdef _HAL_M68K_DELAY_US_LOOPS_UNCACHED_ +// A cache-aware version of the macro +# include <cyg/hal/hal_cache.h> +# define HAL_DELAY_US(_delay_) \ + CYG_MACRO_START \ + int _icache_enabled_; \ + int _loops_; \ + HAL_ICACHE_IS_ENABLED(_icache_enabled_); \ + _loops_ = (_icache_enabled_) ? _HAL_M68K_DELAY_US_LOOPS_ : \ + _HAL_M68K_DELAY_US_LOOPS_UNCACHED_; \ + asm volatile ( "move.l %0, %%d0\n" \ + "1:\n" \ + "subq.l #1, %%d0\n" \ + "beq 3f\n" \ + "move.l %1, %%d1\n" \ + "2:\n" \ + "subq.l #1,%%d1\n" \ + "bne 2b\n" \ + "bra 1b\n" \ + "3:\n" \ + : \ + : "d" ((_delay_) + 1), "d" ((_loops_)) \ + : "cc", "d0", "d1"); \ + CYG_MACRO_END +# else +# define HAL_DELAY_US(_delay_) \ + CYG_MACRO_START \ + int _loops_ = _HAL_M68K_DELAY_US_LOOPS_; \ + asm volatile ( "move.l %0, %%d0\n" \ + "1:\n" \ + "subq.l #1, %%d0\n" \ + "beq 3f\n" \ + "move.l %1, %%d1\n" \ + "2:\n" \ + "subq.l #1,%%d1\n" \ + "bne 2b\n" \ + "bra 1b\n" \ + "3:\n" \ + : \ + : "d" ((_delay_) + 1), "d" ((_loops_)) \ + : "cc", "d0", "d1"); \ + CYG_MACRO_END +# endif +# endif +#endif + +// ---------------------------------------------------------------------------- +// Reset support. This is done by disabling all interrupts and indirecting +// through the exception vector. Where possible variant or processor HALs +// should instead activate an on-chip reset controller. + +#ifndef HAL_PLATFORM_RESET +# define HAL_PLATFORM_RESET() \ CYG_MACRO_START \ - CYG_INTERRUPT_STATE _omsk_ = (CYG_INTERRUPT_STATE)(__oldmask__); \ - asm volatile ("move.w %%sr,%0\n" \ - : "=g" (_omsk_) \ - : ); \ - (__oldmask__) = (typeof(__oldmask__))_omsk_; \ + asm volatile ("move.w #0x2700,%%sr\n" \ + "move.l %0,%%a0\n" \ + "move.l 0(%%a0),%%a7\n" \ + "move.l 4(%%a0),%%a1\n" \ + "jmp (%%a1)\n" \ + : : "a" (hal_m68k_vsr_table) : "a0", "a1", "memory"); \ CYG_MACRO_END +#endif +#ifndef HAL_PLATFORM_RESET_ENTRY +# define HAL_PLATFORM_RESET_ENTRY (*(cyg_uint32*)0x04) +#endif + +// ---------------------------------------------------------------------------- +// Functions/symbols exported to the variant and platform HAL's +externC void hal_m68k_exception_reset(void); +externC void hal_m68k_rte(void); +externC void hal_m68k_exception_vsr(void); +externC void hal_m68k_interrupt_vsr(void); //--------------------------------------------------------------------------- #endif // ifndef CYGONCE_HAL_HAL_INTR_H -
--- a/packages/hal/m68k/arch/current/include/hal_io.h +++ b/packages/hal/m68k/arch/current/include/hal_io.h @@ -8,11 +8,10 @@ // HAL device IO register support. // //============================================================================= -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2006,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -35,19 +34,25 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //============================================================================= +//####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +//####DESCRIPTIONEND#### +//============================================================================= +#if !defined(__ASSEMBLER__) && !defined(__LDI__) #include <cyg/infra/cyg_type.h> +#endif +#include <cyg/hal/var_io.h> +#if !defined(__ASSEMBLER__) && !defined(__LDI__) //----------------------------------------------------------------------------- // IO Register address. // This type is for recording the address of an IO register. - typedef volatile CYG_ADDRWORD HAL_IO_REGISTER; //----------------------------------------------------------------------------- @@ -141,6 +146,8 @@ typedef volatile CYG_ADDRWORD HAL_IO_REG } \ CYG_MACRO_END +#endif + //----------------------------------------------------------------------------- #endif // ifndef CYGONCE_HAL_HAL_IO_H // End of hal_io.h
deleted file mode 100644 --- a/packages/hal/m68k/arch/current/include/hal_startup.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _HAL_STARTUP_H -#define _HAL_STARTUP_H - -#include <cyg/infra/cyg_type.h> - -// Include the variant-specific startup header. - -#include <cyg/hal/var_startup.h> - -// Declare the routine to call to simulate a hardware reset. - -externC void hal_hw_reset(void); - -#endif // _HAL_STARTUP_H -
deleted file mode 100644 --- a/packages/hal/m68k/arch/current/include/m68k_stub.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef CYGONCE_HAL_M68K_STUB_H -#define CYGONCE_HAL_M68K_STUB_H -//======================================================================== -// -// m68k_stub.h -// -// M68K-specific definitions for generic stub -// -//======================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with eCos; if not, write to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// As a special exception, if other files instantiate templates or use macros -// or inline functions from this file, or you compile this file and link it -// with other works to produce a work based on this file, this file does not -// by itself cause the resulting work to be covered by the GNU General Public -// License. However the source code for this file must still be made available -// in accordance with section (3) of the GNU General Public License. -// -// This exception does not invalidate any other reasons why a work based on -// this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ -// ------------------------------------------- -//####ECOSGPLCOPYRIGHTEND#### -//======================================================================== - -#include <pkgconf/system.h> -#include <pkgconf/hal.h> - - - -#ifdef CYGPKG_IO_SERIAL -#include <pkgconf/io_serial.h> -#endif - -#include <cyg/hal/hal_diag.h> - -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - -#include <cyg/infra/cyg_type.h> // CYG_UNUSED_PARAM, externC - -#define HAL_STUB_PLATFORM_INIT_SERIAL() HAL_DIAG_INIT() - -#define HAL_STUB_PLATFORM_GET_CHAR() \ -((cyg_int8)({ \ - cyg_int8 _ch_; \ - HAL_DIAG_READ_CHAR(_ch_); \ - _ch_; \ -})) - -#define HAL_STUB_PLATFORM_PUT_CHAR(c) HAL_DIAG_WRITE_CHAR((c)) - -#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int,(baud)) - -#define HAL_STUB_PLATFORM_RESET() HAL_DIAG_INIT() - -#define HAL_STUB_PLATFORM_INIT() HAL_DIAG_INIT() - -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - - - -#define NUMREGS 18 - -#define REGSIZE( _x_ ) (4) - -typedef unsigned long target_register_t; - -enum regnames { - D0, D1, D2, D3, D4, D5, D6, D7, - A0, A1, A2, A3, A4, A5, FP, SP, - PS, PC, -}; - -typedef enum regnames regnames_t; - -/* Given a trap value TRAP, return the corresponding signal. */ -externC int __computeSignal (unsigned int trap_number); - -/* Return the SPARC trap number corresponding to the last-taken trap. */ -externC int __get_trap_number (void); - -/* Return the currently-saved value corresponding to register REG. */ -externC target_register_t get_register (regnames_t reg); - -/* Store VALUE in the register corresponding to WHICH. */ -externC void put_register (regnames_t which, target_register_t value); - -/* Set the currently-saved pc register value to PC. This also updates NPC - as needed. */ -externC void set_pc (target_register_t pc); - -/* Set things up so that the next user resume will execute one instruction. - This may be done by setting breakpoints or setting a single step flag - in the saved user registers, for example. */ -externC void __single_step (void); - -/* Clear the single-step state. */ -externC void __clear_single_step (void); - -/* If the breakpoint we hit is in the breakpoint() instruction, return a - non-zero value. */ -externC int __is_breakpoint_function (void); - -/* Skip the current instruction. */ -externC void __skipinst (void); - -externC void __install_breakpoints (void); - -externC void __clear_breakpoints (void); - -#endif // ifndef CYGONCE_HAL_M68K_STUB_H
--- a/packages/hal/m68k/arch/current/src/hal_arch.S +++ b/packages/hal/m68k/arch/current/src/hal_arch.S @@ -1,156 +1,760 @@ -##============================================================================= -#####ECOSGPLCOPYRIGHTBEGIN#### -## ------------------------------------------- -## This file is part of eCos, the Embedded Configurable Operating System. -## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -## -## eCos is free software; you can redistribute it and/or modify it under -## the terms of the GNU General Public License as published by the Free -## Software Foundation; either version 2 or (at your option) any later version. -## -## eCos is distributed in the hope that it will be useful, but WITHOUT ANY -## WARRANTY; without even the implied warranty of MERCHANTABILITY or -## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -## for more details. -## -## You should have received a copy of the GNU General Public License along -## with eCos; if not, write to the Free Software Foundation, Inc., -## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -## -## As a special exception, if other files instantiate templates or use macros -## or inline functions from this file, or you compile this file and link it -## with other works to produce a work based on this file, this file does not -## by itself cause the resulting work to be covered by the GNU General Public -## License. However the source code for this file must still be made available -## in accordance with section (3) of the GNU General Public License. -## -## This exception does not invalidate any other reasons why a work based on -## this file might be covered by the GNU General Public License. -## -## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -## at http://sources.redhat.com/ecos/ecos-license/ -## ------------------------------------------- -#####ECOSGPLCOPYRIGHTEND#### -##============================================================================= -/***************************************************************************** -hal_arch.S -- m68k architecture code -*****************************************************************************/ +// #======================================================================== +// # +// # hal_arch.S +// # +// # M68K support for contexts, exceptions and interrupts +// # +// #======================================================================== +//============================================================================= +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003,2004,2005,2006,2008 Free Software Foundation, Inc. +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================ +//###DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +// +//###DESCRIPTIONEND#### +//======================================================================== + .file "hal_arch.S" + +#include <pkgconf/system.h> #include <pkgconf/hal.h> +#include <pkgconf/hal_m68k.h> +#ifdef CYGPKG_KERNEL + // For instrumentation options +# include <pkgconf/kernel.h> +#endif +#include <cyg/hal/arch.inc> -/***************************************************************************** -FUNC_START -- Function declaration macro -*****************************************************************************/ -#define FUNC_START(name) \ - .text; \ - .even; \ - .globl name; \ -name: +// ---------------------------------------------------------------------------- +// The system startup and/or interrupt stack, unless the platform HAL +// provides its own. +// +// The default behaviour is a separate interrupt stack via common HAL +// configuration options, with the interrupt stack reused as the +// startup stack. If the use of an interrupt stack is disabled then +// a separate startup stack is needed. Either the startup stack, the +// interrupt stack, or both can be provided by the platform HAL, for +// example to place the stack in an area of memory that is not otherwise +// readily usable. + +#if defined(_HAL_M68K_INSTANTIATE_STARTUP_STACK_) || defined(_HAL_M68K_INSTANTIATE_INTERRUPT_STACK_) + .section .bss + .balign 4 +# ifdef _HAL_M68K_INSTANTIATE_STARTUP_STACK_ + .global _hal_m68k_startup_stack_base_ +_hal_m68k_startup_stack_base_: +# endif +# ifdef _HAL_M68K_INSTANTIATE_INTERRUPT_STACK_ + .global _hal_m68k_interrupt_stack_base_ +_hal_m68k_interrupt_stack_base_: +# endif +# ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE + .byte 0 + .endr + .balign 4 +# else + .rept CYGNUM_HAL_M68K_STARTUP_STACK_SIZE + .byte 0 + .endr + .balign 4 +# endif +# ifdef _HAL_M68K_INSTANTIATE_STARTUP_STACK_ + .global _hal_m68k_startup_stack_ +_hal_m68k_startup_stack_: +# endif +# ifdef _HAL_M68K_INSTANTIATE_INTERRUPT_STACK_ + .global _hal_m68k_interrupt_stack_ +_hal_m68k_interrupt_stack_: +# endif + +#endif + +// ---------------------------------------------------------------------------- +// M68K calling conventions. +// +// The stack pointer always points at the first word of the stack that +// is currently in use. Pushing additional data requires a predecrement. +// +// Frame pointers are not required but the compiler usually defaults to +// using them, to make debugging easier. This assembler code typically +// does not use a frame pointer. +// +// All arguments are pushed onto the stack, never in registers. D0 is +// used for return values. +// +// According to CALL_USED_REGISTERS in gcc/config/m68k/m68k.h, +// d0/d1/a0/a1/fp0/fp1 are caller-save, i.e. must be saved in an interrupt +// handler but can be ignored in a function called from C. The fp status +// registers are also caller-save. +// +// d2-d7/a2-a6/fp2-fp7 are callee-save registers, i.e. must be saved by +// a C function. fpsr is not callee-save, a C function can perform floating +// point operations and hence clobber the status. Similarly fpiar is not +// callee-save. fpcr is +// +// Floating point support is only available on some variants. There can also +// be other hardware units such as multiply-accumulators which may have state +// that should be saved. -/***************************************************************************** - The following routines assume the hal_jmp_buf structure is defined as -shown below. +// ---------------------------------------------------------------------------- +// Context switch support. +// +// The context consists of generic integer registers, possibly floating +// point registers, possibly another hardware unit, and space for pc/sr +// at the end in a variant-specific format. + + .equ hal_context_integer_offset, 0 + .equ hal_context_integer_d0_offset, 0 + .equ hal_context_integer_d2_offset, (2 * 4) + .equ hal_context_integer_a0_offset, (8 * 4) + .equ hal_context_integer_a2_offset, ((8+2) * 4) + .equ hal_context_integer_size, (15 * 4) + + .equ hal_context_fpu_offset, (hal_context_integer_offset + hal_context_integer_size) +#ifdef CYGIMP_HAL_M68K_FPU_SAVE + .equ hal_context_fpu_fpsr_offset, (hal_context_fpu_offset + 0) + .equ hal_context_fpu_fpiar_offset, (hal_context_fpu_offset + 4) + .equ hal_context_fpu_fp0_offset, (hal_context_fpu_offset + 8) + .equ hal_context_fpu_fp2_offset, (hal_context_fpu_fp0_offset + (2 * 12)) + .equ hal_context_fpu_size, ((2 * 4) + (8 * 12)) +#else + .equ hal_context_fpu_size, 0 +#endif + + .equ hal_context_other_offset, (hal_context_fpu_offset + hal_context_fpu_size) +#ifdef HAL_CONTEXT_OTHER_SIZE + .equ hal_context_other_size, HAL_CONTEXT_OTHER_SIZE +#else + .equ hal_context_other_size, 0 +#endif + + .equ hal_context_pcsr_offset, (hal_context_other_offset + hal_context_other_size) +#ifdef HAL_CONTEXT_PCSR_SIZE + .equ hal_context_pcsr_size, HAL_CONTEXT_PCSR_SIZE +#else + .equ hal_context_pcsr_size, 8 +#endif + .equ hal_context_size, (hal_context_pcsr_offset + hal_context_pcsr_size) + +// The offset to be used when switching to a new thread. For some variants +// this is 0 because the rte instruction will pop the entire pcsr part of +// the structure. For other variants some additional data may have to be popped. +#ifdef HAL_CONTEXT_PCSR_RTE_ADJUST + .equ hal_context_rte_adjust, (hal_context_pcsr_offset + HAL_CONTEXT_PCSR_RTE_ADJUST) +#else + .equ hal_context_rte_adjust, hal_context_pcsr_offset +#endif + + +// Definitions for saving/restoring FPU context, if the FPU is part of the +// saved context. It can be assumed that %sp points at the thread context. +// FIXME: this code should probably use fsave/frestore to ensure that +// floating point operations have completed. +#ifdef CYGIMP_HAL_M68K_FPU_SAVE + + .macro hal_context_fpu_save_caller areg=%sp + fmove.l %fpsr, hal_context_fpu_fpsr_offset(\areg) + fmove.l %fpiar, hal_context_fpu_fpiar_offset(\areg) + fmovem.x %fp0-%fp1, hal_context_fpu_fp0_offset(\areg) + .endm + + .macro hal_context_fpu_load_caller areg=%sp + fmove.l hal_context_fpu_fpsr_offset(\areg), %fpisr + fmove.l hal_context_fpu_fpiar_offset(\areg), %fpiar + fmovem.x hal_context_fpu_fp0_offset(\areg),%fp0-%fp1 + .endm + + .macro hal_context_fpu_save_callee areg=%sp + fmovem.x %fp2-%fp7, hal_context_fpu_fp2_offset(\areg) + .endm + + .macro hal_context_fpu_load_callee areg=%sp + fmovem.x hal_context_fpu_fp2_offset(\areg), %fp2-%fp7 + .endm + + .macro hal_context_fpu_save_all areg=%sp + fmove.l %fpsr, hal_context_fpu_fpsr_offset(\areg) + fmove.l %fpiar, hal_context_fpu_fpiar_offset(\areg) + fmovem.x %fp0-%fp7, hal_context_fpu_fp0_offset(\areg) + .endm -typedef struct { - cyg_uint32 d2; - cyg_uint32 d3; - cyg_uint32 d4; - cyg_uint32 d5; - cyg_uint32 d6; - cyg_uint32 d7; - cyg_uint32 a2; - cyg_uint32 a3; - cyg_uint32 a4; - cyg_uint32 a5; - cyg_uint32 a6; - cyg_uint32 sp; - cyg_uint32 pc; -} hal_jmp_buf_t; -typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)]; -*****************************************************************************/ + .macro hal_context_fpu_load_all areg=%sp + fmove.l hal_context_fpu_fpsr_offset(\areg), %fpsr + fmove.l hal_context_fpu_fpiar_offset(\areg), %fpiar + fmovem.x hal_context_fpu_fp0_offset(\areg), %fp0-%fp7 + .endm +#else + .macro hal_context_fpu_save_caller areg=%sp + .endm + .macro hal_context_fpu_load_caller areg=%sp + .endm + .macro hal_context_fpu_save_callee areg=%sp + .endm + .macro hal_context_fpu_load_callee areg=%sp + .endm + .macro hal_context_fpu_save_all areg=%sp + .endm + .macro hal_context_fpu_load_all areg=%sp + .endm +#endif + +// No-op defaults for saving/restoring the OTHER context. If there is in fact +// something to be done then the variant HAL should have defined +// HAL_CONTEXT_OTHER_SIZE +#ifndef HAL_CONTEXT_OTHER_SIZE + .macro hal_context_other_save_caller areg=%sp + .endm + .macro hal_context_other_load_caller areg=%sp + .endm + .macro hal_context_other_save_callee areg=%sp + .endm + .macro hal_context_other_load_callee areg=%sp + .endm + .macro hal_context_other_save_all areg=%sp + .endm + .macro hal_context_other_load_all areg=%sp + .endm +#endif + +// ---------------------------------------------------------------------------- +// LOAD_CONTEXT is called to start a new thread, usually only during system +// startup. +// +// void hal_thread_load_context(void* sp) + + FUNC_START(hal_thread_load_context) + move.l 4(%sp),%sp + hal_context_other_load_all + hal_context_fpu_load_all + movem.l hal_context_integer_offset(%sp),%d0-%d7/%a0-%a6 + add.l #hal_context_rte_adjust, %sp + rte + +// ---------------------------------------------------------------------------- +// void hal_thread_switch_context(void** from, void* to) + + FUNC_START(hal_thread_switch_context) + + // Space for the saved thread context. The PC is already on the + // stack. "from" is on the stack immediately after the context, + // then "to". + mov.l 4(%sp),%a0 + sub.l # (hal_context_size - 4), %sp + mov.l %sp, 0(%a0) + +#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + // Save all the callee-save integer registers, so that they become + // available to the other macros. + movem.l %d2-%d7, hal_context_integer_d2_offset(%sp) + movem.l %a2-%a6, hal_context_integer_a2_offset(%sp) + + // The status register must be saved here, since loading a thread + // context always involves an rte instruction. The details are + // variant-specific. + hal_context_pcsr_save_sr %sp,0,%d0 -/***************************************************************************** -hal_m68k_setjmp -- Generic setjmp for the m68k architecture + // Now the fpu and other contexts can be saved. All registers + // are available. + hal_context_fpu_save_callee + hal_context_other_save_callee +#else + movem.l %d0-%d7/%a0-%a6, hal_context_integer_offset(%sp) + hal_context_pcsr_save_sr %sp,0,%d0 + hal_context_fpu_save_all + hal_context_other_save_all +#endif + + // All thread state has now been saved, so switch to the new one. + mov.l (hal_context_size+4)(%sp),%sp + +#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + hal_context_other_load_callee + hal_context_fpu_load_callee + movem.l hal_context_integer_d2_offset(%sp),%d2-%d7 + movem.l hal_context_integer_a2_offset(%sp),%a2-%a6 +#else + hal_context_other_load_all + hal_context_fpu_load_all + movem.l hal_context_integer_offset(%sp),%d0-%d7/%a0-%a6 +#endif -externC int hal_m68k_setjmp(hal_jmp_buf env); + add.l #hal_context_rte_adjust, %sp + rte + +// ---------------------------------------------------------------------------- +// setjmp()/longjmp(). See hal_arch.h for details. +// +// int hal_m68k_setjmp(hal_jmp_buf); +// void hal_m68k_longjmp(hal_jmp_buf, val) + + FUNC_START_WEAK(hal_m68k_setjmp) + lea.l 4(%sp),%a1 // return stack pointer. longjmp() does an indirect jmp, not an rts + move.l 0(%a1),%a0 // the jmp_buf structure + move.l 0(%sp),0(%a0) // return pc + move.l %a1,4(%a0) + movem.l %d2-%d7/%a2-%a6,8(%a0) // 11 longs, occupying offsets 8 to 51 +#ifdef CYGINT_HAL_M68K_VARIANT_FPU + fmovem.x %fp2-%fp7,52(%a0) +#endif + clr.l %d0 // setjmp() always returns 0 + rts + + FUNC_START_WEAK(hal_m68k_longjmp) + move.l 8(%sp),%d0 // val argument, and hence return value + move.l 4(%sp),%a0 // The jmp_buf structure + movem.l 8(%a0),%d2-%d7/%a2-%a6 +#ifdef CYGINT_HAL_M68K_VARIANT_FPU + fmovem.x 52(%a0),%fp2-%fp7 +#endif + move.l 0(%a0),%a1 // The return pc + move.l 4(%a0),%sp + jmp (%a1) -INPUT: +// ---------------------------------------------------------------------------- +// Synchronous exceptions. Interrupts are disabled because that could confuse +// some code like gdb stubs (breakpoints also involve synchronous exceptions). +// Full state is saved on the current stack, then usually we switch to the +// interrupt stack and handle the rest of the exception there. That avoids +// having to worry about gdb stubs stack requirements in every thread context. +// +// It is assumed that on entry there is pc/sr context information already +// on the stack. Some or all of this will have been provided by the hardware. +// Other bits, e.g. the specific exception number, may have been pushed by +// software that then jumped here. The hardware may also have pushed some +// additional state which has already been removed or stashes elsewhere, +// to keep things simple. + + .extern hal_m68k_exception_handler + + FUNC_START(hal_m68k_exception_vsr) + mov.w #0x2700, %sr + sub.l #hal_context_pcsr_offset, %sp + + // If CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT is enabled + // then only caller-save registers need to be saved here, but + // exceptions should be rare and the additional info may prove + // useful to higher-level code. + movem.l %d0-%d7/%a0-%a6, hal_context_integer_offset(%sp) + hal_context_fpu_save_all + hal_context_other_save_all + + // Remember the current stack pointer in a callee-save register, + // which have all been saved anyway. That makes it easier to restore + // the stack later. + move.l %sp,%a2 - 0(%sp): return address - - 4(%sp): env - address of a hal_jmp_buf structure - -OUTPUT: +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + // Do we need to switch to the interrupt stack? + cmpa.l _HAL_M68K_INTERRUPT_STACK_, %sp + jbgt 1f + cmpa.l _HAL_M68K_INTERRUPT_STACK_BASE_, %sp + jbge 2f +1: + mova.l _HAL_M68K_INTERRUPT_STACK_, %sp +2: +#endif + // Zero out the frame pointer to encourage GDB to backtrace correctly + suba.l %a6, %a6 + + // Now call into C with a single argument, the HAL_SavedRegisters + mov.l %a2,-(%sp) + jbsr hal_m68k_exception_handler - d0, d1, a0, a1 are ours to abuse. - -RETURN VALUE: + // We can switch back to the right stack by re-using a2, irrespective + // of whether or not we switched to the interrupt stack. + move.l %a2,%sp + + // Restore the entire state. In theory only the callee-save registers + // should have changed, but some others may have been manipulated by + // gdb. + hal_context_other_load_all + hal_context_fpu_load_all + movem.l hal_context_integer_offset(%sp), %d0-%d7/%a0-%a6 + add.l #hal_context_rte_adjust, %sp + rte + +// ---------------------------------------------------------------------------- +// Interrupt handling. +// +// The current stack may be a thread stack or the interrupt stack. +// On some variants this code will be called directly by the hardware. +// On others there will have been a trampoline doing some stack +// manipulation and then jumping here. We assume that the stack is +// properly aligned and that the pc/sr part has been correctly saved. - This routine always returns zero in d0.l. + FUNC_START(hal_m68k_interrupt_vsr) + +#ifndef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING + // If nesting is not of interest then just disable all interrupts. + // Otherwise interrupt nesting is controlled via the M68K IPL + move.w #0x2700, %sr +#endif -*****************************************************************************/ -FUNC_START(hal_m68k_setjmp) + sub.l # hal_context_pcsr_offset, %sp +#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + // Even for a minimum context the callee-save a2 register + // is saved. This makes it easier to restore the stack + // to the right place after the ISR call, allowing for + // the optional interrupt stack. + movem.l %d0-%d1,hal_context_integer_d0_offset(%sp) + movem.l %a0-%a2,hal_context_integer_a0_offset(%sp) + hal_context_fpu_save_caller %sp + hal_context_other_save_caller %sp +#else + movem.l %d0-%d7/%a0-%a6, hal_context_integer_d0_offset(%sp) + hal_context_fpu_save_all %sp + hal_context_other_save_all %sp +#endif - lea.l 4(%sp),%a1 /* Get a pointer to the position */ - /* of the stack pointer before this */ - /* call was made. IMPORTANT: The */ - /* longjmp routine and the */ - /* exception handler assume that */ - /* saved stack pointers point to */ - /* the location of the stack before */ - /* the routine/exception occurred. */ +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + // Let gdb stubs know which thread was interrupted, in case this + // interrupt was a ctrl-C. + .extern hal_saved_interrupt_state + move.l %sp, hal_saved_interrupt_state +#endif + + // d0/d1/a0/a1/a2 are now available. + // We want to extract the ISR vector while it is readily accessible. + // The details depend the particular M68K variant. The result should + // be the vector << 2 to facilitate indexing. On some processors that + // actually requires less code than getting the vector itself. + hal_context_extract_isr_vector_shl2 %sp,0,%d0 + +#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR) + // We need to call cyg_instrument(INTR.RAISE, vector, intr_number) + // The actual interrupt number is not readily available, it depends + // on the variant and possibly the platform, so just instrument 0 + // instead. The vector is preserved in callee-save a2 since it may + // take several instructions to refetch it. + movea.l %d0, %a2 + lsr.l #2, %d0 + move.l #0, -(%sp) + move.l %d0, -(%sp) + move.l #0x0301, -(%sp) + jbsr cyg_instrument + add.l #12, %sp + move.l %a2, %d0 +#endif + + // %d0 holds the ISR vector << 2. d1/a0/a1/a2 are available. + +#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT + // Increment the scheduler lock. In theory the ISR should not look + // at this so it could be deferred till just before the interrupt_end() + // call, but this provides protection against badly written ISR's. + // + // This is not sufficient on SMP systems. The test of the scheduler lock + // below also needs attention. + .extern cyg_scheduler_sched_lock + addq.l #1, cyg_scheduler_sched_lock +#endif + + // At the end of the VSR we need to call interrupt_end(). + // The last two arguments are cyg_hal_interrupt_objects[vec] + // and the saved registers. These are pushed now, while + // vec is readily available, at the cost of a slight increase + // in interrupt latency but saving some instructions later. + move.l %sp,-(%sp) + lea cyg_hal_interrupt_objects,%a0 + move.l 0(%a0,%d0), -(%sp) - move.l (%a1),%a0 /* Get a pointer to the buffer to */ - /* save our state into. */ + // We want to be able to restore the stack pointer to this location, + // irrespective of whether or not an interrupt stack is being used. + // Store it in a callee-save register. + movea.l %sp, %a2 + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + // Switch to the interrupt stack if we are not already running there. + cmpa.l _HAL_M68K_INTERRUPT_STACK_, %sp + jbgt 1f + cmpa.l _HAL_M68K_INTERRUPT_STACK_BASE_, %sp + jbge 2f +1: + movea.l _HAL_M68K_INTERRUPT_STACK_, %sp +2: +#endif + // FIXME: Some variation of the following should be considered to ensure that + // GDB can't get permanently lost when doing a backtrace from within an ISR. +#if 0 && defined(CYGPKG_INFRA_DEBUG) && !defined(CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT) + // Zero out the frame pointer to encourage GDB to backtrace correctly + // But only if explicitly debugging so that we don't adversely affect + // critical ISR latency + move.w #0,%a6 +#endif - movem.l %d2-%d7/%a2-%a6,(%a0) /* Write all of the preserved */ - lea (11*4)(%a0),%a0 /* registers, the stack pointer, */ - move.l %a1,(%a0)+ /* and the return address into the */ - move.l (%sp),(%a0) /* structure. */ + // d0 is the isr vector << 2. a2 holds a saved stack pointer. d1/a0/a1 are available. + // We need to call (*cyg_hal_interrupt_handlers[vec])(vec, cyg_hal_interrupt_data[vec]) + lea cyg_hal_interrupt_data,%a0 + move.l 0(%a0,%d0),-(%sp) + lea cyg_hal_interrupt_handlers,%a0 + move.l 0(%a0,%d0),%a1 + lsr.l #2,%d0 + move.l %d0,-(%sp) + jbsr (%a1) + + // We now want to return to the right position on the current + // stack, or to the thread stack if we switched to the interrupt + // stack. + movea.l %a2, %sp - moveq.l #0,%d0 /* Load a zero return value and */ - rts /* return. */ + // Next we need to call interrupt_end(). If the scheduler was unlocked + // at the time of the interrupt then that will run the DSRs, possibly + // cause a context switch, and eventually return to this VSR. If the + // scheduler was already locked then interrupt_end() will return to + // the VSR almost immediately. The IPL level will be restored when + // the VSR executes the final rte. + // + // DSRs should run with interrupts re-enabled. Ideally we want to + // run them with the IPL level of the interrupted thread, and at + // the end reset the IPL level to what it is now. That way this + // VSR gets to return, without risk of unconstrained stack usage. + // However this is very hard: currently the desired IPL levels + // cannot be passed on the stack; they cannot be passed via globals + // either because of the possibility of a context switch. + // + // Instead there is a defined IPL level for running all DSRs. + // HAL_INTERRUPT_STACK_CALL_PENDING_DSRs() sets the IPL level to + // that value, and restores the IPL level when done. For most + // applications that will be fine, but it does make it more + // difficult to manipulate IPL levels on a per-thread level + // or anything similarly fancy. -/***************************************************************************** -hal_m68k_longjmp -- Generic longjmp for the m68k architecture + // We need to call interrupt_end(isr_return, cyg_hal_interrupt_objects[vec], saved_state_pointer) + // The last two have already been pushed onto the stack. d0 holds the return value. + move.l %d0,-(%sp) + jbsr interrupt_end + add.l #12,%sp -externC void hal_m68k_longjmp(hal_jmp_buf env, int val); - -INPUT: +#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + hal_context_other_load_caller %sp + hal_context_fpu_load_caller %sp + movem.l hal_context_integer_a0_offset(%sp),%a0-%a2 + movem.l hal_context_integer_d0_offset(%sp),%d0-%d1 +#else + hal_context_other_load_all %sp + hal_context_fpu_load_all %sp + movem.l hal_context_integer_d0_offset(%sp),%d0-%d7/%a0-%a6 +#endif + add.l #hal_context_rte_adjust,%sp + rte - 0(%sp): return address +// ---------------------------------------------------------------------------- +// On configurations with an interrupt stack HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() +// is used to run the DSRs on the interrupt stack rather than the thread stack, +// reducing stack size requirements for the latter. It is called only on a thread +// stack. In addition to the stack switch the IPL level is manipulated here, +// ensuring that DSRs run with interrupts enabled. +// +// On other architectures HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() is only called +// when a separate interrupt stack is used. If the interrupt stack is disabled +// then DSRs run with interrupts disabled, which is a bad idea. On the M68K +// HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() is always defined, thus sorting out +// the interrupt level, but only does the stack switch if an interrupt stack +// is actually being used. - 4(%sp): env - address of a hal_jmp_buf structure + .extern hal_m68k_dsr_ipl_level + .extern cyg_interrupt_call_pending_DSRs + + FUNC_START(hal_interrupt_stack_call_pending_DSRs) +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + // Use callee-save registers to store the current stack and status register + // Also store the frame pointer so we can zero it to improve GDB debugging backtraces + move.l %a2,-(%sp) + move.l %d2,-(%sp) + move.l %a6,-(%sp) + movea.l %sp,%a2 + move.w %sr,%d2 + suba.l %a6,%a6 - 8(%sp): val - the non-zero value to return - -OUTPUT: + // There is a problem if the configuration contains the kernel but interrupts + // are enabled while still running the startup code. The kernel's interrupt_end() + // rather than the driver API's will be used, so this code gets to run. We now + // get to switch to the interrupt stack while still on the startup stack, which + // is a shame since the two are the same. This could be easily fixed by checking + // the current stack as happens in the interrupt_vsr, but at the cost of an + // extra four instructions in the DSR path. The scenario should probably not + // arise so those four instructions are left out for now. + movea.l _HAL_M68K_INTERRUPT_STACK_, %sp + move.l hal_m68k_dsr_ipl_level, %d0 + move.w %d0, %sr + + jbsr cyg_interrupt_call_pending_DSRs - d0, d1, a0, a1 are ours to abuse. + move.w %d2, %sr + movea.l %a2, %sp + movea.l (%sp)+,%a6 + move.l (%sp)+,%d2 + movea.l (%sp)+,%a2 + rts +#else + move.l %d2, -(%sp) + move.w %sr, %d2 + move.l hal_m68k_dsr_ipl_level, %d0 + move.w %d0, %sr + jbsr cyg_interrupt_call_pending_DSRs + move.w %d2, %sr + move.l (%sp)+, %d2 + rts +#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + + +// ---------------------------------------------------------------------------- +// A dummy entry point for unused entries in the system exception vector. -RETURN VALUE: + FUNC_START(hal_m68k_rte) + rte - This routine always returns the value from the val parameter in d0.l -and to the location of the PC in the env structure. +// ---------------------------------------------------------------------------- +// Fast implementations of lsbit_index() and msbit_index() -*****************************************************************************/ -FUNC_START(hal_m68k_longjmp) + FUNC_START(hal_lsbit_index) + clr.l %d0 // result + mov.l 4(%sp),%d1 // mask + bne 1f // special case for 0 + subq.l #1,%d0 // lsbit_index(0) -> -1 + rts +1: + tst.w %d1 // anything set in the bottom 16 bits? + bne 2f + swap %d1 // the top 16 bits only are of interest + moveq.l #16, %d0 +2: + tst.b %d1 // anything set in the bottom 8 bits? + bne 3f + addq.l #8, %d0 // bottom byte is 0, switch to next byte + lsr.l #8, %d1 +3: + move.l %d1, %a0 // backup current data, so that we can manipulate it + and.l #0x0F, %d1 // anything in the bottom nibble? + bne 4f + move.l %a0, %d1 // nope, restore and use the next nibble + lsr.l #4, %d1 + and.l #0x0F, %d1 + addq.l #4, %d0 +4: + // The bottom nibble contains a number between 1 and 15 + // (not 0, that would have been caught by the test at the top). + lea 5f, %a0 + mov.b 0(%a0,%d1),%d1 // only zap bottom byte, the other bytes are already 0 + add.l %d1,%d0 + rts +5: + // Every odd number has an index of 0. The first entry is irrelevent. + .byte 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 - move.l 8(%sp),%d0 /* Load the return value */ - /* parameter. */ - - move.l 4(%sp),%a0 /* Get a pointer to the buffer to */ - /* read our state from. */ + FUNC_START(hal_msbit_index) + clr.l %d0 // result + mov.l 4(%sp), %d1 // mask + bne 1f // special case for 0 + subq.l #1, %d0 // msbit_index(0) -> -1 + rts +1: + cmpi.l #0x0000FFFF,%d1 + bls 2f + moveq.l #16,%d0 + clr.w %d1 + swap %d1 +2: + cmpi.l #0x00FF, %d1 + bls 3f + addq.l #8, %d0 + lsr.l #8, %d1 +3: + cmpi.l #0x000F, %d1 + bls 4f + addq.l #4, %d0 + lsr.l #4, %d1 - movem.l (%a0),%d2-%d7/%a2-%a6 /* Load our preserved registers, */ - lea (11*4)(%a0),%a0 /* stack pointer and return address */ - move.l (%a0)+,%d1 /* from the structure. */ - move.l (%a0),%a1 +4: + lea 5f, %a0 + mov.b 0(%a0,%d1), %d1 + add.l %d1,%d0 + rts + +5: + .byte 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 - move.l %d1,%sp /* Set the stack pointer from the */ - jmp (%a1) /* structure as out current stack */ - /* pointer and jump to the return */ - /* address from the structure. */ +// ---------------------------------------------------------------------------- +// Profiling support. When code is compiled with -pg the compiler inserts +// calls to mcount() at the start of each function. This can be used to +// build a callgraph of the application. mcount() is tied to the compiler +// internals and does not always use standard calling conventions. +// +// mcount() should call __profile_mcount() with two arguments, caller_pc +// and callee_pc, where callee_pc refers to the function that calls +// mcount() and caller_pc refers to the place where that function is +// called from. callee_pc is readily accessed relative to sp, caller_pc +// can be accessed using the frame pointer. This assumes the code has +// not been built with -fomit-frame-pointer, a safe assumption since +// the compiler disallows combining -pg and -fomit-frame-pointer. +// +// The m68k compiler appears to implement mcount() a bit differently +// from other targets. It reserves a word for every function entry +// point which presumably is intended to act as the start of a linked +// list chain. On other targets the PC is used to index a hash table +// which contains the start of that linked list. That extra word is +// not used for eCos profiling since it would require customizing the +// profiling package on a per-target basis, so unfortunately the +// memory is wasted. +// +// It is assumed that d0/d1/a0/a1 (the callee-save registers) are +// available. a0 is certainly available because that is used to hold +// the above per-function word. If the assumption is false then this +// would have to save d0/d1/a1 because the C __profile_mcount() could +// zap them. +// +// This code is conditional on CYGPKG_PROFILE_GPROF since that provides +// the implementation of __profile_mcount. +#ifdef CYGPKG_PROFILE_GPROF + FUNC_START(mcount) + // __profile_mcount() should be called with interrupts disabled. + move.w %sr,%d0 + move.l %d0,-(%sp) + // The callee-pc corresponds to the return address on the stack + move.l 4(%sp),%a0 + move.l %a0,-(%sp) + // The caller-pc is accessible relative to the frame pointer a6 + move.l 4(%a6),%a0 + move.l %a0,-(%sp) + + move.w #0x2700, %sr + jbsr __profile_mcount - - + move.l 8(%sp),%d0 + add.l #12, %sp + move.w %d0,%sr + + rts +#endif + + .end
new file mode 100644 --- /dev/null +++ b/packages/hal/m68k/arch/current/src/hal_m68k.c @@ -0,0 +1,224 @@ +//========================================================================== +// +// hal_m68k.c +// +// M68K HAL miscellaneous C functions +// +//========================================================================== +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003,2004,2006,2008 Free Software Foundation, Inc. +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//###DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +// +//###DESCRIPTIONEND#### +//======================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/hal_m68k.h> + +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/infra/diag.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/hal_stub.h> + +// ---------------------------------------------------------------------------- +// Interrupt support. +// +// Space for the interrupt data. These are updated by macros in hal_intr.h +volatile CYG_ADDRESS cyg_hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +volatile CYG_ADDRWORD cyg_hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; +volatile CYG_ADDRESS cyg_hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; + +// A status register value that should be used while running DSRs. +cyg_uint32 hal_m68k_dsr_ipl_level = 0x2000 | (CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL << 8); + +// In virtual vector configurations we can get apparently spurious +// interrupts in application space when the interrupt will be serviced +// by RedBoot instead. Hence the virtual vector code in the common HAL +// provides hal_default_isr() which gets installed as the default +// handler for all interrupts. If it turns out that RedBoot does not +// recognize the interrupt either, i.e. it really is spurious, then +// the virtual vector code will call hal_arch_default_isr(). +// +// In non-virtual vector configurations hal_default_isr() needs to +// be provided by the architecture/variant/processor/platform HAL +// on the off-chance that the interrupt is not entirely spurious +// and some useful processing can take place. + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT +# ifndef _HAL_M68K_HAL_ARCH_DEFAULT_ISR_DEFINED_ +cyg_uint32 +hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + CYG_FAIL("Spurious interrupt!"); + return 0; +} +# endif +#else +# ifndef _HAL_M68K_HAL_DEFAULT_ISR_DEFINED_ +cyg_uint32 +hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + CYG_FAIL("Spurious interrupt!"); + return 0; +} +# endif +#endif + +// ---------------------------------------------------------------------------- +// Exception handling. The assembler routine calls this C function as +// soon as possible. Usually exceptions are passed to gdb stubs - if +// this application does not have gdb stubs included then the relevant +// entries in the exception vector table will still belong to the stubs. + + +void +hal_m68k_exception_handler(HAL_SavedRegisters* regs) +{ +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + + // If we caught an exception inside the stubs, see if we were expecting it + // and if so jump to the saved address + extern void* volatile __mem_fault_handler; + if (__mem_fault_handler) { + regs->pc = (CYG_ADDRWORD)__mem_fault_handler; + return; // Caught an exception inside stubs + } + + _hal_registers = regs; + __handle_exception(); + +#elif defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && defined(CYGPKG_HAL_EXCEPTIONS) + + CYG_WORD code; + HAL_CONTEXT_PCSR_GET_EXCEPTION(regs, code); + cyg_hal_deliver_exception(code, (CYG_ADDRWORD) regs); + +#else + + CYG_FAIL("Exception!!!"); + +#endif +} + +// ---------------------------------------------------------------------------- +// C++ constructor support. The constructors are run in a separate function +// so that a breakpoint can be set, at the cost of a couple of extra bytes +// of code. +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG +cyg_bool cyg_hal_stop_constructors = 0; +#endif + +typedef void (*pfunc)(void); +extern pfunc __CTOR_LIST__[]; +extern pfunc __CTOR_END__[]; + +void +cyg_hal_invoke_constructors(void) +{ +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG + static pfunc* p = &__CTOR_END__[-1]; + cyg_hal_stop_constructors = 0; + for ( ; p >= __CTOR_LIST__; p--) { + (*p)(); + if (cyg_hal_stop_constructors) { + p--; + break; + } + } +#else + pfunc* p; + for ( p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) { + (*p)(); + } +#endif +} + +// ---------------------------------------------------------------------------- +// This entry point is called from vectors.S as soon as the C environment +// has been set up. We are running on the startup stack, interrupts are +// disabled, and the hardware is only minimally initialized. Most of +// the initialization will usually be done by the platform HAL. + +externC void cyg_start(void); + +void +hal_m68k_c_startup(void) +{ + int i; + + for (i = 0; i < CYGNUM_HAL_ISR_COUNT; i++) { + cyg_hal_interrupt_handlers[i] = (CYG_ADDRESS) &hal_default_isr; + } + +#ifdef HAL_M68K_VAR_INIT + HAL_M68K_VAR_INIT(); +#endif +#ifdef HAL_M68K_PROC_INIT + HAL_M68K_PROC_INIT(); +#endif +#ifdef HAL_M68K_PLATFORM_INIT + HAL_M68K_PLATFORM_INIT(); +#endif + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + hal_if_init(); +#endif +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + initialize_stub(); +#endif +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) + { + extern void hal_ctrlc_isr_init(void); + hal_ctrlc_isr_init(); + } +#endif + + cyg_hal_invoke_constructors(); + +#ifdef HAL_M68K_VAR_INIT2 + HAL_M68K_VAR_INIT2(); +#endif +#ifdef HAL_M68K_PROC_INIT2 + HAL_M68K_PROC_INIT2(); +#endif +#ifdef HAL_M68K_PLATFORM_INIT2 + HAL_M68K_PLATFORM_INIT2(); +#endif + + // And call into application-level code + cyg_start(); + for ( ; ; ); +}
deleted file mode 100644 --- a/packages/hal/m68k/arch/current/src/hal_misc.c +++ /dev/null @@ -1,195 +0,0 @@ -//========================================================================== -// -// hal_misc.c -// -// HAL miscellaneous functions -// -//========================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with eCos; if not, write to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// As a special exception, if other files instantiate templates or use macros -// or inline functions from this file, or you compile this file and link it -// with other works to produce a work based on this file, this file does not -// by itself cause the resulting work to be covered by the GNU General Public -// License. However the source code for this file must still be made available -// in accordance with section (3) of the GNU General Public License. -// -// This exception does not invalidate any other reasons why a work based on -// this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ -// ------------------------------------------- -//####ECOSGPLCOPYRIGHTEND#### -//========================================================================== - -#include <pkgconf/hal.h> - -#include <cyg/infra/cyg_type.h> -#include <cyg/infra/cyg_trac.h> // tracing macros -#include <cyg/infra/cyg_ass.h> // assertion macros -#include <cyg/infra/diag.h> // diag_printf - -#include <cyg/hal/hal_arch.h> // HAL header - -#include <cyg/hal/hal_intr.h> // VSR/ISR defines - -//-------------------------------------------------------------------------- -// ISR tables -volatile CYG_ADDRESS cyg_hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; -volatile CYG_ADDRWORD cyg_hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; -volatile CYG_ADDRESS cyg_hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; - -//-------------------------------------------------------------------------- -// VSR table - -// The cyg_hal_vsr_table table is variant-specific. Some processors must -// have the VSR table at specific locations. - -/***************************************************************************** -hal_default_exception_handler -- First level C exception handler - - The assembly default VSR handler calls this routine to handler the -exception. When this routine returns, the state is restored to the state -pointed to by regs. - - We declare this routine as weak so that other handlers can easily -become the default exception handler. - -INPUT: - - vector: The exception vector number. - - regs: A pointer to the saved state. - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ - -externC void -hal_default_exception_handler(CYG_WORD vector, HAL_SavedRegisters *regs) - __attribute__ ((weak)); - -void hal_default_exception_handler(CYG_WORD vector, HAL_SavedRegisters *regs) -{ - -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - externC void __handle_exception(void); - externC HAL_SavedRegisters * _hal_registers; - - // Set the pointer to the registers of the current exception - // context. At entry the GDB stub will expand the - // HAL_SavedRegisters structure into a (bigger) register array. - _hal_registers = regs; - - __handle_exception(); - -#elif defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ - defined(CYGPKG_HAL_EXCEPTIONS) - - // We should decode the vector and pass a more appropriate - // value as the second argument. For now we simply pass a - // pointer to the saved registers. We should also divert - // breakpoint and other debug vectors into the debug stubs. - - cyg_hal_deliver_exception(vector, (CYG_ADDRWORD)regs); - -#else - - CYG_FAIL("Exception!!!"); - -#endif - - return; -} - -//--------------------------------------------------------------------------- -// Default ISRs - -externC cyg_uint32 -hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) -{ - diag_printf("Spurious Interrupt: %d\n", vector); - -// CYG_FAIL("Spurious Interrupt!!!"); - return 0; -} - -//--------------------------------------------------------------------------- -// Idle thread action - -void -hal_idle_thread_action( cyg_uint32 count ) -{ -} - -//--------------------------------------------------------------------------- -// Determine the index of the ls bit of the supplied mask. - -cyg_uint32 -hal_lsbit_index(cyg_uint32 mask) -{ - cyg_uint32 n = mask; - - static const signed char tab[64] = - { -1, 0, 1, 12, 2, 6, 0, 13, 3, 0, 7, 0, 0, 0, 0, 14, 10, - 4, 0, 0, 8, 0, 0, 25, 0, 0, 0, 0, 0, 21, 27 , 15, 31, 11, - 5, 0, 0, 0, 0, 0, 9, 0, 0, 24, 0, 0 , 20, 26, 30, 0, 0, 0, - 0, 23, 0, 19, 29, 0, 22, 18, 28, 17, 16, 0 - }; - - n &= ~(n-1UL); - n = (n<<16)-n; - n = (n<<6)+n; - n = (n<<4)+n; - - return tab[n>>26]; -} - -//--------------------------------------------------------------------------- -// Determine the index of the ms bit of the supplied mask. - -cyg_uint32 -hal_msbit_index(cyg_uint32 mask) -{ - cyg_uint32 x = mask; - cyg_uint32 w; - - // Phase 1: make word with all ones from that one to the right. - x |= x >> 16; - x |= x >> 8; - x |= x >> 4; - x |= x >> 2; - x |= x >> 1; - - // Phase 2: calculate number of "1" bits in the word. - w = (x & 0x55555555) + ((x >> 1) & 0x55555555); - w = (w & 0x33333333) + ((w >> 2) & 0x33333333); - w = w + (w >> 4); - w = (w & 0x000F000F) + ((w >> 8) & 0x000F000F); - return (cyg_uint32)((w + (w >> 16)) & 0xFF); - -} - -//--------------------------------------------------------------------------- -
deleted file mode 100644 --- a/packages/hal/m68k/arch/current/src/hal_startup.c +++ /dev/null @@ -1,262 +0,0 @@ -//========================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with eCos; if not, write to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// As a special exception, if other files instantiate templates or use macros -// or inline functions from this file, or you compile this file and link it -// with other works to produce a work based on this file, this file does not -// by itself cause the resulting work to be covered by the GNU General Public -// License. However the source code for this file must still be made available -// in accordance with section (3) of the GNU General Public License. -// -// This exception does not invalidate any other reasons why a work based on -// this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ -// ------------------------------------------- -//####ECOSGPLCOPYRIGHTEND#### -//========================================================================== - -#include <pkgconf/hal.h> -#include <cyg/hal/hal_startup.h> -#include <cyg/hal/hal_memmap.h> -#include <cyg/hal/hal_intr.h> -#include <cyg/hal/hal_diag.h> // hal_diag_init -#include <cyg/infra/diag.h> // diag_printf -#include <string.h> // memcpy, memset - -externC void cyg_start(void); -externC void hw_vsr_reset(void); - -#define CYG_HAL_RESET_DEBUG_ENABLE -#ifdef CYG_HAL_RESET_DEBUG_ENABLE -#define CYG_HAL_RESET_DEBUG diag_printf -#else -#define CYG_HAL_RESET_DEBUG() -#endif // CYG_HAL_RESET_DEBUG_ENABLE - -/***************************************************************************** -hal_vsr_init -- Initialize the vector table - -INPUT: - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ -static void hal_vsr_init(void) -{ - - /* Initialize the HAL's vector table with the ROM vector table. */ - - memcpy((void*)cyg_hal_vsr_table, __romvec_start, - (size_t)sizeof(cyg_hal_vsr_table)); - -} - -/***************************************************************************** -hal_vsr_init -- Initialize the ISRs - -INPUT: - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ -static void hal_isr_init(void) -{ - int_t i; - - // Initialize all ISR entries to default. - - for (i = 0; i < CYGNUM_HAL_ISR_COUNT; i++) - { - cyg_hal_interrupt_handlers[i] = (CYG_ADDRESS) &hal_default_isr; - cyg_hal_interrupt_data[i] = (CYG_ADDRWORD)0; - cyg_hal_interrupt_objects[i] = (CYG_ADDRESS)0; - } -} - -/***************************************************************************** -hal_init_ram_sections -- Initialize the RAM sections - - Initialize all RAM sections that the C code relies on. data, bss, -sbss. - -INPUT: - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ -static void hal_init_ram_sections(void) -{ - - // Initialize the RAM data section from the ROM image of the data - // section. - - memcpy(__ram_data_start, __rom_data_start, (size_t)__ram_data_size); - - // Initialize the bss and sbss sections to zero. - - memset(__bss_start, 0, (size_t)__bss_size); - memset(__sbss_start, 0, (size_t)__sbss_size); -} - -/***************************************************************************** -cyg_hal_invoke_constructors -- Call static constructors - -INPUT: - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ -#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG -cyg_bool cyg_hal_stop_constructors; -#endif - -typedef void (*pfunc) (void); -extern pfunc __CTOR_LIST__[]; -extern pfunc __CTOR_END__[]; - -static void cyg_hal_invoke_constructors(void) -{ -#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG - static pfunc *p = &__CTOR_END__[-1]; - - cyg_hal_stop_constructors = 0; - for (; p >= __CTOR_LIST__; p--) { - (*p) (); - if (cyg_hal_stop_constructors) { - p--; - break; - } - } -#else - pfunc *p; - - for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) - (*p) (); -#endif -} - -/***************************************************************************** -hal_reset -- Reset vector routine - - This routine must be called with interrupts disabled and will never -return. - - Only the assembly reset vector routine should call this routine. - -INPUT: - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ -void hal_reset(void) CYGBLD_ATTRIB_NORET; -void hal_reset(void) -{ - const char * fname; - - fname = __FUNCTION__; - - // Initialize the RAM sections that the rest of the C code requires. - - hal_init_ram_sections(); - - // It is now safe to call C functions which may rely on initialized - // data. - - // Initialize the ISR and VSR tables. - - hal_isr_init(); - hal_vsr_init(); - - // Do any variant-specific reset initialization. - - var_reset(); - - // Initialize the diagnostics IO. - - HAL_DIAG_INIT(); - CYG_HAL_RESET_DEBUG("%s: RESET\r\n", fname); - - // Call C++ constructors. - - CYG_HAL_RESET_DEBUG("%s: calling cyg_hal_invoke_constructors\r\n", fname); - cyg_hal_invoke_constructors(); - - // It should be safe to enable interrupts now. - - CYG_HAL_RESET_DEBUG("%s: lowering interrupt mask\r\n", fname); - HAL_ENABLE_INTERRUPTS(); - - // Call cyg_start. This routine should not return. - - CYG_HAL_RESET_DEBUG("%s: calling cyg_start\r\n", fname); - cyg_start(); - - // If we return, loop and print out a message. - - HAL_DIAG_INIT(); - for (;;) - { - CYG_HAL_RESET_DEBUG("%s: cyg_start returned!\r\n", fname); - } -} - -/***************************************************************************** -hal_hw_reset -- Simulate a hardware reset - - This routine will never return. - -INPUT: - -OUTPUT: - -RETURN VALUE: - - None - -*****************************************************************************/ -void hal_hw_reset(void) -{ - - // Give control to the reset vector handler. - - hw_vsr_reset(); -} -
--- a/packages/hal/m68k/arch/current/src/m68k.ld +++ b/packages/hal/m68k/arch/current/src/m68k.ld @@ -1,15 +1,14 @@ /*========================================================================== // -// m68k.ld +// m68k.ld // -// Linker script +// Linker script // //========================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2004,2005,2006,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -32,24 +31,29 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== +//###DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +// +//###DESCRIPTIONEND#### +//======================================================================== */ +#include <pkgconf/system.h> +#include <pkgconf/hal.h> +#define __LDI__ 1 +#include CYGHWR_MEMORY_LAYOUT_H + STARTUP(vectors.o) -ENTRY(__exception_reset) +ENTRY(hal_m68k_exception_reset) #ifdef EXTRAS INPUT(extras.o) #endif -#if (__GNUC__ >= 3) GROUP(libtarget.a libgcc.a libsupc++.a) -#else -GROUP(libtarget.a libgcc.a) -#endif #define ALIGN_LMA 4 #define FOLLOWING(_section_) AT ((LOADADDR (_section_) + SIZEOF (_section_) + ALIGN_LMA - 1) & ~ (ALIGN_LMA - 1)) @@ -60,146 +64,236 @@ GROUP(libtarget.a libgcc.a) # define CYG_LABEL_DEFN(_label) _label #endif +// Depending on the startup type and issues such as the memory map +// before and after any remapping, _stext should usually be defined +// either at the beginning of the .m68k_startup section or at the +// beginning of the .text section. Or conceivably somewhere else, in +// which case it is up to the platform-specific linker script or +// code to define _stext. The platform HAL can specify the desired +// behaviour via the LAYOUT_H file. +#if defined(_HAL_M68K_STEXT_AT_M68K_TEXT_) +# define _HAL_M68K_STARTUP_SECTION_STEXT_ +# define _HAL_TEXT_SECTION_STEXT_ _stext = . ; +#elif defined(_HAL_M68K_STEXT_ELSEWHERE_) +# define _HAL_M68K_STARTUP_SECTION_STEXT_ +# define _HAL_TEXT_SECTION_STEXT_ +#else +# define _HAL_M68K_STARTUP_SECTION_STEXT_ _stext = . ; +# define _HAL_TEXT_SECTION_STEXT_ +#endif + #define SECTIONS_BEGIN -#define SECTION_text(_region_, _vma_, _lma_) \ - .text _vma_ : _lma_ \ - { _stext = .; \ - *(.text*) *(.gnu.warning) *(.gnu.linkonce*) *(.init) } \ - > _region_ \ - _etext = .; PROVIDE (etext = .); +// RAM vectors, i.e. the M68K exception table, the virtual vector table, +// and possibly some data that needs to be shared between eCos and +// RedBoot. Usually this will be located at 0 but may be at another +// address via e.g. %vbr. Some platforms in some configurations may +// have an empty ram vectors section with all the work done in +// .vectors instead. The section may or may not be loadable. -#define SECTION_fini(_region_, _vma_, _lma_) \ - .fini _vma_ : _lma_ \ - { FORCE_OUTPUT; *(.fini) } \ - > _region_ +#define SECTION_ram_vectors(_region_, _vma_) \ + . = ALIGN( _vma_ , ALIGN_LMA ) ; \ + _hal_ram_vectors_section_start = . ; \ + .ram_vectors . : { KEEP (*(.ram_vectors)) } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_ram_vectors_section_end = . ; \ + _hal_ram_vectors_section_size = _hal_ram_vectors_section_end - \ + _hal_ram_vectors_section_start ; -#define SECTION_rodata1(_region_, _vma_, _lma_) \ - .rodata1 _vma_ : _lma_ \ - { FORCE_OUTPUT; *(.rodata1) } \ - > _region_ - -#define SECTION_rodata(_region_, _vma_, _lma_) \ - .rodata _vma_ : _lma_ \ - { FORCE_OUTPUT; *(.rodata*) } \ - > _region_ +// .m68k_startup usually contains only the M68K startup code. It may also +// contain the exception vectors if booting from flash and the exception +// vectors are held in flash as well. .vectors.0 is for backwards +// compatibility with older HALs. +#define SECTION_m68k_start(_region_, _vma_) \ + . = ALIGN( _vma_ , ALIGN_LMA ) ; \ + _hal_m68k_start_section_start = . ; \ + _HAL_M68K_STARTUP_SECTION_STEXT_ \ + .m68k_start . : { KEEP (*(.m68k_start)) KEEP (*(.m68k_start.*)) KEEP (*(.vectors.0)) } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_m68k_start_section_end = . ; \ + _hal_m68k_start_section_size = _hal_m68k_start_section_end - _hal_m68k_start_section_start ; -#define SECTION_fixup(_region_, _vma_, _lma_) \ - .fixup _vma_ : _lma_ \ - { __FIXUP_START__ = ABSOLUTE(.); *(.fixup) __FIXUP_END__ = ABSOLUTE(.);}\ - > _region_ - -#define SECTION_gcc_except_table(_region_, _vma_, _lma_) \ - .gcc_except_table _vma_ : _lma_ \ - { __EXCEPT_START__ = ABSOLUTE(.); *(.gcc_except_table) \ - __EXCEPT_END__ = ABSOLUTE(.);} \ - > _region_ +// Some coldfires booting from internal flash need a signature block at +// a magic location +#define SECTION_mcfxxxx_cfm_security_settings(_region_, _vma_) \ + . = ALIGN( _vma_ , ALIGN_LMA ) ; \ + _hal_mcfxxxx_cfm_security_settings_section_start = . ; \ + .mcfxxxx_cfm_security_settings . : \ + { \ + FORCE_OUTPUT; \ + KEEP (*(.mcfxxxx_cfm_security_settings)); \ + } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_mcfxxxx_cfm_security_settings_section_end = . ; \ + _hal_mcfxxxx_cfm_security_settings_section_size = _hal_mcfxxxx_cfm_security_settings_section_end - \ + _hal_mcfxxxx_cfm_security_settings_section_start ; -#define SECTION_data(_region_, _vma_, _lma_, _rom_data_addr_) \ - .data _vma_ : _lma_ \ - { \ - __ram_data_start = ABSOLUTE(.); \ - *(.data*) \ - __GOT1_START__ = ABSOLUTE(.); *(.got1) __GOT1_END__ = ABSOLUTE(.); \ - . = ALIGN (4); \ - KEEP(*( SORT (.ecos.table.*))); \ - . = ALIGN (4); \ - __CTOR_LIST__ = ABSOLUTE(.); \ - KEEP(*(SORT(.ctors*))); \ - __CTOR_END__ = ABSOLUTE(.); \ - __DTOR_LIST__ = ABSOLUTE(.); \ - KEEP(*(SORT(.dtors*))) \ - __DTOR_END__ = ABSOLUTE(.); \ - . = ALIGN(8); \ - __GOT2_START__ = ABSOLUTE(.); *(.got2) __GOT2_END__ = ABSOLUTE(.); \ - __GOT_START = ABSOLUTE(.); _GLOBAL_OFFSET_TABLE_ = ABSOLUTE(. + 32768); \ - _SDA_BASE_ = ABSOLUTE(.); *(.got.plt) *(.got) \ - __GOT_END__ = ABSOLUTE(.); *(.dynamic) \ - *(.eh_frame) \ - /* We want the small data sections together, so single-instruction */ \ - /* offsets can access them all, and initialized data all before */ \ - /* uninitialized, so we can shorten the on-disk segment size. */ \ - __SDATA_START__ = ABSOLUTE(.); *(.sdata) \ - __ram_data_end = ABSOLUTE(.); \ - __ram_data_size = ABSOLUTE (.) - ABSOLUTE(__ram_data_start); \ - } \ - > _region_ \ - __rom_data_start = ABSOLUTE(_rom_data_addr_); \ - __rom_data_size = SIZEOF(.data); \ - __rom_data_end = __rom_data_start + __rom_data_size; +// ---------------------------------------------------------------------------- +// C++ support. It should always be possible to discard the global destructors +// since eCos applications are not expected to exit. The exception handling +// support is normally needed only if linking with libstdc++, otherwise +// there is no code in the system to use the exception frame info. +#if defined(CYGINT_HAL_LINKER_SCRIPT_KEEP_DTORS) +# define _DTORS1_ \ + __DTOR_LIST__ = ABSOLUTE(.); \ + KEEP(*(SORT(.dtors*))) \ + __DTOR_END__ = ABSOLUTE(.); \ +# define _DTORS2_ +#else +# define _DTORS1_ +# define _DTORS2_ /DISCARD/ : { *(.dtors*) } +#endif + +#if defined(CYGPKG_LIBSTDCXX) || defined(CYGINT_HAL_LINKER_SCRIPT_KEEP_EH_FRAME) +# define _EH_FRAME1_(_region_) \ + .eh_frame . : { \ + FORCE_OUTPUT; __EH_FRAME_BEGIN__ = ABSOLUTE(.); \ + KEEP(*(.eh_frame)) \ + . = ALIGN(ALIGN_LMA); \ + __FRAME_END__ = ABSOLUTE(.); \ + LONG(0) \ + LONG(0) \ + } > _region_ = 0 +# define _EH_FRAME2_ +#else +# define _EH_FRAME1_(_region_) +# define _EH_FRAME2_ /DISCARD/ : { *(.eh_frame) } +#endif + +#if defined(CYGPKG_LIBSTDCXX) || defined(CYGINT_HAL_LINKER_SCRIPT_KEEP_GCC_EXCEPT_TABLE) +# define _GCC_EXCEPT_TABLE1_(_region_) \ + .gcc_except_table . : { \ + __EXCEPT_START__ = ABSOLUTE(.); \ + KEEP(*(.gcc_except_table)) *(.gcc_except_table.*) \ + __EXCEPT_END__ = ABSOLUTE(.); \ + } > _region_ +# define _GCC_EXCEPT_TABLE2_ +#else +# define _GCC_EXCEPT_TABLE1_(_region_) +# define _GCC_EXCEPT_TABLE2_ /DISCARD/ : { *(.gcc_except_table) *(.gcc_except_table.*) } +#endif -#define SECTION_sbss(_region_, _vma_, _lma_) \ - .sbss _vma_ : _lma_ \ - { __sbss_start = ABSOLUTE (.); \ - __SBSS_START__ = ABSOLUTE(.); *(.sbss) __SBSS_END__ = ABSOLUTE(.); \ - *(.scommon) \ - __sbss_end = ABSOLUTE (.); \ - __sbss_size = ABSOLUTE (.) - ABSOLUTE(__sbss_start); \ - } \ - > _region_ - -#define SECTION_bss(_region_, _vma_, _lma_) \ - .bss _vma_ : _lma_ \ - { __bss_start = ABSOLUTE (.); \ - FORCE_OUTPUT; *(.dynbss) *(.bss) *(COMMON) \ - __bss_end = ABSOLUTE (.); \ - __bss_size = ABSOLUTE (.) - ABSOLUTE(__bss_start); \ - } \ - > _region_ - -#define SECTION_stab \ - .stab 0 (NOLOAD) : \ - { \ - *(.stab) \ - } - -#define SECTION_stabstr \ - .stabstr 0 (NOLOAD) : \ - { \ - *(.stabstr) \ - } +#define SECTION_code(_region_, _vma_) \ + . = ALIGN( _vma_ , ALIGN_LMA ) ; \ + _hal_code_section_start = . ; \ + _hal_text_section_start = . ; \ + _HAL_TEXT_SECTION_STEXT_ \ + .text . : { \ + *(.text*) *(.gnu.warning) *(.gnu.linkonce.t*) *(.init) \ + . = ALIGN (4); \ + __CTOR_LIST__ = ABSOLUTE(.); \ + KEEP(*(SORT(.ctors*))); \ + __CTOR_END__ = ABSOLUTE(.); \ + . = ALIGN (4); \ + _DTORS1_ \ + } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _etext = . ; PROVIDE (etext = .) ; \ + _hal_text_section_end = . ; \ + _hal_text_section_size = _hal_text_section_end - _hal_text_section_start ; \ + .rodata . : { *(.rodata1) *(.rodata*) *(.gnu.linkonce.r.*) } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _EH_FRAME1_(_region_) \ + . = ALIGN(ALIGN_LMA) ; \ + _GCC_EXCEPT_TABLE1_(_region_) \ + . = ALIGN(ALIGN_LMA) ; \ + .rel.text : { *(.rel.text) *(.rel.text.*) *(.rel.gnu.linkonce.t*) } > _region_ \ + .rela.text : { *(.rela.text) *(.rela.text.*) *(.rela.gnu.linkonce.t*) } > _region_ \ + .rel.data : { *(.rel.data) *(.rel.data.*) *(.rel.gnu.linkonce.d*) } > _region_ \ + .rela.data : { *(.rela.data) *(.rela.data.*) *(.rela.gnu.linkonce.d*) } > _region_ \ + .rel.rodata : { *(.rel.rodata) *(.rel.rodata.*) *(.rel.gnu.linkonce.r*) } > _region_ \ + .rela.rodata : { *(.rela.rodata) *(.rela.rodata.*) *(.rela.gnu.linkonce.r*) } > _region_ \ + .rel.got : { *(.rel.got) } > _region_ \ + .fixup . : { \ + __FIXUP_START__ = ABSOLUTE(.); \ + *(.fixup) \ + __FIXUP_END__ = ABSOLUTE(.); \ + } > _region_ \ + .got . : { \ + FORCE_OUTPUT; *(.got.plt) *(.got) \ + _GOT1_START_ = ABSOLUTE (.); *(.got1) _GOT1_END_ = ABSOLUTE (.); \ + _GOT2_START_ = ABSOLUTE (.); *(.got2) _GOT2_END_ = ABSOLUTE (.); \ + } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_code_section_end = . ; \ + _hal_code_section_size = _hal_code_section_end - _hal_code_section_start ; \ + _DTORS2_ \ + _EH_FRAME2_ \ + _GCC_EXCEPT_TABLE2_ -#define SECTION_comment \ - .comment 0 (NOLOAD) : \ - { \ - *(.comment) \ - } - -#define SECTION_heap1(_region_, _vma_, _lma_, _minsize_) \ - .heap1 _vma_ : _lma_ \ - { __heap1_start = ABSOLUTE (.); \ - . += (_minsize_); \ - __heap1_end = ABSOLUTE (.); \ - __heap1_size = ABSOLUTE (.) - ABSOLUTE(__heap1_start); \ - } \ - > _region_ +#define SECTION_data(_region_, _vma_, _lma_) \ + . = ALIGN( _vma_ , ALIGN_LMA ) ; \ + _hal_data_section_start_vma = . ; \ + .data . : _lma_ { \ + *(.shdata*) *(.data*) *(.gnu.linkonce.d.*) *(.sdata) *(.gnu.linkonce.s.*) \ + . = ALIGN (4); \ + *(.2ram.*) \ + . = ALIGN (4); \ + KEEP(*( SORT (.ecos.table.*))); \ + . = ALIGN (4); \ + } > _region_ \ + . = ALIGN(ALIGN_LMA); \ + _hal_data_section_start_lma = LOADADDR(.data) ; \ + _hal_data_section_end_vma = . ; \ + _hal_data_section_size = _hal_data_section_end_vma - _hal_data_section_start_vma ; \ + _hal_data_section_end_lma = _hal_data_section_start_lma + _hal_data_section_size ; \ + _hal_bss_start = . ; \ + .sbss . : { *(.sbss) *(.gnu.linkonce.sb.*) *(.scommon) } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + .bss . : { *(.dynbss) *(.shbss) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON) } > _region_ \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_bss_end = . ; \ + _hal_bss_size = _hal_bss_end - _hal_bss_start ; -#define SECTION_uninvar(_region_, _vma_, _lma_) \ - .uninvar _vma_ : _lma_ \ - { __uninvar_start = ABSOLUTE (.); \ - FORCE_OUTPUT; *(.uninvar) \ - __uninvar_end = ABSOLUTE (.); \ - __uninvar_size = ABSOLUTE (.) - ABSOLUTE(__uninvar_start); \ - } \ - > _region_ +// Some ColdFire processors have on-chip RAM. Allocate .iram_text, .iram_data +// .iram_bss in the expected fashion. +#define SECTION_iram(_region_, _vma_, _lma_) \ + . = ALIGN( _vma_ , ALIGN_LMA ) ; \ + _hal_iram_section_start_vma = . ; \ + _hal_iram_text_section_start_vma = . ; \ + .iram_text . : _lma_ { *(.iram_text) *(.iram_text.*) } > _region_ =0 \ + _hal_iram_text_section_start_lma = LOADADDR(.iram_text) ; \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_iram_text_section_end_vma = . ; \ + _hal_iram_text_section_size = _hal_iram_text_section_end_vma - _hal_iram_text_section_start_vma ; \ + _hal_iram_text_section_end_lma = _hal_iram_text_section_start_lma + _hal_iram_text_section_size ; \ + _hal_iram_data_section_start_vma = . ; \ + .iram_data . : AT(_hal_iram_text_section_end_lma) { *(.iram_data) *(.iram_data.*) } > _region_ =0 \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_iram_data_section_start_lma = LOADADDR(.iram_data) ; \ + _hal_iram_data_section_end_vma = . ; \ + _hal_iram_data_section_size = _hal_iram_data_section_end_vma - _hal_iram_data_section_start_vma ; \ + _hal_iram_data_section_end_lma = _hal_iram_data_section_start_lma + _hal_iram_data_section_size ; \ + _hal_iram_bss_section_start = . ; \ + _iram_bss . (NOLOAD) : { *(.iram_bss) *(.iram_bss.*) } > _region_ =0 \ + . = ALIGN(ALIGN_LMA) ; \ + _hal_iram_bss_section_end = . ; \ + _hal_iram_section_end_vma = . ; \ + _hal_iram_section_size = _hal_iram_section_end_vma - _hal_iram_section_start_vma ; \ + _hal_iram_section_start_lma = LOADADDR(.iram_text) ; \ + _hal_iram_section_end_lma = _hal_iram_section_start_lma + _hal_iram_text_section_size + \ + _hal_iram_data_section_size ; -#define GENERIC_SECTION(_name_, _region_, _vma_, _lma_, _minsize_) \ - . ## _name_ _vma_ : _lma_ \ - { __ ## _name_ ## _start = ABSOLUTE (.); \ - FORCE_OUTPUT; *(. ## _name_ ## ) \ - __ ## _name_ ## _datasize = (ABSOLUTE (.) - ABSOLUTE(__ ## _name_ ## _start)); \ - . += (_minsize_) > (__ ## _name_ ## _datasize) ? (_minsize_) - (__ ## _name_ ## _datasize) : 0; \ - __ ## _name_ ## _end = ABSOLUTE (.); \ - __ ## _name_ ## _size = (ABSOLUTE (.) - ABSOLUTE(__ ## _name_ ## _start)); \ - } \ - > _region_ +#define SECTIONS_END \ + .stab 0 (NOLOAD) : { *(.stab) } \ + .stabstr 0 (NOLOAD) : { *(.stabstr) } \ + .comment 0 (NOLOAD) : { *(.comment) } \ + . = ALIGN(4); _end = .; PROVIDE (end = .); -#define SECTIONS_END \ - SECTION_stab \ - SECTION_stabstr \ - SECTION_comment \ - . = ALIGN(4); _end = .; PROVIDE (end = .); +// These macros are for backwards compatibility. Some are redundant. +#define SECTION_fixed_vectors(_region_, _vma_, _lma_) SECTION_ram_vectors(_region_, _vma_) +#define SECTION_vectors(_region_, _vma_, _lma_) SECTION_m68k_start(_region_, _vma_) +#define SECTION_text(_region_, _vma_, _lma_) SECTION_code(_region_, _vma_) +#define SECTION_rodata(_region_, _vma_, _lma_) SECTION_constants(_region_, _vma_) +#define SECTION_rodata1(_region_, _vma_, _lma_) +#define SECTION_fini(_region_, _vma_, _lma_) +#define SECTION_fixup(_region_, _vma_, _lma_) +#define SECTION_RELOCS(_region_, _vma_, _lma_) +#define SECTION_eh_frame(_region_, _vma_, _lma_) +#define SECTION_gcc_except_table(_region_, _vma_, _lma) +#define SECTION_got(_region_, _vma_, _lma_) +#define SECTION_sbss(_region_, _vma_, _lma_) +#define SECTION_bss(_region_, _vma_, _lma_) #include <pkgconf/system.h> #include CYGHWR_MEMORY_LAYOUT_LDI -
--- a/packages/hal/m68k/arch/current/src/m68k_stub.c +++ b/packages/hal/m68k/arch/current/src/m68k_stub.c @@ -1,15 +1,14 @@ -//======================================================================== +//========================================================================== // // m68k_stub.c // -// Helper functions for stub +// M68K gdb support // -//======================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- +//========================================================================== +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -// +// Copyright (C) 2003,2008 Free Software Foundation, Inc. // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. @@ -32,160 +31,138 @@ // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. -// -// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -// at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//###DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +// +//###DESCRIPTIONEND#### //======================================================================== -#include <stddef.h> - #include <pkgconf/hal.h> +#include <pkgconf/hal_m68k.h> -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#include <cyg/hal/hal_stub.h> - -#include <cyg/hal/hal_stub.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/infra/diag.h> #include <cyg/hal/hal_arch.h> #include <cyg/hal/hal_intr.h> +#include <cyg/hal/hal_if.h> +#include <cyg/hal/hal_stub.h> -#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT -#include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id -#endif - -/* Given a trap value TRAP, return the corresponding signal. */ - -int __computeSignal (unsigned int trap_number) +// Translate between the eCos save state and what is expected by the gdb +// stubs. d0-d7/a0-a6 are in the right place already. SR/PS and the program +// counter need to come from variant-specific macros. The stack pointer +// can be determined from the saved context. +externC void +hal_get_gdb_registers(CYG_ADDRWORD* gdb_regs, HAL_SavedRegisters* ecos_regs) { - switch (trap_number) - { - - case CYGNUM_HAL_VECTOR_BUSERR: - case CYGNUM_HAL_VECTOR_ADDERR: - return SIGBUS; - - case CYGNUM_HAL_VECTOR_ILLINST: - return SIGILL; - - case CYGNUM_HAL_VECTOR_ZERODIV: - /* This isn't quite accurate: this is integer division only. */ - return SIGFPE; + int sr; + int pc; + int i; + for (i = 0; i < 15; i++) { + gdb_regs[i] = ecos_regs->da[i]; + } + gdb_regs[15] = (CYG_ADDRWORD) &(ecos_regs[1]); + HAL_CONTEXT_PCSR_GET_SR(ecos_regs, sr); + HAL_CONTEXT_PCSR_GET_PC(ecos_regs, pc); + gdb_regs[16] = sr; + gdb_regs[17] = pc; +} - case CYGNUM_HAL_VECTOR_CHKINST: - case CYGNUM_HAL_VECTOR_TRAPVINST: - return SIGTRAP; +externC void +hal_set_gdb_registers(HAL_SavedRegisters* ecos_regs, CYG_ADDRWORD* gdb_regs) +{ + int i; + for (i = 0; i < 15; i++) { + ecos_regs->da[i] = gdb_regs[i]; + } + if (gdb_regs[15] != (CYG_ADDRWORD) &(ecos_regs[1])) { + CYG_FAIL("gdb has requested a thread context switch - not supported,"); + } + HAL_CONTEXT_PCSR_SET_SR(ecos_regs, gdb_regs[16]); + HAL_CONTEXT_PCSR_SET_PC(ecos_regs, gdb_regs[17]); +} - case CYGNUM_HAL_VECTOR_PRIVVIOLATION: - return SIGILL; - case CYGNUM_HAL_VECTOR_TRACE: - /* Instruction trace */ - return SIGTRAP; +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - case CYGNUM_HAL_VECTOR_L1010: - case CYGNUM_HAL_VECTOR_L1111: - case CYGNUM_HAL_VECTOR_UNINITINT: - case CYGNUM_HAL_VECTOR_SPURINT: - return SIGTRAP; - - case CYGNUM_HAL_VECTOR_TRAPFIRST ... CYGNUM_HAL_VECTOR_TRAPLAST: +externC int +__computeSignal(unsigned int trap_number) +{ + switch(trap_number) { + case CYGNUM_HAL_EXCEPTION_DATA_ACCESS: + return SIGBUS; + case CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS: + case CYGNUM_HAL_EXCEPTION_SYSTEM_ERROR: + return SIGSEGV; + case CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION: + return SIGILL; + case CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO: + return SIGFPE; + case CYGNUM_HAL_EXCEPTION_TRACE: + case CYGNUM_HAL_VECTOR_TRAP0 ... CYGNUM_HAL_VECTOR_TRAP15: + default: return SIGTRAP; - - case CYGNUM_HAL_VECTOR_AUTOVEC1 ... CYGNUM_HAL_VECTOR_AUTOVEC7: - case CYGNUM_HAL_VECTOR_INTRFIRST ... CYGNUM_HAL_VECTOR_INTRLAST: - /* External interrupt */ - return SIGINT; - - default: - return SIGTERM; } } - -/* Return the trap number corresponding to the last-taken trap. */ - -int __get_trap_number (void) +externC int +__get_trap_number(void) { - //extern int hal_m68k_trap_number; - - // The vector is not not part of the GDB register set so get it - // directly from the save context. - //return hal_m68k_trap_number; - - return 1; + int result = CYGNUM_HAL_EXCEPTION_SYSTEM_ERROR; + if ((HAL_SavedRegisters*)0 != _hal_registers) { + HAL_CONTEXT_PCSR_GET_EXCEPTION(_hal_registers, result); + } + return result; } -/* Set the currently-saved pc register value to PC. This also updates NPC - as needed. */ - -void set_pc (target_register_t pc) +externC void +set_pc(target_register_t pc) { - put_register (PC, pc); + _registers[PC] = pc; } - -/*---------------------------------------------------------------------- - * Single-step support - */ - -/* Set things up so that the next user resume will execute one instruction. - This may be done by setting breakpoints or setting a single step flag - in the saved user registers, for example. */ - -#define SR_TRACE 0x8000 - -void __single_step (void) +// Single-stepping just involves setting the trace bit in the status register +externC void +__single_step(void) { - target_register_t sr = get_register (PS); - - // Set trace flag in the exception context. - sr |= SR_TRACE; - - put_register (PS, sr); + _registers[PS] |= HAL_M68K_SR_T; } -/* Clear the single-step state. */ - -void __clear_single_step (void) +externC void +__clear_single_step(void) { - target_register_t sr = get_register (PS); - - // Clear single-step flag in the exception context. - sr &= ~SR_TRACE; - - put_register (PS, sr); + _registers[PS] &= ~HAL_M68K_SR_T; } - -void __install_breakpoints (void) -{ - /* NOP since single-step HW exceptions are used instead of - breakpoints. */ -} - -void __clear_breakpoints (void) +// This breakpoint support is (probably) not needed because +// single-stepping is supported instead. +externC void +__install_breakpoints(void) { } - -/* If the breakpoint we hit is in the breakpoint() instruction, return a - non-zero value. */ +externC void +__clear_breakpoints(void) +{ +} -int -__is_breakpoint_function () +externC int +__is_breakpoint_function(void) { - return get_register (PC) == (target_register_t)&CYG_LABEL_NAME(breakinst); + return _registers[PC] == (target_register_t)&_breakinst; } - -/* Skip the current instruction. Since this is only called by the - stub when the PC points to a breakpoint or trap instruction, - we can safely just skip 4. */ - -void __skipinst (void) +// The 68K has variable length instructions so skipping an instruction +// is messy. However __skipinst() is only used for a breakpoint +// instruction or for a trap, and these are always 2 bytes. +externC void +__skipinst(void) { - put_register (PC, get_register (PC) + 4); + _registers[PC] += 2; } -#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - +#endif
new file mode 100644 --- /dev/null +++ b/packages/hal/m68k/arch/current/src/plf_stub.h @@ -0,0 +1,72 @@ +#ifndef CYGONCE_HAL_PLF_STUB_H +#define CYGONCE_HAL_PLF_STUB_H + +//============================================================================= +// +// plf_stub.h +// +// Generic platform header for GDB stub support. +// +//============================================================================= +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003,2006,2007,2008 Free Software Foundation, Inc. +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +// +//####DESCRIPTIONEND#### +//============================================================================= + +#include <pkgconf/hal.h> +#include <cyg/infra/cyg_type.h> // CYG_UNUSED_PARAM +#include <cyg/hal/hal_arch.h> + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +//---------------------------------------------------------------------------- +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS +# define HAL_STUB_PLATFORM_INIT_SERIAL() CYG_EMPTY_STATEMENT +#else +externC void cyg_hal_plf_comms_init(void); +# define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() +#endif + +# define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) +# define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 +# define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT + +#endif +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_PLF_STUB_H +// End of plf_stub.h
new file mode 100644 --- /dev/null +++ b/packages/hal/m68k/arch/current/src/vectors.S @@ -0,0 +1,251 @@ +// #======================================================================== +// # +// # vectors.S +// # +// # M68K startup and exception handling. +// # +// #======================================================================== +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003,2004,2005,2006,2008 Free Software Foundation, Inc. +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//###DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2003-06-04 +// +//###DESCRIPTIONEND#### +//======================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/hal.h> +#include <pkgconf/hal_m68k.h> +#include CYGBLD_HAL_TARGET_H +#include <cyg/hal/hal_io.h> +#include <cyg/hal/arch.inc> + +// ---------------------------------------------------------------------------- +// These are for compatibility with older HALs +#ifdef HAL_M68K_EXCEPTION_VECTORS +# define _HAL_M68K_START_ HAL_M68K_EXCEPTION_VECTORS +# undef HAL_M68K_EXCEPTION_VECTORS +#endif +#ifdef HAL_M68K_COPY_ROM_DATA_TO_RAM +# define _HAL_M68K_COPY_ROM_DATA_TO_RAM_ 1 +# undef HAL_M68K_COPY_ROM_DATA_TO_RAM +#endif + +// ---------------------------------------------------------------------------- +// Exception vectors. Typically there are two exception vectors. There is +// one in flash which contains the h/w entry point. This is the section +// .m68k_start. Then there is the run-time set of exception vectors, typically +// held in RAM, which is the section .ram_vectors. In addition to the pointers +// to the exception and interrupt VSRs that section contains the virtual vector +// table and any data that needs to be shared between RedBoot and the application, +// for example shadow copies of read-only registers. +// +// Typical scenarios include the following: +// +// 1) _HAL_M68K_START_ code relocates the flash from its boot location of 0x0 +// to somewhere else. _HAL_M68K_PLATFORM_SETUP1_ initializes SDRAM and +// places it at 0x0. _HAL_M68K_START_ only contains the two initial exception +// vector slots for the start address and stack, the RAM vectors are fully +// populated at run-time by the architectural HAL. This is the typical +// scenario for "large" systems. +// +// 2) for "small" systems where usually there is no RedBoot and the application +// runs directly from flash, all the exception vectors also reside in flash +// and are statically initialized. _HAL_M68K_START_ contains the full set +// of vectors. +// +// 3) as a variant of (2) the run-time exception vectors may live in RAM, +// typically relocated via the VBR register. The vectors will usually be +// dynamically initialized, but if the application is loaded via gdb then +// some code may be saved by static initialization. + + + .section ".m68k_start", "ax" + // This will typically be defined by the platform HAL to get the world + // in a sane state. It should do one-off initializations like getting + // the system into a state matching the memory map. If booting from + // flash it should also contain the initial PC and stack exception + // vectors. +#ifdef _HAL_M68K_START_ + _HAL_M68K_START_ +#endif + + .section ".m68k_start.hal_m68k_exception_reset", "ax" + // The actual entry point, as defined in the linker script. The exact + // state of the system at this point depends on the configuration and + // the processor. + .global hal_m68k_exception_reset + .type hal_m68k_exception_reset, function +hal_m68k_exception_reset: + + // Make absolutely sure that the status register is in a + // sensible state with interrupts disabled, irrespective of + // the platform. + mov.w #0x2700,%sr + + // Platform-specific initialization. This will do things like starting + // up the SDRAM controller. It may also run variant and processor + // initialization code, but the platform HAL gets to decide the order. +#ifdef _HAL_M68K_PLATFORM_SETUP1_ + _HAL_M68K_PLATFORM_SETUP1_ +#endif + + // All memory should now be running so we can get the C environment + // set up. Clear BSS before switching to C mode + .extern _hal_bss_start + .extern _hal_bss_end + move.l # _hal_bss_start,%a0 + move.l # _hal_bss_end,%a1 +1: + cmp.l %a0,%a1 + ble 2f + clr.l (%a0)+ + jra 1b +2: + + // If booting from ROM, move .data from ROM to RAM +#ifdef _HAL_M68K_COPY_ROM_DATA_TO_RAM_ + .extern _hal_data_section_start_lma + .extern _hal_data_section_end_lma + .extern _hal_data_section_start_vma + move.l # _hal_data_section_start_lma, %a0 + move.l # _hal_data_section_end_lma, %a1 + move.l # _hal_data_section_start_vma, %a2 +1: + cmp.l %a0,%a1 + ble 2f + mov.l (%a0)+,(%a2)+ + jra 1b +2: +#endif + + // If there is an FPU, set the default mode +#ifdef CYGINT_HAL_M68K_VARIANT_FPU + mov.w # CYGNUM_HAL_M68K_FPU_CR_DEFAULT, %fpcr +#endif + + // If there is on-chip RAM, copy code and data there and clear + // its BSS. +#ifdef _HAL_M68K_INITIALIZE_IRAM_ + .extern _hal_iram_text_section_start_lma + .extern _hal_iram_data_section_end_lma + .extern _hal_iram_text_section_start_vma + .extern _hal_iram_bss_section_start + .extern _hal_iram_bss_section_end + + move.l # _hal_iram_text_section_start_lma, %a0 + move.l # _hal_iram_data_section_end_lma, %a1 + move.l # _hal_iram_text_section_start_vma, %a2 +1: + cmp.l %a0, %a1 + ble 2f + mov.l (%a0)+, (%a2)+ + jra 1b +2: + move.l # _hal_iram_bss_section_start, %a0 + move.l # _hal_iram_bss_section_end, %a1 +3: + cmp.l %a0, %a1 + ble 4f + clr.l (%a0)+ + jra 3b +4: +#endif + + // Now we just need a valid stack and we can switch to C + // for the remaining initialization. Clearing the frame + // pointer may make life easier for gdb. + mov.l _HAL_M68K_STARTUP_STACK_,%sp + suba.l %a6, %a6 + + .extern hal_m68k_c_startup + jmp hal_m68k_c_startup + +// The exception vector table. Usually this will be held in RAM +// at location 0x0, although it may get moved around via e.g. +// the %vbr register. In addition to the exception vectors the +// virtual vector table is held here, as is any data that needs +// to be shared between RedBoot and eCos. +// +// Some targets in some configurations may define their own version +// of this, if for example the exception vector is held in ROM. +#if defined(_HAL_M68K_RAM_VECTORS_) + + _HAL_M68K_RAM_VECTORS_ + +#elif !defined(_HAL_M68K_RAM_VECTORS_DEFINED_) + .section ".ram_vectors", "aw", @nobits + +# ifndef _HAL_M68K_SUPPRESS_RAM_VECTORS_VSR_TABLE_ + // Start with the interrupt/exception vectors. + .global hal_m68k_vsr_table +hal_m68k_vsr_table: + .rept HAL_M68K_VSR_COUNT + .long 0 + .endr +# endif + + // Next the virtual vector table. Space for this is usually allocated, + // even if virtual vectors are not supported. That avoids confusion + // if RedBoot and the application are configured differently. If a + // platform will never support RedBoot, e.g. because of lack of memory, + // then it can suppress the virtual vectors. + // + // The size of the table comes from <cyg/hal/hal_if.h>, + // CYGNUM_CALL_IF_TABLE_SIZE, but that header cannot easily be included + // in assembler. +# ifndef _HAL_M68K_SUPPRESS_VIRTUAL_VECTOR_ + .global hal_virtual_vector_table +hal_virtual_vector_table: + .rept 64 + .long 0 + .endr +# endif + + // Allow the variant, processor and platform HALs to store additional + // information in the global vectors section. Typically this is used for + // data which needs to be shared between RedBoot and the application, + // e.g. shadow copies of write-only hardware registers. +# ifdef _HAL_M68K_VARIANT_RAM_VECTORS_ + _HAL_M68K_VARIANT_RAM_VECTORS_ +# endif +# ifdef _HAL_M68K_PROCESSOR_RAM_VECTORS_ + _HAL_M68K_PROCESSOR_RAM_VECTORS_ +# endif +# ifdef _HAL_M68K_PLATFORM_RAM_VECTORS_ + _HAL_M68K_PLATFORM_RAM_VECTORS_ +# endif +#endif // _HAL_M68K_RAM_VECTORS_DEFINED_ + + +// ---------------------------------------------------------------------------- +// end of vectors.S
new file mode 100644 --- /dev/null +++ b/packages/hal/m68k/arch/current/tests/iram1.c @@ -0,0 +1,201 @@ +//================================================================= +// +// iram.c +// +// Test support for on-chip memory +// +//========================================================================== +//###ECOSGPLCOPYRIGHTBEGIN#### +//------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2008 Free Software Foundation, Inc. +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Date: 2008-01-14 +// +//####DESCRIPTIONEND#### +//============================================================================= + +#include <pkgconf/system.h> +#include CYGHWR_MEMORY_LAYOUT_H +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> +#include <cyg/infra/cyg_ass.h> + +#if !defined(CYGMEM_REGION_iram) +# define NA_MSG "No IRAM memory region defined" +#elif defined(CYGMEM_REGION_ram) && (CYGMEM_REGION_iram == CYGMEM_REGION_ram) +# define NA_MSG "IRAM is used as the main RAM memory bank" +#endif + +#ifdef NA_MSG + +externC void +cyg_start( void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} + +#else // NA_MSG + +// These are provided by the linker script +externC cyg_uint8 _hal_iram_section_start_vma[]; +externC cyg_uint8 _hal_iram_bss_section_start[]; +externC cyg_uint8 _hal_iram_section_end_vma[]; + +// The external declarations which allow the attributes to be +// specified. +externC void onchip_fn1(void) CYGBLD_ATTRIB_SECTION(".iram_text.onchip_fn1"); +externC int onchip_fn2(int) CYGBLD_ATTRIB_SECTION(".iram_text.onchip_fn2"); +extern int onchip_data1[8] CYGBLD_ATTRIB_SECTION(".iram_data.onchip_data1"); +extern char onchip_data2 CYGBLD_ATTRIB_SECTION(".iram_data.onchip_data2"); +extern int onchip_data3[1024] CYGBLD_ATTRIB_SECTION(".iram_data.onchip_data3"); +extern int onchip_bss1 CYGBLD_ATTRIB_SECTION(".iram_bss.onchip_bss1"); +extern int onchip_bss2[42] CYGBLD_ATTRIB_SECTION(".iram_bss.onchip_bss2"); + +// Then the definitions. data3 should be garbage collected by the linker. +int onchip_data1[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; +char onchip_data2 = 42; +int onchip_data3[1024] = { 1 } ; +int onchip_bss1; +int onchip_bss2[42]; + +void +onchip_fn1(void) +{ + int i, data1_sum, fn2_result; + + diag_printf("PASS:<onchip_fn1 running>\n"); + + // Check again that the data has been correctly initialized, + // that there are no addressing funnies, and that the data can + // be overwritten. + for (i = 0, data1_sum = 0; i < 8; i++) { + data1_sum += onchip_data1[i]; + onchip_data1[i] -= i; + } + if (36 != data1_sum) { + diag_printf("FAIL:<onchip data1 array should add up to 36>\n"); + } + + for (i = 0, data1_sum = 0; i < 8; i++) { + data1_sum += onchip_data1[i]; + } + if (8 != data1_sum) { + diag_printf("FAIL:<onchip data1 array should now add up to 8>\n"); + } + // Call one on-chip function from another. + fn2_result = onchip_fn2(data1_sum); + if (861 != fn2_result) { + diag_printf("FAIL:<onchip_fn2 should return 903>\n"); + } +} + +int +onchip_fn2(int arg) +{ + int i; + int result; + diag_printf("PASS:<onchip_fn2 running>\n"); + + // Make sure that the on-chip bss is correctly zero-initialized + // and writable. + for (i = 0; i < 42; i++) { + if (0 != onchip_bss2[i]) { + diag_printf("FAIL:<onchip bss2 should be initialized to 0>\n"); + } + onchip_bss2[i] = i; + } + for (i = 0, result = 0; i < 42; i++) { + result += onchip_bss2[i]; + } + return result; +} + +void +check_addr(void* where) +{ + if ((where < (void*)_hal_iram_section_start_vma) || (where >= (void*)_hal_iram_section_end_vma)) { + diag_printf("FAIL:<ptr %p is not in IRAM region\n", where); + } +} + +externC void +cyg_start( void) +{ + int i; + int data1_sum; + + CYG_TEST_INIT(); + // For human inspection + diag_printf("INFO:<IRAM usage : %p -> %p\n", _hal_iram_section_start_vma, _hal_iram_section_end_vma); + diag_printf("INFO:<IRAM bss @ %p\n", _hal_iram_bss_section_start); + diag_printf("INFO:<RAM : %p -> %p\n", (void*)CYGMEM_REGION_ram, (void*)(CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE)); + diag_printf("INFO:<onchip_fn1 @ %p>\n", &onchip_fn1); + diag_printf("INFO:<onchip_fn2 @ %p>\n", &onchip_fn2); + diag_printf("INFO:<onchip_data1 @ %p>\n", &onchip_data1[0]); + + // Make sure that IRAM is really separate from main memory. + if ((_hal_iram_section_start_vma >= (cyg_uint8*)CYGMEM_REGION_ram) && + (_hal_iram_section_start_vma < (cyg_uint8*)(CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE))) { + CYG_TEST_FAIL("IRAM start overlaps SDRAM"); + } + if ((_hal_iram_section_end_vma >= (cyg_uint8*)CYGMEM_REGION_ram) && + (_hal_iram_section_end_vma < (cyg_uint8*)(CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE))) { + CYG_TEST_FAIL("IRAM end overlaps SDRAM"); + } + + // Make sure that various objects are correctly placed. + check_addr(&onchip_fn1); + check_addr(&onchip_fn2); + check_addr(&onchip_data1[0]); + check_addr(&onchip_data2); + // Not data3, we want that one to be garbage collected. + check_addr(&onchip_bss1); + check_addr(&onchip_bss2[0]); + + // Check that on-chip data is correctly initialized. + CYG_TEST_CHECK( 42 == onchip_data2, "onchip_data2 should be the answer"); + for (i = 0, data1_sum = 0; i < 8; i++) { + data1_sum += onchip_data1[i]; + } + CYG_TEST_CHECK( 36 == data1_sum, "onchip data1 array should add up to 36"); + + // Make sure we can call code located in iram. + { + void (*onchip_fn1_ptr)(void) = &onchip_fn1; + (*onchip_fn1_ptr)(); + } + + CYG_TEST_PASS_FINISH("IRAM test"); +} + +#endif // NA_MSG
