Capítulo 5
Capítulo 5
Capítulo 5
Procesamiento VLIW
Captación Cola de
instruccione
(IF) s
Decodificac
ión (ID)
(EX)
Registros de
la
arquitectura
Figura 1. Esquema simplificado de un cauce VLIW.
ld f2, x(r3)
addf4, f2, f0 ld f2, x+8(r3)
sd f4, x(r3) addf4, f2, f0 ld f2, x+16(r3)
sd f4, x+8(r3) addf4, f2, f0
sd f4, x+16(r3)
Figura 2. Construcción del cuerpo del bucle aplicando de segmentación
software.
sd f4, x+16(r3)
if (a && b)
j = j + 1;
else if (c)
k = k + 1;
else
k = k – 1;
i = i + 1;
Inic
io
Si No
¿a ≠ 0?
p1
Si No
¿b ≠ 0?
p
Si No
2
¿c ≠ 0?
p p
p
1 4
jj+1 3 kk–1
kk+1
ii+1
Fin
lw r1, a ; r1 = a
p1, p2cmp.ne r1, r0 ; p1 = 1 si a != 0 (p2 = 1 en caso
contrario)
(p1) lw r2, b ; r2 = b (si a != 0)
(p1) p1, p2cmp.ne r2, r0 ; p1 = 1 si a != 0 y b != 0 (p2 = 1
en caso contrario)
(p1) lw r4, j ; r4 = j (si a != 0 y b != 0)
(p1) addi r4, r4, #1 ; r4 = j + 1 (si a != 0 y b != 0)
(p1) sw r4, j ; j = j + 1 (si a != 0 y b != 0)
(p2) lw r3, c ; r3 = c (si a == 0 ó b == 0)
(p2) lw r5, k ; r5 = k (si a == 0 ó b == 0)
(p2) p3 cmp.ne r0, r0 ; p3 = 0 (si a == 0 ó b == 0)
(p2) p4 cmp.ne r0, r0 ; p4 = 0 (si a == 0 ó b == 0)
(p2) p3, p4cmp.ne r3, r0 ; p3 = 1 ((si a == 0 ó b == 0) y c !
=0)
(p3) addi r5, r5, #1 ; r5 = k + 1 ((si a == 0 ó b ==
0) y c !=0)
(p4) subi r5, r5, #1 ; r5 = k – 1 ((si a == 0 ó b == 0)
y c ==0)
(p2) sw r5, k ; k = r5 (si a == 0 ó b == 0)
lw r6, i ; r6 = i
addi r6, r6, #1 ; r6 = i + 1
sw r6, i ;i=i+1
#. OP1 OP2
1 lw r1, a
2 lw r6, i
p1, p2 cmp.ne
3
r1, r0
addi r6, r6,
4 (p1) lw r2, b
#1
5 sw r6, i
(p1) p1, p2 cmp.ne
6
r2, r0
(p2) p3 cmp.ne
7 (p1) lw r4, j
r0, r0
(p2) p4 cmp.ne
8 (p2) lw r3, c
r0, r0
(p1) addi r4, r4,
9 (p2) lw r5, k
#1
(p2) p3, p4 cmp.ne
10 (p1) sw r4, j
r3, r0
(p3) addi r5, r5, (p4) subi r5, r5,
11
#1 #1
12
13 (p2) sw r5, k
#. OP1 OP2
1 lw r1, a
add r3, r4,
2
r5
beqz r10, add r6, r3,
3
loop r7
lw r8,
4
0(r10)
5
lw r9,
6
0(r8)
#. OP1 OP2
p1 cmp.ne
1 lw r1, a
r10, r0
(p1) lw r8, add r3, r4,
2
0(r10) r5
beqz r10, add r6, r3,
3
loop r7
lw r9,
4
0(r8)
UNIDAD
LATENCIA OP1 OP2 OP3 OP4 OPERACIONES REALIZADAS
FUNCIONAL
Comparaciones, sumas y
restas
ALU 1 X X X X
con enteros y operaciones
lógicas
Memoria 3 X X Cargas y almacenamientos
Saltos condicionales e
Saltos 4 X
incondicionales
Solución
El programa en ensamblador sin desenrollar el bucle puede ser el siguiente:
Solución
En el código que se proporciona en el enunciado existen bastantes latencias
entre las instrucciones que lo componen (por ejemplo, entre la multiplicación
y la suma en coma flotante que aparecen). Se pueden reducir los atascos
causados por esas latencias desenrollado el bucle y reorganizando las
instrucciones, tras renombrar algunos registros. Así, si se desenrolla el bucle
dos veces, y suponiendo que n es par, se obtiene:
nop ; (16)
nop ; (17)
sd f0, z ; (18) Almacenamos el resultado
n
Tseg n 3 12 3 6n 6
2
En el caso del procesador VLIW que puede emitir hasta dos operaciones por
ciclo, se tendrá el código mostrado en la Tabla 10. Debido a las altas
latencias de las unidades de procesamiento de números en coma flotante, el
tiempo de ejecución no mejora demasiado. Como se ha podido solapar la
ejecución de tres instrucciones con respecto al código anterior, el tiempo de
ejecución estimado sería de:
n
TVLIW n 2 10 3 5n 5
2
sd f0, z
Tseg n 6n 6
S n
TVLIW n 5n 5
6n 6
Smax limS n lim 1.2
n n 5n 5
# OP1 OP2
add r10, r11,
1 lw r1, x(r2)
r12
add r13, r10,
2
r14
3 beqz r3, direc
4 lw r4, 0(r3)
5 lw r5, 0(r4)
Solución
La distribución de operaciones entre las distintas instrucciones VLIW
presenta un hueco en el slot 1 de la segunda instrucción. Además, si no se
produce el salto existe una dependencia RAW entre las instrucciones (4) y (5)
que producirá atascos. Con una instrucción de carga condicional lwc que
realice la carga desde memoria en función del valor de r3 se podría mejorar
la situación. Concretamente, se podría utilizar la instrucción lwc r4, 0(r3), r3,
que cargaría el valor de r4 cuando r3 sea distinto de cero, tal y como indica
la Tabla 12, lo que reduciría el código en una instrucción.
# OP1 OP2
add r10, r11,
1 lw r1, x(r2)
r12
add r13, r10,
2 lwc r4, 0(r3), r3
r14
3 beqz r3, direc
4 lw r5, 0(r4)
if (a > b)
x = 1;
else
{
if (c < d)
x = 2;
else
x = 3;
}
Solución
A continuación se muestra el código que implementa el programa anterior
usando predicados:
lw r1, a ; r1 = A
lw r2, b ; r2 = B
p1, p2 cmp.gt r1,r2 ; Si a > b p1 = 1 y p2 = 0 (si no, p1 = 0
y p2 = 1)
(p1) addi r5, r0, #1
p3 cmp.ne r0, r0 ; Inicializamos p3 a 0
p4 cmp.ne r0, r0 ; Inicializamos p4 a 0
(p2) lw r3, c ; r3 = c
(p2) lw r4, d ; r4 = d
(p2) p3, p4 cmp.lt r3, r4 ; Sólo si p2 = 1 p3 o p4 pueden ser 1
(p3) addi r5, r0, #2 ; Se ejecuta si p3 = 1 (y p2 = 1)
(p4) addi r5, r0, #3 ; Se ejecuta si p4 = 1 (y p2 = 1)
sw r5, x ; Almacenamos el resultado
x = 0;
if ((a b) && (b 0))
x = 1;
else if ((b < 0) && (a < b))
x = 2;
Solución
La Figura 4 muestra el organigrama que implementa la secuencia de código
del enunciado, en el que se han resaltado los predicados que se usarán para
sustituir cada uno de los saltos. A partir de esta figura es sencillo escribir el
siguiente código:
Inicio
x←0
Si No
¿a ≥
p1
b?
Si No
¿b ≥
p2
p1 0?
Si No
x←1 ¿b <
p2
0?
Si No
¿a <
p2 b?
x←2
Fin
lw r1, a ; r1 = a
lw r2, b ; r2 = b
add r3, r0, r0 ; r3 = 0
Una vez escrito el código, sólo nos queda optimizarlo para la arquitectura
VLIW propuesta en el enunciado, tal y como se muestra en la Tabla 13.
# SLOT 1 SLOT 2
1 lw r1, a lw r2, b
add r3, r0,
2
r0
3
p1, p2 cmp.ge
4
r1, r2
(p1) p1, p2 cmp.ge
5
r2, r0
6 (p2) p2 cmp.lt r2, r0
7 (p2) p2 cmp.lt r1, r2
(p1) addi r3, r0, (p2) addi r3, r0,
8
#1 #2
9 sw r3, x
Solución
La Figura 5 muestra un posible organigrama para el código del enunciado.
Inic
io
Si No
¿a > b?
p1
Si No
¿a > c?
p
Si 2 No
¿a < b?
p
p Si No
4
3 ¿a < c?
x2*x p
5
x4*x
Fin
Figura 5. Organigrama del problema 6.
Teniendo en cuenta estas dependencias RAW, y que hay que incluir un ciclo
entre cada dos instrucciones con riesgos RAW, podríamos formar las
instrucciones VLIW que muestra la Tabla 14. El gran número de slots vacíos
se debe a la cadena de dependencias existente entre las instrucciones (1),
(2), (8), (9), (10), (11), (13) y (14).
Solución
El realizar un organigrama que refleje el comportamiento del código ayuda
bastante a la resolución de este tipo de problemas, sobre todo a la hora de
decidir qué predicados se deben utilizar y dónde hay que colocarlos. Un
posible organigrama para este problema podría ser el que indica la Figura 6.
Inici
o
Si No
¿a >
b?
p
Si 2 No
¿a >
c?
p p
1 Si No
xx*2 3
¿a <
b?
p
Si No
4
¿a >
p c?
5
xx/2
Fin
Una vez diseñado el organigrama, hay que colocar un predicado en cada una
de las instrucciones que deban estar vigiladas, es decir que dependan de
alguna condición, y tras esto, la traducción a código es directa:
if (x > 3)
{
y = x;
x = x / 2;
}
else if ((x > 0) && (x < 1))
{
y = – x;
x = 2 * x;
}
Solución
Como en el enunciado nos indican que la secuencia de instrucciones debe
quedar sin ningún salto, debemos predicar las instrucciones que contiene en
su interior. La Figura 7 muestra el organigrama del programa una vez que se
han predicado las instrucciones. De este organigrama se puede derivar el
siguiente código ensamblador:
lw r5, x ; r5 = x
p1, p2 cmp.gt r5, r3 ; p1 = 1 si x > 3
p3 cmp.ne r0, r0 ; p3 = 0
p4 cmp.ne r0, r0 ; p4 = 0
(p1) sw r5, y ; y=x
(p1) sra r6, r5, r1 ; r6 = x / 2
(p1) sw r6, x ; x = r6
(p2) p3 cmp.gt r5, r0 ; p3 = 1 si x > 0
(p3) p4 cmp.lt r5, r1 ; p4 = 1 si x < 1
(p4) sub r7, r0, r5 ; r7 = –x
(p4) sw r7, y ; y = –x
(p4) sll r8, r5, r1 ; r8 = 2*x
(p4) sw r8, x ; x = r8
Inicio
Si No
p ¿x > 3?
p2
1 Si
yx N
¿x > 0?
o
xx/2
p
N 3 Si
¿x < 1?
o
p4
y–x
x 2*x
Fin
A partir de este código, sólo nos queda reorganizar el código respetando las
dependencias de datos para construir las instrucciones VLIW, tal y como
muestra la Tabla 16.
Solución
Como en el enunciado nos indican que la secuencia de instrucciones debe
quedar sin ningún salto, debemos desenrollar el bucle y predicar las
instrucciones que contiene en su interior. La Figura 8 muestra el
organigrama del programa una vez que se ha desenrollado el bucle,
destacando los predicados que se usarán para evitar el uso de instrucciones
de salto. A continuación se muestra el código ensamblador derivado del
organigrama:
Inicio
Si No
p ¿x[0] >
2? p
1y[0] x [0] Si No
p ¿x [0] > 2
x[0] 3 * x [0] 3
y[0] – x [0] 0?
x [0] 5 * x [0]
Si No
p ¿x [1] >
p
4y [1] x [1] 2?
Si 5 No
p ¿x [1] >
x [1] 3 * x [1] 6
y[1] – x [1] 0?
x [1] 5* x [1]
Fin
lw r1, x ; r1 x[0]
subi r2, r1, #2 ; r2 x[0] – 2
p1, p2 cmp.gt r2, r0 ; p1 1 si x[0] > 2
p3 cmp.ne r0, r0 ; p3 0
(p1) sw r1, y ; y[0] x[0]
(p1) mult r3, r1, r13 ; r3 3*x[0]
(p1) sw r3, x ; x[0] 3*x[0]
(p2) p3 cmp.gt r1, r0 ; p3 1 si x[0] > 0
(p3) sub r4, r0, r1 ; r4 –x[0]
(p3) sw r4, y ; y[0] –x[0]
(p3) mult r5, r1, r15 ; r5 5*x[0]
(p3) sw r5, x ; x[0] 5*x[0]
Tras desenrollar e introducir las operaciones con predicados, sólo nos queda
reorganizar el código respetando las dependencias de datos para construir
las instrucciones VLIW. El resultado se muestra en la Tabla 17.
# SLOT 1 SLOT 2 SLOT 3
p3 cmp.ne
1 lw r1, x lw r6, x+4
r0, r0
p6 cmp.ne subi r2, r1, subi r7, r6,
2
r0, r0 #2 #2
addi r13, r0, addi r15, r0,
3 p1, p2 cmp.gtr2, r0
#3 #5
(p1) mult r3, r1,
4 p4, p5 cmp.gtr7, r0 (p1) sw r1, y
r13
(p4) mult r8, r6,
5 (p2) p3 cmp.gtr1, r0 (p4) sw r6, y+4
r13
6 (p5) p6 cmp.gtr6, r0 (p1) sw r3, x (p4) sw r8, x+4
(p3) sub r4, r0, (p6) sub r9, r0, (p3) mult r5, r1,
7
r1 r6 r15
(p6) mult r10, r6,
8 (p3) sw r4, y (p6) sw r9, y+4
r15
(p6) sw r10,
9 (p3) sw r5, x
x+4
if ((x[0] % 2) == 0)
{
for (i =1 ; i < 3 ; i++)
{
if ((x[i] % 2) == 0)
x[i] = 2 * x[i];
else if (x[0] < 0)
x[i] = 0;
}
}
Solución
Como en el enunciado nos indican que la secuencia de instrucciones debe
quedar sin ningún salto, debemos desenrollar el bucle y predicar las
instrucciones que contiene en su interior. El código en ensamblador derivado
del bucle, sería el siguiente:
p5 cmp.ne r0, r0 ; p5 = 0
p6 cmp.ne r0, r0 ; p6 = 0
p7 cmp.ne r0, r0 ; p7 = 0
Tras desenrollar e introducir las operaciones con predicados, solo nos queda
reorganizar el código respetando las dependencias de datos para construir
las instrucciones VLIW. El resultado se muestra en la Tabla 18.
# SLOT 1 SLOT 2
1 p2 cmp.ne r0, r0 lw r1, x
2 p3 cmp.ne r0, r0 andi r2, r1, #1
3 p1 cmp.eq r2, r0
4 p4 cmp.ne r0, r0 (p1) lw r3, x+4
5 p5 cmp.ne r0, r0 (p1) lw r5, x+8
6 p6 cmp.ne r0, r0 (p1) andi r4, r3, #1
7 (p1) p2, p3 cmp.eq r4, r0 (p1) andi r6, r5, #1
8 (p1) p5, p6 cmp.eq r6, r0 (p2) slli r3, r1, #1
9 p7 cmp.ne r0, r0 (p5) slli r5, r1, #1
10 (p3) p4 cmp.lt r1, r0 (p2) sw r3, x+4
11 (p6) p7 cmp.lt r1, r0 (p5) sw r5, x+8
12 (p4) sw r0, x+4 (p7) sw r0, x+8
Solución
Como el código está compuesto por un bucle que itera dos veces y se nos
dice en el enunciado que no debe haber instrucciones de salto en la solución,
será necesario desenrollar el bucle dos veces. Cada una de las iteraciones del
bucle seguirá el organigrama mostrado en la Figura 9, que nos ayudará a
escribir el código con predicados que se muestra a continuación:
Inicio
Si
¿x[i]
> 0?
p
Si 1
¿x[i] No
< a?
No
p2
Si
¿x[i]
> 4?
No
Si
¿x[i] <
p3 b? p4
x[i] = 2 * x[i] = 4
No
x[i]
Fin
; Inicializacion
lw r1, a ; r1 = a
lw r2, b ; r2 = b
addi r3, r0, #4 ; r3 = 4
; Primera iteración
lw r4, x ; r4 = x[0]
p1, p2 cmp.gt r4, r0 ; p1 = 1 si x[0] >0
p3 cmp.ne r0, r0 ; p3 = 0
p4 cmp.ne r0, r0 ; p4 = 0
(p1) p3, p2 cmp.lt r4, r1 ; p3 = 1 si x[0] <a
(p2) p4 cmp.gt r4, r3 ; p4 = 1 si x[0] >4
(p2) p4 cmp.lt r4, r2 ; p4 = 1 si x[0] <b
(p3) add r4, r4, r4 ; r4 = 2 * x[0]
(p4) add r4, r0, r3 ; r4 = 4
sw r4, x ; x[0] = r4
; Segunda iteración
lw r5, x+4 ; r5 = x[1]
p5, p6 cmp.gt r5, r0 ; p5 = 1 si x[1] >0
p7 cmp.ne r0, r0 ; p7 = 0
p8 cmp.ne r0, r0 ; p8 = 0
(p5) p7, p6 cmp.lt r5, r1 ; p7 = 1 si x[1] <a
(p6) p8 cmp.gt r5, r3 ; p8 = 1 si x[1] >4
(p6) p8 cmp.lt r5, r2 ; p8 = 1 si x[1] <b
(p7) add r5, r5, r5 ; r5 = 2 * x[1]
(p8) add r5, r0, r3 ; r5 = 4
sw r5, x+4 ; x[1] = r5
Una vez que está escrito el código, sólo nos falta planificarlo en los dos slots
del procesador cumpliendo las restricciones que nos indican en el enunciado,
tal y como muestra la Tabla 19.
# SLOT 1 SLOT 2
p3 cmp.ne
1 lw r4, x
r0, r0
2 p1, p2 cmp.gtr4, r0 lw r5, x+4
3 p5 ,p6 cmp.gtr5, r0 lw r1, a
p7 cmp.ne
4 lw r2, b
r0, r0
5 (p1) p3, p2 cmp.lt r4, r1 addi r3, r0, #4
6 (p5) p7, p6 cmp.lt r5, r1 (p3) add r4, r4, r4
p4 cmp.ne
7 (p7) add r5, r5, r5
r0, r0
8 (p2) p4 cmp.gtr4, r3
9 (p2) p4 cmp.lt r4, r2
p8 cmp.ne
10 (p4) add r4, r0, r3
r0, r0
11 (p6) p8 cmp.gtr5, r3 sw r4, x
12 (p6) p8 cmp.lt r5, r2
13 (p8) add r5, r0, r3
14 sw r5, x+4
Solución
La primera aproximación a la solución definitiva consistirá en escribir un
programa sencillo que resuelva el problema. El código en ensamblador
derivado del bucle, sería el siguiente:
inicio: lw r1, n ; r1 = n
add r2, r0, r0 ; r2 = 0 (desplazamiento para
recorrer x e y)
bucle: lw r3, x(r2) ; r3 = x[i]
p1, p2 cmp.lt r3, r0 ; p1 = 1 si x[i] < 0
(p1) add r4, r3, r0 ; y = 0 si x[i] < 0
(p2) mult r4, r3, r3 ; y = x[i] * x[i] si x[i] ≥ 0
sw r4, y(r2) ; almaceno y(i)
addui r2, r2, #4 ; incremento el
desplazamiento
subi r1, r1, #1 ; queda un elemento menos
p3 cmp.gt r1, r0 ; p3 = 1 si quedan elementos
(p3) jmp bucle ; siguiente iteración (si i < n)
if (a == 0)
a = b;
else
a = a + 2;
Solución
El código ensamblador para esta sentencia, sin utilizar especulación podría
ser:
lw r3, a ; r3 = a
bnez r3, else ; Saltamos a else si a != 0
if: lw r3, b ; r3 = b
j fin ; Saltamos a fin para almacenar el resultado
Tabla 24. Ejecución de la rama if del código sin especulación para el problema
13.
Tabla 25. Ejecución de la rama else del código sin especulación para el
problema 13.
lw r3, a ; r3 = a
lw r4, b ; r4 = b
beqz r3, fin ; Si a es igual a 0, saltamos a fin para
almacenar el resultado
addi r4, r3, #2 ; r4 = a + 2
fin: sw r4, a ; Almacenamos el resultado en a
Tabla 28. Ejecución de la rama else del código con especulación para el
problema 13.
p
Tno_espec 3p 9
S p
Tespec p 9 p
S 0 1 S p S 1 1.5
Como se asume que la variable a será casi siempre igual a cero, la ganancia
tenderá a 1.5. De todas formas, en el peor de los casos, en el que la variable
a nunca tome el valor cero, el tiempo de ejecución no empeoraría, por lo que
esta optimización es aconsejable en cualquier caso, ya que en el peor caso no
empeora y en el resto consigue un tiempo de ejecución menor.
14. Suponga un procesador VLIW que puede codificar tres operaciones
por instrucción con las restricciones que indica la Tabla 29. El
procesador puede utilizar predicados con cualquier instrucción.
Aunque en el caso de utilizarlos, una instrucción con la ALU o de
acceso a memoria incrementa en un ciclo su latencia. Esos predicados
se establecen a partir de los resultados de las instrucciones de
comparación (cmp) con el formato (p) p1, p2 cmp.cnd rx, ry donde
cnd es la condición que se comprueba entre los registros rx y ry (lt,
ge, eq, ne,…). Si la condición es verdadera p1 = 1 y p2 = 0, y si es
falsa, p1 = 0 y p2 = 1. La instrucción sólo se ejecuta si el predicado
p = 1 (habrá sido establecido por otra instrucción de comparación).
También existen instrucciones de comparación con el formato
(p) p1 cmp.cnd rx, ry donde p1 = 1 si la condición es verdadera y
p1 = 0 si es falsa. Si una instrucción no tiene el predicado (p), se
entiende que se ejecuta siempre.
UNIDAD
LATENCIA OP1 OP2 OP3 OPERACIONES REALIZADAS
FUNCIONAL
Comparaciones, sumas y
restas
ALU 1 X X X
con enteros y operaciones
lógicas
Operaciones aritméticas con
FP 4 X
números en coma flotante
Memoria 3 X X Cargas y almacenamientos
Saltos condicionales e
Saltos 3 X
incondicionales
Solución
Sin utilizar procesamiento especulativo ni predicados, el código máquina
puede ser el siguiente:
Tabla 30. Código VLIW sin especulación y sin predicados para el problema 14.
Tabla 31. Código VLIW sin especulación y con predicados para el problema
14.
Tabla 32. Código VLIW con especulación y sin predicados para el problema
14.
Por último, se pueden ahorrar la mitad de los saltos del programa si, además
de especulación, se utilizan instrucciones con predicado. En este caso, se
obtendría el siguiente código. La Tabla 33 muestra su versión VLIW (con un
33% de slots vacíos):
Tabla 33. Código VLIW con especulación y con predicados para el problema
14.
Una vez obtenidos los códigos VLIW para cada una de las situaciones
propuestas en el problema, pasamos a estimar el tiempo de ejecución de cada
una de ellas. Para el primer caso, tenemos que evaluar los tiempos de
ejecución del programa para las dos partes del if. Si a[i] es cero, se tendría la
ejecución mostrada en la Tabla 34, mientras que en cualquier otro caso, se
obtendrían la que muestra la Tabla 35. Asumiendo que la probabilidad de que
a[i] = 0 es p = 0.75, el tiempo medio de ejecución será:
Tabla 35. Ejecución del código de la Tabla 30 suponiendo que a[i] no es cero.
T2 n 7n 1ciclos
Tabla 37. Ejecución del código de la Tabla 32 suponiendo que a[i] es cero.
Tabla 38. Ejecución del código de la Tabla 32 suponiendo que a[i] no es cero.
T4 n 7n 1ciclos
Solución
Lo primero que vamos a hacer es escribir el programa usando predicados:
mult r1, r2, r3
add r4, r5, r1
p1 cmp.ne r4, r0
(p1) lw r6, dato
(p1) add r7, r4, r6
(p1) mult r2, r1, r7
sub r8, r1, r4
mult r1, r8, r2
sw resul, r1
#. OP1 OP2
1 mult r1, r2, r3
2
3 add r4, r5, r1
p1 cmp.ne r4,
4 sub r8, r1, r4
r0
5 (p1) lw r6, dato
6
7
8
9
10 (p1) add r7, r4, r6
11 (p1) mult r2, r1, r7
12
13 mult r1, r8, r2
14
15 sw resul, r1
#. OP1 OP2
1 lw r6, dato
2
3
4
5
6 add r7, r4, r6
7 mult r2, r1, r7
8
9 mult r1, r8, r2
10
11 sw resul, r1
Tabla 42. Rutina de reparación para el código VLIW con especulación para el
problema 15.