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