diff --git a/.gitignore b/.gitignore index cd531cf..357250f 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ Module.symvers Mkfile.old dkms.conf +# Other +*.txt +build/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dbec214 --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ +#!/usr/bin/make -f +# --- +# Project: FIXME WRITE DOC !! +# Author: yann.magnin@epitech.eu +# --- +include global.mk + +NAME := dump +EXEC := $(NAME).g1a +HEADER := -Iinclude +DEBUG := link_map.txt +LDFLAG := -T bootstrap.ld +ICON := icon.bmp +BUILD := build/ + + +SRC := +DIRECTORY := src/ $(sort $(dir $(wildcard src/*/*/))) +$(foreach path,$(DIRECTORY),$(eval \ + SRC += $(wildcard $(path)*.c) \ + $(wildcard $(path)*.s) \ + $(wildcard $(path)*.S)) \ +) +OBJ := $(patsubst src_%,$(BUILD)%.o,$(subst /,_,$(basename $(SRC)))) + +#all: ;@echo $(SRC) $(OBJ) +all: | $(BUILD) $(EXEC) + +install: $(EXEC) + sudo p7 send $< + +$(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) + +$(BUILD): + @ printf "Create $(blue)$@$(nocolor) directory\n" + @ mkdir -p $@ + + +# +# 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 + + + +define rule-src +$(patsubst src_%,$(BUILD)%.o,$(subst /,_,$(basename $1))): $1 + @ printf "compiling $(white)$$<$(nocolor)..." + @ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc + @ printf "$(green)[ok]$(nocolor)\n" +endef + +$(foreach source,$(SRC),$(eval \ + $(call rule-src,$(source))) \ +) + + +#--- +# Clean rules +#--- +clean: + @ printf "$(red)Delete objects files$(nocolor)\n" + rm -rf $(BUILD) + rm -f *.gc* + rm -f $(DEBUG) + +fclean: clean + @ printf "$(red)Delete binary files$(nocolor)\n" + rm -f $(EXEC) + rm -f $(NAME).bin + rm -f $(NAME).elf + +re: fclean all install + + + + +.PHONY: clean re fclean install tests diff --git a/bootstrap.ld b/bootstrap.ld new file mode 100644 index 0000000..630930a --- /dev/null +++ b/bootstrap.ld @@ -0,0 +1,48 @@ +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) + } > 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 new file mode 100644 index 0000000..2ecdb21 --- /dev/null +++ b/global.mk @@ -0,0 +1,27 @@ +# 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 + +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/icon.bmp b/icon.bmp new file mode 100644 index 0000000..30cbde6 Binary files /dev/null and b/icon.bmp differ diff --git a/include/commands.h b/include/commands.h new file mode 100644 index 0000000..a556d27 --- /dev/null +++ b/include/commands.h @@ -0,0 +1,35 @@ +#ifndef __COMMANDS_H__ +# define __COMMANDS_H__ + +#include +#include +#include + +//FIXME: MOVE ME ! +struct cmd_info +{ + char *name; + struct { + ptrdiff_t anchor; + size_t size; + } update; + void (*init)(int argc, char **argv, struct session_s *session, char *info); +}; + +#define CMDBLOCK(bname,cmd,ptr,sizez,callback) \ + static const struct cmd_info bname = { \ + .name = cmd, \ + .update = { \ + .anchor = (ptrdiff_t)(ptr), \ + .size = sizez, \ + }, \ + .init = callback \ + } + +//TODO: write doc. +void command_entry(struct session_s *session, struct dump_s *dump); +void address_jump(int argc, char **argv, struct session_s *session, char *info); +void syscall_jump(int argc, char **argv, struct session_s *session, char *info); +void ram_jump(int argc, char **argv, struct session_s *session, char *info); +void vbr_jump(int arc, char **argv, struct session_s *session, char *info); +#endif /*__COMMANDS_H__*/ diff --git a/include/errno.h b/include/errno.h new file mode 100644 index 0000000..946131c --- /dev/null +++ b/include/errno.h @@ -0,0 +1,156 @@ +#ifndef __KERNEL_ERRNO_H__ +# define __KERNEL_ERRNO_H__ 1 + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ + +/* + * This error code is special: arch syscall entry code will return + * -ENOSYS if users try to call a syscall that doesn't exist. To keep + * failures of syscalls that really do exist distinguishable from + * failures due to attempts to use a nonexistent syscall, syscall + * implementations should refrain from returning -ENOSYS. + */ +#define ENOSYS 38 /* Invalid system call number */ + +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define ENOTSUP EOPNOTSUPP /* Not supported (may be the same value as [EOPNOTSUPP]) */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#define ERFKILL 132 /* Operation not possible due to RF-kill */ + +#define EHWPOISON 133 /* Memory page has hardware error */ + +#endif /* __KERNEL_ERRNO_H__ */ diff --git a/include/history.h b/include/history.h new file mode 100644 index 0000000..e28913e --- /dev/null +++ b/include/history.h @@ -0,0 +1,21 @@ +#ifndef __HISTORY_H__ +# define __HISTORY_H__ + +#include + +struct node +{ + const char data[32]; + struct node *next; +}; + +struct history_s { + struct node *list; + off_t offset; + size_t deep; +}; + +int history_update(struct node **list, const char *data); +const void *history_get(struct node *list, off_t offset); +void history_quit(struct node **list); +#endif /*__HISTORY_H__*/ diff --git a/include/opcode.h b/include/opcode.h new file mode 100644 index 0000000..6d1591f --- /dev/null +++ b/include/opcode.h @@ -0,0 +1,2290 @@ +#ifndef __OPCODE_H__ +# define __OPCODE_H__ + +#include +#include +#include + +struct opcode +{ + const char *name; + uint16_t mask; + uint16_t code; + uint16_t arg_mask[ARGUMENTS_MAX]; +}; + + +static const struct opcode opcode[] = { + { + .name = "add #h'%x,r%d", + .mask = 0b1111000000000000, + .code = 0b0111000000000000, + .arg_mask = { + 0b0000000011111111, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "add r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001100, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "addc r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001110, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "addv r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001111, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "and #h'%x,r0", + .mask = 0b1111111100000000, + .code = 0b1100100100000000, + .arg_mask = { + 0b000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "and r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001001, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "and.b #h'%x,@(r0,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100110100000000, + .arg_mask = { + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bf #h'%x", + .mask = 0b1111111100000000, + .code = 0b1000101100000000, + .arg_mask = { + 0b000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bs/s #h'%x", + .mask = 0b1111111100000000, + .code = 0b1000111100000000, + .arg_mask = { + 0b000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bra #h'%x", + .mask = 0b1111000000000000, + .code = 0b1010000000000000, + .arg_mask = { + 0b0000111111111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "braf r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000100011, + .arg_mask = { + 0b000011110000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bsr #h'%x", + .mask = 0b1111000000000000, + .code = 0b1011000000000000, + .arg_mask = { + 0b0000111111111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bsrf r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000000011, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bt #h'%x", + .mask = 0b1111111100000000, + .code = 0b1000100100000000, + .arg_mask = { + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "bt/s #h'%x", + .mask = 0b1111111100000000, + .code = 0b1000110100000000, + .arg_mask = { + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "clrmac", + .mask = 0b1111111111111111, + .code = 0b0000000000101000, + .arg_mask = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "clrs", + .mask = 0b1111111111111111, + .code = 0b0000000001001000, + .arg_mask = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "clrt", + .mask = 0b1111111111111111, + .code = 0b0000000000001000, + .arg_mask = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/eq #h'%x,r0", + .mask = 0b1111111100000000, + .code = 0b1000100000000000, + .arg_mask = { + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/eq r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000000, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/ge r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000011, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/gt r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000111, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/hi r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000110, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/hs r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000010, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/pl r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000010101, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/pz r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000010001, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "cmp/str r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001100, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "div0s r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000000111, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "div0u", + .mask = 0b1111111111111111, + .code = 0b0000000000011001, + .arg_mask = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "div1 r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000100, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "dmuls.l r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001101, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "dmulu.l r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000000101, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "dt r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000010000, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "exts.b r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001110, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "exts.w r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001111, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "extu.b r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001100, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "extu.w r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001101, + .arg_mask = { + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + //TODO + //TODO ADD FPU INSTRUCTIONS + //TODO + { + .name = "jmp @r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000101011, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "jsr @r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000001011, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,GBR", + .mask = 0b1111000011111111, + .code = 0b0100000000011110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,SR", + .mask = 0b1111000011111111, + .code = 0b0100000000001110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,VBR", + .mask = 0b1111000011111111, + .code = 0b0100000000101110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,SSR", + .mask = 0b1111000011111111, + .code = 0b0100000000111110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,SPC", + .mask = 0b1111000011111111, + .code = 0b0100000001001110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,MOD", + .mask = 0b1111000011111111, + .code = 0b0100000001011110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + //FIXME: find difference between "ldc rm,RE" and "ldc rm,RS" + { + .name = "ldc r%d,RE/RS", + .mask = 0b1111000011111111, + .code = 0b0100000001101110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R0_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010001110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R1_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010011110, + .arg_mask = { + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R2_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010101110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R3_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010111110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R4_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011001110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R5_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011011110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R6_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011101110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc r%d,R7_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011111110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,GBR", + .mask = 0b1111000011111111, + .code = 0b0100000000010111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,SR", + .mask = 0b1111000011111111, + .code = 0b0100000000000111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,VBR", + .mask = 0b1111000011111111, + .code = 0b0100000000100111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,SSR", + .mask = 0b1111000011111111, + .code = 0b0100000000110111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,SPC", + .mask = 0b1111000011111111, + .code = 0b0100000001000111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,MOD", + .mask = 0b1111000011111111, + .code = 0b0100000001010111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,RE", + .mask = 0b1111000011111111, + .code = 0b0100000001110111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,RS", + .mask = 0b1111000011111111, + .code = 0b0100000001100111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R0_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010000111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R1_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010010111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R2_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010100111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @%d+,R3_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000010110111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R4_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011000111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R5_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011010111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R7_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011100111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldc.l @r%d+,R7_BANK", + .mask = 0b1111000011111111, + .code = 0b0100000011110111, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldre @(#h'%x,PC)", + .mask = 0b1111111100000000, + .code = 0b1000111000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldrs @(#h'%x,PC)", + .mask = 0b1111111100000000, + .code = 0b1000110000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + //TODO + //TODO ADD "LDS rm,FPSCR" AND "LDS rm,FPUL" + //TODO + { + .name = "lds r%d,MACH", + .mask = 0b1111000011111111, + .code = 0b0100000000001010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,MACL", + .mask = 0b1111000011111111, + .code = 0b0100000000011010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,PR", + .mask = 0b1111000011111111, + .code = 0b0100000000101010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,A0", + .mask = 0b1111000011111111, + .code = 0b0100000001101010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,DSR", + .mask = 0b1111000011111111, + .code = 0b0100000001111010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,X0", + .mask = 0b1111000011111111, + .code = 0b01000000010001010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,X1", + .mask = 0b1111000011111111, + .code = 0b0100000010011010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,Y0", + .mask = 0b1111000011111111, + .code = 0b0100000010101010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds r%d,Y1", + .mask = 0b1111000011111111, + .code = 0b0100000010111010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + //TODO + //TODO ADD "lds.l @rm+,FPSCR" and "lds.l @rm+,FPUL" + //TODO + { + .name = "lds.l @r%d+,MACH", + .mask = 0b1111000011111111, + .code = 0b0100000000000110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,MACL", + .mask = 0b1111000011111111, + .code = 0b0100000000010110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,PR", + .mask = 0b1111000011111111, + .code = 0b0100000000100110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,DSR", + .mask = 0b1111000011111111, + .code = 0b0100000001100110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,A0", + .mask = 0b1111000011111111, + .code = 0b0100000001110110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,X0", + .mask = 0b1111000011111111, + .code = 0b0100000001000110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,X1", + .mask = 0b1111000011111111, + .code = 0b0100000010010110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,Y0", + .mask = 0b1111000011111111, + .code = 0b0100000010100110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "lds.l @r%d+,Y1", + .mask = 0b1111000011111111, + .code = 0b0100000010110110, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "ldtlb", + .mask = 0b1111111111111111, + .code = 0b0000000000111000, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mac.l @r%d+,@r%d+", + .mask = 0b1111000000001111, + .code = 0b0000000000001111, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mac.w @r%d+,@r%d+", + .mask = 0b1111000000001111, + .code = 0b0100000000001111, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov #h'%x,r%d", + .mask = 0b1111000000000000, + .code = 0b1110000000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000011, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b @(#h'%x,GBR),r0", + .mask = 0b1111111100000000, + .code = 0b1100010000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b @(#h'%x,r%d),r0", + .mask = 0b1111111100000000, + .code = 0b1000010000000000, + .arg_mask ={ + 0b0000000000001111, + 0b0000000011110000, + 0b0000000000000000 + } + }, + { + .name = "mov.b @(r0,r%d),r%d", + .mask = 0b1111000000001111, + .code = 0b0000000000001100, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b @r%d+,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000100, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b @r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000000, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b r0,@(#h'%x,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100000000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b r0,@(#h'%x,r%d)", + .mask = 0b1111111100000000, + .code = 0b1000000000000000, + .arg_mask ={ + 0b0000000000001111, + 0b0000000011110000, + 0b0000000000000000 + } + }, + { + .name = "mov.b r%d,@(r0,r%d)", + .mask = 0b1111000000000000, + .code = 0b0000000000000100, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b r%d,@-r%d", + .mask = 0b1111000000000000, + .code = 0b0010000000000100, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.b r%d,@r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000000000, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l @(#h'%x,GBR),r0", + .mask = 0b1111111100000000, + .code = 0b1100011000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l @(#h'%x,PC),r%d", + .mask = 0b1111000000000000, + .code = 0b1101000000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l @(#h'%x,r%d),r%d", + .mask = 0b1111000000000000, + .code = 0b0101000000000000, + .arg_mask ={ + 0b0000000000001111, + 0b0000000011110000, + 0b0000111100000000 + } + }, + { + .name = "mov.l @(r0,r%d),r%d", + .mask = 0b1111000000001111, + .code = 0b0000000000001110, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l @r%d+,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000110, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l @r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000010, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l r0,@(#h'%x,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100001000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l r%d,@(#h'%x,r%d)", + .mask = 0b1111000000000000, + .code = 0b0001000000000000, + .arg_mask ={ + 0b0000000000001111, + 0b0000000011110000, + 0b0000111100000000 + } + }, + { + .name = "mov.l r%d,@(r0,r%d)", + .mask = 0b1111000000001111, + .code = 0b0000000000000110, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l r%d,@-r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000000110, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.l r%d,@r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000000010, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w @(#h'%x,GBR),r0", + .mask = 0b1111111100000000, + .code = 0b1100010100000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w @(#h'%x,PC),r%d", + .mask = 0b1111000000000000, + .code = 0b1001000000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w @(r0,r%d),r%d", + .mask = 0b1111000000001111, + .code = 0b0000000000001101, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w @r%d+,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000101, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w @r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000001, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w r0,@(#h'%x,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100000100000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w r0,@(#h'%x,,r%d)", + .mask = 0b1111111100000000, + .code = 0b1000000100000000, + .arg_mask ={ + 0b0000000000001111, + 0b0000000011110000, + 0b0000000000000000 + } + }, + { + .name = "mov.w r%d,@(r0,r%d)", + .mask = 0b1111000000001111, + .code = 0b0000000000000101, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w r%d,@-r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000000101, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mov.w r%d,@r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000000001, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mova @(#h'%x,PC),r0", + .mask = 0b1111111100000000, + .code = 0b1100011100000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "movt r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000101001, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "mul.l r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0000000000000111, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "muls.w r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001111, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "mulu.w r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001110, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "neg r%d,@-r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001011, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "negc r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001010, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "nop", + .mask = 0b1111111111111111, + .code = 0b0000000000001001, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "not r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000000111, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "or #h'%x,r0", + .mask = 0b1111111100000000, + .code = 0b1100101100000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "or r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001011, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "or.b #h'%x,@(r0,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100111100000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "pref @r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010000011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "rotcl r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000100100, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "rotcr r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000100101, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "rotl r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000000100, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "rotr r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000000101, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "rte", + .mask = 0b1111111111111111, + .code = 0b0000000000101011, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "rts", + .mask = 0b1111111111111111, + .code = 0b0000000000001011, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + //TODO + //TODO ADD "setrc rm" and "setrc #imm" + //TODO + { + .name = "sets", + .mask = 0b1111111111111111, + .code = 0b0000000001011000, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sett", + .mask = 0b1111111111111111, + .code = 0b0000000000011000, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shad r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0100000000001100, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "shal r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000100000, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shar r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000100001, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shld r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0100000000001101, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "shll r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000000000, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shll2 r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000001000, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shll8 r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000011000, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shll16 r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000101000, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shlr r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000000001, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shlr2 r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000001001, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shlr8 r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000011001, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "shlr16 r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000101001, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sleep", + .mask = 0b1111111111111111, + .code = 0b0000000000011011, + .arg_mask ={ + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc GBR,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000010010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc SR,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000000010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc VBR,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc SSR,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000110010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc SPC,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000001000010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc MOD,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000001010010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc RE,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000001110010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc RS,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000001100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R0_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010000010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R1_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010010010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R2_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R3_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010110010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R4_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000011000010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R5_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000011010010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R6_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000011100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc R7_BANK,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000011110010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l GBR,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000000010011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l SR,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000000000011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l VBR,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000000100011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l SSR,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000000110011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l SPC,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000001000011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l MOD,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000001010011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l RE,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000001110011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l RS,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000001100011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R0_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000010000011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R1_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000010010011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R2_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000010100011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R3_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000010110011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R4_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000011000011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R5_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000011010011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R6_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000011100011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "stc.l R7_BANK,@r-%d", + .mask = 0b1111000011111111, + .code = 0b0100000011110011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + //TODO + //TODO add "sts fpscr,rn" and "sts fpul,rn" + //TODO + { + .name = "sts MACH,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000001010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts MACL,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000011010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts PR,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000000101010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts DSR,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000001101010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts A0,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000001111010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts X0,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010001010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts X1,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010011010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts Y0,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010101010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts Y1,r%d", + .mask = 0b1111000011111111, + .code = 0b0000000010111010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + //TODO + //TODO add "sts.l fpscr,@-rn" and "sts.l fpul,@-rn" + //TODO + { + .name = "sts.l MACH,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000000010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l MACL,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000010010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l PR,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l DSR,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000001100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l A0,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000001110010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l X0,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000010000010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l X1,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000010010010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l Y0,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000010100010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sts.l Y1,@-r%d", + .mask = 0b1111000011111111, + .code = 0b0100000010110010, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "sub r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001000, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "subc r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001010, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "subv r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0011000000001011, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "swap.b r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001000, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "swap.w r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0110000000001001, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "tas.b @r%d", + .mask = 0b1111000011111111, + .code = 0b0100000000011011, + .arg_mask ={ + 0b0000111100000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "trapa #h'%x", + .mask = 0b1111111100000000, + .code = 0b1100001100000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "tst #h'%x,r0", + .mask = 0b1111111100000000, + .code = 0b1100100000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "tst r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001000, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "tst.b #h'%x,@(r0,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100110000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "xor #h'%x,r0", + .mask = 0b1111111100000000, + .code = 0b1100101000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "xor r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001010, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = "wor.b #h'%x,@(r0,GBR)", + .mask = 0b1111111100000000, + .code = 0b1100111000000000, + .arg_mask ={ + 0b0000000011111111, + 0b0000000000000000, + 0b0000000000000000 + } + }, + { + .name = "xtrct r%d,r%d", + .mask = 0b1111000000001111, + .code = 0b0010000000001101, + .arg_mask ={ + 0b0000000011110000, + 0b0000111100000000, + 0b0000000000000000 + } + }, + { + .name = NULL, + .mask = 0b0000000000000000, + .code = 0b0000000000000000, + .arg_mask = { + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000 + } + }, + +}; + +#endif /*__OPCODE_H__*/ diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..076116a --- /dev/null +++ b/include/string.h @@ -0,0 +1,28 @@ +#ifndef __STRING_H__ +# define __STRING_H__ + +#include +#include + +#define WEAK __attribute__((weak)) + +//#ifndef DEBUG +WEAK void *memset(void *s, int c, size_t n); +#ifndef DEBUG +WEAK void vsprintf(char *str, char const *format, va_list ap); +WEAK void sprintf(char *str, char const *format, ...); +#endif /* DEBUG */ +WEAK char *strcat(char *dest, char const *src); +WEAK int strcmp(const char *s1, const char *s2); +WEAK char *strncpy(char *dest, char const *str, size_t size); +WEAK char *strcpy(char *dest, char const *src); +WEAK size_t strlen(char const *str); + +// Custom functions +int strtotab(int *argc, char ***argv, char const *str); +void strtotab_quit(int *argc, char ***argv); + +uint32_t atoi_base(char const *str, int base); +//#endif /* DEBUG */ + +#endif /*__STRING_H__*/ diff --git a/include/syscalls.h b/include/syscalls.h new file mode 100644 index 0000000..ecd2b3b --- /dev/null +++ b/include/syscalls.h @@ -0,0 +1,42 @@ +#ifndef __CASIO_H__ +# define __CASIO_H__ + +#include + +struct rect +{ + int left; + int top; + int right; + int bottom; +}; + + +// Casio prototype. +void casio_GetKey(unsigned int *key); +void casio_Bdisp_AllClr_DDVRAM(void); +void casio_Bdisp_AreaClr_DDVRAM(const struct rect *buf); +void casio_PrintMini(size_t x, size_t y, char const *str, int mode); +void casio_Bdisp_DrawLine_VRAM(int x1, int y1, int x2, int y2); +void casio_RestoreDisp(unsigned char page); +void casio_SaveDisp(unsigned char page); +void *casio_Malloc(size_t size); +void *casio_Free(void *ptr); + + +// Internal casio abstraction. +static INLINE void dclear_area(int x1, int y1, int x2, int y2) +{ + struct rect area = {.left = x1, .top = y1, .right = x2, .bottom = y2}; + casio_Bdisp_AreaClr_DDVRAM(&area); +} +#define print(x, y, str) casio_PrintMini(x, y, str, 0) +#define getkey casio_GetKey +#define dline_horizontal(y, x1, x2) casio_Bdisp_DrawLine_VRAM(x1, y, x2, y) +#define dclear casio_Bdisp_AllClr_DDVRAM +#define save_window casio_SaveDisp +#define restore_window casio_RestoreDisp +#define malloc casio_Malloc +#define free casio_Free + +#endif /*__CASIO_H__*/ diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..f6fcd40 --- /dev/null +++ b/include/types.h @@ -0,0 +1,21 @@ +#ifndef __TYPES_H__ +# define __TYPES_H__ + +#include +#include + +//TODO: write doc + +# ifndef __off_t_defined +typedef uint32_t off_t; +# define __off_t_defined +# endif + +#ifndef __ssize_t_defined +typedef int32_t ssize_t; +# define __ssize_t_defined +#endif + +#define INLINE __attribute__((always_inline)) inline + +#endif /*__TYPES_H__*/ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..83a18e3 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,124 @@ +#ifndef __UTILS_H__ +# define __UTILS_H__ + +#include +#include + +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 +#define FONT_WIDTH 4 +#define FONT_HEIGHT 6 +#define LINE_OFFSET ((SCREEN_HEIGHT / FONT_HEIGHT) - 1) +#define COLUMN_OFFSET (SCREEN_WIDTH / FONT_WIDTH) + +#define KEY_UP 30018 +#define KEY_DOWN 30023 +#define KEY_LEFT 30020 +#define KEY_RIGHT 30021 +#define KEY_OPTN 30008 + +#define KEY_F1 30009 +#define KEY_F2 30010 +#define KEY_F3 30011 +#define KEY_F4 30012 +#define KEY_F5 30013 +#define KEY_F6 30014 + +#define KEY_SHIFT 30006 +#define KEY_ALPHA 30007 +#define KEY_ENTER 30004 +#define KEY_DEL 30025 +#define KEY_SPACE 0x20 +#define KEY_INS 30033 +#define KEY_PI 0xd0 +#define KEY_QUOTE KEY_PI + +#define KEY_A 0x41 +#define KEY_B 0x42 +#define KEY_C 0x43 +#define KEY_D 0x44 +#define KEY_E 0x45 +#define KEY_F 0x46 +#define KEY_G 0x47 +#define KEY_H 0x48 +#define KEY_I 0x49 +#define KEY_J 0x4a +#define KEY_K 0x4b +#define KEY_L 0x4c +#define KEY_M 0x4d +#define KEY_N 0x4e +#define KEY_O 0x4f +#define KEY_P 0x50 +#define KEY_Q 0x51 +#define KEY_R 0x52 +#define KEY_S 0x53 +#define KEY_T 0x54 +#define KEY_U 0x55 +#define KEY_V 0x56 +#define KEY_W 0x57 +#define KEY_X 0x58 +#define KEY_Y 0x59 +#define KEY_Z 0x5a + +#define KEY_0 0x30 +#define KEY_1 0x31 +#define KEY_2 0x32 +#define KEY_3 0x33 +#define KEY_4 0x34 +#define KEY_5 0x35 +#define KEY_6 0x36 +#define KEY_7 0x37 +#define KEY_8 0x38 +#define KEY_9 0x39 + +#define ARGUMENTS_MAX 3 +#define INSTRUCTION_SIZE 2 +#define SESSIONS_SLOT 6 +#define CMD_LENGHT_MAX 15 + +enum mode_e +{ + UNUSED, + COMMAND, + NORMAL, + FREE +}; + +struct session_s +{ + enum mode_e mode; + ptrdiff_t anchor; + off_t cursor; + size_t size; +}; + +enum insert_mode +{ + LETTER, + CAPS_LOCK, + NUMBER, + SHIFT +}; + + +struct dump_s +{ + int current_session; + struct session_s session[SESSIONS_SLOT]; + struct { + char backup[CMD_LENGHT_MAX]; + char cmd[CMD_LENGHT_MAX]; + enum insert_mode mode; + } insert; + char info[CMD_LENGHT_MAX]; + struct history_s history; +}; + +// screen part. +void dclear(void); +void dupdate(void); + +void display_instructions(const struct session_s *session); +void display_metainfos(const struct dump_s *dump, const struct session_s *session); +void key_handling(struct dump_s *dump, struct session_s *session, unsigned int key); +#endif /*__UTILS_H__*/ diff --git a/src/boot/crt0.c b/src/boot/crt0.c new file mode 100644 index 0000000..e0e1d42 --- /dev/null +++ b/src/boot/crt0.c @@ -0,0 +1,56 @@ +#include +#include +extern int main(void); + +//define 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() +// 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/address_jump.c b/src/commands/address_jump.c new file mode 100644 index 0000000..d615bb9 --- /dev/null +++ b/src/commands/address_jump.c @@ -0,0 +1,19 @@ +#include +#include + +static INLINE int check_address(char *str) +{ + --str; + while ((*(++str) >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f')); + return ((*str != '\0') ? 1 : 0); +} + +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; + } + session->anchor = atoi_base(argv[1], 16) >> 1 << 1; + session->size = 0xffffffff; +} diff --git a/src/commands/entry.c b/src/commands/entry.c new file mode 100644 index 0000000..b237270 --- /dev/null +++ b/src/commands/entry.c @@ -0,0 +1,61 @@ +#include +#include +#include + +CMDBLOCK(rom, "rom", 0x00300200, 0xffffffff, NULL); +CMDBLOCK(systab, "systab", 0x80010070, 0xffffffff, NULL); +CMDBLOCK(ram, "ram", NULL, 0xffffffff, &ram_jump); +CMDBLOCK(vbrjmp, "vbrjmp", NULL, 0xffffffff, &vbr_jump); +CMDBLOCK(addr_jump, "jmp", NULL, 0xffffffff, &address_jump); +CMDBLOCK(sysc_jump, "syscall", NULL, 0xffffffff, &syscall_jump); + + +//TODO: +// - dynamique allocation cache. +// - rename function. +static int find_command(int argc, char **argv, struct session_s *session, +struct dump_s *dump) +{ + static const struct cmd_info *cache[] = { + &addr_jump, &vbrjmp, &systab, &sysc_jump, &ram, &rom, NULL + }; + size_t i; + + i = -1; + while (cache[++i] != NULL && strcmp(cache[i]->name, *argv)); + if (cache[i] == NULL) + return (EBADMSG); + if (cache[i]->init == NULL){ + session->cursor = 0; + session->anchor = cache[i]->update.anchor; + session->size = cache[i]->update.size; + sprintf(dump->info, "%#x", session->anchor); + return (0); + } + cache[i]->init(argc, argv, session, dump->info); + sprintf(dump->info, "%#x", session->anchor); + return (0); +} + +void command_entry(struct session_s *session, struct dump_s *dump) +{ + char **argv; + int argc; + int ret; + + if (history_update(&dump->history.list, dump->insert.cmd) == 0){ + dump->history.offset = 0; + dump->history.deep += 1; + } + ret = strtotab(&argc, &argv, dump->insert.cmd); + memset(dump->insert.cmd, '\0', CMD_LENGHT_MAX); + if (ret != 0){ + sprintf(dump->info, "error (%d)", ret); + return; + } + if (find_command(argc, argv, session, dump) != 0) + strcat(dump->info, "command error"); + session->mode = (session->anchor == 0x00000000) ? UNUSED : NORMAL; + session->cursor = 0; + strtotab_quit(&argc, &argv); +} diff --git a/src/commands/ram_jump.c b/src/commands/ram_jump.c new file mode 100644 index 0000000..1f5235a --- /dev/null +++ b/src/commands/ram_jump.c @@ -0,0 +1,20 @@ +#include +#include + +void ram_jump(int argc, char **argv, struct session_s *session, char *info) +{ + if (argc != 2){ + strcpy(info, "arguments error"); + 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], "p2")) + session->anchor = 0xe6000000; + //FIXME: sh3 size is 0x40000; + session->size = 0x80000; +} diff --git a/src/commands/syscall_jump.c b/src/commands/syscall_jump.c new file mode 100644 index 0000000..c3dc152 --- /dev/null +++ b/src/commands/syscall_jump.c @@ -0,0 +1,24 @@ +#include +#include + +static INLINE int check_address(char *str) +{ + --str; + while ((*(++str) >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f')); + return ((*str != '\0') ? 1 : 0); +} + +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]; + session->size = 0xffffffff; +} diff --git a/src/commands/vbr_jump.c b/src/commands/vbr_jump.c new file mode 100644 index 0000000..fc46fec --- /dev/null +++ b/src/commands/vbr_jump.c @@ -0,0 +1,18 @@ +#include +#include + +void vbr_jump(int argc, char **argv, struct session_s *session, char *info) +{ + if (argc != 2){ + strcpy(info, "arguments error"); + return; + } + __asm__ volatile ("stc vbr, %0" : "=r"(session->anchor)); + if (!strcmp(argv[1], "fault")) + session->anchor += 0x100; + if (!strcmp(argv[1], "except")) + session->anchor += 0x400; + if (!strcmp(argv[1], "int")) + session->anchor += 0x600; + session->size = 2048; +} diff --git a/src/display/intructions.c b/src/display/intructions.c new file mode 100644 index 0000000..e7a6f3a --- /dev/null +++ b/src/display/intructions.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +//TODO: +// - move me ! +// - attribute always inline ? +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); +} + +static void get_mnemonic(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]); +} + +//TODO: +// - resize buffer. +// - handle multiple modes. +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); + while (++y < LINE_OFFSET){ + get_mnemonic(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 new file mode 100644 index 0000000..0544680 --- /dev/null +++ b/src/display/metainfos.c @@ -0,0 +1,26 @@ +#include +#include +#include + +void display_metainfos(const struct dump_s *dump, 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], dump->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[dump->insert.mode], dump->insert.cmd); + else { + tmp = (*dump->info == '\0') ? dump->insert.cmd : dump->info; + sprintf(buf, "[%c] %s", insert_name[dump->insert.mode], tmp); + } + print(0, SCREEN_HEIGHT - FONT_HEIGHT, buf); +} diff --git a/src/history.c b/src/history.c new file mode 100644 index 0000000..feb63f5 --- /dev/null +++ b/src/history.c @@ -0,0 +1,48 @@ +#ifndef DEBUG +# include +# include +#else +# include "history.h" +# include +#endif +#include +#include + +// TODO:write docs ! +// *-* +// |A| --> +// *-* +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); +} + +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)); +} + +void history_quit(struct node **list) +{ + if (list == NULL || *list == NULL) + return; + history_quit(&(*list)->next); + free(*list); + *list = NULL; +} diff --git a/src/keys.c b/src/keys.c new file mode 100644 index 0000000..b4dbad2 --- /dev/null +++ b/src/keys.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include + +static int check_session(unsigned int key, struct dump_s *dump) +{ + 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){ + dump->current_session = i; + return (0); + } + return (-1); +} + +static int check_insert(unsigned int key, struct dump_s *dump, struct session_s *session) +{ + if (!(key == KEY_OPTN || key == KEY_SHIFT || key == KEY_ALPHA)) + return (-1); + if (dump->insert.mode == LETTER) + dump->insert.mode = NUMBER; + if (key == KEY_OPTN){ + if (session->mode != COMMAND){ + memset(dump->info, '\0', CMD_LENGHT_MAX); + session->mode = COMMAND; + save_window(1); + } + else + //TODO: restore FREE mode ? + session->mode = (session->anchor == 0x00000000) ? UNUSED : NORMAL; + } + if (key == KEY_SHIFT) + dump->insert.mode = (dump->insert.mode == SHIFT) ? NUMBER : SHIFT; + if (key == KEY_ALPHA){ + if (dump->insert.mode == SHIFT){ + dump->insert.mode = CAPS_LOCK; + return (0); + } + if (dump->insert.mode == CAPS_LOCK){ + dump->insert.mode = NUMBER; + return (0); + } + dump->insert.mode = LETTER; + } + return (0); +} + +//TODO: find better way to do the job (?) +static int check_cmd(unsigned int key, struct dump_s *dump, 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(dump->insert.cmd); + end = (dump->insert.mode == NUMBER) ? 10 : 26; + buf = (dump->insert.mode == NUMBER) ? '0' : 'a'; + cache = (dump->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 += i; + strcat(dump->insert.cmd, &buf); + } + dump->history.offset = 0; + return (0); +} + +static int check_arrow(unsigned int key, struct dump_s *dump, struct session_s *session) +{ + if (key != KEY_UP && key != KEY_DOWN) + return (-1); + if (session->mode == COMMAND + && ((key == KEY_UP && dump->history.offset < dump->history.deep) + || (key == KEY_DOWN && dump->history.offset > 0))){ + if (dump->history.offset == 0) + strcpy(dump->insert.backup, dump->insert.cmd); + dump->history.offset += (key == KEY_UP) ? 1 : -1; + if (dump->history.offset > 0) + strcpy(dump->insert.cmd, + history_get(dump->history.list, dump->history.offset - 1)); + else + strcpy(dump->insert.cmd, dump->insert.backup); + } + if (session->mode != UNUSED && session->mode != COMMAND){ + if (key == KEY_UP && session->cursor > 0) + session->cursor -= INSTRUCTION_SIZE; + if (key == KEY_DOWN && session->cursor < session->size - LINE_OFFSET) + session->cursor += INSTRUCTION_SIZE; + } + return (0); +} + +void key_handling(struct dump_s *dump, struct session_s *session, unsigned int key) +{ + size_t size; + + if (check_session(key, dump) == 0 + || check_insert(key, dump, session) == 0 + || check_arrow(key, dump, session) == 0 + || check_cmd(key, dump, session) == 0 + || session->mode != COMMAND) + return; + if (key == KEY_DEL || key == KEY_INS){ + size = strlen(dump->insert.cmd); + if (size > 0) + strncpy(dump->insert.cmd, dump->insert.cmd, size - 1); + } + if (key == KEY_SPACE) + strcat(dump->insert.cmd, " "); + if (key == KEY_QUOTE) + strcat(dump->insert.cmd, "\""); + if (key == KEY_ENTER){ + dump->insert.mode = NUMBER; + command_entry(session, dump); + } +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b48e784 --- /dev/null +++ b/src/main.c @@ -0,0 +1,49 @@ +#include +#include +#include + +// +// dump_constructor() +// Initialize all information needed by the add-in: session, +// GetKey configuration, ... +// +static void dump_constructor(struct dump_s *dump) +{ + size_t i; + + i = -1; + memset(dump->info, '\0', CMD_LENGHT_MAX); + memset(dump->insert.cmd, '\0', CMD_LENGHT_MAX); + //TODO: Auto detect GetKey configuration !! + dump->insert.mode = NUMBER; + dump->history.list = NULL; + dump->history.offset = 0; + dump->history.deep = 0; + dump->current_session = 0; + while (++i < SESSIONS_SLOT){ + dump->session[i].mode = UNUSED; + dump->session[i].anchor = 0x00000000; + } +} + +// +// main() +// "user" entry, but we need initialize some information before +// starting the "main loop". +// +int main(void) +{ + struct dump_s dump; + unsigned int key; + + key = 0; + dump_constructor(&dump); + while (1){ + dclear(); + display_instructions(&dump.session[dump.current_session]); + display_metainfos(&dump, &dump.session[dump.current_session]); + getkey(&key); + key_handling(&dump, &dump.session[dump.current_session], key); + } + return (0); +} diff --git a/src/string/atoi_base.c b/src/string/atoi_base.c new file mode 100644 index 0000000..59ba1f6 --- /dev/null +++ b/src/string/atoi_base.c @@ -0,0 +1,26 @@ +#include + +static INLINE int check_base(char n, int base) +{ + char max; + + max = (base <= 10) ? '0' + base - 1 : ('a' + base - 11); + return ((max < n)); +} + +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/memset.c b/src/string/memset.c new file mode 100644 index 0000000..6392c74 --- /dev/null +++ b/src/string/memset.c @@ -0,0 +1,9 @@ +#include + +//TODO: update me :( +__attribute__((weak)) void *memset(void *s, int c, size_t n) +{ + while ((int)--n >= 0) + ((uint8_t*)s)[n] = c; + return (s); +} diff --git a/src/string/sprintf.c b/src/string/sprintf.c new file mode 100644 index 0000000..483de7c --- /dev/null +++ b/src/string/sprintf.c @@ -0,0 +1,113 @@ +#include + +static size_t strbase(char *dest, uint32_t nb, size_t size, int base) +{ + uint32_t tmp; + + if (base == 10){ + if ((int32_t)nb < 0){ + *(dest++) = '-'; + nb = -nb; + } + } + if (size == 0){ + tmp = nb; + while (tmp != 0){ + tmp /= base; + size += 1; + } + if (size == 0) + size = 1; + } + tmp = size; + while ((int)(--size) >= 0){ + *(dest + size) = ((nb % base) + '0') + (39 * ((nb % base) > 9)); + nb /= base; + + } + *(dest + tmp) = '\0'; + return (tmp); + +} + +static size_t strndump(char *dest, char const *str, size_t size) +{ + size_t i; + + if (str == NULL || dest == NULL) + return (0); + i = -1; + while (++i < size && str[i] != '\0') + dest[i] = str[i]; + dest[i] = '\0'; + return (i); +} + +__attribute__((weak)) void vsprintf(char *str, char const *format, va_list ap) +{ + size_t size; + size_t len; + + if (format == NULL) + return; + while (*format != '\0'){ + if (*format != '%'){ + *(str++) = *(format++); + continue; + } + /* get size informations */ + size = 0; + len = -1; + format += 1; + while (format[++len] >= '0' && format[len] <= '9') + size = size * 10 + format[len] - '0'; + if (format[len] == '%'){ + *(str++) = '%'; + format += 1; + continue; + } + if (format[len] == 'c'){ + *(str++) = (char)va_arg(ap, int); + format += len + 1; + continue; + } + if (format[len] == 's'){ + char const *tmp = va_arg(ap, char const *); + /* TODO: find better way to do the job */ + str += strndump(str, tmp, (size == 0) ? 1024 : size); + format += len + 1; + continue; + } + if (format[len] == 'd'){ + int nb = va_arg(ap, int); + str += strbase(str, nb, size, 10); + format += len + 1; + continue; + } + if (format[len] == 'x'){ + int nb = va_arg(ap, int); + str += strbase(str, nb, size, 16); + format += len + 1; + continue; + } + if (format[len] == '#' && format[len + 1] == 'x'){ + int nb = va_arg(ap, int); + *(str++) = '0'; + *(str++) = 'x'; + str += strbase(str, nb, 8, 16); + format += len + 2; + continue; + } + *(str++) = '%'; + } + *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/string/strcat.c b/src/string/strcat.c new file mode 100644 index 0000000..c1c1419 --- /dev/null +++ b/src/string/strcat.c @@ -0,0 +1,17 @@ +#include + +__attribute__((weak)) char *strcat(char *dest, char const *src) +{ + size_t i; + size_t start; + + if (src == NULL || dest == NULL) + return (0); + i = -1; + start = -1; + while (dest[++start] != '\0'); + while (src[++i] != '\0') + dest[start + i] = src[i]; + dest[i + start] = '\0'; + return (dest); +} diff --git a/src/string/strcmp.c b/src/string/strcmp.c new file mode 100644 index 0000000..f0e7635 --- /dev/null +++ b/src/string/strcmp.c @@ -0,0 +1,12 @@ +#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/strcpy.c b/src/string/strcpy.c new file mode 100644 index 0000000..f5e78ff --- /dev/null +++ b/src/string/strcpy.c @@ -0,0 +1,27 @@ +#include + +__attribute__((weak)) char *strcpy(char *dest, char const *src) +{ + size_t i; + + if (src == NULL || dest == NULL) + return (0); + i = -1; + while (src[++i] != '\0') + dest[i] = src[i]; + dest[i] = '\0'; + return (dest); +} + +__attribute__((weak)) char *strncpy(char *dest, char const *str, size_t size) +{ + size_t i; + + if (str == NULL || dest == NULL) + return (0); + i = -1; + while (++i < size && str[i] != '\0') + dest[i] = str[i]; + dest[i] = '\0'; + return (dest); +} diff --git a/src/string/strlen.c b/src/string/strlen.c new file mode 100644 index 0000000..56cf1c6 --- /dev/null +++ b/src/string/strlen.c @@ -0,0 +1,12 @@ +#include + +__attribute__((weak)) size_t strlen(char const *str) +{ + size_t i; + + if (str == NULL) + return (0); + i = -1; + while (str[++i] != '\0'); + return (i); +} diff --git a/src/string/strtotab.c b/src/string/strtotab.c new file mode 100644 index 0000000..f84ecf2 --- /dev/null +++ b/src/string/strtotab.c @@ -0,0 +1,140 @@ +#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 inibitor (and check if the +// inibitor charactere 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 remove useless spaces, tabs and handle '\"' inibithor. +// 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); +} + +//TODO: +// - write doc ! +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); +} + +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 new file mode 100644 index 0000000..e1a9a07 --- /dev/null +++ b/src/syscalls.s @@ -0,0 +1,98 @@ +.global _casio_GetKey +.global _casio_PrintMini +.global _casio_Bdisp_PutDisp_DD +.global _casio_Bdisp_AllClr_DDVRAM +.global _casio_Bdisp_DrawLine_VRAM +.global _casio_Bdisp_AreaClr_DDVRAM +.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_DDVRAM, @function +.type _casio_Bdisp_DrawLine_VRAM, @function +.type _casio_Bdisp_AreaClr_DDVRAM, @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_DDVRAM: + 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_DDVRAM: + 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 0x0000014c +.sys_restore_disp: .long 0x00000814 +.sys_save_disp: .long 0x00000813 +.sys_malloc: .long 0x00000acd +.sys_free: .long 0x00000acc + +.end diff --git a/tests/atoi_base_test.c b/tests/atoi_base_test.c new file mode 100644 index 0000000..0297d8c --- /dev/null +++ b/tests/atoi_base_test.c @@ -0,0 +1,31 @@ +#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 new file mode 100644 index 0000000..dac857f --- /dev/null +++ b/tests/history_test.c @@ -0,0 +1,52 @@ +#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 new file mode 100644 index 0000000..71df355 --- /dev/null +++ b/tests/internal.h @@ -0,0 +1,24 @@ +#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_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 new file mode 100644 index 0000000..4d16ab4 --- /dev/null +++ b/tests/malloc_hook.c @@ -0,0 +1,90 @@ +#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_ALWAYS : force all malloc return NULL. +// * NORMAL : 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 new file mode 100644 index 0000000..9372bdf --- /dev/null +++ b/tests/strtab_test.c @@ -0,0 +1,108 @@ +#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); +}