Rev 7597 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7597 | akron1 | 1 | (* |
2 | BSD 2-Clause License |
||
6613 | leency | 3 | |
7597 | akron1 | 4 | Copyright (c) 2018, 2019, Anton Krotov |
5 | All rights reserved. |
||
6613 | leency | 6 | *) |
7 | |||
8 | MODULE X86; |
||
9 | |||
7597 | akron1 | 10 | IMPORT CODE, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, mConst := CONSTANTS, MACHINE, CHL := CHUNKLISTS, PATHS; |
6613 | leency | 11 | |
7597 | akron1 | 12 | |
6613 | leency | 13 | CONST |
14 | |||
7597 | akron1 | 15 | eax = REG.R0; ecx = REG.R1; edx = REG.R2; |
6613 | leency | 16 | |
7597 | akron1 | 17 | al = eax; cl = ecx; dl = edx; ah = 4; |
6613 | leency | 18 | |
7597 | akron1 | 19 | ax = eax; cx = ecx; dx = edx; |
6613 | leency | 20 | |
7597 | akron1 | 21 | esp = 4; |
22 | ebp = 5; |
||
6613 | leency | 23 | |
7597 | akron1 | 24 | sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; |
6613 | leency | 25 | |
7597 | akron1 | 26 | je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H; |
6613 | leency | 27 | |
28 | |||
7597 | akron1 | 29 | CODECHUNK = 8; |
6613 | leency | 30 | |
31 | |||
32 | TYPE |
||
33 | |||
7597 | akron1 | 34 | COMMAND = CODE.COMMAND; |
6613 | leency | 35 | |
36 | |||
7597 | akron1 | 37 | ANYCODE = POINTER TO RECORD (LISTS.ITEM) |
6613 | leency | 38 | |
7597 | akron1 | 39 | offset: INTEGER |
6613 | leency | 40 | |
7597 | akron1 | 41 | END; |
6613 | leency | 42 | |
7597 | akron1 | 43 | TCODE = POINTER TO RECORD (ANYCODE) |
6613 | leency | 44 | |
7597 | akron1 | 45 | code: ARRAY CODECHUNK OF BYTE; |
46 | length: INTEGER |
||
6613 | leency | 47 | |
7597 | akron1 | 48 | END; |
6613 | leency | 49 | |
7597 | akron1 | 50 | LABEL = POINTER TO RECORD (ANYCODE) |
6613 | leency | 51 | |
7597 | akron1 | 52 | label: INTEGER |
6613 | leency | 53 | |
7597 | akron1 | 54 | END; |
6613 | leency | 55 | |
7597 | akron1 | 56 | JUMP = POINTER TO RECORD (ANYCODE) |
7209 | akron1 | 57 | |
7597 | akron1 | 58 | label, diff: INTEGER; |
59 | short: BOOLEAN |
||
6613 | leency | 60 | |
7597 | akron1 | 61 | END; |
6613 | leency | 62 | |
7597 | akron1 | 63 | JMP = POINTER TO RECORD (JUMP) |
6613 | leency | 64 | |
7597 | akron1 | 65 | END; |
6613 | leency | 66 | |
7597 | akron1 | 67 | JCC = POINTER TO RECORD (JUMP) |
6613 | leency | 68 | |
7597 | akron1 | 69 | jmp: INTEGER |
6613 | leency | 70 | |
71 | END; |
||
72 | |||
7597 | akron1 | 73 | CALL = POINTER TO RECORD (JUMP) |
6613 | leency | 74 | |
7597 | akron1 | 75 | END; |
6613 | leency | 76 | |
7597 | akron1 | 77 | RELOC = POINTER TO RECORD (ANYCODE) |
6613 | leency | 78 | |
7597 | akron1 | 79 | op, value: INTEGER |
6613 | leency | 80 | |
7597 | akron1 | 81 | END; |
6613 | leency | 82 | |
83 | |||
7597 | akron1 | 84 | VAR |
6613 | leency | 85 | |
7597 | akron1 | 86 | R: REG.REGS; |
6613 | leency | 87 | |
7597 | akron1 | 88 | program: BIN.PROGRAM; |
6613 | leency | 89 | |
7597 | akron1 | 90 | CodeList: LISTS.LIST; |
6613 | leency | 91 | |
92 | |||
7597 | akron1 | 93 | PROCEDURE Byte (n: INTEGER): BYTE; |
94 | RETURN MACHINE.Byte(n, 0) |
||
95 | END Byte; |
||
6613 | leency | 96 | |
97 | |||
7597 | akron1 | 98 | PROCEDURE Word (n: INTEGER): INTEGER; |
99 | RETURN MACHINE.Byte(n, 0) + MACHINE.Byte(n, 1) * 256 |
||
100 | END Word; |
||
6613 | leency | 101 | |
102 | |||
7597 | akron1 | 103 | PROCEDURE OutByte* (n: BYTE); |
104 | VAR |
||
105 | c: TCODE; |
||
106 | last: ANYCODE; |
||
6613 | leency | 107 | |
7597 | akron1 | 108 | BEGIN |
109 | last := CodeList.last(ANYCODE); |
||
6613 | leency | 110 | |
7597 | akron1 | 111 | IF (last IS TCODE) & (last(TCODE).length < CODECHUNK) THEN |
112 | c := last(TCODE); |
||
113 | c.code[c.length] := n; |
||
114 | INC(c.length) |
||
115 | ELSE |
||
116 | NEW(c); |
||
117 | c.code[0] := n; |
||
118 | c.length := 1; |
||
119 | LISTS.push(CodeList, c) |
||
120 | END |
||
6613 | leency | 121 | |
7597 | akron1 | 122 | END OutByte; |
6613 | leency | 123 | |
124 | |||
7597 | akron1 | 125 | PROCEDURE OutInt (n: INTEGER); |
6613 | leency | 126 | BEGIN |
7597 | akron1 | 127 | OutByte(MACHINE.Byte(n, 0)); |
128 | OutByte(MACHINE.Byte(n, 1)); |
||
129 | OutByte(MACHINE.Byte(n, 2)); |
||
130 | OutByte(MACHINE.Byte(n, 3)) |
||
131 | END OutInt; |
||
6613 | leency | 132 | |
133 | |||
7597 | akron1 | 134 | PROCEDURE OutByte2 (a, b: BYTE); |
6613 | leency | 135 | BEGIN |
7597 | akron1 | 136 | OutByte(a); |
137 | OutByte(b) |
||
138 | END OutByte2; |
||
6613 | leency | 139 | |
140 | |||
7597 | akron1 | 141 | PROCEDURE OutByte3 (a, b, c: BYTE); |
6613 | leency | 142 | BEGIN |
7597 | akron1 | 143 | OutByte(a); |
144 | OutByte(b); |
||
145 | OutByte(c) |
||
146 | END OutByte3; |
||
6613 | leency | 147 | |
148 | |||
7597 | akron1 | 149 | PROCEDURE OutWord (n: INTEGER); |
6613 | leency | 150 | BEGIN |
7597 | akron1 | 151 | ASSERT((0 <= n) & (n <= 65535)); |
152 | OutByte2(n MOD 256, n DIV 256) |
||
153 | END OutWord; |
||
6613 | leency | 154 | |
155 | |||
7597 | akron1 | 156 | PROCEDURE isByte (n: INTEGER): BOOLEAN; |
157 | RETURN (-128 <= n) & (n <= 127) |
||
158 | END isByte; |
||
159 | |||
160 | |||
161 | PROCEDURE short (n: INTEGER): INTEGER; |
||
162 | RETURN 2 * ORD(isByte(n)) |
||
163 | END short; |
||
164 | |||
165 | |||
166 | PROCEDURE long (n: INTEGER): INTEGER; |
||
167 | RETURN 40H * ORD(~isByte(n)) |
||
168 | END long; |
||
169 | |||
170 | |||
171 | PROCEDURE OutIntByte (n: INTEGER); |
||
6613 | leency | 172 | BEGIN |
7597 | akron1 | 173 | IF isByte(n) THEN |
174 | OutByte(Byte(n)) |
||
175 | ELSE |
||
176 | OutInt(n) |
||
177 | END |
||
178 | END OutIntByte; |
||
6613 | leency | 179 | |
7597 | akron1 | 180 | |
181 | PROCEDURE shift* (op, reg: INTEGER); |
||
6613 | leency | 182 | BEGIN |
7597 | akron1 | 183 | CASE op OF |
184 | |CODE.opASR, CODE.opASR1, CODE.opASR2: OutByte(0F8H + reg) |
||
185 | |CODE.opROR, CODE.opROR1, CODE.opROR2: OutByte(0C8H + reg) |
||
186 | |CODE.opLSL, CODE.opLSL1, CODE.opLSL2: OutByte(0E0H + reg) |
||
187 | |CODE.opLSR, CODE.opLSR1, CODE.opLSR2: OutByte(0E8H + reg) |
||
188 | END |
||
189 | END shift; |
||
6613 | leency | 190 | |
7597 | akron1 | 191 | |
192 | PROCEDURE mov (reg1, reg2: INTEGER); |
||
6613 | leency | 193 | BEGIN |
7597 | akron1 | 194 | OutByte2(89H, 0C0H + reg2 * 8 + reg1) // mov reg1, reg2 |
195 | END mov; |
||
6613 | leency | 196 | |
7597 | akron1 | 197 | |
198 | PROCEDURE xchg (reg1, reg2: INTEGER); |
||
199 | VAR |
||
200 | regs: SET; |
||
201 | |||
6613 | leency | 202 | BEGIN |
7597 | akron1 | 203 | regs := {reg1, reg2}; |
204 | IF regs = {eax, ecx} THEN |
||
205 | OutByte(91H) // xchg eax, ecx |
||
206 | ELSIF regs = {eax, edx} THEN |
||
207 | OutByte(92H) // xchg eax, edx |
||
208 | ELSIF regs = {ecx, edx} THEN |
||
209 | OutByte2(87H, 0D1H) // xchg ecx, edx |
||
210 | END |
||
211 | END xchg; |
||
6613 | leency | 212 | |
7597 | akron1 | 213 | |
214 | PROCEDURE pop (reg: INTEGER); |
||
6613 | leency | 215 | BEGIN |
7597 | akron1 | 216 | OutByte(58H + reg) // pop reg |
217 | END pop; |
||
6613 | leency | 218 | |
7597 | akron1 | 219 | |
220 | PROCEDURE push (reg: INTEGER); |
||
6613 | leency | 221 | BEGIN |
7597 | akron1 | 222 | OutByte(50H + reg) // push reg |
223 | END push; |
||
6613 | leency | 224 | |
7597 | akron1 | 225 | |
226 | PROCEDURE movrc (reg, n: INTEGER); |
||
6613 | leency | 227 | BEGIN |
7597 | akron1 | 228 | OutByte(0B8H + reg); // mov reg, n |
229 | OutInt(n) |
||
230 | END movrc; |
||
6613 | leency | 231 | |
7597 | akron1 | 232 | |
233 | PROCEDURE pushc (n: INTEGER); |
||
6613 | leency | 234 | BEGIN |
7597 | akron1 | 235 | OutByte(68H + short(n)); // push n |
236 | OutIntByte(n) |
||
237 | END pushc; |
||
6613 | leency | 238 | |
7597 | akron1 | 239 | |
240 | PROCEDURE test (reg: INTEGER); |
||
6613 | leency | 241 | BEGIN |
7597 | akron1 | 242 | OutByte2(85H, 0C0H + reg * 9) // test reg, reg |
243 | END test; |
||
6613 | leency | 244 | |
7597 | akron1 | 245 | |
246 | PROCEDURE neg (reg: INTEGER); |
||
6613 | leency | 247 | BEGIN |
7597 | akron1 | 248 | OutByte2(0F7H, 0D8H + reg) // neg reg |
249 | END neg; |
||
6613 | leency | 250 | |
7597 | akron1 | 251 | |
252 | PROCEDURE not (reg: INTEGER); |
||
6613 | leency | 253 | BEGIN |
7597 | akron1 | 254 | OutByte2(0F7H, 0D0H + reg) // not reg |
255 | END not; |
||
6613 | leency | 256 | |
7597 | akron1 | 257 | |
258 | PROCEDURE add (reg1, reg2: INTEGER); |
||
6613 | leency | 259 | BEGIN |
7597 | akron1 | 260 | OutByte2(01H, 0C0H + reg2 * 8 + reg1) // add reg1, reg2 |
261 | END add; |
||
6613 | leency | 262 | |
7597 | akron1 | 263 | |
264 | PROCEDURE andrc (reg, n: INTEGER); |
||
6613 | leency | 265 | BEGIN |
7597 | akron1 | 266 | OutByte2(81H + short(n), 0E0H + reg); // and reg, n |
267 | OutIntByte(n) |
||
268 | END andrc; |
||
6613 | leency | 269 | |
7597 | akron1 | 270 | |
271 | PROCEDURE orrc (reg, n: INTEGER); |
||
6613 | leency | 272 | BEGIN |
7597 | akron1 | 273 | OutByte2(81H + short(n), 0C8H + reg); // or reg, n |
274 | OutIntByte(n) |
||
275 | END orrc; |
||
6613 | leency | 276 | |
7597 | akron1 | 277 | |
278 | PROCEDURE addrc (reg, n: INTEGER); |
||
6613 | leency | 279 | BEGIN |
7597 | akron1 | 280 | OutByte2(81H + short(n), 0C0H + reg); // add reg, n |
281 | OutIntByte(n) |
||
282 | END addrc; |
||
6613 | leency | 283 | |
7597 | akron1 | 284 | |
285 | PROCEDURE subrc (reg, n: INTEGER); |
||
6613 | leency | 286 | BEGIN |
7597 | akron1 | 287 | OutByte2(81H + short(n), 0E8H + reg); // sub reg, n |
288 | OutIntByte(n) |
||
289 | END subrc; |
||
6613 | leency | 290 | |
7597 | akron1 | 291 | |
292 | PROCEDURE cmprr (reg1, reg2: INTEGER); |
||
6613 | leency | 293 | BEGIN |
7597 | akron1 | 294 | OutByte2(39H, 0C0H + reg2 * 8 + reg1) // cmp reg1, reg2 |
295 | END cmprr; |
||
6613 | leency | 296 | |
7597 | akron1 | 297 | |
298 | PROCEDURE cmprc (reg, n: INTEGER); |
||
6613 | leency | 299 | BEGIN |
7597 | akron1 | 300 | OutByte2(81H + short(n), 0F8H + reg); // cmp reg, n |
301 | OutIntByte(n) |
||
302 | END cmprc; |
||
6613 | leency | 303 | |
7597 | akron1 | 304 | |
305 | PROCEDURE setcc (cond, reg: INTEGER); |
||
6613 | leency | 306 | BEGIN |
7597 | akron1 | 307 | OutByte3(0FH, cond, 0C0H + reg) // setcc reg |
308 | END setcc; |
||
6613 | leency | 309 | |
7597 | akron1 | 310 | |
7667 | akron1 | 311 | PROCEDURE xor (reg1, reg2: INTEGER); |
312 | BEGIN |
||
313 | OutByte2(31H, 0C0H + reg2 * 8 + reg1) // xor reg1, reg2 |
||
314 | END xor; |
||
315 | |||
316 | |||
7597 | akron1 | 317 | PROCEDURE drop; |
6613 | leency | 318 | BEGIN |
7597 | akron1 | 319 | REG.Drop(R) |
320 | END drop; |
||
6613 | leency | 321 | |
7597 | akron1 | 322 | |
323 | PROCEDURE log2* (x: INTEGER): INTEGER; |
||
324 | VAR |
||
325 | n: INTEGER; |
||
326 | |||
6613 | leency | 327 | BEGIN |
7597 | akron1 | 328 | ASSERT(x > 0); |
6613 | leency | 329 | |
7597 | akron1 | 330 | n := 0; |
331 | WHILE ~ODD(x) DO |
||
332 | x := x DIV 2; |
||
333 | INC(n) |
||
6613 | leency | 334 | END; |
7597 | akron1 | 335 | |
336 | IF x # 1 THEN |
||
337 | n := -1 |
||
6613 | leency | 338 | END |
339 | |||
7597 | akron1 | 340 | RETURN n |
341 | END log2; |
||
6613 | leency | 342 | |
343 | |||
7597 | akron1 | 344 | PROCEDURE cond* (op: INTEGER): INTEGER; |
345 | VAR |
||
346 | res: INTEGER; |
||
6613 | leency | 347 | |
348 | BEGIN |
||
7597 | akron1 | 349 | CASE op OF |
350 | |CODE.opGT, CODE.opGTR, CODE.opLTL: res := jg |
||
351 | |CODE.opGE, CODE.opGER, CODE.opLEL: res := jge |
||
352 | |CODE.opLT, CODE.opLTR, CODE.opGTL: res := jl |
||
353 | |CODE.opLE, CODE.opLER, CODE.opGEL: res := jle |
||
354 | |CODE.opEQ, CODE.opEQR, CODE.opEQL: res := je |
||
355 | |CODE.opNE, CODE.opNER, CODE.opNEL: res := jne |
||
356 | END |
||
6613 | leency | 357 | |
7597 | akron1 | 358 | RETURN res |
359 | END cond; |
||
360 | |||
361 | |||
362 | PROCEDURE inv1* (op: INTEGER): INTEGER; |
||
6613 | leency | 363 | BEGIN |
7597 | akron1 | 364 | IF ODD(op) THEN |
365 | DEC(op) |
||
6613 | leency | 366 | ELSE |
7597 | akron1 | 367 | INC(op) |
6613 | leency | 368 | END |
369 | |||
7597 | akron1 | 370 | RETURN op |
371 | END inv1; |
||
6613 | leency | 372 | |
373 | |||
7597 | akron1 | 374 | PROCEDURE Reloc* (op, value: INTEGER); |
375 | VAR |
||
376 | reloc: RELOC; |
||
6613 | leency | 377 | |
378 | BEGIN |
||
7597 | akron1 | 379 | NEW(reloc); |
380 | reloc.op := op; |
||
381 | reloc.value := value; |
||
382 | LISTS.push(CodeList, reloc) |
||
383 | END Reloc; |
||
6613 | leency | 384 | |
385 | |||
7597 | akron1 | 386 | PROCEDURE jcc* (cc, label: INTEGER); |
387 | VAR |
||
388 | j: JCC; |
||
6613 | leency | 389 | |
390 | BEGIN |
||
7597 | akron1 | 391 | NEW(j); |
392 | j.label := label; |
||
393 | j.jmp := cc; |
||
394 | j.short := FALSE; |
||
395 | LISTS.push(CodeList, j) |
||
396 | END jcc; |
||
6613 | leency | 397 | |
398 | |||
7597 | akron1 | 399 | PROCEDURE jmp* (label: INTEGER); |
400 | VAR |
||
401 | j: JMP; |
||
6613 | leency | 402 | |
403 | BEGIN |
||
7597 | akron1 | 404 | NEW(j); |
405 | j.label := label; |
||
406 | j.short := FALSE; |
||
407 | LISTS.push(CodeList, j) |
||
408 | END jmp; |
||
6613 | leency | 409 | |
410 | |||
7597 | akron1 | 411 | PROCEDURE call* (label: INTEGER); |
412 | VAR |
||
413 | c: CALL; |
||
6613 | leency | 414 | |
415 | BEGIN |
||
7597 | akron1 | 416 | NEW(c); |
417 | c.label := label; |
||
418 | c.short := TRUE; |
||
419 | LISTS.push(CodeList, c) |
||
420 | END call; |
||
6613 | leency | 421 | |
422 | |||
7597 | akron1 | 423 | PROCEDURE Pic (reg, opcode, value: INTEGER); |
6613 | leency | 424 | BEGIN |
7597 | akron1 | 425 | OutByte(0E8H); OutInt(0); // call L |
426 | // L: |
||
427 | pop(reg); |
||
428 | OutByte2(081H, 0C0H + reg); // add reg, ... |
||
429 | Reloc(opcode, value) |
||
430 | END Pic; |
||
6613 | leency | 431 | |
432 | |||
7597 | akron1 | 433 | PROCEDURE CallRTL (pic: BOOLEAN; proc: INTEGER); |
434 | VAR |
||
435 | label: INTEGER; |
||
436 | reg1: INTEGER; |
||
6613 | leency | 437 | |
438 | BEGIN |
||
7597 | akron1 | 439 | label := CODE.codes.rtl[proc]; |
6613 | leency | 440 | |
7597 | akron1 | 441 | IF label < 0 THEN |
442 | label := -label; |
||
443 | IF pic THEN |
||
444 | reg1 := REG.GetAnyReg(R); |
||
445 | Pic(reg1, BIN.PICIMP, label); |
||
446 | OutByte2(0FFH, 010H + reg1); // call dword[reg1] |
||
447 | drop |
||
448 | ELSE |
||
449 | OutByte2(0FFH, 015H); // call dword[label] |
||
450 | Reloc(BIN.RIMP, label) |
||
451 | END |
||
452 | ELSE |
||
453 | call(label) |
||
454 | END |
||
455 | END CallRTL; |
||
6613 | leency | 456 | |
457 | |||
7597 | akron1 | 458 | PROCEDURE SetLabel* (label: INTEGER); |
459 | VAR |
||
460 | L: LABEL; |
||
6613 | leency | 461 | |
462 | BEGIN |
||
7597 | akron1 | 463 | NEW(L); |
464 | L.label := label; |
||
465 | LISTS.push(CodeList, L) |
||
466 | END SetLabel; |
||
6613 | leency | 467 | |
468 | |||
7597 | akron1 | 469 | PROCEDURE fixup*; |
470 | VAR |
||
471 | code: ANYCODE; |
||
472 | count, i: INTEGER; |
||
473 | shorted: BOOLEAN; |
||
474 | jump: JUMP; |
||
6613 | leency | 475 | |
476 | BEGIN |
||
477 | |||
7597 | akron1 | 478 | REPEAT |
6613 | leency | 479 | |
7597 | akron1 | 480 | shorted := FALSE; |
481 | count := 0; |
||
6613 | leency | 482 | |
7597 | akron1 | 483 | code := CodeList.first(ANYCODE); |
484 | WHILE code # NIL DO |
||
485 | code.offset := count; |
||
6613 | leency | 486 | |
7597 | akron1 | 487 | CASE code OF |
488 | |TCODE: INC(count, code.length) |
||
489 | |LABEL: BIN.SetLabel(program, code.label, count) |
||
490 | |JMP: IF code.short THEN INC(count, 2) ELSE INC(count, 5) END; code.offset := count |
||
491 | |JCC: IF code.short THEN INC(count, 2) ELSE INC(count, 6) END; code.offset := count |
||
492 | |CALL: INC(count, 5); code.offset := count |
||
493 | |RELOC: INC(count, 4) |
||
494 | END; |
||
6613 | leency | 495 | |
7597 | akron1 | 496 | code := code.next(ANYCODE) |
497 | END; |
||
6613 | leency | 498 | |
7597 | akron1 | 499 | code := CodeList.first(ANYCODE); |
500 | WHILE code # NIL DO |
||
6613 | leency | 501 | |
7597 | akron1 | 502 | IF code IS JUMP THEN |
503 | jump := code(JUMP); |
||
504 | jump.diff := BIN.GetLabel(program, jump.label) - code.offset; |
||
505 | IF ~jump.short & isByte(jump.diff) THEN |
||
506 | jump.short := TRUE; |
||
507 | shorted := TRUE |
||
508 | END |
||
509 | END; |
||
6613 | leency | 510 | |
7597 | akron1 | 511 | code := code.next(ANYCODE) |
512 | END |
||
6613 | leency | 513 | |
7597 | akron1 | 514 | UNTIL ~shorted; |
6613 | leency | 515 | |
7597 | akron1 | 516 | code := CodeList.first(ANYCODE); |
517 | WHILE code # NIL DO |
||
6613 | leency | 518 | |
7597 | akron1 | 519 | CASE code OF |
6613 | leency | 520 | |
7597 | akron1 | 521 | |TCODE: |
522 | FOR i := 0 TO code.length - 1 DO |
||
523 | BIN.PutCode(program, code.code[i]) |
||
524 | END |
||
6613 | leency | 525 | |
7597 | akron1 | 526 | |LABEL: |
527 | BIN.SetLabel(program, code.label, code.offset) |
||
6613 | leency | 528 | |
7597 | akron1 | 529 | |JMP: |
530 | IF code.short THEN |
||
531 | BIN.PutCode(program, 0EBH); |
||
532 | BIN.PutCode(program, Byte(code.diff)) |
||
533 | ELSE |
||
534 | BIN.PutCode(program, 0E9H); |
||
535 | BIN.PutCode32LE(program, code.diff) |
||
536 | END |
||
6613 | leency | 537 | |
7597 | akron1 | 538 | |JCC: |
539 | IF code.short THEN |
||
540 | BIN.PutCode(program, code.jmp - 16); |
||
541 | BIN.PutCode(program, Byte(code.diff)) |
||
542 | ELSE |
||
543 | BIN.PutCode(program, 0FH); |
||
544 | BIN.PutCode(program, code.jmp); |
||
545 | BIN.PutCode32LE(program, code.diff) |
||
546 | END |
||
6613 | leency | 547 | |
7597 | akron1 | 548 | |CALL: |
549 | BIN.PutCode(program, 0E8H); |
||
550 | BIN.PutCode32LE(program, code.diff) |
||
6613 | leency | 551 | |
7597 | akron1 | 552 | |RELOC: |
553 | BIN.PutReloc(program, code.op); |
||
554 | BIN.PutCode32LE(program, code.value) |
||
6613 | leency | 555 | |
7597 | akron1 | 556 | END; |
557 | |||
558 | code := code.next(ANYCODE) |
||
6613 | leency | 559 | END |
560 | |||
7597 | akron1 | 561 | END fixup; |
6613 | leency | 562 | |
563 | |||
7597 | akron1 | 564 | PROCEDURE UnOp (VAR reg: INTEGER); |
6613 | leency | 565 | BEGIN |
7597 | akron1 | 566 | REG.UnOp(R, reg) |
567 | END UnOp; |
||
6613 | leency | 568 | |
569 | |||
7597 | akron1 | 570 | PROCEDURE BinOp (VAR reg1, reg2: INTEGER); |
6613 | leency | 571 | BEGIN |
7597 | akron1 | 572 | REG.BinOp(R, reg1, reg2) |
573 | END BinOp; |
||
6613 | leency | 574 | |
575 | |||
7597 | akron1 | 576 | PROCEDURE PushAll (NumberOfParameters: INTEGER); |
6613 | leency | 577 | BEGIN |
7597 | akron1 | 578 | REG.PushAll(R); |
579 | R.pushed := R.pushed - NumberOfParameters |
||
580 | END PushAll; |
||
6613 | leency | 581 | |
582 | |||
7597 | akron1 | 583 | PROCEDURE NewLabel (): INTEGER; |
6613 | leency | 584 | BEGIN |
7597 | akron1 | 585 | BIN.NewLabel(program) |
586 | RETURN CODE.NewLabel() |
||
587 | END NewLabel; |
||
6613 | leency | 588 | |
589 | |||
7597 | akron1 | 590 | PROCEDURE GetRegA; |
6613 | leency | 591 | BEGIN |
7597 | akron1 | 592 | ASSERT(REG.GetReg(R, eax)) |
593 | END GetRegA; |
||
6613 | leency | 594 | |
595 | |||
7597 | akron1 | 596 | PROCEDURE translate (code: CODE.CODES; pic: BOOLEAN; stroffs: INTEGER); |
597 | VAR |
||
598 | cmd: COMMAND; |
||
6613 | leency | 599 | |
7597 | akron1 | 600 | reg1, reg2: INTEGER; |
6613 | leency | 601 | |
7597 | akron1 | 602 | n, a, b, label, cc: INTEGER; |
6613 | leency | 603 | |
7597 | akron1 | 604 | param1, param2: INTEGER; |
6613 | leency | 605 | |
7597 | akron1 | 606 | float: REAL; |
6613 | leency | 607 | |
608 | BEGIN |
||
7597 | akron1 | 609 | cmd := code.commands.first(COMMAND); |
6613 | leency | 610 | |
7597 | akron1 | 611 | WHILE cmd # NIL DO |
6613 | leency | 612 | |
7597 | akron1 | 613 | param1 := cmd.param1; |
614 | param2 := cmd.param2; |
||
6613 | leency | 615 | |
7597 | akron1 | 616 | CASE cmd.opcode OF |
6613 | leency | 617 | |
7597 | akron1 | 618 | |CODE.opJMP: |
619 | jmp(param1) |
||
6613 | leency | 620 | |
7597 | akron1 | 621 | |CODE.opCALL: |
622 | call(param1) |
||
6613 | leency | 623 | |
7597 | akron1 | 624 | |CODE.opCALLI: |
625 | IF pic THEN |
||
626 | reg1 := REG.GetAnyReg(R); |
||
627 | Pic(reg1, BIN.PICIMP, param1); |
||
628 | OutByte2(0FFH, 010H + reg1); // call dword[reg1] |
||
629 | drop |
||
630 | ELSE |
||
631 | OutByte2(0FFH, 015H); // call dword[L] |
||
632 | Reloc(BIN.RIMP, param1) |
||
633 | END |
||
6613 | leency | 634 | |
7597 | akron1 | 635 | |CODE.opCALLP: |
636 | UnOp(reg1); |
||
637 | OutByte2(0FFH, 0D0H + reg1); // call reg1 |
||
638 | drop; |
||
639 | ASSERT(R.top = -1) |
||
6613 | leency | 640 | |
7597 | akron1 | 641 | |CODE.opPRECALL: |
642 | n := param2; |
||
643 | IF (param1 # 0) & (n # 0) THEN |
||
644 | subrc(esp, 8) |
||
645 | END; |
||
646 | WHILE n > 0 DO |
||
647 | subrc(esp, 8); |
||
648 | OutByte3(0DDH, 01CH, 024H); // fstp qword[esp] |
||
649 | DEC(n) |
||
650 | END; |
||
651 | PushAll(0) |
||
6613 | leency | 652 | |
7597 | akron1 | 653 | |CODE.opALIGN16: |
654 | ASSERT(eax IN R.regs); |
||
655 | mov(eax, esp); |
||
656 | andrc(esp, -16); |
||
657 | n := (3 - param2 MOD 4) * 4; |
||
658 | IF n > 0 THEN |
||
659 | subrc(esp, n) |
||
660 | END; |
||
661 | push(eax) |
||
662 | |||
663 | |CODE.opRES: |
||
664 | ASSERT(R.top = -1); |
||
665 | GetRegA; |
||
666 | n := param2; |
||
667 | WHILE n > 0 DO |
||
668 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
669 | addrc(esp, 8); |
||
670 | DEC(n) |
||
671 | END |
||
672 | |||
673 | |CODE.opRESF: |
||
674 | n := param2; |
||
675 | IF n > 0 THEN |
||
676 | OutByte3(0DDH, 5CH + long(n * 8), 24H); |
||
677 | OutIntByte(n * 8); // fstp qword[esp + n*8] |
||
678 | INC(n) |
||
679 | END; |
||
680 | |||
681 | WHILE n > 0 DO |
||
682 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
683 | addrc(esp, 8); |
||
684 | DEC(n) |
||
685 | END |
||
686 | |||
687 | |CODE.opENTER: |
||
688 | ASSERT(R.top = -1); |
||
689 | |||
690 | SetLabel(param1); |
||
691 | |||
692 | push(ebp); |
||
693 | mov(ebp, esp); |
||
694 | |||
695 | n := param2; |
||
696 | IF n > 4 THEN |
||
697 | movrc(ecx, n); |
||
698 | pushc(0); // @@: push 0 |
||
699 | OutByte2(0E2H, 0FCH) // loop @b |
||
700 | ELSE |
||
701 | WHILE n > 0 DO |
||
702 | pushc(0); |
||
703 | DEC(n) |
||
704 | END |
||
705 | END |
||
706 | |||
707 | |CODE.opLEAVE, CODE.opLEAVER, CODE.opLEAVEF: |
||
708 | IF cmd.opcode = CODE.opLEAVER THEN |
||
709 | UnOp(reg1); |
||
710 | IF reg1 # eax THEN |
||
711 | GetRegA; |
||
712 | ASSERT(REG.Exchange(R, reg1, eax)); |
||
713 | drop |
||
714 | END; |
||
715 | drop |
||
716 | END; |
||
717 | |||
718 | ASSERT(R.top = -1); |
||
719 | |||
720 | mov(esp, ebp); |
||
721 | pop(ebp); |
||
722 | |||
723 | n := param2; |
||
724 | IF n > 0 THEN |
||
725 | n := n * 4; |
||
726 | OutByte(0C2H); OutWord(Word(n)) // ret n |
||
727 | ELSE |
||
728 | OutByte(0C3H) // ret |
||
729 | END |
||
730 | |||
731 | |CODE.opERRC: |
||
732 | pushc(param2) |
||
733 | |||
734 | |CODE.opPARAM: |
||
735 | n := param2; |
||
736 | IF n = 1 THEN |
||
737 | UnOp(reg1); |
||
738 | push(reg1); |
||
739 | drop |
||
740 | ELSE |
||
741 | ASSERT(R.top + 1 <= n); |
||
742 | PushAll(n) |
||
743 | END |
||
744 | |||
745 | |CODE.opCLEANUP: |
||
746 | n := param2 * 4; |
||
747 | IF n # 0 THEN |
||
748 | addrc(esp, n) |
||
749 | END |
||
750 | |||
751 | |CODE.opPOPSP: |
||
752 | pop(esp) |
||
753 | |||
754 | |CODE.opCONST: |
||
755 | reg1 := REG.GetAnyReg(R); |
||
756 | movrc(reg1, param2) |
||
757 | |||
758 | |CODE.opLABEL: |
||
759 | SetLabel(param2) // L: |
||
760 | |||
761 | |CODE.opNOP: |
||
762 | |||
763 | |CODE.opGADR: |
||
764 | reg1 := REG.GetAnyReg(R); |
||
765 | IF pic THEN |
||
766 | Pic(reg1, BIN.PICBSS, param2) |
||
767 | ELSE |
||
768 | OutByte(0B8H + reg1); // mov reg1, _bss + param2 |
||
769 | Reloc(BIN.RBSS, param2) |
||
770 | END |
||
771 | |||
772 | |CODE.opLADR: |
||
773 | n := param2 * 4; |
||
774 | reg1 := REG.GetAnyReg(R); |
||
775 | OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] |
||
776 | OutIntByte(n) |
||
777 | |||
778 | |CODE.opVADR: |
||
779 | n := param2 * 4; |
||
780 | reg1 := REG.GetAnyReg(R); |
||
781 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
||
782 | OutIntByte(n) |
||
783 | |||
784 | |CODE.opSADR: |
||
785 | reg1 := REG.GetAnyReg(R); |
||
786 | IF pic THEN |
||
787 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
||
788 | ELSE |
||
789 | OutByte(0B8H + reg1); // mov reg1, _data + stroffs + param2 |
||
790 | Reloc(BIN.RDATA, stroffs + param2) |
||
791 | END |
||
792 | |||
793 | |CODE.opSAVEC: |
||
794 | UnOp(reg1); |
||
795 | OutByte2(0C7H, reg1); OutInt(param2); // mov dword[reg1], param2 |
||
796 | drop |
||
797 | |||
798 | |CODE.opSAVE8C: |
||
799 | UnOp(reg1); |
||
800 | OutByte3(0C6H, reg1, Byte(param2)); // mov byte[reg1], param2 |
||
801 | drop |
||
802 | |||
803 | |CODE.opSAVE16C: |
||
804 | UnOp(reg1); |
||
805 | OutByte3(66H, 0C7H, reg1); OutWord(Word(param2)); // mov word[reg1], param2 |
||
806 | drop |
||
807 | |||
808 | |CODE.opVLOAD32: |
||
809 | n := param2 * 4; |
||
810 | reg1 := REG.GetAnyReg(R); |
||
811 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
||
812 | OutIntByte(n); |
||
813 | OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] |
||
814 | |||
815 | |CODE.opGLOAD32: |
||
816 | reg1 := REG.GetAnyReg(R); |
||
817 | IF pic THEN |
||
818 | Pic(reg1, BIN.PICBSS, param2); |
||
819 | OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] |
||
820 | ELSE |
||
821 | OutByte2(08BH, 05H + reg1 * 8); // mov reg1, dword[_bss + param2] |
||
822 | Reloc(BIN.RBSS, param2) |
||
823 | END |
||
824 | |||
825 | |CODE.opLLOAD32: |
||
826 | n := param2 * 4; |
||
827 | reg1 := REG.GetAnyReg(R); |
||
828 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
||
829 | OutIntByte(n) |
||
830 | |||
831 | |CODE.opLOAD32: |
||
832 | UnOp(reg1); |
||
833 | OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] |
||
834 | |||
835 | |CODE.opVLOAD8: |
||
836 | n := param2 * 4; |
||
837 | reg1 := REG.GetAnyReg(R); |
||
838 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
||
839 | OutIntByte(n); |
||
840 | OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] |
||
841 | |||
842 | |CODE.opGLOAD8: |
||
843 | reg1 := REG.GetAnyReg(R); |
||
844 | IF pic THEN |
||
845 | Pic(reg1, BIN.PICBSS, param2); |
||
846 | OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] |
||
847 | ELSE |
||
848 | OutByte3(00FH, 0B6H, 05H + reg1 * 8); // movzx reg1, byte[_bss + param2] |
||
849 | Reloc(BIN.RBSS, param2) |
||
850 | END |
||
851 | |||
852 | |CODE.opLLOAD8: |
||
853 | n := param2 * 4; |
||
854 | reg1 := REG.GetAnyReg(R); |
||
855 | OutByte3(0FH, 0B6H, 45H + reg1 * 8 + long(n)); // movzx reg1, byte[ebp + n] |
||
856 | OutIntByte(n) |
||
857 | |||
858 | |CODE.opLOAD8: |
||
859 | UnOp(reg1); |
||
860 | OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] |
||
861 | |||
862 | |CODE.opVLOAD16: |
||
863 | n := param2 * 4; |
||
864 | reg1 := REG.GetAnyReg(R); |
||
865 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
||
866 | OutIntByte(n); |
||
867 | OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] |
||
868 | |||
869 | |CODE.opGLOAD16: |
||
870 | reg1 := REG.GetAnyReg(R); |
||
871 | IF pic THEN |
||
872 | Pic(reg1, BIN.PICBSS, param2); |
||
873 | OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] |
||
874 | ELSE |
||
875 | OutByte3(00FH, 0B7H, 05H + reg1 * 8); // movzx reg1, word[_bss + param2] |
||
876 | Reloc(BIN.RBSS, param2) |
||
877 | END |
||
878 | |||
879 | |CODE.opLLOAD16: |
||
880 | n := param2 * 4; |
||
881 | reg1 := REG.GetAnyReg(R); |
||
882 | OutByte3(0FH, 0B7H, 45H + reg1 * 8 + long(n)); // movzx reg1, word[ebp + n] |
||
883 | OutIntByte(n) |
||
884 | |||
885 | |CODE.opLOAD16: |
||
886 | UnOp(reg1); |
||
887 | OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] |
||
888 | |||
889 | |CODE.opUMINUS: |
||
890 | UnOp(reg1); |
||
891 | neg(reg1) |
||
892 | |||
893 | |CODE.opADD: |
||
894 | BinOp(reg1, reg2); |
||
895 | add(reg1, reg2); |
||
896 | drop |
||
897 | |||
898 | |CODE.opADDL, CODE.opADDR: |
||
899 | IF param2 # 0 THEN |
||
900 | UnOp(reg1); |
||
901 | IF param2 = 1 THEN |
||
902 | OutByte(40H + reg1) // inc reg1 |
||
903 | ELSIF param2 = -1 THEN |
||
904 | OutByte(48H + reg1) // dec reg1 |
||
905 | ELSE |
||
906 | addrc(reg1, param2) |
||
907 | END |
||
908 | END |
||
909 | |||
910 | |CODE.opSUB: |
||
911 | BinOp(reg1, reg2); |
||
912 | OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 |
||
913 | drop |
||
914 | |||
915 | |CODE.opSUBR, CODE.opSUBL: |
||
916 | UnOp(reg1); |
||
917 | n := param2; |
||
918 | IF n = 1 THEN |
||
919 | OutByte(48H + reg1) // dec reg1 |
||
920 | ELSIF n = -1 THEN |
||
921 | OutByte(40H + reg1) // inc reg1 |
||
922 | ELSIF n # 0 THEN |
||
923 | subrc(reg1, n) |
||
924 | END; |
||
925 | IF cmd.opcode = CODE.opSUBL THEN |
||
926 | neg(reg1) |
||
927 | END |
||
928 | |||
929 | |CODE.opMULC: |
||
930 | UnOp(reg1); |
||
931 | |||
932 | a := param2; |
||
933 | IF a > 1 THEN |
||
934 | n := log2(a) |
||
935 | ELSIF a < -1 THEN |
||
936 | n := log2(-a) |
||
937 | ELSE |
||
938 | n := -1 |
||
939 | END; |
||
940 | |||
941 | IF a = 1 THEN |
||
942 | |||
943 | ELSIF a = -1 THEN |
||
944 | neg(reg1) |
||
945 | ELSIF a = 0 THEN |
||
7667 | akron1 | 946 | xor(reg1, reg1) |
7597 | akron1 | 947 | ELSE |
948 | IF n > 0 THEN |
||
949 | IF a < 0 THEN |
||
950 | neg(reg1) |
||
951 | END; |
||
952 | |||
953 | IF n # 1 THEN |
||
954 | OutByte3(0C1H, 0E0H + reg1, n) // shl reg1, n |
||
955 | ELSE |
||
956 | OutByte2(0D1H, 0E0H + reg1) // shl reg1, 1 |
||
957 | END |
||
958 | ELSE |
||
959 | OutByte2(69H + short(a), 0C0H + reg1 * 9); // imul reg1, a |
||
960 | OutIntByte(a) |
||
961 | END |
||
962 | END |
||
963 | |||
964 | |CODE.opMUL: |
||
965 | BinOp(reg1, reg2); |
||
966 | OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); // imul reg1, reg2 |
||
967 | drop |
||
968 | |||
969 | |CODE.opSAVE, CODE.opSAVE32: |
||
970 | BinOp(reg2, reg1); |
||
971 | OutByte2(89H, reg2 * 8 + reg1); // mov dword[reg1], reg2 |
||
972 | drop; |
||
973 | drop |
||
974 | |||
975 | |CODE.opSAVE8: |
||
976 | BinOp(reg2, reg1); |
||
977 | OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2 |
||
978 | drop; |
||
979 | drop |
||
980 | |||
981 | |CODE.opSAVE16: |
||
982 | BinOp(reg2, reg1); |
||
983 | OutByte3(66H, 89H, reg2 * 8 + reg1); // mov word[reg1], reg2 |
||
984 | drop; |
||
985 | drop |
||
986 | |||
987 | |CODE.opSAVEP: |
||
988 | UnOp(reg1); |
||
989 | IF pic THEN |
||
990 | reg2 := REG.GetAnyReg(R); |
||
991 | Pic(reg2, BIN.PICCODE, param2); |
||
992 | OutByte2(089H, reg2 * 8 + reg1); // mov dword[reg1], reg2 |
||
993 | drop |
||
994 | ELSE |
||
995 | OutByte2(0C7H, reg1); // mov dword[reg1], L |
||
996 | Reloc(BIN.RCODE, param2) |
||
997 | END; |
||
998 | drop |
||
999 | |||
1000 | |CODE.opSAVEIP: |
||
1001 | UnOp(reg1); |
||
1002 | IF pic THEN |
||
1003 | reg2 := REG.GetAnyReg(R); |
||
1004 | Pic(reg2, BIN.PICIMP, param2); |
||
1005 | OutByte2(0FFH, 30H + reg2); // push dword[reg2] |
||
1006 | OutByte2(08FH, reg1); // pop dword[reg1] |
||
1007 | drop |
||
1008 | ELSE |
||
1009 | OutByte2(0FFH, 035H); // push dword[L] |
||
1010 | Reloc(BIN.RIMP, param2); |
||
1011 | OutByte2(08FH, reg1) // pop dword[reg1] |
||
1012 | END; |
||
1013 | drop |
||
1014 | |||
1015 | |CODE.opPUSHP: |
||
1016 | reg1 := REG.GetAnyReg(R); |
||
1017 | IF pic THEN |
||
1018 | Pic(reg1, BIN.PICCODE, param2) |
||
1019 | ELSE |
||
1020 | OutByte(0B8H + reg1); // mov reg1, L |
||
1021 | Reloc(BIN.RCODE, param2) |
||
1022 | END |
||
1023 | |||
1024 | |CODE.opPUSHIP: |
||
1025 | reg1 := REG.GetAnyReg(R); |
||
1026 | IF pic THEN |
||
1027 | Pic(reg1, BIN.PICIMP, param2); |
||
1028 | OutByte2(08BH, reg1 * 9) // mov reg1, dword[reg1] |
||
1029 | ELSE |
||
1030 | OutByte2(08BH, 05H + reg1 * 8); // mov reg1, dword[L] |
||
1031 | Reloc(BIN.RIMP, param2) |
||
1032 | END |
||
1033 | |||
1034 | |CODE.opNOT: |
||
1035 | UnOp(reg1); |
||
1036 | test(reg1); |
||
1037 | setcc(sete, reg1); |
||
1038 | andrc(reg1, 1) |
||
1039 | |||
1040 | |CODE.opORD: |
||
1041 | UnOp(reg1); |
||
1042 | test(reg1); |
||
1043 | setcc(setne, reg1); |
||
1044 | andrc(reg1, 1) |
||
1045 | |||
1046 | |CODE.opSBOOL: |
||
1047 | BinOp(reg2, reg1); |
||
1048 | test(reg2); |
||
1049 | setcc(setne, reg2); |
||
1050 | OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2 |
||
1051 | drop; |
||
1052 | drop |
||
1053 | |||
1054 | |CODE.opSBOOLC: |
||
1055 | UnOp(reg1); |
||
1056 | OutByte3(0C6H, reg1, ORD(param2 # 0)); // mov byte[reg1], 0/1 |
||
1057 | drop |
||
1058 | |||
1059 | |CODE.opODD: |
||
1060 | UnOp(reg1); |
||
1061 | andrc(reg1, 1) |
||
1062 | |||
1063 | |CODE.opGTR, CODE.opLTL, CODE.opGER, CODE.opLEL, |
||
1064 | CODE.opLER, CODE.opGEL, CODE.opLTR, CODE.opGTL, |
||
1065 | CODE.opEQR, CODE.opEQL, CODE.opNER, CODE.opNEL: |
||
1066 | UnOp(reg1); |
||
1067 | IF param2 = 0 THEN |
||
1068 | test(reg1) |
||
1069 | ELSE |
||
1070 | cmprc(reg1, param2) |
||
1071 | END; |
||
1072 | drop; |
||
1073 | cc := cond(cmd.opcode); |
||
1074 | |||
1075 | IF cmd.next(COMMAND).opcode = CODE.opJE THEN |
||
1076 | label := cmd.next(COMMAND).param1; |
||
1077 | jcc(cc, label); |
||
1078 | cmd := cmd.next(COMMAND) |
||
1079 | |||
1080 | ELSIF cmd.next(COMMAND).opcode = CODE.opJNE THEN |
||
1081 | label := cmd.next(COMMAND).param1; |
||
1082 | jcc(inv1(cc), label); |
||
1083 | cmd := cmd.next(COMMAND) |
||
1084 | |||
1085 | ELSE |
||
1086 | reg1 := REG.GetAnyReg(R); |
||
1087 | setcc(cc + 16, reg1); |
||
1088 | andrc(reg1, 1) |
||
7667 | akron1 | 1089 | END |
7597 | akron1 | 1090 | |
1091 | |CODE.opGT, CODE.opGE, CODE.opLT, |
||
1092 | CODE.opLE, CODE.opEQ, CODE.opNE: |
||
1093 | BinOp(reg1, reg2); |
||
1094 | cmprr(reg1, reg2); |
||
1095 | drop; |
||
1096 | drop; |
||
1097 | cc := cond(cmd.opcode); |
||
1098 | |||
1099 | IF cmd.next(COMMAND).opcode = CODE.opJE THEN |
||
1100 | label := cmd.next(COMMAND).param1; |
||
1101 | jcc(cc, label); |
||
1102 | cmd := cmd.next(COMMAND) |
||
1103 | |||
1104 | ELSIF cmd.next(COMMAND).opcode = CODE.opJNE THEN |
||
1105 | label := cmd.next(COMMAND).param1; |
||
1106 | jcc(inv1(cc), label); |
||
1107 | cmd := cmd.next(COMMAND) |
||
1108 | |||
1109 | ELSE |
||
1110 | reg1 := REG.GetAnyReg(R); |
||
1111 | setcc(cc + 16, reg1); |
||
1112 | andrc(reg1, 1) |
||
1113 | END |
||
1114 | |||
1115 | |CODE.opEQB, CODE.opNEB: |
||
1116 | BinOp(reg1, reg2); |
||
1117 | drop; |
||
1118 | drop; |
||
1119 | |||
1120 | test(reg1); |
||
1121 | OutByte2(74H, 5); // je @f |
||
1122 | movrc(reg1, 1); // mov reg1, 1 |
||
1123 | // @@: |
||
1124 | test(reg2); |
||
1125 | OutByte2(74H, 5); // je @f |
||
1126 | movrc(reg2, 1); // mov reg2, 1 |
||
1127 | // @@: |
||
1128 | |||
1129 | cmprr(reg1, reg2); |
||
1130 | reg1 := REG.GetAnyReg(R); |
||
1131 | IF cmd.opcode = CODE.opEQB THEN |
||
1132 | setcc(sete, reg1) |
||
1133 | ELSE |
||
1134 | setcc(setne, reg1) |
||
1135 | END; |
||
1136 | andrc(reg1, 1) |
||
7667 | akron1 | 1137 | |
1138 | |CODE.opACC: |
||
1139 | IF (R.top # 0) OR (R.stk[0] # eax) THEN |
||
1140 | PushAll(0); |
||
1141 | GetRegA; |
||
1142 | pop(eax); |
||
1143 | DEC(R.pushed) |
||
1144 | END |
||
7597 | akron1 | 1145 | |
1146 | |CODE.opDROP: |
||
1147 | UnOp(reg1); |
||
1148 | drop |
||
1149 | |||
1150 | |CODE.opJNZ: |
||
1151 | UnOp(reg1); |
||
1152 | test(reg1); |
||
1153 | jcc(jne, param1) |
||
1154 | |||
1155 | |CODE.opJZ: |
||
1156 | UnOp(reg1); |
||
1157 | test(reg1); |
||
1158 | jcc(je, param1) |
||
1159 | |||
1160 | |CODE.opJE: |
||
1161 | UnOp(reg1); |
||
1162 | test(reg1); |
||
1163 | jcc(jne, param1); |
||
1164 | drop; |
||
1165 | |||
1166 | |CODE.opJNE: |
||
1167 | UnOp(reg1); |
||
1168 | test(reg1); |
||
1169 | jcc(je, param1); |
||
1170 | drop; |
||
1171 | |||
1172 | |CODE.opSWITCH: |
||
1173 | UnOp(reg1); |
||
1174 | IF param2 = 0 THEN |
||
1175 | reg2 := eax |
||
1176 | ELSE |
||
1177 | reg2 := ecx |
||
1178 | END; |
||
1179 | IF reg1 # reg2 THEN |
||
1180 | ASSERT(REG.GetReg(R, reg2)); |
||
1181 | ASSERT(REG.Exchange(R, reg1, reg2)); |
||
1182 | drop |
||
1183 | END; |
||
1184 | drop |
||
1185 | |||
1186 | |CODE.opENDSW: |
||
1187 | |||
1188 | |CODE.opCASEL: |
||
1189 | cmprc(eax, param1); |
||
1190 | jcc(jl, param2) |
||
1191 | |||
1192 | |CODE.opCASER: |
||
1193 | cmprc(eax, param1); |
||
1194 | jcc(jg, param2) |
||
1195 | |||
1196 | |CODE.opCASELR: |
||
1197 | cmprc(eax, param1); |
||
1198 | jcc(jl, param2); |
||
1199 | jcc(jg, cmd.param3) |
||
1200 | |||
1201 | |CODE.opCODE: |
||
1202 | OutByte(param2) |
||
1203 | |||
1204 | |CODE.opGET: |
||
1205 | BinOp(reg1, reg2); |
||
1206 | drop; |
||
1207 | drop; |
||
1208 | |||
1209 | CASE param2 OF |
||
1210 | |1: |
||
1211 | OutByte2(8AH, reg1 * 9); // mov reg1, byte[reg1] |
||
1212 | OutByte2(88H, reg1 * 8 + reg2) // mov byte[reg2], reg1 |
||
1213 | |||
1214 | |2: |
||
1215 | OutByte3(66H, 8BH, reg1 * 9); // mov reg1, word[reg1] |
||
1216 | OutByte3(66H, 89H, reg1 * 8 + reg2) // mov word[reg2], reg1 |
||
1217 | |||
1218 | |4: |
||
1219 | OutByte2(8BH, reg1 * 9); // mov reg1, dword[reg1] |
||
1220 | OutByte2(89H, reg1 * 8 + reg2) // mov dword[reg2], reg1 |
||
1221 | |||
1222 | |8: |
||
1223 | PushAll(0); |
||
1224 | push(reg2); |
||
1225 | push(reg1); |
||
1226 | pushc(8); |
||
1227 | CallRTL(pic, CODE._move) |
||
1228 | |||
1229 | END |
||
1230 | |||
1231 | |CODE.opSAVES: |
||
1232 | UnOp(reg1); |
||
1233 | drop; |
||
1234 | PushAll(0); |
||
1235 | push(reg1); |
||
1236 | |||
1237 | IF pic THEN |
||
1238 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
||
1239 | push(reg1) |
||
1240 | ELSE |
||
1241 | OutByte(068H); // push _data + stroffs + param2 |
||
1242 | Reloc(BIN.RDATA, stroffs + param2); |
||
1243 | END; |
||
1244 | |||
1245 | pushc(param1); |
||
1246 | CallRTL(pic, CODE._move) |
||
1247 | |||
1248 | |CODE.opCHKBYTE: |
||
1249 | BinOp(reg1, reg2); |
||
1250 | cmprc(reg1, 256); |
||
1251 | jcc(jb, param1) |
||
1252 | |||
1253 | |CODE.opCHKIDX: |
||
1254 | UnOp(reg1); |
||
1255 | cmprc(reg1, param2); |
||
1256 | jcc(jb, param1) |
||
1257 | |||
1258 | |CODE.opCHKIDX2: |
||
1259 | BinOp(reg1, reg2); |
||
1260 | IF param2 # -1 THEN |
||
1261 | cmprr(reg2, reg1); |
||
1262 | mov(reg1, reg2); |
||
1263 | drop; |
||
1264 | jcc(jb, param1) |
||
1265 | ELSE |
||
1266 | INCL(R.regs, reg1); |
||
1267 | DEC(R.top); |
||
1268 | R.stk[R.top] := reg2 |
||
1269 | END |
||
1270 | |||
1271 | |CODE.opLEN: |
||
1272 | n := param2; |
||
1273 | UnOp(reg1); |
||
1274 | drop; |
||
1275 | EXCL(R.regs, reg1); |
||
1276 | |||
1277 | WHILE n > 0 DO |
||
1278 | UnOp(reg2); |
||
1279 | drop; |
||
1280 | DEC(n) |
||
1281 | END; |
||
1282 | |||
1283 | INCL(R.regs, reg1); |
||
1284 | ASSERT(REG.GetReg(R, reg1)) |
||
1285 | |||
1286 | |CODE.opINC1: |
||
1287 | UnOp(reg1); |
||
1288 | OutByte2(0FFH, reg1); // inc dword[reg1] |
||
1289 | drop |
||
1290 | |||
1291 | |CODE.opDEC1: |
||
1292 | UnOp(reg1); |
||
1293 | OutByte2(0FFH, 8 + reg1); // dec dword[reg1] |
||
1294 | drop |
||
1295 | |||
1296 | |CODE.opINCC: |
||
1297 | UnOp(reg1); |
||
1298 | n := param2; |
||
1299 | OutByte2(81H + short(n), reg1); OutIntByte(n); // add dword[reg1], n |
||
1300 | drop |
||
1301 | |||
1302 | |CODE.opDECC: |
||
1303 | UnOp(reg1); |
||
1304 | n := param2; |
||
1305 | OutByte2(81H + short(n), 28H + reg1); OutIntByte(n); // sub dword[reg1], n |
||
1306 | drop |
||
1307 | |||
1308 | |CODE.opINC: |
||
1309 | BinOp(reg1, reg2); |
||
1310 | OutByte2(01H, reg1 * 8 + reg2); // add dword[reg2], reg1 |
||
1311 | drop; |
||
1312 | drop |
||
1313 | |||
1314 | |CODE.opDEC: |
||
1315 | BinOp(reg1, reg2); |
||
1316 | OutByte2(29H, reg1 * 8 + reg2); // sub dword[reg2], reg1 |
||
1317 | drop; |
||
1318 | drop |
||
1319 | |||
1320 | |CODE.opINC1B: |
||
1321 | UnOp(reg1); |
||
1322 | OutByte2(0FEH, reg1); // inc byte[reg1] |
||
1323 | drop |
||
1324 | |||
1325 | |CODE.opDEC1B: |
||
1326 | UnOp(reg1); |
||
1327 | OutByte2(0FEH, 08H + reg1); // dec byte[reg1] |
||
1328 | drop |
||
1329 | |||
1330 | |CODE.opINCCB: |
||
1331 | UnOp(reg1); |
||
1332 | OutByte3(80H, reg1, Byte(param2)); // add byte[reg1], n |
||
1333 | drop |
||
1334 | |||
1335 | |CODE.opDECCB: |
||
1336 | UnOp(reg1); |
||
1337 | OutByte3(80H, 28H + reg1, Byte(param2)); // sub byte[reg1], n |
||
1338 | drop |
||
1339 | |||
1340 | |CODE.opINCB, CODE.opDECB: |
||
1341 | BinOp(reg1, reg2); |
||
1342 | IF cmd.opcode = CODE.opINCB THEN |
||
1343 | OutByte2(00H, reg1 * 8 + reg2) // add byte[reg2], reg1 |
||
1344 | ELSE |
||
1345 | OutByte2(28H, reg1 * 8 + reg2) // sub byte[reg2], reg1 |
||
1346 | END; |
||
1347 | drop; |
||
1348 | drop |
||
1349 | |||
1350 | |CODE.opMULS: |
||
1351 | BinOp(reg1, reg2); |
||
1352 | OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 |
||
1353 | drop |
||
1354 | |||
1355 | |CODE.opMULSC: |
||
1356 | UnOp(reg1); |
||
1357 | andrc(reg1, param2) |
||
1358 | |||
1359 | |CODE.opDIVS: |
||
1360 | BinOp(reg1, reg2); |
||
7667 | akron1 | 1361 | xor(reg1, reg2); |
7597 | akron1 | 1362 | drop |
1363 | |||
1364 | |CODE.opDIVSC: |
||
1365 | UnOp(reg1); |
||
1366 | OutByte2(81H + short(param2), 0F0H + reg1); // xor reg1, n |
||
1367 | OutIntByte(param2) |
||
1368 | |||
1369 | |CODE.opADDS: |
||
1370 | BinOp(reg1, reg2); |
||
1371 | OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2 |
||
1372 | drop |
||
1373 | |||
1374 | |CODE.opSUBS: |
||
1375 | BinOp(reg1, reg2); |
||
1376 | not(reg2); |
||
1377 | OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 |
||
1378 | drop |
||
1379 | |||
1380 | |CODE.opADDSL, CODE.opADDSR: |
||
1381 | UnOp(reg1); |
||
1382 | orrc(reg1, param2) |
||
1383 | |||
1384 | |CODE.opSUBSL: |
||
1385 | UnOp(reg1); |
||
1386 | not(reg1); |
||
1387 | andrc(reg1, param2) |
||
1388 | |||
1389 | |CODE.opSUBSR: |
||
1390 | UnOp(reg1); |
||
1391 | andrc(reg1, ORD(-BITS(param2))); |
||
1392 | |||
1393 | |CODE.opUMINS: |
||
1394 | UnOp(reg1); |
||
1395 | not(reg1) |
||
1396 | |||
1397 | |CODE.opLENGTH: |
||
1398 | PushAll(2); |
||
1399 | CallRTL(pic, CODE._length); |
||
1400 | GetRegA |
||
1401 | |||
1402 | |CODE.opLENGTHW: |
||
1403 | PushAll(2); |
||
1404 | CallRTL(pic, CODE._lengthw); |
||
1405 | GetRegA |
||
1406 | |||
1407 | |CODE.opCHR: |
||
1408 | UnOp(reg1); |
||
1409 | andrc(reg1, 255) |
||
1410 | |||
1411 | |CODE.opWCHR: |
||
1412 | UnOp(reg1); |
||
1413 | andrc(reg1, 65535) |
||
1414 | |||
1415 | |CODE.opASR, CODE.opROR, CODE.opLSL, CODE.opLSR: |
||
1416 | UnOp(reg1); |
||
1417 | IF reg1 # ecx THEN |
||
1418 | ASSERT(REG.GetReg(R, ecx)); |
||
1419 | ASSERT(REG.Exchange(R, reg1, ecx)); |
||
1420 | drop |
||
1421 | END; |
||
1422 | |||
1423 | BinOp(reg1, reg2); |
||
1424 | ASSERT(reg2 = ecx); |
||
1425 | OutByte(0D3H); |
||
1426 | shift(cmd.opcode, reg1); // shift reg1, cl |
||
1427 | drop |
||
1428 | |||
1429 | |CODE.opASR1, CODE.opROR1, CODE.opLSL1, CODE.opLSR1: |
||
1430 | UnOp(reg1); |
||
1431 | IF reg1 # ecx THEN |
||
1432 | ASSERT(REG.GetReg(R, ecx)); |
||
1433 | ASSERT(REG.Exchange(R, reg1, ecx)); |
||
1434 | drop |
||
1435 | END; |
||
1436 | |||
1437 | reg1 := REG.GetAnyReg(R); |
||
1438 | movrc(reg1, param2); |
||
1439 | BinOp(reg1, reg2); |
||
1440 | ASSERT(reg1 = ecx); |
||
1441 | OutByte(0D3H); |
||
1442 | shift(cmd.opcode, reg2); // shift reg2, cl |
||
1443 | drop; |
||
1444 | drop; |
||
1445 | ASSERT(REG.GetReg(R, reg2)) |
||
1446 | |||
1447 | |CODE.opASR2, CODE.opROR2, CODE.opLSL2, CODE.opLSR2: |
||
1448 | UnOp(reg1); |
||
1449 | n := ORD(BITS(param2) * {0..4}); |
||
1450 | IF n # 1 THEN |
||
1451 | OutByte(0C1H) |
||
1452 | ELSE |
||
1453 | OutByte(0D1H) |
||
1454 | END; |
||
1455 | shift(cmd.opcode, reg1); // shift reg1, n |
||
1456 | IF n # 1 THEN |
||
1457 | OutByte(n) |
||
1458 | END |
||
1459 | |||
1460 | |CODE.opMIN: |
||
1461 | BinOp(reg1, reg2); |
||
1462 | cmprr(reg1, reg2); |
||
1463 | OutByte2(07EH, 002H); // jle @f |
||
1464 | mov(reg1, reg2); // mov reg1, reg2 |
||
1465 | // @@: |
||
1466 | drop |
||
1467 | |||
1468 | |CODE.opMAX: |
||
1469 | BinOp(reg1, reg2); |
||
1470 | cmprr(reg1, reg2); |
||
1471 | OutByte2(07DH, 002H); // jge @f |
||
1472 | mov(reg1, reg2); // mov reg1, reg2 |
||
1473 | // @@: |
||
1474 | drop |
||
1475 | |||
1476 | |CODE.opMINC: |
||
1477 | UnOp(reg1); |
||
1478 | cmprc(reg1, param2); |
||
1479 | OutByte2(07EH, 005H); // jle @f |
||
1480 | movrc(reg1, param2); // mov reg1, param2 |
||
1481 | // @@: |
||
1482 | |||
1483 | |CODE.opMAXC: |
||
1484 | UnOp(reg1); |
||
1485 | cmprc(reg1, param2); |
||
1486 | OutByte2(07DH, 005H); // jge @f |
||
1487 | movrc(reg1, param2); // mov reg1, param2 |
||
1488 | // @@: |
||
1489 | |||
1490 | |CODE.opIN: |
||
1491 | label := NewLabel(); |
||
1492 | BinOp(reg1, reg2); |
||
1493 | cmprc(reg1, 32); |
||
1494 | OutByte2(72H, 4); // jb L |
||
7667 | akron1 | 1495 | xor(reg1, reg1); |
7597 | akron1 | 1496 | jmp(label); |
1497 | //L: |
||
1498 | OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 |
||
1499 | setcc(setc, reg1); |
||
1500 | andrc(reg1, 1); |
||
1501 | SetLabel(label); |
||
1502 | drop |
||
1503 | |||
1504 | |CODE.opINR: |
||
1505 | label := NewLabel(); |
||
1506 | UnOp(reg1); |
||
1507 | reg2 := REG.GetAnyReg(R); |
||
1508 | cmprc(reg1, 32); |
||
1509 | OutByte2(72H, 4); // jb L |
||
7667 | akron1 | 1510 | xor(reg1, reg1); |
7597 | akron1 | 1511 | jmp(label); |
1512 | //L: |
||
1513 | movrc(reg2, param2); |
||
1514 | OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 |
||
1515 | setcc(setc, reg1); |
||
1516 | andrc(reg1, 1); |
||
1517 | SetLabel(label); |
||
1518 | drop |
||
1519 | |||
1520 | |CODE.opINL: |
||
1521 | UnOp(reg1); |
||
1522 | OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2 |
||
1523 | setcc(setc, reg1); |
||
1524 | andrc(reg1, 1) |
||
1525 | |||
1526 | |CODE.opRSET: |
||
1527 | PushAll(2); |
||
1528 | CallRTL(pic, CODE._set); |
||
1529 | GetRegA |
||
1530 | |||
1531 | |CODE.opRSETR: |
||
1532 | PushAll(1); |
||
1533 | pushc(param2); |
||
1534 | CallRTL(pic, CODE._set); |
||
1535 | GetRegA |
||
1536 | |||
1537 | |CODE.opRSETL: |
||
1538 | PushAll(1); |
||
1539 | pushc(param2); |
||
1540 | CallRTL(pic, CODE._set2); |
||
1541 | GetRegA |
||
1542 | |||
1543 | |CODE.opRSET1: |
||
1544 | UnOp(reg1); |
||
1545 | PushAll(1); |
||
1546 | push(reg1); |
||
1547 | CallRTL(pic, CODE._set); |
||
1548 | GetRegA |
||
1549 | |||
1550 | |CODE.opINCL, CODE.opEXCL: |
||
1551 | BinOp(reg1, reg2); |
||
1552 | cmprc(reg1, 32); |
||
1553 | OutByte2(73H, 03H); // jnb L |
||
1554 | OutByte(0FH); |
||
1555 | IF cmd.opcode = CODE.opINCL THEN |
||
1556 | OutByte(0ABH) // bts dword[reg2], reg1 |
||
1557 | ELSE |
||
1558 | OutByte(0B3H) // btr dword[reg2], reg1 |
||
1559 | END; |
||
1560 | OutByte(reg2 + 8 * reg1); |
||
1561 | //L: |
||
1562 | drop; |
||
1563 | drop |
||
1564 | |||
1565 | |CODE.opINCLC: |
||
1566 | UnOp(reg1); |
||
1567 | OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2 |
||
1568 | drop |
||
1569 | |||
1570 | |CODE.opEXCLC: |
||
1571 | UnOp(reg1); |
||
1572 | OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2 |
||
1573 | drop |
||
1574 | |||
1575 | |CODE.opDIV: |
||
1576 | PushAll(2); |
||
1577 | CallRTL(pic, CODE._div); |
||
1578 | GetRegA |
||
1579 | |||
1580 | |CODE.opDIVR: |
||
1581 | a := param2; |
||
1582 | IF a > 1 THEN |
||
1583 | n := log2(a) |
||
1584 | ELSIF a < -1 THEN |
||
1585 | n := log2(-a) |
||
1586 | ELSE |
||
1587 | n := -1 |
||
1588 | END; |
||
1589 | |||
1590 | IF a = 1 THEN |
||
1591 | |||
1592 | ELSIF a = -1 THEN |
||
1593 | UnOp(reg1); |
||
1594 | neg(reg1) |
||
1595 | ELSE |
||
1596 | IF n > 0 THEN |
||
1597 | UnOp(reg1); |
||
1598 | |||
1599 | IF a < 0 THEN |
||
1600 | reg2 := REG.GetAnyReg(R); |
||
1601 | mov(reg2, reg1); |
||
1602 | IF n # 1 THEN |
||
1603 | OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n |
||
1604 | ELSE |
||
1605 | OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 |
||
1606 | END; |
||
1607 | OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 |
||
1608 | drop |
||
1609 | ELSE |
||
1610 | IF n # 1 THEN |
||
1611 | OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n |
||
1612 | ELSE |
||
1613 | OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 |
||
1614 | END |
||
1615 | END |
||
1616 | |||
1617 | ELSE |
||
1618 | PushAll(1); |
||
1619 | pushc(param2); |
||
1620 | CallRTL(pic, CODE._div); |
||
1621 | GetRegA |
||
1622 | END |
||
1623 | END |
||
1624 | |||
1625 | |CODE.opDIVL: |
||
1626 | PushAll(1); |
||
1627 | pushc(param2); |
||
1628 | CallRTL(pic, CODE._div2); |
||
1629 | GetRegA |
||
1630 | |||
1631 | |CODE.opMOD: |
||
1632 | PushAll(2); |
||
1633 | CallRTL(pic, CODE._mod); |
||
1634 | GetRegA |
||
1635 | |||
1636 | |CODE.opMODR: |
||
1637 | a := param2; |
||
1638 | IF a > 1 THEN |
||
1639 | n := log2(a) |
||
1640 | ELSIF a < -1 THEN |
||
1641 | n := log2(-a) |
||
1642 | ELSE |
||
1643 | n := -1 |
||
1644 | END; |
||
1645 | |||
1646 | IF ABS(a) = 1 THEN |
||
1647 | UnOp(reg1); |
||
7667 | akron1 | 1648 | xor(reg1, reg1) |
7597 | akron1 | 1649 | ELSE |
1650 | IF n > 0 THEN |
||
1651 | UnOp(reg1); |
||
1652 | andrc(reg1, ABS(a) - 1); |
||
1653 | |||
1654 | IF a < 0 THEN |
||
1655 | test(reg1); |
||
1656 | OutByte(74H); // je @f |
||
1657 | IF isByte(a) THEN |
||
1658 | OutByte(3) |
||
1659 | ELSE |
||
1660 | OutByte(6) |
||
1661 | END; |
||
1662 | addrc(reg1, a) |
||
1663 | // @@: |
||
1664 | END |
||
1665 | |||
1666 | ELSE |
||
1667 | PushAll(1); |
||
1668 | pushc(param2); |
||
1669 | CallRTL(pic, CODE._mod); |
||
1670 | GetRegA |
||
1671 | END |
||
1672 | END |
||
1673 | |||
1674 | |CODE.opMODL: |
||
1675 | PushAll(1); |
||
1676 | pushc(param2); |
||
1677 | CallRTL(pic, CODE._mod2); |
||
1678 | GetRegA |
||
1679 | |||
1680 | |CODE.opERR: |
||
1681 | CallRTL(pic, CODE._error) |
||
1682 | |||
1683 | |CODE.opABS: |
||
1684 | UnOp(reg1); |
||
1685 | test(reg1); |
||
1686 | OutByte2(07DH, 002H); // jge @f |
||
1687 | neg(reg1); // neg reg1 |
||
1688 | // @@: |
||
1689 | |||
1690 | |CODE.opCOPY: |
||
1691 | PushAll(2); |
||
1692 | pushc(param2); |
||
1693 | CallRTL(pic, CODE._move2) |
||
1694 | |||
1695 | |CODE.opMOVE: |
||
1696 | PushAll(3); |
||
1697 | CallRTL(pic, CODE._move2) |
||
1698 | |||
1699 | |CODE.opCOPYA: |
||
1700 | PushAll(4); |
||
1701 | pushc(param2); |
||
1702 | CallRTL(pic, CODE._arrcpy); |
||
1703 | GetRegA |
||
1704 | |||
1705 | |CODE.opCOPYS: |
||
1706 | PushAll(4); |
||
1707 | pushc(param2); |
||
1708 | CallRTL(pic, CODE._strcpy) |
||
1709 | |||
1710 | |CODE.opCOPYS2: |
||
1711 | PushAll(4); |
||
1712 | pushc(param2); |
||
1713 | CallRTL(pic, CODE._strcpy2) |
||
1714 | |||
1715 | |CODE.opROT: |
||
1716 | PushAll(0); |
||
1717 | push(esp); |
||
1718 | pushc(param2); |
||
1719 | CallRTL(pic, CODE._rot) |
||
1720 | |||
1721 | |CODE.opNEW: |
||
1722 | PushAll(1); |
||
1723 | n := param2 + 8; |
||
1724 | ASSERT(MACHINE.Align(n, 32)); |
||
1725 | pushc(n); |
||
1726 | pushc(param1); |
||
1727 | CallRTL(pic, CODE._new) |
||
1728 | |||
1729 | |CODE.opDISP: |
||
1730 | PushAll(1); |
||
1731 | CallRTL(pic, CODE._dispose) |
||
1732 | |||
1733 | |CODE.opEQS .. CODE.opGES: |
||
1734 | PushAll(4); |
||
1735 | pushc(cmd.opcode - CODE.opEQS); |
||
1736 | CallRTL(pic, CODE._strcmp); |
||
1737 | GetRegA |
||
1738 | |||
1739 | |CODE.opEQS2 .. CODE.opGES2: |
||
1740 | PushAll(4); |
||
1741 | pushc(cmd.opcode - CODE.opEQS2); |
||
1742 | CallRTL(pic, CODE._strcmp2); |
||
1743 | GetRegA |
||
1744 | |||
1745 | |CODE.opEQSW .. CODE.opGESW: |
||
1746 | PushAll(4); |
||
1747 | pushc(cmd.opcode - CODE.opEQSW); |
||
1748 | CallRTL(pic, CODE._strcmpw); |
||
1749 | GetRegA |
||
1750 | |||
1751 | |CODE.opEQSW2 .. CODE.opGESW2: |
||
1752 | PushAll(4); |
||
1753 | pushc(cmd.opcode - CODE.opEQSW2); |
||
1754 | CallRTL(pic, CODE._strcmpw2); |
||
1755 | GetRegA |
||
1756 | |||
1757 | |CODE.opEQP, CODE.opNEP, CODE.opEQIP, CODE.opNEIP: |
||
1758 | UnOp(reg1); |
||
1759 | CASE cmd.opcode OF |
||
1760 | |CODE.opEQP, CODE.opNEP: |
||
1761 | IF pic THEN |
||
1762 | reg2 := REG.GetAnyReg(R); |
||
1763 | Pic(reg2, BIN.PICCODE, param1); |
||
1764 | cmprr(reg1, reg2); |
||
1765 | drop |
||
1766 | ELSE |
||
1767 | OutByte2(081H, 0F8H + reg1); // cmp reg1, L |
||
1768 | Reloc(BIN.RCODE, param1) |
||
1769 | END |
||
1770 | |||
1771 | |CODE.opEQIP, CODE.opNEIP: |
||
1772 | IF pic THEN |
||
1773 | reg2 := REG.GetAnyReg(R); |
||
1774 | Pic(reg2, BIN.PICIMP, param1); |
||
1775 | OutByte2(03BH, reg1 * 8 + reg2); //cmp reg1, dword [reg2] |
||
1776 | drop |
||
1777 | ELSE |
||
1778 | OutByte2(3BH, 05H + reg1 * 8); // cmp reg1, dword[L] |
||
1779 | Reloc(BIN.RIMP, param1) |
||
1780 | END |
||
1781 | |||
1782 | END; |
||
1783 | drop; |
||
1784 | reg1 := REG.GetAnyReg(R); |
||
1785 | |||
1786 | CASE cmd.opcode OF |
||
1787 | |CODE.opEQP, CODE.opEQIP: setcc(sete, reg1) |
||
1788 | |CODE.opNEP, CODE.opNEIP: setcc(setne, reg1) |
||
1789 | END; |
||
1790 | |||
1791 | andrc(reg1, 1) |
||
1792 | |||
1793 | |CODE.opPUSHT: |
||
1794 | UnOp(reg1); |
||
1795 | reg2 := REG.GetAnyReg(R); |
||
1796 | OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH) // mov reg2, dword[reg1 - 4] |
||
1797 | |||
1798 | |CODE.opISREC: |
||
1799 | PushAll(2); |
||
1800 | pushc(param2); |
||
1801 | CallRTL(pic, CODE._isrec); |
||
1802 | GetRegA |
||
1803 | |||
1804 | |CODE.opIS: |
||
1805 | PushAll(1); |
||
1806 | pushc(param2); |
||
1807 | CallRTL(pic, CODE._is); |
||
1808 | GetRegA |
||
1809 | |||
1810 | |CODE.opTYPEGR: |
||
1811 | PushAll(1); |
||
1812 | pushc(param2); |
||
1813 | CallRTL(pic, CODE._guardrec); |
||
1814 | GetRegA |
||
1815 | |||
1816 | |CODE.opTYPEGP: |
||
1817 | UnOp(reg1); |
||
1818 | PushAll(0); |
||
1819 | push(reg1); |
||
1820 | pushc(param2); |
||
1821 | CallRTL(pic, CODE._guard); |
||
1822 | GetRegA |
||
1823 | |||
1824 | |CODE.opTYPEGD: |
||
1825 | UnOp(reg1); |
||
1826 | PushAll(0); |
||
1827 | OutByte3(0FFH, 070H + reg1, 0FCH); // push dword[reg1 - 4] |
||
1828 | pushc(param2); |
||
1829 | CallRTL(pic, CODE._guardrec); |
||
1830 | GetRegA |
||
1831 | |||
1832 | |CODE.opCASET: |
||
1833 | push(ecx); |
||
1834 | push(ecx); |
||
1835 | pushc(param2); |
||
1836 | CallRTL(pic, CODE._guardrec); |
||
1837 | pop(ecx); |
||
1838 | test(eax); |
||
1839 | jcc(jne, param1) |
||
1840 | |||
1841 | |CODE.opPACK: |
||
1842 | BinOp(reg1, reg2); |
||
1843 | push(reg2); |
||
1844 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1845 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1846 | OutByte2(0D9H, 0FDH); // fscale |
||
1847 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1848 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
1849 | pop(reg2); |
||
1850 | drop; |
||
1851 | drop |
||
1852 | |||
1853 | |CODE.opPACKC: |
||
1854 | UnOp(reg1); |
||
1855 | pushc(param2); |
||
1856 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1857 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1858 | OutByte2(0D9H, 0FDH); // fscale |
||
1859 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1860 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
1861 | pop(reg1); |
||
1862 | drop |
||
1863 | |||
1864 | |CODE.opUNPK: |
||
1865 | BinOp(reg1, reg2); |
||
1866 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1867 | OutByte2(0D9H, 0F4H); // fxtract |
||
1868 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1869 | OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] |
||
1870 | drop; |
||
1871 | drop |
||
1872 | |||
1873 | |CODE.opPUSHF: |
||
1874 | subrc(esp, 8); |
||
1875 | OutByte3(0DDH, 01CH, 024H) // fstp qword[esp] |
||
1876 | |||
1877 | |CODE.opLOADF: |
||
1878 | UnOp(reg1); |
||
1879 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1880 | drop |
||
1881 | |||
1882 | |CODE.opCONSTF: |
||
1883 | float := cmd.float; |
||
1884 | IF float = 0.0 THEN |
||
1885 | OutByte2(0D9H, 0EEH) // fldz |
||
1886 | ELSIF float = 1.0 THEN |
||
1887 | OutByte2(0D9H, 0E8H) // fld1 |
||
1888 | ELSIF float = -1.0 THEN |
||
1889 | OutByte2(0D9H, 0E8H); // fld1 |
||
1890 | OutByte2(0D9H, 0E0H) // fchs |
||
1891 | ELSE |
||
1892 | n := UTILS.splitf(float, a, b); |
||
1893 | pushc(b); |
||
1894 | pushc(a); |
||
1895 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
1896 | addrc(esp, 8) |
||
1897 | END |
||
1898 | |||
1899 | |CODE.opSAVEF: |
||
1900 | UnOp(reg1); |
||
1901 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1902 | drop |
||
1903 | |||
1904 | |CODE.opADDF, CODE.opADDFI: |
||
1905 | OutByte2(0DEH, 0C1H) // faddp st1, st |
||
1906 | |||
1907 | |CODE.opSUBF: |
||
1908 | OutByte2(0DEH, 0E9H) // fsubp st1, st |
||
1909 | |||
1910 | |CODE.opSUBFI: |
||
1911 | OutByte2(0DEH, 0E1H) // fsubrp st1, st |
||
1912 | |||
1913 | |CODE.opMULF: |
||
1914 | OutByte2(0DEH, 0C9H) // fmulp st1, st |
||
1915 | |||
1916 | |CODE.opDIVF: |
||
1917 | OutByte2(0DEH, 0F9H) // fdivp st1, st |
||
1918 | |||
1919 | |CODE.opDIVFI: |
||
1920 | OutByte2(0DEH, 0F1H) // fdivrp st1, st |
||
1921 | |||
1922 | |CODE.opUMINF: |
||
1923 | OutByte2(0D9H, 0E0H) // fchs |
||
1924 | |||
1925 | |CODE.opFABS: |
||
1926 | OutByte2(0D9H, 0E1H) // fabs |
||
1927 | |||
1928 | |CODE.opFLT: |
||
1929 | UnOp(reg1); |
||
1930 | push(reg1); |
||
1931 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1932 | pop(reg1); |
||
1933 | drop |
||
1934 | |||
1935 | |CODE.opFLOOR: |
||
1936 | reg1 := REG.GetAnyReg(R); |
||
1937 | subrc(esp, 8); |
||
1938 | OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); // fstcw word[esp+4] |
||
1939 | OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); // fstcw word[esp+6] |
||
1940 | OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); // and word[esp+4], 1111001111111111b |
||
1941 | OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); // or word[esp+4], 0000010000000000b |
||
1942 | OutByte2(0D9H, 06CH); OutByte2(024H, 004H); // fldcw word[esp+4] |
||
1943 | OutByte2(0D9H, 0FCH); // frndint |
||
1944 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
1945 | pop(reg1); |
||
1946 | OutByte2(0D9H, 06CH); OutByte2(024H, 002H); // fldcw word[esp+2] |
||
1947 | addrc(esp, 4) |
||
1948 | |||
1949 | |CODE.opEQF, CODE.opEQFI: |
||
1950 | GetRegA; |
||
1951 | OutByte2(0DAH, 0E9H); // fucompp |
||
1952 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1953 | OutByte(09EH); // sahf |
||
1954 | movrc(eax, 0); |
||
1955 | OutByte2(07AH, 003H); // jp L |
||
1956 | setcc(sete, al) |
||
1957 | // L: |
||
1958 | |||
1959 | |CODE.opNEF, CODE.opNEFI: |
||
1960 | GetRegA; |
||
1961 | OutByte2(0DAH, 0E9H); // fucompp |
||
1962 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1963 | OutByte(09EH); // sahf |
||
1964 | movrc(eax, 0); |
||
1965 | OutByte2(07AH, 003H); // jp L |
||
1966 | setcc(setne, al) |
||
1967 | // L: |
||
1968 | |||
1969 | |CODE.opLTF, CODE.opGTFI: |
||
1970 | GetRegA; |
||
1971 | OutByte2(0DAH, 0E9H); // fucompp |
||
1972 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1973 | OutByte(09EH); // sahf |
||
1974 | movrc(eax, 0); |
||
1975 | OutByte2(07AH, 00EH); // jp L |
||
1976 | setcc(setc, al); |
||
1977 | setcc(sete, ah); |
||
1978 | test(eax); |
||
1979 | setcc(sete, al); |
||
1980 | andrc(eax, 1) |
||
1981 | // L: |
||
1982 | |||
1983 | |CODE.opGTF, CODE.opLTFI: |
||
1984 | GetRegA; |
||
1985 | OutByte2(0DAH, 0E9H); // fucompp |
||
1986 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1987 | OutByte(09EH); // sahf |
||
1988 | movrc(eax, 0); |
||
1989 | OutByte2(07AH, 00FH); // jp L |
||
1990 | setcc(setc, al); |
||
1991 | setcc(sete, ah); |
||
1992 | cmprc(eax, 1); |
||
1993 | setcc(sete, al); |
||
1994 | andrc(eax, 1) |
||
1995 | // L: |
||
1996 | |||
1997 | |CODE.opLEF, CODE.opGEFI: |
||
1998 | GetRegA; |
||
1999 | OutByte2(0DAH, 0E9H); // fucompp |
||
2000 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
2001 | OutByte(09EH); // sahf |
||
2002 | movrc(eax, 0); |
||
2003 | OutByte2(07AH, 003H); // jp L |
||
2004 | setcc(setnc, al) |
||
2005 | // L: |
||
2006 | |||
2007 | |CODE.opGEF, CODE.opLEFI: |
||
2008 | GetRegA; |
||
2009 | OutByte2(0DAH, 0E9H); // fucompp |
||
2010 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
2011 | OutByte(09EH); // sahf |
||
2012 | movrc(eax, 0); |
||
2013 | OutByte2(07AH, 010H); // jp L |
||
2014 | setcc(setc, al); |
||
2015 | setcc(sete, ah); |
||
2016 | OutByte2(000H, 0E0H); // add al,ah |
||
2017 | OutByte2(03CH, 001H); // cmp al,1 |
||
2018 | setcc(sete, al); |
||
2019 | andrc(eax, 1) |
||
2020 | // L: |
||
2021 | |||
2022 | |CODE.opINF: |
||
2023 | pushc(7FF00000H); |
||
2024 | pushc(0); |
||
2025 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
2026 | addrc(esp, 8) |
||
2027 | |||
2028 | |CODE.opLADR_UNPK: |
||
2029 | n := param2 * 4; |
||
2030 | reg1 := REG.GetAnyReg(R); |
||
2031 | OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] |
||
2032 | OutIntByte(n); |
||
2033 | BinOp(reg1, reg2); |
||
2034 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
2035 | OutByte2(0D9H, 0F4H); // fxtract |
||
2036 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
2037 | OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] |
||
2038 | drop; |
||
2039 | drop |
||
2040 | |||
2041 | |CODE.opSADR_PARAM: |
||
2042 | IF pic THEN |
||
2043 | reg1 := REG.GetAnyReg(R); |
||
2044 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
||
2045 | push(reg1); |
||
2046 | drop |
||
2047 | ELSE |
||
2048 | OutByte(068H); // push _data + stroffs + param2 |
||
2049 | Reloc(BIN.RDATA, stroffs + param2) |
||
2050 | END |
||
2051 | |||
2052 | |CODE.opVADR_PARAM: |
||
2053 | n := param2 * 4; |
||
2054 | OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] |
||
2055 | OutIntByte(n) |
||
2056 | |||
2057 | |CODE.opCONST_PARAM: |
||
2058 | pushc(param2) |
||
2059 | |||
2060 | |CODE.opGLOAD32_PARAM: |
||
2061 | IF pic THEN |
||
2062 | reg1 := REG.GetAnyReg(R); |
||
2063 | Pic(reg1, BIN.PICBSS, param2); |
||
2064 | OutByte2(0FFH, 30H + reg1); // push dword[reg1] |
||
2065 | drop |
||
2066 | ELSE |
||
2067 | OutByte2(0FFH, 035H); // push dword[_bss + param2] |
||
2068 | Reloc(BIN.RBSS, param2) |
||
2069 | END |
||
2070 | |||
2071 | |CODE.opLLOAD32_PARAM: |
||
2072 | n := param2 * 4; |
||
2073 | OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] |
||
2074 | OutIntByte(n) |
||
2075 | |||
2076 | |CODE.opLOAD32_PARAM: |
||
2077 | UnOp(reg1); |
||
2078 | OutByte2(0FFH, 30H + reg1); // push dword[reg1] |
||
2079 | drop |
||
2080 | |||
2081 | |CODE.opGADR_SAVEC: |
||
2082 | IF pic THEN |
||
2083 | reg1 := REG.GetAnyReg(R); |
||
2084 | Pic(reg1, BIN.PICBSS, param1); |
||
2085 | OutByte2(0C7H, reg1); // mov dword[reg1], param2 |
||
2086 | OutInt(param2); |
||
2087 | drop |
||
2088 | ELSE |
||
2089 | OutByte2(0C7H, 05H); // mov dword[_bss + param2], param2 |
||
2090 | Reloc(BIN.RBSS, param1); |
||
2091 | OutInt(param2) |
||
2092 | END |
||
2093 | |||
2094 | |CODE.opLADR_SAVEC: |
||
2095 | n := param1 * 4; |
||
2096 | OutByte2(0C7H, 45H + long(n)); // mov dword[ebp + n], param2 |
||
2097 | OutIntByte(n); |
||
2098 | OutInt(param2) |
||
2099 | |||
2100 | |CODE.opLADR_SAVE: |
||
2101 | n := param2 * 4; |
||
2102 | UnOp(reg1); |
||
2103 | OutByte2(89H, 45H + reg1 * 8 + long(n)); // mov dword[ebp + n], reg1 |
||
2104 | OutIntByte(n); |
||
2105 | drop |
||
2106 | |||
2107 | |CODE.opLADR_INC1: |
||
2108 | n := param2 * 4; |
||
2109 | OutByte2(0FFH, 45H + long(n)); // inc dword[ebp + n] |
||
2110 | OutIntByte(n) |
||
2111 | |||
2112 | |CODE.opLADR_DEC1: |
||
2113 | n := param2 * 4; |
||
2114 | OutByte2(0FFH, 4DH + long(n)); // dec dword[ebp + n] |
||
2115 | OutIntByte(n) |
||
2116 | |||
2117 | |CODE.opLADR_INCC: |
||
2118 | n := param1 * 4; |
||
2119 | OutByte2(81H + short(param2), 45H + long(n)); // add dword[ebp + n], param2 |
||
2120 | OutIntByte(n); |
||
2121 | OutIntByte(param2) |
||
2122 | |||
2123 | |CODE.opLADR_DECC: |
||
2124 | n := param1 * 4; |
||
2125 | OutByte2(81H + short(param2), 6DH + long(n)); // sub dword[ebp + n], param2 |
||
2126 | OutIntByte(n); |
||
2127 | OutIntByte(param2) |
||
2128 | |||
2129 | |CODE.opLADR_INC1B: |
||
2130 | n := param2 * 4; |
||
2131 | OutByte2(0FEH, 45H + long(n)); // inc byte[ebp + n] |
||
2132 | OutIntByte(n) |
||
2133 | |||
2134 | |CODE.opLADR_DEC1B: |
||
2135 | n := param2 * 4; |
||
2136 | OutByte2(0FEH, 4DH + long(n)); // dec byte[ebp + n] |
||
2137 | OutIntByte(n) |
||
2138 | |||
2139 | |CODE.opLADR_INCCB: |
||
2140 | n := param1 * 4; |
||
2141 | OutByte2(80H, 45H + long(n)); // add byte[ebp + n], param2 |
||
2142 | OutIntByte(n); |
||
2143 | OutByte(param2 MOD 256) |
||
2144 | |||
2145 | |CODE.opLADR_DECCB: |
||
2146 | n := param1 * 4; |
||
2147 | OutByte2(80H, 6DH + long(n)); // sub byte[ebp + n], param2 |
||
2148 | OutIntByte(n); |
||
2149 | OutByte(param2 MOD 256) |
||
2150 | |||
2151 | |CODE.opLADR_INC: |
||
2152 | n := param2 * 4; |
||
2153 | UnOp(reg1); |
||
2154 | OutByte2(01H, 45H + long(n) + reg1 * 8); // add dword[ebp + n], reg1 |
||
2155 | OutIntByte(n); |
||
2156 | drop |
||
2157 | |||
2158 | |CODE.opLADR_DEC: |
||
2159 | n := param2 * 4; |
||
2160 | UnOp(reg1); |
||
2161 | OutByte2(29H, 45H + long(n) + reg1 * 8); // sub dword[ebp + n], reg1 |
||
2162 | OutIntByte(n); |
||
2163 | drop |
||
2164 | |||
2165 | |CODE.opLADR_INCB: |
||
2166 | n := param2 * 4; |
||
2167 | UnOp(reg1); |
||
2168 | OutByte2(00H, 45H + long(n) + reg1 * 8); // add byte[ebp + n], reg1 |
||
2169 | OutIntByte(n); |
||
2170 | drop |
||
2171 | |||
2172 | |CODE.opLADR_DECB: |
||
2173 | n := param2 * 4; |
||
2174 | UnOp(reg1); |
||
2175 | OutByte2(28H, 45H + long(n) + reg1 * 8); // sub byte[ebp + n], reg1 |
||
2176 | OutIntByte(n); |
||
2177 | drop |
||
2178 | |||
2179 | |CODE.opLADR_INCL, CODE.opLADR_EXCL: |
||
2180 | n := param2 * 4; |
||
2181 | UnOp(reg1); |
||
2182 | cmprc(reg1, 32); |
||
2183 | label := NewLabel(); |
||
2184 | jcc(jnb, label); |
||
2185 | OutByte3(0FH, 0ABH + 8 * ORD(cmd.opcode = CODE.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1 |
||
2186 | OutIntByte(n); |
||
2187 | SetLabel(label); |
||
2188 | drop |
||
2189 | |||
2190 | |CODE.opLADR_INCLC, CODE.opLADR_EXCLC: |
||
2191 | n := param1 * 4; |
||
2192 | OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(cmd.opcode = CODE.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2 |
||
2193 | OutIntByte(n); |
||
2194 | OutByte(param2) |
||
2195 | |||
2196 | |CODE.opLOOP, CODE.opENDLOOP: |
||
2197 | |||
6613 | leency | 2198 | END; |
7597 | akron1 | 2199 | |
2200 | cmd := cmd.next(COMMAND) |
||
6613 | leency | 2201 | END; |
2202 | |||
7597 | akron1 | 2203 | ASSERT(R.pushed = 0); |
2204 | ASSERT(R.top = -1) |
||
6613 | leency | 2205 | |
7597 | akron1 | 2206 | END translate; |
6613 | leency | 2207 | |
2208 | |||
7597 | akron1 | 2209 | PROCEDURE prolog (code: CODE.CODES; pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER); |
2210 | VAR |
||
2211 | reg1, entry, tcount, dcount: INTEGER; |
||
6613 | leency | 2212 | |
7597 | akron1 | 2213 | BEGIN |
6613 | leency | 2214 | |
7597 | akron1 | 2215 | entry := NewLabel(); |
2216 | SetLabel(entry); |
||
6613 | leency | 2217 | |
7597 | akron1 | 2218 | IF target = mConst.Target_iDLL THEN |
2219 | push(ebp); |
||
2220 | mov(ebp, esp); |
||
2221 | OutByte3(0FFH, 75H, 16); // push dword[ebp+16] |
||
2222 | OutByte3(0FFH, 75H, 12); // push dword[ebp+12] |
||
2223 | OutByte3(0FFH, 75H, 8); // push dword[ebp+8] |
||
2224 | CallRTL(pic, CODE._dllentry); |
||
2225 | test(eax); |
||
2226 | jcc(je, dllret) |
||
2227 | ELSIF target = mConst.Target_iObject THEN |
||
2228 | SetLabel(dllinit) |
||
2229 | END; |
||
6613 | leency | 2230 | |
7597 | akron1 | 2231 | IF target = mConst.Target_iKolibri THEN |
2232 | reg1 := REG.GetAnyReg(R); |
||
2233 | Pic(reg1, BIN.IMPTAB, 0); |
||
2234 | push(reg1); // push IMPORT |
||
2235 | drop |
||
2236 | ELSIF target = mConst.Target_iObject THEN |
||
2237 | OutByte(68H); // push IMPORT |
||
2238 | Reloc(BIN.IMPTAB, 0) |
||
2239 | ELSIF target = mConst.Target_iELF32 THEN |
||
2240 | push(esp) |
||
2241 | ELSE |
||
2242 | pushc(0) |
||
7667 | akron1 | 2243 | END; |
2244 | |||
7597 | akron1 | 2245 | IF pic THEN |
2246 | reg1 := REG.GetAnyReg(R); |
||
2247 | Pic(reg1, BIN.PICCODE, entry); |
||
2248 | push(reg1); // push CODE |
||
2249 | drop |
||
2250 | ELSE |
||
2251 | OutByte(68H); // push CODE |
||
2252 | Reloc(BIN.RCODE, entry) |
||
2253 | END; |
||
6613 | leency | 2254 | |
7597 | akron1 | 2255 | IF pic THEN |
2256 | reg1 := REG.GetAnyReg(R); |
||
2257 | Pic(reg1, BIN.PICDATA, 0); |
||
2258 | push(reg1); // push _data |
||
2259 | drop |
||
2260 | ELSE |
||
2261 | OutByte(68H); // push _data |
||
2262 | Reloc(BIN.RDATA, 0) |
||
2263 | END; |
||
6613 | leency | 2264 | |
7597 | akron1 | 2265 | tcount := CHL.Length(code.types); |
2266 | dcount := CHL.Length(code.data); |
||
6613 | leency | 2267 | |
7597 | akron1 | 2268 | pushc(tcount); |
6613 | leency | 2269 | |
7597 | akron1 | 2270 | IF pic THEN |
2271 | reg1 := REG.GetAnyReg(R); |
||
2272 | Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); |
||
2273 | push(reg1); // push _data + tcount * 4 + dcount |
||
2274 | drop |
||
2275 | ELSE |
||
2276 | OutByte(68H); // push _data |
||
2277 | Reloc(BIN.RDATA, tcount * 4 + dcount) |
||
2278 | END; |
||
6613 | leency | 2279 | |
7597 | akron1 | 2280 | CallRTL(pic, CODE._init) |
2281 | END prolog; |
||
6613 | leency | 2282 | |
2283 | |||
7597 | akron1 | 2284 | PROCEDURE epilog (code: CODE.CODES; pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret: INTEGER); |
2285 | VAR |
||
2286 | i, n: INTEGER; |
||
2287 | exp: CODE.EXPORT_PROC; |
||
2288 | path, name, ext: PATHS.PATH; |
||
6613 | leency | 2289 | |
7597 | akron1 | 2290 | tcount, dcount: INTEGER; |
6613 | leency | 2291 | |
7597 | akron1 | 2292 | |
2293 | PROCEDURE import (imp: LISTS.LIST); |
||
2294 | VAR |
||
2295 | lib: CODE.IMPORT_LIB; |
||
2296 | proc: CODE.IMPORT_PROC; |
||
2297 | |||
2298 | BEGIN |
||
2299 | |||
2300 | lib := imp.first(CODE.IMPORT_LIB); |
||
2301 | WHILE lib # NIL DO |
||
2302 | BIN.Import(program, lib.name, 0); |
||
2303 | proc := lib.procs.first(CODE.IMPORT_PROC); |
||
2304 | WHILE proc # NIL DO |
||
2305 | BIN.Import(program, proc.name, proc.label); |
||
2306 | proc := proc.next(CODE.IMPORT_PROC) |
||
2307 | END; |
||
2308 | lib := lib.next(CODE.IMPORT_LIB) |
||
2309 | END |
||
2310 | |||
2311 | END import; |
||
2312 | |||
2313 | |||
6613 | leency | 2314 | BEGIN |
2315 | |||
7597 | akron1 | 2316 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN |
2317 | pushc(0); |
||
2318 | CallRTL(pic, CODE._exit); |
||
2319 | ELSIF target = mConst.Target_iDLL THEN |
||
2320 | SetLabel(dllret); |
||
2321 | movrc(eax, 1); |
||
2322 | OutByte(0C9H); // leave |
||
2323 | OutByte3(0C2H, 0CH, 0) // ret 12 |
||
2324 | ELSIF target = mConst.Target_iObject THEN |
||
2325 | movrc(eax, 1); |
||
2326 | OutByte(0C3H) // ret |
||
2327 | END; |
||
6613 | leency | 2328 | |
7597 | akron1 | 2329 | fixup; |
2330 | |||
2331 | tcount := CHL.Length(code.types); |
||
2332 | dcount := CHL.Length(code.data); |
||
2333 | |||
2334 | FOR i := 0 TO tcount - 1 DO |
||
2335 | BIN.PutData32LE(program, CHL.GetInt(code.types, i)) |
||
6613 | leency | 2336 | END; |
2337 | |||
7597 | akron1 | 2338 | FOR i := 0 TO dcount - 1 DO |
2339 | BIN.PutData(program, CHL.GetByte(code.data, i)) |
||
6613 | leency | 2340 | END; |
2341 | |||
7597 | akron1 | 2342 | program.modname := CHL.Length(program.data); |
6613 | leency | 2343 | |
7597 | akron1 | 2344 | PATHS.split(modname, path, name, ext); |
2345 | BIN.PutDataStr(program, name); |
||
2346 | BIN.PutDataStr(program, ext); |
||
2347 | BIN.PutData(program, 0); |
||
6613 | leency | 2348 | |
7597 | akron1 | 2349 | IF target = mConst.Target_iObject THEN |
2350 | BIN.Export(program, "lib_init", dllinit); |
||
2351 | END; |
||
6613 | leency | 2352 | |
7597 | akron1 | 2353 | exp := code.export.first(CODE.EXPORT_PROC); |
2354 | WHILE exp # NIL DO |
||
2355 | BIN.Export(program, exp.name, exp.label); |
||
2356 | exp := exp.next(CODE.EXPORT_PROC) |
||
6613 | leency | 2357 | END; |
2358 | |||
7597 | akron1 | 2359 | import(code.import); |
6613 | leency | 2360 | |
7597 | akron1 | 2361 | n := code.dmin - CHL.Length(code.data); |
2362 | IF n > 0 THEN |
||
2363 | INC(code.bss, n) |
||
6613 | leency | 2364 | END; |
2365 | |||
7597 | akron1 | 2366 | BIN.SetParams(program, MAX(code.bss, 4), stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)); |
2367 | |||
2368 | END epilog; |
||
2369 | |||
2370 | |||
2371 | PROCEDURE CodeGen* (code: CODE.CODES; outname: ARRAY OF CHAR; target, stack, base, ver: INTEGER; pic: BOOLEAN); |
||
2372 | VAR |
||
2373 | dllret, dllinit: INTEGER; |
||
2374 | |||
6613 | leency | 2375 | BEGIN |
2376 | |||
7597 | akron1 | 2377 | CodeList := LISTS.create(NIL); |
2378 | |||
2379 | program := BIN.create(code.lcount); |
||
2380 | |||
2381 | dllinit := NewLabel(); |
||
2382 | dllret := NewLabel(); |
||
2383 | |||
2384 | IF target = mConst.Target_iObject THEN |
||
2385 | pic := FALSE |
||
6613 | leency | 2386 | END; |
7597 | akron1 | 2387 | |
2388 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32} THEN |
||
2389 | pic := TRUE |
||
2390 | END; |
||
2391 | |||
2392 | R := REG.Create(push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); |
||
2393 | |||
2394 | prolog(code, pic, target, stack, dllinit, dllret); |
||
2395 | translate(code, pic, CHL.Length(code.types) * 4); |
||
2396 | epilog(code, pic, outname, target, stack, ver, dllinit, dllret); |
||
2397 | |||
2398 | BIN.fixup(program); |
||
2399 | |||
2400 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN |
||
2401 | PE32.write(program, outname, base, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE) |
||
2402 | ELSIF target = mConst.Target_iKolibri THEN |
||
2403 | KOS.write(program, outname) |
||
2404 | ELSIF target = mConst.Target_iObject THEN |
||
2405 | MSCOFF.write(program, outname, ver) |
||
2406 | ELSIF target = mConst.Target_iELF32 THEN |
||
2407 | ELF.write(program, outname, FALSE) |
||
6613 | leency | 2408 | END |
2409 | |||
7597 | akron1 | 2410 | END CodeGen; |
7209 | akron1 | 2411 | |
7597 | akron1 | 2412 | |
2413 | PROCEDURE SetProgram* (prog: BIN.PROGRAM); |
||
7209 | akron1 | 2414 | BEGIN |
7597 | akron1 | 2415 | program := prog; |
2416 | CodeList := LISTS.create(NIL) |
||
2417 | END SetProgram; |
||
2418 | |||
2419 | |||
6613 | leency | 2420 | END X86.>>>>>>=>>=>=>=>=>> |