#include <stdio.h>
#include <stdint.h>

// TP 2/3 de IN330 -- exercices préparatoires
// LG et SM pour IN330, 2024
// BEGIN CUT
// 1. w = 0000 0000 1011 0110 0000 0110 0011 0011
//    Le bit #0 est à droite.
//    Le champ à la position 0 de longueur 7 a pour valeur 0x33 = 51.
// 2. Le champ à la position 15 de longueur 5 a pour valeur 0b01100 = 12.
// 3. 1<<6      = 1000000
//    (1<<6)-1  =  111111
//    Formule : (1 << l) - 1
// 5. +15 sur 8 bits :      0000 1111
//           12 bits : 0000 0000 1111
//    -15 sur 8 bits :      1111 0001
//           12 bits : 1111 1111 0001
//    Les 4 bits ajoutés sont tous égaux au bit de signe.
// 6. On regarde le bit de signe (ici le 11ème) et on le répète.
//      0x3ff -> bit de signe = 0 -> 0x000003ff
//      0xfff -> bit de signe = 1 -> 0xffffffff
// END CUT

uint32_t extract_field(uint32_t w, int p, int l)
{
	// TODO : Extraire de w la série de bits à la position p de longueur l

	// BEGIN CUT
	uint32_t mask = (1 << l) - 1;
	return (w >> p) & mask;
	// END CUT
}

// Extension de signe d'un entier de n-bits (n > 1), i, vers 32 bits
int32_t sign_extend(uint32_t i, int n)
{
	// BEGIN CUT
	return ((int32_t)i << (32 - n)) >> (32 - n);
	// uint32_t mask = ~((1 << n) - 1);
	// if(i & (1 << (n - 1)))
	//	i |= mask;
	// return i;
	// END CUT
}

int main(void)
{
	uint32_t w = 0x00b60633;
	printf("w[6..0] = %u\n", extract_field(w, 0, 7));
	printf("w[19..15] = %u\n", extract_field(w, 15, 5));

	// BEGIN CUT
	w = 0xfd628293;
	printf("w[31..20] = %d (zero ext.)\n", extract_field(w, 20, 12));
	printf("w[31..20] = %d (sign ext.)\n", sign_extend(extract_field(w, 20, 12), 12));
	// END CUT
}
