// ptsize.c — tamaño de una tabla de páginas lineal.
//
// Uso:   ./ptsize bits_de_dirección tamaño_página tamaño_pte
// Ejemplos:
//   ./ptsize 32 4096 4     x86 de 32 bits
//   ./ptsize 48 4096 8     x86-64 (48 bits de dirección virtual)
//   ./ptsize 39 4096 8     RISC-V Sv39, el de xv6
#include <stdio.h>
#include <stdlib.h>

static int log2_exact(unsigned long x) {
    int n = 0;
    while ((1UL << n) < x)
        n++;
    return (1UL << n) == x ? n : -1;
}

// Imprime 2^e bytes con la unidad binaria más grande que quede entera.
static void print_size(int e) {
    static const char *unit[] = {"bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
    int u = e / 10;
    if (u > 6)
        u = 6;
    printf("2^%d bytes = %lu %s", e, 1UL << (e - 10 * u), unit[u]);
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        fprintf(stderr, "uso: %s bits_de_dirección tamaño_página tamaño_pte\n", argv[0]);
        return 1;
    }
    int va_bits = atoi(argv[1]);
    int off_bits = log2_exact(strtoul(argv[2], NULL, 0));
    int pte_bits = log2_exact(strtoul(argv[3], NULL, 0));
    if (off_bits < 0 || pte_bits < 0 || va_bits <= off_bits || va_bits > 64) {
        fprintf(stderr, "use potencias de 2 y una dirección más grande que la página\n");
        return 1;
    }
    int vpn_bits = va_bits - off_bits;
    printf("offset: %d bits, VPN: %d bits\n", off_bits, vpn_bits);
    printf("entradas: 2^%d\n", vpn_bits);
    printf("tabla:    2^%d x %s bytes = ", vpn_bits, argv[3]);
    print_size(vpn_bits + pte_bits);
    printf(" por proceso\n");
    return 0;
}
