From 7dc4c028148a5175a10ceb003bc36edf6ecd1bda Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 10 Feb 2018 00:09:13 +0000 Subject: [PATCH] writei: workaround for sdcc sdcc at least isn't bright enough to turn static uint32 x if (x >> 25) into a byte load of x + 3 followed by an &0xFE Instead it generates a 25 repeat bitshift of a 32bit value across four registers in a fairly critical code path. Allow defines to help it out with its dumbness. --- Kernel/cpu-z80/cpu.h | 3 +++ Kernel/include/kernel.h | 11 ++++++++++- Kernel/inode.c | 10 +++++----- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Kernel/cpu-z80/cpu.h b/Kernel/cpu-z80/cpu.h index 6279ea6b..cb5583cc 100644 --- a/Kernel/cpu-z80/cpu.h +++ b/Kernel/cpu-z80/cpu.h @@ -84,3 +84,6 @@ typedef union { /* this structure is endian dependent */ (((x) & 0xFF0000) >> 8) | (((x >> 24) & 0xFF))) #define CPUTYPE CPUTYPE_Z80 + +/* Deal with SDCC code gen issue */ +#define HIBYTE32(x) (((uint8_t *)&(x))[3]) diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index e21aaebd..b0280ba3 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -40,6 +40,15 @@ From UZI by Doug Braun and UZI280 by Stefan Nitschke. #define ALIGNDOWN(v) (v) #endif +/* These work fine for most compilers but can be overriden for those where the + resulting code generation is foul */ +#ifndef LOWORD +#define LOWORD(x) ((uint16_t)(x)) +#endif +#ifndef HIBYTE32 +#define HIBYTE32(x) ((uint8_t)((x) >> 24)) +#endif + #ifdef CONFIG_LEVEL_2 #include "level2.h" #else @@ -152,7 +161,7 @@ typedef uint16_t blkno_t; /* Can have 65536 512-byte blocks in filesystem */ #define BLKSIZE 512 #define BLKSHIFT 9 #define BLKMASK 511 -#define BLKOVERSIZE 25 /* Bits 25+ mean we exceeded the file size */ +#define BLKOVERSIZE32 0xFE /* Bits 25+ mean we exceeded the file size */ /* Help the 8bit compilers out by preventing any 32bit promotions */ #define BLKOFF(x) (((uint16_t)(x)) & BLKMASK) diff --git a/Kernel/inode.c b/Kernel/inode.c index 340c5db0..8c8650f8 100644 --- a/Kernel/inode.c +++ b/Kernel/inode.c @@ -22,7 +22,7 @@ static uint8_t pipewait(inoptr ino, uint8_t flag) return 0; } } - udata.u_count = min(udata.u_count, (uint16_t)ino->c_node.i_size); + udata.u_count = min(udata.u_count, LOWORD(ino->c_node.i_size)); return 1; } @@ -127,7 +127,7 @@ void readi(regptr inoptr ino, uint8_t flag) gcc_miscompile_workaround(); #endif umove(amount); - if (ispipe && (uint16_t)udata.u_offset >= 18 * BLKSIZE) + if (ispipe && LOWORD(udata.u_offset) >= 18 * BLKSIZE) udata.u_offset = 0; if (ispipe) { ino->c_node.i_size -= amount; @@ -177,7 +177,7 @@ void writei(regptr inoptr ino, uint8_t flag) /* FIXME: this will hang if you ever write > 16 * BLKSIZE in one go - needs merging into the loop */ while (udata.u_count > (16 * BLKSIZE) - - (uint16_t)ino->c_node.i_size) { + LOWORD(ino->c_node.i_size)) { if (ino->c_readers == 0) { /* No readers */ udata.u_done = (usize_t)-1; udata.u_error = EPIPE; @@ -198,7 +198,7 @@ void writei(regptr inoptr ino, uint8_t flag) while (udata.u_count) { pblk = mapcalc(ino, &amount, 0); - if (udata.u_offset >> BLKOVERSIZE) { + if (HIBYTE32(udata.u_offset) & BLKOVERSIZE32) { udata.u_error = EFBIG; ssig(udata.u_ptab, SIGXFSZ); break; @@ -222,7 +222,7 @@ void writei(regptr inoptr ino, uint8_t flag) umove(amount); if (ispipe) { - if ((uint16_t)udata.u_offset >= 18 * 512) + if (LOWORD(udata.u_offset) >= 18 * 512) udata.u_offset = 0; ino->c_node.i_size += amount; /* Wake up any readers */ -- 2.34.1