tests: M4 X11R4 XImage/XEvent/error-event layout

This commit is contained in:
arti committed 2026-11-12 06:53:29 +00:00
1 parent 7a89a1fe4c
commit 8cb060cdb4
5 files changed
+772

No files matched your search

+102
View File
@@ -0,0 +1,102 @@
/*
* Offset-only equivalent of scripts/m4/x11m4.h for the 1987 TI GSP C
* compiler (GSPCC/GSPCG 2.01). The VT1200 C ABI packs struct members, so
* these structs have the same byte layout as the target's x11m4.h. The
* XImage function table is modelled as six 32-bit void* slots: only its
* size and the offset of f are needed here, and that is layout-equivalent
* to the target's six function pointers.
*
* The 1987 compiler's &-of-member is a bit address, so these functions
* return the ROM's bit displacements directly.
*/
struct display {
char pad[0x90];
void *screens;
};
struct screen {
char pad[0x8];
unsigned int root;
};
struct ximage_funcs {
void *create_image;
void *destroy_image;
void *get_pixel;
void *put_pixel;
void *sub_image;
void *add_pixel;
};
struct ximage {
int width, height;
int xoffset;
int format;
char *data;
int byte_order;
int bitmap_unit;
int bitmap_bit_order;
int bitmap_pad;
int depth;
int bytes_per_line;
int bits_per_pixel;
unsigned long red_mask, green_mask, blue_mask;
void *obdata;
struct ximage_funcs f;
};
struct xerror {
int type;
void *display;
unsigned long resourceid;
unsigned long serial;
unsigned char error_code;
unsigned char request_code;
unsigned char minor_code;
unsigned char abi_pad;
};
struct xkey {
int type;
unsigned long serial;
int send_event;
void *display;
unsigned long window;
unsigned long root;
unsigned long subwindow;
unsigned long time;
int x, y;
int x_root, y_root;
unsigned int state;
unsigned int keycode;
int same_screen;
};
struct xexpose {
int type;
unsigned long serial;
int send_event;
void *display;
unsigned long window;
int x, y;
int width, height;
int count;
};
union xevent {
int type;
struct xkey xkey;
struct xexpose xexpose;
long pad[24];
};
int layout_display_screens() { return (int)&((struct display *)0)->screens; }
int layout_screen_root() { return (int)&((struct screen *)0)->root; }
int layout_image_data() { return (int)&((struct ximage *)0)->data; }
int layout_image_byte_order() { return (int)&((struct ximage *)0)->byte_order; }
int layout_image_bytes_per_line() { return (int)&((struct ximage *)0)->bytes_per_line; }
int layout_image_bits_per_pixel() { return (int)&((struct ximage *)0)->bits_per_pixel; }
int layout_image_f() { return (int)&((struct ximage *)0)->f; }
int layout_error_error_code() { return (int)&((struct xerror *)0)->error_code; }
int layout_event_xkey_keycode() { return (int)&((struct xevent *)0)->xkey.keycode; }
int layout_event_size() { return (int)sizeof(union xevent); }
+114
View File
@@ -0,0 +1,114 @@
*******************************************************
* GSP C COMPILER, Version 2.01, 87.300 *
*******************************************************
FP .set A13
STK .set A14
.globl _layout_display_screens
.file "LAYOUT.c"
******************************************************
* FUNCTION DEF : _layout_display_screens
******************************************************
_layout_display_screens:
MOVE A7,-*SP,1
MOVI 1152,A7
MOVE A7,A8
EPI0_1:
MOVE *SP+,A7,1
RETS 0
.globl _layout_screen_root
******************************************************
* FUNCTION DEF : _layout_screen_root
******************************************************
_layout_screen_root:
MOVE A7,-*SP,1
MOVI 64,A7
MOVE A7,A8
EPI0_2:
MOVE *SP+,A7,1
RETS 0
.globl _layout_image_data
******************************************************
* FUNCTION DEF : _layout_image_data
******************************************************
_layout_image_data:
MOVE A7,-*SP,1
MOVI 128,A7
MOVE A7,A8
EPI0_3:
MOVE *SP+,A7,1
RETS 0
.globl _layout_image_byte_order
******************************************************
* FUNCTION DEF : _layout_image_byte_order
******************************************************
_layout_image_byte_order:
MOVE A7,-*SP,1
MOVI 160,A7
MOVE A7,A8
EPI0_4:
MOVE *SP+,A7,1
RETS 0
.globl _layout_image_bytes_per_line
******************************************************
* FUNCTION DEF : _layout_image_bytes_per_line
******************************************************
_layout_image_bytes_per_line:
MOVE A7,-*SP,1
MOVI 320,A7
MOVE A7,A8
EPI0_5:
MOVE *SP+,A7,1
RETS 0
.globl _layout_image_bits_per_pixel
******************************************************
* FUNCTION DEF : _layout_image_bits_per_pixel
******************************************************
_layout_image_bits_per_pixel:
MOVE A7,-*SP,1
MOVI 352,A7
MOVE A7,A8
EPI0_6:
MOVE *SP+,A7,1
RETS 0
.globl _layout_image_f
******************************************************
* FUNCTION DEF : _layout_image_f
******************************************************
_layout_image_f:
MOVE A7,-*SP,1
MOVI 512,A7
MOVE A7,A8
EPI0_7:
MOVE *SP+,A7,1
RETS 0
.globl _layout_error_error_code
******************************************************
* FUNCTION DEF : _layout_error_error_code
******************************************************
_layout_error_error_code:
MOVE A7,-*SP,1
MOVI 128,A7
MOVE A7,A8
EPI0_8:
MOVE *SP+,A7,1
RETS 0
.globl _layout_event_xkey_keycode
******************************************************
* FUNCTION DEF : _layout_event_xkey_keycode
******************************************************
_layout_event_xkey_keycode:
MOVE A7,-*SP,1
MOVI 416,A7
MOVE A7,A8
EPI0_9:
MOVE *SP+,A7,1
RETS 0
.globl _layout_event_size
******************************************************
* FUNCTION DEF : _layout_event_size
******************************************************
_layout_event_size:
MOVI 96,A8
EPI0_10:
RETS 0
.end
+117
View File
@@ -0,0 +1,117 @@
#include "x11m4.h"
/*
* Byte offsets are C offsets; the TMS34010 ROM's indirect displacements are
* bit offsets, so every layout_* function below returns offset * 8. The one
* exception is layout_event_size(), which reports sizeof(XEvent) in bytes
* because the termtris buffer is sized in bytes (vt_u32 evbuf[24]).
*/
_Static_assert(sizeof(void *) == 4, "the VT1200 X11 ABI is 32-bit");
_Static_assert(sizeof(long) == 4, "the VT1200 X11 ABI is 32-bit");
_Static_assert(sizeof(XID) == 4, "XID must be 32-bit");
_Static_assert(sizeof(Time) == 4, "Time must be 32-bit");
_Static_assert(__builtin_offsetof(Display, screens) == 0x90,
"Display.screens must be at byte 0x90 (bit 0x480)");
_Static_assert(__builtin_offsetof(Screen, root) == 0x8,
"Screen.root must be at byte 0x8 (bit 0x40)");
/* 32-bit X11R4 XImage: data 16, byte_order 20, bytes_per_line 40. */
_Static_assert(__builtin_offsetof(XImage, width) == 0, "XImage.width");
_Static_assert(__builtin_offsetof(XImage, height) == 4, "XImage.height");
_Static_assert(__builtin_offsetof(XImage, xoffset) == 8, "XImage.xoffset");
_Static_assert(__builtin_offsetof(XImage, format) == 12, "XImage.format");
_Static_assert(__builtin_offsetof(XImage, data) == 16,
"XImage.data must be at byte 16 (bit 0x80)");
_Static_assert(__builtin_offsetof(XImage, byte_order) == 20,
"XImage.byte_order must be at byte 20 (bit 0xA0)");
_Static_assert(__builtin_offsetof(XImage, bitmap_unit) == 24, "XImage.bitmap_unit");
_Static_assert(__builtin_offsetof(XImage, bitmap_bit_order) == 28,
"XImage.bitmap_bit_order");
_Static_assert(__builtin_offsetof(XImage, bitmap_pad) == 32, "XImage.bitmap_pad");
_Static_assert(__builtin_offsetof(XImage, depth) == 36, "XImage.depth");
_Static_assert(__builtin_offsetof(XImage, bytes_per_line) == 40,
"XImage.bytes_per_line must be at byte 40 (bit 0x140)");
_Static_assert(__builtin_offsetof(XImage, bits_per_pixel) == 44,
"XImage.bits_per_pixel must be at byte 44 (bit 0x160)");
_Static_assert(__builtin_offsetof(XImage, red_mask) == 48, "XImage.red_mask");
_Static_assert(__builtin_offsetof(XImage, green_mask) == 52, "XImage.green_mask");
_Static_assert(__builtin_offsetof(XImage, blue_mask) == 56, "XImage.blue_mask");
_Static_assert(__builtin_offsetof(XImage, obdata) == 60, "XImage.obdata");
_Static_assert(__builtin_offsetof(XImage, f) == 64,
"XImage.f must be at byte 64 (bit 0x200)");
_Static_assert(__builtin_offsetof(struct funcs, destroy_image) == 4,
"XImage.f.destroy_image must be 4 bytes into the inline funcs");
_Static_assert(__builtin_offsetof(XImage, f.destroy_image) == 68,
"XImage.f.destroy_image must be at byte 68 (bit 0x220)");
_Static_assert(sizeof(struct funcs) == 24, "the X11R4 funcs tail is six pointers");
_Static_assert(sizeof(XImage) == 88,
"sizeof(XImage) must cover the ROM's full inline-funcs object");
/* 32-bit X11R4 XErrorEvent: error_code 16, request_code 17, minor_code 18. */
_Static_assert(__builtin_offsetof(XErrorEvent, type) == 0, "XErrorEvent.type");
_Static_assert(__builtin_offsetof(XErrorEvent, display) == 4, "XErrorEvent.display");
_Static_assert(__builtin_offsetof(XErrorEvent, resourceid) == 8,
"XErrorEvent.resourceid");
_Static_assert(__builtin_offsetof(XErrorEvent, serial) == 12, "XErrorEvent.serial");
_Static_assert(__builtin_offsetof(XErrorEvent, error_code) == 16,
"XErrorEvent.error_code must be at byte 16 (bit 0x80)");
_Static_assert(__builtin_offsetof(XErrorEvent, request_code) == 17,
"XErrorEvent.request_code");
_Static_assert(__builtin_offsetof(XErrorEvent, minor_code) == 18,
"XErrorEvent.minor_code");
_Static_assert(sizeof(XErrorEvent) == 20, "sizeof(XErrorEvent) must be 20");
/* XEvent: type 0, xkey.window 16, xkey.keycode 52, xexpose.window 16, x 20. */
_Static_assert(__builtin_offsetof(XEvent, type) == 0, "XEvent.type");
_Static_assert(__builtin_offsetof(XEvent, xkey.window) == 16, "XEvent.xkey.window");
_Static_assert(__builtin_offsetof(XEvent, xkey.keycode) == 52,
"XEvent.xkey.keycode must be at byte 52 (bit 0x1A0)");
_Static_assert(__builtin_offsetof(XEvent, xexpose.window) == 16,
"XEvent.xexpose.window");
_Static_assert(__builtin_offsetof(XEvent, xexpose.x) == 20, "XEvent.xexpose.x");
_Static_assert(__builtin_offsetof(XEvent, xfocus.window) == 16,
"XEvent.xfocus.window");
_Static_assert(__builtin_offsetof(XEvent, xbutton.window) == 16,
"XEvent.xbutton.window");
_Static_assert(__builtin_offsetof(XEvent, xconfigure.window) == 20,
"XEvent.xconfigure.window");
_Static_assert(__builtin_offsetof(XEvent, xclient.window) == 16,
"XEvent.xclient.window");
_Static_assert(sizeof(XEvent) >= 96,
"XEvent must cover the termtris 96-byte vt_u32 evbuf[24]");
_Static_assert(sizeof(XEvent) == 96, "the X11R4 XEvent union is 96 bytes");
int layout_display_screens(void) {
return (int)__builtin_offsetof(Display, screens) * 8;
}
int layout_screen_root(void) {
return (int)__builtin_offsetof(Screen, root) * 8;
}
int layout_image_data(void) {
return (int)__builtin_offsetof(XImage, data) * 8;
}
int layout_image_byte_order(void) {
return (int)__builtin_offsetof(XImage, byte_order) * 8;
}
int layout_image_bytes_per_line(void) {
return (int)__builtin_offsetof(XImage, bytes_per_line) * 8;
}
int layout_image_bits_per_pixel(void) {
return (int)__builtin_offsetof(XImage, bits_per_pixel) * 8;
}
int layout_image_f(void) {
return (int)__builtin_offsetof(XImage, f) * 8;
}
int layout_error_error_code(void) {
return (int)__builtin_offsetof(XErrorEvent, error_code) * 8;
}
int layout_event_xkey_keycode(void) {
return (int)__builtin_offsetof(XEvent, xkey.keycode) * 8;
}
int layout_event_size(void) {
return (int)sizeof(XEvent);
}
/* Exercise the real access path: follows Display.screens and reads Screen.root. */
unsigned int root_probe(Display *d) { return vt_root(d); }
+291
View File
@@ -0,0 +1,291 @@
/*
* Minimal X11R4-compatible declarations for the M4 VT1200 clients.
*
* The VT1200 X server is X11R4 on a 32-bit TMS34010, so this header models
* that ABI: XID/Window/KeySym/Time are 32-bit unsigned long, GC is a 32-bit
* pointer, and XImage carries the inline six-entry struct funcs tail.
*
* Display/Screen deliberately do NOT include the host X11R4 header. The
* VT1200 ROM's Display is the M3-verified layout: Display.screens at byte
* 0x90 (bit 0x480) and Screen.root at byte 0x8 (bit 0x40). Do not include
* scripts/m3/vt1200_xlib.h here; its XOpenDisplay/XCreateSimpleWindow
* prototypes conflict with the wider M4 ones below.
*
* Offset assertions live in scripts/m4/layout.c; the TI golden in
* scripts/m4/layout-ti.s carries the same bit displacements.
*/
#ifndef X11M4_H
#define X11M4_H
typedef unsigned long XID;
typedef XID Window;
typedef XID Drawable;
typedef XID Pixmap;
typedef XID Atom;
typedef XID Colormap;
typedef XID Cursor;
typedef XID Font;
typedef XID GContext;
typedef XID KeySym;
typedef unsigned long Mask;
typedef unsigned long Time;
typedef int Bool;
typedef unsigned char KeyCode;
typedef char *XPointer;
typedef struct _XGC *GC;
typedef struct _Visual Visual; /* opaque: clients only pass a Visual * */
typedef struct _XImage XImage;
/*
* The VT1200 ROM layout, reused from scripts/m3/vt1200_xlib.h. TMS34010
* indirect displacements are bit offsets, so screens is at byte 0x90 and
* root at byte 0x8.
*/
typedef struct _Display {
unsigned char pad[0x90];
void *screens;
} Display;
typedef struct _Screen {
unsigned char pad[0x8];
unsigned int root;
} Screen;
/* X11R4 xlib.h: the image function table is inline in XImage, not a pointer. */
struct funcs {
XImage *(*create_image)(Display *, Visual *, unsigned int, int, int, char *,
unsigned int, unsigned int, int, int);
int (*destroy_image)(XImage *);
unsigned long (*get_pixel)(XImage *, int, int);
int (*put_pixel)(XImage *, int, int, unsigned long);
XImage *(*sub_image)(XImage *, int, int, unsigned int, unsigned int);
int (*add_pixel)(XImage *, long);
};
typedef struct _XImage {
int width, height;
int xoffset;
int format;
char *data;
int byte_order;
int bitmap_unit;
int bitmap_bit_order;
int bitmap_pad;
int depth;
int bytes_per_line;
int bits_per_pixel;
unsigned long red_mask, green_mask, blue_mask;
void *obdata;
struct funcs f;
} XImage;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window window;
} XAnyEvent;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window window;
Window root;
Window subwindow;
Time time;
int x, y;
int x_root, y_root;
unsigned int state;
unsigned int keycode;
Bool same_screen;
} XKeyEvent;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window window;
Window root;
Window subwindow;
Time time;
int x, y;
int x_root, y_root;
unsigned int state;
unsigned int button;
Bool same_screen;
} XButtonEvent;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window window;
int mode;
int detail;
} XFocusChangeEvent;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window window;
int x, y;
int width, height;
int count;
} XExposeEvent;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window event;
Window window;
int x, y;
int width, height;
int border_width;
Window above;
Bool override_redirect;
} XConfigureEvent;
typedef struct {
int type;
unsigned long serial;
Bool send_event;
Display *display;
Window window;
Atom message_type;
int format;
union {
char b[20];
short s[10];
long l[5];
} data;
} XClientMessageEvent;
typedef struct {
int type;
Display *display;
XID resourceid;
unsigned long serial;
unsigned char error_code;
unsigned char request_code;
unsigned char minor_code;
/*
* X11R4's 32-bit XErrorEvent is 20 bytes: the three trailing chars are
* followed by one byte of ABI pad. The TMS34010 C ABI packs structs (and
* TI C does too), so state the pad explicitly to keep sizeof == 20.
*/
unsigned char abi_pad;
} XErrorEvent;
/*
* X11R4's XEvent is 96 bytes: the largest member is pad[24] (the protocol
* xEvent is 24 longs). The termtris event buffer is vt_u32 evbuf[24].
*/
typedef union _XEvent {
int type;
XAnyEvent xany;
XKeyEvent xkey;
XButtonEvent xbutton;
XFocusChangeEvent xfocus;
XExposeEvent xexpose;
XConfigureEvent xconfigure;
XClientMessageEvent xclient;
XErrorEvent xerror;
long pad[24];
} XEvent;
/* Event codes (X11R4). */
#define KeyPress 2
#define KeyRelease 3
#define ButtonPress 4
#define ButtonRelease 5
#define FocusIn 9
#define FocusOut 10
#define Expose 12
/* Event masks (X11R4). */
#define NoEventMask 0L
#define KeyPressMask (1L << 0)
#define KeyReleaseMask (1L << 1)
#define ButtonPressMask (1L << 2)
#define ButtonReleaseMask (1L << 3)
#define ExposureMask (1L << 15)
#define StructureNotifyMask (1L << 17)
#define FocusChangeMask (1L << 21)
/* Image byte/bit order and format. */
#define LSBFirst 0
#define MSBFirst 1
#define XYBitmap 0
#define XYPixmap 1
#define ZPixmap 2
#define True 1
#define False 0
#define None 0L
typedef int (*XErrorHandler)(Display *, XErrorEvent *);
typedef int (*XIOErrorHandler)(Display *);
/*
* Real Xlib entry points. The VT1200 ROM exports these names; Task 5
* validates their bit addresses in symbols/vt1200-v22.syms.
*
* XCreateGC's XGCValues* and XLookupString's XComposeStatus* are modelled as
* void*: the layout is not needed by the M4 clients and the 32-bit pointer
* ABI is unchanged.
*/
extern Display *XOpenDisplay(const char *name);
extern Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
unsigned int width, unsigned int height,
unsigned int border_width,
unsigned long border,
unsigned long background);
extern int XMapWindow(Display *display, Window window);
extern int XSync(Display *display, Bool discard);
extern int XFlush(Display *display);
extern int XSelectInput(Display *display, Window window, long event_mask);
extern GC XCreateGC(Display *display, Drawable drawable,
unsigned long valuemask, void *values);
extern int XSetForeground(Display *display, GC gc, unsigned long foreground);
extern int XFillRectangle(Display *display, Drawable drawable, GC gc, int x,
int y, unsigned int width, unsigned int height);
extern int XDrawString(Display *display, Drawable drawable, GC gc, int x, int y,
const char *string, int length);
extern int XNextEvent(Display *display, XEvent *event);
extern int XLookupString(XKeyEvent *event, char *buffer, int bytes,
KeySym *keysym, void *compose_status);
extern int XPending(Display *display);
extern int XGetInputFocus(Display *display, Window *focus, int *revert_to);
extern Font XLoadFont(Display *display, const char *name);
extern int XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
int src_x, int src_y, unsigned int width,
unsigned int height, int dest_x, int dest_y);
extern XImage *XCreateImage(Display *display, Visual *visual,
unsigned int depth, int format, int offset,
char *data, unsigned int width,
unsigned int height, int bitmap_pad,
int bytes_per_line);
extern int XPutImage(Display *display, Drawable drawable, GC gc, XImage *image,
int src_x, int src_y, int dest_x, int dest_y,
unsigned int width, unsigned int height);
extern int XDestroyImage(XImage *image);
extern XErrorHandler XSetErrorHandler(XErrorHandler handler);
extern XIOErrorHandler XSetIOErrorHandler(XIOErrorHandler handler);
/* Follow Display.screens (bit 0x480) and read Screen.root (bit 0x40). */
static inline __attribute__((always_inline)) unsigned int
vt_root(Display *display) {
return ((Screen *)((Display *)display)->screens)->root;
}
#endif /* X11M4_H */
+148
View File
@@ -0,0 +1,148 @@
#!/bin/sh
# M4 layout gate: the X11R4-compatible XImage/XEvent/XErrorEvent and the ROM's
# Display/Screen layouts must match the 32-bit VT1200 ABI.
#
# layout.c asserts the byte offsets with _Static_assert and returns the ROM's
# bit displacements (byte offset * 8). layout-ti.c is the same layout compiled
# by the 1987 TI compiler once; its &-of-member is already a bit address.
# Both asm files must carry the same constants.
#
# No host X11 headers are used: layout.c includes only scripts/m4/x11m4.h and
# tms-clang runs with -nostdinc.
set -eu
ROOT=$(cd "$(dirname "$0")/../../.." && pwd)
LLVM_BIN=${LLVM_BIN:-$ROOT/build/llvm-clean-build/bin}
TMS_CLANG=${TMS_CLANG:-$LLVM_BIN/clang}
TMS_OPT=${TMS_OPT:-$LLVM_BIN/opt}
TMS_LLC=${TMS_LLC:-$LLVM_BIN/llc}
TMS_BITADDR=${TMS_BITADDR:-$ROOT/tools/tms-bitaddr/tms-bitaddr}
WORK=${M4_LAYOUT_WORK:-$ROOT/build/m4-layout}
GOLDEN=$ROOT/scripts/m4/layout-ti.s
fail() {
echo "layout.sh: FAIL: $*" >&2
exit 1
}
for tool in "$TMS_CLANG" "$TMS_OPT" "$TMS_LLC" "$TMS_BITADDR"; do
[ -x "$tool" ] || fail "missing tool: $tool"
done
[ -f "$GOLDEN" ] || fail "missing TI golden: $GOLDEN"
mkdir -p "$WORK"
# Exit 0 here means every _Static_assert in layout.c held on the target.
TMS_CLANG="$TMS_CLANG" TMS_OPT="$TMS_OPT" TMS_BITADDR="$TMS_BITADDR" \
"$ROOT/scripts/tms-clang" -O0 -o "$WORK/layout.ll" \
"$ROOT/scripts/m4/layout.c" \
|| fail "target compile failed (XImage/XEvent/XErrorEvent/Display static asserts?)"
"$TMS_LLC" -march=tms34010 -O0 -filetype=asm \
"$WORK/layout.ll" -o "$WORK/layout.s" \
|| fail "llc failed for layout.ll"
# Print one function body, stopping at the next function label. TI's
# EPI0_n labels are inside the function and come after the constant we check.
body() { # body FILE FUNC
awk -v want="_$2:" '
$1 == want { infn = 1; next }
infn {
if ($0 ~ /^[A-Za-z_][A-Za-z0-9_]*:/ && $0 !~ /^LBB/) exit
print
}
' "$1"
}
# Allowed spellings for a constant: C hex, assembler hex with `h`, decimal.
has_const() { # has_const FILE FUNC ERE
body "$1" "$2" | tr 'A-Z' 'a-z' | grep -Eq "$3"
}
check() { # check FILE FUNC ERE WHAT
if ! has_const "$1" "$2" "$3"; then
echo "layout.sh: $1: _$2 body:" >&2
body "$1" "$2" >&2
fail "_$2 in $1 does not contain $4"
fi
}
# First MOVI immediate in a function body, in decimal.
const_value() { # const_value FILE FUNC
body "$1" "$2" | awk '
/MOVI/ {
for (i = 1; i <= NF; i++)
if ($i == "MOVI") {
v = $(i + 1)
sub(/,.*/, "", v)
print v
exit
}
}
'
}
to_dec() { # to_dec TOKEN
case "$1" in
0x* | 0X*) printf '%d' "$1" ;;
*h | *H) printf '%d' "0x${1%?}" ;;
*) printf '%d' "$1" ;;
esac
}
HEX480='(0x480|480h|[^0-9a-f]1152[^0-9a-f])'
HEX40='(0x40|40h|[^0-9a-f]64[^0-9a-f])'
HEX80='(0x80|80h|[^0-9a-f]128[^0-9a-f])'
HEXA0='(0xa0|0a0h|[^0-9a-f]160[^0-9a-f])'
HEX140='(0x140|140h|[^0-9a-f]320[^0-9a-f])'
HEX160='(0x160|160h|[^0-9a-f]352[^0-9a-f])'
HEX200='(0x200|200h|[^0-9a-f]512[^0-9a-f])'
HEX1A0='(0x1a0|1a0h|[^0-9a-f]416[^0-9a-f])'
for asm in "$WORK/layout.s" "$GOLDEN"; do
check "$asm" layout_display_screens "$HEX480" "0x480 (Display.screens)"
check "$asm" layout_screen_root "$HEX40" "0x40 (Screen.root)"
check "$asm" layout_image_data "$HEX80" "0x80 (XImage.data at byte 16)"
check "$asm" layout_image_byte_order "$HEXA0" "0xA0 (XImage.byte_order at byte 20)"
check "$asm" layout_image_bytes_per_line "$HEX140" "0x140 (XImage.bytes_per_line at byte 40)"
check "$asm" layout_image_bits_per_pixel "$HEX160" "0x160 (XImage.bits_per_pixel at byte 44)"
check "$asm" layout_image_f "$HEX200" "0x200 (XImage.f at byte 64)"
check "$asm" layout_error_error_code "$HEX80" "0x80 (XErrorEvent.error_code at byte 16)"
check "$asm" layout_event_xkey_keycode "$HEX1A0" "0x1A0 (XEvent.xkey.keycode at byte 52)"
done
# sizeof(XEvent) is in bytes. It must cover the termtris vt_u32 evbuf[24].
TARGET_TOKEN=$(const_value "$WORK/layout.s" layout_event_size) \
|| fail "could not read layout_event_size from layout.s"
GOLDEN_TOKEN=$(const_value "$GOLDEN" layout_event_size) \
|| fail "could not read layout_event_size from the TI golden"
[ -n "$TARGET_TOKEN" ] || fail "layout.s layout_event_size has no MOVI constant"
[ -n "$GOLDEN_TOKEN" ] || fail "TI golden layout_event_size has no MOVI constant"
TARGET_SIZE=$(to_dec "$TARGET_TOKEN") \
|| fail "could not parse layout_event_size '$TARGET_TOKEN' from layout.s"
GOLDEN_SIZE=$(to_dec "$GOLDEN_TOKEN") \
|| fail "could not parse layout_event_size '$GOLDEN_TOKEN' from the TI golden"
[ "$TARGET_SIZE" -ge 96 ] \
|| fail "target sizeof(XEvent) = $TARGET_SIZE bytes, want >= 96"
[ "$GOLDEN_SIZE" -ge 96 ] \
|| fail "TI sizeof(XEvent) = $GOLDEN_SIZE bytes, want >= 96"
[ "$TARGET_SIZE" -eq "$GOLDEN_SIZE" ] \
|| fail "target sizeof(XEvent)=$TARGET_SIZE but TI golden=$GOLDEN_SIZE"
# root_probe exercises the real access path: vt_root() follows Display.screens
# (bit 0x480) and reads Screen.root (bit 0x40). The helper is always_inline.
check "$WORK/layout.s" root_probe "$HEX480" "0x480 (Display.screens)"
check "$WORK/layout.s" root_probe "$HEX40" "0x40 (Screen.root)"
if body "$WORK/layout.s" root_probe | grep -q 'MOVB'; then
fail "root_probe contains MOVB: align-1 field loads did not select MOVE"
fi
# Guard against the old byte/bit-confusion mistake: Display.screens must not
# be 0x480*8 (9216) and Screen.root must not be 0x40*8 (512).
if body "$WORK/layout.s" layout_display_screens | tr 'A-Z' 'a-z' |
grep -Eq '(^|[^0-9])(9216|2400h)([^0-9a-f]|$)' ||
body "$WORK/layout.s" layout_screen_root | tr 'A-Z' 'a-z' |
grep -Eq '(^|[^0-9])(512|200h)([^0-9a-f]|$)'; then
fail "target carries byte-pad offsets (9216/512); ROM displacements are bits 0x480/0x40"
fi
echo "layout.sh: PASS (XImage data/byte_order/bpl/bpp/f = 0x80/0xA0/0x140/0x160/0x200; XErrorEvent.error_code=0x80; XEvent.xkey.keycode=0x1A0; sizeof(XEvent)=$TARGET_SIZE; Display.screens=0x480, Screen.root=0x40; target + TI golden)"