Skip to content

Commit d6b316d

Browse files
committed
simx86: move codegen part of Move2Tree() to ProduceCode()
This way many fields of IMeta are no longer needed, since we can directly use a newly allocated TNode * in ProduceCode().
1 parent 52845e7 commit d6b316d

File tree

4 files changed

+71
-105
lines changed

4 files changed

+71
-105
lines changed

src/base/emu-i386/simx86/codegen.c

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,28 @@ static void OptimizeCode(IMeta *I)
401401
}
402402
}
403403

404-
static unsigned char *ProduceCode(unsigned int PC, IMeta *I0)
404+
/*
405+
* The intermediate code and its associated structures are in the InstrMeta
406+
* array. We allocate a buffer and generate the code, then
407+
* we copy the sequence data from the head element of InstrMeta. In this
408+
* process we lose all the correspondences between original code and compiled
409+
* code addresses. At the end, we reset InstrMeta to prepare for a new
410+
* sequence.
411+
*/
412+
static TNode *ProduceCode(unsigned int PC, IMeta *I0)
405413
{
406414
int i,j,mall_req;
407415
unsigned char *cp, *cp1, *BaseGenBuf, *CodePtr;
408416
size_t GenBufSize;
417+
Addr2Pc *ap;
418+
int nap = CurrIMeta + 2;
419+
420+
TNode *G = calloc(1, sizeof(TNode) + sizeof(Addr2Pc) * nap);
421+
assert(G);
422+
423+
/* transfer info from first node of the Meta list to our new node */
424+
G->key = I0->npc;
425+
G->seqnum = nap - 1;
409426

410427
if (debug_level('e')>1) {
411428
e_printf("---------------------------------------------\n");
@@ -426,20 +443,34 @@ static unsigned char *ProduceCode(unsigned int PC, IMeta *I0)
426443
BaseGenBuf = AllocGenCodeBuf(mall_req);
427444
/* actual code buffer starts from here */
428445
CodePtr = BaseGenBuf;
429-
I0->daddr = 0;
430446
if (debug_level('e')>1)
431447
e_printf("CodeBuf=%p siz %zd\n",BaseGenBuf,GenBufSize);
432448

433-
for (i=0; i<=CurrIMeta; i++) {
449+
/* setup structures for inter-node linking */
450+
G->clink_nt.link = G->clink_t.link = 0;
451+
/* setup source/xlated instruction offsets in G->meta */
452+
for (i=0, ap=G->meta; i<=CurrIMeta; i++, ap++) {
434453
IMeta *I = &I0[i];
435454
if (i < CurrIMeta)
436455
OptimizeCode(I);
437456
cp = cp1 = CodePtr;
438-
I->daddr = cp - BaseGenBuf;
439457
for (j=0; j<I->ngen; j++) {
440458
IGen *IG = &I->gen[j];
441-
if (IG->op == JMP_LINK)
442-
IG->p2 = CodePtr - BaseGenBuf;
459+
if (IG->op == JMP_LINK) {
460+
unsigned int link = CodePtr - BaseGenBuf;
461+
assert(link); // because TheCPU.eip is set first, this can never be 0
462+
if (j < I->ngen - 1) {
463+
G->clink_nt.link = link;
464+
G->clink_nt.target = IG->p0;
465+
}
466+
else {
467+
assert(j == I->ngen - 1);
468+
G->clink_t.link = link;
469+
G->clink_t.target = IG->p0;
470+
}
471+
if ((debug_level('e')>3))
472+
dbug_printf("Link %d: %x:%08x\n",IG->op,link,IG->p0);
473+
}
443474
CodePtr = CodeGen(CodePtr, BaseGenBuf, IG);
444475
if (CodePtr-cp1 > MAX_GEND_BYTES_PER_OP) {
445476
dosemu_error("Generated code (%zd bytes) overflowed into buffer, please "
@@ -455,33 +486,43 @@ static unsigned char *ProduceCode(unsigned int PC, IMeta *I0)
455486
}
456487
cp1 = CodePtr;
457488
}
458-
I->len = CodePtr - cp;
459-
I0->flags |= I->flags;
489+
G->flags |= I->flags;
460490
if (debug_level('e')>3) {
461491
if (debug_level('e')>4) {
462492
e_printf("Metadata %03d PC=%08x flags=%x(%x) ng=%d\n",
463-
i,I->npc,I->flags,I0->flags,I->ngen);
493+
i,I->npc,I->flags,G->flags,I->ngen);
464494
}
465-
GCPrint(cp, BaseGenBuf, I->len);
495+
GCPrint(cp, BaseGenBuf, CodePtr - cp);
466496
}
497+
ap->daddr = cp - BaseGenBuf;
498+
ap->dnpc = I->npc - I0->npc;
499+
if (debug_level('e')>8)
500+
e_printf("Pmeta %03d: %p(%04x):%08x(%04x)\n",i,
501+
cp,ap->daddr,I->npc,ap->dnpc);
467502
}
503+
G->len = ap->daddr = CodePtr - BaseGenBuf;
504+
if (debug_level('e')>8) e_printf("Pmeta %03d: (%04x)\n",i,G->len);
505+
506+
CurrIMeta = -1;
507+
memset(I0,0,sizeof(IMeta));
508+
468509
if (debug_level('e')>1)
469510
e_printf("Size=%td guess=%zd\n",(CodePtr-BaseGenBuf),GenBufSize);
470511
/**/ if ((CodePtr-BaseGenBuf) > GenBufSize) leavedos_main(0x535347);
471-
I0->seqlen = PC - I0->npc;
512+
G->seqlen = PC - G->key;
472513

473514
if (debug_level('e')>1)
474515
e_printf("---------------------------------------------\n");
475516

476-
I0->totlen = CodePtr - BaseGenBuf;
477-
478517
/* shrink buffer to what is actually needed */
479-
mall_req = I0->totlen;
518+
mall_req = G->len;
480519
ShrinkGenCodeBuf(BaseGenBuf, mall_req);
520+
481521
if (debug_level('e')>3)
482-
e_printf("Seq len %#x:%#x\n",I0->seqlen,I0->totlen);
522+
e_printf("Seq len %#x:%#x\n",G->seqlen,G->len);
483523

484-
return BaseGenBuf;
524+
G->addr = BaseGenBuf;
525+
return G;
485526
}
486527

487528

@@ -513,7 +554,6 @@ TNode *Close(unsigned int PC, unsigned int Interp_LONG_CS, int mode,
513554
{
514555
IMeta *I0;
515556
TNode *G;
516-
unsigned char *GenCodeBuf;
517557

518558
assert (CurrIMeta >= 0);
519559

@@ -524,13 +564,13 @@ TNode *Close(unsigned int PC, unsigned int Interp_LONG_CS, int mode,
524564
e_printf("==== Closing sequence at %08x\n", PC);
525565
}
526566

527-
GenCodeBuf = ProduceCode(PC, I0);
567+
G = ProduceCode(PC, I0);
528568

529569
NodesParsed++;
530570
#if PROFILE
531571
if (debug_level('e')) TotalNodesParsed++;
532572
#endif
533-
G = Move2Tree(I0, GenCodeBuf); /* when is G==NULL? */
573+
Move2Tree(G);
534574
/* InstrMeta will be zeroed at this point */
535575
/* mprotect the page here; a page fault will be triggered
536576
* if some other code tries to write over the page including

src/base/emu-i386/simx86/interp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static TNode *DoClose(unsigned int PC, unsigned int Interp_LONG_CS, int mode,
103103
unsigned int P0 = InstrMeta[0].npc;
104104
TNode *G, *nextG = NULL;
105105

106-
assert(InstrMeta[0].ncount > 0);
106+
assert(CurrIMeta >= 0);
107107
/* If the code doesn't terminate with a jump/loop instruction
108108
* it still lacks the tail code; add it here */
109109
IMeta *GL = &InstrMeta[CurrIMeta];

src/base/emu-i386/simx86/trees.c

Lines changed: 9 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,34 +1072,16 @@ static int TraverseAndClean(void)
10721072

10731073
/*
10741074
* Add a node to the collector tree.
1075-
* The code is linearly stored in the CodeBuf and its associated structures
1076-
* are in the InstrMeta array. We allocate a buffer and copy the code, then
1077-
* we copy the sequence data from the head element of InstrMeta. In this
1078-
* process we lose all the correspondences between original code and compiled
1079-
* code addresses. At the end, we reset both CodeBuf and InstrMeta to prepare
1080-
* for a new sequence.
10811075
*/
1082-
TNode *Move2Tree(IMeta *I0, unsigned char *GenCodeBuf)
1076+
void Move2Tree(TNode *nG)
10831077
{
10841078
#if PROFILE >= 2
10851079
hitimer_t t0 = 0;
10861080
if (debug_level('e')) t0 = GETTSC();
10871081
#endif
1088-
int key;
1089-
int nap;
10901082
TNode **found;
1091-
IMeta *I;
1092-
IGen *IG;
1093-
int i, apl=0;
1094-
Addr2Pc *ap;
1095-
unsigned int op;
1096-
1097-
key = I0->npc;
1098-
1099-
nap = I0->ncount + 1;
1100-
TNode *nG = calloc(1, sizeof(TNode) + sizeof(Addr2Pc) * nap);
1101-
assert(nG);
1102-
nG->key = key;
1083+
1084+
nG->alive = NODELIFE(G);
11031085
pthread_mutex_lock(&trees_mtx);
11041086
found = avltr_probe(nG);
11051087
/* since existing code was invalidated in DoClose(),
@@ -1108,73 +1090,24 @@ TNode *Move2Tree(IMeta *I0, unsigned char *GenCodeBuf)
11081090
#if !defined(SINGLESTEP)&&!defined(SINGLEBLOCK)
11091091
if (debug_level('e')>2) {
11101092
e_printf("New TNode %d at=%p key=%08x\n",
1111-
ninodes,nG,key);
1093+
ninodes,nG,nG->key);
11121094
if (debug_level('e')>3)
11131095
e_printf("Header: len=%d n_ops=%d PC=%08x\n",
1114-
I0->totlen, I0->ncount, I0->npc);
1096+
nG->len, nG->seqnum, nG->key);
11151097
}
11161098
#endif
1117-
nG = *found;
1118-
nG->alive = NODELIFE(nG);
1119-
pthread_mutex_unlock(&trees_mtx);
1120-
1121-
/* transfer info from first node of the Meta list to our new node */
1122-
nG->seqlen = I0->seqlen;
1123-
nG->seqnum = I0->ncount;
11241099
#if PROFILE
11251100
if (debug_level('e')) if (nG->len > MaxNodeSize) MaxNodeSize = nG->len;
11261101
#endif
1127-
nG->len = I0->totlen;
1128-
nG->flags = I0->flags;
1129-
__atomic_store_n(&findtree_cache[key&FINDTREE_CACHE_HASH_MASK], nG,
1130-
__ATOMIC_RELAXED);
1131-
1132-
nG->addr = GenCodeBuf;
1133-
1134-
/* setup structures for inter-node linking */
1135-
nG->clink_nt.link = nG->clink_t.link = 0;
1136-
IG = &I0[CurrIMeta].gen[I0[CurrIMeta].ngen-1];
1137-
op = IG->op;
1138-
if (op == JMP_LINK) {
1139-
assert(IG->p2); // because TheCPU.eip is set first, this can never be 0
1140-
nG->clink_t.link = IG->p2;
1141-
nG->clink_t.target = IG->p0;
1142-
if (I0[CurrIMeta].ngen > 1 && (IG-1)->op == JMP_LINK) {
1143-
IG--;
1144-
assert(IG->p2);
1145-
nG->clink_nt.link = IG->p2;
1146-
nG->clink_nt.target = IG->p0;
1147-
}
1148-
if ((debug_level('e')>3))
1149-
dbug_printf("Link %d: %x:%08x\n",op,
1150-
nG->clink_nt.link,
1151-
(nG->clink_nt.link? nG->clink_nt.target:0));
1152-
}
1153-
1154-
/* setup source/xlated instruction offsets */
1155-
ap = nG->meta;
1156-
I = I0;
1157-
for (i=0; i<nG->seqnum; i++) {
1158-
ap->daddr = I->daddr;
1159-
apl = ap->daddr + I->len;
1160-
ap->dnpc = I->npc - I0->npc;
1161-
if (debug_level('e')>8)
1162-
e_printf("Pmeta %03d: %p(%04x):%08x(%04x)\n",i,
1163-
nG->addr+ap->daddr,ap->daddr,I->npc,ap->dnpc);
1164-
ap++, I++;
1165-
}
1166-
ap->daddr = apl;
1167-
if (debug_level('e')>8) e_printf("Pmeta %03d: (%04x)\n",i,apl);
1168-
11691102
#ifdef DEBUG_LINKER
11701103
CheckLinks();
11711104
#endif
1172-
CurrIMeta = -1;
1173-
memset(&InstrMeta[0],0,sizeof(IMeta));
1105+
pthread_mutex_unlock(&trees_mtx);
1106+
__atomic_store_n(&findtree_cache[nG->key&FINDTREE_CACHE_HASH_MASK], nG,
1107+
__ATOMIC_RELAXED);
11741108
#if PROFILE >= 2
11751109
if (debug_level('e')) AddTime += (GETTSC() - t0);
11761110
#endif
1177-
return nG;
11781111
}
11791112

11801113
void tree_gc(void)
@@ -1536,21 +1469,15 @@ int NewIMeta(int npc, int override)
15361469
we allow one more for the instruction following STI/POPss/MOVss */
15371470
if (CurrIMeta < MAXINODES-2+override) {
15381471
// add new opcode metadata
1539-
IMeta *I,*I0;
1472+
IMeta *I;
15401473

15411474
CurrIMeta++;
15421475
I = &InstrMeta[CurrIMeta];
15431476
if (CurrIMeta==0) { // no open code sequences
15441477
if (debug_level('e')>2) e_printf("============ Opening sequence at %08x\n",npc);
1545-
I0 = I;
1546-
}
1547-
else {
1548-
I0 = &InstrMeta[0];
15491478
}
15501479

1551-
I0->ncount += 1;
15521480
I->npc = npc;
1553-
15541481
I->ngen = 0;
15551482
I->flags = 0;
15561483
ret = 1;

src/base/emu-i386/simx86/trees.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ typedef struct _ianpc {
8080

8181
typedef struct _imeta {
8282
int npc;
83-
unsigned short ncount, flags, seqlen;
84-
unsigned int len, totlen, daddr;
83+
unsigned short flags;
8584
int ngen;
8685
IGen gen[NUMGENS];
8786
} IMeta;
@@ -148,7 +147,7 @@ typedef struct avltr_tree
148147
#define MINUS -1
149148

150149
TNode *FindTree(int key);
151-
TNode *Move2Tree(IMeta *I0, unsigned char *GenCodeBuf);
150+
void Move2Tree(TNode *G);
152151
void tree_gc(void);
153152

154153
void InitTrees(void);

0 commit comments

Comments
 (0)