Version 1.0.0 of the XOmB Bare Bones distribution! With Bare Bones, all you get is booting up, printing some stuff out, and then looping into infinity (and beyond). Have fun!

This commit is contained in:
The XOmB Overlord
2009-02-21 22:23:22 -05:00
parent 1aa91d5e2b
commit 6d924a9fd7
62 changed files with 7169 additions and 0 deletions

14
LICENSE Normal file
View File

@@ -0,0 +1,14 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar
14 rue de Plaisance, 75014 Paris, France
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

129
README
View File

@@ -0,0 +1,129 @@
This is the XOmB-barebones distribution. It comes with the bare minimum needed to get a booting OS in D.
Except we added kprintfln. You're welcome.
The updated version of this file is kept on our wiki, located here:
http://wiki.xomb.org/index.php?title=XOmB_Bare_Bones
Don't expect this to be kept as up to date. We'll try, but the newest version will always be on the wiki, so check there.
The XOmB Bare Bones distribution is a minimal 64 bit OS written in D, distilled from the main project by [[User:Wilkie|wilkie]] and [[User:Steveklabnik|Steve Klabnik]].
== About ==
The [http://wiki.osdev.org osdev wiki] has a page called [http://wiki.osdev.org/Bare_Bones Bare Bones]. On it, they show how to make a minimal OS written in the C programming language. When we started [http://forum.osdev.org/viewtopic.php?f=15&t=18914 discussing programming an OS in D], some people indicated an interest in having a similar example, but in the D language.
We decided to oblige. We've distilled a minimal OS out of XOmB, and are releasing it as the "XOmB Bare Bones" distribution.
== Get XBB ==
The git repository is located [http://github.com/xomboverlord/xomb-bare-bones/tree/master here]. If you haven't used git before, check out our [[Using Git]] tutorial.
The short lowdown:
git clone git://github.com/xomboverlord/xomb-bare-bones.git
== Using XBB ==
First, a small word about compilers: GDC is dead. Unfortunatly, LDC isn't quite up to snuff yet, and while it's being worked on, unfortunatly, we have to stick with GDC. Expect things to get better in this area soon.
The first thing that you need to do in order to use XBB is create a cross compiler. Unfortunatly, our wiki is sparse on this subject at the moment, and so is the [http://wiki.osdev.org/GDC_Cross-Compiler osdev wiki]... we're sorry. That's coming soon.
After you have that up and running, you need to add a profile. We use dsss/rebuild to build stuff, and when we did it, it installed to /opt/etc/. So copy the gdc-xomb file from build/ (in the xomb-bare-bones directory) to /opt/etc/rebuild/ and you should be golden. Hopefully.
To build, just run
<pre>dsss build</pre> from within the build/ directory. This will make 'xomb.iso'. Then feel free to run it with bochs, xen, or whatever.
And that's it! Pretty easy, right?
== XBB Features ==
Considering that XBB is, well, bare-bones, it doesn't do much. kmain consists of one kprintfln! statement, which just prints a line to the screen. We've included a kprintfln! implementation to show off the power of D's templating system, but feel free to replace it, of course.
== XBB Organization ==
The XBB directory looks like this:
$ tree -L 1
.
|-- LICENSE
|-- README
|-- build
|-- kernel
2 directories, 2 files
We've moved all of the source into kernel, because you (at some point) will want to write userspace code. You'd probably want to make another directory in the main tree with all of that code in it. The main XOmB project has libos/ and tools/ and such.
=== LICENSE ===
XBB is distributed under the [http://sam.zoy.org/wtfpl/ WTFPL]. This is the most free license we could possibly imagine that still contains a swear word, so have at it.
=== README ===
The readme contains a copy of this page, though it's not updated quite as often as this page is.
=== build/ ===
$ tree -L 1 build/
build/
|-- bochsrc
|-- dsss.conf
|-- dsss.last
|-- dsss_objs
|-- iso
|-- linker.ld
|-- xomb.dump
`-- xomb.iso
2 directories, 6 files
==== bochsrc ====
Assuming you're running bochs, we've given you a bochsrc.
==== dsss.conf ====
This file tells dsss how to build XBB.
==== dsss.last ====
This is another file that dsss generates.
==== dsss_objs ====
This directory contains all of the intermediate stuff that dsss needs to do its job.
==== iso ====
This directory contains a copy of the actual FS contained in xomb.iso.
==== linker.ld ====
This script lets ld know how it should link everything together.
==== xomb.dump ====
A dump of the iso. Very useful for seeing exactly what asm gets generated after compiling things.
==== xomb.iso ====
This is the actual .iso file that needs to be burnt to a CD (or run in some other manner) to run the OS!
=== kernel/ ===
$ tree -L 1 kernel/
kernel/
|-- arch
|-- config.d
|-- core
|-- dev
`-- runtime
4 directories, 1 file
==== arch ====
This directory contains everything pertaining to architecture. If you wanted to port XBB to arm or something, the code would go in here.
==== config.d ====
This sets a bunch of configuration options, mostly relating to debugging information.
==== core ====
This is where it all goes down. The core kernel code is located inside.
==== dev ====
Everything in this directory pertains to devices.
==== runtime ====
The kernel D runtime. This runtime is nowhere near robust as a full userspace runtime would be, as the kernel donesn't need such niceties as garbage collection. Just the bare minimum, thanks.
== For More Info ==
Check out the individual source files for information on how specific things work. We've made an attempt to heavily comment everything, so that you can see in the code itself how things work.
If you find that you need more help, please [[Contact |contact]] us, and we'll do our best. Please let us know if there's anything that we can do to make this project better!

4
build/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
dsss_objs/*
dsss.last
xomb.dump
xomb.iso

5
build/bochsrc Normal file
View File

@@ -0,0 +1,5 @@
romimage: file=/usr/src/bochs-2.3.7/bios/BIOS-bochs-latest
megs: 128
ata1-slave: type=cdrom, path="./xomb.iso", status=inserted
boot: cdrom
cpu: count=2, reset_on_triple_fault=0

64
build/dsss.conf Normal file
View File

@@ -0,0 +1,64 @@
name = xomb
CC = x86_64-pc-elf-gcc
CFLAGS = -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel
[*]
buildflags=-dc=gdc-xomb
[../kernel/core/kmain.d]
buildflags=-dc=gdc-xomb -I..
# compile the assembly for the target
prebuild= \
\
\
echo ; \
echo Compiling Assembly for target: x86_64 ;\
echo '--> boot.S';\
x86_64-pc-elf-gcc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -c ../kernel/arch/x86_64/boot/boot.S -o dsss_objs/G/kernel.arch.x86_64.boot.boot.o ; \
echo '--> load.S';\
x86_64-pc-elf-gcc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -c ../kernel/arch/x86_64/boot/load.S -o dsss_objs/G/kernel.arch.x86_64.boot.load.o ; \
#echo '--> trampoline.S';\
#x86_64-pc-elf-gcc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -c ../kernel/arch/x86_64/boot/trampoline.S -o dsss_objs/G/kernel.arch.x86_64.boot.trampoline.o ;\
\
\
echo ; \
echo Compiling Kernel Runtime ; \
echo '--> kernel/runtime/object.d';\
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/object.d -o dsss_objs/G/kernel.runtime.object.o ;\
echo '--> kernel/runtime/invariant.d';\
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/invariant.d -o dsss_objs/G/kernel.runtime.invariant.o ;\
echo '--> kernel/runtime/std/typeinfo/*';\
x86_64-pc-elf-gdmd -q,-nostdlib,-nodefaultlibs,-g,-DUSE_ASSERT,-mcmodel=kernel -I.. -I../kernel/runtime/. -c `ls ../kernel/runtime/std/typeinfo/*.d` -oddsss_objs/G/. ;\
echo '--> kernel/runtime/dstubs.d';\
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/dstubs.d -o dsss_objs/G/kernel.runtime.dstubs.o ;\
echo '--> kernel/runtime/util.d';\
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/util.d -o dsss_objs/G/kernel.runtime.util.o ;\
\
echo ; \
echo Compiling Kernel Proper ;
# what the target is
target = xomb.iso
# we will need some post build foo to link and create the iso
postbuild = \
\
echo ; \
echo Creating Kernel Executable; \
echo '--> xomb';\
x86_64-pc-elf-ld -nostdlib -nodefaultlibs -b elf64-x86-64 -T linker.ld -o iso/boot/xomb `ls dsss_objs/G/*.o`;\
\
echo ;\
echo Creating Kernel Dump; \
echo '--> xomb.dump';\
rm -f xomb.dump && x86_64-pc-elf-objdump -d -S -r iso/boot/xomb > xomb.dump;\
\
echo ;\
echo Compiling ISO; \
mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 16 -boot-info-table -o xomb.iso ./iso

35
build/gdc-xomb Normal file
View File

@@ -0,0 +1,35 @@
profile=phobos
compiler=x86_64-pc-elf-gdc
exeext=
objext=o
noversion=DigitalMars
version=GNU
testversion=linux
testversion=darwin
version=Unix
version=Posix
noversion=Windows
noversion=Win32
noversion=Win64
testversion=X86
testversion=PPC
testversion=X86_64
testversion=D_InlineAsm
testversion=D_InlineAsm_X86
testversion=D_InlineAsm_PPC
testversion=D_InlineAsm_X86_64
testversion=LittleEndian
testversion=BigEndian
[compile]
cmd=x86_64-pc-elf-gdmd -q,-nostdlib,-nodefaultlibs,-g,-DUSE_ASSERT,-mcmodel=kernel -I../kernel/runtime/ -c $i
[link]
cmd=#
[postlink]
cmd=echo "lol fuckers"

View File

@@ -0,0 +1,129 @@
# menu.lst - See: grub(8), info grub, update-grub(8)
# grub-install(8), grub-floppy(8),
# grub-md5-crypt, /usr/share/doc/grub
# and /usr/share/doc/grub-doc/.
## default num
# Set the default entry to the entry number NUM. Numbering starts from 0, and
# the entry number 0 is the default if the command is not used.
#
# You can specify 'saved' instead of a number. In this case, the default entry
# is the entry saved with the command 'savedefault'.
# WARNING: If you are using dmraid do not change this entry to 'saved' or your
# array will desync and will not let you boot your system.
default 0
## timeout sec
# Set a timeout, in SEC seconds, before automatically booting the default entry
# (normally the first entry defined).
timeout 0
## hiddenmenu
# Hides the menu by default (press ESC to see the menu)
hiddenmenu
# Pretty colours
#color cyan/blue white/blue
## password ['--md5'] passwd
# If used in the first section of a menu file, disable all interactive editing
# control (menu entry editor and command-line) and entries protected by the
# command 'lock'
# e.g. password topsecret
# password --md5 $1$gLhU0/$aW78kHK1QfV3P2b2znUoe/
# password topsecret
#
# examples
#
# title Windows 95/98/NT/2000
# root (hd0,0)
# makeactive
# chainloader +1
#
# title Linux
# root (hd0,1)
# kernel /vmlinuz root=/dev/hda2 ro
#
#
# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
### BEGIN AUTOMAGIC KERNELS LIST
## lines between the AUTOMAGIC KERNELS LIST markers will be modified
## by the debian update-grub script except for the default options below
## DO NOT UNCOMMENT THEM, Just edit them to your needs
## ## Start Default Options ##
## default kernel options
## default kernel options for automagic boot options
## If you want special options for specific kernels use kopt_x_y_z
## where x.y.z is kernel version. Minor versions can be omitted.
## e.g. kopt=root=/dev/hda1 ro
## kopt_2_6_8=root=/dev/hdc1 ro
## kopt_2_6_8_2_686=root=/dev/hdc2 ro
# kopt=root=UUID=766f85b2-0ecb-45b7-8ad9-b108f2eba4a2 ro
## Setup crashdump menu entries
## e.g. crashdump=1
# crashdump=0
## default grub root device
## e.g. groot=(hd0,0)
# groot=(hd0,0)
## should update-grub create alternative automagic boot options
## e.g. alternative=true
## alternative=false
# alternative=true
## should update-grub lock alternative automagic boot options
## e.g. lockalternative=true
## lockalternative=false
# lockalternative=false
## additional options to use with the default boot option, but not with the
## alternatives
## e.g. defoptions=vga=791 resume=/dev/hda5
# defoptions=quiet splash
## should update-grub lock old automagic boot options
## e.g. lockold=false
## lockold=true
# lockold=false
## Xen hypervisor options to use with the default Xen boot option
# xenhopt=
## Xen Linux kernel options to use with the default Xen boot option
# xenkopt=console=tty0
## altoption boot targets option
## multiple altoptions lines are allowed
## e.g. altoptions=(extra menu suffix) extra boot options
## altoptions=(recovery) single
# altoptions=(recovery mode) single
## controls how many kernels should be put into the menu.lst
## only counts the first occurence of a kernel, not the
## alternative kernel options
## e.g. howmany=all
## howmany=7
# howmany=all
## should update-grub create memtest86 boot option
## e.g. memtest86=true
## memtest86=false
# memtest86=true
## should update-grub adjust the value of the default booted system
## can be true or false
# updatedefaultentry=false
## ## End Default Options ##
title XOmB
kernel /boot/xomb
#module /your/module
### END PITTGEEKS AUTOMAGIC KERNELS LIST

Binary file not shown.

125
build/linker.ld Normal file
View File

@@ -0,0 +1,125 @@
/*
linker.ld
* This script is given as the only script to the linker
* Will map boot.S to LMA, and then everything else
will be linked to the VMA and mapped at the LMA
* _etext, _edata, _end are defined here
*/
/* KERNEL LINK LOCATIONS
these are the locations to map to
they need to be set within boot.h
as well
*/
kernel_VMA = 0xffffffff80000000;
kernel_LMA = 0x100000;
/* start from the entry point */
ENTRY(_start)
SECTIONS
{
/* link from LMA */
. = kernel_LMA;
_boot = .;
/* boot.S is ran in linear addresses */
.text_boot :
{
dsss_objs/G/kernel.arch.x86_64.boot.boot.o (.text)
}
_eboot = .;
/* The following is for the trampoline code, if and when
* multiprocessor support will be necessary.
*/
/* PROVIDE(_trampoline = .);
.text_trampoline ALIGN(0x1000) :
{
dsss_objs/G/kernel.arch.x86_64.boot.trampoline.o (.text)
}
PROVIDE(_etrampoline = .); */
/* link from VMA */
. = . + kernel_VMA;
_text = .;
PROVIDE(_kernel = .);
PROVIDE(_kernelBase = kernel_VMA);
/* the rest of the code links to higher memory */
.text : AT(ADDR(.text) - kernel_VMA + kernel_LMA)
{
code = .;
*(.text)
*(.text*)
/* read only data */
*(.rodata*)
*(.rdata*)
. = ALIGN(4096);
}
PROVIDE(_ekernel = .);
/* _etext defined */
PROVIDE (_etext = .);
_data = .;
/* data section */
.data : AT(ADDR(.data) - kernel_VMA + kernel_LMA)
{
data = .;
*(.data)
/* constructors and deconstructors
(if needed, doesn't hurt) */
start_ctors = .;
*(.ctor*)
end_ctors = .;
start_dtors = .;
*(.dtor*)
end_dtors = .;
. = ALIGN(4096);
}
/* _edata defined */
_edata = .; PROVIDE (edata = .);
/* static code */
.bss : AT(ADDR(.bss) - kernel_VMA + kernel_LMA)
{
*(.bss)
. = ALIGN(4096);
}
/* */
.ehframe : AT(ADDR(.ehframe) - kernel_VMA + kernel_LMA)
{
ehframe = .;
*(.ehframe)
. = ALIGN(4096);
}
/* _end defined */
_end = .; PROVIDE (end = .);
}

16
kernel/arch/select.d Normal file
View File

@@ -0,0 +1,16 @@
module kernel.arch.select;
// This module shows D's mixin capabilities to load modules for different architecture targets.
const char[] architecture = "x86_64";
template PublicArchImport(char[] mod)
{
const char[] PublicArchImport = `
public import kernel.arch.` ~ architecture ~ `.` ~ mod ~ `;
`;
}

View File

@@ -0,0 +1,275 @@
/*
boot.S - bootstrap the kernel
The 32 bit bootstrap code that serves these functions:
- contains multiboot header
- contains 32 bit GDT
- contains 32 bit IDT (for debugging, can be removed later)
- contains page tables
- lower 40MB are mapped 1-1
- higher 40MB (from 0xffffffff80000000) are mapped from 0x0 on
- after code in load.S runs, the lower half map should not be needed
- transitions into long mode:
- enables PAE (physical-address-extensions)
- setting PML4 (page-map-level-4)
- setting EFER flags for LMA (long-mode-active) and SYSCALL-SYSRET
- enables paging by setting the PG bit in CR0 (Control Register 0)
- long jumps to code within load.S
- note: some addresses located within the higher half need to be converted
to linear addresses: the stack, _edata, _end
- this is because: the multiboot header expects linear addresses,
the CPU expects stack at linear address, as it would for GDT, IDT, etc
*/
#define EXE_COMPAT_HACK
#define ASM 1
#include "multiboot.h"
#include "boot.h"
.globl start, _start
.text
start:
_start:
.code32
/* Stash values for multiboot we won't touch until 64 bit mode */
movl %ebx, %esi
movl %eax, %edi
/* jump to the 32 bit common start */
jmp (start32)
/* Align 32 bits boundary. */
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#ifdef EXE_COMPAT_HACK
/* header_addr */
.long (multiboot_header)
/* load_addr */
.long (_start)
/* load_end_addr */
.long (_edata-KERNEL_VMA_BASE)
/* bss_end_addr */
.long (_end-KERNEL_VMA_BASE)
/* entry_addr */
.long (start)
#endif
.global start32, _start32
_start32:
start32:
/* disable interrupts (CLear Interrupt flag) */
cli
/* enable 64-bit page-translation-table entries by
setting CR4.PAE=1. Paging not enabled until after
long mode enabled */
movl %cr4, %eax
bts $5, %eax
movl %eax, %cr4
/* Create long mode page table and init CR3 to point to
the base of the PML4 page table. */
movl $(pml4_base), %eax
movl %eax, %cr3
/* Enable Long mode and SYSCALL/SYSRET instructions */
movl $0xc0000080, %ecx
rdmsr
bts $8, %eax
bts $0, %eax
wrmsr
/* Load the 32 bit GDT */
lgdt (pGDT32)
/* Load the 32 bit IDT */
lidt (pIDT32)
/* establish a stack for 32 bit code */
mov $((stack-KERNEL_VMA_BASE) + STACK_SIZE), %esp
/* enable paging to activate long mode */
movl %cr0, %eax
bts $31, %eax
movl %eax, %cr0
// make the jump to long mode!
ljmp $CS_KERNEL, $(start64-KERNEL_VMA_BASE)
// The following are a series of kernel structures used by the cpu
// These are temporary and will be replaced by permanent ones when the
// kernel is executed proper.
// 32 BIT GDT
.align 4096
.globl pGDT32
pGDT32:
.word GDT_END - GDT_TABLE - 1
.quad GDT_TABLE - KERNEL_VMA_BASE
.align 4096
GDT_TABLE:
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00cf9a000000ffff /* __KERNEL32_CS */
.quad 0x00af9a000000ffff /* __KERNEL_CS */
.quad 0x0000000000000000 /* upper half of CS */
.quad 0x00af93000000ffff /* __KERNEL_DS */
.quad 0x0000000000000000 /* upper half of DS */
.quad 0x00affa000000ffff /* __USER_CS */
.quad 0x0000000000000000 /* upper half of CS */
.quad 0x00aff3000000ffff /* __USER_DS */
.quad 0x0000000000000000 /* upper half of DS */
.quad 0,0 /* TSS */
.quad 0,0 /* TSS */
.quad 0,0 /* LDT */
.quad 0,0 /* LDT */
// wtf?
.quad 0,0,0 /* three TLS descriptors */
.quad 0x0000f40000000000 /* node/CPU stored in limit */
GDT_END:
// 32 BIT IDT
.align 4096
.globl pIDT32
pIDT32:
.word IDT_END - IDT_TABLE - 1
.quad IDT_TABLE - KERNEL_VMA_BASE
#define IDT_LOCATION 0x106000
.align 4096
IDT_TABLE:
i = 0
.rept 32
.long 0x100000 | ((IDT_LOCATION + i) & 0xFFFF)
.long ((IDT_LOCATION + i) & 0xFFFF0000) | 0x8E00
i = i + 8
.endr
IDT_END:
.align 4096
int_handler_32:
i = 0
.rept 32
mov i, %eax
iret
i = i + 1
.endr
int_handler_32_end:
.align 4096 // the others may not be needed, but this one MUST BE THERE
.globl pml4_base
// PML4
pml4_base:
.quad (level3_ident_pgt + 0x0000000000000007)
.fill 510,8,0
.quad (level3_ident_pgt + 0x0000000000000007)
// --- THIS SHOULD BE ALIGNED AT 4K --- //
.align 4096
.globl level3_ident_pgt
// PDP
// PML3
level3_ident_pgt:
.quad (level2_ident_pgt + 0x07)
.quad 0 //(level2_ident_pgt + 0x07)
.quad (level2_ident_pgt + 0x07)
.rept (507)
.quad 0
.endr
.quad (level2_ident_pgt + 0x07)
.quad 0 // (level2_ident_pgt + 0x07)
// --- THIS SHOULD BE ALIGNED AT 4K --- //
.align 4096
.globl level2_ident_pgt
// flags 0x00087
// PDE
// PML2
level2_ident_pgt:
i = 0
// 15 TABLE ENTRIES
.rept 15
.quad (level1_ident_pgt + i + 0x0000000000000007)
i = i + 4096
.endr
.fill 497,8,0
// --- THIS SHOULD BE ALIGNED AT 4K --- //
// PTE
// PML1
.align 4096
.globl level1_ident_pgt
level1_ident_pgt:
// UM
// 40MB for bootup.
i = 0
// 15 TABLES
.rept (512 * 15)
.quad i << 12 | 0x087
i = i + 1
.endr

View File

@@ -0,0 +1,21 @@
/*
boot.h
- Contains information pertinant to the bootstrap about where
the kernel is located
*/
/* the code section for the kernel
0x10 = code section 2 ( right shift it by 3 ) */
#define CS_KERNEL 0x10
#define CS_KERNEL32 0x8
/* the location, in physical address (LMA) and virtual (VMA) */
/* these should correspond to linker.ld */
#define KERNEL_LMA_BASE 0x100000
#define KERNEL_VMA_BASE (0xffffffff80000000)
#define KERNEL_LOCATION (KERNEL_VMA_BASE + KERNEL_LMA_BASE)

View File

@@ -0,0 +1,94 @@
/*
load.S
The 64 bit code that serves these functions:
- sets up stack
- transfers %rip to higher half
- clears cpu flags
- calls kmain with multiboot information
*/
#define ASM 1
#include "multiboot.h"
#include "boot.h"
.text
.code64
.globl start64, _start64
start64:
_start64:
/* Initialize the 64 bit stack pointer. */
movq $((stack - KERNEL_VMA_BASE) + STACK_SIZE), %rsp
/* set up the stack for the return */
pushq $CS_KERNEL
pushq $long_entry
/* Go into canonical higher half */
/* This trick is borrowed from the linux kernel,
/arch/x86_64/kernel/head.S */
lretq
long_entry:
/* From here on out, we are running instructions
Within the higher half (0xffffffff80000000 ... )
We can safely unmap the lower half, we do not
need an identity mapping of the lower half. */
movq $(stack + STACK_SIZE), %rsp
/* Set cpu flags */
pushq $0
lss (%rsp), %eax
popf
/* Sets the Input/Output Permission Level to 3, so
that it will not check the IO permissions bitmap when access is requested. */
pushf
popq %rax
or $0x3000, %rax
pushq %rax
popf
addq $(KERNEL_VMA_BASE), %rsi
/* Push the pointer to the Multiboot information structure. */
pushq %rsi
/* Push the magic value. */
pushq %rdi
/* Now enter the kmain function... */
call EXT_C(kmain)
/* We should not get here */
loop:
hlt
jmp loop
// --- STACK --- //
.globl stack
.align 4096
// Our stack area.
stack:
.rept STACK_SIZE
.long 0
.endr

View File

@@ -0,0 +1,104 @@
/* multiboot.h - the header for Multiboot */
/* Macros. */
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
//#ifdef __ELF__
//# define MULTIBOOT_HEADER_FLAGS 0x00000003
//#else
# define MULTIBOOT_HEADER_FLAGS 0x00010003
//#endif
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* The size of our stack (16KB). */
#define STACK_SIZE 0x4000
/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
#ifdef HAVE_ASM_USCORE
# define EXT_C(sym) _ ## sym
#else
# define EXT_C(sym) sym
#endif
#ifndef ASM
/* Do not include here in boot.S. */
/* Types. */
/* The Multiboot header. */
typedef struct multiboot_header
{
unsigned long magic;
unsigned long flags;
unsigned long checksum;
unsigned long header_addr;
unsigned long load_addr;
unsigned long load_end_addr;
unsigned long bss_end_addr;
unsigned long entry_addr;
} multiboot_header_t;
/* The symbol table for a.out. */
typedef struct aout_symbol_table
{
unsigned long tabsize;
unsigned long strsize;
unsigned long addr;
unsigned long reserved;
} aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct elf_section_header_table
{
unsigned long num;
unsigned long size;
unsigned long addr;
unsigned long shndx;
} elf_section_header_table_t;
/* The Multiboot information. */
typedef struct multiboot_info
{
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
unsigned long cmdline;
unsigned long mods_count;
unsigned long mods_addr;
union
{
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
} u;
unsigned long mmap_length;
unsigned long mmap_addr;
} multiboot_info_t;
/* The module structure. */
typedef struct module
{
unsigned long mod_start;
unsigned long mod_end;
unsigned long string;
unsigned long reserved;
} module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low
but no size. */
typedef struct memory_map
{
unsigned long size;
unsigned long base_addr_low;
unsigned long base_addr_high;
unsigned long length_low;
unsigned long length_high;
unsigned long type;
} memory_map_t;
#endif /* ! ASM */

27
kernel/config.d Normal file
View File

@@ -0,0 +1,27 @@
//Config options
bool enable_kgdb = false;
bool remote_debug = true; // Its like debugging for the debugger
// Kernel options
// Make sure this is the same as the value in boot.h
const ulong KERNEL_VM_BASE = 0xFFFFFFFF80000000;
// Debugging options
// Setting DEBUG_ALL to true will cause *ALL* debug
// flags to turn on. If you only want to see some
// debug messages, turn DEBUG_ALL off, and only
// turn on the debug messages you wish to see.
const auto DEBUG_ALL = false;
// Individual debug options
const auto DEBUG_PAGING = false;
const auto DEBUG_PAGEFAULTS = false;
const auto DEBUG_PMEM = false;
const auto DEBUG_INTERRUPTS = false;
const auto DEBUG_MPTABLE = false;
const auto DEBUG_LAPIC = false;
const auto DEBUG_IOAPIC = false;
const auto DEBUG_APENTRY = false;
const auto DEBUG_KBD = false;
const auto DEBUG_SCHEDULER = false;

41
kernel/core/kmain.d Normal file
View File

@@ -0,0 +1,41 @@
/* XOmB Bare Bones
*
* This is the bare minimum needed for an OS written in the D language.
*
* Note: The kmain will be called in the higher memory region.
* The next step is setting up permanent kernel structures.
*
*/
module kernel.core.kmain;
// This module contains our powerful kprintf function
import kernel.core.kprintf;
// The main function for the kernel.
// This will receive data from the boot loader.
// bootLoaderID is the unique identifier for a boot loader.
// data is a structure given by the boot loader.
// For GRUB: the identifier is the magic number.
// data is the pointer to the multiboot structure.
extern(C) void kmain(int bootLoaderID, void *data)
{
kprintfln!("{!cls}Welcome to {}! (version {}.{}.{})")("XOmB Bare Bones", 1,0,0);
kprintfln!("{x} {x}")(bootLoaderID, data);
// Ok, so we don't want to just infinite loop (if you want it to do something)
// Replace this with your kernel logic!
for(;;) {}
}

428
kernel/core/kprintf.d Normal file
View File

@@ -0,0 +1,428 @@
// This module implements the print logic for the kernel
module kernel.core.kprintf;
// Contains the interface to the VGA textmode driver.
import kernel.dev.console;
// Contains some nice logic and cool templates.
import kernel.core.util;
/* This template will generate code for printing and will do
* all parsing of the format string at compile time
*
* USAGE:
* kprintf!("format string {specifier} ... ")(args...);
*
* EXAMPLES:
* kprintf!("Integer: {}")(10);
* kprintf!("{!cls}Cleared the screen.")();
* kprintf!("{!pos:2,3}At position (2,3)")();
* kprintf!("{!fg:LightBlue!bg:Gray}{}")(25);
* kprintf!("{!fg:Red}redness")();
* kprintf!("{x} Hex!")(145);
* kprintf!("Curly Brace: {{")();
*
* COMMANDS:
* !cls - Clears the screen.
* !fg - Sets the foreground color, see the Color enum
* in kernel/dev/console.d.
* !bg - Sets the background color, same as above.
* !pos - Moves the cursor to the x and y given, see example above.
*
* SPECIFIERS:
* {x} - Prints the hex value.
* {u} - Treats as unsigned.
* {} - Prints common form.
*
* WHY IS IT COOL?
* - Compile time parsing of format strings
* - Type checking at compile time as well
* - That means it can tell you that you are dumb before you execute.
* - No need to specify type information.
*
* - So we can do this and not care about the
* output of the function:
*
* auto blah = someFunction();
* kprintf!("Some Arbitrary Info: {}")(blah);
*
* WOWWY WOW WOW!
*
*/
template kprintf(char[] Format)
{
void kprintf(Args...)(Args args)
{
mixin(ConvertFormat!(Format, Args));
}
}
/* This template will generate code like kprintf but will also
* print a newline afterward.
*
* USAGE: See kprintf above.
*
*/
template kprintfln(char[] Format)
{
void kprintfln(Args...)(Args args)
{
mixin(ConvertFormat!(Format, Args));
Console.putChar('\n');
}
}
// The crazy D templating logic that implements the kprintf
private
{
// The following are functions that implement logic for printing different primatives.
void printInt(long i, char[] fmt)
{
char[20] buf;
if(fmt.length is 0)
Console.putString(itoa(buf, 'd', i));
else if(fmt[0] is 'd' || fmt[0] is 'D')
Console.putString(itoa(buf, 'd', i));
else if(fmt[0] is 'u' || fmt[0] is 'U')
Console.putString(itoa(buf, 'u', i));
else if(fmt[0] is 'x' || fmt[0] is 'X')
Console.putString(itoa(buf, 'x', i));
}
// Floats are not supported by the kernel, but the interface to this exists anyway.
void printFloat(real f, char[] fmt)
{
Console.putString("?float?");
}
void printChar(dchar c, char[] fmt)
{
Console.putChar(c);
}
void printString(T)(T s, char[] fmt)
{
static assert(isStringType!(T));
Console.putString(s);
}
void printPointer(void* p, char[] fmt)
{
Console.putString("0x");
char[20] buf;
Console.putString(itoa(buf, 'x', cast(ulong)p));
}
// The core template that will parse the format to find the string until a format specifier and return the length.
template ExtractString(char[] format)
{
static if(format.length == 0)
{
const size_t ExtractString = 0;
}
else static if(format[0] is '{')
{
static if(format.length > 1 && format[1] is '{')
const size_t ExtractString = 2 + ExtractString!(format[2 .. $]);
else
const size_t ExtractString = 0;
}
else
const size_t ExtractString = 1 + ExtractString!(format[1 .. $]);
}
// Extracts the format string and returns the length of that string.
template ExtractFormatStringImpl(char[] format)
{
static assert(format.length !is 0, "Unterminated format specifier");
static if(format[0] is '}')
const ExtractFormatStringImpl = 0;
else
const ExtractFormatStringImpl = 1 + ExtractFormatStringImpl!(format[1 .. $]);
}
// This template compares the format given (eg {x} would be "x") against the type of the argument passed.
template CheckFormatAgainstType(char[] rawFormat, size_t idx, T)
{
const char[] format = rawFormat[1 .. idx];
static if(isIntType!(T))
{
static assert(format == "" || format == "x" || format == "X" || format == "u" || format == "U",
"Invalid integer format specifier '" ~ format ~ "'");
}
// This is an inherited attribute to describe the length of the format string
const size_t res = idx;
}
// This template will compare a format with a type.
template ExtractFormatString(char[] format, T)
{
const ExtractFormatString = CheckFormatAgainstType!(format, ExtractFormatStringImpl!(format), T).res;
}
// This will get the length of a single command
template ExtractCommandStringImpl(char[] format)
{
static if (format.length == 0 || format[0] is '}')
{
const int ExtractCommandStringImpl = 0;
}
else
{
const int ExtractCommandStringImpl = 1 + ExtractCommandStringImpl!(format[1..$]);
}
}
// This template will extract a command string, or set of command strings
template ExtractCommandString(char[] format)
{
const ExtractCommandString = ExtractCommandStringImpl!(format);
}
// This template will take a string 's' and convert any '{{' to a single '{'.
// This is done after parsing the format string.
template StripDoubleLeftBrace(char[] s)
{
static if(s.length is 0)
const char[] StripDoubleLeftBrace = "";
else static if(s.length is 1)
const char[] StripDoubleLeftBrace = s;
else
{
static if(s[0 .. 2] == "{{")
const char[] StripDoubleLeftBrace = "{" ~ StripDoubleLeftBrace!(s[2 .. $]);
else
const char[] StripDoubleLeftBrace = s[0] ~ StripDoubleLeftBrace!(s[1 .. $]);
}
}
// Generates the code to print the string.
template MakePrintString(char[] s)
{
const char[] MakePrintString = "printString(\"" ~ StripDoubleLeftBrace!(s) ~ "\", \"\");\n";
}
// This template will generate the code to print out the string.
template MakePrintOther(T, char[] fmt, size_t idx)
{
static if(isIntType!(T))
const char[] MakePrintOther = "printInt(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
else static if(isCharType!(T))
const char[] MakePrintOther = "printChar(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
else static if(isStringType!(T))
const char[] MakePrintOther = "printString(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
else static if(isFloatType!(T))
const char[] MakePrintOther = "printFloat(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
else static if(isPointerType!(T))
const char[] MakePrintOther = "printPointer(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
else static if(isArrayType!(T))
const char[] MakePrintOther = "printArray(args[" ~ idx.stringof ~ "], true, false);\n";
else
static assert(false, "I don't know how to handle argument " ~ idx.stringof ~ " of type '" ~ T.stringof ~ "'.");
}
// For the !fg command
template MakePrintCommand_fg(char[] format)
{
static if (format.length <= 1)
{
static assert(false, "Not enough parameters to the !fg command.");
}
else
{
const char[] MakePrintCommand_fg = "Console.setForeColor(Color." ~ format[1..$] ~ ");\n";
}
}
// For the !bg command
template MakePrintCommand_bg(char[] format)
{
static if (format.length <= 1)
{
static assert(false, "Not enough parameters to the !bg command.");
}
else
{
const char[] MakePrintCommand_bg = "Console.setBackColor(Color." ~ format[1..$] ~ ");\n";
}
}
template MakePrintCommand_pos(char[] format)
{
static if (format.length <= 3)
{
static assert(false, "Not enough parameters to the !pos command. USAGE: {!pos:x,y} where x and y are integers.");
}
else
{
const char[] MakePrintCommand_pos = "Console.setPosition(" ~ format[1..$] ~ ");\n";
}
}
// Output code to do the command.
template MakePrintCommandGenerate(char[] format)
{
static if (format.length >= 3 && format[0..3] == "cls")
{
const char[] MakePrintCommandGenerate = "Console.clearScreen();\n";
}
else static if (format.length >= 2 && format[0..2] == "fg")
{
const char[] MakePrintCommandGenerate = MakePrintCommand_fg!(format[2..$]);
}
else static if (format.length >= 2 && format[0..2] == "bg")
{
const char[] MakePrintCommandGenerate = MakePrintCommand_bg!(format[2..$]);
}
else static if (format.length >= 3 && format[0..3] == "pos")
{
const char[] MakePrintCommandGenerate = MakePrintCommand_pos!(format[3..$]);
}
else
{
static assert(false, "Unknown Command, !" ~ format ~ ", for kprintf.");
}
}
// Finds the length of the command string
template ExtractCommand(char[] format)
{
static if (format.length == 0 || format[0] is '}' || format[0] is '!')
{
const ExtractCommand = 0;
}
else
{
const ExtractCommand = 1 + ExtractCommand!(format[1..$]);
}
}
// This template will take everything up to a ! or a } and generate the code for that command
template MakePrintCommandImpl(char[] format)
{
static if (format.length == 0)
{
const char[] res = "";
}
else
{
static if (format[0] is '!')
{
const char[] res = MakePrintCommandImpl!(format[1..$]).res;
}
else
{
const lengthOfString = ExtractCommand!(format);
const char[] res = MakePrintCommandGenerate!(format[0..lengthOfString]) ~
MakePrintCommandImpl!(format[lengthOfString..$]).res;
}
}
}
// commands: !cls, !fg:color, !bg:color
// This template parses the command string (excluding the initial !) and generates the commands necessary.
template MakePrintCommand(char[] format)
{
const char[] MakePrintCommand = MakePrintCommandImpl!(format).res;
}
// This template implements the logic behind format extraction.
template ConvertFormatImpl(char[] format, size_t argIdx, Types...)
{
static if(format.length == 0)
{
static assert(argIdx == Types.length, "More parameters than format specifiers");
const char[] res = "";
}
else
{
// Look for a token that starts with a left curly brace that would signify a format specifier.
static if (format[0] is '{' && (!(format.length > 1 && (format[1] is '{' || format[1] is '!'))))
{
// We have a format specifier, but no arguments to convert?
static assert(argIdx < Types.length, "More format specifiers than parameters");
// We will convert the string and generate code for the print.
// Get the format string
const lengthOfString = ExtractFormatString!(format, Types[argIdx]);
// Generate the code and recall this template.
const char[] res = MakePrintOther!(Types[argIdx], format[1 .. lengthOfString] , argIdx) ~
ConvertFormatImpl!(format[lengthOfString + 1 .. $], argIdx + 1, Types).res;
}
else static if (format[0] is '{' && format.length > 1 && format[1] is '!')
{
// Command Token found, acts very similarly to a normal format specifier, expect it doesn't compare the types from the arguments.
const lengthOfString = ExtractCommandString!(format);
// Generate the code and recall this template.
const char[] res = MakePrintCommand!(format[2..lengthOfString])
~ ConvertFormatImpl!(format[lengthOfString + 1 .. $], argIdx, Types).res;
}
else
{
// We want to know how long of a string we can print out without intervention
const lengthOfString = ExtractString!(format);
// Then we can generate the code to print it out with the console and recall this template.
const char[] res = MakePrintString!(format[0..lengthOfString]) ~
ConvertFormatImpl!(format[lengthOfString..$], argIdx, Types).res;
}
}
}
// This template is the core routine. It will take the format and the arguments and generate the code to logically print out the string.
template ConvertFormat(char[] format, Types...)
{
const char[] ConvertFormat = ConvertFormatImpl!(format, 0, Types).res;
}
}

383
kernel/core/util.d Normal file
View File

@@ -0,0 +1,383 @@
module kernel.core.util;
/**
This method checks to see if the value stored in the bit number declared
by the input variable "bit" in the flag declared by the input
variable "flags" is set. Returns a 1 if it is set, returns a 0 if it is not set.
Params:
flags = The flags from the multiboot header the kernel wishes to check.
bit = The number of the bit the kernel would like to check for data.
Returns: Whether the bit "bit" in "flags" has a value (1 if it is set, 0 if it is not)
*/
uint CHECK_FLAG(uint flags, uint bit)
{
return ((flags) & (1 << (bit)));
}
/**
Given a struct type, gives a tuple of strings of the names of fields in the struct.
*/
public template FieldNames(S, int idx = 0)
{
static if(idx >= S.tupleof.length)
alias Tuple!() FieldNames;
else
alias Tuple!(GetLastName!(S.tupleof[idx].stringof), FieldNames!(S, idx + 1)) FieldNames;
}
private template GetLastName(char[] fullName, int idx = fullName.length - 1)
{
static if(idx < 0)
const char[] GetLastName = fullName;
else static if(fullName[idx] == '.')
const char[] GetLastName = fullName[idx + 1 .. $];
else
const char[] GetLastName = GetLastName!(fullName, idx - 1);
}
template Tuple(T...)
{
alias T Tuple;
}
template Bitfield(alias data, Args...)
{
static assert(!(Args.length & 1), "Bitfield arguments must be an even number");
const char[] Bitfield = BitfieldShim!((typeof(data)).stringof, data, Args).Ret;
}
// Odd bug in D templates -- putting "data.stringof" as a template argument gives it the
// string of the type, rather than the string of the symbol. This shim works around that.
template BitfieldShim(char[] typeStr, alias data, Args...)
{
const char[] Name = data.stringof;
const char[] Ret = BitfieldImpl!(typeStr, Name, 0, Args).Ret;
}
template BitfieldImpl(char[] typeStr, char[] nameStr, int offset, Args...)
{
static if(Args.length == 0)
const char[] Ret = "";
else
{
const Name = Args[0];
const Size = Args[1];
const Mask = Bitmask!(Size);
const char[] Getter = "public " ~ typeStr ~ " " ~ Name ~ "() { return ( " ~
nameStr ~ " >> " ~ Itoh!(offset) ~ " ) & " ~ Itoh!(Mask) ~ "; }";
const char[] Setter = "public void " ~ Name ~ "(" ~ typeStr ~ " val) { " ~
nameStr ~ " = (" ~ nameStr ~ " & " ~ Itoh!(~(Mask << offset)) ~ ") | ((val & " ~
Itoh!(Mask) ~ ") << " ~ Itoh!(offset) ~ "); }";
const char[] Ret = Getter ~ Setter ~ BitfieldImpl!(typeStr, nameStr, offset + Size, Args[2 .. $]).Ret;
}
}
template Itoa(long i)
{
static if(i < 0)
const char[] Itoa = "-" ~ IntToStr!(-i, 10);
else
const char[] Itoa = IntToStr!(i, 10);
}
template Itoh(long i)
{
const char[] Itoh = "0x" ~ IntToStr!(i, 16);
}
template Digits(long i)
{
const char[] Digits = "0123456789abcdefghijklmnopqrstuvwxyz"[0 .. i];
}
template IntToStr(ulong i, int base)
{
static if(i >= base)
const char[] IntToStr = IntToStr!(i / base, base) ~ Digits!(base)[i % base];
else
const char[] IntToStr = "" ~ Digits!(base)[i % base];
}
template Bitmask(long size)
{
const long Bitmask = (1L << size) - 1;
}
template isStringType(T)
{
const bool isStringType = is(T : char[]) || is(T : wchar[]) || is(T : dchar[]);
}
/**
Sees if a type is char, wchar, or dchar.
*/
template isCharType(T)
{
const bool isCharType = is(T == char) || is(T == wchar) || is(T == dchar);
}
/**
Sees if a type is a signed or unsigned byte, short, int, or long.
*/
template isIntType(T)
{
const bool isIntType = is(T == int) || is(T == uint) || is(T == long) || is(T == ulong) ||
is(T == short) || is(T == ushort) || is(T == byte) || is(T == ubyte) /* || is(T == cent) || is(T == ucent) */;
}
/**
Sees if a type is a signed or unsigned byte, short, int, or long.
*/
template isUnsignedIntType(T)
{
const bool isUnsignedIntType = is(T == uint) || is(T == ulong) ||
is(T == ushort) || is(T == ubyte) /* || is(T == ucent) */;
}
/**
Sees if a type is a signed or unsigned byte, short, int, or long.
*/
template isSignedIntType(T)
{
const bool isSignedIntType = is(T == int) || is(T == long) ||
is(T == short) || is(T == byte) /* || is(T == cent) */;
}
/**
Sees if a type is float, double, or real.
*/
template isFloatType(T)
{
const bool isFloatType = is(T == float) || is(T == double) || is(T == real);
}
/**
Sees if a type is an array.
*/
template isArrayType(T)
{
const bool isArrayType = false;
}
template isArrayType(T : T[])
{
const bool isArrayType = true;
}
/**
Sees if a type is an associative array.
*/
template isAAType(T)
{
const bool isAAType = is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T);
}
/**
Sees if a type is a pointer.
*/
template isPointerType(T)
{
const bool isPointerType = false;
}
template isPointerType(T : T*)
{
const bool isPointerType = true;
}
/**
Get to the bottom of any chain of typedefs! Returns the first non-typedef'ed type.
*/
template realType(T)
{
static if(is(T Base == typedef) || is(T Base == enum))
alias realType!(Base) realType;
else
alias T realType;
}
/**
See if a character is a lowercase character.
*/
template IsLower(char c)
{
const bool IsLower = c >= 'a' && c <= 'z';
}
/**
See if a character is an uppercase character.
*/
template IsUpper(char c)
{
const bool IsUpper = c >= 'A' && c <= 'Z';
}
/**
Convert a character or string to lowercase.
*/
template ToLower(char c)
{
const char ToLower = IsUpper!(c) ? c + ('a' - 'A') : c;
}
/// ditto
template ToLower(char[] s)
{
static if(s.length == 0)
const ToLower = ""c;
else
const ToLower = ToLower!(s[0]) ~ s[1 .. $];
}
/**
Convert a character or string to uppercase.
*/
template ToUpper(char c)
{
const char ToUpper = IsLower!(c) ? c - ('a' - 'A') : c;
}
/// ditto
template ToUpper(char[] s)
{
static if(s.length == 0)
const ToUpper = ""c;
else
const ToUpper = ToUpper!(s[0]) ~ s[1 .. $];
}
/**
Capitalize a word so that the first letter is capital.
*/
template Capitalize(char[] s)
{
static if(s.length == 0)
const char[] Capitalize = ""c;
else
const char[] Capitalize = ToUpper!(s[0]) ~ ToLower!(s[1 .. $]);
}
/**
Compile-time map. Takes a template "function" which should take a single argument
of the type of the elements of the list of values that follows. Resolves to a tuple.
*/
template Map(alias Templ, List...)
{
static if(List.length == 0)
alias Tuple!() Map;
else
alias Tuple!(Templ!(List[0]), Map!(Templ, List[1 .. $])) Map;
}
/**
Compile-time reduce. Takes a template "function" that should take two arguments of the type
of the elements of the list of values that follows. The list must be at least one element
long. Resolves to a single value of the type that the template function returns.
*/
template Reduce(alias Templ, List...)
{
static assert(List.length > 0, "Reduce must be called on a list of at least one element");
static if(is(List[0]))
{
static if(List.length == 1)
alias List[0] Reduce;
else
alias Reduce!(Templ, Tuple!(Templ!(List[0], List[1]), List[2 .. $])) Reduce;
}
else
{
static if(List.length == 1)
const Reduce = List[0];
else
const Reduce = Reduce!(Templ, Tuple!(Templ!(List[0], List[1]), List[2 .. $]));
}
}
/**
Compile-time range. Given lower and upper bound, yields a tuple of integers in the
range [min, max).
*/
template Range(uint min, uint max)
{
static if(min >= max)
alias Tuple!() Range;
else
alias Tuple!(min, Range!(min + 1, max)) Range;
}
/// ditto
template Range(uint max)
{
alias Range!(0, max) Range;
}
/**
Compile time metafunction meant to be used with Reduce. Concatenates its first two
arguments and resolves to the result of that concatentation.
*/
template Cat(T...)
{
const Cat = T[0] ~ T[1];
}
// standard functions
/**
This function converts an integer to a string, depending on the base passed in.
Params:
buf = The function will save the translated string into this character array.
base = The base of the integer value. If "d," it will be assumed to be decimal. If "x," the integer
will be hexadecimal.
d = The integer to translate.
Returns: The translated string in a character array.
*/
char[] itoa(char[] buf, char base, long d)
{
size_t p = buf.length - 1;
size_t startIdx = 0;
ulong ud = d;
bool negative = false;
int divisor = 10;
// If %d is specified and D is minus, put `-' in the head.
if(base == 'd' && d < 0)
{
negative = true;
ud = -d;
}
else if(base == 'x')
divisor = 16;
// Divide UD by DIVISOR until UD == 0.
do
{
int remainder = ud % divisor;
buf[p--] = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
}
while (ud /= divisor)
if(negative)
buf[p--] = '-';
return buf[p + 1 .. $];
}

191
kernel/dev/console.d Normal file
View File

@@ -0,0 +1,191 @@
// This implements a console (text-mode) VGA driver.
module kernel.dev.console;
// This contains the hexidecimal values for various colors for printing to the screen.
enum Color : ubyte
{
Black = 0x00,
Blue = 0x01,
Green = 0x02,
Cyan = 0x03,
Red = 0x04,
Magenta = 0x05,
Yellow = 0x06,
LightGray = 0x07,
Gray = 0x08,
LightBlue = 0x09,
LightGreen = 0x0A,
LightCyan = 0x0B,
LightRed = 0x0C,
LightMagenta = 0x0D,
LightYellow = 0x0E,
White = 0x0F
}
// This is the true interface to the console
struct Console
{
static:
public:
// The number of columns and lines on the screen.
const uint COLUMNS = 80;
const uint LINES = 24;
// The default color.
const ubyte DEFAULTCOLORS = Color.LightGray;
ubyte* videoMemoryLocation = cast(ubyte*)0xFFFFFFFF800B8000;
// The cursor position
private int xpos = 0;
private int ypos = 0;
// The current color
private ubyte colorAttribute = DEFAULTCOLORS;
// The width of a tab
const auto TABSTOP = 4;
// This method will clear the screen and return the cursor to (0,0).
void clearScreen()
{
int i;
for (i=0; i < COLUMNS * LINES * 2; i++)
{
volatile *(videoMemoryLocation + i) = 0;
}
xpos = 0;
ypos = 0;
}
// This method will return the current location of the cursor
void getPosition(out int x, out int y)
{
x = xpos;
y = ypos;
}
// This method will set the current location of the cursor to the x and y given.
void setPosition(int x, int y)
{
if (x < 0) { x = 0; }
if (y < 0) { y = 0; }
if (x >= COLUMNS) { x = COLUMNS - 1; }
if (y >= LINES) { y = LINES - 1; }
xpos = x;
ypos = y;
}
// This method will post the character to the screen at the current location.
void putChar(char c)
{
if (c == '\t')
{
// Insert a tab.
xpos += TABSTOP;
}
else if (c != '\n' && c != '\r')
{
// Set the current piece of video memory to the character to print.
volatile *(videoMemoryLocation + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
volatile *(videoMemoryLocation + (xpos + ypos * COLUMNS) * 2 + 1) = colorAttribute;
// increase the cursor position
xpos++;
}
// if you have reached the end of the line, or printing a newline, increase the y position
if (c == '\n' || c == '\r' || xpos >= COLUMNS)
{
xpos = 0;
ypos++;
if (ypos >= LINES)
{
scrollDisplay(1);
}
}
}
// This mehtod will post a string to the screen at the current location.
void putString(char[] s)
{
foreach(c; s)
{
putChar(c);
}
}
// This function sets the console colors back to their defaults.
void resetColors()
{
colorAttribute = DEFAULTCOLORS;
}
// This function will set the text foreground to a new color.
void setForeColor(Color newColor)
{
colorAttribute = (colorAttribute & 0xf0) | newColor;
}
// This function will set the text background to a new color.
void setBackColor(Color newColor)
{
colorAttribute = (colorAttribute & 0x0f) | (newColor << 4);
}
// This function will set both the foreground and background colors.
void setColors(Color foreColor, Color backColor)
{
colorAttribute = (foreColor & 0x0f) | (backColor << 4);
}
// This function will scroll the entire screen.
void scrollDisplay(uint numLines)
{
// obviously, scrolling all lines results in a cleared display. Use the faster function.
if (numLines >= LINES)
{
clearScreen();
return;
}
int cury = 0;
int offset1 = 0;
int offset2 = numLines * COLUMNS;
// Go through and shift the correct amount.
for ( ; cury <= LINES - numLines; cury++)
{
for (int curx = 0; curx < COLUMNS; curx++)
{
*(videoMemoryLocation + (curx + offset1) * 2) = *(videoMemoryLocation + (curx + offset1 + offset2) * 2);
*(videoMemoryLocation + (curx + offset1) * 2 + 1) = *(videoMemoryLocation + (curx + offset1 + offset2) * 2 + 1);
}
offset1 += COLUMNS;
}
// clear the remaining lines
for (; cury <= LINES; cury++)
{
for (int curx = 0; curx < COLUMNS; curx++)
{
*(videoMemoryLocation + (curx + offset1) * 2) = 0x00;
*(videoMemoryLocation + (curx + offset1) * 2 + 1) = 0x00;
}
}
ypos -= numLines;
if (ypos < 0)
{
ypos = 0;
}
}
}

1014
kernel/runtime/dstubs.d Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/* GDC -- D front-end for GCC
Copyright (C) 2004 David Friedman
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Declarations are automatically created by the compiler. All
declarations start with "__builtin_". Refer to _builtins.def in the
GCC source for a list of functions. Not all of the functions are
supported.
In addition to built-in functions, the following types are defined.
$(TABLE
$(TR $(TD ___builtin_va_list) $(TD The target's va_list type ))
$(TR $(TD ___builtin_Clong ) $(TD The D equivalent of the target's
C "long" type ))
$(TR $(TD ___builtin_Culong ) $(TD The D equivalent of the target's
C "unsigned long" type ))
$(TR $(TD ___builtin_machine_int ) $(TD Signed word-sized integer ))
$(TR $(TD ___builtin_machine_uint) $(TD Unsigned word-sized integer ))
$(TR $(TD ___builtin_pointer_int ) $(TD Signed pointer-sized integer ))
$(TR $(TD ___builtin_pointer_uint) $(TD Unsigned pointer-sized integer ))
)
*/
module gcc.builtins;

View File

@@ -0,0 +1,28 @@
/*
* Placed into the Public Domain
* written by Walter Bright
* www.digitalmars.com
*/
void _d_invariant(Object o)
{
ClassInfo c;
//printf("__d_invariant(%p)\n", o);
// BUG: needs to be filename/line of caller, not library routine
assert(o !is null); // just do null check, not invariant check
c = o.classinfo;
do
{
if(c.classInvariant)
{
(*c.classInvariant)(o);
}
c = c.base;
} while(c)
}

1053
kernel/runtime/object.d Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/*
* Placed in public domain.
* Written by Hauke Duden and Walter Bright
*/
/* This is for use with variable argument lists with extern(D) linkage. */
module std.c.stdarg;
private import gcc.builtins;
alias __builtin_va_list va_list;
alias __builtin_va_end va_end;
alias __builtin_va_copy va_copy;
// The va_start and va_arg template functions are magically
// handled by the compiler.
template va_start(T)
{
void va_start(out va_list ap, inout T parmn)
{
}
}
template va_arg(T)
{
T va_arg(ref va_list _argptr)
{
return T.init;
}
}

View File

@@ -0,0 +1,264 @@
// written by Walter Bright
// www.digitalmars.com
// Placed into the public domain
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, May 2006
*/
/** These functions are built-in intrinsics to the compiler.
*
Intrinsic functions are functions built in to the compiler,
usually to take advantage of specific CPU features that
are inefficient to handle via external functions.
The compiler's optimizer and code generator are fully
integrated in with intrinsic functions, bringing to bear
their full power on them.
This can result in some surprising speedups.
* Macros:
* WIKI=Phobos/StdIntrinsic
*/
module std.intrinsic;
/**
* Scans the bits in v starting with bit 0, looking
* for the first set bit.
* Returns:
* The bit number of the first bit set.
* The return value is undefined if v is zero.
*/
version (GNU)
int bsf(uint v)
{
uint m = 1;
uint i;
for (i = 0; i < 32; i++,m<<=1) {
if (v&m)
return i;
}
return i; // supposed to be undefined
}
else
int bsf(uint v);
/**
* Scans the bits in v from the most significant bit
* to the least significant bit, looking
* for the first set bit.
* Returns:
* The bit number of the first bit set.
* The return value is undefined if v is zero.
* Example:
* ---
* import std.intrinsic;
*
* int main()
* {
* uint v;
* int x;
*
* v = 0x21;
* x = bsf(v);
* printf("bsf(x%x) = %d\n", v, x);
* x = bsr(v);
* printf("bsr(x%x) = %d\n", v, x);
* return 0;
* }
* ---
* Output:
* bsf(x21) = 0<br>
* bsr(x21) = 5
*/
version (GNU)
int bsr(uint v)
{
uint m = 0x80000000;
uint i;
for (i = 32; i ; i--,m>>>=1) {
if (v&m)
return i-1;
}
return i; // supposed to be undefined
}
else
int bsr(uint v);
/**
* Tests the bit.
*/
version (GNU)
int bt(uint *p, uint bitnum)
{
return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ;
}
else
int bt(uint *p, uint bitnum);
/**
* Tests and complements the bit.
*/
version (GNU)
int btc(uint *p, uint bitnum)
{
uint * q = p + (bitnum / (uint.sizeof*8));
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
int result = *q & mask;
*q ^= mask;
return result ? -1 : 0;
}
else
int btc(uint *p, uint bitnum);
/**
* Tests and resets (sets to 0) the bit.
*/
version (GNU)
int btr(uint *p, uint bitnum)
{
uint * q = p + (bitnum / (uint.sizeof*8));
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
int result = *q & mask;
*q &= ~mask;
return result ? -1 : 0;
}
else
int btr(uint *p, uint bitnum);
/**
* Tests and sets the bit.
* Params:
* p = a non-NULL pointer to an array of uints.
* index = a bit number, starting with bit 0 of p[0],
* and progressing. It addresses bits like the expression:
---
p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
---
* Returns:
* A non-zero value if the bit was set, and a zero
* if it was clear.
*
* Example:
* ---
import std.intrinsic;
int main()
{
uint array[2];
array[0] = 2;
array[1] = 0x100;
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
return 0;
}
* ---
* Output:
<pre>
btc(array, 35) = 0
array = [0]:x2, [1]:x108
btc(array, 35) = -1
array = [0]:x2, [1]:x100
bts(array, 35) = 0
array = [0]:x2, [1]:x108
btr(array, 35) = -1
array = [0]:x2, [1]:x100
bt(array, 1) = -1
array = [0]:x2, [1]:x100
</pre>
*/
version (GNU)
int bts(uint *p, uint bitnum)
{
uint * q = p + (bitnum / (uint.sizeof*8));
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
int result = *q & mask;
*q |= mask;
return result ? -1 : 0;
}
else
int bts(uint *p, uint bitnum);
/**
* Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
becomes byte 0.
*/
version (GNU)
uint bswap(uint v)
{
return ((v&0xFF)<<24)|((v&0xFF00)<<8)|((v&0xFF0000)>>>8)|((v&0xFF000000)>>>24);
}
else
uint bswap(uint v);
/**
* Reads I/O port at port_address.
*/
version (GNU)
ubyte inp(uint p) { return 0; }
else
ubyte inp(uint port_address);
/**
* ditto
*/
version (GNU)
ushort inpw(uint p) { return 0; }
else
ushort inpw(uint port_address);
/**
* ditto
*/
version (GNU)
uint inpl(uint p) { return 0; }
else
uint inpl(uint port_address);
/**
* Writes and returns value to I/O port at port_address.
*/
version (GNU)
ubyte outp(uint p, ubyte v) { return v; }
else
ubyte outp(uint port_address, ubyte value);
/**
* ditto
*/
version (GNU)
ushort outpw(uint p, ushort v) { return v; }
else
ushort outpw(uint port_address, ushort value);
/**
* ditto
*/
version (GNU)
uint outpl(uint p, uint v) { return v; }
else
uint outpl(uint port_address, uint value);

View File

@@ -0,0 +1,43 @@
/*
* Placed in public domain.
* Written by Hauke Duden and Walter Bright
*/
/* This is for use with variable argument lists with extern(D) linkage. */
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2004
*/
module std.stdarg;
version (GNU) {
// va_list might be a pointer, but assuming so is not portable.
private import gcc.builtins;
alias __builtin_va_list va_list;
// va_arg is handled magically by the compiler
} else {
alias void* va_list;
}
template va_arg(T)
{
T va_arg(inout va_list _argptr)
{
/*
T arg = *cast(T*)_argptr;
_argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1));
return arg;
*/
T t; return t;
}
}
private import std.c.stdarg;
/* The existence of std.stdarg.va_copy isn't standard. Prevent
conflicts by using '__'. */
alias std.c.stdarg.va_copy __va_copy;

View File

@@ -0,0 +1,96 @@
module std.typeinfo.ti_AC;
// Object[]
class TypeInfo_AC : TypeInfo
{
hash_t getHash(void *p)
{ Object[] s = *cast(Object[]*)p;
hash_t hash = 0;
foreach (Object o; s)
{
if (o)
hash += o.toHash();
}
return hash;
}
int equals(void *p1, void *p2)
{
Object[] s1 = *cast(Object[]*)p1;
Object[] s2 = *cast(Object[]*)p2;
if (s1.length == s2.length)
{
for (size_t u = 0; u < s1.length; u++)
{ Object o1 = s1[u];
Object o2 = s2[u];
// Do not pass null's to Object.opEquals()
if (o1 is o2 ||
(!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
continue;
return 0;
}
return 1;
}
return 0;
}
int compare(void *p1, void *p2)
{
Object[] s1 = *cast(Object[]*)p1;
Object[] s2 = *cast(Object[]*)p2;
ptrdiff_t c;
c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
if (c == 0)
{
for (size_t u = 0; u < s1.length; u++)
{ Object o1 = s1[u];
Object o2 = s2[u];
if (o1 is o2)
continue;
// Regard null references as always being "less than"
if (o1)
{
if (!o2)
{ c = 1;
break;
}
c = o1.opCmp(o2);
if (c)
break;
}
else
{ c = -1;
break;
}
}
}
if (c < 0)
c = -1;
else if (c > 0)
c = 1;
return c;
}
size_t tsize()
{
return (Object[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(Object);
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_Acdouble;
private import std.typeinfo.ti_cdouble;
// cdouble[]
class TypeInfo_Ar : TypeInfo
{
char[] toString() { return "cdouble[]"; }
hash_t getHash(void *p)
{ cdouble[] s = *cast(cdouble[]*)p;
size_t len = s.length;
cdouble *str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += (cast(uint *)str)[0];
hash += (cast(uint *)str)[1];
hash += (cast(uint *)str)[2];
hash += (cast(uint *)str)[3];
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
cdouble[] s1 = *cast(cdouble[]*)p1;
cdouble[] s2 = *cast(cdouble[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_r._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
cdouble[] s1 = *cast(cdouble[]*)p1;
cdouble[] s2 = *cast(cdouble[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_r._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (cdouble[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(cdouble);
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_Acfloat;
private import std.typeinfo.ti_cfloat;
// cfloat[]
class TypeInfo_Aq : TypeInfo
{
char[] toString() { return "cfloat[]"; }
hash_t getHash(void *p)
{ cfloat[] s = *cast(cfloat[]*)p;
size_t len = s.length;
cfloat *str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += (cast(uint *)str)[0];
hash += (cast(uint *)str)[1];
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
cfloat[] s1 = *cast(cfloat[]*)p1;
cfloat[] s2 = *cast(cfloat[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_q._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
cfloat[] s1 = *cast(cfloat[]*)p1;
cfloat[] s2 = *cast(cfloat[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_q._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (cfloat[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(cfloat);
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_Acreal;
private import std.typeinfo.ti_creal;
// creal[]
class TypeInfo_Ac : TypeInfo
{
char[] toString() { return "creal[]"; }
hash_t getHash(void *p)
{ creal[] s = *cast(creal[]*)p;
size_t len = s.length;
creal *str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += (cast(uint *)str)[0];
hash += (cast(uint *)str)[1];
hash += (cast(uint *)str)[2];
hash += (cast(uint *)str)[3];
hash += (cast(uint *)str)[4];
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
creal[] s1 = *cast(creal[]*)p1;
creal[] s2 = *cast(creal[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_c._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
creal[] s1 = *cast(creal[]*)p1;
creal[] s2 = *cast(creal[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_c._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (creal[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(creal);
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_Adouble;
private import std.typeinfo.ti_double;
// double[]
class TypeInfo_Ad : TypeInfo
{
char[] toString() { return "double[]"; }
hash_t getHash(void *p)
{ double[] s = *cast(double[]*)p;
size_t len = s.length;
auto str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += (cast(uint *)str)[0];
hash += (cast(uint *)str)[1];
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
double[] s1 = *cast(double[]*)p1;
double[] s2 = *cast(double[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_d._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
double[] s1 = *cast(double[]*)p1;
double[] s2 = *cast(double[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_d._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (double[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(double);
}
}
// idouble[]
class TypeInfo_Ap : TypeInfo_Ad
{
char[] toString() { return "idouble[]"; }
TypeInfo next()
{
return typeid(idouble);
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_Afloat;
private import std.typeinfo.ti_float;
// float[]
class TypeInfo_Af : TypeInfo
{
char[] toString() { return "float[]"; }
hash_t getHash(void *p)
{ float[] s = *cast(float[]*)p;
size_t len = s.length;
auto str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += *cast(uint *)str;
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
float[] s1 = *cast(float[]*)p1;
float[] s2 = *cast(float[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_f._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
float[] s1 = *cast(float[]*)p1;
float[] s2 = *cast(float[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_f._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (float[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(float);
}
}
// ifloat[]
class TypeInfo_Ao : TypeInfo_Af
{
char[] toString() { return "ifloat[]"; }
TypeInfo next()
{
return typeid(ifloat);
}
}

View File

@@ -0,0 +1,204 @@
module std.typeinfo.ti_Ag;
import kernel.runtime.util;
// byte[]
class TypeInfo_Ag : TypeInfo
{
char[] toString() { return "byte[]"; }
hash_t getHash(void *p)
{ byte[] s = *cast(byte[]*)p;
size_t len = s.length;
byte *str = s.ptr;
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 9;
hash += *cast(ubyte *)str;
return hash;
case 2:
hash *= 9;
hash += *cast(ushort *)str;
return hash;
case 3:
hash *= 9;
hash += (*cast(ushort *)str << 8) +
(cast(ubyte *)str)[2];
return hash;
default:
hash *= 9;
hash += *cast(uint *)str;
str += 4;
len -= 4;
break;
}
}
return hash;
}
int equals(void *p1, void *p2)
{
ubyte[] s1 = *cast(ubyte[]*)p1;
ubyte[] s2 = *cast(ubyte[]*)p2;
return s1.length == s2.length &&
memcmp(s1.ptr, s2.ptr, s1.length) == 0;
}
int compare(void *p1, void *p2)
{
byte[] s1 = *cast(byte[]*)p1;
byte[] s2 = *cast(byte[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int result = s1[u] - s2[u];
if (result)
return result;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (byte[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(byte);
}
}
// ubyte[]
class TypeInfo_Ah : TypeInfo_Ag
{
char[] toString() { return "ubyte[]"; }
int compare(void *p1, void *p2)
{
ubyte[] s1 = *cast(ubyte[]*)p1;
ubyte[] s2 = *cast(ubyte[]*)p2;
return memcmp(s1.ptr, s2.ptr, s1.length);
}
TypeInfo next()
{
return typeid(ubyte);
}
}
// void[]
class TypeInfo_Av : TypeInfo_Ah
{
char[] toString() { return "void[]"; }
TypeInfo next()
{
return typeid(void);
}
}
// bool[]
class TypeInfo_Ab : TypeInfo_Ah
{
char[] toString() { return "bool[]"; }
TypeInfo next()
{
return typeid(bool);
}
}
// char[]
class TypeInfo_Aa : TypeInfo_Ag
{
char[] toString() { return "char[]"; }
hash_t getHash(void *p)
{ char[] s = *cast(char[]*)p;
hash_t hash = 0;
version (all)
{
foreach (char c; s)
hash = hash * 11 + c;
}
else
{
size_t len = s.length;
char *str = s;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 9;
hash += *cast(ubyte *)str;
return hash;
case 2:
hash *= 9;
hash += *cast(ushort *)str;
return hash;
case 3:
hash *= 9;
hash += (*cast(ushort *)str << 8) +
(cast(ubyte *)str)[2];
return hash;
default:
hash *= 9;
hash += *cast(uint *)str;
str += 4;
len -= 4;
break;
}
}
}
return hash;
}
TypeInfo next()
{
return typeid(char);
}
}

View File

@@ -0,0 +1,119 @@
module std.typeinfo.ti_Aint;
import kernel.runtime.util;
// int[]
class TypeInfo_Ai : TypeInfo
{
char[] toString() { return "int[]"; }
hash_t getHash(void *p)
{ int[] s = *cast(int[]*)p;
auto len = s.length;
auto str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += *cast(uint *)str;
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
int[] s1 = *cast(int[]*)p1;
int[] s2 = *cast(int[]*)p2;
return s1.length == s2.length &&
memcmp(cast(ubyte*)s1.ptr, cast(ubyte*)s2.ptr, s1.length * int.sizeof) == 0;
}
int compare(void *p1, void *p2)
{
int[] s1 = *cast(int[]*)p1;
int[] s2 = *cast(int[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int result = s1[u] - s2[u];
if (result)
return result;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (int[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(int);
}
}
// uint[]
class TypeInfo_Ak : TypeInfo_Ai
{
char[] toString() { return "uint[]"; }
int compare(void *p1, void *p2)
{
uint[] s1 = *cast(uint[]*)p1;
uint[] s2 = *cast(uint[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int result = s1[u] - s2[u];
if (result)
return result;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
TypeInfo next()
{
return typeid(uint);
}
}
// dchar[]
class TypeInfo_Aw : TypeInfo_Ak
{
char[] toString() { return "dchar[]"; }
TypeInfo next()
{
return typeid(dchar);
}
}

View File

@@ -0,0 +1,111 @@
module std.typeinfo.ti_Along;
import kernel.runtime.util;
// long[]
class TypeInfo_Al : TypeInfo
{
char[] toString() { return "long[]"; }
hash_t getHash(void *p)
{ long[] s = *cast(long[]*)p;
size_t len = s.length;
auto str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += *cast(uint *)str + *(cast(uint *)str + 1);
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
long[] s1 = *cast(long[]*)p1;
long[] s2 = *cast(long[]*)p2;
return s1.length == s2.length &&
memcmp(cast(ubyte*)s1.ptr, cast(ubyte*)s2.ptr, s1.length * long.sizeof) == 0;
}
int compare(void *p1, void *p2)
{
long[] s1 = *cast(long[]*)p1;
long[] s2 = *cast(long[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
if (s1[u] < s2[u])
return -1;
else if (s1[u] > s2[u])
return 1;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (long[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(long);
}
}
// ulong[]
class TypeInfo_Am : TypeInfo_Al
{
char[] toString() { return "ulong[]"; }
int compare(void *p1, void *p2)
{
ulong[] s1 = *cast(ulong[]*)p1;
ulong[] s2 = *cast(ulong[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
if (s1[u] < s2[u])
return -1;
else if (s1[u] > s2[u])
return 1;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
TypeInfo next()
{
return typeid(ulong);
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_Areal;
private import std.typeinfo.ti_real;
// real[]
class TypeInfo_Ae : TypeInfo
{
char[] toString() { return "real[]"; }
hash_t getHash(void *p)
{ real[] s = *cast(real[]*)p;
size_t len = s.length;
auto str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += (cast(uint *)str)[0];
hash += (cast(uint *)str)[1];
hash += (cast(ushort *)str)[4];
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
real[] s1 = *cast(real[]*)p1;
real[] s2 = *cast(real[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_e._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
real[] s1 = *cast(real[]*)p1;
real[] s2 = *cast(real[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_e._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (real[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(real);
}
}
// ireal[]
class TypeInfo_Aj : TypeInfo_Ae
{
char[] toString() { return "ireal[]"; }
TypeInfo next()
{
return typeid(ireal);
}
}

View File

@@ -0,0 +1,134 @@
module std.typeinfo.ti_Ashort;
import kernel.runtime.util;
// short[]
class TypeInfo_As : TypeInfo
{
char[] toString() { return "short[]"; }
hash_t getHash(void *p)
{ short[] s = *cast(short[]*)p;
size_t len = s.length;
short *str = s.ptr;
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 9;
hash += *cast(ushort *)str;
return hash;
default:
hash *= 9;
hash += *cast(uint *)str;
str += 2;
len -= 2;
break;
}
}
return hash;
}
int equals(void *p1, void *p2)
{
short[] s1 = *cast(short[]*)p1;
short[] s2 = *cast(short[]*)p2;
return s1.length == s2.length &&
memcmp(cast(ubyte*)s1.ptr, cast(ubyte*)s2.ptr, s1.length * short.sizeof) == 0;
}
int compare(void *p1, void *p2)
{
short[] s1 = *cast(short[]*)p1;
short[] s2 = *cast(short[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int result = s1[u] - s2[u];
if (result)
return result;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (short[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(short);
}
}
// ushort[]
class TypeInfo_At : TypeInfo_As
{
char[] toString() { return "ushort[]"; }
int compare(void *p1, void *p2)
{
ushort[] s1 = *cast(ushort[]*)p1;
ushort[] s2 = *cast(ushort[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int result = s1[u] - s2[u];
if (result)
return result;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
TypeInfo next()
{
return typeid(ushort);
}
}
// wchar[]
class TypeInfo_Au : TypeInfo_At
{
char[] toString() { return "wchar[]"; }
TypeInfo next()
{
return typeid(wchar);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.typeinfo.ti_C;
// Object
class TypeInfo_C : TypeInfo
{
hash_t getHash(void *p)
{
Object o = *cast(Object*)p;
assert(o);
return o.toHash();
}
int equals(void *p1, void *p2)
{
Object o1 = *cast(Object*)p1;
Object o2 = *cast(Object*)p2;
return o1 == o2;
}
int compare(void *p1, void *p2)
{
Object o1 = *cast(Object*)p1;
Object o2 = *cast(Object*)p2;
int c = 0;
// Regard null references as always being "less than"
if (!(o1 is o2))
{
if (o1)
{ if (!o2)
c = 1;
else
c = o1.opCmp(o2);
}
else
c = -1;
}
return c;
}
size_t tsize()
{
return Object.sizeof;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,39 @@
// byte
module std.typeinfo.ti_byte;
class TypeInfo_g : TypeInfo
{
char[] toString() { return "byte"; }
hash_t getHash(void *p)
{
return *cast(byte *)p;
}
int equals(void *p1, void *p2)
{
return *cast(byte *)p1 == *cast(byte *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(byte *)p1 - *cast(byte *)p2;
}
size_t tsize()
{
return byte.sizeof;
}
void swap(void *p1, void *p2)
{
byte t;
t = *cast(byte *)p1;
*cast(byte *)p1 = *cast(byte *)p2;
*cast(byte *)p2 = t;
}
}

View File

@@ -0,0 +1,67 @@
// cdouble
module std.typeinfo.ti_cdouble;
class TypeInfo_r : TypeInfo
{
char[] toString() { return "cdouble"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
(cast(uint *)p)[2] + (cast(uint *)p)[3];
}
static int _equals(cdouble f1, cdouble f2)
{
return f1 == f2;
}
static int _compare(cdouble f1, cdouble f2)
{ int result;
if (f1.re < f2.re)
result = -1;
else if (f1.re > f2.re)
result = 1;
else if (f1.im < f2.im)
result = -1;
else if (f1.im > f2.im)
result = 1;
else
result = 0;
return result;
}
int equals(void *p1, void *p2)
{
return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
}
size_t tsize()
{
return cdouble.sizeof;
}
void swap(void *p1, void *p2)
{
cdouble t;
t = *cast(cdouble *)p1;
*cast(cdouble *)p1 = *cast(cdouble *)p2;
*cast(cdouble *)p2 = t;
}
void[] init()
{ static cdouble r;
return (cast(cdouble *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,66 @@
// cfloat
module std.typeinfo.ti_cfloat;
class TypeInfo_q : TypeInfo
{
char[] toString() { return "cfloat"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
}
static int _equals(cfloat f1, cfloat f2)
{
return f1 == f2;
}
static int _compare(cfloat f1, cfloat f2)
{ int result;
if (f1.re < f2.re)
result = -1;
else if (f1.re > f2.re)
result = 1;
else if (f1.im < f2.im)
result = -1;
else if (f1.im > f2.im)
result = 1;
else
result = 0;
return result;
}
int equals(void *p1, void *p2)
{
return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
}
size_t tsize()
{
return cfloat.sizeof;
}
void swap(void *p1, void *p2)
{
cfloat t;
t = *cast(cfloat *)p1;
*cast(cfloat *)p1 = *cast(cfloat *)p2;
*cast(cfloat *)p2 = t;
}
void[] init()
{ static cfloat r;
return (cast(cfloat *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,43 @@
module std.typeinfo.ti_char;
class TypeInfo_a : TypeInfo
{
char[] toString() { return "char"; }
hash_t getHash(void *p)
{
return *cast(char *)p;
}
int equals(void *p1, void *p2)
{
return *cast(char *)p1 == *cast(char *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(char *)p1 - *cast(char *)p2;
}
size_t tsize()
{
return char.sizeof;
}
void swap(void *p1, void *p2)
{
char t;
t = *cast(char *)p1;
*cast(char *)p1 = *cast(char *)p2;
*cast(char *)p2 = t;
}
void[] init()
{ static char c;
return (cast(char *)&c)[0 .. 1];
}
}

View File

@@ -0,0 +1,68 @@
// creal
module std.typeinfo.ti_creal;
class TypeInfo_c : TypeInfo
{
char[] toString() { return "creal"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
(cast(uint *)p)[2] + (cast(uint *)p)[3] +
(cast(uint *)p)[4];
}
static int _equals(creal f1, creal f2)
{
return f1 == f2;
}
static int _compare(creal f1, creal f2)
{ int result;
if (f1.re < f2.re)
result = -1;
else if (f1.re > f2.re)
result = 1;
else if (f1.im < f2.im)
result = -1;
else if (f1.im > f2.im)
result = 1;
else
result = 0;
return result;
}
int equals(void *p1, void *p2)
{
return _equals(*cast(creal *)p1, *cast(creal *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(creal *)p1, *cast(creal *)p2);
}
size_t tsize()
{
return creal.sizeof;
}
void swap(void *p1, void *p2)
{
creal t;
t = *cast(creal *)p1;
*cast(creal *)p1 = *cast(creal *)p2;
*cast(creal *)p2 = t;
}
void[] init()
{ static creal r;
return (cast(creal *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,45 @@
// dchar
module std.typeinfo.ti_dchar;
class TypeInfo_w : TypeInfo
{
char[] toString() { return "dchar"; }
hash_t getHash(void *p)
{
return *cast(dchar *)p;
}
int equals(void *p1, void *p2)
{
return *cast(dchar *)p1 == *cast(dchar *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(dchar *)p1 - *cast(dchar *)p2;
}
size_t tsize()
{
return dchar.sizeof;
}
void swap(void *p1, void *p2)
{
dchar t;
t = *cast(dchar *)p1;
*cast(dchar *)p1 = *cast(dchar *)p2;
*cast(dchar *)p2 = t;
}
void[] init()
{ static dchar c;
return (cast(dchar *)&c)[0 .. 1];
}
}

View File

@@ -0,0 +1,40 @@
// delegate
module std.typeinfo.ti_delegate;
alias void delegate(int) dg;
class TypeInfo_D : TypeInfo
{
hash_t getHash(void *p)
{ long l = *cast(long *)p;
return cast(uint)(l + (l >> 32));
}
int equals(void *p1, void *p2)
{
return *cast(dg *)p1 == *cast(dg *)p2;
}
size_t tsize()
{
return dg.sizeof;
}
void swap(void *p1, void *p2)
{
dg t;
t = *cast(dg *)p1;
*cast(dg *)p1 = *cast(dg *)p2;
*cast(dg *)p2 = t;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,68 @@
// double
module std.typeinfo.ti_double;
import kernel.runtime.util;
//private import std.math;
class TypeInfo_d : TypeInfo
{
char[] toString() { return "double"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
}
static int _equals(double f1, double f2)
{
return f1 == f2 ||
(isnan(f1) && isnan(f2));
}
static int _compare(double d1, double d2)
{
if (d1 !<>= d2) // if either are NaN
{
if (isnan(d1))
{ if (isnan(d2))
return 0;
return -1;
}
return 1;
}
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
}
int equals(void *p1, void *p2)
{
return _equals(*cast(double *)p1, *cast(double *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(double *)p1, *cast(double *)p2);
}
size_t tsize()
{
return double.sizeof;
}
void swap(void *p1, void *p2)
{
double t;
t = *cast(double *)p1;
*cast(double *)p1 = *cast(double *)p2;
*cast(double *)p2 = t;
}
void[] init()
{ static double r;
return (cast(double *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,68 @@
// float
module std.typeinfo.ti_float;
import kernel.runtime.util;
//private import std.math;
class TypeInfo_f : TypeInfo
{
char[] toString() { return "float"; }
hash_t getHash(void *p)
{
return *cast(uint *)p;
}
static int _equals(float f1, float f2)
{
return f1 == f2 ||
(isnan(f1) && isnan(f2));
}
static int _compare(float d1, float d2)
{
if (d1 !<>= d2) // if either are NaN
{
if (isnan(d1))
{ if (isnan(d2))
return 0;
return -1;
}
return 1;
}
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
}
int equals(void *p1, void *p2)
{
return _equals(*cast(float *)p1, *cast(float *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(float *)p1, *cast(float *)p2);
}
size_t tsize()
{
return float.sizeof;
}
void swap(void *p1, void *p2)
{
float t;
t = *cast(float *)p1;
*cast(float *)p1 = *cast(float *)p2;
*cast(float *)p2 = t;
}
void[] init()
{ static float r;
return (cast(float *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,12 @@
// idouble
module std.typeinfo.ti_idouble;
private import std.typeinfo.ti_double;
class TypeInfo_p : TypeInfo_d
{
char[] toString() { return "idouble"; }
}

View File

@@ -0,0 +1,12 @@
// ifloat
module std.typeinfo.ti_ifloat;
private import std.typeinfo.ti_float;
class TypeInfo_o : TypeInfo_f
{
char[] toString() { return "ifloat"; }
}

View File

@@ -0,0 +1,43 @@
// int
module std.typeinfo.ti_int;
class TypeInfo_i : TypeInfo
{
char[] toString() { return "int"; }
hash_t getHash(void *p)
{
return *cast(uint *)p;
}
int equals(void *p1, void *p2)
{
return *cast(uint *)p1 == *cast(uint *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(int*) p1 < *cast(int*) p2)
return -1;
else if (*cast(int*) p1 > *cast(int*) p2)
return 1;
return 0;
}
size_t tsize()
{
return int.sizeof;
}
void swap(void *p1, void *p2)
{
int t;
t = *cast(int *)p1;
*cast(int *)p1 = *cast(int *)p2;
*cast(int *)p2 = t;
}
}

View File

@@ -0,0 +1,12 @@
// ireal
module std.typeinfo.ti_ireal;
private import std.typeinfo.ti_real;
class TypeInfo_j : TypeInfo_e
{
char[] toString() { return "ireal"; }
}

View File

@@ -0,0 +1,43 @@
// long
module std.typeinfo.ti_long;
class TypeInfo_l : TypeInfo
{
char[] toString() { return "long"; }
hash_t getHash(void *p)
{
return *cast(uint *)p + (cast(uint *)p)[1];
}
int equals(void *p1, void *p2)
{
return *cast(long *)p1 == *cast(long *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(long *)p1 < *cast(long *)p2)
return -1;
else if (*cast(long *)p1 > *cast(long *)p2)
return 1;
return 0;
}
size_t tsize()
{
return long.sizeof;
}
void swap(void *p1, void *p2)
{
long t;
t = *cast(long *)p1;
*cast(long *)p1 = *cast(long *)p2;
*cast(long *)p2 = t;
}
}

View File

@@ -0,0 +1,47 @@
// pointer
module std.typeinfo.ti_ptr;
class TypeInfo_P : TypeInfo
{
hash_t getHash(void *p)
{
return cast(uint)*cast(void* *)p;
}
int equals(void *p1, void *p2)
{
return *cast(void* *)p1 == *cast(void* *)p2;
}
int compare(void *p1, void *p2)
{
auto c = *cast(void* *)p1 - *cast(void* *)p2;
if (c < 0)
return -1;
else if (c > 0)
return 1;
return 0;
}
size_t tsize()
{
return (void*).sizeof;
}
void swap(void *p1, void *p2)
{
void* t;
t = *cast(void* *)p1;
*cast(void* *)p1 = *cast(void* *)p2;
*cast(void* *)p2 = t;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,68 @@
// real
module std.typeinfo.ti_real;
import kernel.runtime.util;
//private import std.math;
class TypeInfo_e : TypeInfo
{
char[] toString() { return "real"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
}
static int _equals(real f1, real f2)
{
return f1 == f2 ||
(isnan(f1) && isnan(f2));
}
static int _compare(real d1, real d2)
{
if (d1 !<>= d2) // if either are NaN
{
if (isnan(d1))
{ if (isnan(d2))
return 0;
return -1;
}
return 1;
}
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
}
int equals(void *p1, void *p2)
{
return _equals(*cast(real *)p1, *cast(real *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(real *)p1, *cast(real *)p2);
}
size_t tsize()
{
return real.sizeof;
}
void swap(void *p1, void *p2)
{
real t;
t = *cast(real *)p1;
*cast(real *)p1 = *cast(real *)p2;
*cast(real *)p2 = t;
}
void[] init()
{ static real r;
return (cast(real *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,39 @@
// short
module std.typeinfo.ti_short;
class TypeInfo_s : TypeInfo
{
char[] toString() { return "short"; }
hash_t getHash(void *p)
{
return *cast(short *)p;
}
int equals(void *p1, void *p2)
{
return *cast(short *)p1 == *cast(short *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(short *)p1 - *cast(short *)p2;
}
size_t tsize()
{
return short.sizeof;
}
void swap(void *p1, void *p2)
{
short t;
t = *cast(short *)p1;
*cast(short *)p1 = *cast(short *)p2;
*cast(short *)p2 = t;
}
}

View File

@@ -0,0 +1,43 @@
// ubyte
module std.typeinfo.ti_ubyte;
class TypeInfo_h : TypeInfo
{
char[] toString() { return "ubyte"; }
hash_t getHash(void *p)
{
return *cast(ubyte *)p;
}
int equals(void *p1, void *p2)
{
return *cast(ubyte *)p1 == *cast(ubyte *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(ubyte *)p1 - *cast(ubyte *)p2;
}
size_t tsize()
{
return ubyte.sizeof;
}
void swap(void *p1, void *p2)
{
ubyte t;
t = *cast(ubyte *)p1;
*cast(ubyte *)p1 = *cast(ubyte *)p2;
*cast(ubyte *)p2 = t;
}
}
class TypeInfo_b : TypeInfo_h
{
char[] toString() { return "bool"; }
}

View File

@@ -0,0 +1,43 @@
// uint
module std.typeinfo.ti_uint;
class TypeInfo_k : TypeInfo
{
char[] toString() { return "uint"; }
hash_t getHash(void *p)
{
return *cast(uint *)p;
}
int equals(void *p1, void *p2)
{
return *cast(uint *)p1 == *cast(uint *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(uint*) p1 < *cast(uint*) p2)
return -1;
else if (*cast(uint*) p1 > *cast(uint*) p2)
return 1;
return 0;
}
size_t tsize()
{
return uint.sizeof;
}
void swap(void *p1, void *p2)
{
int t;
t = *cast(uint *)p1;
*cast(uint *)p1 = *cast(uint *)p2;
*cast(uint *)p2 = t;
}
}

View File

@@ -0,0 +1,43 @@
// ulong
module std.typeinfo.ti_ulong;
class TypeInfo_m : TypeInfo
{
char[] toString() { return "ulong"; }
hash_t getHash(void *p)
{
return *cast(uint *)p + (cast(uint *)p)[1];
}
int equals(void *p1, void *p2)
{
return *cast(ulong *)p1 == *cast(ulong *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(ulong *)p1 < *cast(ulong *)p2)
return -1;
else if (*cast(ulong *)p1 > *cast(ulong *)p2)
return 1;
return 0;
}
size_t tsize()
{
return ulong.sizeof;
}
void swap(void *p1, void *p2)
{
ulong t;
t = *cast(ulong *)p1;
*cast(ulong *)p1 = *cast(ulong *)p2;
*cast(ulong *)p2 = t;
}
}

View File

@@ -0,0 +1,39 @@
// ushort
module std.typeinfo.ti_ushort;
class TypeInfo_t : TypeInfo
{
char[] toString() { return "ushort"; }
hash_t getHash(void *p)
{
return *cast(ushort *)p;
}
int equals(void *p1, void *p2)
{
return *cast(ushort *)p1 == *cast(ushort *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(ushort *)p1 - *cast(ushort *)p2;
}
size_t tsize()
{
return ushort.sizeof;
}
void swap(void *p1, void *p2)
{
ushort t;
t = *cast(ushort *)p1;
*cast(ushort *)p1 = *cast(ushort *)p2;
*cast(ushort *)p2 = t;
}
}

View File

@@ -0,0 +1,44 @@
// void
module std.typeinfo.ti_void;
class TypeInfo_v : TypeInfo
{
char[] toString() { return "void"; }
hash_t getHash(void *p)
{
assert(0);
}
int equals(void *p1, void *p2)
{
return *cast(byte *)p1 == *cast(byte *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(byte *)p1 - *cast(byte *)p2;
}
size_t tsize()
{
return void.sizeof;
}
void swap(void *p1, void *p2)
{
byte t;
t = *cast(byte *)p1;
*cast(byte *)p1 = *cast(byte *)p2;
*cast(byte *)p2 = t;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,44 @@
module std.typeinfo.ti_wchar;
class TypeInfo_u : TypeInfo
{
char[] toString() { return "wchar"; }
hash_t getHash(void *p)
{
return *cast(wchar *)p;
}
int equals(void *p1, void *p2)
{
return *cast(wchar *)p1 == *cast(wchar *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(wchar *)p1 - *cast(wchar *)p2;
}
size_t tsize()
{
return wchar.sizeof;
}
void swap(void *p1, void *p2)
{
wchar t;
t = *cast(wchar *)p1;
*cast(wchar *)p1 = *cast(wchar *)p2;
*cast(wchar *)p2 = t;
}
void[] init()
{ static wchar c;
return (cast(wchar *)&c)[0 .. 1];
}
}

163
kernel/runtime/util.d Normal file
View File

@@ -0,0 +1,163 @@
// This module contains helpful functions found necessary by the runtime and gcc.
// contains: itoa, memcpy, memset, memmove, memcmp, strlen, isnan, toString
module kernel.runtime.util;
/**
This function converts an integer to a string, depending on the base passed in.
Params:
buf = The function will save the translated string into this character array.
base = The base of the integer value. If "d," it will be assumed to be decimal. If "x," the integer
will be hexadecimal.
d = The integer to translate.
Returns: The translated string in a character array.
*/
char[] itoa(char[] buf, char base, long d)
{
size_t p = buf.length - 1;
size_t startIdx = 0;
ulong ud = d;
bool negative = false;
int divisor = 10;
// If %d is specified and D is minus, put `-' in the head.
if(base == 'd' && d < 0)
{
negative = true;
ud = -d;
}
else if(base == 'x')
divisor = 16;
// Divide UD by DIVISOR until UD == 0.
do
{
int remainder = ud % divisor;
buf[p--] = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
}
while (ud /= divisor)
if(negative)
buf[p--] = '-';
return buf[p + 1 .. $];
}
/**
This function copies data from a source piece of memory to a destination piece of memory.
Params:
dest = A pointer to the piece of memory serving as the copy destination.
src = A pointer to the piece of memory serving as the copy source.
count = The number of bytes to copy form src to dest.
Returns: A void pointer to the start of the destination data (dest).
*/
extern(C) void* memcpy(void* dest, void* src, size_t count)
{
ubyte* d = cast(ubyte*)dest;
ubyte* s = cast(ubyte*)src;
for(size_t i = count; count; count--, d++, s++)
*d = *s;
return dest;
}
/**
Memcpy and memmove only really have differences at the user level, where they have slightly
different semantics. Here, they're pretty much the same.
*/
extern(C) void* memmove(void* dest, void* src, size_t count)
{
ubyte* d = cast(ubyte*)dest;
ubyte* s = cast(ubyte*)src;
for(size_t i = count; count; count--, d++, s++)
*d = *s;
return dest;
}
/**
Compare two blocks of memory.
Params:
a = Pointer to the first block.
b = Pointer to the second block.
n = The number of bytes to compare.
Returns:
0 if they are equal, < 0 if a is less than b, and > 0 if a is greater than b.
*/
long memcmp(void* a, void* b, size_t n)
{
ubyte* str_a = cast(ubyte*)a;
ubyte* str_b = cast(ubyte*)b;
for(size_t i = 0; i < n; i++)
{
if(*str_a != *str_b)
return *str_a - *str_b;
str_a++;
str_b++;
}
return 0;
}
/**
This function sets a particular piece of memory to a particular value.
Params:
addr = The address of the piece of memory you wish to write.
val = The value you wish to write to memory.
numBytes = The number of bytes you would like to write to memory.
*/
void memset(void *addr, ubyte val, uint numBytes){
ubyte *data = cast(ubyte*) addr;
for(int i = 0; i < numBytes; i++){
data[i] = val;
}
}
/**
This function determines the size of a passed-in string.
Params:
s = A pointer to the beginning of a character array, declaring a string.
Returns: The size of the string in size_t format.
*/
size_t strlen(char* s)
{
size_t i = 0;
for( ; *s != 0; i++, s++){}
return i;
}
/**
This function takes in a character pointer and returns a character array, or a string.
Params:
s = A pointer to the character(s) you wish to translate to a string.
Returns: A character array (string) containing the information.
*/
char[] toString(char* s)
{
return s[0 .. strlen(s)];
}
/**
This function checks to see if a floating point number is a NaN.
Params:
e = The value / piece of information you would like to check for number status.
Returns:
0 if it isn't a NaN, non-zero if it is.
*/
int isnan(real e)
{
ushort* pe = cast(ushort *)&e;
ulong* ps = cast(ulong *)&e;
return (pe[4] & 0x7FFF) == 0x7FFF &&
*ps & 0x7FFFFFFFFFFFFFFF;
}