Compare commits

...

1 commit

Author SHA1 Message Date
d0p1 🏳️‍⚧️ 7cc3f65a58 xr/17032 boilerplate 2024-02-20 04:11:09 +01:00
64 changed files with 4917 additions and 2 deletions

View file

@ -6,6 +6,7 @@ vars.ackcflags = {
} }
vars.ackldflags = {} vars.ackldflags = {}
vars.plats = { vars.plats = {
"mintia",
"cpm", "cpm",
"linux386", "linux386",
"linux68k", "linux68k",
@ -23,9 +24,7 @@ vars.plats = {
vars.plats_with_tests = { vars.plats_with_tests = {
"cpm", "cpm",
"linux68k", "linux68k",
--"linux386",
"linuxppc", "linuxppc",
--"linuxmips",
"pc86", "pc86",
} }

19
mach/xr17032/as/build.lua Normal file
View file

@ -0,0 +1,19 @@
normalrule {
name = "astables",
outleaves = {"definitions.y", "tokens.y", "rules.y"},
ins = {"./mktables.lua", "./instructions.dat"},
commands = {"$(LUA) %{ins[1]} %{outs} < %{ins[2]}"}
}
bundle {
name = "headers",
srcs = {
"./mach0.c",
"./mach1.c",
"./mach2.c",
"./mach3.c",
"./mach4.c",
"./mach5.c",
}
}

View file

@ -0,0 +1,319 @@
# Syntax:
# <thing---->: a field occupying so many bits.
# T: a field occupying one bit.
# Undefined bits end up as 0.
#
# This is intended to be compatible with MIPS release 5, integer instructions
# only. It's based on the MIPS32 Instruction Set v5.04 manual (available from
# https://www.mips.com/products/architectures/mips32-2/).
# Useful pseudoops.
# beq zero, offset
<OFF---------------->00000111101 "b" OFF=offset21
# jalr zero, lr, 0
00000000000000001111100000111000 "ret"
# jalr zero, RA, 0
0000000000000000<RA->00000111000 "jr" RA=gpr
# add RA, RB, zero LSH 0
0111000000000000<RB-><RA->111001 "mov" RA=gpr ',' RB=gpr
# addi RA, zero, imm
<IMM----------->00000<RA->111100 "li" RA=gpr ',' IMM=e16
# addi zero, zero, 0
00000000000000000000000000111100 "nop"
# Condition code tokens; these have to be defined here because .f overlaps with
# a format code.
%token .f
%token .un
%token .eq
%token .ueq
%token .olt
%token .ult
%token .ole
%token .ule
%token .sf
%token .ngle
%token .seq
%token .ngl
%token .lt
%token .nge
%token .le
%token .ngt
# Core ALU instructions.
<OFF------------------------>111 "jal" OFF=offset29
<OFF------------------------>110 "j" OFF=offset29
<OFF----------------><RA->111101 "beq" RA=gpr ',' OFF=offset21
<OFF----------------><RA->110101 "bne" RA=gpr ',' OFF=offset21
<OFF----------------><RA->101101 "blt" RA=gpr ',' OFF=offset21
<OFF----------------><RA->100101 "bgt" RA=gpr ',' OFF=offset21
<OFF----------------><RA->011101 "ble" RA=gpr ',' OFF=offset21
<OFF----------------><RA->010101 "bge" RA=gpr ',' OFF=offset21
<OFF----------------><RA->001101 "bpe" RA=gpr ',' OFF=offset21
<OFF----------------><RA->000101 "bpo" RA=gpr ',' OFF=offset21
<IMM-----------><RB-><RA->111100 "addi" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RB-><RA->110100 "subi" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RB-><RA->101100 "slti" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RB-><RA->100100 "slti" "signed" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RB-><RA->011100 "andi" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RB-><RA->010100 "xori" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RB-><RA->001100 "ori" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RA-><RB->000100 "lui" RA=gpr ',' RB=gpr ',' IMM=e16
<IMM-----------><RA-><RB->111011 "mov" RA=gpr ',' "byte" '[' RB=gpr '+' IMM=e16 ']'
<IMM-----------><RA-><RB->110011 "mov" RA=gpr ',' "int" '[' RB=gpr '+' IMM=e16 ']'
<IMM-----------><RA-><RB->101011 "mov" RA=gpr ',' "long" '[' RB=gpr '+' IMM=e16 ']'
<IMM-----------><RA-><RB->111010 "mov" "byte" '[' RA=gpr '+' IMM=e16 ']' ',' RB=gpr
<IMM-----------><RA-><RB->110010 "mov" "int" '[' RA=gpr '+' IMM=e16 ']' ',' RB=gpr
<IMM-----------><RA-><RB->101010 "mov" "long" '[' RA=gpr '+' IMM=e16 ']' ',' RB=gpr
<IMM-----------><RA-><I-->011010 "mov" "byte" '[' RA=gpr '+' IMM=e16 ']' ',' I=u5
<IMM-----------><RA-><I-->010010 "mov" "int" '[' RA=gpr '+' IMM=e16 ']' ',' I=u5
<IMM-----------><RA-><I-->001010 "mov" "long" '[' RA=gpr '+' IMM=e16 ']' ',' I=u5
<IMM-----------><RA-><RB->111000 "jalr" RA=gpr ',' RB=gpr ',' IMM=e16
000000<RS-><RT-><RD->00000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr
001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RS=gpr ',' IMM=e16
001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RS=gpr ',' IMM=e16
000000<RS-><RT-><RD->00000100001 "addu" RD=gpr ',' RS=gpr ',' RT=gpr
000000<RS-><RT-><RD->00000100100 "and" RD=gpr ',' RS=gpr ',' RT=gpr
001100<RS-><RT-><IMM-----------> "andi" RT=gpr ',' RS=gpr ',' IMM=e16
0001000000000000<OFF-----------> "b" OFF=offset16
0000010000010001<OFF-----------> "bal" OFF=offset16
000100<RS-><RT-><OFF-----------> "beq" RS=gpr ',' RT=gpr ',' OFF=offset16
010100<RS-><RT-><OFF-----------> "beql" RS=gpr ',' RT=gpr ',' OFF=offset16
000001<RS->00001<OFF-----------> "bgez" RS=gpr ',' OFF=offset16
000001<RS->10001<OFF-----------> "bgezal" RS=gpr ',' OFF=offset16
000001<RS->10011<OFF-----------> "bgezall" RS=gpr ',' OFF=offset16
000001<RS->00011<OFF-----------> "bgezl" RS=gpr ',' OFF=offset16
000111<RS->00000<OFF-----------> "bgtz" RS=gpr ',' OFF=offset16
010111<RS->00000<OFF-----------> "bgtzl" RS=gpr ',' OFF=offset16
000110<RS->00000<OFF-----------> "blez" RS=gpr ',' OFF=offset16
010110<RS->00000<OFF-----------> "blezl" RS=gpr ',' OFF=offset16
000001<RS->00000<OFF-----------> "bltz" RS=gpr ',' OFF=offset16
000001<RS->10000<OFF-----------> "bltzal" RS=gpr ',' OFF=offset16
000001<RS->10010<OFF-----------> "bltzall" RS=gpr ',' OFF=offset16
000001<RS->00010<OFF-----------> "bltzl" RS=gpr ',' OFF=offset16
000101<RS-><RT-><OFF-----------> "bne" RS=gpr ',' RT=gpr ',' OFF=offset16
010101<RS-><RT-><OFF-----------> "bnel" RS=gpr ',' RT=gpr ',' OFF=offset16
101111<RS-><OP-><OFF-----------> "cache" OP=u5 ',' OFF=e16 '(' RS=gpr ')'
011111<RS-><OP-><OFF---->0011011 "cachee" OP=u5 ',' OFF=e9 '(' RS=gpr ')'
011100<RS-><RT-><RD->00000100001 "clo" RD=RT=gpr ',' RS=gpr
011100<RS-><RT-><RD->00000100000 "clz" RD=RT=gpr ',' RS=gpr
01000010000000000000000000011111 "deret"
01000001011<RT->0110000000000000 "di" RT=gpr
01000001011000000110000000000000 "di"
000000<RS-><RT->0000000000011010 "div" RS=gpr ',' RT=gpr
000000<RS-><RT->0000000000011011 "divu" RS=gpr ',' RT=gpr
00000000000000000000000011000000 "ehb"
01000001011<RT->0110000000100000 "ei" RT=gpr
01000001011000000110000000100000 "ei"
011111<RS-><RT-><MSBLSB-->000000 "ext" RT=gpr ',' RS=gpr ',' extmsblsb
011111<RS-><RT-><MSBLSB-->000100 "ins" RT=gpr ',' RS=gpr ',' insmsblsb
000010<ABS---------------------> "j" ABS=abs26
000011<ABS---------------------> "jal" ABS=abs26
000000<RS->00000<RD->00000001001 "jalr" RD=gpr ',' RS=gpr
000000<RS->000001111100000001001 "jalr" RS=gpr
000000<RS->00000<RD->10000001001 "jalr.hb" RD=gpr ',' RS=gpr
000000<RS->000001111110000001001 "jalr.hb" RS=gpr
011101<ABS---------------------> "jalx" ABS=abs26
000000<RS->000000000000000001000 "jr" RS=gpr
000000<RS->000000000010000001000 "jr.hb" RS=gpr
100000<RS-><RT-><IMM-----------> "lb" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0101100 "lbe" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
100100<RS-><RT-><IMM-----------> "lbu" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0101000 "lbue" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
100001<RS-><RT-><IMM-----------> "lh" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0101101 "lhe" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
100101<RS-><RT-><IMM-----------> "lhu" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0101001 "lhue" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
110000<RS-><RT-><IMM-----------> "ll" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0101110 "lle" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
00111100000<RT-><IMM-----------> "lui" RT=gpr ',' IMM=e16
100011<RS-><RT-><IMM-----------> "lw" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0101111 "lwe" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
100010<RS-><RT-><IMM-----------> "lwl" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0011001 "lwle" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
100110<RS-><RT-><IMM-----------> "lwr" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0011010 "lwre" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
011100<RS-><RT->0000000000000000 "madd" RS=gpr ',' RT=gpr
011100<RS-><RT->0000000000000001 "maddu" RS=gpr ',' RT=gpr
0000000000000000<RD->00000010000 "mfhi" RD=gpr
0000000000000000<RD->00000010010 "mflo" RD=gpr
000000<RS-><RT-><RD->00000001011 "movn" RD=gpr ',' RS=gpr ',' RT=gpr
000000<RS-><RT-><RD->00000001010 "movz" RD=gpr ',' RS=gpr ',' RT=gpr
011100<RS-><RT->0000000000000100 "msub" RS=gpr ',' RT=gpr
011100<RS-><RT->0000000000000101 "msubu" RS=gpr ',' RT=gpr
000000<RS->000000000000000010001 "mthi" RS=gpr
000000<RS->000000000000000010011 "mtlo" RS=gpr
011100<RS-><RT-><RD->00000000010 "mul" RD=gpr ',' RS=gpr ',' RT=gpr
000000<RS-><RT->0000000000011000 "mult" RS=gpr ',' RT=gpr
000000<RS-><RT->0000000000000001 "multu" RS=gpr ',' RT=gpr
000000<RS-><RT-><RD->00000100111 "nor" RD=gpr ',' RS=gpr ',' RT=gpr
000000<RS-><RT-><RD->00000100101 "or" RD=gpr ',' RS=gpr ',' RT=gpr
001101<RS-><RT-><IMM-----------> "ori" RT=gpr ',' RS=gpr ',' IMM=e16
00000000000000000000000101000000 "pause"
110011<RS-><H--><IMM-----------> "pref" H=u5 ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><H--><IMM---->0100011 "prefe" H=u5 ',' IMM=e9 '(' RS=gpr ')'
010011<RS-><RT-><H-->00000001111 "prefx" H=u5 ',' RT=gpr '(' RS=gpr ')'
01111100000<RT-><RD->00000111011 "rdhwr" RT=gpr ',' RD=gpr
01000001010<RT-><RD->00000000000 "rdpgpr" RD=gpr ',' RT=gpr
00000000001<RT-><RD-><SA->000010 "rotr" RD=gpr ',' RT=gpr ',' SA=u5
000000<RS-><RT-><RD->00001000110 "rotrv" RD=gpr ',' RT=gpr ',' RS=gpr
101000<RS-><RT-><IMM-----------> "sb" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0011100 "sbe" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
111000<RS-><RT-><IMM-----------> "sc" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0011110 "sce" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
011100<CODE-------------->111111 "sdbbp" CODE=u20
01111100000<RT-><RD->10000100000 "seb" RD=gpr ',' RT=gpr
01111100000<RT-><RD->11000100000 "seh" RD=gpr ',' RT=gpr
101001<RS-><RT-><IMM-----------> "sh" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0011101 "she" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
00000000000<RT-><RD-><SA->000000 "sll" RD=gpr ',' RT=gpr ',' SA=u5
000000<RS-><RT-><RD->00000000100 "sllv" RD=gpr ',' RT=gpr ',' RS=gpr
000000<RS-><RT-><RD->00000101010 "slt" RD=gpr ',' RS=gpr ',' RT=gpr
001010<RS-><RT-><IMM-----------> "slti" RT=gpr ',' RS=gpr ',' IMM=e16
001011<RS-><RT-><IMM-----------> "sltiu" RT=gpr ',' RS=gpr ',' IMM=e16
000000<RS-><RT-><RD->00000101011 "sltu" RD=gpr ',' RS=gpr ',' RT=gpr
00000000000<RT-><RD-><SA->000011 "sra" RD=gpr ',' RT=gpr ',' SA=u5
000000<RS-><RT-><RD->00000000111 "srav" RD=gpr ',' RT=gpr ',' RS=gpr
00000000000<RT-><RD-><SA->000010 "srl" RD=gpr ',' RT=gpr ',' SA=u5
000000<RS-><RT-><RD->00000000110 "srlv" RD=gpr ',' RT=gpr ',' RS=gpr
00000000000000000000000001000000 "ssnop"
000000<RS-><RT-><RD->00000100010 "sub" RD=gpr ',' RS=gpr ',' RT=gpr
000000<RS-><RT-><RD->00000100011 "subu" RD=gpr ',' RS=gpr ',' RT=gpr
101011<RS-><RT-><IMM-----------> "sw" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0011111 "swe" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
101010<RS-><RT-><IMM-----------> "swl" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0010001 "swle" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
101110<RS-><RT-><IMM-----------> "swr" RT=gpr ',' IMM=e16 '(' RS=gpr ')'
011111<RS-><RT-><IMM---->0100010 "swre" RT=gpr ',' IMM=e9 '(' RS=gpr ')'
000001<RS->11111<IMM-----------> "synci" IMM=e16 '(' RS=gpr ')'
000000<CODE-------------->001100 "syscall" CODE=u20
000000<RS-><RT->0000000000110100 "teq" RS=gpr ',' RT=gpr
000001<RS->01100<IMM-----------> "teqi" RS=gpr ',' IMM=e16
000000<RS-><RT->0000000000110000 "tge" RS=gpr ',' RT=gpr
000001<RS->01000<IMM-----------> "tgei" RS=gpr ',' IMM=e16
000001<RS->01001<IMM-----------> "tgeiu" RS=gpr ',' IMM=e16
000000<RS-><RT->0000000000110001 "tgeu" RS=gpr ',' RT=gpr
01000010000000000000000000000011 "tlbinv"
01000010000000000000000000000100 "tlbinvf"
01000010000000000000000000001000 "tlbp"
01000010000000000000000000000001 "tlbr"
01000010000000000000000000000010 "tlbwi"
01000010000000000000000000000110 "tlbwr"
000000<RS-><RT->0000000000110010 "tlt" RS=gpr ',' RT=gpr
000001<RS->01010<IMM-----------> "tlti" RS=gpr ',' IMM=e16
000001<RS->01011<IMM-----------> "tltiu" RS=gpr ',' IMM=e16
000000<RS-><RT->0000000000110011 "tltu" RS=gpr ',' RT=gpr
000000<RS-><RT->0000000000110110 "tne" RS=gpr ',' RT=gpr
000001<RS->01110<IMM-----------> "tnei" RS=gpr ',' IMM=e16
01000010000000000000000000100000 "wait"
01000001110<RT-><RD->00000000000 "wrpgpr" RD=gpr ',' RT=gpr
01111100000<RT-><RD->00010100000 "wsbh" RD=gpr ',' RT=gpr
000000<RS-><RT-><RD->00000100110 "xor" RD=gpr ',' RS=gpr ',' RT=gpr
001110<RS-><RT-><IMM-----------> "xori" RT=gpr ',' RS=gpr ',' IMM=e16
# FPU instructions.
010001<F-->00000<FS-><FD->000101 "abs" F=fmt FD=fpr ',' FS=fpr
010001<F--><FT-><FS-><FD->000000 "add" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr
010011<RS-><FT-><FS-><FD->011110 "alnv" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr ',' RS=gpr
010001<F--><FT-><FS-><C>0011<CO> "c" CO=fcond F=fmt C=u3 ',' FS=fpr ',' FT=fpr
010001<F-->00000<FS-><FD->001010 "ceil" ".l" F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->001110 "ceil" ".w" F=fmt FD=fpr ',' FS=fpr
01000100010<RT-><FS->00000000000 "cfc1" RT=gpr ',' FS=fpr
01000100110<RT-><FS->00000000000 "ctc1" RT=gpr ',' FS=fpr
010001<F-->00000<FS-><FD->100001 "cvt" ".d" F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->100101 "cvt" ".l" F=fmt FD=fpr ',' FS=fpr
01000110000<FT-><FS-><FD->100110 "cvt" ".ps" ".s" FD=fpr ',' FS=fpr ',' FT=fpr
010001<F-->00000<FS-><FD->100000 "cvt" ".s" F=fmt FD=fpr ',' FS=fpr
0100011011000000<FS-><FD->101000 "cvt" ".s" ".pl" FS=fpr ',' FD=fpr
0100011011000000<FS-><FD->100000 "cvt" ".s" ".pu" FS=fpr ',' FD=fpr
010001<F-->00000<FS-><FD->100100 "cvt" ".w" F=fmt FD=fpr ',' FS=fpr
010001<F--><FT-><FS-><FD->000011 "div" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr
010001<F-->00000<FS-><FD->001011 "floor" ".l" F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->001111 "floor" ".w" F=fmt FD=fpr ',' FS=fpr
110101<RS-><FT-><IMM-----------> "ldc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')'
010011<RS-><RT->00000<FD->000001 "ldxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')'
010011<RS-><RT->00000<FD->000101 "luxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')'
110001<RS-><FT-><IMM-----------> "lwc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')'
010011<RS-><RT->00000<FD->000000 "lwxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')'
010011<FR-><FT-><FS-><FD->100<F> "madd" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr
01000100000<RT-><FS->00000000000 "mfc1" RT=gpr ',' FS=fpr
01000100011<RT-><FS->00000000000 "mfhc1" RT=gpr ',' FS=fpr
010001<F-->00000<FS-><FD->000110 "mov" F=fmt FD=fpr ',' FS=fpr
000000<RS-><C>00<RD->00000000001 "movf" RD=gpr ',' RS=gpr ',' C=u3
010001<F--><C>00<FS-><FD->010001 "movf" F=fmt FD=fpr ',' FS=fpr ',' C=u3
010001<F--><RT-><FS-><FD->010011 "movn" F=fmt FD=fpr ',' FS=fpr ',' RT=gpr
000000<RS-><C>01<RD->00000000001 "movt" RD=gpr ',' RS=gpr ',' C=u3
010001<F--><C>01<FS-><FD->010001 "movt" F=fmt FD=fpr ',' FS=fpr ',' C=u3
010001<F--><RT-><FS-><FD->010010 "movz" F=fmt FD=fpr ',' FS=fpr ',' RT=gpr
010011<FR-><FT-><FS-><FD->101<F> "msub" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr
01000100100<RT-><FS->00000000000 "mtc1" RT=gpr ',' FS=fpr
01000100111<RT-><FS->00000000000 "mthc1" RT=gpr ',' FS=fpr
010001<F--><FT-><FS-><FD->000010 "mul" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr
010001<F-->00000<FS-><FD->000111 "neg" F=fmt FD=fpr ',' FS=fpr
010011<FR-><FT-><FS-><FD->110<F> "nmadd" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr
010011<FR-><FT-><FS-><FD->111<F> "nmsub" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr
01000110110<FT-><FS-><FD->101100 "pll" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr
01000110110<FT-><FS-><FD->101101 "plu" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr
01000110110<FT-><FS-><FD->101110 "pul" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr
01000110110<FT-><FS-><FD->101111 "puu" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr
010001<F-->00000<FS-><FD->010101 "recip." F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->001000 "round" ".l" F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->001100 "round" ".w" F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->010110 "rsqrt" F=fmt FD=fpr ',' FS=fpr
111101<RS-><FT-><IMM-----------> "sdc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')'
010011<RS-><RT->00000<FD->001001 "sdxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')'
010001<F-->00000<FS-><FD->000100 "sqrt" F=fmt FD=fpr ',' FS=fpr
010001<F--><FT-><FS-><FD->000001 "sub" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr
010011<RS-><RT->00000<FD->001101 "suxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')'
111001<RS-><FT-><IMM-----------> "swc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')'
010011<RS-><RT->00000<FD->001000 "swxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')'
010001<F-->00000<FS-><FD->001001 "trunc" ".l" F=fmt FD=fpr ',' FS=fpr
010001<F-->00000<FS-><FD->001101 "trunc" ".w" F=fmt FD=fpr ',' FS=fpr
# Generic coprocessor instructions.
01000101000<C>00<OFF-----------> "bc1f" C=u3 ',' OFF=offset16
0100010100000000<OFF-----------> "bc1f" OFF=offset16
01000101000<C>10<OFF-----------> "bc1fl" C=u3 ',' OFF=offset16
0100010100000010<OFF-----------> "bc1fl" OFF=offset16
01000101000<C>01<OFF-----------> "bc1t" C=u3 ',' OFF=offset16
0100010100000001<OFF-----------> "bc1t" OFF=offset16
01000101000<C>11<OFF-----------> "bc1tl" C=u3 ',' OFF=offset16
0100010100000011<OFF-----------> "bc1tl" OFF=offset16
01001001000<C>00<OFF-----------> "bc2f" C=u3 ',' OFF=offset16
0100100100000000<OFF-----------> "bc2f" OFF=offset16
01001001000<C>10<OFF-----------> "bc2fl" C=u3 ',' OFF=offset16
0100100100000010<OFF-----------> "bc2fl" OFF=offset16
01001001000<C>01<OFF-----------> "bc2t" C=u3 ',' OFF=offset16
0100100100000001<OFF-----------> "bc2t" OFF=offset16
01001001000<C>11<OFF-----------> "bc2tl" C=u3 ',' OFF=offset16
0100100100000011<OFF-----------> "bc2tl" OFF=offset16
01001000010<RT-><IMM-----------> "cfc2" RT=gpr ',' IMM=u16
01001000110<RT-><IMM-----------> "ctc2" RT=gpr ',' IMM=u16
0100101<FUN--------------------> "cop2" FUN=u25
110110<RS-><RT-><IMM-----------> "ldc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')'
110010<RS-><RT-><IMM-----------> "lwc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')'
01000000000<RT-><RD->00000000<S> "mfc0" RT=gpr ',' RD=u5 ',' S=u3
01001000000<RT-><IMM-----------> "mfc2" RT=gpr ',' IMM=u16
01000000010<RT-><RD->00000000<S> "mfhc0" RT=gpr ',' RD=u5 ',' S=u3
01001000011<RT-><IMM-----------> "mfhc2" RT=gpr ',' IMM=u16
01000000100<RT-><RD->00000000<S> "mtc0" RT=gpr ',' RD=u5 ',' S=u3
01001000100<RT-><IMM-----------> "mtc2" RT=gpr ',' IMM=u16
01000000110<RT-><RD->00000000<S> "mthc0" RT=gpr ',' RD=u5 ',' S=u3
01001000111<RT-><IMM-----------> "mthc2" RT=gpr ',' IMM=u16
111110<RS-><RT-><IMM-----------> "sdc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')'
111010<RS-><RT-><IMM-----------> "swc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')'

26
mach/xr17032/as/mach0.c Normal file
View file

@ -0,0 +1,26 @@
/*
* $Source$
* $State$
*/
#define THREE_PASS /* branch and offset optimization */
#define LISTING /* enable listing facilities */
#define RELOCATION /* generate relocatable code */
#define DEBUG 0
#undef ADDR_T
#define ADDR_T uint32_t
#undef word_t
#define word_t uint32_t
#undef ALIGNWORD
#define ALIGNWORD 4
#undef ALIGNSECT
#define ALIGNSECT 4
#undef VALWIDTH
#define VALWIDTH 8
#define FIXUPFLAGS 0

3
mach/xr17032/as/mach1.c Normal file
View file

@ -0,0 +1,3 @@
/*
* Do not #include anything here. Do it in mach/proto/as/comm0.h
*/

21
mach/xr17032/as/mach2.c Normal file
View file

@ -0,0 +1,21 @@
%token <y_word> GPR
%token <y_word> FPR
%token <y_word> FCOND
%token <y_word> HI16
%token <y_word> HA16
%token <y_word> LO16
%type <y_word> gpr fpr
%type <y_word> e16 e9
%type <y_word> u25 u20 u16 u5 u3
%type <y_word> abs26 offset16 offset29 offset21
%type <y_word> fmt fmt3
%type <y_word> fcond
%type <y_word> extmsblsb insmsblsb
%type <y_valu> extabsexp
#include "definitions.y"

118
mach/xr17032/as/mach3.c Normal file
View file

@ -0,0 +1,118 @@
/* Integer registers */
0, GPR, 0, "r0",
0, GPR, 0, "zero",
0, GPR, 1, "r1",
0, GPR, 1, "at",
0, GPR, 1, "t0",
0, GPR, 2, "r2",
0, GPR, 2, "t1",
0, GPR, 3, "r3",
0, GPR, 3, "t2",
0, GPR, 4, "r4",
0, GPR, 4, "t3",
0, GPR, 5, "r5",
0, GPR, 5, "t4",
0, GPR, 6, "r6",
0, GPR, 6, "t5",
0, GPR, 7, "r7",
0, GPR, 7, "a0",
0, GPR, 8, "r8",
0, GPR, 8, "a1",
0, GPR, 9, "r9",
0, GPR, 9, "a2",
0, GPR, 10, "r10",
0, GPR, 10, "a3",
0, GPR, 11, "r11",
0, GPR, 11, "s0",
0, GPR, 12, "r12",
0, GPR, 12, "s1",
0, GPR, 13, "r13",
0, GPR, 13, "s2",
0, GPR, 14, "r14",
0, GPR, 14, "s3",
0, GPR, 15, "r15",
0, GPR, 15, "s4",
0, GPR, 16, "r16",
0, GPR, 16, "s5",
0, GPR, 17, "r17",
0, GPR, 17, "s6",
0, GPR, 18, "r18",
0, GPR, 18, "s7",
0, GPR, 19, "r19",
0, GPR, 19, "s8",
0, GPR, 20, "r20",
0, GPR, 20, "s9",
0, GPR, 21, "r21",
0, GPR, 21, "s10",
0, GPR, 22, "r22",
0, GPR, 22, "s11",
0, GPR, 23, "r23",
0, GPR, 23, "s12",
0, GPR, 24, "r24",
0, GPR, 24, "s13",
0, GPR, 25, "r25",
0, GPR, 25, "s14",
0, GPR, 26, "r26",
0, GPR, 26, "s15",
0, GPR, 27, "r27",
0, GPR, 27, "s16",
0, GPR, 28, "r28",
/* xxx */
0, GPR, 28, "gp",
/* xxx */
0, GPR, 28, "s17",
0, GPR, 29, "r29",
/* xxx */
0, GPR, 29, "fp",
/* xxx */
0, GPR, 29, "tp",
0, GPR, 30, "r30",
0, GPR, 30, "sp",
0, GPR, 31, "r31",
0, GPR, 31, "lr",
0, GPR, 31, "ra",
/* Floating-point registers */
0, FPR, 0, "f0",
0, FPR, 1, "f1",
0, FPR, 2, "f2",
0, FPR, 3, "f3",
0, FPR, 4, "f4",
0, FPR, 5, "f5",
0, FPR, 6, "f6",
0, FPR, 7, "f7",
0, FPR, 8, "f8",
0, FPR, 9, "f9",
0, FPR, 10, "f10",
0, FPR, 11, "f11",
0, FPR, 12, "f12",
0, FPR, 13, "f13",
0, FPR, 14, "f14",
0, FPR, 15, "f15",
0, FPR, 16, "f16",
0, FPR, 17, "f17",
0, FPR, 18, "f18",
0, FPR, 19, "f19",
0, FPR, 20, "f20",
0, FPR, 21, "f21",
0, FPR, 22, "f22",
0, FPR, 23, "f23",
0, FPR, 24, "f24",
0, FPR, 25, "f25",
0, FPR, 26, "f26",
0, FPR, 27, "f27",
0, FPR, 28, "f28",
0, FPR, 29, "f29",
0, FPR, 30, "f30",
0, FPR, 31, "f31",
0, OP_LI, 0, "li",
0, HI16, 0, "hi16",
0, HA16, 0, "ha16",
0, LO16, 0, "lo16",
#include "tokens.y"

212
mach/xr17032/as/mach4.c Normal file
View file

@ -0,0 +1,212 @@
#include "rules.y"
| OP_LI GPR ',' extabsexp
{
word_t reg = $2;
uint32_t val = $4;
if (((int32_t)val >= -0x8000) && ((int32_t)val <= 0x7fff))
emit4(0x24000000 | (reg<<16) | (val & 0xffff)); /* addiu reg, zero, value */
else if (val <= 0xffff)
emit4(0x34000000 | (reg<<16) | val); /* ori reg, zero, value */
else
{
emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */
emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */
}
}
extabsexp
: absexp
| LO16 ASC_LPAR expr ASC_RPAR
{
newrelo($3.typ, RELO2 | FIXUPFLAGS);
$$ = $3.val;
}
| HI16 ASC_LPAR expr ASC_RPAR
{
newrelo($3.typ, RELO2HI | FIXUPFLAGS);
if ($3.val & 0xffff0000)
fatal("relocation offset in hi16[] too big");
$$ = $3.val;
}
| HA16 ASC_LPAR expr ASC_RPAR
{
newrelo($3.typ, RELO2HISAD | FIXUPFLAGS);
if ($3.val & 0xffff0000)
fatal("relocation offset in ha16[] too big");
$$ = $3.val;
}
;
gpr: GPR
fpr: FPR
fmt3
: OP__DOT_S { $$ = 0; }
| OP__DOT_D { $$ = 1; }
| OP__DOT_W { $$ = 4; }
| OP__DOT_L { $$ = 5; }
| OP__DOT_PS { $$ = 6; }
;
fmt
: fmt3 { $$ = $1 + 16; }
;
fcond
: OP__DOT_F { $$ = 0; }
| OP__DOT_UN { $$ = 1; }
| OP__DOT_EQ { $$ = 2; }
| OP__DOT_UEQ { $$ = 3; }
| OP__DOT_OLT { $$ = 4; }
| OP__DOT_ULT { $$ = 5; }
| OP__DOT_OLE { $$ = 6; }
| OP__DOT_ULE { $$ = 7; }
| OP__DOT_SF { $$ = 8; }
| OP__DOT_NGLE { $$ = 9; }
| OP__DOT_SEQ { $$ = 10; }
| OP__DOT_NGL { $$ = 11; }
| OP__DOT_LT { $$ = 12; }
| OP__DOT_NGE { $$ = 13; }
| OP__DOT_LE { $$ = 14; }
| OP__DOT_NGT { $$ = 15; }
;
e16
: extabsexp
{
/* Allow signed or unsigned 16-bit values. */
if (($1 < -0x8000) || ($1 > 0xffff))
serror("16-bit signed value out of range");
$$ = (uint16_t) $1;
}
;
e9
: absexp
{
/* Allow signed or unsigned 9-bit values. */
if (($1 < -0x100) || ($1 > 0x1ff))
serror("9-bit signed value out of range");
$$ = (uint16_t) $1;
}
;
u25
: absexp
{
if (($1 < 0) || ($1 > 0x1ffffff))
serror("25-bit unsigned value out of range");
$$ = $1;
}
;
u20
: absexp
{
if (($1 < 0) || ($1 > 0xfffff))
serror("20-bit unsigned value out of range");
$$ = $1;
}
;
u16
: extabsexp
{
if (($1 < 0) || ($1 > 0xffff))
serror("16-bit unsigned value out of range");
$$ = $1;
}
;
u5
: absexp
{
if (($1 < 0) || ($1 > 0x1f))
serror("5-bit unsigned value out of range");
$$ = $1;
}
;
u3
: absexp
{
if (($1 < 0) || ($1 > 0x7))
serror("3-bit unsigned value out of range");
$$ = $1;
}
;
offset16
: expr
{
int dist = $1.val - DOTVAL - 4;
fit(fitx(dist, 18));
if (dist & 0x3)
serror("jump targets must be 4-aligned");
newrelo($1.typ, RELOMIPS | RELPC | FIXUPFLAGS);
$$ = (dist >> 2) & 0x0000ffff;
}
;
offset21
: expr
{
int dist = $1.val - DOTVAL - 4;
fit(fitx(dist, 28));
if (dist & 0x3)
serror("jump targets must be 4-aligned");
newrelo($1.typ, RELOMIPS | RELPC | FIXUPFLAGS);
$$ = (dist >> 2) & 0x001fffff;
}
;
offset29
: expr
{
int dist = $1.val - DOTVAL - 4;
fit(fitx(dist, 32));
if (dist & 0x3)
serror("jump targets must be 4-aligned");
newrelo($1.typ, RELOMIPS | RELPC | FIXUPFLAGS);
$$ = (dist >> 2) & 0x1fffffff;
}
;
abs26
: expr
{
int target = $1.val;
fit(fitx(target, 28));
if (target & 0x3)
serror("jump targets must be 4-aligned");
newrelo($1.typ, RELOMIPS | FIXUPFLAGS);
$$ = (target >> 2) & 0x03ffffff;
}
;
extmsblsb
: u5 ',' u5
{
int pos = $1;
int size = $3;
$$ = ((size-1) << 5) | pos;
}
;
insmsblsb
: u5 ',' u5
{
int pos = $1;
int size = $3;
$$ = ((pos+size-1) << 5) | pos;
}
;

0
mach/xr17032/as/mach5.c Normal file
View file

192
mach/xr17032/as/mktables.lua Executable file
View file

@ -0,0 +1,192 @@
local args = {...}
local words = {}
local insns = {}
local function addword(word)
local w = words[word]
if not w then
w = word:upper()
w = w:gsub("%.", "_DOT_")
if not w:match("^[A-Z0-9_]*$") then
error(word.." is not a valid token")
end
words[word] = w
end
return w
end
local function parsesyntax(line)
local syntax = {}
for word in line:gmatch("%S+") do
local _, _, s = word:find('^"(.*)"$')
if s then
syntax[#syntax+1] = {word=addword(s) }
else
_, _, s = word:find("^('.*')$")
if s then
syntax[#syntax+1] = {punct=s }
else
local token = {}
for equate in word:gmatch("([^=]+)=") do
token[#token+1] = equate
end
_, _, token.token = word:find("([^=]*)$")
syntax[#syntax+1] = token
if not token.token then
error("can't parse "..word)
end
end
end
end
return syntax
end
local function parsefields(line)
local _, _, bits = line:find("^([^ ]+) ")
if #bits ~= 32 then
error("'"..bits.."' isn't 32 bits long")
end
local fields = {}
local i = 1
while i ~= 33 do
local c = line:sub(i, i)
if c ~= "." then
local f = { pos=i }
if c:find("%w") then
f.size = 1
f.value = c
elseif c == "<" then
local _, newi, name = line:find("^<%-*(%w+)%-*>", i)
f.size = 1 + newi - i
f.value = name
i = newi
else
error("bad field char '"..c.."' in '"..line.."'")
end
if f.value:find("[0-9]+") then
f.literal = true
f.variable = false
else
f.literal = false
f.variable = true
end
-- Convert from PowerPC numbering to sane numbering
f.pos = 33-(f.pos + f.size)
fields[#fields+1] = f
if f.value then
fields[f.value] = f
end
end
i = i + 1
end
local value = 0
for _, f in ipairs(fields) do
if f.literal then
local s = math.pow(2, f.pos)
value = value + f.value*s
end
end
fields.value = value
return fields
end
local function emit(fields, code)
local mask = 0
local value = 0
for _, f in ipairs(fields) do
if f.literal then
local s = math.pow(2, f.pos)
local m = math.pow(2, f.size) - 1
mask = mask + m*s
value = value + f.value*s
end
end
print(string.format("if ((value & 0x%x) == 0x%x) {", mask, value))
for _, f in ipairs(fields) do
if f.variable then
local m = math.pow(2, f.size) - 1
print(string.format("uint32_t %s = (value >> %d) & 0x%x;", f.value, f.pos, m))
end
end
print(code)
print("return;")
print("}")
end
while true do
local line = io.stdin:read("*l")
if not line then
break
end
line = line:gsub("#.*$", "")
line = line:gsub(" *$", "")
if line:find("^%%token ") then
addword(line:sub(8))
elseif line ~= "" then
local fields = parsefields(line)
local syntax = parsesyntax(line:sub(34, #line))
insns[#insns+1] = {
fields=parsefields(line),
syntax=parsesyntax(line:sub(34, #line))
}
end
end
local definitionsfp = io.open(args[1], "wb")
for word, value in pairs(words) do
definitionsfp:write("%token <y_word> OP_", tostring(value), " /* ", word, " */\n")
end
definitionsfp:close()
local tokensfp = io.open(args[2], "wb")
for word, value in pairs(words) do
tokensfp:write("0, OP_", value, ", 0, \"", word, "\",\n")
end
tokensfp:close()
local rulesfp = io.open(args[3], "wb")
rulesfp:write("operation\n")
for index, insn in ipairs(insns) do
if index == 1 then
rulesfp:write("\t:")
else
rulesfp:write("\t|")
end
for _, word in ipairs(insn.syntax) do
if word.word then
rulesfp:write(" OP_", word.word)
end
if word.punct then
rulesfp:write(" ", word.punct)
end
if word.token then
rulesfp:write(" ", word.token)
end
end
rulesfp:write("\n")
rulesfp:write("\t{ emit4(", string.format("0x%08x", insn.fields.value))
for wordindex, word in ipairs(insn.syntax) do
if word.token then
for _, alias in ipairs(word) do
local f = insn.fields[alias]
if not f then
error("reference to field "..alias.." which doesn't exist")
end
local mask = math.pow(2, f.size) - 1
rulesfp:write(" | (($", wordindex,
" & ", string.format("0x%x", mask), ") << ", f.pos, ")")
end
end
end
rulesfp:write("); }\n")
end
rulesfp:close()

47
mach/xr17032/libem/aar4.s Normal file
View file

@ -0,0 +1,47 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Get address of element of bounds-checked array.
*
* Stack: ( array-adr index descriptor-adr -- element-adr )
* Sets r2 = size of element for .los4, .sts4
* Preserves r25 (the last volatile register)
*
* An array descriptor is:
*
* +0 lower bound
* +4 range (upper bound - lower bound); *inclusive*
* +8 element size
*/
.sect .text
.define .aar4
.aar4:
lw r4, 0(sp) ! r4 = address of descriptor
lw r5, 4(sp) ! r5 = index
lw r6, 8(sp) ! r6 = address of array
lw r7, 0(r4) ! r7 = lower bound
slt at, r5, r7 ! at = index < lower bound
bne at, zero, .trap_earray
nop
subu r5, r5, r7 ! adjust index for non-zero lower bound
lw at, 4(r4) ! at = range
slt at, at, r5 ! at = range < adjusted index
bne at, zero, .trap_earray
nop
lw r2, 8(r4) ! r2 = size of element
mul r5, r5, r2 ! scale index by size
addu r5, r5, r6 ! calculate address of element
sw r5, 8(sp) ! push address of element
addiu sp, sp, 8
jr ra
nop
.define .trap_earray
.trap_earray:
li r4, 0 ! EARRAY = 0 in h/em_abs.h
b .trp

30
mach/xr17032/libem/and.s Normal file
View file

@ -0,0 +1,30 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Set intersection.
* Stack: ( a b size -- a&b )
*/
.sect .text
.define .and
.and:
lw r4, 0(sp) ! r4 = size
addiu sp, sp, 4 ! sp points at b
addu r5, sp, r4 ! r5 points at a
srl r4, r4, 2 ! r4 = count of words
1:
lw at, 0(r5) ! load a
lw r6, 0(sp) ! load b
and at, at, r6 ! combine
sw at, 0(r5) ! write back to a
addiu r5, r5, 4
addiu sp, sp, 4
addiu r4, r4, -1
bne r4, zero, 1b
nop
jr ra
nop

31
mach/xr17032/libem/bls4.s Normal file
View file

@ -0,0 +1,31 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Does a block move of words between non-overlapping buffers.
* Stack: ( src dst len -- )
*/
.sect .text
.define .bls4
.bls4:
lw r4, 0(sp) ! r4=len
lw r5, 4(sp) ! r5=dst
lw r6, 8(sp) ! r6=src
addiu sp, sp, 12
srl r4, r4, 2 ! convert len to words
1:
beq r4, zero, 2f
nop
lw at, 0(r6)
sw at, 0(r5)
addiu r6, r6, 4
addiu r5, r5, 4
addiu r4, r4, -1
b 1b
nop
2:
jr ra
nop

View file

@ -0,0 +1,43 @@
for _, plat in ipairs(vars.plats) do
acklibrary {
name = "headers_"..plat,
}
acklibrary {
name = "lib_"..plat,
srcs = {
"./aar4.s",
"./and.s",
"./bls4.s",
"./cms.s",
"./compareul.s",
"./com.s",
"./csa.s",
"./csb.s",
"./c_ud_i.s",
"./c_uf_i.s",
"./c_ui_d.s",
"./c_ui_f.s",
"./dus4.s",
"./exg.s",
"./fef8.s",
"./fif8.s",
"./inn.s",
"./ior.s",
"./lar4.s",
"./los4.s",
"./rck.s",
"./sar4.s",
"./set.s",
"./sts4.s",
"./trp.s",
"./xor.s",
"./zer.s",
},
vars = { plat = plat },
deps = {
"h+emheaders",
"+headers_"..plat,
}
}
end

View file

@ -0,0 +1,36 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .c_ud_i
.c_ud_i:
/* Input: f0
* Output: r2
* Only at and f30/f31 may be used.
*/
lui at, ha16[.fd_80000000]
ldc1 f30, lo16[.fd_80000000] (at)
c.le.d 0, f30, f0
bc1t toobig
nop
trunc.w.d f0, f0
mfc1 r2, f0
jr ra
nop
toobig:
sub.d f0, f0, f30
trunc.w.d f0, f0
mfc1 r2, f0
lui at, 0x8000 ! load 0x80000000
addu r2, r2, at
jr ra
nop
.sect .rom
.define .fd_80000000
.fd_80000000:
.dataf8 2147483648.0

View file

@ -0,0 +1,38 @@
#
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
.define .c_uf_i
.c_uf_i:
/* Input: f0
* Output: r2
* Only at and f30/f31 may be used.
*/
lui at, ha16[.ff_80000000]
lwc1 f30, lo16[.ff_80000000] (at)
c.le.s 0, f30, f0
bc1t toobig
nop
trunc.w.s f0, f0
mfc1 r2, f0
jr ra
nop
toobig:
sub.s f0, f0, f30
trunc.w.s f0, f0
mfc1 r2, f0
lui at, 0x8000 ! load 0x80000000
addu r2, r2, at
jr ra
nop
.sect .rom
.ff_80000000:
.dataf4 2147483648.0

View file

@ -0,0 +1,25 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .c_ui_d
.c_ui_d:
/* Input: r2
* Output: f0
* Only at and f30/f31 may be used.
*/
mtc1 r2, f0
cvt.d.w f0, f0
bgez r2, nonnegative
nop
lui at, ha16[.fd_100000000]
ldc1 f30, lo16[.fd_100000000] (at)
add.d f0, f0, f30
nonnegative:
jr ra
nop
.sect .rom
.fd_100000000:
.dataf8 4294967296.0

View file

@ -0,0 +1,26 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .c_ui_f
.c_ui_f:
/* Input: r2
* Output: f0
* Only at and f30/f31 may be used.
*/
mtc1 r2, f0
cvt.s.w f0, f0
bgez r2, nonnegative
nop
lui at, ha16[.fs_100000000]
ldc1 f30, lo16[.fs_100000000] (at)
add.d f0, f0, f30
nonnegative:
jr ra
nop
/* 4294967296 as a float. */
.sect .rom
.fs_100000000:
.dataf4 4294967296.0

35
mach/xr17032/libem/cms.s Normal file
View file

@ -0,0 +1,35 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Set comparison Returns 0 if the sets were equal.
* Stack: ( a b size -- a!=b )
*/
.sect .text
.define .cms
.cms:
lw r4, 0(sp) ! r4 = size; sp points at b-word
addu r5, sp, r4 ! r5 points at a-word
addu r6, r5, r4 ! r6 is final sp-word
srl r4, r4, 2 ! r4 = count of words
li r8, 1 ! result
1:
lw at, 4(r5) ! load a
lw r7, 4(sp) ! load b
bne at, r7, exit ! branch if not equal
nop
addiu r5, r5, 4
addiu sp, sp, 4
addiu r4, r4, -1
bne r4, zero, 1b
nop
li r8, 0 ! Update result.
exit:
mov sp, r6
sw r8, 0(sp)
jr ra
nop

28
mach/xr17032/libem/com.s Normal file
View file

@ -0,0 +1,28 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Set complement.
* Stack: ( a size -- ~a )
*/
.sect .text
.define .com
.com:
lw r4, 0(sp) ! r4 = size
addiu sp, sp, 4
mov r5, sp ! r5 points to set
srl r4, r4, 2 ! r4 = word count
1:
lw at, 0(r5)
nor at, zero, at
sw at, 0(r5)
addiu r5, r5, 4
addiu r4, r4, -1
bne r4, zero, 1b
nop
jr ra
nop

View file

@ -0,0 +1,39 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* 64-big unsigned tristate comparison.
* Inputs:
* r2r3: left
* r4r5: right
* Outputs;
* r2: result
*/
.sect .text
.define .compareul
.compareul:
/* Compare high words. */
sltu at, r3, r5 ! if r3<r5, then 1
subu at, zero, at ! if r3<r5, then -1
bne at, zero, exit
nop
sltu at, r5, r3 ! if r3>r5, then 1
bne at, zero, exit
nop
/* High words are equal --- compare low words. */
sltu at, r2, r4 ! if r2<r4, then 1
subu at, zero, at ! if r2<r4, then -1
bne at, zero, exit
nop
sltu at, r4, r2 ! if r2>r4, then 1
exit:
mov r2, at
jr ra
nop

42
mach/xr17032/libem/csa.s Normal file
View file

@ -0,0 +1,42 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* This is not a subroutine, but just a
* piece of code that computes the jump-
* address and jumps to it.
* traps if resulting address is zero
*
* Stack: ( value tableaddr -- )
*/
.sect .text
.define .csa
.csa:
lw r4, 0(sp) /* r4 = table */
lw r5, 4(sp) /* r5 = value */
addiu sp, sp, 8
lw r6, 0(r4) /* r6 = default target */
lw r7, 4(r4) /* r7 = lower bound */
subu r5, r5, r7 /* adjust value */
bltz r5, 1f /* jump to default if out of range */
nop
lw r7, 8(r4) /* fetch range */
subu r7, r7, r5 /* compute difference within range */
bltz r7, 1f /* jump to default if out of range */
nop
addiu r4, r4, 12 /* skip header */
sll r5, r5, 2 /* value = value<<2 */
addu r4, r4, r5 /* find address of target */
lw r6, 0(r4) /* r6 = new target */
1:
beq r6, zero, 2f /* trap if null */
nop
jr r6 /* otherwise jump */
nop
2:
j .trap_ecase
nop

47
mach/xr17032/libem/csb.s Normal file
View file

@ -0,0 +1,47 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* this is not a subroutine, but just a
* piece of code that computes the jump-
* address and jumps to it.
* traps if resulting address is zero
*
* Stack: ( value tableaddr -- )
*/
.sect .text
.define .csb
.csb:
lw r4, 0(sp) ! r4 = address of table
lw r5, 4(sp) ! r5 = value
addiu sp, sp, 8
lw r6, 0(r4) ! r6 = default target
lw r7, 4(r4) ! r7 = table count
2:
addiu r7, r7, -1 ! decrement count
bltz r7, 1f ! exit loop if out
nop
lw r8, 8(r4) ! candidate value
beq r8, r5, 3f ! branch if equal
nop
addiu r4, r4, 8 ! next entry
b 2b
nop
3:
/* We found an item in the table. */
lw r6, 12(r4) ! load jump target
/* fall through */
1:
beq r6, zero, 4f /* trap if null */
nop
jr r6 /* otherwise jump */
nop
4:
j .trap_ecase
nop

28
mach/xr17032/libem/dus4.s Normal file
View file

@ -0,0 +1,28 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Duplicates some words on top of stack.
* Stack: ( a size -- a a )
*/
.sect .text
.define .dus4
.dus4:
lw r4, 0(sp) ! r4 = size
addiu sp, sp, 4 ! sp = pointer to a
mov r5, sp ! r5 = pointer to a
subu sp, sp, r4 ! sp = pointer to newa
mov r6, sp ! r6 = pointer to b
srl r4, r4, 2 ! r4 = number of words
1:
lw at, 0(r5)
sw at, 0(r6)
addiu r5, r5, 4
addiu r6, r6, 4
addiu r4, r4, -1
bne r4, zero, 1b
nop
jr ra
nop

31
mach/xr17032/libem/exg.s Normal file
View file

@ -0,0 +1,31 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Exchange top two values on stack.
* Stack: ( a b size -- b a )
*/
.sect .text
.define .exg
.exg:
lw r4, 0(sp) ! r4 = size
srl r5, r4, 2 ! r5 = number of words
addiu sp, sp, 4 ! adjust stack for input/output parameter size
mov r6, sp ! r6 = pointer to b
addu r7, r6, r4 ! r7 = pointer to a
! Loop to swap each pair of words.
1:
lw r8, 0(r6)
lw r9, 0(r7)
sw r9, 0(r6)
sw r8, 0(r7)
addiu r6, r6, 4
addiu r7, r7, 4
addiu r5, r5, -1
bne r5, zero, 1b
nop
jr ra
nop

56
mach/xr17032/libem/fef8.s Normal file
View file

@ -0,0 +1,56 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Split a double-precision float into fraction and exponent, like
* frexp(3) in C, http://en.cppreference.com/w/c/numeric/math/frexp
*
* Stack: ( double -- fraction exponent )
*/
#define DBL_EXPBITS 11
#define DBL_FRACHBITS 20
#define DBL_FRACLBITS 32
#define DBL_FRACBITS 52
#define DBL_EXP_INFNAN 2047
#define DBL_EXP_BIAS 1023
.sect .text
.define .fef8
.fef8:
lw r4, 0(sp) ! r4 = low word (bits 0..31)
lw r5, 4(sp) ! r5 = high word (bits 32..63)
! IEEE double = sign * 1.fraction * 2**(exponent - 1023)
! sign exponent fraction
! 31 30..19 18..0, 31..0
!
! IEEE exponent = 1022 in [0.5, 1) or (-1, -0.5].
ext r7, r5, DBL_FRACHBITS, DBL_EXPBITS ! r7 = IEEE exponent
beq r7, zero, zeroexp ! this number is zero or denormalised, treat specially
nop
li at, DBL_EXP_INFNAN
beq r7, at, return ! just return if infinity or NaN
nop
addiu r7, r7, -[DBL_EXP_BIAS-1] ! undo exponent bias
li at, DBL_EXP_BIAS-1
ins r5, at, DBL_FRACHBITS, DBL_EXPBITS ! replace exponent
return:
addiu sp, sp, -4 ! returning one more quad than we got
sw r5, 8(sp)
sw r6, 4(sp)
sw r7, 0(sp)
jr ra
nop
/* We received a denormalised number or zero. */
zeroexp:
/* TODO: we just assume that the number is zero here. */
mov r5, zero
mov r6, zero
mov r7, zero
b return
nop

69
mach/xr17032/libem/fif8.s Normal file
View file

@ -0,0 +1,69 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Multiplies two double-precision floats, then splits the product into
* fraction and integer, both as floats, like modf(3) in C,
* http://en.cppreference.com/w/c/numeric/math/modf
*
* Stack: ( a b -- fraction integer )
*/
.sect .text
.define .fif8
.fif8:
ldc1 f0, 8(sp) ! f0 = a
ldc1 f2, 0(sp) ! f2 = b
mul.d f0, f0, f2 ! f0 = a * b
abs.d f2, f0 ! f2 = abs(f0)
lui at, ha16[max_power_of_two]
ldc1 f4, lo16[max_power_of_two] (at) ! f4 = max power of two
mov.d f6, f2 ! we're going to assemble the integer part in f6
c.lt.d 0, f4, f2 ! if absolute value too big, it must be integral
bc1t 0, return
nop
! Crudely strip off the fractional part.
add.d f6, f2, f4 ! f6 = absolute value + max power of two
sub.d f6, f6, f4 ! f6 -= max_power_of_two
! The above might round, so correct that.
lui at, ha16[one]
ldc1 f8, lo16[one] (at) ! f8 = 1.0
1:
c.le.d 0, f6, f2 ! if result <= absolute value, stop
bc1t 0, 2f
nop
sub.d f6, f6, f8 ! result -= 1.0
b 1b
nop
2:
! Correct the sign of the result.
mtc1 zero, f8
mthc1 zero, f8 ! f8 = 0.0
c.lt.d 0, f0, f8 ! if original value was negative
bc1f 0, 1f
nop
neg.d f6, f6 ! negate the result
1:
return:
sdc1 f6, 0(sp) ! store integer part
sub.d f6, f0, f6 ! calculate fractional part
sdc1 f6, 8(sp) ! store fractional part
jr ra
nop
! doubles >= MAXPOWTWO are already integers
.sect .rom
max_power_of_two:
.dataf8 4.503599627370496000E+15
one:
.dataf8 1.0

32
mach/xr17032/libem/inn.s Normal file
View file

@ -0,0 +1,32 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Tests a bit in a bitset on the stack.
*
* Stack: ( bitset bitnum setsize -- bool )
*
* Some back ends push false if bitnum is too large. We don't because
* the compilers tend to pass a small enough bitnum.
*/
.sect .text
.define .inn
.inn:
lw r4, 0(sp) ! r4 = size of set (bytes)
lw r5, 4(sp) ! r5 = bit number
addiu sp, sp, 4 ! sp now points to word below bitset
andi r6, r5, ~31 ! r6 = bit offset of base of word in set
srl r6, r6, 3 ! r6 = byte offset of base of word in set
addu r6, sp, r6 ! r6 = address of word in set
lw r6, 4(r6) ! r6 = word (remember stack offset)
andi r7, r5, 31 ! r7 = bit number within word
srlv r6, r6, r7 ! r7 = candidate bit now at bit 0
andi r6, r6, 1 ! r7 = bool
addu sp, sp, r4 ! retract over bitfield (remember stack offset)
sw r6, 0(sp) ! store result
jr ra
nop

30
mach/xr17032/libem/ior.s Normal file
View file

@ -0,0 +1,30 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Set union.
* Stack: ( a b size -- a|b )
*/
.sect .text
.define .ior
.ior:
lw r4, 0(sp) ! r4 = size
addiu sp, sp, 4 ! sp points at b
addu r5, sp, r4 ! r5 points at a
srl r4, r4, 2 ! r4 = count of words
1:
lw at, 0(r5) ! load a
lw r6, 0(sp) ! load b
or at, at, r6 ! combine
sw at, 0(r5) ! write back to a
addiu r5, r5, 4
addiu sp, sp, 4
addiu r4, r4, -1
bne r4, zero, 1b
nop
jr ra
nop

23
mach/xr17032/libem/lar4.s Normal file
View file

@ -0,0 +1,23 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Load from bounds-checked array.
*
* Stack: ( array-adr index descriptor-adr -- element )
*/
.sect .text
.define .lar4
.lar4:
mov r25, ra
jal .aar4
nop
/* pass r2 = size from .aar4 to .los4 */
jal .los4
nop
jr r25
nop

55
mach/xr17032/libem/los4.s Normal file
View file

@ -0,0 +1,55 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Loads a variable-sized block onto the stack.
*
* On entry: r2 = size
* Stack: ( address -- block )
* Preserves r25 for .lar4 and .sar4
*/
.sect .text
.define .los4
.los4:
lw r4, 0(sp) ! r4 = address of source block
! Sizes 1 and 2 are handled specially.
li at, 1
beq r2, at, byte_sized
nop
li at, 2
beq r2, at, word_sized
nop
! Else the size must be a multiple of 4.
srl r5, r2, 2 ! r5 = number of words
addiu sp, sp, 4 ! retract over address
subu sp, sp, r2 ! allocate space for destination block
mov r6, sp ! r6 = start of destination block
1:
lw at, 0(r4)
sw at, 0(r6)
addiu r4, r4, 4
addiu r6, r6, 4
addiu r5, r5, -1
bne r5, zero, 1b
nop
jr ra
nop
byte_sized:
lbu at, 0(r4)
sw at, 0(sp)
jr ra
nop
word_sized:
lhu at, 0(r4)
sw at, 0(sp)
jr ra
nop

35
mach/xr17032/libem/rck.s Normal file
View file

@ -0,0 +1,35 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Bounds check. Traps if the value is out of range.
* Stack: ( value descriptor -- value )
*
* This ".rck" only works with 4-byte integers. The name is ".rck" and
* not ".rck4" because many back ends only do rck with the word size.
*/
.sect .text
.define .rck
.rck:
lw r4, 0(sp) ! r4 = pointer to descriptor
addiu sp, sp, 4 ! leave value on stack
lw r5, 0(sp) ! r5 = value
lw at, 0(r4) ! at = lower bound
slt at, r5, at ! at = r5 < at
bne at, zero, .trap_erange
nop
lw at, 4(r4) ! at = upper bound
slt at, at, r5 ! at = at < r5
bne at, zero, .trap_erange
nop
jr ra
nop
.define .trap_erange
.trap_erange:
li r4, 1
j .trp
nop

24
mach/xr17032/libem/sar4.s Normal file
View file

@ -0,0 +1,24 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Store to bounds-checked array.
*
* Stack: ( element array-adr index descriptor-adr -- )
*/
.sect .text
.define .sar4
.sar4:
mov r25, ra
jal .aar4
nop
/* pass r2 = size from .aar4 to .sts4 */
jal .sts4
nop
jr r25
nop

39
mach/xr17032/libem/set.s Normal file
View file

@ -0,0 +1,39 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Create singleton set.
* Stack: ( bitnumber size -- set )
*/
.sect .text
.define .set
.set:
lw r4, 0(sp) ! r4 = size
lw r5, 4(sp) ! r5 = bit number
addiu sp, sp, 8
srl r4, r4, 2 ! r4 = word count
! Create an empty set by pushing zeros.
1:
addiu sp, sp, -4
sw zero, 0(sp)
addiu r4, r4, -1
bne r4, zero, 1b
nop
! sp now points at the set.
andi r6, r5, ~31 ! r6 = bit offset of base of word in set
srl r6,r6, 3 ! r6 = byte offset of word in set
addu r6, sp, r6 ! r6 = address of word in set
andi r7, r5, 31 ! r7 = bit number within word
li r8, 1
sllv r8, r8, r7 ! r8 = word with 1 set
sw r8, 0(r6) ! write to set
jr ra
nop

57
mach/xr17032/libem/sts4.s Normal file
View file

@ -0,0 +1,57 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/* Stores a variable-sized block from the stack.
*
* On entry: r2 = size
* Stack: ( block address -- )
* Preserves r25 for .lar4 and .sar4
*/
.sect .text
.define .sts4
.sts4:
lw r4, 0(sp) ! r4 = address
addiu sp, sp, 4 ! sp = pointer to block
! Sizes 1 and 2 are handled specially.
li at, 1
beq r2, at, byte_sized
nop
li at, 2
beq r2, at, word_sized
nop
! Else the size must be a multiple of 4.
srl r5, r2, 2 ! r5 = number of words
! Copy.
1:
lw at, 0(sp)
sw at, 0(r4)
addiu sp, sp, 4
addiu r4, r4, 4
addiu r5, r5, -1
bne r5, zero, 1b
nop
jr ra
nop
byte_sized:
lw at, 0(sp)
sb at, 0(r4)
addiu sp, sp, 4
jr ra
nop
word_sized:
lw at, 0(sp)
sh at, 0(r4)
addiu sp, sp, 4
jr ra
nop

65
mach/xr17032/libem/trp.s Normal file
View file

@ -0,0 +1,65 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .trap_ecase
.trap_ecase:
li r4, 20 ! ECASE = 20 in h/em_abs.h
! FALLTHROUGH to .trp
! Raises an EM trap.
! Expects r4 = trap number.
.define .trp
.trp:
andi at, r4, 0xfff0
bne at, zero, 1f ! traps > 15 can't be ignored
nop
lui at, ha16[.ignmask]
lw r5, lo16[.ignmask] (at) ! load ignore mask
srlv r5, r5, r4
andi r5, r5, 1
bne r5, zero, return ! return if ignoring trap
nop
1:
lui at, ha16[.trppc]
lw r5, lo16[.trppc] (at) ! r5 = user trap routine
sw zero, lo16[.trppc] (at) ! reset the trap routine for next time
beq r5, zero, abend ! abort if no user trap routine
nop
addiu sp, sp, -8
sw r4, 0(sp) ! push trap number
sw ra, 4(sp) ! and link register
jalr r5 ! call trap routine
nop
lw ra, 4(sp) ! ...and return
addiu sp, sp, 8
return:
jr ra
nop
! No trap handler; write error message and exit.
abend:
addiu sp, sp, -12
li at, 2
sw at, 0(sp)
lui at, hi16[message]
ori at, at, lo16[message]
sw at, 4(sp)
li at, 6
sw at, 8(sp)
jal _write ! write(2, message, 6)
nop
li at, 1
sw at, 0(sp)
j __exit ! _exit(1)
.sect .rom
message:
.ascii "TRAP!\n"

30
mach/xr17032/libem/xor.s Normal file
View file

@ -0,0 +1,30 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Set xor..
* Stack: ( a b size -- a^b )
*/
.sect .text
.define .xor
.xor:
lw r4, 0(sp) ! r4 = size
addiu sp, sp, 4 ! sp points at b
addu r5, sp, r4 ! r5 points at a
srl r4, r4, 2 ! r4 = count of words
1:
lw at, 0(r5) ! load a
lw r6, 0(sp) ! load b
xor at, at, r6 ! combine
sw at, 0(r5) ! write back to a
addiu r5, r5, 4
addiu sp, sp, 4
addiu r4, r4, -1
bne r4, zero, 1b
nop
jr ra
nop

25
mach/xr17032/libem/zer.s Normal file
View file

@ -0,0 +1,25 @@
#
.sect .text; .sect .rom; .sect .data; .sect .bss
/*
* Create empty set.
* Stack: ( size -- set )
*/
.sect .text
.define .zer
.zer:
lw r4, 0(sp) ! r4 = size
addiu sp, sp, 4
srl r4, r4, 2 ! r4 = word count
1:
addiu sp, sp, -4
sw zero, 0(sp)
addiu r4, r4, -1
bne r4, zero, 1b
nop
jr ra
nop

View file

@ -0,0 +1,13 @@
for _, plat in ipairs(vars.plats) do
acklibrary {
name = "lib_"..plat,
srcs = {
"./edata.s",
"./em_end.s",
"./end.s",
"./etext.s",
},
vars = { plat = plat },
}
end

View file

@ -0,0 +1,9 @@
.sect .text
.sect .rom
.sect .data
.sect .bss
.define _edata
.sect .data
.align 4
.sect .data
_edata:

View file

@ -0,0 +1,24 @@
! $Source$
! $State$
! $Revision$
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .end ! only for declaration of _end, __end and endbss.
.define endtext, endrom, enddata, endbss, __end
.sect .text
.align 4
endtext:
.sect .rom
.align 4
endrom:
.sect .data
.align 4
enddata:
.sect .end
.align 4
__end:
endbss:

View file

@ -0,0 +1,7 @@
.sect .text
.sect .rom
.sect .data
.sect .bss
.define _end
.sect .end ! only for declaration of _end, __end and endbss.
_end:

View file

@ -0,0 +1,9 @@
.sect .text
.sect .rom
.sect .data
.sect .bss
.define _etext
.sect .text
.align 4
.sect .text
_etext:

View file

@ -0,0 +1,7 @@
bundle {
name = "headers",
srcs = {
"./platform.c",
}
}

309
mach/xr17032/mcg/platform.c Normal file
View file

@ -0,0 +1,309 @@
#include "mcg.h"
/* mcg stack frames are laid out as:
*
* | ...params...
* | --------------- <- ab
* | old FR
* | old FP
* | --------------- <- fp (a.k.a. lb)
* | locals
* | ---------------
* | spills
* | --------------- <- sb
* | saved regs
* | --------------- <- sp, rb
* V ...user area...
*
* st indexes up; lb indexes down.
*
* Note that [fp] == old_fp and ab == fp + 8.
*/
static ARRAYOF(struct hreg) saved_regs;
void platform_calculate_offsets(void)
{
int i;
saved_regs.count = 0;
for (i=0; i<current_proc->usedregs.count; i++)
{
struct hreg* hreg = current_proc->usedregs.item[i];
if (!(hreg->attrs & burm_volatile_ATTR) &&
((hreg->attrs & burm_long_ATTR) || (hreg->attrs & burm_double_ATTR)))
{
hreg->offset = current_proc->saved_size;
current_proc->saved_size += 8;
array_append(&saved_regs, hreg);
}
}
for (i=0; i<current_proc->usedregs.count; i++)
{
struct hreg* hreg = current_proc->usedregs.item[i];
if (!(hreg->attrs & burm_volatile_ATTR) &&
((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR)))
{
hreg->offset = current_proc->saved_size;
current_proc->saved_size += 4;
array_append(&saved_regs, hreg);
}
}
current_proc->fp_to_ab = 8;
current_proc->fp_to_lb = 0;
current_proc->fp_to_sb = -(current_proc->locals_size + current_proc->spills_size);
current_proc->fp_to_rb = current_proc->fp_to_sb - current_proc->saved_size;
}
struct hop* platform_prologue(void)
{
int i;
int spoffset = current_proc->saved_size + current_proc->spills_size +
current_proc->locals_size;
struct hop* hop = new_hop(current_proc->entry, NULL);
hop_add_insel(hop, "! locals_size = %d", current_proc->locals_size);
hop_add_insel(hop, "! spills_size = %d", current_proc->spills_size);
hop_add_insel(hop, "! saved_size = %d", current_proc->saved_size);
hop_add_insel(hop, "! params @ fp+%d", current_proc->fp_to_ab);
hop_add_insel(hop, "! lr @ fp+4");
hop_add_insel(hop, "! fp @ fp+0");
hop_add_insel(hop, "! locals @ fp-%d to fp+0",
current_proc->locals_size);
hop_add_insel(hop, "! spills @ fp-%d to fp-%d",
-current_proc->fp_to_sb, current_proc->locals_size);
for (i=saved_regs.count-1; i>=0; i--)
{
struct hreg* hreg = saved_regs.item[i];
hop_add_insel(hop, "! %s @ fp-%d",
hreg->id, -(current_proc->fp_to_rb + hreg->offset));
}
hop_add_insel(hop, "addiu sp, sp, %d", -(spoffset + 8));
hop_add_insel(hop, "sw fp, %d(sp)", spoffset + 0);
hop_add_insel(hop, "sw ra, %d(sp)", spoffset + 4);
hop_add_insel(hop, "addiu fp, sp, %d", spoffset);
/* Saved reg offsets are negative. */
for (i=0; i<saved_regs.count; i++)
{
struct hreg* hreg = saved_regs.item[i];
if (hreg->attrs & burm_int_ATTR)
hop_add_insel(hop, "sw %H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset);
else if (hreg->attrs & burm_long_ATTR)
{
hop_add_insel(hop, "sw %0H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset + 0);
hop_add_insel(hop, "sw %1H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset + 4);
}
else if (hreg->attrs & burm_float_ATTR)
hop_add_insel(hop, "swc1 %H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset);
else if (hreg->attrs & burm_double_ATTR)
hop_add_insel(hop, "sdc1 %H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset);
else
fatal("unsavable non-volatile register %s", hreg->id);
}
return hop;
}
struct hop* platform_epilogue(void)
{
struct hop* hop = new_hop(current_proc->exit, NULL);
int i;
for (i=0; i<saved_regs.count; i++)
{
struct hreg* hreg = saved_regs.item[i];
if (hreg->attrs & burm_int_ATTR)
hop_add_insel(hop, "lw %H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset);
else if (hreg->attrs & burm_long_ATTR)
{
hop_add_insel(hop, "lw %0H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset + 0);
hop_add_insel(hop, "lw %1H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset + 4);
}
else if (hreg->attrs & burm_float_ATTR)
hop_add_insel(hop, "lwc1 %H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset);
else if (hreg->attrs & burm_double_ATTR)
hop_add_insel(hop, "ldc1 %H, %d(fp)",
hreg, current_proc->fp_to_rb + hreg->offset);
else
fatal("unloadable non-volatile register %s", hreg->id);
}
hop_add_insel(hop, "lw ra, 4(fp)");
hop_add_insel(hop, "lw at, 0(fp)"); /* load old fp */
hop_add_insel(hop, "addiu sp, fp, %d", current_proc->fp_to_ab);
hop_add_insel(hop, "jr ra");
hop_add_insel(hop, "mov fp, at"); /* delay slot */
return hop;
}
struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest)
{
struct hop* hop = new_hop(bb, NULL);
if ((src->attrs & TYPE_ATTRS) != (dest->attrs & TYPE_ATTRS))
fatal("hreg move of %%%d from %s to %s with mismatched types", vreg->id, src->id, dest->id);
else
{
uint32_t type = src->attrs & TYPE_ATTRS;
tracef('R', "R: non-converting move from %s to %s of type 0x%x\n", src->id, dest->id, type);
if (!src->is_stacked && dest->is_stacked)
{
switch (type)
{
case burm_int_ATTR:
hop_add_insel(hop, "sw %H, %S(fp) ! %H", src, dest, dest);
break;
case burm_long_ATTR:
hop_add_insel(hop, "sw %0H, 0+%S(fp) ! %H", src, dest, dest);
hop_add_insel(hop, "sw %1H, 4+%S(fp) ! %H", src, dest, dest);
break;
case burm_float_ATTR:
hop_add_insel(hop, "swc1 %H, %S(fp) ! %H", src, dest, dest);
break;
case burm_double_ATTR:
hop_add_insel(hop, "sdc1 %H, %S(fp) ! %H", src, dest, dest);
break;
default:
goto nomove;
}
}
else if (src->is_stacked && !dest->is_stacked)
{
switch (type)
{
case burm_int_ATTR:
hop_add_insel(hop, "lw %H, %S(fp) ! %H", dest, src, src);
break;
case burm_long_ATTR:
/* Can't load straight into dest because it might overlap with src. */
hop_add_insel(hop, "lw at, 0+%S(fp) ! %H", dest, src, src);
hop_add_insel(hop, "lw %1H, 4+%S(fp) ! %H", dest, src, src);
hop_add_insel(hop, "mov %0H, at", dest);
break;
case burm_float_ATTR:
hop_add_insel(hop, "lwc1 %H, %S(fp) ! %H", dest, src, src);
break;
case burm_double_ATTR:
hop_add_insel(hop, "ldc1 %H, %S(fp) ! %H", dest, src, src);
break;
default:
goto nomove;
}
}
else if (!src->is_stacked && !dest->is_stacked)
{
switch (type)
{
case burm_int_ATTR:
hop_add_insel(hop, "mov %H, %H", dest, src);
break;
case burm_long_ATTR:
hop_add_insel(hop, "mov %0H, %0H", dest, src);
hop_add_insel(hop, "mov %1H, %1H", dest, src);
break;
case burm_float_ATTR:
hop_add_insel(hop, "mov.s %H, %H", dest, src);
break;
case burm_double_ATTR:
hop_add_insel(hop, "mov.d %H, %H", dest, src);
break;
default:
goto nomove;
}
}
else if (src->is_stacked && dest->is_stacked)
fatal("tried to move stacked object %%%d of type 0x%x from %s to %s", vreg->id, type, src->id, dest->id);
else
goto nomove;
}
return hop;
nomove:
fatal("cannot move %s to %s", src->id, dest->id);
}
struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
{
struct hop* hop = new_hop(bb, NULL);
tracef('R', "R: swap of %s to %s\n", src->id, dest->id);
assert(!src->is_stacked);
assert(!dest->is_stacked);
assert((src->attrs & TYPE_ATTRS) == (dest->attrs & TYPE_ATTRS));
switch (src->attrs & TYPE_ATTRS)
{
case burm_int_ATTR:
hop_add_insel(hop, "mov at, %H", src);
hop_add_insel(hop, "mov %H, %H", src, dest);
hop_add_insel(hop, "mov %H, at", dest);
break;
case burm_long_ATTR:
hop_add_insel(hop, "mov at, %0H", src);
hop_add_insel(hop, "mov %0H, %0H", src, dest);
hop_add_insel(hop, "mov %0H, at", dest);
hop_add_insel(hop, "mov at, %1H", src);
hop_add_insel(hop, "mov %1H, %1H", src, dest);
hop_add_insel(hop, "mov %1H, at", dest);
break;
case burm_float_ATTR:
hop_add_insel(hop, "mov.s f30, %H", src);
hop_add_insel(hop, "mov.s %H, %H", src, dest);
hop_add_insel(hop, "mov.s %H, f30", dest);
break;
case burm_double_ATTR:
hop_add_insel(hop, "mov.d f30, %H", src);
hop_add_insel(hop, "mov.d %H, %H", src, dest);
hop_add_insel(hop, "mov.d %H, f30", dest);
break;
}
return hop;
}
const char* platform_label(const char* label)
{
/* Labels starting with . are internal, not exported, and don't need mangling. */
if (label[0] == '.')
return label;
/* Otherwise, mangle. */
return aprintf("_%s", label);
}
/* vim: set sw=4 ts=4 expandtab : */

1018
mach/xr17032/mcg/table Normal file

File diff suppressed because it is too large Load diff

51
mach/xr17032/top/table Normal file
View file

@ -0,0 +1,51 @@
/* MIPS table for ACK target optimizer */
MAXOP 5;
LABEL_STARTER '.';
{
int plus(const char *, const char *, char *);
}
%%;
X, Y, Z { TRUE };
R { TRUE };
%%;
/* Whitespace is significant here! */
addiu R, R, X : addiu R, R, Y { plus(X, Y, Z) } -> addiu R, R, Z ;
addiu X, X, 0 -> ;
b X : nop : labdef X -> labdef X ;
%%;
/* Does it fit a signed 16-bit integer? */
static int fits16(long l) {
return l >= -32768 && l <= 32767;
}
/* Tries sum = a + b with signed 16-bit integers. */
int plus(const char *a, const char *b, char *sum)
{
long la, lb, lsum;
char *end;
la = strtol(a, &end, 10);
if (*a == '\0' || *end != '\0' || !fits16(la))
return 0;
lb = strtol(b, &end, 10);
if (*b == '\0' || *end != '\0' || !fits16(lb))
return 0;
lsum = la + lb;
if (!fits16(lsum))
return 0;
snprintf(sum, 7, "%ld", lsum);
return 1;
}

37
plat/mintia/README Normal file
View file

@ -0,0 +1,37 @@
The linuxmips platform
======================
linuxmips is a little-endian MIPS32r2 BSP that produces Linux MIPS executables.
This port only implements a very limited number of system calls; basically,
just enough to make the demo apps run. Adding more is easy, but there are some
subtleties that require more thought. The port should be considered only in
proof-of-concept stage right now.
Important note: you *can't* link access ELF shared libraries from these
executables. In other words, you have to all your work from inside ACK.
IEEE floating point is available, but requires an FPU.
The executables are generated with aelfslod and are extremely simple; there's
one rwx ELF section which contains all the application's code and data. This
is not optimal, but it does work. Symbols are provided.
Bugs
====
isatty() is a stub and always returns 0.
Example command line
====================
ack -mlinuxmips -O -o linuxmips.exe examples/paranoia.c
The file linuxmips.exe can then be run on a MIPS32r2 Linux machine (or on an
emulation thereof).
David Given
dg@cowlark.com

58
plat/mintia/boot.s Normal file
View file

@ -0,0 +1,58 @@
#
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
.define .entry
.entry:
! This code is placed at the beginning of the ELF executable and is the
! first thing that runs.
!
! On entry, the stack looks like this:
!
! sp+... NULL
! sp+8+(4*argc) env (X quads)
! sp+4+(4*argc) NULL
! sp+4 argv (argc quads)
! sp argc
!
! The ACK actually expects:
!
! sp+8 argc
! sp+4 ptr to argv
! sp ptr to env
lw r4, 0(sp) ! r4 = argc
addiu r5, sp, 4 ! r5 = argv
sll r6, r4, 2 ! r6 = argc*4
addu r6, r6, r5 ! r6 = null after last arg
addiu r6, r6, 4 ! r6 = env
addiu sp, sp, -3 * 4
sw r4, 0(sp) ! argc
sw r5, 4(sp) ! argv
sw r6, 8(sp) ! envp
j __m_a_i_n
nop
! Define symbols at the beginning of our various segments, so that we can find
! them. (Except .text, which has already been done.)
.sect .data; begdata:
.sect .rom; begrom:
.sect .bss; begbss:
! Some magic data. All EM systems need these.
.define _errno
.comm _errno, 4 ! Posix errno storage
.define .trppc, .ignmask
.comm .trppc, 4 ! ptr to user trap handler
.comm .ignmask, 4 ! user trap ignore mask

25
plat/mintia/build-pkg.lua Normal file
View file

@ -0,0 +1,25 @@
include("plat/build.lua")
ackfile {
name = "boot",
srcs = { "./boot.s" },
vars = { plat = "mintia" }
}
build_plat_libs {
name = "libs",
arch = "xr17032",
plat = "mintia",
}
installable {
name = "pkg",
map = {
"+tools",
"+libs",
"./include+pkg",
["$(PLATIND)/mintia/boot.o"] = "+boot",
["$(PLATIND)/mintia/libsys.a"] = "./libsys+lib",
}
}

View file

@ -0,0 +1,29 @@
include("plat/build.lua")
build_as {
name = "as",
arch = "xr17032",
deps = { "mach/xr17032/as+astables" }
}
build_mcg {
name = "mcg",
arch = "xr17032",
}
build_top {
name = "top",
arch = "xr17032",
}
return installable {
name = "tools",
map = {
["$(PLATDEP)/mintia/as"] = "+as",
["$(PLATDEP)/mintia/mcg"] = "+mcg",
["$(PLATDEP)/mintia/top"] = "+top",
["$(PLATIND)/descr/mintia"] = "./descr",
"util/amisc+axlofflod-pkg",
"util/opt+pkg",
}
}

83
plat/mintia/descr Normal file
View file

@ -0,0 +1,83 @@
# plat/linuxppc/descr
var w=4
var wa=4
var p={w}
var pa={w}
var s=2
var sa={s}
var l={w}
var la={w}
var f={w}
var fa={w}
var d=8
var da={d}
var x=8
var xa={x}
var ARCH=xr17032
var PLATFORM=mintia
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
var CPP_F=-D__mintia
var ALIGN=-a0:8 -a1:8 -a2:8 -a3:8 -b0:0x00400058
var MACHOPT_F=-m2
var C_INCLUDES=-I{EM}/share/ack/mintia/include -I{EM}/share/ack/include/ansi
name be
from .m.g
to .s
program {EM}/lib/ack/{PLATFORM}/mcg
mapflag -gdb GF=-gdb
args {GF?} <
stdout
need .e
end
name asopt
from .s
to .so
program {EM}/lib/ack/{PLATFORM}/top
args
optimizer
stdin
stdout
end
name as
from .s.so
to .o
program {EM}/lib/ack/{PLATFORM}/as
args - -o > <
prep cond
end
name led
from .o.a
to .out
program {EM}/lib/ack/em_led
mapflag -l* LNAME={PLATFORMDIR}/lib*
mapflag -fp FLOATS={EM}/{LIB}fp
args {ALIGN} {SEPID?} \
({RTS}:.b=-u _i_main) \
(.e:{HEAD}={PLATFORMDIR}/boot.o) \
({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \
({RTS}:.c={PLATFORMDIR}/c-ansi.o) \
({RTS}:.mod={PLATFORMDIR}/modula2.o) \
({RTS}:.p={PLATFORMDIR}/pascal.o) \
-o > < \
(.p:{TAIL}={PLATFORMDIR}/libpascal.a) \
(.b:{TAIL}={PLATFORMDIR}/libb.a) \
(.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \
(.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \
(.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \
(.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \
{FLOATS?} \
(.e:{TAIL}={PLATFORMDIR}/libem.a \
{PLATFORMDIR}/libsys.a \
{PLATFORMDIR}/libend.a)
linker
end
name cv
from .out
to .exe
program {EM}/bin/axlofflod
args -m8 -l -f0x70001000 < >
outfile mintia.exe
end

View file

@ -0,0 +1,19 @@
#ifndef _ACK_FCNTL_H
#define _ACK_FCNTL_H
/* Linux O_ constants. */
enum
{
O_ACCMODE = 0x3,
O_RDONLY = 0,
O_WRONLY = 1,
O_RDWR = 2,
O_CREAT = 00000100,
O_TRUNC = 00001000,
O_APPEND = 00002000
};
#endif

View file

@ -0,0 +1,12 @@
/* $Source$
* $State$
* $Revision$
*/
#ifndef _ACK_PLAT_H
#define _ACK_PLAT_H
#define ACKCONF_WANT_STANDARD_O 0
#define ACKCONF_WANT_STANDARD_SIGNALS 0
#endif

View file

@ -0,0 +1,74 @@
#ifndef _ACK_SIGNAL_H
#define _ACK_SIGNAL_H
/* Signal constants. */
typedef int sig_atomic_t;
#define SIG_ERR ((sighandler_t) -1) /* Error return. */
#define SIG_DFL ((sighandler_t) 0) /* Default action. */
#define SIG_IGN ((sighandler_t) 1) /* Ignore signal. */
#define SIGHUP 1 /* Hangup (POSIX). */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGQUIT 3 /* Quit (POSIX). */
#define SIGILL 4 /* Illegal instruction (ANSI). */
#define SIGTRAP 5 /* Trace trap (POSIX). */
#define SIGABRT 6 /* Abort (ANSI). */
#define SIGIOT 6 /* IOT trap (4.2 BSD). */
#define SIGBUS 7 /* BUS error (4.2 BSD). */
#define SIGFPE 8 /* Floating-point exception (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
#define SIGSEGV 11 /* Segmentation violation (ANSI). */
#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
#define SIGPIPE 13 /* Broken pipe (POSIX). */
#define SIGALRM 14 /* Alarm clock (POSIX). */
#define SIGTERM 15 /* Termination (ANSI). */
#define SIGSTKFLT 16 /* Stack fault. */
#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
#define SIGCHLD 17 /* Child status has changed (POSIX). */
#define SIGCONT 18 /* Continue (POSIX). */
#define SIGSTOP 19 /* Stop, unblockable (POSIX). */
#define SIGTSTP 20 /* Keyboard stop (POSIX). */
#define SIGTTIN 21 /* Background read from tty (POSIX). */
#define SIGTTOU 22 /* Background write to tty (POSIX). */
#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */
#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */
#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */
#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */
#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */
#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
#define SIGIO 29 /* I/O now possible (4.2 BSD). */
#define SIGPWR 30 /* Power failure restart (System V). */
#define SIGSYS 31 /* Bad system call. */
#define SIGUNUSED 31
#define _NSIG 32 /* Biggest signal number + 1
(not including real-time signals). */
/* sigprocmask */
#define SIG_BLOCK 0
#define SIG_UNBLOCK 1
#define SIG_SETMASK 2
typedef unsigned long sigset_t;
/* sa_flags */
#define SA_NODEFER 0x40000000UL
#define SA_RESETHAND 0x80000000UL
struct __siginfo;
struct sigaction {
union {
void (*__sa_handler)(int);
void (*__sa_sigaction)(int, struct __siginfo *, void *);
} __sigaction_u;
sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
};
#define sa_handler __sigaction_u.__sa_handler
#define sa_sigaction __sigaction_u.__sa_sigaction
#endif

View file

@ -0,0 +1,28 @@
include("plat/build.lua")
headermap = {}
packagemap = {}
local function addheader(h)
headermap[h] = "./"..h
packagemap["$(PLATIND)/mintia/include/"..h] = "./"..h
end
addheader("ack/fcntl.h")
addheader("ack/plat.h")
addheader("ack/signal.h")
addheader("sys/ioctl.h")
addheader("sys/types.h")
addheader("sys/wait.h")
acklibrary {
name = "headers",
hdrs = headermap
}
installable {
name = "pkg",
map = packagemap
}

View file

@ -0,0 +1,76 @@
/* $Source$
* $State$
* $Revision$
*/
#ifndef _SYS_IOCTL_H
#define _SYS_IOCTL_H
/* These are copied from the ioctl_list(2) man page. */
/* <include/asm-i386/socket.h> */
#define FIOSETOWN 0x00008901
#define SIOCSPGRP 0x00008902
#define FIOGETOWN 0x00008903
#define SIOCGPGRP 0x00008904
#define SIOCATMARK 0x00008905
#define SIOCGSTAMP 0x00008906
/* <include/asm-i386/termios.h> */
#define TCGETS 0x00005401
#define TCSETS 0x00005402
#define TCSETSW 0x00005403
#define TCSETSF 0x00005404
#define TCGETA 0x00005405
#define TCSETA 0x00005406
#define TCSETAW 0x00005407
#define TCSETAF 0x00005408
#define TCSBRK 0x00005409
#define TCXONC 0x0000540A
#define TCFLSH 0x0000540B
#define TIOCEXCL 0x0000540C
#define TIOCNXCL 0x0000540D
#define TIOCSCTTY 0x0000540E
#define TIOCGPGRP 0x0000540F
#define TIOCSPGRP 0x00005410
#define TIOCOUTQ 0x00005411
#define TIOCSTI 0x00005412
#define TIOCGWINSZ 0x00005413
#define TIOCSWINSZ 0x00005414
#define TIOCMGET 0x00005415
#define TIOCMBIS 0x00005416
#define TIOCMBIC 0x00005417
#define TIOCMSET 0x00005418
#define TIOCGSOFTCAR 0x00005419
#define TIOCSSOFTCAR 0x0000541A
#define FIONREAD 0x0000541B
#define TIOCINQ 0x0000541B
#define TIOCLINUX 0x0000541C
#define TIOCCONS 0x0000541D
#define TIOCGSERIAL 0x0000541E
#define TIOCSSERIAL 0x0000541F
#define TIOCPKT 0x00005420
#define FIONBIO 0x00005421
#define TIOCNOTTY 0x00005422
#define TIOCSETD 0x00005423
#define TIOCGETD 0x00005424
#define TCSBRKP 0x00005425
#define TIOCTTYGSTRUCT 0x00005426
#define FIONCLEX 0x00005450
#define FIOCLEX 0x00005451
#define FIOASYNC 0x00005452
#define TIOCSERCONFIG 0x00005453
#define TIOCSERGWILD 0x00005454
#define TIOCSERSWILD 0x00005455
#define TIOCGLCKTRMIOS 0x00005456
#define TIOCSLCKTRMIOS 0x00005457
#define TIOCSERGSTRUCT 0x00005458
#define TIOCSERGETLSR 0x00005459
#define TIOCSERGETMULTI 0x0000545A
#define TIOCSERSETMULTI 0x0000545B
#endif

View file

@ -0,0 +1,9 @@
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
typedef int pid_t;
typedef int mode_t;
typedef long suseconds_t;
typedef long time_t;
#endif

View file

@ -0,0 +1,19 @@
#ifndef _SYS_WAIT_H
#define _SYS_WAIT_H
#include <sys/types.h>
extern pid_t wait(int *__wstatus);
extern pid_t waitpid(pid_t __pid, int *__wstatus, int __options);
#define WNOHANG (1 << 0)
#define WUNTRACED (1 << 1)
#define WSTOPPED WUNTRACED
#define WEXITED (1 << 2)
#define WCONTINUED (1 << 3)
#define WNOWAIT (1 << 24)
#define __WNOTHREAD (1 << 29)
#define __WALL (1 << 30)
#define __WCLONE (1 << 31)
#endif

View file

@ -0,0 +1,34 @@
#
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
#define EINVAL 22
! Perform a Linux system call.
.define __syscall
__syscall:
lw r2, 0(sp) ! syscall number
addiu r2, r2, 4000 ! MIPS uses non-standard numbers
lw r4, 4(sp)
lw r5, 8(sp)
lw r6, 12(sp)
syscall 0
beq r7, zero, exit ! branch on success
nop
/* The result (in r2) is the errno. */
lui at, ha16[_errno]
sw r2, lo16[_errno] (at)
li r2, -1
exit:
jr ra
nop

View file

@ -0,0 +1,36 @@
acklibrary {
name = "lib",
srcs = {
"./_syscall.s",
"plat/linux/libsys/_exit.c",
"plat/linux/libsys/_hol0.s",
"plat/linux/libsys/close.c",
"plat/linux/libsys/creat.c",
"plat/linux/libsys/execve.c",
"plat/linux/libsys/fork.c",
"plat/linux/libsys/getpid.c",
"plat/linux/libsys/gettimeofday.c",
"plat/linux/libsys/ioctl.c",
"plat/linux/libsys/isatty.c",
"plat/linux/libsys/kill.c",
"plat/linux/libsys/lseek.c",
"plat/linux/libsys/open.c",
"plat/linux/libsys/read.c",
"plat/linux/libsys/sbrk.c",
"plat/linux/libsys/signal.c",
"plat/linux/libsys/sigprocmask.c",
"plat/linux/libsys/unlink.c",
"plat/linux/libsys/wait.c",
"plat/linux/libsys/waitpid.c",
"plat/linux/libsys/write.c",
},
deps = {
"plat/linux/libsys+headers",
"lang/cem/libcc.ansi/headers+headers",
"plat/linuxmips/include+pkg",
},
vars = {
plat = "linuxmips"
}
}

63
util/amisc/axlofflod.1 Normal file
View file

@ -0,0 +1,63 @@
.TH AELFLOD 1 2017-01-18
.SH NAME
aelflod \- ACK ELF loader
.SH SYNOPSIS
.B aelflod
[\-a\fInumber\fP] [\-b] [\-h] [\-l] [\-m\fInumber\fP] [\-v]
inputfile outputfile
.SH DESCRIPTION
.I aelflod
converts an absolute ack.out file into a simple binary memory
dump wrapped up in an ELF executable.
It is suitable for producing executables for operating systems
such as Linux.
.PP
.I aelflod
accepts the following flags:
.TP
.BI \-a number
Set the ABI in the ELF header to \fInumber\fP.
The default value is \fI3\fP for Linux.
.TP
.B \-b
Write a big-endian ELF file.
.TP
.B \-h
Print a help message and exit.
.TP
.B \-l
Write a little-endian ELF file.
This is the default.
.TP
.BI \-m number
Set the machine type in the ELF header to \fInumber\fP.
The default value is \fI3\fP for Intel 386 (i386).
Other values are \fI4\fP for Motorola 68000 (m68k)
and \fI20\fP for PowerPC.
.TP
.BI \-f number
Set the processor flags in the ELF header to \fInumber\fP.
The default value is 0.
.TP
.B \-v
Be verbose.
.PP
The input file must contain exactly four segments: TEXT, ROM,
DATA and BSS, in that order, all occupying contiguous memory.
The file must have all references resolved and be linked to a
fixed address.
The fixed address must be at least 0x54 bytes greater than a
page boundary, in order to make room for the ELF header itself.
.PP
.I aelflod
will write out an ELF header followed by each segment, in order,
ensuring that enough padding is inserted between each segment
to keep the offsets correct.
The created executable will contain just one ELF segment mapped rwx.
.PP
If the input file has symbols, then
.I aelflod
will convert the symbol table to ELF.
The output file has ELF section headers if and only if it has symbols.
.SH "SEE ALSO"
ack.out(5)

890
util/amisc/axlofflod.c Normal file
View file

@ -0,0 +1,890 @@
/*
* Simple tool to produce an utterly basic ELF executable
* from an absolute ack.out file. Suitable for operating
* systems like Linux.
*
* This tool produces an executable with a program header
* only and no section header.
*
* Mostly pinched from the ARM cv (and then rewritten in
* ANSI C). Which, according to the comment, was pinched
* from m68k2; therefore I am merely continuing a time-
* honoured tradition.
*
* (I was 10 when the original for this was checked into
* CVS...)
*
* dtrg, 2006-10-17
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/stat.h>
#include "out.h"
#define ASSERT(x) switch (2) { case 0: case (x): ; }
/* Global settings. */
int bigendian = 0;
int elfabi = 3; /* abi = Linux */
int elfmachine = 3; /* machine = EM_386 */
uint32_t elfflags = 0; /* elf processor flags */
/* Header and section table of an ack object file. */
struct outhead outhead;
struct outsect outsect[S_MAX];
struct outname* outname = NULL;
char* stringarea;
uint32_t ack_off_char;
int nstab = 0; /* S_STB symbol count */
int nsym = 0; /* other symbol count */
int nlocal = 0; /* local symbols */
char* outputfile = NULL; /* Name of output file, or NULL */
char* program; /* Name of current program: argv[0] */
FILE* input; /* Input stream */
FILE* output; /* Output stream */
#define readf(a, b, c) fread((a), (b), (int)(c), input)
#define writef(a, b, c) fwrite((a), (b), (int)(c), output)
/* Contents of an ELF object file. */
#define ELF_HEADER_SIZE 0x34
#define PROGRAM_HEADER_SIZE 0x20
#define PROGRAM_HEADER_COUNT 1
#define SECTION_HEADER_SIZE 0x28
#define STAB_SYMBOL_SIZE 12
#define ELF_SYMBOL_SIZE 16
uint32_t code_offset; /* ELF segment */
uint32_t stab_offset; /* Debugger symbol table */
uint32_t symtab_offset; /* ELF symbol table */
uint32_t strtab_offset; /* String table */
uint32_t shstrtab_offset; /* Section header string table */
uint32_t sh_offset; /* ELF section headers */
int sh_count = 0; /* Number of ELF sections */
int shstrtab_nr = 0; /* Section number of .shstrtab */
int shstrtab_size;
const char elf_le_ident_string[] = {
0x7F, 'E', 'L', 'F'
};
bool verbose = false;
/* Segment numbers understood by aelflod. */
enum {
TEXT = 0,
ROM,
DATA,
BSS,
NUM_SEGMENTS
};
/*
* ELF section numbers count up in the order that we write the ELF
* section headers. If we have no debugger symbols, we will skip
* .stab and .stabstr, then subtract 2 from all later numbers.
*/
enum {
N_UNDEF = 0,
N_TEXT,
N_RODATA,
N_DATA,
N_BSS,
N_STAB,
N_STABSTR,
N_SYMTAB,
N_STRTAB,
N_SHSTRTAB,
NUM_ELF_SECTIONS,
};
const char shstrtab[] =
"\0.text\0.rodata\0.data\0.bss\0.stab\0.stabstr\0"
".symtab\0.strtab\0.shstrtab";
/* Compiler appends one more "\0". */
const int sh_name[] = {
/* Index of each name in shstrtab: */
0, 1, 7, 15, 21, 26, 32,
41, 49, 57,
};
/* Produce an error message and exit. */
void fatal(const char* s, ...)
{
va_list ap;
fprintf(stderr, "%s: ",program) ;
va_start(ap, s);
vfprintf(stderr, s, ap);
va_end(ap);
fprintf(stderr, "\n");
if (outputfile)
unlink(outputfile);
exit(1);
}
/* Calculate the result of a aligned to b (rounding up if necessary).
* b must be a power of two. */
long align(long a, long b)
{
a += b - 1;
return a & ~(b-1);
}
int follows(struct outsect* pa, struct outsect* pb)
{
/* return 1 if pa follows pb */
return (pa->os_base >= align(pb->os_base+pb->os_size, pa->os_lign));
}
/* Convert a symbol's name index from ack.out to ELF. */
uint32_t cvname(struct outname* n)
{
if (n->on_foff) {
/* ack.out: offset from beginning of file
* ELF: index in string table
* the + 1 because we prepend a '\0' */
return n->on_foff - ack_off_char + 1;
} else
return 0; /* no name */
}
/* Convert a symbol's type and binding from ack.out to ELF. */
int cvinfo(struct outname* n)
{
int bind, type;
switch (n->on_type & S_ETC) {
case S_SCT:
type = 3; /* STT_SECTION */
break;
case S_FIL:
case S_MOD:
type = 4; /* STT_FILE */
break;
default:
switch (n->on_type & S_TYP) {
case S_MIN + TEXT:
type = 2; /* STT_FUNC */
break;
case S_MIN + ROM:
case S_MIN + DATA:
case S_MIN + BSS:
case S_MIN + NUM_SEGMENTS:
type = 1; /* STT_OBJECT */
break;
default:
type = 0; /* STT_NOTYPE */
break;
}
break;
}
if (n->on_type & S_EXT)
bind = 1; /* STB_GLOBAL */
else
bind = 0; /* STB_LOCAL */
return (bind << 4) | type;
}
/* Convert a symbol's section index from ack.out to ELF. */
int cvsect(struct outname* n)
{
switch (n->on_type & S_TYP) {
case S_ABS:
return 0xfff1; /* SHN_ABS */
case S_MIN + TEXT:
return N_TEXT;
case S_MIN + ROM:
return N_RODATA;
case S_MIN + DATA:
return N_DATA;
case S_MIN + BSS:
case S_MIN + NUM_SEGMENTS:
return N_BSS;
default:
return N_UNDEF;
}
}
/* Writes a byte. */
void emit8(unsigned char value)
{
writef(&value, 1, 1);
}
/* Writes out 16 and 32 bit words in the appropriate endianness. */
void emit16(unsigned short value)
{
unsigned char buffer[2];
if (bigendian)
{
buffer[0] = (value >> 8) & 0xFF;
buffer[1] = (value >> 0) & 0xFF;
}
else
{
buffer[1] = (value >> 8) & 0xFF;
buffer[0] = (value >> 0) & 0xFF;
}
writef(buffer, 1, sizeof(buffer));
}
void emit32(unsigned long value)
{
unsigned char buffer[4];
if (bigendian)
{
buffer[0] = (value >> 24) & 0xFF;
buffer[1] = (value >> 16) & 0xFF;
buffer[2] = (value >> 8) & 0xFF;
buffer[3] = (value >> 0) & 0xFF;
}
else
{
buffer[3] = (value >> 24) & 0xFF;
buffer[2] = (value >> 16) & 0xFF;
buffer[1] = (value >> 8) & 0xFF;
buffer[0] = (value >> 0) & 0xFF;
}
writef(buffer, 1, sizeof(buffer));
}
/* Copies the contents of a section from the input stream
* to the output stream. */
void emits(struct outsect* section)
{
char buffer[BUFSIZ];
long n = section->os_flen;
while (n > 0)
{
int blocksize = (n > BUFSIZ) ? BUFSIZ : n;
readf(buffer, 1, blocksize);
writef(buffer, 1, blocksize);
n -= blocksize;
}
/* Zero fill any remaining space. */
if (section->os_flen != section->os_size)
{
long n = section->os_size - section->os_flen;
memset(buffer, 0, BUFSIZ);
while (n > 0)
{
int blocksize = (n > BUFSIZ) ? BUFSIZ : n;
writef(buffer, 1, blocksize);
n -= blocksize;
}
}
}
/* Writes out an ELF program header. */
void emitphdr(unsigned long address, unsigned long filesize,
unsigned int memsize, unsigned int alignment, int flags)
{
static unsigned long fileoffset = 0;
emit32(1); /* type = PT_LOAD */
emit32(fileoffset); /* file offset */
emit32(address); /* virtual address */
emit32(0); /* physical address */
emit32(filesize); /* file size */
emit32(memsize); /* memory size */
emit32(flags); /* executable, readable, writable */
emit32(alignment); /* alignment */
fileoffset += filesize;
}
/* The next few functions write parts of the symbol table. */
void emit_stab(void)
{
struct outname* n;
int i;
for (i = 0; i < outhead.oh_nname; i++) {
n = &outname[i];
if (n->on_type & S_STB) {
emit32(cvname(n)); /* name index */
emit8(n->on_type >> 8); /* type */
emit8(cvsect(n)); /* section */
emit16(n->on_desc); /* desc */
emit32(n->on_valu); /* value */
}
}
}
void emit_symtab(void)
{
struct outname* n;
int i, pass;
bool global;
/* ELF .symtab must have local symbols before other symbols.
* We emit locals in pass 0, globals in pass 1. */
for (pass = 0; pass < 2; pass++) {
for (i = 0; i < outhead.oh_nname; i++) {
n = &outname[i];
/* Don't emit .stab symbol in .symtab. */
if (n->on_type & S_STB)
continue;
global = (n->on_type & S_EXT);
if ((pass == 0 && !global) ||
(pass == 1 && global)) {
emit32(cvname(n)); /* name index */
emit32(n->on_valu); /* value */
emit32(0); /* size = unknown */
emit8(cvinfo(n)); /* info */
emit8(0); /* other */
emit16(cvsect(n)); /* section */
}
}
}
}
void emit_strtab(void)
{
/* We prepend a '\0' because ELF uses offset 0 for symbols
* without a name. */
emit8('\0');
writef(stringarea, outhead.oh_nchar, 1);
}
void emit_shstrtab(void)
{
if (nstab) {
writef(shstrtab, sizeof(shstrtab), 1);
} else {
/* Skip .stab and .stabstr */
int i = sh_name[N_SYMTAB];
writef(shstrtab, sh_name[N_STAB], 1);
writef(shstrtab + i, sizeof(shstrtab) - i, 1);
}
}
/* Writes out an ELF section header. */
void emit_sh(int i)
{
uint32_t name, type, flags, addr, offset, size, link, info,
addralign, entsize;
/* If no debugger symbols, skip .stab and .stabstr */
if (nstab == 0 && (i == N_STAB || i == N_STABSTR))
return;
name = sh_name[i];
if (nstab == 0 && i >= N_STAB)
name -= (sh_name[N_SYMTAB] - sh_name[N_STAB]);
switch (i) {
case N_TEXT:
case N_RODATA:
case N_DATA:
case N_STAB:
type = 1; /* SHT_PROGBITS */
break;
case N_BSS:
type = 8; /* SHT_NOBITS */
break;
case N_SYMTAB:
type = 2; /* SHT_SYMTAB */
break;
case N_STABSTR:
case N_STRTAB:
case N_SHSTRTAB:
type = 3; /* SHT_STRTAB */
break;
default:
type = 0; /* SHT_NULL */
break;
}
switch (i) {
case N_TEXT:
flags = 4|2; /* SHF_EXECINSTR|SHF_ALLOC */
addr = outsect[TEXT].os_base;
offset = code_offset;
size = outsect[TEXT].os_size;
addralign = outsect[TEXT].os_lign;
break;
case N_RODATA:
flags = 2; /* SHF_ALLOC */
addr = outsect[ROM].os_base;
offset = code_offset + outsect[TEXT].os_size;
size = outsect[ROM].os_size;
addralign = outsect[ROM].os_lign;
break;
case N_DATA:
flags = 2|1; /* SHF_ALLOC|SHF_WRITE */
addr = outsect[DATA].os_base;
offset = code_offset + outsect[TEXT].os_size +
outsect[ROM].os_size;
size = outsect[DATA].os_size;
addralign = outsect[DATA].os_lign;
break;
case N_BSS:
flags = 2|1; /* SHF_ALLOC|SHF_WRITE */
addr = outsect[BSS].os_base;
offset = code_offset + outsect[TEXT].os_size +
outsect[ROM].os_size + outsect[DATA].os_size;
size = outsect[BSS].os_size;
addralign = outsect[BSS].os_lign;
break;
default:
flags = addr = offset = size = addralign = 0;
break;
}
entsize = 0;
switch (i) {
case N_STAB:
offset = stab_offset;
size = STAB_SYMBOL_SIZE * nstab;
entsize = STAB_SYMBOL_SIZE;
break;
case N_SYMTAB:
offset = symtab_offset;
size = ELF_SYMBOL_SIZE * nsym;
entsize = ELF_SYMBOL_SIZE;
break;
case N_STABSTR:
case N_STRTAB:
/* .stabstr, .strtab share the string area */
offset = strtab_offset;
/* the + 1 because we prepend a '\0' */
size = 1 + outhead.oh_nchar;
break;
case N_SHSTRTAB:
offset = shstrtab_offset;
size = shstrtab_size;
break;
}
/* Link .stab to .stabstr and .symtab to .strtab */
switch (i) {
case N_STAB:
link = N_STABSTR;
break;
case N_SYMTAB:
link = N_STRTAB;
if (nstab == 0)
link -= 2;
break;
default:
link = 0;
break;
}
switch (i) {
case N_SYMTAB:
info = nlocal;
break;
default:
info = 0;
break;
}
emit32(name);
emit32(type);
emit32(flags);
emit32(addr);
emit32(offset);
emit32(size);
emit32(link);
emit32(info);
emit32(addralign);
emit32(entsize);
}
/* Macros from modules/src/object/obj.h */
#define Xchar(ch) ((ch) & 0377)
#define uget2(c) (Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8))
#define get4(c) (uget2(c) | ((long) uget2((c)+2) << 16))
/* Read the ack.out file header. */
int rhead(FILE* f, struct outhead* head)
{
char buf[SZ_HEAD], *c;
if (fread(buf, sizeof(buf), 1, f) != 1)
return 0;
c = buf;
head->oh_magic = uget2(c); c += 2;
head->oh_stamp = uget2(c); c += 2;
head->oh_flags = uget2(c); c += 2;
head->oh_nsect = uget2(c); c += 2;
head->oh_nrelo = uget2(c); c += 2;
head->oh_nname = uget2(c); c += 2;
head->oh_nemit = get4(c); c += 4;
head->oh_nchar = get4(c);
return 1;
}
/* Read an ack.out section header. */
int rsect(FILE* f, struct outsect* sect)
{
char buf[SZ_SECT], *c;
if (fread(buf, sizeof(buf), 1, f) != 1)
return 0;
c = buf;
sect->os_base = get4(c); c += 4;
sect->os_size = get4(c); c += 4;
sect->os_foff = get4(c); c += 4;
sect->os_flen = get4(c); c += 4;
sect->os_lign = get4(c);
return 1 ;
}
/*
* Read the ack.out symbol table and string area. Count symbols.
* Seek back to the current file position.
*/
int rnames(FILE* f)
{
long told;
int i;
/* If no symbols, then do nothing successfully. */
if (outhead.oh_nname == 0)
return 1;
/* Seek to the symbol table. */
told = ftell(f);
if (told == -1)
return 0;
ack_off_char = OFF_CHAR(outhead); /* for cvname() */
if (fseek(f, OFF_NAME(outhead), SEEK_SET))
return 0;
/* Using calloc(a, b) to check if a * b would overflow. */
outname = calloc(outhead.oh_nname, sizeof(outname[0]));
if (outname == NULL)
fatal("out of memory.");
for (i = 0; i < outhead.oh_nname; i++) {
char buf[SZ_NAME], *c;
if (fread(buf, SZ_NAME, 1, f) != 1)
return 0;
c = buf;
outname[i].on_foff = get4(c); c += 4;
outname[i].on_type = uget2(c); c += 2;
outname[i].on_desc = uget2(c); c += 2;
outname[i].on_valu = get4(c);
if (outname[i].on_type & S_STB) {
nstab++;
} else {
nsym++;
if (!(outname[i].on_type & S_EXT))
nlocal++;
}
}
stringarea = malloc(outhead.oh_nchar);
if (stringarea == NULL)
fatal("out of memory.");
if (fread(stringarea, outhead.oh_nchar, 1, f) != 1)
return 0;
if (fseek(f, told, SEEK_SET))
return 0;
return 1;
}
int main(int argc, char* argv[])
{
/* General housecleaning and setup. */
input = stdin;
output = stdout;
program = argv[0];
/* Read in and process any flags. */
while ((argc > 1) && (argv[1][0] == '-'))
{
switch (argv[1][1])
{
case 'a':
elfabi = strtoul(&argv[1][2], NULL, 0);
break;
case 'b':
bigendian = 1;
break;
case 'h':
fprintf(stderr, "%s: Syntax: aelflod [-a<number>] [-b] [-h] [-l]\n\t[-m<number>] [-v] <inputfile> <outputfile>\n",
program);
exit(0);
case 'l':
bigendian = 0;
break;
case 'm':
elfmachine = strtoul(&argv[1][2], NULL, 0);
break;
case 'f':
elfflags = strtoul(&argv[1][2], NULL, 0);
break;
case 'v':
verbose = true;
break;
default:
syntaxerror:
fatal("syntax error --- try -h for help");
}
argv++;
argc--;
}
/* Process the rest of the arguments. */
switch (argc)
{
case 1: /* No parameters --- read from stdin, write to stdout. */
break;
case 3: /* Both input and output files specified. */
output = fopen(argv[2], "wb");
if (!output)
fatal("unable to open output file.");
outputfile = argv[2];
/* fall through */
case 2: /* Input file specified. */
input = fopen(argv[1], "rb");
if (!input)
fatal("unable to open input file.");
break;
default:
goto syntaxerror;
}
/* Read and check the ack.out file header. */
if (!rhead(input,&outhead))
fatal("failed to read file header.");
if (BADMAGIC(outhead))
fatal("this isn't an ack object file.");
if (outhead.oh_nrelo > 0)
fprintf(stderr, "Warning: relocation information present.");
if (!((outhead.oh_nsect == NUM_SEGMENTS) ||
(outhead.oh_nsect == (NUM_SEGMENTS+1))))
fatal("the input file must have %d sections, not %ld.",
NUM_SEGMENTS, outhead.oh_nsect);
/* Read in the section headers. */
{
int i;
for (i=0; i<outhead.oh_nsect; i++)
{
if (!rsect(input, &outsect[i]))
fatal("failed to read section header %d.", i);
}
}
/* Read the symbol table, then seek back to the section data. */
if (!rnames(input))
fatal("failed to read symbol table.");
/* A few checks */
if (outsect[BSS].os_flen != 0)
fatal("the bss space contains initialized data.");
if (!follows(&outsect[BSS], &outsect[DATA]))
fatal("the bss segment must follow the data segment.");
if (!follows(& outsect[ROM], &outsect[TEXT]))
fatal("the rom segment must follow the text segment.");
if (!follows(&outsect[DATA], &outsect[ROM]))
fatal("the data segment must follow the rom segment.") ;
/* Check for an optional end segment (which is otherwise
* ignored). */
if (outhead.oh_nsect == (NUM_SEGMENTS+1))
{
if (!follows(&outsect[NUM_SEGMENTS], &outsect[BSS]))
fatal("end segment must follow bss");
if ( outsect[NUM_SEGMENTS].os_size != 0 )
fatal("end segment must be empty");
}
/* Ensure the base address doesn't overlap the file header. */
code_offset = outsect[TEXT].os_base & 0x1FFF;
if (code_offset < (ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE*PROGRAM_HEADER_COUNT))
fatal("base address too small --- overlaps ELF header");
/* Rationalise the memory sizes. */
outsect[TEXT].os_size = outsect[ROM ].os_base - outsect[TEXT].os_base;
outsect[ROM ].os_size = outsect[DATA].os_base - outsect[ROM ].os_base;
outsect[DATA].os_size = outsect[BSS ].os_base - outsect[DATA].os_base;
outsect[BSS ].os_size = align(outsect[BSS].os_size, outsect[BSS].os_lign);
stab_offset = code_offset + outsect[TEXT].os_size +
outsect[ROM].os_size + outsect[DATA].os_size;
/* If we have symbols, then calculate some offsets. */
if (outhead.oh_nname) {
sh_count = NUM_ELF_SECTIONS;
shstrtab_nr = N_SHSTRTAB;
shstrtab_size = sizeof(shstrtab);
if (nstab == 0) {
/* Skip .stab and .stabstr */
sh_count -= 2;
shstrtab_nr -= 2;
shstrtab_size -=
(sh_name[N_SYMTAB] - sh_name[N_STAB]);
}
symtab_offset = stab_offset + STAB_SYMBOL_SIZE * nstab;
strtab_offset = symtab_offset + ELF_SYMBOL_SIZE * nsym;
/* the + 1 because we prepend a '\0' */
shstrtab_offset = strtab_offset + 1 + outhead.oh_nchar;
sh_offset = shstrtab_offset + shstrtab_size;
}
/* Write out the ELF file header. */
writef(elf_le_ident_string, 4, 1);
emit8(1); /* class = ELFCLASS32 */
emit8(bigendian ? 2 : 1); /* endianness */
emit8(1); /* ELF version */
emit8(elfabi); /* ABI */
emit8(0); /* ABI version */
emit8(0); emit16(0); /* padding... */
emit32(0); /* ...to offset 0x10 */
emit16(2); /* type = ET_EXEC */
emit16(elfmachine); /* machine */
emit32(1); /* ELF version again */
emit32(outsect[TEXT].os_base); /* entry point */
emit32(ELF_HEADER_SIZE); /* program header offset */
emit32(sh_offset); /* section header offset */
emit32(elfflags); /* flags */
emit16(ELF_HEADER_SIZE); /* elf header size */
emit16(PROGRAM_HEADER_SIZE); /* program header entry size */
emit16(1); /* number of program header entries */
emit16(SECTION_HEADER_SIZE); /* section header entry size */
emit16(sh_count); /* number of section header entries */
emit16(shstrtab_nr); /* section header string table index */
/* Write out a single rwx section for the entire program. */
{
uint32_t filelength = stab_offset;
uint32_t memlength = filelength + outsect[BSS].os_size;
emitphdr(outsect[TEXT].os_base & ~0x1FFF,
filelength, memlength, 0, 4|2|1);
}
/* Write padding until the code start. */
if (fseek(output, code_offset, SEEK_SET))
fatal("output seek error");
/* Write out the actual data. */
emits(&outsect[TEXT]);
emits(&outsect[ROM]);
emits(&outsect[DATA]);
/* Write out the symbol table and section headers. */
if (outhead.oh_nname) {
int i;
if (nstab)
emit_stab();
emit_symtab();
emit_strtab();
emit_shstrtab();
for (i = 0; i < NUM_ELF_SECTIONS; i++)
emit_sh(i);
}
if (ferror(output))
fatal("output write error");
if (outputfile)
{
/* mode = 0755 in standard UNIX */
chmod(outputfile, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
}
/* Summarise what we've done. */
if (verbose)
{
uint32_t ss = 0;
printf(" address length\n");
printf(" ehdr : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base & ~0x1FFF, code_offset);
printf(" text : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base, outsect[TEXT].os_size);
printf(" rom : %08"PRIx32" %08"PRIx32"\n", outsect[ROM].os_base, outsect[ROM].os_size);
printf(" data : %08"PRIx32" %08"PRIx32"\n", outsect[DATA].os_base, outsect[DATA].os_size);
printf(" bss : %08"PRIx32" %08"PRIx32"\n", outsect[BSS].os_base, outsect[BSS].os_size);
ss += outsect[TEXT].os_size;
ss += outsect[ROM].os_size;
ss += outsect[DATA].os_size;
ss += outsect[BSS].os_size;
printf("TOTAL : %08"PRIx32"\n", ss);
}
return 0;
}

View file

@ -27,6 +27,7 @@ simpleprogram("ashow")
simpleprogram("asize") simpleprogram("asize")
simpleprogram("aslod") simpleprogram("aslod")
simpleprogram("astrip") simpleprogram("astrip")
simpleprogram("axlofflod")
installable { installable {
name = "pkg", name = "pkg",