1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904 |
- /* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file
- *
- * For Intel x86 CPU and Microsoft Visual C++ compiler
- *
- * Last changed in libpng 1.2.6 - August 15, 2004
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2004 Glenn Randers-Pehrson
- * Copyright (c) 1998, Intel Corporation
- *
- * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
- * Interface to libpng contributed by Gilles Vollant, 1999
- *
- *
- * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d,
- * a sign error in the post-MMX cleanup code for each pixel_depth resulted
- * in bad pixels at the beginning of some rows of some images, and also
- * (due to out-of-range memory reads and writes) caused heap corruption
- * when compiled with MSVC 6.0. The error was fixed in version 1.0.4e.
- *
- * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916]
- *
- * [runtime MMX configuration, GRR 20010102]
- *
- */
- #define PNG_INTERNAL
- #include "png.h"
- #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)
- static int mmx_supported=2;
- int PNGAPI
- png_mmx_support(void)
- {
- int mmx_supported_local = 0;
- _asm {
- push ebx //CPUID will trash these
- push ecx
- push edx
- pushfd //Save Eflag to stack
- pop eax //Get Eflag from stack into eax
- mov ecx, eax //Make another copy of Eflag in ecx
- xor eax, 0x200000 //Toggle ID bit in Eflag [i.e. bit(21)]
- push eax //Save modified Eflag back to stack
- popfd //Restored modified value back to Eflag reg
- pushfd //Save Eflag to stack
- pop eax //Get Eflag from stack
- push ecx // save original Eflag to stack
- popfd // restore original Eflag
- xor eax, ecx //Compare the new Eflag with the original Eflag
- jz NOT_SUPPORTED //If the same, CPUID instruction is not supported,
- //skip following instructions and jump to
- //NOT_SUPPORTED label
- xor eax, eax //Set eax to zero
- _asm _emit 0x0f //CPUID instruction (two bytes opcode)
- _asm _emit 0xa2
- cmp eax, 1 //make sure eax return non-zero value
- jl NOT_SUPPORTED //If eax is zero, mmx not supported
- xor eax, eax //set eax to zero
- inc eax //Now increment eax to 1. This instruction is
- //faster than the instruction "mov eax, 1"
- _asm _emit 0x0f //CPUID instruction
- _asm _emit 0xa2
- and edx, 0x00800000 //mask out all bits but mmx bit(24)
- cmp edx, 0 // 0 = mmx not supported
- jz NOT_SUPPORTED // non-zero = Yes, mmx IS supported
- mov mmx_supported_local, 1 //set return value to 1
- NOT_SUPPORTED:
- mov eax, mmx_supported_local //move return value to eax
- pop edx //CPUID trashed these
- pop ecx
- pop ebx
- }
- //mmx_supported_local=0; // test code for force don't support MMX
- //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local);
- mmx_supported = mmx_supported_local;
- return mmx_supported_local;
- }
- /* Combines the row recently read in with the previous row.
- This routine takes care of alpha and transparency if requested.
- This routine also handles the two methods of progressive display
- of interlaced images, depending on the mask value.
- The mask value describes which pixels are to be combined with
- the row. The pattern always repeats every 8 pixels, so just 8
- bits are needed. A one indicates the pixel is to be combined; a
- zero indicates the pixel is to be skipped. This is in addition
- to any alpha or transparency value associated with the pixel. If
- you want all pixels to be combined, pass 0xff (255) in mask. */
- /* Use this routine for x86 platform - uses faster MMX routine if machine
- supports MMX */
- void /* PRIVATE */
- png_combine_row(png_structp png_ptr, png_bytep row, int mask)
- {
- #ifdef PNG_USE_LOCAL_ARRAYS
- const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
- #endif
- png_debug(1,"in png_combine_row_asm\n");
- if (mmx_supported == 2) {
- #if !defined(PNG_1_0_X)
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- #endif
- png_mmx_support();
- }
- if (mask == 0xff)
- {
- png_memcpy(row, png_ptr->row_buf + 1,
- (png_size_t)PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
- png_ptr->width));
- }
- /* GRR: add "else if (mask == 0)" case?
- * or does png_combine_row() not even get called in that case? */
- else
- {
- switch (png_ptr->row_info.pixel_depth)
- {
- case 1:
- {
- png_bytep sp;
- png_bytep dp;
- int s_inc, s_start, s_end;
- int m;
- int shift;
- png_uint_32 i;
- sp = png_ptr->row_buf + 1;
- dp = row;
- m = 0x80;
- #if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 7;
- s_inc = 1;
- }
- else
- #endif
- {
- s_start = 7;
- s_end = 0;
- s_inc = -1;
- }
- shift = s_start;
- for (i = 0; i < png_ptr->width; i++)
- {
- if (m & mask)
- {
- int value;
- value = (*sp >> shift) & 0x1;
- *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
- *dp |= (png_byte)(value << shift);
- }
- if (shift == s_end)
- {
- shift = s_start;
- sp++;
- dp++;
- }
- else
- shift += s_inc;
- if (m == 1)
- m = 0x80;
- else
- m >>= 1;
- }
- break;
- }
- case 2:
- {
- png_bytep sp;
- png_bytep dp;
- int s_start, s_end, s_inc;
- int m;
- int shift;
- png_uint_32 i;
- int value;
- sp = png_ptr->row_buf + 1;
- dp = row;
- m = 0x80;
- #if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 6;
- s_inc = 2;
- }
- else
- #endif
- {
- s_start = 6;
- s_end = 0;
- s_inc = -2;
- }
- shift = s_start;
- for (i = 0; i < png_ptr->width; i++)
- {
- if (m & mask)
- {
- value = (*sp >> shift) & 0x3;
- *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *dp |= (png_byte)(value << shift);
- }
- if (shift == s_end)
- {
- shift = s_start;
- sp++;
- dp++;
- }
- else
- shift += s_inc;
- if (m == 1)
- m = 0x80;
- else
- m >>= 1;
- }
- break;
- }
- case 4:
- {
- png_bytep sp;
- png_bytep dp;
- int s_start, s_end, s_inc;
- int m;
- int shift;
- png_uint_32 i;
- int value;
- sp = png_ptr->row_buf + 1;
- dp = row;
- m = 0x80;
- #if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 4;
- s_inc = 4;
- }
- else
- #endif
- {
- s_start = 4;
- s_end = 0;
- s_inc = -4;
- }
- shift = s_start;
- for (i = 0; i < png_ptr->width; i++)
- {
- if (m & mask)
- {
- value = (*sp >> shift) & 0xf;
- *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *dp |= (png_byte)(value << shift);
- }
- if (shift == s_end)
- {
- shift = s_start;
- sp++;
- dp++;
- }
- else
- shift += s_inc;
- if (m == 1)
- m = 0x80;
- else
- m >>= 1;
- }
- break;
- }
- case 8:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int m;
- int diff, unmask;
- __int64 mask0=0x0102040810204080;
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- #else
- if (mmx_supported)
- #endif
- {
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
- m = 0x80;
- unmask = ~mask;
- len = png_ptr->width &~7; //reduce to multiple of 8
- diff = png_ptr->width & 7; //amount lost
- _asm
- {
- movd mm7, unmask //load bit pattern
- psubb mm6,mm6 //zero mm6
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 //fill register with 8 masks
- movq mm0,mask0
- pand mm0,mm7 //nonzero if keep byte
- pcmpeqb mm0,mm6 //zeros->1s, v versa
- mov ecx,len //load length of line (pixels)
- mov esi,srcptr //load source
- mov ebx,dstptr //load dest
- cmp ecx,0 //lcr
- je mainloop8end
- mainloop8:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- pandn mm6,[ebx]
- por mm4,mm6
- movq [ebx],mm4
- add esi,8 //inc by 8 bytes processed
- add ebx,8
- sub ecx,8 //dec by 8 pixels processed
- ja mainloop8
- mainloop8end:
- mov ecx,diff
- cmp ecx,0
- jz end8
- mov edx,mask
- sal edx,24 //make low byte the high byte
- secondloop8:
- sal edx,1 //move high bit to CF
- jnc skip8 //if CF = 0
- mov al,[esi]
- mov [ebx],al
- skip8:
- inc esi
- inc ebx
- dec ecx
- jnz secondloop8
- end8:
- emms
- }
- }
- else /* mmx not supported - use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
- break;
- } // end 8 bpp
- case 16:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
- __int64 mask1=0x0101020204040808,
- mask0=0x1010202040408080;
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- #else
- if (mmx_supported)
- #endif
- {
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
- _asm
- {
- movd mm7, unmask //load bit pattern
- psubb mm6,mm6 //zero mm6
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 //fill register with 8 masks
- movq mm0,mask0
- movq mm1,mask1
- pand mm0,mm7
- pand mm1,mm7
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- mov ecx,len //load length of line
- mov esi,srcptr //load source
- mov ebx,dstptr //load dest
- cmp ecx,0 //lcr
- jz mainloop16end
- mainloop16:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- movq mm7,[ebx]
- pandn mm6,mm7
- por mm4,mm6
- movq [ebx],mm4
- movq mm5,[esi+8]
- pand mm5,mm1
- movq mm7,mm1
- movq mm6,[ebx+8]
- pandn mm7,mm6
- por mm5,mm7
- movq [ebx+8],mm5
- add esi,16 //inc by 16 bytes processed
- add ebx,16
- sub ecx,8 //dec by 8 pixels processed
- ja mainloop16
- mainloop16end:
- mov ecx,diff
- cmp ecx,0
- jz end16
- mov edx,mask
- sal edx,24 //make low byte the high byte
- secondloop16:
- sal edx,1 //move high bit to CF
- jnc skip16 //if CF = 0
- mov ax,[esi]
- mov [ebx],ax
- skip16:
- add esi,2
- add ebx,2
- dec ecx
- jnz secondloop16
- end16:
- emms
- }
- }
- else /* mmx not supported - use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
- break;
- } // end 16 bpp
- case 24:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
- __int64 mask2=0x0101010202020404, //24bpp
- mask1=0x0408080810101020,
- mask0=0x2020404040808080;
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- #else
- if (mmx_supported)
- #endif
- {
- _asm
- {
- movd mm7, unmask //load bit pattern
- psubb mm6,mm6 //zero mm6
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 //fill register with 8 masks
- movq mm0,mask0
- movq mm1,mask1
- movq mm2,mask2
- pand mm0,mm7
- pand mm1,mm7
- pand mm2,mm7
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- pcmpeqb mm2,mm6
- mov ecx,len //load length of line
- mov esi,srcptr //load source
- mov ebx,dstptr //load dest
- cmp ecx,0
- jz mainloop24end
- mainloop24:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- movq mm7,[ebx]
- pandn mm6,mm7
- por mm4,mm6
- movq [ebx],mm4
- movq mm5,[esi+8]
- pand mm5,mm1
- movq mm7,mm1
- movq mm6,[ebx+8]
- pandn mm7,mm6
- por mm5,mm7
- movq [ebx+8],mm5
- movq mm6,[esi+16]
- pand mm6,mm2
- movq mm4,mm2
- movq mm7,[ebx+16]
- pandn mm4,mm7
- por mm6,mm4
- movq [ebx+16],mm6
- add esi,24 //inc by 24 bytes processed
- add ebx,24
- sub ecx,8 //dec by 8 pixels processed
- ja mainloop24
- mainloop24end:
- mov ecx,diff
- cmp ecx,0
- jz end24
- mov edx,mask
- sal edx,24 //make low byte the high byte
- secondloop24:
- sal edx,1 //move high bit to CF
- jnc skip24 //if CF = 0
- mov ax,[esi]
- mov [ebx],ax
- xor eax,eax
- mov al,[esi+2]
- mov [ebx+2],al
- skip24:
- add esi,3
- add ebx,3
- dec ecx
- jnz secondloop24
- end24:
- emms
- }
- }
- else /* mmx not supported - use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
- break;
- } // end 24 bpp
- case 32:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
- __int64 mask3=0x0101010102020202, //32bpp
- mask2=0x0404040408080808,
- mask1=0x1010101020202020,
- mask0=0x4040404080808080;
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- #else
- if (mmx_supported)
- #endif
- {
- _asm
- {
- movd mm7, unmask //load bit pattern
- psubb mm6,mm6 //zero mm6
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 //fill register with 8 masks
- movq mm0,mask0
- movq mm1,mask1
- movq mm2,mask2
- movq mm3,mask3
- pand mm0,mm7
- pand mm1,mm7
- pand mm2,mm7
- pand mm3,mm7
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- pcmpeqb mm2,mm6
- pcmpeqb mm3,mm6
- mov ecx,len //load length of line
- mov esi,srcptr //load source
- mov ebx,dstptr //load dest
- cmp ecx,0 //lcr
- jz mainloop32end
- mainloop32:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- movq mm7,[ebx]
- pandn mm6,mm7
- por mm4,mm6
- movq [ebx],mm4
- movq mm5,[esi+8]
- pand mm5,mm1
- movq mm7,mm1
- movq mm6,[ebx+8]
- pandn mm7,mm6
- por mm5,mm7
- movq [ebx+8],mm5
- movq mm6,[esi+16]
- pand mm6,mm2
- movq mm4,mm2
- movq mm7,[ebx+16]
- pandn mm4,mm7
- por mm6,mm4
- movq [ebx+16],mm6
- movq mm7,[esi+24]
- pand mm7,mm3
- movq mm5,mm3
- movq mm4,[ebx+24]
- pandn mm5,mm4
- por mm7,mm5
- movq [ebx+24],mm7
- add esi,32 //inc by 32 bytes processed
- add ebx,32
- sub ecx,8 //dec by 8 pixels processed
- ja mainloop32
- mainloop32end:
- mov ecx,diff
- cmp ecx,0
- jz end32
- mov edx,mask
- sal edx,24 //make low byte the high byte
- secondloop32:
- sal edx,1 //move high bit to CF
- jnc skip32 //if CF = 0
- mov eax,[esi]
- mov [ebx],eax
- skip32:
- add esi,4
- add ebx,4
- dec ecx
- jnz secondloop32
- end32:
- emms
- }
- }
- else /* mmx _not supported - Use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
- break;
- } // end 32 bpp
- case 48:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
- __int64 mask5=0x0101010101010202,
- mask4=0x0202020204040404,
- mask3=0x0404080808080808,
- mask2=0x1010101010102020,
- mask1=0x2020202040404040,
- mask0=0x4040808080808080;
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- #else
- if (mmx_supported)
- #endif
- {
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
- _asm
- {
- movd mm7, unmask //load bit pattern
- psubb mm6,mm6 //zero mm6
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 //fill register with 8 masks
- movq mm0,mask0
- movq mm1,mask1
- movq mm2,mask2
- movq mm3,mask3
- movq mm4,mask4
- movq mm5,mask5
- pand mm0,mm7
- pand mm1,mm7
- pand mm2,mm7
- pand mm3,mm7
- pand mm4,mm7
- pand mm5,mm7
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- pcmpeqb mm2,mm6
- pcmpeqb mm3,mm6
- pcmpeqb mm4,mm6
- pcmpeqb mm5,mm6
- mov ecx,len //load length of line
- mov esi,srcptr //load source
- mov ebx,dstptr //load dest
- cmp ecx,0
- jz mainloop48end
- mainloop48:
- movq mm7,[esi]
- pand mm7,mm0
- movq mm6,mm0
- pandn mm6,[ebx]
- por mm7,mm6
- movq [ebx],mm7
- movq mm6,[esi+8]
- pand mm6,mm1
- movq mm7,mm1
- pandn mm7,[ebx+8]
- por mm6,mm7
- movq [ebx+8],mm6
- movq mm6,[esi+16]
- pand mm6,mm2
- movq mm7,mm2
- pandn mm7,[ebx+16]
- por mm6,mm7
- movq [ebx+16],mm6
- movq mm7,[esi+24]
- pand mm7,mm3
- movq mm6,mm3
- pandn mm6,[ebx+24]
- por mm7,mm6
- movq [ebx+24],mm7
- movq mm6,[esi+32]
- pand mm6,mm4
- movq mm7,mm4
- pandn mm7,[ebx+32]
- por mm6,mm7
- movq [ebx+32],mm6
- movq mm7,[esi+40]
- pand mm7,mm5
- movq mm6,mm5
- pandn mm6,[ebx+40]
- por mm7,mm6
- movq [ebx+40],mm7
- add esi,48 //inc by 32 bytes processed
- add ebx,48
- sub ecx,8 //dec by 8 pixels processed
- ja mainloop48
- mainloop48end:
- mov ecx,diff
- cmp ecx,0
- jz end48
- mov edx,mask
- sal edx,24 //make low byte the high byte
- secondloop48:
- sal edx,1 //move high bit to CF
- jnc skip48 //if CF = 0
- mov eax,[esi]
- mov [ebx],eax
- skip48:
- add esi,4
- add ebx,4
- dec ecx
- jnz secondloop48
- end48:
- emms
- }
- }
- else /* mmx _not supported - Use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
- break;
- } // end 48 bpp
- default:
- {
- png_bytep sptr;
- png_bytep dp;
- png_size_t pixel_bytes;
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- unsigned int i;
- register int disp = png_pass_inc[png_ptr->pass]; // get the offset
- register unsigned int incr1, initial_val, final_val;
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dp = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dp, sptr, pixel_bytes);
- sptr += incr1;
- dp += incr1;
- }
- break;
- }
- } /* end switch (png_ptr->row_info.pixel_depth) */
- } /* end if (non-trivial mask) */
- } /* end png_combine_row() */
- #if defined(PNG_READ_INTERLACING_SUPPORTED)
- void /* PRIVATE */
- png_do_read_interlace(png_structp png_ptr)
- {
- png_row_infop row_info = &(png_ptr->row_info);
- png_bytep row = png_ptr->row_buf + 1;
- int pass = png_ptr->pass;
- png_uint_32 transformations = png_ptr->transformations;
- #ifdef PNG_USE_LOCAL_ARRAYS
- const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
- #endif
- png_debug(1,"in png_do_read_interlace\n");
- if (mmx_supported == 2) {
- #if !defined(PNG_1_0_X)
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- #endif
- png_mmx_support();
- }
- if (row != NULL && row_info != NULL)
- {
- png_uint_32 final_width;
- final_width = row_info->width * png_pass_inc[pass];
- switch (row_info->pixel_depth)
- {
- case 1:
- {
- png_bytep sp, dp;
- int sshift, dshift;
- int s_start, s_end, s_inc;
- png_byte v;
- png_uint_32 i;
- int j;
- sp = row + (png_size_t)((row_info->width - 1) >> 3);
- dp = row + (png_size_t)((final_width - 1) >> 3);
- #if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (transformations & PNG_PACKSWAP)
- {
- sshift = (int)((row_info->width + 7) & 7);
- dshift = (int)((final_width + 7) & 7);
- s_start = 7;
- s_end = 0;
- s_inc = -1;
- }
- else
- #endif
- {
- sshift = 7 - (int)((row_info->width + 7) & 7);
- dshift = 7 - (int)((final_width + 7) & 7);
- s_start = 0;
- s_end = 7;
- s_inc = 1;
- }
- for (i = row_info->width; i; i--)
- {
- v = (png_byte)((*sp >> sshift) & 0x1);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
- if (dshift == s_end)
- {
- dshift = s_start;
- dp--;
- }
- else
- dshift += s_inc;
- }
- if (sshift == s_end)
- {
- sshift = s_start;
- sp--;
- }
- else
- sshift += s_inc;
- }
- break;
- }
- case 2:
- {
- png_bytep sp, dp;
- int sshift, dshift;
- int s_start, s_end, s_inc;
- png_uint_32 i;
- sp = row + (png_size_t)((row_info->width - 1) >> 2);
- dp = row + (png_size_t)((final_width - 1) >> 2);
- #if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (transformations & PNG_PACKSWAP)
- {
- sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
- dshift = (png_size_t)(((final_width + 3) & 3) << 1);
- s_start = 6;
- s_end = 0;
- s_inc = -2;
- }
- else
- #endif
- {
- sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
- dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
- s_start = 0;
- s_end = 6;
- s_inc = 2;
- }
- for (i = row_info->width; i; i--)
- {
- png_byte v;
- int j;
- v = (png_byte)((*sp >> sshift) & 0x3);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
- if (dshift == s_end)
- {
- dshift = s_start;
- dp--;
- }
- else
- dshift += s_inc;
- }
- if (sshift == s_end)
- {
- sshift = s_start;
- sp--;
- }
- else
- sshift += s_inc;
- }
- break;
- }
- case 4:
- {
- png_bytep sp, dp;
- int sshift, dshift;
- int s_start, s_end, s_inc;
- png_uint_32 i;
- sp = row + (png_size_t)((row_info->width - 1) >> 1);
- dp = row + (png_size_t)((final_width - 1) >> 1);
- #if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (transformations & PNG_PACKSWAP)
- {
- sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
- dshift = (png_size_t)(((final_width + 1) & 1) << 2);
- s_start = 4;
- s_end = 0;
- s_inc = -4;
- }
- else
- #endif
- {
- sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
- dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
- s_start = 0;
- s_end = 4;
- s_inc = 4;
- }
- for (i = row_info->width; i; i--)
- {
- png_byte v;
- int j;
- v = (png_byte)((*sp >> sshift) & 0xf);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
- if (dshift == s_end)
- {
- dshift = s_start;
- dp--;
- }
- else
- dshift += s_inc;
- }
- if (sshift == s_end)
- {
- sshift = s_start;
- sp--;
- }
- else
- sshift += s_inc;
- }
- break;
- }
- default: // This is the place where the routine is modified
- {
- __int64 const4 = 0x0000000000FFFFFF;
- // __int64 const5 = 0x000000FFFFFF0000; // unused...
- __int64 const6 = 0x00000000000000FF;
- png_bytep sptr, dp;
- png_uint_32 i;
- png_size_t pixel_bytes;
- int width = row_info->width;
- pixel_bytes = (row_info->pixel_depth >> 3);
- sptr = row + (width - 1) * pixel_bytes;
- dp = row + (final_width - 1) * pixel_bytes;
- // New code by Nirav Chhatrapati - Intel Corporation
- // sign fix by GRR
- // NOTE: there is NO MMX code for 48-bit and 64-bit images
- // use MMX routine if machine supports it
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)
- /* && mmx_supported */ )
- #else
- if (mmx_supported)
- #endif
- {
- if (pixel_bytes == 3)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width
- sub edi, 21 // (png_pass_inc[pass] - 1)*pixel_bytes
- loop_pass0:
- movd mm0, [esi] ; X X X X X v2 v1 v0
- pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0
- movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0
- psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0
- movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0
- psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0
- psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1
- por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0
- por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1
- movq mm3, mm0 ; v2 v1 v0 v2 v1 v0 v2 v1
- psllq mm0, 16 ; v0 v2 v1 v0 v2 v1 0 0
- movq mm4, mm3 ; v2 v1 v0 v2 v1 v0 v2 v1
- punpckhdq mm3, mm0 ; v0 v2 v1 v0 v2 v1 v0 v2
- movq [edi+16] , mm4
- psrlq mm0, 32 ; 0 0 0 0 v0 v2 v1 v0
- movq [edi+8] , mm3
- punpckldq mm0, mm4 ; v1 v0 v2 v1 v0 v2 v1 v0
- sub esi, 3
- movq [edi], mm0
- sub edi, 24
- //sub esi, 3
- dec ecx
- jnz loop_pass0
- EMMS
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width
- sub edi, 9 // (png_pass_inc[pass] - 1)*pixel_bytes
- loop_pass2:
- movd mm0, [esi] ; X X X X X v2 v1 v0
- pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0
- movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0
- psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0
- movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0
- psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0
- psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1
- por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0
- por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1
- movq [edi+4], mm0 ; move to memory
- psrlq mm0, 16 ; 0 0 v2 v1 v0 v2 v1 v0
- movd [edi], mm0 ; move to memory
- sub esi, 3
- sub edi, 12
- dec ecx
- jnz loop_pass2
- EMMS
- }
- }
- else if (width) /* && ((pass == 4) || (pass == 5)) */
- {
- int width_mmx = ((width >> 1) << 1) - 8;
- if (width_mmx < 0)
- width_mmx = 0;
- width -= width_mmx; // 8 or 9 pix, 24 or 27 bytes
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 3
- sub edi, 9
- loop_pass4:
- movq mm0, [esi] ; X X v2 v1 v0 v5 v4 v3
- movq mm7, mm0 ; X X v2 v1 v0 v5 v4 v3
- movq mm6, mm0 ; X X v2 v1 v0 v5 v4 v3
- psllq mm0, 24 ; v1 v0 v5 v4 v3 0 0 0
- pand mm7, const4 ; 0 0 0 0 0 v5 v4 v3
- psrlq mm6, 24 ; 0 0 0 X X v2 v1 v0
- por mm0, mm7 ; v1 v0 v5 v4 v3 v5 v4 v3
- movq mm5, mm6 ; 0 0 0 X X v2 v1 v0
- psllq mm6, 8 ; 0 0 X X v2 v1 v0 0
- movq [edi], mm0 ; move quad to memory
- psrlq mm5, 16 ; 0 0 0 0 0 X X v2
- pand mm5, const6 ; 0 0 0 0 0 0 0 v2
- por mm6, mm5 ; 0 0 X X v2 v1 v0 v2
- movd [edi+8], mm6 ; move double to memory
- sub esi, 6
- sub edi, 12
- sub ecx, 2
- jnz loop_pass4
- EMMS
- }
- }
- sptr -= width_mmx*3;
- dp -= width_mmx*6;
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, 3);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, 3);
- dp -= 3;
- }
- sptr -= 3;
- }
- }
- } /* end of pixel_bytes == 3 */
- else if (pixel_bytes == 1)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- int width_mmx = ((width >> 2) << 2);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub edi, 31
- sub esi, 3
- loop1_pass0:
- movd mm0, [esi] ; X X X X v0 v1 v2 v3
- movq mm1, mm0 ; X X X X v0 v1 v2 v3
- punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- movq mm2, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
- movq mm3, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
- punpckldq mm0, mm0 ; v3 v3 v3 v3 v3 v3 v3 v3
- punpckhdq mm3, mm3 ; v2 v2 v2 v2 v2 v2 v2 v2
- movq [edi], mm0 ; move to memory v3
- punpckhwd mm2, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1
- movq [edi+8], mm3 ; move to memory v2
- movq mm4, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1
- punpckldq mm2, mm2 ; v1 v1 v1 v1 v1 v1 v1 v1
- punpckhdq mm4, mm4 ; v0 v0 v0 v0 v0 v0 v0 v0
- movq [edi+16], mm2 ; move to memory v1
- movq [edi+24], mm4 ; move to memory v0
- sub esi, 4
- sub edi, 32
- sub ecx, 4
- jnz loop1_pass0
- EMMS
- }
- }
- sptr -= width_mmx;
- dp -= width_mmx*8;
- for (i = width; i; i--)
- {
- int j;
- /* I simplified this part in version 1.0.4e
- * here and in several other instances where
- * pixel_bytes == 1 -- GR-P
- *
- * Original code:
- *
- * png_byte v[8];
- * png_memcpy(v, sptr, pixel_bytes);
- * for (j = 0; j < png_pass_inc[pass]; j++)
- * {
- * png_memcpy(dp, v, pixel_bytes);
- * dp -= pixel_bytes;
- * }
- * sptr -= pixel_bytes;
- *
- * Replacement code is in the next three lines:
- */
- for (j = 0; j < png_pass_inc[pass]; j++)
- *dp-- = *sptr;
- sptr--;
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- int width_mmx = ((width >> 2) << 2);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub edi, 15
- sub esi, 3
- loop1_pass2:
- movd mm0, [esi] ; X X X X v0 v1 v2 v3
- punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
- punpckhwd mm1, mm1 ; v0 v0 v0 v0 v1 v1 v1 v1
- movq [edi], mm0 ; move to memory v2 and v3
- sub esi, 4
- movq [edi+8], mm1 ; move to memory v1 and v0
- sub edi, 16
- sub ecx, 4
- jnz loop1_pass2
- EMMS
- }
- }
- sptr -= width_mmx;
- dp -= width_mmx*4;
- for (i = width; i; i--)
- {
- int j;
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp-- = *sptr;
- }
- sptr --;
- }
- }
- else if (width) /* && ((pass == 4) || (pass == 5))) */
- {
- int width_mmx = ((width >> 3) << 3);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub edi, 15
- sub esi, 7
- loop1_pass4:
- movq mm0, [esi] ; v0 v1 v2 v3 v4 v5 v6 v7
- movq mm1, mm0 ; v0 v1 v2 v3 v4 v5 v6 v7
- punpcklbw mm0, mm0 ; v4 v4 v5 v5 v6 v6 v7 v7
- //movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- punpckhbw mm1, mm1 ;v0 v0 v1 v1 v2 v2 v3 v3
- movq [edi+8], mm1 ; move to memory v0 v1 v2 and v3
- sub esi, 8
- movq [edi], mm0 ; move to memory v4 v5 v6 and v7
- //sub esi, 4
- sub edi, 16
- sub ecx, 8
- jnz loop1_pass4
- EMMS
- }
- }
- sptr -= width_mmx;
- dp -= width_mmx*2;
- for (i = width; i; i--)
- {
- int j;
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp-- = *sptr;
- }
- sptr --;
- }
- }
- } /* end of pixel_bytes == 1 */
- else if (pixel_bytes == 2)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- int width_mmx = ((width >> 1) << 1);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 2
- sub edi, 30
- loop2_pass0:
- movd mm0, [esi] ; X X X X v1 v0 v3 v2
- punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2
- punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0
- movq [edi], mm0
- movq [edi + 8], mm0
- movq [edi + 16], mm1
- movq [edi + 24], mm1
- sub esi, 4
- sub edi, 32
- sub ecx, 2
- jnz loop2_pass0
- EMMS
- }
- }
- sptr -= (width_mmx*2 - 2); // sign fixed
- dp -= (width_mmx*16 - 2); // sign fixed
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 2;
- png_memcpy(v, sptr, 2);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 2;
- png_memcpy(dp, v, 2);
- }
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 2
- sub edi, 14
- loop2_pass2:
- movd mm0, [esi] ; X X X X v1 v0 v3 v2
- punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2
- punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0
- movq [edi], mm0
- sub esi, 4
- movq [edi + 8], mm1
- //sub esi, 4
- sub edi, 16
- sub ecx, 2
- jnz loop2_pass2
- EMMS
- }
- }
- sptr -= (width_mmx*2 - 2); // sign fixed
- dp -= (width_mmx*8 - 2); // sign fixed
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 2;
- png_memcpy(v, sptr, 2);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 2;
- png_memcpy(dp, v, 2);
- }
- }
- }
- else if (width) // pass == 4 or 5
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 2
- sub edi, 6
- loop2_pass4:
- movd mm0, [esi] ; X X X X v1 v0 v3 v2
- punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- sub esi, 4
- movq [edi], mm0
- sub edi, 8
- sub ecx, 2
- jnz loop2_pass4
- EMMS
- }
- }
- sptr -= (width_mmx*2 - 2); // sign fixed
- dp -= (width_mmx*4 - 2); // sign fixed
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 2;
- png_memcpy(v, sptr, 2);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 2;
- png_memcpy(dp, v, 2);
- }
- }
- }
- } /* end of pixel_bytes == 2 */
- else if (pixel_bytes == 4)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 4
- sub edi, 60
- loop4_pass0:
- movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
- movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
- punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
- punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
- movq [edi], mm0
- movq [edi + 8], mm0
- movq [edi + 16], mm0
- movq [edi + 24], mm0
- movq [edi+32], mm1
- movq [edi + 40], mm1
- movq [edi+ 48], mm1
- sub esi, 8
- movq [edi + 56], mm1
- sub edi, 64
- sub ecx, 2
- jnz loop4_pass0
- EMMS
- }
- }
- sptr -= (width_mmx*4 - 4); // sign fixed
- dp -= (width_mmx*32 - 4); // sign fixed
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 4;
- png_memcpy(v, sptr, 4);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 4;
- png_memcpy(dp, v, 4);
- }
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 4
- sub edi, 28
- loop4_pass2:
- movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
- movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
- punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
- punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
- movq [edi], mm0
- movq [edi + 8], mm0
- movq [edi+16], mm1
- movq [edi + 24], mm1
- sub esi, 8
- sub edi, 32
- sub ecx, 2
- jnz loop4_pass2
- EMMS
- }
- }
- sptr -= (width_mmx*4 - 4); // sign fixed
- dp -= (width_mmx*16 - 4); // sign fixed
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 4;
- png_memcpy(v, sptr, 4);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 4;
- png_memcpy(dp, v, 4);
- }
- }
- }
- else if (width) // pass == 4 or 5
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 4
- sub edi, 12
- loop4_pass4:
- movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
- movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
- punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
- punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
- movq [edi], mm0
- sub esi, 8
- movq [edi + 8], mm1
- sub edi, 16
- sub ecx, 2
- jnz loop4_pass4
- EMMS
- }
- }
- sptr -= (width_mmx*4 - 4); // sign fixed
- dp -= (width_mmx*8 - 4); // sign fixed
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 4;
- png_memcpy(v, sptr, 4);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 4;
- png_memcpy(dp, v, 4);
- }
- }
- }
- } /* end of pixel_bytes == 4 */
- else if (pixel_bytes == 6)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, 6);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, 6);
- dp -= 6;
- }
- sptr -= 6;
- }
- } /* end of pixel_bytes == 6 */
- else
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr-= pixel_bytes;
- }
- }
- } /* end of mmx_supported */
- else /* MMX not supported: use modified C code - takes advantage
- * of inlining of memcpy for a constant */
- {
- if (pixel_bytes == 1)
- {
- for (i = width; i; i--)
- {
- int j;
- for (j = 0; j < png_pass_inc[pass]; j++)
- *dp-- = *sptr;
- sptr--;
- }
- }
- else if (pixel_bytes == 3)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else if (pixel_bytes == 2)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else if (pixel_bytes == 4)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else if (pixel_bytes == 6)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- } /* end of MMX not supported */
- break;
- }
- } /* end switch (row_info->pixel_depth) */
- row_info->width = final_width;
- row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
- }
- }
- #endif /* PNG_READ_INTERLACING_SUPPORTED */
- // These variables are utilized in the functions below. They are declared
- // globally here to ensure alignment on 8-byte boundaries.
- union uAll {
- __int64 use;
- double align;
- } LBCarryMask = {0x0101010101010101},
- HBClearMask = {0x7f7f7f7f7f7f7f7f},
- ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem;
- // Optimized code for PNG Average filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row
- , png_bytep prev_row)
- {
- int bpp;
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- //png_uint_32 len;
- int diff;
- bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
- FullLength = row_info->rowbytes; // # of bytes to filter
- _asm {
- // Init address pointers and offset
- mov edi, row // edi ==> Avg(x)
- xor ebx, ebx // ebx ==> x
- mov edx, edi
- mov esi, prev_row // esi ==> Prior(x)
- sub edx, bpp // edx ==> Raw(x-bpp)
- xor eax, eax
- // Compute the Raw value for the first bpp bytes
- // Raw(x) = Avg(x) + (Prior(x)/2)
- davgrlp:
- mov al, [esi + ebx] // Load al with Prior(x)
- inc ebx
- shr al, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, bpp
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davgrlp
- // get # of bytes to alignment
- mov diff, edi // take start of row
- add diff, ebx // add bpp
- add diff, 0xf // add 7 + 8 to incr past alignment boundary
- and diff, 0xfffffff8 // mask to alignment boundary
- sub diff, edi // subtract from start ==> value ebx at alignment
- jz davggo
- // fix alignment
- // Compute the Raw value for the bytes upto the alignment boundary
- // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
- xor ecx, ecx
- davglp1:
- xor eax, eax
- mov cl, [esi + ebx] // load cl with Prior(x)
- mov al, [edx + ebx] // load al with Raw(x-bpp)
- add ax, cx
- inc ebx
- shr ax, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, diff // Check if at alignment boundary
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davglp1 // Repeat until at alignment boundary
- davggo:
- mov eax, FullLength
- mov ecx, eax
- sub eax, ebx // subtract alignment fix
- and eax, 0x00000007 // calc bytes over mult of 8
- sub ecx, eax // drop over bytes from original length
- mov MMXLength, ecx
- } // end _asm block
- // Now do the math for the rest of the row
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000000000ffffff;
- ShiftBpp.use = 24; // == 3 * 8
- ShiftRem.use = 40; // == 64 - 24
- _asm {
- // Re-init address pointers and offset
- movq mm7, ActiveMask
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- movq mm5, LBCarryMask
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov esi, prev_row // esi ==> Prior(x)
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (we correct position in loop below)
- davg3lp:
- movq mm0, [edi + ebx] // Load mm0 with Avg(x)
- // Add (Prev_row/2) to Average
- movq mm3, mm5
- psrlq mm2, ShiftRem // Correct position Raw(x-bpp) data
- movq mm1, [esi + ebx] // Load mm1 with Prior(x)
- movq mm6, mm7
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 3-5
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover the last two
- // bytes
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- // Data only needs to be shifted once here to
- // get the correct x-bpp offset.
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- add ebx, 8
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Now ready to write back to memory
- movq [edi + ebx - 8], mm0
- // Move updated Raw(x) to use as Raw(x-bpp) for next loop
- cmp ebx, MMXLength
- movq mm2, mm0 // mov updated Raw(x) to mm2
- jb davg3lp
- } // end _asm block
- }
- break;
- case 6:
- case 4:
- case 7:
- case 5:
- {
- ActiveMask.use = 0xffffffffffffffff; // use shift below to clear
- // appropriate inactive bytes
- ShiftBpp.use = bpp << 3;
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm {
- movq mm4, HBClearMask
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- // Load ActiveMask and clear all bytes except for 1st active group
- movq mm7, ActiveMask
- mov edi, row // edi ==> Avg(x)
- psrlq mm7, ShiftRem
- mov esi, prev_row // esi ==> Prior(x)
- movq mm6, mm7
- movq mm5, LBCarryMask
- psllq mm6, ShiftBpp // Create mask for 2nd active group
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (we correct position in loop below)
- davg4lp:
- movq mm0, [edi + ebx]
- psrlq mm2, ShiftRem // shift data to position correctly
- movq mm1, [esi + ebx]
- // Add (Prev_row/2) to Average
- movq mm3, mm5
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm7 // Leave only Active Group 1 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- add ebx, 8
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- cmp ebx, MMXLength
- // Now ready to write back to memory
- movq [edi + ebx - 8], mm0
- // Prep Raw(x-bpp) for next loop
- movq mm2, mm0 // mov updated Raws to mm2
- jb davg4lp
- } // end _asm block
- }
- break;
- case 2:
- {
- ActiveMask.use = 0x000000000000ffff;
- ShiftBpp.use = 16; // == 2 * 8 [BUGFIX]
- ShiftRem.use = 48; // == 64 - 16 [BUGFIX]
- _asm {
- // Load ActiveMask
- movq mm7, ActiveMask
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- movq mm5, LBCarryMask
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov esi, prev_row // esi ==> Prior(x)
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (we correct position in loop below)
- davg2lp:
- movq mm0, [edi + ebx]
- psrlq mm2, ShiftRem // shift data to position correctly [BUGFIX]
- movq mm1, [esi + ebx]
- // Add (Prev_row/2) to Average
- movq mm3, mm5
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- movq mm6, mm7
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- // Data only needs to be shifted once here to
- // get the correct x-bpp offset.
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 6 & 7
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- // Data only needs to be shifted once here to
- // get the correct x-bpp offset.
- add ebx, 8
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- cmp ebx, MMXLength
- // Now ready to write back to memory
- movq [edi + ebx - 8], mm0
- // Prep Raw(x-bpp) for next loop
- movq mm2, mm0 // mov updated Raws to mm2
- jb davg2lp
- } // end _asm block
- }
- break;
- case 1: // bpp == 1
- {
- _asm {
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- mov edi, row // edi ==> Avg(x)
- cmp ebx, FullLength // Test if offset at end of array
- jnb davg1end
- // Do Paeth decode for remaining bytes
- mov esi, prev_row // esi ==> Prior(x)
- mov edx, edi
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // edx ==> Raw(x-bpp)
- davg1lp:
- // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
- xor eax, eax
- mov cl, [esi + ebx] // load cl with Prior(x)
- mov al, [edx + ebx] // load al with Raw(x-bpp)
- add ax, cx
- inc ebx
- shr ax, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, FullLength // Check if at end of array
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davg1lp
- davg1end:
- } // end _asm block
- }
- return;
- case 8: // bpp == 8
- {
- _asm {
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- movq mm5, LBCarryMask
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov esi, prev_row // esi ==> Prior(x)
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (NO NEED to correct position in loop below)
- davg8lp:
- movq mm0, [edi + ebx]
- movq mm3, mm5
- movq mm1, [esi + ebx]
- add ebx, 8
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm3, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm3 // add LBCarrys to Avg for each byte
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- paddb mm0, mm2 // add (Raw/2) to Avg for each byte
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm0
- movq mm2, mm0 // reuse as Raw(x-bpp)
- jb davg8lp
- } // end _asm block
- }
- break;
- default: // bpp greater than 8
- {
- _asm {
- movq mm5, LBCarryMask
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov edx, edi
- mov esi, prev_row // esi ==> Prior(x)
- sub edx, bpp // edx ==> Raw(x-bpp)
- davgAlp:
- movq mm0, [edi + ebx]
- movq mm3, mm5
- movq mm1, [esi + ebx]
- pand mm3, mm1 // get lsb for each prev_row byte
- movq mm2, [edx + ebx]
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm3, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm3 // add LBCarrys to Avg for each byte
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- add ebx, 8
- paddb mm0, mm2 // add (Raw/2) to Avg for each byte
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm0
- jb davgAlp
- } // end _asm block
- }
- break;
- } // end switch ( bpp )
- _asm {
- // MMX acceleration complete now do clean-up
- // Check if any remaining bytes left to decode
- mov ebx, MMXLength // ebx ==> x = offset bytes remaining after MMX
- mov edi, row // edi ==> Avg(x)
- cmp ebx, FullLength // Test if offset at end of array
- jnb davgend
- // Do Paeth decode for remaining bytes
- mov esi, prev_row // esi ==> Prior(x)
- mov edx, edi
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // edx ==> Raw(x-bpp)
- davglp2:
- // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
- xor eax, eax
- mov cl, [esi + ebx] // load cl with Prior(x)
- mov al, [edx + ebx] // load al with Raw(x-bpp)
- add ax, cx
- inc ebx
- shr ax, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, FullLength // Check if at end of array
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davglp2
- davgend:
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized code for PNG Paeth filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
- png_bytep prev_row)
- {
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- //png_uint_32 len;
- int bpp;
- int diff;
- //int ptemp;
- int patemp, pbtemp, pctemp;
- bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
- FullLength = row_info->rowbytes; // # of bytes to filter
- _asm
- {
- xor ebx, ebx // ebx ==> x offset
- mov edi, row
- xor edx, edx // edx ==> x-bpp offset
- mov esi, prev_row
- xor eax, eax
- // Compute the Raw value for the first bpp bytes
- // Note: the formula works out to be always
- // Paeth(x) = Raw(x) + Prior(x) where x < bpp
- dpthrlp:
- mov al, [edi + ebx]
- add al, [esi + ebx]
- inc ebx
- cmp ebx, bpp
- mov [edi + ebx - 1], al
- jb dpthrlp
- // get # of bytes to alignment
- mov diff, edi // take start of row
- add diff, ebx // add bpp
- xor ecx, ecx
- add diff, 0xf // add 7 + 8 to incr past alignment boundary
- and diff, 0xfffffff8 // mask to alignment boundary
- sub diff, edi // subtract from start ==> value ebx at alignment
- jz dpthgo
- // fix alignment
- dpthlp1:
- xor eax, eax
- // pav = p - a = (a + b - c) - a = b - c
- mov al, [esi + ebx] // load Prior(x) into al
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- sub eax, ecx // subtract Prior(x-bpp)
- mov patemp, eax // Save pav for later use
- xor eax, eax
- // pbv = p - b = (a + b - c) - b = a - c
- mov al, [edi + edx] // load Raw(x-bpp) into al
- sub eax, ecx // subtract Prior(x-bpp)
- mov ecx, eax
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- add eax, patemp // pcv = pav + pbv
- // pc = abs(pcv)
- test eax, 0x80000000
- jz dpthpca
- neg eax // reverse sign of neg values
- dpthpca:
- mov pctemp, eax // save pc for later use
- // pb = abs(pbv)
- test ecx, 0x80000000
- jz dpthpba
- neg ecx // reverse sign of neg values
- dpthpba:
- mov pbtemp, ecx // save pb for later use
- // pa = abs(pav)
- mov eax, patemp
- test eax, 0x80000000
- jz dpthpaa
- neg eax // reverse sign of neg values
- dpthpaa:
- mov patemp, eax // save pa for later use
- // test if pa <= pb
- cmp eax, ecx
- jna dpthabb
- // pa > pb; now test if pb <= pc
- cmp ecx, pctemp
- jna dpthbbc
- // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth
- dpthbbc:
- // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
- mov cl, [esi + ebx] // load Prior(x) into cl
- jmp dpthpaeth
- dpthabb:
- // pa <= pb; now test if pa <= pc
- cmp eax, pctemp
- jna dpthabc
- // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth
- dpthabc:
- // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
- mov cl, [edi + edx] // load Raw(x-bpp) into cl
- dpthpaeth:
- inc ebx
- inc edx
- // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
- add [edi + ebx - 1], cl
- cmp ebx, diff
- jb dpthlp1
- dpthgo:
- mov ecx, FullLength
- mov eax, ecx
- sub eax, ebx // subtract alignment fix
- and eax, 0x00000007 // calc bytes over mult of 8
- sub ecx, eax // drop over bytes from original length
- mov MMXLength, ecx
- } // end _asm block
- // Now do the math for the rest of the row
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000000000ffffff;
- ActiveMaskEnd.use = 0xffff000000000000;
- ShiftBpp.use = 24; // == bpp(3) * 8
- ShiftRem.use = 40; // == 64 - 24
- _asm
- {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dpth3lp:
- psrlq mm1, ShiftRem // shift last 3 bytes to 1st 3 bytes
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm1, mm0 // Unpack High bytes of a
- movq mm3, [esi+ebx-8] // Prep c=Prior(x-bpp) bytes
- punpcklbw mm2, mm0 // Unpack High bytes of b
- psrlq mm3, ShiftRem // shift last 3 bytes to 1st 3 bytes
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpcklbw mm3, mm0 // Unpack High bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx] // load c=Prior(x-bpp)
- pand mm7, ActiveMask
- movq mm2, mm3 // load b=Prior(x) step 1
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- punpcklbw mm3, mm0 // Unpack High bytes of c
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp)
- // Now do Paeth for 2nd set of bytes (3-5)
- psrlq mm2, ShiftBpp // load b=Prior(x) step 2
- punpcklbw mm1, mm0 // Unpack High bytes of a
- pxor mm7, mm7
- punpcklbw mm2, mm0 // Unpack High bytes of b
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- psubw mm5, mm3
- psubw mm4, mm3
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
- // pav + pbv = pbv + pav
- movq mm6, mm5
- paddw mm6, mm4
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm5 // Create mask pbv bytes < 0
- pcmpgtw mm7, mm4 // Create mask pav bytes < 0
- pand mm0, mm5 // Only pbv bytes < 0 in mm0
- pand mm7, mm4 // Only pav bytes < 0 in mm7
- psubw mm5, mm0
- psubw mm4, mm7
- psubw mm5, mm0
- psubw mm4, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- movq mm2, [esi + ebx] // load b=Prior(x)
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, mm2 // load c=Prior(x-bpp) step 1
- pand mm7, ActiveMask
- punpckhbw mm2, mm0 // Unpack High bytes of b
- psllq mm7, ShiftBpp // Shift bytes to 2nd group of 3 bytes
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- psllq mm3, ShiftBpp // load c=Prior(x-bpp) step 2
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, mm7
- punpckhbw mm3, mm0 // Unpack High bytes of c
- psllq mm1, ShiftBpp // Shift bytes
- // Now mm1 will be used as Raw(x-bpp)
- // Now do Paeth for 3rd, and final, set of bytes (6-7)
- pxor mm7, mm7
- punpckhbw mm1, mm0 // Unpack High bytes of a
- psubw mm4, mm3
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- pxor mm0, mm0
- paddw mm6, mm5
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- pandn mm0, mm1
- pandn mm7, mm4
- paddw mm0, mm2
- paddw mm7, mm5
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm1, mm1
- packuswb mm1, mm7
- // Step ebx to next set of 8 bytes and repeat loop til done
- add ebx, 8
- pand mm1, ActiveMaskEnd
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- pxor mm0, mm0 // pxor does not affect flags
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- // mm3 ready to be used as Prior(x-bpp) next loop
- jb dpth3lp
- } // end _asm block
- }
- break;
- case 6:
- case 7:
- case 5:
- {
- ActiveMask.use = 0x00000000ffffffff;
- ActiveMask2.use = 0xffffffff00000000;
- ShiftBpp.use = bpp << 3; // == bpp * 8
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm
- {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- pxor mm0, mm0
- dpth6lp:
- // Must shift to position Raw(x-bpp) data
- psrlq mm1, ShiftRem
- // Do first set of 4 bytes
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- punpcklbw mm1, mm0 // Unpack Low bytes of a
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm2, mm0 // Unpack Low bytes of b
- // Must shift to position Prior(x-bpp) data
- psrlq mm3, ShiftRem
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpcklbw mm3, mm0 // Unpack Low bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx - 8] // load c=Prior(x-bpp)
- pand mm7, ActiveMask
- psrlq mm3, ShiftRem
- movq mm2, [esi + ebx] // load b=Prior(x) step 1
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- movq mm6, mm2
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, [edi+ebx-8]
- psllq mm6, ShiftBpp
- movq mm5, mm7
- psrlq mm1, ShiftRem
- por mm3, mm6
- psllq mm5, ShiftBpp
- punpckhbw mm3, mm0 // Unpack High bytes of c
- por mm1, mm5
- // Do second set of 4 bytes
- punpckhbw mm2, mm0 // Unpack High bytes of b
- punpckhbw mm1, mm0 // Unpack High bytes of a
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- // Step ex to next set of 8 bytes and repeat loop til done
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- jb dpth6lp
- } // end _asm block
- }
- break;
- case 4:
- {
- ActiveMask.use = 0x00000000ffffffff;
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8] // Only time should need to read
- // a=Raw(x-bpp) bytes
- dpth4lp:
- // Do first set of 4 bytes
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- punpckhbw mm1, mm0 // Unpack Low bytes of a
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm2, mm0 // Unpack High bytes of b
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpckhbw mm3, mm0 // Unpack High bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx] // load c=Prior(x-bpp)
- pand mm7, ActiveMask
- movq mm2, mm3 // load b=Prior(x) step 1
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- punpcklbw mm3, mm0 // Unpack High bytes of c
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp)
- // Do second set of 4 bytes
- punpckhbw mm2, mm0 // Unpack Low bytes of b
- punpcklbw mm1, mm0 // Unpack Low bytes of a
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- // Step ex to next set of 8 bytes and repeat loop til done
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- jb dpth4lp
- } // end _asm block
- }
- break;
- case 8: // bpp == 8
- {
- ActiveMask.use = 0x00000000ffffffff;
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8] // Only time should need to read
- // a=Raw(x-bpp) bytes
- dpth8lp:
- // Do first set of 4 bytes
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- punpcklbw mm1, mm0 // Unpack Low bytes of a
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm2, mm0 // Unpack Low bytes of b
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpcklbw mm3, mm0 // Unpack Low bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- pand mm7, ActiveMask
- movq mm2, [esi + ebx] // load b=Prior(x)
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- punpckhbw mm3, mm0 // Unpack High bytes of c
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, [edi+ebx-8] // read a=Raw(x-bpp) bytes
- // Do second set of 4 bytes
- punpckhbw mm2, mm0 // Unpack High bytes of b
- punpckhbw mm1, mm0 // Unpack High bytes of a
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- // Step ex to next set of 8 bytes and repeat loop til done
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- jb dpth8lp
- } // end _asm block
- }
- break;
- case 1: // bpp = 1
- case 2: // bpp = 2
- default: // bpp > 8
- {
- _asm {
- mov ebx, diff
- cmp ebx, FullLength
- jnb dpthdend
- mov edi, row
- mov esi, prev_row
- // Do Paeth decode for remaining bytes
- mov edx, ebx
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // Set edx = ebx - bpp
- dpthdlp:
- xor eax, eax
- // pav = p - a = (a + b - c) - a = b - c
- mov al, [esi + ebx] // load Prior(x) into al
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- sub eax, ecx // subtract Prior(x-bpp)
- mov patemp, eax // Save pav for later use
- xor eax, eax
- // pbv = p - b = (a + b - c) - b = a - c
- mov al, [edi + edx] // load Raw(x-bpp) into al
- sub eax, ecx // subtract Prior(x-bpp)
- mov ecx, eax
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- add eax, patemp // pcv = pav + pbv
- // pc = abs(pcv)
- test eax, 0x80000000
- jz dpthdpca
- neg eax // reverse sign of neg values
- dpthdpca:
- mov pctemp, eax // save pc for later use
- // pb = abs(pbv)
- test ecx, 0x80000000
- jz dpthdpba
- neg ecx // reverse sign of neg values
- dpthdpba:
- mov pbtemp, ecx // save pb for later use
- // pa = abs(pav)
- mov eax, patemp
- test eax, 0x80000000
- jz dpthdpaa
- neg eax // reverse sign of neg values
- dpthdpaa:
- mov patemp, eax // save pa for later use
- // test if pa <= pb
- cmp eax, ecx
- jna dpthdabb
- // pa > pb; now test if pb <= pc
- cmp ecx, pctemp
- jna dpthdbbc
- // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthdpaeth
- dpthdbbc:
- // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
- mov cl, [esi + ebx] // load Prior(x) into cl
- jmp dpthdpaeth
- dpthdabb:
- // pa <= pb; now test if pa <= pc
- cmp eax, pctemp
- jna dpthdabc
- // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthdpaeth
- dpthdabc:
- // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
- mov cl, [edi + edx] // load Raw(x-bpp) into cl
- dpthdpaeth:
- inc ebx
- inc edx
- // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
- add [edi + ebx - 1], cl
- cmp ebx, FullLength
- jb dpthdlp
- dpthdend:
- } // end _asm block
- }
- return; // No need to go further with this one
- } // end switch ( bpp )
- _asm
- {
- // MMX acceleration complete now do clean-up
- // Check if any remaining bytes left to decode
- mov ebx, MMXLength
- cmp ebx, FullLength
- jnb dpthend
- mov edi, row
- mov esi, prev_row
- // Do Paeth decode for remaining bytes
- mov edx, ebx
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // Set edx = ebx - bpp
- dpthlp2:
- xor eax, eax
- // pav = p - a = (a + b - c) - a = b - c
- mov al, [esi + ebx] // load Prior(x) into al
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- sub eax, ecx // subtract Prior(x-bpp)
- mov patemp, eax // Save pav for later use
- xor eax, eax
- // pbv = p - b = (a + b - c) - b = a - c
- mov al, [edi + edx] // load Raw(x-bpp) into al
- sub eax, ecx // subtract Prior(x-bpp)
- mov ecx, eax
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- add eax, patemp // pcv = pav + pbv
- // pc = abs(pcv)
- test eax, 0x80000000
- jz dpthpca2
- neg eax // reverse sign of neg values
- dpthpca2:
- mov pctemp, eax // save pc for later use
- // pb = abs(pbv)
- test ecx, 0x80000000
- jz dpthpba2
- neg ecx // reverse sign of neg values
- dpthpba2:
- mov pbtemp, ecx // save pb for later use
- // pa = abs(pav)
- mov eax, patemp
- test eax, 0x80000000
- jz dpthpaa2
- neg eax // reverse sign of neg values
- dpthpaa2:
- mov patemp, eax // save pa for later use
- // test if pa <= pb
- cmp eax, ecx
- jna dpthabb2
- // pa > pb; now test if pb <= pc
- cmp ecx, pctemp
- jna dpthbbc2
- // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth2
- dpthbbc2:
- // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
- mov cl, [esi + ebx] // load Prior(x) into cl
- jmp dpthpaeth2
- dpthabb2:
- // pa <= pb; now test if pa <= pc
- cmp eax, pctemp
- jna dpthabc2
- // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth2
- dpthabc2:
- // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
- mov cl, [edi + edx] // load Raw(x-bpp) into cl
- dpthpaeth2:
- inc ebx
- inc edx
- // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
- add [edi + ebx - 1], cl
- cmp ebx, FullLength
- jb dpthlp2
- dpthend:
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized code for PNG Sub filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
- {
- //int test;
- int bpp;
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- int diff;
- bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
- FullLength = row_info->rowbytes - bpp; // # of bytes to filter
- _asm {
- mov edi, row
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- xor eax, eax
- // get # of bytes to alignment
- mov diff, edi // take start of row
- add diff, 0xf // add 7 + 8 to incr past
- // alignment boundary
- xor ebx, ebx
- and diff, 0xfffffff8 // mask to alignment boundary
- sub diff, edi // subtract from start ==> value
- // ebx at alignment
- jz dsubgo
- // fix alignment
- dsublp1:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, diff
- jb dsublp1
- dsubgo:
- mov ecx, FullLength
- mov edx, ecx
- sub edx, ebx // subtract alignment fix
- and edx, 0x00000007 // calc bytes over mult of 8
- sub ecx, edx // drop over bytes from length
- mov MMXLength, ecx
- } // end _asm block
- // Now do the math for the rest of the row
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000ffffff000000;
- ShiftBpp.use = 24; // == 3 * 8
- ShiftRem.use = 40; // == 64 - 24
- _asm {
- mov edi, row
- movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- movq mm6, mm7
- mov ebx, diff
- psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active
- // byte group
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dsub3lp:
- psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
- // no need for mask; shift clears inactive bytes
- // Add 1st active group
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- // Add 2nd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm7 // mask to use only 2nd active group
- paddb mm0, mm1
- // Add 3rd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm6 // mask to use only 3rd active group
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // Write updated Raws back to array
- // Prep for doing 1st add at top of loop
- movq mm1, mm0
- jb dsub3lp
- } // end _asm block
- }
- break;
- case 1:
- {
- // Placed here just in case this is a duplicate of the
- // non-MMX code for the SUB filter in png_read_filter_row below
- //
- // png_bytep rp;
- // png_bytep lp;
- // png_uint_32 i;
- // bpp = (row_info->pixel_depth + 7) >> 3;
- // for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
- // i < row_info->rowbytes; i++, rp++, lp++)
- // {
- // *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
- // }
- _asm {
- mov ebx, diff
- mov edi, row
- cmp ebx, FullLength
- jnb dsub1end
- mov esi, edi // lp = row
- xor eax, eax
- add edi, bpp // rp = row + bpp
- dsub1lp:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, FullLength
- jb dsub1lp
- dsub1end:
- } // end _asm block
- }
- return;
- case 6:
- case 7:
- case 4:
- case 5:
- {
- ShiftBpp.use = bpp << 3;
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm {
- mov edi, row
- mov ebx, diff
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dsub4lp:
- psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
- // no need for mask; shift clears inactive bytes
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- // Add 2nd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- // there is no need for any mask
- // since shift clears inactive bits/bytes
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0
- movq mm1, mm0 // Prep for doing 1st add at top of loop
- jb dsub4lp
- } // end _asm block
- }
- break;
- case 2:
- {
- ActiveMask.use = 0x00000000ffff0000;
- ShiftBpp.use = 16; // == 2 * 8
- ShiftRem.use = 48; // == 64 - 16
- _asm {
- movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group
- mov ebx, diff
- movq mm6, mm7
- mov edi, row
- psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active
- // byte group
- mov esi, edi // lp = row
- movq mm5, mm6
- add edi, bpp // rp = row + bpp
- psllq mm5, ShiftBpp // Move mask in mm5 to cover 4th active
- // byte group
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dsub2lp:
- // Add 1st active group
- psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
- // no need for mask; shift clears inactive
- // bytes
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- // Add 2nd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm7 // mask to use only 2nd active group
- paddb mm0, mm1
- // Add 3rd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm6 // mask to use only 3rd active group
- paddb mm0, mm1
- // Add 4th active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm5 // mask to use only 4th active group
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // Write updated Raws back to array
- movq mm1, mm0 // Prep for doing 1st add at top of loop
- jb dsub2lp
- } // end _asm block
- }
- break;
- case 8:
- {
- _asm {
- mov edi, row
- mov ebx, diff
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- mov ecx, MMXLength
- movq mm7, [edi+ebx-8] // PRIME the pump (load the first
- // Raw(x-bpp) data set
- and ecx, 0x0000003f // calc bytes over mult of 64
- dsub8lp:
- movq mm0, [edi+ebx] // Load Sub(x) for 1st 8 bytes
- paddb mm0, mm7
- movq mm1, [edi+ebx+8] // Load Sub(x) for 2nd 8 bytes
- movq [edi+ebx], mm0 // Write Raw(x) for 1st 8 bytes
- // Now mm0 will be used as Raw(x-bpp) for
- // the 2nd group of 8 bytes. This will be
- // repeated for each group of 8 bytes with
- // the 8th group being used as the Raw(x-bpp)
- // for the 1st group of the next loop.
- paddb mm1, mm0
- movq mm2, [edi+ebx+16] // Load Sub(x) for 3rd 8 bytes
- movq [edi+ebx+8], mm1 // Write Raw(x) for 2nd 8 bytes
- paddb mm2, mm1
- movq mm3, [edi+ebx+24] // Load Sub(x) for 4th 8 bytes
- movq [edi+ebx+16], mm2 // Write Raw(x) for 3rd 8 bytes
- paddb mm3, mm2
- movq mm4, [edi+ebx+32] // Load Sub(x) for 5th 8 bytes
- movq [edi+ebx+24], mm3 // Write Raw(x) for 4th 8 bytes
- paddb mm4, mm3
- movq mm5, [edi+ebx+40] // Load Sub(x) for 6th 8 bytes
- movq [edi+ebx+32], mm4 // Write Raw(x) for 5th 8 bytes
- paddb mm5, mm4
- movq mm6, [edi+ebx+48] // Load Sub(x) for 7th 8 bytes
- movq [edi+ebx+40], mm5 // Write Raw(x) for 6th 8 bytes
- paddb mm6, mm5
- movq mm7, [edi+ebx+56] // Load Sub(x) for 8th 8 bytes
- movq [edi+ebx+48], mm6 // Write Raw(x) for 7th 8 bytes
- add ebx, 64
- paddb mm7, mm6
- cmp ebx, ecx
- movq [edi+ebx-8], mm7 // Write Raw(x) for 8th 8 bytes
- jb dsub8lp
- cmp ebx, MMXLength
- jnb dsub8lt8
- dsub8lpA:
- movq mm0, [edi+ebx]
- add ebx, 8
- paddb mm0, mm7
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // use -8 to offset early add to ebx
- movq mm7, mm0 // Move calculated Raw(x) data to mm1 to
- // be the new Raw(x-bpp) for the next loop
- jb dsub8lpA
- dsub8lt8:
- } // end _asm block
- }
- break;
- default: // bpp greater than 8 bytes
- {
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- dsubAlp:
- movq mm0, [edi+ebx]
- movq mm1, [esi+ebx]
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // mov does not affect flags; -8 to offset
- // add ebx
- jb dsubAlp
- } // end _asm block
- }
- break;
- } // end switch ( bpp )
- _asm {
- mov ebx, MMXLength
- mov edi, row
- cmp ebx, FullLength
- jnb dsubend
- mov esi, edi // lp = row
- xor eax, eax
- add edi, bpp // rp = row + bpp
- dsublp2:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, FullLength
- jb dsublp2
- dsubend:
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized code for PNG Up filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
- png_bytep prev_row)
- {
- png_uint_32 len;
- len = row_info->rowbytes; // # of bytes to filter
- _asm {
- mov edi, row
- // get # of bytes to alignment
- mov ecx, edi
- xor ebx, ebx
- add ecx, 0x7
- xor eax, eax
- and ecx, 0xfffffff8
- mov esi, prev_row
- sub ecx, edi
- jz dupgo
- // fix alignment
- duplp1:
- mov al, [edi+ebx]
- add al, [esi+ebx]
- inc ebx
- cmp ebx, ecx
- mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
- jb duplp1
- dupgo:
- mov ecx, len
- mov edx, ecx
- sub edx, ebx // subtract alignment fix
- and edx, 0x0000003f // calc bytes over mult of 64
- sub ecx, edx // drop over bytes from length
- // Unrolled loop - use all MMX registers and interleave to reduce
- // number of branch instructions (loops) and reduce partial stalls
- duploop:
- movq mm1, [esi+ebx]
- movq mm0, [edi+ebx]
- movq mm3, [esi+ebx+8]
- paddb mm0, mm1
- movq mm2, [edi+ebx+8]
- movq [edi+ebx], mm0
- paddb mm2, mm3
- movq mm5, [esi+ebx+16]
- movq [edi+ebx+8], mm2
- movq mm4, [edi+ebx+16]
- movq mm7, [esi+ebx+24]
- paddb mm4, mm5
- movq mm6, [edi+ebx+24]
- movq [edi+ebx+16], mm4
- paddb mm6, mm7
- movq mm1, [esi+ebx+32]
- movq [edi+ebx+24], mm6
- movq mm0, [edi+ebx+32]
- movq mm3, [esi+ebx+40]
- paddb mm0, mm1
- movq mm2, [edi+ebx+40]
- movq [edi+ebx+32], mm0
- paddb mm2, mm3
- movq mm5, [esi+ebx+48]
- movq [edi+ebx+40], mm2
- movq mm4, [edi+ebx+48]
- movq mm7, [esi+ebx+56]
- paddb mm4, mm5
- movq mm6, [edi+ebx+56]
- movq [edi+ebx+48], mm4
- add ebx, 64
- paddb mm6, mm7
- cmp ebx, ecx
- movq [edi+ebx-8], mm6 // (+56)movq does not affect flags;
- // -8 to offset add ebx
- jb duploop
- cmp edx, 0 // Test for bytes over mult of 64
- jz dupend
- // 2 lines added by lcreeve at netins.net
- // (mail 11 Jul 98 in png-implement list)
- cmp edx, 8 //test for less than 8 bytes
- jb duplt8
- add ecx, edx
- and edx, 0x00000007 // calc bytes over mult of 8
- sub ecx, edx // drop over bytes from length
- jz duplt8
- // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously
- duplpA:
- movq mm1, [esi+ebx]
- movq mm0, [edi+ebx]
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, ecx
- movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx
- jb duplpA
- cmp edx, 0 // Test for bytes over mult of 8
- jz dupend
- duplt8:
- xor eax, eax
- add ecx, edx // move over byte count into counter
- // Loop using x86 registers to update remaining bytes
- duplp2:
- mov al, [edi + ebx]
- add al, [esi + ebx]
- inc ebx
- cmp ebx, ecx
- mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
- jb duplp2
- dupend:
- // Conversion of filtered row completed
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized png_read_filter_row routines
- void /* PRIVATE */
- png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
- row, png_bytep prev_row, int filter)
- {
- #ifdef PNG_DEBUG
- char filnm[10];
- #endif
- if (mmx_supported == 2) {
- #if !defined(PNG_1_0_X)
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- #endif
- png_mmx_support();
- }
- #ifdef PNG_DEBUG
- png_debug(1, "in png_read_filter_row\n");
- switch (filter)
- {
- case 0: sprintf(filnm, "none");
- break;
- #if !defined(PNG_1_0_X)
- case 1: sprintf(filnm, "sub-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86");
- break;
- case 2: sprintf(filnm, "up-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86");
- break;
- case 3: sprintf(filnm, "avg-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86");
- break;
- case 4: sprintf(filnm, "Paeth-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86");
- break;
- #else
- case 1: sprintf(filnm, "sub");
- break;
- case 2: sprintf(filnm, "up");
- break;
- case 3: sprintf(filnm, "avg");
- break;
- case 4: sprintf(filnm, "Paeth");
- break;
- #endif
- default: sprintf(filnm, "unknw");
- break;
- }
- png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
- png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
- (int)((row_info->pixel_depth + 7) >> 3));
- png_debug1(0,"len=%8d, ", row_info->rowbytes);
- #endif /* PNG_DEBUG */
- switch (filter)
- {
- case PNG_FILTER_VALUE_NONE:
- break;
- case PNG_FILTER_VALUE_SUB:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_sub(row_info, row);
- }
- else
- {
- png_uint_32 i;
- png_uint_32 istop = row_info->rowbytes;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_bytep rp = row + bpp;
- png_bytep lp = row;
- for (i = bpp; i < istop; i++)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
- rp++;
- }
- }
- break;
- }
- case PNG_FILTER_VALUE_UP:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_up(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_uint_32 istop = row_info->rowbytes;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- for (i = 0; i < istop; ++i)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
- rp++;
- }
- }
- break;
- }
- case PNG_FILTER_VALUE_AVG:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_avg(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- png_bytep lp = row;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_uint_32 istop = row_info->rowbytes - bpp;
- for (i = 0; i < bpp; i++)
- {
- *rp = (png_byte)(((int)(*rp) +
- ((int)(*pp++) >> 1)) & 0xff);
- rp++;
- }
- for (i = 0; i < istop; i++)
- {
- *rp = (png_byte)(((int)(*rp) +
- ((int)(*pp++ + *lp++) >> 1)) & 0xff);
- rp++;
- }
- }
- break;
- }
- case PNG_FILTER_VALUE_PAETH:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_paeth(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- png_bytep lp = row;
- png_bytep cp = prev_row;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_uint_32 istop=row_info->rowbytes - bpp;
- for (i = 0; i < bpp; i++)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
- rp++;
- }
- for (i = 0; i < istop; i++) // use leftover rp,pp
- {
- int a, b, c, pa, pb, pc, p;
- a = *lp++;
- b = *pp++;
- c = *cp++;
- p = b - c;
- pc = a - c;
- #ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
- #else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
- #endif
- /*
- if (pa <= pb && pa <= pc)
- p = a;
- else if (pb <= pc)
- p = b;
- else
- p = c;
- */
- p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
- *rp = (png_byte)(((int)(*rp) + p) & 0xff);
- rp++;
- }
- }
- break;
- }
- default:
- png_warning(png_ptr, "Ignoring bad row filter type");
- *row=0;
- break;
- }
- }
- #endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */
|