From 4741ed8e14ebea48b25b8bf3b20dbacebaffac3d Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 1 Sep 2018 19:35:31 +0200 Subject: [PATCH 01/79] Add a completely non-tested table-based MIPS assembler. --- build.lua | 1 + h/out.h | 3 +- mach/mips/as/build.lua | 6 + mach/mips/as/instructions.dat | 152 +++++++++++++++++++++++++ mach/mips/as/mach0.c | 31 +++++ mach/mips/as/mach1.c | 12 ++ mach/mips/as/mach2.c | 12 ++ mach/mips/as/mach3.c | 84 ++++++++++++++ mach/mips/as/mach4.c | 88 +++++++++++++++ mach/mips/as/mach5.c | 0 mach/mips/as/mktables.lua | 188 +++++++++++++++++++++++++++++++ mach/proto/as/build.lua | 7 +- mach/proto/as/comm0.h | 1 + plat/linuxmips/build-pkg.lua | 25 ++++ plat/linuxmips/build-tools.lua | 30 +++++ plat/linuxmips/descr | 87 ++++++++++++++ plat/linuxmips/include/build.lua | 4 + 17 files changed, 728 insertions(+), 3 deletions(-) create mode 100644 mach/mips/as/build.lua create mode 100644 mach/mips/as/instructions.dat create mode 100644 mach/mips/as/mach0.c create mode 100644 mach/mips/as/mach1.c create mode 100644 mach/mips/as/mach2.c create mode 100644 mach/mips/as/mach3.c create mode 100644 mach/mips/as/mach4.c create mode 100644 mach/mips/as/mach5.c create mode 100755 mach/mips/as/mktables.lua create mode 100644 plat/linuxmips/build-pkg.lua create mode 100644 plat/linuxmips/build-tools.lua create mode 100644 plat/linuxmips/descr create mode 100644 plat/linuxmips/include/build.lua diff --git a/build.lua b/build.lua index 9bce99f90..df51d0d13 100644 --- a/build.lua +++ b/build.lua @@ -10,6 +10,7 @@ vars.plats = { "linux386", "linux68k", "linuxppc", + "linuxmips", "osx386", "osxppc", -- --"qemuppc", diff --git a/h/out.h b/h/out.h index 9cc791ab2..17a4c908c 100644 --- a/h/out.h +++ b/h/out.h @@ -67,7 +67,8 @@ struct outname { #define RELO4 3 /* 4 bytes */ #define RELOPPC 4 /* PowerPC 26-bit address */ #define RELOPPC_LIS 5 /* PowerPC lis */ -#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ +#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ +#define RELOMIPS 7 /* MIPS */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ diff --git a/mach/mips/as/build.lua b/mach/mips/as/build.lua new file mode 100644 index 000000000..8732fdf14 --- /dev/null +++ b/mach/mips/as/build.lua @@ -0,0 +1,6 @@ +normalrule { + name = "astables", + outleaves = {"definitions.y", "tokens.y", "rules.y"}, + ins = {"./mktables.lua", "./instructions.dat"}, + commands = {"$(LUA) %{ins[1]} %{outs} < %{ins[2]}"} +} diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat new file mode 100644 index 000000000..af5209e5b --- /dev/null +++ b/mach/mips/as/instructions.dat @@ -0,0 +1,152 @@ +# Syntax: +# : 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/). + +00000000000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr +001000 "addi" RT=gpr ',' RT=gpr ',' IMM=e16 +001001 "addiu" RT=gpr ',' RT=gpr ',' IMM=e16 +00000000000100001 "addu" RD=gpr ',' RS=gpr ',' RT=gpr +00000000000100100 "and" RD=gpr ',' RS=gpr ',' RT=gpr +001100 "andi" RT=gpr ',' RS=gpr ',' IMM=e16 +0001000000000000 "b" OFF=offset16 +0000010000010001 "bal" OFF=offset16 +000100 "beq" RS=gpr ',' RT=gpr ',' OFF=offset16 +010100 "beql" RS=gpr ',' RT=gpr ',' OFF=offset16 +00000100001 "bgez" RS=gpr ',' OFF=offset16 +00000110001 "bgezal" RS=gpr ',' OFF=offset16 +00000110011 "bgezall" RS=gpr ',' OFF=offset16 +00000100011 "bgezl" RS=gpr ',' OFF=offset16 +00011100000 "bgtz" RS=gpr ',' OFF=offset16 +01011100000 "bgtzl" RS=gpr ',' OFF=offset16 +00011000000 "blez" RS=gpr ',' OFF=offset16 +01011000000 "blezl" RS=gpr ',' OFF=offset16 +00000100000 "bltz" RS=gpr ',' OFF=offset16 +00000110000 "bltzal" RS=gpr ',' OFF=offset16 +00000110010 "bltzall" RS=gpr ',' OFF=offset16 +00000100010 "bltzl" RS=gpr ',' OFF=offset16 +000101 "bne" RS=gpr ',' RT=gpr ',' OFF=offset16 +010101 "bnel" RS=gpr ',' RT=gpr ',' OFF=offset16 +101111 "cache" OP=u5 ',' OFF=e16 '(' RS=gpr ')' +0111110011011 "cachee" OP=u5 ',' OFF=e9 '(' RS=gpr ')' +01110000000100001 "clo" RD=RT=gpr ',' RS=gpr +01110000000100000 "clz" RD=RT=gpr ',' RS=gpr +01000010000000000000000000011111 "deret" +010000010110110000000000000 "di" RT=gpr +01000001011000000110000000000000 "di" +0000000000000000011010 "div" RS=gpr ',' RT=gpr +0000000000000000011011 "divu" RS=gpr ',' RT=gpr +00000000000000000000000011000000 "ehb" +010000010110110000000100000 "ei" RT=gpr +01000001011000000110000000100000 "ei" +011111000000 "ext" RT=gpr ',' RS=gpr ',' extmsblsb +011111000100 "ins" RT=gpr ',' RS=gpr ',' insmsblsb +000010 "j" ABS=abs26 +000011 "jal" ABS=abs26 +0000000000000000001001 "jalr" RD=gpr ',' RS=gpr +000000000001111100000001001 "jalr" RS=gpr +0000000000010000001001 "jalr.hb" RD=gpr ',' RS=gpr +000000000001111110000001001 "jalr.hb" RS=gpr +011101 "jalx" ABS=abs26 +000000000000000000000001000 "jr" RS=gpr +000000000000000010000001000 "jr.hb" RS=gpr +100000 "lb" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110101100 "lbe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +100100 "lbu" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110101000 "lbue" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +100001 "lh" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110101101 "lhe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +100101 "lhu" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110101001 "lhue" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +110000 "ll" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110101110 "lle" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +00111100000 "lui" RT=gpr ',' IMM=e16 +100011 "lw" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110101111 "lwe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +100010 "lwl" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110011001 "lwle" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +100110 "lwr" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110011010 "lwre" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +0111000000000000000000 "madd" RS=gpr ',' RT=gpr +0111000000000000000001 "maddu" RS=gpr ',' RT=gpr +000000000000000000000010000 "mfhi" RD=gpr +000000000000000000000010010 "mflo" RD=gpr +00000000000001011 "movn" RD=gpr ',' RS=gpr ',' RT=gpr +00000000000001010 "movz" RD=gpr ',' RS=gpr ',' RT=gpr +0111000000000000000100 "msub" RS=gpr ',' RT=gpr +0111000000000000000101 "msubu" RS=gpr ',' RT=gpr +000000000000000000000010001 "mthi" RS=gpr +000000000000000000000010011 "mtlo" RS=gpr +01110000000000010 "mul" RD=gpr ',' RS=gpr ',' RT=gpr +0000000000000000011000 "mult" RS=gpr ',' RT=gpr +0000000000000000000001 "multu" RS=gpr ',' RT=gpr +00000000000000000000000000000000 "nop" +00000000000100111 "nor" RD=gpr ',' RS=gpr ',' RT=gpr +00000000000100101 "or" RD=gpr ',' RS=gpr ',' RT=gpr +001101 "ori" RS=gpr ',' RT=gpr +00000000000000000000000101000000 "pause" +110011 "pref" H=u5 ',' IMM=e16 '(' RS=gpr ')' +0111110100011 "prefe" H=u5 ',' IMM=e9 '(' RS=gpr ')' +01001100000001111 "prefx" H=u5 ',' RT=gpr '(' RS=gpr ')' +0111110000000000111011 "rdhwr" RT=gpr ',' RD=gpr +0100000101000000000000 "rdpgpr" RD=gpr ',' RT=gpr +00000000001000010 "rotr" RD=gpr ',' RT=gpr ',' SA=u5 +00000000001000110 "rotrv" RD=gpr ',' RT=gpr ',' RS=gpr +101000 "sb" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110011100 "sbe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +111000 "sc" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110011110 "sce" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +011100111111 "sdbbp" CODE=u20 +0111110000010000100000 "seb" RD=gpr ',' RT=gpr +0111110000011000100000 "seh" RD=gpr ',' RT=gpr +101001 "sh" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110011101 "she" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +00000000000000000 "sll" RD=gpr ',' RT=gpr ',' SA=u5 +00000000000000100 "sllv" RD=gpr ',' RT=gpr ',' RS=gpr +00000000000101010 "slt" RD=gpr ',' RS=gpr ',' RT=gpr +001010 "slti" RT=gpr ',' RS=gpr ',' IMM=e16 +001011 "sltiu" RT=gpr ',' RS=gpr ',' IMM=e16 +00000000000101011 "sltu" RD=gpr ',' RS=gpr ',' RT=gpr +00000000000000011 "sra" RD=gpr ',' RT=gpr ',' SA=u5 +00000000000000111 "srav" RD=gpr ',' RT=gpr ',' RS=gpr +00000000000000010 "srl" RD=gpr ',' RT=gpr ',' SA=u5 +00000000000000110 "srlv" RD=gpr ',' RT=gpr ',' RS=gpr +00000000000000000000000001000000 "ssnop" +00000000000100010 "sub" RD=gpr ',' RS=gpr ',' RT=gpr +00000000000100011 "subu" RD=gpr ',' RS=gpr ',' RT=gpr +101011 "sw" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110011111 "swe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +101010 "swl" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110010001 "swle" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +101110 "swr" RT=gpr ',' IMM=e16 '(' RS=gpr ')' +0111110100010 "swre" RT=gpr ',' IMM=e9 '(' RS=gpr ')' +00000111111 "synci" IMM=e16 '(' RS=gpr ')' +000000001100 "syscall" CODE=u20 +0000000000000000110100 "teq" RS=gpr ',' RT=gpr +00000101100 "teqi" RS=gpr ',' IMM=e16 +0000000000000000110000 "tge" RS=gpr ',' RT=gpr +00000101000 "tgei" RS=gpr ',' IMM=e16 +00000101001 "tgeiu" RS=gpr ',' IMM=e16 +0000000000000000110001 "tgeu" RS=gpr ',' RT=gpr +01000010000000000000000000000011 "tlbinv" +01000010000000000000000000000100 "tlbinvf" +01000010000000000000000000001000 "tlbp" +01000010000000000000000000000001 "tlbr" +01000010000000000000000000000010 "tlbwi" +01000010000000000000000000000110 "tlbwr" +0000000000000000110010 "tlt" RS=gpr ',' RT=gpr +00000101010 "tlti" RS=gpr ',' IMM=e16 +00000101011 "tltiu" RS=gpr ',' IMM=e16 +0000000000000000110011 "tltu" RS=gpr ',' RT=gpr +0000000000000000110110 "tne" RS=gpr ',' RT=gpr +00000101110 "tnei" RS=gpr ',' IMM=e16 +01000010000000000000000000100000 "wait" +0100000111000000000000 "wrpgpr" RD=gpr ',' RT=gpr +0111110000000010100000 "wsbh" RD=gpr ',' RT=gpr +00000000000100110 "xor" RD=gpr ',' RS=gpr ',' RT=gpr +001110 "xori" RT=gpr ',' RS=gpr ',' IMM=e16 + diff --git a/mach/mips/as/mach0.c b/mach/mips/as/mach0.c new file mode 100644 index 000000000..f390bccf5 --- /dev/null +++ b/mach/mips/as/mach0.c @@ -0,0 +1,31 @@ +/* + * $Source$ + * $State$ + */ + +#define THREE_PASS /* branch and offset optimization */ +#define BYTES_REVERSED /* high order byte has lowest address */ +#define WORDS_REVERSED /* high order word has lowest address */ +#define LISTING /* enable listing facilities */ +#define RELOCATION /* generate relocatable code */ +#define DEBUG 0 + +#undef valu_t +#define valu_t int32_t + +#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 (RELBR | RELWR) diff --git a/mach/mips/as/mach1.c b/mach/mips/as/mach1.c new file mode 100644 index 000000000..50f799684 --- /dev/null +++ b/mach/mips/as/mach1.c @@ -0,0 +1,12 @@ +/* + * $Source$ + * $State$ + */ + +/* + * Do not #include anything here. Do it in mach/proto/as/comm0.h + */ + +void no_hl(void); +word_t eval_hl(struct expr_t* expr, int token); +void emit_hl(word_t in); diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c new file mode 100644 index 000000000..2672c0b9a --- /dev/null +++ b/mach/mips/as/mach2.c @@ -0,0 +1,12 @@ +%token GPR +%token FPR + +%type gpr +%type e16 e9 +%type u20 u5 +%type abs26 offset16 + +%type extmsblsb insmsblsb + +#include "definitions.y" + diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c new file mode 100644 index 000000000..d6da5e016 --- /dev/null +++ b/mach/mips/as/mach3.c @@ -0,0 +1,84 @@ +/* + * $Source$ + * $State$ + */ + +/* Integer registers */ + +0, GPR, 0, "$0", +0, GPR, 0, "$zero", +0, GPR, 1, "$1", +0, GPR, 1, "$at", +0, GPR, 2, "$2", +0, GPR, 3, "$3", +0, GPR, 4, "$4", +0, GPR, 5, "$5", +0, GPR, 6, "$6", +0, GPR, 7, "$7", +0, GPR, 8, "$8", +0, GPR, 9, "$9", +0, GPR, 10, "$10", +0, GPR, 11, "$11", +0, GPR, 12, "$12", +0, GPR, 13, "$13", +0, GPR, 14, "$14", +0, GPR, 15, "$15", +0, GPR, 16, "$16", +0, GPR, 17, "$17", +0, GPR, 18, "$18", +0, GPR, 19, "$19", +0, GPR, 20, "$20", +0, GPR, 21, "$21", +0, GPR, 22, "$22", +0, GPR, 23, "$23", +0, GPR, 24, "$24", +0, GPR, 25, "$25", +0, GPR, 26, "$26", +0, GPR, 27, "$27", +0, GPR, 28, "$28", +0, GPR, 28, "$gp", +0, GPR, 29, "$29", +0, GPR, 29, "$sp", +0, GPR, 30, "$30", +0, GPR, 30, "$fp", +0, GPR, 31, "$31", +0, GPR, 31, "$a", + +/* 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", + +#include "tokens.y" + + diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c new file mode 100644 index 000000000..2185fb245 --- /dev/null +++ b/mach/mips/as/mach4.c @@ -0,0 +1,88 @@ +#include "rules.y" + +gpr: GPR + +e16 + : absexp + { + /* 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; + } + ; + +u20 + : absexp + { + if (($1 < 0) || ($1 > 0xfffff)) + serror("20-bit unsigned value out of range"); + $$ = $1; + } + ; + + +u5 + : absexp + { + if (($1 < 0) || ($1 > 0x1f)) + serror("5-bit unsigned value out of range"); + $$ = $1; + } + ; + +offset16 + : expr + { + int dist = $1.val - DOTVAL; + fit(fitx(dist, 18)); + + if (dist & 0x3) + serror("jump targets must be 4-aligned"); + + newrelo($1.typ, RELOMIPS | RELPC | FIXUPFLAGS); + $$ = (dist >> 2) & 0x0000ffff; + } + ; + +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) & 0x03fffffd; + } + ; + +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; + } + ; \ No newline at end of file diff --git a/mach/mips/as/mach5.c b/mach/mips/as/mach5.c new file mode 100644 index 000000000..e69de29bb diff --git a/mach/mips/as/mktables.lua b/mach/mips/as/mktables.lua new file mode 100755 index 000000000..cb8565fc4 --- /dev/null +++ b/mach/mips/as/mktables.lua @@ -0,0 +1,188 @@ +local args = {...} + +local wordscount = 0 +local words = {} +local insns = {} + +local function addword(word) + local n = words[word] + if not n then + words[word] = wordscount + wordscount = wordscount + 1 + n = wordscount + end + return n +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 ~= "" 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], "w") +for word, value in pairs(words) do + definitionsfp:write("%token OP_", tostring(value), " /* ", word, " */\n") +end +definitionsfp:close() + +local tokensfp = io.open(args[2], "w") +for word, value in pairs(words) do + tokensfp:write("0, OP_", tostring(value), ", 0, \"", word, "\",\n") +end +tokensfp:close() + +local rulesfp = io.open(args[3], "w") +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_", tostring(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() + diff --git a/mach/proto/as/build.lua b/mach/proto/as/build.lua index 9782b4b4b..52536cbbf 100644 --- a/mach/proto/as/build.lua +++ b/mach/proto/as/build.lua @@ -2,7 +2,8 @@ include("first/yacc.lua") definerule("build_as", { - arch = { type="string" } + arch = { type="string" }, + deps = { type="targets", default={} }, }, function(e) -- Remember this is executed from the caller's directory; local @@ -25,6 +26,7 @@ definerule("build_as", "mach/proto/as/comm1.h", "h+emheaders", archlib, + e.deps, }, } @@ -43,7 +45,8 @@ definerule("build_as", "h+emheaders", "modules/src/object+lib", archlib, - yaccfiles + yaccfiles, + e.deps } } end diff --git a/mach/proto/as/comm0.h b/mach/proto/as/comm0.h index 60fb172b4..03b48f75e 100644 --- a/mach/proto/as/comm0.h +++ b/mach/proto/as/comm0.h @@ -22,6 +22,7 @@ _include #include #include #include +#include #endif /* ========== ON/OFF options (use #define in mach0.c) ========== */ diff --git a/plat/linuxmips/build-pkg.lua b/plat/linuxmips/build-pkg.lua new file mode 100644 index 000000000..6aec05157 --- /dev/null +++ b/plat/linuxmips/build-pkg.lua @@ -0,0 +1,25 @@ +include("plat/build.lua") + +--ackfile { +-- name = "boot", +-- srcs = { "./boot.s" }, +-- vars = { plat = "linuxppc" } +--} +-- +--build_plat_libs { +-- name = "libs", +-- arch = "powerpc", +-- plat = "linuxppc", +--} + +installable { + name = "pkg", + map = { + "+tools", +-- "+libs", + "./include+pkg", +-- ["$(PLATIND)/linuxppc/boot.o"] = "+boot", +-- ["$(PLATIND)/linuxppc/libsys.a"] = "./libsys+lib", + } +} + diff --git a/plat/linuxmips/build-tools.lua b/plat/linuxmips/build-tools.lua new file mode 100644 index 000000000..04a385d47 --- /dev/null +++ b/plat/linuxmips/build-tools.lua @@ -0,0 +1,30 @@ +include("plat/build.lua") + +build_as { + name = "as", + arch = "mips", + deps = { "mach/mips/as+astables" } +} + +--build_mcg { +-- name = "mcg", +-- arch = "powerpc", +--} +-- +--build_top { +-- name = "top", +-- arch = "powerpc", +--} + +return installable { + name = "tools", + map = { + ["$(PLATDEP)/linuxmips/as"] = "+as", + --["$(PLATDEP)/linuxppc/ncg"] = "+ncg", + --["$(PLATDEP)/linuxppc/mcg"] = "+mcg", + --["$(PLATDEP)/linuxppc/top"] = "+top", + ["$(PLATIND)/descr/linuxmips"] = "./descr", + "util/amisc+aelflod-pkg", + "util/opt+pkg", + } +} diff --git a/plat/linuxmips/descr b/plat/linuxmips/descr new file mode 100644 index 000000000..7ddaf941b --- /dev/null +++ b/plat/linuxmips/descr @@ -0,0 +1,87 @@ +# 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=mips +var PLATFORM=linuxmips +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__unix +var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x00400054 +var MACHOPT_F=-m2 +var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr + +# Override the setting in fe so that files compiled for linuxppc can see +# the platform-specific headers. + +var C_INCLUDES=-I{EM}/share/ack/linux/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/{PLATFORM}/ncg + 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/aelflod + args -m20 -b < > + outfile linuxppc.exe +end diff --git a/plat/linuxmips/include/build.lua b/plat/linuxmips/include/build.lua new file mode 100644 index 000000000..747e52089 --- /dev/null +++ b/plat/linuxmips/include/build.lua @@ -0,0 +1,4 @@ +installable { + name = "pkg", + map = { "plat/linux/include+pkg" } +} From a023fd85915df5e9959641e1b2ad8816b3cae0d6 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 2 Sep 2018 18:55:44 +0200 Subject: [PATCH 02/79] Better error reporting for unterminated strings. --- util/mcgg/scan.l | 1 + 1 file changed, 1 insertion(+) diff --git a/util/mcgg/scan.l b/util/mcgg/scan.l index 447a7d395..9d06d5b38 100644 --- a/util/mcgg/scan.l +++ b/util/mcgg/scan.l @@ -30,6 +30,7 @@ static int braces = 0; yylval.string = strdup(yytext); return QFRAGMENT; } +. yyerror("bad string input '%s' at line %d\n", yytext, yylineno); "/*" BEGIN(COMMENT); "*/" BEGIN(INITIAL); From 1d6ecddcf48991949a064e7cdfad8175f42fca71 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 2 Sep 2018 18:57:25 +0200 Subject: [PATCH 03/79] The MIPS backend is still full of holes, and cut-and-pasted PowerPC code, but is beginning to look like an actual code generator. --- mach/mips/as/instructions.dat | 6 + mach/mips/as/mach3.c | 145 ++++----- mach/mips/mcg/platform.c | 331 +++++++++++++++++++ mach/mips/mcg/table | 566 +++++++++++++++++++++++++++++++++ mach/mips/top/table | 20 ++ plat/linuxmips/build-tools.lua | 23 +- plat/linuxmips/descr | 6 +- 7 files changed, 1007 insertions(+), 90 deletions(-) create mode 100644 mach/mips/mcg/platform.c create mode 100644 mach/mips/mcg/table create mode 100644 mach/mips/top/table diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index af5209e5b..1f7aae7f8 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -7,6 +7,12 @@ # only. It's based on the MIPS32 Instruction Set v5.04 manual (available from # https://www.mips.com/products/architectures/mips32-2/). +# Useful pseudoops. + +0000000000000000100000 "move" RD=gpr ',' RS=gpr + +# Core ALU instructions. + 00000000000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr 001000 "addi" RT=gpr ',' RT=gpr ',' IMM=e16 001001 "addiu" RT=gpr ',' RT=gpr ',' IMM=e16 diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index d6da5e016..0de4b37be 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -1,83 +1,78 @@ -/* - * $Source$ - * $State$ - */ - /* Integer registers */ -0, GPR, 0, "$0", -0, GPR, 0, "$zero", -0, GPR, 1, "$1", -0, GPR, 1, "$at", -0, GPR, 2, "$2", -0, GPR, 3, "$3", -0, GPR, 4, "$4", -0, GPR, 5, "$5", -0, GPR, 6, "$6", -0, GPR, 7, "$7", -0, GPR, 8, "$8", -0, GPR, 9, "$9", -0, GPR, 10, "$10", -0, GPR, 11, "$11", -0, GPR, 12, "$12", -0, GPR, 13, "$13", -0, GPR, 14, "$14", -0, GPR, 15, "$15", -0, GPR, 16, "$16", -0, GPR, 17, "$17", -0, GPR, 18, "$18", -0, GPR, 19, "$19", -0, GPR, 20, "$20", -0, GPR, 21, "$21", -0, GPR, 22, "$22", -0, GPR, 23, "$23", -0, GPR, 24, "$24", -0, GPR, 25, "$25", -0, GPR, 26, "$26", -0, GPR, 27, "$27", -0, GPR, 28, "$28", -0, GPR, 28, "$gp", -0, GPR, 29, "$29", -0, GPR, 29, "$sp", -0, GPR, 30, "$30", -0, GPR, 30, "$fp", -0, GPR, 31, "$31", -0, GPR, 31, "$a", +0, GPR, 0, "r0", +0, GPR, 0, "zero", +0, GPR, 1, "r1", +0, GPR, 1, "at", +0, GPR, 2, "r2", +0, GPR, 3, "r3", +0, GPR, 4, "r4", +0, GPR, 5, "r5", +0, GPR, 6, "r6", +0, GPR, 7, "r7", +0, GPR, 8, "r8", +0, GPR, 9, "r9", +0, GPR, 10, "r10", +0, GPR, 11, "r11", +0, GPR, 12, "r12", +0, GPR, 13, "r13", +0, GPR, 14, "r14", +0, GPR, 15, "r15", +0, GPR, 16, "r16", +0, GPR, 17, "r17", +0, GPR, 18, "r18", +0, GPR, 19, "r19", +0, GPR, 20, "r20", +0, GPR, 21, "r21", +0, GPR, 22, "r22", +0, GPR, 23, "r23", +0, GPR, 24, "r24", +0, GPR, 25, "r25", +0, GPR, 26, "r26", +0, GPR, 27, "r27", +0, GPR, 28, "r28", +0, GPR, 28, "gp", +0, GPR, 29, "r29", +0, GPR, 29, "sp", +0, GPR, 30, "r30", +0, GPR, 30, "fp", +0, GPR, 31, "r31", +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, 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", #include "tokens.y" diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c new file mode 100644 index 000000000..23b01f13e --- /dev/null +++ b/mach/mips/mcg/platform.c @@ -0,0 +1,331 @@ +#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; iusedregs.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; iusedregs.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; iattrs & burm_int_ATTR) + hop_add_insel(hop, "sw %H, %d(fp)", + hreg, current_proc->fp_to_rb + hreg->offset); + else if (hreg->attrs & burm_float_ATTR) + hop_add_insel(hop, "swc1 %H, %d(fp)", + hreg, current_proc->fp_to_rb + hreg->offset); + } + return hop; +} + +struct hop* platform_epilogue(void) +{ + struct hop* hop = new_hop(current_proc->exit, NULL); + int i; + + for (i=0; iattrs & burm_int_ATTR) + hop_add_insel(hop, "lw %H, %d(fp)", + hreg, current_proc->fp_to_rb + hreg->offset); + else if (hreg->attrs & burm_float_ATTR) + hop_add_insel(hop, "lwc1 %H, %d(fp)", + hreg, current_proc->fp_to_rb + hreg->offset); + } + + 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, "move fp, at"); + hop_add_insel(hop, "jr ra"); + + return hop; +} + +struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest) +{ + struct hop* hop = new_hop(bb, NULL); + + if ((src->attrs & TYPE_ATTRS) != (dest->attrs & TYPE_ATTRS)) + { + assert(!src->is_stacked); + assert(!dest->is_stacked); + + switch (src->attrs & TYPE_ATTRS) + { + case burm_int_ATTR: + hop_add_insel(hop, "stwu %H, -4(sp)", src); + break; + + case burm_long_ATTR: + hop_add_insel(hop, "stwu %0H, -4(sp)", src); + hop_add_insel(hop, "stwu %1H, -4(sp)", src); + break; + + case burm_float_ATTR: + hop_add_insel(hop, "stfsu %H, -4(sp)", src); + break; + + case burm_double_ATTR: + hop_add_insel(hop, "stfdu %H, -8(sp)", src); + break; + + default: + goto nomove; + } + + switch (dest->attrs & TYPE_ATTRS) + { + case burm_int_ATTR: + hop_add_insel(hop, "lwz %H, 0(sp)", dest); + break; + + case burm_long_ATTR: + hop_add_insel(hop, "lwz %0H, 4(sp)", dest); + hop_add_insel(hop, "lwz %1H, 0(sp)", dest); + break; + + case burm_float_ATTR: + hop_add_insel(hop, "lfs %H, 0(sp)", dest); + break; + + case burm_double_ATTR: + hop_add_insel(hop, "lfd %H, 0(sp)", dest); + break; + + default: + goto nomove; + } + + switch (dest->attrs & TYPE_ATTRS) + { + case burm_int_ATTR: + case burm_float_ATTR: + hop_add_insel(hop, "addi sp, sp, 4"); + break; + + case burm_double_ATTR: + case burm_long_ATTR: + hop_add_insel(hop, "addi sp, sp, 8"); + break; + + default: + goto nomove; + } + } + else + { + uint32_t type = src->attrs & TYPE_ATTRS; + + if (!src->is_stacked && dest->is_stacked) + { + switch (type) + { + case burm_int_ATTR: + hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest); + break; + + case burm_float_ATTR: + hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); + break; + + case burm_long_ATTR: + hop_add_insel(hop, "stw %0H, 4+%S(fp) ! %H", src, dest, dest); + hop_add_insel(hop, "stw %1H, 0+%S(fp) ! %H", src, dest, dest); + break; + + case burm_double_ATTR: + hop_add_insel(hop, "stfd %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, "lwz %H, %S(fp) ! %H", dest, src, src); + break; + + case burm_float_ATTR: + hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src); + break; + + case burm_double_ATTR: + hop_add_insel(hop, "lfd %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, "move %H, %H", dest, src); + break; + + case burm_long_ATTR: + hop_add_insel(hop, "move %0H, %0H", dest, src); + hop_add_insel(hop, "move %1H, %1H", dest, src); + break; + + case burm_float_ATTR: + case burm_double_ATTR: + hop_add_insel(hop, "fmr %H, %H", dest, src); + break; + + default: + goto nomove; + } + } + 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); + + 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, "mr r0, %H", src); + hop_add_insel(hop, "mr %H, %H", src, dest); + hop_add_insel(hop, "mr %H, r0", dest); + break; + + case burm_long_ATTR: + hop_add_insel(hop, "mr r0, %0H", src); + hop_add_insel(hop, "mr %0H, %0H", src, dest); + hop_add_insel(hop, "mr %0H, r0", dest); + + hop_add_insel(hop, "mr r0, %1H", src); + hop_add_insel(hop, "mr %1H, %1H", src, dest); + hop_add_insel(hop, "mr %1H, r0", dest); + break; + + case burm_float_ATTR: + case burm_double_ATTR: + hop_add_insel(hop, "fmr f0, %H", src); + hop_add_insel(hop, "fmr %H, %H", src, dest); + hop_add_insel(hop, "fmr %H, f0", 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 : */ + diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table new file mode 100644 index 000000000..e2553729b --- /dev/null +++ b/mach/mips/mcg/table @@ -0,0 +1,566 @@ +REGISTERS + + /* Registers are allocated top down. The odd order below is to make sure + * that cheap registers get allocated first. + * + * Attributes may have at most one of: int, float, long, double. These + * indicate that the register is used to store a value of that type. If + * your register can store more than one type, create an alias. Registers + * with none of these cannot be copied by the code generator (and so cannot + * be moved from register to register or spilt). + */ + + r4 named("r4") int volatile; + r5 named("r5") int volatile; + r6 named("r6") int volatile; + r7 named("r7") int volatile; + r8 named("r8") int volatile; + r9 named("r9") int volatile; + r10 named("r10") int volatile; + r11 named("r11") int volatile; + r12 named("r12") int volatile; + r13 named("r13") int volatile; + r14 named("r14") int volatile; + r15 named("r15") int volatile; + r24 named("r24") int volatile; + r25 named("r25") int volatile; + r2 named("r2") int volatile iret; + r3 named("r3") int volatile; + + r17 named("r16") int; + r18 named("r18") int; + r19 named("r19") int; + r20 named("r20") int; + r21 named("r21") int; + r22 named("r22") int; + r23 named("r23") int; + + r4r5 named("r4", "r5") aliases(r4, r5) long volatile; + r6r7 named("r6", "r7") aliases(r6, r7) long volatile; + r8r9 named("r8", "r9") aliases(r8, r9) long volatile; + r10r11 named("r10", "r11") aliases(r10, r11) long volatile; + r12r13 named("r12", "r13") aliases(r12, r13) long volatile; + r14r15 named("r14", "r15") aliases(r14, r15) long volatile; + r24r25 named("r24", "r25") aliases(r24, r25) long volatile; + r2r3 named("r2", "r3") aliases(r2, r3) long volatile lret; + + zero named("zero") zero int volatile; + + f0 float; + d0 double; + +DECLARATIONS + + ubyteX; /* bottom 8 bits valid, the rest undefined */ + ubyte0; /* bottom 8 bits valid, the rest 0 */ + ushortX; /* bottom 16 bits valid, the rest undefined */ + ushort0; /* bottom 16 bits valid, the rest 0 */ + + address fragment; + + + +PATTERNS + +/* Special */ + + PAIR(BLOCK.I, BLOCK.I); + + + +/* Miscellaneous special things */ + + PUSH.I(in:(int)reg) + emit "addiu sp, sp, -4" + emit "sw %in, 0(sp)" + cost 8; + + PUSH.L(in:(long)reg) + emit "addiu sp, sp, -8" + emit "sw %in.0, 0(sp)" + emit "sw %in.1, 4(sp)" + cost 12; + + out:(int)reg = POP.I + emit "lw %out, 0(sp)" + emit "addiu sp, sp, 4" + cost 8; + + out:(long)reg = POP.L + emit "lw %out.0, 4(sp)" + emit "lw %out.1, 0(sp)" + emit "addiu sp, sp, 8" + cost 12; + + SETRET.I(in:(iret)reg) + emit "! setret4" + cost 1; + + SETRET.L(in:(lret)reg) + emit "! setret8" + cost 1; + + STACKADJUST.I(delta:CONST.I) + when signed_constant(%delta, 16) + emit "addiu sp, sp, $delta" + cost 4; + + STACKADJUST.I(in:(int)reg) + emit "addu sp, sp, %in" + cost 4; + + STACKADJUST.I(NEG.I(in:(int)reg)) + emit "subu sp, sp, %in" + cost 4; + + out:(int)reg = GETFP.I + emit "move %out, fp" + cost 4; + + SETFP.I(in:(int)reg) + emit "move fp, %in" + cost 4; + + out:(int)reg = CHAINFP.I(in:(int)reg) + emit "lw %out, 0(%in)" + cost 4; + + out:(int)reg = FPTOAB.I(GETFP.I) + emit "addiu %out, fp, 8" + cost 4; + + out:(int)reg = FPTOAB.I(in:(int)reg) + emit "addiu %out, %in, 8" + cost 4; + + out:(int)reg = FPTOLB.I(in:(int)reg) + with %out == %in + cost 1; + + out:(int)reg = GETSP.I + emit "move %out, sp" + cost 4; + + SETSP.I(in:(int)reg) + emit "move sp, %in" + cost 4; + + out:(int)reg = ANY.I + cost 1; + + out:(long)reg = ANY.L + cost 1; + + + +/* Memory operations */ + + /* Stores */ + + STORE.L(addr:address, value:(long)reg) + emit "sw %value.0, 4+%addr" + emit "sw %value.1, 0+%addr" + cost 8; + + STORE.I(addr:address, value:(int)reg) + emit "sw %value, %addr" + cost 4; + + STOREH.I(addr:address, value:(int)ushortX) + emit "sh %value, %addr" + cost 4; + + STOREB.I(addr:address, value:(int)ubyteX) + emit "sb %value, %addr" + cost 4; + + /* Loads */ + + out:(int)reg = LOAD.I(addr:address) + emit "lw %out, %addr" + cost 4; + + /* We can't just load directly because %out.0 and %addr might share + * a register, resulting in %addr being corrupted before %out.1 is + * loaded. */ + out:(long)reg = LOAD.L(addr:address) + emit "lw at, 4+%addr" + emit "lw %out.1, 0+%addr" + emit "move %out.0, at" + cost 12; + + out:(int)ushort0 = LOADH.I(addr:address) + emit "lh %out, %addr" + cost 4; + + out:(int)ubyte0 = LOADB.I(addr:address) + emit "lb %out, %addr" + cost 4; + + /* ubyte intrinsics */ + + out:(int)ubyteX = in:(int)ubyte0 + with %out == %in + emit "! ubyte0 -> ubyteX" + cost 1; + + out:(int)ubyte0 = in:(int)ubyteX + emit "andiu %out, %in, 0xff ! ubyteX -> ubyte0" + cost 4; + + out:(int)reg = in:(int)ubyte0 + with %out == %in + emit "! ubyte0 -> reg" + cost 4; + + out:(int)ubyteX = in:(int)reg + with %out == %in + emit "! reg -> ubyteX" + cost 1; + + /* ushort intrinsics */ + + out:(int)ushortX = in:(int)ushort0 + with %out == %in + emit "! ushort0 -> ushortX" + cost 1; + + out:(int)ushort0 = in:(int)ushortX + emit "andiu %out, %in, 0xffff ! ushortX -> ushort0" + cost 4; + + out:(int)reg = in:(int)ushort0 + with %out == %in + emit "! ushort0 -> reg" + cost 4; + + out:(int)ushortX = in:(int)reg + with %out == %in + emit "! reg -> ushortX" + cost 1; + + + +/* Extensions and conversions */ + + out:(int)reg = EXTENDB.I(in:(int)reg) + emit "seb %out, %in" + cost 4; + + out:(int)reg = EXTENDH.I(in:(int)reg) + emit "seh %out, %in" + cost 4; + + out:(int)reg = FROMSI.I(in:(int)reg) + with %out == %in + emit "! FROMSI.I(int) -> int" + cost 1; + + out:(int)reg = FROMUI.I(in:(int)reg) + with %out == %in + emit "! FROMUI.I(int) -> int" + cost 1; + + out:(long)reg = FROMSI.L(in:(int)reg) + emit "move %out.0, %in" + emit "sra %out.1, %in, 31" + cost 8; + + out:(long)reg = FROMUI.L(in:(int)reg) + emit "mr %out.0, %in" + emit "li %out.1, 0" + cost 8; + + out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg) + emit "move %out.0, %in1" + emit "move %out.1, %in2" + cost 8; + + out:(int)reg = FROML0.I(in:(long)reg) + emit "move %out, %in.0" + cost 4; + + out:(int)reg = FROML1.I(in:(long)reg) + emit "move %out, %in.1" + cost 4; + + + +/* Locals */ + + out:(int)reg = in:LOCAL.I + emit "addiu %out, fp, $in" + cost 4; + + address = in:LOCAL.I + emit "$in(fp)"; + + + +/* Memory addressing modes */ + + address = ADD.I(addr:(int)reg, offset:CONST.I) + when signed_constant(%offset, 16) + emit "$offset(%addr)"; + + address = addr:(int)reg + emit "0(%addr)"; + + + +/* Branches */ + + JUMP(addr:BLOCK.I) + emit "b $addr" + emit "nop" + cost 8; + + FARJUMP(addr:LABEL.I) + with corrupted(volatile) + emit "b $addr" + emit "nop" + cost 8; + + JUMP(dest:(int)reg) + emit "jr %dest" + emit "nop" + cost 8; + + CJUMPEQ(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "beq %left, %right, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLT(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "slt at, %left, %right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLT(COMPAREUI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "sltu at, %left, %right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLT(COMPARESI.I(left:(int)reg, right:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%right, 0) + emit "bltz %left, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLE(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "sle at, %left, %right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLE(COMPAREUI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "sleu at, %left, %right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLE(COMPARESI.I(left:(int)reg, right:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%right, 0) + emit "blez %left, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + COMPAREUI.I(left:(int)reg, right:(int)reg); + + #define CALLLABEL(insn) \ + insn (dest:LABEL.I) \ + with corrupted(volatile) \ + emit "bal $dest" \ + emit "nop" \ + cost 8; + + CALLLABEL(CALL) + out:(iret)reg = CALLLABEL(CALL.I) + out:(lret)reg = CALLLABEL(CALL.L) + + #define CALLINDIRECT(insn) \ + insn (dest:(int)reg) \ + with corrupted(volatile) \ + emit "jalr %dest" \ + emit "nop" \ + cost 8; + + CALLINDIRECT(CALL) + out:(iret)reg = CALLINDIRECT(CALL.I) + out:(lret)reg = CALLINDIRECT(CALL.L) + + JUMP(dest:LABEL.I) + emit "b $dest" + emit "nop" + cost 8; + + + +/* Comparisons */ + + /* The COMPARE nodes return tristate integer values; -1, 0 or 1. */ + + out:(int)reg = COMPARESI.I(left:(int)reg, right:(int)reg) + emit "slt at, %left, %right" + emit "bne at, zero, 1f" + emit "li %out, -1" + emit "slt %out, %right, %left" + emit "1:" + cost 20; + + out:(int)reg = COMPAREUI.I(left:(int)reg, right:(int)reg) + emit "sltu at, %left, %right" + emit "bne at, zero, 1f" + emit "li %out, -1" + emit "sltu %out, %right, %left" + emit "1:" + cost 20; + +/* Booleans */ + + /* If 0 then 1, else 0 */ + out:(int)reg = IFEQ.I(in:(int)reg) + emit "sleu %out, %in, zero" + cost 4;; + + /* If -1 then 1, else 0 */ + out:(int)reg = IFLT.I(in:(int)reg) + emit "slt %out, %in, zero" + cost 4; + + /* If 1 or 0 then 1, else 0 */ + out:(int)reg = IFLE.I(in:(int)reg) + emit "sle %out, %in, zero" + cost 4; + + + +/* Conversions */ + +#if 0 + out:(int)reg = CIU44(in:(int)reg) + with %out == %in + emit "! ciu44" + cost 4; + + out:(int)reg = CUI44(in:(int)reg) + with %out == %in + emit "! cui44" + cost 4; +#endif + +/* ALU operations */ + + /* reg + reg */ + #define ALUR(name, instr) \ + out:(int)reg = name(left:(int)reg, right:(int)reg) \ + emit instr " %out, %left, %right" \ + cost 4; \ + + /* reg + const */ + #define ALUC(name, instr) \ + out:(int)reg = name(left:(int)reg, right:CONST.I) \ + when signed_constant(%right, 16) \ + emit instr " %out, %left, $right" \ + cost 4; \ + + /* const + reg */ + #define ALUC_reversed(name, instr) \ + out:(int)reg = name(left:CONST.I, right:(int)reg) \ + when signed_constant(%left, 16) \ + emit instr " %out, %right, $left" \ + cost 4; \ + + /* reg + const AND const + reg */ + #define ALUCC(name, instr) \ + ALUC(name, instr) \ + ALUC_reversed(name, instr) + + ALUR(ADD.I, "addu") + ALUCC(ADD.I, "addiu") + + out:(int)reg = SUB.I(left:(int)reg, right:(int)reg) + emit "subu %out, %right, %left" + cost 4; + + out:(int)reg = SUB.I(left:(int)reg, right:CONST.I) + emit "addiu %out, %left, -[$right]" + cost 4; + + out:(int)reg = MOD.I(left:(int)reg, right:(int)reg) + emit "div %left, %right" + emit "mfhi %out" + cost 8; + + out:(int)reg = MODU.I(left:(int)reg, right:(int)reg) + emit "divu %left, %right" + emit "mfhi %out" + cost 8; + + ALUR(MUL.I, "mul") + + ALUR(DIV.I, "divw") + ALUR(DIVU.I, "divwu") + + ALUR(ASL.I, "sll") + ALUC(ASL.I, "sllv") + ALUR(ASR.I, "sra") + ALUC(ASR.I, "srav") + + ALUR(LSL.I, "sll") + ALUC(LSL.I, "sllv") + ALUR(LSR.I, "srl") + ALUC(LSR.I, "srlv") + + out:(int)reg = NEG.I(left:(int)reg) + emit "neg %out, %left" + cost 4; + + out:(int)reg = NOT.I(in:(int)reg) + emit "nor %out, %in, %in" + cost 4; + + ALUR(AND.I, "and") + ALUCC(AND.I, "andi.") + + ALUR(OR.I, "or") + ALUCC(OR.I, "ori") + + ALUR(EOR.I, "xor") + ALUCC(EOR.I, "xori") + + out:(int)reg = value:LABEL.I + emit "li32 %out, $value" + cost 4; + + out:(int)reg = value:BLOCK.I + emit "li32 %out, $value" + cost 4; + + out:(int)reg = value:CONST.I + emit "li %out, $value" + cost 4; + + out:(zero)reg = value:CONST.I + when specific_constant(%value, 0) + cost 1; + + +/* vim: set sw=4 ts=4 expandtab : */ + diff --git a/mach/mips/top/table b/mach/mips/top/table new file mode 100644 index 000000000..8f6a5d6d7 --- /dev/null +++ b/mach/mips/top/table @@ -0,0 +1,20 @@ + +/* MIPS table for ACK target optimizer */ + +MAXOP 5; +LABEL_STARTER '.'; + +%%; + +X, Y, Z { TRUE }; + +%%; + +/* Whitespace is significant here! */ + +addiu RNZ, RNZ, 0 -> ; + +b X : nop : labdef X -> labdef X ; + +%%; + diff --git a/plat/linuxmips/build-tools.lua b/plat/linuxmips/build-tools.lua index 04a385d47..92167ba63 100644 --- a/plat/linuxmips/build-tools.lua +++ b/plat/linuxmips/build-tools.lua @@ -6,23 +6,22 @@ build_as { deps = { "mach/mips/as+astables" } } ---build_mcg { --- name = "mcg", --- arch = "powerpc", ---} --- ---build_top { --- name = "top", --- arch = "powerpc", ---} +build_mcg { + name = "mcg", + arch = "mips", +} + +build_top { + name = "top", + arch = "mips", +} return installable { name = "tools", map = { ["$(PLATDEP)/linuxmips/as"] = "+as", - --["$(PLATDEP)/linuxppc/ncg"] = "+ncg", - --["$(PLATDEP)/linuxppc/mcg"] = "+mcg", - --["$(PLATDEP)/linuxppc/top"] = "+top", + ["$(PLATDEP)/linuxmips/mcg"] = "+mcg", + ["$(PLATDEP)/linuxmips/top"] = "+top", ["$(PLATIND)/descr/linuxmips"] = "./descr", "util/amisc+aelflod-pkg", "util/opt+pkg", diff --git a/plat/linuxmips/descr b/plat/linuxmips/descr index 7ddaf941b..ad7f5180f 100644 --- a/plat/linuxmips/descr +++ b/plat/linuxmips/descr @@ -20,7 +20,7 @@ var PLATFORMDIR={EM}/share/ack/{PLATFORM} var CPP_F=-D__unix var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x00400054 var MACHOPT_F=-m2 -var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr +#var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr # Override the setting in fe so that files compiled for linuxppc can see # the platform-specific headers. @@ -30,7 +30,7 @@ var C_INCLUDES=-I{EM}/share/ack/linux/include -I{EM}/share/ack/include/ansi name be from .m.g to .s - program {EM}/lib/ack/{PLATFORM}/ncg + program {EM}/lib/ack/{PLATFORM}/mcg mapflag -gdb GF=-gdb args {GF?} < stdout @@ -83,5 +83,5 @@ name cv to .exe program {EM}/bin/aelflod args -m20 -b < > - outfile linuxppc.exe + outfile linuxmips.exe end From f8e71d888bc5bd5f635d52264eec8c7285d6d418 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 2 Sep 2018 21:36:09 +0200 Subject: [PATCH 04/79] Add some painfully untested FPU instructions. --- mach/mips/as/instructions.dat | 94 +++++++++++++++++++++++++++++++++++ mach/mips/as/mach2.c | 7 ++- mach/mips/as/mach3.c | 32 +++++++++++- mach/mips/as/mach4.c | 27 ++++++++++ 4 files changed, 157 insertions(+), 3 deletions(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index 1f7aae7f8..f3736d651 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -156,3 +156,97 @@ 00000000000100110 "xor" RD=gpr ',' RS=gpr ',' RT=gpr 001110 "xori" RT=gpr ',' RS=gpr ',' IMM=e16 +# FPU instructions. + +01000100000000101 "abs." F=FMT FD=fpr ',' FS=fpr +010001000000 "add." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr +010011011110 "alnv.ps" FD=fpr ',' FS=fpr ',' FT=fpr ',' RS=gpr +0100010011 "c." CO=FCOND '.' F=FMT FS=fpr ',' FT=fpr +01000100000001010 "ceil.l." F=FMT FD=fpr ',' FS=fpr +01000100000001110 "ceil.w." F=FMT FD=fpr ',' FS=fpr +0100010001000000000000 "cfc1" RT=gpr ',' FS=fpr +0100010011000000000000 "ctc1" RT=gpr ',' FS=fpr +01000100000100001 "cvt.d." F=FMT FD=fpr ',' FS=fpr +01000100000100101 "cvt.l." F=FMT FD=fpr ',' FS=fpr +01000110000100110 "cvt.ps.s" FD=fpr ',' FS=fpr ',' FT=fpr +01000100000100000 "cvt.s." F=FMT FD=fpr ',' FS=fpr +0100011011000000101000 "cvt.s.pl" FS=fpr ',' FD=fpr +0100011011000000100000 "cvt.s.pu" FS=fpr ',' FD=fpr +01000100000100100 "cvt.w." F=FMT FD=fpr ',' FS=fpr +010001000011 "div." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr +01000100000001011 "floor.l." F=FMT FD=fpr ',' FS=fpr +01000100000001111 "floor.w." F=FMT FD=fpr ',' FS=fpr +110101 "ldc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' +01001100000000001 "ldxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' +01001100000000101 "luxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' +110001 "lwc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' +01001100000000000 "lwxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' +010011100 "madd." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +0100010000000000000000 "mfc1" RT=gpr ',' FS=fpr +0100010001100000000000 "mfhc1" RT=gpr ',' FS=fpr +01000100000000110 "mov." F=FMT FD=fpr ',' FS=fpr +0000000000000000001 "movf" RD=gpr ',' RS=gpr ',' C=FCOND +01000100010001 "movf." F=FMT FD=fpr ',' FS=fpr ',' C=FCOND +010001010011 "movn." F=FMT FD=fpr ',' FS=fpr ',' RT=gpr +0000000100000000001 "movt" RD=gpr ',' RS=gpr ',' C=FCOND +01000101010001 "movt." F=FMT FD=fpr ',' FS=fpr ',' C=FCOND +010001010010 "movz." F=FMT FD=fpr ',' FS=fpr ',' RT=gpr +010011101 "msub." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +0100010010000000000000 "mtc1" RT=gpr ',' FS=fpr +0100010011100000000000 "mthc1" RT=gpr ',' FS=fpr +010001000010 "mul." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr +01000100000000111 "neg." F=FMT FD=fpr ',' FS=fpr +010011110 "nmadd." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +010011111 "nmsub." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +01000110110101100 "pll.ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000110110101101 "plu.ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000110110101110 "pul.ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000110110101111 "puu.ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000100000010101 "recip." F=FMT FD=fpr ',' FS=fpr +01000100000001000 "round.l." F=FMT FD=fpr ',' FS=fpr +01000100000001100 "round.w." F=FMT FD=fpr ',' FS=fpr +01000100000010110 "rsqrt." F=FMT FD=fpr ',' FS=fpr +111101 "sdc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' +01001100000001001 "sdxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' +01000100000000100 "sqrt." F=FMT FD=fpr ',' FS=fpr +010001000001 "sub." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr +01001100000001101 "suxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' +111001 "swc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' +01001100000001000 "swxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' + +# Generic coprocessor instructions. + +0100010100000 "bc1f" C=u3 ',' OFF=offset16 +0100010100000000 "bc1f" OFF=offset16 +0100010100010 "bc1fl" C=u3 ',' OFF=offset16 +0100010100000010 "bc1fl" OFF=offset16 +0100010100001 "bc1t" C=u3 ',' OFF=offset16 +0100010100000001 "bc1t" OFF=offset16 +0100010100011 "bc1tl" C=u3 ',' OFF=offset16 +0100010100000011 "bc1tl" OFF=offset16 +0100100100000 "bc2f" C=u3 ',' OFF=offset16 +0100100100000000 "bc2f" OFF=offset16 +0100100100010 "bc2fl" C=u3 ',' OFF=offset16 +0100100100000010 "bc2fl" OFF=offset16 +0100100100001 "bc2t" C=u3 ',' OFF=offset16 +0100100100000001 "bc2t" OFF=offset16 +0100100100011 "bc2tl" C=u3 ',' OFF=offset16 +0100100100000011 "bc2tl" OFF=offset16 +01001000010 "cfc2" RT=gpr ',' IMM=u16 +01001000110 "ctc2" RT=gpr ',' IMM=u16 +0100101 "cop2" FUN=u25 +110110 "ldc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' +110010 "lwc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' +0100000000000000000 "mfc0" RT=gpr ',' RD=u5 ',' S=u3 +01001000000 "mfc2" RT=gpr ',' IMM=u16 +0100000001000000000 "mfhc0" RT=gpr ',' RD=u5 ',' S=u3 +01001000011 "mfhc2" RT=gpr ',' IMM=u16 +0100000010000000000 "mtc0" RT=gpr ',' RD=u5 ',' S=u3 +01001000100 "mtc2" RT=gpr ',' IMM=u16 +0100000011000000000 "mthc0" RT=gpr ',' RD=u5 ',' S=u3 +01001000111 "mthc2" RT=gpr ',' IMM=u16 +111110 "sdc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' +111010 "swc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' + + + diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index 2672c0b9a..11886d052 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -1,9 +1,12 @@ %token GPR %token FPR +%token FMT +%token FMT3 +%token FCOND -%type gpr +%type gpr fpr %type e16 e9 -%type u20 u5 +%type u25 u20 u16 u5 u3 %type abs26 offset16 %type extmsblsb insmsblsb diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 0de4b37be..45af1c4fd 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -74,6 +74,36 @@ 0, FPR, 30, "f30", 0, FPR, 31, "f31", +/* Floating-point comparison values */ + +0, FCOND, 0, "f", +0, FCOND, 1, "un", +0, FCOND, 2, "eq", +0, FCOND, 3, "ueq", +0, FCOND, 4, "olt", +0, FCOND, 5, "ult", +0, FCOND, 6, "ole", +0, FCOND, 7, "ule", +0, FCOND, 8, "sf", +0, FCOND, 9, "ngle", +0, FCOND, 10, "seq", +0, FCOND, 11, "ngl", +0, FCOND, 12, "lt", +0, FCOND, 13, "nge", +0, FCOND, 14, "le", +0, FCOND, 15, "ngt", + +0, FMT, 16, "s", +0, FMT, 17, "d", +0, FMT, 20, "w", +0, FMT, 21, "l", +0, FMT, 22, "ps", + +0, FMT3, 0, "s", +0, FMT3, 1, "d", +0, FMT3, 4, "w", +0, FMT3, 5, "l", +0, FMT3, 6, "ps", + #include "tokens.y" - diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 2185fb245..f4d4c5e8d 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -1,6 +1,7 @@ #include "rules.y" gpr: GPR +fpr: FPR e16 : absexp @@ -22,6 +23,15 @@ e9 } ; +u25 + : absexp + { + if (($1 < 0) || ($1 > 0x1ffffff)) + serror("25-bit unsigned value out of range"); + $$ = $1; + } + ; + u20 : absexp { @@ -31,6 +41,14 @@ u20 } ; +u16 + : absexp + { + if (($1 < 0) || ($1 > 0xffff)) + serror("16-bit unsigned value out of range"); + $$ = $1; + } + ; u5 : absexp @@ -41,6 +59,15 @@ u5 } ; +u3 + : absexp + { + if (($1 < 0) || ($1 > 0x7)) + serror("3-bit unsigned value out of range"); + $$ = $1; + } + ; + offset16 : expr { From 83cf1be6a8b02e92220c976be5c27ce22e8f9853 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 3 Sep 2018 22:03:57 +0200 Subject: [PATCH 05/79] mcgg now checks that registers have at most one type attribute set. --- util/mcgg/iburg.c | 23 +++++++++++++++++++++-- util/mcgg/ircodes.h | 5 +++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 0477f216b..9979627c0 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -16,7 +16,10 @@ #include "smap.h" #include "mcgg.h" -static char rcsid[] = "$Id$"; +#define REGATTR_INT 0 +#define REGATTR_LONG 1 +#define REGATTR_FLOAT 2 +#define REGATTR_DOUBLE 3 int maxcost = SHRT_MAX / 2; @@ -162,6 +165,18 @@ int main(int argc, char* argv[]) rule(®, tree(&NOPL, tree(®, NULL, NULL), NULL))->cost = 1; rule(®, tree(&NOPD, tree(®, NULL, NULL), NULL))->cost = 1; rule(NULL, tree(&RET, NULL, NULL))->cost = 1; + + } + + { + struct regattr* attr = makeregattr("int"); + assert(attr->number == REGATTR_INT); + attr = makeregattr("long"); + assert(attr->number == REGATTR_LONG); + attr = makeregattr("float"); + assert(attr->number == REGATTR_FLOAT); + attr = makeregattr("double"); + assert(attr->number == REGATTR_DOUBLE); } yyin = infp; @@ -612,7 +627,8 @@ static void emitregisterattrs(void) assert(rc->number == i); print("%1\"%s\",\n", rc->name); - printh("#define %P%s_ATTR (1U<<%d)\n", rc->name, rc->number); + if (rc->number > REGATTR_DOUBLE) + printh("#define %P%s_ATTR (1U<<%d)\n", rc->name, rc->number); } print("};\n\n"); printh("\n"); @@ -655,7 +671,10 @@ static void emitregisters(void) for (i=0; iattrs & TYPE_ATTRS; assert(r->number == i); + if (type & (type-1)) + yyerror("register %s has more than one type attribute set", r->name); print("%1{ \"%s\", 0x%x, %Pregister_names_%d_%s, %Pregister_aliases_%d_%s },\n", r->name, r->attrs, i, r->name, i, r->name); diff --git a/util/mcgg/ircodes.h b/util/mcgg/ircodes.h index d9c05126f..16be32a5b 100644 --- a/util/mcgg/ircodes.h +++ b/util/mcgg/ircodes.h @@ -17,6 +17,11 @@ struct ir_data extern const struct ir_data ir_data[]; +#define burm_int_ATTR (1U<<0) +#define burm_long_ATTR (1U<<1) +#define burm_float_ATTR (1U<<2) +#define burm_double_ATTR (1U<<3) + #define TYPE_ATTRS \ (burm_int_ATTR | burm_long_ATTR | burm_float_ATTR | burm_double_ATTR) From 26f9b4ceae798db1cc7fb56b3737ca753e3daea1 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 3 Sep 2018 22:06:05 +0200 Subject: [PATCH 06/79] Add in floating point support to the code generator. --- mach/mips/as/instructions.dat | 2 +- mach/mips/mcg/platform.c | 44 ++++--- mach/mips/mcg/table | 236 ++++++++++++++++++++++++++++------ 3 files changed, 227 insertions(+), 55 deletions(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index f3736d651..bb46958ba 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -9,7 +9,7 @@ # Useful pseudoops. -0000000000000000100000 "move" RD=gpr ',' RS=gpr +0000000000000000100000 "mov" RD=gpr ',' RS=gpr # Core ALU instructions. diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index 23b01f13e..0f6881c59 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -120,8 +120,9 @@ struct hop* platform_epilogue(void) 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, "move fp, at"); + hop_add_insel(hop, "mov fp, at"); hop_add_insel(hop, "jr ra"); + hop_add_insel(hop, "nop"); return hop; } @@ -200,6 +201,7 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* 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) { @@ -251,17 +253,20 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* switch (type) { case burm_int_ATTR: - hop_add_insel(hop, "move %H, %H", dest, src); + hop_add_insel(hop, "mov %H, %H", dest, src); break; case burm_long_ATTR: - hop_add_insel(hop, "move %0H, %0H", dest, src); - hop_add_insel(hop, "move %1H, %1H", dest, src); + 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.f %H, %H", dest, src); + break; + case burm_double_ATTR: - hop_add_insel(hop, "fmr %H, %H", dest, src); + hop_add_insel(hop, "mov.d %H, %H", dest, src); break; default: @@ -289,26 +294,31 @@ struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* switch (src->attrs & TYPE_ATTRS) { case burm_int_ATTR: - hop_add_insel(hop, "mr r0, %H", src); - hop_add_insel(hop, "mr %H, %H", src, dest); - hop_add_insel(hop, "mr %H, r0", dest); + 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, "mr r0, %0H", src); - hop_add_insel(hop, "mr %0H, %0H", src, dest); - hop_add_insel(hop, "mr %0H, r0", dest); + 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, "mr r0, %1H", src); - hop_add_insel(hop, "mr %1H, %1H", src, dest); - hop_add_insel(hop, "mr %1H, r0", 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.f f31, %H", src); + hop_add_insel(hop, "mov.f %H, %H", src, dest); + hop_add_insel(hop, "mov.f %H, f31", dest); + break; + case burm_double_ATTR: - hop_add_insel(hop, "fmr f0, %H", src); - hop_add_insel(hop, "fmr %H, %H", src, dest); - hop_add_insel(hop, "fmr %H, f0", dest); + hop_add_insel(hop, "mov.d f31, %H", src); + hop_add_insel(hop, "mov.d %H, %H", src, dest); + hop_add_insel(hop, "mov.d %H, f31", dest); break; } diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index e2553729b..53b73fa53 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -10,22 +10,22 @@ REGISTERS * be moved from register to register or spilt). */ - r4 named("r4") int volatile; - r5 named("r5") int volatile; - r6 named("r6") int volatile; - r7 named("r7") int volatile; - r8 named("r8") int volatile; - r9 named("r9") int volatile; - r10 named("r10") int volatile; - r11 named("r11") int volatile; - r12 named("r12") int volatile; - r13 named("r13") int volatile; - r14 named("r14") int volatile; - r15 named("r15") int volatile; - r24 named("r24") int volatile; - r25 named("r25") int volatile; - r2 named("r2") int volatile iret; - r3 named("r3") int volatile; + r4 int volatile; + r5 int volatile; + r6 int volatile; + r7 int volatile; + r8 int volatile; + r9 int volatile; + r10 int volatile; + r11 int volatile; + r12 int volatile; + r13 int volatile; + r14 int volatile; + r15 int volatile; + r24 int volatile; + r25 int volatile; + r2 int volatile iret; + r3 int volatile; r17 named("r16") int; r18 named("r18") int; @@ -44,10 +44,74 @@ REGISTERS r24r25 named("r24", "r25") aliases(r24, r25) long volatile; r2r3 named("r2", "r3") aliases(r2, r3) long volatile lret; - zero named("zero") zero int volatile; + f0 float volatile fret; + f1 float volatile; + f2 float volatile; + f3 float volatile; + f4 float volatile; + f5 float volatile; + f6 float volatile; + f7 float volatile; + f8 float volatile; + f9 float volatile; + f10 float volatile; + f11 float volatile; + f12 float volatile; + f13 float volatile; + f14 float volatile; + f15 float volatile; + f16 float volatile; + f17 float volatile; + f18 float volatile; + f19 float volatile; + + f20 float; + f21 float; + f22 float; + f23 float; + f24 float; + f25 float; + f26 float; + f27 float; + f28 float; + f29 float; + f30 float; + /* f31 is used by the compiler as a temporary. */ + + d0 named("f0") aliases(f0) double volatile dret; + d1 named("f1") aliases(f1) double volatile; + d2 named("f2") aliases(f2) double volatile; + d3 named("f3") aliases(f3) double volatile; + d4 named("f4") aliases(f4) double volatile; + d5 named("f5") aliases(f5) double volatile; + d6 named("f6") aliases(f6) double volatile; + d7 named("f7") aliases(f7) double volatile; + d8 named("f8") aliases(f8) double volatile; + d9 named("f9") aliases(f9) double volatile; + d10 named("f10") aliases(f10) double volatile; + d11 named("f11") aliases(f11) double volatile; + d12 named("f12") aliases(f12) double volatile; + d13 named("f13") aliases(f13) double volatile; + d14 named("f14") aliases(f14) double volatile; + d15 named("f15") aliases(f15) double volatile; + d16 named("f16") aliases(f16) double volatile; + d17 named("f17") aliases(f17) double volatile; + d18 named("f18") aliases(f18) double volatile; + d19 named("f19") aliases(f19) double volatile; + + d20 named("f20") aliases(f20) double; + d21 named("f21") aliases(f21) double; + d22 named("f22") aliases(f22) double; + d23 named("f23") aliases(f23) double; + d24 named("f24") aliases(f24) double; + d25 named("f25") aliases(f25) double; + d26 named("f26") aliases(f26) double; + d27 named("f27") aliases(f27) double; + d28 named("f28") aliases(f28) double; + d29 named("f29") aliases(f29) double; + d30 named("f30") aliases(f30) double; + - f0 float; - d0 double; DECLARATIONS @@ -81,6 +145,16 @@ PATTERNS emit "sw %in.1, 4(sp)" cost 12; + PUSH.F(in:(float)reg) + emit "addiu sp, sp, -4" + emit "swc1 %in, 0(sp)" + cost 8; + + PUSH.D(in:(double)reg) + emit "addiu sp, sp, -8" + emit "sdc1 %in, 0(sp)" + cost 8; + out:(int)reg = POP.I emit "lw %out, 0(sp)" emit "addiu sp, sp, 4" @@ -92,14 +166,32 @@ PATTERNS emit "addiu sp, sp, 8" cost 12; + out:(float)reg = POP.F + emit "lwc1 %out, 0(sp)" + emit "addiu sp, sp, 4" + cost 8; + + out:(double)reg = POP.D + emit "ldc1 %out, 0(sp)" + emit "addiu sp, sp, 8" + cost 8; + SETRET.I(in:(iret)reg) - emit "! setret4" + emit "! setret.i" cost 1; SETRET.L(in:(lret)reg) - emit "! setret8" + emit "! setret.l" cost 1; + SETRET.F(in:(fret)reg) + emit "! setret.f" + cost 1; + + SETRET.D(in:(dret)reg) + emit "! setret.d" + cost 1; + STACKADJUST.I(delta:CONST.I) when signed_constant(%delta, 16) emit "addiu sp, sp, $delta" @@ -114,11 +206,11 @@ PATTERNS cost 4; out:(int)reg = GETFP.I - emit "move %out, fp" + emit "mov %out, fp" cost 4; SETFP.I(in:(int)reg) - emit "move fp, %in" + emit "mov fp, %in" cost 4; out:(int)reg = CHAINFP.I(in:(int)reg) @@ -138,11 +230,11 @@ PATTERNS cost 1; out:(int)reg = GETSP.I - emit "move %out, sp" + emit "mov %out, sp" cost 4; SETSP.I(in:(int)reg) - emit "move sp, %in" + emit "mov sp, %in" cost 4; out:(int)reg = ANY.I @@ -174,6 +266,14 @@ PATTERNS emit "sb %value, %addr" cost 4; + STORE.F(addr:address, value:(float)reg) + emit "swc1 %value, %addr" + cost 4; + + STORE.D(addr:address, value:(double)reg) + emit "sdc1 %value, %addr" + cost 4; + /* Loads */ out:(int)reg = LOAD.I(addr:address) @@ -186,7 +286,7 @@ PATTERNS out:(long)reg = LOAD.L(addr:address) emit "lw at, 4+%addr" emit "lw %out.1, 0+%addr" - emit "move %out.0, at" + emit "mov %out.0, at" cost 12; out:(int)ushort0 = LOADH.I(addr:address) @@ -197,6 +297,14 @@ PATTERNS emit "lb %out, %addr" cost 4; + out:(float)reg = LOAD.F(addr:address) + emit "lwc1 %out, %addr" + cost 4; + + out:(double)reg = LOAD.D(addr:address) + emit "ldc1 %out, %addr" + cost 4; + /* ubyte intrinsics */ out:(int)ubyteX = in:(int)ubyte0 @@ -262,7 +370,7 @@ PATTERNS cost 1; out:(long)reg = FROMSI.L(in:(int)reg) - emit "move %out.0, %in" + emit "mov %out.0, %in" emit "sra %out.1, %in, 31" cost 8; @@ -272,16 +380,16 @@ PATTERNS cost 8; out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg) - emit "move %out.0, %in1" - emit "move %out.1, %in2" + emit "mov %out.0, %in1" + emit "mov %out.1, %in2" cost 8; out:(int)reg = FROML0.I(in:(long)reg) - emit "move %out, %in.0" + emit "mov %out, %in.0" cost 4; out:(int)reg = FROML1.I(in:(long)reg) - emit "move %out, %in.1" + emit "mov %out, %in.1" cost 4; @@ -419,7 +527,7 @@ PATTERNS out:(int)reg = COMPARESI.I(left:(int)reg, right:(int)reg) emit "slt at, %left, %right" emit "bne at, zero, 1f" - emit "li %out, -1" + emit "li %out, -1" /* delay slot */ emit "slt %out, %right, %left" emit "1:" cost 20; @@ -427,17 +535,26 @@ PATTERNS out:(int)reg = COMPAREUI.I(left:(int)reg, right:(int)reg) emit "sltu at, %left, %right" emit "bne at, zero, 1f" - emit "li %out, -1" + emit "li %out, -1" /* delay slot */ emit "sltu %out, %right, %left" emit "1:" cost 20; + out:(int)reg = COMPARED.I(left:(double)reg, right:(double)reg) + emit "c.lt.d 0, %left, %right" + emit "bc1t 0, 1f" + emit "li %out, -1" /* delay slot */ + emit "c.lt.d 0, %right, %left" + emit "li %out, 1" + emit "movf %out, zero, 0" + cost 28; + /* Booleans */ /* If 0 then 1, else 0 */ out:(int)reg = IFEQ.I(in:(int)reg) emit "sleu %out, %in, zero" - cost 4;; + cost 4; /* If -1 then 1, else 0 */ out:(int)reg = IFLT.I(in:(int)reg) @@ -557,10 +674,55 @@ PATTERNS emit "li %out, $value" cost 4; - out:(zero)reg = value:CONST.I - when specific_constant(%value, 0) - cost 1; +/* FPU operations */ + + /* Doubles */ + + out:(double)reg = ADDF.D(left:(double)reg, right:(double)reg) + emit "add.d %out, %left, %right" + cost 4; + + out:(double)reg = SUBF.D(left:(double)reg, right:(double)reg) + emit "sub.d %out, %left, %right" + cost 4; + + out:(double)reg = MULF.D(left:(double)reg, right:(double)reg) + emit "mul.d %out, %left, %right" + cost 4; + + out:(double)reg = DIVF.D(left:(double)reg, right:(double)reg) + emit "div.d %out, %left, %right" + cost 4; + + out:(double)reg = FROMSI.D(in:(int)reg) + emit "mtc1 %out, %in" + emit "cvt.d.w %out, %out" + cost 4; + + /* Floats */ + + out:(float)reg = ADDF.F(left:(float)reg, right:(float)reg) + emit "add.d %out, %left, %right" + cost 4; + + out:(float)reg = SUBF.F(left:(float)reg, right:(float)reg) + emit "sub.d %out, %left, %right" + cost 4; + + out:(float)reg = MULF.F(left:(float)reg, right:(float)reg) + emit "mul.d %out, %left, %right" + cost 4; + + out:(float)reg = DIVF.F(left:(float)reg, right:(float)reg) + emit "div.d %out, %left, %right" + cost 4; + + out:(float)reg = FROMSI.F(in:(int)reg) + emit "mtc1 %out, %in" + emit "cvt.s.w %out, %out" + cost 4; + /* vim: set sw=4 ts=4 expandtab : */ From fe5ca5a85f01b494d55d2373d42e06f0e2d75c7c Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 3 Sep 2018 22:47:41 +0200 Subject: [PATCH 07/79] Added li and la instructions. --- h/out.h | 3 ++- mach/mips/as/instructions.dat | 7 ++++--- mach/mips/as/mach1.c | 9 --------- mach/mips/as/mach2.c | 3 +++ mach/mips/as/mach3.c | 3 +++ mach/mips/as/mach4.c | 31 +++++++++++++++++++++++++++++++ mach/mips/mcg/table | 20 ++++++++++---------- 7 files changed, 53 insertions(+), 23 deletions(-) diff --git a/h/out.h b/h/out.h index 17a4c908c..4176fd341 100644 --- a/h/out.h +++ b/h/out.h @@ -68,7 +68,8 @@ struct outname { #define RELOPPC 4 /* PowerPC 26-bit address */ #define RELOPPC_LIS 5 /* PowerPC lis */ #define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ -#define RELOMIPS 7 /* MIPS */ +#define RELOMIPS 7 /* MIPS, low half of word or other*/ +#define RELOMIPSHI 8 /* MIPS, high half of word */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index bb46958ba..80af89fdc 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -9,13 +9,14 @@ # Useful pseudoops. -0000000000000000100000 "mov" RD=gpr ',' RS=gpr +# or RD, RS, zero +0000000000000000100101 "mov" RD=gpr ',' RS=gpr # Core ALU instructions. 00000000000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr -001000 "addi" RT=gpr ',' RT=gpr ',' IMM=e16 -001001 "addiu" RT=gpr ',' RT=gpr ',' IMM=e16 +001000 "addi" RT=gpr ',' RS=gpr ',' IMM=e16 +001001 "addiu" RT=gpr ',' RS=gpr ',' IMM=e16 00000000000100001 "addu" RD=gpr ',' RS=gpr ',' RT=gpr 00000000000100100 "and" RD=gpr ',' RS=gpr ',' RT=gpr 001100 "andi" RT=gpr ',' RS=gpr ',' IMM=e16 diff --git a/mach/mips/as/mach1.c b/mach/mips/as/mach1.c index 50f799684..55c6b5507 100644 --- a/mach/mips/as/mach1.c +++ b/mach/mips/as/mach1.c @@ -1,12 +1,3 @@ -/* - * $Source$ - * $State$ - */ - /* * Do not #include anything here. Do it in mach/proto/as/comm0.h */ - -void no_hl(void); -word_t eval_hl(struct expr_t* expr, int token); -void emit_hl(word_t in); diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index 11886d052..db6a311f8 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -4,6 +4,9 @@ %token FMT3 %token FCOND +%token OP_LI +%token OP_LA + %type gpr fpr %type e16 e9 %type u25 u20 u16 u5 u3 diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 45af1c4fd..4e346d742 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -105,5 +105,8 @@ 0, FMT3, 5, "l", 0, FMT3, 6, "ps", +0, OP_LI, 0, "li", +0, OP_LA, 0, "la", + #include "tokens.y" diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index f4d4c5e8d..3cce17e66 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -1,4 +1,35 @@ #include "rules.y" + | OP_LI GPR ',' expr + { + word_t reg = $2; + word_t type = $4.typ & S_TYP; + word_t val = $4.val; + if (type != S_ABS) + serror("li cannot be used with values that need a fixup"); + + if (val == 0) + emit4(0x00000025 | (reg<<11)); /* or reg, zero, zero */ + else if ((val < -0x8000) || (val > 0xffff)) + emit4(0x24000000 | (reg<<16) | (val & 0xffff)); /* addiu 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 */ + } + } + | OP_LA GPR ',' expr + { + word_t reg = $2; + word_t type = $4.typ & S_TYP; + word_t val = $4.val; + + if (type != S_ABS) + newrelo($4.typ, RELOMIPSHI | FIXUPFLAGS); + emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ + if (type != S_ABS) + newrelo($4.typ, RELOMIPS | FIXUPFLAGS); + emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */ + } gpr: GPR fpr: FPR diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 53b73fa53..fc69ba7de 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -635,15 +635,15 @@ PATTERNS ALUR(DIV.I, "divw") ALUR(DIVU.I, "divwu") - ALUR(ASL.I, "sll") - ALUC(ASL.I, "sllv") - ALUR(ASR.I, "sra") - ALUC(ASR.I, "srav") + ALUR(ASL.I, "sllv") + ALUC(ASL.I, "sll") + ALUR(ASR.I, "srav") + ALUC(ASR.I, "sra") - ALUR(LSL.I, "sll") - ALUC(LSL.I, "sllv") - ALUR(LSR.I, "srl") - ALUC(LSR.I, "srlv") + ALUR(LSL.I, "sllv") + ALUC(LSL.I, "sll") + ALUR(LSR.I, "srlv") + ALUC(LSR.I, "srl") out:(int)reg = NEG.I(left:(int)reg) emit "neg %out, %left" @@ -663,11 +663,11 @@ PATTERNS ALUCC(EOR.I, "xori") out:(int)reg = value:LABEL.I - emit "li32 %out, $value" + emit "la %out, $value" cost 4; out:(int)reg = value:BLOCK.I - emit "li32 %out, $value" + emit "la %out, $value" cost 4; out:(int)reg = value:CONST.I From 9d80756253cc0b218e83a98c93e49f514db77409 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 4 Sep 2018 23:43:24 +0200 Subject: [PATCH 08/79] Lots of assembler and rule bugfixing. --- mach/mips/as/instructions.dat | 100 ++++++++++++++++++++-------------- mach/mips/as/mach2.c | 5 +- mach/mips/as/mach3.c | 31 ----------- mach/mips/as/mach4.c | 26 +++++++++ mach/mips/as/mktables.lua | 24 ++++---- mach/mips/mcg/table | 84 ++++++++++++---------------- 6 files changed, 138 insertions(+), 132 deletions(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index 80af89fdc..0d6b90909 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -12,6 +12,26 @@ # or RD, RS, zero 0000000000000000100101 "mov" RD=gpr ',' RS=gpr +# 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. 00000000000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr @@ -94,7 +114,7 @@ 00000000000000000000000000000000 "nop" 00000000000100111 "nor" RD=gpr ',' RS=gpr ',' RT=gpr 00000000000100101 "or" RD=gpr ',' RS=gpr ',' RT=gpr -001101 "ori" RS=gpr ',' RT=gpr +001101 "ori" RS=gpr ',' RT=gpr ',' IMM=e16 00000000000000000000000101000000 "pause" 110011 "pref" H=u5 ',' IMM=e16 '(' RS=gpr ')' 0111110100011 "prefe" H=u5 ',' IMM=e9 '(' RS=gpr ')' @@ -159,64 +179,64 @@ # FPU instructions. -01000100000000101 "abs." F=FMT FD=fpr ',' FS=fpr -010001000000 "add." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr -010011011110 "alnv.ps" FD=fpr ',' FS=fpr ',' FT=fpr ',' RS=gpr -0100010011 "c." CO=FCOND '.' F=FMT FS=fpr ',' FT=fpr -01000100000001010 "ceil.l." F=FMT FD=fpr ',' FS=fpr -01000100000001110 "ceil.w." F=FMT FD=fpr ',' FS=fpr +01000100000000101 "abs" F=fmt FD=fpr ',' FS=fpr +010001000000 "add" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr +010011011110 "alnv" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr ',' RS=gpr +01000100000001010 "ceil" ".l" F=fmt FD=fpr ',' FS=fpr +01000100000001110 "ceil" ".w" F=fmt FD=fpr ',' FS=fpr 0100010001000000000000 "cfc1" RT=gpr ',' FS=fpr 0100010011000000000000 "ctc1" RT=gpr ',' FS=fpr -01000100000100001 "cvt.d." F=FMT FD=fpr ',' FS=fpr -01000100000100101 "cvt.l." F=FMT FD=fpr ',' FS=fpr -01000110000100110 "cvt.ps.s" FD=fpr ',' FS=fpr ',' FT=fpr -01000100000100000 "cvt.s." F=FMT FD=fpr ',' FS=fpr -0100011011000000101000 "cvt.s.pl" FS=fpr ',' FD=fpr -0100011011000000100000 "cvt.s.pu" FS=fpr ',' FD=fpr -01000100000100100 "cvt.w." F=FMT FD=fpr ',' FS=fpr -010001000011 "div." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr -01000100000001011 "floor.l." F=FMT FD=fpr ',' FS=fpr -01000100000001111 "floor.w." F=FMT FD=fpr ',' FS=fpr +01000100000100001 "cvt" ".d" F=fmt FD=fpr ',' FS=fpr +01000100000100101 "cvt" ".l" F=fmt FD=fpr ',' FS=fpr +01000110000100110 "cvt" ".ps" ".s" FD=fpr ',' FS=fpr ',' FT=fpr +01000100000100000 "cvt" ".s" F=fmt FD=fpr ',' FS=fpr +0100011011000000101000 "cvt" ".s" ".pl" FS=fpr ',' FD=fpr +0100011011000000100000 "cvt" ".s" ".pu" FS=fpr ',' FD=fpr +01000100000100100 "cvt" ".w" F=fmt FD=fpr ',' FS=fpr +010001000011 "div" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr +01000100000001011 "floor" ".l" F=fmt FD=fpr ',' FS=fpr +01000100000001111 "floor" ".w" F=fmt FD=fpr ',' FS=fpr 110101 "ldc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' 01001100000000001 "ldxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' 01001100000000101 "luxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' 110001 "lwc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' 01001100000000000 "lwxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' -010011100 "madd." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +010011100 "madd" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr 0100010000000000000000 "mfc1" RT=gpr ',' FS=fpr 0100010001100000000000 "mfhc1" RT=gpr ',' FS=fpr -01000100000000110 "mov." F=FMT FD=fpr ',' FS=fpr -0000000000000000001 "movf" RD=gpr ',' RS=gpr ',' C=FCOND -01000100010001 "movf." F=FMT FD=fpr ',' FS=fpr ',' C=FCOND -010001010011 "movn." F=FMT FD=fpr ',' FS=fpr ',' RT=gpr -0000000100000000001 "movt" RD=gpr ',' RS=gpr ',' C=FCOND -01000101010001 "movt." F=FMT FD=fpr ',' FS=fpr ',' C=FCOND -010001010010 "movz." F=FMT FD=fpr ',' FS=fpr ',' RT=gpr -010011101 "msub." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +01000100000000110 "mov" F=fmt FD=fpr ',' FS=fpr +0000000000000000001 "movf" RD=gpr ',' RS=gpr ',' C=u3 +01000100010001 "movf" F=fmt FD=fpr ',' FS=fpr ',' C=u3 +010001010011 "movn" F=fmt FD=fpr ',' FS=fpr ',' RT=gpr +0000000100000000001 "movt" RD=gpr ',' RS=gpr ',' C=u3 +01000101010001 "movt" F=fmt FD=fpr ',' FS=fpr ',' C=u3 +010001010010 "movz" F=fmt FD=fpr ',' FS=fpr ',' RT=gpr +010011101 "msub" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr 0100010010000000000000 "mtc1" RT=gpr ',' FS=fpr 0100010011100000000000 "mthc1" RT=gpr ',' FS=fpr -010001000010 "mul." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr -01000100000000111 "neg." F=FMT FD=fpr ',' FS=fpr -010011110 "nmadd." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr -010011111 "nmsub." F=FMT3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr -01000110110101100 "pll.ps" FD=fpr ',' FS=fpr ',' FT=fpr -01000110110101101 "plu.ps" FD=fpr ',' FS=fpr ',' FT=fpr -01000110110101110 "pul.ps" FD=fpr ',' FS=fpr ',' FT=fpr -01000110110101111 "puu.ps" FD=fpr ',' FS=fpr ',' FT=fpr -01000100000010101 "recip." F=FMT FD=fpr ',' FS=fpr -01000100000001000 "round.l." F=FMT FD=fpr ',' FS=fpr -01000100000001100 "round.w." F=FMT FD=fpr ',' FS=fpr -01000100000010110 "rsqrt." F=FMT FD=fpr ',' FS=fpr +010001000010 "mul" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr +01000100000000111 "neg" F=fmt FD=fpr ',' FS=fpr +010011110 "nmadd" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +010011111 "nmsub" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr +01000110110101100 "pll" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000110110101101 "plu" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000110110101110 "pul" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000110110101111 "puu" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr +01000100000010101 "recip." F=fmt FD=fpr ',' FS=fpr +01000100000001000 "round" ".l" F=fmt FD=fpr ',' FS=fpr +01000100000001100 "round" ".w" F=fmt FD=fpr ',' FS=fpr +01000100000010110 "rsqrt" F=fmt FD=fpr ',' FS=fpr 111101 "sdc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' 01001100000001001 "sdxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' -01000100000000100 "sqrt." F=FMT FD=fpr ',' FS=fpr -010001000001 "sub." F=FMT FD=fpr ',' FS=fpr ',' FT=fpr +01000100000000100 "sqrt" F=fmt FD=fpr ',' FS=fpr +010001000001 "sub" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr 01001100000001101 "suxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' 111001 "swc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' 01001100000001000 "swxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' # Generic coprocessor instructions. +0100010011 "c" CO=fcond F=fmt C=u3 ',' FS=fpr ',' FT=fpr 0100010100000 "bc1f" C=u3 ',' OFF=offset16 0100010100000000 "bc1f" OFF=offset16 0100010100010 "bc1fl" C=u3 ',' OFF=offset16 diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index db6a311f8..9c81ed9a8 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -1,7 +1,5 @@ %token GPR %token FPR -%token FMT -%token FMT3 %token FCOND %token OP_LI @@ -12,6 +10,9 @@ %type u25 u20 u16 u5 u3 %type abs26 offset16 +%type fmt fmt3 +%type fcond + %type extmsblsb insmsblsb #include "definitions.y" diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 4e346d742..d75845e7b 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -74,37 +74,6 @@ 0, FPR, 30, "f30", 0, FPR, 31, "f31", -/* Floating-point comparison values */ - -0, FCOND, 0, "f", -0, FCOND, 1, "un", -0, FCOND, 2, "eq", -0, FCOND, 3, "ueq", -0, FCOND, 4, "olt", -0, FCOND, 5, "ult", -0, FCOND, 6, "ole", -0, FCOND, 7, "ule", -0, FCOND, 8, "sf", -0, FCOND, 9, "ngle", -0, FCOND, 10, "seq", -0, FCOND, 11, "ngl", -0, FCOND, 12, "lt", -0, FCOND, 13, "nge", -0, FCOND, 14, "le", -0, FCOND, 15, "ngt", - -0, FMT, 16, "s", -0, FMT, 17, "d", -0, FMT, 20, "w", -0, FMT, 21, "l", -0, FMT, 22, "ps", - -0, FMT3, 0, "s", -0, FMT3, 1, "d", -0, FMT3, 4, "w", -0, FMT3, 5, "l", -0, FMT3, 6, "ps", - 0, OP_LI, 0, "li", 0, OP_LA, 0, "la", diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 3cce17e66..fddeb25c7 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -34,6 +34,32 @@ 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 : absexp { diff --git a/mach/mips/as/mktables.lua b/mach/mips/as/mktables.lua index cb8565fc4..f1214e248 100755 --- a/mach/mips/as/mktables.lua +++ b/mach/mips/as/mktables.lua @@ -1,17 +1,19 @@ local args = {...} -local wordscount = 0 local words = {} local insns = {} local function addword(word) - local n = words[word] - if not n then - words[word] = wordscount - wordscount = wordscount + 1 - n = wordscount + 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 n + return w end local function parsesyntax(line) @@ -125,7 +127,9 @@ while true do end line = line:gsub("#.*$", "") line = line:gsub(" *$", "") - if line ~= "" then + 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] = { @@ -143,7 +147,7 @@ definitionsfp:close() local tokensfp = io.open(args[2], "w") for word, value in pairs(words) do - tokensfp:write("0, OP_", tostring(value), ", 0, \"", word, "\",\n") + tokensfp:write("0, OP_", value, ", 0, \"", word, "\",\n") end tokensfp:close() @@ -157,7 +161,7 @@ for index, insn in ipairs(insns) do end for _, word in ipairs(insn.syntax) do if word.word then - rulesfp:write(" OP_", tostring(word.word)) + rulesfp:write(" OP_", word.word) end if word.punct then rulesfp:write(" ", word.punct) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index fc69ba7de..054a39bdd 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -434,62 +434,26 @@ PATTERNS emit "nop" cost 8; - CJUMPEQ(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) - emit "beq %left, %right, $true" + CJUMPEQ(left:(int)reg, PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "beq %left, zero, $true" emit "nop" emit "b $false" emit "nop" cost 16; - CJUMPLT(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) - emit "slt at, %left, %right" - emit "bne at, zero, $true" - emit "nop" - emit "b $false" - emit "nop" - cost 20; - - CJUMPLT(COMPAREUI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) - emit "sltu at, %left, %right" - emit "bne at, zero, $true" - emit "nop" - emit "b $false" - emit "nop" - cost 20; - - CJUMPLT(COMPARESI.I(left:(int)reg, right:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) - when specific_constant(%right, 0) + CJUMPLT(left:(int)reg, PAIR(true:BLOCK.I, false:BLOCK.I)) emit "bltz %left, $true" emit "nop" emit "b $false" emit "nop" - cost 16; - - CJUMPLE(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) - emit "sle at, %left, %right" - emit "bne at, zero, $true" - emit "nop" - emit "b $false" - emit "nop" cost 20; - CJUMPLE(COMPAREUI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) - emit "sleu at, %left, %right" - emit "bne at, zero, $true" - emit "nop" - emit "b $false" - emit "nop" - cost 20; - - CJUMPLE(COMPARESI.I(left:(int)reg, right:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) - when specific_constant(%right, 0) + CJUMPLE(left:(int)reg, PAIR(true:BLOCK.I, false:BLOCK.I)) emit "blez %left, $true" emit "nop" emit "b $false" emit "nop" - cost 16; - - COMPAREUI.I(left:(int)reg, right:(int)reg); + cost 20; #define CALLLABEL(insn) \ insn (dest:LABEL.I) \ @@ -553,17 +517,17 @@ PATTERNS /* If 0 then 1, else 0 */ out:(int)reg = IFEQ.I(in:(int)reg) - emit "sleu %out, %in, zero" + emit "sltiu %out, %in, 1" cost 4; /* If -1 then 1, else 0 */ out:(int)reg = IFLT.I(in:(int)reg) - emit "slt %out, %in, zero" + emit "srl %out, %in, 31" cost 4; /* If 1 or 0 then 1, else 0 */ out:(int)reg = IFLE.I(in:(int)reg) - emit "sle %out, %in, zero" + emit "slt %out, %in, 1" cost 4; @@ -620,6 +584,16 @@ PATTERNS emit "addiu %out, %left, -[$right]" cost 4; + out:(int)reg = DIV.I(left:(int)reg, right:(int)reg) + emit "div %left, %right" + emit "mflo %out" + cost 8; + + out:(int)reg = DIVU.I(left:(int)reg, right:(int)reg) + emit "divu %left, %right" + emit "mflo %out" + cost 8; + out:(int)reg = MOD.I(left:(int)reg, right:(int)reg) emit "div %left, %right" emit "mfhi %out" @@ -632,9 +606,6 @@ PATTERNS ALUR(MUL.I, "mul") - ALUR(DIV.I, "divw") - ALUR(DIVU.I, "divwu") - ALUR(ASL.I, "sllv") ALUC(ASL.I, "sll") ALUR(ASR.I, "srav") @@ -697,10 +668,20 @@ PATTERNS cost 4; out:(double)reg = FROMSI.D(in:(int)reg) - emit "mtc1 %out, %in" + emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ emit "cvt.d.w %out, %out" cost 4; + out:(int)reg = FROMSD.I(in:(double)reg) + emit "trunc.w.d f31, %in" + emit "mfc1 %out, f31" + cost 8; + + out:(double)reg = COPYL.D(in:(long)reg) + emit "mtc1 %in.0, %out" /* mtc1 has reversed parameters */ + emit "mthic1 %in.1, %out" /* mtc1 has reversed parameters */ + cost 8; + /* Floats */ out:(float)reg = ADDF.F(left:(float)reg, right:(float)reg) @@ -720,9 +701,14 @@ PATTERNS cost 4; out:(float)reg = FROMSI.F(in:(int)reg) - emit "mtc1 %out, %in" + emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ emit "cvt.s.w %out, %out" cost 4; + out:(int)reg = FROMSF.I(in:(double)reg) + emit "trunc.w.s f31, %in" + emit "mfc1 %out, f31" + cost 8; + /* vim: set sw=4 ts=4 expandtab : */ From 26c0228b14992f0088e708599f867e9dce660314 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 4 Sep 2018 23:55:28 +0200 Subject: [PATCH 09/79] The examples all compile now (probably incorrectly, and the libc doesn't compile yet). --- mach/mips/as/instructions.dat | 2 ++ mach/mips/mcg/platform.c | 29 ++++++++++++++++++----------- mach/mips/mcg/table | 15 ++++++++++++++- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index 0d6b90909..b1084675b 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -233,6 +233,8 @@ 01001100000001101 "suxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' 111001 "swc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' 01001100000001000 "swxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' +01000100000001001 "trunc" ".l" F=fmt FS=fpr ',' FD=fpr +01000100000001101 "trunc" ".w" F=fmt FS=fpr ',' FD=fpr # Generic coprocessor instructions. diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index 0f6881c59..ab0032664 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -208,20 +208,20 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* switch (type) { case burm_int_ATTR: - hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest); - break; - - case burm_float_ATTR: - hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); + hop_add_insel(hop, "sw %H, %S(fp) ! %H", src, dest, dest); break; case burm_long_ATTR: - hop_add_insel(hop, "stw %0H, 4+%S(fp) ! %H", src, dest, dest); - hop_add_insel(hop, "stw %1H, 0+%S(fp) ! %H", src, dest, dest); + 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, "stfd %H, %S(fp) ! %H", src, dest, dest); + hop_add_insel(hop, "sdc1 %H, %S(fp) ! %H", src, dest, dest); break; default: @@ -233,15 +233,22 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* switch (type) { case burm_int_ATTR: - hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src); + 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, "lfs %H, %S(fp) ! %H", dest, src, src); + hop_add_insel(hop, "lwc1 %H, %S(fp) ! %H", dest, src, src); break; case burm_double_ATTR: - hop_add_insel(hop, "lfd %H, %S(fp) ! %H", dest, src, src); + hop_add_insel(hop, "ldc1 %H, %S(fp) ! %H", dest, src, src); break; default: diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 054a39bdd..24c362d7b 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -679,7 +679,12 @@ PATTERNS out:(double)reg = COPYL.D(in:(long)reg) emit "mtc1 %in.0, %out" /* mtc1 has reversed parameters */ - emit "mthic1 %in.1, %out" /* mtc1 has reversed parameters */ + emit "mthc1 %in.1, %out" /* mtc1 has reversed parameters */ + cost 8; + + out:(long)reg = COPYD.L(in:(double)reg) + emit "mfc1 %out.0, %in" + emit "mfhc1 %out.1, %in" cost 8; /* Floats */ @@ -710,5 +715,13 @@ PATTERNS emit "mfc1 %out, f31" cost 8; + out:(double)reg = COPYI.F(in:(long)reg) + emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ + cost 8; + + out:(long)reg = COPYF.I(in:(double)reg) + emit "mfc1 %out, %in" + cost 8; + /* vim: set sw=4 ts=4 expandtab : */ From 98afb42095350ce59b8f4bf5ea6c521522479216 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 5 Sep 2018 00:00:13 +0200 Subject: [PATCH 10/79] Added a boot.o based on the PowerPC one. --- plat/linuxmips/boot.s | 57 ++++++++++++++++++++++++++++++++++++ plat/linuxmips/build-pkg.lua | 12 ++++---- 2 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 plat/linuxmips/boot.s diff --git a/plat/linuxmips/boot.s b/plat/linuxmips/boot.s new file mode 100644 index 000000000..cc6d9ce32 --- /dev/null +++ b/plat/linuxmips/boot.s @@ -0,0 +1,57 @@ +# +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +begtext: + ! 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 = last arg + addiu r6, r6, 8 ! r6 = env + + addiu sp, sp, -3 * 4 + sw r4, 0(sp) + sw r5, 0(sp) + sw r6, 0(sp) + + b __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 diff --git a/plat/linuxmips/build-pkg.lua b/plat/linuxmips/build-pkg.lua index 6aec05157..8f9a100b2 100644 --- a/plat/linuxmips/build-pkg.lua +++ b/plat/linuxmips/build-pkg.lua @@ -1,10 +1,10 @@ include("plat/build.lua") ---ackfile { --- name = "boot", --- srcs = { "./boot.s" }, --- vars = { plat = "linuxppc" } ---} +ackfile { + name = "boot", + srcs = { "./boot.s" }, + vars = { plat = "linuxmips" } +} -- --build_plat_libs { -- name = "libs", @@ -18,7 +18,7 @@ installable { "+tools", -- "+libs", "./include+pkg", --- ["$(PLATIND)/linuxppc/boot.o"] = "+boot", + ["$(PLATIND)/linuxmips/boot.o"] = "+boot", -- ["$(PLATIND)/linuxppc/libsys.a"] = "./libsys+lib", } } From 26fe3f7530a51f5ebdc6b00b881c82e602d7a684 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 5 Sep 2018 00:07:07 +0200 Subject: [PATCH 11/79] Added library skeletons. --- mach/mips/libem/build.lua | 17 ++++++++++++++++ mach/mips/libend/build.lua | 8 ++++++++ mach/mips/libend/edata.s | 9 +++++++++ mach/mips/libend/em_end.s | 24 +++++++++++++++++++++++ mach/mips/libend/end.s | 7 +++++++ mach/mips/libend/etext.s | 9 +++++++++ plat/linuxmips/build-pkg.lua | 16 ++++++++-------- plat/linuxmips/libsys/_syscall.s | 18 +++++++++++++++++ plat/linuxmips/libsys/build.lua | 33 ++++++++++++++++++++++++++++++++ 9 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 mach/mips/libem/build.lua create mode 100644 mach/mips/libend/build.lua create mode 100644 mach/mips/libend/edata.s create mode 100644 mach/mips/libend/em_end.s create mode 100644 mach/mips/libend/end.s create mode 100644 mach/mips/libend/etext.s create mode 100644 plat/linuxmips/libsys/_syscall.s create mode 100644 plat/linuxmips/libsys/build.lua diff --git a/mach/mips/libem/build.lua b/mach/mips/libem/build.lua new file mode 100644 index 000000000..5ed9b52e8 --- /dev/null +++ b/mach/mips/libem/build.lua @@ -0,0 +1,17 @@ +for _, plat in ipairs(vars.plats) do + acklibrary { + name = "headers_"..plat, + } + + acklibrary { + name = "lib_"..plat, + srcs = { + "./*.s", -- dus4.s + }, + vars = { plat = plat }, + deps = { + "h+emheaders", + "+headers_"..plat, + } + } +end diff --git a/mach/mips/libend/build.lua b/mach/mips/libend/build.lua new file mode 100644 index 000000000..ca5a13c65 --- /dev/null +++ b/mach/mips/libend/build.lua @@ -0,0 +1,8 @@ +for _, plat in ipairs(vars.plats) do + acklibrary { + name = "lib_"..plat, + srcs = { "./*.s" }, + vars = { plat = plat }, + } +end + diff --git a/mach/mips/libend/edata.s b/mach/mips/libend/edata.s new file mode 100644 index 000000000..f53adc109 --- /dev/null +++ b/mach/mips/libend/edata.s @@ -0,0 +1,9 @@ +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _edata +.sect .data + .align 4 + .sect .data +_edata: diff --git a/mach/mips/libend/em_end.s b/mach/mips/libend/em_end.s new file mode 100644 index 000000000..0271f09f6 --- /dev/null +++ b/mach/mips/libend/em_end.s @@ -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: diff --git a/mach/mips/libend/end.s b/mach/mips/libend/end.s new file mode 100644 index 000000000..93a1e6e00 --- /dev/null +++ b/mach/mips/libend/end.s @@ -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: diff --git a/mach/mips/libend/etext.s b/mach/mips/libend/etext.s new file mode 100644 index 000000000..8c7453cb4 --- /dev/null +++ b/mach/mips/libend/etext.s @@ -0,0 +1,9 @@ +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _etext +.sect .text + .align 4 + .sect .text +_etext: diff --git a/plat/linuxmips/build-pkg.lua b/plat/linuxmips/build-pkg.lua index 8f9a100b2..73f73e68e 100644 --- a/plat/linuxmips/build-pkg.lua +++ b/plat/linuxmips/build-pkg.lua @@ -5,21 +5,21 @@ ackfile { srcs = { "./boot.s" }, vars = { plat = "linuxmips" } } --- ---build_plat_libs { --- name = "libs", --- arch = "powerpc", --- plat = "linuxppc", ---} + +build_plat_libs { + name = "libs", + arch = "mips", + plat = "linuxmips", +} installable { name = "pkg", map = { "+tools", --- "+libs", + "+libs", "./include+pkg", ["$(PLATIND)/linuxmips/boot.o"] = "+boot", --- ["$(PLATIND)/linuxppc/libsys.a"] = "./libsys+lib", + ["$(PLATIND)/linuxmips/libsys.a"] = "./libsys+lib", } } diff --git a/plat/linuxmips/libsys/_syscall.s b/plat/linuxmips/libsys/_syscall.s new file mode 100644 index 000000000..75c551d20 --- /dev/null +++ b/plat/linuxmips/libsys/_syscall.s @@ -0,0 +1,18 @@ +# +! 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: + syscall 0 + diff --git a/plat/linuxmips/libsys/build.lua b/plat/linuxmips/libsys/build.lua new file mode 100644 index 000000000..2265e6869 --- /dev/null +++ b/plat/linuxmips/libsys/build.lua @@ -0,0 +1,33 @@ +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/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/write.c", + }, + deps = { + "plat/linux/libsys/*.h", + "lang/cem/libcc.ansi/headers+headers", + "plat/linuxmips/include+pkg", + }, + vars = { + plat = "linuxmips" + } +} + From 7fbce066f8e0b36ca64674ad436c806a64ddacc5 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 5 Sep 2018 00:13:01 +0200 Subject: [PATCH 12/79] We attempt to compile the first library function; we fail. --- mach/mips/libem/trp.s | 13 +++++++++++++ mach/mips/mcg/table | 8 ++++++++ 2 files changed, 21 insertions(+) create mode 100644 mach/mips/libem/trp.s diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s new file mode 100644 index 000000000..7801d471c --- /dev/null +++ b/mach/mips/libem/trp.s @@ -0,0 +1,13 @@ +.sect .text +.sect .rom +.sect .data +.sect .bss + +.define .trap_ecase +.trap_ecase: + li r3, 20 ! ECASE = 20 in h/em_abs.h + ! FALLTHROUGH to .trp + +.trap: + syscall + diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 24c362d7b..d9ec7a6ac 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -667,6 +667,10 @@ PATTERNS emit "div.d %out, %left, %right" cost 4; + out:(float)reg = NEGF.D(left:(float)reg) + emit "neg.d %out, %left" + cost 4; + out:(double)reg = FROMSI.D(in:(int)reg) emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ emit "cvt.d.w %out, %out" @@ -705,6 +709,10 @@ PATTERNS emit "div.d %out, %left, %right" cost 4; + out:(float)reg = NEGF.F(left:(float)reg) + emit "neg.f %out, %left" + cost 4; + out:(float)reg = FROMSI.F(in:(int)reg) emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ emit "cvt.s.w %out, %out" From fc0b0ae1780b39b14a226276cf051d2966d629a8 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 5 Sep 2018 23:53:08 +0200 Subject: [PATCH 13/79] (Slightly) better errors on phi congruence group mismatches. --- mach/proto/mcg/pass_phigroups.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mach/proto/mcg/pass_phigroups.c b/mach/proto/mcg/pass_phigroups.c index dfff73faa..e57378ad4 100644 --- a/mach/proto/mcg/pass_phigroups.c +++ b/mach/proto/mcg/pass_phigroups.c @@ -36,8 +36,10 @@ static void recursively_associate_group(struct phicongruence* c, struct vreg* vr struct constraint* constraint = pmap_findleft(&vreg->defined->constraints, vreg); if (c->type == 0) c->type = vreg->type; - - assert(c->type == vreg->type); + + if (c->type != vreg->type) + fatal("tried to add register %%%d of type 0x%x to a phi congruence group of type 0x%x", + vreg->id, vreg->type, c->type); array_appendu(&c->definitions, vreg->defined); } From b7a1c969864d5eeadf02410a1e24c0f94008ac0e Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 5 Sep 2018 23:53:38 +0200 Subject: [PATCH 14/79] MIPS appears to hate converting unsigneds to floats and vice versa. --- mach/mips/libem/fromud.s | 37 +++++++++++++++++++++++++++++++++++++ mach/mips/libem/fromuf.s | 37 +++++++++++++++++++++++++++++++++++++ mach/mips/mcg/table | 24 ++++++++++++++++++------ 3 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 mach/mips/libem/fromud.s create mode 100644 mach/mips/libem/fromuf.s diff --git a/mach/mips/libem/fromud.s b/mach/mips/libem/fromud.s new file mode 100644 index 000000000..3b2c459ca --- /dev/null +++ b/mach/mips/libem/fromud.s @@ -0,0 +1,37 @@ +# +.sect .text +.sect .rom +.sect .data +.sect .bss + +.data + +.define .fromud +.fromud: + /* Input: f0 + * Output: r2 + * Only at and f31 may be used. + */ + li at, hi(.fd_80000000) + ldc1 f31, lo(.fd_800000000)(at) + c.le.d 0, f31, f0 + bc1t toobig + nop + + trunc.w.d f0, f0 + mfc1 r2, f0 + jr ra + nop + +toobig: + sub.d f0, f0, f31 + trunc.w.d f0, f0 + mfc1 r2, f0 + addiu r2, r2, 0x8000 + jr ra + nop + +sect .rom +.fd_80000000: + !float 2.147483648e+9 sz 8 + .data4 0x41e00000, 0 diff --git a/mach/mips/libem/fromuf.s b/mach/mips/libem/fromuf.s new file mode 100644 index 000000000..0b9517134 --- /dev/null +++ b/mach/mips/libem/fromuf.s @@ -0,0 +1,37 @@ +# +.sect .text +.sect .rom +.sect .data +.sect .bss + +.data + +.define .fromuf +.fromuf: + /* Input: f0 + * Output: r2 + * Only at and f31 may be used. + */ + li at, hi(.fd_80000000) + lwc1 f31, lo(.fd_800000000)(at) + c.le.f 0, f31, f0 + bc1t toobig + nop + + trunc.w.f f0, f0 + mfc1 r2, f0 + jr ra + nop + +toobig: + sub.f f0, f0, f31 + trunc.w.f f0, f0 + mfc1 r2, f0 + addiu r2, r2, 0x8000 + jr ra + nop + +sect .rom +.fd_80000000: + !float 2.147483648e+9 sz 4 + .data4 0x4f000000, 0 diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index d9ec7a6ac..c2b7e3eb3 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -617,7 +617,7 @@ PATTERNS ALUC(LSR.I, "srl") out:(int)reg = NEG.I(left:(int)reg) - emit "neg %out, %left" + emit "subu %out, zero, %left" cost 4; out:(int)reg = NOT.I(in:(int)reg) @@ -625,7 +625,7 @@ PATTERNS cost 4; ALUR(AND.I, "and") - ALUCC(AND.I, "andi.") + ALUCC(AND.I, "andi") ALUR(OR.I, "or") ALUCC(OR.I, "ori") @@ -667,7 +667,7 @@ PATTERNS emit "div.d %out, %left, %right" cost 4; - out:(float)reg = NEGF.D(left:(float)reg) + out:(double)reg = NEGF.D(left:(double)reg) emit "neg.d %out, %left" cost 4; @@ -681,6 +681,12 @@ PATTERNS emit "mfc1 %out, f31" cost 8; + out:(iret)reg = FROMUD.I(in:(dret)reg) + with corrupted(dret) + emit "jal .fromud" + emit "nop" + cost 30; + out:(double)reg = COPYL.D(in:(long)reg) emit "mtc1 %in.0, %out" /* mtc1 has reversed parameters */ emit "mthc1 %in.1, %out" /* mtc1 has reversed parameters */ @@ -718,16 +724,22 @@ PATTERNS emit "cvt.s.w %out, %out" cost 4; - out:(int)reg = FROMSF.I(in:(double)reg) + out:(int)reg = FROMSF.I(in:(float)reg) emit "trunc.w.s f31, %in" emit "mfc1 %out, f31" cost 8; - out:(double)reg = COPYI.F(in:(long)reg) + out:(iret)reg = FROMUD.I(in:(fret)reg) + with corrupted(fret) + emit "jal .fromuf" + emit "nop" + cost 30; + + out:(float)reg = COPYI.F(in:(int)reg) emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ cost 8; - out:(long)reg = COPYF.I(in:(double)reg) + out:(int)reg = COPYF.I(in:(float)reg) emit "mfc1 %out, %in" cost 8; From d2c14ca44fedab72dd41d430754a96a8522fd063 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 8 Sep 2018 18:59:55 +0200 Subject: [PATCH 15/79] Precisely one stack hreg gets allocated for each vreg/congruence group for eviction; this prevents us from having to worry about moving values from stack slot to stack slot, which is hard. --- mach/mips/mcg/platform.c | 5 ++++- mach/powerpc/mcg/platform.c | 2 +- mach/proto/mcg/mcg.h | 2 +- mach/proto/mcg/pass_phigroups.c | 3 ++- mach/proto/mcg/pass_registerallocator.c | 27 ++++++++++++++++++++----- mach/proto/mcg/reg.h | 2 ++ 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index ab0032664..0b7ee65bb 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -127,7 +127,7 @@ struct hop* platform_epilogue(void) return hop; } -struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest) +struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest) { struct hop* hop = new_hop(bb, NULL); @@ -280,6 +280,8 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* 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; } @@ -294,6 +296,7 @@ struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* { 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)); diff --git a/mach/powerpc/mcg/platform.c b/mach/powerpc/mcg/platform.c index 65b158cac..706797250 100644 --- a/mach/powerpc/mcg/platform.c +++ b/mach/powerpc/mcg/platform.c @@ -128,7 +128,7 @@ struct hop* platform_epilogue(void) return hop; } -struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest) +struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest) { struct hop* hop = new_hop(bb, NULL); diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 540f5799c..b813b7973 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -123,7 +123,7 @@ extern void pass_wire_up_return_values(void); extern void platform_calculate_offsets(void); extern struct hop* platform_prologue(void); extern struct hop* platform_epilogue(void); -extern struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest); +extern struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest); extern struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest); extern const char* platform_label(const char* label); diff --git a/mach/proto/mcg/pass_phigroups.c b/mach/proto/mcg/pass_phigroups.c index e57378ad4..abb892445 100644 --- a/mach/proto/mcg/pass_phigroups.c +++ b/mach/proto/mcg/pass_phigroups.c @@ -10,7 +10,8 @@ static void make_phimap(void) for (i=0; iphis.count; j++) { struct vreg* vreg = bb->phis.item[j].left; diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index a5436bc73..0a25fc4f0 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -386,16 +386,28 @@ static void find_new_home_for_evicted_register(struct vreg* vreg, struct hreg* s for (i=0; iattrs & srctype) && + if (!hreg->is_stacked && (hreg->attrs & srctype) && allocatable_through(hreg, vreg)) { goto found; } } - /* No more registers --- allocate a stack slot. */ + /* No more registers --- allocate a stack slot. Ensure that we use the same stack + * slot for this vreg throughout the function. */ - hreg = new_stacked_hreg(srctype); + hreg = vreg->evicted; + if (!hreg) + { + if (vreg->congruence) + hreg = vreg->evicted = vreg->congruence->evicted; + if (!hreg) + { + hreg = vreg->evicted = new_stacked_hreg(srctype); + if (vreg->congruence) + vreg->congruence->evicted = hreg; + } + } array_append(&hregs, hreg); found: @@ -617,7 +629,8 @@ static int insert_moves(struct basicblock* bb, int index, { /* Copy. */ - hop = platform_move(bb, src, dest); + struct vreg* vreg = pmap_findleft(srcregs, src); + hop = platform_move(bb, vreg, src, dest); pmap_remove(&copies, src, dest); } else @@ -710,13 +723,17 @@ static void insert_phi_copies(void) for (k=0; kregsin.count; k++) { - struct hreg*hreg = bb->regsin.item[k].left; + struct hreg* hreg = bb->regsin.item[k].left; struct vreg* vreg = bb->regsin.item[k].right; struct hreg* src = pmap_findright(prevbb->regsout, vreg); if (!pmap_findleft(&bb->phis, vreg)) { tracef('R', "R: input map %%%d (%s) -> (%s)\n", vreg->id, src->id, hreg->id); + if ((src->id != hreg->id) && src->is_stacked && hreg->is_stacked) + fatal("vreg %%%d is stacked in %s on entry to %s, but is passed in in %s from %s", + vreg->id, hreg->id, bb->name, + src->id, prevbb->name); pmap_add(&destregs, hreg, vreg); } diff --git a/mach/proto/mcg/reg.h b/mach/proto/mcg/reg.h index 00c8220b5..b3f231494 100644 --- a/mach/proto/mcg/reg.h +++ b/mach/proto/mcg/reg.h @@ -9,6 +9,7 @@ struct phicongruence ARRAYOF(struct vreg) vregs; ARRAYOF(struct hop) definitions; uint32_t type; + struct hreg* evicted; /* stack slot to evict to */ }; struct hreg @@ -28,6 +29,7 @@ struct vreg struct phicongruence* congruence; struct hop* defined; ARRAYOF(struct hop) used; + struct hreg* evicted; /* stack slot to evict to */ }; typedef PMAPOF(struct hreg, struct vreg) register_assignment_t; From 379c1a4a3cb5d057251782c6d31b001b9ec94be4 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 8 Sep 2018 22:06:38 +0200 Subject: [PATCH 16/79] Rework floating point conversion. Bash enough of the table into workingness that the libraries build now. --- mach/mips/libem/{fromud.s => c_ud_i.s} | 9 +---- mach/mips/libem/{fromuf.s => c_uf_i.s} | 8 +--- mach/mips/libem/fd_80000000.s | 11 ++++++ mach/mips/libem/ff_80000000.s | 11 ++++++ mach/mips/mcg/platform.c | 8 ++-- mach/mips/mcg/table | 54 ++++++++++++++++++++++---- 6 files changed, 76 insertions(+), 25 deletions(-) rename mach/mips/libem/{fromud.s => c_ud_i.s} (78%) rename mach/mips/libem/{fromuf.s => c_uf_i.s} (78%) create mode 100644 mach/mips/libem/fd_80000000.s create mode 100644 mach/mips/libem/ff_80000000.s diff --git a/mach/mips/libem/fromud.s b/mach/mips/libem/c_ud_i.s similarity index 78% rename from mach/mips/libem/fromud.s rename to mach/mips/libem/c_ud_i.s index 3b2c459ca..e9c9dda19 100644 --- a/mach/mips/libem/fromud.s +++ b/mach/mips/libem/c_ud_i.s @@ -6,8 +6,8 @@ .data -.define .fromud -.fromud: +.define .c_ud_i +.c_ud_i: /* Input: f0 * Output: r2 * Only at and f31 may be used. @@ -30,8 +30,3 @@ toobig: addiu r2, r2, 0x8000 jr ra nop - -sect .rom -.fd_80000000: - !float 2.147483648e+9 sz 8 - .data4 0x41e00000, 0 diff --git a/mach/mips/libem/fromuf.s b/mach/mips/libem/c_uf_i.s similarity index 78% rename from mach/mips/libem/fromuf.s rename to mach/mips/libem/c_uf_i.s index 0b9517134..ac0642fc7 100644 --- a/mach/mips/libem/fromuf.s +++ b/mach/mips/libem/c_uf_i.s @@ -6,8 +6,8 @@ .data -.define .fromuf -.fromuf: +.define .c_uf_i +.c_uf_i: /* Input: f0 * Output: r2 * Only at and f31 may be used. @@ -31,7 +31,3 @@ toobig: jr ra nop -sect .rom -.fd_80000000: - !float 2.147483648e+9 sz 4 - .data4 0x4f000000, 0 diff --git a/mach/mips/libem/fd_80000000.s b/mach/mips/libem/fd_80000000.s new file mode 100644 index 000000000..1cc52cab0 --- /dev/null +++ b/mach/mips/libem/fd_80000000.s @@ -0,0 +1,11 @@ +# +.sect .text; .sect .rom; .sect .data; .sect .bss + +.sect .rom + +/* 2147483648 as a double; used as a pivot for double->unsigned and unsigned->double. */ + +.define .fd_80000000 +.fd_80000000: + .data4 0x41e00000, 0 + diff --git a/mach/mips/libem/ff_80000000.s b/mach/mips/libem/ff_80000000.s new file mode 100644 index 000000000..54e274fb5 --- /dev/null +++ b/mach/mips/libem/ff_80000000.s @@ -0,0 +1,11 @@ +# +.sect .text; .sect .rom; .sect .data; .sect .bss + +.sect .rom + +/* 2147483648 as a float; used as a pivot for double->float and unsigned->float. */ + +.define .ff_80000000 +.ff_80000000: + .data4 0x4f000000 + diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index 0b7ee65bb..cd3a3762b 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -269,7 +269,7 @@ struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* break; case burm_float_ATTR: - hop_add_insel(hop, "mov.f %H, %H", dest, src); + hop_add_insel(hop, "mov.s %H, %H", dest, src); break; case burm_double_ATTR: @@ -320,9 +320,9 @@ struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* break; case burm_float_ATTR: - hop_add_insel(hop, "mov.f f31, %H", src); - hop_add_insel(hop, "mov.f %H, %H", src, dest); - hop_add_insel(hop, "mov.f %H, f31", dest); + hop_add_insel(hop, "mov.s f31, %H", src); + hop_add_insel(hop, "mov.s %H, %H", src, dest); + hop_add_insel(hop, "mov.s %H, f31", dest); break; case burm_double_ATTR: diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index c2b7e3eb3..76ca419f2 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -504,13 +504,26 @@ PATTERNS emit "1:" cost 20; + out:(int)reg = COMPAREF.I(left:(float)reg, right:(float)reg) + emit "c.lt.s 0, %left, %right" + emit "li %out, -1" + emit "bc1t 0, 1f" + emit "nop" + emit "c.lt.s 0, %right, %left" + emit "li %out, 1" + emit "movf %out, zero, 0" + emit "1:" + cost 28; + out:(int)reg = COMPARED.I(left:(double)reg, right:(double)reg) emit "c.lt.d 0, %left, %right" + emit "li %out, -1" emit "bc1t 0, 1f" - emit "li %out, -1" /* delay slot */ + emit "nop" emit "c.lt.d 0, %right, %left" emit "li %out, 1" emit "movf %out, zero, 0" + emit "1:" cost 28; /* Booleans */ @@ -527,7 +540,7 @@ PATTERNS /* If 1 or 0 then 1, else 0 */ out:(int)reg = IFLE.I(in:(int)reg) - emit "slt %out, %in, 1" + emit "slti %out, %in, 1" cost 4; @@ -676,14 +689,24 @@ PATTERNS emit "cvt.d.w %out, %out" cost 4; + out:(dret)reg = FROMUI.D(in:(iret)reg) + emit "jal .c_ui_d" + emit "nop" + cost 30; + out:(int)reg = FROMSD.I(in:(double)reg) emit "trunc.w.d f31, %in" emit "mfc1 %out, f31" cost 8; + out:(lret)reg = FROMSD.L(in:(dret)reg) + emit "jal .c_sd_l" + emit "nop" + cost 30; + out:(iret)reg = FROMUD.I(in:(dret)reg) with corrupted(dret) - emit "jal .fromud" + emit "jal .c_ud_i" emit "nop" cost 30; @@ -716,7 +739,7 @@ PATTERNS cost 4; out:(float)reg = NEGF.F(left:(float)reg) - emit "neg.f %out, %left" + emit "neg.s %out, %left" cost 4; out:(float)reg = FROMSI.F(in:(int)reg) @@ -729,19 +752,34 @@ PATTERNS emit "mfc1 %out, f31" cost 8; - out:(iret)reg = FROMUD.I(in:(fret)reg) + out:(lret)reg = FROMSF.L(in:(fret)reg) + emit "jal .c_sf_l" + emit "nop" + cost 30; + + out:(fret)reg = FROMUI.F(in:(iret)reg) + emit "jal .c_ui_f" + emit "nop" + cost 30; + + out:(iret)reg = FROMUF.I(in:(fret)reg) with corrupted(fret) - emit "jal .fromuf" + emit "jal .c_uf_i" emit "nop" cost 30; out:(float)reg = COPYI.F(in:(int)reg) emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ - cost 8; + cost 4; out:(int)reg = COPYF.I(in:(float)reg) emit "mfc1 %out, %in" - cost 8; + cost 4; + + out:(float)reg = value:CONST.F + when specific_constant(%value, 0) + emit "mtc1 zero, %out" /* mtc1 has reversed parameters */ + cost 4; /* vim: set sw=4 ts=4 expandtab : */ From 75308901bc39915266e56bf4a9a183e2fdcc8d25 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 8 Sep 2018 22:42:06 +0200 Subject: [PATCH 17/79] Added hi[] and lo[] functions to the assembler; fix things enough that we now get to the point of failing to link programs. --- mach/mips/as/mach2.c | 5 +++++ mach/mips/as/mach3.c | 2 ++ mach/mips/as/mach4.c | 25 ++++++++++++++++++++++--- mach/mips/libem/c_ud_i.s | 8 ++++---- mach/mips/libem/c_uf_i.s | 16 ++++++++-------- mach/mips/libem/trp.s | 4 ++-- 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index 9c81ed9a8..48fce7760 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -5,6 +5,9 @@ %token OP_LI %token OP_LA +%token HI +%token LO + %type gpr fpr %type e16 e9 %type u25 u20 u16 u5 u3 @@ -14,6 +17,8 @@ %type fcond %type extmsblsb insmsblsb +%type hilo +%type extabsexp #include "definitions.y" diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index d75845e7b..519bb02e3 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -76,6 +76,8 @@ 0, OP_LI, 0, "li", 0, OP_LA, 0, "la", +0, HI, RELOMIPSHI, "hi", +0, LO, RELOMIPS, "lo", #include "tokens.y" diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index fddeb25c7..7b2e7e2e0 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -31,6 +31,20 @@ emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */ } +extabsexp + : absexp + | hilo ASC_LPAR expr ASC_RPAR + { + newrelo($3.typ, $1 | FIXUPFLAGS); + $$ = $3.val; + } + ; + +hilo + : HI { $$ = $1; } + | LO { $$ = $1; } + ; + gpr: GPR fpr: FPR @@ -40,7 +54,11 @@ fmt3 | OP__DOT_W { $$ = 4; } | OP__DOT_L { $$ = 5; } | OP__DOT_PS { $$ = 6; } -fmt: fmt3 { $$ = $1 + 16; } + ; + +fmt + : fmt3 { $$ = $1 + 16; } + ; fcond : OP__DOT_F { $$ = 0; } @@ -59,9 +77,10 @@ fcond | OP__DOT_NGE { $$ = 13; } | OP__DOT_LE { $$ = 14; } | OP__DOT_NGT { $$ = 15; } + ; e16 - : absexp + : extabsexp { /* Allow signed or unsigned 16-bit values. */ if (($1 < -0x8000) || ($1 > 0xffff)) @@ -99,7 +118,7 @@ u20 ; u16 - : absexp + : extabsexp { if (($1 < 0) || ($1 > 0xffff)) serror("16-bit unsigned value out of range"); diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index e9c9dda19..c0dc10b32 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -4,16 +4,16 @@ .sect .data .sect .bss -.data - +.sect .text .define .c_ud_i .c_ud_i: /* Input: f0 * Output: r2 * Only at and f31 may be used. */ - li at, hi(.fd_80000000) - ldc1 f31, lo(.fd_800000000)(at) + + ori at, zero, hi[.fd_80000000] + ldc1 f31, lo[.fd_80000000] (at) c.le.d 0, f31, f0 bc1t toobig nop diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index ac0642fc7..6dd9f2360 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -4,28 +4,28 @@ .sect .data .sect .bss -.data - +.sect .text .define .c_uf_i .c_uf_i: /* Input: f0 * Output: r2 * Only at and f31 may be used. */ - li at, hi(.fd_80000000) - lwc1 f31, lo(.fd_800000000)(at) - c.le.f 0, f31, f0 + + ori at, zero, hi[.ff_80000000] + lwc1 f31, lo[.ff_80000000] (at) + c.le.s 0, f31, f0 bc1t toobig nop - trunc.w.f f0, f0 + trunc.w.s f0, f0 mfc1 r2, f0 jr ra nop toobig: - sub.f f0, f0, f31 - trunc.w.f f0, f0 + sub.s f0, f0, f31 + trunc.w.s f0, f0 mfc1 r2, f0 addiu r2, r2, 0x8000 jr ra diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s index 7801d471c..58187079e 100644 --- a/mach/mips/libem/trp.s +++ b/mach/mips/libem/trp.s @@ -8,6 +8,6 @@ li r3, 20 ! ECASE = 20 in h/em_abs.h ! FALLTHROUGH to .trp -.trap: - syscall +.trp: + syscall 0 From d2a1d4dcda6282ae989db07a0e0f969251fe5437 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 8 Sep 2018 23:12:57 +0200 Subject: [PATCH 18/79] Added some very untested csa and csb implementations, based on the PowerPC ones. --- mach/mips/libem/csa.s | 41 +++++++++++++++++++++++++++++++++++++ mach/mips/libem/csb.s | 47 +++++++++++++++++++++++++++++++++++++++++++ mach/mips/libem/trp.s | 1 + 3 files changed, 89 insertions(+) create mode 100644 mach/mips/libem/csa.s create mode 100644 mach/mips/libem/csb.s diff --git a/mach/mips/libem/csa.s b/mach/mips/libem/csa.s new file mode 100644 index 000000000..b03572511 --- /dev/null +++ b/mach/mips/libem/csa.s @@ -0,0 +1,41 @@ +# +.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 -- ) + */ + +.define .csa +.csa: + lw r4, 0(sp) /* r4 = table */ + lw r5, 0(sp) /* r5 = value */ + addiu sp, sp, 8 + + lw r6, 0(r4) /* r6 = default target */ + lw r7, 4(r4) /* r7 = lower bound */ + subu r5, r5, r6 /* adjust value */ + bltz r5, 1f /* jump to default if out of range */ + nop + + lw r7, 8(r4) /* fetch range */ + subu r7, r5, r7 /* compute (adjusted value - range) */ + blez 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 diff --git a/mach/mips/libem/csb.s b/mach/mips/libem/csb.s new file mode 100644 index 000000000..acc1f636e --- /dev/null +++ b/mach/mips/libem/csb.s @@ -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, 0(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 + diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s index 58187079e..827a50b85 100644 --- a/mach/mips/libem/trp.s +++ b/mach/mips/libem/trp.s @@ -8,6 +8,7 @@ li r3, 20 ! ECASE = 20 in h/em_abs.h ! FALLTHROUGH to .trp +.define .trp .trp: syscall 0 From 0d8d98fd0fb0aaccc4fb65d9075eea6049052960 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 12:22:59 +0200 Subject: [PATCH 19/79] Warning fix. --- mach/proto/as/comm2.y | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mach/proto/as/comm2.y b/mach/proto/as/comm2.y index 20b729cf3..1b3e19917 100644 --- a/mach/proto/as/comm2.y +++ b/mach/proto/as/comm2.y @@ -58,14 +58,6 @@ static item_t *last_it, *o_it; %token LINE %token FILe %token LIST -%token OP_EQ -%token OP_NE -%token OP_LE -%token OP_GE -%token OP_LL -%token OP_RR -%token OP_OO -%token OP_AA %left OP_OO %left OP_AA From b3b7c684c68e767923446eac347d21206f20d52c Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 12:23:59 +0200 Subject: [PATCH 20/79] Simplify MIPS relocations. Add RELS2 (for generic high-word relocations). Add support for MIPS branch-and-jump relocations. --- h/out.h | 4 +-- mach/mips/as/mach3.c | 4 +-- mach/mips/as/mach4.c | 4 +-- util/led/relocate.c | 71 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 8 deletions(-) diff --git a/h/out.h b/h/out.h index 4176fd341..cb7995133 100644 --- a/h/out.h +++ b/h/out.h @@ -68,9 +68,9 @@ struct outname { #define RELOPPC 4 /* PowerPC 26-bit address */ #define RELOPPC_LIS 5 /* PowerPC lis */ #define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ -#define RELOMIPS 7 /* MIPS, low half of word or other*/ -#define RELOMIPSHI 8 /* MIPS, high half of word */ +#define RELOMIPS 7 /* MIPS */ +#define RELS2 0x1000 /* shift result right 16 bits before writing back */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ #define RELWR 0x8000 /* High order word lowest address. */ diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 519bb02e3..98e62c044 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -76,8 +76,8 @@ 0, OP_LI, 0, "li", 0, OP_LA, 0, "la", -0, HI, RELOMIPSHI, "hi", -0, LO, RELOMIPS, "lo", +0, HI, RELO2|RELS2,"hi", +0, LO, RELO2, "lo", #include "tokens.y" diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 7b2e7e2e0..45c1bedc6 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -24,10 +24,10 @@ word_t val = $4.val; if (type != S_ABS) - newrelo($4.typ, RELOMIPSHI | FIXUPFLAGS); + newrelo($4.typ, RELO2 | RELS2 | FIXUPFLAGS); emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ if (type != S_ABS) - newrelo($4.typ, RELOMIPS | FIXUPFLAGS); + newrelo($4.typ, RELO2 | FIXUPFLAGS); emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */ } diff --git a/util/led/relocate.c b/util/led/relocate.c index f2e9f784d..8b34e8ec2 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -179,6 +179,30 @@ static uint32_t get_lis_valu(char *addr, uint16_t type) return valu; } +/* RELOMIPS is used for j and b instructions only. */ +static uint32_t get_mips_valu(char* addr) +{ + uint32_t value = read4(addr, 0); + switch (value >> 26) + { + case 2: /* j */ + case 3: /* jal */ + case 29: /* jalx */ + /* Unsigned 26-bit payload. */ + value = value & ((1<<26)-1); + break; + + default: /* assume everything else is a b, there are lots */ + /* Signed 16-bit payload. */ + value = ((int32_t)value << 16) >> 16; + break; + } + + /* The value has two implicit zero bits on the bottom. */ + value <<= 2; + return value; +} + /* * The bits in type indicate how many bytes the value occupies and what * significance should be attributed to each byte. @@ -198,8 +222,10 @@ static uint32_t getvalu(char* addr, uint16_t type) return get_lis_valu(addr, type); case RELOVC4: return get_vc4_valu(addr); + case RELOMIPS: + return get_mips_valu(addr); default: - fatal("bad relocation type %x", type & RELSZ); + fatal("can't read relocation type %x", type & RELSZ); } /* NOTREACHED */ } @@ -369,6 +395,36 @@ static void put_lis_valu(char* addr, uint32_t value, uint16_t type) write4(opcode, addr, type); } +/* RELOMIPS is used for j and b instructions only. */ +static void put_mips_valu(char* addr, uint32_t value) +{ + uint32_t opcode = read4(addr, 0); + + /* The two bottom zero bits are implicit. */ + if (value & 3) + fatal("invalid MIPS relocation value 0x%x", value); + value >>= 2; + + switch (value >> 26) + { + case 2: /* j */ + case 3: /* jal */ + case 29: /* jalx */ + /* Unsigned 26-bit payload. */ + value = value & ((1<<26)-1); + opcode = opcode & ~((1<<26)-1); + break; + + default: /* assume everything else is a b, there are lots */ + /* Signed 16-bit payload. */ + value = value & ((1<<16)-1); + opcode = opcode & ~((1<<16)-1); + break; + } + + write4(opcode | value, addr, 0); +} + /* * The bits in type indicate how many bytes the value occupies and what * significance should be attributed to each byte. @@ -396,8 +452,11 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) case RELOVC4: put_vc4_valu(addr, valu); break; + case RELOMIPS: + put_mips_valu(addr, valu); + break; default: - fatal("bad relocation type %x", type & RELSZ); + fatal("can't write relocation type %x", type & RELSZ); } } @@ -506,6 +565,14 @@ relocate(head, emit, names, relo, off) if (relo->or_type & RELPC) valu -= relorig[sectindex].org_size+outsect[sectindex].os_base; + /* + * If RELS2 is set, right shift the value by sixteen bits; this + * allows 32-bit values to be fixed up as a high word and a low + * word. + */ + if (relo->or_type & RELS2) + valu >>= 16; + /* * Now put the value back. */ From 95dd6f0141576d391e9d9df5a09fb046249be8a1 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 12:24:22 +0200 Subject: [PATCH 21/79] Fix some niggling issues --- we have our first binary now! --- mach/mips/libem/csa.s | 1 + mach/mips/libem/fd_80000000.s | 3 +-- mach/mips/libem/ff_80000000.s | 3 +-- mach/mips/libem/trp.s | 2 ++ 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mach/mips/libem/csa.s b/mach/mips/libem/csa.s index b03572511..1bdd41b62 100644 --- a/mach/mips/libem/csa.s +++ b/mach/mips/libem/csa.s @@ -9,6 +9,7 @@ * Stack: ( value tableaddr -- ) */ +.sect .text .define .csa .csa: lw r4, 0(sp) /* r4 = table */ diff --git a/mach/mips/libem/fd_80000000.s b/mach/mips/libem/fd_80000000.s index 1cc52cab0..3618d0b44 100644 --- a/mach/mips/libem/fd_80000000.s +++ b/mach/mips/libem/fd_80000000.s @@ -1,10 +1,9 @@ # .sect .text; .sect .rom; .sect .data; .sect .bss -.sect .rom - /* 2147483648 as a double; used as a pivot for double->unsigned and unsigned->double. */ +.sect .rom .define .fd_80000000 .fd_80000000: .data4 0x41e00000, 0 diff --git a/mach/mips/libem/ff_80000000.s b/mach/mips/libem/ff_80000000.s index 54e274fb5..95e4f9506 100644 --- a/mach/mips/libem/ff_80000000.s +++ b/mach/mips/libem/ff_80000000.s @@ -1,10 +1,9 @@ # .sect .text; .sect .rom; .sect .data; .sect .bss -.sect .rom - /* 2147483648 as a float; used as a pivot for double->float and unsigned->float. */ +.sect .rom .define .ff_80000000 .ff_80000000: .data4 0x4f000000 diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s index 827a50b85..1794459f6 100644 --- a/mach/mips/libem/trp.s +++ b/mach/mips/libem/trp.s @@ -1,8 +1,10 @@ +# .sect .text .sect .rom .sect .data .sect .bss +.sect .text .define .trap_ecase .trap_ecase: li r3, 20 ! ECASE = 20 in h/em_abs.h From 5dfef6f1800d5ce930a1644f1639c27faa7804e9 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 14:11:11 +0200 Subject: [PATCH 22/79] Rework relocations again: add RELO2HI and RELO2HISAD for the high two bytes of a word. --- h/out.h | 3 ++- mach/mips/as/mach0.c | 4 +--- mach/mips/as/mach2.c | 6 +++--- mach/mips/as/mach3.c | 5 +++-- mach/mips/as/mach4.c | 27 ++++++++++++++++++--------- mach/mips/libem/c_ud_i.s | 4 ++-- mach/mips/libem/c_uf_i.s | 4 ++-- util/amisc/ashow.c | 9 +++++++++ util/led/relocate.c | 18 +++++++++--------- 9 files changed, 49 insertions(+), 31 deletions(-) diff --git a/h/out.h b/h/out.h index cb7995133..ac770738b 100644 --- a/h/out.h +++ b/h/out.h @@ -69,8 +69,9 @@ struct outname { #define RELOPPC_LIS 5 /* PowerPC lis */ #define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #define RELOMIPS 7 /* MIPS */ +#define RELO2HI 8 /* high 2 bytes of word */ +#define RELO2HISAD 9 /* high 2 bytes of word, sign adjusted */ -#define RELS2 0x1000 /* shift result right 16 bits before writing back */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ #define RELWR 0x8000 /* High order word lowest address. */ diff --git a/mach/mips/as/mach0.c b/mach/mips/as/mach0.c index f390bccf5..edce6640b 100644 --- a/mach/mips/as/mach0.c +++ b/mach/mips/as/mach0.c @@ -4,8 +4,6 @@ */ #define THREE_PASS /* branch and offset optimization */ -#define BYTES_REVERSED /* high order byte has lowest address */ -#define WORDS_REVERSED /* high order word has lowest address */ #define LISTING /* enable listing facilities */ #define RELOCATION /* generate relocatable code */ #define DEBUG 0 @@ -28,4 +26,4 @@ #undef VALWIDTH #define VALWIDTH 8 -#define FIXUPFLAGS (RELBR | RELWR) +#define FIXUPFLAGS 0 diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index 48fce7760..9b11f1f1c 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -5,8 +5,9 @@ %token OP_LI %token OP_LA -%token HI -%token LO +%token HI16 +%token HA16 +%token LO16 %type gpr fpr %type e16 e9 @@ -17,7 +18,6 @@ %type fcond %type extmsblsb insmsblsb -%type hilo %type extabsexp #include "definitions.y" diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 98e62c044..008759d9d 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -76,8 +76,9 @@ 0, OP_LI, 0, "li", 0, OP_LA, 0, "la", -0, HI, RELO2|RELS2,"hi", -0, LO, RELO2, "lo", +0, HI16, 0, "hi16", +0, HA16, 0, "ha16", +0, LO16, 0, "lo16", #include "tokens.y" diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 45c1bedc6..da7bc1bfb 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -24,7 +24,7 @@ word_t val = $4.val; if (type != S_ABS) - newrelo($4.typ, RELO2 | RELS2 | FIXUPFLAGS); + newrelo($4.typ, RELO2HI | FIXUPFLAGS); emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ if (type != S_ABS) newrelo($4.typ, RELO2 | FIXUPFLAGS); @@ -33,16 +33,25 @@ extabsexp : absexp - | hilo ASC_LPAR expr ASC_RPAR + | LO16 ASC_LPAR expr ASC_RPAR { - newrelo($3.typ, $1 | FIXUPFLAGS); + 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; } - ; - -hilo - : HI { $$ = $1; } - | LO { $$ = $1; } ; gpr: GPR @@ -147,7 +156,7 @@ u3 offset16 : expr { - int dist = $1.val - DOTVAL; + int dist = $1.val - DOTVAL - 4; fit(fitx(dist, 18)); if (dist & 0x3) diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index c0dc10b32..c43658b23 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -12,8 +12,8 @@ * Only at and f31 may be used. */ - ori at, zero, hi[.fd_80000000] - ldc1 f31, lo[.fd_80000000] (at) + ori at, zero, hi16[.fd_80000000] + ldc1 f31, lo16[.fd_80000000] (at) c.le.d 0, f31, f0 bc1t toobig nop diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 6dd9f2360..0a4af443d 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -12,8 +12,8 @@ * Only at and f31 may be used. */ - ori at, zero, hi[.ff_80000000] - lwc1 f31, lo[.ff_80000000] (at) + ori at, zero, hi16[.ff_80000000] + lwc1 f31, lo16[.ff_80000000] (at) c.le.s 0, f31, f0 bc1t toobig nop diff --git a/util/amisc/ashow.c b/util/amisc/ashow.c index 6ead9db6c..107e5f8ed 100644 --- a/util/amisc/ashow.c +++ b/util/amisc/ashow.c @@ -134,6 +134,12 @@ showrelo() case RELO2: printf("\t2 bytes\n"); break; + case RELO2HI: + printf("\ttop 2 bytes of result\n"); + break; + case RELO2HISAD: + printf("\ttop 2 bytes of result, sign adjusted\n"); + break; case RELO4: printf("\t4 bytes\n"); break; @@ -146,6 +152,9 @@ showrelo() case RELOVC4: printf("\tVideoCore IV address in 32-bit instruction\n"); break; + case RELOMIPS: + printf("\tMIPS b or j instruction\n"); + break; default: printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ); break; diff --git a/util/led/relocate.c b/util/led/relocate.c index 8b34e8ec2..1f1dc89e6 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -213,6 +213,8 @@ static uint32_t getvalu(char* addr, uint16_t type) case RELO1: return UBYTE(addr[0]); case RELO2: + case RELO2HI: + case RELO2HISAD: return read2(addr, type); case RELO4: return read4(addr, type); @@ -405,7 +407,7 @@ static void put_mips_valu(char* addr, uint32_t value) fatal("invalid MIPS relocation value 0x%x", value); value >>= 2; - switch (value >> 26) + switch (opcode >> 26) { case 2: /* j */ case 3: /* jal */ @@ -440,6 +442,12 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) case RELO2: write2(valu, addr, type); break; + case RELO2HI: + write2(valu>>16, addr, type); + break; + case RELO2HISAD: + write2((valu>>16) + !!(valu&0x8000), addr, type); + break; case RELO4: write4(valu, addr, type); break; @@ -565,14 +573,6 @@ relocate(head, emit, names, relo, off) if (relo->or_type & RELPC) valu -= relorig[sectindex].org_size+outsect[sectindex].os_base; - /* - * If RELS2 is set, right shift the value by sixteen bits; this - * allows 32-bit values to be fixed up as a high word and a low - * word. - */ - if (relo->or_type & RELS2) - valu >>= 16; - /* * Now put the value back. */ From ec46643124d144b49bb1baebd5d79e9abdea09c2 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 14:29:34 +0200 Subject: [PATCH 23/79] Allow the ELF processor flags to be set. Generate MIPS ELF executables, not PowerPC ones. --- plat/linuxmips/descr | 2 +- util/amisc/aelflod.1 | 4 ++++ util/amisc/aelflod.c | 11 ++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plat/linuxmips/descr b/plat/linuxmips/descr index ad7f5180f..1afa470a7 100644 --- a/plat/linuxmips/descr +++ b/plat/linuxmips/descr @@ -82,6 +82,6 @@ name cv from .out to .exe program {EM}/bin/aelflod - args -m20 -b < > + args -m8 -l -f0x70000000 < > outfile linuxmips.exe end diff --git a/util/amisc/aelflod.1 b/util/amisc/aelflod.1 index e6af7ef2e..9c6134b33 100644 --- a/util/amisc/aelflod.1 +++ b/util/amisc/aelflod.1 @@ -35,6 +35,10 @@ 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 diff --git a/util/amisc/aelflod.c b/util/amisc/aelflod.c index dbaafc9b5..de4bcedd8 100644 --- a/util/amisc/aelflod.c +++ b/util/amisc/aelflod.c @@ -33,6 +33,7 @@ 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. */ @@ -643,7 +644,7 @@ int main(int argc, char* argv[]) switch (argv[1][1]) { case 'a': - elfabi = atoi(&argv[1][2]); + elfabi = strtoul(&argv[1][2], NULL, 0); break; case 'b': @@ -660,7 +661,11 @@ int main(int argc, char* argv[]) break; case 'm': - elfmachine = atoi(&argv[1][2]); + elfmachine = strtoul(&argv[1][2], NULL, 0); + break; + + case 'f': + elfflags = strtoul(&argv[1][2], NULL, 0); break; case 'v': @@ -808,7 +813,7 @@ int main(int argc, char* argv[]) emit32(outsect[TEXT].os_base); /* entry point */ emit32(ELF_HEADER_SIZE); /* program header offset */ emit32(sh_offset); /* section header offset */ - emit32(0); /* flags */ + 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 */ From e88670dad4c74419fc3981fe950fd79a02d3ce7a Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 18:25:00 +0200 Subject: [PATCH 24/79] Yikes! Turns out that FPU registers are only 32 bits wide, and doubles are stored in pairs, just like on the PowerPC! --- mach/mips/libem/c_ud_i.s | 8 +++--- mach/mips/libem/c_uf_i.s | 8 +++--- mach/mips/mcg/platform.c | 8 +++--- mach/mips/mcg/table | 61 +++++++++++++++------------------------- 4 files changed, 34 insertions(+), 51 deletions(-) diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index c43658b23..cfb9668ea 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -9,12 +9,12 @@ .c_ud_i: /* Input: f0 * Output: r2 - * Only at and f31 may be used. + * Only at and f30/f31 may be used. */ ori at, zero, hi16[.fd_80000000] - ldc1 f31, lo16[.fd_80000000] (at) - c.le.d 0, f31, f0 + ldc1 f30, lo16[.fd_80000000] (at) + c.le.d 0, f30, f0 bc1t toobig nop @@ -24,7 +24,7 @@ nop toobig: - sub.d f0, f0, f31 + sub.d f0, f0, f30 trunc.w.d f0, f0 mfc1 r2, f0 addiu r2, r2, 0x8000 diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 0a4af443d..f8b7f5f22 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -9,12 +9,12 @@ .c_uf_i: /* Input: f0 * Output: r2 - * Only at and f31 may be used. + * Only at and f30/f31 may be used. */ ori at, zero, hi16[.ff_80000000] - lwc1 f31, lo16[.ff_80000000] (at) - c.le.s 0, f31, f0 + lwc1 f30, lo16[.ff_80000000] (at) + c.le.s 0, f30, f0 bc1t toobig nop @@ -24,7 +24,7 @@ nop toobig: - sub.s f0, f0, f31 + sub.s f0, f0, f30 trunc.w.s f0, f0 mfc1 r2, f0 addiu r2, r2, 0x8000 diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index cd3a3762b..998b5dcdb 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -320,15 +320,15 @@ struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* break; case burm_float_ATTR: - hop_add_insel(hop, "mov.s f31, %H", src); + 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, f31", dest); + hop_add_insel(hop, "mov.s %H, f30", dest); break; case burm_double_ATTR: - hop_add_insel(hop, "mov.d f31, %H", src); + 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, f31", dest); + hop_add_insel(hop, "mov.d %H, f30", dest); break; } diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 76ca419f2..5b5c1ae98 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -75,41 +75,24 @@ REGISTERS f27 float; f28 float; f29 float; - f30 float; - /* f31 is used by the compiler as a temporary. */ + /* f30 and f31 is used by the compiler as a temporary. */ - d0 named("f0") aliases(f0) double volatile dret; - d1 named("f1") aliases(f1) double volatile; - d2 named("f2") aliases(f2) double volatile; - d3 named("f3") aliases(f3) double volatile; - d4 named("f4") aliases(f4) double volatile; - d5 named("f5") aliases(f5) double volatile; - d6 named("f6") aliases(f6) double volatile; - d7 named("f7") aliases(f7) double volatile; - d8 named("f8") aliases(f8) double volatile; - d9 named("f9") aliases(f9) double volatile; - d10 named("f10") aliases(f10) double volatile; - d11 named("f11") aliases(f11) double volatile; - d12 named("f12") aliases(f12) double volatile; - d13 named("f13") aliases(f13) double volatile; - d14 named("f14") aliases(f14) double volatile; - d15 named("f15") aliases(f15) double volatile; - d16 named("f16") aliases(f16) double volatile; - d17 named("f17") aliases(f17) double volatile; - d18 named("f18") aliases(f18) double volatile; - d19 named("f19") aliases(f19) double volatile; + d0 named("f0") aliases(f0, f1) double volatile dret; + d2 named("f2") aliases(f2, f3) double volatile; + d4 named("f4") aliases(f4, f5) double volatile; + d6 named("f6") aliases(f6, f7) double volatile; + d8 named("f8") aliases(f8, f9) double volatile; + d10 named("f10") aliases(f10, f11) double volatile; + d12 named("f12") aliases(f12, f13) double volatile; + d14 named("f14") aliases(f14, f15) double volatile; + d16 named("f16") aliases(f16, f17) double volatile; + d18 named("f18") aliases(f18, f19) double volatile; - d20 named("f20") aliases(f20) double; - d21 named("f21") aliases(f21) double; - d22 named("f22") aliases(f22) double; - d23 named("f23") aliases(f23) double; - d24 named("f24") aliases(f24) double; - d25 named("f25") aliases(f25) double; - d26 named("f26") aliases(f26) double; - d27 named("f27") aliases(f27) double; - d28 named("f28") aliases(f28) double; - d29 named("f29") aliases(f29) double; - d30 named("f30") aliases(f30) double; + d20 named("f20") aliases(f20, f21) double; + d22 named("f22") aliases(f22, f23) double; + d24 named("f24") aliases(f24, f25) double; + d26 named("f26") aliases(f26, f27) double; + d28 named("f28") aliases(f28, f29) double; @@ -425,7 +408,7 @@ PATTERNS FARJUMP(addr:LABEL.I) with corrupted(volatile) - emit "b $addr" + emit "j $addr" emit "nop" cost 8; @@ -458,7 +441,7 @@ PATTERNS #define CALLLABEL(insn) \ insn (dest:LABEL.I) \ with corrupted(volatile) \ - emit "bal $dest" \ + emit "jal $dest" \ emit "nop" \ cost 8; @@ -695,8 +678,8 @@ PATTERNS cost 30; out:(int)reg = FROMSD.I(in:(double)reg) - emit "trunc.w.d f31, %in" - emit "mfc1 %out, f31" + emit "trunc.w.d f30, %in" + emit "mfc1 %out, f30" cost 8; out:(lret)reg = FROMSD.L(in:(dret)reg) @@ -748,8 +731,8 @@ PATTERNS cost 4; out:(int)reg = FROMSF.I(in:(float)reg) - emit "trunc.w.s f31, %in" - emit "mfc1 %out, f31" + emit "trunc.w.s f30, %in" + emit "mfc1 %out, f30" cost 8; out:(lret)reg = FROMSF.L(in:(fret)reg) From bb15c033399ebb939c4f9963288d6a1aaba54f6a Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 18:53:49 +0200 Subject: [PATCH 25/79] Remember to preserve input registers if we're going to be reading from them after writing to the output register. --- mach/mips/mcg/table | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 5b5c1ae98..f7d0b423a 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -363,6 +363,7 @@ PATTERNS cost 8; out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg) + with preserved(%in1), preserved(%in2) emit "mov %out.0, %in1" emit "mov %out.1, %in2" cost 8; @@ -472,6 +473,7 @@ PATTERNS /* The COMPARE nodes return tristate integer values; -1, 0 or 1. */ out:(int)reg = COMPARESI.I(left:(int)reg, right:(int)reg) + with preserved(%left), preserved(%right) emit "slt at, %left, %right" emit "bne at, zero, 1f" emit "li %out, -1" /* delay slot */ @@ -480,6 +482,7 @@ PATTERNS cost 20; out:(int)reg = COMPAREUI.I(left:(int)reg, right:(int)reg) + with preserved(%left), preserved(%right) emit "sltu at, %left, %right" emit "bne at, zero, 1f" emit "li %out, -1" /* delay slot */ @@ -488,6 +491,7 @@ PATTERNS cost 20; out:(int)reg = COMPAREF.I(left:(float)reg, right:(float)reg) + with preserved(%left), preserved(%right) emit "c.lt.s 0, %left, %right" emit "li %out, -1" emit "bc1t 0, 1f" @@ -499,6 +503,7 @@ PATTERNS cost 28; out:(int)reg = COMPARED.I(left:(double)reg, right:(double)reg) + with preserved(%left), preserved(%right) emit "c.lt.d 0, %left, %right" emit "li %out, -1" emit "bc1t 0, 1f" From f3bc9ef92a8bcd012c9eea30676eca19f567f0f7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 18:57:12 +0200 Subject: [PATCH 26/79] Call proper Linux system calls proper-like. --- plat/linuxmips/libsys/_syscall.s | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plat/linuxmips/libsys/_syscall.s b/plat/linuxmips/libsys/_syscall.s index 75c551d20..8d5ecde90 100644 --- a/plat/linuxmips/libsys/_syscall.s +++ b/plat/linuxmips/libsys/_syscall.s @@ -14,5 +14,21 @@ .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 + From c769fbec93ea08c1c4d1f4a09e0bc7103b9b3bf7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 18:57:35 +0200 Subject: [PATCH 27/79] Use the correct ELF processor flags; align properly. --- plat/linuxmips/descr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plat/linuxmips/descr b/plat/linuxmips/descr index 1afa470a7..7da3fbff1 100644 --- a/plat/linuxmips/descr +++ b/plat/linuxmips/descr @@ -18,7 +18,7 @@ var ARCH=mips var PLATFORM=linuxmips var PLATFORMDIR={EM}/share/ack/{PLATFORM} var CPP_F=-D__unix -var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x00400054 +var ALIGN=-a0:8 -a1:8 -a2:8 -a3:8 -b0:0x00400058 var MACHOPT_F=-m2 #var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr @@ -82,6 +82,6 @@ name cv from .out to .exe program {EM}/bin/aelflod - args -m8 -l -f0x70000000 < > + args -m8 -l -f0x70001000 < > outfile linuxmips.exe end From 776e93221f439117a96f7ce454d22ad6d804b496 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 18:57:44 +0200 Subject: [PATCH 28/79] Thinko fix. --- plat/linuxmips/boot.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plat/linuxmips/boot.s b/plat/linuxmips/boot.s index cc6d9ce32..eed95ebd4 100644 --- a/plat/linuxmips/boot.s +++ b/plat/linuxmips/boot.s @@ -34,10 +34,10 @@ begtext: addiu sp, sp, -3 * 4 sw r4, 0(sp) - sw r5, 0(sp) - sw r6, 0(sp) + sw r5, 4(sp) + sw r6, 8(sp) - b __m_a_i_n + j __m_a_i_n nop ! Define symbols at the beginning of our various segments, so that we can find From f8f6fa9fc1bca1734c178c048b8fb629ccc81f1c Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 00:21:16 +0200 Subject: [PATCH 29/79] Added some more incredibly untested helper functions. --- mach/mips/libem/bls4.s | 30 +++++++++++++++++++ mach/mips/libem/c_ud_i.s | 12 +++++--- mach/mips/libem/c_uf_i.s | 5 ++++ mach/mips/libem/c_ui_d.s | 26 ++++++++++++++++ mach/mips/libem/c_ui_f.s | 26 ++++++++++++++++ mach/mips/libem/fd_80000000.s | 10 ------- mach/mips/libem/fef8.s | 56 +++++++++++++++++++++++++++++++++++ mach/mips/libem/ff_80000000.s | 10 ------- 8 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 mach/mips/libem/bls4.s create mode 100644 mach/mips/libem/c_ui_d.s create mode 100644 mach/mips/libem/c_ui_f.s delete mode 100644 mach/mips/libem/fd_80000000.s create mode 100644 mach/mips/libem/fef8.s delete mode 100644 mach/mips/libem/ff_80000000.s diff --git a/mach/mips/libem/bls4.s b/mach/mips/libem/bls4.s new file mode 100644 index 000000000..559e23fe2 --- /dev/null +++ b/mach/mips/libem/bls4.s @@ -0,0 +1,30 @@ +# +.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 + +2: + jr ra + nop diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index cfb9668ea..ccd798e03 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -1,8 +1,5 @@ # -.sect .text -.sect .rom -.sect .data -.sect .bss +.sect .text; .sect .rom; .sect .data; .sect .bss .sect .text .define .c_ud_i @@ -30,3 +27,10 @@ toobig: addiu r2, r2, 0x8000 jr ra nop + +/* 2147483648 as a double. */ +.sect .rom +.define .fd_80000000 +.fd_80000000: + .data4 0, 0x41e00000 + diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index f8b7f5f22..8bd840b40 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -31,3 +31,8 @@ toobig: jr ra nop +/* 2147483648 as a float. */ +.sect .rom +.ff_80000000: + .data4 0x4f000000 + diff --git a/mach/mips/libem/c_ui_d.s b/mach/mips/libem/c_ui_d.s new file mode 100644 index 000000000..c46a2cf4a --- /dev/null +++ b/mach/mips/libem/c_ui_d.s @@ -0,0 +1,26 @@ +# +.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 + + ori at, zero, hi16[.fd_100000000] + ldc1 f30, lo16[.fd_100000000] (at) + add.d f0, f0, f30 +nonnegative: + jr ra + nop + +/* 4294967296 as a double. */ +.sect .rom +.fd_100000000: + .data4 0, 0x41f00000 diff --git a/mach/mips/libem/c_ui_f.s b/mach/mips/libem/c_ui_f.s new file mode 100644 index 000000000..46f9f0b62 --- /dev/null +++ b/mach/mips/libem/c_ui_f.s @@ -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 + + ori at, zero, hi16[.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: + .data4 0x4f800000 diff --git a/mach/mips/libem/fd_80000000.s b/mach/mips/libem/fd_80000000.s deleted file mode 100644 index 3618d0b44..000000000 --- a/mach/mips/libem/fd_80000000.s +++ /dev/null @@ -1,10 +0,0 @@ -# -.sect .text; .sect .rom; .sect .data; .sect .bss - -/* 2147483648 as a double; used as a pivot for double->unsigned and unsigned->double. */ - -.sect .rom -.define .fd_80000000 -.fd_80000000: - .data4 0x41e00000, 0 - diff --git a/mach/mips/libem/fef8.s b/mach/mips/libem/fef8.s new file mode 100644 index 000000000..4fa545676 --- /dev/null +++ b/mach/mips/libem/fef8.s @@ -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 diff --git a/mach/mips/libem/ff_80000000.s b/mach/mips/libem/ff_80000000.s deleted file mode 100644 index 95e4f9506..000000000 --- a/mach/mips/libem/ff_80000000.s +++ /dev/null @@ -1,10 +0,0 @@ -# -.sect .text; .sect .rom; .sect .data; .sect .bss - -/* 2147483648 as a float; used as a pivot for double->float and unsigned->float. */ - -.sect .rom -.define .ff_80000000 -.ff_80000000: - .data4 0x4f000000 - From 185e910246b3c372a09abccf1e934816324f0d76 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 01:08:25 +0200 Subject: [PATCH 30/79] Lots more untested helper functions. --- mach/mips/libem/aar4.s | 39 ++++++++++++++++++++++++++++++ mach/mips/libem/dus4.s | 28 +++++++++++++++++++++ mach/mips/libem/exg.s | 31 ++++++++++++++++++++++++ mach/mips/libem/inn.s | 33 +++++++++++++++++++++++++ mach/mips/libem/lar4.s | 23 ++++++++++++++++++ mach/mips/libem/los4.s | 55 ++++++++++++++++++++++++++++++++++++++++++ mach/mips/libem/rck.s | 33 +++++++++++++++++++++++++ mach/mips/libem/trp.s | 2 +- 8 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 mach/mips/libem/aar4.s create mode 100644 mach/mips/libem/dus4.s create mode 100644 mach/mips/libem/exg.s create mode 100644 mach/mips/libem/inn.s create mode 100644 mach/mips/libem/lar4.s create mode 100644 mach/mips/libem/los4.s create mode 100644 mach/mips/libem/rck.s diff --git a/mach/mips/libem/aar4.s b/mach/mips/libem/aar4.s new file mode 100644 index 000000000..fc1068f48 --- /dev/null +++ b/mach/mips/libem/aar4.s @@ -0,0 +1,39 @@ +# +.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) + */ + +.sect .text +.define .aar4 +.aar4: + lw r4, 0(sp) ! r4 = address of descriptor + lw r5, 0(sp) ! r5 = index + lw r6, 0(sp) ! r6 = address of array + + lw r7, 0(r4) ! at = lower bound + slt at, r7, at ! at = r5 < at + bne at, zero, .trap_earray + + lw at, 4(r4) ! at = upper bound + slt at, at, r5 ! at = at < r5 + bne at, zero, .trap_earray + + lw r2, 8(r4) ! r2 = size of element + subu r5, r5, r7 ! adjust index for non-zero lower bound + 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 diff --git a/mach/mips/libem/dus4.s b/mach/mips/libem/dus4.s new file mode 100644 index 000000000..ca5a295a9 --- /dev/null +++ b/mach/mips/libem/dus4.s @@ -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 diff --git a/mach/mips/libem/exg.s b/mach/mips/libem/exg.s new file mode 100644 index 000000000..24753f328 --- /dev/null +++ b/mach/mips/libem/exg.s @@ -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 diff --git a/mach/mips/libem/inn.s b/mach/mips/libem/inn.s new file mode 100644 index 000000000..07a4991b6 --- /dev/null +++ b/mach/mips/libem/inn.s @@ -0,0 +1,33 @@ +# +.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, 0(sp) ! r5 = bit number + addiu sp, sp, 8 ! sp now points at bitset + + srl r6, r5, 3 ! r6 = offset of word in set + addu r6, sp, r6 ! r6 = address of word in set + lw r6, 0(r6) ! r6 = word + + ext r7, r5, 0, 3 ! 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 + + addiu sp, sp, -4 + sw r6, 0(sp) ! push result + + jr ra + nop diff --git a/mach/mips/libem/lar4.s b/mach/mips/libem/lar4.s new file mode 100644 index 000000000..870140255 --- /dev/null +++ b/mach/mips/libem/lar4.s @@ -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 diff --git a/mach/mips/libem/los4.s b/mach/mips/libem/los4.s new file mode 100644 index 000000000..be9434a34 --- /dev/null +++ b/mach/mips/libem/los4.s @@ -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 + + ! 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 ! adjust to end of block + subu sp, sp, r4 ! sp = start of block + mov r6, sp ! r6 = start of block + +1: + lw at, 0(r2) + sw at, 0(r6) + addiu r2, r2, 4 + addiu r6, r6, 4 + addiu r5, r5, -1 + bne r5, zero, 1b + nop + + jr ra + nop + +byte_sized: + lb at, 0(r4) + sw at, 0(sp) + jr ra + nop + +word_sized: + lh at, 0(r4) + sw at, 0(sp) + jr ra + nop diff --git a/mach/mips/libem/rck.s b/mach/mips/libem/rck.s new file mode 100644 index 000000000..01eca7156 --- /dev/null +++ b/mach/mips/libem/rck.s @@ -0,0 +1,33 @@ +# +.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(sp) ! at = lower bound + slt at, r5, at ! at = r5 < at + bne at, zero, .trap_erange + + lw at, 4(sp) ! at = upper bound + slt at, at, r5 ! at = at < r5 + bne at, zero, .trap_erange + + jr ra + nop + +.define .trap_erange +.trap_erange: + li r4, 1 + j .trp + nop diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s index 1794459f6..a283b07a2 100644 --- a/mach/mips/libem/trp.s +++ b/mach/mips/libem/trp.s @@ -7,7 +7,7 @@ .sect .text .define .trap_ecase .trap_ecase: - li r3, 20 ! ECASE = 20 in h/em_abs.h + li r4, 20 ! ECASE = 20 in h/em_abs.h ! FALLTHROUGH to .trp .define .trp From 6275896a1179badcc67b421d3e0c746e5585dbb1 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 22:25:14 +0200 Subject: [PATCH 31/79] Clang-format before editing. --- mach/proto/as/comm5.c | 638 +++++++++++++++++++++++------------------- 1 file changed, 352 insertions(+), 286 deletions(-) diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index e7d45c7fb..0703f3bfb 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -5,26 +5,26 @@ */ /* @(#)comm5.c 1.1 */ -#include "comm0.h" -#include "comm1.h" -#include "y.tab.h" +#include "comm0.h" +#include "comm1.h" +#include "y.tab.h" -extern YYSTYPE yylval; +extern YYSTYPE yylval; -static void readcode(int); -static int induo(int); -static int inident(int); -static int innumber(int); -static int instring(int); -static int inescape(void); -static int infbsym(const char *); +static void readcode(int); +static int induo(int); +static int inident(int); +static int innumber(int); +static int instring(int); +static int inescape(void); +static int infbsym(const char*); -int -yylex(void) +int yylex(void) { int c, c0, c1; - if (pass == PASS_1) { + if (pass == PASS_1) + { /* scan the input file */ do c = nextchar(); @@ -33,126 +33,149 @@ yylex(void) c = inident(c); else if (isdigit(c)) c = innumber(c); - else switch (c) { - case '=': - case '<': - case '>': - case '|': - case '&': - c = induo(c); break; - case ASC_SQUO: - case ASC_DQUO: - c = instring(c); break; - case ASC_COMM: - do - c = nextchar(); - while (c != '\n' && c != '\0'); - break; - case CTRL('A'): - c = CODE1; readcode(1); break; - case CTRL('B'): - c = CODE2; readcode(2); break; - case CTRL('C'): - c = CODE4; readcode(4); break; - } + else + switch (c) + { + case '=': + case '<': + case '>': + case '|': + case '&': + c = induo(c); + break; + case ASC_SQUO: + case ASC_DQUO: + c = instring(c); + break; + case ASC_COMM: + do + c = nextchar(); + while (c != '\n' && c != '\0'); + break; + case CTRL('A'): + c = CODE1; + readcode(1); + break; + case CTRL('B'): + c = CODE2; + readcode(2); + break; + case CTRL('C'): + c = CODE4; + readcode(4); + break; + } /* produce the intermediate token file */ if (c <= 0) - return(0); - if (c < 256) { + return (0); + if (c < 256) + { putc(c, tempfile); putc(0, tempfile); - } else { + } + else + { putval(c); } - } else { + } + else + { /* read from intermediate token file */ c0 = getc(tempfile); if (c0 == EOF) - return(0); + return (0); c1 = getc(tempfile); if (c1 == EOF) - return(0); + return (0); c = c0 + (c1 << 8); if (c >= 256) c = getval(c); } curr_token = c; - return(c); + return (c); } -void -putval(int c) +void putval(int c) { valu_t v; int n = 0; - char *p = 0; + char* p = 0; assert(c == (c & 0xffff)); - switch (c) { - case CODE1: - n = 1; goto putnum; - case CODE2: - n = 2; goto putnum; - case CODE4: - n = 4; goto putnum; - case NUMBER: - v = yylval.y_valu; - for (n = 0; n < sizeof(v); n++) { - if (v == 0) - break; - v >>= 8; - } - assert(n <= 4); - c = NUMBER0 + n; - putnum: - putc(c, tempfile); - putc(c >> 8, tempfile); - v = yylval.y_valu; - while (--n >= 0) - putc((int) (v >> (n*8)), tempfile); - return; - case IDENT: - case FBSYM: - n = sizeof(item_t *); - p = (char *) &yylval.y_item; break; + switch (c) + { + case CODE1: + n = 1; + goto putnum; + case CODE2: + n = 2; + goto putnum; + case CODE4: + n = 4; + goto putnum; + case NUMBER: + v = yylval.y_valu; + for (n = 0; n < sizeof(v); n++) + { + if (v == 0) + break; + v >>= 8; + } + assert(n <= 4); + c = NUMBER0 + n; + putnum: + putc(c, tempfile); + putc(c >> 8, tempfile); + v = yylval.y_valu; + while (--n >= 0) + putc((int)(v >> (n * 8)), tempfile); + return; + case IDENT: + case FBSYM: + n = sizeof(item_t*); + p = (char*)&yylval.y_item; + break; #ifdef ASLD - case MODULE: - n = sizeof(char *); - p = (char *) &yylval.y_strp; break; + case MODULE: + n = sizeof(char*); + p = (char*)&yylval.y_strp; + break; #endif - case STRING: - v = stringlen; - putc(c, tempfile); - putc(c >> 8, tempfile); - for (n = 0; n < sizeof(v); n++) { - if (v == 0) - break; - v >>= 8; - } - assert(n <= 4); - putc(n, tempfile); - v = stringlen; - while (--n >= 0) - putc((int) (v >> (n*8)), tempfile); - p = stringbuf; - n = stringlen; - while (--n >= 0) - putc(*p++, tempfile); - return; - case OP_EQ: - case OP_NE: - case OP_LE: - case OP_GE: - case OP_LL: - case OP_RR: - case OP_OO: - case OP_AA: - break; - default: - n = sizeof(word_t); - p = (char *) &yylval.y_word; break; + case STRING: + v = stringlen; + putc(c, tempfile); + putc(c >> 8, tempfile); + for (n = 0; n < sizeof(v); n++) + { + if (v == 0) + break; + v >>= 8; + } + assert(n <= 4); + putc(n, tempfile); + v = stringlen; + while (--n >= 0) + putc((int)(v >> (n * 8)), tempfile); + p = stringbuf; + n = stringlen; + while (--n >= 0) + putc(*p++, tempfile); + return; + case OP_EQ: + case OP_NE: + case OP_LE: + case OP_GE: + case OP_LL: + case OP_RR: + case OP_OO: + case OP_AA: + break; + default: + n = sizeof(word_t); + p = (char*)&yylval.y_word; + break; } putc(c, tempfile); putc(c >> 8, tempfile); @@ -160,151 +183,171 @@ putval(int c) putc(*p++, tempfile); } -int -getval(int c) +int getval(int c) { int n = 0; valu_t v; - char *p = 0; + char* p = 0; - switch (c) { - case CODE1: - n = 1; goto getnum; - case CODE2: - n = 2; goto getnum; - case CODE4: - n = 4; goto getnum; - case NUMBER0: - c = NUMBER; goto getnum; - case NUMBER1: - n = 1; c = NUMBER; goto getnum; - case NUMBER2: - n = 2; c = NUMBER; goto getnum; - case NUMBER3: - n = 3; c = NUMBER; goto getnum; - case NUMBER: - n = 4; - getnum: - v = 0; - while (--n >= 0) { - v <<= 8; - v |= getc(tempfile); - } - yylval.y_valu = v; - return(c); - case IDENT: - case FBSYM: - n = sizeof(item_t *); - p = (char *) &yylval.y_item; break; + switch (c) + { + case CODE1: + n = 1; + goto getnum; + case CODE2: + n = 2; + goto getnum; + case CODE4: + n = 4; + goto getnum; + case NUMBER0: + c = NUMBER; + goto getnum; + case NUMBER1: + n = 1; + c = NUMBER; + goto getnum; + case NUMBER2: + n = 2; + c = NUMBER; + goto getnum; + case NUMBER3: + n = 3; + c = NUMBER; + goto getnum; + case NUMBER: + n = 4; + getnum: + v = 0; + while (--n >= 0) + { + v <<= 8; + v |= getc(tempfile); + } + yylval.y_valu = v; + return (c); + case IDENT: + case FBSYM: + n = sizeof(item_t*); + p = (char*)&yylval.y_item; + break; #ifdef ASLD - case MODULE: - n = sizeof(char *); - p = (char *) &yylval.y_strp; break; + case MODULE: + n = sizeof(char*); + p = (char*)&yylval.y_strp; + break; #endif - case STRING: - getval(getc(tempfile)+NUMBER0); - stringlen = n = yylval.y_valu; - p = stringbuf; - p[n] = '\0'; break; - case OP_EQ: - case OP_NE: - case OP_LE: - case OP_GE: - case OP_LL: - case OP_RR: - case OP_OO: - case OP_AA: - break; - default: - n = sizeof(word_t); - p = (char *) &yylval.y_word; break; + case STRING: + getval(getc(tempfile) + NUMBER0); + stringlen = n = yylval.y_valu; + p = stringbuf; + p[n] = '\0'; + break; + case OP_EQ: + case OP_NE: + case OP_LE: + case OP_GE: + case OP_LL: + case OP_RR: + case OP_OO: + case OP_AA: + break; + default: + n = sizeof(word_t); + p = (char*)&yylval.y_word; + break; } while (--n >= 0) *p++ = getc(tempfile); - return(c); + return (c); } /* ---------- lexical scan in pass 1 ---------- */ -int -nextchar(void) +int nextchar(void) { int c; - if (peekc != -1) { + if (peekc != -1) + { c = peekc; peekc = -1; - return(c); + return (c); } #ifdef ASLD if (archmode && --archsize < 0) - return(0); + return (0); #endif if ((c = getc(input)) == EOF) - return(0); + return (0); if (isascii(c) == 0) fatal("non-ascii character"); #ifdef LISTING if (listflag & 0440) putc(c, listfile); #endif - return(c); + return (c); } -static void -readcode(int n) +static void readcode(int n) { int c; yylval.y_valu = 0; - do { + do + { if ( #ifdef ASLD - (archmode && --archsize < 0) - || + (archmode && --archsize < 0) || #endif - (c = getc(input)) == EOF - ) + (c = getc(input)) == EOF) fatal("unexpected EOF in compact input"); yylval.y_valu <<= 8; yylval.y_valu |= c; } while (--n); } -static int -induo(int c) +static int induo(int c) { static short duo[] = { - ('='<<8) | '=', OP_EQ, - ('<'<<8) | '>', OP_NE, - ('<'<<8) | '=', OP_LE, - ('>'<<8) | '=', OP_GE, - ('<'<<8) | '<', OP_LL, - ('>'<<8) | '>', OP_RR, - ('|'<<8) | '|', OP_OO, - ('&'<<8) | '&', OP_AA, - 0 /* terminates array */ + ('=' << 8) | '=', + OP_EQ, + ('<' << 8) | '>', + OP_NE, + ('<' << 8) | '=', + OP_LE, + ('>' << 8) | '=', + OP_GE, + ('<' << 8) | '<', + OP_LL, + ('>' << 8) | '>', + OP_RR, + ('|' << 8) | '|', + OP_OO, + ('&' << 8) | '&', + OP_AA, + 0 /* terminates array */ }; - short *p; + short* p; - c = (c<<8) | nextchar(); + c = (c << 8) | nextchar(); for (p = duo; *p; p++) if (*p++ == c) - return(*p++); + return (*p++); peekc = c & 0377; - return(c>>8); + return (c >> 8); } -static char name[NAMEMAX+1]; +static char name[NAMEMAX + 1]; -static int -inident(int c) +static int inident(int c) { - char *p = name; - item_t *ip; + char* p = name; + item_t* ip; int n = NAMEMAX; - do { + do + { if (--n >= 0) *p++ = c; c = nextchar(); @@ -312,49 +355,52 @@ inident(int c) *p = '\0'; peekc = c; ip = item_search(name); - if (ip == 0) { + if (ip == 0) + { ip = item_alloc(S_UND); ip->i_name = remember(name); /* printf("ident %s %o\n", ip->i_name, ip); */ unresolved++; - item_insert(ip, H_LOCAL + (hashindex%H_SIZE)); - } else if (hashindex < H_SIZE) { + item_insert(ip, H_LOCAL + (hashindex % H_SIZE)); + } + else if (hashindex < H_SIZE) + { assert(H_KEY == 0); - yylval.y_word = (word_t) ip->i_valu; - return(ip->i_type); + yylval.y_word = (word_t)ip->i_valu; + return (ip->i_type); } yylval.y_item = ip; - return(IDENT); + return (IDENT); } #ifdef ASLD -char * -readident(int c) +char* readident(int c) { int n = NAMEMAX; - char *p = name; + char* p = name; - do { + do + { if (--n >= 0) *p++ = c; c = nextchar(); } while (ISALNUM(c)); *p++ = '\0'; peekc = c; - return(name); + return (name); } #endif -static int -innumber(int c) +static int innumber(int c) { - char *p; + char* p; int radix; - static char num[20+1]; + static char num[20 + 1]; p = num; radix = 20; - do { + do + { if (--radix < 0) fatal("number too long"); if (isupper(c)) @@ -367,21 +413,26 @@ innumber(int c) c = *--p; p = num; radix = 10; - if (*p == '0') { + if (*p == '0') + { radix = 8; p++; - if (*p == 'x') { + if (*p == 'x') + { radix = 16; p++; - } else if (*p == 'b') { + } + else if (*p == 'b') + { radix = 2; p++; } } if (radix != 16 && (c == 'f' || c == 'b')) - return(infbsym(num)); + return (infbsym(num)); yylval.y_valu = 0; - while (c = *p++) { + while (c = *p++) + { if (c > '9') c -= ('a' - '9' - 1); c -= '0'; @@ -389,26 +440,29 @@ innumber(int c) serror("digit exceeds radix"); yylval.y_valu = yylval.y_valu * radix + c; } - return(NUMBER); + return (NUMBER); } -static int -instring(int termc) +static int instring(int termc) { - char *p; + char* p; int c; static int maxstring = 0; - if (! maxstring) { + if (!maxstring) + { maxstring = STRINGMAX; - if ((stringbuf = malloc(maxstring)) == 0) { + if ((stringbuf = malloc(maxstring)) == 0) + { fatal("out of memory"); } } p = stringbuf; - for (;;) { + for (;;) + { c = nextchar(); - if (c == '\n' || c == '\0') { + if (c == '\n' || c == '\0') + { peekc = c; serror("non-terminated string"); break; @@ -417,10 +471,12 @@ instring(int termc) break; if (c == '\\') c = inescape(); - if (p >= &stringbuf[maxstring - 1]) { + if (p >= &stringbuf[maxstring - 1]) + { int cnt = p - stringbuf; - if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0) { + if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0) + { fatal("out of memory"); } p = stringbuf + cnt; @@ -429,57 +485,69 @@ instring(int termc) } stringlen = p - stringbuf; *p = '\0'; - return(STRING); + return (STRING); } -static int -inescape(void) +static int inescape(void) { int c, j, r; c = nextchar(); - if (c >= '0' && c <= '7') { + if (c >= '0' && c <= '7') + { r = c - '0'; - for (j = 0; j < 2; j++) { + for (j = 0; j < 2; j++) + { c = nextchar(); - if (c < '0' || c > '7') { + if (c < '0' || c > '7') + { peekc = c; - return(r); + return (r); } r <<= 3; r += (c - '0'); } - return(r); + return (r); } - switch (c) { - case 'b': return('\b'); - case 'f': return('\f'); - case 'n': return('\n'); - case 'r': return('\r'); - case 't': return('\t'); - case '\'': return('\''); - case '"': return('"'); + switch (c) + { + case 'b': + return ('\b'); + case 'f': + return ('\f'); + case 'n': + return ('\n'); + case 'r': + return ('\r'); + case 't': + return ('\t'); + case '\'': + return ('\''); + case '"': + return ('"'); } - return(c); + return (c); } -static int -infbsym(const char *p) +static int infbsym(const char* p) { int lab; - item_t *ip; + item_t* ip; lab = *p++ - '0'; - if ((unsigned)lab < 10) { - if (*p++ == 'f') { - ip = fb_ptr[FB_FORW+lab]; - if (ip == 0) { + if ((unsigned)lab < 10) + { + if (*p++ == 'f') + { + ip = fb_ptr[FB_FORW + lab]; + if (ip == 0) + { ip = fb_alloc(lab); - fb_ptr[FB_FORW+lab] = ip; + fb_ptr[FB_FORW + lab] = ip; } goto ok; } - ip = fb_ptr[FB_BACK+lab]; + ip = fb_ptr[FB_BACK + lab]; if (ip != 0 && *p == 0) goto ok; } @@ -487,32 +555,33 @@ infbsym(const char *p) ip = fb_alloc(0); ok: yylval.y_item = ip; - return(FBSYM); + return (FBSYM); } -int -hash(const char *p) +int hash(const char* p) { unsigned short h; int c; h = 0; - while (c = *p++) { + while (c = *p++) + { h <<= 2; h += c; } - return(h % H_SIZE); + return (h % H_SIZE); } -item_t * -item_search(const char *p) +item_t* item_search(const char* p) { int h; - item_t *ip; + item_t* ip; - for (h = hash(p); h < H_TOTAL; h += H_SIZE) { + for (h = hash(p); h < H_TOTAL; h += H_SIZE) + { ip = hashtab[h]; - while (ip != 0) { + while (ip != 0) + { if (strcmp(p, ip->i_name) == 0) goto done; ip = ip->i_next; @@ -520,25 +589,24 @@ item_search(const char *p) } done: hashindex = h; - return(ip); + return (ip); } -void -item_insert(item_t *ip, int h) +void item_insert(item_t* ip, int h) { ip->i_next = hashtab[h]; hashtab[h] = ip; } -item_t * -item_alloc(int typ) +item_t* item_alloc(int typ) { - item_t *ip; + item_t* ip; static int nleft = 0; - static item_t *next; + static item_t* next; - if (--nleft < 0) { - next = (item_t *) malloc(MEMINCR); + if (--nleft < 0) + { + next = (item_t*)malloc(MEMINCR); if (next == 0) fatal("out of memory"); nleft += (MEMINCR / sizeof(item_t)); @@ -548,36 +616,34 @@ item_alloc(int typ) ip->i_type = typ; ip->i_name = 0; ip->i_valu = 0; - return(ip); + return (ip); } -item_t * -fb_alloc(int lab) +item_t* fb_alloc(int lab) { item_t *ip, *p; ip = item_alloc(S_UND); - p = fb_ptr[FB_TAIL+lab]; + p = fb_ptr[FB_TAIL + lab]; if (p == 0) - fb_ptr[FB_HEAD+lab] = ip; + fb_ptr[FB_HEAD + lab] = ip; else p->i_next = ip; - fb_ptr[FB_TAIL+lab] = ip; - return(ip); + fb_ptr[FB_TAIL + lab] = ip; + return (ip); } -item_t * -fb_shift(int lab) +item_t* fb_shift(int lab) { - item_t *ip; + item_t* ip; - ip = fb_ptr[FB_FORW+lab]; + ip = fb_ptr[FB_FORW + lab]; if (ip == 0) if (pass == PASS_1) ip = fb_alloc(lab); else - ip = fb_ptr[FB_HEAD+lab]; - fb_ptr[FB_BACK+lab] = ip; - fb_ptr[FB_FORW+lab] = ip->i_next; - return(ip); + ip = fb_ptr[FB_HEAD + lab]; + fb_ptr[FB_BACK + lab] = ip; + fb_ptr[FB_FORW + lab] = ip->i_next; + return (ip); } From 976fa0efca528d5502b3eea9f3a1f275ca568c80 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 22:37:04 +0200 Subject: [PATCH 32/79] Clang-format before editing. --- mach/proto/as/comm7.c | 345 ++++++++++++++++++++++-------------------- 1 file changed, 179 insertions(+), 166 deletions(-) diff --git a/mach/proto/as/comm7.c b/mach/proto/as/comm7.c index b75794d88..66147b130 100644 --- a/mach/proto/as/comm7.c +++ b/mach/proto/as/comm7.c @@ -8,37 +8,37 @@ * miscellaneous */ -#include "comm0.h" -#include "comm1.h" -#include "y.tab.h" -#include -#include +#include "comm0.h" +#include "comm1.h" +#include "y.tab.h" +#include +#include -valu_t -load(const item_t *ip) +valu_t load(const item_t* ip) { #ifdef ASLD int typ; typ = ip->i_type & S_TYP; - if ((typ -= S_MIN) < 0) /* S_UND or S_ABS */ - return(ip->i_valu); - return(ip->i_valu + sect[typ].s_base); + if ((typ -= S_MIN) < 0) /* S_UND or S_ABS */ + return (ip->i_valu); + return (ip->i_valu + sect[typ].s_base); #else - if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) { - if (pass == PASS_3) { + if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) + { + if (pass == PASS_3) + { if (relonami != 0) serror("relocation error (relonami=%d, type=%08x)", relonami, ip->i_type); - relonami = ip->i_valu+1; + relonami = ip->i_valu + 1; } - return(0); + return (0); } - return(ip->i_valu); + return (ip->i_valu); #endif } -int -store(item_t *ip, valu_t val) +int store(item_t* ip, valu_t val) { #ifdef ASLD int typ; @@ -48,27 +48,27 @@ store(item_t *ip, valu_t val) val -= sect[typ].s_base; #else if ((ip->i_type & S_TYP) == S_UND) - return(0); + return (0); #endif assert(pass != PASS_3 || (ip->i_type & S_VAR) || ip->i_valu == val); ip->i_valu = val; - return(1); + return (1); } -char * -remember(char *s) +char* remember(char* s) { - char *p; + char* p; int n; static int nleft = 0; - static char *next; + static char* next; p = s; n = 0; do n++; while (*p++); - if ((nleft -= n) < 0) { + if ((nleft -= n) < 0) + { next = malloc(MEMINCR); if (next == 0) fatal("out of memory"); @@ -80,84 +80,86 @@ remember(char *s) ; s = next; next = p; - return(s); + return (s); } -int -combine(int typ1, int typ2, int op) +int combine(int typ1, int typ2, int op) { - switch (op) { - case '+': - if (typ1 == S_ABS) - return(typ2); - if (typ2 == S_ABS) - return(typ1); - break; - case '-': - if (typ2 == S_ABS) - return(typ1); - if ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) - return(S_ABS|S_VAR); - break; - case '>': - if (typ1 == S_ABS && typ2 == S_ABS) - return(S_ABS); - if ( - ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) - || (typ1 == S_ABS) - || (typ2 == S_ABS) - ) - return(S_ABS|S_VAR); - break; - default: - if (typ1 == S_ABS && typ2 == S_ABS) - return(S_ABS); - break; + switch (op) + { + case '+': + if (typ1 == S_ABS) + return (typ2); + if (typ2 == S_ABS) + return (typ1); + break; + case '-': + if (typ2 == S_ABS) + return (typ1); + if ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) + return (S_ABS | S_VAR); + break; + case '>': + if (typ1 == S_ABS && typ2 == S_ABS) + return (S_ABS); + if (((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) || (typ1 == S_ABS) + || (typ2 == S_ABS)) + return (S_ABS | S_VAR); + break; + default: + if (typ1 == S_ABS && typ2 == S_ABS) + return (S_ABS); + break; } if (pass != PASS_1) serror("illegal operator"); - return(S_UND); + return (S_UND); } #ifdef LISTING -int -printx(int ndig, valu_t val) +int printx(int ndig, valu_t val) { static char buf[8]; - char *p; + char* p; int c, n; - p = buf; n = ndig; - do { - *p++ = (int) val & 017; + p = buf; + n = ndig; + do + { + *p++ = (int)val & 017; val >>= 4; } while (--n); - do { + do + { c = "0123456789ABCDEF"[*--p]; putchar(c); } while (p > buf); - return(ndig); + return (ndig); } -void -listline(int textline) +void listline(int textline) { int c; - if ((listflag & 4) && (c = getc(listfile)) != '\n' && textline) { + if ((listflag & 4) && (c = getc(listfile)) != '\n' && textline) + { if (listcolm >= 24) printf(" \\\n\t\t\t"); else - do { + do + { putchar('\t'); listcolm += 8; } while (listcolm < 24); - do { + do + { assert(c != EOF); putchar(c); } while ((c = getc(listfile)) != '\n'); } - if (listflag & 7) { + if (listflag & 7) + { putchar('\n'); fflush(stdout); } @@ -170,35 +172,40 @@ listline(int textline) /* ---------- code optimization ---------- */ #ifdef THREE_PASS -#define PBITTABSZ 128 -static char *pbittab[PBITTABSZ]; +#define PBITTABSZ 128 +static char* pbittab[PBITTABSZ]; -int -small(int fitsmall, int gain) +int small(int fitsmall, int gain) { int bit; - char *p; + char* p; if (DOTSCT == NULL) nosect(); if (bflag) - return(0); - if (nbits == BITCHUNK) { + return (0); + if (nbits == BITCHUNK) + { bitindex++; nbits = 0; - if (bitindex == PBITTABSZ) { + if (bitindex == PBITTABSZ) + { static int w_given; - if (pass == PASS_1 && ! w_given) { + if (pass == PASS_1 && !w_given) + { w_given = 1; warning("bit table overflow"); } - return(0); + return (0); } - if (pbittab[bitindex] == 0 && pass == PASS_1) { - if ((pbittab[bitindex] = calloc(MEMINCR, 1)) == 0) { + if (pbittab[bitindex] == 0 && pass == PASS_1) + { + if ((pbittab[bitindex] = calloc(MEMINCR, 1)) == 0) + { static int w2_given; - if (!w2_given) { + if (!w2_given) + { w2_given = 1; warning("out of space for bit table"); } @@ -207,21 +214,23 @@ small(int fitsmall, int gain) if (pbittab[bitindex] == 0) return (0); } - bit = 1 << (nbits&7); - p = pbittab[bitindex]+(nbits>>3); + bit = 1 << (nbits & 7); + p = pbittab[bitindex] + (nbits >> 3); nbits++; - switch (pass) { - case PASS_1: - return(0); - case PASS_2: - if (fitsmall) { - DOTGAIN += gain; - *p |= bit; - } - return(fitsmall); - case PASS_3: - assert(fitsmall || (*p & bit) == 0); - return(*p & bit); + switch (pass) + { + case PASS_1: + return (0); + case PASS_2: + if (fitsmall) + { + DOTGAIN += gain; + *p |= bit; + } + return (fitsmall); + case PASS_3: + assert(fitsmall || (*p & bit) == 0); + return (*p & bit); } /*NOTREACHED*/ } @@ -229,13 +238,14 @@ small(int fitsmall, int gain) /* ---------- output ---------- */ -void -emit1(int arg) +void emit1(int arg) { static int olddottyp = -1; #ifdef LISTING - if (listeoln) { - if (listflag & 1) { + if (listeoln) + { + if (listflag & 1) + { listcolm += printx(VALWIDTH, (valu_t)DOTVAL); listcolm++; putchar(' '); @@ -243,81 +253,90 @@ emit1(int arg) listeoln = 0; } if (listflag & 2) - listcolm += printx(2, (valu_t) arg); + listcolm += printx(2, (valu_t)arg); #endif - switch (pass) { - case PASS_1: - if (DOTSCT == NULL) - nosect(); - /* no break */ - case PASS_2: - DOTSCT->s_zero = 0; - break; - case PASS_3: - if (DOTTYP != olddottyp) { - wr_outsect(DOTTYP-S_MIN); - olddottyp = DOTTYP; - } - while (DOTSCT->s_zero) { - wr_putc(0); - DOTSCT->s_zero--; - } - wr_putc(arg); - break; + switch (pass) + { + case PASS_1: + if (DOTSCT == NULL) + nosect(); + /* no break */ + case PASS_2: + DOTSCT->s_zero = 0; + break; + case PASS_3: + if (DOTTYP != olddottyp) + { + wr_outsect(DOTTYP - S_MIN); + olddottyp = DOTTYP; + } + while (DOTSCT->s_zero) + { + wr_putc(0); + DOTSCT->s_zero--; + } + wr_putc(arg); + break; } DOTVAL++; } -void -emit2(int arg) +void emit2(int arg) { #ifdef BYTES_REVERSED - emit1((arg>>8)); emit1(arg); + emit1((arg >> 8)); + emit1(arg); #else - emit1(arg); emit1((arg>>8)); + emit1(arg); + emit1((arg >> 8)); #endif } -void -emit4(long arg) +void emit4(long arg) { #ifdef WORDS_REVERSED - emit2((int)(arg>>16)); emit2((int)(arg)); + emit2((int)(arg >> 16)); + emit2((int)(arg)); #else - emit2((int)(arg)); emit2((int)(arg>>16)); + emit2((int)(arg)); + emit2((int)(arg >> 16)); #endif } -void -emitx(valu_t val, int n) +void emitx(valu_t val, int n) { - switch (n) { - case RELO1: - emit1((int)val); break; - case RELO2: + switch (n) + { + case RELO1: + emit1((int)val); + break; + case RELO2: #ifdef BYTES_REVERSED - emit1(((int)val>>8)); emit1((int)val); + emit1(((int)val >> 8)); + emit1((int)val); #else - emit1((int)val); emit1(((int)val>>8)); + emit1((int)val); + emit1(((int)val >> 8)); #endif - break; - case RELO4: + break; + case RELO4: #ifdef WORDS_REVERSED - emit2((int)(val>>16)); emit2((int)(val)); + emit2((int)(val >> 16)); + emit2((int)(val)); #else - emit2((int)(val)); emit2((int)(val>>16)); + emit2((int)(val)); + emit2((int)(val >> 16)); #endif - break; - default: - assert(0); + break; + default: + assert(0); } } -void -emitstr(int zero) +void emitstr(int zero) { int i; - char *p; + char* p; p = stringbuf; i = stringlen; @@ -329,55 +348,50 @@ emitstr(int zero) /* ---------- Error checked file I/O ---------- */ -void -ffreopen(char *s, FILE *f) +void ffreopen(char* s, FILE* f) { if (freopen(s, "r", f) == NULL) fatal("can't reopen %s", s); } -FILE * -ffcreat(char *s) +FILE* ffcreat(char* s) { - FILE *f; + FILE* f; if ((f = fopen(s, "w")) == NULL) fatal("can't create %s", s); - return(f); + return (f); } #ifndef TMPDIR #define TMPDIR "/tmp" #endif -char *tmp_dir = TMPDIR; +char* tmp_dir = TMPDIR; -FILE * -fftemp(char *path, char *tail) +FILE* fftemp(char* path, char* tail) { - char *dir; + char* dir; if ((dir = getenv("TMPDIR")) == NULL) dir = tmp_dir; sprintf(path, "%s/%s", dir, tail); close(mkstemp(path)); - return(ffcreat(path)); + return (ffcreat(path)); } /* ---------- Error handling ---------- */ /* ARGSUSED */ -void -yyerror(const char *message) -{} /* we will do our own error printing */ +void yyerror(const char* message) +{ +} /* we will do our own error printing */ -void -nosect(void) +void nosect(void) { fatal("no sections"); } -void -wr_fatal(void) +void wr_fatal(void) { fatal("write error"); } @@ -432,8 +446,7 @@ void warning(const char* s, ...) va_end(ap); } -void -nofit(void) +void nofit(void) { if (pass == PASS_3) warning("too big"); From 9733454d8ed93f1f1c3276eb981d59a70f5f2f1b Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 22:42:30 +0200 Subject: [PATCH 33/79] Clang-format before editing. --- h/con_float | 204 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 81 deletions(-) diff --git a/h/con_float b/h/con_float index 903c2ce5b..ad959d34b 100644 --- a/h/con_float +++ b/h/con_float @@ -5,7 +5,7 @@ /* $Id$ */ -/* +/* #define CODE_GENERATOR for code generator #define CODE_EXPANDER for code expander @@ -20,9 +20,9 @@ Unfortunately, the IEEE standard does not define the byte-order. depends on the #defines - FL_MSL_AT_LOW_ADDRESS 1 if most significant long is at low address - FL_MSW_AT_LOW_ADDRESS 1 if most significant word is at low address - FL_MSB_AT_LOW_ADDRESS 1 if most significant byte is at low address + FL_MSL_AT_LOW_ADDRESS 1 if most significant long is at low address + FL_MSW_AT_LOW_ADDRESS 1 if most significant word is at low address + FL_MSB_AT_LOW_ADDRESS 1 if most significant byte is at low address */ #ifdef IEEEFLOAT #define USE_FLT @@ -37,47 +37,57 @@ #define FL_MSB_AT_LOW_ADDRESS 0 #endif -#define I0 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ - + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) -#define I1 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ - + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) -#define I2 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ - + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) -#define I3 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ - + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) -#define I4 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ - + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) -#define I5 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ - + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) -#define I6 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ - + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) -#define I7 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ - + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) +#define I0 \ + ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ + + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) +#define I1 \ + ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ + + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) +#define I2 \ + ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ + + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) +#define I3 \ + ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ + + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) +#define I4 \ + ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ + + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) +#define I5 \ + ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ + + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) +#define I6 \ + ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ + + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) +#define I7 \ + ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ + + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) #ifndef USE_FLT -static int -float_cst(str, sz, buf) - char *str, *buf; - int sz; +static int float_cst(str, sz, buf) char *str, *buf; +int sz; { int i; - char *p; + char* p; float fl; double f; double atof(); - if (sz!= 4 && sz!= 8) { + if (sz != 4 && sz != 8) + { return 1; } f = atof(str); - if (sz == 4) { + if (sz == 4) + { fl = f; - p = (char *) &fl; + p = (char*)&fl; } - else { - p = (char *) &f; + else + { + p = (char*)&f; } - for (i = sz; i; i--) { + for (i = sz; i; i--) + { *buf++ = *p++; } return 0; @@ -87,89 +97,105 @@ float_cst(str, sz, buf) #include #include -int -float_cst(str, sz, buf) - char *str, *buf; - int sz; +int float_cst(str, sz, buf) char *str, *buf; +int sz; { int overflow = 0; flt_arith e; - if (sz!= 4 && sz!= 8) { + if (sz != 4 && sz != 8) + { return 1; } flt_str2flt(str, &e); #ifdef IEEEFLOAT - if (sz == 4) { + if (sz == 4) + { #endif #ifdef PDPFLOAT e.flt_exp += 129; #else - e.flt_exp += 127; + e.flt_exp += 127; #endif - if (e.flt_mantissa.flt_h_32 == 0) e.flt_exp = 0; + if (e.flt_mantissa.flt_h_32 == 0) + e.flt_exp = 0; #ifdef IEEEFLOAT - if (e.flt_mantissa.flt_h_32 & 0x80) { + if (e.flt_mantissa.flt_h_32 & 0x80) + { /* rounding */ - if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) { + if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) + { e.flt_exp++; e.flt_mantissa.flt_h_32 = 0x80000000; } - else { + else + { e.flt_mantissa.flt_h_32 += 0x80; } } - if (e.flt_exp >= 255) { + if (e.flt_exp >= 255) + { overflow = 1; e.flt_exp = 255; e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0; } - if (e.flt_exp <= 0) { + if (e.flt_exp <= 0) + { flt_b64_sft(&(e.flt_mantissa), 1); - if (e.flt_exp < 0) { + if (e.flt_exp < 0) + { flt_b64_sft(&(e.flt_mantissa), -e.flt_exp); e.flt_exp = 0; } } #endif #ifndef IEEEFLOAT - if (sz == 4 && (e.flt_mantissa.flt_h_32 & 0x80)) { + if (sz == 4 && (e.flt_mantissa.flt_h_32 & 0x80)) + { /* rounding */ - if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) { + if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) + { e.flt_exp++; e.flt_mantissa.flt_h_32 = 0x80000000; } - else { + else + { e.flt_mantissa.flt_h_32 += 0x80; } } - if (sz == 8 && (e.flt_mantissa.flt_l_32 & 0x80)) { + if (sz == 8 && (e.flt_mantissa.flt_l_32 & 0x80)) + { /* rounding */ - if ((e.flt_mantissa.flt_l_32 & 0xffffff00) == 0xffffff00) { + if ((e.flt_mantissa.flt_l_32 & 0xffffff00) == 0xffffff00) + { e.flt_mantissa.flt_l_32 = 0; - if (e.flt_mantissa.flt_h_32 == 0xffffffff) { + if (e.flt_mantissa.flt_h_32 == 0xffffffff) + { e.flt_exp++; e.flt_mantissa.flt_h_32 = 0x80000000; } - else e.flt_mantissa.flt_h_32++; + else + e.flt_mantissa.flt_h_32++; } - else { + else + { e.flt_mantissa.flt_l_32 += 0x80; } } - if (e.flt_exp > 255) { + if (e.flt_exp > 255) + { overflow = 1; e.flt_exp = 255; e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0xffffffff; } #endif buf[I0] = (e.flt_sign << 7) | (e.flt_exp >> 1); - buf[I1] = ((e.flt_exp&1) << 7) | - ((e.flt_mantissa.flt_h_32 & 0x7fffffff) >> 24); + buf[I1] = ((e.flt_exp & 1) << 7) | ((e.flt_mantissa.flt_h_32 & 0x7fffffff) >> 24); buf[I2] = e.flt_mantissa.flt_h_32 >> 16; buf[I3] = e.flt_mantissa.flt_h_32 >> 8; #ifndef IEEEFLOAT - if (sz == 8) { + if (sz == 8) + { buf[I4] = e.flt_mantissa.flt_h_32; buf[I5] = e.flt_mantissa.flt_l_32 >> 24; buf[I6] = e.flt_mantissa.flt_l_32 >> 16; @@ -181,37 +207,47 @@ float_cst(str, sz, buf) flt_b64_sft(&(e.flt_mantissa), -24); #ifdef IEEEFLOAT } - else { + else + { e.flt_exp += 1023; - if (e.flt_mantissa.flt_h_32 == 0) e.flt_exp = 0; - if (e.flt_mantissa.flt_l_32 & 0x400) { + if (e.flt_mantissa.flt_h_32 == 0) + e.flt_exp = 0; + if (e.flt_mantissa.flt_l_32 & 0x400) + { /* rounding */ - if ((e.flt_mantissa.flt_l_32 & 0xfffff800) == 0xfffff800) { + if ((e.flt_mantissa.flt_l_32 & 0xfffff800) == 0xfffff800) + { e.flt_mantissa.flt_l_32 = 0; - if (e.flt_mantissa.flt_h_32 == 0xffffffff) { + if (e.flt_mantissa.flt_h_32 == 0xffffffff) + { e.flt_exp++; e.flt_mantissa.flt_h_32 = 0x80000000; } - else e.flt_mantissa.flt_h_32++; + else + e.flt_mantissa.flt_h_32++; } - else { + else + { e.flt_mantissa.flt_l_32 += 0x400; } } - if (e.flt_exp >= 2047) { + if (e.flt_exp >= 2047) + { overflow = 1; e.flt_exp = 2047; e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0; } - if (e.flt_exp <= 0) { + if (e.flt_exp <= 0) + { flt_b64_sft(&(e.flt_mantissa), 1); - if (e.flt_exp < 0) { + if (e.flt_exp < 0) + { flt_b64_sft(&(e.flt_mantissa), -e.flt_exp); e.flt_exp = 0; } } buf[I0] = (e.flt_sign << 7) | (e.flt_exp >> 4); - buf[I1] = ((e.flt_exp & 017)<< 4) | ((e.flt_mantissa.flt_h_32 >> 27) & 017); + buf[I1] = ((e.flt_exp & 017) << 4) | ((e.flt_mantissa.flt_h_32 >> 27) & 017); buf[I2] = e.flt_mantissa.flt_h_32 >> 19; buf[I3] = e.flt_mantissa.flt_h_32 >> 11; buf[I4] = e.flt_mantissa.flt_h_32 >> 3; @@ -221,15 +257,17 @@ float_cst(str, sz, buf) flt_b64_sft(&(e.flt_mantissa), -53); } #endif -#if ! FL_MSL_AT_LOW_ADDRESS - if (sz == 4) { +#if !FL_MSL_AT_LOW_ADDRESS + if (sz == 4) + { buf[I4] = buf[I0]; buf[I5] = buf[I1]; buf[I6] = buf[I2]; buf[I7] = buf[I3]; } #endif - if (overflow) { + if (overflow) + { return 2; } return 0; @@ -243,16 +281,19 @@ con_float() int rval = float_cst(str, (int)argval, buf); int i; - if (rval == 1) { - fprintf(stderr,"float constant size = %d\n",(int)argval); + if (rval == 1) + { + fprintf(stderr, "float constant size = %d\n", (int)argval); fatal("bad fcon size"); } - fprintf(codefile,"!float %s sz %d\n", str, (int)argval); - if (rval == 2) { + fprintf(codefile, "!float %s sz %d\n", str, (int)argval); + if (rval == 2) + { fprintf(stderr, "Warning: overflow in floating point constant %s\n", str); } fprintf(codefile, ".data1 0%o", buf[0] & 0377); - for (i = 1; i < (int)argval; i++) { + for (i = 1; i < (int)argval; i++) + { fprintf(codefile, ",0%o", buf[i] & 0377); } putc('\n', codefile); @@ -260,19 +301,20 @@ con_float() #endif /* CODE_GENERATOR */ #ifdef CODE_EXPANDER -con_float(str, argval) - char *str; - arith argval; +con_float(str, argval) char* str; +arith argval; { char buf[8]; int rval = float_cst(str, (int)argval, buf); int i; - if (rval == 1) { + if (rval == 1) + { argval = 8; rval = float_cst(str, 8, buf); } - for (i = 0; i < (int)argval; i++) { + for (i = 0; i < (int)argval; i++) + { gen1(buf[i]); } } From 53f7de794ac79b03787a7c0838bb8f6448457968 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 22:55:05 +0200 Subject: [PATCH 34/79] Ansify. --- h/con_float | 5 ++--- mach/proto/ncg/fillem.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/h/con_float b/h/con_float index ad959d34b..a0ce783cc 100644 --- a/h/con_float +++ b/h/con_float @@ -275,7 +275,7 @@ int sz; #endif /* USE_FLT */ #ifdef CODE_GENERATOR -con_float() +void con_float(void) { char buf[8]; int rval = float_cst(str, (int)argval, buf); @@ -301,8 +301,7 @@ con_float() #endif /* CODE_GENERATOR */ #ifdef CODE_EXPANDER -con_float(str, argval) char* str; -arith argval; +void con_float(const char* str, arith argval) { char buf[8]; int rval = float_cst(str, (int)argval, buf); diff --git a/mach/proto/ncg/fillem.c b/mach/proto/ncg/fillem.c index 7f479337e..7f0e4c681 100644 --- a/mach/proto/ncg/fillem.c +++ b/mach/proto/ncg/fillem.c @@ -83,7 +83,7 @@ extern short em_ptyp[]; /* machine dependent */ void con_part(int, word); void con_mult(word); -int con_float(void); /* actually returns void, but need K&R C compatibility */ +void con_float(void); /* actually returns void, but need K&R C compatibility */ void prolog(full nlocals); void mes(word); From a1747ac91621250d640d08136cc6b0730db3b955 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 22:56:18 +0200 Subject: [PATCH 35/79] Add the .dataf4 and .dataf8 directives to the assembler --- manually converting floats and doubles to bytes is not fun. It might even work! --- mach/mips/libem/c_ud_i.s | 3 +-- mach/mips/libem/c_uf_i.s | 3 +-- mach/mips/libem/c_ui_d.s | 3 +-- mach/mips/libem/c_ui_f.s | 2 +- mach/pdp/as/mach0.c | 1 + mach/proto/as/build.lua | 1 + mach/proto/as/comm1.h | 1 + mach/proto/as/comm2.y | 15 +++++++++++++++ mach/proto/as/comm3.c | 2 ++ mach/proto/as/comm5.c | 24 ++++++++++++++++++++++-- mach/proto/as/comm7.c | 28 ++++++++++++++++++++++++++++ man/uni_ass.6 | 10 ++++++++++ 12 files changed, 84 insertions(+), 9 deletions(-) diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index ccd798e03..ed2c6479e 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -28,9 +28,8 @@ toobig: jr ra nop -/* 2147483648 as a double. */ .sect .rom .define .fd_80000000 .fd_80000000: - .data4 0, 0x41e00000 + .dataf8 2147483648.0 diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 8bd840b40..8d7129cad 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -31,8 +31,7 @@ toobig: jr ra nop -/* 2147483648 as a float. */ .sect .rom .ff_80000000: - .data4 0x4f000000 + .dataf4 2147483648.0 diff --git a/mach/mips/libem/c_ui_d.s b/mach/mips/libem/c_ui_d.s index c46a2cf4a..0d339b702 100644 --- a/mach/mips/libem/c_ui_d.s +++ b/mach/mips/libem/c_ui_d.s @@ -20,7 +20,6 @@ nonnegative: jr ra nop -/* 4294967296 as a double. */ .sect .rom .fd_100000000: - .data4 0, 0x41f00000 + .dataf8 4294967296.0 diff --git a/mach/mips/libem/c_ui_f.s b/mach/mips/libem/c_ui_f.s index 46f9f0b62..7c1a05d6a 100644 --- a/mach/mips/libem/c_ui_f.s +++ b/mach/mips/libem/c_ui_f.s @@ -23,4 +23,4 @@ nonnegative: /* 4294967296 as a float. */ .sect .rom .fs_100000000: - .data4 0x4f800000 + .dataf4 4294967296.0 diff --git a/mach/pdp/as/mach0.c b/mach/pdp/as/mach0.c index c3e5c0a81..afede3407 100644 --- a/mach/pdp/as/mach0.c +++ b/mach/pdp/as/mach0.c @@ -12,6 +12,7 @@ #define WORDS_REVERSED #define LISTING #define RELOCATION +#define PDPFLOAT #undef ISALPHA #define ISALPHA(c) (isalpha(c) || c == '_' || c == '.' || c == '~') #undef ISALNUM diff --git a/mach/proto/as/build.lua b/mach/proto/as/build.lua index 52536cbbf..d9718e06f 100644 --- a/mach/proto/as/build.lua +++ b/mach/proto/as/build.lua @@ -44,6 +44,7 @@ definerule("build_as", deps = { "h+emheaders", "modules/src/object+lib", + "modules/src/flt_arith+lib", archlib, yaccfiles, e.deps diff --git a/mach/proto/as/comm1.h b/mach/proto/as/comm1.h index 7ea697015..47f4302b3 100644 --- a/mach/proto/as/comm1.h +++ b/mach/proto/as/comm1.h @@ -153,6 +153,7 @@ void emit1(int); void emit2(int); void emit4(long); void emitx(valu_t, int); +void emitf(int size); void emitstr(int); void ffreopen(char *, FILE *); FILE *ffcreat(char *); diff --git a/mach/proto/as/comm2.y b/mach/proto/as/comm2.y index 1b3e19917..0643928d8 100644 --- a/mach/proto/as/comm2.y +++ b/mach/proto/as/comm2.y @@ -43,9 +43,11 @@ static item_t *last_it, *o_it; %token NUMBER2 %token NUMBER3 %token NUMBER +%token NUMBERF %token DOT %token EXTERN %token DATA +%token DATAF %token ASCII %token SECTION %token COMMON @@ -249,6 +251,7 @@ operation DOTSCT->s_zero += $2; } | DATA datalist + | DATAF dataflist | ASCII STRING { emitstr($1);} ; @@ -276,6 +279,18 @@ datalist emitx($3.val, (int)$0); } ; + +dataflist + : NUMBERF + { + emitf((int)$0); + } + | dataflist ',' NUMBERF + { + emitf((int)$3); + } + ; + expr : error { serror("expr syntax err"); $$.val = 0; $$.typ = S_UND; diff --git a/mach/proto/as/comm3.c b/mach/proto/as/comm3.c index f35d1818c..2a24a0878 100644 --- a/mach/proto/as/comm3.c +++ b/mach/proto/as/comm3.c @@ -29,6 +29,8 @@ item_t keytab[] = { 0, DATA, RELO1, ".data1", 0, DATA, RELO2, ".data2", 0, DATA, RELO4, ".data4", + 0, DATAF, 4, ".dataf4", + 0, DATAF, 8, ".dataf8", 0, ASCII, 0, ".ascii", 0, ASCII, 1, ".asciz", 0, ALIGN, 0, ".align", diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index 0703f3bfb..b91ad3466 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -395,10 +395,12 @@ static int innumber(int c) { char* p; int radix; - static char num[20 + 1]; + static char num[40 + 1]; p = num; - radix = 20; + radix = 40; + if (c == '.') + goto floatconstant; do { if (--radix < 0) @@ -407,6 +409,8 @@ static int innumber(int c) c += ('a' - 'A'); *p++ = c; c = nextchar(); + if (c == '.') + goto floatconstant; } while (isalnum(c)); peekc = c; *p = '\0'; @@ -441,6 +445,22 @@ static int innumber(int c) yylval.y_valu = yylval.y_valu * radix + c; } return (NUMBER); + +floatconstant: + do + { + if (--radix < 0) + fatal("number too long"); + if (isupper(c)) + c += ('a' - 'A'); + *p++ = c; + c = nextchar(); + } while (isdigit(c) || (c == '.') || (c == 'E') || (c == '+') || (c == '-')); + + *p = '\0'; + stringbuf = strdup(num); + stringlen = p - num; + return NUMBERF; } static int instring(int termc) diff --git a/mach/proto/as/comm7.c b/mach/proto/as/comm7.c index 66147b130..c9e340191 100644 --- a/mach/proto/as/comm7.c +++ b/mach/proto/as/comm7.c @@ -346,6 +346,34 @@ void emitstr(int zero) emit1(0); } +#define CODE_EXPANDER + +#if !defined IEEEFLOAT && !defined PDPFLOAT + #define IEEEFLOAT +#endif + +#if defined WORDS_REVERSED + #define FL_MSL_AT_LOW_ADDRESS 1 + #define FL_MSW_AT_LOW_ADDRESS 1 +#else + #define FL_MSL_AT_LOW_ADDRESS 0 + #define FL_MSW_AT_LOW_ADDRESS 0 +#endif + +#if defined BYTES_REVERSED + #define FL_MSB_AT_LOW_ADDRESS 1 +#else + #define FL_MSB_AT_LOW_ADDRESS 0 +#endif + +#define gen1 emit1 +#include + +void emitf(int size) +{ + con_float(stringbuf, size); +} + /* ---------- Error checked file I/O ---------- */ void ffreopen(char* s, FILE* f) diff --git a/man/uni_ass.6 b/man/uni_ass.6 index 94b60a3cc..6d970621e 100644 --- a/man/uni_ass.6 +++ b/man/uni_ass.6 @@ -206,6 +206,16 @@ This is not followed by automatic alignment. .Pu ".data4 \fIexpression [, expression]*\fP" Initialize a sequence of longs (4-byte values). This is not followed by automatic alignment. +.Pu ".dataf4 \fIliteralfloat [, literalfloat]*\fP" +Initialize a sequence of floats (4-byte values). +The values must be literal floating point constants containing +a dot character. +This is not followed by automatic alignment. +.Pu ".dataf8 \fIliteralfloat [, literalfloat]*\fP" +Initialize a sequence of doubles (8-byte values). +The values must be literal floating point constants containing +a dot character. +This is not followed by automatic alignment. .Pu ".ascii \fIstring\fP" Initialize a sequence of bytes with the value of the bytes in the string. From 008737ed19603185c1a3df15917f9c0dc93d049c Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 23:20:52 +0200 Subject: [PATCH 36/79] Added some more very untested helper functions. --- mach/mips/libem/fif8.s | 69 ++++++++++++++++++++++++++++++++++++++++++ mach/mips/libem/sar4.s | 24 +++++++++++++++ mach/mips/libem/sts4.s | 57 ++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 mach/mips/libem/fif8.s create mode 100644 mach/mips/libem/sar4.s create mode 100644 mach/mips/libem/sts4.s diff --git a/mach/mips/libem/fif8.s b/mach/mips/libem/fif8.s new file mode 100644 index 000000000..6b18ee746 --- /dev/null +++ b/mach/mips/libem/fif8.s @@ -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) + + li 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. + + li 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 diff --git a/mach/mips/libem/sar4.s b/mach/mips/libem/sar4.s new file mode 100644 index 000000000..a1ddea33c --- /dev/null +++ b/mach/mips/libem/sar4.s @@ -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 + diff --git a/mach/mips/libem/sts4.s b/mach/mips/libem/sts4.s new file mode 100644 index 000000000..56ea9efa8 --- /dev/null +++ b/mach/mips/libem/sts4.s @@ -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 From 3122946a6f45420ef761177b552c4dbdb7533dff Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 23:21:54 +0200 Subject: [PATCH 37/79] Replaced some incorrect hi16s with ha16s. --- mach/mips/libem/c_ud_i.s | 2 +- mach/mips/libem/c_uf_i.s | 2 +- mach/mips/libem/c_ui_d.s | 2 +- mach/mips/libem/c_ui_f.s | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index ed2c6479e..5af88483d 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -9,7 +9,7 @@ * Only at and f30/f31 may be used. */ - ori at, zero, hi16[.fd_80000000] + li at, ha16[.fd_80000000] ldc1 f30, lo16[.fd_80000000] (at) c.le.d 0, f30, f0 bc1t toobig diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 8d7129cad..1a3c2a1f7 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -12,7 +12,7 @@ * Only at and f30/f31 may be used. */ - ori at, zero, hi16[.ff_80000000] + li at, ha16[.ff_80000000] lwc1 f30, lo16[.ff_80000000] (at) c.le.s 0, f30, f0 bc1t toobig diff --git a/mach/mips/libem/c_ui_d.s b/mach/mips/libem/c_ui_d.s index 0d339b702..ef987d50d 100644 --- a/mach/mips/libem/c_ui_d.s +++ b/mach/mips/libem/c_ui_d.s @@ -13,7 +13,7 @@ bgez r2, nonnegative nop - ori at, zero, hi16[.fd_100000000] + li at, ha16[.fd_100000000] ldc1 f30, lo16[.fd_100000000] (at) add.d f0, f0, f30 nonnegative: diff --git a/mach/mips/libem/c_ui_f.s b/mach/mips/libem/c_ui_f.s index 7c1a05d6a..f54179fb8 100644 --- a/mach/mips/libem/c_ui_f.s +++ b/mach/mips/libem/c_ui_f.s @@ -13,7 +13,7 @@ bgez r2, nonnegative nop - ori at, zero, hi16[.fs_100000000] + li at, ha16[.fs_100000000] ldc1 f30, lo16[.fs_100000000] (at) add.d f0, f0, f30 nonnegative: From 2f8fe3ce6e9054a11509e51f6ee67329eab12119 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 23:37:04 +0200 Subject: [PATCH 38/79] Do some cleanup; ha16[] and friends can now be used with li. --- mach/mips/as/instructions.dat | 2 +- mach/mips/as/mach4.c | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index b1084675b..98c4dbbe9 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -182,6 +182,7 @@ 01000100000000101 "abs" F=fmt FD=fpr ',' FS=fpr 010001000000 "add" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr 010011011110 "alnv" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr ',' RS=gpr +0100010011 "c" CO=fcond F=fmt C=u3 ',' FS=fpr ',' FT=fpr 01000100000001010 "ceil" ".l" F=fmt FD=fpr ',' FS=fpr 01000100000001110 "ceil" ".w" F=fmt FD=fpr ',' FS=fpr 0100010001000000000000 "cfc1" RT=gpr ',' FS=fpr @@ -238,7 +239,6 @@ # Generic coprocessor instructions. -0100010011 "c" CO=fcond F=fmt C=u3 ',' FS=fpr ',' FT=fpr 0100010100000 "bc1f" C=u3 ',' OFF=offset16 0100010100000000 "bc1f" OFF=offset16 0100010100010 "bc1fl" C=u3 ',' OFF=offset16 diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index da7bc1bfb..c7f158234 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -1,12 +1,9 @@ #include "rules.y" - | OP_LI GPR ',' expr + | OP_LI GPR ',' extabsexp { word_t reg = $2; - word_t type = $4.typ & S_TYP; - word_t val = $4.val; - if (type != S_ABS) - serror("li cannot be used with values that need a fixup"); - + word_t val = $4; + if (val == 0) emit4(0x00000025 | (reg<<11)); /* or reg, zero, zero */ else if ((val < -0x8000) || (val > 0xffff)) From 0ce368324ed41b03f37c9a8dcd4eba5631fc7447 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 23:37:28 +0200 Subject: [PATCH 39/79] Add the bitset helpers. We now have enough helpers for the tests to run (and massively fail). --- mach/mips/libem/and.s | 30 ++++++++++++++++++++++++++++++ mach/mips/libem/com.s | 27 +++++++++++++++++++++++++++ mach/mips/libem/ior.s | 30 ++++++++++++++++++++++++++++++ mach/mips/libem/set.s | 37 +++++++++++++++++++++++++++++++++++++ mach/mips/libem/zer.s | 24 ++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 mach/mips/libem/and.s create mode 100644 mach/mips/libem/com.s create mode 100644 mach/mips/libem/ior.s create mode 100644 mach/mips/libem/set.s create mode 100644 mach/mips/libem/zer.s diff --git a/mach/mips/libem/and.s b/mach/mips/libem/and.s new file mode 100644 index 000000000..5f0eacb2c --- /dev/null +++ b/mach/mips/libem/and.s @@ -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 + diff --git a/mach/mips/libem/com.s b/mach/mips/libem/com.s new file mode 100644 index 000000000..fae0d64e5 --- /dev/null +++ b/mach/mips/libem/com.s @@ -0,0 +1,27 @@ +# +.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 + + jr ra + nop + diff --git a/mach/mips/libem/ior.s b/mach/mips/libem/ior.s new file mode 100644 index 000000000..df2828dfe --- /dev/null +++ b/mach/mips/libem/ior.s @@ -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 + diff --git a/mach/mips/libem/set.s b/mach/mips/libem/set.s new file mode 100644 index 000000000..01a6ff654 --- /dev/null +++ b/mach/mips/libem/set.s @@ -0,0 +1,37 @@ +# +.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, 4 + srl r4, r4, 2 ! r4 = word count + + ! Create an empty set. + +1: + addiu sp, sp, -4 + sw zero, 0(sp) + addiu r4, r4, -1 + bne r4, zero, 1b + + ! sp now points at the set. + + srl r6, r5, 3 ! r6 = offset of word in set + addu r6, sp, r6 ! r6 = address of word in set + + ext r7, r5, 0, 3 ! 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 + diff --git a/mach/mips/libem/zer.s b/mach/mips/libem/zer.s new file mode 100644 index 000000000..6941d340b --- /dev/null +++ b/mach/mips/libem/zer.s @@ -0,0 +1,24 @@ +# +.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 + + jr ra + nop + From b81e060372c5ce39745acc699c1ef612afa0eda5 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 10 Sep 2018 23:40:03 +0200 Subject: [PATCH 40/79] Add huge numbers of failing tests. --- build.lua | 3 +-- plat/linuxmips/tests/build.lua | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 plat/linuxmips/tests/build.lua diff --git a/build.lua b/build.lua index df51d0d13..b653c1c9f 100644 --- a/build.lua +++ b/build.lua @@ -13,7 +13,6 @@ vars.plats = { "linuxmips", "osx386", "osxppc", --- --"qemuppc", "pc86", "rpi", "pdpv7", @@ -23,7 +22,7 @@ vars.plats_with_tests = { "linux68k", "linux386", "linuxppc", --- --"qemuppc", + "linuxmips", "pc86", } diff --git a/plat/linuxmips/tests/build.lua b/plat/linuxmips/tests/build.lua new file mode 100644 index 000000000..68ffccc68 --- /dev/null +++ b/plat/linuxmips/tests/build.lua @@ -0,0 +1,8 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "linuxmips", + method = "qemu-mipsel", + skipsets = {"m2"} +} From 8230ec42ac46965215f31f29f158c4b2b6a21d9c Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 11 Sep 2018 23:16:30 +0200 Subject: [PATCH 41/79] Fix a subtle thinko which was causing bits 2-3 of jump targets to be reset. --- mach/mips/as/mach4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index c7f158234..6208fff9d 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -174,7 +174,7 @@ abs26 serror("jump targets must be 4-aligned"); newrelo($1.typ, RELOMIPS | FIXUPFLAGS); - $$ = (target >> 2) & 0x03fffffd; + $$ = (target >> 2) & 0x03ffffff; } ; From 8379969b6ff76bdd2104b7cd961a8ec904a554dc Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 11 Sep 2018 23:16:50 +0200 Subject: [PATCH 42/79] Fix an unsubtle bug where subtractions were done backwards... --- mach/mips/mcg/table | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index f7d0b423a..43051cb4e 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -578,7 +578,7 @@ PATTERNS ALUCC(ADD.I, "addiu") out:(int)reg = SUB.I(left:(int)reg, right:(int)reg) - emit "subu %out, %right, %left" + emit "subu %out, %left, %right" cost 4; out:(int)reg = SUB.I(left:(int)reg, right:CONST.I) From 5264db860de8329171d5f875e1a149e35b1b99f1 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 11 Sep 2018 23:17:09 +0200 Subject: [PATCH 43/79] Values are more useful shown in hex. --- util/led/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/led/main.c b/util/led/main.c index 36950dbef..0caf2d7d3 100644 --- a/util/led/main.c +++ b/util/led/main.c @@ -579,7 +579,7 @@ addbase(name) return; name->on_valu += outsect[sectindex].os_base; - debug( "%s: type 0x%x, value %ld\n", + debug( "%s: type 0x%x, value 0x%lx\n", address((name->on_type & S_EXT) ? ALLOGCHR : ALLOLCHR, (ind_t)name->on_foff ), From a8df9721d3f3d37955696f23389a63184eb5ecbd Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 12 Sep 2018 22:27:39 +0200 Subject: [PATCH 44/79] Adding new tokens to the assembler isn't quite as easy as I thought: ensure that NUMBERF is stored properly in the temporary file. --- mach/proto/as/comm5.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index b91ad3466..9dc7a80bb 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -144,6 +144,7 @@ void putval(int c) break; #endif case STRING: + case NUMBERF: v = stringlen; putc(c, tempfile); putc(c >> 8, tempfile); @@ -238,6 +239,7 @@ int getval(int c) break; #endif case STRING: + case NUMBERF: getval(getc(tempfile) + NUMBER0); stringlen = n = yylval.y_valu; p = stringbuf; @@ -456,6 +458,7 @@ floatconstant: *p++ = c; c = nextchar(); } while (isdigit(c) || (c == '.') || (c == 'E') || (c == '+') || (c == '-')); + peekc = c; *p = '\0'; stringbuf = strdup(num); From 8105281534e29d071f2ad228705114faeb45d092 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 12 Sep 2018 22:28:40 +0200 Subject: [PATCH 45/79] Make sure li works properly when loading fixed up values which end up as 0. Use lui rather than li to load high values. --- mach/mips/as/mach4.c | 4 +--- mach/mips/libem/c_ud_i.s | 2 +- mach/mips/libem/c_uf_i.s | 2 +- mach/mips/libem/c_ui_d.s | 2 +- mach/mips/libem/c_ui_f.s | 2 +- mach/mips/libem/fif8.s | 4 ++-- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 6208fff9d..443ca1e49 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -4,9 +4,7 @@ word_t reg = $2; word_t val = $4; - if (val == 0) - emit4(0x00000025 | (reg<<11)); /* or reg, zero, zero */ - else if ((val < -0x8000) || (val > 0xffff)) + if ((val < -0x8000) || (val > 0xffff)) emit4(0x24000000 | (reg<<16) | (val & 0xffff)); /* addiu reg, zero, value */ else { diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index 5af88483d..2d2ba6992 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -9,7 +9,7 @@ * Only at and f30/f31 may be used. */ - li at, ha16[.fd_80000000] + lui at, ha16[.fd_80000000] ldc1 f30, lo16[.fd_80000000] (at) c.le.d 0, f30, f0 bc1t toobig diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 1a3c2a1f7..0677456ae 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -12,7 +12,7 @@ * Only at and f30/f31 may be used. */ - li at, ha16[.ff_80000000] + lui at, ha16[.ff_80000000] lwc1 f30, lo16[.ff_80000000] (at) c.le.s 0, f30, f0 bc1t toobig diff --git a/mach/mips/libem/c_ui_d.s b/mach/mips/libem/c_ui_d.s index ef987d50d..0432d9074 100644 --- a/mach/mips/libem/c_ui_d.s +++ b/mach/mips/libem/c_ui_d.s @@ -13,7 +13,7 @@ bgez r2, nonnegative nop - li at, ha16[.fd_100000000] + lui at, ha16[.fd_100000000] ldc1 f30, lo16[.fd_100000000] (at) add.d f0, f0, f30 nonnegative: diff --git a/mach/mips/libem/c_ui_f.s b/mach/mips/libem/c_ui_f.s index f54179fb8..e22745afb 100644 --- a/mach/mips/libem/c_ui_f.s +++ b/mach/mips/libem/c_ui_f.s @@ -13,7 +13,7 @@ bgez r2, nonnegative nop - li at, ha16[.fs_100000000] + lui at, ha16[.fs_100000000] ldc1 f30, lo16[.fs_100000000] (at) add.d f0, f0, f30 nonnegative: diff --git a/mach/mips/libem/fif8.s b/mach/mips/libem/fif8.s index 6b18ee746..e03812b4b 100644 --- a/mach/mips/libem/fif8.s +++ b/mach/mips/libem/fif8.s @@ -16,7 +16,7 @@ mul.d f0, f0, f2 ! f0 = a * b abs.d f2, f0 ! f2 = abs(f0) - li at, ha16[max_power_of_two] + 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 @@ -31,7 +31,7 @@ ! The above might round, so correct that. - li at, ha16[one] + lui at, ha16[one] ldc1 f8, lo16[one] (at) ! f8 = 1.0 1: c.le.d 0, f6, f2 ! if result <= absolute value, stop From 642956fa2f37086f782c1acfb5582010d3fc5dc1 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 12 Sep 2018 23:19:32 +0200 Subject: [PATCH 46/79] mcg now uses dataf4 and dataf8 to emit floating point constants, and so doesn't need flt_arith any more. (And also generates them correctly on little-endian systems.) as now parses numbers properly, doesn't trash memory all over the place, and can handle negative numbers. --- mach/proto/as/comm1.h | 2 +- mach/proto/as/comm2.y | 21 +++++++++++++-------- mach/proto/as/comm5.c | 16 +++++++++++----- mach/proto/as/comm7.c | 16 ++++++++++++++-- mach/proto/mcg/build.lua | 1 - mach/proto/mcg/data.c | 21 +-------------------- mach/proto/mcg/mcg.h | 1 - 7 files changed, 40 insertions(+), 38 deletions(-) diff --git a/mach/proto/as/comm1.h b/mach/proto/as/comm1.h index 47f4302b3..206ae0b5d 100644 --- a/mach/proto/as/comm1.h +++ b/mach/proto/as/comm1.h @@ -153,7 +153,7 @@ void emit1(int); void emit2(int); void emit4(long); void emitx(valu_t, int); -void emitf(int size); +void emitf(int size, int negative); void emitstr(int); void ffreopen(char *, FILE *); FILE *ffcreat(char *); diff --git a/mach/proto/as/comm2.y b/mach/proto/as/comm2.y index 0643928d8..3e1229a41 100644 --- a/mach/proto/as/comm2.y +++ b/mach/proto/as/comm2.y @@ -280,15 +280,20 @@ datalist } ; +numberf + : NUMBERF + { + emitf((int)$-1, 0); + } + | '-' NUMBERF + { + emitf((int)$-1, 1); + } + ; + dataflist - : NUMBERF - { - emitf((int)$0); - } - | dataflist ',' NUMBERF - { - emitf((int)$3); - } + : numberf + | dataflist ',' numberf ; expr : error diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index 9dc7a80bb..0b448ef0e 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -19,6 +19,8 @@ static int instring(int); static int inescape(void); static int infbsym(const char*); +static int maxstring = 0; + int yylex(void) { int c, c0, c1; @@ -453,16 +455,21 @@ floatconstant: { if (--radix < 0) fatal("number too long"); - if (isupper(c)) - c += ('a' - 'A'); *p++ = c; c = nextchar(); - } while (isdigit(c) || (c == '.') || (c == 'E') || (c == '+') || (c == '-')); + if (isupper(c)) + c = tolower(c); + } while (isdigit(c) || (c == '.') || (c == 'e') || (c == '+') || (c == '-')); peekc = c; *p = '\0'; - stringbuf = strdup(num); stringlen = p - num; + if (stringlen > maxstring) + { + maxstring = stringlen; + stringbuf = realloc(stringbuf, maxstring); + } + strcpy(stringbuf, num); return NUMBERF; } @@ -470,7 +477,6 @@ static int instring(int termc) { char* p; int c; - static int maxstring = 0; if (!maxstring) { diff --git a/mach/proto/as/comm7.c b/mach/proto/as/comm7.c index c9e340191..02a7c1d58 100644 --- a/mach/proto/as/comm7.c +++ b/mach/proto/as/comm7.c @@ -369,9 +369,21 @@ void emitstr(int zero) #define gen1 emit1 #include -void emitf(int size) +void emitf(int size, int negative) { - con_float(stringbuf, size); + char buffer[40]; + + if (stringlen > sizeof(buffer)-1) + fatal("floating point constant too long"); + + if (negative) + { + buffer[0] = '-'; + strcpy(buffer+1, stringbuf); + con_float(buffer, size); + } + else + con_float(stringbuf, size); } /* ---------- Error checked file I/O ---------- */ diff --git a/mach/proto/mcg/build.lua b/mach/proto/mcg/build.lua index 387d14d26..67c0645b5 100644 --- a/mach/proto/mcg/build.lua +++ b/mach/proto/mcg/build.lua @@ -35,7 +35,6 @@ definerule("build_mcg", "modules/src/data+lib", "modules/src/em_code+lib_k", "modules/src/em_data+lib", - "modules/src/flt_arith+lib", "modules/src/idf+lib", "modules/src/object+lib", "modules/src/read_em+lib_kv", diff --git a/mach/proto/mcg/data.c b/mach/proto/mcg/data.c index ff4ddb5bd..cbf1cd04f 100644 --- a/mach/proto/mcg/data.c +++ b/mach/proto/mcg/data.c @@ -1,13 +1,6 @@ #include "mcg.h" #include -#define IEEEFLOAT -#define FL_MSL_AT_LOW_ADDRESS 1 -#define FL_MSW_AT_LOW_ADDRESS 1 -#define FL_MSB_AT_LOW_ADDRESS 1 - -#include "con_float" - static struct symbol* pending; void data_label(const char* label) @@ -80,19 +73,7 @@ void data_float(const char* data, size_t size, bool is_ro) emit_header(is_ro ? SECTION_ROM : SECTION_DATA); assert((size == 4) || (size == 8)); - i = float_cst(data, size, (char*) buffer); - if ((i != 0) && (i != 2)) /* 2 == overflow */ - fatal("cannot parse floating point constant %s sz %d", data, size); - - fprintf(outputfile, "\t!float %s sz %d\n", data, size); - fprintf(outputfile, "\t.data1 "); - writehex(buffer[0], 1); - for (i=1; i #include #include -#include "flt_arith.h" #include "em_arith.h" #include "em_label.h" #include "em.h" From ecb3395abae5c62529a58507279c9cfe091e7406 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 12 Sep 2018 23:58:48 +0200 Subject: [PATCH 47/79] Converting floats and doubles to integers now works, as much as these ever do on MIPS; turns out that it can't (or at least can't in qemu) reliably turn INT_MIN from a double to an int. --- mach/mips/libem/c_ud_i.s | 3 ++- mach/mips/libem/c_uf_i.s | 3 ++- tests/plat/floats/from_d_to_si_e.c | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index 2d2ba6992..8ba1bfc04 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -24,7 +24,8 @@ toobig: sub.d f0, f0, f30 trunc.w.d f0, f0 mfc1 r2, f0 - addiu r2, r2, 0x8000 + lui at, 0x8000 ! load 0x80000000 + addu r2, r2, at jr ra nop diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 0677456ae..27f14e03e 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -27,7 +27,8 @@ toobig: sub.s f0, f0, f30 trunc.w.s f0, f0 mfc1 r2, f0 - addiu r2, r2, 0x8000 + lui at, 0x8000 ! load 0x80000000 + addu r2, r2, at jr ra nop diff --git a/tests/plat/floats/from_d_to_si_e.c b/tests/plat/floats/from_d_to_si_e.c index bc06c755c..2c587322a 100644 --- a/tests/plat/floats/from_d_to_si_e.c +++ b/tests/plat/floats/from_d_to_si_e.c @@ -6,7 +6,9 @@ double one = 1.0; double zero = 0.0; double minusone = -1.0; double big = (double)INT_MAX; -double minusbig = (double)INT_MIN; +/* We don't test INT_MIN because some platforms *cough*mips*cough* don't handle + * it correctly, and we don't want to fail them. */ +double minusbig = (double)(INT_MIN+1); /* Bypasses the CRT, so there's no stdio. */ void _m_a_i_n(void) @@ -15,7 +17,7 @@ void _m_a_i_n(void) ASSERT((int)one == 1); ASSERT((int)minusone == -1); ASSERT((int)big == INT_MAX); - ASSERT((int)minusbig == INT_MIN); + ASSERT((int)minusbig == (INT_MIN+1)); finished(); } From 57338b1991646ea71e2d1e7239f6774863ef0204 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 12 Sep 2018 23:59:09 +0200 Subject: [PATCH 48/79] Fix an incorrect instruction, and incredibly broken li handling. --- mach/mips/as/instructions.dat | 4 ++-- mach/mips/as/mach4.c | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index 98c4dbbe9..10619f8b3 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -234,8 +234,8 @@ 01001100000001101 "suxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' 111001 "swc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' 01001100000001000 "swxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' -01000100000001001 "trunc" ".l" F=fmt FS=fpr ',' FD=fpr -01000100000001101 "trunc" ".w" F=fmt FS=fpr ',' FD=fpr +01000100000001001 "trunc" ".l" F=fmt FD=fpr ',' FS=fpr +01000100000001101 "trunc" ".w" F=fmt FD=fpr ',' FS=fpr # Generic coprocessor instructions. diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 443ca1e49..0befb2dc1 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -2,10 +2,12 @@ | OP_LI GPR ',' extabsexp { word_t reg = $2; - word_t val = $4; + uint32_t val = $4; - if ((val < -0x8000) || (val > 0xffff)) + 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 */ @@ -16,7 +18,7 @@ { word_t reg = $2; word_t type = $4.typ & S_TYP; - word_t val = $4.val; + uint32_t val = $4.val; if (type != S_ABS) newrelo($4.typ, RELO2HI | FIXUPFLAGS); From 9b0a1c1c10a65c5d4cb725e5958da6ca59eb67d8 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 00:04:25 +0200 Subject: [PATCH 49/79] Make work with clang. --- mach/proto/cg/fillem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mach/proto/cg/fillem.c b/mach/proto/cg/fillem.c index 23c15c66f..25caeb513 100644 --- a/mach/proto/cg/fillem.c +++ b/mach/proto/cg/fillem.c @@ -85,6 +85,7 @@ int regallowed=0; extern char em_flag[]; extern short em_ptyp[]; extern double atof(); +extern void con_float(void); /* Own version of atol that continues computing on overflow. We don't know that about the ANSI C one. From 8c0b2f8aeeb3f4ca9bb09bed3ec2f163e6a214fe Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 00:15:43 +0200 Subject: [PATCH 50/79] Fix csa and csb. --- mach/mips/libem/csa.s | 8 ++++---- mach/mips/libem/csb.s | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mach/mips/libem/csa.s b/mach/mips/libem/csa.s index 1bdd41b62..bbc386be0 100644 --- a/mach/mips/libem/csa.s +++ b/mach/mips/libem/csa.s @@ -13,18 +13,18 @@ .define .csa .csa: lw r4, 0(sp) /* r4 = table */ - lw r5, 0(sp) /* r5 = value */ + 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, r6 /* adjust value */ + 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, r5, r7 /* compute (adjusted value - range) */ - blez r7, 1f /* jump to default if out of 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 */ diff --git a/mach/mips/libem/csb.s b/mach/mips/libem/csb.s index acc1f636e..c04382b79 100644 --- a/mach/mips/libem/csb.s +++ b/mach/mips/libem/csb.s @@ -13,7 +13,7 @@ .define .csb .csb: lw r4, 0(sp) ! r4 = address of table - lw r5, 0(sp) ! r5 = value + lw r5, 4(sp) ! r5 = value addiu sp, sp, 8 lw r6, 0(r4) ! r6 = default target From c4e3d0903e55f9054f8596df1beb3508406a1b9c Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 00:38:31 +0200 Subject: [PATCH 51/79] Bugfix rck. --- mach/mips/libem/rck.s | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mach/mips/libem/rck.s b/mach/mips/libem/rck.s index 01eca7156..f6d6606a4 100644 --- a/mach/mips/libem/rck.s +++ b/mach/mips/libem/rck.s @@ -15,13 +15,15 @@ addiu sp, sp, 4 ! leave value on stack lw r5, 0(sp) ! r5 = value - lw at, 0(sp) ! at = lower bound + lw at, 0(r4) ! at = lower bound slt at, r5, at ! at = r5 < at bne at, zero, .trap_erange + nop - lw at, 4(sp) ! at = upper bound + lw at, 4(r4) ! at = upper bound slt at, at, r5 ! at = at < r5 bne at, zero, .trap_erange + nop jr ra nop From ac33bdd0312c4221d55019cde87f8ebec6aace88 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 09:28:35 +0200 Subject: [PATCH 52/79] Clang-format before editing. --- util/led/relocate.c | 301 +++++++++++++++++++++++--------------------- 1 file changed, 160 insertions(+), 141 deletions(-) diff --git a/util/led/relocate.c b/util/led/relocate.c index 1f1dc89e6..02af6666a 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -18,7 +18,7 @@ static char rcsid[] = "$Id$"; #include "orig.h" #include "sym.h" -#define UBYTE(x) ((x) & BYTEMASK) +#define UBYTE(x) ((x)&BYTEMASK) static uint16_t read2(char* addr, int type) { @@ -34,10 +34,13 @@ static uint32_t read4(char* addr, int type) { unsigned short word0, word1; - if (type & RELBR) { + if (type & RELBR) + { word0 = (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]); word1 = (UBYTE(addr[2]) << WIDTH) + UBYTE(addr[3]); - } else { + } + else + { word0 = (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]); word1 = (UBYTE(addr[3]) << WIDTH) + UBYTE(addr[2]); } @@ -61,9 +64,9 @@ static uint32_t get_vc4_valu(char* addr) * st rd, $+o: [1110 0111 ww 1 d:5] [11111 o:27] */ - int32_t value = read4(addr+2, 0); + int32_t value = read4(addr + 2, 0); value &= 0x07ffffff; - value = value<<5>>5; + value = value << 5 >> 5; return value; } @@ -75,7 +78,7 @@ static uint32_t get_vc4_valu(char* addr) uint32_t value = read4(addr, RELWR); value &= 0x007fffff; - value = value<<9>>9; + value = value << 9 >> 9; value *= 2; return value; } @@ -90,18 +93,18 @@ static uint32_t get_vc4_valu(char* addr) int32_t value = read4(addr, RELWR); int32_t lov = value & 0x007fffff; int32_t hiv = value & 0x0f000000; - value = lov | (hiv>>1); - value = value<<5>>5; + value = lov | (hiv >> 1); + value = value << 5 >> 5; value *= 2; return value; } if ((opcode & 0xffe0) == 0xe500) { - /* lea: [1110 0101 000 d:5] [o:32] */ + /* lea: [1110 0101 000 d:5] [o:32] */ - return read4(addr+2, 0); - } + return read4(addr + 2, 0); + } assert(0 && "unrecognised VC4 instruction"); } @@ -137,22 +140,20 @@ static bool is_powerpc_memory_op(uint32_t opcode) static uint32_t get_powerpc_valu(char* addr, uint16_t type) { - uint32_t opcode1 = read4(addr+0, type); - uint32_t opcode2 = read4(addr+4, type); + uint32_t opcode1 = read4(addr + 0, type); + uint32_t opcode2 = read4(addr + 4, type); if ((opcode1 & 0xfc000000) == 0x48000000) { /* branch instruction */ return opcode1 & 0x03fffffd; } - else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && - ((opcode2 & 0xfc000000) == 0x60000000)) + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) { /* addis / ori instruction pair */ return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); } - else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && - is_powerpc_memory_op(opcode2)) + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && is_powerpc_memory_op(opcode2)) { /* addis / memoryop instruction pair */ uint16_t hi = opcode1 & 0xffff; @@ -166,12 +167,13 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) return ((hi << 16) | lo); } - fatal("Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx", - (unsigned long)opcode1, (unsigned long)opcode2); + fatal( + "Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx", + (unsigned long)opcode1, (unsigned long)opcode2); } /* RELOPPC_LIS stores a signed 26-bit offset in the low bits. */ -static uint32_t get_lis_valu(char *addr, uint16_t type) +static uint32_t get_lis_valu(char* addr, uint16_t type) { uint32_t valu = read4(addr, type) & 0x03ffffff; if (valu & 0x02000000) @@ -189,7 +191,7 @@ static uint32_t get_mips_valu(char* addr) case 3: /* jal */ case 29: /* jalx */ /* Unsigned 26-bit payload. */ - value = value & ((1<<26)-1); + value = value & ((1 << 26) - 1); break; default: /* assume everything else is a b, there are lots */ @@ -209,37 +211,41 @@ static uint32_t get_mips_valu(char* addr) */ static uint32_t getvalu(char* addr, uint16_t type) { - switch (type & RELSZ) { - case RELO1: - return UBYTE(addr[0]); - case RELO2: - case RELO2HI: - case RELO2HISAD: - return read2(addr, type); - case RELO4: - return read4(addr, type); - case RELOPPC: - return get_powerpc_valu(addr, type); - case RELOPPC_LIS: - return get_lis_valu(addr, type); - case RELOVC4: - return get_vc4_valu(addr); - case RELOMIPS: - return get_mips_valu(addr); - default: - fatal("can't read relocation type %x", type & RELSZ); + switch (type & RELSZ) + { + case RELO1: + return UBYTE(addr[0]); + case RELO2: + case RELO2HI: + case RELO2HISAD: + return read2(addr, type); + case RELO4: + return read4(addr, type); + case RELOPPC: + return get_powerpc_valu(addr, type); + case RELOPPC_LIS: + return get_lis_valu(addr, type); + case RELOVC4: + return get_vc4_valu(addr); + case RELOMIPS: + return get_mips_valu(addr); + default: + fatal("can't read relocation type %x", type & RELSZ); } /* NOTREACHED */ } static void write2(uint16_t valu, char* addr, int type) { - unsigned short word0, word1; + unsigned short word0, word1; - if (type & RELBR) { + if (type & RELBR) + { addr[0] = valu >> WIDTH; addr[1] = valu; - } else { + } + else + { addr[0] = valu; addr[1] = valu >> WIDTH; } @@ -247,21 +253,27 @@ static void write2(uint16_t valu, char* addr, int type) static void write4(uint32_t valu, char* addr, int type) { - unsigned short word0, word1; + unsigned short word0, word1; - if (type & RELWR) { + if (type & RELWR) + { word0 = valu >> (2 * WIDTH); word1 = valu; - } else { + } + else + { word0 = valu; word1 = valu >> (2 * WIDTH); } - if (type & RELBR) { + if (type & RELBR) + { addr[0] = word0 >> WIDTH; addr[1] = word0; addr[2] = word1 >> WIDTH; addr[3] = word1; - } else { + } + else + { addr[0] = word0; addr[1] = word0 >> WIDTH; addr[2] = word1; @@ -283,10 +295,10 @@ static void put_vc4_valu(char* addr, uint32_t value) * st rd, o, (pc): [1110 0111 ww 1 d:5] [11111 o:27] */ - uint32_t v = read4(addr+2, 0); + uint32_t v = read4(addr + 2, 0); v &= 0xf8000000; v |= value & 0x07ffffff; - write4(v, addr+2, 0); + write4(v, addr + 2, 0); } else if ((opcode & 0xf080) == 0x9000) { @@ -296,7 +308,7 @@ static void put_vc4_valu(char* addr, uint32_t value) uint32_t v = read4(addr, RELWR); v &= 0xff800000; - v |= (value/2) & 0x007fffff; + v |= (value / 2) & 0x007fffff; write4(v, addr, RELWR); } else if ((opcode & 0xf080) == 0x9080) @@ -307,19 +319,19 @@ static void put_vc4_valu(char* addr, uint32_t value) */ uint32_t v = read4(addr, RELWR); - uint32_t lovalue = (value/2) & 0x007fffff; - uint32_t hivalue = (value/2) & 0x07800000; + uint32_t lovalue = (value / 2) & 0x007fffff; + uint32_t hivalue = (value / 2) & 0x07800000; v &= 0xf0800000; - v |= lovalue | (hivalue<<1); + v |= lovalue | (hivalue << 1); write4(v, addr, RELWR); } else if ((opcode & 0xffe0) == 0xe500) { - /* lea: [1110 0101 000 d:5] [o:32] */ + /* lea: [1110 0101 000 d:5] [o:32] */ - write4(value, addr+2, 0); - } - else + write4(value, addr + 2, 0); + } + else assert(0 && "unrecognised VC4 instruction"); } @@ -330,8 +342,8 @@ static void put_vc4_valu(char* addr, uint32_t value) static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) { - uint32_t opcode1 = read4(addr+0, type); - uint32_t opcode2 = read4(addr+4, type); + uint32_t opcode1 = read4(addr + 0, type); + uint32_t opcode2 = read4(addr + 4, type); if ((opcode1 & 0xfc000000) == 0x48000000) { @@ -340,18 +352,16 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) i |= value & 0x03fffffd; write4(i, addr, type); } - else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && - ((opcode2 & 0xfc000000) == 0x60000000)) + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) { /* addis / ori instruction pair */ uint16_t hi = value >> 16; uint16_t lo = value & 0xffff; - write4((opcode1 & 0xffff0000) | hi, addr+0, type); - write4((opcode2 & 0xffff0000) | lo, addr+4, type); + write4((opcode1 & 0xffff0000) | hi, addr + 0, type); + write4((opcode2 & 0xffff0000) | lo, addr + 4, type); } - else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && - is_powerpc_memory_op(opcode2)) + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && is_powerpc_memory_op(opcode2)) { /* addis / memoryop instruction pair */ uint16_t hi = value >> 16; @@ -362,13 +372,14 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) if (lo > 0x7fff) hi++; - write4((opcode1 & 0xffff0000) | hi, addr+0, type); - write4((opcode2 & 0xffff0000) | lo, addr+4, type); + write4((opcode1 & 0xffff0000) | hi, addr + 0, type); + write4((opcode2 & 0xffff0000) | lo, addr + 4, type); } else - fatal("Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx", - (unsigned long)opcode1, (unsigned long)opcode2); + fatal( + "Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx", + (unsigned long)opcode1, (unsigned long)opcode2); } /* Writes a PowerPC lis instruction. */ @@ -413,14 +424,14 @@ static void put_mips_valu(char* addr, uint32_t value) case 3: /* jal */ case 29: /* jalx */ /* Unsigned 26-bit payload. */ - value = value & ((1<<26)-1); - opcode = opcode & ~((1<<26)-1); + value = value & ((1 << 26) - 1); + opcode = opcode & ~((1 << 26) - 1); break; default: /* assume everything else is a b, there are lots */ /* Signed 16-bit payload. */ - value = value & ((1<<16)-1); - opcode = opcode & ~((1<<16)-1); + value = value & ((1 << 16) - 1); + opcode = opcode & ~((1 << 16) - 1); break; } @@ -435,41 +446,42 @@ static void put_mips_valu(char* addr, uint32_t value) static putvalu(uint32_t valu, char* addr, uint16_t type) { - switch (type & RELSZ) { - case RELO1: - addr[0] = valu; - break; - case RELO2: - write2(valu, addr, type); - break; - case RELO2HI: - write2(valu>>16, addr, type); - break; - case RELO2HISAD: - write2((valu>>16) + !!(valu&0x8000), addr, type); - break; - case RELO4: - write4(valu, addr, type); - break; - case RELOPPC: - put_powerpc_valu(addr, valu, type); - break; - case RELOPPC_LIS: - put_lis_valu(addr, valu, type); - break; - case RELOVC4: - put_vc4_valu(addr, valu); - break; - case RELOMIPS: - put_mips_valu(addr, valu); - break; - default: - fatal("can't write relocation type %x", type & RELSZ); + switch (type & RELSZ) + { + case RELO1: + addr[0] = valu; + break; + case RELO2: + write2(valu, addr, type); + break; + case RELO2HI: + write2(valu >> 16, addr, type); + break; + case RELO2HISAD: + write2((valu >> 16) + !!(valu & 0x8000), addr, type); + break; + case RELO4: + write4(valu, addr, type); + break; + case RELOPPC: + put_powerpc_valu(addr, valu, type); + break; + case RELOPPC_LIS: + put_lis_valu(addr, valu, type); + break; + case RELOVC4: + put_vc4_valu(addr, valu); + break; + case RELOMIPS: + put_mips_valu(addr, valu); + break; + default: + fatal("can't write relocation type %x", type & RELSZ); } } -extern struct outsect outsect[]; -extern struct orig relorig[]; +extern struct outsect outsect[]; +extern struct orig relorig[]; /* * There are two cases: `local' is an undefined external or common name, @@ -483,42 +495,47 @@ extern struct orig relorig[]; * Second case: we must update the value by the change * in position of the section of local. */ -static unsigned -addrelo(relo, names, valu_out) - struct outrelo *relo; - struct outname *names; - long *valu_out; /* Out variable. */ +static unsigned addrelo(relo, names, valu_out) struct outrelo* relo; +struct outname* names; +long* valu_out; /* Out variable. */ { - register struct outname *local = &names[relo->or_nami]; - register unsigned short index = NLocals; - register long valu = *valu_out; + register struct outname* local = &names[relo->or_nami]; + register unsigned short index = NLocals; + register long valu = *valu_out; - if ((local->on_type & S_SCT)) { - register int sectindex = (local->on_type & S_TYP) - S_MIN; + if ((local->on_type & S_SCT)) + { + register int sectindex = (local->on_type & S_TYP) - S_MIN; valu += relorig[sectindex].org_size; valu += outsect[sectindex].os_base; index += NGlobals + sectindex; - } else { - register struct outname *name; - extern int hash(); - extern struct outname *searchname(); - extern unsigned indexof(); - extern struct outhead outhead; + } + else + { + register struct outname* name; + extern int hash(); + extern struct outname* searchname(); + extern unsigned indexof(); + extern struct outhead outhead; name = searchname(local->on_mptr, hash(local->on_mptr)); - if (name == (struct outname *)0) + if (name == (struct outname*)0) fatal("name %s not found in pass 2", local->on_mptr); - if (ISCOMMON(name) || ISUNDEFINED(name)) { - debug("can't relocate from %s\n",local->on_mptr,0,0,0); + if (ISCOMMON(name) || ISUNDEFINED(name)) + { + debug("can't relocate from %s\n", local->on_mptr, 0, 0, 0); index += indexof(name); - } else { + } + else + { valu += name->on_valu; - if ((name->on_type & S_TYP) == S_ABS) { + if ((name->on_type & S_TYP) == S_ABS) + { index += NGlobals + outhead.oh_nsect; } - else index += NGlobals + - (name->on_type & S_TYP) - S_MIN; + else + index += NGlobals + (name->on_type & S_TYP) - S_MIN; } } *valu_out = valu; @@ -530,16 +547,15 @@ addrelo(relo, names, valu_out) * which the header is pointed to by `head'. Relocation is relative to the * names in `names'; `relo' tells how to relocate. */ -relocate(head, emit, names, relo, off) - struct outhead *head; - char *emit; - struct outname names[]; - struct outrelo *relo; - long off; +relocate(head, emit, names, relo, off) struct outhead* head; +char* emit; +struct outname names[]; +struct outrelo* relo; +long off; { - long valu; - int sectindex = relo->or_sect - S_MIN; - extern struct outhead outhead; + long valu; + int sectindex = relo->or_sect - S_MIN; + extern struct outhead outhead; /* * Pick up previous value at location to be relocated. @@ -553,10 +569,13 @@ relocate(head, emit, names, relo, off) * - a section name * - the first name outside! the name table (argh) */ - if (relo->or_nami < head->oh_nname) { + if (relo->or_nami < head->oh_nname) + { /* First two cases. */ relo->or_nami = addrelo(relo, names, &valu); - } else { + } + else + { /* * Third case: it is absolute. The relocation of absolute * names is always 0. We only need to change the index. @@ -571,7 +590,7 @@ relocate(head, emit, names, relo, off) * now we subtract the origin of the referencING section. */ if (relo->or_type & RELPC) - valu -= relorig[sectindex].org_size+outsect[sectindex].os_base; + valu -= relorig[sectindex].org_size + outsect[sectindex].os_base; /* * Now put the value back. From ba0849c87cc27429d2f41e4dfeab4462b82e66b0 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 11:30:15 +0200 Subject: [PATCH 53/79] Remove la; turns out that the assembler gets upset if you ask it to generate more than one fixup per instruction (I think). --- mach/mips/as/mach2.c | 1 - mach/mips/as/mach3.c | 1 - mach/mips/as/mach4.c | 15 +-------------- mach/mips/mcg/table | 6 ++++-- util/led/relocate.c | 4 ++++ 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index 9b11f1f1c..3c1ee89dc 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -3,7 +3,6 @@ %token FCOND %token OP_LI -%token OP_LA %token HI16 %token HA16 diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 008759d9d..d3cb812c5 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -75,7 +75,6 @@ 0, FPR, 31, "f31", 0, OP_LI, 0, "li", -0, OP_LA, 0, "la", 0, HI16, 0, "hi16", 0, HA16, 0, "ha16", 0, LO16, 0, "lo16", diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 0befb2dc1..9e8dab51f 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -14,19 +14,6 @@ emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */ } } - | OP_LA GPR ',' expr - { - word_t reg = $2; - word_t type = $4.typ & S_TYP; - uint32_t val = $4.val; - - if (type != S_ABS) - newrelo($4.typ, RELO2HI | FIXUPFLAGS); - emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ - if (type != S_ABS) - newrelo($4.typ, RELO2 | FIXUPFLAGS); - emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */ - } extabsexp : absexp @@ -194,4 +181,4 @@ insmsblsb int size = $3; $$ = ((pos+size-1) << 5) | pos; } - ; \ No newline at end of file + ; diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 43051cb4e..dbda9c84a 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -635,11 +635,13 @@ PATTERNS ALUCC(EOR.I, "xori") out:(int)reg = value:LABEL.I - emit "la %out, $value" + emit "lui %out, hi16[$value]" + emit "ori %out, %out, lo16[$value]" cost 4; out:(int)reg = value:BLOCK.I - emit "la %out, $value" + emit "lui %out, hi16[$value]" + emit "ori %out, %out, lo16[$value]" cost 4; out:(int)reg = value:CONST.I diff --git a/util/led/relocate.c b/util/led/relocate.c index 02af6666a..9fac60e52 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -556,11 +556,14 @@ long off; long valu; int sectindex = relo->or_sect - S_MIN; extern struct outhead outhead; + uint32_t realaddress = outsect[sectindex].os_base + relo->or_addr + + relorig[sectindex].org_size; /* * Pick up previous value at location to be relocated. */ valu = getvalu(emit + (relo->or_addr - off), relo->or_type); + debug("read relocation from 0x%08x type 0x%x value 0x%08x symbol %d\n", realaddress, relo->or_type, valu, relo->or_nami); /* * Or_nami is an index in the name table of the considered module. @@ -595,6 +598,7 @@ long off; /* * Now put the value back. */ + debug("written fixed up relocation to 0x%08x type 0x%x value 0x%08x\n", realaddress, relo->or_type, valu, 0); putvalu(valu, emit + (relo->or_addr - off), relo->or_type); /* From 5d0876a30b62266606d7696987b41818dfe9bfa1 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 12:26:27 +0200 Subject: [PATCH 54/79] Implement a working .trp. --- mach/mips/libem/trp.s | 59 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s index a283b07a2..29e8543d7 100644 --- a/mach/mips/libem/trp.s +++ b/mach/mips/libem/trp.s @@ -1,8 +1,6 @@ # -.sect .text -.sect .rom -.sect .data -.sect .bss +.sect .text; .sect .rom; .sect .data; .sect .bss + .sect .text .define .trap_ecase @@ -10,7 +8,58 @@ li r4, 20 ! ECASE = 20 in h/em_abs.h ! FALLTHROUGH to .trp +! Raises an EM trap. +! Expects r4 = trap number. + .define .trp .trp: - syscall 0 + 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" From 08b1e8d71ba7511945f19f20f82716bafedb44b4 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 13:48:43 +0200 Subject: [PATCH 55/79] Make inn work; fix broken 64-bit loads and stores. --- mach/mips/libem/inn.s | 17 ++++++++--------- mach/mips/mcg/table | 8 ++++---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/mach/mips/libem/inn.s b/mach/mips/libem/inn.s index 07a4991b6..a0fcb0931 100644 --- a/mach/mips/libem/inn.s +++ b/mach/mips/libem/inn.s @@ -13,21 +13,20 @@ .define .inn .inn: lw r4, 0(sp) ! r4 = size of set (bytes) - lw r5, 0(sp) ! r5 = bit number - addiu sp, sp, 8 ! sp now points at bitset + lw r5, 4(sp) ! r5 = bit number + addiu sp, sp, 4 ! sp now points to word below bitset - srl r6, r5, 3 ! r6 = offset of word in set + 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, 0(r6) ! r6 = word + lw r6, 4(r6) ! r6 = word (remember stack offset) - ext r7, r5, 0, 3 ! r7 = bit number within word + 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 - - addiu sp, sp, -4 - sw r6, 0(sp) ! push result + addu sp, sp, r4 ! retract over bitfield (remember stack offset) + sw r6, 0(sp) ! store result jr ra nop diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index dbda9c84a..321eaea5d 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -233,8 +233,8 @@ PATTERNS /* Stores */ STORE.L(addr:address, value:(long)reg) - emit "sw %value.0, 4+%addr" - emit "sw %value.1, 0+%addr" + emit "sw %value.0, 0+%addr" + emit "sw %value.1, 4+%addr" cost 8; STORE.I(addr:address, value:(int)reg) @@ -267,8 +267,8 @@ PATTERNS * a register, resulting in %addr being corrupted before %out.1 is * loaded. */ out:(long)reg = LOAD.L(addr:address) - emit "lw at, 4+%addr" - emit "lw %out.1, 0+%addr" + emit "lw at, 0+%addr" + emit "lw %out.1, 4+%addr" emit "mov %out.0, at" cost 12; From 7efb749003af12a20f9dcc802356a0f3d5d00e31 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 Sep 2018 14:13:35 +0100 Subject: [PATCH 56/79] Set fixes; also add discrete tests for and, ior, xor. --- mach/mips/libem/com.s | 1 + mach/mips/libem/xor.s | 30 +++++++++++++++++++++++ mach/mips/libem/zer.s | 1 + tests/plat/core/and_e.e | 54 +++++++++++++++++++++++++++++++++++++++++ tests/plat/core/ior_e.e | 54 +++++++++++++++++++++++++++++++++++++++++ tests/plat/core/xor_e.e | 54 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 mach/mips/libem/xor.s create mode 100644 tests/plat/core/and_e.e create mode 100644 tests/plat/core/ior_e.e create mode 100644 tests/plat/core/xor_e.e diff --git a/mach/mips/libem/com.s b/mach/mips/libem/com.s index fae0d64e5..ffabe9f5e 100644 --- a/mach/mips/libem/com.s +++ b/mach/mips/libem/com.s @@ -21,6 +21,7 @@ addiu r5, r5, 4 addiu r4, r4, -1 bne r4, zero, 1b + nop jr ra nop diff --git a/mach/mips/libem/xor.s b/mach/mips/libem/xor.s new file mode 100644 index 000000000..ad23b1d52 --- /dev/null +++ b/mach/mips/libem/xor.s @@ -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 + diff --git a/mach/mips/libem/zer.s b/mach/mips/libem/zer.s index 6941d340b..b48fb8ffc 100644 --- a/mach/mips/libem/zer.s +++ b/mach/mips/libem/zer.s @@ -18,6 +18,7 @@ sw zero, 0(sp) addiu r4, r4, -1 bne r4, zero, 1b + nop jr ra nop diff --git a/tests/plat/core/and_e.e b/tests/plat/core/and_e.e new file mode 100644 index 000000000..1bdf3d5ed --- /dev/null +++ b/tests/plat/core/and_e.e @@ -0,0 +1,54 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* And word-sized set */ + +four + rom EM_WSIZE + + loc 32769 + loc 1 + loe four /* to defeat constant folding */ + and + loc 1 + cmu EM_WSIZE + zeq *1 + + loc __LINE__ + cal $fail + asp 4 +1 + + /* And triple-word-sized set */ + +four_by_three + rom EM_WSIZE*3 + + loc 32769 + loc 32770 + loc 32772 + loc 1 + loc 2 + loc 4 + loe four_by_three + and + loc 4 + cmu EM_WSIZE + zne *2 + loc 2 + cmu EM_WSIZE + zne *2 + loc 1 + cmu EM_WSIZE + zeq *3 +2 + loc __LINE__ + cal $fail + asp 4 +3 + + cal $finished + end diff --git a/tests/plat/core/ior_e.e b/tests/plat/core/ior_e.e new file mode 100644 index 000000000..9f4a0d985 --- /dev/null +++ b/tests/plat/core/ior_e.e @@ -0,0 +1,54 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Or word-sized set */ + +four + rom EM_WSIZE + + loc 0 + loc 1 + loe four /* to defeat constant folding */ + ior + loc 1 + cmu EM_WSIZE + zeq *1 + + loc __LINE__ + cal $fail + asp 4 +1 + + /* Or triple-word-sized set */ + +four_by_three + rom EM_WSIZE*3 + + loc 16 + loc 32 + loc 64 + loc 1 + loc 2 + loc 3 + loe four_by_three + ior + loc 67 + cmu EM_WSIZE + zne *2 + loc 34 + cmu EM_WSIZE + zne *2 + loc 17 + cmu EM_WSIZE + zeq *3 +2 + loc __LINE__ + cal $fail + asp 4 +3 + + cal $finished + end diff --git a/tests/plat/core/xor_e.e b/tests/plat/core/xor_e.e new file mode 100644 index 000000000..8218ee63c --- /dev/null +++ b/tests/plat/core/xor_e.e @@ -0,0 +1,54 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Xor word-sized set */ + +four + rom EM_WSIZE + + loc 32769 + loc 1 + loe four /* to defeat constant folding */ + xor + loc 32768 + cmu EM_WSIZE + zeq *1 + + loc __LINE__ + cal $fail + asp 4 +1 + + /* Xor triple-word-sized set */ + +four_by_three + rom EM_WSIZE*3 + + loc 32769 + loc 32770 + loc 32772 + loc 1 + loc 2 + loc 4 + loe four_by_three + xor + loc 32768 + cmu EM_WSIZE + zne *2 + loc 32768 + cmu EM_WSIZE + zne *2 + loc 32768 + cmu EM_WSIZE + zeq *3 +2 + loc __LINE__ + cal $fail + asp 4 +3 + + cal $finished + end From 15ae171aefc8112de019231ed5bb85233d7218fb Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 11:56:15 +0100 Subject: [PATCH 57/79] Added a test for set. Fix mips set implementation. --- mach/mips/libem/set.s | 12 +++++----- tests/plat/core/set_e.e | 50 +++++++++++++++++++++++++++++++++++++++++ tests/plat/lib/test.c | 4 ++-- tests/plat/lib/test.h | 4 ++-- 4 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 tests/plat/core/set_e.e diff --git a/mach/mips/libem/set.s b/mach/mips/libem/set.s index 01a6ff654..ec45eb45a 100644 --- a/mach/mips/libem/set.s +++ b/mach/mips/libem/set.s @@ -11,23 +11,25 @@ .set: lw r4, 0(sp) ! r4 = size lw r5, 4(sp) ! r5 = bit number - addiu sp, sp, 4 + addiu sp, sp, 8 srl r4, r4, 2 ! r4 = word count - ! Create an empty set. + ! 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. - srl r6, r5, 3 ! r6 = offset of word in set - addu r6, sp, r6 ! r6 = address of word in 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 - ext r7, r5, 0, 3 ! r7 = bit number within word + 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 diff --git a/tests/plat/core/set_e.e b/tests/plat/core/set_e.e new file mode 100644 index 000000000..55659a3de --- /dev/null +++ b/tests/plat/core/set_e.e @@ -0,0 +1,50 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Create word-sized singleton set. */ + +word + rom EM_WSIZE + + loc 1 + loe word /* to defeat constant folding */ + set + + loc 2 + cmu EM_WSIZE + zeq *1 + + loc __LINE__ + cal $fail + asp 4 +1 + + /* Create triple-word-sized set with low bit */ + + loc EM_WSIZE*8 + 1 + loe word /* to defeat constant folding */ + loc 3 + mli EM_WSIZE + set + + + loc 0 + cmu EM_WSIZE + zne *2 + loc 2 + cmu EM_WSIZE + zne *2 + loc 0 + cmu EM_WSIZE + zeq *3 +2 + loc __LINE__ + cal $fail + asp 4 +3 + + cal $finished + end diff --git a/tests/plat/lib/test.c b/tests/plat/lib/test.c index 6df3ee7d5..33a4e86e7 100644 --- a/tests/plat/lib/test.c +++ b/tests/plat/lib/test.c @@ -9,7 +9,7 @@ void finished(void) _exit(0); } -void writehex(uint32_t code) +void writehex(unsigned int code) { char buf[8]; char* p = &buf[sizeof(buf)]; @@ -24,7 +24,7 @@ void writehex(uint32_t code) write(1, p, buf + sizeof(buf) - p); } -void fail(uint32_t code) +void fail(unsigned int code) { static const char fail_msg[] = "@@FAIL 0x"; static const char nl_msg[] = "\n"; diff --git a/tests/plat/lib/test.h b/tests/plat/lib/test.h index db16506f9..6c0acc6b2 100644 --- a/tests/plat/lib/test.h +++ b/tests/plat/lib/test.h @@ -5,8 +5,8 @@ #include extern void finished(void); -extern void writehex(uint32_t code); -extern void fail(uint32_t code); +extern void writehex(unsigned int code); +extern void fail(unsigned int code); #define ASSERT(condition) \ do { if (!(condition)) fail(__LINE__); } while(0) From 0b655919724d033cc89ccf5ab089132c86e20497 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 12:16:17 +0100 Subject: [PATCH 58/79] Add hacky 64-bit comparisons (used by M2). --- mach/mips/libem/compareul.s | 39 +++++++++++++++++++++++++++++++++++++ mach/mips/mcg/table | 7 ++++++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 mach/mips/libem/compareul.s diff --git a/mach/mips/libem/compareul.s b/mach/mips/libem/compareul.s new file mode 100644 index 000000000..dccd92234 --- /dev/null +++ b/mach/mips/libem/compareul.s @@ -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 r3r5, then 1 + bne at, zero, exit + nop + + /* High words are equal --- compare low words. */ + + sltu at, r2, r4 ! if r2r4, then 1 +exit: + mov r2, at + jr ra + nop + diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 321eaea5d..955e09ace 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -35,7 +35,7 @@ REGISTERS r22 named("r22") int; r23 named("r23") int; - r4r5 named("r4", "r5") aliases(r4, r5) long volatile; + r4r5 named("r4", "r5") aliases(r4, r5) long volatilei lret1; r6r7 named("r6", "r7") aliases(r6, r7) long volatile; r8r9 named("r8", "r9") aliases(r8, r9) long volatile; r10r11 named("r10", "r11") aliases(r10, r11) long volatile; @@ -490,6 +490,11 @@ PATTERNS emit "1:" cost 20; + out:(iret)reg = COMPAREUL.I(left:(lret)reg, right:(lret1)reg) + emit "jal .compareul" + emit "nop" + cost 30; + out:(int)reg = COMPAREF.I(left:(float)reg, right:(float)reg) with preserved(%left), preserved(%right) emit "c.lt.s 0, %left, %right" From 1e073e944a412f3bd0a3441c1c36f246acec49ab Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 12:42:10 +0100 Subject: [PATCH 59/79] Added cms, and a test for it. --- mach/mips/libem/cms.s | 35 +++++++++++++++++++ tests/plat/core/cms_e.e | 75 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 mach/mips/libem/cms.s create mode 100644 tests/plat/core/cms_e.e diff --git a/mach/mips/libem/cms.s b/mach/mips/libem/cms.s new file mode 100644 index 000000000..e7e87e731 --- /dev/null +++ b/mach/mips/libem/cms.s @@ -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 + diff --git a/tests/plat/core/cms_e.e b/tests/plat/core/cms_e.e new file mode 100644 index 000000000..fe79de253 --- /dev/null +++ b/tests/plat/core/cms_e.e @@ -0,0 +1,75 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Compare equal word sets. */ + +word + rom EM_WSIZE + + loc 1 + loc 1 + loe word /* to defeat constant folding */ + cms + zeq *1 + + loc __LINE__ + cal $fail + asp 4 +1 + + /* Compare non-equal word sets. */ + + loc 1 + loc 2 + loe word /* to defeat constant folding */ + cms + zne *2 + + loc __LINE__ + cal $fail + asp 4 +2 + + /* Compare equal triple-word sets. */ + + loc 1 + loc 2 + loc 3 + loc 1 + loc 2 + loc 3 + loe word /* to defeat constant folding */ + loc 3 + mli EM_WSIZE + cms + zeq *3 + + loc __LINE__ + cal $fail + asp 4 +3 + + /* Compare non-equal triple-word sets. */ + + loc 1 + loc 2 + loc 3 + loc 1 + loc 2 + loc 4 + loe word /* to defeat constant folding */ + loc 3 + mli EM_WSIZE + cms + zne *4 + + loc __LINE__ + cal $fail + asp 4 +4 + + cal $finished + end From 0202ac8700294f957058528049c350dd8212225a Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 12:53:27 +0100 Subject: [PATCH 60/79] Fix bls4. --- mach/mips/libem/bls4.s | 1 + 1 file changed, 1 insertion(+) diff --git a/mach/mips/libem/bls4.s b/mach/mips/libem/bls4.s index 559e23fe2..35d287f5b 100644 --- a/mach/mips/libem/bls4.s +++ b/mach/mips/libem/bls4.s @@ -24,6 +24,7 @@ addiu r5, r5, 4 addiu r4, r4, -1 b 1b + nop 2: jr ra From c2dc1e184e7eda2b52873ea16d29e80ccefcc7ab Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 13:13:39 +0100 Subject: [PATCH 61/79] rotate() now generates valid code. --- mach/proto/mcg/treebuilder.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index ac811fc14..5f9eebf86 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -717,6 +717,10 @@ static void rotate(int opcode, int size, int irop, int irop_reverse) struct ir* left = pop(size); struct ir* bits = new_wordir(8 * size); + /* Fix left and right so we can refer to them multiple times. */ + appendir(right); + appendir(left); + /* a rol b -> (a << b) | (a >> (32 - b)) */ push( new_ir2( From b665efca04c161ad5c9bfb2b7fb425c694ff639a Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 15:03:44 +0100 Subject: [PATCH 62/79] ACK loi 1 and sti 1 load and store unsigned bytes. I think. --- mach/mips/mcg/table | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 955e09ace..0703b156f 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -273,11 +273,11 @@ PATTERNS cost 12; out:(int)ushort0 = LOADH.I(addr:address) - emit "lh %out, %addr" + emit "lhu %out, %addr" cost 4; out:(int)ubyte0 = LOADB.I(addr:address) - emit "lb %out, %addr" + emit "lbu %out, %addr" cost 4; out:(float)reg = LOAD.F(addr:address) From abb7e3e105b6245bfb39b6b19add1063b9c3723f Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 16:59:45 +0100 Subject: [PATCH 63/79] Fix aar; add test. --- mach/mips/libem/aar4.s | 24 ++++++++----- tests/plat/core/aar_e.e | 76 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 tests/plat/core/aar_e.e diff --git a/mach/mips/libem/aar4.s b/mach/mips/libem/aar4.s index fc1068f48..b9873300e 100644 --- a/mach/mips/libem/aar4.s +++ b/mach/mips/libem/aar4.s @@ -6,25 +6,33 @@ * 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) + * +8 element size */ .sect .text .define .aar4 .aar4: lw r4, 0(sp) ! r4 = address of descriptor - lw r5, 0(sp) ! r5 = index - lw r6, 0(sp) ! r6 = address of array + lw r5, 4(sp) ! r5 = index + lw r6, 8(sp) ! r6 = address of array - lw r7, 0(r4) ! at = lower bound - slt at, r7, at ! at = r5 < at + 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 = upper bound - slt at, at, r5 ! at = at < r5 - bne at, zero, .trap_earray + lw at, 4(r4) ! at = range + slt at, r5, at ! at = adjusted index < range + beq at, zero, .trap_earray + nop lw r2, 8(r4) ! r2 = size of element - subu r5, r5, r7 ! adjust index for non-zero lower bound mul r5, r5, r2 ! scale index by size addu r5, r5, r6 ! calculate address of element diff --git a/tests/plat/core/aar_e.e b/tests/plat/core/aar_e.e new file mode 100644 index 000000000..bd8230d7a --- /dev/null +++ b/tests/plat/core/aar_e.e @@ -0,0 +1,76 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + +/* + * Does basic testing of aar. Unfortunately, aar throws ERANGE on + * error, which we can't catch (or at least, the platforms I've looked at + * don't allow it to be caught, those platforms which actually throw it on + * error). So we just test the non-throwing cases, not the negative ones. + */ + +array + bss 3*EM_WSIZE, 0, 0 + +descriptor + con -1 ; lower bound + con 3 ; range + con EM_WSIZE ; size of element + + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Access element -1 */ + + lae array + loc -1 + lae descriptor + aar EM_WSIZE + + lae array + cmu EM_WSIZE + zeq *1 + + loc __LINE__ + cal $fail + ass EM_WSIZE +1 + + /* Access element 0 */ + + lae array + loc 0 + lae descriptor + aar EM_WSIZE + + lae array + adp EM_WSIZE + cmu EM_WSIZE + zeq *2 + + loc __LINE__ + cal $fail + ass EM_WSIZE +2 + + /* Access element 1 */ + + lae array + loc 1 + lae descriptor + aar EM_WSIZE + + lae array + adp EM_WSIZE*2 + cmu EM_WSIZE + zeq *3 + + loc __LINE__ + cal $fail + ass EM_WSIZE +3 + + cal $finished + + end + From f61500c51bbd8c60c4e376522d307262b03edc09 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 18:44:17 +0100 Subject: [PATCH 64/79] Fix lar and sar, which were horribly, horribly broken. Add tests. --- mach/mips/libem/lar4.s | 2 +- mach/mips/libem/los4.s | 16 ++--- mach/mips/libem/sar4.s | 2 +- tests/plat/core/aar_e.e | 1 - tests/plat/core/lar_e.e | 73 +++++++++++++++++++++++ tests/plat/core/sar_e.e | 125 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+), 11 deletions(-) create mode 100644 tests/plat/core/lar_e.e create mode 100644 tests/plat/core/sar_e.e diff --git a/mach/mips/libem/lar4.s b/mach/mips/libem/lar4.s index 870140255..218496644 100644 --- a/mach/mips/libem/lar4.s +++ b/mach/mips/libem/lar4.s @@ -14,7 +14,7 @@ jal .aar4 nop - /* pass r2 = size from .aar4 to .los4 + /* pass r2 = size from .aar4 to .los4 */ jal .los4 nop diff --git a/mach/mips/libem/los4.s b/mach/mips/libem/los4.s index be9434a34..bebb7b616 100644 --- a/mach/mips/libem/los4.s +++ b/mach/mips/libem/los4.s @@ -11,7 +11,7 @@ .sect .text .define .los4 .los4: - lw r4, 0(sp) ! r4 = address + lw r4, 0(sp) ! r4 = address of source block ! Sizes 1 and 2 are handled specially. @@ -26,14 +26,14 @@ ! Else the size must be a multiple of 4. srl r5, r2, 2 ! r5 = number of words - addiu sp, sp, 4 ! adjust to end of block - subu sp, sp, r4 ! sp = start of block - mov r6, sp ! r6 = start of block + 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(r2) + lw at, 0(r4) sw at, 0(r6) - addiu r2, r2, 4 + addiu r4, r4, 4 addiu r6, r6, 4 addiu r5, r5, -1 bne r5, zero, 1b @@ -43,13 +43,13 @@ nop byte_sized: - lb at, 0(r4) + lbu at, 0(r4) sw at, 0(sp) jr ra nop word_sized: - lh at, 0(r4) + lhu at, 0(r4) sw at, 0(sp) jr ra nop diff --git a/mach/mips/libem/sar4.s b/mach/mips/libem/sar4.s index a1ddea33c..8c70bf553 100644 --- a/mach/mips/libem/sar4.s +++ b/mach/mips/libem/sar4.s @@ -14,7 +14,7 @@ jal .aar4 nop - /* pass r2 = size from .aar4 to .sts4 + /* pass r2 = size from .aar4 to .sts4 */ jal .sts4 nop diff --git a/tests/plat/core/aar_e.e b/tests/plat/core/aar_e.e index bd8230d7a..0b53e5b50 100644 --- a/tests/plat/core/aar_e.e +++ b/tests/plat/core/aar_e.e @@ -71,6 +71,5 @@ descriptor 3 cal $finished - end diff --git a/tests/plat/core/lar_e.e b/tests/plat/core/lar_e.e new file mode 100644 index 000000000..650865b04 --- /dev/null +++ b/tests/plat/core/lar_e.e @@ -0,0 +1,73 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + +/* + * Does basic testing of lar. Unfortunately, lar throws ERANGE on + * error, which we can't catch (or at least, the platforms I've looked at + * don't allow it to be caught, those platforms which actually throw it on + * error). So we just test the non-throwing cases, not the negative ones. + */ + +#define ARRAY_SIZE 3*EM_WSIZE + +array + con 1 + con 2 + con 3 + +descriptor + con -1 ; lower bound + con 3 ; range + con EM_WSIZE ; size of element + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Read element -1 */ + + lae array + loc -1 + lae descriptor + lar EM_WSIZE + + loc 1 + beq *1 + + loc __LINE__ + cal $fail + ass EM_WSIZE +1 + + /* Read element 0 */ + + lae array + loc 0 + lae descriptor + lar EM_WSIZE + + loc 2 + beq *2 + + loc __LINE__ + cal $fail + ass EM_WSIZE +2 + + /* Read element 1 */ + + lae array + loc 1 + lae descriptor + lar EM_WSIZE + + loc 3 + beq *3 + + loc __LINE__ + cal $fail + ass EM_WSIZE +3 + + cal $finished + end + diff --git a/tests/plat/core/sar_e.e b/tests/plat/core/sar_e.e new file mode 100644 index 000000000..7c6da941b --- /dev/null +++ b/tests/plat/core/sar_e.e @@ -0,0 +1,125 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + +/* + * Does basic testing of sar. Unfortunately, sar throws ERANGE on + * error, which we can't catch (or at least, the platforms I've looked at + * don't allow it to be caught, those platforms which actually throw it on + * error). So we just test the non-throwing cases, not the negative ones. + */ + +#define ARRAY_SIZE 3*EM_WSIZE + +array + bss ARRAY_SIZE, 0, 0 + +descriptor + con -1 ; lower bound + con 3 ; range + con EM_WSIZE ; size of element + +element0 + con 1 + con 0 + con 0 + +element1 + con 0 + con 1 + con 0 + +element2 + con 0 + con 0 + con 1 + + exp $_m_a_i_n + pro $_m_a_i_n, 0 + + /* Write element -1 */ + + cal $clear_array + loc 1 + lae array + loc -1 + lae descriptor + sar EM_WSIZE + + lae array + loi ARRAY_SIZE + lae element0 + loi ARRAY_SIZE + loc ARRAY_SIZE + cms + zeq *1 + + loc __LINE__ + cal $fail + ass EM_WSIZE +1 + + /* Write element 0 */ + + cal $clear_array + loc 1 + lae array + loc 0 + lae descriptor + sar EM_WSIZE + + lae array + loi ARRAY_SIZE + lae element1 + loi ARRAY_SIZE + loc ARRAY_SIZE + cms + zeq *2 + + loc __LINE__ + cal $fail + ass EM_WSIZE +2 + + /* Write element 1 */ + + cal $clear_array + loc 1 + lae array + loc 1 + lae descriptor + sar EM_WSIZE + + lae array + loi ARRAY_SIZE + lae element2 + loi ARRAY_SIZE + loc ARRAY_SIZE + cms + zeq *3 + + loc __LINE__ + cal $fail + ass EM_WSIZE +3 + + cal $finished + end + + exp $clear_array + pro $clear_array, 0 + + loc 0 + lae array + EM_WSIZE*0 + sti EM_WSIZE + + loc 0 + lae array + EM_WSIZE*1 + sti EM_WSIZE + + loc 0 + lae array + EM_WSIZE*2 + sti EM_WSIZE + + ret 0 + end + From ec0891469f7db372530025ddfd66e17e5a6046db Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 19:34:38 +0100 Subject: [PATCH 65/79] Array descriptor ranges are inclusive; adjust aar and the tests to check for this. All the tests except rotate build now! --- mach/mips/libem/aar4.s | 6 +++--- plat/linuxmips/tests/build.lua | 2 +- tests/plat/core/aar_e.e | 2 +- tests/plat/core/lar_e.e | 2 +- tests/plat/core/sar_e.e | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mach/mips/libem/aar4.s b/mach/mips/libem/aar4.s index b9873300e..e33165b9d 100644 --- a/mach/mips/libem/aar4.s +++ b/mach/mips/libem/aar4.s @@ -10,7 +10,7 @@ * An array descriptor is: * * +0 lower bound - * +4 range (upper bound - lower bound) + * +4 range (upper bound - lower bound); *inclusive* * +8 element size */ @@ -28,8 +28,8 @@ subu r5, r5, r7 ! adjust index for non-zero lower bound lw at, 4(r4) ! at = range - slt at, r5, at ! at = adjusted index < range - beq at, zero, .trap_earray + slt at, at, r5 ! at = range < adjusted index + bne at, zero, .trap_earray nop lw r2, 8(r4) ! r2 = size of element diff --git a/plat/linuxmips/tests/build.lua b/plat/linuxmips/tests/build.lua index 68ffccc68..529277fd9 100644 --- a/plat/linuxmips/tests/build.lua +++ b/plat/linuxmips/tests/build.lua @@ -4,5 +4,5 @@ plat_testsuite { name = "tests", plat = "linuxmips", method = "qemu-mipsel", - skipsets = {"m2"} +-- skipsets = {"m2"}, } diff --git a/tests/plat/core/aar_e.e b/tests/plat/core/aar_e.e index 0b53e5b50..352277d03 100644 --- a/tests/plat/core/aar_e.e +++ b/tests/plat/core/aar_e.e @@ -13,7 +13,7 @@ array descriptor con -1 ; lower bound - con 3 ; range + con 2 ; range, *inclusive* con EM_WSIZE ; size of element diff --git a/tests/plat/core/lar_e.e b/tests/plat/core/lar_e.e index 650865b04..fb96522d6 100644 --- a/tests/plat/core/lar_e.e +++ b/tests/plat/core/lar_e.e @@ -17,7 +17,7 @@ array descriptor con -1 ; lower bound - con 3 ; range + con 2 ; range, *inclusive* con EM_WSIZE ; size of element exp $_m_a_i_n diff --git a/tests/plat/core/sar_e.e b/tests/plat/core/sar_e.e index 7c6da941b..803e8dffe 100644 --- a/tests/plat/core/sar_e.e +++ b/tests/plat/core/sar_e.e @@ -15,7 +15,7 @@ array descriptor con -1 ; lower bound - con 3 ; range + con 2 ; range, *inclusive* con EM_WSIZE ; size of element element0 From fe177bd68880db90b29c227507cf3f3602442cf3 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 23:53:18 +0200 Subject: [PATCH 66/79] Add specialist rules for signed integer comparisons; much better code. --- mach/mips/mcg/table | 89 +++++++++++++++++++++++++++++++++++++ mach/proto/mcg/predicates.c | 8 ++++ 2 files changed, 97 insertions(+) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 0703b156f..de7b9b248 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -468,6 +468,95 @@ PATTERNS +/* Conditional branches */ + + /* Normally COMPARE returns a condition code (in a flags register) which the CJUMP + * instructions can then operate on. But MIPS doesn't have a flags register, and + * requires you to know what condition you're testing for when you do the comparison. + * mcg doesn't like this much and we have to list every combination individually. + */ + + /* Signed integer comparisons against zero */ + + CJUMPEQ(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%zero, 0) + emit "beq %left, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLT(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%zero, 0) + emit "bltz %left, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLE(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%zero, 0) + emit "blez %left, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + /* Signed integer comparisons against a constant */ + + CJUMPEQ(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "li at, $value" + emit "beq %left, at, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLT(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when signed_constant(%value, 16) + emit "slti at, %left, $value" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLE(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when constant_within_inclusive_range(%value, -0x8000, 0x7ffe) + emit "slti at, %left, 1+$value" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + /* Signed integer comparisons against a register */ + + CJUMPEQ(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "beq %left, %right, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLT(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "slt at, %left, %right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + CJUMPLE(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) + emit "slt at, %right, %left" + emit "beq at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + + /* Comparisons */ /* The COMPARE nodes return tristate integer values; -1, 0 or 1. */ diff --git a/mach/proto/mcg/predicates.c b/mach/proto/mcg/predicates.c index 427a59836..21423852e 100644 --- a/mach/proto/mcg/predicates.c +++ b/mach/proto/mcg/predicates.c @@ -27,6 +27,14 @@ bool burm_predicate_specific_constant(struct burm_node* node, arith val) return ir->u.ivalue == val; } +bool burm_predicate_constant_within_inclusive_range(struct burm_node* node, arith min, arith max) +{ + struct ir* ir = node->ir; + assert(ir->opcode == IR_CONST); + + return (ir->u.ivalue >= min) && (ir->u.ivalue <= max); +} + /* vim: set sw=4 ts=4 expandtab : */ From f362d12dee493028972d6164fcbcc9f9c857447c Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 23:59:49 +0200 Subject: [PATCH 67/79] Add extern declaration which I forget to check in. --- mach/proto/mcg/mcgg_generated_header.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mach/proto/mcg/mcgg_generated_header.h b/mach/proto/mcg/mcgg_generated_header.h index f0bfa99a0..8869a0401 100644 --- a/mach/proto/mcg/mcgg_generated_header.h +++ b/mach/proto/mcg/mcgg_generated_header.h @@ -10,6 +10,7 @@ extern void burm_panic_cannot_match(NODEPTR_TYPE node); extern bool burm_predicate_signed_constant(struct burm_node* node, arith size); extern bool burm_predicate_unsigned_constant(struct burm_node* node, arith size); extern bool burm_predicate_specific_constant(struct burm_node* node, arith value); +extern bool burm_predicate_constant_within_inclusive_range(struct burm_node* node, arith min, arith max); /* vim: set sw=4 ts=4 expandtab : */ From 692caa2b0a2d48bffe421c9b509ea6a0fc51a1eb Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 18 Sep 2018 00:19:40 +0200 Subject: [PATCH 68/79] Add unsigned comparison rules. --- mach/mips/mcg/table | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index de7b9b248..584416fa0 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -555,6 +555,57 @@ PATTERNS emit "nop" cost 20; + /* Unsigned integer comparisons against a constant */ + + CJUMPLT(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:CONST.I), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when signed_constant(%right, 16) + when specific_constant(%alwayszero, 0) + emit "sltiu at, %left, $right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLE(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:CONST.I), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when constant_within_inclusive_range(%right, -0x8000, 0x7ffe) + when specific_constant(%alwayszero, 0) + emit "sltiu at, %left, 1+$right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 20; + + /* Unsigned integer comparisons against registers */ + + CJUMPEQ(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:(int)reg), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%alwayszero, 0) + emit "beq %left, %right, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLT(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:(int)reg), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%alwayszero, 0) + emit "sltu at, %left, %right" + emit "bne at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + CJUMPLE(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:(int)reg), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) + when specific_constant(%alwayszero, 0) + emit "sltu at, %right, %left" + emit "beq at, zero, $true" + emit "nop" + emit "b $false" + emit "nop" + cost 16; + + /* Comparisons */ From 52ee3178786bfc48adf676ad29aac296348ce650 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 18 Sep 2018 23:32:53 +0200 Subject: [PATCH 69/79] Fixed some bad mcg ir code generation: only nodes which have been appendir'd may be used multiple times. --- mach/proto/mcg/treebuilder.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 5f9eebf86..3328bf620 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -85,6 +85,8 @@ static struct ir* pop(int size) } else if ((size == EM_wordsize) && (ir->size == (EM_wordsize*2))) { + appendir(ir); + /* Tried to read an int, but we got a long. */ push( new_ir1( @@ -553,6 +555,7 @@ static void insn_simple(int opcode) { struct ir* label = new_labelir(".trppc"); struct ir* value = pop(EM_pointersize); + appendir(label); /* because we need to use label twice */ push( load( EM_pointersize, From d23d2dd1b3fb480028b8666898076c4fd62a2593 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 18 Sep 2018 23:38:37 +0200 Subject: [PATCH 70/79] Loads and stores (except longs, which are difficult) are now loaded with two instructions rather than three. --- mach/mips/mcg/table | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 584416fa0..f1701813e 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -241,28 +241,58 @@ PATTERNS emit "sw %value, %addr" cost 4; + STORE.I(label:LABEL.I, value:(int)reg) + emit "lui at, ha16[$label]" + emit "sw %value, lo16[$label] (at)" + cost 8; + STOREH.I(addr:address, value:(int)ushortX) emit "sh %value, %addr" cost 4; + STOREH.I(label:LABEL.I, value:(int)reg) + emit "lui at, ha16[$label]" + emit "sh %value, lo16[$label] (at)" + cost 8; + STOREB.I(addr:address, value:(int)ubyteX) emit "sb %value, %addr" cost 4; + STOREB.I(label:LABEL.I, value:(int)reg) + emit "lui at, ha16[$label]" + emit "sb %value, lo16[$label] (at)" + cost 8; + STORE.F(addr:address, value:(float)reg) emit "swc1 %value, %addr" cost 4; + STORE.F(label:LABEL.I, value:(int)reg) + emit "lui at, ha16[$label]" + emit "swc1 %value, lo16[$label] (at)" + cost 8; + STORE.D(addr:address, value:(double)reg) emit "sdc1 %value, %addr" cost 4; + STORE.D(label:LABEL.I, value:(int)reg) + emit "lui at, ha16[$label]" + emit "sdc1 %value, lo16[$label] (at)" + cost 8; + /* Loads */ out:(int)reg = LOAD.I(addr:address) emit "lw %out, %addr" cost 4; + out:(int)reg = LOAD.I(label:LABEL.I) + emit "lui at, ha16[$label]" + emit "lw %out, lo16[$label] (at)" + cost 8; + /* We can't just load directly because %out.0 and %addr might share * a register, resulting in %addr being corrupted before %out.1 is * loaded. */ @@ -276,18 +306,38 @@ PATTERNS emit "lhu %out, %addr" cost 4; + out:(int)ushort0 = LOADH.I(label:LABEL.I) + emit "lui at, ha16[$label]" + emit "lhu %out, lo16[$label] (at)" + cost 8; + out:(int)ubyte0 = LOADB.I(addr:address) emit "lbu %out, %addr" cost 4; + out:(int)ubyte0 = LOADB.I(label:LABEL.I) + emit "lui at, ha16[$label]" + emit "lbu %out, lo16[$label] (at)" + cost 8; + out:(float)reg = LOAD.F(addr:address) emit "lwc1 %out, %addr" cost 4; + out:(float)reg = LOAD.F(label:LABEL.I) + emit "lui at, ha16[$label]" + emit "lwc1 %out, lo16[$label] (at)" + cost 8; + out:(double)reg = LOAD.D(addr:address) emit "ldc1 %out, %addr" cost 4; + out:(double)reg = LOAD.D(label:LABEL.I) + emit "lui at, ha16[$label]" + emit "ldc1 %out, lo16[$label] (at)" + cost 8; + /* ubyte intrinsics */ out:(int)ubyteX = in:(int)ubyte0 From 9333b323a5d63ba31595aa3f832e7338584a371f Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 18 Sep 2018 23:39:04 +0200 Subject: [PATCH 71/79] Make the MIPS boot code produce correct code. --- plat/linuxmips/boot.s | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plat/linuxmips/boot.s b/plat/linuxmips/boot.s index eed95ebd4..7f5ff16c2 100644 --- a/plat/linuxmips/boot.s +++ b/plat/linuxmips/boot.s @@ -8,7 +8,8 @@ .sect .text -begtext: +.define .entry +.entry: ! This code is placed at the beginning of the ELF executable and is the ! first thing that runs. ! @@ -29,13 +30,13 @@ begtext: lw r4, 0(sp) ! r4 = argc addiu r5, sp, 4 ! r5 = argv sll r6, r4, 2 ! r6 = argc*4 - addu r6, r6, r5 ! r6 = last arg - addiu r6, r6, 8 ! r6 = env + addu r6, r6, r5 ! r6 = null after last arg + addiu r6, r6, 4 ! r6 = env addiu sp, sp, -3 * 4 - sw r4, 0(sp) - sw r5, 4(sp) - sw r6, 8(sp) + sw r4, 0(sp) ! argc + sw r5, 4(sp) ! argv + sw r6, 8(sp) ! envp j __m_a_i_n nop From 365c89c9e7706737671bbac8091ce5d571b43ff7 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 18 Sep 2018 23:49:31 +0200 Subject: [PATCH 72/79] Updated READMEs with the MIPS platform. --- README | 3 ++- plat/linuxmips/README | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 plat/linuxmips/README diff --git a/README b/README index b959ba4a1..c27385337 100644 --- a/README +++ b/README @@ -33,6 +33,7 @@ pc86 produces bootable floppy disk images for 8086 PCs linux386 produces ELF executables for PC Linux systems linux68k produces ELF executables for m68020 Linux systems linuxppc produces ELF executables for PowerPC Linux systems +linuxmips produces ELF executables for little-endian MIPS32r2 Linux systems cpm produces i80 CP/M .COM files rpi produces Raspberry Pi GPU binaries pdpv7 produces PDP/11 V7 Unix binaries @@ -194,4 +195,4 @@ Please enjoy. David Given (davidgiven on Github) dg@cowlark.com -2016-11-26 +2018-09-18 diff --git a/plat/linuxmips/README b/plat/linuxmips/README new file mode 100644 index 000000000..ab294db86 --- /dev/null +++ b/plat/linuxmips/README @@ -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 From 8fda024ec8b6cdac163107d89bd45a73e1dacbb6 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 19 Sep 2018 00:09:50 +0200 Subject: [PATCH 73/79] Remember to save longs and doubles. Yikes. --- mach/mips/mcg/platform.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index 998b5dcdb..8a937ebef 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -94,9 +94,21 @@ struct hop* platform_prologue(void) 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; } @@ -112,9 +124,21 @@ struct hop* platform_epilogue(void) 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)"); From ac921080b7007ab731d422453becd2e4d70cd565 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 20 Sep 2018 00:06:26 +0200 Subject: [PATCH 74/79] Fix incorrect ori encoding. --- mach/mips/as/instructions.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat index 10619f8b3..81dece634 100644 --- a/mach/mips/as/instructions.dat +++ b/mach/mips/as/instructions.dat @@ -114,7 +114,7 @@ 00000000000000000000000000000000 "nop" 00000000000100111 "nor" RD=gpr ',' RS=gpr ',' RT=gpr 00000000000100101 "or" RD=gpr ',' RS=gpr ',' RT=gpr -001101 "ori" RS=gpr ',' RT=gpr ',' IMM=e16 +001101 "ori" RT=gpr ',' RS=gpr ',' IMM=e16 00000000000000000000000101000000 "pause" 110011 "pref" H=u5 ',' IMM=e16 '(' RS=gpr ')' 0111110100011 "prefe" H=u5 ',' IMM=e9 '(' RS=gpr ')' From ac856f3b09287874f05bed101bd42fec96fd125b Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 20 Sep 2018 00:12:03 +0200 Subject: [PATCH 75/79] The approach I was taking to csa and csb turns out not to work --- critical edge splitting can cause new basic blocks to be added to the graph, but while the graph itself gets properly rewritten the descriptor tables can't be updated to take these into account, so they end up pointing at the wrong blocks. This causes really hard-to-debug problems. The new approach is to parse the descriptor blocks and then generate a comparison chain. Brute force, but much easier for the compiler to reason about. --- mach/proto/mcg/data.c | 8 +- mach/proto/mcg/parse_em.c | 60 +++++++---- mach/proto/mcg/treebuilder.c | 195 +++++++++++++++++++++++++++++------ 3 files changed, 207 insertions(+), 56 deletions(-) diff --git a/mach/proto/mcg/data.c b/mach/proto/mcg/data.c index cbf1cd04f..95d828650 100644 --- a/mach/proto/mcg/data.c +++ b/mach/proto/mcg/data.c @@ -59,7 +59,7 @@ void data_int(arith data, size_t size, bool is_ro) { emit_header(is_ro ? SECTION_ROM : SECTION_DATA); assert((size == 1) || (size == 2) || (size == 4) || (size == 8)); - fprintf(outputfile, "\t.data%d ", size); + fprintf(outputfile, "\t.data%ld ", size); writehex(data, size); fprintf(outputfile, "\n"); } @@ -73,7 +73,7 @@ void data_float(const char* data, size_t size, bool is_ro) emit_header(is_ro ? SECTION_ROM : SECTION_DATA); assert((size == 4) || (size == 8)); - fprintf(outputfile, "\t.dataf%d %s\n", size, data); + fprintf(outputfile, "\t.dataf%ld %s\n", size, data); } static bool istext(c) @@ -130,7 +130,7 @@ void data_block(const uint8_t* data, size_t size, bool is_ro) void data_offset(const char* label, arith offset, bool is_ro) { emit_header(is_ro ? SECTION_ROM : SECTION_DATA); - fprintf(outputfile, "\t.data%d %s+%lld\n", + fprintf(outputfile, "\t.data%d %s+%ld\n", EM_pointersize, platform_label(label), offset); } @@ -140,7 +140,7 @@ void data_bss(arith size, int init) fatal("non-zero-initialised bss not supported"); emit_header(SECTION_BSS); - fprintf(outputfile, "\t.space %lld\n", size); + fprintf(outputfile, "\t.space %ld\n", size); } /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index b66b177c4..bb6d6f108 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -181,6 +181,36 @@ static void queue_ilabel(arith label) change_basicblock(bb_get(ilabel_to_str(label))); } +/* This is really hacky; to handle basic block flow + * descriptor blocks, we need to be able to identify + * them, read them and parse them. So we create + * can exit to. So we create fake bb objects for each + * block, purely to track this, and copy ints and labels + * into them. + */ + +static void data_block_int(arith value) +{ + if (data_bb) + { + struct em* em = new_insn(op_loc); + em->paramtype = PARAM_IVALUE; + em->u.ivalue = value; + array_append(&data_bb->ems, em); + } +} + +static void data_block_label(const char* label) +{ + if (data_bb) + { + struct em* em = new_insn(op_bra); + em->paramtype = PARAM_BVALUE; + em->u.bvalue.left = bb_get(label); + array_append(&data_bb->ems, em); + } +} + static void parse_pseu(void) { switch (em.em_opcode) @@ -227,6 +257,7 @@ static void parse_pseu(void) { arith val = atol(em.em_string); data_int(val, em.em_size, ro); + data_block_int(val); break; } @@ -237,12 +268,16 @@ static void parse_pseu(void) } case str_ptyp: - data_block(strdup(em.em_string), em.em_size, ro); + data_block((const uint8_t*) strdup(em.em_string), em.em_size, ro); break; case cst_ptyp: - data_int(em.em_cst, EM_wordsize, ro); + { + arith value = em.em_cst; + data_int(value, EM_wordsize, ro); + data_block_int(value); break; + } case nof_ptyp: data_offset(dlabel_to_str(em.em_dlb), em.em_off, ro); @@ -256,22 +291,8 @@ static void parse_pseu(void) case ilb_ptyp: { const char* label = ilabel_to_str(em.em_ilb); - - /* This is really hacky; to handle basic block flow - * descriptor blocks, we need to track which bbs a descriptor - * can exit to. So we create fake bb objects for each - * block, purely to track this. - */ - - if (data_bb) - { - struct em* em = new_insn(op_bra); - em->paramtype = PARAM_BVALUE; - em->u.bvalue.left = bb_get(label); - array_append(&data_bb->ems, em); - } - data_offset(label, 0, ro); + data_block_label(label); break; } @@ -384,9 +405,12 @@ static void create_data_label(const char* label) data_label(label); if (current_proc) { + /* Create the fake bb used to track values inside this data block + * (as it's a chance it's a jump table which we'll need to process + * later). + */ data_bb = bb_get(label); data_bb->is_fake = true; - array_append(¤t_proc->blocks, data_bb); } } diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 3328bf620..c1b5c7eb6 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -5,10 +5,20 @@ static struct basicblock* current_bb; static int stackptr; static struct ir* stack[64]; +struct jumptable +{ + struct basicblock* defaulttarget; + IMAPOF(struct basicblock) targets; +}; + static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode); static struct ir* appendir(struct ir* ir); static void insn_ivalue(int opcode, arith value); +static void parse_csa(struct basicblock* data_bb, struct jumptable* table); +static void parse_csb(struct basicblock* data_bb, struct jumptable* table); +static void emit_jumptable(struct ir* targetvalue, struct jumptable* table); + static void reset_stack(void) { stackptr = 0; @@ -739,27 +749,6 @@ static void rotate(int opcode, int size, int irop, int irop_reverse) } } -static struct ir* extract_block_refs(struct basicblock* bb) -{ - struct ir* outir = NULL; - int i; - - for (i=0; iems.count; i++) - { - struct em* em = bb->ems.item[i]; - assert(em->opcode == op_bra); - assert(em->paramtype == PARAM_BVALUE); - - outir = new_ir2( - IR_PAIR, 0, - new_bbir(em->u.bvalue.left), - outir - ); - } - - return outir; -} - static void change_by(struct ir* address, int amount) { appendir( @@ -1339,25 +1328,34 @@ static void insn_ivalue(int opcode, arith value) } case op_csa: - case op_csb: { - const char* helper = aprintf(".%s", - (opcode == op_csa) ? "csa" : "csb"); struct ir* descriptor = pop(EM_pointersize); + struct ir* targetvalue = appendir(pop(EM_pointersize)); + struct jumptable jumptable = {}; + int i; if (descriptor->opcode != IR_LABEL) - fatal("csa/csb are only supported if they refer " + fatal("csa is only supported if it refers " "directly to a descriptor block"); - push(descriptor); - materialise_stack(); - appendir( - new_ir2( - IR_FARJUMP, 0, - new_labelir(helper), - extract_block_refs(bb_get(descriptor->u.lvalue)) - ) - ); + parse_csa(bb_get(descriptor->u.lvalue), &jumptable); + emit_jumptable(targetvalue, &jumptable); + break; + } + + case op_csb: + { + struct ir* descriptor = pop(EM_pointersize); + struct ir* targetvalue = appendir(pop(EM_pointersize)); + struct jumptable jumptable = {}; + int i; + + if (descriptor->opcode != IR_LABEL) + fatal("csb is only supported if it refers " + "directly to a descriptor block"); + + parse_csb(bb_get(descriptor->u.lvalue), &jumptable); + emit_jumptable(targetvalue, &jumptable); break; } @@ -1762,4 +1760,133 @@ void tb_procedure(void) generate_tree(current_proc->blocks.item[i]); } +static void parse_csa(struct basicblock* data_bb, struct jumptable* table) +{ + struct em* em; + int lowerbound; + int count; + int i; + + assert(data_bb->ems.count >= 3); + + /* Default target */ + + em = data_bb->ems.item[0]; + assert(em->opcode == op_bra); + assert(em->paramtype == PARAM_BVALUE); + table->defaulttarget = em->u.bvalue.left; + + /* Lower bound */ + + em = data_bb->ems.item[1]; + assert(em->opcode == op_loc); + assert(em->paramtype == PARAM_IVALUE); + lowerbound = em->u.ivalue; + + /* Count */ + + em = data_bb->ems.item[2]; + assert(em->opcode == op_loc); + assert(em->paramtype == PARAM_IVALUE); + count = em->u.ivalue + 1; /* value in descriptor is inclusive */ + assert(data_bb->ems.count >= (count + 3)); + + /* Now, each target in turn. */ + + for (i=0; iems.item[3 + i]; + assert(em->opcode == op_bra); + assert(em->paramtype == PARAM_BVALUE); + target = em->u.bvalue.left; + + imap_put(&table->targets, lowerbound+i, target); + } +} + +static void parse_csb(struct basicblock* data_bb, struct jumptable* table) +{ + struct em* em; + int count; + int i; + + assert(data_bb->ems.count >= 2); + + /* Default target */ + + em = data_bb->ems.item[0]; + assert(em->opcode == op_bra); + assert(em->paramtype == PARAM_BVALUE); + table->defaulttarget = em->u.bvalue.left; + + /* Number of targets */ + + em = data_bb->ems.item[1]; + assert(em->opcode == op_loc); + assert(em->paramtype == PARAM_IVALUE); + count = em->u.ivalue; + assert(data_bb->ems.count >= (count*2 + 2)); + + /* Now, each target in turn. */ + + for (i=0; iems.item[2 + i*2]; + assert(em->opcode == op_loc); + assert(em->paramtype == PARAM_IVALUE); + value = em->u.ivalue; + + em = data_bb->ems.item[3 + i*2]; + assert(em->opcode == op_bra); + assert(em->paramtype == PARAM_BVALUE); + target = em->u.bvalue.left; + + imap_put(&table->targets, value, target); + } +} + +static void emit_jumptable(struct ir* targetvalue, struct jumptable* jumptable) +{ + int i; + + materialise_stack(); + for (i=0; itargets.count; i++) + { + int value = jumptable->targets.item[i].left; + struct basicblock* target = jumptable->targets.item[i].right; + struct basicblock* nextblock = bb_get(NULL); + + array_append(¤t_proc->blocks, nextblock); + appendir( + new_ir2( + IR_CJUMPEQ, 0, + new_ir2( + IR_COMPARESI, EM_wordsize, + targetvalue, + new_wordir(value) + ), + new_ir2( + IR_PAIR, 0, + new_bbir(target), + new_bbir(nextblock) + ) + ) + ); + + current_bb = nextblock; + } + + appendir( + new_ir1( + IR_JUMP, 0, + new_bbir(jumptable->defaulttarget) + ) + ); +} + /* vim: set sw=4 ts=4 expandtab : */ From cb20856aeadc76ee4af83daf810a5f49c46bd5e2 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 20 Sep 2018 00:39:13 +0200 Subject: [PATCH 76/79] A few more minor optimisations. --- mach/mips/mcg/table | 18 ++++++++++++++++++ mach/mips/top/table | 29 ++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index f1701813e..ff4d77e28 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -306,20 +306,38 @@ PATTERNS emit "lhu %out, %addr" cost 4; + out:(int)reg = EXTENDH.I(LOADH.I(addr:address)) + emit "lh %out, %addr" + cost 4; + out:(int)ushort0 = LOADH.I(label:LABEL.I) emit "lui at, ha16[$label]" emit "lhu %out, lo16[$label] (at)" cost 8; + out:(int)reg = EXTENDH.I(LOADH.I(label:LABEL.I)) + emit "lui at, ha16[$label]" + emit "lh %out, lo16[$label] (at)" + cost 8; + out:(int)ubyte0 = LOADB.I(addr:address) emit "lbu %out, %addr" cost 4; + out:(int)reg = EXTENDB.I(LOADB.I(addr:address)) + emit "lb %out, %addr" + cost 4; + out:(int)ubyte0 = LOADB.I(label:LABEL.I) emit "lui at, ha16[$label]" emit "lbu %out, lo16[$label] (at)" cost 8; + out:(int)reg = EXTENDB.I(LOADB.I(label:LABEL.I)) + emit "lui at, ha16[$label]" + emit "lb %out, lo16[$label] (at)" + cost 8; + out:(float)reg = LOAD.F(addr:address) emit "lwc1 %out, %addr" cost 4; diff --git a/mach/mips/top/table b/mach/mips/top/table index 8f6a5d6d7..c0037f54d 100644 --- a/mach/mips/top/table +++ b/mach/mips/top/table @@ -7,14 +7,41 @@ LABEL_STARTER '.'; %%; X, Y, Z { TRUE }; +R { TRUE }; %%; /* Whitespace is significant here! */ -addiu RNZ, RNZ, 0 -> ; +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, const 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; +} From 436d50b54cf30f604a1bfbf808b484552e0523f4 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 20 Sep 2018 00:49:31 +0200 Subject: [PATCH 77/79] Create correctly sized csa descriptors in the Basic compiler. --- lang/basic/src/graph.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lang/basic/src/graph.c b/lang/basic/src/graph.c index 732fc301d..a960659b7 100644 --- a/lang/basic/src/graph.c +++ b/lang/basic/src/graph.c @@ -199,19 +199,26 @@ int lab; genreturns() { + int count; int nr; nr= genlabel(); C_df_dnam("returns"); C_rom_ilb((label) nr); C_rom_cst((arith)1); - C_rom_cst((arith) (gosubcnt-1)); + C_rom_cst((arith) (gosubcnt-2)); + count = 0; while ( gosubhead) { C_rom_ilb((label) gosubhead->emlabel); gosubhead= gosubhead->nextlist; + count++; } + + if (count != (gosubcnt-1)) + error("gosub count table mismatch"); + C_df_ilb((label) nr); C_loc((arith) 1); C_cal("error"); From 65a20ce2d6beb8918a0250439bfea1b3c8edeeab Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 20 Sep 2018 23:24:46 +0200 Subject: [PATCH 78/79] Fix subtle register corruption bug where aliases weren't taken into account when assigning input registers to phis, which could cause the same hreg to be assigned to two vregs of different types. Also improve tracing. --- mach/proto/mcg/pass_registerallocator.c | 4 ++-- mach/proto/mcg/procedure.c | 28 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index 0a25fc4f0..97cfa8224 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -492,7 +492,7 @@ static void assign_hregs_to_vregs(void) { tracef('R', "R: import hreg %s for input %%%d from %s\n", hreg->id, vreg->id, prevbb->name); - assert(!pmap_findleft(old, hreg)); + assert(!register_used(old, hreg)); pmap_put(old, hreg, vreg); goto nextvreg; } @@ -518,7 +518,7 @@ static void assign_hregs_to_vregs(void) struct hreg* hreg = pmap_findright( phi->prev->regsout, phi->ir->result); - if (hreg && !pmap_findleft(old, hreg)) + if (hreg && !register_used(old, hreg)) { tracef('R', "R: import hreg %s for %%%d, imported from %s %%%d\n", hreg->id, vreg->id, diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index f819c56e3..abd94d19b 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -38,6 +38,18 @@ static void print_blocks(char k) } } +static void print_vreg(char k, register_assignment_t* assignments, struct vreg* vreg) +{ + struct hreg* hreg; + tracef(k, "%%%d", vreg->id); + if (assignments) + { + hreg = pmap_findright(assignments, vreg); + if (hreg) + tracef(k, "(%s)", hreg->id); + } +} + static void print_hops(char k) { int i; @@ -73,7 +85,10 @@ static void print_hops(char k) { tracef(k, "%c: INS:", k); for (j=0; jliveins.count; j++) - tracef(k, " %%%d", bb->liveins.item[j]->id); + { + tracef(k, " "); + print_vreg(k, &bb->regsin, bb->liveins.item[j]); + } tracef(k, "\n"); } @@ -81,7 +96,10 @@ static void print_hops(char k) { tracef(k, "%c: OUTS:", k); for (j=0; jliveouts.count; j++) - tracef(k, " %%%d", bb->liveouts.item[j]->id); + { + tracef(k, " "); + print_vreg(k, bb->regsout, bb->liveouts.item[j]); + } tracef(k, "\n"); } @@ -93,10 +111,10 @@ static void print_hops(char k) struct vreg* vreg = bb->phis.item[j].left; struct phi* phi = bb->phis.item[j].right; - tracef(k, " %%%d(via %s)=>%%%d", + tracef(k, " %%%d(via %s)=>", phi->ir->result->id, - phi->prev->name, - vreg->id); + phi->prev->name); + print_vreg(k, &bb->regsin, vreg); } tracef(k, "\n"); } From 985d3dc7d13d2658cc1dbadbb63734adcfb3a436 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 20 Sep 2018 23:30:38 +0200 Subject: [PATCH 79/79] Remove some old, hopefully unused PowerPC code. Teach the code generator about non-volatile long registers. --- mach/mips/mcg/platform.c | 67 +--------------------------------------- mach/mips/mcg/table | 4 +++ 2 files changed, 5 insertions(+), 66 deletions(-) diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c index 8a937ebef..74396ddcb 100644 --- a/mach/mips/mcg/platform.c +++ b/mach/mips/mcg/platform.c @@ -156,72 +156,7 @@ struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* struct hop* hop = new_hop(bb, NULL); if ((src->attrs & TYPE_ATTRS) != (dest->attrs & TYPE_ATTRS)) - { - assert(!src->is_stacked); - assert(!dest->is_stacked); - - switch (src->attrs & TYPE_ATTRS) - { - case burm_int_ATTR: - hop_add_insel(hop, "stwu %H, -4(sp)", src); - break; - - case burm_long_ATTR: - hop_add_insel(hop, "stwu %0H, -4(sp)", src); - hop_add_insel(hop, "stwu %1H, -4(sp)", src); - break; - - case burm_float_ATTR: - hop_add_insel(hop, "stfsu %H, -4(sp)", src); - break; - - case burm_double_ATTR: - hop_add_insel(hop, "stfdu %H, -8(sp)", src); - break; - - default: - goto nomove; - } - - switch (dest->attrs & TYPE_ATTRS) - { - case burm_int_ATTR: - hop_add_insel(hop, "lwz %H, 0(sp)", dest); - break; - - case burm_long_ATTR: - hop_add_insel(hop, "lwz %0H, 4(sp)", dest); - hop_add_insel(hop, "lwz %1H, 0(sp)", dest); - break; - - case burm_float_ATTR: - hop_add_insel(hop, "lfs %H, 0(sp)", dest); - break; - - case burm_double_ATTR: - hop_add_insel(hop, "lfd %H, 0(sp)", dest); - break; - - default: - goto nomove; - } - - switch (dest->attrs & TYPE_ATTRS) - { - case burm_int_ATTR: - case burm_float_ATTR: - hop_add_insel(hop, "addi sp, sp, 4"); - break; - - case burm_double_ATTR: - case burm_long_ATTR: - hop_add_insel(hop, "addi sp, sp, 8"); - break; - - default: - goto nomove; - } - } + 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; diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index ff4d77e28..f2b64333e 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -44,6 +44,10 @@ REGISTERS r24r25 named("r24", "r25") aliases(r24, r25) long volatile; r2r3 named("r2", "r3") aliases(r2, r3) long volatile lret; + r17r18 named("r17", "r18") aliases(r17, r18) long; + r19r20 named("r19", "r20") aliases(r19, r20) long; + r21r22 named("r21", "r22") aliases(r21, r22) long; + f0 float volatile fret; f1 float volatile; f2 float volatile;