Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
d0p1 🏳️⚧️ | 7cc3f65a58 |
|
@ -6,6 +6,7 @@ vars.ackcflags = {
|
|||
}
|
||||
vars.ackldflags = {}
|
||||
vars.plats = {
|
||||
"mintia",
|
||||
"cpm",
|
||||
"linux386",
|
||||
"linux68k",
|
||||
|
@ -23,9 +24,7 @@ vars.plats = {
|
|||
vars.plats_with_tests = {
|
||||
"cpm",
|
||||
"linux68k",
|
||||
--"linux386",
|
||||
"linuxppc",
|
||||
--"linuxmips",
|
||||
"pc86",
|
||||
}
|
||||
|
||||
|
|
19
mach/xr17032/as/build.lua
Normal file
19
mach/xr17032/as/build.lua
Normal 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",
|
||||
}
|
||||
}
|
||||
|
319
mach/xr17032/as/instructions.dat
Normal file
319
mach/xr17032/as/instructions.dat
Normal 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
26
mach/xr17032/as/mach0.c
Normal 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
3
mach/xr17032/as/mach1.c
Normal 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
21
mach/xr17032/as/mach2.c
Normal 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
118
mach/xr17032/as/mach3.c
Normal 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
212
mach/xr17032/as/mach4.c
Normal 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
0
mach/xr17032/as/mach5.c
Normal file
192
mach/xr17032/as/mktables.lua
Executable file
192
mach/xr17032/as/mktables.lua
Executable 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
47
mach/xr17032/libem/aar4.s
Normal 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
30
mach/xr17032/libem/and.s
Normal 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
31
mach/xr17032/libem/bls4.s
Normal 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
|
43
mach/xr17032/libem/build.lua
Normal file
43
mach/xr17032/libem/build.lua
Normal 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
|
36
mach/xr17032/libem/c_ud_i.s
Normal file
36
mach/xr17032/libem/c_ud_i.s
Normal 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
|
||||
|
38
mach/xr17032/libem/c_uf_i.s
Normal file
38
mach/xr17032/libem/c_uf_i.s
Normal 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
|
||||
|
25
mach/xr17032/libem/c_ui_d.s
Normal file
25
mach/xr17032/libem/c_ui_d.s
Normal 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
|
26
mach/xr17032/libem/c_ui_f.s
Normal file
26
mach/xr17032/libem/c_ui_f.s
Normal 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
35
mach/xr17032/libem/cms.s
Normal 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
28
mach/xr17032/libem/com.s
Normal 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
|
||||
|
39
mach/xr17032/libem/compareul.s
Normal file
39
mach/xr17032/libem/compareul.s
Normal 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
42
mach/xr17032/libem/csa.s
Normal 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
47
mach/xr17032/libem/csb.s
Normal 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
28
mach/xr17032/libem/dus4.s
Normal 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
31
mach/xr17032/libem/exg.s
Normal 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
56
mach/xr17032/libem/fef8.s
Normal 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
69
mach/xr17032/libem/fif8.s
Normal 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
32
mach/xr17032/libem/inn.s
Normal 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
30
mach/xr17032/libem/ior.s
Normal 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
23
mach/xr17032/libem/lar4.s
Normal 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
55
mach/xr17032/libem/los4.s
Normal 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
35
mach/xr17032/libem/rck.s
Normal 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
24
mach/xr17032/libem/sar4.s
Normal 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
39
mach/xr17032/libem/set.s
Normal 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
57
mach/xr17032/libem/sts4.s
Normal 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
65
mach/xr17032/libem/trp.s
Normal 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
30
mach/xr17032/libem/xor.s
Normal 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
25
mach/xr17032/libem/zer.s
Normal 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
|
||||
|
13
mach/xr17032/libend/build.lua
Normal file
13
mach/xr17032/libend/build.lua
Normal 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
|
||||
|
9
mach/xr17032/libend/edata.s
Normal file
9
mach/xr17032/libend/edata.s
Normal file
|
@ -0,0 +1,9 @@
|
|||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
.define _edata
|
||||
.sect .data
|
||||
.align 4
|
||||
.sect .data
|
||||
_edata:
|
24
mach/xr17032/libend/em_end.s
Normal file
24
mach/xr17032/libend/em_end.s
Normal 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:
|
7
mach/xr17032/libend/end.s
Normal file
7
mach/xr17032/libend/end.s
Normal 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:
|
9
mach/xr17032/libend/etext.s
Normal file
9
mach/xr17032/libend/etext.s
Normal file
|
@ -0,0 +1,9 @@
|
|||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
.define _etext
|
||||
.sect .text
|
||||
.align 4
|
||||
.sect .text
|
||||
_etext:
|
7
mach/xr17032/mcg/build.lua
Normal file
7
mach/xr17032/mcg/build.lua
Normal file
|
@ -0,0 +1,7 @@
|
|||
bundle {
|
||||
name = "headers",
|
||||
srcs = {
|
||||
"./platform.c",
|
||||
}
|
||||
}
|
||||
|
309
mach/xr17032/mcg/platform.c
Normal file
309
mach/xr17032/mcg/platform.c
Normal 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
1018
mach/xr17032/mcg/table
Normal file
File diff suppressed because it is too large
Load diff
51
mach/xr17032/top/table
Normal file
51
mach/xr17032/top/table
Normal 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
37
plat/mintia/README
Normal 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
58
plat/mintia/boot.s
Normal 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
25
plat/mintia/build-pkg.lua
Normal 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",
|
||||
}
|
||||
}
|
||||
|
29
plat/mintia/build-tools.lua
Normal file
29
plat/mintia/build-tools.lua
Normal 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
83
plat/mintia/descr
Normal 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
|
19
plat/mintia/include/ack/fcntl.h
Normal file
19
plat/mintia/include/ack/fcntl.h
Normal 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
|
12
plat/mintia/include/ack/plat.h
Normal file
12
plat/mintia/include/ack/plat.h
Normal 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
|
74
plat/mintia/include/ack/signal.h
Normal file
74
plat/mintia/include/ack/signal.h
Normal 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
|
28
plat/mintia/include/build.lua
Normal file
28
plat/mintia/include/build.lua
Normal 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
|
||||
}
|
||||
|
||||
|
76
plat/mintia/include/sys/ioctl.h
Normal file
76
plat/mintia/include/sys/ioctl.h
Normal 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
|
9
plat/mintia/include/sys/types.h
Normal file
9
plat/mintia/include/sys/types.h
Normal 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
|
19
plat/mintia/include/sys/wait.h
Normal file
19
plat/mintia/include/sys/wait.h
Normal 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
|
34
plat/mintia/libsys/_syscall.s
Normal file
34
plat/mintia/libsys/_syscall.s
Normal 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
|
||||
|
36
plat/mintia/libsys/build.lua
Normal file
36
plat/mintia/libsys/build.lua
Normal 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
63
util/amisc/axlofflod.1
Normal 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
890
util/amisc/axlofflod.c
Normal 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;
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ simpleprogram("ashow")
|
|||
simpleprogram("asize")
|
||||
simpleprogram("aslod")
|
||||
simpleprogram("astrip")
|
||||
simpleprogram("axlofflod")
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
|
|
Loading…
Reference in a new issue