Esempio calcolo indice array da indirizzo device register

From Sistemi Operativi
Jump to navigation Jump to search

Ecco un esempio di codice:

#include "listx.h"
#include "umps3/umps/const.h"
#include "umps3/umps/arch.h"
#include "pandos_const.h"
#include "pandos_types.h"

// https://stackoverflow.com/questions/27581671/how-to-compute-log-with-the-preprocessor
// ---8<-----
#define NEEDS_BIT(N, B)     (((unsigned long)N >> B) > 0)

#define BITS_TO_REPRESENT(N)                            \
        (NEEDS_BIT(N,  0) + NEEDS_BIT(N,  1) + NEEDS_BIT(N,  2) + NEEDS_BIT(N,  3) + \
         NEEDS_BIT(N,  4) + NEEDS_BIT(N,  5) + NEEDS_BIT(N,  6) + NEEDS_BIT(N,  7) + \
         NEEDS_BIT(N,  8) + NEEDS_BIT(N,  9) + NEEDS_BIT(N, 10) + NEEDS_BIT(N, 11) + \
         NEEDS_BIT(N, 12) + NEEDS_BIT(N, 13) + NEEDS_BIT(N, 14) + NEEDS_BIT(N, 15) + \
         NEEDS_BIT(N, 16) + NEEDS_BIT(N, 17) + NEEDS_BIT(N, 18) + NEEDS_BIT(N, 19) + \
         NEEDS_BIT(N, 20) + NEEDS_BIT(N, 21) + NEEDS_BIT(N, 22) + NEEDS_BIT(N, 23) + \
         NEEDS_BIT(N, 24) + NEEDS_BIT(N, 25) + NEEDS_BIT(N, 26) + NEEDS_BIT(N, 27) + \
         NEEDS_BIT(N, 28) + NEEDS_BIT(N, 29) + NEEDS_BIT(N, 30) + NEEDS_BIT(N, 31))
// ---8<-----

#define LOG_WORD_SIZE (BITS_TO_REPRESENT(WORD_SIZE) - 1)
#define LOG_DEV_REG_SIZE (BITS_TO_REPRESENT(DEV_REG_SIZE) - 1)
#define DEV_REG_MASK (DEV_REG_SIZE -1)
#define ERR -1

int devaddr_to_index(unsigned int addr) {
  // consistency ck
  if (addr < DEV_REG_START || addr >= DEV_REG_END)
    return ERR;
  else if (addr < DEV_REG_ADDR(IL_TERMINAL, 0)) {
    // dev != terminal
    addr -= DEV_REG_START;
    if ((addr & DEV_REG_MASK) == (COMMAND << LOG_WORD_SIZE))
      return addr >> LOG_DEV_REG_SIZE;
    else
      return ERR;
  } else {
    // dev == terminal
    addr -= DEV_REG_START;
    if ((addr & DEV_REG_MASK) == (RECVCOMMAND << LOG_WORD_SIZE))
      return addr >> LOG_DEV_REG_SIZE;
    else if ((addr & DEV_REG_MASK) == (TRANCOMMAND << LOG_WORD_SIZE))
      return (addr >> LOG_DEV_REG_SIZE) + N_DEV_PER_IL;
    else
      return ERR;
  }
}

#if TESTING
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
  for (int i = 1; i < argc; i++) {
    unsigned int addr = strtoul(argv[i], NULL, 0);
    printf("%08x -> %d\n", addr, devaddr_to_index(addr));
  }
}
#endif

Per provarlo (dopo averlo compilato con -DTESTING):

$ ./a.out 0x10000058
10000058 -> 0
$ ./a.out 0x10000068
10000068 -> 1
$ ./a.out 0x000002c8
000002c8 -> -1
$ ./a.out 0x100002c8
100002c8 -> 39
$ ./a.out 0x100002c0
100002c0 -> 46
$ ./a.out 0x100002d0
100002d0 -> 47