uxndebug

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 81418dfc8eca7f85e745b31e2d2d15b73058a7fb
parent b97e22a90af15408ca33c0b9f30e1235881474cc
Author: aabacchus <ben@bvnf.space>
Date:   Sun,  5 Jun 2022 20:19:32 +0100

naive debug file generation, add tool to parse debug file, add file format manpage

Diffstat:
Auxndebug.5 | 35+++++++++++++++++++++++++++++++++++
Muxndebug.c | 28++++++++++++++++++++++++++++
Auxnsolve | 50++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/uxndebug.5 b/uxndebug.5 @@ -0,0 +1,35 @@ +.Dd June 5, 2022 +.Dt UXNDEBUG 5 +.Os +.Sh NAME +.Nm uxndebug , +.Nm .tal.debug +.Nd uxntal debug info file format +.Sh DESCRIPTION +The format of debug information for an uxntal rom file is documented in this file. +.Pp +Each line of the debug file is terminated by a single +.Aq newline +character, and contains a single hexadecimal number. +The line number of the file corresponds to the +.Em byte +of the rom, +and the number written on the line signifies which +.Em token +in the source files was assembled into that +.Em byte . +The name of the debug file is used to identify which source file contains the relevant +.Em token Ns s . +.Sh FILES +For a source file +.Pa example.tal , +the corresponding rom +.Pa example.rom +and debug information file +.Pa example.tal.debug +are created by running: +.Bd -literal -offset indent +uxndebug example.tal example.rom +.Ed +.Sh SEE ALSO +.Xr uxndebug 1 diff --git a/uxndebug.c b/uxndebug.c @@ -48,6 +48,9 @@ static int litlast = 0; static int jsrlast = 0; static int token_number = 0; +static int debug_lineno = 0; +static char *debug_filename = "debug.tal.debug"; +FILE *debug_file = NULL; /* clang-format off */ @@ -191,6 +194,17 @@ makereference(char *scope, char *label, Uint16 addr) return 1; } +static void +debug_next_byte(void) { + while (p.ptr - 0x0100 != debug_lineno) { + fprintf(debug_file, "\n"); + debug_lineno++; + /* TODO: better way to handle this is to write to buffer with byte,token pairs, then write to file at end */ + } + fprintf(debug_file, "%d\n", token_number); + debug_lineno++; +} + static int writebyte(Uint8 b) { @@ -200,6 +214,7 @@ writebyte(Uint8 b) return error("Writing after the end of RAM", ""); else if(p.ptr < p.length) return error("Memory overwrite", ""); + debug_next_byte(); p.data[p.ptr++] = b; p.length = p.ptr; litlast = 0; @@ -211,11 +226,14 @@ static int writeopcode(char *w) { Uint8 res; + /* disable optimizations which go back if(jsrlast && scmp(w, "JMP2r", 5)) { /* tail-call optimization */ + /* p.data[p.ptr - 1] = jsrlast == 2 ? findopcode("JMP2") : findopcode("JMP"); jsrlast = 0; return 1; } + */ res = writebyte(findopcode(w)); if(scmp(w, "JSR2", 4)) jsrlast = 2; @@ -235,12 +253,15 @@ writeshort(Uint16 s, int lit) static int writelitbyte(Uint8 b) { + /* disable optimizations which go back if(litlast) { /* literals optimization */ + /* Uint8 hb = p.data[p.ptr - 1]; p.ptr -= 2; p.length = p.ptr; return writeshort((hb << 8) + b, 1); } + */ if(!writebyte(findopcode("LIT"))) return 0; if(!writebyte(b)) return 0; litlast = 1; @@ -454,6 +475,12 @@ int main(int argc, char *argv[]) { FILE *src, *dst; + debug_file = fopen(debug_filename, "w"); + if (debug_file == NULL) { + perror(debug_filename); + return 1; + } + if(argc < 3) return !error("usage", "input.tal output.rom"); if(!(src = fopen(argv[1], "r"))) @@ -466,5 +493,6 @@ main(int argc, char *argv[]) return !error("Assembly", "Output rom is empty."); fwrite(p.data + TRIM, p.length - TRIM, 1, dst); review(argv[2]); + fclose(debug_file); return 0; } diff --git a/uxnsolve b/uxnsolve @@ -0,0 +1,50 @@ +#!/bin/sh + +# desired behaviour +# shellcheck disable=SC2015 +[ "$#" -eq 2 ] && [ -r "$1" ] || { + printf "usage: %s file.tal.debug address\n" "$0" >&2 + exit 1 +} + +case "$1" in + *.tal.debug) ;; + *) + printf "%s: does not end in .tal.debug, can't work out source file\n" "$1" >&2 + exit 1 + ;; +esac + +debug_file="$1" +source_file="${1%.debug}" + +address="$(printf "%s" "$2" | tr 'a-f' 'A-F')" +dec_address="$(printf "16iAo%sp\n" "$address" | dc || kill 0)" +# add 1 because the zeroth byte is on the first line +dec_address="$((dec_address + 1))" +# TODO: should we subtract the #0100 offset or request the user to do that? + +is_integer() { + printf %d "$1" >/dev/null 2>&1 +} + +token="$(sed -n "${dec_address}p" "$debug_file")" +: "${token:?can\'t find integer from debug file at given byte}" +is_integer "$token" || { + printf "can't find an integer token number in %s for byte %X\n" "$debug_file" "$address" >&2 + exit 1 +} + +i=0 +lineno=0 +while read -r line; do + lineno="$((lineno + 1))" + # word splitting is desired. + # shellcheck disable=SC2086 + set -- $line + i="$((i + $#))" + [ "$i" -ge "$token" ] && { + printf "line %d: %s\n" "$lineno" "$line" + break + } +done < "$source_file"