From 0ca05aa2e4c4685ef40f1a48495b6d2aad4d6d8a Mon Sep 17 00:00:00 2001 From: "Jeffrey H. Johnson" Date: Thu, 16 Jul 2026 12:50:24 -0400 Subject: [PATCH] mcg: fix ha16 far data, O_CREAT, adjust mcg spills Allow ha16/lo16 for locals past 64K via symbol relative relocations with linker handling of module local names. Define MIPS compatible O_CREAT correctly. Fail (and don't crash) in mcg when a stacked spill is still insn operand. Signed-off-by: Jeffrey H. Johnson --- mach/mips/as/mach1.c | 2 ++ mach/mips/as/mach4.c | 12 +++---- mach/mips/as/mach5.c | 43 ++++++++++++++++++++++ mach/proto/as/comm1.h | 5 +++ mach/proto/as/comm2.y | 2 +- mach/proto/as/comm6.c | 58 +++++++++++++++++++++++++++++- mach/proto/mcg/hop.c | 5 ++- plat/linux/include/ack/fcntl.h | 14 +++++--- plat/linuxmips/descr | 7 ++-- plat/linuxmips/include/ack/fcntl.h | 19 ++++++++++ plat/linuxmips/include/build.py | 13 +++++-- util/led/relocate.c | 14 ++++++++ 12 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 plat/linuxmips/include/ack/fcntl.h diff --git a/mach/mips/as/mach1.c b/mach/mips/as/mach1.c index 55c6b55073..2f0508d282 100644 --- a/mach/mips/as/mach1.c +++ b/mach/mips/as/mach1.c @@ -1,3 +1,5 @@ /* * Do not #include anything here. Do it in mach/proto/as/comm0.h */ + +int mips_small_relo(expr_t *e, int relotype, valu_t *out); diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 9e8dab51f2..d23c274b3a 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -19,22 +19,18 @@ extabsexp : absexp | LO16 ASC_LPAR expr ASC_RPAR { - newrelo($3.typ, RELO2 | FIXUPFLAGS); - $$ = $3.val; + if (!mips_small_relo(&$3, RELO2, &$$)) + fatal("relocation offset in lo16[] too big"); } | HI16 ASC_LPAR expr ASC_RPAR { - newrelo($3.typ, RELO2HI | FIXUPFLAGS); - if ($3.val & 0xffff0000) + if (!mips_small_relo(&$3, RELO2HI, &$$)) fatal("relocation offset in hi16[] too big"); - $$ = $3.val; } | HA16 ASC_LPAR expr ASC_RPAR { - newrelo($3.typ, RELO2HISAD | FIXUPFLAGS); - if ($3.val & 0xffff0000) + if (!mips_small_relo(&$3, RELO2HISAD, &$$)) fatal("relocation offset in ha16[] too big"); - $$ = $3.val; } ; diff --git a/mach/mips/as/mach5.c b/mach/mips/as/mach5.c index e69de29bb2..ebbe6bde57 100644 --- a/mach/mips/as/mach5.c +++ b/mach/mips/as/mach5.c @@ -0,0 +1,43 @@ +/* + * MIPS assembler helpers. + */ + +extern item_t *last_it; + +int +mips_small_relo(expr_t *e, int relotype, valu_t *out) +{ + valu_t addend; + unsigned short nami; + + if ((e->val & 0xffff0000) == 0) { + newrelo(e->typ, relotype | FIXUPFLAGS); + *out = e->val; + return 1; + } + + if (pass == PASS_1) { + *out = 0; + return 1; + } + +#ifndef ASLD + nami = item_get_nami(last_it); + if (last_it != 0 && nami != 0 + && (last_it->i_type & S_TYP) >= S_MIN + && (last_it->i_type & S_TYP) != S_UND) { + addend = e->val - last_it->i_valu; + if ((addend & 0xffff0000) == 0) { + valu_t saved = relonami; + + relonami = nami; + newrelo(S_UND, relotype | FIXUPFLAGS); + relonami = saved; + *out = addend; + return 1; + } + } +#endif + + return 0; +} diff --git a/mach/proto/as/comm1.h b/mach/proto/as/comm1.h index 87df5279ac..3cf6a3173a 100644 --- a/mach/proto/as/comm1.h +++ b/mach/proto/as/comm1.h @@ -74,6 +74,11 @@ extern unsigned short nname; /* Counts name table index in PASS_3 */ extern item_t *hashtab[H_TOTAL]; extern short hashindex; /* see item_search() */ +extern item_t *last_it; /* last identifier seen in an expression */ + +void item_set_nami(item_t *ip, unsigned short nami); +unsigned short item_get_nami(item_t *ip); + extern item_t *fb_ptr[4*FB_SIZE]; #ifdef THREE_PASS diff --git a/mach/proto/as/comm2.y b/mach/proto/as/comm2.y index b6e809b9ff..38728121af 100644 --- a/mach/proto/as/comm2.y +++ b/mach/proto/as/comm2.y @@ -14,7 +14,7 @@ #include "comm0.h" #include "comm1.h" -static item_t *last_it, *o_it; +static item_t *o_it; %} /* ========== Machine independent Yacc definitions ========== */ diff --git a/mach/proto/as/comm6.c b/mach/proto/as/comm6.c index fc1d2f1bfb..2a3e51d33e 100644 --- a/mach/proto/as/comm6.c +++ b/mach/proto/as/comm6.c @@ -67,13 +67,18 @@ newident(item_t *ip, int typ) strncmp(ip->i_name, genlab, sizeof(genlab)-1) == 0) flag = SYM_LAB; #endif /* GENLAB */ - if (sflag & flag) + if (sflag & flag) { +#ifndef ASLD + if (pass != PASS_3) + item_set_nami(ip, (unsigned short)outhead.oh_nname + 1); +#endif newsymb( ip->i_name, ip->i_type & (S_EXT|S_TYP), 0, load(ip) ); + } } void @@ -333,6 +338,57 @@ new_string(const char *s) return r; } +#define NAMI_HASH 256 + +struct nami_entry { + struct nami_entry *next; + item_t *ip; + unsigned short nami; +}; + +static struct nami_entry *nami_tab[NAMI_HASH]; + +static unsigned +nami_hash(item_t *ip) +{ + return ((unsigned)(uintptr_t)ip >> 3) % NAMI_HASH; +} + +void +item_set_nami(item_t *ip, unsigned short nami) +{ + unsigned h = nami_hash(ip); + struct nami_entry *e; + + for (e = nami_tab[h]; e; e = e->next) { + if (e->ip == ip) { + e->nami = nami; + return; + } + } + e = (struct nami_entry *)malloc(sizeof(*e)); + if (e == 0) + fatal("out of memory"); + e->ip = ip; + e->nami = nami; + e->next = nami_tab[h]; + nami_tab[h] = e; +} + +unsigned short +item_get_nami(item_t *ip) +{ + struct nami_entry *e; + + if (ip == 0) + return 0; + for (e = nami_tab[nami_hash(ip)]; e; e = e->next) { + if (e->ip == ip) + return e->nami; + } + return 0; +} + void newsymb(const char *name, int type, int desc, valu_t valu) { diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 77c6dc260d..62ae78daa3 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -240,8 +240,11 @@ char* hop_render(struct hop* hop) struct hreg* hreg = pmap_findright(&hop->regsin, vreg); if (!hreg) hreg = pmap_findright(&hop->regsout, vreg); - if (hreg) + if (hreg && hreg->brd) appendf("%s", hreg->brd->names[insel->index]); + else if (hreg) + fatal("vreg %%%d still in stacked hreg %s at hop render", + vreg->id, hreg->id); else appendf("%%%d.%d", vreg->id, insel->index); break; diff --git a/plat/linux/include/ack/fcntl.h b/plat/linux/include/ack/fcntl.h index 361fad97a5..7a1428c5f8 100644 --- a/plat/linux/include/ack/fcntl.h +++ b/plat/linux/include/ack/fcntl.h @@ -1,19 +1,25 @@ #ifndef _ACK_FCNTL_H #define _ACK_FCNTL_H -/* Linux O_ constants. */ - enum { O_ACCMODE = 0x3, - + O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, - + +#ifdef __mips + O_APPEND = 0x0008, + O_CREAT = 0x0100, + O_TRUNC = 0x0200, + O_EXCL = 0x0400, + O_NOCTTY = 0x0800 +#else O_CREAT = 00000100, O_TRUNC = 00001000, O_APPEND = 00002000 +#endif }; #endif diff --git a/plat/linuxmips/descr b/plat/linuxmips/descr index 7da3fbff14..7714d72726 100644 --- a/plat/linuxmips/descr +++ b/plat/linuxmips/descr @@ -17,15 +17,16 @@ var xa={x} var ARCH=mips var PLATFORM=linuxmips var PLATFORMDIR={EM}/share/ack/{PLATFORM} -var CPP_F=-D__unix +var CPP_F=-D__unix -D__mips 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 -# Override the setting in fe so that files compiled for linuxppc can see +# Override the setting in fe so that files compiled for linuxmips can see # the platform-specific headers. -var C_INCLUDES=-I{EM}/share/ack/linux/include -I{EM}/share/ack/include/ansi +# linuxmips/include is first so arch-specific headers can override shared ones. +var C_INCLUDES=-I{EM}/share/ack/linuxmips/include -I{EM}/share/ack/linux/include -I{EM}/share/ack/include/ansi name be from .m.g diff --git a/plat/linuxmips/include/ack/fcntl.h b/plat/linuxmips/include/ack/fcntl.h new file mode 100644 index 0000000000..c9dc0d0ad7 --- /dev/null +++ b/plat/linuxmips/include/ack/fcntl.h @@ -0,0 +1,19 @@ +#ifndef _ACK_FCNTL_H +#define _ACK_FCNTL_H + +enum +{ + O_ACCMODE = 0x3, + + O_RDONLY = 0, + O_WRONLY = 1, + O_RDWR = 2, + + O_APPEND = 0x0008, + O_CREAT = 0x0100, + O_TRUNC = 0x0200, + O_EXCL = 0x0400, + O_NOCTTY = 0x0800 +}; + +#endif diff --git a/plat/linuxmips/include/build.py b/plat/linuxmips/include/build.py index cfe225476d..77d3ba6eae 100644 --- a/plat/linuxmips/include/build.py +++ b/plat/linuxmips/include/build.py @@ -1,6 +1,13 @@ from build.ab import export -from build.ack import clibrary +from build.ack import exportheaders, clibrary +from glob import glob -clibrary(name="include", deps=["plat/linux/include"]) +headers = glob("**/*.h", root_dir="plat/linuxmips/include", recursive=True) -export(name="all", deps=["plat/linux/include+all"]) +clibrary(name="include", hdrs={k: f"./{k}" for k in headers}, deps=["plat/linux/include"]) + +export( + name="all", + items=exportheaders(".+include", prefix="$(PLATIND)/linuxmips/include"), + deps=["plat/linux/include+all"], +) diff --git a/util/led/relocate.c b/util/led/relocate.c index cc4cab0d0c..16e42ce0db 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -517,6 +517,20 @@ static unsigned addrelo( { struct outname* name; extern struct outhead outhead; + int local_typ = local->on_type & S_TYP; + + if (!(local->on_type & S_EXT) && local_typ != S_UND + && local_typ != S_ABS && !(local->on_type & S_COM)) + { + int sectindex = local_typ - S_MIN; + + valu += local->on_valu; + valu += relorig[sectindex].org_size; + valu += outsect[sectindex].os_base; + index += NGlobals + sectindex; + *valu_out = valu; + return index; + } name = searchname(local->on_mptr, hash(local->on_mptr)); if (name == (struct outname*)0)