From 84efc8c4517cd19c862bd5eb78c1d31085333e85 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Mon, 2 Dec 2019 16:48:36 +0100 Subject: [PATCH] Vhex v2 - add-in redisign: Add minimal kernel and minimal libs --- .gitignore | 3 + Makefile | 128 +++-- bootstrap.ld | 52 -- global.mk | 28 - include/kernel/atomic.h | 10 + include/kernel/attributes.h | 9 + include/kernel/context.h | 40 ++ include/kernel/hardware/intc.h | 514 ++++++++++++++++++ include/kernel/hardware/keysc.h | 66 +++ include/kernel/hardware/t6k11.h | 10 + include/kernel/tty.h | 25 + include/{ => kernel}/types.h | 10 + include/kernel/union_types.h | 32 ++ include/lib/display.h | 32 ++ include/lib/stdio.h | 12 + include/lib/string.h | 24 + include/string.h | 46 -- src/boot/crt0.c | 56 -- src/commands/cache.c | 30 - src/commands/entry.c | 57 -- src/commands/help.c | 228 -------- src/commands/jump_address.c | 65 --- src/commands/jump_ram.c | 51 -- src/commands/jump_rom.c | 44 -- src/commands/jump_syscall.c | 120 ---- src/commands/jump_systab.c | 29 - src/commands/jump_vbr.c | 49 -- src/commands/quit.c | 18 - src/commands/where.c | 16 - src/display/intructions.c | 72 --- src/display/metainfos.c | 27 - src/history.c | 64 --- src/kernel/bootstrap/fx9860_context.c | 59 ++ src/kernel/bootstrap/mpu.c | 64 +++ src/kernel/bootstrap/section_actions.s | 49 ++ src/kernel/bootstrap/start.c | 151 +++++ src/kernel/bootstrap/vbr.s | 35 ++ src/kernel/bootstrap/vhex_context.c | 52 ++ src/kernel/hardware/t6k11/display.s | 55 ++ src/kernel/tty/close.c | 7 + src/kernel/tty/open.c | 18 + src/kernel/tty/write.c | 49 ++ src/kernel/util/atomic.s | 27 + src/kernel/vbr/exception.c | 38 ++ src/kernel/vbr/interrupt.c | 10 + src/kernel/vbr/tlb.c | 38 ++ src/keys.c | 170 ------ src/lib/display/dascii.c | 109 ++++ src/lib/display/dclear.c | 10 + src/lib/display/dprint.c | 31 ++ src/lib/display/dscroll.c | 26 + src/lib/display/dupdate.c | 8 + src/lib/stdio/sprintf.c | 10 + .../sprintf.c => lib/stdio/vsprintf.c} | 13 +- src/lib/string/memcpy.c | 9 + src/{ => lib}/string/memset.c | 4 +- src/{ => lib}/string/strcat.c | 4 +- src/lib/string/strcmp.c | 13 + src/{ => lib}/string/strcpy.c | 6 +- src/{ => lib}/string/strlen.c | 4 +- src/main.c | 49 -- src/string/atoi_base.c | 31 -- src/string/strcmp.c | 12 - src/string/strtotab.c | 143 ----- src/syscalls.s | 98 ---- src/user/main.c | 34 ++ tests/atoi_base_test.c | 31 -- tests/history_test.c | 52 -- tests/internal.h | 25 - tests/malloc_hook.c | 91 ---- tests/strtab_test.c | 108 ---- vhex.g1a | Bin 29660 -> 10180 bytes vhex.ld | 93 ++++ 73 files changed, 1870 insertions(+), 1933 deletions(-) delete mode 100644 bootstrap.ld delete mode 100644 global.mk create mode 100644 include/kernel/atomic.h create mode 100644 include/kernel/attributes.h create mode 100644 include/kernel/context.h create mode 100644 include/kernel/hardware/intc.h create mode 100644 include/kernel/hardware/keysc.h create mode 100644 include/kernel/hardware/t6k11.h create mode 100644 include/kernel/tty.h rename include/{ => kernel}/types.h (78%) create mode 100644 include/kernel/union_types.h create mode 100644 include/lib/display.h create mode 100644 include/lib/stdio.h create mode 100644 include/lib/string.h delete mode 100644 include/string.h delete mode 100644 src/boot/crt0.c delete mode 100644 src/commands/cache.c delete mode 100644 src/commands/entry.c delete mode 100644 src/commands/help.c delete mode 100644 src/commands/jump_address.c delete mode 100644 src/commands/jump_ram.c delete mode 100644 src/commands/jump_rom.c delete mode 100644 src/commands/jump_syscall.c delete mode 100644 src/commands/jump_systab.c delete mode 100644 src/commands/jump_vbr.c delete mode 100644 src/commands/quit.c delete mode 100644 src/commands/where.c delete mode 100644 src/display/intructions.c delete mode 100644 src/display/metainfos.c delete mode 100644 src/history.c create mode 100644 src/kernel/bootstrap/fx9860_context.c create mode 100644 src/kernel/bootstrap/mpu.c create mode 100644 src/kernel/bootstrap/section_actions.s create mode 100644 src/kernel/bootstrap/start.c create mode 100644 src/kernel/bootstrap/vbr.s create mode 100644 src/kernel/bootstrap/vhex_context.c create mode 100644 src/kernel/hardware/t6k11/display.s create mode 100644 src/kernel/tty/close.c create mode 100644 src/kernel/tty/open.c create mode 100644 src/kernel/tty/write.c create mode 100644 src/kernel/util/atomic.s create mode 100644 src/kernel/vbr/exception.c create mode 100644 src/kernel/vbr/interrupt.c create mode 100644 src/kernel/vbr/tlb.c delete mode 100644 src/keys.c create mode 100644 src/lib/display/dascii.c create mode 100644 src/lib/display/dclear.c create mode 100644 src/lib/display/dprint.c create mode 100644 src/lib/display/dscroll.c create mode 100644 src/lib/display/dupdate.c create mode 100644 src/lib/stdio/sprintf.c rename src/{string/sprintf.c => lib/stdio/vsprintf.c} (88%) create mode 100644 src/lib/string/memcpy.c rename src/{ => lib}/string/memset.c (51%) rename src/{ => lib}/string/strcat.c (73%) create mode 100644 src/lib/string/strcmp.c rename src/{ => lib}/string/strcpy.c (66%) rename src/{ => lib}/string/strlen.c (57%) delete mode 100644 src/main.c delete mode 100644 src/string/atoi_base.c delete mode 100644 src/string/strcmp.c delete mode 100644 src/string/strtotab.c delete mode 100644 src/syscalls.s create mode 100644 src/user/main.c delete mode 100644 tests/atoi_base_test.c delete mode 100644 tests/history_test.c delete mode 100644 tests/internal.h delete mode 100644 tests/malloc_hook.c delete mode 100644 tests/strtab_test.c create mode 100644 vhex.ld diff --git a/.gitignore b/.gitignore index 357250f..6050722 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ dkms.conf # Other *.txt build/ +debug +.tests +.old diff --git a/Makefile b/Makefile index 3382f8d..e358daf 100644 --- a/Makefile +++ b/Makefile @@ -1,64 +1,93 @@ #!/usr/bin/make -f -# --- -# Project: FIXME WRITE DOC !! -# Author: yann.magnin@epitech.eu -# --- -include global.mk +## --- +## Project: sprite-coder +## Author: +## theo.cousinet@epitech.eu +## yann.magnin@epitech.eu +## --- -NAME := vhex -EXEC := $(NAME).g1a -HEADER := -Iinclude -DEBUG := link_map.txt -LDFLAG := -T bootstrap.ld -ICON := icon.bmp -BUILD := build/ +##--- +## Static variables +##-- +HEADER := include +BUILD := build +DEBUG := debug + +NAME := vhex +EXEC := $(NAME).g1a +LDFLAG := -T $(NAME).ld +MEMORY_MAP := $(DEBUG)/$(NAME).map +ICON := icon.bmp +COMPILER := sh3eb-elf- +CC := $(COMPILER)gcc +OBJCOPY := $(COMPILER)objcopy +WRAPPER := g1a-wrapper +CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \ + -ffreestanding -nostdlib -fstrict-volatile-bitfields \ + -Wno-unused-const-variable -Wno-unused-function \ + -Wno-unused-variable -Wno-unused-but-set-variable \ + -Wno-unused-parameter + + +red := \033[1;31m +green := \033[1;32m +blue := \033[1;34m +white := \033[1;37m +nocolor := \033[1;0m + + + + +##--- +## Automated variables +##--- SRC := -DIRECTORY := src/ $(sort $(dir $(wildcard src/*/*/))) +DIRECTORY := $(shell find src -not -path "*/\.*" -type d) +# Get all source files $(foreach path,$(DIRECTORY),$(eval \ - SRC += $(wildcard $(path)*.c) \ - $(wildcard $(path)*.s) \ - $(wildcard $(path)*.S)) \ -) -OBJ := $(patsubst src_%,$(BUILD)%.o,$(subst /,_,$(basename $(SRC)))) + SRC += $(wildcard $(path)/*.c) \ + $(wildcard $(path)/*.S) \ + $(wildcard $(path)/*.s) \ +)) +# Geneate all object files +OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC))))) -#all: ;@echo $(SRC) $(OBJ) -all: | $(BUILD) $(EXEC) -install: $(EXEC) - sudo p7 send $< + + +##--- +## General rules +##--- +all: | $(BUILD) $(DEBUG) $(EXEC) $(EXEC): $(OBJ) - @ printf "$(green)/-------\n/ Link files\n/-------$(nocolor)\n" - $(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(BUILD)$(NAME).elf $^ $(HEADER) -lgcc > $(DEBUG) - $(OBJCPY) -R .comment -R .bss -O binary $(BUILD)$(NAME).elf $(BUILD)$(NAME).bin - $(WRAPPER) $(BUILD)$(NAME).bin -o $@ -i $(ICON) + $(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) -I $(HEADER) -lgcc > $(MEMORY_MAP) + $(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin + $(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON) -$(BUILD): +$(BUILD) $(DEBUG): @ printf "Create $(blue)$@$(nocolor) directory\n" @ mkdir -p $@ +install: $(EXEC) + sudo p7 send --force $^ -# -# TODO: find better way to do the job -# Units tests part. -# -tests: - gcc -std=c11 -Wall -Wno-error=deprecated-declarations -Wno-deprecated-declarations \ - -Werror -D DEBUG -o unit_tests $(HEADER) -I. src/history.c src/string/strtotab.c \ - src/string/atoi_base.c $(wildcard tests/*.c) --coverage -lcriterion - ./unit_tests - gcovr --exclude tests/ --branches - rm *.gc* - rm ./unit_tests +check: + @ echo 'src: $(SRC)' + @ echo 'obj: $(OBJ)' + @ echo 'directory: $(DIRECTORY)' +##--- +## Automated rules +##--- define rule-src -$(patsubst src_%,$(BUILD)%.o,$(subst /,_,$(basename $1))): $1 +$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1 @ printf "compiling $(white)$$<$(nocolor)..." - @ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc + @ $(CC) $(CFLAGS) -o $$@ -c $$< -I $(HEADER) -lgcc @ printf "$(green)[ok]$(nocolor)\n" endef @@ -67,19 +96,16 @@ $(foreach source,$(SRC),$(eval \ ) -#--- -# Clean rules -#--- + + +##--- +## Cleaning rules +##--- clean: - @ printf "$(red)Delete objects files$(nocolor)\n" rm -rf $(BUILD) - rm -f *.gc* - rm -f $(DEBUG) - rm -f $(NAME).bin - rm -f $(NAME).elf + rm -rf $(DEBUG) fclean: clean - @ printf "$(red)Delete binary files$(nocolor)\n" rm -f $(EXEC) re: fclean all @@ -87,4 +113,4 @@ re: fclean all -.PHONY: clean re fclean install tests +.PHONY: re fclean clean all install diff --git a/bootstrap.ld b/bootstrap.ld deleted file mode 100644 index 042fae1..0000000 --- a/bootstrap.ld +++ /dev/null @@ -1,52 +0,0 @@ -OUTPUT_ARCH(sh3) -OUTPUT_FORMAT(elf32-sh) -ENTRY(_initialize) - -MEMORY -{ - rom : o = 0x00300200, l = 512k - ram : o = 0x08100000, l = 8k -} - -SECTIONS -{ - . = ORIGIN(rom); - .pretext : { - *(.pretext.entry) - *(.pretext) - } > rom - - .text : { - *(.text) - } > rom - - .rodata : SUBALIGN(4) { - *(.rodata) - . = ALIGN(4); - _bcmd_cache = . ; - *(.cmd.cache) - _ecmd_cache = . ; - } > rom - - - . = ORIGIN(ram); - .bss (NOLOAD) : { - _bbss = . ; - *(.bss) - *(COMMON) - } > ram : NONE - _sbss = SIZEOF(.bss); - - .data ALIGN(4) : ALIGN(4) { - _bdata_rom = LOADADDR(.data) ; - _bdata_ram = . ; - *(.data) - } > ram AT> rom - _sdata = SIZEOF(.data) ; - - /* unused sections */ - /DISCARD/ : { - *(.comment) - *(.comment.*) - } -} diff --git a/global.mk b/global.mk deleted file mode 100644 index aff5d7f..0000000 --- a/global.mk +++ /dev/null @@ -1,28 +0,0 @@ -# Global options, used in each Makefile in the project -# If you have to change a tool name, or to add an option -# for every part of the project, this is the good place. - -COMPILER := sh3eb-elf- -CC := $(COMPILER)gcc -OBJCPY := $(COMPILER)objcopy -AR := $(COMPILER)ar -LD := $(COMPILER)ld -WRAPPER := g1a-wrapper - -CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \ - -ffreestanding -nostdlib -fstrict-volatile-bitfields \ - -Wno-unused-const-variable - -BUILD-DIR := build/ -SRC-DIR := src/ - -red := \033[1;31m -green := \033[1;32m -blue := \033[1;34m -white := \033[1;37m -nocolor := \033[1;0m - -define n -# Force new line character - -endef diff --git a/include/kernel/atomic.h b/include/kernel/atomic.h new file mode 100644 index 0000000..f6c56c6 --- /dev/null +++ b/include/kernel/atomic.h @@ -0,0 +1,10 @@ +#ifndef __KERNEL_ATOMIC_H__ +# define __KERNEL_ATOMIC_H__ + +#include +#include + +extern void atomic_start(void); +extern void atomic_end(void); + +#endif /*__KERNEL_ATOMIC_H__*/ diff --git a/include/kernel/attributes.h b/include/kernel/attributes.h new file mode 100644 index 0000000..ba0890b --- /dev/null +++ b/include/kernel/attributes.h @@ -0,0 +1,9 @@ +#ifndef __KERNEL_ARCH_ATTRIBUTES_H__ +# define __KERNEL_ARCH_ATTRIBUTES_H__ + +// Generate "anonyme name" for each gaps. +#define gap_name2(name) _##name +#define gap_name(name) gap_name2(name) +#define GAPS(bytes) const uint8_t gap_name(__LINE__)[bytes] + +#endif /*__KERNEL_ARCH_ATTRIBUTES_H__*/ diff --git a/include/kernel/context.h b/include/kernel/context.h new file mode 100644 index 0000000..f89e0d7 --- /dev/null +++ b/include/kernel/context.h @@ -0,0 +1,40 @@ +#ifndef __KERNEL_CONTEXT_H__ +# define __KERNEL_CONTEXT_H__ + +#include +#include + +typedef struct fx9860_context_s +{ + struct { + uint16_t control; + uint16_t autofix; + uint16_t scan_mode; + uint16_t scan_state; + uint16_t interrupt; + uint16_t scan_wait; + uint16_t scan_interval; + uint16_t kyoutdr; + uint16_t kyindr; + } keyboard; + struct { + uint16_t ipra; + uint16_t iprb; + uint16_t iprc; + uint16_t iprd; + uint16_t ipre; + uint16_t iprf; + uint16_t iprg; + uint16_t iprh; + uint16_t ipri; + uint16_t iprj; + uint16_t iprk; + uint16_t iprl; + } intc; +} fx9860_context_t; + +// Context primitive. +extern void fx9860_context_save(fx9860_context_t *context); +extern void fx9860_context_restore(fx9860_context_t *context); + +#endif /*__KERNEL_CONTEXT_H__*/ diff --git a/include/kernel/hardware/intc.h b/include/kernel/hardware/intc.h new file mode 100644 index 0000000..6d1fac1 --- /dev/null +++ b/include/kernel/hardware/intc.h @@ -0,0 +1,514 @@ +#ifndef __KERNEL_MODULES_SH7724_INTC_H__ +# define __KERNEL_MODULES_SH7724_INTC_H__ + +#include +#include +#include +#include + +struct SH7305_intc_s +{ + //--- + // Interrupt priority register. + //--- + volatile word_union(IPRA, + uint8_t TMU0_0 : 4; /* Timer 0 */ + uint8_t TMU0_1 : 4; /* Timer 1 */ + uint8_t TMU0_2 : 4; /* Timer 2 */ + uint8_t IrDA : 4; /* Infrared Communication */ + ); + GAPS(2); + volatile word_union(IPRB, + uint8_t const : 4; + uint8_t LCDC : 4; /* LCD Controller */ + uint8_t DMAC1A : 4; /* Direct Memory Controller 1 */ + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRC, + uint8_t TMU1_0 : 4; /* TMU1 Channel 0 */ + uint8_t TMU1_1 : 4; /* TMU1 Channel 1 */ + uint8_t TMU1_2 : 4; /* TMU1 Channel 2 */ + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRD, + uint8_t const : 4; + uint8_t MMCIF : 4; /* MultiMedia Card Interface */ + uint8_t const : 4; + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRE, + uint8_t DMAC0A : 4; /* Direct Memory Controller 1 */ + uint8_t const : 4; + uint8_t const : 4; /* Extra TMU ?? */ + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRF, + uint8_t KEYSC : 4; /* Key Scan Interface */ + uint8_t DMAC0B : 4; /* Direct Memory transfer / error info */ + uint8_t USB0_1 : 4; /* USB Controller */ + uint8_t CMT : 4; /* Compare Match Timer*/ + ); + GAPS(2); + volatile word_union(IPRG, + uint8_t SCIF0 : 4; /* SCIF0 transfert / error info */ + uint8_t const : 4; /* Extra TMU ?? */ + uint8_t const : 4; /* Extra TMU ?? */ + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRH, + uint8_t MSIOF0 : 4; /* Clock-synchronized SCIF channel 0 */ + uint8_t MSIOF1 : 4; /* Clock-synchronized SCIF channel 1 */ + uint8_t const : 4; + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRI, + uint8_t const : 4; /* Extra TMU ?? */ + uint8_t const : 4; + uint8_t const : 4; + uint8_t const : 4; + ); + GAPS(2); + volatile word_union(IPRJ, + uint8_t const : 4; /* Extra TMU ?? */ + uint8_t const : 4; + uint8_t FSI : 4; /* FIFO - buffered Serial Interface */ + uint8_t SDHI1 : 4; /* SD Card Host channel 1 */ + ); + GAPS(2); + volatile word_union(IPRK, + uint8_t RTC : 4; /* Real Time Clock */ + uint8_t DMAC1B : 4; /* DMAC1 transfer/error info */ + uint8_t const : 4; + uint8_t SDHI0 : 4; /* SD Card Host channel 0 */ + ); + GAPS(2); + volatile word_union(IPRL, + uint8_t const : 4; /* Extra TMU ?? */ + uint8_t const : 4; + uint8_t TPU : 4; /* Timer-Pulse Unit */ + uint8_t const : 4; + ); + GAPS(0x52); + + + //--- + // Interrupt mask register. + // FIXME + // This is the SH7224 Interrupt mask registers, so find + // the interrupt mask regiters for the SH7305. + //--- + volatile byte_union(IMR0, + uint8_t const : 1; + uint8_t TUNI2 : 1; /* TMU1 (timer2) */ + uint8_t TUNI1 : 1; /* TMU1 (timer1) */ + uint8_t TUNI0 : 1; /* TMU1 (timer0) */ + uint8_t SDHII3 : 1; /* SDHI1 */ + uint8_t SDHII2 : 1; /* SDHI1 */ + uint8_t SDHII1 : 1; /* SDHI1 */ + uint8_t SDHII0 : 1; /* SDHI1 */ + ); + GAPS(3); + volatile byte_union(IMR1, + uint8_t VOUI : 1; /* VIO */ + uint8_t VEU1I : 1; /* VIO */ + uint8_t BEU0I : 1; /* VIO */ + uint8_t CEU0I : 1; /* VIO */ + uint8_t DEI3 : 1; /* DMAC0A */ + uint8_t DEI2 : 1; /* DMAC0A */ + uint8_t DEI1 : 1; /* DMAC0A */ + uint8_t DEI0 : 1; /* DMAC0A */ + ); + GAPS(3); + volatile byte_union(IMR2, + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t VPUI : 1; /* VPU */ + uint8_t ATAPI : 1; /* ATAPI */ + uint8_t EtherMAC: 1; /* Ether */ + uint8_t const : 1; + uint8_t SCIFA0 : 1; /* SCIFA0 */ + ); + GAPS(3); + volatile byte_union(IMR3, + uint8_t DEI3 : 1; /* DMAC1A */ + uint8_t DEI2 : 1; /* DMAC1A */ + uint8_t DEI1 : 1; /* DMAC1A */ + uint8_t DEI0 : 1; /* DMAC1A */ + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t IRDAI : 1; /* IrDA */ + ); + GAPS(3); + volatile byte_union(IMR4, + uint8_t const : 1; + uint8_t TUNI2 : 1; /* TMU0 (timer2) */ + uint8_t TUNI1 : 1; /* TMU0 (timer1) */ + uint8_t TUNI0 : 1; /* TMU0 (timer0) */ + uint8_t JPUI : 1; /* JPU */ + uint8_t const : 1; + uint8_t const : 1; + uint8_t LCDCI : 1; /* LCDC */ + ); + GAPS(3); + volatile byte_union(IMR5, + uint8_t KEYI : 1; /* KEYSC */ + uint8_t DADERR : 1; /* DMAC0B */ + uint8_t DEI5 : 1; /* DMAC0B */ + uint8_t DEI4 : 1; /* DMAC0B */ + uint8_t VEU0I : 1; /* VEU3F0 */ + uint8_t SCIF2 : 1; /* SCIF */ + uint8_t SCIF1 : 1; /* SCIF */ + uint8_t SCIF0 : 1; /* SCIF */ + ); + GAPS(3); + volatile byte_union(IMR6, + uint8_t const : 1; + uint8_t const : 1; + uint8_t ICBI : 1; /* ICB */ + uint8_t SCIFA4 : 1; /* SCIFA4 */ + uint8_t CEU1I : 1; /* CEU1 */ + uint8_t const : 1; + uint8_t MSIOFI1 : 1; /* MSIOF */ + uint8_t MSIOFI0 : 1; /* MSIOF */ + ); + GAPS(3); + volatile byte_union(IMR7, + uint8_t DTE0I : 1; /* I2C0 */ + uint8_t WAITT0I : 1; /* I2C0 */ + uint8_t TACK0I : 1; /* I2C0 */ + uint8_t AL0I : 1; /* I2C0 */ + uint8_t DTE1I : 1; /* I2C1 */ + uint8_t WAITT1I : 1; /* I2C1 */ + uint8_t TACK1I : 1; /* I2C1 */ + uint8_t AL1I : 1; /* I2C1 */ + ); + GAPS(3); + volatile byte_union(IMR8, + uint8_t SDHII3 : 1; /* SDHI0 */ + uint8_t SDHII2 : 1; /* SDHI0 */ + uint8_t SDHII1 : 1; /* SDHI0 */ + uint8_t SDHII0 : 1; /* SDHI0 */ + uint8_t const : 1; + uint8_t const : 1; + uint8_t SCIFA5 : 1; /* SCIFA5 */ + uint8_t FSI : 1; /* FSI */ + ); + GAPS(3); + volatile byte_union(IMR9, + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t CMTI : 1; /* CMT */ + uint8_t const : 1; + uint8_t USI1 : 1; /* USB */ + uint8_t USI0 : 1; /* USB */ + uint8_t const : 1; + ); + GAPS(3); + volatile byte_union(IMR10, + uint8_t const : 1; + uint8_t DADERR : 1; /* DMAC1B */ + uint8_t DEI5 : 1; /* DMAC1B */ + uint8_t DEI4 : 1; /* DMAC1B */ + uint8_t const : 1; + uint8_t ATI : 1; /* RTC */ + uint8_t PRI : 1; /* RTC */ + uint8_t CUI : 1; /* RTC */ + ); + GAPS(3); + volatile byte_union(IMR11, + uint8_t BRK : 1; /* 2DG */ + uint8_t CEI : 1; /* 2DG */ + uint8_t INI : 1; /* 2DG */ + uint8_t TRI : 1; /* 2DG */ + uint8_t const : 1; + uint8_t TPUI : 1; /* TPU */ + uint8_t LMBI : 1; /* ICB */ + uint8_t TSIFI : 1; /* TSIF */ + ); + GAPS(3); + volatile byte_union(IMR12, + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t _2DDMAC : 1; /* 2DDMAC */ + ); + GAPS(15); + + + //--- + // Interrupt clear mask register. + // FIXME + // This is the SH7224 Interrupt mask registers, so find + // the interrupt mask regiters for the SH7305. + //--- + volatile byte_union(IMCR0, + uint8_t const : 1; + uint8_t TUNI2 : 1; /* TMU1 (timer2) */ + uint8_t TUNI1 : 1; /* TMU1 (timer1) */ + uint8_t TUNI0 : 1; /* TMU1 (timer0) */ + uint8_t SDHII3 : 1; /* SDHI1 */ + uint8_t SDHII2 : 1; /* SDHI1 */ + uint8_t SDHII1 : 1; /* SDHI1 */ + uint8_t SDHII0 : 1; /* SDHI1 */ + ); + GAPS(3); + volatile byte_union(IMCR1, + uint8_t VOUI : 1; /* VIO */ + uint8_t VEU1I : 1; /* VIO */ + uint8_t BEU0I : 1; /* VIO */ + uint8_t CEU0I : 1; /* VIO */ + uint8_t DEI3 : 1; /* DMAC0A */ + uint8_t DEI2 : 1; /* DMAC0A */ + uint8_t DEI1 : 1; /* DMAC0A */ + uint8_t DEI0 : 1; /* DMAC0A */ + ); + GAPS(3); + volatile byte_union(IMCR2, + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t VPUI : 1; /* VPU */ + uint8_t ATAPI : 1; /* ATAPI */ + uint8_t EtherMAC: 1; /* Ether */ + uint8_t const : 1; + uint8_t SCIFA0 : 1; /* SCIFA0 */ + ); + GAPS(3); + volatile byte_union(IMCR3, + uint8_t DEI3 : 1; /* DMAC1A */ + uint8_t DEI2 : 1; /* DMAC1A */ + uint8_t DEI1 : 1; /* DMAC1A */ + uint8_t DEI0 : 1; /* DMAC1A */ + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t IRDAI : 1; /* IrDA */ + ); + GAPS(3); + volatile byte_union(IMCR4, + uint8_t const : 1; + uint8_t TUNI2 : 1; /* TMU0 (timer2) */ + uint8_t TUNI1 : 1; /* TMU0 (timer1) */ + uint8_t TUNI0 : 1; /* TMU0 (timer0) */ + uint8_t JPUI : 1; /* JPU */ + uint8_t const : 1; + uint8_t const : 1; + uint8_t LCDCI : 1; /* LCDC */ + ); + GAPS(3); + volatile byte_union(IMCR5, + uint8_t KEYI : 1; /* KEYSC */ + uint8_t DADERR : 1; /* DMAC0B */ + uint8_t DEI5 : 1; /* DMAC0B */ + uint8_t DEI4 : 1; /* DMAC0B */ + uint8_t VEU0I : 1; /* VEU3F0 */ + uint8_t SCIF2 : 1; /* SCIF */ + uint8_t SCIF1 : 1; /* SCIF */ + uint8_t SCIF0 : 1; /* SCIF */ + ); + GAPS(3); + volatile byte_union(IMCR6, + uint8_t const : 1; + uint8_t const : 1; + uint8_t ICBI : 1; /* ICB */ + uint8_t SCIFA4 : 1; /* SCIFA4 */ + uint8_t CEU1I : 1; /* CEU1 */ + uint8_t const : 1; + uint8_t MSIOFI1 : 1; /* MSIOF */ + uint8_t MSIOFI0 : 1; /* MSIOF */ + ); + GAPS(3); + volatile byte_union(IMCR7, + uint8_t DTE0I : 1; /* I2C0 */ + uint8_t WAITT0I : 1; /* I2C0 */ + uint8_t TACK0I : 1; /* I2C0 */ + uint8_t AL0I : 1; /* I2C0 */ + uint8_t DTE1I : 1; /* I2C1 */ + uint8_t WAITT1I : 1; /* I2C1 */ + uint8_t TACK1I : 1; /* I2C1 */ + uint8_t AL1I : 1; /* I2C1 */ + ); + GAPS(3); + volatile byte_union(IMCR8, + uint8_t SDHII3 : 1; /* SDHI0 */ + uint8_t SDHII2 : 1; /* SDHI0 */ + uint8_t SDHII1 : 1; /* SDHI0 */ + uint8_t SDHII0 : 1; /* SDHI0 */ + uint8_t const : 1; + uint8_t const : 1; + uint8_t SCIFA5 : 1; /* SCIFA5 */ + uint8_t FSI : 1; /* FSI */ + ); + GAPS(3); + volatile byte_union(IMCR9, + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t CMTI : 1; /* CMT */ + uint8_t const : 1; + uint8_t USI1 : 1; /* USB */ + uint8_t USI0 : 1; /* USB */ + uint8_t const : 1; + ); + GAPS(3); + volatile byte_union(IMCR10, + uint8_t const : 1; + uint8_t DADERR : 1; /* DMAC1B */ + uint8_t DEI5 : 1; /* DMAC1B */ + uint8_t DEI4 : 1; /* DMAC1B */ + uint8_t const : 1; + uint8_t ATI : 1; /* RTC */ + uint8_t PRI : 1; /* RTC */ + uint8_t CUI : 1; /* RTC */ + ); + GAPS(3); + volatile byte_union(IMCR11, + uint8_t BRK : 1; /* 2DG */ + uint8_t CEI : 1; /* 2DG */ + uint8_t INI : 1; /* 2DG */ + uint8_t TRI : 1; /* 2DG */ + uint8_t const : 1; + uint8_t TPUI : 1; /* TPU */ + uint8_t LMBI : 1; /* ICB */ + uint8_t TSIFI : 1; /* TSIF */ + ); + GAPS(3); + volatile byte_union(IMCR12, + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t const : 1; + uint8_t _2DDMAC : 1; /* 2DDMAC */ + ); + GAPS(0xbff0e); + + //--- + // Interrupt Control registers 0 + //--- + volatile word_union(ICR0, + uint8_t NMIL :1; /* Non Maskable Interrupt Input level */ + uint8_t MAI :1; /* Non Maskable Interrupt interrupt Mask */ + uint8_t const :4; /* All 0 */ + uint8_t NMIB :1; /* Non Maskable Interrupt Block Mode */ + uint8_t NMIE :1; /* Non Maskable Interrupt Edge Select */ + uint8_t const :2; /* All 1 */ + uint8_t LVLMODE :1; /* Interrupt Source Retention Mode */ + uint8_t const :5; /* All 0 */ + ); + GAPS(0x0e); + + + //--- + // Interrupt Priority registers + //--- + volatile long_union(INTPRI00, + uint32_t IRQ0 : 4; /* Interrupt Request 0 */ + uint32_t IRQ1 : 4; /* Interrupt Request 1 */ + uint32_t IRQ2 : 4; /* Interrupt Request 2 */ + uint32_t IRQ3 : 4; /* Interrupt Request 3 */ + uint32_t IRQ4 : 4; /* Interrupt Request 4 */ + uint32_t IRQ5 : 4; /* Interrupt Request 5 */ + uint32_t IRQ6 : 4; /* Interrupt Request 6 */ + uint32_t IRQ7 : 4; /* Interrupt Request 7 */ + ); + GAPS(8); + + //--- + // Interrupt Control register 1 + //--- + volatile word_union(ICR1, + uint8_t IRQ0S :2; /* Interrupt Request 0 Sense Select */ + uint8_t IRQ1S :2; /* Interrupt Request 1 Sense Select */ + uint8_t IRQ2S :2; /* Interrupt Request 2 Sense Select */ + uint8_t IRQ3S :2; /* Interrupt Request 3 Sense Select */ + uint8_t IRQ4S :2; /* Interrupt Request 4 Sense Select */ + uint8_t IRQ5S :2; /* Interrupt Request 5 Sense Select */ + uint8_t IRQ6S :2; /* Interrupt Request 6 Sense Select */ + uint8_t IRQ7S :2; /* Interrupt Request 7 Sense Select */ + ); + GAPS(6); + + //--- + // Interrupt request register. + //--- + volatile byte_union(INTREQ00, + uint8_t IRQ0 : 1; /* Interrupt Request 0 */ + uint8_t IRQ1 : 1; /* Interrupt Request 1 */ + uint8_t IRQ2 : 1; /* Interrupt Request 2 */ + uint8_t IRQ3 : 1; /* Interrupt Request 3 */ + uint8_t IRQ4 : 1; /* Interrupt Request 4 */ + uint8_t IRQ5 : 1; /* Interrupt Request 5 */ + uint8_t IRQ6 : 1; /* Interrupt Request 6 */ + uint8_t IRQ7 : 1; /* Interrupt Request 7 */ + ); + GAPS(0x1f); + + //--- + // Interrupt mask register. + //--- + volatile byte_union(INTMSK00, + uint8_t IRQ0 : 1; /* Interrupt Request 0 */ + uint8_t IRQ1 : 1; /* Interrupt Request 1 */ + uint8_t IRQ2 : 1; /* Interrupt Request 2 */ + uint8_t IRQ3 : 1; /* Interrupt Request 3 */ + uint8_t IRQ4 : 1; /* Interrupt Request 4 */ + uint8_t IRQ5 : 1; /* Interrupt Request 5 */ + uint8_t IRQ6 : 1; /* Interrupt Request 6 */ + uint8_t IRQ7 : 1; /* Interrupt Request 7 */ + ); + GAPS(0x1f); + + //--- + // Interrupt mask clear register. (write only). + //--- + volatile byte_union(INTMSKCLR00, + uint8_t IRQ0 : 1; /* Interrupt Request 0 */ + uint8_t IRQ1 : 1; /* Interrupt Request 1 */ + uint8_t IRQ2 : 1; /* Interrupt Request 2 */ + uint8_t IRQ3 : 1; /* Interrupt Request 3 */ + uint8_t IRQ4 : 1; /* Interrupt Request 4 */ + uint8_t IRQ5 : 1; /* Interrupt Request 5 */ + uint8_t IRQ6 : 1; /* Interrupt Request 6 */ + uint8_t IRQ7 : 1; /* Interrupt Request 7 */ + ); + GAPS(0x5b); + + //--- + // Non Maskable Interrupt flags control register + //--- + volatile word_union(NMIFCR, + uint16_t const NMIL : 1; /* NMI input Level */ + uint16_t const : 14; /* All 0 */ + uint16_t NMIFL : 1; /* NMI Interrupt Request Detection */ + ); + GAPS(0x5bff3e); + + //--- + // User interrupt mask level register. + //--- + volatile long_union(USERMSK, + uint32_t SECRET : 8; /* Only write 0xa5 */ + uint32_t const : 8; /* All 0 */ + uint32_t UIMASK : 4; /* User Interrupt Mask Level */ + uint32_t const : 4; /* All 0 */ + ); +}; + +#define SH7305_INTC (*(volatile struct SH7305_intc_s *)0xa4080000) +#endif /*__KERNEL_MODULES_SH7724_INTC_H__*/ diff --git a/include/kernel/hardware/keysc.h b/include/kernel/hardware/keysc.h new file mode 100644 index 0000000..f6ea2e3 --- /dev/null +++ b/include/kernel/hardware/keysc.h @@ -0,0 +1,66 @@ +#ifndef __KERNEL_MODULES_SH7724_KEYSC_H__ +# define __KERNEL_MODULES_SH7724_KEYSC_H__ + +#include +#include +#include +#include + +struct sh7305_keysc_s +{ + volatile const uint16_t KIUDATA[6]; + volatile word_union(CONTROL, + uint16_t KEYIE : 1; /* Key Interrupt enable */ + uint16_t const :13; /* All 0 */ + uint16_t INTMODE : 2; /* Key Interrupt mode (?) */ + ); + volatile word_union(AUTOFIX, + uint16_t ENABLE : 1; /* enable AUTOFIX (?) */ + uint16_t const : 8; /* All 0 */ + uint16_t UNKNOWN0 : 3; /* ????? */ + uint16_t const : 1; /* All 0 */ + uint16_t UNKNOWN1 : 3; /* ????? */ + ); + volatile word_union(SCAN_MODE, + uint16_t UNKNOWN0 : 3; /* Scan Timing (?) */ + uint16_t UNKNOWN1 : 3; /* Scan mode (?) */ + uint16_t const : 10; /* All 0 */ + ); + volatile word_union(SCAN_STATE, + uint16_t const :15; /* All 0 */ + uint16_t STATE : 1; /* ????? */ + ); + volatile word_union(INTERRUPT, + uint16_t const : 1; /* All 0 */ + uint16_t KYCPU_IE : 7; /* KEYSC interrupt setup (see Planet Casio's bible) */ + uint16_t const STATUS : 8; /* Indicate the "type" of interruption (pressed, released, etc) */ + ); + volatile word_union(SCAN_WAIT, + uint16_t const : 1; /* All 0 */ + uint16_t TIME :15; /* Time between interrupt */ + ); + volatile uint16_t SCAN_INTERVAL; + volatile word_union(KYOUTDR, + uint16_t const : 4; /* All 0 */ + uint16_t KYO5DT : 2; /* Key Controll ouput 5 */ + uint16_t KYO4DT : 2; /* Key Controll ouput 4 */ + uint16_t KYO3DT : 2; /* Key Controll ouput 3 */ + uint16_t KYO2DT : 2; /* Key Controll ouput 2 */ + uint16_t KYO1DT : 2; /* Key Controll ouput 1 */ + uint16_t KYO0DT : 2; /* Key Controll ouput 0 */ + ); + volatile word_union(KYINDR, + uint16_t const : 8; /* All 0 */ + uint16_t KYDIR6 : 1; /* Key Direction 6 */ + uint16_t KYDIR5 : 1; /* Key Direction 5 */ + uint16_t KYDIR4 : 1; /* Key Direction 4 */ + uint16_t KYDIR3 : 1; /* Key Direction 3 */ + uint16_t KYDIR2 : 1; /* Key Direction 2 */ + uint16_t KYDIR1 : 1; /* Key Direction 1 */ + uint16_t KYDIR0 : 1; /* Key Direction 0 */ + ); +}; + +#define SH7305_KEYSC (*(volatile struct sh7305_keysc_s *)0xa44b0000) + +#endif /*__KERNEL_MODULES_SH7724_KEYSC_H__*/ diff --git a/include/kernel/hardware/t6k11.h b/include/kernel/hardware/t6k11.h new file mode 100644 index 0000000..1010fea --- /dev/null +++ b/include/kernel/hardware/t6k11.h @@ -0,0 +1,10 @@ +#ifndef __KERNEL_HARDWARE_T6K11_H__ +# define __KERNEL_HARDWARE_T6K11_H__ + +#include +#include + +// Screen primitive +extern void t6k11_display(void *vram); + +#endif /*__KERNEL_HARDWARE_T6K11_H__*/ diff --git a/include/kernel/tty.h b/include/kernel/tty.h new file mode 100644 index 0000000..57f224a --- /dev/null +++ b/include/kernel/tty.h @@ -0,0 +1,25 @@ +#ifndef __KERNEL_TTY_H__ +# define __KERNEL_TTY_H__ + +#include +#include + +struct tty_s +{ + struct { + uint8_t x; + uint8_t y; + struct { + uint8_t x; + uint8_t y; + } max; + } cursor; +}; + +// primitives. +extern int tty_open(void); +extern int tty_write(char const *buffer, ...); +//extern void tty_read(char *buffer, size_t count); +extern int tty_close(void); + +#endif /*__KERNEL_TTY_H__*/ diff --git a/include/types.h b/include/kernel/types.h similarity index 78% rename from include/types.h rename to include/kernel/types.h index 3258831..6c30e36 100644 --- a/include/types.h +++ b/include/kernel/types.h @@ -16,6 +16,16 @@ typedef int32_t ssize_t; # define __ssize_t_defined #endif +// Define MPU arch. +typedef enum mpu_e +{ + MPU_SH7305, + MPU_SH7724, + MPU_SH7337, + MPU_SH7355, + MPU_UNKNOWN, +} mpu_t; + // Force inline function. #define INLINE __attribute__((always_inline)) inline diff --git a/include/kernel/union_types.h b/include/kernel/union_types.h new file mode 100644 index 0000000..37cc0d3 --- /dev/null +++ b/include/kernel/union_types.h @@ -0,0 +1,32 @@ +#ifndef __KERNEL_MODULES_TYPES_H__ +# define __KERNEL_MODULES_TYPES_H__ + +#include +#include + +#define byte_union(name, fields) \ + union { \ + uint8_t BYTE; \ + struct { \ + fields \ + } __attribute__((packed, aligned(1))); \ + } __attribute__((packed, aligned(1))) name + +#define word_union(name, fields) \ + union { \ + uint16_t WORD; \ + struct { \ + fields \ + } __attribute__((packed, aligned(2))); \ + } __attribute__((packed, aligned(2))) name + +#define long_union(name, fields) \ + union { \ + uint32_t LONG_WORD; \ + struct { \ + fields \ + } __attribute__((packed, aligned(4))); \ + } __attribute__((packed, aligned(4))) name + + +#endif /*__KERNEL_MODULES_TYPES_H__*/ diff --git a/include/lib/display.h b/include/lib/display.h new file mode 100644 index 0000000..0238cef --- /dev/null +++ b/include/lib/display.h @@ -0,0 +1,32 @@ +#ifndef __LIB_DISPLAY_H__ +# define __LIB_DISPLAY_H__ + +#include +#include + + +// Define font bitmap informations. +#define KERNEL_FONT_BITMAP_WIDTH 127 // Bitmap width +#define KERNEL_FONT_BITMAP_HEIGHT 23 // Bitmap height +#define KERNEL_FONT_BITMAP_CWIDTH 4 // Character width (bitmap) +#define KERNEL_FONT_BITMAP_CHEIGHT 6 // Character height (bitmap) +#define KERNEL_FONT_REAL_WIDTH 3 // Charater width (real) +#define KERNEL_FONT_REAL_HEIGHT 5 // Character height (real) +#define KERNEL_FONT_NB_CHAR_X ((KERNEL_FONT_BITMAP_WIDTH / KERNEL_FONT_BITMAP_CWIDTH) + 1) +#define KERNEL_FONT_NB_CHAR_Y ((KERNEL_FONT_BITMAP_HEIGHT / KERNEL_FONT_BITMAP_CHEIGHT) + 1) + +// Define screen informations. +#define DISPLAY_SCREEN_WIDTH 128 +#define DISPLAY_SCREEN_HEIGHT 64 + +// Primtives +extern void dclear(void); +extern void dprint(int x, int y, char const *str, ...); +extern void dascii(int x, int y, char const c); +extern void dscroll(int line); +extern void dupdate(void); + +// Sheared Video RAM +extern uint32_t *VRAM; + +#endif /*__LIB_DISPLAY_H__*/ diff --git a/include/lib/stdio.h b/include/lib/stdio.h new file mode 100644 index 0000000..c60de95 --- /dev/null +++ b/include/lib/stdio.h @@ -0,0 +1,12 @@ +#ifndef __LIB_STDIO_H__ +# define __LIB_STDIO_H__ + +#include +#include +#include + +/* vsprintf(), sprintf() - formatted output conversion. */ +void vsprintf(char *str, char const *format, va_list ap); +void sprintf(char *str, char const *format, ...); + +#endif /*__LIB_STDIO_H__*/ diff --git a/include/lib/string.h b/include/lib/string.h new file mode 100644 index 0000000..7575735 --- /dev/null +++ b/include/lib/string.h @@ -0,0 +1,24 @@ +#ifndef __STRING_H__ +# define __STRING_H__ + +#include +#include + +/* memset() - fill memory with a constant byte. */ +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); + +/* strcat() - concatenate two string */ +char *strcat(char *dest, char const *src); + +/* strcmp() - compare two strings */ +int strcmp(const char *s1, const char *s2); + +/* strcpy(), strncpy() - copy a string. */ +char *strncpy(char *dest, char const *str, size_t size); +char *strcpy(char *dest, char const *src); + +/* strlen - calculate the lenght of a string. */ +size_t strlen(char const *str); + +#endif /*__STRING_H__*/ diff --git a/include/string.h b/include/string.h deleted file mode 100644 index 2aeebf2..0000000 --- a/include/string.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __STRING_H__ -# define __STRING_H__ - -#include -#include - -// Define weak symbols -#define WEAK __attribute__((weak)) - -/* memset() - fill memory with a constant byte. */ -WEAK void *memset(void *s, int c, size_t n); - -#ifndef DEBUG -/* vsprintf(), sprintf() - formatted output conversion. */ -void vsprintf(char *str, char const *format, va_list ap); -void sprintf(char *str, char const *format, ...); -#endif /* DEBUG */ - -/* strcat() - concatenate two string */ -WEAK char *strcat(char *dest, char const *src); - -/* strcmp() - compare two strings */ -WEAK int strcmp(const char *s1, const char *s2); - -/* strcpy(), strncpy() - copy a string. */ -WEAK char *strncpy(char *dest, char const *str, size_t size); -WEAK char *strcpy(char *dest, char const *src); - -/* strlen - calculate the lenght of a string. */ -WEAK size_t strlen(char const *str); - - - -// -// Custom string function. -// -/* strtotab() - generate table of word and indicate the number of word. */ -int strtotab(int *argc, char ***argv, char const *str); - -/* strtotab_quit() - free all allocated memory by strtotab function. */ -void strtotab_quit(int *argc, char ***argv); - -/* atoi_base() - atoi wrapped function, but add the base number. */ -uint32_t atoi_base(char const *str, int base); - -#endif /*__STRING_H__*/ diff --git a/src/boot/crt0.c b/src/boot/crt0.c deleted file mode 100644 index a354909..0000000 --- a/src/boot/crt0.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -extern int main(void); - -//defined by bootstrap.ld -extern uint32_t bbss; -extern uint32_t sbss; -extern uint32_t bdata_rom; -extern uint32_t bdata_ram; -extern uint32_t sdata; - - -// -// section_dump() -// copy a memory region using symbol information. -// -__attribute__((section(".pretext"))) -void section_dump(uint32_t * restrict dest, uint32_t * restrict load, size_t size) -{ - size_t i; - - i = -1; - while (++i < size >> 2) - dest[i] = load[i]; -} - -// -// section_reset() -// clear a memory region using symbol information. -// -__attribute__((section(".pretext"))) -void section_reset(uint32_t *bsection, size_t size) -{ - size_t i; - - i = -1; - while (++i < size >> 2) - bsection[i] = 0; -} - -// -// initialize() - the real add-in entry. -// We are currently running in the storage memory, so we should -// load data in RAM and wipe the bss section for initialize static -// and global variables. -// -__attribute__((section(".pretext.entry"))) -int initialize(void) -{ - int exit; - - section_reset(&bbss, (size_t)&sbss); - section_dump(&bdata_ram, &bdata_rom, (size_t)&sdata); - exit = main(); - return (exit); -} diff --git a/src/commands/cache.c b/src/commands/cache.c deleted file mode 100644 index e07726e..0000000 --- a/src/commands/cache.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -// External symbols defined by the linker script. -extern uint32_t bcmd_cache; -extern uint32_t ecmd_cache; - -// -// cmd_cache_find() -// Try to find the command into the command cache. -// -// NOTE: -// The cache is generated during the compilation; all command -// blocks is stored in the ".cmd.cache" section. -// We use the section symbols to know where the cache end. -// (see bootstrap.ld). -// -const struct cmd_block *cmd_cache_find(char const *name) -{ - const struct cmd_block *cache; - size_t i; - - i = -1; - cache = (void *)&bcmd_cache; - while ((ptrdiff_t)(&cache[++i]) != (ptrdiff_t)&ecmd_cache - && strcmp(cache[i].name, name)); - if ((ptrdiff_t)(&cache[i]) == (ptrdiff_t)&ecmd_cache) - return (NULL); - return (&cache[i]); -} diff --git a/src/commands/entry.c b/src/commands/entry.c deleted file mode 100644 index e4a80fd..0000000 --- a/src/commands/entry.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include - -// -// command_find -// Try to find the user command in the internal cache and execute -// the command's function. -// -static int command_find(int argc, char **argv, struct session_s *session, -struct vhex_s *vhex) -{ - const struct cmd_block *command; - int tmp; - - command = cmd_cache_find(*argv); - if (command == NULL) - return (EINVAL); - if (command->constructor == NULL){ - strcpy(vhex->info, "function error"); - return (ENOSYS); - } - tmp = session->anchor; - memset(vhex->info, '\0', CMD_LENGHT_MAX); - command->constructor(argc, argv, session, vhex->info); - if (*vhex->info == '\0') - sprintf(vhex->info, "%#x", session->anchor); - if (tmp != session->anchor) - session->cursor = 0; - return (0); -} - -// -// command_entry() -// The goal of this part is to parse and execute the user's command. -// -void command_entry(struct session_s *session, struct vhex_s *vhex) -{ - char **argv; - int argc; - int ret; - - if (history_update(&vhex->history.list, vhex->insert.cmd) == 0){ - vhex->history.offset = 0; - vhex->history.deep += 1; - } - ret = strtotab(&argc, &argv, vhex->insert.cmd); - memset(vhex->insert.cmd, '\0', CMD_LENGHT_MAX); - if (ret != 0){ - sprintf(vhex->info, "error (%d)", ret); - return; - } - if (command_find(argc, argv, session, vhex) != 0) - strcat(vhex->info, "command error"); - session->mode = (session->anchor == 0x00000000) ? UNUSED : NORMAL; - strtotab_quit(&argc, &argv); -} diff --git a/src/commands/help.c b/src/commands/help.c deleted file mode 100644 index 533cf3a..0000000 --- a/src/commands/help.c +++ /dev/null @@ -1,228 +0,0 @@ -#include -#include -#include -#include - -// Internal prototype. -static void help(int argc, char **argv, struct session_s *session, char *info); - -// Define help command into the cache section. -CMDBLOCK("help", &help, -"Help for Vhex version 1.0\n" -"This chapter introduces\noperations available with vhex.\n" -"\n" -"I] Keys mapping\n" -"II] Status bar\n" -"III] Unused mode\n" -"IV] Command mode\n" -"V] Normal mode\n" -"VI] Credits\n" -"VII] Copyright\n" -"\n" -"================================" -"I] Keys mapping\n" -"Move around: [UP], [DOWN]\n" -"Change mode: [OPTN]\n" -"Letter: [ALPHA] + [A ~ Z]\n" -"Letter lock: [SHIFT] + [ALPHA]\n" -"Letter unlock: [ALPHA]\n" -"Number: [0 ~ 9]\n" -"sessions: [F0 ~ F9]\n" -"\n" -"================================" -"II] Status bar\n" -"The first information (at the\nbottom left) display is the\nkeyboard status:\n" -" * [s] : shift mode.\n" -" * [l] : letter mode.\n" -" * [L] : caps lock.\n" -" * [n] : number mode.\n" -"The second information is the\ncommand zone.\n" -"The third information is the\ncurrent mode (unused, normal,\ncommand).\n" -"And the last information is the session's id currently using.\n" -"\n" -"================================" -"III] Unused mode\n" -"This mode is set when the\nsession is not used.\n" -"Basically you can't do a lot of things, but you can enter into\n" -"the command mode using the\n[OPTN] key.\n" -"\n" -"================================" -"IV] Normal mode.\n" -"This mode allows the user to\nmove into the Virtual Memory\n" -"using [UP] and [DOWN].\n" -"Be careful, there is no security" -"and some parts of the Virtual\n" -"Memory can make your\ncalculator crash.\n" -"If a crash occurs, don't worry, you have \"just\" read a\n" -"non-readable space.\n" -"Your machine will continue to\nwork perfectly after\nthe reset.\n" -"\n" -"================================" -"V] Command mode\n" -"The command mode is probably\nthe most important part\nof Vhex.\n" -"It's the only way to move\nquickly into the different part\n" -"of the Virtual Memory.\n" -"To enter in command mode the\nuser can press the [OTPN] key,\n" -"normally a \":#\" appear and\nthe user can write\ncommand.\n" -"All commands currently\nintegrated in Vhex:\n" -" :systab\n" -" :vbrjmp \n" -" :syscall \n" -" :ram \n" -" :rom\n" -" :help \n" -"We invited you to try\n\":help \" if you don't know how a" -" command work.\n" -"Each command typed by the user\nis stored in a history that it\n" -"can access using [UP] and\n[DOWN] keys.\n" -"\n" -"================================" -"VI] Credits\n" -"Special thank to:\n" -" - Lephenixnoir\n" -" - PierrotLL\n" -" - Simon Lothar\n" -" - Kristaba\n" -"And all communities of Planet\nCasio for his help.\n" -"specially to LephenixNoir for\nhis advices and his patience.\n" -"\n" -"================================" -"VII] Copyright\n" -"The Vhex programme use CC0\nlicence.\n" -"It allows anyone to freely\nreuse, improve or modify my\n" -"work for any purpose and\nwithout any legal restrictions, " -"except those required by law.\n"); - -/* get_nb_line() - Return the number of lines contain in the command's manual. */ -static int get_nb_line(char const *str) -{ - int nb_line; - int cursor; - - if (str == NULL || *str == '\0') - return (-EBADMSG); - cursor = 0; - nb_line = 0; - do { - cursor += 1; - if (cursor >= COLUMN_OFFSET || *str == '\n'){ - nb_line += 1; - cursor = 0; - } - } while (*(++str) != '\0'); - return (nb_line + 1); -} - -/* get_line() - Return the address of a target line */ -static const char *get_line(char const *str, int line) -{ - int cursor; - int nb_line; - - if (line == 0) - return (str); - cursor = 0; - nb_line = 0; - do { - cursor += 1; - if (cursor >= COLUMN_OFFSET || *str == '\n'){ - nb_line += 1; - cursor = 0; - } - } while (*(++str) != '\0' && nb_line < line); - return (str); -} - -// -// display_text() - Display only lines which should be visible. -// -// NOTE: -// Due to the Casio's GetKey function, the font used is a little bit weird, -// some characters have not the same size, so we can't calculate easily -// the line size. (TODO: fix that). -// -static void display_text(char *buf, char const *str, int current_line) -{ - char const *text; - int nb_line; - int cursor; - - text = get_line(str, current_line); - if (*text == '\0') - return; - nb_line = 0; - cursor = 0; - do { - if (*text != '\n'){ - buf[cursor] = *text; - cursor += 1; - } - if (cursor >= COLUMN_OFFSET || *text == '\n'){ - buf[cursor] = '\0'; - print(0, nb_line * FONT_HEIGHT, buf); - nb_line += 1; - cursor = 0; - continue; - } - } while (*(++text) != '\0' && nb_line < LINE_OFFSET); - if (cursor != 0) - print(0, nb_line * FONT_HEIGHT, buf); -} - -/* help_engine() - Display help information and handle keyboard. */ -static void help_engine(char const *text, int nb_line) -{ - char buf[COLUMN_OFFSET + 1]; - unsigned int key; - int cursor; - int exit; - - exit = 1; - cursor = 0; - while (exit != 0){ - dclear(); - // Display text. - display_text(buf, text, cursor); - - // Display exit info. - dclear_area(0, SCREEN_HEIGHT - FONT_HEIGHT - 2, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1); - dline_horizontal(SCREEN_HEIGHT - FONT_HEIGHT - 2, 0, SCREEN_WIDTH - 1); - print(0, SCREEN_HEIGHT - FONT_HEIGHT, "press [EXIT]"); - sprintf(buf, "%d/%d", cursor + 1, nb_line + 1); - print(SCREEN_WIDTH - (strlen(buf) * FONT_WIDTH) - 1, SCREEN_HEIGHT - FONT_HEIGHT, buf); - getkey(&key); - - // Keys hanlding. - if (key == KEY_UP && cursor > 0) - cursor -= 1; - if (key == KEY_DOWN && cursor < nb_line) - cursor += 1; - if (key == KEY_EXIT) - exit = 0; - } -} - -/* help() - display command manual pages. */ -static void help(int argc, char **argv, struct session_s *session, char *info) -{ - const struct cmd_block *command; - int nb_line; - - (void)session; - command = cmd_cache_find((argc == 1) ? "help" : argv[1]); - if (command == NULL){ - strcpy(info, "command error"); - return; - } - nb_line = 0; - if (command->man != NULL) - nb_line = get_nb_line(command->man); - if (command->man == NULL || nb_line < 0){ - strcpy(info, "no help entry"); - return; - } - nb_line -= LINE_OFFSET + 1; - if (nb_line < 0) - nb_line = 0; - help_engine(command->man, nb_line); -} diff --git a/src/commands/jump_address.c b/src/commands/jump_address.c deleted file mode 100644 index fdaf618..0000000 --- a/src/commands/jump_address.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -// Internal prototype. -static void address_jump(int argc, char **argv, struct session_s *session, char *info); - -// Define the command block into the cache. -CMDBLOCK("jmp", &address_jump, -"JMP command help\n" -"This command takes one\nparameter: the address (hexa)\n" -"you would jump into the Virtual Memory.\n" -"\n" -"Be careful, there is no security" -"and some parts of the Virtual\n" -"Memory can make your\ncalculator crash.\n" -"\n" -"If a crash occurs, don't worry, you have \"just\" read a\n" -"non-readable space.\n" -"Your calculator will continue\nto work perfectly after\nthe reset.\n" -"\n" -"Virtual Memory map:\n" -"Area P0 - 2Go - MMU enable\n" -"0x00300000 : add-in header\n" -"0x00300200 : add-in mapping\n" -"0x08000000 : RAM (cache)\n" -"Area P1 - 500Mo - MMU disable\n" -"0x80000000 : ROM (cache)\n" -"0x88000000 : RAM (cache)\n" -"Area P2 - 500Mo - MMU disable\n" -"0xa0000000 : ROM (no cache)\n" -"0xa8000000 : RAM (no cache)\n" -"Area P3 - 500Mo - MMU enable\n" -"?????? CRASH ??????\n" -"Area P4 - 500Mo - MMU disable\n" -"0xe0000000 : Store queue area\n" -"0xe5000000 : On chip RAM\n" -"0xf0000000 : Instr. cache addr\n" -"0xf1000000 : Instr. cache data\n" -"0xf2000000 : Instr. TLB addr\n" -"0xf3000000 : Instr. TLB data\n" -"0xf4000000 : Operand cache addr\n" -"0xf5000000 : Operand cache data\n" -"0xf6000000 : TLB/PMB cache addr\n" -"0xf7000000 : TLB/PMB cache data\n" -"0xfc000000 : Control register\n" -); - -static INLINE int check_address(char *str) -{ - --str; - while ((*(++str) >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f')); - return ((*str != '\0') ? 1 : 0); -} - -/* address_jump() - jump into Virtual Memory. */ -static void address_jump(int argc, char **argv, struct session_s *session, char *info) -{ - if (argc != 2 || check_address(argv[1]) != 0){ - strcpy(info, "arguments error"); - return; - } - // clear the lower bits to force align the address. - // (one instruction takes 2 bytes, so we need to respect the alignment). - session->anchor = atoi_base(argv[1], 16) >> 1 << 1; -} diff --git a/src/commands/jump_ram.c b/src/commands/jump_ram.c deleted file mode 100644 index 5099064..0000000 --- a/src/commands/jump_ram.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -// Internal prototype. -static void ram_jump(int argc, char **argv, struct session_s *session, char *info); - -/* Define the command block into the cache section. */ -CMDBLOCK("ram", &ram_jump, -"RAM command help\n" -"This function allows user to\njump into different parts of\n" -"the RAM mapped in the Virtual\nMemory.\n" -"\n" -":ram p0\n" -"Jump into the P0 area, basically" -"the user space who is managed\n" -"by the Memory Management\nUnit.\n" -"\n" -":ram p1\n" -"Jump into the RAM mapped in the P1 area; MMU is disabled and\n" -"the area is cached.\n" -"\n" -":ram p2\n" -"Jump into the RAM mapped in the P2 area; MMU is disable " -"and the area is not cached.\n" -"\n" -":ram p4\n" -"Jump into the internal chip\nmemory area; MMU is enabled\n" -"and the area is cached.\n" -); - -/* ram_jump() - jump into the RAM mapped in different parts of the Virtual Memory. */ -static void ram_jump(int argc, char **argv, struct session_s *session, char *info) -{ - if (argc != 2){ - strcpy(info, "argument error"); - return; - } - if (strcmp(argv[1], "p0") && strcmp(argv[1], "p1") - && strcmp(argv[1], "p2") && strcmp(argv[1], "p4")){ - sprintf(info, "bad argument"); - return; - } - if (!strcmp(argv[1], "p0")) - session->anchor = 0x08100000; - if (!strcmp(argv[1], "p1")) - session->anchor = 0x88000000; - if (!strcmp(argv[1], "p2")) - session->anchor = 0xa8000000; - if (!strcmp(argv[1], "p4")) - session->anchor = 0xe5000000; -} diff --git a/src/commands/jump_rom.c b/src/commands/jump_rom.c deleted file mode 100644 index d449b42..0000000 --- a/src/commands/jump_rom.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -// internal prototype. -static void rom_jump(int argc, char **argv, struct session_s *session, char *info); - -// Define the command into the cache. -CMDBLOCK("rom", &rom_jump, -"ROM command help\n" -"This command allows user to\njump into different parts of\n" -"the ROM mapped in the Virtual\nMemory.\n" -"\n" -":rom addin\n" -"Jump into the dynamic add-in\nmapping area.\n" -"Normaly you can see the\nVhex binary :)\n" -"(see \":help jmp\" to get the\nVirtual Memory map)\n" -"\n" -":rom p1\n" -"Jump into the ROM mapped in\nthe P1 area.\n" -"MMU is disable and the area\nis cached.\n" -"\n" -"rom p2\n" -"Jump into the ROM mapped in\nthe P2 area.\n" -"MMU is disable and the area\nis not cached.\n" -); - -/* rom_jump() - jump into the ROM mapped in different parts of the Virtual Memory. */ -static void rom_jump(int argc, char **argv, struct session_s *session, char *info) -{ - if (argc != 2){ - strcpy(info, "argument error"); - return; - } - if (strcmp(argv[1], "addin") && strcmp(argv[1], "p1") && strcmp(argv[1], "p2")){ - sprintf(info, "bad argument"); - return; - } - if (!strcmp(argv[1], "addin")) - session->anchor = 0x00300200; - if (!strcmp(argv[1], "p1")) - session->anchor = 0x80000000; - if (!strcmp(argv[1], "p2")) - session->anchor = 0xa0000000; -} diff --git a/src/commands/jump_syscall.c b/src/commands/jump_syscall.c deleted file mode 100644 index 14cf4b3..0000000 --- a/src/commands/jump_syscall.c +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include - -// Internal prototype. -static void syscall_jump(int argc, char **argv, struct session_s *session, char *info); - -/* Define command block into the cache section. */ -CMDBLOCK("syscall", &syscall_jump, -"SYSCALL command help\n" -"Take one parameter: syscall id.\n" -"This command will jump at the\nsyscall's code entry.\n" -"\n" -"Syscall list (not exhaustive):\n" -"0x013 : GLibAddinAppExecutionCheck\n" -"0x014 : GLibGetAddinLibInfo\n" -"0x014 : GLibGetOSVersionInfo\n" -"0x01c : Bdisp_WriteGraph_VRAM\n" -"0x01d : Bdisp_WriteGraph_DD\n" -"0x01e : Bdisp_WriteGraph_DDVRAM\n" -"0x022 : Bdisp_ReadArea_VRAM\n" -"0x023 : Bdisp_ReadArea_DD_OS\n" -"0x024 : Bdisp_GetDisp_DD\n" -"0x026 : DD_GET\n" -"0x028 : Bdisp_PutDisp_DD\n" -"0x030 : Bdisp_DrawLineVRAM\n" -"0x031 : Bdisp_ClearLine_VRAM\n" -"0x118 : Bcre_cychdr\n" -"0x119 : Bdel_cychdr\n" -"0x142 : Bdisp_AllClr_DD\n" -"0x143 : Bdisp_AllClr_VRAM\n" -"0x144 : Bdisp_AllClr_DDVRAM\n" -"0x145 : Bdisp_GetDisp_VRAM\n" -"0x147 : Bdisp_SetPoint_DD\n" -"0x148 : Bdisp_SetPoint_DDVRAM\n" -"0x149 : Bdisp_GetPoint_VRAM\n" -"0x14a : Bdisp_AreaClr_DD\n" -"0x14b : Bdisp_AreaClr_VRAM\n" -"0x14c : Bdisp_AreaClr_DDVRAM\n" -"0x14d : Bdisp_AreaReverseVRAM\n" -"0x11a : Bsta_cychdr\n" -"0x11b : Bstp_cychdr\n" -"0x11f : Bdisp_PutDispArea_DD\n" -"0x1e7 : BfileFLS_CloseFile\n" -"0x218 : flsFindCLose\n" -"0x242 : Bkey_Set_RepeatTime\n" -"0x243 : Bkey_Get_RepeatTime\n" -"0x244 : Bkey_Set_RepeatTime_Default\n" -"0x247 : Bkey_GetKeyWait\n" -"0x24c : Chattering\n" -"0x374 : BMCSRenameVariable\n" -"0x3ed : SetFlagPaturn\n" -"0x3fa : Hmem_SetMMU\n" -"0x420 : BSrl_DummyWAIT\n" -"0x42c : Bfile_OpenFile_OS\n" -"0x42d : Bfile_CloseFile_OS\n" -"0x42e : Bfile_GetMediaFree_OS\n" -"0x42f : Bfile_GetFileSize_OS\n" -"0x431 : Bfile_SeekFile_OS\n" -"0x432 : Bfile_ReadFile_OS\n" -"0x434 : Bfile_CreateEntry\n" -"0x435 : Bfile_WriteFile_OS\n" -"0x439 : Bfile_DeleteEntry\n" -"0x43b : Bfile_FindFirst\n" -"0x43d : Bfile_FindClose\n" -"0x43c : Bfile_FindNext\n" -"0x462 : GetAppName\n" -"0x494 : CallBackAtQuitMainFunction\n" -"0x807 : Locate_OS\n" -"0x82b : MCSPutVar2\n" -"0x830 : MCSOvwDat2\n" -"0x836 : MCSDelVar2\n" -"0x840 : MCSGetDlen2\n" -"0x841 : MCSGetData1\n" -"0x844 : MCSGetCapa\n" -"0x8fe : PopUpWin\n" -"0x808 : Print\n" -"0x809 : PrintRev\n" -"0x80b : PrintRev\n" -"0x80d : PrintRLine\n" -"0x80a : PrintC\n" -"0x80c : PrintLine\n" -"0x813 : SaveDisp\n" -"0x814 : RestoreDisp\n" -"0x90f : GetKey\n" -"0x9ad : PrintXY\n" -"0xacc : free\n" -"0xacd : malloc\n" -"0xc4f : PrintMiniSd\n" -"0xe6b : calloc\n" -"0xe6d : realloc\n" -"0x1032 : Bkey_GetKeyTableInfo\nJumpFunc\n" -); - -static INLINE int check_address(char *str) -{ - --str; - while ((*(++str) >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f')); - return ((*str != '\0') ? 1 : 0); -} - -// -// syscall_jump() -// Casio doesn't use the TRAPA instruction (software interruption), for switch from -// user mode to privileged mode. They just jump always at 0x80010070 and use the -// table of syscall addresses to redirect the jump. (and the table address is always -// stored at 0x8001007c). -// -static void syscall_jump(int argc, char **argv, struct session_s *session, char *info) -{ - uint32_t *systab; - uint32_t id; - - if (argc != 2 || check_address(argv[1]) != 0){ - strcpy(info, "arguments error"); - return; - } - id = atoi_base(argv[1], 16); - systab = (void*)(*(uint32_t *)0x8001007c); - session->anchor = systab[id]; -} diff --git a/src/commands/jump_systab.c b/src/commands/jump_systab.c deleted file mode 100644 index f2c236f..0000000 --- a/src/commands/jump_systab.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -// Internal prototype. -static void systab_jump(int argc, char **argv, struct session_s *session, char *info); - -// Define the command block into the cache -CMDBLOCK("systab", &systab_jump, -"SYSTAB command help\n" -"This function allows user to\njump into the Casio \"syscall\n" -"handler\".\n" -"\n" -"Curiously, Casio doesn't use the" -"TRAPA instruction for handle\n" -"syscall, but jump at\n0x80010070.\n" -"This don't explain why we are\nalways in privileged mode, but\n" -"now we can affirm that Casio\ndo it intentionally.\n" -); - -/* systab_jump() - Jump into the Casio "syscall handler". */ -static void systab_jump(int argc, char **argv, struct session_s *session, char *info) -{ - if (argc != 1){ - strcpy(info, "argument error"); - return; - } - (void)argv; - session->anchor = 0x80010070; -} diff --git a/src/commands/jump_vbr.c b/src/commands/jump_vbr.c deleted file mode 100644 index 461c5c8..0000000 --- a/src/commands/jump_vbr.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include - -// Internal prototype -static void vbrjmp(int argc, char **argv, struct session_s *session, char *info); - -// TODO: write doc. -CMDBLOCK("vbrjmp", &vbrjmp, -"VBR JUMP command help\n" -"This command jump into Casio's\nhandlers.\n" -"\n" -"Due to the SH3 / SH4 VBR system\n, there are 3 vectors offset\n" -"called by the processor:\n" -" * exception (VBR + 0x100)\n" -" * tlb miss (VBR + 0x400)\n" -" * interrupt (VBR + 0x600)\n" -"\n" -"You can access to each handler\nusing this command list:\n" -":vbrjmp except VBR + 0x100\n" -":vbrjmp fault VBR + 0x400\n" -":vbrjmp int VBR + 0x600\n" -); - -// -// vbr_jump() - jump to the exception, tlb or interrupt, Casio handler. -// Due to the SH3 / SH4 VBR system, there are 3 vectors offset called -// by the processor: -// * vbr + 0x100 -> general exeptions. -// * vbr + 0x400 -> tlb miss. -// * vbr + 0x600 -> interrupts. -// -static void vbrjmp(int argc, char **argv, struct session_s *session, char *info) -{ - if (argc != 2){ - strcpy(info, "arguments error"); - return; - } - if (strcmp(argv[1], "fault") && strcmp(argv[1], "except") && strcmp(argv[1], "int")){ - sprintf(info, "bad argument"); - return; - } - __asm__ volatile ("stc vbr, %0" : "=r"(session->anchor)); - if (!strcmp(argv[1], "except")) - session->anchor += 0x100; - if (!strcmp(argv[1], "fault")) - session->anchor += 0x400; - if (!strcmp(argv[1], "int")) - session->anchor += 0x600; -} diff --git a/src/commands/quit.c b/src/commands/quit.c deleted file mode 100644 index 9a3832e..0000000 --- a/src/commands/quit.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -// internal prototype. -static void quit(int argc, char **argv, struct session_s *session, char *info); - -// Define the command into the cache. -CMDBLOCK("quit", &quit, NULL); - -/* quit() - switch to UNUSED mode */ -static void quit(int argc, char **argv, struct session_s *session, char *info) -{ - (void)argc; - (void)argv; - strcpy(info, "exit"); - session->mode = UNUSED; - session->anchor = 0x00000000; -} diff --git a/src/commands/where.c b/src/commands/where.c deleted file mode 100644 index 8228d1f..0000000 --- a/src/commands/where.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -// internal prototype. -static void where(int argc, char **argv, struct session_s *session, char *info); - -// Define the command into the cache. -CMDBLOCK("where", &where, NULL); - -/* where() - display the user positision in the Virtual Memory. */ -static void where(int argc, char **argv, struct session_s *session, char *info) -{ - (void)argc; - (void)argv; - sprintf(info, "%#x", session->anchor + (session->cursor << 1)); -} diff --git a/src/display/intructions.c b/src/display/intructions.c deleted file mode 100644 index 6c5aacc..0000000 --- a/src/display/intructions.c +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include - -//TODO: move me ? -static INLINE int get_shift(uint16_t mask) -{ - int i; - - if (mask == 0x0000) - return (0); - i = -1; - while (++i < 16 && !(mask & (0x01 << i))); - return (i); -} - -/* get_instructions() - find mnemonic and instruction argument(s) */ -static void get_instructions(char *str, uint16_t bytes_code) -{ - int shift[ARGUMENTS_MAX]; - size_t i; - size_t j; - - i = -1; - while (opcode[++i].name != NULL - && (bytes_code & opcode[i].mask) != opcode[i].code); - if (opcode[i].name == NULL){ - strcpy(str, "????"); - return; - } - j = -1; - while (++j < ARGUMENTS_MAX) - shift[j] = get_shift(opcode[i].arg_mask[j]); - //TODO: update this. - sprintf(str, opcode[i].name, - (bytes_code & opcode[i].arg_mask[0]) >> shift[0], - (bytes_code & opcode[i].arg_mask[1]) >> shift[1], - (bytes_code & opcode[i].arg_mask[2]) >> shift[2]); -} - -// -// display_instructions() -// Translate "on-the-fly" each binary instructions stored at -// the anchor location. -// Almost instructions can be translated; only FPU instructions -// is not handled because it's not available on the SH3 based MPU. -// -void display_instructions(const struct session_s *session) -{ - char mnemonic[128]; - uint16_t *area; - char buf[64]; - size_t y; - - if (session->mode == COMMAND){ - restore_window(1); - return; - } - if (session->mode == UNUSED || session->anchor == 0x00000000){ - print((SCREEN_WIDTH >> 1) - ((sizeof("Empty session") * FONT_WIDTH) >> 1), - (SCREEN_HEIGHT >> 1) - (FONT_HEIGHT >> 1), "Empty session"); - return; - } - y = -1; - area = (void*)(session->anchor + (session->cursor << 1)); - while (++y < LINE_OFFSET){ - get_instructions(mnemonic, area[y]); - sprintf(buf, "%4x %4x %s", &(area[y]), area[y], mnemonic); - print(0, y * FONT_HEIGHT, buf); - } -} diff --git a/src/display/metainfos.c b/src/display/metainfos.c deleted file mode 100644 index 4cc000f..0000000 --- a/src/display/metainfos.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include - -/* display_metainfo() - display the "status" bar and display user's information */ -void display_metainfos(const struct vhex_s *vhex, const struct session_s *session) -{ - static const char *mode_name[] = {"unused", "command", "normal", "free"}; - static const char insert_name[] = {'l', 'L', 'n', 's'}; - const void *tmp; - char buf[32]; - - // clear area - dclear_area(0, SCREEN_HEIGHT - FONT_HEIGHT - 2, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1); - dline_horizontal(SCREEN_HEIGHT - FONT_HEIGHT - 2, 0, SCREEN_WIDTH - 1); - - // Display informations - sprintf(buf, "[%s][%d]", mode_name[session->mode], vhex->current_session); - print(SCREEN_WIDTH - (strlen(buf) * FONT_WIDTH) - 1, SCREEN_HEIGHT - FONT_HEIGHT, buf); - if (session->mode == COMMAND) - sprintf(buf, "[%c]:%s#", insert_name[vhex->insert.mode], vhex->insert.cmd); - else { - tmp = (*vhex->info == '\0') ? vhex->insert.cmd : vhex->info; - sprintf(buf, "[%c] %s", insert_name[vhex->insert.mode], tmp); - } - print(0, SCREEN_HEIGHT - FONT_HEIGHT, buf); -} diff --git a/src/history.c b/src/history.c deleted file mode 100644 index b549b63..0000000 --- a/src/history.c +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef DEBUG -# include -# include -#else -# include "history.h" -# include -#endif -#include -#include - -//--- -// history_update() -// Add new history node to the chained list. This is a singly -// linked list, but the node insertion from the beginning. -// -// Exemple: add node A, B, C and D -// 1. A -> NULL -// 2. B -> A -> NULL -// 3. C -> B -> A -> NULL -// 4. D -> C -> B -> A -> NULL -//--- -int history_update(struct node **list, const char *data) -{ - void *swap; - - if (list == NULL) - return (EFAULT); - swap = *list; - *list = (struct node *)malloc(sizeof(struct node)); - if (*list == NULL){ - *list = swap; - return (ENOMEM); - } - strcpy((void*)(*list)->data, data); - (*list)->next = swap; - return (0); -} - -// -// history_get() -// primitive function which will return the data stored in -// the "offset" position in the list. -// -const void *history_get(struct node *list, off_t offset) -{ - if (list == NULL) - return (NULL); - if (offset == 0) - return (list->data); - return (history_get(list->next, offset - 1)); -} - -// -// history_quit() -// Free all allocated memory. -// -void history_quit(struct node **list) -{ - if (list == NULL || *list == NULL) - return; - history_quit(&(*list)->next); - free(*list); - *list = NULL; -} diff --git a/src/kernel/bootstrap/fx9860_context.c b/src/kernel/bootstrap/fx9860_context.c new file mode 100644 index 0000000..3487746 --- /dev/null +++ b/src/kernel/bootstrap/fx9860_context.c @@ -0,0 +1,59 @@ +#include +#include +#include + +void fx9860_context_save(fx9860_context_t *context) +{ + // Save Interrupt Controller (INTC) + context->intc.ipra = SH7305_INTC.IPRA.WORD; + context->intc.iprb = SH7305_INTC.IPRB.WORD; + context->intc.iprc = SH7305_INTC.IPRC.WORD; + context->intc.iprd = SH7305_INTC.IPRD.WORD; + context->intc.ipre = SH7305_INTC.IPRE.WORD; + context->intc.iprf = SH7305_INTC.IPRF.WORD; + context->intc.iprg = SH7305_INTC.IPRG.WORD; + context->intc.iprh = SH7305_INTC.IPRH.WORD; + context->intc.ipri = SH7305_INTC.IPRI.WORD; + context->intc.iprj = SH7305_INTC.IPRJ.WORD; + context->intc.iprk = SH7305_INTC.IPRK.WORD; + context->intc.iprl = SH7305_INTC.IPRL.WORD; + + // Save Key Scan (KEYSC) context. + context->keyboard.control = SH7305_KEYSC.CONTROL.WORD; + context->keyboard.autofix = SH7305_KEYSC.AUTOFIX.WORD; + context->keyboard.scan_mode = SH7305_KEYSC.SCAN_MODE.WORD; + context->keyboard.scan_state = SH7305_KEYSC.SCAN_STATE.WORD; + context->keyboard.interrupt = SH7305_KEYSC.INTERRUPT.WORD; + context->keyboard.scan_wait = SH7305_KEYSC.SCAN_WAIT.WORD; + context->keyboard.scan_interval = SH7305_KEYSC.SCAN_INTERVAL; + context->keyboard.kyoutdr = SH7305_KEYSC.KYOUTDR.WORD; + context->keyboard.kyindr = SH7305_KEYSC.KYINDR.WORD; +} + +void fx9860_context_restore(fx9860_context_t *context) +{ + // Restore Key Scan (KEYSC) context. + SH7305_KEYSC.CONTROL.WORD = context->keyboard.control; + SH7305_KEYSC.AUTOFIX.WORD = context->keyboard.autofix; + SH7305_KEYSC.SCAN_MODE.WORD = context->keyboard.scan_mode; + SH7305_KEYSC.SCAN_STATE.WORD = context->keyboard.scan_state; + SH7305_KEYSC.INTERRUPT.WORD = context->keyboard.interrupt; + SH7305_KEYSC.SCAN_WAIT.WORD = context->keyboard.scan_wait; + SH7305_KEYSC.SCAN_INTERVAL = context->keyboard.scan_interval; + SH7305_KEYSC.KYOUTDR.WORD = context->keyboard.kyoutdr; + SH7305_KEYSC.KYINDR.WORD = context->keyboard.kyindr; + + // Restore Interrupt Controller (INTC) + SH7305_INTC.IPRA.WORD = context->intc.ipra; + SH7305_INTC.IPRB.WORD = context->intc.iprb; + SH7305_INTC.IPRC.WORD = context->intc.iprc; + SH7305_INTC.IPRD.WORD = context->intc.iprd; + SH7305_INTC.IPRE.WORD = context->intc.ipre; + SH7305_INTC.IPRF.WORD = context->intc.iprf; + SH7305_INTC.IPRG.WORD = context->intc.iprg; + SH7305_INTC.IPRH.WORD = context->intc.iprh; + SH7305_INTC.IPRI.WORD = context->intc.ipri; + SH7305_INTC.IPRJ.WORD = context->intc.iprj; + SH7305_INTC.IPRK.WORD = context->intc.iprk; + SH7305_INTC.IPRL.WORD = context->intc.iprl; +} diff --git a/src/kernel/bootstrap/mpu.c b/src/kernel/bootstrap/mpu.c new file mode 100644 index 0000000..6804b71 --- /dev/null +++ b/src/kernel/bootstrap/mpu.c @@ -0,0 +1,64 @@ +#include + +/* check_sh3 - Detecting sh3-based MPU */ +static mpu_t check_sh3(uint16_t tplcr) +{ + if (tplcr == 0x0fff) + return (MPU_SH7337); + if (tplcr == 0x00ff) + return (MPU_SH7355); + return (MPU_UNKNOWN); +} + +/* check_sh3 - Detecting sh4-based MPU */ +static mpu_t check_sh4(void) +{ + volatile uint32_t *pvr = (void *)0xff000030; + volatile uint32_t *prr = (void *)0xff000044; + uint32_t product; + + if ((*pvr & 0xffffff00) != 0x10300b00) + return (MPU_UNKNOWN); + product = *prr & 0xfffffff0; + if (product == 0x00002c00) + return (MPU_SH7305); + if (product == 0x00002200) + return (MPU_SH7724); + return (MPU_UNKNOWN); +} + +// +// get_mpu() +// +// Return the MPU identifier of the calculator. +// Thanks to SimonLothar and Lephenixnoir for this function +// and related information. +// +// Processor version register (PVR) and product control register (PRR) +// hold information about the MPU version, they but are only accessible on +// SH-4-based MPUs. +// To detect SH-3-based MPUs, this function uses port L control register +// (PLCR), whose bits 8 to 15 cannot be set with SH7337 where bits 8 to 11 +// can be set with SH7355. +// +// Additionally, the CPU core ID register (CPIDR) at 0xff000048 returns 1 +// on SH7305. +// +mpu_t mpu_get(void) +{ + volatile uint16_t *plcr = (void *)0xa4000114; + uint16_t splcr; + uint16_t tplcr; + mpu_t mpu; + + // Check port L control register. + splcr = *plcr; + *plcr = 0xffff; + tplcr = *plcr; + *plcr = splcr; + + mpu = check_sh3(tplcr); + if (mpu != MPU_UNKNOWN) + return (mpu); + return (check_sh4()); +} diff --git a/src/kernel/bootstrap/section_actions.s b/src/kernel/bootstrap/section_actions.s new file mode 100644 index 0000000..776bd7f --- /dev/null +++ b/src/kernel/bootstrap/section_actions.s @@ -0,0 +1,49 @@ +.globl _section_wipe +.global _section_load +.type _section_load, @function +.type _section_wipe, @function + +.align 2 +/* +** section_map(uint32_t *dest, uint32_t *src, size_t size) +** Load section using his symbols. +*/ +_section_load: + shlr2 r6 ! sections are force 4-aligned by the linker. + tst r6, r6 ! check null section... + bt load_loop_end ! ...if null, exit. + +load_loop_entry: + mov.l @r5, r1 ! get "src" data. + mov.l r1, @r4 ! copy into the "dest" section. + add #4, r5 ! update "src" address. + dt r6 ! check the load size. + bf/s load_loop_entry ! loop jump. + add #4, r4 ! update "dest" address. + +load_loop_end: + rts ! clean exit. + nop ! delayed branch. + + +/* +** section_wipe(uint32_t *bsection, size_t size) +** Wipe section using his symbols. +*/ +_section_wipe: + mov #0, r0 ! wipe data. + shlr2 r5 ! the section force 4-aligned by the linker. + tst r5, r5 ! Check null section... + bt wipe_loop_end ! ...if null, exit ! + +wipe_loop_entry: + mov.l r0, @r4 ! wipe section part. + dt r5 ! check the section size. + bf/s wipe_loop_entry ! loop jump. + add #4, r4 ! address update. + +wipe_loop_end: + rts ! clean exit. + nop ! delayed branch. + +.end diff --git a/src/kernel/bootstrap/start.c b/src/kernel/bootstrap/start.c new file mode 100644 index 0000000..012bb09 --- /dev/null +++ b/src/kernel/bootstrap/start.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +#include +#include + +// Internal symbols +//uint32_t gcc_fix[256]; +//uint32_t *VRAM = gcc_fix; +mpu_t current_mpu = MPU_UNKNOWN; +const char *casio_os_version = (void*)0xa0010020; +fx9860_context_t casio_context; +uint32_t casio_vbr; + +// Symbols defined by the linker +extern uint32_t bbss; +extern uint32_t sbss; +extern uint32_t bdata_ram; +extern uint32_t bdata_rom; +extern uint32_t sdata; +extern uint32_t bvhex_ram; +extern uint32_t bvhex_rom; +extern uint32_t svhex; +extern uint32_t vhex_vbr; + +// Internal functions. +extern void section_wipe(uint32_t *section, size_t size); +extern void section_load(uint32_t *dest, uint32_t *src, size_t size); +extern uint32_t vbr_set(uint32_t new_vbr); +extern uint32_t vbr_get(void); +extern mpu_t mpu_get(void); +extern int main(void); +extern void vhex_context_set(void); + + +__attribute__((section(".pretext"))) +int start(void) +{ + int error; + + // Wipe .bss section and dump .data / Vhex sections + section_wipe(&bbss, (size_t)&sbss); + section_load(&bdata_ram, &bdata_rom, (size_t)&sdata); + section_load(&bvhex_ram, &bvhex_rom, (size_t)&svhex); + + // Check MPU hardware. + current_mpu = mpu_get(); + if (current_mpu != MPU_SH7305) + { + return (0); + } + + // Mask interrupt, change context and switch VBR. + atomic_start(); + fx9860_context_save(&casio_context); + casio_vbr = vbr_set((uint32_t)&vhex_vbr); + vhex_context_set(); + atomic_end(); + +// VBR test. + __asm__ volatile ("trapa #0"); + + // Call high level abstraction. + error = main(); + + // Mask interrupt, change context and switch VBR. + atomic_start(); + fx9860_context_restore(&casio_context); + vbr_set(casio_vbr); + atomic_end(); + + // Return the abstraction error. + return (error); +} + +// +// initialize() - kernel entry +// This is the "real" entry of the kernel (after stack and CPU configuration). +// This part *SHOULD* be exception safe because the CPU block all exception and interruption, +// so if an exception occur during the "bootstrap" part, the processor will "crash". +// +/*void initialize(void) +{ + interrupt_block(); + printk(KERN_NOTICE, "Kernel initialization...\n"); + + // Wipe BSS section ! + printk(KERN_NOTICE, "Wipe bss / dump data...\n"); + memcpy(&bdata_ram, &bdata_rom, (size_t)&sdata); + memset(&bbss, 0x00, (size_t)&sbss); + + + // Check MPU. + current_mpu = mpu_get(); + if (current_mpu != MPU_SH7305) + { + printk(KERN_NOTICE, "ARCH ERROR !\n"); + int i = -1; + while (++i < 500000); + return (0); + } + + // Dump kernel and data. + printk(KERN_NOTICE, "Dump VBR space...\n"); + memcpy(&bvhex_ram, &bvhex_rom, (size_t)&svhex); + + // Initialize Interruption (extern module, VBR, handlers) + printk(KERN_NOTICE, "Initialize hardware context...\n"); + sh7305_context_initialize(); + + // Save / set new VBR. + printk(KERN_NOTICE, "Switch VBR / SR register...\n"); + __asm__ volatile ( + "stc vbr, %0;" + "stc sr, %1;" + "ldc %2, vbr;" + "ldc %3, sr" + : "=r"(casio_vbr), "=r"(casio_sr) + : "r"(&vhex_vbr), "r"(0x60000000) + : + ); + + printk(KERN_NOTICE, "Initialize heap space...\n"); + pm_heap_initialize((void*)0x8806000, (void*)0x8808000, 32); + + // Kernel initialized ! + printk(KERN_NOTICE, "Kernel initialized !\n"); + interrupt_unblock(); + + // Call shell. + shell_entry(); + + // Kernel exit part. + printk(KERN_NOTICE, "Kernel exit !"); + interrupt_block(); + + // restore Casio's context. + printk(KERN_NOTICE, "Restore hardware context...\n"); + sh7305_context_restore(); + + // Restore VBR / CPU configurations. + printk(KERN_NOTICE, "Restore VBR / SR...\n"); + __asm__ volatile ("ldc %0, vbr" : : "r"(&casio_vbr) : ); + __asm__ volatile ("ldc %0, sr" : : "r"(casio_sr) : ); + + // Clean exit. + interrupt_unblock(); + return (0); +}*/ diff --git a/src/kernel/bootstrap/vbr.s b/src/kernel/bootstrap/vbr.s new file mode 100644 index 0000000..93e6c73 --- /dev/null +++ b/src/kernel/bootstrap/vbr.s @@ -0,0 +1,35 @@ +.global _vbr_get +.global _vbr_set + +.type _vbr_set, @function +.type _vbr_get, @function + +.text +.align 2 +_vbr_get: + stc vbr, r0 ! Get VBR register. + rts ! Exit + nop ! (db) nop + +_vbr_set: + ! Block interrupt + stc sr, r1 ! Get SR register. + mov r1, r3 ! Save current SR data. + mov.l .bl_mask, r2 ! Get SR.BL mask. + or r2, r1 ! Set SR.BL to 1. + ldc r1, sr ! Update SR register. + + ! Get / Changle VBR + stc vbr, r0 ! Get VBR register. + ldc r4, vbr ! Update VBR register. + + ! Unblock interrupt. + ldc r3, sr ! Restore SR register. + + ! Exit + rts ! Exit + nop ! (db) nop + +.align 4 +.bl_mask: .long 0x100000f0 +.end diff --git a/src/kernel/bootstrap/vhex_context.c b/src/kernel/bootstrap/vhex_context.c new file mode 100644 index 0000000..0b6c18b --- /dev/null +++ b/src/kernel/bootstrap/vhex_context.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +void vhex_context_set(void) +{ + // Initialize Interrupt Controller (INTC). + SH7305_INTC.IPRA.WORD = 0x0000; + SH7305_INTC.IPRB.WORD = 0x0000; + SH7305_INTC.IPRC.WORD = 0x0000; + SH7305_INTC.IPRD.WORD = 0x0000; + SH7305_INTC.IPRE.WORD = 0x0000; + SH7305_INTC.IPRF.WORD = 0x0000; + SH7305_INTC.IPRG.WORD = 0x0000; + SH7305_INTC.IPRH.WORD = 0x0000; + SH7305_INTC.IPRI.WORD = 0x0000; + SH7305_INTC.IPRJ.WORD = 0x0000; + SH7305_INTC.IPRK.WORD = 0x0000; + SH7305_INTC.IPRL.WORD = 0x0000; + + // Configure Key Scan (KEYSC) +/* SH7305_INTC.IMR5.KEYI = 1; // Mask KEYSC interrupt. + SH7305_INTC.IPRF.KEYSC = 15; // Disable KEYSC interrupt. + SH7305_KEYSC.CONTROL.KEYIE = 0; // Disable KEYSC interrupt during init. + SH7305_KEYSC.CONTROL.INTMODE = 0b00; // Use default (?) interrupt mode. + SH7305_KEYSC.AUTOFIX.ENABLE = 1; // Enable key bounce fix (?) + SH7305_KEYSC.AUTOFIX.UNKNOWN0 = 0b100; // Unknown, use Casio's value. (autofix) + SH7305_KEYSC.AUTOFIX.UNKNOWN1 = 0b10; // Unknown, use Casio's value. (autofix) + SH7305_KEYSC.SCAN_MODE.UNKNOWN0 = 0b000; // Unknown, use Casio's value. (scan mode) + SH7305_KEYSC.SCAN_MODE.UNKNOWN1 = 0b010; // Unknown, use Casio's value. (scan mode) + SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000100; // Interrupt when one key is pressed or released. + SH7305_KEYSC.SCAN_WAIT.TIME = 0x00; // No time between each interrupt. + SH7305_KEYSC.SCAN_INTERVAL = 0x98; // Unknown, use Casio's value. (scan interval) + SH7305_KEYSC.KYOUTDR.KYO5DT = 0b11; // Trigger when high-impedance state is detected. + SH7305_KEYSC.KYOUTDR.KYO4DT = 0b11; // Trigger when high-impedance state is detected. + SH7305_KEYSC.KYOUTDR.KYO3DT = 0b11; // Trigger when high-impedance state is detected. + SH7305_KEYSC.KYOUTDR.KYO2DT = 0b11; // Trigger when high-impedance state is detected. + SH7305_KEYSC.KYOUTDR.KYO1DT = 0b11; // Trigger when high-impedance state is detected. + SH7305_KEYSC.KYOUTDR.KYO0DT = 0b11; // Trigger when high-impedance state is detected. + SH7305_KEYSC.KYINDR.KYDIR6 = 1; // Scan [F1],[SHIFT],[ALPHA],[x,o,T],[div],[7],[4],[1],[0] + SH7305_KEYSC.KYINDR.KYDIR5 = 1; // Scan [F2],[OPT],[^2],[log],[FD],[8],[5],[2],[.] + SH7305_KEYSC.KYINDR.KYDIR4 = 1; // Scan [F3],[VAR],[^],[ln],[(],[9],[6],[3],[x10] + SH7305_KEYSC.KYINDR.KYDIR3 = 1; // Scan [F4],[MENU],[EXIT],[sin],[)],[DEL],[x],[+],[(-)] + SH7305_KEYSC.KYINDR.KYDIR2 = 1; // Scan [F5],[left],[down],[cos],[,],[%],[-],[EXE] + SH7305_KEYSC.KYINDR.KYDIR1 = 1; // Scan [F6],[up],[right],[tan],[->] + SH7305_KEYSC.KYINDR.KYDIR0 = 1; // Scan [AC/ON] + SH7305_KEYSC.CONTROL.KEYIE = 1; // Enable KEYSC interrupt. + SH7305_INTC.IPRF.KEYSC = 15; // Set KEYSC interrupt priority (max). + SH7305_INTC.IMCR5.KEYI = 1; // Clear KEYSC interrupt mask. +*/ +} diff --git a/src/kernel/hardware/t6k11/display.s b/src/kernel/hardware/t6k11/display.s new file mode 100644 index 0000000..d47a28b --- /dev/null +++ b/src/kernel/hardware/t6k11/display.s @@ -0,0 +1,55 @@ +.global _t6k11_display +.type _t6k11_display, @function + +.text +.align 2 +/* + _t6k11_display(void *vram) + This function will display the vram on the screen. + This is the T6K11 drivers, DO NOT USE this function if you are + not absolutly sure that what you are doing. + + TODO: use DMA ? +*/ +# register organisation: +# r0 Y axis loop. +# r1 LCD register selector. +# r2 LCD data register. +# r3 X axis loop. +# r4 VRAM address. +_t6k11_display: + mov.l r8, @-r15 + mov.l r9, @-r15 + mov.l 1f, r1 + mov.l 2f, r2 + mov #4, r6 + mov #0, r7 + mov #7, r8 + mov #192, r5 + mov #64, r0 + loop_y: + + mov.b r6, @r1 + mov.b r5, @r2 + mov.b r6, @r1 + mov.b r7, @r2 + mov.b r8, @r1 + mov #16, r3 + loop_x: + + mov.b @r4+, r9 + mov.b r9, @r2 + + dt r3 + bf loop_x + + dt r0 + bf.s loop_y + add #1, r5 + mov.l @r15+, r9 + rts + mov.l @r15+, r8 + +.align 4 +1: .long 0xb4000000 /* LCD register selector */ +2: .long 0xb4010000 /* LCD data register */ diff --git a/src/kernel/tty/close.c b/src/kernel/tty/close.c new file mode 100644 index 0000000..bd0bacf --- /dev/null +++ b/src/kernel/tty/close.c @@ -0,0 +1,7 @@ +#include + +int tty_close(void) +{ + // Do nothing for now. + return (0); +} diff --git a/src/kernel/tty/open.c b/src/kernel/tty/open.c new file mode 100644 index 0000000..42cd727 --- /dev/null +++ b/src/kernel/tty/open.c @@ -0,0 +1,18 @@ +#include +#include + +// Internal TTY object. +struct tty_s tty; + +int tty_open(void) +{ + // Initialize TTY. + tty.cursor.x = 0; + tty.cursor.y = 0; + tty.cursor.max.x = DISPLAY_SCREEN_WIDTH / (KERNEL_FONT_REAL_WIDTH + 1); + tty.cursor.max.y = DISPLAY_SCREEN_HEIGHT / (KERNEL_FONT_REAL_HEIGHT + 1); + + // Clear VRAM. + dclear(); + return (0); +} diff --git a/src/kernel/tty/write.c b/src/kernel/tty/write.c new file mode 100644 index 0000000..51fb577 --- /dev/null +++ b/src/kernel/tty/write.c @@ -0,0 +1,49 @@ +#include +#include + +// Internal TTY object. +extern struct tty_s tty; + +static void tty_new_line(void) +{ + tty.cursor.x = 0; + if (tty.cursor.y + 1 >= tty.cursor.max.y) + { + dscroll(KERNEL_FONT_REAL_HEIGHT + 1); + return; + } + tty.cursor.y = tty.cursor.y + 1; + return; +} + +static void tty_update_cursor(void) +{ + tty.cursor.x = tty.cursor.x + 1; + if (tty.cursor.x >= tty.cursor.max.x) + tty_new_line(); +} + +int tty_write(char const *str, ...) +{ + int i; + + // Do not handle strig format for now. + + // Display string format. + i = -1; + while (str[++i] != '\0') + { + // Check new line char. + if (str[i] == '\n') + tty_new_line(); + // Display char. + dascii( + tty.cursor.x * (KERNEL_FONT_REAL_WIDTH + 1), + tty.cursor.y * (KERNEL_FONT_REAL_HEIGHT + 1), + str[i] + ); + tty_update_cursor(); + } + dupdate(); + return (i); +} diff --git a/src/kernel/util/atomic.s b/src/kernel/util/atomic.s new file mode 100644 index 0000000..6d7b28a --- /dev/null +++ b/src/kernel/util/atomic.s @@ -0,0 +1,27 @@ +.global _atomic_start +.global _atomic_end + +.type _atomic_start, @function +.type _atomic_end, @function + +.align 2 +_atomic_start: + stc sr, r1 ! Get SR register. + mov.l .bl_mask, r0 ! Get SR.BL mask. + or r0, r1 ! Set SR.BL to 1. + ldc r1, sr ! Update SR register. + rts ! Exit. + nop ! (db) nop. + +_atomic_end: + stc sr, r1 ! Get SR regiter. + mov.l .bl_mask, r0 ! Get SR.BL register. + not r0, r0 ! Get correct mask to remove the SR.BL bit. + and r0, r1 ! Set SR.BL to 0. + ldc r1, sr ! Update SR register. + rts ! Exit. + nop ! (db) nop. + +.align 4 +.bl_mask: .long (1 << 28) +.end diff --git a/src/kernel/vbr/exception.c b/src/kernel/vbr/exception.c new file mode 100644 index 0000000..6fe5a78 --- /dev/null +++ b/src/kernel/vbr/exception.c @@ -0,0 +1,38 @@ +#include + +__attribute__((section(".vhex.exception"), interrupt_handler)) +void exception_handler(void) +{ + uint32_t spc; + uint32_t ssr; + uint32_t sr; + + + // Get some registers's data. + __asm__ volatile ( + "stc spc, %0;" + "stc ssr, %1;" + "stc sr, %2" + : "=r"(spc), "=r"(ssr), "=r"(sr) + : + : + ); + + // Write exception informations. + dclear(); + dprint(0, 0, + "Ho crap ! Exception !\n" + "tra: %#x\n" + "expevt: %#x\n" + "spc: %#x\n" + "ssr: %#x\n" + "sr: %#x", + *((uint32_t *)0xff000020), + *((uint32_t *)0xff000024), + spc, + ssr, + sr + ); + dupdate(); + while (1); +} diff --git a/src/kernel/vbr/interrupt.c b/src/kernel/vbr/interrupt.c new file mode 100644 index 0000000..f1d6f32 --- /dev/null +++ b/src/kernel/vbr/interrupt.c @@ -0,0 +1,10 @@ +#include + +__attribute__((section(".vhex.interrupt"), interrupt_handler)) +void interrupt_handler(void) +{ + dclear(); + dprint(0, 0, "Interrupt handler (%#x)\n", *(uint32_t*)0xff000028); + dupdate(); + while (1); +} diff --git a/src/kernel/vbr/tlb.c b/src/kernel/vbr/tlb.c new file mode 100644 index 0000000..41d6280 --- /dev/null +++ b/src/kernel/vbr/tlb.c @@ -0,0 +1,38 @@ +#include + +__attribute__((section(".glados.tlb"), interrupt_handler)) +void tlb_handler(void) +{ + uint32_t spc; + uint32_t ssr; + uint32_t sr; + + + // Get some registers's data. + __asm__ volatile ( + "stc spc, %0;" + "stc ssr, %1;" + "stc sr, %2" + : "=r"(spc), "=r"(ssr), "=r"(sr) + : + : + ); + + // Write exception informations. + dclear(); + dprint(0, 0, + "Ho crap ! Exception !\n" + "tra: %#x\n" + "expevt: %#x\n" + "spc: %#x\n" + "ssr: %#x\n" + "sr: %#x", + *((uint32_t *)0xff000020), + *((uint32_t *)0xff000024), + spc, + ssr, + sr + ); + dupdate(); + while (1); +} diff --git a/src/keys.c b/src/keys.c deleted file mode 100644 index 36ef02f..0000000 --- a/src/keys.c +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include -#include -#include - -// -// check_session() -// Check if the pressed key is [Fx], and switch the current session. -// -static int check_session(unsigned int key, struct vhex_s *vhex) -{ - static const unsigned int keys_switch[SESSIONS_SLOT] = { - KEY_F1, KEY_F2, KEY_F3, - KEY_F4, KEY_F5, KEY_F6 - }; - size_t i; - - i = -1; - while (++i < SESSIONS_SLOT && key != keys_switch[i]); - if (i < SESSIONS_SLOT){ - vhex->current_session = i; - return (0); - } - return (-1); -} - -// -// check_special() -// As explained below, the Casio getkey function has an internal status. -// Here we check if a "special" keys are pressed and update internal Vhex -// "keyboard's status". -// -static int check_special(unsigned int key, struct vhex_s *vhex, struct session_s *session) -{ - if (!(key == KEY_OPTN || key == KEY_SHIFT || key == KEY_ALPHA)) - return (-1); - if (vhex->insert.mode == LETTER){ - vhex->insert.mode = NUMBER; - if (key == KEY_ALPHA) - return (0); - } - if (key == KEY_OPTN){ - if (session->mode != COMMAND){ - memset(vhex->info, '\0', CMD_LENGHT_MAX); - session->mode = COMMAND; - save_window(1); - } - else - session->mode = (session->anchor == 0x00000000) ? UNUSED : NORMAL; - } - if (key == KEY_SHIFT) - vhex->insert.mode = (vhex->insert.mode == SHIFT) ? NUMBER : SHIFT; - if (key == KEY_ALPHA){ - //TODO: update this. - if (vhex->insert.mode == SHIFT) - vhex->insert.mode = CAPS_LOCK; - else if (vhex->insert.mode == CAPS_LOCK) - vhex->insert.mode = NUMBER; - else - vhex->insert.mode = LETTER; - } - return (0); -} - -// -// check_alphanum() -// Check if the key pressed is an alphanumeric character and update the user command. -// -/* TODO: find better way to do the job (?) */ -static int check_alphanum(unsigned int key, struct vhex_s *vhex, struct session_s *session) -{ - static const unsigned int keys_alpha[] = { - KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, - KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, - KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, - KEY_Y, KEY_Z - }; - static const unsigned int keys_number[] = { - KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 - }; - unsigned int *cache; - size_t size; - size_t end; - size_t i; - char buf; - - if (session->mode != COMMAND) - return (-1); - i = -1; - size = strlen(vhex->insert.cmd); - end = (vhex->insert.mode == NUMBER) ? 10 : 26; - cache = (vhex->insert.mode == NUMBER) ? (void *)keys_number : (void *)keys_alpha; - while (++i < end && key != cache[i]); - if (i >= end) - return (-1); - if (size < CMD_LENGHT_MAX){ - buf = (vhex->insert.mode == NUMBER) ? '0' + i : 'a' + i; - strcat(vhex->insert.cmd, &buf); - } - if (vhex->insert.mode == LETTER) - vhex->insert.mode = NUMBER; - vhex->history.offset = 0; - return (0); -} - -// -// check_arrow() -// Check if the key pressed is an arrow key. -// Here we just check left and right key, but they do not have the same action when -// the mode is COMMAND or not; basically: -// * COMMAND : Udpate the user's command using the history. -// * NORMAL : Move the anchor cursor. -// * UNUSED : Do nothing. -// -static int check_arrow(unsigned int key, struct vhex_s *vhex, struct session_s *session) -{ - if (key != KEY_UP && key != KEY_DOWN) - return (-1); - if (session->mode == COMMAND - && ((key == KEY_UP && vhex->history.offset < vhex->history.deep) - || (key == KEY_DOWN && vhex->history.offset > 0))){ - if (vhex->history.offset == 0) - strcpy(vhex->insert.backup, vhex->insert.cmd); - vhex->history.offset += (key == KEY_UP) ? 1 : -1; - if (vhex->history.offset > 0) - strcpy(vhex->insert.cmd, - history_get(vhex->history.list, vhex->history.offset - 1)); - else - strcpy(vhex->insert.cmd, vhex->insert.backup); - } - if (session->mode == NORMAL) - session->cursor += (key == KEY_UP) ? -1 : 1; - return (0); -} - -// -// key_handling() -// We need to do several things here; the Casio getkey function handles [SHIFT], [ALPHA] -// and [MENU] key and it is able to do some special thing using the key combination like -// shutdown the calculator, change the brightness or return to the main menu using. -// But when the user press on [SHIFT] or [ALPHA], getkey() return not the same value for -// the same key (and we cannot know the "status"). -// So we need to "emulate" the getkey's status and execute the appropriate action with -// the key returned by Casio. -// -void key_handling(struct vhex_s *vhex, struct session_s *session, unsigned int key) -{ - size_t size; - - if (check_session(key, vhex) == 0 - || check_special(key, vhex, session) == 0 - || check_arrow(key, vhex, session) == 0 - || check_alphanum(key, vhex, session) == 0 - || session->mode != COMMAND) - return; - if (key == KEY_DEL || key == KEY_INS){ - size = strlen(vhex->insert.cmd); - if (size > 0) - strncpy(vhex->insert.cmd, vhex->insert.cmd, size - 1); - } - if (key == KEY_SPACE) - strcat(vhex->insert.cmd, " "); - if (key == KEY_QUOTE) - strcat(vhex->insert.cmd, "\""); - if (key == KEY_ENTER){ - vhex->insert.mode = NUMBER; - command_entry(session, vhex); - } -} diff --git a/src/lib/display/dascii.c b/src/lib/display/dascii.c new file mode 100644 index 0000000..082fcdb --- /dev/null +++ b/src/lib/display/dascii.c @@ -0,0 +1,109 @@ +#include +#include + +static const uint8_t kernel_font_bitmap[] = { + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xef, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xad, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x5e, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x2a, 0x92, 0x11, 0x11, 0x28, 0x00, 0x00, 0x38, 0xbb, 0xab, 0xbb, 0xbb, + 0x80, 0x08, 0x23, 0x02, 0x57, 0x31, 0x52, 0x41, 0x22, 0x00, 0x01, 0x51, + 0x11, 0x54, 0x41, 0x55, 0x22, 0x27, 0x21, 0x04, 0x0a, 0xc4, 0x40, 0x82, + 0xae, 0x0e, 0x04, 0xa2, 0xee, 0xee, 0xe2, 0xee, 0x00, 0x80, 0x24, 0x00, + 0x1c, 0xd1, 0x41, 0x04, 0x08, 0x80, 0x11, 0x45, 0x04, 0x45, 0x45, 0x44, + 0x88, 0x9c, 0x80, 0x10, 0x2b, 0x09, 0x81, 0x10, 0x02, 0x01, 0x03, 0x8b, + 0xb8, 0xbb, 0x8b, 0xb8, 0x20, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xee, + 0xec, 0xee, 0xea, 0xee, 0xa8, 0xae, 0xee, 0xee, 0x6e, 0xaa, 0xaa, 0xae, + 0xe0, 0xe4, 0x05, 0x55, 0x15, 0x11, 0x14, 0x89, 0x51, 0xd5, 0x55, 0x55, + 0x09, 0x55, 0x55, 0x45, 0x10, 0x54, 0x0b, 0xb2, 0x2b, 0xba, 0xb9, 0x13, + 0x22, 0xaa, 0xba, 0xb3, 0x92, 0xaa, 0x91, 0x12, 0x10, 0x80, 0x55, 0x54, + 0x54, 0x45, 0x52, 0x25, 0x45, 0x55, 0x47, 0x51, 0x25, 0x57, 0x52, 0x44, + 0x11, 0x00, 0xca, 0xee, 0xce, 0x8e, 0xae, 0xca, 0xea, 0xae, 0x8e, 0xac, + 0x4e, 0x4a, 0xa4, 0xee, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, + 0x90, 0x9a, 0x11, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, + 0x30, 0x39, 0x14, 0x31, 0x52, 0x54, 0x00, 0x42, 0x76, 0x26, 0x35, 0x37, + 0x55, 0x55, 0x57, 0x22, 0x20, 0x70, 0x6c, 0x86, 0xee, 0x6c, 0xc4, 0xa4, + 0xea, 0xaa, 0xac, 0xc4, 0xaa, 0xa4, 0xa4, 0x84, 0x26, 0xe1, 0x55, 0x15, + 0x08, 0x54, 0x89, 0x89, 0x55, 0x58, 0xd0, 0x49, 0x55, 0xd4, 0x90, 0x88, + 0x99, 0xc1, 0xb1, 0x99, 0x93, 0x2b, 0xb2, 0x9a, 0xa9, 0x20, 0xa3, 0x19, + 0x92, 0xa9, 0x39, 0x93, 0x03, 0x80 +}; + +void dascii(int x, int y, char const c) +{ + off_t bitmap_offset_x; + off_t bitmap_offset_y; + off_t vram_offset_y; + int real_width; + int real_height; + uint8_t pixel_test; + int pixel_cursor; + int i; + int j; + + // Calculate the charactere position (bitmap) + bitmap_offset_y = (c / KERNEL_FONT_NB_CHAR_X) * (KERNEL_FONT_BITMAP_WIDTH * KERNEL_FONT_BITMAP_CHEIGHT); + bitmap_offset_x = (c - ((c / KERNEL_FONT_NB_CHAR_X) * KERNEL_FONT_NB_CHAR_X)) * KERNEL_FONT_BITMAP_CWIDTH; + + // Set default size. + real_width = KERNEL_FONT_REAL_WIDTH; + real_height = KERNEL_FONT_REAL_HEIGHT; + + // Check X axis culling. + if (x < 0) + { + bitmap_offset_x = bitmap_offset_x + x; + real_width = KERNEL_FONT_REAL_WIDTH + x; + x = 0; + } + else if (x + KERNEL_FONT_REAL_WIDTH >= DISPLAY_SCREEN_WIDTH) + real_width = DISPLAY_SCREEN_WIDTH - x; + + // Check Y axis culling. + if (y < 0) + { + real_height = KERNEL_FONT_REAL_HEIGHT + y; + bitmap_offset_y = bitmap_offset_y + ((-y) * KERNEL_FONT_BITMAP_WIDTH); + y = 0; + } + else if (y + KERNEL_FONT_REAL_HEIGHT >= DISPLAY_SCREEN_HEIGHT) + real_height = DISPLAY_SCREEN_HEIGHT - y; + + // Check potential error. + // @note we do not check real_height because the while() while do the job for us. + if (real_width < 0) + return; + + // Calculate VRAM buffer starting position. + // @note: + // The screen width size is always 128 and we + // use 4-aligned Video RAM so 32 pixel per "slot" + // and 128 / 32 = 4 + // y * 4 can be optimised by used shift operator + // this is why we use y << 2 because 2^2 = 4. + vram_offset_y = y << 2; + + // Draw character, pixer per pixel... (x_x) + i = -1; + while (++i < real_height) + { + j = -1; + while (++j < real_width) + { + pixel_cursor = bitmap_offset_x + bitmap_offset_y + j; + pixel_test = 0x80 >> (pixel_cursor & 0x07); + if (pixel_test & kernel_font_bitmap[pixel_cursor >> 3]) + { + VRAM[((x + j) >> 5) + vram_offset_y] |= 0x80000000 >> ((x + j) & 0x1f); + } + } + bitmap_offset_y = bitmap_offset_y + KERNEL_FONT_BITMAP_WIDTH; + vram_offset_y = vram_offset_y + 4; + } +} diff --git a/src/lib/display/dclear.c b/src/lib/display/dclear.c new file mode 100644 index 0000000..1490b75 --- /dev/null +++ b/src/lib/display/dclear.c @@ -0,0 +1,10 @@ +#include + +void dclear(void) +{ + int i; + + i = 256; + while (--i >= 0) + VRAM[i] = 0x00000000; +} diff --git a/src/lib/display/dprint.c b/src/lib/display/dprint.c new file mode 100644 index 0000000..b790ca5 --- /dev/null +++ b/src/lib/display/dprint.c @@ -0,0 +1,31 @@ +#include +#include +#include + +void dprint(int x, int y, char const *str, ...) +{ + char buffer[512]; + int default_pos_x; + va_list ap; + int i; + + // printf string manipulation. + // TODO: remove me ! + va_start(ap, str); + vsprintf(buffer, str, ap); + va_end(ap); + + i = -1; + default_pos_x = x; + while (buffer[++i] != '\0') + { + if (buffer[i] == '\n') + { + y = y + KERNEL_FONT_REAL_HEIGHT + 1; + x = default_pos_x; + continue; + } + dascii(x, y, buffer[i]); + x = x + KERNEL_FONT_REAL_WIDTH + 1; + } +} diff --git a/src/lib/display/dscroll.c b/src/lib/display/dscroll.c new file mode 100644 index 0000000..a371a34 --- /dev/null +++ b/src/lib/display/dscroll.c @@ -0,0 +1,26 @@ +#include + +void dscroll(int lines) +{ + int i; + + // Scoll n lines + i = 0; + while ((i >> 2) < 63 - lines) + { + VRAM[i + 0] = VRAM[i + (lines << 2) + 0]; + VRAM[i + 1] = VRAM[i + (lines << 2) + 1]; + VRAM[i + 2] = VRAM[i + (lines << 2) + 2]; + VRAM[i + 3] = VRAM[i + (lines << 2) + 3]; + i = i + 4; + } + // Clear last n lines + while ((i >> 2) < 64) + { + VRAM[i + 0] = 0x0000; + VRAM[i + 1] = 0x0000; + VRAM[i + 2] = 0x0000; + VRAM[i + 3] = 0x0000; + i = i + 4; + } +} diff --git a/src/lib/display/dupdate.c b/src/lib/display/dupdate.c new file mode 100644 index 0000000..1ec82a9 --- /dev/null +++ b/src/lib/display/dupdate.c @@ -0,0 +1,8 @@ +#include +#include + +//FIXME: Check OS 3.00 ! +void dupdate(void) +{ + t6k11_display(VRAM); +} diff --git a/src/lib/stdio/sprintf.c b/src/lib/stdio/sprintf.c new file mode 100644 index 0000000..a9bcdd0 --- /dev/null +++ b/src/lib/stdio/sprintf.c @@ -0,0 +1,10 @@ +#include + +void sprintf(char *str, char const *format, ...) +{ + va_list ap; + + va_start(ap, format); + vsprintf(str, format, ap); + va_end(ap); +} diff --git a/src/string/sprintf.c b/src/lib/stdio/vsprintf.c similarity index 88% rename from src/string/sprintf.c rename to src/lib/stdio/vsprintf.c index 483de7c..1e24a9d 100644 --- a/src/string/sprintf.c +++ b/src/lib/stdio/vsprintf.c @@ -1,4 +1,4 @@ -#include +#include static size_t strbase(char *dest, uint32_t nb, size_t size, int base) { @@ -43,7 +43,7 @@ static size_t strndump(char *dest, char const *str, size_t size) return (i); } -__attribute__((weak)) void vsprintf(char *str, char const *format, va_list ap) +void vsprintf(char *str, char const *format, va_list ap) { size_t size; size_t len; @@ -102,12 +102,3 @@ __attribute__((weak)) void vsprintf(char *str, char const *format, va_list ap) } *str = '\0'; } - -__attribute__((weak)) void sprintf(char *str, char const *format, ...) -{ - va_list ap; - - va_start(ap, format); - vsprintf(str, format, ap); - va_end(ap); -} diff --git a/src/lib/string/memcpy.c b/src/lib/string/memcpy.c new file mode 100644 index 0000000..f8cc900 --- /dev/null +++ b/src/lib/string/memcpy.c @@ -0,0 +1,9 @@ +#include +#include + +void *memcpy(void *dest, const void *src, size_t count) +{ + for (size_t i = 0 ; i < count ; i = i + 1) + ((uint8_t*)dest)[i] = ((uint8_t*)src)[i]; + return (dest); +} diff --git a/src/string/memset.c b/src/lib/string/memset.c similarity index 51% rename from src/string/memset.c rename to src/lib/string/memset.c index 6392c74..6c20f8a 100644 --- a/src/string/memset.c +++ b/src/lib/string/memset.c @@ -1,7 +1,7 @@ -#include +#include //TODO: update me :( -__attribute__((weak)) void *memset(void *s, int c, size_t n) +void *memset(void *s, int c, size_t n) { while ((int)--n >= 0) ((uint8_t*)s)[n] = c; diff --git a/src/string/strcat.c b/src/lib/string/strcat.c similarity index 73% rename from src/string/strcat.c rename to src/lib/string/strcat.c index c1c1419..5cc1601 100644 --- a/src/string/strcat.c +++ b/src/lib/string/strcat.c @@ -1,6 +1,6 @@ -#include +#include -__attribute__((weak)) char *strcat(char *dest, char const *src) +char *strcat(char *dest, char const *src) { size_t i; size_t start; diff --git a/src/lib/string/strcmp.c b/src/lib/string/strcmp.c new file mode 100644 index 0000000..e225db5 --- /dev/null +++ b/src/lib/string/strcmp.c @@ -0,0 +1,13 @@ +#include + +int strcmp(const char *s1, const char *s2) +{ + if (s1 == NULL || s2 == NULL) + return (0); + while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) + { + s1 += 1; + s2 += 1; + } + return (*s1 - *s2); +} diff --git a/src/string/strcpy.c b/src/lib/string/strcpy.c similarity index 66% rename from src/string/strcpy.c rename to src/lib/string/strcpy.c index f5e78ff..a9eb95d 100644 --- a/src/string/strcpy.c +++ b/src/lib/string/strcpy.c @@ -1,6 +1,6 @@ -#include +#include -__attribute__((weak)) char *strcpy(char *dest, char const *src) +char *strcpy(char *dest, char const *src) { size_t i; @@ -13,7 +13,7 @@ __attribute__((weak)) char *strcpy(char *dest, char const *src) return (dest); } -__attribute__((weak)) char *strncpy(char *dest, char const *str, size_t size) +char *strncpy(char *dest, char const *str, size_t size) { size_t i; diff --git a/src/string/strlen.c b/src/lib/string/strlen.c similarity index 57% rename from src/string/strlen.c rename to src/lib/string/strlen.c index 56cf1c6..d151965 100644 --- a/src/string/strlen.c +++ b/src/lib/string/strlen.c @@ -1,6 +1,6 @@ -#include +#include -__attribute__((weak)) size_t strlen(char const *str) +size_t strlen(char const *str) { size_t i; diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 74f9613..0000000 --- a/src/main.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include - -// -// vhex_constructor() -// Initialize all information needed by the add-in: session, -// GetKey configuration, ... -// -static void vhex_constructor(struct vhex_s *vhex) -{ - size_t i; - - i = -1; - memset(vhex->info, '\0', CMD_LENGHT_MAX); - memset(vhex->insert.cmd, '\0', CMD_LENGHT_MAX); - //TODO: Auto detect GetKey configuration !! - vhex->insert.mode = NUMBER; - vhex->history.list = NULL; - vhex->history.offset = 0; - vhex->history.deep = 0; - vhex->current_session = 0; - while (++i < SESSIONS_SLOT){ - vhex->session[i].mode = UNUSED; - vhex->session[i].anchor = 0x00000000; - } -} - -// -// main() -// User entry, but we need to initialize some information before -// starting the "main loop". -// -int main(void) -{ - struct vhex_s vhex; - unsigned int key; - - key = 0; - vhex_constructor(&vhex); - while (1){ - dclear(); - display_instructions(&vhex.session[vhex.current_session]); - display_metainfos(&vhex, &vhex.session[vhex.current_session]); - getkey(&key); - key_handling(&vhex, &vhex.session[vhex.current_session], key); - } - return (0); -} diff --git a/src/string/atoi_base.c b/src/string/atoi_base.c deleted file mode 100644 index f949050..0000000 --- a/src/string/atoi_base.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -static INLINE int check_base(char n, int base) -{ - char max; - - max = (base <= 10) ? '0' + base - 1 : ('a' + base - 11); - return ((max < n)); -} - -// -// atoi_base() -// Wrapped atoi function that takes the base which the number -// (stored in the string) are encoded -// -uint32_t atoi_base(char const *str, int base) -{ - uint32_t result; - size_t start; - - start = -1; - result = 0; - while (str[++start] != '\0' && check_base(str[start], base) == 0){ - result *= base; - if (str[start] <= '9') - result += str[start] - '0'; - else - result += (str[start] - 'a') + 10; - } - return (result); -} diff --git a/src/string/strcmp.c b/src/string/strcmp.c deleted file mode 100644 index f0e7635..0000000 --- a/src/string/strcmp.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -__attribute__((weak)) int strcmp(const char *s1, const char *s2) -{ - if (s1 == NULL || s2 == NULL) - return (0); - while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){ - s1 += 1; - s2 += 1; - } - return (*s1 - *s2); -} diff --git a/src/string/strtotab.c b/src/string/strtotab.c deleted file mode 100644 index a5efe7c..0000000 --- a/src/string/strtotab.c +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef DEBUG -//# include -# include -#else -//# include "commands.h" -# include -# include -#endif -#include -#include - -// Internal prototypes. -extern int strtotab(int *argc, char ***argv, char const *str); -extern void strtotab_quit(int *argc, char ***argv); - -// -// parser_get_word() -// Get the word at the current cursor location. -// -static ssize_t parser_get_word(char ***tab, size_t *tab_pos, -char const *str, int *counter) -{ - ssize_t i; - - i = -1; - while (str[++i] != '\0' && str[i] != '\n' && str[i] != ' ' && str[i] != '\t'); - if (*tab != NULL){ - (*tab)[*tab_pos] = (char*)malloc(i + 1); - if ((*tab)[*tab_pos] == NULL) - return (-1); - memset((*tab)[*tab_pos], 0, i + 1); - strncpy((*tab)[(*tab_pos)++], str, i); - } - (*counter)++; - return (i); -} - -// -// parser_get_inibitor() -// This function will get the content of an inhibitor (and check if the -// inhibitor characteres are alone or not). -// -static ssize_t parser_get_inibitor(char ***tab, size_t *tab_pos, -char const *str, int *counter) -{ - ssize_t i; - - i = 0; - while (str[++i] != '\0' && str[i] != '\"'); - if (str[i] != '\"') - return (0); - if (*tab != NULL){ - (*tab)[*tab_pos] = (char*)malloc(i + 1); - if ((*tab)[*tab_pos] == NULL) - return (-1); - memset((*tab)[*tab_pos], 0, i + 1); - strncpy((*tab)[(*tab_pos)++], str + 1, i - 1); - } - (*counter)++; - return (i + 1); -} - -// -// parser_setup_arg() -// This function removes useless spaces, tabs and handle '\"' inhibitor. -// Return the number of word(s) stored in "str". -// -static int parser_entry(char ***tab, char const *str) -{ - size_t tab_pos; - ssize_t size; - int counter; - - str--; - counter = 0; - tab_pos = 0; - while (*(++str) != '\0' && *str != '\n'){ - if (*str == '\"'){ - size = parser_get_inibitor(tab, &tab_pos, str, &counter); - if (size < 0) - return (-1); - str += size; - } - if (*str != ' ' && *str != '\t'){ - size = parser_get_word(tab, &tab_pos, str, &counter) - 1; - if (size < 0) - return (-1); - str += size; - } - } - return (counter); -} - -// -// strtotab() -// Generate word table and indicated the number of word find in the string. -// -int strtotab(int *argc, char ***argv, char const *str) -{ - int i; - - // Check memory fault. - if (argc == NULL || argv == NULL || str == NULL) - return (EFAULT); - - // Get the number of word. - *argv = NULL; - *argc = parser_entry(argv, str); - if (*argc <= 0) - return (EINVAL); - - // Alloc tab. - *argv = (char **)malloc(sizeof(char *) * (*argc + 1)); - if (*argv == NULL) - return (ENOMEM); - i = *argc; - while (--i >= 0) - (*argv)[i] = NULL; - - // Get word. - if (parser_entry(argv, str) != *argc){ - strtotab_quit(argc, argv); - return (ENOMEM); - } - (*argv)[*argc] = NULL; - return (0); -} - -/* strtotab() - Free all allocated memory generated by "strtotab()" */ -void strtotab_quit(int *argc, char ***argv) -{ - if (argc == NULL || argv == NULL) - return; - if (*argv == NULL){ - *argc = 0; - return; - } - while (--(*argc) >= 0) - free((*argv)[*argc]); - free(*argv); - *argv = NULL; - *argc = 0; -} diff --git a/src/syscalls.s b/src/syscalls.s deleted file mode 100644 index 70c827b..0000000 --- a/src/syscalls.s +++ /dev/null @@ -1,98 +0,0 @@ -.global _casio_GetKey -.global _casio_PrintMini -.global _casio_Bdisp_PutDisp_DD -.global _casio_Bdisp_AllClr_VRAM -.global _casio_Bdisp_DrawLine_VRAM -.global _casio_Bdisp_AreaClr_VRAM -.global _casio_RestoreDisp -.global _casio_SaveDisp -.global _casio_Malloc -.global _casio_Free - -.type _casio_GetKey, @function -.type _casio_PrintMini, @function -.type _casio_Bdisp_PutDisp_DD, @function -.type _casio_Bdisp_AllClr_VRAM, @function -.type _casio_Bdisp_DrawLine_VRAM, @function -.type _casio_Bdisp_AreaClr_VRAM, @function -.type _casio_RestoreDisp, @function -.type _casio_SaveDisp, @function -.type _casio_Malloc, @function -.type _casio_Free, @function - -.align 2 -_casio_GetKey: - mov.l .syscall_tab, r1 - mov.l .sys_getkey, r0 - jmp @r1 - nop - -_casio_PrintMini: - mov.l .syscall_tab, r1 - mov.l .sys_printMini, r0 - jmp @r1 - nop - -_casio_Bdisp_AllClr_VRAM: - mov.l .syscall_tab, r1 - mov.l .sys_clear, r0 - jmp @r1 - nop - -_casio_Bdisp_PutDisp_DD: - mov.l .syscall_tab, r1 - mov.l .sys_display, r0 - jmp @r1 - nop - -_casio_Bdisp_DrawLine_VRAM: - mov.l .syscall_tab, r1 - mov.l .sys_line, r0 - jmp @r1 - nop - -_casio_Bdisp_AreaClr_VRAM: - mov.l .syscall_tab, r1 - mov.l .sys_clear_area, r0 - jmp @r1 - nop - -_casio_RestoreDisp: - mov.l .syscall_tab, r1 - mov.l .sys_restore_disp, r0 - jmp @r1 - nop - -_casio_SaveDisp: - mov.l .syscall_tab, r1 - mov.l .sys_save_disp, r0 - jmp @r1 - nop - -_casio_Malloc: - mov.l .syscall_tab, r1 - mov.l .sys_malloc, r0 - jmp @r1 - nop - -_casio_Free: - mov.l .syscall_tab, r1 - mov.l .sys_free, r0 - jmp @r1 - nop - - -.align 4 -.syscall_tab: .long 0x80010070 -.sys_line: .long 0x00000030 -.sys_clear: .long 0x00000143 /*Bdisp_AllClr_VRAM */ -.sys_getkey: .long 0x0000090f -.sys_display: .long 0x00000028 -.sys_printMini: .long 0x00000c4f -.sys_clear_area: .long 0x0000014b -.sys_restore_disp: .long 0x00000814 -.sys_save_disp: .long 0x00000813 -.sys_malloc: .long 0x00000acd -.sys_free: .long 0x00000acc - -.end diff --git a/src/user/main.c b/src/user/main.c new file mode 100644 index 0000000..0f94379 --- /dev/null +++ b/src/user/main.c @@ -0,0 +1,34 @@ +#include +#include +#include + +int main(void) +{ + char *line; + + // Open TTY and display entry message + tty_open(); + tty_write("Welcome to Vhex !\n"); + + // Main loop + while (1) + { + // Write input indications. + // TODO: write current working directory ? + tty_write(">"); + + // Get each line writen by the user. + /*nbread = getline(&line, &size, 0); + if (nbread == EOF) + { + // TODO: check jobs ? + break; + }*/ + + // TODO: do some job. + } + + // Close TTY and return. + tty_close(); + return (0); +} diff --git a/tests/atoi_base_test.c b/tests/atoi_base_test.c deleted file mode 100644 index 0297d8c..0000000 --- a/tests/atoi_base_test.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -// Internal prototypes. -extern uint32_t atoi_base(char const *str, int base); - -Test(atoi_base, base_10) -{ - uint32_t result; - - result = atoi_base("12345", 10); - cr_assert_eq(result, 12345, "returned: %d\n", result); - cr_assert_eq(atoi_base("50926", 10), 50926); - cr_assert_eq(atoi_base("999999", 10), 999999); -} - -Test(atoi_base, base_16) -{ - uint32_t result; - - result = atoi_base("abcdef", 16); - cr_assert_eq(result, 0xabcdef, "returned: %#x\n", result); - cr_assert_eq(atoi_base("50926", 16), 0x50926); - cr_assert_eq(atoi_base("999999", 16), 0x999999); -} - -Test(atoi_base, base_error) -{ - cr_assert_eq(atoi_base("xxxxxx", 16), 0); - cr_assert_eq(atoi_base("50926x56", 16), 0x50926); - cr_assert_eq(atoi_base("o", 16), 0); -} diff --git a/tests/history_test.c b/tests/history_test.c deleted file mode 100644 index dac857f..0000000 --- a/tests/history_test.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "tests/internal.h" -#include "history.h" -#include - - -//TODO: write doc. - -Test(history, add) -{ - struct node *list; - - list = NULL; - cr_assert_eq(history_update(&list, "ls -l"), 0); - cr_assert_eq(history_update(&list, "cat -e"), 0); - cr_assert_eq(history_update(NULL, "cat -e"), EFAULT); - // malloc fails. - malloc_hook_update(FAIL_NEXT); - cr_assert_eq(history_update(&list, "cat -e"), ENOMEM); - - // Check info. - cr_assert_str_eq(list->data, "cat -e"); - cr_assert_str_eq(list->next->data, "ls -l"); - cr_assert_null(list->next->next); -} - -Test(history, get) -{ - struct node *list; - - list = NULL; - history_update(&list, "ls -l"); - history_update(&list, "cat -e"); - cr_assert_str_eq(history_get(list, 1), "ls -l"); - cr_assert_str_eq(history_get(list, 0), "cat -e"); - cr_assert_null(history_get(list, 4)); -} - -Test(history, quit) -{ - struct node *list; - - list = NULL; - history_quit(&list); - history_update(&list, "ls -l"); - history_update(&list, "cat -e"); - history_update(&list, "test"); - history_update(&list, "yes"); - history_quit(&list); - history_quit(NULL); - cr_assert_null(list); -} diff --git a/tests/internal.h b/tests/internal.h deleted file mode 100644 index ff3b006..0000000 --- a/tests/internal.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __INTERNAL_H__ -# define __INTERNAL_H__ - -#include -#include - -// -// status_t - all status available for hook. -// * FAIL_NONE : force malloc to work normaly. -// * FAIL_NEXT : force the next call of malloc to return NULL. -// * FAIL_NEXT_DYN : force X-nth call of malloc to return NULL. -// * FAIL_ALWAYS : force all malloc to return NULL. -// -typedef enum status_e -{ - FAIL_NONE, - FAIL_NEXT, - FAIL_ALWAYS, - FAIL_NEXT_DYN -} status_t; - -/* malloc_hook_update - udpate the behavior of the malloc hook */ -void malloc_hook_update(status_t status, ...); - -#endif /*__INTERNAL_H__*/ diff --git a/tests/malloc_hook.c b/tests/malloc_hook.c deleted file mode 100644 index fd54d84..0000000 --- a/tests/malloc_hook.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "tests/internal.h" -#include -#include - -// Internal prototypes / static symbols. -static void my_malloc_init_hook(void); -static void *my_malloc_hook(size_t size, const void *caller); -static void *old_malloc_hook; -static int hook_dyn_fail; -static int hook_status; - -// -// my_malloc_hook() -// This function will replace the current malloc hook by our own -// hook (which can return NULL if we want, it allows us to check -// the behavior of our code). -// -// NOTE: -// "man __malloc_hook" indicate to use "__malloc_initialize_hook" -// which will execute the initialization routine. But from glibc 2.24 -// onwards, this variable has been removed from the API. -// So, this is why we use "constructor" attribute to call our routine -// at the beginning of the test. -// -__attribute__((constructor)) -static void my_malloc_init_hook(void) -{ - old_malloc_hook = __malloc_hook; - __malloc_hook = my_malloc_hook; - hook_status = FAIL_NONE; -} - -// -// my_malloc_hook() -// For some tests we need to simulate (properly) a malloc fail; to do this -// we use a malloc hook and add static variables to force him to return -// NULL address. -// -// NOTE: -// All hooks of the glibc will be removed because of their poor behavior -// in multi threaded environment. -// But recently we have seen that the malloc() function is defined by the -// weak symbol, so it is probably possible to override malloc() and do -// the same job. -// -static void *my_malloc_hook(size_t size, const void *caller) -{ - void *result; - - if (hook_status != FAIL_NONE && hook_status != FAIL_NEXT_DYN){ - if (hook_status == FAIL_NEXT) - hook_status = FAIL_NONE; - return (NULL); - } - if (hook_status == FAIL_NEXT_DYN){ - hook_dyn_fail -= 1; - if (hook_dyn_fail <= 0){ - hook_status = FAIL_NONE; - return (NULL); - } - } - __malloc_hook = old_malloc_hook; - result = malloc(size); - (void)caller; - //printf("caller: %p - area: %p\n", caller, result); - old_malloc_hook = __malloc_hook; - __malloc_hook = my_malloc_hook; - return (result); -} - -// -// malloc_hook_udpate() -// This function is the only way to interact with the hook; it will -// define the behavior of malloc: -// * FAIL_NEXT : force the next call of malloc to return NULL. -// * FAIL_NEXT_DYN : force X-nth call of malloc to return NULL. -// * FAIL_ALWAYS : force all malloc return NULL. -// * FAIL_NONE : force malloc to work normally. -// -void malloc_hook_update(status_t status, ...) -{ - va_list ap; - - hook_dyn_fail = 0; - if (status == FAIL_NEXT_DYN){ - va_start(ap, status); - hook_dyn_fail = va_arg(ap, int); - va_end(ap); - } - hook_status = status; -} diff --git a/tests/strtab_test.c b/tests/strtab_test.c deleted file mode 100644 index 9372bdf..0000000 --- a/tests/strtab_test.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include "tests/internal.h" -#include - -// Internal prototypes. -extern int strtotab(int *argc, char ***argv, char const *str); -extern void strtotab_quit(int *argc, char ***argv); - -Test(strtotab, quote) -{ - char **argv; - int argc; - int ret; - - ret = strtotab(&argc, &argv, "hey? \"What's \nup?\" yo!\"\n"); - cr_expect_eq(ret, 0); - cr_expect_eq(argc, 3); - cr_assert_str_eq(argv[0], "hey?"); - cr_assert_str_eq(argv[1], "What's \nup?"); - cr_assert_str_eq(argv[2], "yo!\""); -} - -Test(strtotab, noword) -{ - char **argv; - int argc; - int ret; - - ret = strtotab(&argc, &argv, ""); - cr_expect_eq(ret, EINVAL); - cr_expect_eq(argc, 0); - cr_assert_null(argv); -} - -Test(strtotab, entry_error) -{ - char **argv; - int argc; - int ret; - - ret = strtotab(NULL, &argv, "aaaaaaaaa aa"); - cr_expect_eq(ret, EFAULT); - ret = strtotab(&argc, NULL, "aaaaaaaaa aa"); - cr_expect_eq(ret, EFAULT); - ret = strtotab(&argc, &argv, NULL); - cr_expect_eq(ret, EFAULT); -} - -Test(strtotab, spaces_tabs) -{ - char **argv; - int argc; - int ret; - - ret = strtotab(&argc, &argv, "hey? What's\t\t \t up?"); - cr_expect_eq(ret, 0); - cr_expect_eq(argc, 3); - cr_assert_str_eq(argv[0], "hey?"); - cr_assert_str_eq(argv[1], "What's"); - cr_assert_str_eq(argv[2], "up?"); -} - -Test(strtotab, normal) -{ - char **argv; - int argc; - int ret; - - ret = strtotab(&argc, &argv, "hey? What's up?\n"); - cr_expect_eq(ret, 0); - cr_assert_eq(argc, 3); - cr_assert_str_eq(argv[0], "hey?"); - cr_assert_str_eq(argv[1], "What's"); - cr_assert_str_eq(argv[2], "up?"); -} - -Test(strtotab, alloc_fails) -{ - char **argv; - int argc; - int ret; - - malloc_hook_update(FAIL_NEXT); - ret = strtotab(&argc, &argv, "hey? \"What's up?"); - cr_assert_eq(ret, ENOMEM); - malloc_hook_update(FAIL_NEXT_DYN, 2); - ret = strtotab(&argc, &argv, "hey? \"What's up?"); - cr_assert_eq(ret, ENOMEM); - malloc_hook_update(FAIL_NEXT_DYN, 2); - ret = strtotab(&argc, &argv, "\"What's\" up?"); - cr_assert_eq(ret, ENOMEM); - -} - -Test(strtotab, quit) -{ - char **argv; - int argc; - - strtotab(&argc, &argv, "hey? What's up?"); - strtotab_quit(&argc, &argv); - cr_assert_eq(argc, 0); - cr_assert_null(argv); - strtotab_quit(NULL, &argv); - strtotab_quit(&argc, NULL); - argv = NULL; - strtotab_quit(&argc, &argv); -} diff --git a/vhex.g1a b/vhex.g1a index 8d620d4f2d54f82c8c7d797ff1536f942c14d5d4..fec54dff0ced6e3a0db5c85c98ab59fbc58232af 100644 GIT binary patch literal 10180 zcmeG>YiwKBd4~^)q^!uiq#mS1@hQoAP<;9wKcrZ4<}S8FO0+$s50NxwXHad4ay$nM z7Nxa13tE%N$yzkn0J`;$)XSW%>kqHl;0+T7tq=wsRm*}bXf27hi$G8Wq$|2KtM+~0 zIlLlWdDsRF9Z=K0_nz~e?{&V{`R>(?xBlksSFgPB)ynmc;NK^|Twj0h@h`J~t6i7B zuI`?mBgdHf3xxvoKNMmt5(@7Lgd?FyAiOiWolx{_nCUft1egBs>ss%dKhi}+m^(w~n4yO5ZH(VjOSjnY|dNlZ7THxZ@%%z8uZksM%3w|Yd@3{BHPtSck zAL5~m@3fVNy091MF=CZNdBBv$M;Wrg;;NlRBG=*VCFEXx%hwNLpZQqcN=|mq(^!t^w;G=+7@7 zZ#nm~vp-`%3;!6~enk)Wknw8}Vn!Bn4#9jo%*Pljdzyv37p@rAVBN4!!oLGgJqziY zt{6T-x)Xxl@E(l+nuY4uSV%t;yodHdsmgJlPAaKJse$h$JO9GCC8;Zd)bnS?t4kma z{KR-|3BQ1(J2xOBZjXm|jkq`T8F3HzUQ+nuBkp3I z2x{Rw09vFMLBZDmEz*sk)x4t^22!?-*KNop8NLVfw{YjUy#&X~>mS%rHLn?OD8Z@W z$^(0><(1=&B{+55SiEbHZeu3&{5kUabt7Zff19yVAElPF)A3-+lj;QgTK)wwANQnm z1gYcCNQhTLZ2W|T_$0*6;}X&&A@%&IgfvS?13w}mEfV73Jrc4_LK=COgtSVClkby| zHiUqEcguOZ#IW$~64D_d)jTL6ehI1N9TL(hAvWG3Apr@g=Uxd3N{E9u3P{#1t>fhO z0z}w{;;LGOk%eRoRjE+2l8hFU3MESsw6?@Y;2-pp>ZAO?p_g2cL-}zR`g*E1VxH74 zYIBuP0XCqO1l8p<%(SQ%*)Dv(b)BsPub)y*&dxU|L7nEmsICUF4mJVpHY(tCrm1G3@*%ix1@E2vm^Umjh_3o22D(_djh@xKmY%h| znw~app=Uie)6>DL=;`E@BW|Lvz$bAq$Wb*flOynR!9L7{J_Zv(E!Jq$*7-6|M|TzT z_5==9$@&a6+RWG*)oQHQ@b9px>=2t!y zFskoNqn$H&wg6v}GN&IfcuZm@_yK<=M&b@W`WmmA-+E7fpZ&ye_iyiXc?P^s!!_&~ zTQ)!2<9+pzdGZ%s=2t#`PV+2O6gW$yX5#rhVD~-E22VUK!LpTL88@#$yNoH^xCE7V z%)-l;D&T45W$2$pHeeOrL0#co39!&s@C(r^M8Ea2lGG&~BbxcgE@MXd!@kL~d^xW` zdW=bKC}5-mf-Y3m^)ZxFhrtVv(k5%z~2XROFUP$kWS z*39VXD7O$5-Emdc3Jv9oitDjW{)5=H;IMJF<33r)G%W0AhBMtX%|ezrjBjCKVGF1S zKc{*yqZ|VsGchOd#BKym3!LM=@Cou~;=wG)#}Pu}ftV}oPnrRLl_;^ZFczY^i0^S+ zRX#6ppx42S6mrZUCnV%-@W)k}1wa~BrkR)vrA%xUbTlU2pkkQ|Fv#?OE#QJ>NkY<` z_C;;U=mUDmxJ!Ik5mq1H;iMF>=e~V^~M@`V~(_&BkkstA;6qdb(~Xme4KQgE7EZe zF;yLDR-)q^XfdbiD6oSui1P{Dp-L@vepiJR>kRTiXLFIKAFA^bgRFo^Qu!3DSE5LQ)}(&I%s zga7CH_N$)XOmm=;+}>9u1Y;lpXYtOkUq%3E`hYbH@rijeOL;S^d=bxhpcGLRj5QLU z*?2(OPQ+ekc3qs%vBqv?;y%(-zptLf*h?JuPF*-?qbOTYo&uZ&<(aEPkrf)@`Mwax z^Rsf$_x04SmBgjOo6Xc`!z&nRQ>VgsA}_@KN+7q3w5pss7GA;q%9>Y&TnMKlTds8A z?CSo=N<5(Wb52RILr|p6h=&-1(L_hTgV$o+Q|bL#z2aAA9ZJWPJ-l+Y4tN!6QRS3b zaH2|diJ8*xx`+?KYBEyf_1` zpc4jrV)er{W#Yr)-VBa5Je&4`JuNTJku}$p!+^V{B$CSm=`pB5m#sV5-n=CwxlB)tu2+2t=D3;plvO##OV&vy4H6vvXAz%20L4ew`2=6 zOliqMeG}M=FGT7lX^dE}Jr!@sM0d2N`UL-24e)g$Ch=&_N_p{`q;J{Yy+7Q#Y=FBz zjrCXH1VAe0+Zt4Y=3JGOQ?s}iu>z>L+XJH^OcgZOLD z{UI}HKVf5X-j+*IL=mSrWLN}y#I=}RJe5|O+3p)W&tJWqY?I z*ni*Ud49efWHs{EGnT>Si^So?V9dS~I1Hq_;Qe%vYy=#JfWr&k$2}Nz!e(u7?zO2L z+n_pICtp@q1KAgaMac)9kRN0jnzaLEyGq#}Ylv7UG;jYd^hEG30MQ$Qyr>l?4I9J$ zz;Oy=cnsP!*$b7^Hv{U!iaQ<=>+o)Wr|4Wi20G19h0j11ouVv)a~*peT)~sE+Zcg& zc6xt+IqY;_$_rmHj&6oKq9N?V1#Fy4{O(QhwS>P{#fQ1X-?1saj_?C2KFkF^Y717w z{zfml9njU&?NR%PhLMBdgRkZSuurGttyT+OUx1LtSl7M0MunkP0%lfWD4Adnm%Mlo zGGqpPrgl_nz42~zY@l^D@(^0bF{)<_53x&?KIQ@*cS#;{gSt4fuq4-rs~@-?5?uSR zX25y%FM-p(O!P_Mc}8d0rKuNH@(fmjg#ymI&4_ata0YedfD^GTnj*E(BW$C0Ru+B% z-U31??CnTT=$jl69|5t?BK@uXjjI0pQG(D4&I+MFRnXdgKc?uxV8#F_g zj&&~|x8XhQ8`UVg3EvJ@&!4gWp2qq-cGK5x3M#BFxGuZ4JXkd!Z-q!{&A}TqadIVn zm`!1Lx58C|wPK$I?{QH&1M=B9!G)*`Jzo(fXcmNQt0<)h=pKM#XH|*|yO_j|As@pp zKzYiCJxk3LCq)`wdy3AbQra}oV&9*S)d8Iz=`FjcE&#V88;GdO$DmWlY7igS`gX%< z+Ir2s3ExrRyYpB0qUIJ0c5`{mDthyR5ytz}A0tPUKWI(t?{DKzV!cRXwuwEofvh&7 z+(d`mk2cZaH0VIyD%qRR0W&e*=P20ne#MDkCfaZ3^gaB)E%jTQNWBD7x09a578O#l zI^_GX@{kwqo2Asp{zrQ~%S`ZbJXHG>3sv7L@QPE6L5%o7KE8o~uizU3NQ$>oAB=i+ zKSVF=`%0rHB%-GzqAm$ooUrek?-?^bu$be&)Lo05H)2J8pDUFmBQ<8DH)+kypv+J^ zRw>yjG;MUy*e6ue_ZR${FTSC1L(n2e9@|i)7j)O)Q{dv>CEtjXV0H=dnztulY8Cp zYxZ5L$XpuET)eQC#-qb&6+Swe-584@;y_Z@&E2vCmvzt%5&zmi#mp_Uapo4`A^6 z#q6Oy)!}$Qd*Witj$MhwNw0f&=qsy3)7L+|@z(T>>(?*0EGBA<{Sy<3Q*%cW3$I@J z#^3$LH(u-b?i=5Bf6IRL+k0NqjWKpIGn796#f2ImY+C=|ua~luGA1q1UBR0PbywxoUD2JoEBG5S O^i{1a)bNu+4f{_~_we}u literal 29660 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 diff --git a/vhex.ld b/vhex.ld new file mode 100644 index 0000000..b419ecd --- /dev/null +++ b/vhex.ld @@ -0,0 +1,93 @@ +OUTPUT_ARCH(sh3) +OUTPUT_FORMAT(elf32-sh) +ENTRY(_start) + +MEMORY +{ + /* + ** bootram is the RAM physical location for global variable + ** during the bootloader step. + ** This location is realy important because no Casio's OS data + ** should be overwrite (specially TLB information stored by Casio). + */ + bootram (rwx) : o = 0x88040000, l = 252k + osram (rwx) : o = 0x8807f000, l = 4k + rom (rx) : o = 0x00300200, l = 512k +} + +SECTIONS +{ + /* + ** ROM sections + */ + . = ORIGIN(rom); + .text : { + *(.pretext) + *(.text) + + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + } > rom + + + /* + ** RAM sctions + */ + . = ORIGIN(bootram); + + /* BootStrap Stack: should be wiped later ! */ + /* (we force the section to be non loadable when the program is run) */ + .bss (NOLOAD) : { + _bbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4); + } > bootram :NONE + _sbss = SIZEOF(.bss); + + /* Read-write data going to RAM */ + .data : ALIGN(4) { + _bdata_rom = LOADADDR(.data) ; + _bdata_ram = . ; + *(.data) + + /* Video RAM space */ + _VRAM = ALIGN(4); + . = (. + 1024); + } > bootram AT> rom + _sdata = SIZEOF(.data); + + + /* + ** VBR space ! + */ + /* Interrupt / exception handlers */ + .vhex : SUBALIGN(4) { + _bvhex_rom = LOADADDR(.vhex) ; + _bvhex_ram = . ; + _vhex_vbr = . - 0x100; + *(.vhex.exception) ; + . = _vhex_vbr + 0x400 ; + *(.vhex.tlb) ; + . = _vhex_vbr + 0x600 ; + *(.vhex.interrupt) ; + . = ALIGN(4); + } > osram AT> rom + _svhex = SIZEOF(.vhex); + + /* unwanted section */ + /DISCARD/ : { + *(.debug_info) + *(.debug_abbrev) + *(.debug_loc) + *(.debug_aranges) + *(.debug_ranges) + *(.debug_line) + *(.debug_str) + *(.jcr) + *(.eh_frame_hdr) + *(.eh_frame) + *(.comment) + } +}