mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
23d333c090
This change includes many bug fixes, for the NT polyfills, strings, memory, boot, and math libraries which were discovered by adding more tools for recreational programming, such as PC emulation. Lemon has also been vendored because it works so well at parsing languages.
85 lines
3.3 KiB
C
85 lines
3.3 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ This program is free software; you can redistribute it and/or modify │
|
|
│ it under the terms of the GNU General Public License as published by │
|
|
│ the Free Software Foundation; version 2 of the License. │
|
|
│ │
|
|
│ This program is distributed in the hope that it will be useful, but │
|
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
|
│ General Public License for more details. │
|
|
│ │
|
|
│ You should have received a copy of the GNU General Public License │
|
|
│ along with this program; if not, write to the Free Software │
|
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
|
│ 02110-1301 USA │
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
#include "third_party/xed/x86.h"
|
|
#include "tool/build/lib/address.h"
|
|
#include "tool/build/lib/endian.h"
|
|
#include "tool/build/lib/modrm.h"
|
|
#include "tool/build/lib/throw.h"
|
|
|
|
uint8_t *GetSegment(struct Machine *m, uint32_t rde, int s) {
|
|
switch (s & 7) {
|
|
case 0:
|
|
return m->es;
|
|
case 1:
|
|
return m->cs;
|
|
case 2:
|
|
return m->ss;
|
|
case 3:
|
|
return m->ds;
|
|
case 4:
|
|
return m->fs;
|
|
case 5:
|
|
return m->gs;
|
|
case 6:
|
|
case 7:
|
|
OpUd(m, rde);
|
|
default:
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
uint64_t AddSegment(struct Machine *m, uint32_t rde, uint64_t i, uint8_t s[8]) {
|
|
if (!Sego(rde)) {
|
|
return i + Read64(s);
|
|
} else {
|
|
return i + Read64(GetSegment(m, rde, Sego(rde) - 1));
|
|
}
|
|
}
|
|
|
|
uint64_t DataSegment(struct Machine *m, uint32_t rde, uint64_t i) {
|
|
return AddSegment(m, rde, i, m->ds);
|
|
}
|
|
|
|
uint64_t AddressSi(struct Machine *m, uint32_t rde) {
|
|
switch (Eamode(rde)) {
|
|
case XED_MODE_LONG:
|
|
return DataSegment(m, rde, Read64(m->si));
|
|
case XED_MODE_REAL:
|
|
return DataSegment(m, rde, Read16(m->si));
|
|
case XED_MODE_LEGACY:
|
|
return DataSegment(m, rde, Read32(m->si));
|
|
default:
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
uint64_t AddressDi(struct Machine *m, uint32_t rde) {
|
|
uint64_t i = Read64(m->es);
|
|
switch (Eamode(rde)) {
|
|
case XED_MODE_LONG:
|
|
return i + Read64(m->di);
|
|
case XED_MODE_REAL:
|
|
return i + Read16(m->di);
|
|
case XED_MODE_LEGACY:
|
|
return i + Read32(m->di);
|
|
default:
|
|
unreachable;
|
|
}
|
|
}
|