LoongArch LBT Basics
LBT (LoongArch Binary Translation) is a set of instructions for emulating x86, ARM, and MIPS instruction sets. It provides hardware-accelerated flag manipulation, x87 FPU stack management, and conditional execution primitives.
Registers
5 dedicated registers shared with the floating-point unit:
| Register | Purpose |
|---|---|
| LBT0–LBT3 | Scratch registers (GPR save/restore) |
| LBT4 | High 32 bits: x87 FTOP, Low 32 bits: EFLAGS |
Scratch registers are accessible via:
$scr0= LBT0$scr1= LBT1$scr2= LBT2$scr3= LBT3
// movgr2scr $scrd, $rj
movgr2scr(scrd, rj) {
SCR[scrd] = GPR[rj];
}
// movscr2gr $rd, $scrj
movscr2gr(rd, scrj) {
GPR[rd] = SCR[scrj];
}
jiscr
// jiscr0 imm
jiscr0(imm) {
PC = SCR[0] + imm;
}
// jiscr1 imm
jiscr1(imm) {
SCR[0] = PC;
PC = SCR[1] + imm;
}
x86 EFLAGS
EFLAGS bits are stored in the low 32 bits of LBT4:
| Bit | Flag | Position Shift |
|---|---|---|
| CF | 0x001 | 0 |
| PF | 0x004 | 2 |
| AF | 0x010 | 4 |
| ZF | 0x040 | 6 |
| SF | 0x080 | 7 |
| OF | 0x800 | 11 |
All flags set: 0x8d5
PF (Parity Flag) is set when the least significant byte of the result has an even number of 1 bits:
bool PF = parity_even((uint8_t)result);
ARMFLAGS
ARM condition flags (N, Z, C, V) are mapped to the corresponding x86 EFLAGS bits in LBT4:
| ARM Flag | x86 Equivalent | Bit Position |
|---|---|---|
| N (Negative) | SF | 0x080 |
| Z (Zero) | ZF | 0x040 |
| C (Carry) | CF | 0x001 |
| V (Overflow) | OF | 0x800 |
Condition Codes
x86 Condition Codes
setx86j rd, cond evaluates the x86 condition cond against EFLAGS and stores 1 or 0 in rd.
| cond | Mnemonic | Condition |
|---|---|---|
| 0 | A / NBE | CF = 0 and ZF = 0 |
| 1 | AE / NB / NC | CF = 0 |
| 2 | B / C / NAE | CF = 1 |
| 3 | BE / NA | CF = 1 or ZF = 1 |
| 4 | E / Z | ZF = 1 |
| 5 | NE / NZ | ZF = 0 |
| 6 | G / NLE | ZF = 0 and SF = OF |
| 7 | GE / NL | SF = OF |
| 8 | L / NGE | SF != OF |
| 9 | LE / NG | ZF = 1 or SF != OF |
| 10 | S | SF = 1 |
| 11 | NS | SF = 0 |
| 12 | O | OF = 1 |
| 13 | NO | OF = 0 |
| 14 | P / PE | PF = 1 |
| 15 | NP / PO | PF = 0 |
ARM Condition Codes
setarmj rd, cond evaluates the ARM condition cond against ARMFLAGS and stores 1 or 0 in rd. These same condition codes govern all ARM instructions (the operation only executes when the condition holds).
| cond | Mnemonic | Condition |
|---|---|---|
| 0 | EQ | Z = 1 |
| 1 | NE | Z = 0 |
| 2 | CS / HS | C = 1 |
| 3 | CC / LO | C = 0 |
| 4 | MI | N = 1 |
| 5 | PL | N = 0 |
| 6 | VS | V = 1 |
| 7 | VC | V = 0 |
| 8 | HI | C = 1 and Z = 0 |
| 9 | LS | C = 0 or Z = 1 |
| 10 | GE | N = V |
| 11 | LT | N != V |
| 12 | GT | Z = 0 and N = V |
| 13 | LE | Z = 1 or N != V |
| 14 | AL | always |
| 15 | AL | always |
x87 FPU Emulation
FTOP (Stack Top Pointer)
The x87 FPU uses an 8-entry stack. FTOP (3-bit, stored in high 32 bits of LBT4) points to the current stack top. FPR register indices are remapped by TOP when TM mode is enabled.
// x86mftop $rd
x86mftop(rd) {
GPR[rd] = TOP;
}
// x86mttop imm
x86mttop(imm) {
TOP = imm;
}
// x86inctop (FINCSTP)
x86inctop() {
TOP = (TOP + 1) & 0x7;
}
// x86dectop (FDECSTP)
x86dectop() {
TOP = (TOP - 1) & 0x7;
}
TM (Translation Mode)
When TM is set, FPR indices 0-7 are offset by TOP:
// x86settm
x86settm() {
TM = 1;
}
// x86clrtm
x86clrtm() {
TM = 0;
}
mappedFPR(fpr) {
if (TM && fpr < 8) {
return FPR[(fpr + TOP) % 8];
} else {
return FPR[fpr];
}
}
LSX/LASX registers are not remapped.
x87 80-bit Extended Precision
x87 long double (80-bit) is stored across two FPRs:
| Part | Format | Register |
|---|---|---|
| Low 64 bits | J(bit 63) + fraction(bits 62:0) | fd |
| High 16 bits | sign(bit 15) + exponent(bits 14:0) | upper bits of paired register |
Conversion instructions:
fcvt.ld.d fd, fj— double → low 64 bits of extendedfcvt.ud.d fd, fj— double → high 16 bits of extendedfcvt.d.ld fd, fj, fk— extended → double
Tag Word
x86settag rd, imm1, imm2 manipulates the x87 tag word (stored in a GPR). The operation mode is encoded in imm1 % 8:
- 0: set bit (0→1 only), raises BTE on invalid transition
- 1: clear bit (1→0 only), raises BTE on invalid transition
- 2–4: check tag byte then modify, raises BTE on invalid state
MIPS Unaligned Memory
LBT provides MIPS-style unaligned load and store instructions for emulating ldl/ldr/stl/str:
ldl.w/ldl.d— load doubleword left: load left part of an unaligned value from memory, merge with existing bytes inrdldr.w/ldr.d— load doubleword right: load right part of an unaligned value from memory, merge with existing bytes inrdstl.w/stl.d— store doubleword left: store left part of an unaligned value to memorystr.w/str.d— store doubleword right: store right part of an unaligned value to memory
Instruction Groups
All LBT instruction groups are documented in the following pages:
- LBT Integer:
addu12i,adc,sbc,rotr,rotri,rcr,rcri - x86 Integer:
x86adc,x86add,x86inc,x86sbc,x86sub,x86dec,x86mul - x86 Logical:
x86and,x86or,x86xor - x86 Shift:
x86rcl,x86rcli,x86rcr,x86rcri,x86rotl,x86rotli,x86rotr,x86rotri,x86sll,x86slli,x86srl,x86srli,x86sra,x86srai - x86 FPU:
x86mftop,x86mttop,x86inctop,x86dectop,x86settm,x86clrtm,x86settag,fcvt.ud.d,fcvt.ld.d,fcvt.d.ld - x86 Misc:
setx86j,setx86loope,setx86loopne - ARM Integer:
armadd,armsub,armadc,armsbc - ARM Logical:
armand,armor,armxor,armnot - ARM Shift:
armsll,armsrl,armsra,armrotr,armslli,armsrli,armsrai,armrotri - ARM Misc:
armrrx,armmove,armmov,setarmj - LBT State Transfer:
movgr2scr,movscr2gr,x86mfflag,x86mtflag,armmfflag,armmtflag - LBT Jump:
jiscr0,jiscr1 - MIPS Memory:
ldl.d,ldl.w,ldr.w,ldr.d,stl.w,stl.d,str.w,str.d