From: Robert Pengelly Date: Sat, 27 Jun 2026 07:30:14 +0000 (+0100) Subject: Alignment and AMD64 fixes X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=034bd0957dfe9a599939b3a92f881fcb552d98bd;p=scc.git Alignment and AMD64 fixes --- diff --git a/amd64.c b/amd64.c index 2c84230..e1b74d1 100644 --- a/amd64.c +++ b/amd64.c @@ -12296,11 +12296,23 @@ static void emit_load_const32_to_reg_now (const char *reg, int64_s v) { /* * A 32-bit integer constant loaded through the dword register form - * zero-extends the upper half of the AMD64 register. Do not use a - * qword immediate move here: assemblers may choose a sign-extended - * imm32 encoding for values with bit 31 set, which is wrong for plain - * unsigned 32-bit constants promoted into a 64-bit register. + * zero-extends the upper half of the AMD64 register. That is only + * correct when the folded value really fits in 32 bits. Macro-expanded + * EFI status constants such as: + * + * (0x8000000000000000LLU | 5) + * + * reach this helper through the generic foldable-expression path. The + * old code always used the dword register name and silently discarded + * v.high, turning EFI_BUFFER_TOO_SMALL into plain 5 in comparisons. */ + if ((v.high & U32_MASK) != 0) { + + amd64_emit_mov_i64_to_qword_reg_now (reg, v); + return; + + } + if (state->syntax & ASM_SYNTAX_INTEL) { fprintf (state->ofp, " mov %s, %lu\n", dreg, v.low & U32_MASK); } else { diff --git a/parse.c b/parse.c index 7a8084d..447c042 100644 --- a/parse.c +++ b/parse.c @@ -2359,6 +2359,21 @@ int type_alignment (int size) { return 2; } + /* + * Keep 64-bit scalar members naturally aligned. + * + * The old code capped aggregate member alignment at DATA_PTR, which + * makes i386 lay out uint64_t / EFI_LBA fields on 4-byte boundaries. + * That is wrong for PE/UEFI-style structures such as + * EFI_BLOCK_IO_MEDIA, where LastBlock must be read after the padding + * inserted before the 64-bit field. Without this, code reads the + * preceding IoAlign field as the low half of LastBlock, which is how + * values such as 5 can appear for a disk size. + */ + if (size == 8) { + return 8; + } + if (size >= DATA_PTR) { return DATA_PTR; }