Quote:
What about marking them with pseudo ops like "_name .proc" and ".endp _name".
I thought about this and the assembler handles something similar '_name .begin' and '.end _name'. For convenience though the double-dot is used as a synonym for '.end', it is shorter and easier to type. I was not so crazy as to rely on a ret instruction indicating the end of a routine. "()" is shorter and easier to type than "begin" or "proc". Dots are optional in the pseudo-ops for the assembler. Exactly what to use to mark the beginning and end of a function seems to vary from one assembler to the next.
The emulator is not going to be cycle exact, but it has fetch / decode and execute stages so there is some similarity to the hardware. I am reusing an emulator already in existence.
Busy day. Implemented the sync, mtbase and mfbase instructions.
Toying with the idea of having the base register used in an address calculation be specified as the low order four bits of an address value instead of the high order bits. Address bits 0 an on upwards would be specified in bits 4 and up.
ATM the base register to use is specified as the high order bits, an idea borrowed from the PowerPC segmentation, but for ANY1 the position of the base register spec changes depending on the number of address bits used to form an address. Some examples:
Currently: sto $a0,$A000C000 will store using the stack base register which is identified with the ‘A’ in the high order four bits of the address. This is for 32-bit addressing. For 24-bit addressing this would be: sto $a0,$A0C000. The processor’s address range is specified in control register zero. With the base register as the low order four bits these addresses would be specified as: sto $a0,$C000A. The issue with switching things is that it may reduce the number of bits available to encode an address in load / store instructions. The data base register was carefully chosen as base register #0 so that it would automatically be selected by addressing that assumes the high order bits are all zeros. Without using extended constants, load and store instruction support only an 11-bit displacement. I am not sure I wish to reduce this to 7 bits.
At startup the boot software initializes base registers for access to various sections. For instance, base register $b12 is loaded with the address of the rodata section. The use of base registers is spec’d in the ABI. Instead of using a global pointer register, data is referenced relative to a base register. Base register $15 is used for code and is automatically set along with the IP at reset.
I decided to reduce the base register shift amount to four bits from fourteen bits. This gives a much finer granularity for base registers. Having a finer granularity means less memory may be wasted. Rather than requiring sections to be aligned on 16kB boundaries they may now be aligned on 16B boundaries. Base registers control the access rights to memory and paging controls the visibility of memory.
In the future the base registers may be more than 64-bits wide, being split into base low and base high registers. This would allow an address space up to 128 bits.
**********
The performance of the assembler was decreased with the use of the GetName() method from the NameTable class. Rather than invoke the method GetName() the assembler was modified to go directly to the NameTable’s class data variable nametext[]. Going directly at the variable improved performance by about 25%.
It is a full minute faster to do this:
Code:
int icmp (const void *m1, const void *m2)
{
SYM *n1; SYM *n2;
n1 = (SYM *)m1;
n2 = (SYM *)m2;
if (n1->name==0) return 1;
if (n2->name==0) return -1;
return (strcmp(&nmTable.nametext[n1->name], &nmTable.nametext[n2->name]));
}
As opposed to:
Code:
int icmp (const void *m1, const void *m2)
{
SYM *n1; SYM *n2;
n1 = (SYM *)m1;
n2 = (SYM *)m2;
if (n1->name==0) return 1;
if (n2->name==0) return -1;
return (strcmp(nmTable.GetName(n1->name), nmTable.GetName(n2->name)));
}
Normally one would not want to access internal class variables directly, the preference is to use an accessor method, but in this case it improves performance substantially.