mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
12
.clang-format
Normal file
12
.clang-format
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
BasedOnStyle: Google
|
||||
StatementMacros:
|
||||
- INITIALIZER
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
---
|
||||
Language: Proto
|
||||
...
|
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/o
|
||||
|
||||
*.tmp
|
||||
/.bochs.log
|
||||
/HTAGS
|
||||
/TAGS
|
||||
/bx_enh_dbg.ini
|
||||
/tool/emacs/*.elc
|
259
Makefile
Normal file
259
Makefile
Normal file
|
@ -0,0 +1,259 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Freestanding Hermetically-Sealed Monolithic Repository
|
||||
#
|
||||
# REQUIREMENTS
|
||||
#
|
||||
# You can run your programs on any operating system, but you have
|
||||
# to build them on Linux 2.6+ (or WSL) using GNU Make. A modern C
|
||||
# compiler that's statically-linked comes included as a courtesy.
|
||||
#
|
||||
# EXAMPLES
|
||||
#
|
||||
# # build and run everything
|
||||
# make -j8 -O
|
||||
# make -j8 -O MODE=dbg
|
||||
# make -j8 -O MODE=opt
|
||||
# make -j8 -O MODE=rel
|
||||
# make -j8 -O MODE=tiny
|
||||
#
|
||||
# # build individual target
|
||||
# make -j8 -O o//examples/hello.com
|
||||
# o//examples/hello.com
|
||||
#
|
||||
# # view source
|
||||
# less examples/hello.c
|
||||
#
|
||||
# # view binary
|
||||
# o//tool/viz/bing.com o//examples/hello.com |
|
||||
# o//tool/viz/fold.com
|
||||
#
|
||||
# # view transitive closure of legalese
|
||||
# o//tool/viz/bing.com -n o//examples/hello.com |
|
||||
# o//tool/viz/fold.com
|
||||
#
|
||||
# # basic debugging
|
||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
|
||||
# o/dbg/examples/crashreport.com
|
||||
# less examples/crashreport.c
|
||||
#
|
||||
# # extremely tiny binaries
|
||||
# make -j8 -O MODE=tiny \
|
||||
# LDFLAGS=-s \
|
||||
# CPPFLAGS=-DSUPPORT_VECTOR=0b00000001 \
|
||||
# o/tiny/examples/hello4.elf
|
||||
# ls -hal o/tiny/examples/hello4.elf
|
||||
# o/tiny/examples/hello4.elf
|
||||
#
|
||||
# TROUBLESHOOTING
|
||||
#
|
||||
# make -j8 -O SILENT=0 o//examples/hello.com
|
||||
# make o//examples/life.elf -pn |& less
|
||||
# etc.
|
||||
#
|
||||
# SEE ALSO
|
||||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = dash
|
||||
HOSTS ?= freebsd openbsd alpine
|
||||
|
||||
.SUFFIXES:
|
||||
.DELETE_ON_ERROR:
|
||||
.FEATURES: output-sync
|
||||
.PHONY: all o bins check test depend tags
|
||||
|
||||
all: o
|
||||
o: o/libc \
|
||||
o/$(MODE)/ape \
|
||||
o/$(MODE)/dsp \
|
||||
o/$(MODE)/net \
|
||||
o/$(MODE)/libc \
|
||||
o/$(MODE)/test \
|
||||
o/$(MODE)/tool \
|
||||
o/$(MODE)/examples \
|
||||
o/$(MODE)/third_party
|
||||
|
||||
PKGS =
|
||||
|
||||
include build/functions.mk #─┐
|
||||
include build/definitions.mk # ├──meta
|
||||
include build/config.mk # │
|
||||
include build/rules.mk # │
|
||||
include build/online.mk # │
|
||||
include libc/stubs/stubs.mk #─┘
|
||||
include libc/nexgen32e/nexgen32e.mk #─┐
|
||||
include libc/intrin/intrin.mk # │
|
||||
include libc/math/math.mk # ├──metal
|
||||
include libc/tinymath/tinymath.mk # │
|
||||
include third_party/compiler_rt/compiler_rt.mk # │
|
||||
include libc/bits/bits.mk # │
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/zlib/zlib.mk # │
|
||||
include libc/elf/elf.mk # │
|
||||
include ape/lib/apelib.mk # │
|
||||
include ape/ape.mk #─┘
|
||||
include libc/sysv/sysv.mk #─┐
|
||||
include libc/nt/nt.mk # ├──system
|
||||
include libc/conv/conv.mk # │
|
||||
include libc/fmt/fmt.mk # │
|
||||
include libc/rand/rand.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include libc/runtime/runtime.mk # ├──systems
|
||||
include libc/unicode/unicode.mk # │
|
||||
include third_party/dlmalloc/dlmalloc.mk # │
|
||||
include libc/mem/mem.mk # │
|
||||
include libc/zipos/zipos.mk # │
|
||||
include third_party/dtoa/dtoa.mk # │
|
||||
include libc/time/time.mk # │
|
||||
include libc/escape/escape.mk # │
|
||||
include libc/alg/alg.mk # │
|
||||
include libc/calls/hefty/hefty.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include third_party/f2c/f2c.mk # │
|
||||
include third_party/blas/blas.mk # │
|
||||
include net/net.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include dsp/core/core.mk # │
|
||||
include libc/x/x.mk # │
|
||||
include third_party/stb/stb.mk # │
|
||||
include dsp/scale/scale.mk # │
|
||||
include dsp/mpeg/mpeg.mk # │
|
||||
include dsp/dsp.mk # │
|
||||
include third_party/musl/musl.mk # │
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include libc/libc.mk #─┘
|
||||
include libc/sock/sock.mk #─┐
|
||||
include dsp/tty/tty.mk # ├──online
|
||||
include libc/dns/dns.mk # │
|
||||
include libc/crypto/crypto.mk # │
|
||||
include net/http/http.mk #─┘
|
||||
include third_party/linenoise/linenoise.mk
|
||||
include third_party/editline/editline.mk
|
||||
include third_party/duktape/duktape.mk
|
||||
include third_party/regex/regex.mk
|
||||
include third_party/avir/avir.mk
|
||||
include third_party/third_party.mk
|
||||
include libc/testlib/testlib.mk
|
||||
include libc/crt/crt.mk
|
||||
include tool/viz/lib/vizlib.mk
|
||||
include examples/examples.mk
|
||||
include third_party/lex/lex.mk
|
||||
include third_party/m4/m4.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include third_party/bzip2/bzip2.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include tool/build/build.mk
|
||||
include tool/debug/debug.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/hash/hash.mk
|
||||
include tool/net/net.mk
|
||||
include tool/viz/viz.mk
|
||||
include tool/cc/cc.mk
|
||||
include tool/tool.mk
|
||||
include test/libc/alg/test.mk
|
||||
include test/libc/tinymath/test.mk
|
||||
include test/libc/math/test.mk
|
||||
include test/libc/intrin/test.mk
|
||||
include test/libc/mem/test.mk
|
||||
include test/libc/nexgen32e/test.mk
|
||||
include test/libc/runtime/test.mk
|
||||
include test/libc/sock/test.mk
|
||||
include test/libc/bits/test.mk
|
||||
include test/libc/crypto/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/unicode/test.mk
|
||||
include test/libc/calls/test.mk
|
||||
include test/libc/x/test.mk
|
||||
include test/libc/xed/test.mk
|
||||
include test/libc/fmt/test.mk
|
||||
include test/libc/dns/test.mk
|
||||
include test/libc/rand/test.mk
|
||||
include test/libc/time/test.mk
|
||||
include test/libc/stdio/test.mk
|
||||
include test/libc/conv/test.mk
|
||||
include test/libc/test.mk
|
||||
include test/ape/lib/test.mk
|
||||
include test/ape/test.mk
|
||||
include test/net/http/test.mk
|
||||
include test/net/test.mk
|
||||
include test/tool/build/lib/test.mk
|
||||
include test/tool/build/test.mk
|
||||
include test/tool/viz/lib/test.mk
|
||||
include test/tool/viz/test.mk
|
||||
include test/tool/test.mk
|
||||
include test/test.mk
|
||||
include test/dsp/core/test.mk
|
||||
include test/dsp/scale/test.mk
|
||||
include test/dsp/tty/test.mk
|
||||
include test/dsp/test.mk
|
||||
|
||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||
SRCS = $(foreach x,$(PKGS),$($(x)_SRCS))
|
||||
HDRS = $(foreach x,$(PKGS),$($(x)_HDRS))
|
||||
BINS = $(foreach x,$(PKGS),$($(x)_BINS))
|
||||
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS))
|
||||
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||
|
||||
bins: $(BINS)
|
||||
check: $(CHECKS)
|
||||
test: $(TESTS)
|
||||
depend: o/$(MODE)/depend
|
||||
tags: TAGS HTAGS
|
||||
|
||||
o/$(MODE)/.x:
|
||||
@mkdir -p $(dir $@) && touch $@
|
||||
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS),$(file >>$@,$(x)))
|
||||
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS)
|
||||
@build/mkdeps -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
|
||||
|
||||
TAGS: o/$(MODE)/srcs.txt $(SRCS)
|
||||
@rm -f $@
|
||||
@ACTION=TAGS TARGET=$@ build/do $(TAGS) $(TAGSFLAGS) -L $< -o $@
|
||||
|
||||
HTAGS: o/$(MODE)/hdrs.txt $(HDRS)
|
||||
@rm -f $@
|
||||
@ACTION=TAGS TARGET=$@ build/do build/htags -L $< -o $@
|
||||
|
||||
loc:; find -name \*.h -or -name \*.c -or -name \*.S | \
|
||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | summy
|
||||
|
||||
# UNSPECIFIED PREREQUISITES TUTORIAL
|
||||
#
|
||||
# A build rule must exist for all files that make needs to consider in
|
||||
# order to build the requested goal. That includes input source files,
|
||||
# even if the rule is empty and does nothing. Otherwise, the .DEFAULT
|
||||
# rule gets triggered.
|
||||
#
|
||||
# This is a normal and neecssary behavior when source files get deleted.
|
||||
# The build reacts automatically to this happening, by simply deleting
|
||||
# and regenerating the dependency graph; so we can safely use wildcard.
|
||||
#
|
||||
# This is abnormal if it needs to keep doing that repeatedly. That can
|
||||
# only mean the build config is broken.
|
||||
#
|
||||
# Also note that a suboptimal in-between state may exist, where running
|
||||
# `make -pn` reveals rules being generated with the .DEFAULT target, but
|
||||
# never get executed since they're not members of the transitive closure
|
||||
# of `make all`. In that case the build config could be improved.
|
||||
%.mk:
|
||||
$(SRCS):
|
||||
$(HDRS):
|
||||
.DEFAULT:
|
||||
@echo >&2
|
||||
@echo NOTE: deleting o/$(MODE)/depend due to unspecified prerequisite: $@ >&2
|
||||
@echo >&2
|
||||
rm -f o/$(MODE)/depend
|
||||
|
||||
-include o/$(MODE)/depend
|
354
NOTICE
Normal file
354
NOTICE
Normal file
|
@ -0,0 +1,354 @@
|
|||
Cosmopolitan is Free Software licensed under the GPLv2. The build config
|
||||
**will embed all linked sources inside your binaries** so the compliance
|
||||
is easy while facilitating trust and transparency similar to JavaScript.
|
||||
You can audit your source filesystem using ZIP GUIs e.g. WIN10, InfoZip.
|
||||
|
||||
If you want to be able to distribute binaries in binary form only, then
|
||||
please send $1,000 to jtunney@gmail.com on PayPal for a license lasting
|
||||
1 year. Please be sure to provide your contact information, and details
|
||||
on whether or not the license is for an individual or a corporation. If
|
||||
you want your license to last 5 years, send $10,000 to the author above
|
||||
who is Justine Tunney <jtunney@gmail.com>. Reach out, for more details.
|
||||
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
51
README.md
Normal file
51
README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Cosmopolitan
|
||||
|
||||
Cosmopolitan builds run natively on most platforms without dependencies,
|
||||
because it implements the subset of the C library, compiler runtimes and
|
||||
system call interfaces that've achieved near universal consensus amongst
|
||||
all major platforms, e.g. Linux/BSD/XNU/NT. Containerization is achieved
|
||||
by having binaries also be ZIP files. Modern static stock GNU toolchains
|
||||
are provided in a hermetic mono repo for maximum historical determinism.
|
||||
|
||||
Here's how you can get started by printing cat videos inside a terminal:
|
||||
|
||||
make -j8 o//tool/viz/printvideo.com
|
||||
wget https://justine.storage.googleapis.com/cats.mpg
|
||||
o//tool/viz/printvideo.com cats.mpg
|
||||
unzip -vl o//tool/viz/printvideo.com
|
||||
|
||||
Cosmopolitan provides a native development environment similar to those
|
||||
currently being offered by RedHat, Google, Apple, Microsoft, etc. We're
|
||||
different in two ways: (1) we're not a platform therefore we don't have
|
||||
any commercial interest in making our tooling work better on one rather
|
||||
than another; and (2) we're only focused on catering towards interfaces
|
||||
all platforms agree upon. Goal is software that stands the test of time
|
||||
without the costs and restrictions cross-platform distribution entails.
|
||||
That makes Cosmopolitan an excellent fit for writing small CLI programs
|
||||
that do things like heavyweight numerical computations as a subprocess.
|
||||
|
||||
## Licensing
|
||||
|
||||
Cosmopolitan is Free Software licensed under the GPLv2. The build config
|
||||
**will embed all linked sources inside your binaries** so the compliance
|
||||
is easy while facilitating trust and transparency similar to JavaScript.
|
||||
You can audit your source filesystem using ZIP GUIs e.g. WIN10, InfoZip.
|
||||
|
||||
### Commercial Support
|
||||
|
||||
If you want to be able to distribute binaries in binary form only, then
|
||||
please send $1,000 to jtunney@gmail.com on PayPal for a license lasting
|
||||
1 year. Please be sure to provide your contact information, and details
|
||||
on whether or not the license is for an individual or a corporation. If
|
||||
you want your license to last 5 years, send $10,000 to the author above
|
||||
who is Justine Tunney <jtunney@gmail.com>. This README will be updated,
|
||||
if pricing and other details should change. Reach out for more details.
|
||||
|
||||
## Contributing
|
||||
|
||||
We'd love to accept your patches! Before we can take them, we have to
|
||||
jump through one legal hurdle. Please write an email to Justine Tunney
|
||||
<jtunney@gmail.com> saying you agree to give her copyright ownership to
|
||||
any changes you contribute to Cosmopolitan. We need to do that in order
|
||||
to dual license Cosmopolitan. Otherwise we can't tax corporations that
|
||||
don't want to share their code with the community.
|
660
ape/ape.lds
Normal file
660
ape/ape.lds
Normal file
|
@ -0,0 +1,660 @@
|
|||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § linker │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
Having an executable run natively on stock Windows / Mac / Linux / BSD
|
||||
entails two steps: (1) create a .com.dbg binary w/ Linux toolchain and
|
||||
then (2) unwrap the .com binary embedded within:
|
||||
|
||||
objcopy -SO binary input.com.dbg output.com
|
||||
|
||||
Both executables will work fine, but only the .com format is portable.
|
||||
|
||||
───BUILDING─────────────────────────────────────────────────────────────
|
||||
|
||||
LC_ALL=C ld -T ape/ape.lds ...
|
||||
|
||||
───RUNNING──────────────────────────────────────────────────────────────
|
||||
|
||||
./foo.com.dbg # works on host machine
|
||||
./foo.com # works on any os / arch
|
||||
qemu-system-x86_64 -s foo.com # works on any os / arch
|
||||
|
||||
───BACKGROUND───────────────────────────────────────────────────────────
|
||||
|
||||
The purpose of this software is to help native programs have the same
|
||||
level of consistency, in terms of user experience, that we enjoy with
|
||||
web applications. It's basically like MeteorJS, except primarily CLI,
|
||||
bootable, and more on the order of a few kilobytes than hundred megs.
|
||||
|
||||
Rather than Isomorphic JavaScript it's built using Isomorphic Binary,
|
||||
since it grants the fastest possible performance and can be trivially
|
||||
emulated in the browser. System resource utilization is also a few kb
|
||||
and GUIs are possible too since Cosmopolitan exports the Windows API,
|
||||
but we recommend doing it with a CLI web server instead and embedding
|
||||
files in your αcτµαlly pδrταblε εxεcµταblε as it's isomorphic to zip.
|
||||
|
||||
Isomorphic Binary principles state that most platform differences are
|
||||
just numbers, which we integrate easily into a unified business logic
|
||||
through the use of a sufficiently powerful linker. System numbers are
|
||||
otherwise known as ABIs and they're usually the most stable canonical
|
||||
interfaces that platforms provide. This is how we are able to support
|
||||
more versions of Linux than most Linux-only software, e.g. glibc FTMP
|
||||
|
||||
───DEBUGGING────────────────────────────────────────────────────────────
|
||||
|
||||
Can be done in a few ways:
|
||||
|
||||
gdb --tui foo.com.dbg
|
||||
gdb --tui foo.com -ex 'add-symbol-file foo.com.dbg 0x200000'
|
||||
gdb --tui -ex 'add-symbol-file foo.com.dbg 0x7c00' \
|
||||
-ex 'add-symbol-file foo.com.dbg 0x200000' \
|
||||
-ex -target remote localhost:1234'
|
||||
|
||||
───TRANSPARENCY─────────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is designed to facilitate maximum
|
||||
transparency to engender trust in this linker process.
|
||||
|
||||
The headers and symbols can be viewed using readelf or objdump:
|
||||
|
||||
readelf -Wa input.com.dbg # maximum transparency
|
||||
objdump -wxd input.com.dbg # maximum transparency
|
||||
|
||||
The disassembly can be viewed using objdump:
|
||||
|
||||
readelf -Wa input.com.dbg # maximum transparency
|
||||
objdump -d input.com.dbg # maximum transparency
|
||||
objdump -dj.text input.com.dbg # skip αpε boilerplate
|
||||
objdump -j.load -dMi8086 input.com.dbg # fixes real mode code
|
||||
|
||||
Some commands for controlling the verbosity of binaries:
|
||||
|
||||
strip -X input.com.dbg # remove ".L" symbols
|
||||
strip input.com.dbg # remove all symbols
|
||||
strip -S input.com.dbg # remove debug info only
|
||||
make CPPFLAGS=-DNDEBUG # remove asserts (prod)
|
||||
make CPPFLAGS=-DIM_FEELING_NAUGHTY # remove legal notices
|
||||
|
||||
The Makefile build is also configured to always produce a .map file
|
||||
when building each program, which provides further details.
|
||||
|
||||
───HACKABILITY──────────────────────────────────────────────────────────
|
||||
|
||||
Your linker and assemblies were designed provide extensibility through
|
||||
the use of link-time data structures we call "decentralized sections".
|
||||
They allow functions like _init() to be comprised of many small pieces
|
||||
defined throughout the codebase. The same applies to ELF / PE headers.
|
||||
|
||||
Extending that content usually entails writing a .S file. The process
|
||||
has more in common with JavaScript programming than contemporary C++
|
||||
development practices. It's the reason Cosmopolitan is able to build
|
||||
the fast tiny multiplatform autonomous binaries that indie developers
|
||||
love using a scalable development model that big businesses respect.
|
||||
|
||||
───SECURITY─────────────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is designed to be secure in untrustworthy
|
||||
computing environments. Code and data are separated. Data structures
|
||||
initialized at startup are automatically memory protected afterwards.
|
||||
Code intended for platforms you don't use is automatically unmapped
|
||||
too, minimizing any possible chance of impacting your system, while
|
||||
still being there in case you ever need it.
|
||||
|
||||
───CONFIDENTIALITY──────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is also designed to not leak confidential
|
||||
information by default. Details relating to the host build environment
|
||||
such as system/library versions, user ids, home folder locations, etc.
|
||||
are not taken into consideration at build time since it's hermetic. We
|
||||
can't make speak for debug information, which is why it's put in other
|
||||
files. We also provide the bing and fold programs for auditing binary.
|
||||
|
||||
───DESIGN─DETAILS───────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is a non-reflective (a.k.a. flat) binary
|
||||
format that includes ELF, PE, and Macho-O headers only to respect the
|
||||
initialization rituals that supported platforms require.
|
||||
|
||||
Binaries are sparse because Intel's six thousand page manual says:
|
||||
|
||||
“Always put code and data on separate pages. [...] If code is
|
||||
to be modified, try to do it all at once and make sure the
|
||||
code that performs the modifications and the code being
|
||||
modified are on separate 4KByte pages or on separate aligned
|
||||
1-KByte subpages. [...] If (hopefully read-only) data must
|
||||
occur on the same page as code, avoid placing it immediately
|
||||
after an indirect jump [...] or inserting an illegal opcode
|
||||
[...] after the indirect branch [which] may degrade perf in
|
||||
some circumstances.” ──Intel V.O §3.6.9
|
||||
|
||||
Support for linking dynamic shared objects is only implemented on
|
||||
Windows NT for the reasons described by Ulrich Drepper in his DSO
|
||||
tutorial. We've implemented this independently of the ld codebase
|
||||
because authentic GNU tooling is powerful enough to generalize to
|
||||
arbitrary formats without needing to add features to its codebase.
|
||||
|
||||
Cosmopolitan core library functions may be converted to the COFF or
|
||||
Mach-O object formats using objconv. That gives you some freedom to
|
||||
choose to use the Microsoft or Apple linker instead of this one. We
|
||||
otherwise can't use those formats, due to how they heavily restrict
|
||||
naming, which basically makes everything we're doing impossible. In
|
||||
the future an authentic GNU toolchain will be made available on the
|
||||
Windows and Apple platforms, using canonical formats and behaviors.
|
||||
Until then, we can build for those platforms using Linux or WSL. */
|
||||
|
||||
#ifdef __LINKER__
|
||||
#include "ape/macros.h"
|
||||
#include "ape/config.h"
|
||||
#include "libc/nt/pedef.h"
|
||||
#include "libc/zip.h"
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
/* Plans real memory solution at linktime. */
|
||||
MEMORY {
|
||||
PageZero : org = 0x0000000000000000, len = 0x0000000000001000
|
||||
RealBss : org = XLM_BASE_REAL, len = XLM_SIZE
|
||||
RealProgram : org = IMAGE_BASE_REAL, len = 0x0000000000010000 - IMAGE_BASE_REAL
|
||||
RealScratch : org = REAL_SCRATCH_AREA, len = REAL_STACK_FRAME - REAL_SCRATCH_AREA
|
||||
RealStack : org = REAL_STACK_FRAME, len = 0x0000000000010000
|
||||
EbdaMemory : org = 0x0000000000080000, len = 0x0000000000020000
|
||||
VideoMemory : org = 0x00000000000a0000, len = 0x0000000000020000
|
||||
Romz : org = 0x00000000000c0000, len = 0x0000000000030000
|
||||
BiosMemory : org = 0x00000000000f0000, len = 0x0000000000010000
|
||||
SmallCode : org = IMAGE_BASE_PHYSICAL, len = 0x0000000040000000 - IMAGE_BASE_PHYSICAL
|
||||
ZipData : org = 0x0000000040000000, len = 0x0000000040000000
|
||||
}
|
||||
|
||||
PHDRS {
|
||||
Head PT_LOAD FLAGS(5);
|
||||
Rom PT_LOAD FLAGS(5);
|
||||
Ram PT_LOAD FLAGS(6);
|
||||
stack PT_GNU_STACK FLAGS(6);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/*BEGIN: realmode addressability guarantee */
|
||||
/*BEGIN: xnu addressability guarantee */
|
||||
/*BEGIN: linux addressability guarantee */
|
||||
/*BEGIN: bsd addressability guarantee */
|
||||
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : {
|
||||
HIDDEN(_base = .);
|
||||
|
||||
/* Real Mode */
|
||||
KEEP(*(.head))
|
||||
. += 1;
|
||||
|
||||
/* Executable & Linkable Format */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
||||
KEEP(*(.elf.phdrs))
|
||||
HIDDEN(.Lape.phdrs.end = .);
|
||||
. += 1;
|
||||
|
||||
/* OpenBSD */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
||||
HIDDEN(.Lape.note = .);
|
||||
KEEP(*(.note.openbsd.ident))
|
||||
HIDDEN(.Lape.note.end = .);
|
||||
. += 1;
|
||||
|
||||
/* Portable Executable */
|
||||
KEEP(*(.pe.header))
|
||||
HIDDEN(.Lape.pe.sections = .);
|
||||
KEEP(*(.pe.sections))
|
||||
HIDDEN(.Lape.pe.sections_end = .);
|
||||
. += 1;
|
||||
|
||||
/* Mach-O */
|
||||
KEEP(*(.macho))
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
HIDDEN(.Lape.macho.end = .);
|
||||
. += 1;
|
||||
|
||||
KEEP(*(.ape.pad.head))
|
||||
. = ALIGN(4096); /* alignments only mandatory when impossible otherwise */
|
||||
HIDDEN(_ehead = .);
|
||||
} AT>SmallCode :Head
|
||||
|
||||
/*BEGIN: nt addressability guarantee */
|
||||
|
||||
.text . : {
|
||||
/* Code that needs to be addressable in Real Mode */
|
||||
*(.text.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
|
||||
*(.rodata.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.real.*)))
|
||||
HIDDEN(_ereal = .);
|
||||
|
||||
/*END: realmode addressability guarantee */
|
||||
|
||||
/* Normal Code */
|
||||
*(.start)
|
||||
KEEP(*(.initprologue))
|
||||
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||
KEEP(*(SORT_NONE(.init)))
|
||||
KEEP(*(.initepilogue))
|
||||
KEEP(*(.pltprologue))
|
||||
*(.plt)
|
||||
KEEP(*(.pltepilogue))
|
||||
KEEP(*(.pltgotprologue))
|
||||
*(.plt.got)
|
||||
KEEP(*(.pltgotepilogue))
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(SORT_BY_ALIGNMENT(.text.antiquity))
|
||||
*(SORT_BY_ALIGNMENT(.text.antiquity.*))
|
||||
KEEP(*(.textwindowsprologue))
|
||||
*(.text.windows)
|
||||
KEEP(*(.textwindowsepilogue))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot.*))
|
||||
KEEP(*(.keep.text))
|
||||
*(.text .stub .text.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.*)))
|
||||
|
||||
/* Won't support NX bit DRM for tiny executables */
|
||||
HIDDEN(.Lape.piro.align = ABSOLUTE(. > APE_PIRO_THRESHOLD ? 0x1000 : 8));
|
||||
|
||||
/* Code that musn't be mapped in production */
|
||||
KEEP(*(.ape.pad.test));
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__test_start = .);
|
||||
*(.test.unlikely)
|
||||
*(.test .test.*)
|
||||
|
||||
/* Privileged code invulnerable to magic */
|
||||
KEEP(*(.ape.pad.privileged));
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__privileged_start = .);
|
||||
HIDDEN(__test_end = .);
|
||||
. += 1;
|
||||
*(.privileged)
|
||||
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
KEEP(*(.ape.pad.rodata));
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
. += 1;
|
||||
|
||||
/* Nonspecific Read-Only Data */
|
||||
*(.rodata .rodata.*)
|
||||
. += 1;
|
||||
|
||||
/* Undefined Behavior Sanitizer Types */
|
||||
HIDDEN(__ubsan_types_start = .);
|
||||
*(.ubsan.types)
|
||||
HIDDEN(__ubsan_types_end = .);
|
||||
. += 1;
|
||||
|
||||
/* Undefined Behavior Sanitizer Data */
|
||||
HIDDEN(__ubsan_data_start = .);
|
||||
*(.ubsan.data)
|
||||
HIDDEN(__ubsan_data_end = .);
|
||||
|
||||
/* Unit Test & Fixture Registry */
|
||||
|
||||
/*BEGIN: Read only data that needn't be mapped after initialization */
|
||||
|
||||
/* Legal Notices */
|
||||
KEEP(*(.commentprologue))
|
||||
KEEP(*(.comment))
|
||||
KEEP(*(.commentepilogue))
|
||||
|
||||
/* Windows DLL Import Directory */
|
||||
KEEP(*(.idata.ro));
|
||||
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
||||
. += 1;
|
||||
|
||||
/* Encoded Data Structures w/ Linear Initialization Order */
|
||||
KEEP(*(.initroprologue))
|
||||
KEEP(*(SORT_BY_NAME(.initro.*)))
|
||||
KEEP(*(.initroepilogue))
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
HIDDEN(.Lape.data.align = ABSOLUTE(PAGESIZE));
|
||||
. = ALIGN(.Lape.data.align);
|
||||
HIDDEN(_etext = .);
|
||||
PROVIDE_HIDDEN(etext = .);
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
/*END: Read Only Data */
|
||||
} AT>SmallCode :Rom
|
||||
|
||||
.data . : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
KEEP(*(.dataprologue))
|
||||
*(.data .data.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
. += . > 0 ? 1 : 0;
|
||||
|
||||
KEEP(*(.gotprologue))
|
||||
*(.got)
|
||||
KEEP(*(.gotepilogue))
|
||||
|
||||
KEEP(*(.gotpltprologue))
|
||||
*(.got.plt)
|
||||
KEEP(*(.gotpltepilogue))
|
||||
|
||||
/*BEGIN: Post-Initialization Read-Only */
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__piro_start = .);
|
||||
|
||||
QUAD(IMAGE_BASE_VIRTUAL);
|
||||
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(SORT_NONE(.ctors)))
|
||||
KEEP(*(SORT_NONE(.init_array)))
|
||||
KEEP(*(SORT_NONE(.preinit_array)))
|
||||
PROVIDE_HIDDEN(__init_array_end = .);
|
||||
|
||||
. += 1;
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(SORT_NONE(.dtors)))
|
||||
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
PROVIDE_HIDDEN(__relo_end = .);
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
. = ALIGN(.Lape.data.align);
|
||||
HIDDEN(_edata = .);
|
||||
PROVIDE_HIDDEN(edata = .);
|
||||
} AT>SmallCode :Ram
|
||||
|
||||
.bss . : {
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||
*(.piro.bss)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
. += 1;
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__piro_end = .);
|
||||
/*END: Post-Initialization Read-Only */
|
||||
|
||||
/* Statically Allocated Empty Space */
|
||||
*(SORT_BY_ALIGNMENT(.bss))
|
||||
*(SORT_BY_ALIGNMENT(.bss.*))
|
||||
*(COMMON)
|
||||
|
||||
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
|
||||
|
||||
/* eXtreme Low Memory w/ Userspace Remapping */
|
||||
. = ALIGN(0x1000);
|
||||
*(.xlm)
|
||||
. = ALIGN(0x1000);
|
||||
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
} AT>SmallCode :Ram
|
||||
|
||||
/*END: nt addressability guarantee */
|
||||
/*END: bsd addressability guarantee */
|
||||
/*END: linux addressability guarantee */
|
||||
/*END: xnu addressability guarantee */
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.discard)
|
||||
*(.yoink)
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
PFSTUB8(.Lape.elf.entry, _start);
|
||||
PFSTUB8(.Lape.elf.phoff, RVA(ape.phdrs));
|
||||
PFSTUB8(.Lape.elf.shoff, 0);
|
||||
PFSTUB4(.Lape.elf.phnum, (.Lape.phdrs.end - ape.phdrs) / 56);
|
||||
PFSTUB4(.Lape.elf.shnum, 0);
|
||||
PFSTUB4(.Lape.elf.shstrndx, 0);
|
||||
SHSTUB2(.Lape.macho.dd.skip, RVA(ape.macho) / 8);
|
||||
SHSTUB2(.Lape.macho.dd.count, (.Lape.macho.end - ape.macho) / 8);
|
||||
PFSTUB4(.Lape.pe.offset, ape.pe - ape.mz);
|
||||
|
||||
HIDDEN(.Lape.pe.optsz = .Lape.pe.sections - (ape.pe + 24));
|
||||
HIDDEN(.Lape.pe.shnum = (.Lape.pe.sections_end - .Lape.pe.sections) / 40);
|
||||
HIDDEN(.Lidata.idtsize = idata.idtend - idata.idt);
|
||||
HIDDEN(.Lidata.iatsize = idata.iatend - idata.iat);
|
||||
|
||||
HIDDEN(.Lape.rom.offset = 0);
|
||||
HIDDEN(.Lape.rom.vaddr = ADDR(.head));
|
||||
HIDDEN(.Lape.rom.paddr = LOADADDR(.head));
|
||||
HIDDEN(.Lape.rom.filesz = LOADADDR(.data) - .Lape.rom.paddr);
|
||||
HIDDEN(.Lape.rom.memsz = ADDR(.data) - ADDR(.head));
|
||||
HIDDEN(.Lape.rom.align = 0x1000);
|
||||
HIDDEN(.Lape.rom.rva = RVA(.Lape.rom.vaddr));
|
||||
|
||||
HIDDEN(.Lape.ram.offset = .Lape.rom.offset + .Lape.rom.filesz);
|
||||
HIDDEN(.Lape.ram.vaddr = ADDR(.data));
|
||||
HIDDEN(.Lape.ram.paddr = LOADADDR(.data));
|
||||
HIDDEN(.Lape.ram.filesz = LOADADDR(.bss) - LOADADDR(.data));
|
||||
HIDDEN(.Lape.ram.memsz = ADDR(.bss) + SIZEOF(.bss) - .Lape.ram.vaddr);
|
||||
HIDDEN(.Lape.ram.align = 0x1000);
|
||||
HIDDEN(.Lape.ram.rva = RVA(.Lape.ram.vaddr));
|
||||
|
||||
HIDDEN(.Lape.note.offset = .Lape.rom.offset + (.Lape.note - .Lape.rom.vaddr));
|
||||
HIDDEN(.Lape.note.vaddr = .Lape.note);
|
||||
HIDDEN(.Lape.note.paddr = .Lape.rom.paddr + .Lape.note.offset);
|
||||
HIDDEN(.Lape.note.filesz = .Lape.note.end - .Lape.note);
|
||||
HIDDEN(.Lape.note.memsz = .Lape.note.filesz);
|
||||
HIDDEN(.Lape.note.align = __SIZEOF_POINTER__);
|
||||
|
||||
HIDDEN(.Lape.text.offset = .Lape.rom.offset + LOADADDR(.text) - .Lape.rom.paddr);
|
||||
HIDDEN(.Lape.text.paddr = LOADADDR(.text));
|
||||
HIDDEN(.Lape.text.vaddr = ADDR(.text));
|
||||
HIDDEN(.Lape.text.filesz = SIZEOF(.text));
|
||||
HIDDEN(.Lape.text.memsz = SIZEOF(.text));
|
||||
HIDDEN(.Lape.text.align = 4096);
|
||||
HIDDEN(.Lape.text.rva = RVA(.Lape.text.vaddr));
|
||||
|
||||
HIDDEN(.Lape.data.offset = .Lape.ram.offset + LOADADDR(.data) - .Lape.ram.paddr);
|
||||
HIDDEN(.Lape.data.paddr = LOADADDR(.data));
|
||||
HIDDEN(.Lape.data.vaddr = ADDR(.data));
|
||||
HIDDEN(.Lape.data.filesz = SIZEOF(.data));
|
||||
HIDDEN(.Lape.data.memsz = SIZEOF(.data));
|
||||
HIDDEN(.Lape.data.align = 0x1000);
|
||||
HIDDEN(.Lape.data.rva = RVA(.Lape.data.vaddr));
|
||||
|
||||
HIDDEN(.Lape.bss.offset = .Lape.ram.offset + LOADADDR(.bss) - .Lape.ram.paddr);
|
||||
HIDDEN(.Lape.bss.paddr = LOADADDR(.bss));
|
||||
HIDDEN(.Lape.bss.vaddr = ADDR(.bss));
|
||||
HIDDEN(.Lape.bss.filesz = 0);
|
||||
HIDDEN(.Lape.bss.memsz = SIZEOF(.bss));
|
||||
HIDDEN(.Lape.bss.align = .Lape.data.align);
|
||||
|
||||
/* Program Loader Auto-Tune */
|
||||
HIDDEN(v_ape_realsectors =
|
||||
MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 512)) / 512);
|
||||
HIDDEN(v_ape_highsectors =
|
||||
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);
|
||||
|
||||
/* Windows NT Auto-Subsystem Embedding */
|
||||
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui));
|
||||
|
||||
/* ZIP End of Central Directory header */
|
||||
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
|
||||
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
|
||||
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
|
||||
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
|
||||
ZIPCONST(v_zip_commentsize, _edata - __zip_end - kZipCdirHdrMinSize);
|
||||
|
||||
/* Generates deterministic ID for Mach-O. */
|
||||
#define PHI 0x9e3779b9925d4c17
|
||||
#define XOR(X,Y) ((X | Y) - (X & Y))
|
||||
#define XORSHIFT(X,Y) \
|
||||
X = XOR(X, (Y >> 12)); \
|
||||
X = XOR(X, (Y << 25)); \
|
||||
X = XOR(X, (Y >> 27))
|
||||
#define KMH(X,Y) \
|
||||
X = (X + (Y >> 000) & 0xFF) * PHI; \
|
||||
X = (X + (Y >> 010) & 0xFF) * PHI; \
|
||||
X = (X + (Y >> 020) & 0xFF) * PHI; \
|
||||
X = (X + (Y >> 030) & 0xFF) * PHI
|
||||
#define BOOP(X) \
|
||||
XORSHIFT(uuid1_, X); \
|
||||
KMH(uuid1_, X); \
|
||||
XORSHIFT(uuid2_, X); \
|
||||
KMH(uuid2_, X)
|
||||
|
||||
HIDDEN(uuid1_ = 88172645463325252);
|
||||
HIDDEN(uuid2_ = 88172645463325252);
|
||||
|
||||
BOOP(.Lape.bss.align);
|
||||
BOOP(.Lape.bss.filesz);
|
||||
BOOP(.Lape.bss.memsz);
|
||||
BOOP(.Lape.bss.offset);
|
||||
BOOP(.Lape.bss.paddr);
|
||||
BOOP(.Lape.data.align);
|
||||
BOOP(.Lape.data.filesz);
|
||||
BOOP(.Lape.data.memsz);
|
||||
BOOP(.Lape.data.offset);
|
||||
BOOP(.Lape.data.paddr);
|
||||
BOOP(.Lape.data.rva);
|
||||
BOOP(.Lape.data.vaddr);
|
||||
BOOP(.Lape.elf.entry);
|
||||
BOOP(.Lape.elf.phnum);
|
||||
BOOP(.Lape.elf.phoff);
|
||||
BOOP(.Lape.elf.shnum);
|
||||
BOOP(.Lape.elf.shoff);
|
||||
BOOP(.Lape.elf.shstrndx);
|
||||
BOOP(.Lape.macho.end);
|
||||
BOOP(.Lape.note);
|
||||
BOOP(.Lape.note.align);
|
||||
BOOP(.Lape.note.end);
|
||||
BOOP(.Lape.note.filesz);
|
||||
BOOP(.Lape.note.memsz);
|
||||
BOOP(.Lape.note.offset);
|
||||
BOOP(.Lape.note.paddr);
|
||||
BOOP(.Lape.note.vaddr);
|
||||
BOOP(.Lape.pe.offset);
|
||||
BOOP(.Lape.pe.optsz);
|
||||
BOOP(.Lape.pe.sections);
|
||||
BOOP(.Lape.pe.sections_end);
|
||||
BOOP(.Lape.pe.shnum);
|
||||
BOOP(.Lape.phdrs.end);
|
||||
BOOP(.Lape.ram.align);
|
||||
BOOP(.Lape.ram.filesz);
|
||||
BOOP(.Lape.ram.memsz);
|
||||
BOOP(.Lape.ram.offset);
|
||||
BOOP(.Lape.ram.paddr);
|
||||
BOOP(.Lape.ram.rva);
|
||||
BOOP(.Lape.ram.vaddr);
|
||||
BOOP(.Lape.rom.align);
|
||||
BOOP(.Lape.rom.filesz);
|
||||
BOOP(.Lape.rom.memsz);
|
||||
BOOP(.Lape.rom.offset);
|
||||
BOOP(.Lape.rom.paddr);
|
||||
BOOP(.Lape.rom.rva);
|
||||
BOOP(.Lape.rom.vaddr);
|
||||
BOOP(.Lape.text.align);
|
||||
BOOP(.Lape.text.filesz);
|
||||
BOOP(.Lape.text.memsz);
|
||||
BOOP(.Lape.text.offset);
|
||||
BOOP(.Lape.text.paddr);
|
||||
BOOP(.Lape.text.rva);
|
||||
BOOP(.Lape.text.vaddr);
|
||||
BOOP(ADDR(.bss));
|
||||
BOOP(WinMain);
|
||||
BOOP(_start);
|
||||
BOOP(ape.macho);
|
||||
BOOP(ape.mz);
|
||||
BOOP(ape.pe);
|
||||
BOOP(ape.phdrs);
|
||||
BOOP(v_ape_realsectors);
|
||||
|
||||
ASSERT(ape.mz == IMAGE_BASE_VIRTUAL, "linker panic");
|
||||
ASSERT((DEFINED(__init_bss_end) ? __init_bss_end : 0) % __SIZEOF_POINTER__ == 0,
|
||||
"__init_bss misalign");
|
||||
ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
|
||||
__SIZEOF_POINTER__ == 0),
|
||||
"__init_rodata misalign");
|
||||
|
||||
ASSERT((!DEFINED(ape.grub) ? 1 : RVA(ape.grub) < 8192),
|
||||
"grub stub needs to be in first 8kb of image");
|
||||
|
||||
ASSERT(DEFINED(_start) || DEFINED(_start16),
|
||||
"please link a _start() or _start16() entrypoint");
|
||||
|
||||
ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
|
||||
"ape won't support non-tiny real mode programs");
|
||||
|
||||
/* Let's not be like Knight Capital. */
|
||||
/* NOCROSSREFS_TO(.test .text) */
|
||||
|
||||
/* ASSERT(ape_sysv_start == .Lape.text.vaddr, */
|
||||
/* "ape_sysv_start() must be first in .text"); */
|
||||
|
||||
#endif /* __LINKER__ */
|
57
ape/ape.mk
Normal file
57
ape/ape.mk
Normal file
|
@ -0,0 +1,57 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# αcτµαlly pδrταblε εxεcµταblε
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This file defines the libraries, runtimes, and build rules needed to
|
||||
# create executables from your Linux workstation that'll run anywhere.
|
||||
# Loading this package will make certain systemic modifications to the
|
||||
# build like turning off the System V "Red Zone" optimization, because
|
||||
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
||||
|
||||
PKGS += APE
|
||||
|
||||
DEFAULT_COPTS += -mno-red-zone
|
||||
DEFAULT_LDFLAGS += -z max-page-size=0x1000
|
||||
|
||||
APELINK = ACTION=LINK.ape $(LINK) $(LINKARGS) $(OUTPUT_OPTION) && $(STRIP) -X $@ && $(GZ) $(ZFLAGS) -f $@.map
|
||||
|
||||
APE = $(APE_DEPS) \
|
||||
$(APE_OBJS) \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
APE_FILES := \
|
||||
$(wildcard ape/*.*)
|
||||
|
||||
APE_HDRS = \
|
||||
$(filter %.h,$(APE_FILES))
|
||||
|
||||
APE_SRCS = \
|
||||
$(filter %.S,$(APE_FILES))
|
||||
|
||||
APE_OBJS = \
|
||||
$(APE_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(APE_SRCS:%.S=o/$(MODE)/%.o)
|
||||
|
||||
APE_DEPS = \
|
||||
$(APE_LIB)
|
||||
|
||||
APE_CHECKS = \
|
||||
$(APE_HDRS:%=o/%.ok)
|
||||
|
||||
o/%.com: o/%.com.dbg
|
||||
@ACTION=OBJCOPY.ape TARGET=$@ build/do $(OBJCOPY) -SO binary $< $@
|
||||
|
||||
o/ape/idata.inc: ape/idata.h ape/relocations.h
|
||||
|
||||
$(APE_OBJS): $(BUILD_FILES) \
|
||||
ape/ape.mk
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE) \
|
||||
$(APE_CHECKS) \
|
||||
o/$(MODE)/ape/lib
|
137
ape/config.h
Normal file
137
ape/config.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef APE_CONFIG_H_
|
||||
#define APE_CONFIG_H_
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/**
|
||||
* @fileverview αcτµαlly pδrταblε εxεcµταblε configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Post-Initialization Read-Only Code Size Threshold.
|
||||
*
|
||||
* An executable needs to have at least this much code, before the
|
||||
* linker adds non-mandatory 4kb alignments. The benefit is better
|
||||
* memory protection. The tradeoff is sparser binaries.
|
||||
*/
|
||||
#ifndef APE_PIRO_THRESHOLD
|
||||
#ifdef CONFIG_DBG
|
||||
#define APE_PIRO_THRESHOLD 0x1000
|
||||
#else
|
||||
#define APE_PIRO_THRESHOLD 0x10000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PC Standard I/O Configuration.
|
||||
*/
|
||||
#ifndef METAL_STDIN
|
||||
#define METAL_STDIN COM1
|
||||
#endif
|
||||
#ifndef METAL_STDOUT
|
||||
#define METAL_STDOUT COM1
|
||||
#endif
|
||||
#ifndef METAL_STDERR
|
||||
#define METAL_STDERR COM2 /* will fallback to stdout if COM2 not present */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PC Display Configuration (MDA/CGA)
|
||||
* @see www.lammertbies.nl/comm/info/serial-uart.html
|
||||
* @see ape/lib/vidya.h
|
||||
*/
|
||||
#ifndef VIDYA_MODE
|
||||
#define VIDYA_MODE VIDYA_MODE_MDA
|
||||
#endif
|
||||
|
||||
/* FPU Control Word (x87) Exception Masks
|
||||
@see Intel Manual V1 §8.1.5
|
||||
|
||||
IM: Invalid Operation ───────────────┐
|
||||
DM: Denormal Operand ───────────────┐│
|
||||
ZM: Zero Divide ───────────────────┐││
|
||||
OM: Overflow ─────────────────────┐│││
|
||||
UM: Underflow ───────────────────┐││││
|
||||
PM: Precision ──────────────────┐│││││
|
||||
PC: Precision Control ────────┐ ││││││
|
||||
{float,∅,double,long double} │ ││││││
|
||||
RC: Rounding Control ───────┐ │ ││││││
|
||||
{even, →-∞, →+∞, →0} │┌┤ ││││││
|
||||
┌┤││ ││││││
|
||||
d││││rr││││││*/
|
||||
#define X87_NORMAL 0b000000000001101111111
|
||||
#define X87_DTOA 0b000000000001000000000
|
||||
#define X87_DTOA_MASK 0b000000000001100000000
|
||||
#ifndef X87_DEFAULT
|
||||
#define X87_DEFAULT X87_NORMAL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Serial Line Configuration (8250 UART 16550)
|
||||
* @see ape/lib/uart.h
|
||||
*/
|
||||
#ifndef UART_BAUD_RATE
|
||||
#define UART_BAUD_RATE 9600 /* bits per second ∈ [50,115200] */
|
||||
#endif
|
||||
#define UART_CONF_DLR (1843200 /*hz*/ / 16 /*wut*/ / (UART_BAUD_RATE))
|
||||
#ifndef UART_CONF_IIR
|
||||
/* ┌interrupt trigger level {1,4,8,14}
|
||||
│ ┌enable 64 byte fifo (UART 16750+)
|
||||
│ │ ┌select dma mode
|
||||
│ │ │┌clear transmit fifo
|
||||
│ │ ││┌clear receive fifo
|
||||
├┐│ │││┌enable fifos*/
|
||||
#define UART_CONF_IIR 0b00000000
|
||||
#endif
|
||||
#ifndef UART_CONF_LCR
|
||||
/* ┌dlab: flips configuration mode state
|
||||
│┌enable break signal
|
||||
││ ┌parity {none,odd,even,high,low}
|
||||
││ │ ┌extra stop bit
|
||||
││ │ │┌data word length (bits+5)
|
||||
││┌┴┐│├┐*/
|
||||
#define UART_CONF_LCR 0b01000011
|
||||
#endif
|
||||
|
||||
/**
|
||||
* eXtreme Low Memory.
|
||||
*/
|
||||
#define XLM(VAR) (XLM_BASE_REAL + XLM_##VAR)
|
||||
#define XLMV(VAR) (__xlm + XLM_##VAR)
|
||||
#define XLM_BASE_REAL 0x1000
|
||||
#define XLM_E820 0
|
||||
#define XLM_E820_SIZE 0x2000
|
||||
#define XLM_BIOS_DATA_AREA 0x2000
|
||||
#define XLM_BIOS_DATA_AREA_SIZE 256
|
||||
#define XLM_DRIVE_BASE_TABLE 0x2200 /* drive values are contiguous */
|
||||
#define XLM_DRIVE_BASE_TABLE_SIZE 11
|
||||
#define XLM_DRIVE_TYPE 0x220b
|
||||
#define XLM_DRIVE_TYPE_SIZE 1
|
||||
#define XLM_DRIVE_LAST_SECTOR 0x220c /* 1-based inclusive, e.g. 18 */
|
||||
#define XLM_DRIVE_LAST_SECTOR_SIZE 1
|
||||
#define XLM_DRIVE_LAST_CYLINDER 0x220d /* 0-based incl, e.g. 79 */
|
||||
#define XLM_DRIVE_LAST_CYLINDER_SIZE 2
|
||||
#define XLM_DRIVE_ATTACHED 0x220f
|
||||
#define XLM_DRIVE_ATTACHED_SIZE 1
|
||||
#define XLM_DRIVE_LAST_HEAD 0x2210 /* 0-based inclusive, e.g. 1 */
|
||||
#define XLM_DRIVE_LAST_HEAD_SIZE 1
|
||||
#define XLM_DRIVE 0x2211
|
||||
#define XLM_DRIVE_SIZE 1
|
||||
#define XLM_HAVEEXTMEMKB 0x2212
|
||||
#define XLM_HAVEEXTMEMKB_SIZE 4
|
||||
#define XLM_VIDEO_POSITION_FAR_POINTER 0x2216 /* video cursor far pointer */
|
||||
#define XLM_VIDEO_POSITION_FAR_POINTER_SIZE 4
|
||||
#define XLM_PAGE_TABLE_STACK_POINTER 0x2220
|
||||
#define XLM_PAGE_TABLE_STACK_POINTER_SIZE 8
|
||||
#define XLM_BADIDT 0x2230
|
||||
#define XLM_BADIDT_SIZE 6
|
||||
#define XLM_LOADSTATE 0x2240
|
||||
#define XLM_LOADSTATE_SIZE 4
|
||||
#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000)
|
||||
#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE)
|
||||
|
||||
#if !defined(__LINKER__) && !defined(__ASSEMBLER__)
|
||||
extern char __xlm[XLM_SIZE];
|
||||
#endif /* !defined(__LINKER__) && !defined(__ASSEMBLER__) */
|
||||
|
||||
#endif /* APE_CONFIG_H_ */
|
1279
ape/etc/bochsrc.dbg
Normal file
1279
ape/etc/bochsrc.dbg
Normal file
File diff suppressed because it is too large
Load diff
1294
ape/etc/bochsrc.ffs
Normal file
1294
ape/etc/bochsrc.ffs
Normal file
File diff suppressed because it is too large
Load diff
119
ape/idata.h
Normal file
119
ape/idata.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_IDATA_H_
|
||||
#define APE_IDATA_H_
|
||||
#ifdef __ASSEMBLER__
|
||||
#include "ape/relocations.h"
|
||||
/* clang-format off */
|
||||
|
||||
/ Links function from external DLL.
|
||||
/
|
||||
/ This embeds a function pointer in the binary. The NT Executive
|
||||
/ fills its value before control is handed off to the program.
|
||||
/
|
||||
/ @note only ELF toolchains are powerful enough to use this
|
||||
/ @see libc/nt/master.sh
|
||||
/ @see ape/ape.lds
|
||||
/ @see winimp
|
||||
.macro .imp dll:req fn:req actual hint
|
||||
.dll \dll
|
||||
.section .piro.data.sort.iat.2.\dll\().2.\fn,"aw",@progbits
|
||||
.type \fn,@object
|
||||
.align __SIZEOF_POINTER__
|
||||
\fn: .quad RVA((.L\dll\().\fn))
|
||||
.size \fn,.-\fn
|
||||
.globl \fn
|
||||
.hidden \fn
|
||||
.previous
|
||||
.section .idata.ro.ilt.\dll\().2.\fn,"a",@progbits
|
||||
.Lidata.ilt.\dll\().\fn:
|
||||
.quad RVA((.L\dll\().\fn))
|
||||
.type .Lidata.ilt..L\dll\().\fn,@object
|
||||
.size .Lidata.ilt..L\dll\().\fn,.-.Lidata.ilt.\dll\().\fn
|
||||
.previous
|
||||
.section .idata.ro.hnt.\dll\().2.\fn,"a",@progbits
|
||||
.L\dll\().\fn:
|
||||
.ifnb \hint # hint i.e. guess function ordinal
|
||||
.short \hint
|
||||
.else
|
||||
.short 0
|
||||
.endif
|
||||
.ifnb \actual # name
|
||||
.asciz "\actual"
|
||||
.else
|
||||
.asciz "\fn"
|
||||
.endif
|
||||
.align 2 # documented requirement
|
||||
/ .globl .L\dll\().\fn
|
||||
/ .hidden .L\dll\().\fn
|
||||
.type .L\dll\().\fn,@object
|
||||
.size .L\dll\().\fn,.-.L\dll\().\fn
|
||||
.previous
|
||||
.endm
|
||||
|
||||
/ Defines DLL import.
|
||||
/ @note this is an implementation detail of .imp
|
||||
.macro .dll name:req
|
||||
.section .idata.ro.idt.2.\name,"aG",\name,comdat
|
||||
.equ .Lidata.idt.\name,.
|
||||
.long RVA(idata.ilt.\name) # ImportLookupTable
|
||||
.long 0 # TimeDateStamp
|
||||
.long 0 # ForwarderChain
|
||||
.long RVA(.Lidata.str.\name) # DllNameRva
|
||||
.long RVA(idata.iat.\name) # ImportAddressTable
|
||||
.type .Lidata.idt.\name,@object
|
||||
.size .Lidata.idt.\name,.-.Lidata.idt.\name
|
||||
.previous
|
||||
.section .idata.ro.ilt.\name\().1,"aG",\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.ilt.\name,@object
|
||||
idata.ilt.\name:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .idata.ro.ilt.\name\().3,"aG",\name,comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.section .idata.ro.hnt.\name\().1,"aG",\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.hnt.\name,@object
|
||||
.equ idata.hnt.\name,.
|
||||
.previous
|
||||
.section .piro.data.sort.iat.2.\name\().1,"awG",\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.iat.\name,@object
|
||||
idata.iat.\name:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.data.sort.iat.2.\name\().3,"awG",\name,comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.pushsection .rodata.str1.1,"aSM",@progbits,1
|
||||
.Lidata.str.\name:
|
||||
.asciz "\name\().dll"
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
/* clang-format on */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_IDATA_H_ */
|
42
ape/lib/apelib.mk
Normal file
42
ape/lib/apelib.mk
Normal file
|
@ -0,0 +1,42 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += APE_LIB
|
||||
|
||||
APE_LIB_ARTIFACTS += APE_LIB_A
|
||||
APE_LIB = $(APE_LIB_A_DEPS) $(APE_LIB_A)
|
||||
APE_LIB_A = o/$(MODE)/ape/lib/apelib.a
|
||||
APE_LIB_A_FILES := $(wildcard ape/lib/*)
|
||||
APE_LIB_A_HDRS = $(filter %.h,$(APE_LIB_A_FILES))
|
||||
APE_LIB_A_SRCS_S = $(filter %.S,$(APE_LIB_A_FILES))
|
||||
APE_LIB_A_SRCS_C = $(filter %.c,$(APE_LIB_A_FILES))
|
||||
|
||||
APE_LIB_A_SRCS = \
|
||||
$(APE_LIB_A_SRCS_S) \
|
||||
$(APE_LIB_A_SRCS_C)
|
||||
|
||||
APE_LIB_A_OBJS = \
|
||||
$(APE_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(APE_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(APE_LIB_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
o/$(MODE)/NOTICE.zip.o
|
||||
|
||||
APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
APE_LIB_A_DIRECTDEPS = LIBC_STR LIBC_STUBS
|
||||
APE_LIB_A_DEPS = $(call uniq,$(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(APE_LIB_A): ape/lib/ $(APE_LIB_A).pkg $(APE_LIB_A_OBJS)
|
||||
$(APE_LIB_A).pkg: $(APE_LIB_A_OBJS) $(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
APE_LIB_LIBS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)))
|
||||
APE_LIB_SRCS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||
APE_LIB_HDRS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_HDRS))
|
||||
APE_LIB_BINS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_BINS))
|
||||
APE_LIB_CHECKS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_CHECKS))
|
||||
APE_LIB_OBJS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_OBJS))
|
||||
$(APE_LIB_OBJS): $(BUILD_FILES) libc/str/str.mk
|
||||
|
||||
.PHONY: o/$(MODE)/ape/lib
|
||||
o/$(MODE)/ape/lib: \
|
||||
$(APE_LIB_CHECKS) \
|
||||
$(APE_LIB_A)
|
59
ape/lib/apm.h
Normal file
59
ape/lib/apm.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § green energy │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_LIB_APM_H_
|
||||
#define APE_LIB_APM_H_
|
||||
|
||||
/**
|
||||
* @fileoverview Advanced Power Management.
|
||||
*
|
||||
* <p>APM is useful for exiting programs, without needing to ask the
|
||||
* human to flip a physical switch or pass QEMU's -no-reboot flag.
|
||||
*
|
||||
* <p><b>Implementation Detail:</b> Supporting ACPI would literally
|
||||
* require implementing a programming language.
|
||||
*
|
||||
* @see APM BIOS Interface Specification v1.2
|
||||
* @since IBM PC/AT
|
||||
*/
|
||||
|
||||
#define APM_SERVICE 0x15
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
void apmoff(void) noreturn;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* APE_LIB_APM_H_ */
|
36
ape/lib/bootdr.S
Normal file
36
ape/lib/bootdr.S
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
/ Resets personal computer.
|
||||
/
|
||||
/ @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
|
||||
/ @mode real
|
||||
/ @noreturn
|
||||
bootdr: push %bp
|
||||
mov %sp,%bp
|
||||
mov %di,%dx
|
||||
int $0x19
|
||||
ljmp $0xf000,$0xfff0
|
||||
.endfn bootdr,globl
|
38
ape/lib/e820map.S
Normal file
38
ape/lib/e820map.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl e820map
|
||||
.hidden e820map
|
||||
.type e820map,@object
|
||||
.size e820map,XLM_E820_SIZE
|
||||
e820map = ape.xlm + XLM_E820
|
||||
|
||||
.globl e820map_xlm
|
||||
.hidden e820map_xlm
|
||||
.type e820map_xlm,@object
|
||||
.size e820map_xlm,XLM_E820_SIZE
|
||||
e820map_xlm = XLM(E820)
|
59
ape/lib/flattenhighmemory.c
Normal file
59
ape/lib/flattenhighmemory.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/config.h"
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
|
||||
/**
|
||||
* Virtualizes physical memory.
|
||||
*
|
||||
* This function removes memory holes (discovered by e820() earlier) and
|
||||
* creates the illusion of flat contiguous memory for as much RAM as the
|
||||
* BIOS reports usable. Memory is safe to use and remap afterwards.
|
||||
*
|
||||
* @see ape/ape.S
|
||||
*/
|
||||
textreal void flattenhighmemory(struct SmapEntry *e820, struct PageTable *pml4t,
|
||||
uint64_t *ptsp) {
|
||||
struct SmapEntry *smap = e820;
|
||||
struct SmapEntry *hole = e820;
|
||||
uint64_t paddr = IMAGE_BASE_PHYSICAL;
|
||||
uint64_t vaddr = IMAGE_BASE_VIRTUAL;
|
||||
while (smap->size) {
|
||||
while (smap->size && smap->type != kMemoryUsable) smap++;
|
||||
paddr = roundup(max(paddr, smap->addr), PAGESIZE);
|
||||
while (paddr < rounddown(smap->addr + smap->size, PAGESIZE)) {
|
||||
while (hole->size &&
|
||||
(hole->type == kMemoryUsable || hole->addr + hole->size < paddr)) {
|
||||
hole++;
|
||||
}
|
||||
if (paddr >= hole->addr && paddr < hole->addr + hole->size) {
|
||||
paddr = roundup(hole->addr + hole->size, PAGESIZE);
|
||||
} else {
|
||||
uint64_t *entry = getpagetableentry(vaddr, 3, pml4t, ptsp);
|
||||
*entry = paddr | PAGE_V | PAGE_RW;
|
||||
vaddr += 0x1000;
|
||||
paddr += 0x1000;
|
||||
}
|
||||
}
|
||||
smap++;
|
||||
}
|
||||
}
|
32
ape/lib/g_pml4t.S
Normal file
32
ape/lib/g_pml4t.S
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl g_pml4t
|
||||
.hidden g_pml4t
|
||||
.type g_pml4t,@object
|
||||
.size g_pml4t,0x1000
|
||||
g_pml4t = REAL_STACK_FRAME - 0x1000
|
38
ape/lib/g_ptsp.S
Normal file
38
ape/lib/g_ptsp.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl g_ptsp
|
||||
.hidden g_ptsp
|
||||
.type g_ptsp,@object
|
||||
.size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE
|
||||
g_ptsp = ape.xlm + XLM_PAGE_TABLE_STACK_POINTER
|
||||
|
||||
.globl g_ptsp_xlm
|
||||
.hidden g_ptsp_xlm
|
||||
.type g_ptsp_xlm,@object
|
||||
.size g_ptsp_xlm,XLM_PAGE_TABLE_STACK_POINTER_SIZE
|
||||
g_ptsp_xlm = XLM(PAGE_TABLE_STACK_POINTER)
|
40
ape/lib/getpagetableentry.c
Normal file
40
ape/lib/getpagetableentry.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/assert.h"
|
||||
|
||||
textreal static uint64_t pushpagetable(uint64_t *ptsp) {
|
||||
return (*ptsp -= PAGESIZE) | PAGE_V | PAGE_RW;
|
||||
}
|
||||
|
||||
textreal uint64_t *getpagetableentry(uint64_t vaddr, unsigned depth,
|
||||
struct PageTable *pml4t, uint64_t *ptsp) {
|
||||
assert(depth <= 3);
|
||||
assert(*ptsp % PAGESIZE == 0);
|
||||
assert((intptr_t)pml4t % PAGESIZE == 0);
|
||||
unsigned char shift = 39;
|
||||
for (;;) {
|
||||
uint64_t *entry = &pml4t->p[(vaddr >> shift) & 511];
|
||||
if (!depth--) return entry;
|
||||
shift -= 9;
|
||||
if (!*entry) *entry = pushpagetable(ptsp);
|
||||
pml4t = (void *)(*entry & PAGE_TA);
|
||||
}
|
||||
}
|
46
ape/lib/kbiosdataarea.S
Normal file
46
ape/lib/kbiosdataarea.S
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl kBiosDataArea
|
||||
.hidden kBiosDataArea
|
||||
.type kBiosDataArea,@object
|
||||
.size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE
|
||||
kBiosDataArea = ape.xlm + XLM_BIOS_DATA_AREA
|
||||
|
||||
.globl kBiosDataAreaXlm
|
||||
.hidden kBiosDataAreaXlm
|
||||
.type kBiosDataAreaXlm,@object
|
||||
.size kBiosDataAreaXlm,XLM_BIOS_DATA_AREA_SIZE
|
||||
kBiosDataAreaXlm = XLM(BIOS_DATA_AREA)
|
||||
|
||||
.section .sort.real.init.2.kBiosDataArea,"ax",@progbits
|
||||
movpp %ds,%es # copy bios data to valid page
|
||||
mov $PC_BIOS_DATA_AREA,%si
|
||||
mov $XLM(BIOS_DATA_AREA),%di
|
||||
mov $XLM_BIOS_DATA_AREA_SIZE,%cx
|
||||
rep movsb
|
||||
.previous
|
27
ape/lib/pageunmap.c
Normal file
27
ape/lib/pageunmap.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/bits/bits.h"
|
||||
|
||||
textreal void pageunmap(uint64_t vaddr) {
|
||||
uint64_t *entry = getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm);
|
||||
*entry &= ~PAGE_V;
|
||||
invlpg(vaddr);
|
||||
}
|
239
ape/lib/pc.h
Normal file
239
ape/lib/pc.h
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_LIB_PC_H_
|
||||
#define APE_LIB_PC_H_
|
||||
|
||||
#define BOOTSIG 0xaa55 /* master boot record signature */
|
||||
#define PC_BIOS_DATA_AREA 0x400
|
||||
|
||||
#define kInterruptFlag (1u << 9)
|
||||
|
||||
/* FPU Status Word (x87)
|
||||
@see Intel Manual V1 §8.1.3
|
||||
IE: Invalid Operation ────────────────┐
|
||||
DE: Denormalized Operand ────────────┐│
|
||||
ZE: Zero Divide ────────────────────┐││
|
||||
OE: Overflow Flag ─────────────────┐│││
|
||||
UE: Underflow Flag ───────────────┐││││
|
||||
PE: Precision Flag ──────────────┐│││││
|
||||
SF: Stack Fault ────────────────┐││││││
|
||||
ES: Exception Summary Status ──┐│││││││
|
||||
C0-3: Condition Codes ──┬────┐ ││││││││
|
||||
Top of Stack Pointer ─────┐ │ ││││││││
|
||||
B: FPU Busy ───────────┐│ │ │ ││││││││
|
||||
││┌┴┐┌┼┐││││││││
|
||||
│↓│ │↓↓↓││││││││*/
|
||||
#define FPU_ZE 0b0000000000100000000000100
|
||||
#define FPU_C0 0b0000000000000000100000000
|
||||
#define FPU_C1 0b0000000000000001000000000
|
||||
#define FPU_C2 0b0000000000000010000000000
|
||||
#define FPU_C3 0b0000000000100000000000000
|
||||
|
||||
#define CR0_PE (1u << 0) /* protected mode enabled */
|
||||
#define CR0_MP (1u << 1) /* monitor coprocessor */
|
||||
#define CR0_EM (1u << 2) /* no x87 fpu present if set */
|
||||
#define CR0_TS (1u << 3) /* task switched x87 */
|
||||
#define CR0_ET (1u << 4) /* extension type 287 or 387 */
|
||||
#define CR0_NE (1u << 5) /* enable x87 error reporting */
|
||||
#define CR0_WP (1u << 16) /* write protect read-only pages @pl0 */
|
||||
#define CR0_AM (1u << 18) /* alignment mask */
|
||||
#define CR0_NW (1u << 29) /* global write-through cache disable */
|
||||
#define CR0_CD (1u << 30) /* global cache disable */
|
||||
#define CR0_PG (1u << 31) /* paging enabled */
|
||||
|
||||
#define CR4_VME (1u << 0) /* virtual 8086 mode extension */
|
||||
#define CR4_PVI (1u << 1) /* protected mode virtual interrupts */
|
||||
#define CR4_TSD (1u << 2) /* time stamp disable (rdtsc) */
|
||||
#define CR4_DE (1u << 3) /* debugging extensions */
|
||||
#define CR4_PSE (1u << 4) /* page size extension */
|
||||
#define CR4_PAE (1u << 5) /* physical address extension */
|
||||
#define CR4_MCE (1u << 6) /* machine check exception */
|
||||
#define CR4_PGE (1u << 7) /* page global enabled */
|
||||
#define CR4_OSFXSR (1u << 9) /* enable SSE and fxsave/fxrestor */
|
||||
#define CR4_OSXMMEXCPT (1u << 10) /* enable unmasked SSE exceptions */
|
||||
#define CR4_LA57 (1u << 12) /* enable level-5 paging */
|
||||
#define CR4_VMXE (1u << 13) /* enable VMX operations */
|
||||
#define CR4_SMXE (1u << 14) /* enable SMX operations */
|
||||
#define CR4_FSGSBASE (1u << 16) /* enable *FSBASE and *GSBASE instructions */
|
||||
#define CR4_PCIDE (1u << 17) /* enable process-context identifiers */
|
||||
#define CR4_OSXSAVE (1u << 18) /* enable XSAVE */
|
||||
|
||||
#define XCR0_X87 (1u << 0)
|
||||
#define XCR0_SSE (1u << 1)
|
||||
#define XCR0_AVX (1u << 2)
|
||||
#define XCR0_BNDREG (1u << 3)
|
||||
#define XCR0_BNDCSR (1u << 4)
|
||||
#define XCR0_OPMASK (1u << 5)
|
||||
#define XCR0_ZMM_HI256 (1u << 6)
|
||||
#define XCR0_HI16_ZMM (1u << 7)
|
||||
|
||||
#define EFER 0xC0000080 /* extended feature enable register */
|
||||
#define EFER_SCE (1u << 0) /* system call extensions */
|
||||
#define EFER_LME (1u << 8) /* long mode enable */
|
||||
#define EFER_LMA (1u << 10) /* long mode active */
|
||||
#define EFER_NXE (1u << 11) /* no-execute enable */
|
||||
|
||||
#define GDT_REAL_CODE 8
|
||||
#define GDT_REAL_DATA 16
|
||||
#define GDT_LEGACY_CODE 24
|
||||
#define GDT_LEGACY_DATA 32
|
||||
#define GDT_LONG_CODE 40
|
||||
#define GDT_LONG_DATA 48
|
||||
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||
#define PIC1_CMD PIC1
|
||||
#define PIC1_DATA (PIC1 + 1)
|
||||
#define PIC2_CMD PIC2
|
||||
#define PIC2_DATA (PIC2 + 1)
|
||||
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||
|
||||
/* Long Mode Paging
|
||||
@see Intel Manual V.3A §4.1 §4.5
|
||||
IsValid (ignored on CR3) V┐
|
||||
┌Block Instr. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
||||
│ Permit User-Mode Access - u┐││
|
||||
│ Page-level Write-Through - PWT┐│││
|
||||
│ Page-level Cache Disable - PCD┐││││
|
||||
│ Set if has been read - Accessed┐│││││
|
||||
│ Set if has been written - Dirty┐││││││
|
||||
│ IsPage (if PDPTE/PDE) or PAT (if PT)┐│││││││
|
||||
│ (If this maps 2MB/1GB page and CR4.PGE) Global┐││││││││
|
||||
│ (If IsPage 2MB/1GB, see Intel V3A § 11.12) PAT │││││││││
|
||||
│ │ │││││││││
|
||||
│ ┌────────────────────────────────────┤ │││││││││
|
||||
│ Must Be 0┐│ Next Page Table Address (!IsPage) │ │││││││││
|
||||
│ │├────────────────────────────────────┤ │││││││││
|
||||
│ ││ Physical Address 4KB │ │││││││││
|
||||
│┌───┐┌─────┐│├───────────────────────────┐ │ign│││││││││
|
||||
││PKE││ ign │││ Physical Address 2MB │ │┌┴┐│││││││││
|
||||
││ ││ ││├──────────────────┐ │ ││ ││││││││││
|
||||
││ ││ │││ Phys. Addr. 1GB │ │ ││ ││││││││││
|
||||
││ ││ │││ │ │ ││ ││││││││││
|
||||
0b00000000000011111111111111111111111111111111111111000000000000
|
||||
6666555555555544444444443333333333222222222211111111110000000000
|
||||
3210987654321098765432109876543210987654321098765432109876543210*/
|
||||
#define PAGE_V /* */ 0b000000001
|
||||
#define PAGE_RW /* */ 0b000000010
|
||||
#define PAGE_U /* */ 0b000000100
|
||||
#define PAGE_2MB /* */ 0b110000000
|
||||
#define PAGE_1GB /* */ 0b110000000
|
||||
#define PAGE_TA 0b011111111111111111111111111111111111111000000000000
|
||||
#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
#include "ape/config.h"
|
||||
|
||||
struct thatispacked GlobalDescriptorTable {
|
||||
uint16_t size;
|
||||
uint64_t *entries;
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory hole map.
|
||||
* @see wiki.osdev.org/Detecting_Memory_(x86)
|
||||
* @since 2002
|
||||
*/
|
||||
struct SmapEntry {
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
enum {
|
||||
kMemoryUsable = 1,
|
||||
kMemoryUnusable = 2,
|
||||
kMemoryAcpiReclaimable = 3,
|
||||
kMemoryAcpiNvs = 4,
|
||||
kMemoryBad = 5
|
||||
} type;
|
||||
uint32_t __acpi3; /* is abstracted */
|
||||
};
|
||||
|
||||
struct IdtDescriptor {
|
||||
uint16_t offset_1; /* offset bits 0..15 */
|
||||
uint16_t selector; /* a code segment selector in GDT or LDT */
|
||||
uint8_t ist; /* bits 0..2 hold stack table offset, rest are zero */
|
||||
uint8_t type_attr; /* type and attributes */
|
||||
uint16_t offset_2; /* offset bits 16..31 */
|
||||
uint32_t offset_3; /* offset bits 32..63 */
|
||||
uint32_t zero; /* reserved */
|
||||
};
|
||||
|
||||
struct thatispacked PageTable {
|
||||
uint64_t p[512];
|
||||
} aligned(PAGESIZE);
|
||||
|
||||
extern struct PageTable g_pml4t;
|
||||
extern struct GlobalDescriptorTable gdt;
|
||||
|
||||
extern const unsigned char kBiosDataArea[256];
|
||||
extern const unsigned char kBiosDataAreaXlm[256];
|
||||
|
||||
extern struct SmapEntry e820map[XLM_E820_SIZE / sizeof(struct SmapEntry)];
|
||||
extern struct SmapEntry e820map_xlm[XLM_E820_SIZE / sizeof(struct SmapEntry)];
|
||||
|
||||
extern uint64_t g_ptsp;
|
||||
extern uint64_t g_ptsp_xlm;
|
||||
|
||||
void bootdr(char drive) noreturn;
|
||||
|
||||
void smapsort(struct SmapEntry *);
|
||||
uint64_t *getpagetableentry(uint64_t, unsigned, struct PageTable *, uint64_t *);
|
||||
void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *);
|
||||
void pageunmap(uint64_t);
|
||||
|
||||
forceinline unsigned long eflags(void) {
|
||||
unsigned long res;
|
||||
asm("pushf\n\t"
|
||||
"pop\t%0"
|
||||
: "=rm"(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
forceinline unsigned char inb(unsigned short port) {
|
||||
unsigned char al;
|
||||
asm volatile("inb\t%1,%0" : "=a"(al) : "dN"(port));
|
||||
return al;
|
||||
}
|
||||
|
||||
forceinline void outb(unsigned short port, unsigned char byte) {
|
||||
asm volatile("outb\t%0,%1"
|
||||
: /* no inputs */
|
||||
: "a"(byte), "dN"(port));
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* APE_LIB_PC_H_ */
|
140
ape/lib/pic.c
Normal file
140
ape/lib/pic.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
|
||||
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||
|
||||
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||
|
||||
static inline void io_wait(void) {
|
||||
/* Magic technique from Linux, according to:
|
||||
* wiki.osdev.org/index.php?title=Inline_Assembly/Examples&oldid=23541
|
||||
*/
|
||||
outb(0x80, 0);
|
||||
}
|
||||
|
||||
void PIC_sendEOI(unsigned char irq) {
|
||||
if (irq >= 8) outb(PIC2_CMD, PIC_EOI);
|
||||
outb(PIC1_CMD, PIC_EOI);
|
||||
}
|
||||
|
||||
bool AreInterruptsEnabled() {
|
||||
return (eflags() & kInterruptFlag) == kInterruptFlag;
|
||||
}
|
||||
|
||||
nodiscard forceinline unsigned long irqdisable(void) {
|
||||
unsigned long eflags;
|
||||
asm("pushf\n\t"
|
||||
"cli\n\t"
|
||||
"pop\t%0"
|
||||
: "=r"(eflags)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
return eflags;
|
||||
}
|
||||
|
||||
forceinline void irqrestore(unsigned long eflags) {
|
||||
asm volatile(
|
||||
"push\t%0\n\t"
|
||||
"popf"
|
||||
: /* no outputs */
|
||||
: "rm"(eflags)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param offset1 is vector offset for master PIC
|
||||
* vectors on the master become offset1..offset1+7
|
||||
* @param offset2 is same for slave PIC: offset2..offset2+7
|
||||
**/
|
||||
void PIC_remap(int offset1, int offset2) {
|
||||
unsigned char a1, a2;
|
||||
a1 = inb(PIC1_DATA); // save masks
|
||||
a2 = inb(PIC2_DATA);
|
||||
outb(PIC1_CMD,
|
||||
ICW1_INIT |
|
||||
ICW1_ICW4); // starts the initialization sequence (in cascade mode)
|
||||
io_wait();
|
||||
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset
|
||||
io_wait();
|
||||
outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset
|
||||
io_wait();
|
||||
outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at
|
||||
// IRQ2 (0000 0100)
|
||||
io_wait();
|
||||
outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
|
||||
io_wait();
|
||||
outb(PIC1_DATA, ICW4_8086);
|
||||
io_wait();
|
||||
outb(PIC2_DATA, ICW4_8086);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, a1); // restore saved masks.
|
||||
outb(PIC2_DATA, a2);
|
||||
}
|
||||
|
||||
void IRQ_set_mask(unsigned char IRQline) {
|
||||
uint16_t port;
|
||||
uint8_t value;
|
||||
if (IRQline < 8) {
|
||||
port = PIC1_DATA;
|
||||
} else {
|
||||
port = PIC2_DATA;
|
||||
IRQline -= 8;
|
||||
}
|
||||
value = inb(port) | (1 << IRQline);
|
||||
outb(port, value);
|
||||
}
|
||||
|
||||
void IRQ_clear_mask(unsigned char IRQline) {
|
||||
uint16_t port;
|
||||
uint8_t value;
|
||||
if (IRQline < 8) {
|
||||
port = PIC1_DATA;
|
||||
} else {
|
||||
port = PIC2_DATA;
|
||||
IRQline -= 8;
|
||||
}
|
||||
value = inb(port) & ~(1 << IRQline);
|
||||
outb(port, value);
|
||||
}
|
||||
|
||||
static uint16_t __pic_get_irq_reg(int ocw3) {
|
||||
/* OCW3 to PIC CMD to get the register values. PIC2 is chained, and
|
||||
* represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */
|
||||
outb(PIC1_CMD, ocw3);
|
||||
outb(PIC2_CMD, ocw3);
|
||||
return (inb(PIC2_CMD) << 8) | inb(PIC1_CMD);
|
||||
}
|
||||
|
||||
/* Returns the combined value of the cascaded PICs irq request register */
|
||||
uint16_t pic_get_irr(void) { return __pic_get_irq_reg(PIC_READ_IRR); }
|
||||
|
||||
/* Returns the combined value of the cascaded PICs in-service register */
|
||||
uint16_t pic_get_isr(void) { return __pic_get_irq_reg(PIC_READ_ISR); }
|
47
ape/lib/smapsort.c
Normal file
47
ape/lib/smapsort.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
|
||||
textreal static unsigned smapcount(const struct SmapEntry *se) {
|
||||
unsigned i = 0;
|
||||
while (se[i].size) ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
textreal static void smapsorter(size_t n, struct SmapEntry a[n]) {
|
||||
struct SmapEntry t;
|
||||
unsigned i, j;
|
||||
for (i = 1; i < n; ++i) {
|
||||
j = i;
|
||||
t = a[i];
|
||||
while (j > 0 && (intptr_t)t.addr - (intptr_t)a[j - 1].addr) {
|
||||
a[j] = a[j - 1];
|
||||
--j;
|
||||
}
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts BIOS e820 memory map.
|
||||
*/
|
||||
textreal void smapsort(struct SmapEntry *smap) {
|
||||
smapsorter(smapcount(smap), smap);
|
||||
}
|
281
ape/macros.h
Normal file
281
ape/macros.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § macros │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_MACROS_H_
|
||||
#define APE_MACROS_H_
|
||||
#include "libc/macros.h"
|
||||
#ifdef __ASSEMBLER__
|
||||
/* clang-format off */
|
||||
|
||||
/**
|
||||
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
|
||||
*/
|
||||
|
||||
/ Calls near (i.e. pc+pcrel<64kB) FUNCTION.
|
||||
/ @mode long,legacy,real
|
||||
/ @cost 9 bytes overhead
|
||||
.macro rlcall function:req
|
||||
.byte 0x50 # push %[er]ax
|
||||
.byte 0xb8,0,0 # mov $?,%[e]ax
|
||||
jmp 911f
|
||||
.byte 0x58 # pop %[er]ax
|
||||
.byte 0xe8 # call Jvds
|
||||
.long \function\()-.-4
|
||||
jmp 912f
|
||||
911: .byte 0x58 # pop %[er]ax
|
||||
.byte 0xe8 # call Jvds
|
||||
.short \function\()-.-2
|
||||
912:
|
||||
.endm
|
||||
|
||||
/ Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
|
||||
/ @mode long,legacy,real
|
||||
.macro movesdi address:req
|
||||
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||
.short \address>>4
|
||||
.byte 0x8e,0xc7 # mov %di,%es
|
||||
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||
.short \address&0xf
|
||||
jmp 297f
|
||||
.byte 0xbf # mov $0x????xxxx,%edi
|
||||
.long \address
|
||||
297:
|
||||
.endm
|
||||
|
||||
/ Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
|
||||
.ifnb \abcd
|
||||
.if (\constexpr)<128 && (\constexpr)>=0
|
||||
pushpop \constexpr,\abcd
|
||||
.exitm
|
||||
.endif
|
||||
.endif
|
||||
movb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
movb $(\constexpr)&0xff,\abcd.lo
|
||||
.endm
|
||||
|
||||
/ Compares 16-bit CONSTEXPR with Qw-register.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
|
||||
cmpb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
jnz 387f
|
||||
cmpb $(\constexpr)&0xff,\abcd.lo
|
||||
387:
|
||||
.endm
|
||||
|
||||
/ Adds 16-bit CONSTEXPR to Qw-register.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
|
||||
addb $(\constexpr)&0xff,\abcd.lo
|
||||
.if (\constexpr) != 0
|
||||
adcb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Subtracts 16-bit CONSTEXPR from Qw-register.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
|
||||
subb $(\constexpr)&0xff,\abcd.lo
|
||||
.if (\constexpr) != 0
|
||||
sbbb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Ands Qw-register with 16-bit CONSTEXPR.
|
||||
/ @mode long,legacy,real
|
||||
.macro bband constexpr:req abcd.hi:req abcd.lo:req
|
||||
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
|
||||
andb $(\constexpr)&0xff,\abcd.lo
|
||||
.endif
|
||||
.if ((\constexpr)>>8&0xff) != 0xff
|
||||
andb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Ors Qw-register with 16-bit CONSTEXPR.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
|
||||
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
|
||||
orb $(\constexpr)&0xff,\abcd.lo
|
||||
.endif
|
||||
.if ((\constexpr)>>8&0xff) != 0
|
||||
orb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Performs ACTION only if in real mode.
|
||||
/ @mode long,legacy,real
|
||||
.macro rlo clobber:req action:vararg
|
||||
990: mov $0,\clobber
|
||||
.if .-990b!=3
|
||||
.error "bad clobber or assembler mode"
|
||||
.endif
|
||||
991: \action
|
||||
.rept 2-(.-991b)
|
||||
nop
|
||||
.endr
|
||||
.if .-991b!=2
|
||||
.error "ACTION must be 1-2 bytes"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Initializes real mode stack.
|
||||
/ The most holiest of holy code.
|
||||
/ @mode real
|
||||
/ @see www.pcjs.org/pubs/pc/reference/intel/8086/
|
||||
.macro rlstack seg:req addr:req
|
||||
cli
|
||||
mov \seg,%ss
|
||||
mov \addr,%sp
|
||||
sti
|
||||
.endm
|
||||
|
||||
/ Symbolic Linker-Defined Binary Content.
|
||||
.macro .stub name:req kind:req default type=@object
|
||||
.ifnb \default
|
||||
.equ \name,\default
|
||||
.endif
|
||||
.\kind \name
|
||||
.type \name,\type
|
||||
.weak \name
|
||||
.hidden \name
|
||||
.endm
|
||||
|
||||
/ Symbolic Linker-Defined Binary-Encoded-Bourne Content.
|
||||
/ @param units is the number of encoded 32-bit values to insert,
|
||||
/ e.g. \000 can be encoded as 0x3030305c.
|
||||
.macro .shstub name:req units:req
|
||||
ss \name,0
|
||||
.if \units>1
|
||||
ss \name,1
|
||||
.if \units>2
|
||||
ss \name,2
|
||||
ss \name,3
|
||||
.if \units>4
|
||||
ss \name,4
|
||||
ss \name,5
|
||||
ss \name,6
|
||||
ss \name,7
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
.macro ss name n
|
||||
.stub \name\()_bcs\n,long
|
||||
.endm
|
||||
|
||||
/* clang-format on */
|
||||
#elif defined(__LINKER__)
|
||||
|
||||
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCXSTUB(SYM, X) \
|
||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||
HIDDEN(SYM##_bcx2 = BCX_INT16((X) >> 16)); \
|
||||
HIDDEN(SYM##_bcx3 = BCX_INT16((X) >> 0))
|
||||
|
||||
/**
|
||||
* Binary coded backslash octet support.
|
||||
*
|
||||
* <p>This allows linker scripts to generate printf commands.
|
||||
*/
|
||||
#define BCO_OCTET(X) (((X)&0x7) + 0x30)
|
||||
#define BCOB_UNIT(X) \
|
||||
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
|
||||
(BCO_OCTET(((X)&0xff) >> 6) << 8) | 0x5c)
|
||||
|
||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I)*8)))
|
||||
#define PFSTUB2(SYM, X) \
|
||||
HIDDEN(SYM = (X)); \
|
||||
PFBYTE(SYM, X, 0); \
|
||||
PFBYTE(SYM, X, 1)
|
||||
#define PFSTUB4(SYM, X) \
|
||||
PFSTUB2(SYM, X); \
|
||||
PFBYTE(SYM, X, 2); \
|
||||
PFBYTE(SYM, X, 3)
|
||||
#define PFSTUB8(SYM, X) \
|
||||
PFSTUB4(SYM, X); \
|
||||
PFBYTE(SYM, X, 4); \
|
||||
PFBYTE(SYM, X, 5); \
|
||||
PFBYTE(SYM, X, 6); \
|
||||
PFBYTE(SYM, X, 7)
|
||||
|
||||
/**
|
||||
* Binary coded decimal support.
|
||||
*
|
||||
* <p>This allows linker scripts to generate dd commands. Leading spaces
|
||||
* need to be inserted so Mac doesn't consider them octal; therefore,
|
||||
* parameters must be quoted; and eight digits should be good enough.
|
||||
*/
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD10K(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD(X))
|
||||
#define BCD(X) \
|
||||
((X) == 0 \
|
||||
? 0x20202030 \
|
||||
: (X) < 10 ? 0x30202020 + (((X) % 10) << 24) \
|
||||
: (X) < 100 ? 0x30302020 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) \
|
||||
: (X) < 1000 ? 0x30303020 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) + \
|
||||
(((X) / 100 % 10) << 8) \
|
||||
: 0x30303030 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) + \
|
||||
(((X) / 100 % 10) << 8) + \
|
||||
(((X) / 1000 % 10) << 0))
|
||||
#define BCD10K(X) \
|
||||
((X) < 10000 \
|
||||
? 0x20202020 \
|
||||
: (X) < 100000 \
|
||||
? 0x30202020 + (((X) / 10000 % 10) << 24) \
|
||||
: (X) < 1000000 \
|
||||
? 0x30302020 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) \
|
||||
: (X) < 10000000 \
|
||||
? 0x30303020 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) + \
|
||||
(((X) / 1000000 % 10) << 8) \
|
||||
: (X) < 100000000 \
|
||||
? 0x30303030 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) + \
|
||||
(((X) / 1000000 % 10) << 8) + \
|
||||
(((X) / 10000000 % 10) << 0) \
|
||||
: 0xffffffffffffffff)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_MACROS_H_ */
|
41
ape/mtime.h
Normal file
41
ape/mtime.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef COSMOPOLITAN_APE_MTIME_H_
|
||||
#define COSMOPOLITAN_APE_MTIME_H_
|
||||
#include "libc/dos.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Deterministic last modified timestamp embedding.
|
||||
*/
|
||||
|
||||
#ifndef MTIME_YEAR
|
||||
#define MTIME_YEAR 2019
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_MONTH
|
||||
#define MTIME_MONTH 1
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_DAY
|
||||
#define MTIME_DAY 1
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_HOUR
|
||||
#define MTIME_HOUR 0
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_MINUTES
|
||||
#define MTIME_MINUTES 0
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_SECONDS
|
||||
#define MTIME_SECONDS 0
|
||||
#endif
|
||||
|
||||
#ifndef ZIP_MTIME_DATE
|
||||
#define ZIP_MTIME_DATE DOS_DATE(MTIME_YEAR, MTIME_MONTH, MTIME_DAY)
|
||||
#endif
|
||||
|
||||
#ifndef ZIP_MTIME_TIME
|
||||
#define ZIP_MTIME_TIME DOS_TIME(MTIME_HOUR, MTIME_MINUTES, MTIME_SECONDS)
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_MTIME_H_ */
|
69
ape/mz.ansi
Normal file
69
ape/mz.ansi
Normal file
|
@ -0,0 +1,69 @@
|
|||
ProTip: cat ape/mz.ansi
|
||||
|
||||
[38;5;150;48;5;150m▀[38;5;186m▀[38;5;150m▀▀[38;5;144m▀[48;5;144m▀[38;5;143m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀[38;5;241;48;5;241m▀[38;5;240;48;5;59m▀[48;5;240m▀▀[38;5;239m▀[38;5;240m▀[38;5;239m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀▀▀[48;5;238m▀▀▀▀▀[0m
|
||||
[38;5;150;48;5;150m▀▀▀▀[48;5;144m▀[38;5;144;48;5;143m▀[38;5;143m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀[38;5;241m▀[38;5;59;48;5;59m▀[38;5;240;48;5;240m▀▀▀▀▀▀▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀▀▀[0m
|
||||
[38;5;150;48;5;150m▀▀▀▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107;48;5;107m▀▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀▀[38;5;59;48;5;59m▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[38;5;239m▀▀[38;5;240m▀▀[38;5;239m▀▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀[48;5;238m▀▀▀▀[0m
|
||||
[38;5;144;48;5;144m▀▀▀[48;5;143m▀[38;5;143m▀[48;5;107m▀[38;5;107;48;5;101m▀[38;5;101m▀▀[48;5;65m▀[38;5;65m▀▀[38;5;59;48;5;59m▀▀[38;5;240;48;5;240m▀▀[48;5;59m▀▀[48;5;240m▀▀▀▀▀▀▀▀▀▀▀[38;5;239m▀▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀[48;5;239m▀[48;5;238m▀▀[0m
|
||||
[38;5;143;48;5;107m▀▀[48;5;143m▀▀[38;5;107;48;5;107m▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀[38;5;59m▀▀[38;5;241m▀[38;5;65;48;5;101m▀▀[48;5;107m▀▀▀▀▀▀▀▀[38;5;242m▀[38;5;241;48;5;101m▀[38;5;59m▀▀[38;5;240;48;5;65m▀[48;5;241m▀[48;5;59m▀[38;5;239;48;5;240m▀▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀[48;5;239m▀[0m
|
||||
[38;5;107;48;5;107m▀▀▀▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀[48;5;101m▀[38;5;101m▀[48;5;107m▀[38;5;107m▀[48;5;143m▀[38;5;143m▀▀[48;5;150m▀[48;5;144m▀▀▀[38;5;144m▀▀▀[38;5;143;48;5;143m▀▀[38;5;107m▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀[38;5;240;48;5;59m▀[48;5;240m▀[38;5;239m▀[48;5;239m▀[48;5;238m▀▀[38;5;240;48;5;239m▀[48;5;238m▀[38;5;239m▀[48;5;237m▀▀▀▀[48;5;238m▀[48;5;237m▀[48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;144m▀▀[48;5;107m▀[38;5;101;48;5;101m▀[38;5;65;48;5;65m▀[48;5;59m▀▀▀▀▀[48;5;65m▀[38;5;101;48;5;101m▀[48;5;107m▀[38;5;107m▀[48;5;143m▀[38;5;143m▀▀[48;5;186m▀[38;5;186m▀▀▀▀▀▀▀[38;5;144;48;5;144m▀▀[38;5;143;48;5;143m▀▀[38;5;101;48;5;101m▀[48;5;59m▀[38;5;242;48;5;239m▀[38;5;239;48;5;238m▀[38;5;238;48;5;237m▀▀▀▀[38;5;237;48;5;236m▀▀[48;5;235m▀[38;5;236m▀[38;5;235m▀[38;5;236;48;5;234m▀[38;5;237;48;5;235m▀[38;5;236m▀[38;5;237m▀[38;5;236m▀[38;5;237;48;5;234m▀[38;5;236;48;5;235m▀[38;5;237m▀[38;5;239;48;5;236m▀[48;5;238m▀[48;5;239m▀[48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀[0m
|
||||
[38;5;144;48;5;144m▀▀▀[38;5;107;48;5;108m▀[38;5;65;48;5;101m▀[48;5;65m▀[38;5;59m▀[48;5;59m▀▀▀[38;5;65;48;5;65m▀[38;5;101;48;5;101m▀[38;5;107;48;5;107m▀[48;5;143m▀[38;5;143m▀[48;5;150m▀[38;5;150;48;5;186m▀[38;5;186m▀▀[48;5;187m▀▀[48;5;186m▀▀▀▀[38;5;150;48;5;180m▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107;48;5;101m▀[38;5;101;48;5;240m▀[38;5;240m▀[38;5;239;48;5;238m▀[38;5;238;48;5;237m▀▀[38;5;237;48;5;239m▀[48;5;236m▀[38;5;236;48;5;237m▀[48;5;235m▀[38;5;235m▀[38;5;234m▀[38;5;235m▀▀▀[48;5;234m▀[38;5;234m▀[38;5;235;48;5;233m▀▀[38;5;234m▀[38;5;235m▀[38;5;234;48;5;234m▀▀[38;5;235m▀▀[38;5;237;48;5;235m▀[38;5;239m▀[48;5;237m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;238m▀[38;5;238m▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀▀▀[38;5;107;48;5;107m▀[38;5;65;48;5;101m▀[48;5;65m▀[38;5;59;48;5;59m▀▀[48;5;65m▀[38;5;65m▀▀[38;5;101;48;5;101m▀[38;5;143;48;5;144m▀[38;5;144;48;5;150m▀[38;5;186;48;5;186m▀▀[38;5;187;48;5;187m▀▀▀▀▀[38;5;186;48;5;186m▀▀[48;5;144m▀[38;5;144;48;5;101m▀[38;5;137;48;5;95m▀[38;5;95m▀[38;5;59;48;5;101m▀[48;5;239m▀[38;5;238;48;5;238m▀[38;5;237m▀▀[38;5;236;48;5;236m▀[38;5;238m▀[38;5;237m▀[38;5;235m▀▀[48;5;235m▀▀[48;5;234m▀▀[38;5;234;48;5;235m▀▀[48;5;234m▀▀[38;5;233m▀[48;5;233m▀[38;5;234m▀[48;5;234m▀▀▀▀[38;5;235m▀▀▀[38;5;236;48;5;235m▀[38;5;239m▀[48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;238m▀[38;5;238m▀▀▀[0m
|
||||
[38;5;186;48;5;186m▀[38;5;144;48;5;150m▀[48;5;144m▀[48;5;108m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀[38;5;65;48;5;65m▀[38;5;241;48;5;241m▀[38;5;59;48;5;65m▀[38;5;65m▀[48;5;101m▀[38;5;101m▀[38;5;107;48;5;107m▀[38;5;144;48;5;144m▀[38;5;150;48;5;150m▀[38;5;186;48;5;186m▀[38;5;187m▀[48;5;187m▀▀▀▀▀[38;5;186;48;5;144m▀[38;5;144;48;5;101m▀[38;5;101;48;5;95m▀[38;5;240;48;5;238m▀[38;5;59;48;5;240m▀[38;5;101;48;5;95m▀[38;5;239;48;5;239m▀[38;5;237m▀[38;5;238m▀[48;5;238m▀[38;5;235;48;5;237m▀[48;5;236m▀▀[38;5;234;48;5;235m▀[48;5;234m▀[38;5;235m▀▀[38;5;234;48;5;235m▀[48;5;234m▀▀[38;5;235m▀▀▀[38;5;234m▀▀▀[38;5;233m▀[38;5;234;48;5;233m▀▀▀▀▀[48;5;234m▀▀▀▀[38;5;235;48;5;235m▀[38;5;238;48;5;236m▀[38;5;239;48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀▀▀[0m
|
||||
[38;5;186;48;5;150m▀[38;5;150;48;5;144m▀[38;5;144;48;5;143m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀[38;5;65;48;5;65m▀[48;5;241m▀[38;5;241m▀[38;5;65;48;5;65m▀[48;5;101m▀[38;5;101m▀[48;5;107m▀[38;5;144;48;5;144m▀▀[48;5;150m▀[38;5;186;48;5;186m▀[38;5;187m▀[48;5;187m▀▀▀▀[48;5;137m▀[38;5;101;48;5;101m▀[48;5;95m▀[38;5;239;48;5;240m▀[38;5;238;48;5;239m▀[38;5;59;48;5;95m▀[38;5;95;48;5;240m▀[38;5;59m▀[38;5;239;48;5;239m▀[38;5;238;48;5;240m▀[48;5;238m▀[38;5;237m▀[48;5;236m▀[48;5;235m▀[38;5;236m▀[38;5;235m▀▀[38;5;234m▀[48;5;234m▀▀[38;5;235;48;5;235m▀[38;5;234;48;5;234m▀▀▀▀▀[48;5;233m▀[38;5;233m▀▀▀▀[48;5;234m▀[48;5;233m▀[48;5;234m▀▀[48;5;233m▀[38;5;234;48;5;234m▀[38;5;235;48;5;235m▀[38;5;236;48;5;236m▀[38;5;237;48;5;237m▀[38;5;238;48;5;238m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀[48;5;238m▀▀▀[0m
|
||||
[38;5;150;48;5;143m▀[38;5;143;48;5;107m▀[38;5;107;48;5;65m▀[38;5;101m▀[38;5;65;48;5;59m▀▀[38;5;59m▀[48;5;65m▀[38;5;65m▀▀[38;5;101;48;5;101m▀[38;5;107;48;5;108m▀[38;5;144;48;5;144m▀▀[38;5;186;48;5;186m▀[38;5;187m▀[48;5;187m▀▀▀[48;5;186m▀[38;5;144;48;5;101m▀[38;5;101m▀▀[38;5;95;48;5;240m▀[38;5;59m▀▀▀[38;5;240;48;5;95m▀[48;5;101m▀[38;5;101;48;5;144m▀[38;5;138;48;5;101m▀[38;5;240;48;5;95m▀[38;5;237;48;5;239m▀[48;5;237m▀[38;5;236;48;5;236m▀[48;5;235m▀▀[38;5;235;48;5;236m▀▀▀[48;5;235m▀[38;5;234m▀▀[38;5;235m▀[38;5;234;48;5;234m▀▀▀[48;5;233m▀[38;5;233;48;5;234m▀▀▀[38;5;234;48;5;236m▀[48;5;237m▀[38;5;235;48;5;238m▀▀[38;5;234;48;5;236m▀[48;5;234m▀[48;5;233m▀[38;5;235;48;5;234m▀[48;5;235m▀[38;5;237m▀[48;5;237m▀[38;5;238m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀[38;5;239m▀[0m
|
||||
[38;5;107;48;5;107m▀[38;5;65;48;5;65m▀▀[38;5;59;48;5;59m▀▀[48;5;241m▀[38;5;65;48;5;65m▀▀[48;5;101m▀[38;5;101;48;5;107m▀[38;5;107;48;5;144m▀[38;5;108m▀[38;5;144m▀[38;5;150;48;5;150m▀[48;5;186m▀[38;5;186m▀▀[48;5;150m▀[48;5;144m▀[38;5;144m▀[38;5;101;48;5;95m▀[48;5;101m▀[38;5;95;48;5;241m▀[38;5;59;48;5;59m▀[48;5;95m▀[38;5;240;48;5;239m▀[48;5;95m▀[38;5;101;48;5;181m▀[38;5;253;48;5;255m▀[38;5;255;48;5;224m▀[38;5;188;48;5;187m▀[38;5;180;48;5;181m▀[38;5;101;48;5;180m▀[38;5;239;48;5;137m▀[38;5;236;48;5;95m▀▀▀[38;5;235m▀▀▀[38;5;236;48;5;238m▀[38;5;235;48;5;237m▀[48;5;236m▀[38;5;234;48;5;235m▀[48;5;234m▀▀▀[48;5;235m▀▀[38;5;235;48;5;237m▀[38;5;236;48;5;239m▀[38;5;237;48;5;240m▀[38;5;239;48;5;95m▀▀[38;5;240m▀[38;5;239;48;5;240m▀[38;5;235;48;5;236m▀[38;5;233;48;5;234m▀[38;5;235m▀[48;5;235m▀[38;5;236;48;5;236m▀▀[38;5;237;48;5;237m▀[38;5;239;48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;101;48;5;65m▀[38;5;65m▀[38;5;241;48;5;59m▀[38;5;240m▀[38;5;241;48;5;65m▀[38;5;65m▀[48;5;101m▀[38;5;101;48;5;107m▀[38;5;107;48;5;144m▀[38;5;108m▀[38;5;144;48;5;150m▀[38;5;150m▀▀▀[38;5;186m▀▀[48;5;186m▀[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀[38;5;101;48;5;101m▀▀[38;5;95;48;5;95m▀[38;5;59m▀[38;5;95;48;5;239m▀[38;5;238;48;5;237m▀[38;5;240;48;5;95m▀[38;5;144;48;5;224m▀[38;5;224;48;5;255m▀[38;5;254;48;5;224m▀[38;5;253;48;5;223m▀[38;5;187;48;5;187m▀[38;5;181;48;5;181m▀[38;5;180;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137m▀▀[38;5;131m▀[38;5;95m▀▀[38;5;137m▀▀▀[38;5;101m▀[38;5;95m▀▀[38;5;240;48;5;95m▀[38;5;238m▀▀[38;5;239m▀[38;5;95m▀▀▀▀▀▀▀[38;5;237;48;5;239m▀[38;5;235;48;5;235m▀[48;5;234m▀▀[48;5;235m▀[38;5;236m▀▀[38;5;238;48;5;238m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀[38;5;59;48;5;241m▀[38;5;241;48;5;65m▀[38;5;65;48;5;101m▀[38;5;101;48;5;107m▀[38;5;107;48;5;144m▀[38;5;144m▀[38;5;150;48;5;150m▀▀[48;5;186m▀▀▀[38;5;186m▀[38;5;150;48;5;150m▀▀[48;5;144m▀[38;5;144m▀▀[38;5;101;48;5;137m▀[48;5;95m▀[38;5;239;48;5;59m▀[38;5;240;48;5;238m▀[38;5;236m▀[38;5;238m▀[38;5;137;48;5;180m▀[38;5;224;48;5;224m▀[38;5;255m▀[38;5;187;48;5;187m▀[48;5;181m▀[38;5;181;48;5;180m▀[38;5;180;48;5;144m▀[38;5;138;48;5;138m▀[38;5;137;48;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;95m▀[38;5;137m▀▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀[38;5;235;48;5;237m▀[38;5;233;48;5;233m▀▀[38;5;235;48;5;234m▀▀[48;5;235m▀[38;5;237;48;5;237m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;101m▀[48;5;65m▀▀▀[38;5;107;48;5;107m▀[48;5;144m▀[38;5;144m▀▀[38;5;150;48;5;150m▀▀[38;5;186m▀[48;5;186m▀▀[48;5;150m▀[38;5;150m▀▀[38;5;144;48;5;144m▀▀[38;5;101;48;5;101m▀▀[38;5;240;48;5;239m▀[38;5;239;48;5;237m▀[38;5;237;48;5;238m▀[38;5;239;48;5;239m▀[48;5;95m▀[38;5;187;48;5;187m▀[38;5;224m▀▀[38;5;181;48;5;180m▀[38;5;180m▀▀[38;5;138m▀[48;5;144m▀[38;5;137;48;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131;48;5;131m▀[38;5;137m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀▀▀▀[38;5;238;48;5;239m▀[38;5;234;48;5;235m▀[38;5;233;48;5;234m▀▀[48;5;233m▀[38;5;234;48;5;234m▀[38;5;236;48;5;236m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;101;48;5;107m▀▀▀[38;5;107m▀[38;5;144;48;5;144m▀▀[38;5;150;48;5;150m▀▀▀▀▀▀▀[48;5;144m▀[38;5;144;48;5;143m▀[48;5;107m▀[38;5;143m▀[38;5;107m▀[38;5;101;48;5;101m▀[38;5;59;48;5;238m▀[38;5;236;48;5;235m▀[38;5;238;48;5;238m▀[38;5;241;48;5;241m▀[38;5;240m▀[38;5;95;48;5;101m▀[38;5;180;48;5;180m▀[38;5;187;48;5;181m▀[38;5;181;48;5;180m▀▀[38;5;180m▀▀▀[38;5;138m▀[38;5;137;48;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131m▀[38;5;95;48;5;131m▀[48;5;95m▀▀▀▀▀▀▀▀[38;5;239;48;5;239m▀[38;5;235;48;5;235m▀[38;5;234m▀[48;5;234m▀▀[38;5;235;48;5;235m▀[38;5;237;48;5;237m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;144;48;5;144m▀[38;5;108m▀▀[38;5;144m▀▀▀▀[38;5;150m▀▀[38;5;144m▀[48;5;143m▀[48;5;107m▀[38;5;143m▀[38;5;107;48;5;101m▀[48;5;65m▀▀[38;5;101m▀[48;5;101m▀[38;5;59;48;5;239m▀[38;5;237;48;5;237m▀[38;5;236;48;5;236m▀[38;5;238;48;5;239m▀[38;5;241m▀[38;5;240;48;5;59m▀[38;5;101;48;5;95m▀[38;5;180;48;5;180m▀▀[48;5;187m▀[48;5;181m▀▀[38;5;181m▀▀[38;5;180;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131m▀[38;5;137m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀[48;5;240m▀[38;5;238;48;5;238m▀[38;5;235;48;5;234m▀[38;5;234m▀▀▀▀[38;5;237;48;5;236m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;144;48;5;150m▀[48;5;144m▀▀▀▀▀▀▀▀[48;5;107m▀[38;5;143m▀[38;5;107;48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀[48;5;241m▀[38;5;59m▀[38;5;241;48;5;59m▀[38;5;238;48;5;238m▀[38;5;235;48;5;236m▀[38;5;236;48;5;237m▀[38;5;237;48;5;238m▀[38;5;240;48;5;237m▀[38;5;239;48;5;238m▀[38;5;95;48;5;137m▀[38;5;180;48;5;180m▀[38;5;181;48;5;223m▀[38;5;187;48;5;187m▀▀[48;5;138m▀[38;5;180;48;5;95m▀[38;5;144m▀[38;5;137;48;5;240m▀▀[48;5;95m▀▀[48;5;101m▀[48;5;137m▀[48;5;131m▀[48;5;137m▀▀▀▀▀▀▀▀[48;5;95m▀[38;5;95m▀[38;5;131m▀[38;5;95m▀▀▀▀▀▀[38;5;240m▀[38;5;238;48;5;238m▀[38;5;234;48;5;234m▀[38;5;233;48;5;233m▀[38;5;234;48;5;234m▀▀▀[38;5;237;48;5;236m▀[38;5;239;48;5;239m▀[48;5;240m▀[48;5;239m▀[48;5;240m▀▀▀[48;5;239m▀▀▀[48;5;240m▀▀▀▀▀▀[48;5;239m▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀▀▀[38;5;107;48;5;107m▀[38;5;108;48;5;108m▀[48;5;107m▀[38;5;107m▀▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀[38;5;241m▀[38;5;59;48;5;59m▀[38;5;238;48;5;238m▀[38;5;236;48;5;236m▀[48;5;237m▀[38;5;237;48;5;239m▀[48;5;237m▀[48;5;236m▀[38;5;239;48;5;95m▀[38;5;144;48;5;187m▀[38;5;181;48;5;223m▀[38;5;187;48;5;180m▀[38;5;181;48;5;137m▀[38;5;137;48;5;101m▀[38;5;95;48;5;95m▀[48;5;101m▀[38;5;240m▀[48;5;95m▀[38;5;239m▀▀[38;5;240m▀[38;5;95m▀▀▀▀[38;5;131m▀[38;5;137m▀▀▀[38;5;95;48;5;101m▀[48;5;95m▀[48;5;240m▀▀[38;5;239m▀[48;5;239m▀▀[38;5;240;48;5;240m▀[38;5;239m▀▀[38;5;95;48;5;239m▀[48;5;95m▀▀[38;5;239;48;5;240m▀[38;5;235;48;5;236m▀[38;5;233;48;5;233m▀[38;5;234;48;5;234m▀▀▀[38;5;236;48;5;236m▀[38;5;239;48;5;239m▀[38;5;240;48;5;240m▀▀▀▀[48;5;239m▀[38;5;239m▀[48;5;240m▀[38;5;240m▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;150;48;5;144m▀[38;5;144;48;5;143m▀▀[48;5;107m▀[38;5;107m▀▀▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀[48;5;59m▀[38;5;241;48;5;65m▀[38;5;239;48;5;138m▀[38;5;237;48;5;238m▀[38;5;238m▀[48;5;237m▀[38;5;236;48;5;236m▀[38;5;237;48;5;238m▀[38;5;137;48;5;180m▀[38;5;224;48;5;253m▀[38;5;187;48;5;187m▀[38;5;144;48;5;181m▀▀[38;5;138;48;5;137m▀[38;5;137m▀[48;5;95m▀[48;5;236m▀[38;5;138;48;5;235m▀[38;5;137;48;5;236m▀[38;5;101;48;5;238m▀[38;5;95;48;5;240m▀[48;5;95m▀▀▀▀▀[38;5;137;48;5;137m▀[38;5;95m▀[48;5;95m▀▀[48;5;240m▀[48;5;239m▀[38;5;239;48;5;240m▀[38;5;240;48;5;239m▀[38;5;95m▀[38;5;101;48;5;95m▀[48;5;101m▀[38;5;95;48;5;95m▀▀▀[38;5;239;48;5;239m▀[38;5;95;48;5;240m▀[38;5;240;48;5;95m▀[38;5;237;48;5;237m▀[38;5;233;48;5;233m▀[38;5;235;48;5;234m▀[38;5;234m▀[38;5;235;48;5;235m▀▀[38;5;237;48;5;237m▀[38;5;239;48;5;239m▀[38;5;240m▀▀[38;5;239m▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;143;48;5;107m▀[38;5;107m▀▀[48;5;101m▀▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀[38;5;59;48;5;241m▀[38;5;180;48;5;173m▀[38;5;137;48;5;131m▀[38;5;240;48;5;240m▀[38;5;238m▀[38;5;236;48;5;238m▀[38;5;238;48;5;240m▀[38;5;239;48;5;101m▀[38;5;181;48;5;187m▀[38;5;188m▀[38;5;181;48;5;144m▀[38;5;187;48;5;137m▀[38;5;137;48;5;240m▀[38;5;239;48;5;239m▀[38;5;236;48;5;95m▀[38;5;239m▀[38;5;236;48;5;240m▀▀[38;5;238;48;5;239m▀[38;5;240m▀[38;5;238m▀▀[38;5;239;48;5;238m▀[38;5;95;48;5;95m▀[38;5;131;48;5;131m▀[38;5;95m▀[38;5;137m▀[38;5;95;48;5;95m▀▀[38;5;240;48;5;239m▀[38;5;238m▀[48;5;238m▀▀[38;5;237;48;5;240m▀[38;5;235;48;5;236m▀[48;5;235m▀[38;5;234;48;5;237m▀[38;5;237m▀[38;5;95;48;5;234m▀[48;5;238m▀[48;5;95m▀[38;5;240m▀[38;5;95m▀[38;5;238;48;5;239m▀[38;5;234;48;5;235m▀[38;5;233;48;5;234m▀[38;5;234m▀[38;5;235;48;5;235m▀[38;5;238;48;5;239m▀[38;5;240m▀[38;5;239m▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;107m▀[48;5;101m▀[38;5;101m▀[48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀[48;5;241m▀[38;5;241m▀[38;5;59;48;5;59m▀[38;5;167;48;5;131m▀[38;5;131;48;5;95m▀[38;5;101;48;5;180m▀[38;5;95;48;5;95m▀[38;5;238;48;5;239m▀[38;5;242;48;5;95m▀[38;5;138;48;5;187m▀[38;5;187m▀[38;5;180;48;5;144m▀[38;5;181;48;5;180m▀[38;5;137m▀[48;5;137m▀[48;5;95m▀▀▀▀▀[38;5;131m▀[38;5;95m▀▀▀[38;5;239m▀[38;5;240m▀[38;5;137;48;5;138m▀[38;5;131;48;5;137m▀▀[38;5;95;48;5;95m▀▀▀[38;5;240m▀[38;5;95m▀[38;5;240m▀▀[38;5;95m▀[38;5;241;48;5;101m▀[38;5;95;48;5;95m▀▀[38;5;239m▀[38;5;240m▀[38;5;239m▀[38;5;95m▀▀[38;5;240m▀[38;5;235;48;5;235m▀▀[48;5;236m▀[38;5;237;48;5;239m▀[38;5;95;48;5;95m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀[38;5;240m▀[48;5;240m▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀▀[48;5;241m▀[38;5;241m▀[38;5;59;48;5;59m▀[48;5;240m▀[38;5;173;48;5;173m▀[38;5;137;48;5;180m▀[38;5;181;48;5;137m▀[38;5;137m▀[38;5;239;48;5;95m▀[38;5;137;48;5;180m▀[38;5;187;48;5;187m▀[38;5;223;48;5;181m▀[38;5;181;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137;48;5;144m▀[38;5;95;48;5;137m▀▀▀[48;5;95m▀▀▀▀▀▀[48;5;137m▀▀[38;5;137;48;5;180m▀[38;5;180m▀[38;5;137;48;5;137m▀▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;236;48;5;237m▀▀[38;5;238;48;5;95m▀[38;5;95m▀▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀[38;5;240m▀▀▀▀▀[0m
|
||||
[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀▀▀[38;5;241;48;5;241m▀[38;5;59m▀▀[48;5;59m▀[38;5;174;48;5;137m▀[38;5;180;48;5;180m▀[38;5;95;48;5;95m▀▀[48;5;186m▀[38;5;180;48;5;180m▀▀[38;5;181m▀[38;5;180m▀[48;5;187m▀[38;5;187m▀[38;5;180;48;5;180m▀[38;5;137;48;5;137m▀▀▀▀[48;5;131m▀▀[48;5;137m▀▀▀[38;5;138;48;5;180m▀[38;5;180;48;5;181m▀[38;5;181;48;5;187m▀[38;5;137;48;5;137m▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀[48;5;131m▀[38;5;131;48;5;137m▀▀[38;5;95m▀▀[48;5;131m▀[48;5;95m▀▀▀▀[38;5;242;48;5;101m▀[38;5;237;48;5;95m▀[38;5;95m▀▀[48;5;241m▀[38;5;239;48;5;239m▀▀▀▀▀▀[48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;241m▀[38;5;241m▀[38;5;59m▀[38;5;101;48;5;240m▀[38;5;174;48;5;180m▀[38;5;95;48;5;95m▀[38;5;131;48;5;137m▀[38;5;137;48;5;131m▀[38;5;180;48;5;180m▀▀▀[38;5;181;48;5;187m▀[38;5;224m▀[38;5;181;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137m▀▀▀▀[38;5;131;48;5;131m▀[38;5;137m▀▀[48;5;180m▀[38;5;138m▀[38;5;180m▀[38;5;181;48;5;187m▀[38;5;187;48;5;180m▀[38;5;137;48;5;137m▀▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀[38;5;131m▀[38;5;137;48;5;131m▀[48;5;137m▀▀▀[38;5;131m▀[48;5;131m▀[48;5;95m▀[38;5;95m▀▀▀[38;5;101m▀[38;5;95;48;5;101m▀[48;5;95m▀▀[38;5;239;48;5;239m▀▀▀▀▀▀[38;5;238;48;5;238m▀▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;241;48;5;241m▀[38;5;59;48;5;65m▀[38;5;181;48;5;101m▀[38;5;223;48;5;180m▀[38;5;137;48;5;137m▀[48;5;173m▀[38;5;180;48;5;180m▀▀▀▀[48;5;137m▀[38;5;137m▀[48;5;131m▀[38;5;131m▀[38;5;137;48;5;95m▀[38;5;131m▀[38;5;95m▀▀▀▀[38;5;180;48;5;144m▀[38;5;181;48;5;180m▀▀[38;5;187m▀[38;5;180;48;5;137m▀[38;5;137;48;5;131m▀[48;5;137m▀[38;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀▀[48;5;240m▀▀[38;5;131;48;5;95m▀[38;5;137m▀[38;5;131m▀▀[38;5;95m▀▀▀▀▀▀▀[48;5;59m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀[38;5;238m▀[38;5;239m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀[38;5;241;48;5;59m▀[38;5;65;48;5;241m▀[48;5;65m▀▀▀▀▀▀▀▀▀▀▀[38;5;241;48;5;241m▀[38;5;65m▀[38;5;180;48;5;245m▀[38;5;173;48;5;180m▀[38;5;180;48;5;137m▀[48;5;180m▀▀▀[38;5;137;48;5;131m▀[48;5;137m▀[38;5;95;48;5;95m▀▀▀[48;5;238m▀[38;5;240;48;5;239m▀[48;5;238m▀[38;5;95;48;5;240m▀[48;5;239m▀▀[48;5;95m▀[48;5;240m▀[38;5;137;48;5;238m▀[48;5;237m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀[48;5;238m▀[48;5;239m▀[38;5;240m▀[38;5;95m▀▀[48;5;240m▀[38;5;240m▀[38;5;239;48;5;238m▀[38;5;95;48;5;237m▀[48;5;95m▀▀▀▀▀▀▀▀[38;5;101;48;5;101m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀[38;5;59;48;5;59m▀[38;5;241;48;5;241m▀[38;5;65;48;5;65m▀▀▀[48;5;241m▀[48;5;65m▀▀▀▀▀▀▀▀[38;5;241;48;5;59m▀[38;5;65m▀[38;5;180;48;5;65m▀[38;5;181;48;5;137m▀[38;5;180m▀[48;5;180m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;240;48;5;236m▀[38;5;235m▀[38;5;238;48;5;237m▀[38;5;237m▀[38;5;240m▀[38;5;238;48;5;239m▀[48;5;238m▀[38;5;239;48;5;239m▀[38;5;238m▀[38;5;239;48;5;238m▀[38;5;238;48;5;239m▀[48;5;238m▀[38;5;236;48;5;236m▀[38;5;238;48;5;239m▀[38;5;239m▀[48;5;238m▀[38;5;240;48;5;239m▀[38;5;236;48;5;237m▀[38;5;238m▀[38;5;237;48;5;238m▀▀[38;5;238;48;5;237m▀[38;5;239;48;5;238m▀[38;5;238;48;5;237m▀▀[38;5;236m▀[48;5;235m▀[38;5;95;48;5;238m▀[48;5;240m▀▀[48;5;95m▀▀▀▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀[38;5;241;48;5;241m▀[38;5;59;48;5;59m▀▀[38;5;241;48;5;241m▀▀▀▀▀[38;5;65m▀[48;5;65m▀▀▀[48;5;241m▀[38;5;241;48;5;59m▀▀▀[38;5;59m▀▀[38;5;240;48;5;240m▀[38;5;242m▀[38;5;180;48;5;180m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;236;48;5;239m▀▀[48;5;238m▀[38;5;237;48;5;236m▀▀[48;5;238m▀[38;5;239;48;5;239m▀▀[38;5;238;48;5;238m▀[38;5;237m▀[38;5;239;48;5;237m▀[38;5;237;48;5;236m▀[38;5;236m▀▀[38;5;237;48;5;237m▀[48;5;235m▀[38;5;238;48;5;236m▀[38;5;237;48;5;237m▀[48;5;238m▀[48;5;236m▀[38;5;239;48;5;237m▀[38;5;237;48;5;235m▀[48;5;238m▀[48;5;237m▀[48;5;235m▀[48;5;236m▀[38;5;234m▀[38;5;239;48;5;239m▀[38;5;240;48;5;240m▀▀[38;5;95m▀[38;5;241m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀[38;5;59;48;5;241m▀[48;5;59m▀▀▀[38;5;241;48;5;241m▀▀[48;5;59m▀[48;5;241m▀▀▀[38;5;65;48;5;65m▀▀[48;5;241m▀[38;5;241m▀▀[38;5;59;48;5;59m▀▀[38;5;240;48;5;240m▀▀▀[38;5;180;48;5;143m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[48;5;240m▀[48;5;95m▀▀[38;5;240m▀[38;5;95m▀[38;5;240m▀[38;5;237;48;5;240m▀[38;5;236;48;5;239m▀[38;5;235;48;5;237m▀[38;5;240;48;5;242m▀[38;5;239;48;5;101m▀[38;5;237;48;5;138m▀[38;5;238m▀[38;5;236;48;5;101m▀[38;5;234m▀[38;5;238;48;5;95m▀[38;5;236;48;5;240m▀[38;5;237;48;5;59m▀[38;5;235;48;5;95m▀▀[38;5;237;48;5;101m▀[38;5;235;48;5;241m▀[38;5;236;48;5;238m▀[38;5;234m▀[38;5;236m▀[38;5;237;48;5;239m▀[38;5;239;48;5;240m▀[38;5;240;48;5;59m▀[48;5;95m▀[38;5;95m▀[38;5;240;48;5;240m▀[48;5;239m▀[48;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;241m▀[38;5;241m▀[38;5;59;48;5;59m▀▀[48;5;65m▀[38;5;241m▀[38;5;65m▀▀▀▀[38;5;241m▀[38;5;65m▀[38;5;241m▀[38;5;65m▀[38;5;241m▀[48;5;241m▀▀[38;5;59;48;5;59m▀[48;5;240m▀[38;5;240m▀▀▀[38;5;137;48;5;101m▀[48;5;137m▀▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀[38;5;239m▀[38;5;236;48;5;239m▀[38;5;59;48;5;238m▀[38;5;144;48;5;102m▀[38;5;245;48;5;95m▀[38;5;248;48;5;239m▀[38;5;249;48;5;240m▀[48;5;238m▀[38;5;248;48;5;237m▀[48;5;238m▀[38;5;247;48;5;239m▀[38;5;243;48;5;238m▀[38;5;246;48;5;241m▀[38;5;239;48;5;239m▀[38;5;235m▀[38;5;238m▀[38;5;239;48;5;95m▀[38;5;95m▀▀[48;5;240m▀▀[38;5;240;48;5;239m▀[38;5;239m▀[48;5;240m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;240m▀[48;5;239m▀▀[38;5;240;48;5;240m▀▀[0m
|
||||
[38;5;65;48;5;241m▀[38;5;241m▀[38;5;59;48;5;65m▀[38;5;65m▀▀▀▀[48;5;101m▀▀▀▀▀[48;5;65m▀[48;5;242m▀▀[38;5;241;48;5;65m▀[48;5;59m▀[38;5;59;48;5;241m▀[38;5;240;48;5;59m▀[48;5;240m▀▀[48;5;239m▀[38;5;101;48;5;101m▀[38;5;143;48;5;180m▀[38;5;137;48;5;137m▀[38;5;95m▀[48;5;95m▀▀▀▀▀▀[48;5;101m▀[48;5;137m▀▀[48;5;131m▀[38;5;240;48;5;95m▀[38;5;246m▀[38;5;247m▀[38;5;248m▀[38;5;245m▀[38;5;248m▀[38;5;247m▀[38;5;243m▀[38;5;239m▀▀▀▀[38;5;95m▀▀▀▀[38;5;240m▀[48;5;240m▀[48;5;239m▀[48;5;240m▀[48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;240m▀▀▀[48;5;240m▀[0m
|
||||
[38;5;241;48;5;241m▀[48;5;65m▀[38;5;65m▀▀▀▀[38;5;101;48;5;101m▀▀▀▀▀▀▀[38;5;243m▀[38;5;65;48;5;242m▀[38;5;242m▀[38;5;241m▀[48;5;243m▀[38;5;59;48;5;245m▀[38;5;240;48;5;247m▀[48;5;246m▀[38;5;239m▀[38;5;245;48;5;181m▀[38;5;180;48;5;180m▀[38;5;137m▀[48;5;137m▀[38;5;95m▀[48;5;95m▀▀▀▀[48;5;101m▀▀[38;5;101;48;5;137m▀[38;5;137m▀[48;5;101m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀[38;5;101;48;5;240m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀[38;5;59;48;5;59m▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239;48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;101m▀▀▀▀▀▀[38;5;101m▀▀▀▀▀▀▀▀[38;5;65m▀[48;5;65m▀[38;5;241;48;5;145m▀[38;5;255;48;5;231m▀[38;5;174;48;5;180m▀[38;5;131;48;5;131m▀▀▀[38;5;180;48;5;223m▀[48;5;180m▀▀[38;5;137m▀[48;5;137m▀[38;5;95m▀[38;5;101;48;5;95m▀[38;5;137;48;5;137m▀▀[38;5;95m▀[38;5;137m▀[38;5;101m▀[48;5;95m▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;59m▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239;48;5;240m▀[38;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;107m▀[38;5;101m▀▀[48;5;101m▀▀▀[48;5;107m▀[48;5;108m▀▀[38;5;107m▀[38;5;245m▀[38;5;101;48;5;101m▀▀▀▀[38;5;242;48;5;249m▀[38;5;231;48;5;231m▀▀[38;5;181;48;5;255m▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀[48;5;131m▀[38;5;223;48;5;223m▀[38;5;180;48;5;180m▀▀▀[38;5;137;48;5;137m▀▀[38;5;95m▀[38;5;101;48;5;101m▀[38;5;137;48;5;137m▀▀▀▀▀[38;5;95m▀▀▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[48;5;59m▀[38;5;240;48;5;240m▀[38;5;239m▀[38;5;240m▀[38;5;95;48;5;95m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;143;48;5;144m▀[38;5;107;48;5;143m▀[48;5;107m▀▀[38;5;101;48;5;101m▀[38;5;107;48;5;107m▀[38;5;108m▀[48;5;108m▀▀[48;5;107m▀[38;5;107m▀[38;5;101;48;5;101m▀▀▀[48;5;145m▀[38;5;255;48;5;231m▀[38;5;231m▀▀▀[38;5;131;48;5;174m▀[48;5;95m▀[38;5;174;48;5;223m▀[38;5;223;48;5;187m▀[38;5;180;48;5;180m▀▀▀[38;5;179;48;5;179m▀[38;5;137;48;5;137m▀▀▀[48;5;95m▀[48;5;137m▀▀▀▀▀[38;5;95;48;5;95m▀[38;5;131m▀[38;5;95m▀▀▀[48;5;101m▀[38;5;137m▀[38;5;95;48;5;95m▀▀▀▀▀▀[48;5;240m▀[38;5;240;48;5;239m▀[38;5;239;48;5;240m▀[38;5;240m▀[38;5;95m▀[48;5;95m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;240m▀[48;5;239m▀▀▀▀▀▀[0m
|
||||
[38;5;144;48;5;144m▀[38;5;143m▀[48;5;143m▀[38;5;107;48;5;107m▀[38;5;101m▀[38;5;107m▀▀[38;5;108m▀▀[48;5;108m▀▀[38;5;107;48;5;107m▀[48;5;108m▀[38;5;101;48;5;144m▀[38;5;255;48;5;231m▀[38;5;231m▀▀▀▀[38;5;224m▀[38;5;94;48;5;95m▀[38;5;223;48;5;223m▀[38;5;181;48;5;180m▀[38;5;180m▀[48;5;179m▀[38;5;179;48;5;173m▀▀[38;5;137;48;5;137m▀▀▀[38;5;95;48;5;95m▀▀[38;5;137m▀▀▀[38;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239m▀▀[38;5;240;48;5;240m▀▀[38;5;95;48;5;95m▀[48;5;101m▀[38;5;239;48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[38;5;239m▀▀▀[0m
|
||||
[38;5;150;48;5;186m▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107;48;5;107m▀▀▀[48;5;143m▀▀[38;5;143m▀[38;5;107m▀▀▀[48;5;108m▀[38;5;252;48;5;231m▀[38;5;231m▀▀▀▀▀[38;5;255;48;5;224m▀[38;5;138m▀[38;5;223;48;5;180m▀[38;5;180m▀▀[38;5;179;48;5;173m▀[38;5;173m▀[48;5;137m▀[38;5;137m▀▀[48;5;131m▀[38;5;95;48;5;95m▀▀▀▀[48;5;240m▀[48;5;239m▀▀▀▀[48;5;240m▀[38;5;240;48;5;239m▀▀▀▀▀[48;5;238m▀▀[38;5;239;48;5;239m▀▀▀[48;5;240m▀[38;5;240m▀[48;5;95m▀[38;5;95m▀[38;5;138;48;5;144m▀[38;5;243;48;5;247m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[48;5;59m▀[48;5;240m▀[48;5;59m▀[48;5;241m▀▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107m▀[48;5;107m▀▀[38;5;143;48;5;143m▀▀▀[48;5;151m▀[48;5;255m▀[38;5;144;48;5;231m▀[38;5;188m▀[38;5;231m▀▀▀▀▀▀▀[48;5;255m▀[38;5;144;48;5;224m▀[38;5;180;48;5;95m▀[48;5;180m▀[38;5;173;48;5;173m▀[38;5;137;48;5;137m▀▀▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀▀[38;5;240m▀[38;5;239;48;5;239m▀▀▀[38;5;238m▀▀▀▀[48;5;238m▀▀▀[48;5;239m▀[38;5;239;48;5;238m▀▀[48;5;239m▀[48;5;240m▀[38;5;240m▀[38;5;95m▀[38;5;240;48;5;95m▀[38;5;95m▀[38;5;138;48;5;138m▀[38;5;181;48;5;251m▀[38;5;239;48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀[48;5;59m▀▀[38;5;59m▀▀[48;5;241m▀[38;5;241;48;5;65m▀[38;5;65m▀▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;149m▀[38;5;143;48;5;143m▀[48;5;144m▀[48;5;187m▀[48;5;255m▀[38;5;144;48;5;231m▀[38;5;252m▀[38;5;231;48;5;255m▀[48;5;231m▀[38;5;255;48;5;224m▀[38;5;224;48;5;182m▀[38;5;231;48;5;231m▀▀▀▀▀▀▀▀▀[38;5;255;48;5;224m▀[38;5;138;48;5;252m▀[38;5;137;48;5;95m▀[48;5;131m▀[48;5;137m▀▀▀[38;5;131;48;5;131m▀[48;5;95m▀[38;5;95m▀▀▀▀[48;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀[48;5;238m▀▀[38;5;238m▀▀[48;5;239m▀[38;5;239m▀▀[38;5;95;48;5;95m▀▀▀▀[48;5;239m▀[38;5;138;48;5;138m▀[38;5;181;48;5;181m▀[38;5;244;48;5;247m▀[38;5;240;48;5;240m▀[38;5;239m▀[38;5;240m▀[38;5;239m▀▀▀▀[38;5;240m▀▀▀▀[48;5;59m▀▀▀▀▀[38;5;59m▀[38;5;240m▀[38;5;59m▀[38;5;241;48;5;241m▀[38;5;65;48;5;65m▀▀[38;5;101;48;5;101m▀[0m
|
||||
[38;5;150;48;5;231m▀[38;5;187m▀[38;5;255;48;5;255m▀[38;5;231m▀[48;5;224m▀[38;5;255m▀[38;5;231;48;5;231m▀[38;5;255;48;5;255m▀[38;5;231;48;5;254m▀[38;5;254;48;5;224m▀[38;5;224m▀[38;5;181;48;5;252m▀[38;5;231;48;5;255m▀[48;5;231m▀▀▀▀▀▀▀[38;5;255;48;5;255m▀[38;5;254m▀[38;5;224;48;5;254m▀[38;5;181;48;5;253m▀[38;5;239;48;5;138m▀[38;5;95;48;5;95m▀[38;5;131m▀▀▀[38;5;95m▀▀▀▀▀▀▀[38;5;240;48;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀[38;5;238m▀▀[38;5;239m▀[38;5;238m▀[38;5;239;48;5;240m▀[48;5;95m▀[38;5;95m▀▀[48;5;240m▀[48;5;239m▀[38;5;239;48;5;238m▀[38;5;237;48;5;95m▀[38;5;248;48;5;181m▀[38;5;181;48;5;251m▀[38;5;249m▀[38;5;59;48;5;247m▀[48;5;242m▀[38;5;240;48;5;241m▀▀[48;5;59m▀▀▀[48;5;241m▀[38;5;59;48;5;242m▀▀[38;5;241m▀[48;5;65m▀▀▀▀[38;5;59;48;5;241m▀▀[48;5;59m▀▀[38;5;241;48;5;241m▀[38;5;65;48;5;65m▀▀[38;5;101;48;5;101m▀[0m
|
||||
[38;5;255;48;5;253m▀[38;5;224;48;5;252m▀[48;5;188m▀[38;5;188m▀[48;5;253m▀[38;5;255;48;5;231m▀[38;5;231m▀[38;5;255;48;5;224m▀[38;5;224m▀▀[38;5;252;48;5;252m▀▀[38;5;254;48;5;253m▀[38;5;231;48;5;231m▀▀▀▀▀▀▀[38;5;255m▀[48;5;255m▀▀[38;5;254;48;5;254m▀[38;5;224m▀[38;5;95;48;5;181m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;239m▀[38;5;240m▀[38;5;239m▀▀[38;5;240m▀[38;5;239;48;5;239m▀▀[38;5;240m▀[48;5;95m▀[38;5;95;48;5;239m▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239m▀[38;5;238;48;5;238m▀[48;5;138m▀[38;5;181;48;5;181m▀[48;5;251m▀[48;5;181m▀[38;5;251;48;5;251m▀[38;5;252;48;5;252m▀[38;5;188;48;5;224m▀[38;5;246m▀[38;5;243;48;5;181m▀[48;5;246m▀[38;5;244;48;5;108m▀▀[38;5;102;48;5;247m▀▀[38;5;244;48;5;108m▀▀▀[48;5;245m▀[38;5;243;48;5;244m▀[38;5;65m▀[48;5;243m▀[38;5;241;48;5;65m▀[38;5;59;48;5;241m▀[48;5;59m▀[38;5;241m▀▀[38;5;65;48;5;65m▀[38;5;101m▀[0m
|
||||
[38;5;252;48;5;252m▀▀[38;5;188;48;5;188m▀[48;5;254m▀[38;5;255;48;5;231m▀[38;5;231m▀[38;5;255;48;5;224m▀[38;5;224m▀▀[48;5;188m▀[38;5;252;48;5;252m▀▀[38;5;224;48;5;254m▀[38;5;231;48;5;255m▀[48;5;231m▀▀▀▀▀▀[48;5;255m▀[38;5;255m▀▀▀[38;5;224;48;5;254m▀[38;5;253;48;5;188m▀[38;5;181;48;5;138m▀[38;5;240;48;5;95m▀[38;5;95m▀▀▀[48;5;240m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀[38;5;239;48;5;239m▀▀[38;5;240;48;5;95m▀[38;5;95m▀[48;5;240m▀[38;5;239;48;5;239m▀▀[38;5;238;48;5;238m▀[48;5;95m▀[38;5;181;48;5;138m▀[48;5;251m▀[38;5;251m▀[38;5;181m▀[38;5;251m▀[38;5;252m▀▀[48;5;181m▀▀[38;5;250;48;5;252m▀[38;5;247;48;5;250m▀[48;5;248m▀[38;5;248;48;5;145m▀▀▀[38;5;247;48;5;248m▀[38;5;108m▀[48;5;247m▀[38;5;245;48;5;108m▀[38;5;102m▀[38;5;244;48;5;102m▀[38;5;243;48;5;101m▀[38;5;65;48;5;65m▀[38;5;241m▀[38;5;240;48;5;241m▀[48;5;240m▀▀[38;5;65m▀[0m
|
||||
[38;5;252;48;5;252m▀▀[38;5;188;48;5;253m▀[38;5;255;48;5;255m▀[38;5;231;48;5;231m▀[38;5;255;48;5;224m▀[38;5;224;48;5;188m▀▀▀[38;5;188;48;5;252m▀[38;5;252m▀[38;5;188;48;5;253m▀[38;5;253;48;5;224m▀[38;5;255;48;5;254m▀[38;5;231;48;5;231m▀▀▀▀▀▀▀[38;5;255m▀▀[38;5;231;48;5;182m▀[38;5;181;48;5;181m▀▀▀[38;5;95m▀[48;5;95m▀▀[38;5;240m▀[38;5;239;48;5;239m▀▀▀▀[38;5;95;48;5;240m▀[48;5;95m▀▀▀▀▀[38;5;240m▀[48;5;240m▀[38;5;239m▀[38;5;95;48;5;95m▀▀[48;5;240m▀[38;5;239;48;5;239m▀▀▀[38;5;237;48;5;236m▀[38;5;138;48;5;95m▀[38;5;181;48;5;248m▀[38;5;239m▀[38;5;181;48;5;95m▀[38;5;251;48;5;251m▀[48;5;181m▀[48;5;251m▀▀[38;5;181;48;5;181m▀▀▀[38;5;251m▀[38;5;252;48;5;252m▀[38;5;250m▀[38;5;249m▀[48;5;251m▀[48;5;249m▀[38;5;145m▀[38;5;144;48;5;248m▀[38;5;108;48;5;144m▀▀▀[48;5;108m▀▀[38;5;245m▀[38;5;244;48;5;102m▀[38;5;243;48;5;101m▀[38;5;65m▀▀[0m
|
||||
[38;5;252;48;5;252m▀[48;5;188m▀[38;5;254;48;5;254m▀[38;5;231;48;5;231m▀[48;5;255m▀[38;5;253;48;5;188m▀[38;5;188m▀[48;5;252m▀[38;5;252m▀▀▀[38;5;253;48;5;253m▀[48;5;254m▀[48;5;253m▀[38;5;255;48;5;255m▀[38;5;231;48;5;231m▀▀▀▀▀▀[48;5;254m▀[38;5;188;48;5;175m▀[38;5;181;48;5;181m▀[48;5;138m▀[48;5;181m▀▀[38;5;252;48;5;252m▀[38;5;188;48;5;224m▀[38;5;95;48;5;138m▀[48;5;95m▀▀[38;5;240m▀[38;5;239;48;5;239m▀[48;5;240m▀[48;5;239m▀▀[38;5;95m▀[38;5;240m▀[48;5;95m▀▀▀▀[38;5;95m▀▀▀[38;5;239m▀[48;5;239m▀▀▀[38;5;236;48;5;236m▀[38;5;95;48;5;95m▀[38;5;145;48;5;145m▀[38;5;181;48;5;181m▀[38;5;95;48;5;95m▀[38;5;181;48;5;248m▀[38;5;250;48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181;48;5;181m▀▀▀▀▀[38;5;252;48;5;251m▀▀[48;5;252m▀▀[38;5;251;48;5;188m▀[38;5;145;48;5;252m▀[38;5;144;48;5;250m▀[48;5;248m▀[48;5;144m▀[48;5;108m▀[38;5;108m▀▀▀[48;5;144m▀▀▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;188;48;5;188m▀[38;5;255;48;5;255m▀[38;5;231;48;5;231m▀[38;5;254;48;5;188m▀[38;5;188;48;5;252m▀▀[38;5;252m▀▀▀[48;5;188m▀[38;5;254;48;5;254m▀[38;5;253;48;5;253m▀▀[38;5;255;48;5;254m▀[48;5;255m▀▀[38;5;231;48;5;231m▀▀▀▀[38;5;252;48;5;175m▀[38;5;181;48;5;181m▀▀▀▀[48;5;252m▀[38;5;224;48;5;188m▀[38;5;181;48;5;138m▀[38;5;95;48;5;95m▀▀▀[38;5;239m▀▀[48;5;240m▀[48;5;239m▀▀[48;5;240m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀[48;5;240m▀[38;5;239;48;5;239m▀[38;5;235;48;5;95m▀[38;5;95;48;5;137m▀[38;5;181;48;5;181m▀[48;5;251m▀[38;5;95;48;5;131m▀[38;5;138;48;5;248m▀[38;5;181;48;5;251m▀▀▀▀[48;5;181m▀▀▀▀▀[38;5;251m▀[38;5;181m▀[38;5;252m▀▀[48;5;251m▀[38;5;188;48;5;252m▀[38;5;252m▀[38;5;250;48;5;188m▀[38;5;144;48;5;187m▀[48;5;249m▀[48;5;144m▀▀▀▀[48;5;150m▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;188;48;5;253m▀[38;5;255;48;5;231m▀[48;5;224m▀[38;5;252;48;5;252m▀▀[48;5;251m▀[38;5;251m▀▀[38;5;252;48;5;252m▀[38;5;188;48;5;188m▀[38;5;254;48;5;253m▀[38;5;253;48;5;188m▀[38;5;254;48;5;254m▀▀[38;5;255;48;5;255m▀▀▀[38;5;231m▀[48;5;231m▀[38;5;255;48;5;255m▀[38;5;132;48;5;138m▀[38;5;181;48;5;181m▀▀▀▀[38;5;188;48;5;252m▀[38;5;138;48;5;95m▀[38;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;138m▀[38;5;138m▀[38;5;137m▀[38;5;248;48;5;181m▀[38;5;181;48;5;95m▀[38;5;132;48;5;132m▀[38;5;181;48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181m▀[38;5;251m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀▀[38;5;251m▀[38;5;252m▀[48;5;251m▀▀[38;5;187;48;5;252m▀▀[38;5;144;48;5;187m▀[38;5;150m▀▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;254;48;5;254m▀[38;5;255;48;5;255m▀[38;5;252;48;5;252m▀▀[48;5;251m▀[38;5;251m▀[38;5;181;48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;188;48;5;252m▀[38;5;253;48;5;188m▀[38;5;252;48;5;252m▀[38;5;253;48;5;188m▀[38;5;254;48;5;253m▀[38;5;253;48;5;188m▀[38;5;255;48;5;255m▀▀▀[38;5;231;48;5;231m▀[38;5;224;48;5;252m▀[38;5;175;48;5;181m▀[38;5;174;48;5;132m▀[38;5;181;48;5;181m▀[38;5;252;48;5;188m▀[48;5;224m▀[38;5;224;48;5;138m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀[48;5;131m▀[48;5;95m▀▀▀▀▀▀[38;5;131m▀[48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀[38;5;239m▀[38;5;181;48;5;181m▀[38;5;138m▀[48;5;138m▀[48;5;145m▀[48;5;138m▀[48;5;181m▀[38;5;181m▀▀▀[38;5;251m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀[38;5;252;48;5;252m▀▀[38;5;251;48;5;251m▀[38;5;181;48;5;181m▀[38;5;187m▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;255;48;5;255m▀[38;5;254;48;5;188m▀[38;5;181;48;5;181m▀▀[38;5;251m▀▀[38;5;181m▀▀▀[38;5;252;48;5;252m▀▀▀▀[38;5;253;48;5;188m▀[38;5;188m▀[38;5;224;48;5;252m▀[48;5;254m▀[38;5;255;48;5;231m▀[38;5;231;48;5;255m▀[38;5;251;48;5;181m▀[38;5;181m▀[38;5;138m▀[38;5;181;48;5;138m▀[38;5;255;48;5;255m▀[38;5;188;48;5;181m▀[38;5;95;48;5;138m▀[48;5;95m▀▀▀▀▀▀▀▀[38;5;137m▀[48;5;137m▀▀[38;5;95;48;5;95m▀▀[48;5;131m▀[38;5;137m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀▀[38;5;181;48;5;181m▀▀[48;5;138m▀[38;5;138;48;5;181m▀[38;5;181;48;5;138m▀[38;5;138;48;5;181m▀[38;5;181;48;5;251m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;188;48;5;254m▀[38;5;255;48;5;253m▀[38;5;251;48;5;181m▀[38;5;181m▀▀▀▀▀▀[38;5;251m▀[38;5;252;48;5;251m▀[48;5;252m▀[48;5;251m▀▀[48;5;252m▀▀[38;5;251m▀[38;5;255;48;5;254m▀[38;5;231;48;5;255m▀[38;5;188;48;5;182m▀[38;5;181m▀[48;5;251m▀▀[38;5;138;48;5;181m▀[38;5;224;48;5;95m▀[38;5;181;48;5;181m▀▀[38;5;95m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131m▀▀[38;5;95m▀▀▀▀[38;5;137;48;5;180m▀[38;5;181;48;5;181m▀▀▀[38;5;145m▀[38;5;132;48;5;138m▀[38;5;181;48;5;251m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;254;48;5;224m▀[38;5;252;48;5;181m▀[38;5;181m▀▀▀▀▀▀[48;5;251m▀▀[38;5;251m▀[38;5;252;48;5;252m▀[38;5;251;48;5;251m▀▀[38;5;252m▀[48;5;252m▀[48;5;251m▀[48;5;181m▀▀[38;5;181m▀[38;5;251;48;5;251m▀▀▀[38;5;181m▀[38;5;138;48;5;181m▀[48;5;138m▀[38;5;181m▀[48;5;181m▀▀[38;5;137m▀[38;5;95;48;5;138m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;138m▀[38;5;180;48;5;181m▀[38;5;181;48;5;95m▀▀[48;5;248m▀[38;5;249;48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;145;48;5;248m▀[38;5;181;48;5;181m▀▀[48;5;145m▀[0m
|
||||
[38;5;188;48;5;251m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀▀▀▀▀[38;5;252;48;5;252m▀[38;5;251;48;5;251m▀▀▀[48;5;252m▀[38;5;252m▀[38;5;181;48;5;251m▀[48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181m▀[38;5;138;48;5;181m▀[38;5;95;48;5;138m▀[38;5;181;48;5;131m▀▀[48;5;181m▀[38;5;137m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131;48;5;181m▀[38;5;181;48;5;248m▀[38;5;138;48;5;181m▀[38;5;96m▀[38;5;248m▀[38;5;181m▀▀▀▀[38;5;249m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;145m▀[38;5;181m▀▀▀[38;5;145m▀[38;5;181m▀[48;5;145m▀[38;5;145;48;5;248m▀[0m
|
||||
[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀▀[48;5;181m▀[38;5;181m▀[38;5;251m▀[48;5;251m▀▀[38;5;181;48;5;181m▀▀[38;5;251;48;5;251m▀[38;5;188;48;5;188m▀[38;5;251;48;5;252m▀[48;5;181m▀[38;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181m▀[48;5;181m▀▀[48;5;251m▀[38;5;138;48;5;188m▀[38;5;174;48;5;181m▀[38;5;181;48;5;138m▀[38;5;95;48;5;181m▀[48;5;95m▀▀▀▀▀▀▀▀[48;5;138m▀[38;5;138;48;5;248m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[48;5;249m▀[38;5;145;48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;248m▀[48;5;181m▀▀▀▀▀[48;5;145m▀[48;5;181m▀▀▀[38;5;145;48;5;248m▀▀[0m
|
||||
[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀▀[38;5;181;48;5;181m▀▀▀[48;5;250m▀[48;5;181m▀▀▀▀[38;5;252;48;5;251m▀[48;5;252m▀[38;5;251;48;5;251m▀[38;5;181;48;5;181m▀▀[38;5;251;48;5;251m▀▀▀[38;5;181;48;5;181m▀[38;5;188;48;5;251m▀[38;5;181;48;5;253m▀[48;5;254m▀[38;5;182;48;5;181m▀[38;5;181;48;5;251m▀[48;5;181m▀[38;5;95;48;5;138m▀[48;5;95m▀▀▀▀▀[38;5;138;48;5;181m▀[38;5;248;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[38;5;249;48;5;249m▀[48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;145m▀[38;5;248;48;5;248m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[38;5;145;48;5;145m▀[38;5;248;48;5;248m▀▀[0m
|
||||
[38;5;181;48;5;249m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;250;48;5;250m▀[38;5;181;48;5;181m▀▀▀▀[38;5;251;48;5;251m▀[38;5;252m▀[48;5;252m▀[38;5;181;48;5;251m▀[48;5;181m▀▀[38;5;251m▀▀[38;5;181m▀▀[38;5;251;48;5;251m▀[38;5;181m▀[38;5;251;48;5;181m▀[38;5;181m▀[38;5;251;48;5;251m▀[38;5;181m▀[38;5;95;48;5;138m▀[48;5;95m▀▀[48;5;238m▀[38;5;248;48;5;181m▀[48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[38;5;249m▀[48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀[48;5;249m▀[48;5;181m▀▀▀▀▀[38;5;248;48;5;145m▀[48;5;248m▀[38;5;181;48;5;145m▀[48;5;181m▀▀▀▀▀[38;5;248;48;5;145m▀[48;5;248m▀▀[0m
|
||||
[38;5;145;48;5;145m▀▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;251m▀[48;5;251m▀▀[38;5;181m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;95;48;5;95m▀[38;5;240;48;5;239m▀[38;5;138;48;5;181m▀[38;5;181m▀[38;5;249m▀[38;5;181m▀▀▀▀▀▀▀[38;5;145;48;5;145m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀[48;5;249m▀[38;5;249;48;5;181m▀▀[38;5;181m▀▀▀▀▀[48;5;249m▀[38;5;249;48;5;145m▀[38;5;181;48;5;181m▀▀▀▀▀[38;5;145m▀[38;5;248;48;5;248m▀▀[38;5;145;48;5;145m▀[38;5;181m▀▀[48;5;181m▀[48;5;145m▀[38;5;145m▀[38;5;248;48;5;248m▀▀[0m
|
||||
[38;5;145;48;5;248m▀[48;5;145m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀[48;5;249m▀▀[48;5;181m▀▀▀▀▀▀▀▀[38;5;251m▀▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;252;48;5;251m▀[38;5;240;48;5;240m▀[38;5;95;48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀[48;5;145m▀[38;5;248m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀[48;5;249m▀▀[38;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀[48;5;249m▀[38;5;145;48;5;145m▀[38;5;181m▀[48;5;249m▀[48;5;145m▀[48;5;181m▀▀[38;5;249m▀[38;5;248;48;5;248m▀▀▀[38;5;145m▀▀▀▀[38;5;248m▀[38;5;138m▀[38;5;248;48;5;247m▀[0m
|
||||
[38;5;145;48;5;248m▀[48;5;145m▀[38;5;249m▀[48;5;249m▀[38;5;181m▀▀[48;5;181m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀[48;5;249m▀[38;5;249m▀[38;5;181m▀[38;5;249m▀[38;5;181;48;5;181m▀▀[48;5;249m▀[48;5;181m▀[48;5;249m▀[38;5;250;48;5;250m▀[38;5;181;48;5;181m▀▀▀▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀[38;5;249;48;5;249m▀[38;5;181m▀[48;5;181m▀▀▀▀▀▀[38;5;95m▀[38;5;181m▀▀▀▀▀▀▀[48;5;249m▀[48;5;181m▀[38;5;249;48;5;249m▀[38;5;145;48;5;248m▀[48;5;249m▀[38;5;249m▀[48;5;181m▀[38;5;181m▀[38;5;249;48;5;249m▀[38;5;145;48;5;145m▀▀▀[38;5;181m▀[48;5;249m▀▀▀[38;5;249;48;5;145m▀[38;5;145m▀▀[38;5;181m▀[38;5;249m▀▀[38;5;181m▀▀[38;5;145;48;5;181m▀[48;5;145m▀[38;5;248;48;5;248m▀▀▀▀▀▀▀[48;5;138m▀[38;5;247m▀[0m
|
||||
[38;5;248;48;5;248m▀[38;5;145m▀[48;5;145m▀▀▀[38;5;249m▀[48;5;249m▀▀▀[38;5;181m▀▀[38;5;249m▀[48;5;145m▀▀[48;5;249m▀▀[38;5;181m▀▀[38;5;249m▀[48;5;145m▀[48;5;249m▀[48;5;145m▀[38;5;181;48;5;249m▀▀[48;5;181m▀▀[38;5;249;48;5;249m▀▀[38;5;181m▀[38;5;249m▀▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀[48;5;145m▀[38;5;145m▀[38;5;181m▀[48;5;181m▀▀▀[38;5;249;48;5;249m▀[38;5;181m▀[38;5;145;48;5;248m▀[38;5;248m▀[38;5;249;48;5;181m▀[48;5;249m▀[38;5;181m▀▀[38;5;145;48;5;145m▀[48;5;248m▀▀[48;5;145m▀[38;5;249m▀▀[48;5;249m▀[38;5;145;48;5;145m▀▀[48;5;248m▀[38;5;248m▀▀▀▀▀[38;5;145m▀[48;5;145m▀▀[38;5;248;48;5;248m▀[48;5;138m▀[48;5;248m▀▀▀[48;5;247m▀▀[48;5;138m▀[38;5;138m▀[0m
|
||||
|
||||
The αcτµαlly pδrταblε εxεcµταblε software is dedicated to:
|
||||
|
||||
Mark "Zibo" Joseph Zbikowski
|
||||
Architect @ Microsoft Corporation & Early Computer Hacker
|
||||
Whose Initials Grace Every Executable
|
||||
|
0
ape/notice.inc
Normal file
0
ape/notice.inc
Normal file
67
ape/relocations.h
Normal file
67
ape/relocations.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef COSMOPOLITAN_APE_RELOCATIONS_H_
|
||||
#define COSMOPOLITAN_APE_RELOCATIONS_H_
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § relocations │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
One of the things αcτµαlly pδrταblε εxεcµταblε does a good job
|
||||
abstracting, is how a program needs to exist at three addresses
|
||||
simultaneously during the early stages of the loading process.
|
||||
|
||||
By default, the linker calculates all symbols using virtual addresses.
|
||||
In some cases it's necessary to use addend macros that change virtual
|
||||
addresses into the other two types: physical and real. */
|
||||
|
||||
#ifndef IMAGE_BASE_VIRTUAL
|
||||
#define IMAGE_BASE_VIRTUAL 0x400000
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_BASE_PHYSICAL
|
||||
#define IMAGE_BASE_PHYSICAL 0x100000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Location of anything goes memory for real mode.
|
||||
*
|
||||
* The MBR won't load program content beyond this address, so we have
|
||||
* room for buffers, page tables, etc. before we reach the stack frame.
|
||||
*/
|
||||
#ifndef REAL_SCRATCH_AREA
|
||||
#define REAL_SCRATCH_AREA 0x40000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Location of real mode 64kb stack frame.
|
||||
*
|
||||
* This address was chosen because memory beyond 0x80000 can't be
|
||||
* accessed safely without consulting e820.
|
||||
*/
|
||||
#ifndef REAL_STACK_FRAME
|
||||
#define REAL_STACK_FRAME 0x70000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns Relative Virtual Address.
|
||||
*/
|
||||
#define RVA(x) ((x) - (IMAGE_BASE_VIRTUAL))
|
||||
|
||||
/**
|
||||
* Adjusts virtual address so it's relative to load address.
|
||||
*/
|
||||
#define PHYSICAL(x) ((x) - (IMAGE_BASE_VIRTUAL - IMAGE_BASE_PHYSICAL))
|
||||
|
||||
/**
|
||||
* Makes high-entropy read-only addresses relocatable in real mode.
|
||||
*/
|
||||
#define REAL(x) ((x) - (IMAGE_BASE_VIRTUAL - IMAGE_BASE_REAL))
|
||||
|
||||
#if IMAGE_BASE_VIRTUAL % 0x200000 != 0
|
||||
#error "IMAGE_BASE_VIRTUAL must be 2mb aligned"
|
||||
#endif
|
||||
#if IMAGE_BASE_PHYSICAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_PHYSICAL must be 4kb aligned"
|
||||
#endif
|
||||
#if IMAGE_BASE_REAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_REAL must be 4kb aligned"
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_RELOCATIONS_H_ */
|
28
build/actuallynice
Executable file
28
build/actuallynice
Executable file
|
@ -0,0 +1,28 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Program Deprioritizer
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# This is a drop-in replacement for the traditional Unix `nice`
|
||||
# command that also invokes `ionice`, which is important, since
|
||||
# network and traffic is usually what clobber the system.
|
||||
|
||||
if [ -z "$IONICE" ]; then
|
||||
if IONICE=$(command -v ionice 2>/dev/null); then
|
||||
IONICE="$IONICE -c3"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$NICE" ]; then
|
||||
NICE=$(command -v nice 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ -z "$IONICE$NICE" ]; then
|
||||
echo "error: can't be nice" >&2
|
||||
fi
|
||||
|
||||
exec $IONICE $NICE "$@"
|
80
build/archive
Executable file
80
build/archive
Executable file
|
@ -0,0 +1,80 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# GNU Archiver Veneer
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This script wraps normal archive commands that're transparently
|
||||
# passed-through. It adds value too, by addressing difficulties
|
||||
# that would normally cause a developer to need `make clean`.
|
||||
#
|
||||
# EXAMPLE
|
||||
#
|
||||
# build/archive ar rcsD library.a foo.o ...
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
export LC_ALL=C
|
||||
RM=${RM:-$(command -v rm) -f} || exit
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
AR=$1
|
||||
ARFLAGS=$2
|
||||
OUT=$3
|
||||
shift 3
|
||||
|
||||
# remove directory arguments (having .a targets depend on dirs is what
|
||||
# lets them be invalidated by deleted files)
|
||||
FIRST=1
|
||||
for x; do
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set --
|
||||
FIRST=0
|
||||
fi
|
||||
if [ -d "$x" ]; then
|
||||
if [ -f "$OUT" ] && [ "$x" -nt "$OUT" ]; then
|
||||
$RM "$OUT"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
if [ "$x" != "${x%.o}" ]; then
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
done
|
||||
|
||||
set -- "$AR" "$ARFLAGS" "$OUT" "$@"
|
||||
|
||||
OUTDIR="${OUT%/*}"
|
||||
if [ "$OUTDIR" != "$OUT" ] && [ ! -d "$OUTDIR" ]; then
|
||||
$MKDIR "$OUTDIR" || exit 2
|
||||
fi
|
||||
|
||||
printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2
|
||||
# if [ "$SILENT" = "0" ]; then
|
||||
# # some of these windows nt archives are quite huge
|
||||
# COLUMNS=${COLUMNS:-80}
|
||||
# COLUMNS=$((COLUMNS - 4))
|
||||
# printf "%s\n" "$*" |
|
||||
# /usr/bin/fold -s -w $COLUMNS |
|
||||
# sed -e '1bb' -e 's/^/ /' -e ':b' -e '$b' -e 's/$/ \\/' >&2
|
||||
# else
|
||||
# printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2
|
||||
# fi
|
||||
|
||||
REASON=failed
|
||||
trap REASON=interrupted INT
|
||||
|
||||
"$@" >/dev/null && exit
|
||||
|
||||
if [ "$TERM" = "dumb" ]; then
|
||||
f='%s %s\r\n\r\n'
|
||||
else
|
||||
f='\033[91m%s\033[39m \033[94m%s\033[39m\r\n\r\n'
|
||||
fi
|
||||
printf "$f" "archive $REASON:" "$*" >&2
|
||||
exit 1
|
49
build/assemble
Executable file
49
build/assemble
Executable file
|
@ -0,0 +1,49 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# GNU Assembler Veneer
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This script wraps normal assembler commands that're transparently
|
||||
# passed-through. It adds ephemeral logging and directory creation.
|
||||
#
|
||||
# EXAMPLE
|
||||
#
|
||||
# TARGET=program build/assemble as -o program program.o
|
||||
#
|
||||
# SEE ALSO
|
||||
#
|
||||
# https://justine.storage.googleapis.com/perm/as.pdf
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
export LC_ALL=C
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-OBJECTIFY.s}" "$TARGET" >&2
|
||||
fi
|
||||
|
||||
if [ "$TARGET" ]; then
|
||||
TARGETDIR="${TARGET%/*}"
|
||||
if [ "$TARGETDIR" != "$TARGET" ] && [ ! -d "$TARGETDIR" ]; then
|
||||
$MKDIR "$TARGETDIR" || exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
"$@" && exit
|
||||
|
||||
if [ "$TERM" = "dumb" ]; then
|
||||
f='%s %s\r\n\r\n'
|
||||
else
|
||||
f='\033[91m%s\033[39m \033[94m%s\033[39m\r\n\r\n'
|
||||
fi
|
||||
printf "$f" "assemble failed:" "$*" >&2
|
||||
exit 1
|
8
build/bochs-debugger
Executable file
8
build/bochs-debugger
Executable file
|
@ -0,0 +1,8 @@
|
|||
# -*- mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8 -*-
|
||||
# vi: set net ft=sh ts=2 sts=2 sw=2 fenc=utf-8 :vi
|
||||
|
||||
echo c |
|
||||
bochs \
|
||||
-q \
|
||||
-f ape/etc/bochsrc.dbg \
|
||||
floppya:1_44=$1,status=inserted
|
51
build/bochs-scriptable
Executable file
51
build/bochs-scriptable
Executable file
|
@ -0,0 +1,51 @@
|
|||
#!/bin/sh
|
||||
# -*- mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8 -*-
|
||||
# vi: set net ft=sh ts=2 sts=2 sw=2 fenc=utf-8 :vi
|
||||
#
|
||||
# bochs-scriptable executes a disk with serial uart stdio.
|
||||
#
|
||||
# USAGE
|
||||
#
|
||||
# build/bochs-scriptable IMAGE...
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This script is useful for end-to-end testing metal apps in <100ms.
|
||||
#
|
||||
# SEE ALSO
|
||||
#
|
||||
# build/boot(1)
|
||||
|
||||
while getopts h X; do
|
||||
case $X in
|
||||
h) exec less "$0" ;;
|
||||
\?) echo "$0: bad arg" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
trap '' INT
|
||||
|
||||
IMG=$1
|
||||
OUT=/tmp/$USER.$$.bochs.stdout
|
||||
ERR=/tmp/$USER.$$.bochs.stderr
|
||||
|
||||
mkfifo $OUT || exit
|
||||
|
||||
cat <$OUT &
|
||||
CAT=$!
|
||||
exec 4>$OUT
|
||||
rm -f $OUT
|
||||
|
||||
echo c |
|
||||
bochs \
|
||||
-q \
|
||||
-f ape/etc/bochsrc.ffs \
|
||||
display_library:nogui \
|
||||
floppya:1_44=$1,status=inserted \
|
||||
>>$ERR 2>>$ERR
|
||||
RC=$?
|
||||
|
||||
kill $CAT
|
||||
exec 4>&-
|
||||
rm -f $ERR
|
BIN
build/bootstrap/mkdeps.com
Executable file
BIN
build/bootstrap/mkdeps.com
Executable file
Binary file not shown.
BIN
build/bootstrap/net/http/uricspn.c.gz
Normal file
BIN
build/bootstrap/net/http/uricspn.c.gz
Normal file
Binary file not shown.
BIN
build/bootstrap/net/http/uriparse.c.gz
Normal file
BIN
build/bootstrap/net/http/uriparse.c.gz
Normal file
Binary file not shown.
BIN
build/bootstrap/package.com
Executable file
BIN
build/bootstrap/package.com
Executable file
Binary file not shown.
BIN
build/bootstrap/zipobj.com
Executable file
BIN
build/bootstrap/zipobj.com
Executable file
Binary file not shown.
20
build/catcode
Executable file
20
build/catcode
Executable file
|
@ -0,0 +1,20 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Source File Concatenation Tool
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This program is the same as cat, but inserts preprocessor directives
|
||||
# that allow compiler errors to point back to the original lines.
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
cat
|
||||
else
|
||||
for x; do
|
||||
printf '# 1 "%s"\n' "$x"
|
||||
cat "$x"
|
||||
done
|
||||
fi
|
279
build/compile
Executable file
279
build/compile
Executable file
|
@ -0,0 +1,279 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# GNU/LLVM Compiler Frontend Frontend
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This wrapper script filters out certain flags so the compiler won't
|
||||
# whine, and passes extra information to the preprocessor.
|
||||
#
|
||||
# EXAMPLE
|
||||
#
|
||||
# build/compile cc -o program program.c
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
if [ "$1" = "clang-10" ]; then
|
||||
if ! command -v clang-10 >/dev/null; then
|
||||
shift
|
||||
set -- o/third_party/gcc/bin/x86_64-linux-musl-gcc "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "clang++-10" ]; then
|
||||
if ! command -v clang++-10 >/dev/null; then
|
||||
shift
|
||||
set -- o/third_party/gcc/bin/x86_64-linux-musl-g++ "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
export LC_ALL=C
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
GZME=
|
||||
PLAT="${1%% *}"
|
||||
FDIAGNOSTIC_COLOR=
|
||||
CCNAME=${CCNAME:-gcc}
|
||||
CCVERSION=${CCVERSION:-4}
|
||||
COUNTERMAND=
|
||||
|
||||
# The GNU Compiler Collection passes a lot of CFLAGS to the preprocessor
|
||||
# (which we call CCFLAGS) but it should pass more; and we do just that.
|
||||
FIRST=1
|
||||
OUTARG=0
|
||||
INVISIBLE=0
|
||||
for x; do
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set --
|
||||
FIRST=0
|
||||
fi
|
||||
if [ $OUTARG -eq 1 ]; then
|
||||
OUTARG=0
|
||||
OUT="$x"
|
||||
fi
|
||||
case "$x" in
|
||||
-o)
|
||||
set -- "$@" "$x"
|
||||
OUTARG=1
|
||||
;;
|
||||
-w)
|
||||
set -- "$@" "$x" -D__W__
|
||||
;;
|
||||
-pg)
|
||||
if [ $INVISIBLE -eq 0 ]; then
|
||||
set -- "$@" "$x" -D__PG__ # @see libc/macros.h
|
||||
fi
|
||||
;;
|
||||
-mfentry)
|
||||
if [ $INVISIBLE -eq 0 ]; then
|
||||
set -- "$@" "$x" -D__MFENTRY__
|
||||
fi
|
||||
;;
|
||||
-fomit-frame-pointer)
|
||||
INVISIBLE=1
|
||||
set -- "$@" "$x"
|
||||
;;
|
||||
-mno-vzeroupper)
|
||||
set -- "$@" "$x" -Wa,-msse2avx -D__MNO_VZEROUPPER__
|
||||
;;
|
||||
-fsanitize=undefined)
|
||||
set -- "$@" "$x" -D__FSANITIZE_UNDEFINED__
|
||||
COUNTERMAND="$COUNTERMAND -fno-data-sections" # sqlite.o
|
||||
;;
|
||||
-mnop-mcount)
|
||||
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 6 ]; then
|
||||
set -- "$@" "$x" -D__MNOP_MCOUNT__
|
||||
fi
|
||||
;;
|
||||
-mrecord-mcount)
|
||||
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 6 ]; then
|
||||
set -- "$@" "$x" -D__MRECORD_MCOUNT__
|
||||
fi
|
||||
;;
|
||||
-fsanitize=implicit*integer*)
|
||||
if ! [ "$CCNAME" = "gcc" ]; then
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
;;
|
||||
-f*sanitize*|-gz*|-*stack-protector*|-fvect-cost*|-mstringop*)
|
||||
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 6 ]; then
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
;;
|
||||
-freorder-blocks-and-partition|-fstack-clash-protection)
|
||||
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 8 ]; then
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
;;
|
||||
-fdiagnostic-color=*)
|
||||
FDIAGNOSTIC_COLOR=$x
|
||||
;;
|
||||
-fopt-info*=*.optinfo)
|
||||
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 9 ]; then
|
||||
GZME="$GZME ${x##*=}"
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
;;
|
||||
-R*) # e.g. clang's -Rpass-missed=all
|
||||
if [ "${PLAT#*clang}" != "${PLAT}" ]; then
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
;;
|
||||
-fsave-optimization-record) # clang only
|
||||
if [ "${PLAT#*clang}" != "${PLAT}" ]; then
|
||||
set -- "$@" "$x"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
set -- "$@" "$x"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -z "$FDIAGNOSTIC_COLOR" ] && [ "$TERM" != "dumb" ]; then
|
||||
FDIAGNOSTIC_COLOR=-fdiagnostics-color=always
|
||||
fi
|
||||
|
||||
if [ "${PLAT#*clang}" != "${PLAT}" ]; then
|
||||
FIRST=1
|
||||
for x; do
|
||||
# clang's assembler isn't complete yet
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set -- \
|
||||
"$x" \
|
||||
-fno-integrated-as \
|
||||
-Wno-unused-command-line-argument \
|
||||
-Wno-incompatible-pointer-types-discards-qualifiers
|
||||
FIRST=0
|
||||
continue
|
||||
fi
|
||||
# removes flags clang whines about
|
||||
case "$x" in
|
||||
-gstabs) ;;
|
||||
-ffixed-*) ;;
|
||||
-fcall-saved*) ;;
|
||||
-fsignaling-nans) ;;
|
||||
-fcx-limited-range) ;;
|
||||
-fno-fp-int-builtin-inexact) ;;
|
||||
-Wno-unused-but-set-variable) ;;
|
||||
-Wunsafe-loop-optimizations) ;;
|
||||
-ftracer) ;;
|
||||
-frounding-math) ;;
|
||||
-fmerge-constants) ;;
|
||||
-fmodulo-sched) ;;
|
||||
-msse2avx)
|
||||
set -- "$@" -Wa,-msse2avx
|
||||
;;
|
||||
-fopt-info-vec) ;;
|
||||
-fopt-info-vec-missed) ;;
|
||||
-fmodulo-sched-allow-regmoves) ;;
|
||||
-fgcse-*) ;;
|
||||
-freschedule-modulo-scheduled-loops) ;;
|
||||
-freschedule-modulo-scheduled-loops) ;;
|
||||
-fipa-pta) ;;
|
||||
-fsched2-use-superblocks) ;;
|
||||
-fbranch-target-load-optimize) ;;
|
||||
-fdelete-dead-exceptions) ;;
|
||||
-funsafe-loop-optimizations) ;;
|
||||
-fcall-used*) ;;
|
||||
-mmitigate-rop) ;;
|
||||
-mnop-mcount) ;;
|
||||
-fno-align-jumps) ;;
|
||||
-fno-align-labels) ;;
|
||||
-fno-align-loops) ;;
|
||||
-fivopts) ;;
|
||||
-fschedule-insns) ;;
|
||||
-fno-semantic-interposition) ;;
|
||||
-mno-fentry) ;;
|
||||
-f*schedule-insns2) ;;
|
||||
-fvect-cost-model=*) ;;
|
||||
-fsimd-cost-model=*) ;;
|
||||
-fversion-loops-for-strides) ;;
|
||||
-fopt-info*) ;;
|
||||
-f*var-tracking-assignments) ;;
|
||||
-femit-struct-debug-baseonly) ;;
|
||||
-ftree-loop-vectorize) ;;
|
||||
-gdescribe-dies) ;;
|
||||
-flimit-function-alignment) ;;
|
||||
-ftree-loop-im) ;;
|
||||
-fno-instrument-functions) ;;
|
||||
-fstack-clash-protection) ;;
|
||||
-mstringop-strategy=*) ;;
|
||||
-mpreferred-stack-boundary=*) ;;
|
||||
-*stack-protector*) ;; # clang requires segmented memory for this
|
||||
-f*gnu-unique) ;;
|
||||
-Wframe-larger-than=*) ;;
|
||||
-f*whole-program) ;;
|
||||
-Wa,--size-check=*) ;;
|
||||
-Wa,--listing*) ;;
|
||||
-mfpmath=sse+387) ;;
|
||||
-Wa,--noexecstack) ;;
|
||||
-freg-struct-return) ;;
|
||||
-mcall-ms2sysv-xlogues) ;;
|
||||
-mno-vzeroupper)
|
||||
set -- "$@" -mllvm -x86-use-vzeroupper=0
|
||||
;;
|
||||
-Wa,-a*)
|
||||
x="${x#*=}"
|
||||
if [ "$x" ] && [ -p "$x" ]; then
|
||||
printf '' >"$x"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
set -- "$@" "$x"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
# removes flags only clang supports
|
||||
FIRST=1
|
||||
for x; do
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set --
|
||||
FIRST=0
|
||||
fi
|
||||
case "$x" in
|
||||
-Oz) set -- "$@" -Os ;;
|
||||
*) set -- "$@" "$x" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
set -- "$@" -no-canonical-prefixes $FDIAGNOSTIC_COLOR $COUNTERMAND
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-COMPILE}" "${TARGET:-$OUT}" >&2
|
||||
fi
|
||||
|
||||
OUTDIR="${OUT%/*}"
|
||||
if [ "$OUTDIR" != "$OUT" ] && [ ! -d "$OUTDIR" ]; then
|
||||
$MKDIR "$OUTDIR" || exit 2
|
||||
fi
|
||||
|
||||
REASON=failed
|
||||
trap REASON=interrupted INT
|
||||
|
||||
if "$@"; then
|
||||
for f in $GZME; do
|
||||
if GZ=${GZ:-$(command -v gzip)}; then
|
||||
if [ -f "$f" ]; then
|
||||
build/actuallynice $GZ $ZFLAGS -qf $f &
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TERM" = "dumb" ]; then
|
||||
f='%s %s\r\n\r\n'
|
||||
else
|
||||
f='\033[91m%s\033[39m \033[94m%s\033[39m\r\n\r\n'
|
||||
fi
|
||||
printf "$f" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
|
||||
exit 1
|
152
build/config.mk
Normal file
152
build/config.mk
Normal file
|
@ -0,0 +1,152 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
# Default Mode
|
||||
#
|
||||
# - `make`
|
||||
# - Backtraces
|
||||
# - Function tracing
|
||||
# - Reasonably small
|
||||
# - Reasonably optimized
|
||||
# - Reasonably debuggable
|
||||
|
||||
ifeq ($(MODE),)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-Og
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
RAGELFLAGS ?= -G2
|
||||
|
||||
endif
|
||||
|
||||
# Optimized Mode
|
||||
#
|
||||
# - `make MODE=opt`
|
||||
# - Backtraces
|
||||
# - More optimized
|
||||
# - Reasonably small
|
||||
# - No memory corruption detection
|
||||
# - assert() / CHECK_xx() may leak code into binary for debuggability
|
||||
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
|
||||
|
||||
ifeq ($(MODE), opt)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O3
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
|
||||
RAGELFLAGS ?= -G2
|
||||
|
||||
endif
|
||||
|
||||
# Release Mode
|
||||
#
|
||||
# - `make MODE=rel`
|
||||
# - More optimized
|
||||
# - Reasonably small
|
||||
# - Numeric backtraces
|
||||
# - Toilsome debuggability
|
||||
# - assert() statements removed
|
||||
# - DCHECK_xx() statements removed
|
||||
# - No memory corruption detection
|
||||
# - CHECK_xx() won't leak strings into binary
|
||||
|
||||
ifeq ($(MODE), rel)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O3
|
||||
|
||||
#TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
RAGELFLAGS = -G2
|
||||
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
#
|
||||
# - `make MODE=dbg`
|
||||
# - Backtraces
|
||||
# - Zero optimization
|
||||
# - Enables sanitization
|
||||
# - Enables stack canaries
|
||||
# - Enormous binaries (b/c ubsan suboptimalities)
|
||||
|
||||
ifeq ($(MODE), dbg)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DMODE_DBG
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-fno-inline
|
||||
|
||||
CONFIG_COPTS += \
|
||||
$(SECURITY_BLANKETS) \
|
||||
$(SANITIZER)
|
||||
|
||||
OVERRIDE_CCFLAGS += \
|
||||
-fno-pie
|
||||
|
||||
endif
|
||||
|
||||
# Tiny Mode
|
||||
#
|
||||
# - `make MODE=tiny`
|
||||
# - No checks
|
||||
# - No asserts
|
||||
# - No canaries
|
||||
# - No paranoia
|
||||
# - No avx hooks
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tiny)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# ANSI Mode
|
||||
#
|
||||
# Folks who want it deserve to get it, good and hard.
|
||||
|
||||
ifeq ($(MODE), ansi)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
-std=c11 \
|
||||
-Og
|
||||
|
||||
endif
|
357
build/definitions.mk
Normal file
357
build/definitions.mk
Normal file
|
@ -0,0 +1,357 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan Core Build Definitions
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Nearly all compiler flag tuning is done within this one file. Flags
|
||||
# may be customized with environment variables. We also use this file
|
||||
# to compute expensive values once per build.
|
||||
#
|
||||
# When tuning the variables below, please note they're interpreted in
|
||||
# the strictest sense. For example, we don't pass CFLAGS to gcc if we
|
||||
# know it's compiling a .S file. This allows our `make SILENT=0` logs
|
||||
# to be succinct and informative, at the cost of being less forgiving.
|
||||
#
|
||||
# Further note that link order is equally unforgiving in repositories
|
||||
# of this scale. We approach that by over-specifying dependencies, in
|
||||
# packages that're broken down usually on a per-directory basis. This
|
||||
# is aided by the checkdeps and functional programming tools which in
|
||||
# most cases should be able to deduce correct ordering automatically.
|
||||
#
|
||||
# Concerning our approach to flag tuning, most of it is non-essential
|
||||
# and largely serves to turn features off. Particularly features that
|
||||
# would otherwise lock us in to a particular platform or legal terms.
|
||||
# Other flags will usually be the ones that provide us marginal gains
|
||||
# in terms of performance and code size, but the world won't end when
|
||||
# they aren't used. Flags that play a critical role in source working
|
||||
# correctly will usually be specified on a target-by-target basis, in
|
||||
# their respective packages.
|
||||
#
|
||||
# NOTE might have gotten the per-target override flag flow wrong since
|
||||
# flags defined that way might flow quadratically opposite blaze.
|
||||
#
|
||||
# VARIABLES
|
||||
#
|
||||
# CCFLAGS gcc frontend flags (.i, .c, .cc, .f, .S, .lds, etc.)
|
||||
# CPPFLAGS preprocessor flags (.h, .c, .cc, .S, .inc, .lds, etc.)
|
||||
# CFLAGS c flags (.c only)
|
||||
# CXXFLAGS c++ flags (.cc only)
|
||||
# COPTS c/c++ flags (.c, .cc)
|
||||
# LDFLAGS linker flags (don't use -Wl, frontend prefix)
|
||||
# ASFLAGS assembler flags (don't use -Wa, frontend prefix)
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
|
||||
SHELL = /bin/sh
|
||||
DD ?= /bin/dd
|
||||
CP ?= /bin/cp -f
|
||||
RM ?= /bin/rm -f
|
||||
SED ?= /bin/sed
|
||||
MKDIR ?= /bin/mkdir -p
|
||||
TAGS ?= ctags
|
||||
ARFLAGS = rcsD
|
||||
TAGSFLAGS ?= -e -a --if0=no --langmap=c:.c.h.i --line-directives=yes
|
||||
SILENT ?= 1
|
||||
ZFLAGS ?= -4 --rsyncable
|
||||
XARGS ?= xargs -P4 -rs8000
|
||||
NICE ?= build/actuallynice
|
||||
RAGEL ?= ragel
|
||||
DOT ?= dot
|
||||
GZ ?= gzip
|
||||
CLANG = clang-11
|
||||
FC = gfortran #/opt/cross9f/bin/x86_64-linux-musl-gfortran
|
||||
|
||||
# see build/compile, etc. which run third_party/gcc/unbundle.sh
|
||||
AS = o/third_party/gcc/bin/x86_64-linux-musl-as
|
||||
CC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
CXX = o/third_party/gcc/bin/x86_64-linux-musl-g++
|
||||
LD = o/third_party/gcc/bin/x86_64-linux-musl-ld.bfd
|
||||
AR = o/third_party/gcc/bin/x86_64-linux-musl-ar
|
||||
NM = o/third_party/gcc/bin/x86_64-linux-musl-nm
|
||||
GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-linux-musl-objcopy
|
||||
ADDR2LINE = o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
|
||||
COMMA := ,
|
||||
PWD := $(shell pwd)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
TMPDIR := $(shell build/findtmp)
|
||||
LOGFMT := $(shell build/getlogfmt)
|
||||
CCNAME := $(shell build/getccname $(CC))
|
||||
CCVERSION := $(shell build/getccversion $(CC))
|
||||
BLAH1 := $(shell build/zipobj 2>/dev/null)
|
||||
BLAH2 := $(shell build/package 2>/dev/null)
|
||||
|
||||
export ADDR2LINE
|
||||
export CCNAME
|
||||
export CCVERSION
|
||||
export CP
|
||||
export DD
|
||||
export GZ
|
||||
export IMAGE_BASE_VIRTUAL
|
||||
export LOGFMT
|
||||
export MKDIR
|
||||
export MODE
|
||||
export RM
|
||||
export SED
|
||||
export SILENT
|
||||
export TMPDIR
|
||||
export ZFLAGS
|
||||
|
||||
FTRACE = \
|
||||
-pg
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=undefined \
|
||||
-fsanitize=leak \
|
||||
-fsanitize=implicit-signed-integer-truncation \
|
||||
-fsanitize=implicit-integer-sign-change
|
||||
|
||||
NO_MAGIC = \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fno-sanitize=all
|
||||
|
||||
OLD_CODE = \
|
||||
-fno-strict-aliasing \
|
||||
-fno-strict-overflow
|
||||
|
||||
TRADITIONAL = \
|
||||
-Wno-implicit-int \
|
||||
-Wno-return-type \
|
||||
-Wno-pointer-sign
|
||||
|
||||
DEFAULT_CCFLAGS = \
|
||||
-Wall \
|
||||
-Werror \
|
||||
-fmerge-all-constants \
|
||||
-fdebug-prefix-map="$(PWD)"= \
|
||||
-frecord-gcc-switches
|
||||
|
||||
DEFAULT_OFLAGS = \
|
||||
-g \
|
||||
-gdescribe-dies
|
||||
|
||||
DEFAULT_COPTS = \
|
||||
-fno-math-errno \
|
||||
-fno-trapping-math \
|
||||
-fno-fp-int-builtin-inexact \
|
||||
-fno-ident \
|
||||
-fno-common \
|
||||
-fno-gnu-unique \
|
||||
-fmerge-constants \
|
||||
-fstrict-aliasing \
|
||||
-fstrict-overflow \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
DEFAULT_CPPFLAGS = \
|
||||
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
|
||||
-nostdinc \
|
||||
-iquote . \
|
||||
-include libc/integral/normalize.inc
|
||||
|
||||
DEFAULT_CFLAGS = \
|
||||
-std=gnu2x
|
||||
|
||||
DEFAULT_CXXFLAGS = \
|
||||
-std=gnu++11 \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fuse-cxa-atexit \
|
||||
-fno-threadsafe-statics
|
||||
|
||||
DEFAULT_ASFLAGS = \
|
||||
-W \
|
||||
-I. \
|
||||
--noexecstack
|
||||
|
||||
DEFAULT_LDFLAGS = \
|
||||
-h \
|
||||
-static \
|
||||
--relax \
|
||||
-nostdlib \
|
||||
-m elf_x86_64 \
|
||||
--gc-sections \
|
||||
--build-id=none \
|
||||
--cref -Map=$@.map \
|
||||
--no-dynamic-linker \
|
||||
-Ttext-segment=$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ASONLYFLAGS = \
|
||||
-g \
|
||||
--debug-prefix-map="$(PWD)"=
|
||||
|
||||
DEFAULT_LDLIBS =
|
||||
|
||||
MCA = llvm-mca-10 \
|
||||
-mtriple=x86_64-pc-linux-gnu \
|
||||
-iterations=3 \
|
||||
-instruction-info \
|
||||
-iterations=3 \
|
||||
-all-stats \
|
||||
-all-views \
|
||||
-timeline
|
||||
|
||||
cc.flags = \
|
||||
$(DEFAULT_CCFLAGS) \
|
||||
$(CONFIG_CCFLAGS) \
|
||||
$(CCFLAGS) \
|
||||
$(OVERRIDE_CCFLAGS) \
|
||||
-D__SAUCE__=\"$<\"
|
||||
|
||||
o.flags = \
|
||||
$(DEFAULT_OFLAGS) \
|
||||
$(CONFIG_OFLAGS) \
|
||||
$(OFLAGS) \
|
||||
$(OVERRIDE_OFLAGS)
|
||||
|
||||
cpp.flags = \
|
||||
$(DEFAULT_CPPFLAGS) \
|
||||
$(CONFIG_CPPFLAGS) \
|
||||
$(CPPFLAGS) \
|
||||
$(OVERRIDE_CPPFLAGS)
|
||||
|
||||
copt.flags = \
|
||||
$(TARGET_ARCH) \
|
||||
$(DEFAULT_COPTS) \
|
||||
$(CONFIG_COPTS) \
|
||||
$(COPTS) \
|
||||
$(OVERRIDE_COPTS)
|
||||
|
||||
f.flags = \
|
||||
$(DEFAULT_FFLAGS) \
|
||||
$(CONFIG_FFLAGS) \
|
||||
$(FFLAGS) \
|
||||
$(OVERRIDE_FFLAGS)
|
||||
|
||||
c.flags = \
|
||||
$(DEFAULT_CFLAGS) \
|
||||
$(CONFIG_CFLAGS) \
|
||||
$(CFLAGS) \
|
||||
$(OVERRIDE_CFLAGS)
|
||||
|
||||
cxx.flags = \
|
||||
$(DEFAULT_CXXFLAGS) \
|
||||
$(CONFIG_CXXFLAGS) \
|
||||
$(CXXFLAGS) \
|
||||
$(OVERRIDE_CXXFLAGS)
|
||||
|
||||
s.flags = \
|
||||
$(DEFAULT_ASFLAGS) \
|
||||
$(CONFIG_ASFLAGS) \
|
||||
$(ASFLAGS) \
|
||||
$(OVERRIDE_ASFLAGS)
|
||||
|
||||
S.flags = $(addprefix -Wa$(COMMA),$(s.flags))
|
||||
|
||||
LD.libs = \
|
||||
$(LDLIBS) \
|
||||
$(LOADLIBES) \
|
||||
$(DEFAULT_LDLIBS) \
|
||||
$(CONFIG_LDLIBS) \
|
||||
$(LDLIBS) \
|
||||
$(DEFAULT_LIBS) \
|
||||
$(CONFIG_LIBS) \
|
||||
$(LIBS)
|
||||
|
||||
COMPILE.c.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
|
||||
COMPILE.f.flags = $(cc.flags) $(copt.flags) $(f.flags)
|
||||
COMPILE.F.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(f.flags)
|
||||
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
|
||||
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
|
||||
OBJECTIFY.c.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(c.flags)
|
||||
OBJECTIFY.cxx.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(cxx.flags)
|
||||
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
|
||||
OBJECTIFY.S.flags = $(copt.flags) $(cc.flags) $(o.flags) $(cpp.flags) $(S.flags)
|
||||
OBJECTIFY.f.flags = $(copt.flags) $(cc.flags) $(o.flags) $(copt.flags) $(S.flags) $(f.flags)
|
||||
OBJECTIFY.F.flags = $(OBJECTIFY.f.flags) $(cpp.flags)
|
||||
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
|
||||
PREPROCESS.lds.flags = -D__LINKER__ $(filter-out -g%,$(PREPROCESS.flags)) -P -xc
|
||||
|
||||
COMPILE.c = $(CC) -S $(COMPILE.c.flags)
|
||||
COMPILE.i = $(CC) -S $(COMPILE.i.flags)
|
||||
COMPILE.f = $(FC) -S $(COMPILE.f.flags)
|
||||
COMPILE.F = $(FC) -S $(COMPILE.F.flags)
|
||||
OBJECTIFY.s = $(AS) $(OBJECTIFY.s.flags)
|
||||
OBJECTIFY.S = $(CC) $(OBJECTIFY.S.flags) -c
|
||||
OBJECTIFY.f = $(FC) $(OBJECTIFY.f.flags) -c
|
||||
OBJECTIFY.F = $(FC) $(OBJECTIFY.F.flags) -c
|
||||
OBJECTIFY.c = $(CC) $(OBJECTIFY.c.flags) -c
|
||||
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
|
||||
PREPROCESS = $(CC) $(PREPROCESS.flags)
|
||||
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
|
||||
LINK = build/link $(LD) $(LINK.flags)
|
||||
ELF = o/libc/elf/elf.lds
|
||||
ELFLINK = ACTION=LINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
|
||||
ARCHIVE = build/archive $(AR) $(ARFLAGS)
|
||||
LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^)))
|
||||
LOLSAN = build/lolsan -b $(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
# The compiler won't generate %xmm code for sources extensioned .greg.c,
|
||||
# which is needed for C modules wanting to run at the executive level or
|
||||
# during privileged runtime states, e.g. code morphing.
|
||||
OBJECTIFY.greg.c = \
|
||||
$(CC) \
|
||||
$(filter-out -pg,$(OBJECTIFY.c.flags)) \
|
||||
-D__MGENERAL_REGS_ONLY__ \
|
||||
-mgeneral-regs-only \
|
||||
-fno-stack-protector \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
-fno-sanitize=all \
|
||||
-c
|
||||
|
||||
OBJECTIFY.ansi.c = $(CC) $(OBJECTIFY.c.flags) -ansi -Wextra -Werror -pedantic-errors -c
|
||||
OBJECTIFY.c99.c = $(CC) $(OBJECTIFY.c.flags) -std=c99 -Wextra -Werror -pedantic-errors -c
|
||||
OBJECTIFY.c11.c = $(CC) $(OBJECTIFY.c.flags) -std=c11 -Wextra -Werror -pedantic-errors -c
|
||||
OBJECTIFY.c2x.c = $(CC) $(OBJECTIFY.c.flags) -std=c2x -Wextra -Werror -pedantic-errors -c
|
||||
|
||||
# No-Clobber ABI (clobbers nothing, except rax and flags)
|
||||
#
|
||||
# This ABI is intended for core library functions that're frequently
|
||||
# called by just about everything, e.g. memcpy, malloc, etc. By offering
|
||||
# this guarantee, callers can optionally call these functions via asm(),
|
||||
# which reduces register allocator pressure at call sites.
|
||||
#
|
||||
# This makes unrelated caller code faster, but the NCABI functions
|
||||
# themselves a tiny bit slower. That's OK, since modern NexGen-32e CPUs
|
||||
# seem to have one fifth of their execution engines devoted to pushing
|
||||
# and popping, probably so legacy IA-32 code keeps going fast; so we use
|
||||
# it to our advantage.
|
||||
OBJECTIFY.ncabi.c = \
|
||||
$(GCC) \
|
||||
$(OBJECTIFY.c.flags) \
|
||||
-mno-sse \
|
||||
-mfpmath=387 \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mpreferred-stack-boundary=3 \
|
||||
-fno-sanitize=all \
|
||||
-fcall-saved-rcx \
|
||||
-fcall-saved-rdx \
|
||||
-fcall-saved-rdi \
|
||||
-fcall-saved-rsi \
|
||||
-fcall-saved-r8 \
|
||||
-fcall-saved-r9 \
|
||||
-fcall-saved-r10 \
|
||||
-fcall-saved-r11 \
|
||||
-c \
|
||||
-xc
|
||||
|
||||
BUILD_SRCS = \
|
||||
build/definitions.mk \
|
||||
build/rules.mk \
|
||||
build/compile \
|
||||
build/link \
|
||||
build/lolsan \
|
||||
build/remote
|
54
build/do
Executable file
54
build/do
Executable file
|
@ -0,0 +1,54 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Generic Command Runner
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This does auto mkdir and ephemeral logging.
|
||||
#
|
||||
# EXAMPLE
|
||||
#
|
||||
# build/do PROG [ARGS...]
|
||||
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
# Ensure directory creation if -o PATH flag is passed.
|
||||
OUT=
|
||||
FIRST=1
|
||||
OUTARG=0
|
||||
for x; do
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set --
|
||||
FIRST=0
|
||||
elif [ $OUTARG -eq 1 ]; then
|
||||
OUTARG=0
|
||||
OUT="$x"
|
||||
fi
|
||||
case "$x" in
|
||||
-o)
|
||||
OUTARG=1
|
||||
;;
|
||||
-o*)
|
||||
OUT=${x#-o}
|
||||
;;
|
||||
esac
|
||||
set -- "$@" "$x"
|
||||
done
|
||||
if [ "$OUT" ]; then
|
||||
OUTDIR="${OUT%/*}"
|
||||
if [ "$OUTDIR" != "$OUT" ] && [ ! -d "$OUTDIR" ]; then
|
||||
$MKDIR "$OUTDIR" || exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Log command.
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-BUILD}" "$TARGET" >&2
|
||||
fi
|
||||
|
||||
exec "$@"
|
19
build/findtmp
Executable file
19
build/findtmp
Executable file
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env bash
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Temporary Directory Discovery
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# We call this script once per build to ideally find a folder that's
|
||||
# backed by an in-memory file system. We then export it to the TMPDIR
|
||||
# environment variable. Many programs use it under the hood, e.g. gcc,
|
||||
# so it grants many small performance improvements.
|
||||
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
$MKDIR o/tmp
|
||||
echo o/tmp
|
16
build/functions.mk
Normal file
16
build/functions.mk
Normal file
|
@ -0,0 +1,16 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan Functional Programming Build System
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# It's basically Blaze except a few lines of code, made possible due
|
||||
# to the power and the glory of variables that're secretly lambdas.
|
||||
|
||||
tail = $(wordlist 2,$(words $1),$1)
|
||||
reverse = $(if $1,$(call reverse,$(call tail,$1)) $(firstword $1))
|
||||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||
uniqr = $(if $1,$(call uniqr,$(filter-out $(firstword $1),$1)) $(firstword $1))
|
40
build/getccname
Executable file
40
build/getccname
Executable file
|
@ -0,0 +1,40 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Compiler Name Discovery
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Cosmopolitan itself may be built using either GCC and Clang, and our
|
||||
# build irons out many of the differences between the two. This script
|
||||
# determines which one's in play, which is nontrivial, since they tend
|
||||
# to call themselves so many different names.
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
SPECIAL_TEXT=$(
|
||||
$1 --version |
|
||||
sed -n '
|
||||
/Free Software/ {
|
||||
i\
|
||||
gcc
|
||||
q
|
||||
}
|
||||
/clang/ {
|
||||
i\
|
||||
clang
|
||||
q
|
||||
}
|
||||
')
|
||||
|
||||
if [ -z "$SPECIAL_TEXT" ]; then
|
||||
echo gcc
|
||||
else
|
||||
printf '%s\n' "$SPECIAL_TEXT"
|
||||
fi
|
38
build/getccversion
Executable file
38
build/getccversion
Executable file
|
@ -0,0 +1,38 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Compiler Version Discovery
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Cosmopolitan itself may be built using either GCC and Clang, and our
|
||||
# build irons out many of the differences between the two. This script
|
||||
# is used by build/definitions.mk alongside build/getccname to support
|
||||
# the different versions folks use.
|
||||
#
|
||||
# Our aim is to support GCC 4.2.1+ since that's the last GPLv2 version
|
||||
# with any sort of industry consensus. Please note, Cosmopolitan never
|
||||
# links GCC runtimes when using later versions, so some concerns might
|
||||
# not apply.
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
MAJOR_VERSION=$(
|
||||
$1 --version |
|
||||
head -n1 |
|
||||
sed -n '
|
||||
s!^[^(]*([^)]*) \([[:digit:]][[:digit:]]*\).*!\1!p
|
||||
s!^.*clang.*version \([[:digit:]][[:digit:]]*\).*!\1!p
|
||||
')
|
||||
|
||||
if [ -z "$MAJOR_VERSION" ]; then
|
||||
echo 6
|
||||
else
|
||||
printf '%s\n' "$MAJOR_VERSION"
|
||||
fi
|
32
build/getlogfmt
Executable file
32
build/getlogfmt
Executable file
|
@ -0,0 +1,32 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Printf Logger Initializer
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This program is invoked once by build/definitions.mk to choose the
|
||||
# most appropriate format string when logging command invocations.
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "''"
|
||||
else
|
||||
W1=15
|
||||
if [ "$TERM" = "dumb" ]; then # e.g. emacs' dismal tty
|
||||
if [ "$COLUMNS" = "" ]; then
|
||||
if TPUT=$(command -v tput); then
|
||||
COLUMNS=$("$TPUT" cols)
|
||||
else
|
||||
COLUMNS=80
|
||||
fi
|
||||
fi
|
||||
COLUMNS=$((COLUMNS - 1))
|
||||
W2=$((COLUMNS - W1))
|
||||
printf '%%-%ds%%-%ds\\r' "$W1" "$W2"
|
||||
else
|
||||
echo ♥cosmo >&2
|
||||
printf '\\033[F\\033[K%%-%ds%%s\\r\\n' "$W1"
|
||||
fi
|
||||
fi
|
57
build/htags
Executable file
57
build/htags
Executable file
|
@ -0,0 +1,57 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Header Symbol Index Generator
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This is a static source analyzer that lets us configure Emacs
|
||||
# keybindings to insert #include lines.
|
||||
#
|
||||
# EXAMPLES
|
||||
#
|
||||
# build/htags -o HTAGS $(find . -name \*.h)
|
||||
#
|
||||
# (defun jart-add-include ()
|
||||
# (interactive)
|
||||
# (let* ((tag-file "HTAGS")
|
||||
# (case-fold-search nil)
|
||||
# (search (thing-at-point 'symbol))
|
||||
# (buffer (find-file-noselect (format "%s/%s"
|
||||
# (locate-dominating-file
|
||||
# (buffer-name) tag-file)
|
||||
# tag-file)))
|
||||
# (header (with-current-buffer buffer
|
||||
# (save-excursion
|
||||
# (goto-char 0)
|
||||
# (when (re-search-forward
|
||||
# (concat "\177" search "\001") nil t)
|
||||
# (when (re-search-backward "\f\n\\([^,]*\\)," nil t)
|
||||
# (match-string 1)))))))
|
||||
# (when header
|
||||
# (save-excursion
|
||||
# (goto-char 0)
|
||||
# (re-search-forward "#include")
|
||||
# (re-search-forward "^$")
|
||||
# (insert (concat "#include \"" header "\"\n"))))))
|
||||
# (defun jart-c-mode-common-hook ()
|
||||
# (define-key c-mode-base-map (kbd "C-c C-h") 'jart-add-include))
|
||||
# (eval-after-load 'markdown-mode
|
||||
# '(progn
|
||||
# (add-hook 'c-mode-common-hook 'jart-c-mode-common-hook)))
|
||||
|
||||
# ctags doesn't understand variable prototypes, e.g.
|
||||
# extern char **environ;
|
||||
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
|
||||
|
||||
# ctags doesn't understand function prototypes, e.g.
|
||||
# bool isheap(void *p) nothrow nocallback;
|
||||
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
|
||||
|
||||
# ctags doesn't understand function pointers, e.g.
|
||||
# extern int32_t (*const SetEvent)(int64_t hEvent) wincall;
|
||||
set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@"
|
||||
|
||||
exec ${TAGS:-ctags} -e --langmap=c:.c.h "$@"
|
6
build/includeall
Executable file
6
build/includeall
Executable file
|
@ -0,0 +1,6 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
for x; do
|
||||
printf '#include "%s"\n' "$x"
|
||||
done
|
65
build/link
Executable file
65
build/link
Executable file
|
@ -0,0 +1,65 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# GNU Linker Veneer
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This script wraps normal linker commands that're transparently
|
||||
# passed-through. It adds ephemeral logging and directory creation.
|
||||
#
|
||||
# EXAMPLE
|
||||
#
|
||||
# build/linker ld -o program program.o
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
export LC_ALL=C # very important for ld
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
OUT=
|
||||
FIRST=1
|
||||
OUTARG=0
|
||||
for x; do
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set --
|
||||
FIRST=0
|
||||
elif [ $OUTARG -eq 1 ]; then
|
||||
OUTARG=0
|
||||
OUT="$x"
|
||||
fi
|
||||
case "$x" in
|
||||
-o)
|
||||
OUTARG=1
|
||||
;;
|
||||
esac
|
||||
set -- "$@" "$x"
|
||||
done
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-LINK.elf}" "$OUT" >&2
|
||||
fi
|
||||
|
||||
OUTDIR="${OUT%/*}"
|
||||
if [ "$OUTDIR" != "$OUT" ] && [ ! -d "$OUTDIR" ]; then
|
||||
$MKDIR "$OUTDIR" || exit 2
|
||||
fi
|
||||
|
||||
REASON=failed
|
||||
trap REASON=interrupted INT
|
||||
|
||||
"$@" && exit
|
||||
|
||||
if [ "$TERM" = "dumb" ]; then
|
||||
f='%s %s\r\n\r\n'
|
||||
else
|
||||
f='\033[91m%s\033[39m \033[94m%s\033[39m\r\n\r\n'
|
||||
fi
|
||||
printf "$f" "link $REASON:" "$*" >&2
|
||||
exit 1
|
21
build/mkdeps
Executable file
21
build/mkdeps
Executable file
|
@ -0,0 +1,21 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then
|
||||
set -- "o/$MODE/tool/build/mkdeps.com" "$@"
|
||||
else
|
||||
if [ ! -x o/build/bootstrap/mkdeps.com ]; then
|
||||
mkdir -p o/build/bootstrap &&
|
||||
cp -a build/bootstrap/mkdeps.com \
|
||||
o/build/bootstrap/mkdeps.com || exit
|
||||
fi
|
||||
set -- o/build/bootstrap/mkdeps.com "$@"
|
||||
fi
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-MKDEPS}" "$3" >&2
|
||||
fi
|
||||
|
||||
exec "$@"
|
31
build/online.mk
Normal file
31
build/online.mk
Normal file
|
@ -0,0 +1,31 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan Online Testing
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# make test HOSTS="rhel5 windows mac freebsd openbsd wsl"
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This code deploys and spawns testing infrastructure to a fleet of
|
||||
# virtual machines running the various supported platforms. This is
|
||||
# super trivial since αcτµαlly pδrταblε εxεcµταblε is an autonomous
|
||||
# format requiring one simple file copy. Latencies are outstanding.
|
||||
# Configuration is trivial using /etc/hosts and ~/.ssh/config.
|
||||
#
|
||||
# SEE ALSO
|
||||
#
|
||||
# - tool/build/runit.c
|
||||
# - tool/build/runitd.c
|
||||
|
||||
.PRECIOUS: o/$(MODE)/%.com.ok
|
||||
o/$(MODE)/%.com.ok: \
|
||||
o/$(MODE)/tool/build/runit.com.dbg \
|
||||
o/$(MODE)/tool/build/runitd.com \
|
||||
o/$(MODE)/%.com
|
||||
@ACTION=TEST TARGET=$@ build/do $^ $(HOSTS)
|
||||
@touch $@
|
31
build/package
Executable file
31
build/package
Executable file
|
@ -0,0 +1,31 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
if [ "$TOOL_BUILD_PACKAGE" ]; then
|
||||
set -- "$TOOL_BUILD_PACKAGE" "$@"
|
||||
else
|
||||
if [ -x "o/tool/build/package.com" ]; then
|
||||
set -- "o/tool/build/package.com" "$@"
|
||||
else
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
CP=${CP:-$(command -v cp) -f} || exit
|
||||
if [ ! -x o/build/bootstrap/package.com ]; then
|
||||
$MKDIR o/build/bootstrap &&
|
||||
$CP -a build/bootstrap/package.com \
|
||||
o/build/bootstrap/package.com || exit
|
||||
fi
|
||||
set -- o/build/bootstrap/package.com "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
COLUMNS=${COLUMNS:-80}
|
||||
COLUMNS=$((COLUMNS - 4))
|
||||
printf "%s\n" "$*" |
|
||||
/usr/bin/fold -s -w $COLUMNS |
|
||||
sed -e '1bb' -e 's/^/ /' -e ':b' -e '$b' -e 's/$/ \\/' >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-PACKAGE}" "$3" >&2
|
||||
fi
|
||||
|
||||
exec "$@"
|
2186
build/rle.py
Normal file
2186
build/rle.py
Normal file
File diff suppressed because it is too large
Load diff
99
build/rules.mk
Normal file
99
build/rules.mk
Normal file
|
@ -0,0 +1,99 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan Core Build Rules
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This file shows GNU Make how to convert between file types, based on
|
||||
# their extensions. We use everyday, ordinary, boring, and ubiquitous
|
||||
# system commands for everything, e.g. as, cc, ld, etc. with plain and
|
||||
# simple shell-script wrappers, e.g. build/assemble and build/compile.
|
||||
# Those veneers abstract away most of the boring trivialities, to keep
|
||||
# our makefiles pristine and readable.
|
||||
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
o/%.a:; @$(ARCHIVE) $@ $^
|
||||
o/%.o: %.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.s: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.s: o/%.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.i: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.o: %.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/%.s: %.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/%.s: o/%.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/%.o: %.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/%.lds: %.lds; @ACTION=PREPROCESS build/compile $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/%.inc: %.h; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
|
||||
o/%.pkg:; @build/package $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
|
||||
o/%.h.ok: %.h; @ACTION=CHECK.h build/compile $(COMPILE.c) -x c -g0 -o $@ $<
|
||||
o/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/%.zip.o: %; @build/zipobj $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.a:; @$(ARCHIVE) $@ $^
|
||||
o/$(MODE)/%.o: %.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: o/$(MODE)/%.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.f; @ACTION=OBJECTIFY.f build/compile $(OBJECTIFY.f) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.F; @ACTION=OBJECTIFY.F build/compile $(OBJECTIFY.F) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ss: %.c; @ACTION=COMPILE.c build/compile $(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ss: o/$(MODE)/%.c; @ACTION=OBJECTIFY.s build/compile $(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: %.c; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: %.cc; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: o/$(MODE)/%.c; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h: %.c; @ACTION=AMALGAMATE build/compile $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.h: o/$(MODE)/%.c; @ACTION=AMALGAMATE build/compile $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.o: %.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: %.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: o/$(MODE)/%.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.lds: %.lds; @ACTION=PREPROCESS build/compile $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h.ok: %.h; @ACTION=CHECK.h build/compile $(COMPILE.c) -x c -g0 -o $@ $<
|
||||
o/$(MODE)/%.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ansi.o: %.ansi.c; @ACTION=OBJECTIFY.ansi build/compile $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ansi.o: %.c; @ACTION=OBJECTIFY.ansi build/compile $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.c99.o: %.c99.c; @ACTION=OBJECTIFY.c99 build/compile $(OBJECTIFY.c99.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.c11.o: %.c11.c; @ACTION=OBJECTIFY.c11 build/compile $(OBJECTIFY.c11.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.c2x.o: %.c2x.c; @ACTION=OBJECTIFY.c2x build/compile $(OBJECTIFY.c2x.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.initabi.o: %.initabi.c; @ACTION=OBJECTIFY.init build/compile $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ncabi.o: %.ncabi.c; @ACTION=OBJECTIFY.nc build/compile $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.runs: o/$(MODE)/%; @ACTION=CHECK.runs TARGET=$< build/runcom $< $(TESTARGS) && touch $@
|
||||
o/$(MODE)/%.pkg:; @build/package $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
|
||||
o/$(MODE)/%.zip.o: %; @build/zipobj $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-gcc.asm: %.c; @ACTION=COMPILE.c build/compile $(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: %.c; @ACTION=COMPILE.c build/compile $(COMPILE.c) $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
|
||||
o/$(MODE)/%-gcc.asm: %.f; @ACTION=COMPILE.f build/compile $(COMPILE.f) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: %.f; @ACTION=COMPILE.f build/compile $(COMPILE.f) $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
|
||||
o/$(MODE)/%-gcc.asm: %.F; @ACTION=COMPILE.F build/compile $(COMPILE.F) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: %.F; @ACTION=COMPILE.F build/compile $(COMPILE.F) $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
|
||||
|
||||
# ragel state machine compiler
|
||||
.PRECIOUS: build/bootstrap/%.c.gz
|
||||
o/$(MODE)/%.c: %.rl build/bootstrap/%.c.gz
|
||||
@mkdir -p $(dir $@)
|
||||
@$(GZ) $(ZFLAGS) -dc $(<:%.rl=build/bootstrap/%.c.gz) >$@
|
||||
-@ACTION=RAGEL build/do $(RAGEL) $(RAGELFLAGS) $(OUTPUT_OPTION) $<
|
||||
build/bootstrap/%.c.gz: %.rl
|
||||
@mkdir -p $(dir $@)
|
||||
@$(RAGEL) -o $(@:%.gz=%) $<
|
||||
@$(GZ) $(ZFLAGS) -f $(@:%.gz=%)
|
||||
%.svgz: %.rl
|
||||
@$(RAGEL) -V -p $< | $(DOT) -Tsvg | $(GZ) $(ZFLAGS) >$@
|
||||
|
||||
$(LIBC__A_SRCS:%=o/$(MODE)/%.zip.o) \
|
9
build/runcom
Executable file
9
build/runcom
Executable file
|
@ -0,0 +1,9 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
DD=${DD:-$(command -v dd)} || exit
|
||||
$DD if="$1" of="$1.bak" bs=4096 count=1 conv=notrunc 2>/dev/null
|
||||
"$@"
|
||||
rc=$?
|
||||
$DD if="$1.bak" of="$1" bs=4096 count=1 conv=notrunc 2>/dev/null
|
||||
exit $rc
|
13
build/ssh
Executable file
13
build/ssh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# SSH Command Wrapper
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This script, like most of our wrappers, asks the tooling to whine
|
||||
# less often.
|
||||
|
||||
exec ${SSH:-ssh} -o LogLevel=QUIET "$@"
|
54
build/zipobj
Executable file
54
build/zipobj
Executable file
|
@ -0,0 +1,54 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
CP=${CP:-$(command -v cp) -f} || exit
|
||||
SED=${SED:-$(command -v sed)} || exit
|
||||
|
||||
MODE=
|
||||
|
||||
OUT=
|
||||
FIRST=1
|
||||
OUTARG=0
|
||||
for x; do
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
set --
|
||||
FIRST=0
|
||||
elif [ $OUTARG -eq 1 ]; then
|
||||
OUTARG=0
|
||||
OUT="$x"
|
||||
fi
|
||||
case "$x" in
|
||||
-o)
|
||||
OUTARG=1
|
||||
;;
|
||||
esac
|
||||
set -- "$@" "$x"
|
||||
done
|
||||
OUTDIR="${OUT%/*}"
|
||||
if [ "$OUTDIR" != "$OUT" ] && [ ! -d "$OUTDIR" ]; then
|
||||
$MKDIR "$OUTDIR" || exit 2
|
||||
fi
|
||||
|
||||
if [ -x "o/$MODE/tool/build/zipobj.com.dbg" ]; then
|
||||
set -- "o/$MODE/tool/build/zipobj.com.dbg" "$@"
|
||||
else
|
||||
if [ ! -x o/build/bootstrap/zipobj.com ]; then
|
||||
$MKDIR o/build/bootstrap &&
|
||||
$CP -a build/bootstrap/zipobj.com \
|
||||
o/build/bootstrap/zipobj.com || exit
|
||||
fi
|
||||
set -- o/build/bootstrap/zipobj.com "$@"
|
||||
fi
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
COLUMNS=${COLUMNS:-80}
|
||||
COLUMNS=$((COLUMNS - 4))
|
||||
printf "%s\n" "$*" |
|
||||
/usr/bin/fold -s -w $COLUMNS |
|
||||
$SED -e '1bb' -e 's/^/ /' -e ':b' -e '$b' -e 's/$/ \\/' >&2
|
||||
else
|
||||
printf "$LOGFMT" "${ACTION:-ZIPOBJ}" "$3" >&2
|
||||
fi
|
||||
|
||||
exec "$@"
|
60
dsp/bmp/bmp.mk
Normal file
60
dsp/bmp/bmp.mk
Normal file
|
@ -0,0 +1,60 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += DSP_BMP
|
||||
|
||||
DSP_BMP_ARTIFACTS += DSP_BMP_A
|
||||
DSP_BMP = $(DSP_BMP_A_DEPS) $(DSP_BMP_A)
|
||||
DSP_BMP_A = o/$(MODE)/dsp/bmp/bmp.a
|
||||
DSP_BMP_A_FILES := $(wildcard dsp/bmp/*)
|
||||
DSP_BMP_A_HDRS = $(filter %.h,$(DSP_BMP_A_FILES))
|
||||
DSP_BMP_A_SRCS_S = $(filter %.S,$(DSP_BMP_A_FILES))
|
||||
DSP_BMP_A_SRCS_C = $(filter %.c,$(DSP_BMP_A_FILES))
|
||||
|
||||
DSP_BMP_A_SRCS = \
|
||||
$(DSP_BMP_A_SRCS_S) \
|
||||
$(DSP_BMP_A_SRCS_C)
|
||||
|
||||
DSP_BMP_A_OBJS = \
|
||||
$(DSP_BMP_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(DSP_BMP_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(DSP_BMP_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
DSP_BMP_A_CHECKS = \
|
||||
$(DSP_BMP_A).pkg \
|
||||
$(DSP_BMP_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
DSP_BMP_A_DIRECTDEPS = \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STUBS
|
||||
|
||||
DSP_BMP_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_BMP_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(DSP_BMP_A): dsp/bmp/ \
|
||||
$(DSP_BMP_A).pkg \
|
||||
$(DSP_BMP_A_OBJS)
|
||||
|
||||
$(DSP_BMP_A).pkg: \
|
||||
$(DSP_BMP_A_OBJS) \
|
||||
$(foreach x,$(DSP_BMP_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/bmp/float2short.o \
|
||||
o/$(MODE)/dsp/bmp/scalevolume.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
o/tiny/dsp/bmp/scalevolume.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
DSP_BMP_LIBS = $(foreach x,$(DSP_BMP_ARTIFACTS),$($(x)))
|
||||
DSP_BMP_SRCS = $(foreach x,$(DSP_BMP_ARTIFACTS),$($(x)_SRCS))
|
||||
DSP_BMP_HDRS = $(foreach x,$(DSP_BMP_ARTIFACTS),$($(x)_HDRS))
|
||||
DSP_BMP_CHECKS = $(foreach x,$(DSP_BMP_ARTIFACTS),$($(x)_CHECKS))
|
||||
DSP_BMP_OBJS = $(foreach x,$(DSP_BMP_ARTIFACTS),$($(x)_OBJS))
|
||||
$(DSP_BMP_OBJS): $(BUILD_FILES) dsp/bmp/bmp.mk
|
||||
|
||||
.PHONY: o/$(MODE)/dsp/bmp
|
||||
o/$(MODE)/dsp/bmp: $(DSP_BMP_CHECKS)
|
36
dsp/core/byte2double.c
Normal file
36
dsp/core/byte2double.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
void *byte2double(long n, const void *p, double weight, double bias) {
|
||||
long i;
|
||||
double f, *dst;
|
||||
unsigned char *src;
|
||||
if ((dst = valloc(n * sizeof(double)))) {
|
||||
for (src = p, i = 0; i < n; ++i) {
|
||||
f = src[i];
|
||||
f -= bias;
|
||||
f *= 1 / weight;
|
||||
dst[i] = f;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
22
dsp/core/c11.h
Normal file
22
dsp/core/c11.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C11_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C11_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Fixed-point 8-bit rounded mean kernel.
|
||||
*
|
||||
* @define (a + b) / 2
|
||||
*/
|
||||
static inline pureconst artificial unsigned char C11(unsigned char al,
|
||||
unsigned char bl) {
|
||||
short ax;
|
||||
ax = al;
|
||||
ax += bl;
|
||||
ax += 1;
|
||||
ax /= 2;
|
||||
al = ax;
|
||||
return al;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C11_H_ */
|
21
dsp/core/c121.h
Normal file
21
dsp/core/c121.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C121_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C121_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
forceinline pureconst artificial unsigned char C121(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl) {
|
||||
unsigned short ax, bx;
|
||||
ax = al;
|
||||
ax += bl;
|
||||
ax += bl;
|
||||
ax += cl;
|
||||
ax += 2;
|
||||
ax >>= 2;
|
||||
return ax;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C121_H_ */
|
19
dsp/core/c121s.h
Normal file
19
dsp/core/c121s.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C121S_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C121S_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline pureconst artificial signed char C121S(signed char al,
|
||||
signed char bl,
|
||||
signed char cl) {
|
||||
short ax, bx;
|
||||
ax = al;
|
||||
ax += bl;
|
||||
ax += bl;
|
||||
ax += cl;
|
||||
ax += 2;
|
||||
ax >>= 2;
|
||||
return ax;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C121S_H_ */
|
30
dsp/core/c1331.h
Normal file
30
dsp/core/c1331.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C1331_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C1331_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Byte sized kernel for resampling memory in half.
|
||||
*
|
||||
* @define (1*𝑎 + 3*𝑏 + 3*𝑐 + 1*𝑑) / (1 + 3 + 3 + 1)
|
||||
* @see C161() afterward for superior sin(𝑥)/𝑥
|
||||
* @limit [0,255] → [0..2,044] → [0..255]
|
||||
*/
|
||||
forceinline pureconst artificial unsigned char C1331(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl,
|
||||
unsigned char dl) {
|
||||
short ax, bx;
|
||||
bx = bl;
|
||||
bx += cl;
|
||||
bx *= 3;
|
||||
ax = al;
|
||||
ax += dl;
|
||||
ax += bx;
|
||||
ax += 4;
|
||||
ax >>= 3;
|
||||
al = ax;
|
||||
return al;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C1331_H_ */
|
28
dsp/core/c1331s.h
Normal file
28
dsp/core/c1331s.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C1331S_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C1331S_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Byte sized kernel for resampling difference samples in half.
|
||||
*
|
||||
* @define (1*(a-128)+3*(a-128)+3*(a-128)+1*(a-128))/(1+3+3+1)+128
|
||||
* @see C1331(), Y420CbCr2RgbScale()
|
||||
*/
|
||||
forceinline pureconst artificial signed char C1331S(signed char al,
|
||||
signed char bl,
|
||||
signed char cl,
|
||||
signed char dl) {
|
||||
short ax, bx;
|
||||
bx = bl;
|
||||
bx += cl;
|
||||
bx *= 3;
|
||||
ax = al;
|
||||
ax += dl;
|
||||
ax += bx;
|
||||
ax += 4;
|
||||
ax >>= 3;
|
||||
return ax;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C1331S_H_ */
|
33
dsp/core/c161.h
Normal file
33
dsp/core/c161.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C161_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C161_H_
|
||||
#include "libc/macros.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define EXTRA_SHARP 2
|
||||
|
||||
/**
|
||||
* Byte sized kernel for restoring sharpness of resampled memory.
|
||||
*
|
||||
* @define CLAMP[(-1*𝑎 + 6*𝑏 + -1*𝑐) / (-1 + 6 + -1)]
|
||||
* @limit [0..255] → [-510..1,532] → [-127..383] → [0..255]
|
||||
* @see C1331()
|
||||
*/
|
||||
forceinline pureconst artificial unsigned char C161(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl) {
|
||||
short ax, bx, cx;
|
||||
ax = al;
|
||||
bx = bl;
|
||||
cx = cl;
|
||||
ax *= -1;
|
||||
bx *= +6;
|
||||
cx *= -1;
|
||||
ax += bx;
|
||||
ax += cx;
|
||||
ax += 2;
|
||||
ax >>= 2;
|
||||
return MIN(255, MAX(0, ax));
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C161_H_ */
|
26
dsp/core/c161s.h
Normal file
26
dsp/core/c161s.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C161S_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C161S_H_
|
||||
#include "dsp/core/c161.h"
|
||||
#include "libc/macros.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline pureconst artificial signed char C161S(signed char al,
|
||||
signed char bl,
|
||||
signed char cl) {
|
||||
short ax, bx, cx;
|
||||
ax = al;
|
||||
bx = bl;
|
||||
cx = cl;
|
||||
ax *= -1 * EXTRA_SHARP;
|
||||
bx *= 6 * EXTRA_SHARP;
|
||||
cx *= -1 * EXTRA_SHARP;
|
||||
ax += bx;
|
||||
ax += cx;
|
||||
ax += 2 * EXTRA_SHARP;
|
||||
ax /= 4 * EXTRA_SHARP;
|
||||
al = MIN(112, MAX(-112, ax));
|
||||
return al;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C161S_H_ */
|
30
dsp/core/c331.h
Normal file
30
dsp/core/c331.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_C331_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_C331_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Fixed-point 8-bit magic edge resampling kernel.
|
||||
*
|
||||
* @define (3*a + 3*b + 1*c) / 7
|
||||
* @see C1331()
|
||||
*/
|
||||
static inline pureconst artificial unsigned char C331(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl) {
|
||||
unsigned eax, ebx, ecx;
|
||||
eax = al;
|
||||
ebx = bl;
|
||||
ecx = cl;
|
||||
eax += ebx;
|
||||
eax *= 3 * 2350;
|
||||
ecx *= 1 * 2350;
|
||||
eax += ecx;
|
||||
eax >>= 14;
|
||||
al = eax;
|
||||
return al;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_C331_H_ */
|
37
dsp/core/core.h
Normal file
37
dsp/core/core.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_CORE_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_CORE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Digital Signal Processing.
|
||||
*/
|
||||
|
||||
int mulaw(int);
|
||||
void *double2byte(long, const void *, double, double) vallocesque;
|
||||
void *byte2double(long, const void *, double, double) vallocesque;
|
||||
|
||||
void *dct(float[8][8], float, float, float, float, float);
|
||||
void *dctjpeg(float[8][8]);
|
||||
|
||||
double det3(const double[3][3]) nosideeffect;
|
||||
void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
|
||||
void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]);
|
||||
void *vmatmul3(double[restrict 3], const double[3], const double[3][3]);
|
||||
void *matvmul3(double[restrict 3], const double[3][3], const double[3]);
|
||||
|
||||
double rgb2stdtv(double) pureconst;
|
||||
double rgb2lintv(double) pureconst;
|
||||
double rgb2stdpc(double, double) pureconst;
|
||||
double rgb2linpc(double, double) pureconst;
|
||||
double tv2pcgamma(double, double) pureconst;
|
||||
|
||||
#ifndef __cplusplus
|
||||
void sad16x8n(size_t n, short[n][8], const short[n][8]);
|
||||
void float2short(size_t n, short[n][8], const float[n][8]);
|
||||
void scalevolume(size_t n, int16_t[n][8], int);
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_CORE_H_ */
|
69
dsp/core/core.mk
Normal file
69
dsp/core/core.mk
Normal file
|
@ -0,0 +1,69 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += DSP_CORE
|
||||
|
||||
DSP_CORE_ARTIFACTS += DSP_CORE_A
|
||||
DSP_CORE = $(DSP_CORE_A_DEPS) $(DSP_CORE_A)
|
||||
DSP_CORE_A = o/$(MODE)/dsp/core/core.a
|
||||
DSP_CORE_A_FILES := $(wildcard dsp/core/*)
|
||||
DSP_CORE_A_HDRS = $(filter %.h,$(DSP_CORE_A_FILES))
|
||||
DSP_CORE_A_SRCS_S = $(filter %.S,$(DSP_CORE_A_FILES))
|
||||
DSP_CORE_A_SRCS_C = $(filter %.c,$(DSP_CORE_A_FILES))
|
||||
|
||||
DSP_CORE_A_SRCS = \
|
||||
$(DSP_CORE_A_SRCS_S) \
|
||||
$(DSP_CORE_A_SRCS_C)
|
||||
|
||||
DSP_CORE_A_OBJS = \
|
||||
$(DSP_CORE_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(DSP_CORE_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(DSP_CORE_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
DSP_CORE_A_CHECKS = \
|
||||
$(DSP_CORE_A).pkg \
|
||||
$(DSP_CORE_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
DSP_CORE_A_DIRECTDEPS = \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_MEM \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STUBS
|
||||
|
||||
DSP_CORE_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_CORE_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(DSP_CORE_A): dsp/core/ \
|
||||
$(DSP_CORE_A).pkg \
|
||||
$(DSP_CORE_A_OBJS)
|
||||
|
||||
$(DSP_CORE_A).pkg: \
|
||||
$(DSP_CORE_A_OBJS) \
|
||||
$(foreach x,$(DSP_CORE_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/core/dct.o \
|
||||
o/$(MODE)/dsp/core/c1331.o \
|
||||
o/$(MODE)/dsp/core/magikarp.o \
|
||||
o/$(MODE)/dsp/core/c93654369.o \
|
||||
o/$(MODE)/dsp/core/float2short.o \
|
||||
o/$(MODE)/dsp/core/scalevolume.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
o/tiny/dsp/core/scalevolume.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/dsp/core/det3.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-ffast-math
|
||||
|
||||
DSP_CORE_LIBS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)))
|
||||
DSP_CORE_SRCS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_SRCS))
|
||||
DSP_CORE_HDRS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_HDRS))
|
||||
DSP_CORE_CHECKS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_CHECKS))
|
||||
DSP_CORE_OBJS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_OBJS))
|
||||
$(DSP_CORE_OBJS): $(BUILD_FILES) dsp/core/core.mk
|
||||
|
||||
.PHONY: o/$(MODE)/dsp/core
|
||||
o/$(MODE)/dsp/core: $(DSP_CORE_CHECKS)
|
85
dsp/core/dct.c
Normal file
85
dsp/core/dct.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
#define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \
|
||||
do { \
|
||||
T z1, z2, z3, z4, z5, z11, z13; \
|
||||
T t0, t1, t2, t3, t4, t5, t6, t7, t8, t10, t11, t12, t13; \
|
||||
t0 = A + H; \
|
||||
t7 = A - H; \
|
||||
t1 = B + G; \
|
||||
t6 = B - G; \
|
||||
t2 = C + F; \
|
||||
t5 = C - F; \
|
||||
t3 = D + E; \
|
||||
t4 = D - E; \
|
||||
t10 = t0 + t3; \
|
||||
t13 = t0 - t3; \
|
||||
t11 = t1 + t2; \
|
||||
t12 = t1 - t2; \
|
||||
A = t10 + t11; \
|
||||
E = t10 - t11; \
|
||||
z1 = (t12 + t13) * C0; \
|
||||
C = t13 + z1; \
|
||||
G = t13 - z1; \
|
||||
t10 = t4 + t5; \
|
||||
t11 = t5 + t6; \
|
||||
t12 = t6 + t7; \
|
||||
z5 = (t10 - t12) * C1; \
|
||||
z2 = t10 * C2 + z5; \
|
||||
z4 = t12 * C3 + z5; \
|
||||
z3 = t11 * C4; \
|
||||
z11 = t7 + z3; \
|
||||
z13 = t7 - z3; \
|
||||
F = z13 + z2; \
|
||||
D = z13 - z2; \
|
||||
B = z11 + z4; \
|
||||
H = z11 - z4; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Performs float forward discrete cosine transform.
|
||||
*
|
||||
* This takes a tiny block of image data and shoves the information it
|
||||
* represents into the top left corner. It can be reversed using idct().
|
||||
* It matters because iterating the result in a serpentine pattern makes
|
||||
* run-length delta encoding super effective. Furthermore, data downward
|
||||
* rightly may be divided away for lossy compression.
|
||||
*
|
||||
* @cost ~100ns
|
||||
*/
|
||||
void *dct(float M[8][8], float c0, float c1, float c2, float c3, float c4) {
|
||||
unsigned y, x;
|
||||
for (y = 0; y < 8; ++y) {
|
||||
DCT(M[y][0], M[y][1], M[y][2], M[y][3], M[y][4], M[y][5], M[y][6], M[y][7],
|
||||
float, c0, c1, c2, c3, c4);
|
||||
}
|
||||
for (x = 0; x < 8; ++x) {
|
||||
DCT(M[0][x], M[1][x], M[2][x], M[3][x], M[4][x], M[5][x], M[6][x], M[7][x],
|
||||
float, c0, c1, c2, c3, c4);
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
void *dctjpeg(float M[8][8]) {
|
||||
return dct(M, .707106781f, .382683433f, .541196100f, 1.306562965f,
|
||||
.707106781f);
|
||||
}
|
36
dsp/core/det3.c
Normal file
36
dsp/core/det3.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
#define LEIBNIZ_FORMULA(a, b, c, d, e, f, g, h, i) \
|
||||
(a * e * i + b * f * g + c * d * h - c * e * g - b * d * i - a * f * h)
|
||||
|
||||
/**
|
||||
* Computes determinant of 3×3 matrix.
|
||||
* i.e. how much space is inside the cube
|
||||
*
|
||||
* @param 𝐀 is input matrix
|
||||
* @param 𝑑 is det(𝐀)
|
||||
* @return |𝐀| or 0 if degenerate
|
||||
*/
|
||||
double det3(const double A[3][3]) {
|
||||
return LEIBNIZ_FORMULA(A[0][0], A[0][1], A[0][2], A[1][0], A[1][1], A[1][2],
|
||||
A[2][0], A[2][1], A[2][2]);
|
||||
}
|
67
dsp/core/differsumsq.c
Normal file
67
dsp/core/differsumsq.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Computes Σ𝑥ᵢΣ𝑥ⱼΣ𝑥ₖΣ𝑥ₗΣ𝑥ₘΣ𝑥ₙ(δ₁𝑥ᵢ+δ₂𝑥ⱼ+δ₃𝑥ₖ+δ₄𝑥ₗ+δ₅𝑥ₘ+δ₆𝑥ₙ)² over 𝐿..𝐻
|
||||
*
|
||||
* “As soon as an Analytical Engine exists, it will necessarily
|
||||
* guide the future course of the science. Whenever any result
|
||||
* is sought by its aid, the question will then arise — by what
|
||||
* course of calculation can these results be arrived at by the
|
||||
* machine in the shortest time?
|
||||
*
|
||||
* — Charles Babbage (Life of a Philosopher, 1864)
|
||||
*
|
||||
* @see itu.int/rec/R-REC-BT.601/
|
||||
*/
|
||||
double DifferSumSq(const double D[static 6], double L, double H) {
|
||||
double T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T2, T20, T21, T22,
|
||||
T23, T24, T25, T26, T27, T3, T4, T5, T6, T7, T8, T9;
|
||||
T2 = H * H, T3 = (H * H * H), T4 = (H * H * H * H), T5 = (H * H * H * H * H),
|
||||
T6 = (H * H * H * H * H * H), T7 = -10 * H, T8 = (H * H * H * H * H * H * H),
|
||||
T9 = (L * L * L * L * L * L * L * L), T10 = (L * L * L * L * L * L * L),
|
||||
T11 = (L * L * L * L * L * L), T12 = (L * L * L * L * L), T13 = -45 * T2,
|
||||
T14 = (L * L * L * L), T15 = 180 * T3, T16 = 120 * T2, T17 = (L * L * L),
|
||||
T18 = L * L, T19 = 18 * T2, T20 = (H * H * H * H * H * H * H * H);
|
||||
T21 = 45 * T4;
|
||||
T22 = 3 * T9 + (-12 * H - 18) * T10 + (12 * T2 + 54 * H + 45) * T11 +
|
||||
(12 * T3 - T19 - 90 * H - 60) * T12 +
|
||||
(-30 * T4 - 90 * T3 + T13 + 60 * H + 45) * T14 +
|
||||
(12 * T5 + 90 * T4 + T15 + T16 - 18) * T17 +
|
||||
(12 * T6 + 18 * T5 - T21 - 120 * T3 - 90 * T2 - 18 * H + 3) * T18 +
|
||||
(-12 * T8 - 54 * T6 - 90 * T5 - 60 * T4 + T19 + 6 * H) * L + 3 * T20 +
|
||||
18 * T8 + 45 * T6 + 60 * T5 + T21 + 18 * T3 + 3 * T2;
|
||||
T23 =
|
||||
2 * T9 + (T7 - 13) * T10 + (20 * T2 + 55 * H + 36) * T11 +
|
||||
(-22 * T3 - 93 * T2 - 126 * H - 55) * T12 +
|
||||
(20 * T4 + 95 * T3 + 180 * T2 + 155 * H + 50) * T14 +
|
||||
(-22 * T5 - 95 * T4 - T15 - 190 * T2 - 110 * H - 27) * T17 +
|
||||
(20 * T6 + 93 * T5 + 180 * T4 + 190 * T3 + T16 + 45 * H + 8) * T18 +
|
||||
(-10 * T8 - 55 * T6 - 126 * T5 - 155 * T4 - 110 * T3 + T13 + T7 - 1) * L +
|
||||
2 * T20 + 13 * T8 + 36 * T6 + 55 * T5 + 50 * T4 + 27 * T3 + 8 * T2 + H;
|
||||
T24 = T22 * D[3], T25 = T22 * D[2], T26 = T22 * D[1], T27 = T22 * D[0];
|
||||
return (T23 * D[5] * D[5] + (T22 * D[4] + T24 + T25 + T26 + T27) * D[5] +
|
||||
T23 * D[4] * D[4] + (T24 + T25 + T26 + T27) * D[4] +
|
||||
T23 * D[3] * D[3] + (T25 + T26 + T27) * D[3] + T23 * D[2] * D[2] +
|
||||
(T26 + T27) * D[2] + T23 * D[1] * D[1] + T22 * D[0] * D[1] +
|
||||
T23 * D[0] * D[0]) /
|
||||
6;
|
||||
}
|
463
dsp/core/differsumsq8.c
Normal file
463
dsp/core/differsumsq8.c
Normal file
|
@ -0,0 +1,463 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/core/q.h"
|
||||
|
||||
/**
|
||||
* Computes Σ𝑥ᵢΣ𝑥ⱼΣ𝑥ₖΣ𝑥ₗΣ𝑥ₘΣ𝑥ₙΣ𝑥ₚΣ𝑥ₛ(δ₁𝑥ᵢ+δ₂𝑥ⱼ+δ₃𝑥ₖ+δ₄𝑥ₗ+δ₅𝑥ₘ+δ₆𝑥ₙ+δₚ𝑥ₚ+δₛ𝑥ₛ)²
|
||||
*
|
||||
* “As soon as an Analytical Engine exists, it will necessarily
|
||||
* guide the future course of the science. Whenever any result
|
||||
* is sought by its aid, the question will then arise — by what
|
||||
* course of calculation can these results be arrived at by the
|
||||
* machine in the shortest time?
|
||||
*
|
||||
* — Charles Babbage (Life of a Philosopher, 1864)
|
||||
*
|
||||
*/
|
||||
double DifferSumSq8(const double D[static 8], double L, double H) {
|
||||
double T10, T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T11;
|
||||
double T110, T111, T112, T113, T114, T115, T116, T117, T118, T119, T12, T120;
|
||||
double T121, T122, T123, T124, T125, T126, T127, T128, T129, T13, T130, T131;
|
||||
double T132, T133, T134, T135, T136, T137, T138, T139, T14, T140, T141, T142;
|
||||
double T143, T144, T145, T146, T147, T148, T149, T15, T150, T151, T152, T153;
|
||||
double T154, T155, T156, T157, T158, T159, T16, T160, T161, T162, T163, T164;
|
||||
double T165, T166, T167, T168, T169, T17, T170, T171, T172, T173, T174, T175;
|
||||
double T176, T177, T178, T179, T18, T180, T181, T182, T183, T184, T185, T186;
|
||||
double T187, T188, T189, T19, T190, T191, T192, T193, T194, T195, T196, T197;
|
||||
double T198, T199, T2, T20, T200, T201, T202, T203, T204, T205, T206, T207;
|
||||
double T208, T209, T21, T210, T211, T212, T213, T214, T215, T216, T217, T218;
|
||||
double T219, T22, T220, T221, T222, T223, T224, T225, T226, T227, T228, T229;
|
||||
double T230, T231, T232, T233, T234, T235, T236, T237, T238, T239, T24, T240;
|
||||
double T241, T242, T243, T244, T245, T246, T247, T248, T249, T25, T250, T251;
|
||||
double T252, T253, T254, T255, T256, T257, T258, T259, T26, T260, T261, T262;
|
||||
double T263, T264, T265, T266, T267, T268, T269, T27, T270, T271, T272, T273;
|
||||
double T274, T275, T276, T277, T278, T279, T28, T280, T281, T282, T283, T284;
|
||||
double T285, T286, T287, T288, T289, T29, T290, T291, T292, T293, T294, T295;
|
||||
double T296, T297, T298, T299, T3, T30, T300, T301, T302, T303, T304, T305;
|
||||
double T307, T308, T309, T31, T310, T311, T312, T313, T314, T315, T316, T317;
|
||||
double T318, T319, T32, T320, T321, T322, T323, T324, T325, T326, T327, T328;
|
||||
double T329, T33, T330, T331, T332, T333, T334, T335, T336, T337, T338, T339;
|
||||
double T34, T340, T341, T342, T343, T344, T345, T346, T347, T348, T349, T35;
|
||||
double T350, T351, T352, T353, T354, T355, T356, T357, T358, T359, T36, T360;
|
||||
double T361, T362, T363, T364, T365, T366, T367, T368, T369, T37, T370, T371;
|
||||
double T372, T373, T374, T375, T376, T377, T378, T379, T38, T380, T381, T382;
|
||||
double T383, T384, T385, T386, T387, T388, T389, T39, T390, T391, T392, T393;
|
||||
double T394, T395, T396, T397, T398, T399, T4, T40, T400, T401, T402, T403;
|
||||
double T405, T406, T407, T41, T42, T43, T44, T45, T46, T47, T48, T49, T5, T50;
|
||||
double T51, T52, T53, T54, T55, T56, T57, T58, T59, T6, T60, T61, T62, T63;
|
||||
double T65, T66, T67, T68, T69, T7, T70, T71, T72, T73, T74, T75, T76, T77;
|
||||
double T79, T8, T80, T81, T82, T83, T84, T85, T86, T87, T88, T89, T9, T90;
|
||||
double T92, T93, T94, T95, T96, T97, T98, T99, T23, T306, T91, T78, T64, T404;
|
||||
T2 = 4 * D[5], T3 = 3 * D[4], T4 = 3 * D[3], T5 = 3 * D[2], T6 = 3 * D[1],
|
||||
T7 = 3 * D[0], T8 = D[7] * D[7], T9 = D[6] * D[6], T10 = -28 * D[5],
|
||||
T11 = -18 * D[4], T12 = -18 * D[3], T13 = -18 * D[2], T14 = -18 * D[1],
|
||||
T15 = -18 * D[0], T16 = D[5] * D[5], T17 = D[4] * D[4], T18 = D[3] * D[3],
|
||||
T19 = D[2] * D[2], T20 = D[1] * D[1], T21 = D[0] * D[0], T22 = -34 * D[5],
|
||||
T23 = -24 * D[4], T24 = -24 * D[3], T25 = -24 * D[2], T26 = -24 * D[1],
|
||||
T27 = -24 * D[0], T28 = 84 * D[5], T29 = 39 * D[4], T30 = 39 * D[3],
|
||||
T31 = 39 * D[2], T32 = 39 * D[1], T33 = 39 * D[0], T34 = 210 * D[5],
|
||||
T35 = 120 * D[4], T36 = 120 * D[3], T37 = 120 * D[2], T38 = 120 * D[1],
|
||||
T39 = 120 * D[0], T40 = 128 * D[5], T41 = 84 * D[4], T42 = 84 * D[3],
|
||||
T43 = 84 * D[2], T44 = 84 * D[1], T45 = 84 * D[0];
|
||||
T46 = -144 * D[5], T47 = (T23 + T24 + T25 + T26 + T27) * D[5],
|
||||
T48 = (T24 + T25 + T26 + T27) * D[4], T49 = (T25 + T26 + T27) * D[3],
|
||||
T50 = (T26 + T27) * D[2], T51 = -24 * D[0] * D[1], T52 = -552 * D[5],
|
||||
T53 = -192 * D[4], T54 = -192 * D[3], T55 = -192 * D[2], T56 = -192 * D[1],
|
||||
T57 = -192 * D[0], T58 = H * H, T59 = -688 * D[5], T60 = -336 * D[4],
|
||||
T61 = -336 * D[3], T62 = -336 * D[2], T63 = -336 * D[1], T64 = -336 * D[0],
|
||||
T65 = -280 * D[5], T66 = -168 * D[4], T67 = -168 * D[3], T68 = -168 * D[2],
|
||||
T69 = -168 * D[1], T70 = -168 * D[0], T71 = 168 * D[5], T72 = -42 * D[4],
|
||||
T73 = -42 * D[3], T74 = -42 * D[2], T75 = -42 * D[1], T76 = -42 * D[0],
|
||||
T77 = (H * H * H), T78 = 336 * D[4], T79 = 336 * D[3], T80 = 336 * D[2],
|
||||
T81 = 336 * D[1], T82 = 336 * D[0], T83 = 1568 * D[5],
|
||||
T84 = 336 * D[0] * D[1], T85 = 1288 * D[5], T86 = 504 * D[4],
|
||||
T87 = 504 * D[3], T88 = 504 * D[2], T89 = 504 * D[1], T90 = 504 * D[0],
|
||||
T91 = 392 * D[5], T92 = 210 * D[4], T93 = 210 * D[3], T94 = 210 * D[2],
|
||||
T95 = 210 * D[1], T96 = 210 * D[0], T97 = 84 * T8, T98 = 168 * D[6],
|
||||
T99 = 84 * T9, T100 = 84 * T16, T101 = (T41 + T42 + T43 + T44 + T45) * D[5],
|
||||
T102 = 84 * T17, T103 = (T42 + T43 + T44 + T45) * D[4], T104 = 84 * T18,
|
||||
T105 = (T43 + T44 + T45) * D[3], T106 = 84 * T19, T107 = (T44 + T45) * D[2],
|
||||
T108 = 84 * T20, T109 = 84 * D[0] * D[1], T110 = 84 * T21, T111 = -924 * D[5],
|
||||
T112 = (T78 + T79 + T80 + T81 + T82) * D[5],
|
||||
T113 = (T79 + T80 + T81 + T82) * D[4], T114 = (T80 + T81 + T82) * D[3],
|
||||
T115 = (T81 + T82) * D[2], T116 = (H * H * H * H), T117 = -2128 * D[5],
|
||||
T118 = -2520 * D[5], T119 = (T66 + T67 + T68 + T69 + T70) * D[5],
|
||||
T120 = (T67 + T68 + T69 + T70) * D[4], T121 = (T68 + T69 + T70) * D[3],
|
||||
T122 = (T69 + T70) * D[2], T123 = -168 * D[0] * D[1], T124 = -1512 * D[5],
|
||||
T125 = -420 * D[4], T126 = -420 * D[3], T127 = -420 * D[2],
|
||||
T128 = -420 * D[1], T129 = -420 * D[0], T130 = -364 * D[5];
|
||||
T131 = T97 + (T98 + T71 + T72 + T73 + T74 + T75 + T76) * D[7] + T99 +
|
||||
(T71 + T72 + T73 + T74 + T75 + T76) * D[6] + T100 +
|
||||
(T72 + T73 + T74 + T75 + T76) * D[5] + T102 +
|
||||
(T73 + T74 + T75 + T76) * D[4] + T104 + (T74 + T75 + T76) * D[3] +
|
||||
T106 + (T75 + T76) * D[2] + T108 - 42 * D[0] * D[1] + T110;
|
||||
T132 = 462 * T8, T133 = 924 * D[6], T134 = 924 * D[5], T135 = 462 * T9,
|
||||
T136 = 462 * T16, T137 = (T60 + T61 + T62 + T63 + T64) * D[5],
|
||||
T138 = 462 * T17, T139 = (T61 + T62 + T63 + T64) * D[4], T140 = 462 * T18,
|
||||
T141 = (T62 + T63 + T64) * D[3], T142 = 462 * T19, T143 = (T63 + T64) * D[2],
|
||||
T144 = 462 * T20, T145 = 462 * T21, T146 = (H * H * H * H * H),
|
||||
T147 = 2240 * D[5], T148 = -840 * D[4], T149 = -840 * D[3],
|
||||
T150 = -840 * D[2], T151 = -840 * D[1], T152 = -840 * D[0],
|
||||
T153 = 3080 * D[5], T154 = (T148 + T149 + T150 + T151 + T152) * D[5],
|
||||
T155 = (T149 + T150 + T151 + T152) * D[4], T156 = (T150 + T151 + T152) * D[3],
|
||||
T157 = (T151 + T152) * D[2], T158 = -840 * D[0] * D[1], T159 = 1260 * T8,
|
||||
T160 = 2520 * D[6], T161 = 2520 * D[5], T162 = 1260 * T9, T163 = 1260 * T16,
|
||||
T164 = 1260 * T17, T165 = 1260 * T18, T166 = 1260 * T19, T167 = 1260 * T20,
|
||||
T168 = 210 * D[0] * D[1], T169 = 1260 * T21, T170 = 168 * D[4],
|
||||
T171 = 168 * D[3], T172 = 168 * D[2], T173 = 168 * D[1], T174 = 168 * D[0],
|
||||
T175 = 1148 * D[5], T176 = 168 * D[0] * D[1], T177 = 224 * D[5];
|
||||
T178 = -72 * T8 + (-144 * D[6] + T46 + T23 + T24 + T25 + T26 + T27) * D[7] -
|
||||
72 * T9 + (T46 + T23 + T24 + T25 + T26 + T27) * D[6] - 72 * T16 + T47 -
|
||||
72 * T17 + T48 - 72 * T18 + T49 - 72 * T19 + T50 - 72 * T20 + T51 -
|
||||
72 * T21;
|
||||
T179 = 420 * T8, T180 = 840 * D[6], T181 = 840 * D[5], T182 = 420 * T9,
|
||||
T183 = 840 * D[5] * D[6], T184 = 420 * T16, T185 = 420 * T17,
|
||||
T186 = 420 * T18, T187 = 420 * T19, T188 = 420 * T20, T189 = 420 * T21,
|
||||
T190 = (H * H * H * H * H * H);
|
||||
T191 = -1064 * T8 +
|
||||
(-2128 * D[6] + T117 + T78 + T79 + T80 + T81 + T82) * D[7] -
|
||||
1064 * T9 + (T117 + T78 + T79 + T80 + T81 + T82) * D[6] - 1064 * T16 +
|
||||
T112 - 1064 * T17 + T113 - 1064 * T18 + T114 - 1064 * T19 + T115 -
|
||||
1064 * T20 + T84 - 1064 * T21;
|
||||
T192 = 1540 * T8, T193 = 3080 * D[6], T194 = 840 * D[4], T195 = 840 * D[3],
|
||||
T196 = 840 * D[2], T197 = 840 * D[1], T198 = 840 * D[0], T199 = 1540 * T9,
|
||||
T200 = 1540 * T16, T201 = 1540 * T17, T202 = 1540 * T18, T203 = 1540 * T19,
|
||||
T204 = 1540 * T20, T205 = 840 * D[0] * D[1], T206 = 1540 * T21,
|
||||
T207 = -2800 * D[5], T208 = (T194 + T195 + T196 + T197 + T198) * D[5],
|
||||
T209 = (T195 + T196 + T197 + T198) * D[4], T210 = (T196 + T197 + T198) * D[3],
|
||||
T211 = (T197 + T198) * D[2], T212 = -1624 * D[5], T213 = -88 * D[5];
|
||||
T214 = 42 * T8 + (84 * D[6] + T28 + T29 + T30 + T31 + T32 + T33) * D[7] +
|
||||
42 * T9 + (T28 + T29 + T30 + T31 + T32 + T33) * D[6] + 42 * T16 +
|
||||
(T29 + T30 + T31 + T32 + T33) * D[5] + 42 * T17 +
|
||||
(T30 + T31 + T32 + T33) * D[4] + 42 * T18 + (T31 + T32 + T33) * D[3] +
|
||||
42 * T19 + (T32 + T33) * D[2] + 42 * T20 + 39 * D[0] * D[1] + 42 * T21;
|
||||
T215 = 276 * T8, T216 = 552 * D[6], T217 = 552 * D[5], T218 = 192 * D[4],
|
||||
T219 = 192 * D[3], T220 = 192 * D[2], T221 = 192 * D[1], T222 = 192 * D[0],
|
||||
T223 = 276 * T9, T224 = 276 * T16, T225 = 276 * T17, T226 = 276 * T18,
|
||||
T227 = 276 * T19, T228 = 276 * T20, T229 = 192 * D[0] * D[1],
|
||||
T230 = 276 * T21, T231 = (H * H * H * H * H * H * H);
|
||||
T232 = 784 * T8 + (1568 * D[6] + T83 + T78 + T79 + T80 + T81 + T82) * D[7] +
|
||||
784 * T9 + (T83 + T78 + T79 + T80 + T81 + T82) * D[6] + 784 * T16 +
|
||||
T112 + 784 * T17 + T113 + 784 * T18 + T114 + 784 * T19 + T115 +
|
||||
784 * T20 + T84 + 784 * T21;
|
||||
T233 = (T170 + T171 + T172 + T173 + T174) * D[5];
|
||||
T234 = (T171 + T172 + T173 + T174) * D[4];
|
||||
T235 = (T172 + T173 + T174) * D[3];
|
||||
T236 = (T173 + T174) * D[2];
|
||||
T237 = T159 + (T160 + T161 - T92 - T93 - T94 - T95 - T96) * D[7] + T162 +
|
||||
(T161 - T92 - T93 - T94 - T95 - T96) * D[6] + T163 +
|
||||
(-T92 - T93 - T94 - T95 - T96) * D[5] + T164 +
|
||||
(-T93 - T94 - T95 - T96) * D[4] + T165 + (-T94 - T95 - T96) * D[3] +
|
||||
T166 + (-T95 - T96) * D[2] + T167 - T168 + T169;
|
||||
T238 = 812 * T8, T239 = 1624 * D[6], T240 = 1624 * D[5], T241 = 812 * T9,
|
||||
T242 = 812 * T16, T243 = 812 * T17, T244 = 812 * T18, T245 = 812 * T19,
|
||||
T246 = 812 * T20, T247 = 812 * T21, T248 = 672 * D[5], T249 = 20 * D[5],
|
||||
T250 = (T3 + T4 + T5 + T6 + T7) * D[5], T251 = (T4 + T5 + T6 + T7) * D[4],
|
||||
T252 = (T5 + T6 + T7) * D[3], T253 = (T6 + T7) * D[2], T254 = 3 * D[0] * D[1];
|
||||
T255 = -14 * T8 + (-28 * D[6] + T10 + T11 + T12 + T13 + T14 + T15) * D[7] -
|
||||
14 * T9 + (T10 + T11 + T12 + T13 + T14 + T15) * D[6] - 14 * T16 +
|
||||
(T11 + T12 + T13 + T14 + T15) * D[5] - 14 * T17 +
|
||||
(T12 + T13 + T14 + T15) * D[4] - 14 * T18 + (T13 + T14 + T15) * D[3] -
|
||||
14 * T19 + (T14 + T15) * D[2] - 14 * T20 - 18 * D[0] * D[1] - 14 * T21;
|
||||
T256 = 105 * T8, T257 = 210 * D[6], T258 = 105 * T9, T259 = 105 * T16,
|
||||
T260 = 105 * T17, T261 = 105 * T18, T262 = 105 * T19, T263 = 105 * T20,
|
||||
T264 = 120 * D[0] * D[1], T265 = 105 * T21,
|
||||
T266 = (H * H * H * H * H * H * H * H);
|
||||
T267 = -344 * T8 + (-688 * D[6] + T59 + T60 + T61 + T62 + T63 + T64) * D[7] -
|
||||
344 * T9 + (T59 + T60 + T61 + T62 + T63 + T64) * D[6] - 344 * T16 +
|
||||
T137 - 344 * T17 + T139 - 344 * T18 + T141 - 344 * T19 + T143 -
|
||||
344 * T20 - T84 - 344 * T21;
|
||||
T268 = 644 * T8, T269 = 1288 * D[6], T270 = 644 * T9, T271 = 644 * T16,
|
||||
T272 = 644 * T17, T273 = 644 * T18, T274 = 644 * T19, T275 = 644 * T20,
|
||||
T276 = 504 * D[0] * D[1], T277 = 644 * T21;
|
||||
T278 = -756 * T8 +
|
||||
(-1512 * D[6] + T124 + T125 + T126 + T127 + T128 + T129) * D[7] -
|
||||
756 * T9 + (T124 + T125 + T126 + T127 + T128 + T129) * D[6] -
|
||||
756 * T16 + (T125 + T126 + T127 + T128 + T129) * D[5] - 756 * T17 +
|
||||
(T126 + T127 + T128 + T129) * D[4] - 756 * T18 +
|
||||
(T127 + T128 + T129) * D[3] - 756 * T19 + (T128 + T129) * D[2] -
|
||||
756 * T20 - 420 * D[0] * D[1] - 756 * T21;
|
||||
T279 = 574 * T8, T280 = 1148 * D[6], T281 = 574 * T9, T282 = 574 * T16,
|
||||
T283 = 574 * T17, T284 = 574 * T18, T285 = 574 * T19, T286 = 574 * T20,
|
||||
T287 = 574 * T21;
|
||||
T288 = -280 * T8 + (-560 * D[6] - 560 * D[5]) * D[7] - 280 * T9 -
|
||||
560 * D[5] * D[6] - 280 * T16 - 280 * T17 - 280 * T18 - 280 * T19 -
|
||||
280 * T20 - 280 * T21;
|
||||
T289 = 24 * D[4], T290 = 24 * D[3], T291 = 24 * D[2], T292 = 24 * D[1],
|
||||
T293 = 24 * D[0], T294 = 24 * D[0] * D[1], T295 = -14 * T8, T296 = -28 * D[6],
|
||||
T297 = -14 * T9, T298 = 6 * D[4], T299 = 6 * D[3], T300 = 6 * D[2],
|
||||
T301 = 6 * D[1], T302 = 6 * D[0], T303 = -14 * T16, T304 = -14 * T17,
|
||||
T305 = -14 * T18, T306 = -14 * T19, T307 = -14 * T20, T308 = -14 * T21;
|
||||
T309 = 2 * T8 + (4 * D[6] + T2 + T3 + T4 + T5 + T6 + T7) * D[7] + 2 * T9 +
|
||||
(T2 + T3 + T4 + T5 + T6 + T7) * D[6] + 2 * T16 + T250 + 2 * T17 +
|
||||
T251 + 2 * T18 + T252 + 2 * T19 + T253 + 2 * T20 + T254 + 2 * T21;
|
||||
T310 = 17 * T8, T311 = 34 * D[6], T312 = 34 * D[5], T313 = 17 * T9,
|
||||
T314 = 17 * T16, T315 = (T289 + T290 + T291 + T292 + T293) * D[5];
|
||||
T316 = 17 * T17, T317 = (T290 + T291 + T292 + T293) * D[4];
|
||||
T318 = 17 * T18, T319 = (T291 + T292 + T293) * D[3];
|
||||
T320 = 17 * T19, T321 = (T292 + T293) * D[2];
|
||||
T322 = 17 * T20, T323 = 17 * T21, T324 = (H * H * H * H * H * H * H * H * H);
|
||||
T325 = 64 * T8,
|
||||
T326 = (128 * D[6] + T40 + T41 + T42 + T43 + T44 + T45) * D[7];
|
||||
T327 = 64 * T9, T328 = (T40 + T41 + T42 + T43 + T44 + T45) * D[6];
|
||||
T329 = 64 * T16, T330 = 64 * T17, T331 = 64 * T18, T332 = 64 * T19,
|
||||
T333 = 64 * T20, T334 = 64 * T21, T335 = 140 * T8, T336 = 280 * D[6],
|
||||
T337 = 280 * D[5], T338 = 140 * T9, T339 = 140 * T16, T340 = 140 * T17,
|
||||
T341 = 140 * T18, T342 = 140 * T19, T343 = 140 * T20, T344 = 140 * T21,
|
||||
T345 = 196 * T8;
|
||||
T346 = (392 * D[6] + T91 + T92 + T93 + T94 + T95 + T96) * D[7];
|
||||
T347 = 196 * T9;
|
||||
T348 = (T91 + T92 + T93 + T94 + T95 + T96) * D[6];
|
||||
T349 = 196 * T16;
|
||||
T350 = (T92 + T93 + T94 + T95 + T96) * D[5];
|
||||
T351 = 196 * T17;
|
||||
T352 = (T93 + T94 + T95 + T96) * D[4];
|
||||
T353 = 196 * T18;
|
||||
T354 = (T94 + T95 + T96) * D[3];
|
||||
T355 = 196 * T19;
|
||||
T356 = (T95 + T96) * D[2];
|
||||
T357 = 196 * T20, T358 = 196 * T21, T359 = 182 * T8, T360 = 364 * D[6],
|
||||
T361 = 364 * D[5], T362 = 182 * T9, T363 = 182 * T16, T364 = 182 * T17,
|
||||
T365 = 182 * T18, T366 = 182 * T19, T367 = 182 * T20, T368 = 182 * T21,
|
||||
T369 = 112 * T8;
|
||||
T370 = (224 * D[6] + T177 + T41 + T42 + T43 + T44 + T45) * D[7];
|
||||
T371 = 112 * T9;
|
||||
T372 = (T177 + T41 + T42 + T43 + T44 + T45) * D[6];
|
||||
T373 = 112 * T16, T374 = 112 * T17, T375 = 112 * T18, T376 = 112 * T19,
|
||||
T377 = 112 * T20, T378 = 112 * T21, T379 = 44 * T8, T380 = 88 * D[6],
|
||||
T381 = 88 * D[5], T382 = 44 * T9, T383 = 44 * T16, T384 = 44 * T17,
|
||||
T385 = 44 * T18, T386 = 44 * T19, T387 = 44 * T20, T388 = 44 * T21,
|
||||
T389 = 10 * T8, T390 = (20 * D[6] + T249 + T3 + T4 + T5 + T6 + T7) * D[7];
|
||||
T391 = 10 * T9, T392 = (T249 + T3 + T4 + T5 + T6 + T7) * D[6];
|
||||
T393 = 10 * T16, T394 = 10 * T17, T395 = 10 * T18, T396 = 10 * T19,
|
||||
T397 = 10 * T20, T398 = 10 * T21, T399 = 2 * D[6], T400 = 2 * D[5],
|
||||
T401 = 2 * D[5] * D[6];
|
||||
T402 = T309 * (L * L * L * L * L * L * L * L * L * L) +
|
||||
(T255 * H - T310 + (-T311 + T22 + T23 + T24 + T25 + T26 + T27) * D[7] -
|
||||
T313 + (T22 + T23 + T24 + T25 + T26 + T27) * D[6] - T314 + T47 -
|
||||
T316 + T48 - T318 + T49 - T320 + T50 - T322 + T51 - T323) *
|
||||
(L * L * L * L * L * L * L * L * L) +
|
||||
(T214 * T58 +
|
||||
(T256 + (T257 + T34 + T35 + T36 + T37 + T38 + T39) * D[7] + T258 +
|
||||
(T34 + T35 + T36 + T37 + T38 + T39) * D[6] + T259 +
|
||||
(T35 + T36 + T37 + T38 + T39) * D[5] + T260 +
|
||||
(T36 + T37 + T38 + T39) * D[4] + T261 + (T37 + T38 + T39) * D[3] +
|
||||
T262 + (T38 + T39) * D[2] + T263 + T264 + T265) *
|
||||
H +
|
||||
T325 + T326 + T327 + T328 + T329 + T101 + T330 + T103 + T331 + T105 +
|
||||
T332 + T107 + T333 + T109 + T334) *
|
||||
(L * L * L * L * L * L * L * L) +
|
||||
(T178 * T77 +
|
||||
(-T215 + (-T216 + T52 + T53 + T54 + T55 + T56 + T57) * D[7] - T223 +
|
||||
(T52 + T53 + T54 + T55 + T56 + T57) * D[6] - T224 +
|
||||
(T53 + T54 + T55 + T56 + T57) * D[5] - T225 +
|
||||
(T54 + T55 + T56 + T57) * D[4] - T226 + (T55 + T56 + T57) * D[3] -
|
||||
T227 + (T56 + T57) * D[2] - T228 - T229 - T230) *
|
||||
T58 +
|
||||
T267 * H - T335 + (-T336 + T65 + T66 + T67 + T68 + T69 + T70) * D[7] -
|
||||
T338 + (T65 + T66 + T67 + T68 + T69 + T70) * D[6] - T339 + T119 -
|
||||
T340 + T120 - T341 + T121 - T342 + T122 - T343 + T123 - T344) *
|
||||
(L * L * L * L * L * L * L);
|
||||
T403 =
|
||||
T402 +
|
||||
(T131 * T116 +
|
||||
(T179 + (T180 + T181) * D[7] + T182 + T183 + T184 + T185 + T186 + T187 +
|
||||
T188 + T189) *
|
||||
T77 +
|
||||
T232 * T58 +
|
||||
(T268 + (T269 + T85 + T86 + T87 + T88 + T89 + T90) * D[7] + T270 +
|
||||
(T85 + T86 + T87 + T88 + T89 + T90) * D[6] + T271 +
|
||||
(T86 + T87 + T88 + T89 + T90) * D[5] + T272 +
|
||||
(T87 + T88 + T89 + T90) * D[4] + T273 + (T88 + T89 + T90) * D[3] +
|
||||
T274 + (T89 + T90) * D[2] + T275 + T276 + T277) *
|
||||
H +
|
||||
T345 + T346 + T347 + T348 + T349 + T350 + T351 + T352 + T353 + T354 +
|
||||
T355 + T356 + T357 + T168 + T358) *
|
||||
(L * L * L * L * L * L) +
|
||||
((-T97 + (-T98 - T71 + T41 + T42 + T43 + T44 + T45) * D[7] - T99 +
|
||||
(-T71 + T41 + T42 + T43 + T44 + T45) * D[6] - T100 + T101 - T102 +
|
||||
T103 - T104 + T105 - T106 + T107 - T108 + T109 - T110) *
|
||||
T146 +
|
||||
(-T132 + (-T133 + T111 + T78 + T79 + T80 + T81 + T82) * D[7] - T135 +
|
||||
(T111 + T78 + T79 + T80 + T81 + T82) * D[6] - T136 + T112 - T138 +
|
||||
T113 - T140 + T114 - T142 + T115 - T144 + T84 - T145) *
|
||||
T116 +
|
||||
T191 * T77 +
|
||||
(-T159 + (-T160 + T118 + T66 + T67 + T68 + T69 + T70) * D[7] - T162 +
|
||||
(T118 + T66 + T67 + T68 + T69 + T70) * D[6] - T163 + T119 - T164 +
|
||||
T120 - T165 + T121 - T166 + T122 - T167 + T123 - T169) *
|
||||
T58 +
|
||||
T278 * H - T359 + (-T360 + T130 + T66 + T67 + T68 + T69 + T70) * D[7] -
|
||||
T362 + (T130 + T66 + T67 + T68 + T69 + T70) * D[6] - T363 + T119 - T364 +
|
||||
T120 - T365 + T121 - T366 + T122 - T367 + T123 - T368) *
|
||||
(L * L * L * L * L);
|
||||
T404 =
|
||||
T403 +
|
||||
(T131 * T190 +
|
||||
(T132 + (T133 + T134 + T60 + T61 + T62 + T63 + T64) * D[7] + T135 +
|
||||
(T134 + T60 + T61 + T62 + T63 + T64) * D[6] + T136 + T137 + T138 +
|
||||
T139 + T140 + T141 + T142 + T143 + T144 - T84 + T145) *
|
||||
T146 +
|
||||
(1120 * T8 +
|
||||
(2240 * D[6] + T147 + T148 + T149 + T150 + T151 + T152) * D[7] +
|
||||
1120 * T9 + (T147 + T148 + T149 + T150 + T151 + T152) * D[6] +
|
||||
1120 * T16 + T154 + 1120 * T17 + T155 + 1120 * T18 + T156 + 1120 * T19 +
|
||||
T157 + 1120 * T20 + T158 + 1120 * T21) *
|
||||
T116 +
|
||||
(T192 + (T193 + T153 + T148 + T149 + T150 + T151 + T152) * D[7] + T199 +
|
||||
(T153 + T148 + T149 + T150 + T151 + T152) * D[6] + T200 + T154 + T201 +
|
||||
T155 + T202 + T156 + T203 + T157 + T204 + T158 + T206) *
|
||||
T77 +
|
||||
T237 * T58 +
|
||||
(T279 + (T280 + T175 + T170 + T171 + T172 + T173 + T174) * D[7] + T281 +
|
||||
(T175 + T170 + T171 + T172 + T173 + T174) * D[6] + T282 + T233 + T283 +
|
||||
T234 + T284 + T235 + T285 + T236 + T286 + T176 + T287) *
|
||||
H +
|
||||
T369 + T370 + T371 + T372 + T373 + T101 + T374 + T103 + T375 + T105 +
|
||||
T376 + T107 + T377 + T109 + T378) *
|
||||
(L * L * L * L) +
|
||||
(T178 * T231 +
|
||||
(-T179 + (-T180 - T181) * D[7] - T182 - T183 - T184 - T185 - T186 -
|
||||
T187 - T188 - T189) *
|
||||
T190 +
|
||||
T191 * T146 +
|
||||
(-T192 + (-T193 - T153 + T194 + T195 + T196 + T197 + T198) * D[7] -
|
||||
T199 + (-T153 + T194 + T195 + T196 + T197 + T198) * D[6] - T200 + T208 -
|
||||
T201 + T209 - T202 + T210 - T203 + T211 - T204 + T205 - T206) *
|
||||
T116 +
|
||||
(-1400 * T8 +
|
||||
(-2800 * D[6] + T207 + T194 + T195 + T196 + T197 + T198) * D[7] -
|
||||
1400 * T9 + (T207 + T194 + T195 + T196 + T197 + T198) * D[6] -
|
||||
1400 * T16 + T208 - 1400 * T17 + T209 - 1400 * T18 + T210 - 1400 * T19 +
|
||||
T211 - 1400 * T20 + T205 - 1400 * T21) *
|
||||
T77 +
|
||||
(-T238 + (-T239 + T212 + T78 + T79 + T80 + T81 + T82) * D[7] - T241 +
|
||||
(T212 + T78 + T79 + T80 + T81 + T82) * D[6] - T242 + T112 - T243 +
|
||||
T113 - T244 + T114 - T245 + T115 - T246 + T84 - T247) *
|
||||
T58 +
|
||||
T288 * H - T379 + (-T380 + T213 + T23 + T24 + T25 + T26 + T27) * D[7] -
|
||||
T382 + (T213 + T23 + T24 + T25 + T26 + T27) * D[6] - T383 + T47 - T384 +
|
||||
T48 - T385 + T49 - T386 + T50 - T387 + T51 - T388) *
|
||||
(L * L * L);
|
||||
T405 =
|
||||
T214 * T266 +
|
||||
(T215 + (T216 + T217 + T218 + T219 + T220 + T221 + T222) * D[7] + T223 +
|
||||
(T217 + T218 + T219 + T220 + T221 + T222) * D[6] + T224 +
|
||||
(T218 + T219 + T220 + T221 + T222) * D[5] + T225 +
|
||||
(T219 + T220 + T221 + T222) * D[4] + T226 + (T220 + T221 + T222) * D[3] +
|
||||
T227 + (T221 + T222) * D[2] + T228 + T229 + T230) *
|
||||
T231 +
|
||||
T232 * T190 +
|
||||
(T159 + (T160 + T161 + T170 + T171 + T172 + T173 + T174) * D[7] + T162 +
|
||||
(T161 + T170 + T171 + T172 + T173 + T174) * D[6] + T163 + T233 + T164 +
|
||||
T234 + T165 + T235 + T166 + T236 + T167 + T176 + T169) *
|
||||
T146 +
|
||||
T237 * T116 +
|
||||
(T238 + (T239 + T240 + T60 + T61 + T62 + T63 + T64) * D[7] + T241 +
|
||||
(T240 + T60 + T61 + T62 + T63 + T64) * D[6] + T242 + T137 + T243 + T139 +
|
||||
T244 + T141 + T245 + T143 + T246 - T84 + T247) *
|
||||
T77 +
|
||||
(336 * T8 + (672 * D[6] + T248 + T66 + T67 + T68 + T69 + T70) * D[7] +
|
||||
336 * T9 + (T248 + T66 + T67 + T68 + T69 + T70) * D[6] + 336 * T16 +
|
||||
T119 + 336 * T17 + T120 + 336 * T18 + T121 + 336 * T19 + T122 +
|
||||
336 * T20 - T176 + 336 * T21) *
|
||||
T58 +
|
||||
(T97 + (T98 + T71 + T23 + T24 + T25 + T26 + T27) * D[7] + T99 +
|
||||
(T71 + T23 + T24 + T25 + T26 + T27) * D[6] + T100 + T47 + T102 + T48 +
|
||||
T104 + T49 + T106 + T50 + T108 + T51 + T110) *
|
||||
H +
|
||||
T389 + T390 + T391;
|
||||
T406 = T255 * T324 +
|
||||
(-T256 + (-T257 - T34 - T35 - T36 - T37 - T38 - T39) * D[7] - T258 +
|
||||
(-T34 - T35 - T36 - T37 - T38 - T39) * D[6] - T259 +
|
||||
(-T35 - T36 - T37 - T38 - T39) * D[5] - T260 +
|
||||
(-T36 - T37 - T38 - T39) * D[4] - T261 + (-T37 - T38 - T39) * D[3] -
|
||||
T262 + (-T38 - T39) * D[2] - T263 - T264 - T265) *
|
||||
T266 +
|
||||
T267 * T231 +
|
||||
(-T268 + (-T269 - T85 - T86 - T87 - T88 - T89 - T90) * D[7] - T270 +
|
||||
(-T85 - T86 - T87 - T88 - T89 - T90) * D[6] - T271 +
|
||||
(-T86 - T87 - T88 - T89 - T90) * D[5] - T272 +
|
||||
(-T87 - T88 - T89 - T90) * D[4] - T273 + (-T88 - T89 - T90) * D[3] -
|
||||
T274 + (-T89 - T90) * D[2] - T275 - T276 - T277) *
|
||||
T190 +
|
||||
T278 * T146 +
|
||||
(-T279 + (-T280 - T175 + T66 + T67 + T68 + T69 + T70) * D[7] - T281 +
|
||||
(-T175 + T66 + T67 + T68 + T69 + T70) * D[6] - T282 + T119 - T283 +
|
||||
T120 - T284 + T121 - T285 + T122 - T286 - T176 - T287) *
|
||||
T116 +
|
||||
T288 * T77 +
|
||||
(-T97 + (-T98 - T71 + T289 + T290 + T291 + T292 + T293) * D[7] - T99 +
|
||||
(-T71 + T289 + T290 + T291 + T292 + T293) * D[6] - T100 + T315 -
|
||||
T102 + T317 - T104 + T319 - T106 + T321 - T108 + T294 - T110) *
|
||||
T58;
|
||||
T407 = T404 +
|
||||
(T405 + T392 + T393 + T250 + T394 + T251 + T395 + T252 + T396 + T253 +
|
||||
T397 + T254 + T398) *
|
||||
L * L +
|
||||
(T406 +
|
||||
(T295 + (T296 + T10 + T298 + T299 + T300 + T301 + T302) * D[7] +
|
||||
T297 + (T10 + T298 + T299 + T300 + T301 + T302) * D[6] + T303 +
|
||||
(T298 + T299 + T300 + T301 + T302) * D[5] + T304 +
|
||||
(T299 + T300 + T301 + T302) * D[4] + T305 +
|
||||
(T300 + T301 + T302) * D[3] + T306 + (T301 + T302) * D[2] + T307 +
|
||||
6 * D[0] * D[1] + T308) *
|
||||
H -
|
||||
T8 + (-T399 - T400) * D[7] - T9 - T401 - T16 - T17 - T18 - T19 - T20 -
|
||||
T21) *
|
||||
L +
|
||||
T309 * (H * H * H * H * H * H * H * H * H * H) +
|
||||
(T310 + (T311 + T312 + T289 + T290 + T291 + T292 + T293) * D[7] +
|
||||
T313 + (T312 + T289 + T290 + T291 + T292 + T293) * D[6] + T314 +
|
||||
T315 + T316 + T317 + T318 + T319 + T320 + T321 + T322 + T294 + T323) *
|
||||
T324 +
|
||||
(T325 + T326 + T327 + T328 + T329 + T101 + T330 + T103 + T331 + T105 +
|
||||
T332 + T107 + T333 + T109 + T334) *
|
||||
T266 +
|
||||
(T335 + (T336 + T337 + T170 + T171 + T172 + T173 + T174) * D[7] +
|
||||
T338 + (T337 + T170 + T171 + T172 + T173 + T174) * D[6] + T339 +
|
||||
T233 + T340 + T234 + T341 + T235 + T342 + T236 + T343 + T176 + T344) *
|
||||
T231 +
|
||||
(T345 + T346 + T347 + T348 + T349 + T350 + T351 + T352 + T353 + T354 +
|
||||
T355 + T356 + T357 + T168 + T358) *
|
||||
T190;
|
||||
return (T407 +
|
||||
(T359 + (T360 + T361 + T170 + T171 + T172 + T173 + T174) * D[7] +
|
||||
T362 + (T361 + T170 + T171 + T172 + T173 + T174) * D[6] + T363 +
|
||||
T233 + T364 + T234 + T365 + T235 + T366 + T236 + T367 + T176 +
|
||||
T368) *
|
||||
T146 +
|
||||
(T369 + T370 + T371 + T372 + T373 + T101 + T374 + T103 + T375 + T105 +
|
||||
T376 + T107 + T377 + T109 + T378) *
|
||||
T116 +
|
||||
(T379 + (T380 + T381 + T289 + T290 + T291 + T292 + T293) * D[7] +
|
||||
T382 + (T381 + T289 + T290 + T291 + T292 + T293) * D[6] + T383 +
|
||||
T315 + T384 + T317 + T385 + T319 + T386 + T321 + T387 + T294 +
|
||||
T388) *
|
||||
T77 +
|
||||
(T389 + T390 + T391 + T392 + T393 + T250 + T394 + T251 + T395 + T252 +
|
||||
T396 + T253 + T397 + T254 + T398) *
|
||||
T58 +
|
||||
(T8 + (T399 + T400) * D[7] + T9 + T401 + T16 + T17 + T18 + T19 + T20 +
|
||||
T21) *
|
||||
H) /
|
||||
6;
|
||||
}
|
35
dsp/core/double2byte.c
Normal file
35
dsp/core/double2byte.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
void *double2byte(long n, const void *p, double weight, double bias) {
|
||||
long i;
|
||||
const double *src;
|
||||
unsigned char *dst;
|
||||
if ((dst = valloc(n * sizeof(unsigned char)))) {
|
||||
for (src = p, i = 0; i < n; ++i) {
|
||||
dst[i] = MIN(255, MAX(0, rint(src[i] * weight + bias)));
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
41
dsp/core/float2short.c
Normal file
41
dsp/core/float2short.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Converts floating point audio samples to pulse code modulation.
|
||||
*
|
||||
* @param rdi is number of sample chunks
|
||||
* @param rsi points to aligned pcm [-32k,+32k] output memory
|
||||
* @param rdx points to aligned float32 [-1,+1] input memory
|
||||
*/
|
||||
void float2short(size_t n, short pcm16[n][8], const float binary32[n][8]) {
|
||||
size_t i, j;
|
||||
float f[8], w[8];
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
pcm16[i][j] =
|
||||
MIN(SHRT_MAX, MAX(SHRT_MIN, floorf(binary32[i][j] * (SHRT_MAX + 1))));
|
||||
}
|
||||
}
|
||||
}
|
40
dsp/core/gamma.c
Normal file
40
dsp/core/gamma.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/core/gamma.h"
|
||||
#include "libc/math.h"
|
||||
|
||||
double rgb2stdpc(double x, double g) {
|
||||
return COMPANDLUMA_SRGB(x, g);
|
||||
}
|
||||
double rgb2linpc(double x, double g) {
|
||||
return UNCOMPANDLUMA_SRGB(x, g);
|
||||
}
|
||||
|
||||
double rgb2stdtv(double x) {
|
||||
return COMPANDLUMA_BT1886(x);
|
||||
}
|
||||
double rgb2lintv(double x) {
|
||||
return UNCOMPANDLUMA_BT1886(x);
|
||||
}
|
||||
|
||||
double tv2pcgamma(double x, double g) {
|
||||
return rgb2stdpc(rgb2lintv(x), g);
|
||||
}
|
23
dsp/core/gamma.h
Normal file
23
dsp/core/gamma.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_GAMMA_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_GAMMA_H_
|
||||
#include "libc/math.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define COMPANDLUMA(X, ...) COMPANDLUMA_(X, __VA_ARGS__)
|
||||
#define COMPANDLUMA_(X, K1, K2, K3, K4) \
|
||||
((X) > (K3) / (K4) ? (1 + (K2)) * pow((X), 1 / (K1)) - (K2) : (X) * (K4))
|
||||
|
||||
#define UNCOMPANDLUMA(X, ...) UNCOMPANDLUMA_(X, __VA_ARGS__)
|
||||
#define UNCOMPANDLUMA_(X, K1, K2, K3, K4) \
|
||||
((X) > (K3) ? pow(1 / (1 + (K2)) * ((X) + (K2)), K1) : (X) / (K4))
|
||||
|
||||
#define COMPANDLUMA_SRGB_MAGNUM .055, .04045, 12.92
|
||||
#define COMPANDLUMA_SRGB(X, G) COMPANDLUMA(X, G, COMPANDLUMA_SRGB_MAGNUM)
|
||||
#define UNCOMPANDLUMA_SRGB(X, G) UNCOMPANDLUMA(X, G, COMPANDLUMA_SRGB_MAGNUM)
|
||||
|
||||
#define COMPANDLUMA_BT1886_MAGNUM 1 / .45, .099, .081, 4.5
|
||||
#define COMPANDLUMA_BT1886(X) COMPANDLUMA(X, COMPANDLUMA_BT1886_MAGNUM)
|
||||
#define UNCOMPANDLUMA_BT1886(X) UNCOMPANDLUMA(X, COMPANDLUMA_BT1886_MAGNUM)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_GAMMA_H_ */
|
113
dsp/core/getintegercoefficients.c
Normal file
113
dsp/core/getintegercoefficients.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/q.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Precomputes integers that can replace floating-point operands.
|
||||
*
|
||||
* “G-d made the integers, all else is the work of man.
|
||||
* — Leopold Kronecker
|
||||
*
|
||||
* This function shifts the decimal point to the left:
|
||||
*
|
||||
* 𝑛ᵢ ← ROUND[𝑐ᵢ × 2ᵐ] + φᵢ
|
||||
*
|
||||
* With extra effort to compute φ which is normally all zeroes but gives
|
||||
* us better rounding when it isn't. It's assumed optimized coefficients
|
||||
* will be used like this:
|
||||
*
|
||||
* (Σᵢ𝑥ᵢ𝑛ᵢ + 2⁽ᵐ⁻¹⁾) / 2ᵐ where 𝑥∈[𝐿,𝐻] and 𝑖∈[0,6)
|
||||
*
|
||||
* Intended to compute this
|
||||
*
|
||||
* ROUND[Σᵢ𝑥ᵢ𝑐ᵢ]
|
||||
*
|
||||
* As accurately or approximately as you want it to be. Popular scaling
|
||||
* factors are 7, 15, 16, 22, and 31. Building this code under MODE=tiny
|
||||
* will DCE the math.
|
||||
*
|
||||
* @param N receives optimized integers
|
||||
* @param C provides ideal coefficients
|
||||
* @param M is log₂ scaling factor, e.g. 7
|
||||
* @param L is minimum input data size, e.g. 0
|
||||
* @param H is maximum input data size, e.g. 255
|
||||
* @return sum of errors for all inputs
|
||||
* @see en.wikipedia.org/wiki/Binary_scaling
|
||||
* @see o/tool/build/coefficients.com
|
||||
* @cost ~300ns
|
||||
*/
|
||||
long GetIntegerCoefficients(long N[static 6], const double C[static 6], long M,
|
||||
long L, long H) {
|
||||
int i;
|
||||
int j[6], J[6];
|
||||
int O[6] = {0};
|
||||
int S[3] = {0, -1, +1};
|
||||
double R[6], K[6], D[6], HM, HL, least, error;
|
||||
least = 1;
|
||||
HM = 1L << M;
|
||||
HL = H - L + 1;
|
||||
assert(H >= L);
|
||||
assert(HL <= HM);
|
||||
for (i = 0; i < 6; ++i) {
|
||||
least *= HL;
|
||||
if (fabs(C[i]) > DBL_MIN) {
|
||||
J[i] = ARRAYLEN(S);
|
||||
R[i] = C[i] * HM;
|
||||
K[i] = rint(R[i]);
|
||||
N[i] = K[i];
|
||||
} else {
|
||||
J[i] = 1;
|
||||
R[i] = 0;
|
||||
K[i] = 0;
|
||||
N[i] = 0;
|
||||
}
|
||||
}
|
||||
if (!IsTiny() && least > 1) {
|
||||
for (j[0] = 0; j[0] < J[0]; ++j[0]) {
|
||||
for (j[1] = 0; j[1] < J[1]; ++j[1]) {
|
||||
for (j[2] = 0; j[2] < J[2]; ++j[2]) {
|
||||
for (j[3] = 0; j[3] < J[3]; ++j[3]) {
|
||||
for (j[4] = 0; j[4] < J[4]; ++j[4]) {
|
||||
for (j[5] = 0; j[5] < J[5]; ++j[5]) {
|
||||
for (i = 0; i < ARRAYLEN(J); ++i) {
|
||||
D[i] = S[j[i]] + K[i] - R[i];
|
||||
}
|
||||
if ((error = DifferSumSq(D, L, H) / HM) < least) {
|
||||
least = error;
|
||||
memcpy(O, j, sizeof(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 6; ++i) {
|
||||
N[i] += S[O[i]];
|
||||
}
|
||||
}
|
||||
return lround(least);
|
||||
}
|
83
dsp/core/getintegercoefficients8.c
Normal file
83
dsp/core/getintegercoefficients8.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/core/q.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Same as GetIntegerCoefficients() but with eight terms.
|
||||
* @cost ~3ms
|
||||
*/
|
||||
long GetIntegerCoefficients8(long N[static 8], const double C[static 8], long M,
|
||||
long L, long H) {
|
||||
int i;
|
||||
int j[8], J[8];
|
||||
int O[8] = {0};
|
||||
int S[3] = {0, -1, +1};
|
||||
double R[8], K[8], D[8], Z, least, error;
|
||||
least = 1;
|
||||
Z = 1L << M;
|
||||
for (i = 0; i < ARRAYLEN(J); ++i) {
|
||||
least *= H - L;
|
||||
if (fabs(C[i]) > DBL_MIN) {
|
||||
J[i] = ARRAYLEN(S);
|
||||
R[i] = C[i] * Z;
|
||||
K[i] = rint(R[i]);
|
||||
N[i] = K[i];
|
||||
} else {
|
||||
J[i] = 1;
|
||||
R[i] = 0;
|
||||
K[i] = 0;
|
||||
N[i] = 0;
|
||||
}
|
||||
}
|
||||
if (least > 1) {
|
||||
for (j[0] = 0; j[0] < J[0]; ++j[0]) {
|
||||
for (j[1] = 0; j[1] < J[1]; ++j[1]) {
|
||||
for (j[2] = 0; j[2] < J[2]; ++j[2]) {
|
||||
for (j[3] = 0; j[3] < J[3]; ++j[3]) {
|
||||
for (j[4] = 0; j[4] < J[4]; ++j[4]) {
|
||||
for (j[5] = 0; j[5] < J[5]; ++j[5]) {
|
||||
for (j[6] = 0; j[6] < J[6]; ++j[6]) {
|
||||
for (j[7] = 0; j[7] < J[7]; ++j[7]) {
|
||||
for (i = 0; i < ARRAYLEN(J); ++i) {
|
||||
D[i] = S[j[i]] + K[i] - R[i];
|
||||
}
|
||||
if ((error = DifferSumSq8(D, L, H) / Z) < least) {
|
||||
least = error;
|
||||
memcpy(O, j, sizeof(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
N[i] += S[O[i]];
|
||||
}
|
||||
}
|
||||
return lround(least);
|
||||
}
|
12
dsp/core/half.h
Normal file
12
dsp/core/half.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_HALF_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_HALF_H_
|
||||
#include "libc/macros.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Divides integer in half w/ rounding.
|
||||
*/
|
||||
#define HALF(X) (((X) + 1) / (2 / TYPE_INTEGRAL(typeof(X))))
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_HALF_H_ */
|
79
dsp/core/illumination.c
Normal file
79
dsp/core/illumination.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/core/illumination.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const double kIlluminantA[3] = {1.0985, 1, 0.35585};
|
||||
const double kIlluminantAD10[3] = {1.11144, 1, 0.35200};
|
||||
const double kIlluminantC[3] = {0.98074, 1, 1.18232};
|
||||
const double kIlluminantCD10[3] = {0.97285, 1, 1.16145};
|
||||
const double kIlluminantD50[3] = {0.96422, 1, 0.82521};
|
||||
const double kIlluminantD50D10[3] = {0.9672, 1, 0.81427};
|
||||
const double kIlluminantD55[3] = {0.95682, 1, 0.92149};
|
||||
const double kIlluminantD55D10[3] = {0.95799, 1, 0.90926};
|
||||
const double kIlluminantD65[3] = {0.95047, 1, 1.08883};
|
||||
const double kIlluminantD65D10[3] = {0.94811, 1, 1.07304};
|
||||
const double kIlluminantD75[3] = {0.94972, 1, 1.22638};
|
||||
const double kIlluminantD75D10[3] = {0.94416, 1, 1.20641};
|
||||
const double kIlluminantF2[3] = {0.99187, 1, 0.67395};
|
||||
const double kIlluminantF2D10[3] = {1.0328, 1, 0.69026};
|
||||
const double kIlluminantF7[3] = {0.95044, 1, 1.08755};
|
||||
const double kIlluminantF7D10[3] = {0.95792, 1, 1.07687};
|
||||
const double kIlluminantF11[3] = {1.00966, 1, 0.6437};
|
||||
const double kIlluminantF11D10[3] = {1.03866, 1, 0.65627};
|
||||
|
||||
/**
|
||||
* System of equations used for changing illumination.
|
||||
*
|
||||
* @see brucelindbloom.com/Eqn_ChromAdapt.html “The Bradford method is
|
||||
* the newest of the three methods, and is considered by most
|
||||
* experts to be the best of them. This is the method used in Adobe
|
||||
* Photoshop. A related article comparing the chromatic adaptation
|
||||
* algorithms may be found here.” ─Quoth Bruce Lindbloom
|
||||
*/
|
||||
const double kBradford[3][3] = {
|
||||
{0.8951, 0.2664, -.1614},
|
||||
{-.7502, 1.7135, 0.0367},
|
||||
{0.0389, -.0685, 1.0296},
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes lightbulb changing coefficients.
|
||||
*
|
||||
* @param R will store result
|
||||
* @param S has intended input illuminant primaries
|
||||
* @param D has desired output illuminant primaries
|
||||
* @return R
|
||||
* @see brucelindbloom.com/Eqn_ChromAdapt.html
|
||||
* @see fluxometer.com/rainbow/
|
||||
*/
|
||||
void *GetChromaticAdaptationMatrix(double R[3][3], const double S[3],
|
||||
const double D[3]) {
|
||||
double M[3][3], T[3][3], U[3][3], V[3], W[3];
|
||||
matvmul3(V, kBradford, S);
|
||||
matvmul3(W, kBradford, D);
|
||||
memset(M, 0, sizeof(M));
|
||||
M[0][0] = W[0] / V[0];
|
||||
M[1][1] = W[1] / V[1];
|
||||
M[2][2] = W[2] / V[2];
|
||||
return matmul3(R, matmul3(T, kBradford, M),
|
||||
inv3(U, kBradford, det3(kBradford)));
|
||||
}
|
31
dsp/core/illumination.h
Normal file
31
dsp/core/illumination.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_ILLUMINANT_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_ILLUMINANT_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const double kBradford[3][3];
|
||||
extern const double kIlluminantA[3];
|
||||
extern const double kIlluminantAD10[3];
|
||||
extern const double kIlluminantC[3];
|
||||
extern const double kIlluminantCD10[3];
|
||||
extern const double kIlluminantD50[3];
|
||||
extern const double kIlluminantD50D10[3];
|
||||
extern const double kIlluminantD55[3];
|
||||
extern const double kIlluminantD55D10[3];
|
||||
extern const double kIlluminantD65[3];
|
||||
extern const double kIlluminantD65D10[3];
|
||||
extern const double kIlluminantD75[3];
|
||||
extern const double kIlluminantD75D10[3];
|
||||
extern const double kIlluminantF2[3];
|
||||
extern const double kIlluminantF2D10[3];
|
||||
extern const double kIlluminantF7[3];
|
||||
extern const double kIlluminantF7D10[3];
|
||||
extern const double kIlluminantF11[3];
|
||||
extern const double kIlluminantF11D10[3];
|
||||
|
||||
void *GetChromaticAdaptationMatrix(double[3][3], const double[3],
|
||||
const double[3]);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_ILLUMINANT_H_ */
|
46
dsp/core/inv3.c
Normal file
46
dsp/core/inv3.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Computes 𝐀⁻¹ inverted 3×3 matrix, if it exists.
|
||||
*
|
||||
* @param 𝐁 is destination memory
|
||||
* @param 𝐀 is input matrix, which can't overlap 𝐁
|
||||
* @param 𝑑 is |𝐀| the determinant scalar or 0 if degenerate
|
||||
* @return 𝐀⁻¹ stored inside 𝐁 or NaNs if 𝑑=0
|
||||
* @define 𝐀⁻¹=𝐁 such that 𝐀×𝐁=𝐁×𝐀=𝐈ₙ
|
||||
* @see det3()
|
||||
*/
|
||||
void *inv3(double B[restrict 3][3], const double A[restrict 3][3], double d) {
|
||||
d = d ? 1 / d : NAN;
|
||||
B[0][0] = (A[1][1] * A[2][2] - A[2][1] * A[1][2]) * d;
|
||||
B[0][1] = (A[2][1] * A[0][2] - A[0][1] * A[2][2]) * d;
|
||||
B[0][2] = (A[0][1] * A[1][2] - A[1][1] * A[0][2]) * d;
|
||||
B[1][0] = (A[2][0] * A[1][2] - A[1][0] * A[2][2]) * d;
|
||||
B[1][1] = (A[0][0] * A[2][2] - A[2][0] * A[0][2]) * d;
|
||||
B[1][2] = (A[1][0] * A[0][2] - A[0][0] * A[1][2]) * d;
|
||||
B[2][0] = (A[1][0] * A[2][1] - A[2][0] * A[1][1]) * d;
|
||||
B[2][1] = (A[2][0] * A[0][1] - A[0][0] * A[2][1]) * d;
|
||||
B[2][2] = (A[0][0] * A[1][1] - A[1][0] * A[0][1]) * d;
|
||||
return B;
|
||||
}
|
23
dsp/core/ituround.h
Normal file
23
dsp/core/ituround.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_ITUROUND_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_ITUROUND_H_
|
||||
#include "libc/math.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* An ITU recommended rounding function.
|
||||
*
|
||||
* 1. Negative numbers round toward zero
|
||||
* 2. Positive numbers round toward infinity
|
||||
*
|
||||
* @see round(), rint()
|
||||
*/
|
||||
static inline pureconst artificial long ituround(double x) {
|
||||
return floor(x + .5);
|
||||
}
|
||||
|
||||
static inline pureconst artificial int ituroundf(float x) {
|
||||
return floorf(x + .5f);
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_ITUROUND_H_ */
|
47
dsp/core/ks8.h
Normal file
47
dsp/core/ks8.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_KS8_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_KS8_H_
|
||||
#include "libc/macros.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Performs 16-bit scaled rounded madd w/ eight coefficients or fewer.
|
||||
*
|
||||
* (Σᵢ₌₀₋₈𝑘ᵢ𝑥ᵢ + 2ᵐ⁻¹)/2ᵐ
|
||||
*
|
||||
* @note intent is avoiding type promotion
|
||||
*/
|
||||
#define KS8(M, K1, K2, K3, K4, K5, K6, K7, K8, X1, X2, X3, X4, X5, X6, X7, X8) \
|
||||
({ \
|
||||
short x1, x2, x3, x4, x5, x6, x7, x8; \
|
||||
x1 = X1; \
|
||||
x2 = X2; \
|
||||
x3 = X3; \
|
||||
x4 = X4; \
|
||||
x5 = X5; \
|
||||
x6 = X6; \
|
||||
x7 = X7; \
|
||||
x8 = X8; \
|
||||
x1 *= K1; \
|
||||
x2 *= K2; \
|
||||
x3 *= K3; \
|
||||
x4 *= K4; \
|
||||
x5 *= K5; \
|
||||
x6 *= K6; \
|
||||
x7 *= K7; \
|
||||
x8 *= K8; \
|
||||
x1 += x2; \
|
||||
x3 += x4; \
|
||||
x5 += x6; \
|
||||
x7 += x8; \
|
||||
x1 += x3; \
|
||||
x5 += x7; \
|
||||
x1 += x5; \
|
||||
if (M) { \
|
||||
x1 += 1 << MAX(0, M - 1); \
|
||||
x1 >>= M; \
|
||||
} \
|
||||
x1; \
|
||||
})
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_KS8_H_ */
|
43
dsp/core/kss8.h
Normal file
43
dsp/core/kss8.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_KSS8_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_KSS8_H_
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Performs 16-bit scaled rounded saturated madd w/ eight coefficients or fewer.
|
||||
*
|
||||
* (Σᵢ₌₀₋₈𝑘ᵢ𝑥ᵢ + 2ᵐ⁻¹)/2ᵐ
|
||||
*
|
||||
* @note compiler struggles with this
|
||||
*/
|
||||
#define KSS8(M, K1, K2, K3, K4, K5, K6, K7, K8, X1, X2, X3, X4, X5, X6, X7, \
|
||||
X8) \
|
||||
({ \
|
||||
short x1, x2, x3, x4, x5, x6, x7, x8; \
|
||||
x1 = X1, x2 = X2, x3 = X3, x4 = X4; \
|
||||
x5 = X5, x6 = X6, x7 = X7, x8 = X8; \
|
||||
x1 = MIN(SHRT_MAX, MAX(SHRT_MIN, x1 * K1)); \
|
||||
x2 = MIN(SHRT_MAX, MAX(SHRT_MIN, x2 * K2)); \
|
||||
x3 = MIN(SHRT_MAX, MAX(SHRT_MIN, x3 * K3)); \
|
||||
x4 = MIN(SHRT_MAX, MAX(SHRT_MIN, x4 * K4)); \
|
||||
x5 = MIN(SHRT_MAX, MAX(SHRT_MIN, x5 * K5)); \
|
||||
x6 = MIN(SHRT_MAX, MAX(SHRT_MIN, x6 * K6)); \
|
||||
x7 = MIN(SHRT_MAX, MAX(SHRT_MIN, x7 * K7)); \
|
||||
x8 = MIN(SHRT_MAX, MAX(SHRT_MIN, x8 * K8)); \
|
||||
x1 = MIN(SHRT_MAX, MAX(SHRT_MIN, x1 + x2)); \
|
||||
x3 = MIN(SHRT_MAX, MAX(SHRT_MIN, x3 + x4)); \
|
||||
x5 = MIN(SHRT_MAX, MAX(SHRT_MIN, x5 + x6)); \
|
||||
x7 = MIN(SHRT_MAX, MAX(SHRT_MIN, x7 + x8)); \
|
||||
x1 = MIN(SHRT_MAX, MAX(SHRT_MIN, x1 + x3)); \
|
||||
x5 = MIN(SHRT_MAX, MAX(SHRT_MIN, x5 + x7)); \
|
||||
x1 = MIN(SHRT_MAX, MAX(SHRT_MIN, x1 + x5)); \
|
||||
if (M) { \
|
||||
x1 += 1 << MAX(0, M - 1); \
|
||||
x1 >>= M; \
|
||||
} \
|
||||
x1; \
|
||||
})
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_KSS8_H_ */
|
38
dsp/core/matmul3.c
Normal file
38
dsp/core/matmul3.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Multiplies 3×3 matrices.
|
||||
*/
|
||||
void *matmul3(double R[restrict 3][3], const double A[3][3],
|
||||
const double B[3][3]) {
|
||||
int i, j, k;
|
||||
memset(R, 0, sizeof(double) * 3 * 3);
|
||||
for (i = 0; i < 3; ++i) {
|
||||
for (j = 0; j < 3; ++j) {
|
||||
for (k = 0; k < 3; ++k) {
|
||||
R[i][j] += A[k][j] * B[i][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return R;
|
||||
}
|
32
dsp/core/matvmul3.c
Normal file
32
dsp/core/matvmul3.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Computes M×V.
|
||||
*
|
||||
* @see vmatmul3() for noncommutative corollary
|
||||
*/
|
||||
void *matvmul3(double R[restrict 3], const double M[3][3], const double V[3]) {
|
||||
R[0] = V[0] * M[0][0] + V[1] * M[0][1] + V[2] * M[0][2];
|
||||
R[1] = V[0] * M[1][0] + V[1] * M[1][1] + V[2] * M[1][2];
|
||||
R[2] = V[0] * M[2][0] + V[1] * M[2][1] + V[2] * M[2][2];
|
||||
return R;
|
||||
}
|
64
dsp/core/mulaw.S
Normal file
64
dsp/core/mulaw.S
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
#define BIAS 0x84
|
||||
|
||||
/ Encodes audio sample with µ-Law.
|
||||
/
|
||||
/ This is both the highest quality and most widely supported
|
||||
/ telephony codec, whose use was phased out in the 2000's in
|
||||
/ favor of cost-saving GSM audio compression that was so bad
|
||||
/ consumers were willing to pay more cash, for the privilege
|
||||
/ of saving telcos even more money w/ text messaging. Mu Law
|
||||
/ reduces PCM data to half its original size, by diminishing
|
||||
/ audio bands not vocalized by human voice.
|
||||
/
|
||||
/ @param %edi is pcm sample
|
||||
/ @return %eax is uint8_t encoded sample
|
||||
mulaw: .leafprologue
|
||||
.profilable
|
||||
mov $BIAS,%eax
|
||||
xor %edx,%edx
|
||||
test %edi,%edi
|
||||
js 1f
|
||||
lea (%edi,%eax),%eax
|
||||
mov $0xFF,%dl
|
||||
jmp 2f
|
||||
1: sub %edi,%eax
|
||||
mov $0x7F,%dl
|
||||
2: mov %eax,%esi
|
||||
or $0xFF,%sil
|
||||
bsr %esi,%esi
|
||||
sub $7,%esi
|
||||
cmp $8,%esi
|
||||
jge 4f
|
||||
lea 3(%rdx),%ecx
|
||||
sar %cl,%eax
|
||||
and $0xF,%eax
|
||||
shl $4,%esi
|
||||
or %esi,%eax
|
||||
xor %edx,%eax
|
||||
3: .leafepilogue
|
||||
4: xor $0x7F,%dl
|
||||
mov %edx,%eax
|
||||
jmp 3b
|
||||
.endfn mulaw,globl
|
||||
.yoink __FILE__
|
27
dsp/core/q.h
Normal file
27
dsp/core/q.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_Q_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_Q_H_
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* @fileoverview Fixed point arithmetic macros.
|
||||
* @see en.wikipedia.org/wiki/Q_(number_format)
|
||||
*/
|
||||
|
||||
#define F2Q(Q, I) MIN((1 << Q) - 1, roundf((I) * (1.f * ((1 << Q) - 1))))
|
||||
#define Q2F(Q, I) ((I) * (1.f / ((1 << Q) - 1)))
|
||||
#define QRS(Q, X) (((X) + (1 << (Q - 1))) >> Q)
|
||||
#define LQRS(Q, X) (((X) + (1L << (Q - 1))) >> Q)
|
||||
|
||||
double DifferSumSq(const double[static 6], double, double);
|
||||
double DifferSumSq8(const double[static 8], double, double);
|
||||
|
||||
long GetIntegerCoefficients(long[static 6], const double[static 6], long, long,
|
||||
long);
|
||||
long GetIntegerCoefficients8(long[static 8], const double[static 8], long, long,
|
||||
long);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_Q_H_ */
|
41
dsp/core/sad16x8n.S
Normal file
41
dsp/core/sad16x8n.S
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.align 16
|
||||
|
||||
/ Mixes audio.
|
||||
/
|
||||
/ @param rdi is # aligned int16[16] sample chunks to process
|
||||
/ @param rsi points to aligned pcm s16le input/output memory
|
||||
/ @param rdx points to aligned pcm s16le [0..1] input memory
|
||||
sad16x8n:
|
||||
.leafprologue
|
||||
.profilable
|
||||
test %rdi,%rdi
|
||||
jz 1f
|
||||
shl $3,%rdi
|
||||
0: sub $8,%rdi
|
||||
movdqa (%rsi,%rdi,2),%xmm0
|
||||
paddsw (%rdx,%rdi,2),%xmm0
|
||||
movdqa %xmm0,(%rsi,%rdi,2)
|
||||
jnz 0b
|
||||
1: .leafepilogue
|
||||
.endfn sad16x8n,globl,hidden
|
||||
.yoink __FILE__
|
50
dsp/core/scalevolume.c
Normal file
50
dsp/core/scalevolume.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Increases or decreases audio volume.
|
||||
*
|
||||
* @param 𝑝 is two-power w/ effective range [-15,15]
|
||||
*/
|
||||
void scalevolume(size_t n, int16_t pcm[n][8], int p) {
|
||||
/* TODO(jart): This isn't acceptable. */
|
||||
size_t i, j;
|
||||
if (p > 0) {
|
||||
if (p > 15) p = 15;
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
pcm[i][j] =
|
||||
MIN(SHRT_MAX, MAX(SHRT_MIN, (int)((unsigned)pcm[i][j] << p)));
|
||||
}
|
||||
}
|
||||
} else if (p < 0) {
|
||||
p = -p;
|
||||
if (p > 15) p = 15;
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
pcm[i][j] = SAR(pcm[i][j], p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
dsp/core/twixt8.h
Normal file
24
dsp/core/twixt8.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef COSMOPOLITAN_DSP_CORE_TWIXT8_H_
|
||||
#define COSMOPOLITAN_DSP_CORE_TWIXT8_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* 8-bit linear interpolation kernel.
|
||||
*/
|
||||
static inline pureconst artificial unsigned char twixt8(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char p) {
|
||||
short bx;
|
||||
bx = bl;
|
||||
bx -= al;
|
||||
bx *= p;
|
||||
bx >>= 8;
|
||||
bx += al;
|
||||
al = bx;
|
||||
return al;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_DSP_CORE_TWIXT8_H_ */
|
32
dsp/core/vmatmul3.c
Normal file
32
dsp/core/vmatmul3.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Computes V×M.
|
||||
*
|
||||
* @see matvmul3() for noncommutative corollary
|
||||
*/
|
||||
void *vmatmul3(double R[restrict 3], const double V[3], const double M[3][3]) {
|
||||
R[0] = V[0] * M[0][0] + V[1] * M[1][0] + V[2] * M[2][0];
|
||||
R[1] = V[0] * M[0][1] + V[1] * M[1][1] + V[2] * M[2][1];
|
||||
R[2] = V[0] * M[0][2] + V[1] * M[1][2] + V[2] * M[2][2];
|
||||
return R;
|
||||
}
|
8
dsp/dsp.mk
Normal file
8
dsp/dsp.mk
Normal file
|
@ -0,0 +1,8 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
.PHONY: o/$(MODE)/dsp
|
||||
o/$(MODE)/dsp: o/$(MODE)/dsp/core \
|
||||
o/$(MODE)/dsp/mpeg \
|
||||
o/$(MODE)/dsp/scale \
|
||||
o/$(MODE)/dsp/tty
|
92
dsp/mpeg/README.txt
Normal file
92
dsp/mpeg/README.txt
Normal file
|
@ -0,0 +1,92 @@
|
|||
PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer
|
||||
Dominic Szablewski - https://phoboslab.org
|
||||
|
||||
-- Synopsis
|
||||
|
||||
// This function gets called for each decoded video frame
|
||||
void my_video_callback(plm_t *plm, plm_frame_t *frame, void *user) {
|
||||
// Do something with frame->y.data, frame->cr.data, frame->cb.data
|
||||
}
|
||||
|
||||
// This function gets called for each decoded audio frame
|
||||
void my_audio_callback(plm_t *plm, plm_samples_t *frame, void *user) {
|
||||
// Do something with samples->interleaved
|
||||
}
|
||||
|
||||
// Load a .mpg (MPEG Program Stream) file
|
||||
plm_t *plm = plm_create_with_filename("some-file.mpg");
|
||||
|
||||
// Install the video & audio decode callbacks
|
||||
plm_set_video_decode_callback(plm, my_video_callback, my_data);
|
||||
plm_set_audio_decode_callback(plm, my_audio_callback, my_data);
|
||||
|
||||
|
||||
// Decode
|
||||
do {
|
||||
plm_decode(plm, time_since_last_call);
|
||||
} while (!plm_has_ended(plm));
|
||||
|
||||
// All done
|
||||
plm_destroy(plm);
|
||||
|
||||
|
||||
|
||||
-- Documentation
|
||||
|
||||
This library provides several interfaces to load, demux and decode MPEG video
|
||||
and audio data. A high-level API combines the demuxer, video & audio decoders
|
||||
in an easy to use wrapper.
|
||||
|
||||
Lower-level APIs for accessing the demuxer, video decoder and audio decoder,
|
||||
as well as providing different data sources are also available.
|
||||
|
||||
Interfaces are written in an object orientet style, meaning you create object
|
||||
instances via various different constructor functions (plm_*create()),
|
||||
do some work on them and later dispose them via plm_*destroy().
|
||||
|
||||
plm_* -- the high-level interface, combining demuxer and decoders
|
||||
plm_buffer_* -- the data source used by all interfaces
|
||||
plm_demux_* -- the MPEG-PS demuxer
|
||||
plm_video_* -- the MPEG1 Video ("mpeg1") decoder
|
||||
plm_audio_* -- the MPEG1 Audio Layer II ("mp2") decoder
|
||||
|
||||
|
||||
This library uses malloc(), realloc() and free() to manage memory. Typically
|
||||
all allocation happens up-front when creating the interface. However, the
|
||||
default buffer size may be too small for certain inputs. In these cases plmpeg
|
||||
will realloc() the buffer with a larger size whenever needed. You can configure
|
||||
the default buffer size by defining PLM_BUFFER_DEFAULT_SIZE *before*
|
||||
including this library.
|
||||
|
||||
With the high-level interface you have two options to decode video & audio:
|
||||
|
||||
1) Use plm_decode() and just hand over the delta time since the last call.
|
||||
It will decode everything needed and call your callbacks (specified through
|
||||
plm_set_{video|audio}_decode_callback()) any number of times.
|
||||
|
||||
2) Use plm_decode_video() and plm_decode_audio() to decode exactly one
|
||||
frame of video or audio data at a time. How you handle the synchronization of
|
||||
both streams is up to you.
|
||||
|
||||
If you only want to decode video *or* audio through these functions, you should
|
||||
disable the other stream (plm_set_{video|audio}_enabled(false))
|
||||
|
||||
|
||||
Video data is decoded into a struct with all 3 planes (Y, Cr, Cb) stored in
|
||||
separate buffers. You can either convert this to RGB on the CPU (slow) via the
|
||||
plm_frame_to_rgb() function or do it on the GPU with the following matrix:
|
||||
|
||||
mat4 rec601 = mat4(
|
||||
1.16438, 0.00000, 1.59603, -0.87079,
|
||||
1.16438, -0.39176, -0.81297, 0.52959,
|
||||
1.16438, 2.01723, 0.00000, -1.08139,
|
||||
0, 0, 0, 1
|
||||
);
|
||||
gl_FragColor = vec4(y, cb, cr, 1.0) * rec601;
|
||||
|
||||
Audio data is decoded into a struct with either one single float array with the
|
||||
samples for the left and right channel interleaved, or if the
|
||||
PLM_AUDIO_SEPARATE_CHANNELS is defined *before* including this library, into
|
||||
two separate float arrays - one for each channel.
|
||||
|
||||
See below for detailed the API documentation.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue