NOTA BENE: tutti i numeri esadecimali usati in questo testo sono da considerarsi come numeri di 8 cifre (per ottenere 32 bit). Per comodita', un numero del tipo 0x00003244 e'stato scritto omettendo le cifre piu' significative uguali a 0, ovvero 0x3244. SOTTOPROGETTO MIC-2 Lo scopo di questo progetto e' l'estensione del set d'istruzioni IJVM da utilizzare nella scrittura di programmi. Le nuove istruzioni da realizzare sono di due tipi: gestione di array statici globali ed istruzioni di shift. Per l'implementazione delle istruzioni per la gestione degli array, supporre che il riferimento all'array sia memorizzato nel constant pool (ossia supporre che esso rappresenti uno scostamento da CPP) e che la relativa locazione nel constant pool contenga l'indirizzo di memoria a partire dal quale si trovano, uno di seguito all'altro, gli elementi dell'array. Supporre inoltre che l'indice di un elemento dell'array rappresenti uno scostamento da tale indirizzo. ESEMPIO: se abbiamo un array V di 4 elementi in memoria centrale a partire dall'indirizzo 0x5000 la situazione della memoria centrale sara': MEMORIA INDIRIZZO |_____0x5000____| 0x4000 < CPP -------- |_______________| |_______________| |_______________| |_______________| |_______________| |_______________| ::::::::::::::: |_____0x23B4____| 0x5000 |_____0x123A____| 0x5001 ARRAY V |_____0xDA80____| 0x5002 DI 4 ELEMENTI |_____0x12F2____| 0x5003 |_______________| |_______________| |_______________| |_______________| |_______________| ::::::::::::::: |_______________| 0x8000 < SP -------- |_______________| |_______________| |_______________| |_______________| |_______________| |_______________| L'indice di un elemento dell'array si intende come scostamento da 0x5000 per cui, V[0]=0x23B4 (ovvero la parola a scostamento 0 da 0x5000) V[1]=0x123A (ovvero la parola a scostamento 1 da 0x5000) V[2]=0xDA80 (ovvero la parola a scostamento 2 da 0x5000) V[3]=0x12F2 (ovvero la parola a scostamento 3 da 0x5000) ISTRUZIONE NUMERO 1 - IALOAD (Integer Array LOAD). Questa istruzione, il cui codice operativo e' 0x2E, carica un elemento di un array in cima allo stack. Subito prima della sua esecuzione, IALOAD si aspetta di trovare in cima allo stack il riferimento all'array (indirizzo del primo elemento) e l'indice dell'elemento da caricare. L'esecuzione di IALOAD ha come effetto la rimozione dallo stack dei due dati prima menzionati, il calcolo dell'indirizzo dell'elemento da caricare, e la scrittura in cima allo stack del valore di tale elemento. ESEMPIO: se in un programma IJVM vogliamo caricare in cima allo stack l'elemento V[2] allora dobbiamo scrivere un frammento di codice del tipo .constant V 0x5000 .end-constant ....... LDC_W V BIPUSH 2 IALOAD ....... ottenendo per lo stack (dopo le prime due istruzioni) |____0x5000_____| |____0x0002_____| 0x8002 < SP -------- |_______________| |_______________| |_______________| |_______________| |_______________| e dopo IALOAD |____0xDA80__-__| 0x8001 < SP -------- |_______________| |_______________| |_______________| |_______________| |_______________| |_______________| ISTRUZIONE NUMERO 2 - IASTORE (Integer Array STORE). Questa istruzione, il cui codice operativo e` 0x4F, carica il valore in cima allo stack in un elemento di un array. Subito prima della sua esecuzione, IASTORE si aspetta di trovare in cima allo stack il riferimento all'array, l'indice dell'elemento in cui caricare il valore, e il valore. L'esecuzione di IASTORE prevede la rimozione dallo stack dei tre dati prima menzionati, il calcolo dell'indirizzo dell'elemento su cui caricare il valore, e la scrittura del valore nell'indirizzo precedentemente calcolato. ESEMPIO: se vogliamo assegnare a V[3] il valore in cima allo stack (ad esempio, 0x1D1A) allora lo stack prima dell'esecuzione di IASTORE deve essere |____0x5000_____| |____0x0003_____| |____0x1D1A_____| 0x8003 < SP -------- |_______________| |_______________| |_______________| |_______________| dopo l'esecuzione di IASTORE si otterra' ::::::::::::::: |_____0x23B4____| 0x5000 |_____0x123A____| 0x5001 ARRAY V |_____0xDA80____| 0x5002 DI 4 ELEMENTI |_____0x1D1A ___| 0x5003 |_______________| |_______________| |_______________| |_______________| |_______________| ::::::::::::::: |_______________| 0x8000 < SP -------- |_______________| |_______________| |_______________| |_______________| |_______________| |_______________| ISTRUZIONE NUMERO 3 - ISHL (Integer SHift Left). Questa istruzione, il cui codice operativo e' 0x78, effettua uno shift a sinistra. Subito prima della sua esecuzione, ISHL si aspetta di trovare in cima allo stack due valori che specificano rispettivamente l'oggetto e la dimensione dello shift. L'esecuzione di ISHL prevede la rimozione dallo stack dei due valori prima menzionati, lo shift a sinistra del primo valore di s bit dove s e' dato dai 5 bit meno significativi del secondo valore, e la scrittura in cima allo stack del risultato dello shift. ESEMPIO: se vogliamo effettuare uno shift a sinistra di 3 posizioni della parola 0x0020 allora sullo stack deve esserci |____0x0020_____| |____0x0003_____| 0x8002 < SP -------- |_______________| |_______________| |_______________| |_______________| |_______________| dopo l'esecuzione di ISHL lo stack sara' |____0x0100_____| 0x8001 < SP -------- |_______________| |_______________| |_______________| |_______________| |_______________| |_______________| ISTRUZIONE NUMERO 4 - ISHR (Integer Shift Right). Questa istruzione, il cui codice operativo e' 0x7A, effettua uno shift a destra preservando il segno. Subito prima della sua esecuzione, ISHR si aspetta di trovare in cima allo stack due valori che specificano rispettivamente l'oggetto e la dimensione dello shift. L'esecuzione di ISHR prevede la rimozione dallo stack dei due valori prima menzionati, lo shift a destra del primo valore (con estensione del segno) di s bit dove s e' dato dai 5 bit meno significativi del secondo valore, e la scrittura in cima allo stack del risultato dello shift. ISTRUZIONE NUMERO 5 - IUSHR (Integer Unsigned Shift Right). Questa istruzione, il cui codice operativo e' 0x7C, effettua uno shift a destra senza preservare il segno. Subito prima della sua esecuzione, IUSHR si aspetta di trovare in cima allo stack due valori che specificano rispettivamente l'oggetto e la dimensione dello shift. L'esecuzione di IUSHR prevede la rimozione dallo stack dei due valori prima menzionati, lo shift a destra del primo valore (con estensione 0) di s bit dove s e` dato dai 5 bit meno significativi del secondo valore, e la scrittura in cima allo stack del risultato dello shift. COME PROCEDERE Per poter ottenere un set di istruzioni esteso e' necessario agire su due fronti: 1) Permettere che l'assemblatore di programmi IJVM riconosca come parte del set di istruzioni le nuove istruzioni. A tal fine bisogna modificare il file ijvm.conf nella cartella mic2001; questo file contiene una riga per ogni istruzione IJVM dove viene specificato il codice mnemonico, il codice operativo in esadecimale ed eventuali argomenti. Questo file e' usato dall'assemblatore ijvmasm per produrre un file che l'emulatore puo' caricare nella sua rappresentazione della memoria centrale dell'architettura. P.S. se il file ijvm.conf non fosse modificabile con un editor di testi allora selezionare la sua icona con il tasto destro del mouse, scegliere la voce proprieta' e deselezionare la casella "solo lettura" dalla sezione attributi. 2) Modificare opportunamente il microinterprete (memorizzato nel file mic1ijvm.mal da scaricare dalla pagina del software) affinche' realizzi correttamente il fetch e l'esecuzione delle 5 nuove istruzioni. COME VERIFICARE LA CORRETTEZZA DELL'IMPLEMENTAZIONE Per le istruzioni di shift usare il seguente programma IJVM variando a piacimento i valori e le istruzioni usate. Si deve: - salvarlo in un file con l'estensione .jas - assemblarlo con ijvmasm (l'equivalente di mic1asm per i programmi IJVM) - tradurre il vostro microinterprete modificato - con l'emulatore, caricare il micro interprete (File->Load Microprogram) - con l'emulatore, caricare il vostro esempio (File->Load Macroprogram) - eseguire il programma con run e verificare il risultato sullo stack //////////////////////////////////////// // --- Start program --- .constant VALUE_TO_SHIFT 0x0A10 // Notazione per ii numeri esadecimali NUMBER_OF_SHIFT 7 // Notazione per ii numeri decimali .end-constant .main LDC_W VALUE_TO_SHIFT // push sullo stack del valore da shiftare LDC_W NUMBER_OF_SHIFT // push sullo stack del numero di shift ISHL // oppure ISHR o IUSHR HALT .end-main // --- End program --- COMPITI D'ESAME Per questo esercizio dovete consegnare una relazione che contenga, - microinterprete commentato - commenti sul trattamento degli shift - file di definizione del set di istruzioni commentato - descrizione sintetica delle prove effettuate