## Manage module data relocation and instruction patch information.# dreloc: ref Ipatch;Ipatchtid: int; setIpatchtid(){ Ipatchtid = descid(1, 0, array [1] of { byte 0 });} ## Add an instruction patch directive to ip.# (flag == SAVEINST) <=> runtime relocation: Inst* needed later# (flag == !SAVEINST) <=> other: pinfo expected in sequential order# addIpatch(ip: ref Ipatch, i: ref Inst, operand: int, patchkind: int, flag: int){ j: int; if(ip.n >= ip.max) { oldmax := ip.max; ip.max += ALLOCINCR; newippinfo := array [ip.max] of int; for(j = 0; j < oldmax; j++) newippinfo[j] = ip.pinfo[j]; ip.pinfo = newippinfo; if(flag == SAVEINST) { newipi := array [ip.max] of ref Inst; for(j = 0; j < oldmax; j++) newipi[j] = ip.i[j]; ip.i = newipi; } } ip.pinfo[ip.n] = (i.pc << 8) | operand | patchkind; if(flag == SAVEINST) ip.i[ip.n] = i; ip.n += 1;} operand := array [] of { "?", "src", # PSRC >> 2 "dst", # PDST >> 2 "mid" # PMID >> 2}; mode := array [] of { "$x", # PIMM "x(reg)", # PSIND "n(x(reg))", # PDIND1 "x(n(reg))" # PDIND2}; ba: array of byte;nba: int;HIGHBIT: con byte 16r80; sizeba(sz: int){ if(sz > len ba) { newba := array [sz] of byte; for(i := 0; i < nba; i++) newba[i] = ba[i]; ba = newba; }} fillba(ip: ref Ipatch){ i: int; pclast, pcnext, delta, skip: int; sizeba(2*ip.n); pclast = 0; for(i = 0; i < ip.n; i++) { pcnext = ip.pinfo[i] >> 8; delta = pcnext-pclast; sizeba(nba + delta/1024 + 2); while(delta > 7) { if(delta > 1024) skip = 1024; else skip = delta & int 16rfffffff8; ba[nba++] = byte(256 - (skip >> 3)); delta -= skip; } ba[nba++] = byte((delta << 4) | (ip.pinfo[i] & 16rf)); pclast = pcnext; }} ## Write Ipatch information to .s file.# asmIpatch(off: int, ip: ref Ipatch){ i: int; reloff: int; # relative offset for array elements pc: int; if(ip == nil || ip.n == 0) return; fillba(ip); reloff = 0; asmarray(off, Ipatchtid, nba, reloff); pc = 0; for(i = 0; i < nba; i++) { bout.puts("\tbyte\t@mp+" + string reloff + "," + string ba[i]); if(int(ba[i] & HIGHBIT)) pc += (256 - int ba[i]) << 3; else pc += int ba[i] >> 4; bout.puts("\t# " + string pc); if(!int(ba[i] & HIGHBIT)) { bout.puts(", " + operand[(int ba[i] >> 2) & 16r3] + ", " + mode[int ba[i] & 16r3]); } bout.putc('\n'); reloff += 1; } bout.puts("\tapop\n"); ba = nil; nba = 0;} ## Write Ipatch information to .dis file.# disIpatch(off: int, ip: ref Ipatch){ i: int; reloff: int; # relative offset for array elements if(ip == nil || ip.n == 0) return; fillba(ip); disarray(off, Ipatchtid, nba); reloff = 0; for(i = 0; i < nba; i++) { disbyte(reloff, ba[i]); reloff += 1; } disapop(); ba = nil; nba = 0;} ## Add instruction patch information to dreloc.# addDreloc(i: ref Inst, operand: int, patchkind: int){ if(dreloc == nil) dreloc = ref Ipatch(0, 0, nil, nil); addIpatch(dreloc, i, operand, patchkind, !SAVEINST);} ## Write Dreloc information to .s file.# asmDreloc(off: int){ asmIpatch(off, dreloc);} ## Write Dreloc information to .dis file.# disDreloc(off: int){ disIpatch(off, dreloc);}
#
# Manage module data relocation and instruction patch information.
#
dreloc: ref Ipatch;
Ipatchtid: int;
setIpatchtid()
{
Ipatchtid = descid(1, 0, array [1] of { byte 0 });
}
#
# Add an instruction patch directive to ip.
# (flag == SAVEINST) <=> runtime relocation: Inst* needed later
# (flag == !SAVEINST) <=> other: pinfo expected in sequential order
#
addIpatch(ip: ref Ipatch, i: ref Inst, operand: int, patchkind: int, flag: int)
{
j: int;
if(ip.n >= ip.max) {
oldmax := ip.max;
ip.max += ALLOCINCR;
newippinfo := array [ip.max] of int;
for(j = 0; j < oldmax; j++)
newippinfo[j] = ip.pinfo[j];
ip.pinfo = newippinfo;
if(flag == SAVEINST) {
newipi := array [ip.max] of ref Inst;
for(j = 0; j < oldmax; j++)
newipi[j] = ip.i[j];
ip.i = newipi;
}
}
ip.pinfo[ip.n] = (i.pc << 8) | operand | patchkind;
if(flag == SAVEINST)
ip.i[ip.n] = i;
ip.n += 1;
}
operand := array [] of {
"?",
"src", # PSRC >> 2
"dst", # PDST >> 2
"mid" # PMID >> 2
};
mode := array [] of {
"$x", # PIMM
"x(reg)", # PSIND
"n(x(reg))", # PDIND1
"x(n(reg))" # PDIND2
};
ba: array of byte;
nba: int;
HIGHBIT: con byte 16r80;
sizeba(sz: int)
{
if(sz > len ba) {
newba := array [sz] of byte;
for(i := 0; i < nba; i++)
newba[i] = ba[i];
ba = newba;
}
}
fillba(ip: ref Ipatch)
{
i: int;
pclast, pcnext, delta, skip: int;
sizeba(2*ip.n);
pclast = 0;
for(i = 0; i < ip.n; i++) {
pcnext = ip.pinfo[i] >> 8;
delta = pcnext-pclast;
sizeba(nba + delta/1024 + 2);
while(delta > 7) {
if(delta > 1024)
skip = 1024;
else
skip = delta & int 16rfffffff8;
ba[nba++] = byte(256 - (skip >> 3));
delta -= skip;
}
ba[nba++] = byte((delta << 4) | (ip.pinfo[i] & 16rf));
pclast = pcnext;
}
}
#
# Write Ipatch information to .s file.
#
asmIpatch(off: int, ip: ref Ipatch)
{
i: int;
reloff: int; # relative offset for array elements
pc: int;
if(ip == nil || ip.n == 0)
return;
fillba(ip);
reloff = 0;
asmarray(off, Ipatchtid, nba, reloff);
pc = 0;
for(i = 0; i < nba; i++) {
bout.puts("\tbyte\t@mp+" + string reloff + "," + string ba[i]);
if(int(ba[i] & HIGHBIT))
pc += (256 - int ba[i]) << 3;
else
pc += int ba[i] >> 4;
bout.puts("\t# " + string pc);
if(!int(ba[i] & HIGHBIT)) {
bout.puts(", " + operand[(int ba[i] >> 2) & 16r3]
+ ", " + mode[int ba[i] & 16r3]);
}
bout.putc('\n');
reloff += 1;
}
bout.puts("\tapop\n");
ba = nil;
nba = 0;
}
#
# Write Ipatch information to .dis file.
#
disIpatch(off: int, ip: ref Ipatch)
{
i: int;
reloff: int; # relative offset for array elements
if(ip == nil || ip.n == 0)
return;
fillba(ip);
disarray(off, Ipatchtid, nba);
reloff = 0;
for(i = 0; i < nba; i++) {
disbyte(reloff, ba[i]);
reloff += 1;
}
disapop();
ba = nil;
nba = 0;
}
#
# Add instruction patch information to dreloc.
#
addDreloc(i: ref Inst, operand: int, patchkind: int)
{
if(dreloc == nil)
dreloc = ref Ipatch(0, 0, nil, nil);
addIpatch(dreloc, i, operand, patchkind, !SAVEINST);
}
#
# Write Dreloc information to .s file.
#
asmDreloc(off: int)
{
asmIpatch(off, dreloc);
}
#
# Write Dreloc information to .dis file.
#
disDreloc(off: int)
{
disIpatch(off, dreloc);
}